Merge branch 'main' into main
This commit is contained in:
commit
0d2780f0e7
32
go.mod
32
go.mod
@ -1,9 +1,9 @@
|
||||
module github.com/containernetworking/plugins
|
||||
|
||||
go 1.20
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/Microsoft/hcsshim v0.12.4
|
||||
github.com/Microsoft/hcsshim v0.12.6
|
||||
github.com/alexflint/go-filemutex v1.3.0
|
||||
github.com/buger/jsonparser v1.1.1
|
||||
github.com/containernetworking/cni v1.1.2
|
||||
@ -15,34 +15,34 @@ require (
|
||||
github.com/godbus/dbus/v5 v5.1.0
|
||||
github.com/mattn/go-shellwords v1.0.12
|
||||
github.com/networkplumbing/go-nft v0.4.0
|
||||
github.com/onsi/ginkgo/v2 v2.19.0
|
||||
github.com/onsi/gomega v1.33.1
|
||||
github.com/onsi/ginkgo/v2 v2.20.1
|
||||
github.com/onsi/gomega v1.34.1
|
||||
github.com/opencontainers/selinux v1.11.0
|
||||
github.com/safchain/ethtool v0.4.1
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2
|
||||
golang.org/x/sys v0.21.0
|
||||
github.com/vishvananda/netlink v1.3.0
|
||||
golang.org/x/sys v0.23.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/containerd/cgroups/v3 v3.0.2 // indirect
|
||||
github.com/containerd/cgroups/v3 v3.0.3 // indirect
|
||||
github.com/containerd/errdefs v0.1.0 // indirect
|
||||
github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect
|
||||
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/vishvananda/netns v0.0.4 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
golang.org/x/net v0.25.0 // indirect
|
||||
golang.org/x/text v0.15.0 // indirect
|
||||
golang.org/x/tools v0.21.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect
|
||||
google.golang.org/grpc v1.62.0 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
||||
golang.org/x/net v0.28.0 // indirect
|
||||
golang.org/x/text v0.17.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect
|
||||
google.golang.org/grpc v1.65.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
65
go.sum
65
go.sum
@ -2,8 +2,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/Microsoft/hcsshim v0.12.4 h1:Ev7YUMHAHoWNm+aDSPzc5W9s6E2jyL1szpVDJeZ/Rr4=
|
||||
github.com/Microsoft/hcsshim v0.12.4/go.mod h1:Iyl1WVpZzr+UkzjekHZbV8o5Z9ZkxNGx6CtY2Qg/JVQ=
|
||||
github.com/Microsoft/hcsshim v0.12.6 h1:qEnZjoHXv+4/s0LmKZWE0/AiZmMWEIkFfWBSf1a0wlU=
|
||||
github.com/Microsoft/hcsshim v0.12.6/go.mod h1:ZABCLVcvLMjIkzr9rUGcQ1QA0p0P3Ps+d3N1g2DsFfk=
|
||||
github.com/alexflint/go-filemutex v1.3.0 h1:LgE+nTUWnQCyRKbpoceKZsPQbs84LivvgwUymZXdOcM=
|
||||
github.com/alexflint/go-filemutex v1.3.0/go.mod h1:U0+VA/i30mGBlLCrFPGtTe9y6wGQfNAWPBTekHQ+c8A=
|
||||
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||
@ -14,8 +14,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0=
|
||||
github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE=
|
||||
github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0=
|
||||
github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0=
|
||||
github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM=
|
||||
github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0=
|
||||
github.com/containernetworking/cni v1.1.2 h1:wtRGZVv7olUHMOqouPpn3cXJWpJgM6+EUl31EQbXALQ=
|
||||
@ -41,8 +41,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
@ -66,8 +66,6 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
@ -78,8 +76,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg=
|
||||
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
||||
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=
|
||||
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
@ -93,13 +91,13 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
|
||||
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
||||
github.com/onsi/ginkgo/v2 v2.20.1 h1:YlVIbqct+ZmnEph770q9Q7NVAz4wwIiVNahee6JyUzo=
|
||||
github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
||||
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
|
||||
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
||||
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
||||
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
|
||||
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@ -121,9 +119,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs=
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk=
|
||||
github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
|
||||
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@ -134,6 +132,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
@ -151,8 +151,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
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.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -167,9 +167,7 @@ golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -177,15 +175,18 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
|
||||
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
@ -194,8 +195,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
|
||||
golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@ -205,15 +206,15 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk=
|
||||
google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
|
||||
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@ -225,8 +226,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
|
@ -50,3 +50,16 @@ func AddDefaultRoute(gw net.IP, dev netlink.Link) error {
|
||||
}
|
||||
return AddRoute(defNet, gw, dev)
|
||||
}
|
||||
|
||||
// IsIPNetZero check if the IPNet is "0.0.0.0/0" or "::/0"
|
||||
// This is needed as go-netlink replaces nil Dst with a '0' IPNet since
|
||||
// https://github.com/vishvananda/netlink/commit/acdc658b8613655ddb69f978e9fb4cf413e2b830
|
||||
func IsIPNetZero(ipnet *net.IPNet) bool {
|
||||
if ipnet == nil {
|
||||
return true
|
||||
}
|
||||
if ones, _ := ipnet.Mask.Size(); ones != 0 {
|
||||
return false
|
||||
}
|
||||
return ipnet.IP.Equal(net.IPv4zero) || ipnet.IP.Equal(net.IPv6zero)
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ func DeleteConntrackEntriesForDstIP(dstIP string, protocol uint8) error {
|
||||
filter.AddIP(netlink.ConntrackOrigDstIP, ip)
|
||||
filter.AddProtocol(protocol)
|
||||
|
||||
_, err := netlink.ConntrackDeleteFilter(netlink.ConntrackTable, family, filter)
|
||||
_, err := netlink.ConntrackDeleteFilters(netlink.ConntrackTable, family, filter)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting connection tracking state for protocol: %d IP: %s, error: %v", protocol, ip, err)
|
||||
}
|
||||
@ -65,7 +65,7 @@ func DeleteConntrackEntriesForDstPort(port uint16, protocol uint8, family netlin
|
||||
filter.AddProtocol(protocol)
|
||||
filter.AddPort(netlink.ConntrackOrigDstPort, port)
|
||||
|
||||
_, err := netlink.ConntrackDeleteFilter(netlink.ConntrackTable, family, filter)
|
||||
_, err := netlink.ConntrackDeleteFilters(netlink.ConntrackTable, family, filter)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting connection tracking state for protocol: %d Port: %d, error: %v", protocol, port, err)
|
||||
}
|
||||
|
@ -724,7 +724,7 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result,
|
||||
continue
|
||||
}
|
||||
for _, route := range routes {
|
||||
*found = (route.Dst == nil && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
*found = (ip.IsIPNetZero(route.Dst) && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
if *found {
|
||||
break
|
||||
}
|
||||
@ -809,7 +809,7 @@ func (tester *testerV10x) cmdCheckTest(tc testCase, conf *Net, _ string) {
|
||||
continue
|
||||
}
|
||||
for _, route := range routes {
|
||||
*found = (route.Dst == nil && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
*found = (ip.IsIPNetZero(route.Dst) && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
if *found {
|
||||
break
|
||||
}
|
||||
@ -1059,7 +1059,7 @@ func (tester *testerV04x) cmdAddTest(tc testCase, dataDir string) (types.Result,
|
||||
continue
|
||||
}
|
||||
for _, route := range routes {
|
||||
*found = (route.Dst == nil && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
*found = (ip.IsIPNetZero(route.Dst) && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
if *found {
|
||||
break
|
||||
}
|
||||
@ -1143,7 +1143,7 @@ func (tester *testerV04x) cmdCheckTest(tc testCase, conf *Net, _ string) {
|
||||
continue
|
||||
}
|
||||
for _, route := range routes {
|
||||
*found = (route.Dst == nil && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
*found = (ip.IsIPNetZero(route.Dst) && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
if *found {
|
||||
break
|
||||
}
|
||||
@ -1391,7 +1391,7 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) (types.Result,
|
||||
continue
|
||||
}
|
||||
for _, route := range routes {
|
||||
*found = (route.Dst == nil && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
*found = (ip.IsIPNetZero(route.Dst) && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
if *found {
|
||||
break
|
||||
}
|
||||
@ -1612,7 +1612,7 @@ func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) (types.Re
|
||||
continue
|
||||
}
|
||||
for _, route := range routes {
|
||||
*found = (route.Dst == nil && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
*found = (ip.IsIPNetZero(route.Dst) && route.Src == nil && route.Gw.Equal(gwIP))
|
||||
if *found {
|
||||
break
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ func getDefaultRouteInterfaceName() (string, error) {
|
||||
}
|
||||
|
||||
for _, v := range routeToDstIP {
|
||||
if v.Dst == nil {
|
||||
if ip.IsIPNetZero(v.Dst) {
|
||||
l, err := netlink.LinkByIndex(v.LinkIndex)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -67,7 +67,7 @@ func getDefaultRouteInterfaceName() (string, error) {
|
||||
}
|
||||
|
||||
for _, v := range routeToDstIP {
|
||||
if v.Dst == nil {
|
||||
if ip.IsIPNetZero(v.Dst) {
|
||||
l, err := netlink.LinkByIndex(v.LinkIndex)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -291,6 +291,7 @@ var _ = Describe("sbr test", func() {
|
||||
expNet1.Routes = append(expNet1.Routes,
|
||||
netlink.Route{
|
||||
Gw: net.IPv4(192, 168, 1, 1),
|
||||
Dst: &net.IPNet{IP: net.IPv4zero, Mask: net.IPMask(net.IPv4zero)},
|
||||
Table: 100,
|
||||
LinkIndex: expNet1.Routes[0].LinkIndex,
|
||||
})
|
||||
@ -491,6 +492,7 @@ var _ = Describe("sbr test", func() {
|
||||
}
|
||||
expNet1.Routes = append(expNet1.Routes,
|
||||
netlink.Route{
|
||||
Dst: &net.IPNet{IP: net.IPv4zero, Mask: net.IPMask(net.IPv4zero)},
|
||||
Gw: net.IPv4(192, 168, 1, 1),
|
||||
Table: 100,
|
||||
LinkIndex: expNet1.Routes[0].LinkIndex,
|
||||
@ -498,6 +500,7 @@ var _ = Describe("sbr test", func() {
|
||||
|
||||
expNet1.Routes = append(expNet1.Routes,
|
||||
netlink.Route{
|
||||
Dst: &net.IPNet{IP: net.IPv4zero, Mask: net.IPMask(net.IPv4zero)},
|
||||
Gw: net.IPv4(192, 168, 101, 1),
|
||||
Table: 101,
|
||||
LinkIndex: expNet1.Routes[0].LinkIndex,
|
||||
|
12
vendor/github.com/Microsoft/hcsshim/hcn/hcn.go
generated
vendored
12
vendor/github.com/Microsoft/hcsshim/hcn/hcn.go
generated
vendored
@ -336,6 +336,18 @@ func DisableHostPortSupported() error {
|
||||
return platformDoesNotSupportError("DisableHostPort")
|
||||
}
|
||||
|
||||
// AccelnetSupported returns an error if the HCN version does not support Accelnet Feature.
|
||||
func AccelnetSupported() error {
|
||||
supported, err := GetCachedSupportedFeatures()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if supported.Accelnet {
|
||||
return nil
|
||||
}
|
||||
return platformDoesNotSupportError("Accelnet")
|
||||
}
|
||||
|
||||
// RequestType are the different operations performed to settings.
|
||||
// Used to update the settings of Endpoint/Namespace objects.
|
||||
type RequestType string
|
||||
|
2
vendor/github.com/Microsoft/hcsshim/hcn/hcnglobals.go
generated
vendored
2
vendor/github.com/Microsoft/hcsshim/hcn/hcnglobals.go
generated
vendored
@ -89,6 +89,8 @@ var (
|
||||
DisableHostPortVersion = VersionRanges{VersionRange{MinVersion: Version{Major: 15, Minor: 1}, MaxVersion: Version{Major: math.MaxInt32, Minor: math.MaxInt32}}}
|
||||
// HNS 15.4 allows for Modify Loadbalancer support
|
||||
ModifyLoadbalancerVersion = VersionRanges{VersionRange{MinVersion: Version{Major: 15, Minor: 4}, MaxVersion: Version{Major: math.MaxInt32, Minor: math.MaxInt32}}}
|
||||
// HNS 15.4 allows for Accelnet support
|
||||
AccelnetVersion = VersionRanges{VersionRange{MinVersion: Version{Major: 15, Minor: 4}, MaxVersion: Version{Major: math.MaxInt32, Minor: math.MaxInt32}}}
|
||||
)
|
||||
|
||||
// GetGlobals returns the global properties of the HCN Service.
|
||||
|
1
vendor/github.com/Microsoft/hcsshim/hcn/hcnnetwork.go
generated
vendored
1
vendor/github.com/Microsoft/hcsshim/hcn/hcnnetwork.go
generated
vendored
@ -73,6 +73,7 @@ const (
|
||||
None NetworkFlags = 0
|
||||
EnableNonPersistent NetworkFlags = 8
|
||||
DisableHostPort NetworkFlags = 1024
|
||||
EnableIov NetworkFlags = 8192
|
||||
)
|
||||
|
||||
// HostComputeNetwork represents a network
|
||||
|
2
vendor/github.com/Microsoft/hcsshim/hcn/hcnsupport.go
generated
vendored
2
vendor/github.com/Microsoft/hcsshim/hcn/hcnsupport.go
generated
vendored
@ -39,6 +39,7 @@ type SupportedFeatures struct {
|
||||
NestedIpSet bool `json:"NestedIpSet"`
|
||||
DisableHostPort bool `json:"DisableHostPort"`
|
||||
ModifyLoadbalancer bool `json:"ModifyLoadbalancer"`
|
||||
Accelnet bool `json:"Accelnet"`
|
||||
}
|
||||
|
||||
// AclFeatures are the supported ACL possibilities.
|
||||
@ -118,6 +119,7 @@ func getSupportedFeatures() (SupportedFeatures, error) {
|
||||
features.NestedIpSet = isFeatureSupported(globals.Version, NestedIpSetVersion)
|
||||
features.DisableHostPort = isFeatureSupported(globals.Version, DisableHostPortVersion)
|
||||
features.ModifyLoadbalancer = isFeatureSupported(globals.Version, ModifyLoadbalancerVersion)
|
||||
features.Accelnet = isFeatureSupported(globals.Version, AccelnetVersion)
|
||||
|
||||
log.L.WithFields(logrus.Fields{
|
||||
"version": globals.Version,
|
||||
|
46
vendor/github.com/Microsoft/hcsshim/hnsaccelnet.go
generated
vendored
Normal file
46
vendor/github.com/Microsoft/hcsshim/hnsaccelnet.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
//go:build windows
|
||||
|
||||
package hcsshim
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Microsoft/hcsshim/internal/hns"
|
||||
)
|
||||
|
||||
// HNSNnvManagementMacAddress represents management mac address
|
||||
// which needs to be excluded from VF reassignment
|
||||
type HNSNnvManagementMacAddress = hns.HNSNnvManagementMacAddress
|
||||
|
||||
// HNSNnvManagementMacList represents a list of management
|
||||
// mac addresses for exclusion from VF reassignment
|
||||
type HNSNnvManagementMacList = hns.HNSNnvManagementMacList
|
||||
|
||||
var (
|
||||
ErrorEmptyMacAddressList = errors.New("management mac_address list is empty")
|
||||
)
|
||||
|
||||
// SetNnvManagementMacAddresses sets a list of
|
||||
// management mac addresses in hns for exclusion from VF reassignment.
|
||||
func SetNnvManagementMacAddresses(managementMacAddresses []string) (*HNSNnvManagementMacList, error) {
|
||||
if len(managementMacAddresses) == 0 {
|
||||
return nil, ErrorEmptyMacAddressList
|
||||
}
|
||||
nnvManagementMacList := &HNSNnvManagementMacList{}
|
||||
for _, mac := range managementMacAddresses {
|
||||
nnvManagementMacList.MacAddressList = append(nnvManagementMacList.MacAddressList, HNSNnvManagementMacAddress{MacAddress: mac})
|
||||
}
|
||||
return nnvManagementMacList.Set()
|
||||
}
|
||||
|
||||
// GetNnvManagementMacAddresses retrieves a list of
|
||||
// management mac addresses in hns for exclusion from VF reassignment.
|
||||
func GetNnvManagementMacAddresses() (*HNSNnvManagementMacList, error) {
|
||||
return hns.GetNnvManagementMacAddressList()
|
||||
}
|
||||
|
||||
// DeleteNnvManagementMacAddresses delete list of
|
||||
// management mac addresses in hns which are excluded from VF reassignment.
|
||||
func DeleteNnvManagementMacAddresses() (*HNSNnvManagementMacList, error) {
|
||||
return hns.DeleteNnvManagementMacAddressList()
|
||||
}
|
60
vendor/github.com/Microsoft/hcsshim/internal/hns/hnsaccelnet.go
generated
vendored
Normal file
60
vendor/github.com/Microsoft/hcsshim/internal/hns/hnsaccelnet.go
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
//go:build windows
|
||||
|
||||
package hns
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// HNSNnvManagementMacAddress represents management mac address
|
||||
// which needs to be excluded from VF reassignment
|
||||
type HNSNnvManagementMacAddress struct {
|
||||
MacAddress string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// HNSNnvManagementMacList represents a list of management
|
||||
// mac addresses for exclusion from VF reassignment
|
||||
type HNSNnvManagementMacList struct {
|
||||
MacAddressList []HNSNnvManagementMacAddress `json:",omitempty"`
|
||||
}
|
||||
|
||||
// HNSNnvManagementMacRequest makes a HNS call to modify/query NnvManagementMacList
|
||||
func HNSNnvManagementMacRequest(method, path, request string) (*HNSNnvManagementMacList, error) {
|
||||
nnvManagementMacList := &HNSNnvManagementMacList{}
|
||||
err := hnsCall(method, "/accelnet/"+path, request, &nnvManagementMacList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nnvManagementMacList, nil
|
||||
}
|
||||
|
||||
// Set ManagementMacAddressList by sending "POST" NnvManagementMacRequest to HNS.
|
||||
func (nnvManagementMacList *HNSNnvManagementMacList) Set() (*HNSNnvManagementMacList, error) {
|
||||
operation := "Set"
|
||||
title := "hcsshim::nnvManagementMacList::" + operation
|
||||
logrus.Debugf(title+" id=%s", nnvManagementMacList.MacAddressList)
|
||||
|
||||
jsonString, err := json.Marshal(nnvManagementMacList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return HNSNnvManagementMacRequest("POST", "", string(jsonString))
|
||||
}
|
||||
|
||||
// Get ManagementMacAddressList by sending "GET" NnvManagementMacRequest to HNS.
|
||||
func GetNnvManagementMacAddressList() (*HNSNnvManagementMacList, error) {
|
||||
operation := "Get"
|
||||
title := "hcsshim::nnvManagementMacList::" + operation
|
||||
logrus.Debugf(title)
|
||||
return HNSNnvManagementMacRequest("GET", "", "")
|
||||
}
|
||||
|
||||
// Delete ManagementMacAddressList by sending "DELETE" NnvManagementMacRequest to HNS.
|
||||
func DeleteNnvManagementMacAddressList() (*HNSNnvManagementMacList, error) {
|
||||
operation := "Delete"
|
||||
title := "hcsshim::nnvManagementMacList::" + operation
|
||||
logrus.Debugf(title)
|
||||
return HNSNnvManagementMacRequest("DELETE", "", "")
|
||||
}
|
23
vendor/github.com/Microsoft/hcsshim/internal/hns/hnsendpoint.go
generated
vendored
23
vendor/github.com/Microsoft/hcsshim/internal/hns/hnsendpoint.go
generated
vendored
@ -10,6 +10,28 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// EndpointState represents the states of an HNS Endpoint lifecycle.
|
||||
type EndpointState uint16
|
||||
|
||||
// EndpointState const
|
||||
// The lifecycle of an Endpoint goes through created, attached, AttachedSharing - endpoint is being shared with other containers,
|
||||
// detached, after being attached, degraded and finally destroyed.
|
||||
// Note: This attribute is used by calico to define stale containers and is dependent on HNS v1 api, if we move to HNS v2 api we will need
|
||||
// to update the current calico code and cordinate the change with calico. Reach out to Microsoft to facilate the change via HNS.
|
||||
const (
|
||||
Uninitialized EndpointState = iota
|
||||
Created EndpointState = 1
|
||||
Attached EndpointState = 2
|
||||
AttachedSharing EndpointState = 3
|
||||
Detached EndpointState = 4
|
||||
Degraded EndpointState = 5
|
||||
Destroyed EndpointState = 6
|
||||
)
|
||||
|
||||
func (es EndpointState) String() string {
|
||||
return [...]string{"Uninitialized", "Attached", "AttachedSharing", "Detached", "Degraded", "Destroyed"}[es]
|
||||
}
|
||||
|
||||
// HNSEndpoint represents a network endpoint in HNS
|
||||
type HNSEndpoint struct {
|
||||
Id string `json:"ID,omitempty"`
|
||||
@ -34,6 +56,7 @@ type HNSEndpoint struct {
|
||||
Namespace *Namespace `json:",omitempty"`
|
||||
EncapOverhead uint16 `json:",omitempty"`
|
||||
SharedContainers []string `json:",omitempty"`
|
||||
State EndpointState `json:",omitempty"`
|
||||
}
|
||||
|
||||
// SystemType represents the type of the system on which actions are done
|
||||
|
1
vendor/github.com/go-logr/logr/README.md
generated
vendored
1
vendor/github.com/go-logr/logr/README.md
generated
vendored
@ -1,6 +1,7 @@
|
||||
# A minimal logging API for Go
|
||||
|
||||
[](https://pkg.go.dev/github.com/go-logr/logr)
|
||||
[](https://goreportcard.com/report/github.com/go-logr/logr)
|
||||
[](https://securityscorecards.dev/viewer/?platform=github.com&org=go-logr&repo=logr)
|
||||
|
||||
logr offers an(other) opinion on how Go programs and libraries can do logging
|
||||
|
185
vendor/github.com/go-logr/logr/funcr/funcr.go
generated
vendored
185
vendor/github.com/go-logr/logr/funcr/funcr.go
generated
vendored
@ -236,15 +236,14 @@ func newFormatter(opts Options, outfmt outputFormat) Formatter {
|
||||
// implementation. It should be constructed with NewFormatter. Some of
|
||||
// its methods directly implement logr.LogSink.
|
||||
type Formatter struct {
|
||||
outputFormat outputFormat
|
||||
prefix string
|
||||
values []any
|
||||
valuesStr string
|
||||
parentValuesStr string
|
||||
depth int
|
||||
opts *Options
|
||||
group string // for slog groups
|
||||
groupDepth int
|
||||
outputFormat outputFormat
|
||||
prefix string
|
||||
values []any
|
||||
valuesStr string
|
||||
depth int
|
||||
opts *Options
|
||||
groupName string // for slog groups
|
||||
groups []groupDef
|
||||
}
|
||||
|
||||
// outputFormat indicates which outputFormat to use.
|
||||
@ -257,6 +256,13 @@ const (
|
||||
outputJSON
|
||||
)
|
||||
|
||||
// groupDef represents a saved group. The values may be empty, but we don't
|
||||
// know if we need to render the group until the final record is rendered.
|
||||
type groupDef struct {
|
||||
name string
|
||||
values string
|
||||
}
|
||||
|
||||
// PseudoStruct is a list of key-value pairs that gets logged as a struct.
|
||||
type PseudoStruct []any
|
||||
|
||||
@ -264,76 +270,102 @@ type PseudoStruct []any
|
||||
func (f Formatter) render(builtins, args []any) string {
|
||||
// Empirically bytes.Buffer is faster than strings.Builder for this.
|
||||
buf := bytes.NewBuffer(make([]byte, 0, 1024))
|
||||
|
||||
if f.outputFormat == outputJSON {
|
||||
buf.WriteByte('{') // for the whole line
|
||||
buf.WriteByte('{') // for the whole record
|
||||
}
|
||||
|
||||
// Render builtins
|
||||
vals := builtins
|
||||
if hook := f.opts.RenderBuiltinsHook; hook != nil {
|
||||
vals = hook(f.sanitize(vals))
|
||||
}
|
||||
f.flatten(buf, vals, false, false) // keys are ours, no need to escape
|
||||
f.flatten(buf, vals, false) // keys are ours, no need to escape
|
||||
continuing := len(builtins) > 0
|
||||
|
||||
if f.parentValuesStr != "" {
|
||||
// Turn the inner-most group into a string
|
||||
argsStr := func() string {
|
||||
buf := bytes.NewBuffer(make([]byte, 0, 1024))
|
||||
|
||||
vals = args
|
||||
if hook := f.opts.RenderArgsHook; hook != nil {
|
||||
vals = hook(f.sanitize(vals))
|
||||
}
|
||||
f.flatten(buf, vals, true) // escape user-provided keys
|
||||
|
||||
return buf.String()
|
||||
}()
|
||||
|
||||
// Render the stack of groups from the inside out.
|
||||
bodyStr := f.renderGroup(f.groupName, f.valuesStr, argsStr)
|
||||
for i := len(f.groups) - 1; i >= 0; i-- {
|
||||
grp := &f.groups[i]
|
||||
if grp.values == "" && bodyStr == "" {
|
||||
// no contents, so we must elide the whole group
|
||||
continue
|
||||
}
|
||||
bodyStr = f.renderGroup(grp.name, grp.values, bodyStr)
|
||||
}
|
||||
|
||||
if bodyStr != "" {
|
||||
if continuing {
|
||||
buf.WriteByte(f.comma())
|
||||
}
|
||||
buf.WriteString(f.parentValuesStr)
|
||||
continuing = true
|
||||
}
|
||||
|
||||
groupDepth := f.groupDepth
|
||||
if f.group != "" {
|
||||
if f.valuesStr != "" || len(args) != 0 {
|
||||
if continuing {
|
||||
buf.WriteByte(f.comma())
|
||||
}
|
||||
buf.WriteString(f.quoted(f.group, true)) // escape user-provided keys
|
||||
buf.WriteByte(f.colon())
|
||||
buf.WriteByte('{') // for the group
|
||||
continuing = false
|
||||
} else {
|
||||
// The group was empty
|
||||
groupDepth--
|
||||
}
|
||||
}
|
||||
|
||||
if f.valuesStr != "" {
|
||||
if continuing {
|
||||
buf.WriteByte(f.comma())
|
||||
}
|
||||
buf.WriteString(f.valuesStr)
|
||||
continuing = true
|
||||
}
|
||||
|
||||
vals = args
|
||||
if hook := f.opts.RenderArgsHook; hook != nil {
|
||||
vals = hook(f.sanitize(vals))
|
||||
}
|
||||
f.flatten(buf, vals, continuing, true) // escape user-provided keys
|
||||
|
||||
for i := 0; i < groupDepth; i++ {
|
||||
buf.WriteByte('}') // for the groups
|
||||
buf.WriteString(bodyStr)
|
||||
}
|
||||
|
||||
if f.outputFormat == outputJSON {
|
||||
buf.WriteByte('}') // for the whole line
|
||||
buf.WriteByte('}') // for the whole record
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// flatten renders a list of key-value pairs into a buffer. If continuing is
|
||||
// true, it assumes that the buffer has previous values and will emit a
|
||||
// separator (which depends on the output format) before the first pair it
|
||||
// writes. If escapeKeys is true, the keys are assumed to have
|
||||
// non-JSON-compatible characters in them and must be evaluated for escapes.
|
||||
// renderGroup returns a string representation of the named group with rendered
|
||||
// values and args. If the name is empty, this will return the values and args,
|
||||
// joined. If the name is not empty, this will return a single key-value pair,
|
||||
// where the value is a grouping of the values and args. If the values and
|
||||
// args are both empty, this will return an empty string, even if the name was
|
||||
// specified.
|
||||
func (f Formatter) renderGroup(name string, values string, args string) string {
|
||||
buf := bytes.NewBuffer(make([]byte, 0, 1024))
|
||||
|
||||
needClosingBrace := false
|
||||
if name != "" && (values != "" || args != "") {
|
||||
buf.WriteString(f.quoted(name, true)) // escape user-provided keys
|
||||
buf.WriteByte(f.colon())
|
||||
buf.WriteByte('{')
|
||||
needClosingBrace = true
|
||||
}
|
||||
|
||||
continuing := false
|
||||
if values != "" {
|
||||
buf.WriteString(values)
|
||||
continuing = true
|
||||
}
|
||||
|
||||
if args != "" {
|
||||
if continuing {
|
||||
buf.WriteByte(f.comma())
|
||||
}
|
||||
buf.WriteString(args)
|
||||
}
|
||||
|
||||
if needClosingBrace {
|
||||
buf.WriteByte('}')
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// flatten renders a list of key-value pairs into a buffer. If escapeKeys is
|
||||
// true, the keys are assumed to have non-JSON-compatible characters in them
|
||||
// and must be evaluated for escapes.
|
||||
//
|
||||
// This function returns a potentially modified version of kvList, which
|
||||
// ensures that there is a value for every key (adding a value if needed) and
|
||||
// that each key is a string (substituting a key if needed).
|
||||
func (f Formatter) flatten(buf *bytes.Buffer, kvList []any, continuing bool, escapeKeys bool) []any {
|
||||
func (f Formatter) flatten(buf *bytes.Buffer, kvList []any, escapeKeys bool) []any {
|
||||
// This logic overlaps with sanitize() but saves one type-cast per key,
|
||||
// which can be measurable.
|
||||
if len(kvList)%2 != 0 {
|
||||
@ -354,7 +386,7 @@ func (f Formatter) flatten(buf *bytes.Buffer, kvList []any, continuing bool, esc
|
||||
}
|
||||
v := kvList[i+1]
|
||||
|
||||
if i > 0 || continuing {
|
||||
if i > 0 {
|
||||
if f.outputFormat == outputJSON {
|
||||
buf.WriteByte(f.comma())
|
||||
} else {
|
||||
@ -766,46 +798,17 @@ func (f Formatter) sanitize(kvList []any) []any {
|
||||
// startGroup opens a new group scope (basically a sub-struct), which locks all
|
||||
// the current saved values and starts them anew. This is needed to satisfy
|
||||
// slog.
|
||||
func (f *Formatter) startGroup(group string) {
|
||||
func (f *Formatter) startGroup(name string) {
|
||||
// Unnamed groups are just inlined.
|
||||
if group == "" {
|
||||
if name == "" {
|
||||
return
|
||||
}
|
||||
|
||||
// Any saved values can no longer be changed.
|
||||
buf := bytes.NewBuffer(make([]byte, 0, 1024))
|
||||
continuing := false
|
||||
|
||||
if f.parentValuesStr != "" {
|
||||
buf.WriteString(f.parentValuesStr)
|
||||
continuing = true
|
||||
}
|
||||
|
||||
if f.group != "" && f.valuesStr != "" {
|
||||
if continuing {
|
||||
buf.WriteByte(f.comma())
|
||||
}
|
||||
buf.WriteString(f.quoted(f.group, true)) // escape user-provided keys
|
||||
buf.WriteByte(f.colon())
|
||||
buf.WriteByte('{') // for the group
|
||||
continuing = false
|
||||
}
|
||||
|
||||
if f.valuesStr != "" {
|
||||
if continuing {
|
||||
buf.WriteByte(f.comma())
|
||||
}
|
||||
buf.WriteString(f.valuesStr)
|
||||
}
|
||||
|
||||
// NOTE: We don't close the scope here - that's done later, when a log line
|
||||
// is actually rendered (because we have N scopes to close).
|
||||
|
||||
f.parentValuesStr = buf.String()
|
||||
n := len(f.groups)
|
||||
f.groups = append(f.groups[:n:n], groupDef{f.groupName, f.valuesStr})
|
||||
|
||||
// Start collecting new values.
|
||||
f.group = group
|
||||
f.groupDepth++
|
||||
f.groupName = name
|
||||
f.valuesStr = ""
|
||||
f.values = nil
|
||||
}
|
||||
@ -900,7 +903,7 @@ func (f *Formatter) AddValues(kvList []any) {
|
||||
|
||||
// Pre-render values, so we don't have to do it on each Info/Error call.
|
||||
buf := bytes.NewBuffer(make([]byte, 0, 1024))
|
||||
f.flatten(buf, vals, false, true) // escape user-provided keys
|
||||
f.flatten(buf, vals, true) // escape user-provided keys
|
||||
f.valuesStr = buf.String()
|
||||
}
|
||||
|
||||
|
3
vendor/github.com/golang/protobuf/AUTHORS
generated
vendored
3
vendor/github.com/golang/protobuf/AUTHORS
generated
vendored
@ -1,3 +0,0 @@
|
||||
# This source code refers to The Go Authors for copyright purposes.
|
||||
# The master list of authors is in the main Go distribution,
|
||||
# visible at http://tip.golang.org/AUTHORS.
|
3
vendor/github.com/golang/protobuf/CONTRIBUTORS
generated
vendored
3
vendor/github.com/golang/protobuf/CONTRIBUTORS
generated
vendored
@ -1,3 +0,0 @@
|
||||
# This source code was written by the Go contributors.
|
||||
# The master list of contributors is in the main Go distribution,
|
||||
# visible at http://tip.golang.org/CONTRIBUTORS.
|
324
vendor/github.com/golang/protobuf/proto/buffer.go
generated
vendored
324
vendor/github.com/golang/protobuf/proto/buffer.go
generated
vendored
@ -1,324 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/protobuf/encoding/prototext"
|
||||
"google.golang.org/protobuf/encoding/protowire"
|
||||
"google.golang.org/protobuf/runtime/protoimpl"
|
||||
)
|
||||
|
||||
const (
|
||||
WireVarint = 0
|
||||
WireFixed32 = 5
|
||||
WireFixed64 = 1
|
||||
WireBytes = 2
|
||||
WireStartGroup = 3
|
||||
WireEndGroup = 4
|
||||
)
|
||||
|
||||
// EncodeVarint returns the varint encoded bytes of v.
|
||||
func EncodeVarint(v uint64) []byte {
|
||||
return protowire.AppendVarint(nil, v)
|
||||
}
|
||||
|
||||
// SizeVarint returns the length of the varint encoded bytes of v.
|
||||
// This is equal to len(EncodeVarint(v)).
|
||||
func SizeVarint(v uint64) int {
|
||||
return protowire.SizeVarint(v)
|
||||
}
|
||||
|
||||
// DecodeVarint parses a varint encoded integer from b,
|
||||
// returning the integer value and the length of the varint.
|
||||
// It returns (0, 0) if there is a parse error.
|
||||
func DecodeVarint(b []byte) (uint64, int) {
|
||||
v, n := protowire.ConsumeVarint(b)
|
||||
if n < 0 {
|
||||
return 0, 0
|
||||
}
|
||||
return v, n
|
||||
}
|
||||
|
||||
// Buffer is a buffer for encoding and decoding the protobuf wire format.
|
||||
// It may be reused between invocations to reduce memory usage.
|
||||
type Buffer struct {
|
||||
buf []byte
|
||||
idx int
|
||||
deterministic bool
|
||||
}
|
||||
|
||||
// NewBuffer allocates a new Buffer initialized with buf,
|
||||
// where the contents of buf are considered the unread portion of the buffer.
|
||||
func NewBuffer(buf []byte) *Buffer {
|
||||
return &Buffer{buf: buf}
|
||||
}
|
||||
|
||||
// SetDeterministic specifies whether to use deterministic serialization.
|
||||
//
|
||||
// Deterministic serialization guarantees that for a given binary, equal
|
||||
// messages will always be serialized to the same bytes. This implies:
|
||||
//
|
||||
// - Repeated serialization of a message will return the same bytes.
|
||||
// - Different processes of the same binary (which may be executing on
|
||||
// different machines) will serialize equal messages to the same bytes.
|
||||
//
|
||||
// Note that the deterministic serialization is NOT canonical across
|
||||
// languages. It is not guaranteed to remain stable over time. It is unstable
|
||||
// across different builds with schema changes due to unknown fields.
|
||||
// Users who need canonical serialization (e.g., persistent storage in a
|
||||
// canonical form, fingerprinting, etc.) should define their own
|
||||
// canonicalization specification and implement their own serializer rather
|
||||
// than relying on this API.
|
||||
//
|
||||
// If deterministic serialization is requested, map entries will be sorted
|
||||
// by keys in lexographical order. This is an implementation detail and
|
||||
// subject to change.
|
||||
func (b *Buffer) SetDeterministic(deterministic bool) {
|
||||
b.deterministic = deterministic
|
||||
}
|
||||
|
||||
// SetBuf sets buf as the internal buffer,
|
||||
// where the contents of buf are considered the unread portion of the buffer.
|
||||
func (b *Buffer) SetBuf(buf []byte) {
|
||||
b.buf = buf
|
||||
b.idx = 0
|
||||
}
|
||||
|
||||
// Reset clears the internal buffer of all written and unread data.
|
||||
func (b *Buffer) Reset() {
|
||||
b.buf = b.buf[:0]
|
||||
b.idx = 0
|
||||
}
|
||||
|
||||
// Bytes returns the internal buffer.
|
||||
func (b *Buffer) Bytes() []byte {
|
||||
return b.buf
|
||||
}
|
||||
|
||||
// Unread returns the unread portion of the buffer.
|
||||
func (b *Buffer) Unread() []byte {
|
||||
return b.buf[b.idx:]
|
||||
}
|
||||
|
||||
// Marshal appends the wire-format encoding of m to the buffer.
|
||||
func (b *Buffer) Marshal(m Message) error {
|
||||
var err error
|
||||
b.buf, err = marshalAppend(b.buf, m, b.deterministic)
|
||||
return err
|
||||
}
|
||||
|
||||
// Unmarshal parses the wire-format message in the buffer and
|
||||
// places the decoded results in m.
|
||||
// It does not reset m before unmarshaling.
|
||||
func (b *Buffer) Unmarshal(m Message) error {
|
||||
err := UnmarshalMerge(b.Unread(), m)
|
||||
b.idx = len(b.buf)
|
||||
return err
|
||||
}
|
||||
|
||||
type unknownFields struct{ XXX_unrecognized protoimpl.UnknownFields }
|
||||
|
||||
func (m *unknownFields) String() string { panic("not implemented") }
|
||||
func (m *unknownFields) Reset() { panic("not implemented") }
|
||||
func (m *unknownFields) ProtoMessage() { panic("not implemented") }
|
||||
|
||||
// DebugPrint dumps the encoded bytes of b with a header and footer including s
|
||||
// to stdout. This is only intended for debugging.
|
||||
func (*Buffer) DebugPrint(s string, b []byte) {
|
||||
m := MessageReflect(new(unknownFields))
|
||||
m.SetUnknown(b)
|
||||
b, _ = prototext.MarshalOptions{AllowPartial: true, Indent: "\t"}.Marshal(m.Interface())
|
||||
fmt.Printf("==== %s ====\n%s==== %s ====\n", s, b, s)
|
||||
}
|
||||
|
||||
// EncodeVarint appends an unsigned varint encoding to the buffer.
|
||||
func (b *Buffer) EncodeVarint(v uint64) error {
|
||||
b.buf = protowire.AppendVarint(b.buf, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeZigzag32 appends a 32-bit zig-zag varint encoding to the buffer.
|
||||
func (b *Buffer) EncodeZigzag32(v uint64) error {
|
||||
return b.EncodeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31))))
|
||||
}
|
||||
|
||||
// EncodeZigzag64 appends a 64-bit zig-zag varint encoding to the buffer.
|
||||
func (b *Buffer) EncodeZigzag64(v uint64) error {
|
||||
return b.EncodeVarint(uint64((uint64(v) << 1) ^ uint64((int64(v) >> 63))))
|
||||
}
|
||||
|
||||
// EncodeFixed32 appends a 32-bit little-endian integer to the buffer.
|
||||
func (b *Buffer) EncodeFixed32(v uint64) error {
|
||||
b.buf = protowire.AppendFixed32(b.buf, uint32(v))
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeFixed64 appends a 64-bit little-endian integer to the buffer.
|
||||
func (b *Buffer) EncodeFixed64(v uint64) error {
|
||||
b.buf = protowire.AppendFixed64(b.buf, uint64(v))
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeRawBytes appends a length-prefixed raw bytes to the buffer.
|
||||
func (b *Buffer) EncodeRawBytes(v []byte) error {
|
||||
b.buf = protowire.AppendBytes(b.buf, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeStringBytes appends a length-prefixed raw bytes to the buffer.
|
||||
// It does not validate whether v contains valid UTF-8.
|
||||
func (b *Buffer) EncodeStringBytes(v string) error {
|
||||
b.buf = protowire.AppendString(b.buf, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeMessage appends a length-prefixed encoded message to the buffer.
|
||||
func (b *Buffer) EncodeMessage(m Message) error {
|
||||
var err error
|
||||
b.buf = protowire.AppendVarint(b.buf, uint64(Size(m)))
|
||||
b.buf, err = marshalAppend(b.buf, m, b.deterministic)
|
||||
return err
|
||||
}
|
||||
|
||||
// DecodeVarint consumes an encoded unsigned varint from the buffer.
|
||||
func (b *Buffer) DecodeVarint() (uint64, error) {
|
||||
v, n := protowire.ConsumeVarint(b.buf[b.idx:])
|
||||
if n < 0 {
|
||||
return 0, protowire.ParseError(n)
|
||||
}
|
||||
b.idx += n
|
||||
return uint64(v), nil
|
||||
}
|
||||
|
||||
// DecodeZigzag32 consumes an encoded 32-bit zig-zag varint from the buffer.
|
||||
func (b *Buffer) DecodeZigzag32() (uint64, error) {
|
||||
v, err := b.DecodeVarint()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64((uint32(v) >> 1) ^ uint32((int32(v&1)<<31)>>31)), nil
|
||||
}
|
||||
|
||||
// DecodeZigzag64 consumes an encoded 64-bit zig-zag varint from the buffer.
|
||||
func (b *Buffer) DecodeZigzag64() (uint64, error) {
|
||||
v, err := b.DecodeVarint()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64((uint64(v) >> 1) ^ uint64((int64(v&1)<<63)>>63)), nil
|
||||
}
|
||||
|
||||
// DecodeFixed32 consumes a 32-bit little-endian integer from the buffer.
|
||||
func (b *Buffer) DecodeFixed32() (uint64, error) {
|
||||
v, n := protowire.ConsumeFixed32(b.buf[b.idx:])
|
||||
if n < 0 {
|
||||
return 0, protowire.ParseError(n)
|
||||
}
|
||||
b.idx += n
|
||||
return uint64(v), nil
|
||||
}
|
||||
|
||||
// DecodeFixed64 consumes a 64-bit little-endian integer from the buffer.
|
||||
func (b *Buffer) DecodeFixed64() (uint64, error) {
|
||||
v, n := protowire.ConsumeFixed64(b.buf[b.idx:])
|
||||
if n < 0 {
|
||||
return 0, protowire.ParseError(n)
|
||||
}
|
||||
b.idx += n
|
||||
return uint64(v), nil
|
||||
}
|
||||
|
||||
// DecodeRawBytes consumes a length-prefixed raw bytes from the buffer.
|
||||
// If alloc is specified, it returns a copy the raw bytes
|
||||
// rather than a sub-slice of the buffer.
|
||||
func (b *Buffer) DecodeRawBytes(alloc bool) ([]byte, error) {
|
||||
v, n := protowire.ConsumeBytes(b.buf[b.idx:])
|
||||
if n < 0 {
|
||||
return nil, protowire.ParseError(n)
|
||||
}
|
||||
b.idx += n
|
||||
if alloc {
|
||||
v = append([]byte(nil), v...)
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// DecodeStringBytes consumes a length-prefixed raw bytes from the buffer.
|
||||
// It does not validate whether the raw bytes contain valid UTF-8.
|
||||
func (b *Buffer) DecodeStringBytes() (string, error) {
|
||||
v, n := protowire.ConsumeString(b.buf[b.idx:])
|
||||
if n < 0 {
|
||||
return "", protowire.ParseError(n)
|
||||
}
|
||||
b.idx += n
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// DecodeMessage consumes a length-prefixed message from the buffer.
|
||||
// It does not reset m before unmarshaling.
|
||||
func (b *Buffer) DecodeMessage(m Message) error {
|
||||
v, err := b.DecodeRawBytes(false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return UnmarshalMerge(v, m)
|
||||
}
|
||||
|
||||
// DecodeGroup consumes a message group from the buffer.
|
||||
// It assumes that the start group marker has already been consumed and
|
||||
// consumes all bytes until (and including the end group marker).
|
||||
// It does not reset m before unmarshaling.
|
||||
func (b *Buffer) DecodeGroup(m Message) error {
|
||||
v, n, err := consumeGroup(b.buf[b.idx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.idx += n
|
||||
return UnmarshalMerge(v, m)
|
||||
}
|
||||
|
||||
// consumeGroup parses b until it finds an end group marker, returning
|
||||
// the raw bytes of the message (excluding the end group marker) and the
|
||||
// the total length of the message (including the end group marker).
|
||||
func consumeGroup(b []byte) ([]byte, int, error) {
|
||||
b0 := b
|
||||
depth := 1 // assume this follows a start group marker
|
||||
for {
|
||||
_, wtyp, tagLen := protowire.ConsumeTag(b)
|
||||
if tagLen < 0 {
|
||||
return nil, 0, protowire.ParseError(tagLen)
|
||||
}
|
||||
b = b[tagLen:]
|
||||
|
||||
var valLen int
|
||||
switch wtyp {
|
||||
case protowire.VarintType:
|
||||
_, valLen = protowire.ConsumeVarint(b)
|
||||
case protowire.Fixed32Type:
|
||||
_, valLen = protowire.ConsumeFixed32(b)
|
||||
case protowire.Fixed64Type:
|
||||
_, valLen = protowire.ConsumeFixed64(b)
|
||||
case protowire.BytesType:
|
||||
_, valLen = protowire.ConsumeBytes(b)
|
||||
case protowire.StartGroupType:
|
||||
depth++
|
||||
case protowire.EndGroupType:
|
||||
depth--
|
||||
default:
|
||||
return nil, 0, errors.New("proto: cannot parse reserved wire type")
|
||||
}
|
||||
if valLen < 0 {
|
||||
return nil, 0, protowire.ParseError(valLen)
|
||||
}
|
||||
b = b[valLen:]
|
||||
|
||||
if depth == 0 {
|
||||
return b0[:len(b0)-len(b)-tagLen], len(b0) - len(b), nil
|
||||
}
|
||||
}
|
||||
}
|
63
vendor/github.com/golang/protobuf/proto/defaults.go
generated
vendored
63
vendor/github.com/golang/protobuf/proto/defaults.go
generated
vendored
@ -1,63 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
)
|
||||
|
||||
// SetDefaults sets unpopulated scalar fields to their default values.
|
||||
// Fields within a oneof are not set even if they have a default value.
|
||||
// SetDefaults is recursively called upon any populated message fields.
|
||||
func SetDefaults(m Message) {
|
||||
if m != nil {
|
||||
setDefaults(MessageReflect(m))
|
||||
}
|
||||
}
|
||||
|
||||
func setDefaults(m protoreflect.Message) {
|
||||
fds := m.Descriptor().Fields()
|
||||
for i := 0; i < fds.Len(); i++ {
|
||||
fd := fds.Get(i)
|
||||
if !m.Has(fd) {
|
||||
if fd.HasDefault() && fd.ContainingOneof() == nil {
|
||||
v := fd.Default()
|
||||
if fd.Kind() == protoreflect.BytesKind {
|
||||
v = protoreflect.ValueOf(append([]byte(nil), v.Bytes()...)) // copy the default bytes
|
||||
}
|
||||
m.Set(fd, v)
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
|
||||
switch {
|
||||
// Handle singular message.
|
||||
case fd.Cardinality() != protoreflect.Repeated:
|
||||
if fd.Message() != nil {
|
||||
setDefaults(m.Get(fd).Message())
|
||||
}
|
||||
// Handle list of messages.
|
||||
case fd.IsList():
|
||||
if fd.Message() != nil {
|
||||
ls := m.Get(fd).List()
|
||||
for i := 0; i < ls.Len(); i++ {
|
||||
setDefaults(ls.Get(i).Message())
|
||||
}
|
||||
}
|
||||
// Handle map of messages.
|
||||
case fd.IsMap():
|
||||
if fd.MapValue().Message() != nil {
|
||||
ms := m.Get(fd).Map()
|
||||
ms.Range(func(_ protoreflect.MapKey, v protoreflect.Value) bool {
|
||||
setDefaults(v.Message())
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
113
vendor/github.com/golang/protobuf/proto/deprecated.go
generated
vendored
113
vendor/github.com/golang/protobuf/proto/deprecated.go
generated
vendored
@ -1,113 +0,0 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
protoV2 "google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
// Deprecated: No longer returned.
|
||||
ErrNil = errors.New("proto: Marshal called with nil")
|
||||
|
||||
// Deprecated: No longer returned.
|
||||
ErrTooLarge = errors.New("proto: message encodes to over 2 GB")
|
||||
|
||||
// Deprecated: No longer returned.
|
||||
ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
|
||||
)
|
||||
|
||||
// Deprecated: Do not use.
|
||||
type Stats struct{ Emalloc, Dmalloc, Encode, Decode, Chit, Cmiss, Size uint64 }
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func GetStats() Stats { return Stats{} }
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func MarshalMessageSet(interface{}) ([]byte, error) {
|
||||
return nil, errors.New("proto: not implemented")
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func UnmarshalMessageSet([]byte, interface{}) error {
|
||||
return errors.New("proto: not implemented")
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func MarshalMessageSetJSON(interface{}) ([]byte, error) {
|
||||
return nil, errors.New("proto: not implemented")
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func UnmarshalMessageSetJSON([]byte, interface{}) error {
|
||||
return errors.New("proto: not implemented")
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func RegisterMessageSetType(Message, int32, string) {}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func EnumName(m map[int32]string, v int32) string {
|
||||
s, ok := m[v]
|
||||
if ok {
|
||||
return s
|
||||
}
|
||||
return strconv.Itoa(int(v))
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) {
|
||||
if data[0] == '"' {
|
||||
// New style: enums are strings.
|
||||
var repr string
|
||||
if err := json.Unmarshal(data, &repr); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
val, ok := m[repr]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr)
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
// Old style: enums are ints.
|
||||
var val int32
|
||||
if err := json.Unmarshal(data, &val); err != nil {
|
||||
return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName)
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
// Deprecated: Do not use; this type existed for intenal-use only.
|
||||
type InternalMessageInfo struct{}
|
||||
|
||||
// Deprecated: Do not use; this method existed for intenal-use only.
|
||||
func (*InternalMessageInfo) DiscardUnknown(m Message) {
|
||||
DiscardUnknown(m)
|
||||
}
|
||||
|
||||
// Deprecated: Do not use; this method existed for intenal-use only.
|
||||
func (*InternalMessageInfo) Marshal(b []byte, m Message, deterministic bool) ([]byte, error) {
|
||||
return protoV2.MarshalOptions{Deterministic: deterministic}.MarshalAppend(b, MessageV2(m))
|
||||
}
|
||||
|
||||
// Deprecated: Do not use; this method existed for intenal-use only.
|
||||
func (*InternalMessageInfo) Merge(dst, src Message) {
|
||||
protoV2.Merge(MessageV2(dst), MessageV2(src))
|
||||
}
|
||||
|
||||
// Deprecated: Do not use; this method existed for intenal-use only.
|
||||
func (*InternalMessageInfo) Size(m Message) int {
|
||||
return protoV2.Size(MessageV2(m))
|
||||
}
|
||||
|
||||
// Deprecated: Do not use; this method existed for intenal-use only.
|
||||
func (*InternalMessageInfo) Unmarshal(m Message, b []byte) error {
|
||||
return protoV2.UnmarshalOptions{Merge: true}.Unmarshal(b, MessageV2(m))
|
||||
}
|
58
vendor/github.com/golang/protobuf/proto/discard.go
generated
vendored
58
vendor/github.com/golang/protobuf/proto/discard.go
generated
vendored
@ -1,58 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
)
|
||||
|
||||
// DiscardUnknown recursively discards all unknown fields from this message
|
||||
// and all embedded messages.
|
||||
//
|
||||
// When unmarshaling a message with unrecognized fields, the tags and values
|
||||
// of such fields are preserved in the Message. This allows a later call to
|
||||
// marshal to be able to produce a message that continues to have those
|
||||
// unrecognized fields. To avoid this, DiscardUnknown is used to
|
||||
// explicitly clear the unknown fields after unmarshaling.
|
||||
func DiscardUnknown(m Message) {
|
||||
if m != nil {
|
||||
discardUnknown(MessageReflect(m))
|
||||
}
|
||||
}
|
||||
|
||||
func discardUnknown(m protoreflect.Message) {
|
||||
m.Range(func(fd protoreflect.FieldDescriptor, val protoreflect.Value) bool {
|
||||
switch {
|
||||
// Handle singular message.
|
||||
case fd.Cardinality() != protoreflect.Repeated:
|
||||
if fd.Message() != nil {
|
||||
discardUnknown(m.Get(fd).Message())
|
||||
}
|
||||
// Handle list of messages.
|
||||
case fd.IsList():
|
||||
if fd.Message() != nil {
|
||||
ls := m.Get(fd).List()
|
||||
for i := 0; i < ls.Len(); i++ {
|
||||
discardUnknown(ls.Get(i).Message())
|
||||
}
|
||||
}
|
||||
// Handle map of messages.
|
||||
case fd.IsMap():
|
||||
if fd.MapValue().Message() != nil {
|
||||
ms := m.Get(fd).Map()
|
||||
ms.Range(func(_ protoreflect.MapKey, v protoreflect.Value) bool {
|
||||
discardUnknown(v.Message())
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
// Discard unknown fields.
|
||||
if len(m.GetUnknown()) > 0 {
|
||||
m.SetUnknown(nil)
|
||||
}
|
||||
}
|
356
vendor/github.com/golang/protobuf/proto/extensions.go
generated
vendored
356
vendor/github.com/golang/protobuf/proto/extensions.go
generated
vendored
@ -1,356 +0,0 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"google.golang.org/protobuf/encoding/protowire"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
"google.golang.org/protobuf/runtime/protoiface"
|
||||
"google.golang.org/protobuf/runtime/protoimpl"
|
||||
)
|
||||
|
||||
type (
|
||||
// ExtensionDesc represents an extension descriptor and
|
||||
// is used to interact with an extension field in a message.
|
||||
//
|
||||
// Variables of this type are generated in code by protoc-gen-go.
|
||||
ExtensionDesc = protoimpl.ExtensionInfo
|
||||
|
||||
// ExtensionRange represents a range of message extensions.
|
||||
// Used in code generated by protoc-gen-go.
|
||||
ExtensionRange = protoiface.ExtensionRangeV1
|
||||
|
||||
// Deprecated: Do not use; this is an internal type.
|
||||
Extension = protoimpl.ExtensionFieldV1
|
||||
|
||||
// Deprecated: Do not use; this is an internal type.
|
||||
XXX_InternalExtensions = protoimpl.ExtensionFields
|
||||
)
|
||||
|
||||
// ErrMissingExtension reports whether the extension was not present.
|
||||
var ErrMissingExtension = errors.New("proto: missing extension")
|
||||
|
||||
var errNotExtendable = errors.New("proto: not an extendable proto.Message")
|
||||
|
||||
// HasExtension reports whether the extension field is present in m
|
||||
// either as an explicitly populated field or as an unknown field.
|
||||
func HasExtension(m Message, xt *ExtensionDesc) (has bool) {
|
||||
mr := MessageReflect(m)
|
||||
if mr == nil || !mr.IsValid() {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check whether any populated known field matches the field number.
|
||||
xtd := xt.TypeDescriptor()
|
||||
if isValidExtension(mr.Descriptor(), xtd) {
|
||||
has = mr.Has(xtd)
|
||||
} else {
|
||||
mr.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool {
|
||||
has = int32(fd.Number()) == xt.Field
|
||||
return !has
|
||||
})
|
||||
}
|
||||
|
||||
// Check whether any unknown field matches the field number.
|
||||
for b := mr.GetUnknown(); !has && len(b) > 0; {
|
||||
num, _, n := protowire.ConsumeField(b)
|
||||
has = int32(num) == xt.Field
|
||||
b = b[n:]
|
||||
}
|
||||
return has
|
||||
}
|
||||
|
||||
// ClearExtension removes the extension field from m
|
||||
// either as an explicitly populated field or as an unknown field.
|
||||
func ClearExtension(m Message, xt *ExtensionDesc) {
|
||||
mr := MessageReflect(m)
|
||||
if mr == nil || !mr.IsValid() {
|
||||
return
|
||||
}
|
||||
|
||||
xtd := xt.TypeDescriptor()
|
||||
if isValidExtension(mr.Descriptor(), xtd) {
|
||||
mr.Clear(xtd)
|
||||
} else {
|
||||
mr.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool {
|
||||
if int32(fd.Number()) == xt.Field {
|
||||
mr.Clear(fd)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
clearUnknown(mr, fieldNum(xt.Field))
|
||||
}
|
||||
|
||||
// ClearAllExtensions clears all extensions from m.
|
||||
// This includes populated fields and unknown fields in the extension range.
|
||||
func ClearAllExtensions(m Message) {
|
||||
mr := MessageReflect(m)
|
||||
if mr == nil || !mr.IsValid() {
|
||||
return
|
||||
}
|
||||
|
||||
mr.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool {
|
||||
if fd.IsExtension() {
|
||||
mr.Clear(fd)
|
||||
}
|
||||
return true
|
||||
})
|
||||
clearUnknown(mr, mr.Descriptor().ExtensionRanges())
|
||||
}
|
||||
|
||||
// GetExtension retrieves a proto2 extended field from m.
|
||||
//
|
||||
// If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil),
|
||||
// then GetExtension parses the encoded field and returns a Go value of the specified type.
|
||||
// If the field is not present, then the default value is returned (if one is specified),
|
||||
// otherwise ErrMissingExtension is reported.
|
||||
//
|
||||
// If the descriptor is type incomplete (i.e., ExtensionDesc.ExtensionType is nil),
|
||||
// then GetExtension returns the raw encoded bytes for the extension field.
|
||||
func GetExtension(m Message, xt *ExtensionDesc) (interface{}, error) {
|
||||
mr := MessageReflect(m)
|
||||
if mr == nil || !mr.IsValid() || mr.Descriptor().ExtensionRanges().Len() == 0 {
|
||||
return nil, errNotExtendable
|
||||
}
|
||||
|
||||
// Retrieve the unknown fields for this extension field.
|
||||
var bo protoreflect.RawFields
|
||||
for bi := mr.GetUnknown(); len(bi) > 0; {
|
||||
num, _, n := protowire.ConsumeField(bi)
|
||||
if int32(num) == xt.Field {
|
||||
bo = append(bo, bi[:n]...)
|
||||
}
|
||||
bi = bi[n:]
|
||||
}
|
||||
|
||||
// For type incomplete descriptors, only retrieve the unknown fields.
|
||||
if xt.ExtensionType == nil {
|
||||
return []byte(bo), nil
|
||||
}
|
||||
|
||||
// If the extension field only exists as unknown fields, unmarshal it.
|
||||
// This is rarely done since proto.Unmarshal eagerly unmarshals extensions.
|
||||
xtd := xt.TypeDescriptor()
|
||||
if !isValidExtension(mr.Descriptor(), xtd) {
|
||||
return nil, fmt.Errorf("proto: bad extended type; %T does not extend %T", xt.ExtendedType, m)
|
||||
}
|
||||
if !mr.Has(xtd) && len(bo) > 0 {
|
||||
m2 := mr.New()
|
||||
if err := (proto.UnmarshalOptions{
|
||||
Resolver: extensionResolver{xt},
|
||||
}.Unmarshal(bo, m2.Interface())); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if m2.Has(xtd) {
|
||||
mr.Set(xtd, m2.Get(xtd))
|
||||
clearUnknown(mr, fieldNum(xt.Field))
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the message has the extension field set or a default.
|
||||
var pv protoreflect.Value
|
||||
switch {
|
||||
case mr.Has(xtd):
|
||||
pv = mr.Get(xtd)
|
||||
case xtd.HasDefault():
|
||||
pv = xtd.Default()
|
||||
default:
|
||||
return nil, ErrMissingExtension
|
||||
}
|
||||
|
||||
v := xt.InterfaceOf(pv)
|
||||
rv := reflect.ValueOf(v)
|
||||
if isScalarKind(rv.Kind()) {
|
||||
rv2 := reflect.New(rv.Type())
|
||||
rv2.Elem().Set(rv)
|
||||
v = rv2.Interface()
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// extensionResolver is a custom extension resolver that stores a single
|
||||
// extension type that takes precedence over the global registry.
|
||||
type extensionResolver struct{ xt protoreflect.ExtensionType }
|
||||
|
||||
func (r extensionResolver) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) {
|
||||
if xtd := r.xt.TypeDescriptor(); xtd.FullName() == field {
|
||||
return r.xt, nil
|
||||
}
|
||||
return protoregistry.GlobalTypes.FindExtensionByName(field)
|
||||
}
|
||||
|
||||
func (r extensionResolver) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
|
||||
if xtd := r.xt.TypeDescriptor(); xtd.ContainingMessage().FullName() == message && xtd.Number() == field {
|
||||
return r.xt, nil
|
||||
}
|
||||
return protoregistry.GlobalTypes.FindExtensionByNumber(message, field)
|
||||
}
|
||||
|
||||
// GetExtensions returns a list of the extensions values present in m,
|
||||
// corresponding with the provided list of extension descriptors, xts.
|
||||
// If an extension is missing in m, the corresponding value is nil.
|
||||
func GetExtensions(m Message, xts []*ExtensionDesc) ([]interface{}, error) {
|
||||
mr := MessageReflect(m)
|
||||
if mr == nil || !mr.IsValid() {
|
||||
return nil, errNotExtendable
|
||||
}
|
||||
|
||||
vs := make([]interface{}, len(xts))
|
||||
for i, xt := range xts {
|
||||
v, err := GetExtension(m, xt)
|
||||
if err != nil {
|
||||
if err == ErrMissingExtension {
|
||||
continue
|
||||
}
|
||||
return vs, err
|
||||
}
|
||||
vs[i] = v
|
||||
}
|
||||
return vs, nil
|
||||
}
|
||||
|
||||
// SetExtension sets an extension field in m to the provided value.
|
||||
func SetExtension(m Message, xt *ExtensionDesc, v interface{}) error {
|
||||
mr := MessageReflect(m)
|
||||
if mr == nil || !mr.IsValid() || mr.Descriptor().ExtensionRanges().Len() == 0 {
|
||||
return errNotExtendable
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(v)
|
||||
if reflect.TypeOf(v) != reflect.TypeOf(xt.ExtensionType) {
|
||||
return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", v, xt.ExtensionType)
|
||||
}
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
if rv.IsNil() {
|
||||
return fmt.Errorf("proto: SetExtension called with nil value of type %T", v)
|
||||
}
|
||||
if isScalarKind(rv.Elem().Kind()) {
|
||||
v = rv.Elem().Interface()
|
||||
}
|
||||
}
|
||||
|
||||
xtd := xt.TypeDescriptor()
|
||||
if !isValidExtension(mr.Descriptor(), xtd) {
|
||||
return fmt.Errorf("proto: bad extended type; %T does not extend %T", xt.ExtendedType, m)
|
||||
}
|
||||
mr.Set(xtd, xt.ValueOf(v))
|
||||
clearUnknown(mr, fieldNum(xt.Field))
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetRawExtension inserts b into the unknown fields of m.
|
||||
//
|
||||
// Deprecated: Use Message.ProtoReflect.SetUnknown instead.
|
||||
func SetRawExtension(m Message, fnum int32, b []byte) {
|
||||
mr := MessageReflect(m)
|
||||
if mr == nil || !mr.IsValid() {
|
||||
return
|
||||
}
|
||||
|
||||
// Verify that the raw field is valid.
|
||||
for b0 := b; len(b0) > 0; {
|
||||
num, _, n := protowire.ConsumeField(b0)
|
||||
if int32(num) != fnum {
|
||||
panic(fmt.Sprintf("mismatching field number: got %d, want %d", num, fnum))
|
||||
}
|
||||
b0 = b0[n:]
|
||||
}
|
||||
|
||||
ClearExtension(m, &ExtensionDesc{Field: fnum})
|
||||
mr.SetUnknown(append(mr.GetUnknown(), b...))
|
||||
}
|
||||
|
||||
// ExtensionDescs returns a list of extension descriptors found in m,
|
||||
// containing descriptors for both populated extension fields in m and
|
||||
// also unknown fields of m that are in the extension range.
|
||||
// For the later case, an type incomplete descriptor is provided where only
|
||||
// the ExtensionDesc.Field field is populated.
|
||||
// The order of the extension descriptors is undefined.
|
||||
func ExtensionDescs(m Message) ([]*ExtensionDesc, error) {
|
||||
mr := MessageReflect(m)
|
||||
if mr == nil || !mr.IsValid() || mr.Descriptor().ExtensionRanges().Len() == 0 {
|
||||
return nil, errNotExtendable
|
||||
}
|
||||
|
||||
// Collect a set of known extension descriptors.
|
||||
extDescs := make(map[protoreflect.FieldNumber]*ExtensionDesc)
|
||||
mr.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
|
||||
if fd.IsExtension() {
|
||||
xt := fd.(protoreflect.ExtensionTypeDescriptor)
|
||||
if xd, ok := xt.Type().(*ExtensionDesc); ok {
|
||||
extDescs[fd.Number()] = xd
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
// Collect a set of unknown extension descriptors.
|
||||
extRanges := mr.Descriptor().ExtensionRanges()
|
||||
for b := mr.GetUnknown(); len(b) > 0; {
|
||||
num, _, n := protowire.ConsumeField(b)
|
||||
if extRanges.Has(num) && extDescs[num] == nil {
|
||||
extDescs[num] = nil
|
||||
}
|
||||
b = b[n:]
|
||||
}
|
||||
|
||||
// Transpose the set of descriptors into a list.
|
||||
var xts []*ExtensionDesc
|
||||
for num, xt := range extDescs {
|
||||
if xt == nil {
|
||||
xt = &ExtensionDesc{Field: int32(num)}
|
||||
}
|
||||
xts = append(xts, xt)
|
||||
}
|
||||
return xts, nil
|
||||
}
|
||||
|
||||
// isValidExtension reports whether xtd is a valid extension descriptor for md.
|
||||
func isValidExtension(md protoreflect.MessageDescriptor, xtd protoreflect.ExtensionTypeDescriptor) bool {
|
||||
return xtd.ContainingMessage() == md && md.ExtensionRanges().Has(xtd.Number())
|
||||
}
|
||||
|
||||
// isScalarKind reports whether k is a protobuf scalar kind (except bytes).
|
||||
// This function exists for historical reasons since the representation of
|
||||
// scalars differs between v1 and v2, where v1 uses *T and v2 uses T.
|
||||
func isScalarKind(k reflect.Kind) bool {
|
||||
switch k {
|
||||
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// clearUnknown removes unknown fields from m where remover.Has reports true.
|
||||
func clearUnknown(m protoreflect.Message, remover interface {
|
||||
Has(protoreflect.FieldNumber) bool
|
||||
}) {
|
||||
var bo protoreflect.RawFields
|
||||
for bi := m.GetUnknown(); len(bi) > 0; {
|
||||
num, _, n := protowire.ConsumeField(bi)
|
||||
if !remover.Has(num) {
|
||||
bo = append(bo, bi[:n]...)
|
||||
}
|
||||
bi = bi[n:]
|
||||
}
|
||||
if bi := m.GetUnknown(); len(bi) != len(bo) {
|
||||
m.SetUnknown(bo)
|
||||
}
|
||||
}
|
||||
|
||||
type fieldNum protoreflect.FieldNumber
|
||||
|
||||
func (n1 fieldNum) Has(n2 protoreflect.FieldNumber) bool {
|
||||
return protoreflect.FieldNumber(n1) == n2
|
||||
}
|
306
vendor/github.com/golang/protobuf/proto/properties.go
generated
vendored
306
vendor/github.com/golang/protobuf/proto/properties.go
generated
vendored
@ -1,306 +0,0 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/runtime/protoimpl"
|
||||
)
|
||||
|
||||
// StructProperties represents protocol buffer type information for a
|
||||
// generated protobuf message in the open-struct API.
|
||||
//
|
||||
// Deprecated: Do not use.
|
||||
type StructProperties struct {
|
||||
// Prop are the properties for each field.
|
||||
//
|
||||
// Fields belonging to a oneof are stored in OneofTypes instead, with a
|
||||
// single Properties representing the parent oneof held here.
|
||||
//
|
||||
// The order of Prop matches the order of fields in the Go struct.
|
||||
// Struct fields that are not related to protobufs have a "XXX_" prefix
|
||||
// in the Properties.Name and must be ignored by the user.
|
||||
Prop []*Properties
|
||||
|
||||
// OneofTypes contains information about the oneof fields in this message.
|
||||
// It is keyed by the protobuf field name.
|
||||
OneofTypes map[string]*OneofProperties
|
||||
}
|
||||
|
||||
// Properties represents the type information for a protobuf message field.
|
||||
//
|
||||
// Deprecated: Do not use.
|
||||
type Properties struct {
|
||||
// Name is a placeholder name with little meaningful semantic value.
|
||||
// If the name has an "XXX_" prefix, the entire Properties must be ignored.
|
||||
Name string
|
||||
// OrigName is the protobuf field name or oneof name.
|
||||
OrigName string
|
||||
// JSONName is the JSON name for the protobuf field.
|
||||
JSONName string
|
||||
// Enum is a placeholder name for enums.
|
||||
// For historical reasons, this is neither the Go name for the enum,
|
||||
// nor the protobuf name for the enum.
|
||||
Enum string // Deprecated: Do not use.
|
||||
// Weak contains the full name of the weakly referenced message.
|
||||
Weak string
|
||||
// Wire is a string representation of the wire type.
|
||||
Wire string
|
||||
// WireType is the protobuf wire type for the field.
|
||||
WireType int
|
||||
// Tag is the protobuf field number.
|
||||
Tag int
|
||||
// Required reports whether this is a required field.
|
||||
Required bool
|
||||
// Optional reports whether this is a optional field.
|
||||
Optional bool
|
||||
// Repeated reports whether this is a repeated field.
|
||||
Repeated bool
|
||||
// Packed reports whether this is a packed repeated field of scalars.
|
||||
Packed bool
|
||||
// Proto3 reports whether this field operates under the proto3 syntax.
|
||||
Proto3 bool
|
||||
// Oneof reports whether this field belongs within a oneof.
|
||||
Oneof bool
|
||||
|
||||
// Default is the default value in string form.
|
||||
Default string
|
||||
// HasDefault reports whether the field has a default value.
|
||||
HasDefault bool
|
||||
|
||||
// MapKeyProp is the properties for the key field for a map field.
|
||||
MapKeyProp *Properties
|
||||
// MapValProp is the properties for the value field for a map field.
|
||||
MapValProp *Properties
|
||||
}
|
||||
|
||||
// OneofProperties represents the type information for a protobuf oneof.
|
||||
//
|
||||
// Deprecated: Do not use.
|
||||
type OneofProperties struct {
|
||||
// Type is a pointer to the generated wrapper type for the field value.
|
||||
// This is nil for messages that are not in the open-struct API.
|
||||
Type reflect.Type
|
||||
// Field is the index into StructProperties.Prop for the containing oneof.
|
||||
Field int
|
||||
// Prop is the properties for the field.
|
||||
Prop *Properties
|
||||
}
|
||||
|
||||
// String formats the properties in the protobuf struct field tag style.
|
||||
func (p *Properties) String() string {
|
||||
s := p.Wire
|
||||
s += "," + strconv.Itoa(p.Tag)
|
||||
if p.Required {
|
||||
s += ",req"
|
||||
}
|
||||
if p.Optional {
|
||||
s += ",opt"
|
||||
}
|
||||
if p.Repeated {
|
||||
s += ",rep"
|
||||
}
|
||||
if p.Packed {
|
||||
s += ",packed"
|
||||
}
|
||||
s += ",name=" + p.OrigName
|
||||
if p.JSONName != "" {
|
||||
s += ",json=" + p.JSONName
|
||||
}
|
||||
if len(p.Enum) > 0 {
|
||||
s += ",enum=" + p.Enum
|
||||
}
|
||||
if len(p.Weak) > 0 {
|
||||
s += ",weak=" + p.Weak
|
||||
}
|
||||
if p.Proto3 {
|
||||
s += ",proto3"
|
||||
}
|
||||
if p.Oneof {
|
||||
s += ",oneof"
|
||||
}
|
||||
if p.HasDefault {
|
||||
s += ",def=" + p.Default
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Parse populates p by parsing a string in the protobuf struct field tag style.
|
||||
func (p *Properties) Parse(tag string) {
|
||||
// For example: "bytes,49,opt,name=foo,def=hello!"
|
||||
for len(tag) > 0 {
|
||||
i := strings.IndexByte(tag, ',')
|
||||
if i < 0 {
|
||||
i = len(tag)
|
||||
}
|
||||
switch s := tag[:i]; {
|
||||
case strings.HasPrefix(s, "name="):
|
||||
p.OrigName = s[len("name="):]
|
||||
case strings.HasPrefix(s, "json="):
|
||||
p.JSONName = s[len("json="):]
|
||||
case strings.HasPrefix(s, "enum="):
|
||||
p.Enum = s[len("enum="):]
|
||||
case strings.HasPrefix(s, "weak="):
|
||||
p.Weak = s[len("weak="):]
|
||||
case strings.Trim(s, "0123456789") == "":
|
||||
n, _ := strconv.ParseUint(s, 10, 32)
|
||||
p.Tag = int(n)
|
||||
case s == "opt":
|
||||
p.Optional = true
|
||||
case s == "req":
|
||||
p.Required = true
|
||||
case s == "rep":
|
||||
p.Repeated = true
|
||||
case s == "varint" || s == "zigzag32" || s == "zigzag64":
|
||||
p.Wire = s
|
||||
p.WireType = WireVarint
|
||||
case s == "fixed32":
|
||||
p.Wire = s
|
||||
p.WireType = WireFixed32
|
||||
case s == "fixed64":
|
||||
p.Wire = s
|
||||
p.WireType = WireFixed64
|
||||
case s == "bytes":
|
||||
p.Wire = s
|
||||
p.WireType = WireBytes
|
||||
case s == "group":
|
||||
p.Wire = s
|
||||
p.WireType = WireStartGroup
|
||||
case s == "packed":
|
||||
p.Packed = true
|
||||
case s == "proto3":
|
||||
p.Proto3 = true
|
||||
case s == "oneof":
|
||||
p.Oneof = true
|
||||
case strings.HasPrefix(s, "def="):
|
||||
// The default tag is special in that everything afterwards is the
|
||||
// default regardless of the presence of commas.
|
||||
p.HasDefault = true
|
||||
p.Default, i = tag[len("def="):], len(tag)
|
||||
}
|
||||
tag = strings.TrimPrefix(tag[i:], ",")
|
||||
}
|
||||
}
|
||||
|
||||
// Init populates the properties from a protocol buffer struct tag.
|
||||
//
|
||||
// Deprecated: Do not use.
|
||||
func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
|
||||
p.Name = name
|
||||
p.OrigName = name
|
||||
if tag == "" {
|
||||
return
|
||||
}
|
||||
p.Parse(tag)
|
||||
|
||||
if typ != nil && typ.Kind() == reflect.Map {
|
||||
p.MapKeyProp = new(Properties)
|
||||
p.MapKeyProp.Init(nil, "Key", f.Tag.Get("protobuf_key"), nil)
|
||||
p.MapValProp = new(Properties)
|
||||
p.MapValProp.Init(nil, "Value", f.Tag.Get("protobuf_val"), nil)
|
||||
}
|
||||
}
|
||||
|
||||
var propertiesCache sync.Map // map[reflect.Type]*StructProperties
|
||||
|
||||
// GetProperties returns the list of properties for the type represented by t,
|
||||
// which must be a generated protocol buffer message in the open-struct API,
|
||||
// where protobuf message fields are represented by exported Go struct fields.
|
||||
//
|
||||
// Deprecated: Use protobuf reflection instead.
|
||||
func GetProperties(t reflect.Type) *StructProperties {
|
||||
if p, ok := propertiesCache.Load(t); ok {
|
||||
return p.(*StructProperties)
|
||||
}
|
||||
p, _ := propertiesCache.LoadOrStore(t, newProperties(t))
|
||||
return p.(*StructProperties)
|
||||
}
|
||||
|
||||
func newProperties(t reflect.Type) *StructProperties {
|
||||
if t.Kind() != reflect.Struct {
|
||||
panic(fmt.Sprintf("%v is not a generated message in the open-struct API", t))
|
||||
}
|
||||
|
||||
var hasOneof bool
|
||||
prop := new(StructProperties)
|
||||
|
||||
// Construct a list of properties for each field in the struct.
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
p := new(Properties)
|
||||
f := t.Field(i)
|
||||
tagField := f.Tag.Get("protobuf")
|
||||
p.Init(f.Type, f.Name, tagField, &f)
|
||||
|
||||
tagOneof := f.Tag.Get("protobuf_oneof")
|
||||
if tagOneof != "" {
|
||||
hasOneof = true
|
||||
p.OrigName = tagOneof
|
||||
}
|
||||
|
||||
// Rename unrelated struct fields with the "XXX_" prefix since so much
|
||||
// user code simply checks for this to exclude special fields.
|
||||
if tagField == "" && tagOneof == "" && !strings.HasPrefix(p.Name, "XXX_") {
|
||||
p.Name = "XXX_" + p.Name
|
||||
p.OrigName = "XXX_" + p.OrigName
|
||||
} else if p.Weak != "" {
|
||||
p.Name = p.OrigName // avoid possible "XXX_" prefix on weak field
|
||||
}
|
||||
|
||||
prop.Prop = append(prop.Prop, p)
|
||||
}
|
||||
|
||||
// Construct a mapping of oneof field names to properties.
|
||||
if hasOneof {
|
||||
var oneofWrappers []interface{}
|
||||
if fn, ok := reflect.PtrTo(t).MethodByName("XXX_OneofFuncs"); ok {
|
||||
oneofWrappers = fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[3].Interface().([]interface{})
|
||||
}
|
||||
if fn, ok := reflect.PtrTo(t).MethodByName("XXX_OneofWrappers"); ok {
|
||||
oneofWrappers = fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[0].Interface().([]interface{})
|
||||
}
|
||||
if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(protoreflect.ProtoMessage); ok {
|
||||
if m, ok := m.ProtoReflect().(interface{ ProtoMessageInfo() *protoimpl.MessageInfo }); ok {
|
||||
oneofWrappers = m.ProtoMessageInfo().OneofWrappers
|
||||
}
|
||||
}
|
||||
|
||||
prop.OneofTypes = make(map[string]*OneofProperties)
|
||||
for _, wrapper := range oneofWrappers {
|
||||
p := &OneofProperties{
|
||||
Type: reflect.ValueOf(wrapper).Type(), // *T
|
||||
Prop: new(Properties),
|
||||
}
|
||||
f := p.Type.Elem().Field(0)
|
||||
p.Prop.Name = f.Name
|
||||
p.Prop.Parse(f.Tag.Get("protobuf"))
|
||||
|
||||
// Determine the struct field that contains this oneof.
|
||||
// Each wrapper is assignable to exactly one parent field.
|
||||
var foundOneof bool
|
||||
for i := 0; i < t.NumField() && !foundOneof; i++ {
|
||||
if p.Type.AssignableTo(t.Field(i).Type) {
|
||||
p.Field = i
|
||||
foundOneof = true
|
||||
}
|
||||
}
|
||||
if !foundOneof {
|
||||
panic(fmt.Sprintf("%v is not a generated message in the open-struct API", t))
|
||||
}
|
||||
prop.OneofTypes[p.Prop.OrigName] = p
|
||||
}
|
||||
}
|
||||
|
||||
return prop
|
||||
}
|
||||
|
||||
func (sp *StructProperties) Len() int { return len(sp.Prop) }
|
||||
func (sp *StructProperties) Less(i, j int) bool { return false }
|
||||
func (sp *StructProperties) Swap(i, j int) { return }
|
167
vendor/github.com/golang/protobuf/proto/proto.go
generated
vendored
167
vendor/github.com/golang/protobuf/proto/proto.go
generated
vendored
@ -1,167 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package proto provides functionality for handling protocol buffer messages.
|
||||
// In particular, it provides marshaling and unmarshaling between a protobuf
|
||||
// message and the binary wire format.
|
||||
//
|
||||
// See https://developers.google.com/protocol-buffers/docs/gotutorial for
|
||||
// more information.
|
||||
//
|
||||
// Deprecated: Use the "google.golang.org/protobuf/proto" package instead.
|
||||
package proto
|
||||
|
||||
import (
|
||||
protoV2 "google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/runtime/protoiface"
|
||||
"google.golang.org/protobuf/runtime/protoimpl"
|
||||
)
|
||||
|
||||
const (
|
||||
ProtoPackageIsVersion1 = true
|
||||
ProtoPackageIsVersion2 = true
|
||||
ProtoPackageIsVersion3 = true
|
||||
ProtoPackageIsVersion4 = true
|
||||
)
|
||||
|
||||
// GeneratedEnum is any enum type generated by protoc-gen-go
|
||||
// which is a named int32 kind.
|
||||
// This type exists for documentation purposes.
|
||||
type GeneratedEnum interface{}
|
||||
|
||||
// GeneratedMessage is any message type generated by protoc-gen-go
|
||||
// which is a pointer to a named struct kind.
|
||||
// This type exists for documentation purposes.
|
||||
type GeneratedMessage interface{}
|
||||
|
||||
// Message is a protocol buffer message.
|
||||
//
|
||||
// This is the v1 version of the message interface and is marginally better
|
||||
// than an empty interface as it lacks any method to programatically interact
|
||||
// with the contents of the message.
|
||||
//
|
||||
// A v2 message is declared in "google.golang.org/protobuf/proto".Message and
|
||||
// exposes protobuf reflection as a first-class feature of the interface.
|
||||
//
|
||||
// To convert a v1 message to a v2 message, use the MessageV2 function.
|
||||
// To convert a v2 message to a v1 message, use the MessageV1 function.
|
||||
type Message = protoiface.MessageV1
|
||||
|
||||
// MessageV1 converts either a v1 or v2 message to a v1 message.
|
||||
// It returns nil if m is nil.
|
||||
func MessageV1(m GeneratedMessage) protoiface.MessageV1 {
|
||||
return protoimpl.X.ProtoMessageV1Of(m)
|
||||
}
|
||||
|
||||
// MessageV2 converts either a v1 or v2 message to a v2 message.
|
||||
// It returns nil if m is nil.
|
||||
func MessageV2(m GeneratedMessage) protoV2.Message {
|
||||
return protoimpl.X.ProtoMessageV2Of(m)
|
||||
}
|
||||
|
||||
// MessageReflect returns a reflective view for a message.
|
||||
// It returns nil if m is nil.
|
||||
func MessageReflect(m Message) protoreflect.Message {
|
||||
return protoimpl.X.MessageOf(m)
|
||||
}
|
||||
|
||||
// Marshaler is implemented by messages that can marshal themselves.
|
||||
// This interface is used by the following functions: Size, Marshal,
|
||||
// Buffer.Marshal, and Buffer.EncodeMessage.
|
||||
//
|
||||
// Deprecated: Do not implement.
|
||||
type Marshaler interface {
|
||||
// Marshal formats the encoded bytes of the message.
|
||||
// It should be deterministic and emit valid protobuf wire data.
|
||||
// The caller takes ownership of the returned buffer.
|
||||
Marshal() ([]byte, error)
|
||||
}
|
||||
|
||||
// Unmarshaler is implemented by messages that can unmarshal themselves.
|
||||
// This interface is used by the following functions: Unmarshal, UnmarshalMerge,
|
||||
// Buffer.Unmarshal, Buffer.DecodeMessage, and Buffer.DecodeGroup.
|
||||
//
|
||||
// Deprecated: Do not implement.
|
||||
type Unmarshaler interface {
|
||||
// Unmarshal parses the encoded bytes of the protobuf wire input.
|
||||
// The provided buffer is only valid for during method call.
|
||||
// It should not reset the receiver message.
|
||||
Unmarshal([]byte) error
|
||||
}
|
||||
|
||||
// Merger is implemented by messages that can merge themselves.
|
||||
// This interface is used by the following functions: Clone and Merge.
|
||||
//
|
||||
// Deprecated: Do not implement.
|
||||
type Merger interface {
|
||||
// Merge merges the contents of src into the receiver message.
|
||||
// It clones all data structures in src such that it aliases no mutable
|
||||
// memory referenced by src.
|
||||
Merge(src Message)
|
||||
}
|
||||
|
||||
// RequiredNotSetError is an error type returned when
|
||||
// marshaling or unmarshaling a message with missing required fields.
|
||||
type RequiredNotSetError struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (e *RequiredNotSetError) Error() string {
|
||||
if e.err != nil {
|
||||
return e.err.Error()
|
||||
}
|
||||
return "proto: required field not set"
|
||||
}
|
||||
func (e *RequiredNotSetError) RequiredNotSet() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func checkRequiredNotSet(m protoV2.Message) error {
|
||||
if err := protoV2.CheckInitialized(m); err != nil {
|
||||
return &RequiredNotSetError{err: err}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Clone returns a deep copy of src.
|
||||
func Clone(src Message) Message {
|
||||
return MessageV1(protoV2.Clone(MessageV2(src)))
|
||||
}
|
||||
|
||||
// Merge merges src into dst, which must be messages of the same type.
|
||||
//
|
||||
// Populated scalar fields in src are copied to dst, while populated
|
||||
// singular messages in src are merged into dst by recursively calling Merge.
|
||||
// The elements of every list field in src is appended to the corresponded
|
||||
// list fields in dst. The entries of every map field in src is copied into
|
||||
// the corresponding map field in dst, possibly replacing existing entries.
|
||||
// The unknown fields of src are appended to the unknown fields of dst.
|
||||
func Merge(dst, src Message) {
|
||||
protoV2.Merge(MessageV2(dst), MessageV2(src))
|
||||
}
|
||||
|
||||
// Equal reports whether two messages are equal.
|
||||
// If two messages marshal to the same bytes under deterministic serialization,
|
||||
// then Equal is guaranteed to report true.
|
||||
//
|
||||
// Two messages are equal if they are the same protobuf message type,
|
||||
// have the same set of populated known and extension field values,
|
||||
// and the same set of unknown fields values.
|
||||
//
|
||||
// Scalar values are compared with the equivalent of the == operator in Go,
|
||||
// except bytes values which are compared using bytes.Equal and
|
||||
// floating point values which specially treat NaNs as equal.
|
||||
// Message values are compared by recursively calling Equal.
|
||||
// Lists are equal if each element value is also equal.
|
||||
// Maps are equal if they have the same set of keys, where the pair of values
|
||||
// for each key is also equal.
|
||||
func Equal(x, y Message) bool {
|
||||
return protoV2.Equal(MessageV2(x), MessageV2(y))
|
||||
}
|
||||
|
||||
func isMessageSet(md protoreflect.MessageDescriptor) bool {
|
||||
ms, ok := md.(interface{ IsMessageSet() bool })
|
||||
return ok && ms.IsMessageSet()
|
||||
}
|
317
vendor/github.com/golang/protobuf/proto/registry.go
generated
vendored
317
vendor/github.com/golang/protobuf/proto/registry.go
generated
vendored
@ -1,317 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/protobuf/reflect/protodesc"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
"google.golang.org/protobuf/runtime/protoimpl"
|
||||
)
|
||||
|
||||
// filePath is the path to the proto source file.
|
||||
type filePath = string // e.g., "google/protobuf/descriptor.proto"
|
||||
|
||||
// fileDescGZIP is the compressed contents of the encoded FileDescriptorProto.
|
||||
type fileDescGZIP = []byte
|
||||
|
||||
var fileCache sync.Map // map[filePath]fileDescGZIP
|
||||
|
||||
// RegisterFile is called from generated code to register the compressed
|
||||
// FileDescriptorProto with the file path for a proto source file.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalFiles.RegisterFile instead.
|
||||
func RegisterFile(s filePath, d fileDescGZIP) {
|
||||
// Decompress the descriptor.
|
||||
zr, err := gzip.NewReader(bytes.NewReader(d))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("proto: invalid compressed file descriptor: %v", err))
|
||||
}
|
||||
b, err := ioutil.ReadAll(zr)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("proto: invalid compressed file descriptor: %v", err))
|
||||
}
|
||||
|
||||
// Construct a protoreflect.FileDescriptor from the raw descriptor.
|
||||
// Note that DescBuilder.Build automatically registers the constructed
|
||||
// file descriptor with the v2 registry.
|
||||
protoimpl.DescBuilder{RawDescriptor: b}.Build()
|
||||
|
||||
// Locally cache the raw descriptor form for the file.
|
||||
fileCache.Store(s, d)
|
||||
}
|
||||
|
||||
// FileDescriptor returns the compressed FileDescriptorProto given the file path
|
||||
// for a proto source file. It returns nil if not found.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalFiles.FindFileByPath instead.
|
||||
func FileDescriptor(s filePath) fileDescGZIP {
|
||||
if v, ok := fileCache.Load(s); ok {
|
||||
return v.(fileDescGZIP)
|
||||
}
|
||||
|
||||
// Find the descriptor in the v2 registry.
|
||||
var b []byte
|
||||
if fd, _ := protoregistry.GlobalFiles.FindFileByPath(s); fd != nil {
|
||||
b, _ = Marshal(protodesc.ToFileDescriptorProto(fd))
|
||||
}
|
||||
|
||||
// Locally cache the raw descriptor form for the file.
|
||||
if len(b) > 0 {
|
||||
v, _ := fileCache.LoadOrStore(s, protoimpl.X.CompressGZIP(b))
|
||||
return v.(fileDescGZIP)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// enumName is the name of an enum. For historical reasons, the enum name is
|
||||
// neither the full Go name nor the full protobuf name of the enum.
|
||||
// The name is the dot-separated combination of just the proto package that the
|
||||
// enum is declared within followed by the Go type name of the generated enum.
|
||||
type enumName = string // e.g., "my.proto.package.GoMessage_GoEnum"
|
||||
|
||||
// enumsByName maps enum values by name to their numeric counterpart.
|
||||
type enumsByName = map[string]int32
|
||||
|
||||
// enumsByNumber maps enum values by number to their name counterpart.
|
||||
type enumsByNumber = map[int32]string
|
||||
|
||||
var enumCache sync.Map // map[enumName]enumsByName
|
||||
var numFilesCache sync.Map // map[protoreflect.FullName]int
|
||||
|
||||
// RegisterEnum is called from the generated code to register the mapping of
|
||||
// enum value names to enum numbers for the enum identified by s.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalTypes.RegisterEnum instead.
|
||||
func RegisterEnum(s enumName, _ enumsByNumber, m enumsByName) {
|
||||
if _, ok := enumCache.Load(s); ok {
|
||||
panic("proto: duplicate enum registered: " + s)
|
||||
}
|
||||
enumCache.Store(s, m)
|
||||
|
||||
// This does not forward registration to the v2 registry since this API
|
||||
// lacks sufficient information to construct a complete v2 enum descriptor.
|
||||
}
|
||||
|
||||
// EnumValueMap returns the mapping from enum value names to enum numbers for
|
||||
// the enum of the given name. It returns nil if not found.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalTypes.FindEnumByName instead.
|
||||
func EnumValueMap(s enumName) enumsByName {
|
||||
if v, ok := enumCache.Load(s); ok {
|
||||
return v.(enumsByName)
|
||||
}
|
||||
|
||||
// Check whether the cache is stale. If the number of files in the current
|
||||
// package differs, then it means that some enums may have been recently
|
||||
// registered upstream that we do not know about.
|
||||
var protoPkg protoreflect.FullName
|
||||
if i := strings.LastIndexByte(s, '.'); i >= 0 {
|
||||
protoPkg = protoreflect.FullName(s[:i])
|
||||
}
|
||||
v, _ := numFilesCache.Load(protoPkg)
|
||||
numFiles, _ := v.(int)
|
||||
if protoregistry.GlobalFiles.NumFilesByPackage(protoPkg) == numFiles {
|
||||
return nil // cache is up-to-date; was not found earlier
|
||||
}
|
||||
|
||||
// Update the enum cache for all enums declared in the given proto package.
|
||||
numFiles = 0
|
||||
protoregistry.GlobalFiles.RangeFilesByPackage(protoPkg, func(fd protoreflect.FileDescriptor) bool {
|
||||
walkEnums(fd, func(ed protoreflect.EnumDescriptor) {
|
||||
name := protoimpl.X.LegacyEnumName(ed)
|
||||
if _, ok := enumCache.Load(name); !ok {
|
||||
m := make(enumsByName)
|
||||
evs := ed.Values()
|
||||
for i := evs.Len() - 1; i >= 0; i-- {
|
||||
ev := evs.Get(i)
|
||||
m[string(ev.Name())] = int32(ev.Number())
|
||||
}
|
||||
enumCache.LoadOrStore(name, m)
|
||||
}
|
||||
})
|
||||
numFiles++
|
||||
return true
|
||||
})
|
||||
numFilesCache.Store(protoPkg, numFiles)
|
||||
|
||||
// Check cache again for enum map.
|
||||
if v, ok := enumCache.Load(s); ok {
|
||||
return v.(enumsByName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// walkEnums recursively walks all enums declared in d.
|
||||
func walkEnums(d interface {
|
||||
Enums() protoreflect.EnumDescriptors
|
||||
Messages() protoreflect.MessageDescriptors
|
||||
}, f func(protoreflect.EnumDescriptor)) {
|
||||
eds := d.Enums()
|
||||
for i := eds.Len() - 1; i >= 0; i-- {
|
||||
f(eds.Get(i))
|
||||
}
|
||||
mds := d.Messages()
|
||||
for i := mds.Len() - 1; i >= 0; i-- {
|
||||
walkEnums(mds.Get(i), f)
|
||||
}
|
||||
}
|
||||
|
||||
// messageName is the full name of protobuf message.
|
||||
type messageName = string
|
||||
|
||||
var messageTypeCache sync.Map // map[messageName]reflect.Type
|
||||
|
||||
// RegisterType is called from generated code to register the message Go type
|
||||
// for a message of the given name.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalTypes.RegisterMessage instead.
|
||||
func RegisterType(m Message, s messageName) {
|
||||
mt := protoimpl.X.LegacyMessageTypeOf(m, protoreflect.FullName(s))
|
||||
if err := protoregistry.GlobalTypes.RegisterMessage(mt); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
messageTypeCache.Store(s, reflect.TypeOf(m))
|
||||
}
|
||||
|
||||
// RegisterMapType is called from generated code to register the Go map type
|
||||
// for a protobuf message representing a map entry.
|
||||
//
|
||||
// Deprecated: Do not use.
|
||||
func RegisterMapType(m interface{}, s messageName) {
|
||||
t := reflect.TypeOf(m)
|
||||
if t.Kind() != reflect.Map {
|
||||
panic(fmt.Sprintf("invalid map kind: %v", t))
|
||||
}
|
||||
if _, ok := messageTypeCache.Load(s); ok {
|
||||
panic(fmt.Errorf("proto: duplicate proto message registered: %s", s))
|
||||
}
|
||||
messageTypeCache.Store(s, t)
|
||||
}
|
||||
|
||||
// MessageType returns the message type for a named message.
|
||||
// It returns nil if not found.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalTypes.FindMessageByName instead.
|
||||
func MessageType(s messageName) reflect.Type {
|
||||
if v, ok := messageTypeCache.Load(s); ok {
|
||||
return v.(reflect.Type)
|
||||
}
|
||||
|
||||
// Derive the message type from the v2 registry.
|
||||
var t reflect.Type
|
||||
if mt, _ := protoregistry.GlobalTypes.FindMessageByName(protoreflect.FullName(s)); mt != nil {
|
||||
t = messageGoType(mt)
|
||||
}
|
||||
|
||||
// If we could not get a concrete type, it is possible that it is a
|
||||
// pseudo-message for a map entry.
|
||||
if t == nil {
|
||||
d, _ := protoregistry.GlobalFiles.FindDescriptorByName(protoreflect.FullName(s))
|
||||
if md, _ := d.(protoreflect.MessageDescriptor); md != nil && md.IsMapEntry() {
|
||||
kt := goTypeForField(md.Fields().ByNumber(1))
|
||||
vt := goTypeForField(md.Fields().ByNumber(2))
|
||||
t = reflect.MapOf(kt, vt)
|
||||
}
|
||||
}
|
||||
|
||||
// Locally cache the message type for the given name.
|
||||
if t != nil {
|
||||
v, _ := messageTypeCache.LoadOrStore(s, t)
|
||||
return v.(reflect.Type)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func goTypeForField(fd protoreflect.FieldDescriptor) reflect.Type {
|
||||
switch k := fd.Kind(); k {
|
||||
case protoreflect.EnumKind:
|
||||
if et, _ := protoregistry.GlobalTypes.FindEnumByName(fd.Enum().FullName()); et != nil {
|
||||
return enumGoType(et)
|
||||
}
|
||||
return reflect.TypeOf(protoreflect.EnumNumber(0))
|
||||
case protoreflect.MessageKind, protoreflect.GroupKind:
|
||||
if mt, _ := protoregistry.GlobalTypes.FindMessageByName(fd.Message().FullName()); mt != nil {
|
||||
return messageGoType(mt)
|
||||
}
|
||||
return reflect.TypeOf((*protoreflect.Message)(nil)).Elem()
|
||||
default:
|
||||
return reflect.TypeOf(fd.Default().Interface())
|
||||
}
|
||||
}
|
||||
|
||||
func enumGoType(et protoreflect.EnumType) reflect.Type {
|
||||
return reflect.TypeOf(et.New(0))
|
||||
}
|
||||
|
||||
func messageGoType(mt protoreflect.MessageType) reflect.Type {
|
||||
return reflect.TypeOf(MessageV1(mt.Zero().Interface()))
|
||||
}
|
||||
|
||||
// MessageName returns the full protobuf name for the given message type.
|
||||
//
|
||||
// Deprecated: Use protoreflect.MessageDescriptor.FullName instead.
|
||||
func MessageName(m Message) messageName {
|
||||
if m == nil {
|
||||
return ""
|
||||
}
|
||||
if m, ok := m.(interface{ XXX_MessageName() messageName }); ok {
|
||||
return m.XXX_MessageName()
|
||||
}
|
||||
return messageName(protoimpl.X.MessageDescriptorOf(m).FullName())
|
||||
}
|
||||
|
||||
// RegisterExtension is called from the generated code to register
|
||||
// the extension descriptor.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalTypes.RegisterExtension instead.
|
||||
func RegisterExtension(d *ExtensionDesc) {
|
||||
if err := protoregistry.GlobalTypes.RegisterExtension(d); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
type extensionsByNumber = map[int32]*ExtensionDesc
|
||||
|
||||
var extensionCache sync.Map // map[messageName]extensionsByNumber
|
||||
|
||||
// RegisteredExtensions returns a map of the registered extensions for the
|
||||
// provided protobuf message, indexed by the extension field number.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalTypes.RangeExtensionsByMessage instead.
|
||||
func RegisteredExtensions(m Message) extensionsByNumber {
|
||||
// Check whether the cache is stale. If the number of extensions for
|
||||
// the given message differs, then it means that some extensions were
|
||||
// recently registered upstream that we do not know about.
|
||||
s := MessageName(m)
|
||||
v, _ := extensionCache.Load(s)
|
||||
xs, _ := v.(extensionsByNumber)
|
||||
if protoregistry.GlobalTypes.NumExtensionsByMessage(protoreflect.FullName(s)) == len(xs) {
|
||||
return xs // cache is up-to-date
|
||||
}
|
||||
|
||||
// Cache is stale, re-compute the extensions map.
|
||||
xs = make(extensionsByNumber)
|
||||
protoregistry.GlobalTypes.RangeExtensionsByMessage(protoreflect.FullName(s), func(xt protoreflect.ExtensionType) bool {
|
||||
if xd, ok := xt.(*ExtensionDesc); ok {
|
||||
xs[int32(xt.TypeDescriptor().Number())] = xd
|
||||
} else {
|
||||
// TODO: This implies that the protoreflect.ExtensionType is a
|
||||
// custom type not generated by protoc-gen-go. We could try and
|
||||
// convert the type to an ExtensionDesc.
|
||||
}
|
||||
return true
|
||||
})
|
||||
extensionCache.Store(s, xs)
|
||||
return xs
|
||||
}
|
801
vendor/github.com/golang/protobuf/proto/text_decode.go
generated
vendored
801
vendor/github.com/golang/protobuf/proto/text_decode.go
generated
vendored
@ -1,801 +0,0 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"google.golang.org/protobuf/encoding/prototext"
|
||||
protoV2 "google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
)
|
||||
|
||||
const wrapTextUnmarshalV2 = false
|
||||
|
||||
// ParseError is returned by UnmarshalText.
|
||||
type ParseError struct {
|
||||
Message string
|
||||
|
||||
// Deprecated: Do not use.
|
||||
Line, Offset int
|
||||
}
|
||||
|
||||
func (e *ParseError) Error() string {
|
||||
if wrapTextUnmarshalV2 {
|
||||
return e.Message
|
||||
}
|
||||
if e.Line == 1 {
|
||||
return fmt.Sprintf("line 1.%d: %v", e.Offset, e.Message)
|
||||
}
|
||||
return fmt.Sprintf("line %d: %v", e.Line, e.Message)
|
||||
}
|
||||
|
||||
// UnmarshalText parses a proto text formatted string into m.
|
||||
func UnmarshalText(s string, m Message) error {
|
||||
if u, ok := m.(encoding.TextUnmarshaler); ok {
|
||||
return u.UnmarshalText([]byte(s))
|
||||
}
|
||||
|
||||
m.Reset()
|
||||
mi := MessageV2(m)
|
||||
|
||||
if wrapTextUnmarshalV2 {
|
||||
err := prototext.UnmarshalOptions{
|
||||
AllowPartial: true,
|
||||
}.Unmarshal([]byte(s), mi)
|
||||
if err != nil {
|
||||
return &ParseError{Message: err.Error()}
|
||||
}
|
||||
return checkRequiredNotSet(mi)
|
||||
} else {
|
||||
if err := newTextParser(s).unmarshalMessage(mi.ProtoReflect(), ""); err != nil {
|
||||
return err
|
||||
}
|
||||
return checkRequiredNotSet(mi)
|
||||
}
|
||||
}
|
||||
|
||||
type textParser struct {
|
||||
s string // remaining input
|
||||
done bool // whether the parsing is finished (success or error)
|
||||
backed bool // whether back() was called
|
||||
offset, line int
|
||||
cur token
|
||||
}
|
||||
|
||||
type token struct {
|
||||
value string
|
||||
err *ParseError
|
||||
line int // line number
|
||||
offset int // byte number from start of input, not start of line
|
||||
unquoted string // the unquoted version of value, if it was a quoted string
|
||||
}
|
||||
|
||||
func newTextParser(s string) *textParser {
|
||||
p := new(textParser)
|
||||
p.s = s
|
||||
p.line = 1
|
||||
p.cur.line = 1
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *textParser) unmarshalMessage(m protoreflect.Message, terminator string) (err error) {
|
||||
md := m.Descriptor()
|
||||
fds := md.Fields()
|
||||
|
||||
// A struct is a sequence of "name: value", terminated by one of
|
||||
// '>' or '}', or the end of the input. A name may also be
|
||||
// "[extension]" or "[type/url]".
|
||||
//
|
||||
// The whole struct can also be an expanded Any message, like:
|
||||
// [type/url] < ... struct contents ... >
|
||||
seen := make(map[protoreflect.FieldNumber]bool)
|
||||
for {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return tok.err
|
||||
}
|
||||
if tok.value == terminator {
|
||||
break
|
||||
}
|
||||
if tok.value == "[" {
|
||||
if err := p.unmarshalExtensionOrAny(m, seen); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// This is a normal, non-extension field.
|
||||
name := protoreflect.Name(tok.value)
|
||||
fd := fds.ByName(name)
|
||||
switch {
|
||||
case fd == nil:
|
||||
gd := fds.ByName(protoreflect.Name(strings.ToLower(string(name))))
|
||||
if gd != nil && gd.Kind() == protoreflect.GroupKind && gd.Message().Name() == name {
|
||||
fd = gd
|
||||
}
|
||||
case fd.Kind() == protoreflect.GroupKind && fd.Message().Name() != name:
|
||||
fd = nil
|
||||
case fd.IsWeak() && fd.Message().IsPlaceholder():
|
||||
fd = nil
|
||||
}
|
||||
if fd == nil {
|
||||
typeName := string(md.FullName())
|
||||
if m, ok := m.Interface().(Message); ok {
|
||||
t := reflect.TypeOf(m)
|
||||
if t.Kind() == reflect.Ptr {
|
||||
typeName = t.Elem().String()
|
||||
}
|
||||
}
|
||||
return p.errorf("unknown field name %q in %v", name, typeName)
|
||||
}
|
||||
if od := fd.ContainingOneof(); od != nil && m.WhichOneof(od) != nil {
|
||||
return p.errorf("field '%s' would overwrite already parsed oneof '%s'", name, od.Name())
|
||||
}
|
||||
if fd.Cardinality() != protoreflect.Repeated && seen[fd.Number()] {
|
||||
return p.errorf("non-repeated field %q was repeated", fd.Name())
|
||||
}
|
||||
seen[fd.Number()] = true
|
||||
|
||||
// Consume any colon.
|
||||
if err := p.checkForColon(fd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Parse into the field.
|
||||
v := m.Get(fd)
|
||||
if !m.Has(fd) && (fd.IsList() || fd.IsMap() || fd.Message() != nil) {
|
||||
v = m.Mutable(fd)
|
||||
}
|
||||
if v, err = p.unmarshalValue(v, fd); err != nil {
|
||||
return err
|
||||
}
|
||||
m.Set(fd, v)
|
||||
|
||||
if err := p.consumeOptionalSeparator(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *textParser) unmarshalExtensionOrAny(m protoreflect.Message, seen map[protoreflect.FieldNumber]bool) error {
|
||||
name, err := p.consumeExtensionOrAnyName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If it contains a slash, it's an Any type URL.
|
||||
if slashIdx := strings.LastIndex(name, "/"); slashIdx >= 0 {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return tok.err
|
||||
}
|
||||
// consume an optional colon
|
||||
if tok.value == ":" {
|
||||
tok = p.next()
|
||||
if tok.err != nil {
|
||||
return tok.err
|
||||
}
|
||||
}
|
||||
|
||||
var terminator string
|
||||
switch tok.value {
|
||||
case "<":
|
||||
terminator = ">"
|
||||
case "{":
|
||||
terminator = "}"
|
||||
default:
|
||||
return p.errorf("expected '{' or '<', found %q", tok.value)
|
||||
}
|
||||
|
||||
mt, err := protoregistry.GlobalTypes.FindMessageByURL(name)
|
||||
if err != nil {
|
||||
return p.errorf("unrecognized message %q in google.protobuf.Any", name[slashIdx+len("/"):])
|
||||
}
|
||||
m2 := mt.New()
|
||||
if err := p.unmarshalMessage(m2, terminator); err != nil {
|
||||
return err
|
||||
}
|
||||
b, err := protoV2.Marshal(m2.Interface())
|
||||
if err != nil {
|
||||
return p.errorf("failed to marshal message of type %q: %v", name[slashIdx+len("/"):], err)
|
||||
}
|
||||
|
||||
urlFD := m.Descriptor().Fields().ByName("type_url")
|
||||
valFD := m.Descriptor().Fields().ByName("value")
|
||||
if seen[urlFD.Number()] {
|
||||
return p.errorf("Any message unpacked multiple times, or %q already set", urlFD.Name())
|
||||
}
|
||||
if seen[valFD.Number()] {
|
||||
return p.errorf("Any message unpacked multiple times, or %q already set", valFD.Name())
|
||||
}
|
||||
m.Set(urlFD, protoreflect.ValueOfString(name))
|
||||
m.Set(valFD, protoreflect.ValueOfBytes(b))
|
||||
seen[urlFD.Number()] = true
|
||||
seen[valFD.Number()] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
xname := protoreflect.FullName(name)
|
||||
xt, _ := protoregistry.GlobalTypes.FindExtensionByName(xname)
|
||||
if xt == nil && isMessageSet(m.Descriptor()) {
|
||||
xt, _ = protoregistry.GlobalTypes.FindExtensionByName(xname.Append("message_set_extension"))
|
||||
}
|
||||
if xt == nil {
|
||||
return p.errorf("unrecognized extension %q", name)
|
||||
}
|
||||
fd := xt.TypeDescriptor()
|
||||
if fd.ContainingMessage().FullName() != m.Descriptor().FullName() {
|
||||
return p.errorf("extension field %q does not extend message %q", name, m.Descriptor().FullName())
|
||||
}
|
||||
|
||||
if err := p.checkForColon(fd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v := m.Get(fd)
|
||||
if !m.Has(fd) && (fd.IsList() || fd.IsMap() || fd.Message() != nil) {
|
||||
v = m.Mutable(fd)
|
||||
}
|
||||
v, err = p.unmarshalValue(v, fd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.Set(fd, v)
|
||||
return p.consumeOptionalSeparator()
|
||||
}
|
||||
|
||||
func (p *textParser) unmarshalValue(v protoreflect.Value, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return v, tok.err
|
||||
}
|
||||
if tok.value == "" {
|
||||
return v, p.errorf("unexpected EOF")
|
||||
}
|
||||
|
||||
switch {
|
||||
case fd.IsList():
|
||||
lv := v.List()
|
||||
var err error
|
||||
if tok.value == "[" {
|
||||
// Repeated field with list notation, like [1,2,3].
|
||||
for {
|
||||
vv := lv.NewElement()
|
||||
vv, err = p.unmarshalSingularValue(vv, fd)
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
lv.Append(vv)
|
||||
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return v, tok.err
|
||||
}
|
||||
if tok.value == "]" {
|
||||
break
|
||||
}
|
||||
if tok.value != "," {
|
||||
return v, p.errorf("Expected ']' or ',' found %q", tok.value)
|
||||
}
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// One value of the repeated field.
|
||||
p.back()
|
||||
vv := lv.NewElement()
|
||||
vv, err = p.unmarshalSingularValue(vv, fd)
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
lv.Append(vv)
|
||||
return v, nil
|
||||
case fd.IsMap():
|
||||
// The map entry should be this sequence of tokens:
|
||||
// < key : KEY value : VALUE >
|
||||
// However, implementations may omit key or value, and technically
|
||||
// we should support them in any order.
|
||||
var terminator string
|
||||
switch tok.value {
|
||||
case "<":
|
||||
terminator = ">"
|
||||
case "{":
|
||||
terminator = "}"
|
||||
default:
|
||||
return v, p.errorf("expected '{' or '<', found %q", tok.value)
|
||||
}
|
||||
|
||||
keyFD := fd.MapKey()
|
||||
valFD := fd.MapValue()
|
||||
|
||||
mv := v.Map()
|
||||
kv := keyFD.Default()
|
||||
vv := mv.NewValue()
|
||||
for {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return v, tok.err
|
||||
}
|
||||
if tok.value == terminator {
|
||||
break
|
||||
}
|
||||
var err error
|
||||
switch tok.value {
|
||||
case "key":
|
||||
if err := p.consumeToken(":"); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if kv, err = p.unmarshalSingularValue(kv, keyFD); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if err := p.consumeOptionalSeparator(); err != nil {
|
||||
return v, err
|
||||
}
|
||||
case "value":
|
||||
if err := p.checkForColon(valFD); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if vv, err = p.unmarshalSingularValue(vv, valFD); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if err := p.consumeOptionalSeparator(); err != nil {
|
||||
return v, err
|
||||
}
|
||||
default:
|
||||
p.back()
|
||||
return v, p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value)
|
||||
}
|
||||
}
|
||||
mv.Set(kv.MapKey(), vv)
|
||||
return v, nil
|
||||
default:
|
||||
p.back()
|
||||
return p.unmarshalSingularValue(v, fd)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *textParser) unmarshalSingularValue(v protoreflect.Value, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return v, tok.err
|
||||
}
|
||||
if tok.value == "" {
|
||||
return v, p.errorf("unexpected EOF")
|
||||
}
|
||||
|
||||
switch fd.Kind() {
|
||||
case protoreflect.BoolKind:
|
||||
switch tok.value {
|
||||
case "true", "1", "t", "True":
|
||||
return protoreflect.ValueOfBool(true), nil
|
||||
case "false", "0", "f", "False":
|
||||
return protoreflect.ValueOfBool(false), nil
|
||||
}
|
||||
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
|
||||
if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
|
||||
return protoreflect.ValueOfInt32(int32(x)), nil
|
||||
}
|
||||
|
||||
// The C++ parser accepts large positive hex numbers that uses
|
||||
// two's complement arithmetic to represent negative numbers.
|
||||
// This feature is here for backwards compatibility with C++.
|
||||
if strings.HasPrefix(tok.value, "0x") {
|
||||
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
|
||||
return protoreflect.ValueOfInt32(int32(-(int64(^x) + 1))), nil
|
||||
}
|
||||
}
|
||||
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
|
||||
if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil {
|
||||
return protoreflect.ValueOfInt64(int64(x)), nil
|
||||
}
|
||||
|
||||
// The C++ parser accepts large positive hex numbers that uses
|
||||
// two's complement arithmetic to represent negative numbers.
|
||||
// This feature is here for backwards compatibility with C++.
|
||||
if strings.HasPrefix(tok.value, "0x") {
|
||||
if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
|
||||
return protoreflect.ValueOfInt64(int64(-(int64(^x) + 1))), nil
|
||||
}
|
||||
}
|
||||
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
|
||||
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
|
||||
return protoreflect.ValueOfUint32(uint32(x)), nil
|
||||
}
|
||||
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
|
||||
if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
|
||||
return protoreflect.ValueOfUint64(uint64(x)), nil
|
||||
}
|
||||
case protoreflect.FloatKind:
|
||||
// Ignore 'f' for compatibility with output generated by C++,
|
||||
// but don't remove 'f' when the value is "-inf" or "inf".
|
||||
v := tok.value
|
||||
if strings.HasSuffix(v, "f") && v != "-inf" && v != "inf" {
|
||||
v = v[:len(v)-len("f")]
|
||||
}
|
||||
if x, err := strconv.ParseFloat(v, 32); err == nil {
|
||||
return protoreflect.ValueOfFloat32(float32(x)), nil
|
||||
}
|
||||
case protoreflect.DoubleKind:
|
||||
// Ignore 'f' for compatibility with output generated by C++,
|
||||
// but don't remove 'f' when the value is "-inf" or "inf".
|
||||
v := tok.value
|
||||
if strings.HasSuffix(v, "f") && v != "-inf" && v != "inf" {
|
||||
v = v[:len(v)-len("f")]
|
||||
}
|
||||
if x, err := strconv.ParseFloat(v, 64); err == nil {
|
||||
return protoreflect.ValueOfFloat64(float64(x)), nil
|
||||
}
|
||||
case protoreflect.StringKind:
|
||||
if isQuote(tok.value[0]) {
|
||||
return protoreflect.ValueOfString(tok.unquoted), nil
|
||||
}
|
||||
case protoreflect.BytesKind:
|
||||
if isQuote(tok.value[0]) {
|
||||
return protoreflect.ValueOfBytes([]byte(tok.unquoted)), nil
|
||||
}
|
||||
case protoreflect.EnumKind:
|
||||
if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
|
||||
return protoreflect.ValueOfEnum(protoreflect.EnumNumber(x)), nil
|
||||
}
|
||||
vd := fd.Enum().Values().ByName(protoreflect.Name(tok.value))
|
||||
if vd != nil {
|
||||
return protoreflect.ValueOfEnum(vd.Number()), nil
|
||||
}
|
||||
case protoreflect.MessageKind, protoreflect.GroupKind:
|
||||
var terminator string
|
||||
switch tok.value {
|
||||
case "{":
|
||||
terminator = "}"
|
||||
case "<":
|
||||
terminator = ">"
|
||||
default:
|
||||
return v, p.errorf("expected '{' or '<', found %q", tok.value)
|
||||
}
|
||||
err := p.unmarshalMessage(v.Message(), terminator)
|
||||
return v, err
|
||||
default:
|
||||
panic(fmt.Sprintf("invalid kind %v", fd.Kind()))
|
||||
}
|
||||
return v, p.errorf("invalid %v: %v", fd.Kind(), tok.value)
|
||||
}
|
||||
|
||||
// Consume a ':' from the input stream (if the next token is a colon),
|
||||
// returning an error if a colon is needed but not present.
|
||||
func (p *textParser) checkForColon(fd protoreflect.FieldDescriptor) *ParseError {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return tok.err
|
||||
}
|
||||
if tok.value != ":" {
|
||||
if fd.Message() == nil {
|
||||
return p.errorf("expected ':', found %q", tok.value)
|
||||
}
|
||||
p.back()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// consumeExtensionOrAnyName consumes an extension name or an Any type URL and
|
||||
// the following ']'. It returns the name or URL consumed.
|
||||
func (p *textParser) consumeExtensionOrAnyName() (string, error) {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return "", tok.err
|
||||
}
|
||||
|
||||
// If extension name or type url is quoted, it's a single token.
|
||||
if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] {
|
||||
name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0]))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return name, p.consumeToken("]")
|
||||
}
|
||||
|
||||
// Consume everything up to "]"
|
||||
var parts []string
|
||||
for tok.value != "]" {
|
||||
parts = append(parts, tok.value)
|
||||
tok = p.next()
|
||||
if tok.err != nil {
|
||||
return "", p.errorf("unrecognized type_url or extension name: %s", tok.err)
|
||||
}
|
||||
if p.done && tok.value != "]" {
|
||||
return "", p.errorf("unclosed type_url or extension name")
|
||||
}
|
||||
}
|
||||
return strings.Join(parts, ""), nil
|
||||
}
|
||||
|
||||
// consumeOptionalSeparator consumes an optional semicolon or comma.
|
||||
// It is used in unmarshalMessage to provide backward compatibility.
|
||||
func (p *textParser) consumeOptionalSeparator() error {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return tok.err
|
||||
}
|
||||
if tok.value != ";" && tok.value != "," {
|
||||
p.back()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *textParser) errorf(format string, a ...interface{}) *ParseError {
|
||||
pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset}
|
||||
p.cur.err = pe
|
||||
p.done = true
|
||||
return pe
|
||||
}
|
||||
|
||||
func (p *textParser) skipWhitespace() {
|
||||
i := 0
|
||||
for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') {
|
||||
if p.s[i] == '#' {
|
||||
// comment; skip to end of line or input
|
||||
for i < len(p.s) && p.s[i] != '\n' {
|
||||
i++
|
||||
}
|
||||
if i == len(p.s) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if p.s[i] == '\n' {
|
||||
p.line++
|
||||
}
|
||||
i++
|
||||
}
|
||||
p.offset += i
|
||||
p.s = p.s[i:len(p.s)]
|
||||
if len(p.s) == 0 {
|
||||
p.done = true
|
||||
}
|
||||
}
|
||||
|
||||
func (p *textParser) advance() {
|
||||
// Skip whitespace
|
||||
p.skipWhitespace()
|
||||
if p.done {
|
||||
return
|
||||
}
|
||||
|
||||
// Start of non-whitespace
|
||||
p.cur.err = nil
|
||||
p.cur.offset, p.cur.line = p.offset, p.line
|
||||
p.cur.unquoted = ""
|
||||
switch p.s[0] {
|
||||
case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/':
|
||||
// Single symbol
|
||||
p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)]
|
||||
case '"', '\'':
|
||||
// Quoted string
|
||||
i := 1
|
||||
for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' {
|
||||
if p.s[i] == '\\' && i+1 < len(p.s) {
|
||||
// skip escaped char
|
||||
i++
|
||||
}
|
||||
i++
|
||||
}
|
||||
if i >= len(p.s) || p.s[i] != p.s[0] {
|
||||
p.errorf("unmatched quote")
|
||||
return
|
||||
}
|
||||
unq, err := unquoteC(p.s[1:i], rune(p.s[0]))
|
||||
if err != nil {
|
||||
p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err)
|
||||
return
|
||||
}
|
||||
p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)]
|
||||
p.cur.unquoted = unq
|
||||
default:
|
||||
i := 0
|
||||
for i < len(p.s) && isIdentOrNumberChar(p.s[i]) {
|
||||
i++
|
||||
}
|
||||
if i == 0 {
|
||||
p.errorf("unexpected byte %#x", p.s[0])
|
||||
return
|
||||
}
|
||||
p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)]
|
||||
}
|
||||
p.offset += len(p.cur.value)
|
||||
}
|
||||
|
||||
// Back off the parser by one token. Can only be done between calls to next().
|
||||
// It makes the next advance() a no-op.
|
||||
func (p *textParser) back() { p.backed = true }
|
||||
|
||||
// Advances the parser and returns the new current token.
|
||||
func (p *textParser) next() *token {
|
||||
if p.backed || p.done {
|
||||
p.backed = false
|
||||
return &p.cur
|
||||
}
|
||||
p.advance()
|
||||
if p.done {
|
||||
p.cur.value = ""
|
||||
} else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) {
|
||||
// Look for multiple quoted strings separated by whitespace,
|
||||
// and concatenate them.
|
||||
cat := p.cur
|
||||
for {
|
||||
p.skipWhitespace()
|
||||
if p.done || !isQuote(p.s[0]) {
|
||||
break
|
||||
}
|
||||
p.advance()
|
||||
if p.cur.err != nil {
|
||||
return &p.cur
|
||||
}
|
||||
cat.value += " " + p.cur.value
|
||||
cat.unquoted += p.cur.unquoted
|
||||
}
|
||||
p.done = false // parser may have seen EOF, but we want to return cat
|
||||
p.cur = cat
|
||||
}
|
||||
return &p.cur
|
||||
}
|
||||
|
||||
func (p *textParser) consumeToken(s string) error {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return tok.err
|
||||
}
|
||||
if tok.value != s {
|
||||
p.back()
|
||||
return p.errorf("expected %q, found %q", s, tok.value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var errBadUTF8 = errors.New("proto: bad UTF-8")
|
||||
|
||||
func unquoteC(s string, quote rune) (string, error) {
|
||||
// This is based on C++'s tokenizer.cc.
|
||||
// Despite its name, this is *not* parsing C syntax.
|
||||
// For instance, "\0" is an invalid quoted string.
|
||||
|
||||
// Avoid allocation in trivial cases.
|
||||
simple := true
|
||||
for _, r := range s {
|
||||
if r == '\\' || r == quote {
|
||||
simple = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if simple {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
buf := make([]byte, 0, 3*len(s)/2)
|
||||
for len(s) > 0 {
|
||||
r, n := utf8.DecodeRuneInString(s)
|
||||
if r == utf8.RuneError && n == 1 {
|
||||
return "", errBadUTF8
|
||||
}
|
||||
s = s[n:]
|
||||
if r != '\\' {
|
||||
if r < utf8.RuneSelf {
|
||||
buf = append(buf, byte(r))
|
||||
} else {
|
||||
buf = append(buf, string(r)...)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
ch, tail, err := unescape(s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
buf = append(buf, ch...)
|
||||
s = tail
|
||||
}
|
||||
return string(buf), nil
|
||||
}
|
||||
|
||||
func unescape(s string) (ch string, tail string, err error) {
|
||||
r, n := utf8.DecodeRuneInString(s)
|
||||
if r == utf8.RuneError && n == 1 {
|
||||
return "", "", errBadUTF8
|
||||
}
|
||||
s = s[n:]
|
||||
switch r {
|
||||
case 'a':
|
||||
return "\a", s, nil
|
||||
case 'b':
|
||||
return "\b", s, nil
|
||||
case 'f':
|
||||
return "\f", s, nil
|
||||
case 'n':
|
||||
return "\n", s, nil
|
||||
case 'r':
|
||||
return "\r", s, nil
|
||||
case 't':
|
||||
return "\t", s, nil
|
||||
case 'v':
|
||||
return "\v", s, nil
|
||||
case '?':
|
||||
return "?", s, nil // trigraph workaround
|
||||
case '\'', '"', '\\':
|
||||
return string(r), s, nil
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7':
|
||||
if len(s) < 2 {
|
||||
return "", "", fmt.Errorf(`\%c requires 2 following digits`, r)
|
||||
}
|
||||
ss := string(r) + s[:2]
|
||||
s = s[2:]
|
||||
i, err := strconv.ParseUint(ss, 8, 8)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss)
|
||||
}
|
||||
return string([]byte{byte(i)}), s, nil
|
||||
case 'x', 'X', 'u', 'U':
|
||||
var n int
|
||||
switch r {
|
||||
case 'x', 'X':
|
||||
n = 2
|
||||
case 'u':
|
||||
n = 4
|
||||
case 'U':
|
||||
n = 8
|
||||
}
|
||||
if len(s) < n {
|
||||
return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n)
|
||||
}
|
||||
ss := s[:n]
|
||||
s = s[n:]
|
||||
i, err := strconv.ParseUint(ss, 16, 64)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss)
|
||||
}
|
||||
if r == 'x' || r == 'X' {
|
||||
return string([]byte{byte(i)}), s, nil
|
||||
}
|
||||
if i > utf8.MaxRune {
|
||||
return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss)
|
||||
}
|
||||
return string(rune(i)), s, nil
|
||||
}
|
||||
return "", "", fmt.Errorf(`unknown escape \%c`, r)
|
||||
}
|
||||
|
||||
func isIdentOrNumberChar(c byte) bool {
|
||||
switch {
|
||||
case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z':
|
||||
return true
|
||||
case '0' <= c && c <= '9':
|
||||
return true
|
||||
}
|
||||
switch c {
|
||||
case '-', '+', '.', '_':
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isWhitespace(c byte) bool {
|
||||
switch c {
|
||||
case ' ', '\t', '\n', '\r':
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isQuote(c byte) bool {
|
||||
switch c {
|
||||
case '"', '\'':
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
560
vendor/github.com/golang/protobuf/proto/text_encode.go
generated
vendored
560
vendor/github.com/golang/protobuf/proto/text_encode.go
generated
vendored
@ -1,560 +0,0 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/protobuf/encoding/prototext"
|
||||
"google.golang.org/protobuf/encoding/protowire"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
)
|
||||
|
||||
const wrapTextMarshalV2 = false
|
||||
|
||||
// TextMarshaler is a configurable text format marshaler.
|
||||
type TextMarshaler struct {
|
||||
Compact bool // use compact text format (one line)
|
||||
ExpandAny bool // expand google.protobuf.Any messages of known types
|
||||
}
|
||||
|
||||
// Marshal writes the proto text format of m to w.
|
||||
func (tm *TextMarshaler) Marshal(w io.Writer, m Message) error {
|
||||
b, err := tm.marshal(m)
|
||||
if len(b) > 0 {
|
||||
if _, err := w.Write(b); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Text returns a proto text formatted string of m.
|
||||
func (tm *TextMarshaler) Text(m Message) string {
|
||||
b, _ := tm.marshal(m)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (tm *TextMarshaler) marshal(m Message) ([]byte, error) {
|
||||
mr := MessageReflect(m)
|
||||
if mr == nil || !mr.IsValid() {
|
||||
return []byte("<nil>"), nil
|
||||
}
|
||||
|
||||
if wrapTextMarshalV2 {
|
||||
if m, ok := m.(encoding.TextMarshaler); ok {
|
||||
return m.MarshalText()
|
||||
}
|
||||
|
||||
opts := prototext.MarshalOptions{
|
||||
AllowPartial: true,
|
||||
EmitUnknown: true,
|
||||
}
|
||||
if !tm.Compact {
|
||||
opts.Indent = " "
|
||||
}
|
||||
if !tm.ExpandAny {
|
||||
opts.Resolver = (*protoregistry.Types)(nil)
|
||||
}
|
||||
return opts.Marshal(mr.Interface())
|
||||
} else {
|
||||
w := &textWriter{
|
||||
compact: tm.Compact,
|
||||
expandAny: tm.ExpandAny,
|
||||
complete: true,
|
||||
}
|
||||
|
||||
if m, ok := m.(encoding.TextMarshaler); ok {
|
||||
b, err := m.MarshalText()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
w.Write(b)
|
||||
return w.buf, nil
|
||||
}
|
||||
|
||||
err := w.writeMessage(mr)
|
||||
return w.buf, err
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
defaultTextMarshaler = TextMarshaler{}
|
||||
compactTextMarshaler = TextMarshaler{Compact: true}
|
||||
)
|
||||
|
||||
// MarshalText writes the proto text format of m to w.
|
||||
func MarshalText(w io.Writer, m Message) error { return defaultTextMarshaler.Marshal(w, m) }
|
||||
|
||||
// MarshalTextString returns a proto text formatted string of m.
|
||||
func MarshalTextString(m Message) string { return defaultTextMarshaler.Text(m) }
|
||||
|
||||
// CompactText writes the compact proto text format of m to w.
|
||||
func CompactText(w io.Writer, m Message) error { return compactTextMarshaler.Marshal(w, m) }
|
||||
|
||||
// CompactTextString returns a compact proto text formatted string of m.
|
||||
func CompactTextString(m Message) string { return compactTextMarshaler.Text(m) }
|
||||
|
||||
var (
|
||||
newline = []byte("\n")
|
||||
endBraceNewline = []byte("}\n")
|
||||
posInf = []byte("inf")
|
||||
negInf = []byte("-inf")
|
||||
nan = []byte("nan")
|
||||
)
|
||||
|
||||
// textWriter is an io.Writer that tracks its indentation level.
|
||||
type textWriter struct {
|
||||
compact bool // same as TextMarshaler.Compact
|
||||
expandAny bool // same as TextMarshaler.ExpandAny
|
||||
complete bool // whether the current position is a complete line
|
||||
indent int // indentation level; never negative
|
||||
buf []byte
|
||||
}
|
||||
|
||||
func (w *textWriter) Write(p []byte) (n int, _ error) {
|
||||
newlines := bytes.Count(p, newline)
|
||||
if newlines == 0 {
|
||||
if !w.compact && w.complete {
|
||||
w.writeIndent()
|
||||
}
|
||||
w.buf = append(w.buf, p...)
|
||||
w.complete = false
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
frags := bytes.SplitN(p, newline, newlines+1)
|
||||
if w.compact {
|
||||
for i, frag := range frags {
|
||||
if i > 0 {
|
||||
w.buf = append(w.buf, ' ')
|
||||
n++
|
||||
}
|
||||
w.buf = append(w.buf, frag...)
|
||||
n += len(frag)
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
for i, frag := range frags {
|
||||
if w.complete {
|
||||
w.writeIndent()
|
||||
}
|
||||
w.buf = append(w.buf, frag...)
|
||||
n += len(frag)
|
||||
if i+1 < len(frags) {
|
||||
w.buf = append(w.buf, '\n')
|
||||
n++
|
||||
}
|
||||
}
|
||||
w.complete = len(frags[len(frags)-1]) == 0
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (w *textWriter) WriteByte(c byte) error {
|
||||
if w.compact && c == '\n' {
|
||||
c = ' '
|
||||
}
|
||||
if !w.compact && w.complete {
|
||||
w.writeIndent()
|
||||
}
|
||||
w.buf = append(w.buf, c)
|
||||
w.complete = c == '\n'
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *textWriter) writeName(fd protoreflect.FieldDescriptor) {
|
||||
if !w.compact && w.complete {
|
||||
w.writeIndent()
|
||||
}
|
||||
w.complete = false
|
||||
|
||||
if fd.Kind() != protoreflect.GroupKind {
|
||||
w.buf = append(w.buf, fd.Name()...)
|
||||
w.WriteByte(':')
|
||||
} else {
|
||||
// Use message type name for group field name.
|
||||
w.buf = append(w.buf, fd.Message().Name()...)
|
||||
}
|
||||
|
||||
if !w.compact {
|
||||
w.WriteByte(' ')
|
||||
}
|
||||
}
|
||||
|
||||
func requiresQuotes(u string) bool {
|
||||
// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
|
||||
for _, ch := range u {
|
||||
switch {
|
||||
case ch == '.' || ch == '/' || ch == '_':
|
||||
continue
|
||||
case '0' <= ch && ch <= '9':
|
||||
continue
|
||||
case 'A' <= ch && ch <= 'Z':
|
||||
continue
|
||||
case 'a' <= ch && ch <= 'z':
|
||||
continue
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// writeProto3Any writes an expanded google.protobuf.Any message.
|
||||
//
|
||||
// It returns (false, nil) if sv value can't be unmarshaled (e.g. because
|
||||
// required messages are not linked in).
|
||||
//
|
||||
// It returns (true, error) when sv was written in expanded format or an error
|
||||
// was encountered.
|
||||
func (w *textWriter) writeProto3Any(m protoreflect.Message) (bool, error) {
|
||||
md := m.Descriptor()
|
||||
fdURL := md.Fields().ByName("type_url")
|
||||
fdVal := md.Fields().ByName("value")
|
||||
|
||||
url := m.Get(fdURL).String()
|
||||
mt, err := protoregistry.GlobalTypes.FindMessageByURL(url)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
b := m.Get(fdVal).Bytes()
|
||||
m2 := mt.New()
|
||||
if err := proto.Unmarshal(b, m2.Interface()); err != nil {
|
||||
return false, nil
|
||||
}
|
||||
w.Write([]byte("["))
|
||||
if requiresQuotes(url) {
|
||||
w.writeQuotedString(url)
|
||||
} else {
|
||||
w.Write([]byte(url))
|
||||
}
|
||||
if w.compact {
|
||||
w.Write([]byte("]:<"))
|
||||
} else {
|
||||
w.Write([]byte("]: <\n"))
|
||||
w.indent++
|
||||
}
|
||||
if err := w.writeMessage(m2); err != nil {
|
||||
return true, err
|
||||
}
|
||||
if w.compact {
|
||||
w.Write([]byte("> "))
|
||||
} else {
|
||||
w.indent--
|
||||
w.Write([]byte(">\n"))
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (w *textWriter) writeMessage(m protoreflect.Message) error {
|
||||
md := m.Descriptor()
|
||||
if w.expandAny && md.FullName() == "google.protobuf.Any" {
|
||||
if canExpand, err := w.writeProto3Any(m); canExpand {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
fds := md.Fields()
|
||||
for i := 0; i < fds.Len(); {
|
||||
fd := fds.Get(i)
|
||||
if od := fd.ContainingOneof(); od != nil {
|
||||
fd = m.WhichOneof(od)
|
||||
i += od.Fields().Len()
|
||||
} else {
|
||||
i++
|
||||
}
|
||||
if fd == nil || !m.Has(fd) {
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case fd.IsList():
|
||||
lv := m.Get(fd).List()
|
||||
for j := 0; j < lv.Len(); j++ {
|
||||
w.writeName(fd)
|
||||
v := lv.Get(j)
|
||||
if err := w.writeSingularValue(v, fd); err != nil {
|
||||
return err
|
||||
}
|
||||
w.WriteByte('\n')
|
||||
}
|
||||
case fd.IsMap():
|
||||
kfd := fd.MapKey()
|
||||
vfd := fd.MapValue()
|
||||
mv := m.Get(fd).Map()
|
||||
|
||||
type entry struct{ key, val protoreflect.Value }
|
||||
var entries []entry
|
||||
mv.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
|
||||
entries = append(entries, entry{k.Value(), v})
|
||||
return true
|
||||
})
|
||||
sort.Slice(entries, func(i, j int) bool {
|
||||
switch kfd.Kind() {
|
||||
case protoreflect.BoolKind:
|
||||
return !entries[i].key.Bool() && entries[j].key.Bool()
|
||||
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
|
||||
return entries[i].key.Int() < entries[j].key.Int()
|
||||
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
|
||||
return entries[i].key.Uint() < entries[j].key.Uint()
|
||||
case protoreflect.StringKind:
|
||||
return entries[i].key.String() < entries[j].key.String()
|
||||
default:
|
||||
panic("invalid kind")
|
||||
}
|
||||
})
|
||||
for _, entry := range entries {
|
||||
w.writeName(fd)
|
||||
w.WriteByte('<')
|
||||
if !w.compact {
|
||||
w.WriteByte('\n')
|
||||
}
|
||||
w.indent++
|
||||
w.writeName(kfd)
|
||||
if err := w.writeSingularValue(entry.key, kfd); err != nil {
|
||||
return err
|
||||
}
|
||||
w.WriteByte('\n')
|
||||
w.writeName(vfd)
|
||||
if err := w.writeSingularValue(entry.val, vfd); err != nil {
|
||||
return err
|
||||
}
|
||||
w.WriteByte('\n')
|
||||
w.indent--
|
||||
w.WriteByte('>')
|
||||
w.WriteByte('\n')
|
||||
}
|
||||
default:
|
||||
w.writeName(fd)
|
||||
if err := w.writeSingularValue(m.Get(fd), fd); err != nil {
|
||||
return err
|
||||
}
|
||||
w.WriteByte('\n')
|
||||
}
|
||||
}
|
||||
|
||||
if b := m.GetUnknown(); len(b) > 0 {
|
||||
w.writeUnknownFields(b)
|
||||
}
|
||||
return w.writeExtensions(m)
|
||||
}
|
||||
|
||||
func (w *textWriter) writeSingularValue(v protoreflect.Value, fd protoreflect.FieldDescriptor) error {
|
||||
switch fd.Kind() {
|
||||
case protoreflect.FloatKind, protoreflect.DoubleKind:
|
||||
switch vf := v.Float(); {
|
||||
case math.IsInf(vf, +1):
|
||||
w.Write(posInf)
|
||||
case math.IsInf(vf, -1):
|
||||
w.Write(negInf)
|
||||
case math.IsNaN(vf):
|
||||
w.Write(nan)
|
||||
default:
|
||||
fmt.Fprint(w, v.Interface())
|
||||
}
|
||||
case protoreflect.StringKind:
|
||||
// NOTE: This does not validate UTF-8 for historical reasons.
|
||||
w.writeQuotedString(string(v.String()))
|
||||
case protoreflect.BytesKind:
|
||||
w.writeQuotedString(string(v.Bytes()))
|
||||
case protoreflect.MessageKind, protoreflect.GroupKind:
|
||||
var bra, ket byte = '<', '>'
|
||||
if fd.Kind() == protoreflect.GroupKind {
|
||||
bra, ket = '{', '}'
|
||||
}
|
||||
w.WriteByte(bra)
|
||||
if !w.compact {
|
||||
w.WriteByte('\n')
|
||||
}
|
||||
w.indent++
|
||||
m := v.Message()
|
||||
if m2, ok := m.Interface().(encoding.TextMarshaler); ok {
|
||||
b, err := m2.MarshalText()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w.Write(b)
|
||||
} else {
|
||||
w.writeMessage(m)
|
||||
}
|
||||
w.indent--
|
||||
w.WriteByte(ket)
|
||||
case protoreflect.EnumKind:
|
||||
if ev := fd.Enum().Values().ByNumber(v.Enum()); ev != nil {
|
||||
fmt.Fprint(w, ev.Name())
|
||||
} else {
|
||||
fmt.Fprint(w, v.Enum())
|
||||
}
|
||||
default:
|
||||
fmt.Fprint(w, v.Interface())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// writeQuotedString writes a quoted string in the protocol buffer text format.
|
||||
func (w *textWriter) writeQuotedString(s string) {
|
||||
w.WriteByte('"')
|
||||
for i := 0; i < len(s); i++ {
|
||||
switch c := s[i]; c {
|
||||
case '\n':
|
||||
w.buf = append(w.buf, `\n`...)
|
||||
case '\r':
|
||||
w.buf = append(w.buf, `\r`...)
|
||||
case '\t':
|
||||
w.buf = append(w.buf, `\t`...)
|
||||
case '"':
|
||||
w.buf = append(w.buf, `\"`...)
|
||||
case '\\':
|
||||
w.buf = append(w.buf, `\\`...)
|
||||
default:
|
||||
if isPrint := c >= 0x20 && c < 0x7f; isPrint {
|
||||
w.buf = append(w.buf, c)
|
||||
} else {
|
||||
w.buf = append(w.buf, fmt.Sprintf(`\%03o`, c)...)
|
||||
}
|
||||
}
|
||||
}
|
||||
w.WriteByte('"')
|
||||
}
|
||||
|
||||
func (w *textWriter) writeUnknownFields(b []byte) {
|
||||
if !w.compact {
|
||||
fmt.Fprintf(w, "/* %d unknown bytes */\n", len(b))
|
||||
}
|
||||
|
||||
for len(b) > 0 {
|
||||
num, wtyp, n := protowire.ConsumeTag(b)
|
||||
if n < 0 {
|
||||
return
|
||||
}
|
||||
b = b[n:]
|
||||
|
||||
if wtyp == protowire.EndGroupType {
|
||||
w.indent--
|
||||
w.Write(endBraceNewline)
|
||||
continue
|
||||
}
|
||||
fmt.Fprint(w, num)
|
||||
if wtyp != protowire.StartGroupType {
|
||||
w.WriteByte(':')
|
||||
}
|
||||
if !w.compact || wtyp == protowire.StartGroupType {
|
||||
w.WriteByte(' ')
|
||||
}
|
||||
switch wtyp {
|
||||
case protowire.VarintType:
|
||||
v, n := protowire.ConsumeVarint(b)
|
||||
if n < 0 {
|
||||
return
|
||||
}
|
||||
b = b[n:]
|
||||
fmt.Fprint(w, v)
|
||||
case protowire.Fixed32Type:
|
||||
v, n := protowire.ConsumeFixed32(b)
|
||||
if n < 0 {
|
||||
return
|
||||
}
|
||||
b = b[n:]
|
||||
fmt.Fprint(w, v)
|
||||
case protowire.Fixed64Type:
|
||||
v, n := protowire.ConsumeFixed64(b)
|
||||
if n < 0 {
|
||||
return
|
||||
}
|
||||
b = b[n:]
|
||||
fmt.Fprint(w, v)
|
||||
case protowire.BytesType:
|
||||
v, n := protowire.ConsumeBytes(b)
|
||||
if n < 0 {
|
||||
return
|
||||
}
|
||||
b = b[n:]
|
||||
fmt.Fprintf(w, "%q", v)
|
||||
case protowire.StartGroupType:
|
||||
w.WriteByte('{')
|
||||
w.indent++
|
||||
default:
|
||||
fmt.Fprintf(w, "/* unknown wire type %d */", wtyp)
|
||||
}
|
||||
w.WriteByte('\n')
|
||||
}
|
||||
}
|
||||
|
||||
// writeExtensions writes all the extensions in m.
|
||||
func (w *textWriter) writeExtensions(m protoreflect.Message) error {
|
||||
md := m.Descriptor()
|
||||
if md.ExtensionRanges().Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
type ext struct {
|
||||
desc protoreflect.FieldDescriptor
|
||||
val protoreflect.Value
|
||||
}
|
||||
var exts []ext
|
||||
m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
|
||||
if fd.IsExtension() {
|
||||
exts = append(exts, ext{fd, v})
|
||||
}
|
||||
return true
|
||||
})
|
||||
sort.Slice(exts, func(i, j int) bool {
|
||||
return exts[i].desc.Number() < exts[j].desc.Number()
|
||||
})
|
||||
|
||||
for _, ext := range exts {
|
||||
// For message set, use the name of the message as the extension name.
|
||||
name := string(ext.desc.FullName())
|
||||
if isMessageSet(ext.desc.ContainingMessage()) {
|
||||
name = strings.TrimSuffix(name, ".message_set_extension")
|
||||
}
|
||||
|
||||
if !ext.desc.IsList() {
|
||||
if err := w.writeSingularExtension(name, ext.val, ext.desc); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
lv := ext.val.List()
|
||||
for i := 0; i < lv.Len(); i++ {
|
||||
if err := w.writeSingularExtension(name, lv.Get(i), ext.desc); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *textWriter) writeSingularExtension(name string, v protoreflect.Value, fd protoreflect.FieldDescriptor) error {
|
||||
fmt.Fprintf(w, "[%s]:", name)
|
||||
if !w.compact {
|
||||
w.WriteByte(' ')
|
||||
}
|
||||
if err := w.writeSingularValue(v, fd); err != nil {
|
||||
return err
|
||||
}
|
||||
w.WriteByte('\n')
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *textWriter) writeIndent() {
|
||||
if !w.complete {
|
||||
return
|
||||
}
|
||||
for i := 0; i < w.indent*2; i++ {
|
||||
w.buf = append(w.buf, ' ')
|
||||
}
|
||||
w.complete = false
|
||||
}
|
78
vendor/github.com/golang/protobuf/proto/wire.go
generated
vendored
78
vendor/github.com/golang/protobuf/proto/wire.go
generated
vendored
@ -1,78 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
protoV2 "google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/runtime/protoiface"
|
||||
)
|
||||
|
||||
// Size returns the size in bytes of the wire-format encoding of m.
|
||||
func Size(m Message) int {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
mi := MessageV2(m)
|
||||
return protoV2.Size(mi)
|
||||
}
|
||||
|
||||
// Marshal returns the wire-format encoding of m.
|
||||
func Marshal(m Message) ([]byte, error) {
|
||||
b, err := marshalAppend(nil, m, false)
|
||||
if b == nil {
|
||||
b = zeroBytes
|
||||
}
|
||||
return b, err
|
||||
}
|
||||
|
||||
var zeroBytes = make([]byte, 0, 0)
|
||||
|
||||
func marshalAppend(buf []byte, m Message, deterministic bool) ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, ErrNil
|
||||
}
|
||||
mi := MessageV2(m)
|
||||
nbuf, err := protoV2.MarshalOptions{
|
||||
Deterministic: deterministic,
|
||||
AllowPartial: true,
|
||||
}.MarshalAppend(buf, mi)
|
||||
if err != nil {
|
||||
return buf, err
|
||||
}
|
||||
if len(buf) == len(nbuf) {
|
||||
if !mi.ProtoReflect().IsValid() {
|
||||
return buf, ErrNil
|
||||
}
|
||||
}
|
||||
return nbuf, checkRequiredNotSet(mi)
|
||||
}
|
||||
|
||||
// Unmarshal parses a wire-format message in b and places the decoded results in m.
|
||||
//
|
||||
// Unmarshal resets m before starting to unmarshal, so any existing data in m is always
|
||||
// removed. Use UnmarshalMerge to preserve and append to existing data.
|
||||
func Unmarshal(b []byte, m Message) error {
|
||||
m.Reset()
|
||||
return UnmarshalMerge(b, m)
|
||||
}
|
||||
|
||||
// UnmarshalMerge parses a wire-format message in b and places the decoded results in m.
|
||||
func UnmarshalMerge(b []byte, m Message) error {
|
||||
mi := MessageV2(m)
|
||||
out, err := protoV2.UnmarshalOptions{
|
||||
AllowPartial: true,
|
||||
Merge: true,
|
||||
}.UnmarshalState(protoiface.UnmarshalInput{
|
||||
Buf: b,
|
||||
Message: mi.ProtoReflect(),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if out.Flags&protoiface.UnmarshalInitialized > 0 {
|
||||
return nil
|
||||
}
|
||||
return checkRequiredNotSet(mi)
|
||||
}
|
34
vendor/github.com/golang/protobuf/proto/wrappers.go
generated
vendored
34
vendor/github.com/golang/protobuf/proto/wrappers.go
generated
vendored
@ -1,34 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
// Bool stores v in a new bool value and returns a pointer to it.
|
||||
func Bool(v bool) *bool { return &v }
|
||||
|
||||
// Int stores v in a new int32 value and returns a pointer to it.
|
||||
//
|
||||
// Deprecated: Use Int32 instead.
|
||||
func Int(v int) *int32 { return Int32(int32(v)) }
|
||||
|
||||
// Int32 stores v in a new int32 value and returns a pointer to it.
|
||||
func Int32(v int32) *int32 { return &v }
|
||||
|
||||
// Int64 stores v in a new int64 value and returns a pointer to it.
|
||||
func Int64(v int64) *int64 { return &v }
|
||||
|
||||
// Uint32 stores v in a new uint32 value and returns a pointer to it.
|
||||
func Uint32(v uint32) *uint32 { return &v }
|
||||
|
||||
// Uint64 stores v in a new uint64 value and returns a pointer to it.
|
||||
func Uint64(v uint64) *uint64 { return &v }
|
||||
|
||||
// Float32 stores v in a new float32 value and returns a pointer to it.
|
||||
func Float32(v float32) *float32 { return &v }
|
||||
|
||||
// Float64 stores v in a new float64 value and returns a pointer to it.
|
||||
func Float64(v float64) *float64 { return &v }
|
||||
|
||||
// String stores v in a new string value and returns a pointer to it.
|
||||
func String(v string) *string { return &v }
|
2
vendor/github.com/google/pprof/profile/profile.go
generated
vendored
2
vendor/github.com/google/pprof/profile/profile.go
generated
vendored
@ -847,7 +847,7 @@ func (p *Profile) HasFileLines() bool {
|
||||
// "[vdso]", [vsyscall]" and some others, see the code.
|
||||
func (m *Mapping) Unsymbolizable() bool {
|
||||
name := filepath.Base(m.File)
|
||||
return strings.HasPrefix(name, "[") || strings.HasPrefix(name, "linux-vdso") || strings.HasPrefix(m.File, "/dev/dri/")
|
||||
return strings.HasPrefix(name, "[") || strings.HasPrefix(name, "linux-vdso") || strings.HasPrefix(m.File, "/dev/dri/") || m.File == "//anon"
|
||||
}
|
||||
|
||||
// Copy makes a fully independent copy of a profile.
|
||||
|
25
vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md
generated
vendored
25
vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md
generated
vendored
@ -1,3 +1,28 @@
|
||||
## 2.20.1
|
||||
|
||||
### Fixes
|
||||
- make BeSpecEvent duration matcher more forgiving [d6f9640]
|
||||
|
||||
## 2.20.0
|
||||
|
||||
### Features
|
||||
- Add buildvcs flag [be5ab95]
|
||||
|
||||
### Maintenance
|
||||
- Add update-deps to makefile [d303d14]
|
||||
- bump all dependencies [7a50221]
|
||||
|
||||
## 2.19.1
|
||||
|
||||
### Fixes
|
||||
- update supported platforms for race conditions [63c8c30]
|
||||
- [build] Allow custom name for binaries. [ff41e27]
|
||||
|
||||
### Maintenance
|
||||
- bump gomega [76f4e0c]
|
||||
- Bump rexml from 3.2.6 to 3.2.8 in /docs (#1417) [b69c00d]
|
||||
- Bump golang.org/x/sys from 0.20.0 to 0.21.0 (#1425) [f097741]
|
||||
|
||||
## 2.19.0
|
||||
|
||||
### Features
|
||||
|
7
vendor/github.com/onsi/ginkgo/v2/Makefile
generated
vendored
7
vendor/github.com/onsi/ginkgo/v2/Makefile
generated
vendored
@ -4,8 +4,13 @@ all: vet test
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
go run github.com/onsi/ginkgo/v2/ginkgo -r -p
|
||||
go run github.com/onsi/ginkgo/v2/ginkgo -r -p -randomize-all -keep-going
|
||||
|
||||
.PHONY: vet
|
||||
vet:
|
||||
go vet ./...
|
||||
|
||||
.PHONY: update-deps
|
||||
update-deps:
|
||||
go get -u ./...
|
||||
go mod tidy
|
15
vendor/github.com/onsi/ginkgo/v2/ginkgo/build/build_command.go
generated
vendored
15
vendor/github.com/onsi/ginkgo/v2/ginkgo/build/build_command.go
generated
vendored
@ -2,6 +2,8 @@ package build
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/onsi/ginkgo/v2/ginkgo/command"
|
||||
"github.com/onsi/ginkgo/v2/ginkgo/internal"
|
||||
@ -53,7 +55,18 @@ func buildSpecs(args []string, cliConfig types.CLIConfig, goFlagsConfig types.Go
|
||||
if suite.State.Is(internal.TestSuiteStateFailedToCompile) {
|
||||
fmt.Println(suite.CompilationError.Error())
|
||||
} else {
|
||||
fmt.Printf("Compiled %s.test\n", suite.PackageName)
|
||||
if len(goFlagsConfig.O) == 0 {
|
||||
goFlagsConfig.O = path.Join(suite.Path, suite.PackageName+".test")
|
||||
} else {
|
||||
stat, err := os.Stat(goFlagsConfig.O)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if stat.IsDir() {
|
||||
goFlagsConfig.O += "/" + suite.PackageName + ".test"
|
||||
}
|
||||
}
|
||||
fmt.Printf("Compiled %s\n", goFlagsConfig.O)
|
||||
}
|
||||
}
|
||||
|
||||
|
14
vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/compile.go
generated
vendored
14
vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/compile.go
generated
vendored
@ -25,6 +25,18 @@ func CompileSuite(suite TestSuite, goFlagsConfig types.GoFlagsConfig) TestSuite
|
||||
return suite
|
||||
}
|
||||
|
||||
if len(goFlagsConfig.O) > 0 {
|
||||
userDefinedPath, err := filepath.Abs(goFlagsConfig.O)
|
||||
if err != nil {
|
||||
suite.State = TestSuiteStateFailedToCompile
|
||||
suite.CompilationError = fmt.Errorf("Failed to compute compilation target path %s:\n%s", goFlagsConfig.O, err.Error())
|
||||
return suite
|
||||
}
|
||||
path = userDefinedPath
|
||||
}
|
||||
|
||||
goFlagsConfig.O = path
|
||||
|
||||
ginkgoInvocationPath, _ := os.Getwd()
|
||||
ginkgoInvocationPath, _ = filepath.Abs(ginkgoInvocationPath)
|
||||
packagePath := suite.AbsPath()
|
||||
@ -34,7 +46,7 @@ func CompileSuite(suite TestSuite, goFlagsConfig types.GoFlagsConfig) TestSuite
|
||||
suite.CompilationError = fmt.Errorf("Failed to get relative path from package to the current working directory:\n%s", err.Error())
|
||||
return suite
|
||||
}
|
||||
args, err := types.GenerateGoTestCompileArgs(goFlagsConfig, path, "./", pathToInvocationPath)
|
||||
args, err := types.GenerateGoTestCompileArgs(goFlagsConfig, "./", pathToInvocationPath)
|
||||
if err != nil {
|
||||
suite.State = TestSuiteStateFailedToCompile
|
||||
suite.CompilationError = fmt.Errorf("Failed to generate go test compile flags:\n%s", err.Error())
|
||||
|
12
vendor/github.com/onsi/ginkgo/v2/types/config.go
generated
vendored
12
vendor/github.com/onsi/ginkgo/v2/types/config.go
generated
vendored
@ -202,6 +202,7 @@ type GoFlagsConfig struct {
|
||||
A bool
|
||||
ASMFlags string
|
||||
BuildMode string
|
||||
BuildVCS bool
|
||||
Compiler string
|
||||
GCCGoFlags string
|
||||
GCFlags string
|
||||
@ -219,6 +220,7 @@ type GoFlagsConfig struct {
|
||||
ToolExec string
|
||||
Work bool
|
||||
X bool
|
||||
O string
|
||||
}
|
||||
|
||||
func NewDefaultGoFlagsConfig() GoFlagsConfig {
|
||||
@ -511,7 +513,7 @@ var GinkgoCLIWatchFlags = GinkgoFlags{
|
||||
// GoBuildFlags provides flags for the Ginkgo CLI build, run, and watch commands that capture go's build-time flags. These are passed to go test -c by the ginkgo CLI
|
||||
var GoBuildFlags = GinkgoFlags{
|
||||
{KeyPath: "Go.Race", Name: "race", SectionKey: "code-and-coverage-analysis",
|
||||
Usage: "enable data race detection. Supported only on linux/amd64, freebsd/amd64, darwin/amd64, windows/amd64, linux/ppc64le and linux/arm64 (only for 48-bit VMA)."},
|
||||
Usage: "enable data race detection. Supported on linux/amd64, linux/ppc64le, linux/arm64, linux/s390x, freebsd/amd64, netbsd/amd64, darwin/amd64, darwin/arm64, and windows/amd64."},
|
||||
{KeyPath: "Go.Vet", Name: "vet", UsageArgument: "list", SectionKey: "code-and-coverage-analysis",
|
||||
Usage: `Configure the invocation of "go vet" during "go test" to use the comma-separated list of vet checks. If list is empty, "go test" runs "go vet" with a curated list of checks believed to be always worth addressing. If list is "off", "go test" does not run "go vet" at all. Available checks can be found by running 'go doc cmd/vet'`},
|
||||
{KeyPath: "Go.Cover", Name: "cover", SectionKey: "code-and-coverage-analysis",
|
||||
@ -527,6 +529,8 @@ var GoBuildFlags = GinkgoFlags{
|
||||
Usage: "arguments to pass on each go tool asm invocation."},
|
||||
{KeyPath: "Go.BuildMode", Name: "buildmode", UsageArgument: "mode", SectionKey: "go-build",
|
||||
Usage: "build mode to use. See 'go help buildmode' for more."},
|
||||
{KeyPath: "Go.BuildVCS", Name: "buildvcs", SectionKey: "go-build",
|
||||
Usage: "adds version control information."},
|
||||
{KeyPath: "Go.Compiler", Name: "compiler", UsageArgument: "name", SectionKey: "go-build",
|
||||
Usage: "name of compiler to use, as in runtime.Compiler (gccgo or gc)."},
|
||||
{KeyPath: "Go.GCCGoFlags", Name: "gccgoflags", UsageArgument: "'[pattern=]arg list'", SectionKey: "go-build",
|
||||
@ -561,6 +565,8 @@ var GoBuildFlags = GinkgoFlags{
|
||||
Usage: "print the name of the temporary work directory and do not delete it when exiting."},
|
||||
{KeyPath: "Go.X", Name: "x", SectionKey: "go-build",
|
||||
Usage: "print the commands."},
|
||||
{KeyPath: "Go.O", Name: "o", SectionKey: "go-build",
|
||||
Usage: "output binary path (including name)."},
|
||||
}
|
||||
|
||||
// GoRunFlags provides flags for the Ginkgo CLI run, and watch commands that capture go's run-time flags. These are passed to the compiled test binary by the ginkgo CLI
|
||||
@ -614,7 +620,7 @@ func VetAndInitializeCLIAndGoConfig(cliConfig CLIConfig, goFlagsConfig GoFlagsCo
|
||||
}
|
||||
|
||||
// GenerateGoTestCompileArgs is used by the Ginkgo CLI to generate command line arguments to pass to the go test -c command when compiling the test
|
||||
func GenerateGoTestCompileArgs(goFlagsConfig GoFlagsConfig, destination string, packageToBuild string, pathToInvocationPath string) ([]string, error) {
|
||||
func GenerateGoTestCompileArgs(goFlagsConfig GoFlagsConfig, packageToBuild string, pathToInvocationPath string) ([]string, error) {
|
||||
// if the user has set the CoverProfile run-time flag make sure to set the build-time cover flag to make sure
|
||||
// the built test binary can generate a coverprofile
|
||||
if goFlagsConfig.CoverProfile != "" {
|
||||
@ -637,7 +643,7 @@ func GenerateGoTestCompileArgs(goFlagsConfig GoFlagsConfig, destination string,
|
||||
goFlagsConfig.CoverPkg = strings.Join(adjustedCoverPkgs, ",")
|
||||
}
|
||||
|
||||
args := []string{"test", "-c", "-o", destination, packageToBuild}
|
||||
args := []string{"test", "-c", packageToBuild}
|
||||
goArgs, err := GenerateFlagArgs(
|
||||
GoBuildFlags,
|
||||
map[string]interface{}{
|
||||
|
2
vendor/github.com/onsi/ginkgo/v2/types/version.go
generated
vendored
2
vendor/github.com/onsi/ginkgo/v2/types/version.go
generated
vendored
@ -1,3 +1,3 @@
|
||||
package types
|
||||
|
||||
const VERSION = "2.19.0"
|
||||
const VERSION = "2.20.1"
|
||||
|
22
vendor/github.com/onsi/gomega/CHANGELOG.md
generated
vendored
22
vendor/github.com/onsi/gomega/CHANGELOG.md
generated
vendored
@ -1,3 +1,25 @@
|
||||
## 1.34.1
|
||||
|
||||
### Maintenance
|
||||
- Use slices from exp/slices to keep golang 1.20 compat [5e71dcd]
|
||||
|
||||
## 1.34.0
|
||||
|
||||
### Features
|
||||
- Add RoundTripper method to ghttp.Server [c549e0d]
|
||||
|
||||
### Fixes
|
||||
- fix incorrect handling of nil slices in HaveExactElements (fixes #771) [878940c]
|
||||
- issue_765 - fixed bug in Hopcroft-Karp algorithm [ebadb67]
|
||||
|
||||
### Maintenance
|
||||
- bump ginkgo [8af2ece]
|
||||
- Fix typo in docs [123a071]
|
||||
- Bump github.com/onsi/ginkgo/v2 from 2.17.2 to 2.17.3 (#756) [0e69083]
|
||||
- Bump google.golang.org/protobuf from 1.33.0 to 1.34.1 (#755) [2675796]
|
||||
- Bump golang.org/x/net from 0.24.0 to 0.25.0 (#754) [4160c0f]
|
||||
- Bump github-pages from 230 to 231 in /docs (#748) [892c303]
|
||||
|
||||
## 1.33.1
|
||||
|
||||
### Fixes
|
||||
|
2
vendor/github.com/onsi/gomega/gomega_dsl.go
generated
vendored
2
vendor/github.com/onsi/gomega/gomega_dsl.go
generated
vendored
@ -22,7 +22,7 @@ import (
|
||||
"github.com/onsi/gomega/types"
|
||||
)
|
||||
|
||||
const GOMEGA_VERSION = "1.33.1"
|
||||
const GOMEGA_VERSION = "1.34.1"
|
||||
|
||||
const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler.
|
||||
If you're using Ginkgo then you probably forgot to put your assertion in an It().
|
||||
|
7
vendor/github.com/onsi/gomega/matchers/have_exact_elements.go
generated
vendored
7
vendor/github.com/onsi/gomega/matchers/have_exact_elements.go
generated
vendored
@ -30,15 +30,18 @@ func (matcher *HaveExactElementsMatcher) Match(actual interface{}) (success bool
|
||||
|
||||
lenMatchers := len(matchers)
|
||||
lenValues := len(values)
|
||||
success = true
|
||||
|
||||
for i := 0; i < lenMatchers || i < lenValues; i++ {
|
||||
if i >= lenMatchers {
|
||||
matcher.extraIndex = i
|
||||
success = false
|
||||
continue
|
||||
}
|
||||
|
||||
if i >= lenValues {
|
||||
matcher.missingIndex = i
|
||||
success = false
|
||||
return
|
||||
}
|
||||
|
||||
@ -49,15 +52,17 @@ func (matcher *HaveExactElementsMatcher) Match(actual interface{}) (success bool
|
||||
index: i,
|
||||
failure: err.Error(),
|
||||
})
|
||||
success = false
|
||||
} else if !match {
|
||||
matcher.mismatchFailures = append(matcher.mismatchFailures, mismatchFailure{
|
||||
index: i,
|
||||
failure: elemMatcher.FailureMessage(values[i]),
|
||||
})
|
||||
success = false
|
||||
}
|
||||
}
|
||||
|
||||
return matcher.missingIndex+matcher.extraIndex+len(matcher.mismatchFailures) == 0, nil
|
||||
return success, nil
|
||||
}
|
||||
|
||||
func (matcher *HaveExactElementsMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
|
@ -1,6 +1,8 @@
|
||||
package bipartitegraph
|
||||
|
||||
import (
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
. "github.com/onsi/gomega/matchers/support/goraph/edge"
|
||||
. "github.com/onsi/gomega/matchers/support/goraph/node"
|
||||
"github.com/onsi/gomega/matchers/support/goraph/util"
|
||||
@ -157,6 +159,11 @@ func (bg *BipartiteGraph) createSLAPGuideLayers(matching EdgeSet) (guideLayers [
|
||||
if len(currentLayer) == 0 {
|
||||
return []NodeOrderedSet{}
|
||||
}
|
||||
if done { // if last layer - into last layer must be only 'free' nodes
|
||||
currentLayer = slices.DeleteFunc(currentLayer, func(in Node) bool {
|
||||
return !matching.Free(in)
|
||||
})
|
||||
}
|
||||
guideLayers = append(guideLayers, currentLayer)
|
||||
}
|
||||
|
||||
|
1
vendor/github.com/vishvananda/netlink/.gitignore
generated
vendored
1
vendor/github.com/vishvananda/netlink/.gitignore
generated
vendored
@ -1 +1,2 @@
|
||||
.idea/
|
||||
.vscode/
|
||||
|
52
vendor/github.com/vishvananda/netlink/addr_linux.go
generated
vendored
52
vendor/github.com/vishvananda/netlink/addr_linux.go
generated
vendored
@ -74,17 +74,19 @@ func (h *Handle) AddrDel(link Link, addr *Addr) error {
|
||||
}
|
||||
|
||||
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)
|
||||
if link == nil {
|
||||
msg.Index = uint32(addr.LinkIndex)
|
||||
} else {
|
||||
base := link.Attrs()
|
||||
if addr.Label != "" && !strings.HasPrefix(addr.Label, base.Name) {
|
||||
return fmt.Errorf("label must begin with interface name")
|
||||
}
|
||||
h.ensureIndex(base)
|
||||
msg.Index = uint32(base.Index)
|
||||
}
|
||||
mask := addr.Mask
|
||||
if addr.Peer != nil {
|
||||
mask = addr.Peer.Mask
|
||||
@ -296,23 +298,24 @@ type AddrUpdate struct {
|
||||
// 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, nil)
|
||||
return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0, nil, false)
|
||||
}
|
||||
|
||||
// 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, nil)
|
||||
return addrSubscribeAt(ns, netns.None(), ch, done, nil, false, 0, nil, false)
|
||||
}
|
||||
|
||||
// AddrSubscribeOptions contains a set of options to use with
|
||||
// AddrSubscribeWithOptions.
|
||||
type AddrSubscribeOptions struct {
|
||||
Namespace *netns.NsHandle
|
||||
ErrorCallback func(error)
|
||||
ListExisting bool
|
||||
ReceiveBufferSize int
|
||||
ReceiveTimeout *unix.Timeval
|
||||
Namespace *netns.NsHandle
|
||||
ErrorCallback func(error)
|
||||
ListExisting bool
|
||||
ReceiveBufferSize int
|
||||
ReceiveBufferForceSize bool
|
||||
ReceiveTimeout *unix.Timeval
|
||||
}
|
||||
|
||||
// AddrSubscribeWithOptions work like AddrSubscribe but enable to
|
||||
@ -323,10 +326,12 @@ func AddrSubscribeWithOptions(ch chan<- AddrUpdate, done <-chan struct{}, option
|
||||
none := netns.None()
|
||||
options.Namespace = &none
|
||||
}
|
||||
return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting, options.ReceiveBufferSize, options.ReceiveTimeout)
|
||||
return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting,
|
||||
options.ReceiveBufferSize, options.ReceiveTimeout, options.ReceiveBufferForceSize)
|
||||
}
|
||||
|
||||
func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool, rcvbuf int, rcvTimeout *unix.Timeval) error {
|
||||
func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool,
|
||||
rcvbuf int, rcvTimeout *unix.Timeval, rcvBufForce bool) error {
|
||||
s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_IFADDR, unix.RTNLGRP_IPV6_IFADDR)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -336,19 +341,18 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if rcvbuf != 0 {
|
||||
err = s.SetReceiveBufferSize(rcvbuf, rcvBufForce)
|
||||
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)
|
||||
|
45
vendor/github.com/vishvananda/netlink/bridge_linux.go
generated
vendored
45
vendor/github.com/vishvananda/netlink/bridge_linux.go
generated
vendored
@ -63,7 +63,19 @@ func BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) err
|
||||
// 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)
|
||||
return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, 0, pvid, untagged, self, master)
|
||||
}
|
||||
|
||||
// BridgeVlanAddRange adds a new vlan filter entry
|
||||
// Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
|
||||
func BridgeVlanAddRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
|
||||
return pkgHandle.BridgeVlanAddRange(link, vid, vidEnd, pvid, untagged, self, master)
|
||||
}
|
||||
|
||||
// BridgeVlanAddRange adds a new vlan filter entry
|
||||
// Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
|
||||
func (h *Handle) BridgeVlanAddRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
|
||||
return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, vidEnd, pvid, untagged, self, master)
|
||||
}
|
||||
|
||||
// BridgeVlanDel adds a new vlan filter entry
|
||||
@ -75,10 +87,22 @@ func BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) err
|
||||
// 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)
|
||||
return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, 0, pvid, untagged, self, master)
|
||||
}
|
||||
|
||||
func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged, self, master bool) error {
|
||||
// BridgeVlanDelRange adds a new vlan filter entry
|
||||
// Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
|
||||
func BridgeVlanDelRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
|
||||
return pkgHandle.BridgeVlanDelRange(link, vid, vidEnd, pvid, untagged, self, master)
|
||||
}
|
||||
|
||||
// BridgeVlanDelRange adds a new vlan filter entry
|
||||
// Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
|
||||
func (h *Handle) BridgeVlanDelRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
|
||||
return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, vidEnd, pvid, untagged, self, master)
|
||||
}
|
||||
|
||||
func (h *Handle) bridgeVlanModify(cmd int, link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
|
||||
base := link.Attrs()
|
||||
h.ensureIndex(base)
|
||||
req := h.newNetlinkRequest(cmd, unix.NLM_F_ACK)
|
||||
@ -105,7 +129,20 @@ func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged
|
||||
if untagged {
|
||||
vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_UNTAGGED
|
||||
}
|
||||
br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
|
||||
|
||||
if vidEnd != 0 {
|
||||
vlanEndInfo := &nl.BridgeVlanInfo{Vid: vidEnd}
|
||||
vlanEndInfo.Flags = vlanInfo.Flags
|
||||
|
||||
vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_RANGE_BEGIN
|
||||
br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
|
||||
|
||||
vlanEndInfo.Flags |= nl.BRIDGE_VLAN_INFO_RANGE_END
|
||||
br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanEndInfo.Serialize())
|
||||
} else {
|
||||
br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
|
||||
}
|
||||
|
||||
req.AddData(br)
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
|
22
vendor/github.com/vishvananda/netlink/chain.go
generated
vendored
Normal file
22
vendor/github.com/vishvananda/netlink/chain.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Chain contains the attributes of a Chain
|
||||
type Chain struct {
|
||||
Parent uint32
|
||||
Chain uint32
|
||||
}
|
||||
|
||||
func (c Chain) String() string {
|
||||
return fmt.Sprintf("{Parent: %d, Chain: %d}", c.Parent, c.Chain)
|
||||
}
|
||||
|
||||
func NewChain(parent uint32, chain uint32) Chain {
|
||||
return Chain{
|
||||
Parent: parent,
|
||||
Chain: chain,
|
||||
}
|
||||
}
|
112
vendor/github.com/vishvananda/netlink/chain_linux.go
generated
vendored
Normal file
112
vendor/github.com/vishvananda/netlink/chain_linux.go
generated
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// ChainDel will delete a chain from the system.
|
||||
func ChainDel(link Link, chain Chain) error {
|
||||
// Equivalent to: `tc chain del $chain`
|
||||
return pkgHandle.ChainDel(link, chain)
|
||||
}
|
||||
|
||||
// ChainDel will delete a chain from the system.
|
||||
// Equivalent to: `tc chain del $chain`
|
||||
func (h *Handle) ChainDel(link Link, chain Chain) error {
|
||||
return h.chainModify(unix.RTM_DELCHAIN, 0, link, chain)
|
||||
}
|
||||
|
||||
// ChainAdd will add a chain to the system.
|
||||
// Equivalent to: `tc chain add`
|
||||
func ChainAdd(link Link, chain Chain) error {
|
||||
return pkgHandle.ChainAdd(link, chain)
|
||||
}
|
||||
|
||||
// ChainAdd will add a chain to the system.
|
||||
// Equivalent to: `tc chain add`
|
||||
func (h *Handle) ChainAdd(link Link, chain Chain) error {
|
||||
return h.chainModify(
|
||||
unix.RTM_NEWCHAIN,
|
||||
unix.NLM_F_CREATE|unix.NLM_F_EXCL,
|
||||
link,
|
||||
chain)
|
||||
}
|
||||
|
||||
func (h *Handle) chainModify(cmd, flags int, link Link, chain Chain) error {
|
||||
req := h.newNetlinkRequest(cmd, flags|unix.NLM_F_ACK)
|
||||
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,
|
||||
Parent: chain.Parent,
|
||||
}
|
||||
req.AddData(msg)
|
||||
req.AddData(nl.NewRtAttr(nl.TCA_CHAIN, nl.Uint32Attr(chain.Chain)))
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// ChainList gets a list of chains in the system.
|
||||
// Equivalent to: `tc chain list`.
|
||||
// The list can be filtered by link.
|
||||
func ChainList(link Link, parent uint32) ([]Chain, error) {
|
||||
return pkgHandle.ChainList(link, parent)
|
||||
}
|
||||
|
||||
// ChainList gets a list of chains in the system.
|
||||
// Equivalent to: `tc chain list`.
|
||||
// The list can be filtered by link.
|
||||
func (h *Handle) ChainList(link Link, parent uint32) ([]Chain, error) {
|
||||
req := h.newNetlinkRequest(unix.RTM_GETCHAIN, 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,
|
||||
Parent: parent,
|
||||
}
|
||||
req.AddData(msg)
|
||||
|
||||
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWCHAIN)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var res []Chain
|
||||
for _, m := range msgs {
|
||||
msg := nl.DeserializeTcMsg(m)
|
||||
|
||||
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// skip chains from other interfaces
|
||||
if link != nil && msg.Ifindex != index {
|
||||
continue
|
||||
}
|
||||
|
||||
var chain Chain
|
||||
for _, attr := range attrs {
|
||||
switch attr.Attr.Type {
|
||||
case nl.TCA_CHAIN:
|
||||
chain.Chain = native.Uint32(attr.Value)
|
||||
chain.Parent = parent
|
||||
}
|
||||
}
|
||||
res = append(res, chain)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
2
vendor/github.com/vishvananda/netlink/class.go
generated
vendored
2
vendor/github.com/vishvananda/netlink/class.go
generated
vendored
@ -47,6 +47,7 @@ type ClassStatistics struct {
|
||||
Basic *GnetStatsBasic
|
||||
Queue *GnetStatsQueue
|
||||
RateEst *GnetStatsRateEst
|
||||
BasicHw *GnetStatsBasic // Hardward statistics added in kernel 4.20
|
||||
}
|
||||
|
||||
// NewClassStatistics Construct a ClassStatistics struct which fields are all initialized by 0.
|
||||
@ -55,6 +56,7 @@ func NewClassStatistics() *ClassStatistics {
|
||||
Basic: &GnetStatsBasic{},
|
||||
Queue: &GnetStatsQueue{},
|
||||
RateEst: &GnetStatsRateEst{},
|
||||
BasicHw: &GnetStatsBasic{},
|
||||
}
|
||||
}
|
||||
|
||||
|
5
vendor/github.com/vishvananda/netlink/class_linux.go
generated
vendored
5
vendor/github.com/vishvananda/netlink/class_linux.go
generated
vendored
@ -388,6 +388,11 @@ func parseTcStats2(data []byte) (*ClassStatistics, error) {
|
||||
return nil, fmt.Errorf("Failed to parse ClassStatistics.RateEst with: %v\n%s",
|
||||
err, hex.Dump(datum.Value))
|
||||
}
|
||||
case nl.TCA_STATS_BASIC_HW:
|
||||
if err := parseGnetStats(datum.Value, stats.BasicHw); err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse ClassStatistics.BasicHw with: %v\n%s",
|
||||
err, hex.Dump(datum.Value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
423
vendor/github.com/vishvananda/netlink/conntrack_linux.go
generated
vendored
423
vendor/github.com/vishvananda/netlink/conntrack_linux.go
generated
vendored
@ -55,10 +55,30 @@ func ConntrackTableFlush(table ConntrackTableType) error {
|
||||
return pkgHandle.ConntrackTableFlush(table)
|
||||
}
|
||||
|
||||
// ConntrackCreate creates a new conntrack flow in the desired table
|
||||
// conntrack -I [table] Create a conntrack or expectation
|
||||
func ConntrackCreate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error {
|
||||
return pkgHandle.ConntrackCreate(table, family, flow)
|
||||
}
|
||||
|
||||
// ConntrackUpdate updates an existing conntrack flow in the desired table using the handle
|
||||
// conntrack -U [table] Update a conntrack
|
||||
func ConntrackUpdate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error {
|
||||
return pkgHandle.ConntrackUpdate(table, family, flow)
|
||||
}
|
||||
|
||||
// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter
|
||||
// conntrack -D [table] parameters Delete conntrack or expectation
|
||||
//
|
||||
// Deprecated: use [ConntrackDeleteFilter] instead.
|
||||
func ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter CustomConntrackFilter) (uint, error) {
|
||||
return pkgHandle.ConntrackDeleteFilter(table, family, filter)
|
||||
return pkgHandle.ConntrackDeleteFilters(table, family, filter)
|
||||
}
|
||||
|
||||
// ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters
|
||||
// conntrack -D [table] parameters Delete conntrack or expectation
|
||||
func ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (uint, error) {
|
||||
return pkgHandle.ConntrackDeleteFilters(table, family, filters...)
|
||||
}
|
||||
|
||||
// ConntrackTableList returns the flow list of a table of a specific family using the netlink handle passed
|
||||
@ -87,9 +107,51 @@ func (h *Handle) ConntrackTableFlush(table ConntrackTableType) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// ConntrackCreate creates a new conntrack flow in the desired table using the handle
|
||||
// conntrack -I [table] Create a conntrack or expectation
|
||||
func (h *Handle) ConntrackCreate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error {
|
||||
req := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_NEW, unix.NLM_F_ACK|unix.NLM_F_CREATE)
|
||||
attr, err := flow.toNlData()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, a := range attr {
|
||||
req.AddData(a)
|
||||
}
|
||||
|
||||
_, err = req.Execute(unix.NETLINK_NETFILTER, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// ConntrackUpdate updates an existing conntrack flow in the desired table using the handle
|
||||
// conntrack -U [table] Update a conntrack
|
||||
func (h *Handle) ConntrackUpdate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error {
|
||||
req := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_NEW, unix.NLM_F_ACK|unix.NLM_F_REPLACE)
|
||||
attr, err := flow.toNlData()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, a := range attr {
|
||||
req.AddData(a)
|
||||
}
|
||||
|
||||
_, 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
|
||||
//
|
||||
// Deprecated: use [Handle.ConntrackDeleteFilters] instead.
|
||||
func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter CustomConntrackFilter) (uint, error) {
|
||||
return h.ConntrackDeleteFilters(table, family, filter)
|
||||
}
|
||||
|
||||
// ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters using the netlink handle passed
|
||||
// conntrack -D [table] parameters Delete conntrack or expectation
|
||||
func (h *Handle) ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (uint, error) {
|
||||
res, err := h.dumpConntrackTable(table, family)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@ -98,12 +160,16 @@ func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFami
|
||||
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++
|
||||
for _, filter := range filters {
|
||||
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++
|
||||
// flow is already deleted, no need to match on other filters and continue to the next flow.
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,10 +194,44 @@ func (h *Handle) dumpConntrackTable(table ConntrackTableType, family InetFamily)
|
||||
return req.Execute(unix.NETLINK_NETFILTER, 0)
|
||||
}
|
||||
|
||||
// ProtoInfo wraps an L4-protocol structure - roughly corresponds to the
|
||||
// __nfct_protoinfo union found in libnetfilter_conntrack/include/internal/object.h.
|
||||
// Currently, only protocol names, and TCP state is supported.
|
||||
type ProtoInfo interface {
|
||||
Protocol() string
|
||||
}
|
||||
|
||||
// ProtoInfoTCP corresponds to the `tcp` struct of the __nfct_protoinfo union.
|
||||
// Only TCP state is currently supported.
|
||||
type ProtoInfoTCP struct {
|
||||
State uint8
|
||||
}
|
||||
// Protocol returns "tcp".
|
||||
func (*ProtoInfoTCP) Protocol() string {return "tcp"}
|
||||
func (p *ProtoInfoTCP) toNlData() ([]*nl.RtAttr, error) {
|
||||
ctProtoInfo := nl.NewRtAttr(unix.NLA_F_NESTED | nl.CTA_PROTOINFO, []byte{})
|
||||
ctProtoInfoTCP := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_PROTOINFO_TCP, []byte{})
|
||||
ctProtoInfoTCPState := nl.NewRtAttr(nl.CTA_PROTOINFO_TCP_STATE, nl.Uint8Attr(p.State))
|
||||
ctProtoInfoTCP.AddChild(ctProtoInfoTCPState)
|
||||
ctProtoInfo.AddChild(ctProtoInfoTCP)
|
||||
|
||||
return []*nl.RtAttr{ctProtoInfo}, nil
|
||||
}
|
||||
|
||||
// ProtoInfoSCTP only supports the protocol name.
|
||||
type ProtoInfoSCTP struct {}
|
||||
// Protocol returns "sctp".
|
||||
func (*ProtoInfoSCTP) Protocol() string {return "sctp"}
|
||||
|
||||
// ProtoInfoDCCP only supports the protocol name.
|
||||
type ProtoInfoDCCP struct {}
|
||||
// Protocol returns "dccp".
|
||||
func (*ProtoInfoDCCP) Protocol() string {return "dccp"}
|
||||
|
||||
// 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 {
|
||||
type IPTuple struct {
|
||||
Bytes uint64
|
||||
DstIP net.IP
|
||||
DstPort uint16
|
||||
@ -141,28 +241,150 @@ type ipTuple struct {
|
||||
SrcPort uint16
|
||||
}
|
||||
|
||||
// toNlData generates the inner fields of a nested tuple netlink datastructure
|
||||
// does not generate the "nested"-flagged outer message.
|
||||
func (t *IPTuple) toNlData(family uint8) ([]*nl.RtAttr, error) {
|
||||
|
||||
var srcIPsFlag, dstIPsFlag int
|
||||
if family == nl.FAMILY_V4 {
|
||||
srcIPsFlag = nl.CTA_IP_V4_SRC
|
||||
dstIPsFlag = nl.CTA_IP_V4_DST
|
||||
} else if family == nl.FAMILY_V6 {
|
||||
srcIPsFlag = nl.CTA_IP_V6_SRC
|
||||
dstIPsFlag = nl.CTA_IP_V6_DST
|
||||
} else {
|
||||
return []*nl.RtAttr{}, fmt.Errorf("couldn't generate netlink message for tuple due to unrecognized FamilyType '%d'", family)
|
||||
}
|
||||
|
||||
ctTupleIP := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_IP, nil)
|
||||
ctTupleIPSrc := nl.NewRtAttr(srcIPsFlag, t.SrcIP)
|
||||
ctTupleIP.AddChild(ctTupleIPSrc)
|
||||
ctTupleIPDst := nl.NewRtAttr(dstIPsFlag, t.DstIP)
|
||||
ctTupleIP.AddChild(ctTupleIPDst)
|
||||
|
||||
ctTupleProto := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_PROTO, nil)
|
||||
ctTupleProtoNum := nl.NewRtAttr(nl.CTA_PROTO_NUM, []byte{t.Protocol})
|
||||
ctTupleProto.AddChild(ctTupleProtoNum)
|
||||
ctTupleProtoSrcPort := nl.NewRtAttr(nl.CTA_PROTO_SRC_PORT, nl.BEUint16Attr(t.SrcPort))
|
||||
ctTupleProto.AddChild(ctTupleProtoSrcPort)
|
||||
ctTupleProtoDstPort := nl.NewRtAttr(nl.CTA_PROTO_DST_PORT, nl.BEUint16Attr(t.DstPort))
|
||||
ctTupleProto.AddChild(ctTupleProtoDstPort, )
|
||||
|
||||
return []*nl.RtAttr{ctTupleIP, ctTupleProto}, nil
|
||||
}
|
||||
|
||||
type ConntrackFlow struct {
|
||||
FamilyType uint8
|
||||
Forward ipTuple
|
||||
Reverse ipTuple
|
||||
Forward IPTuple
|
||||
Reverse IPTuple
|
||||
Mark uint32
|
||||
Zone uint16
|
||||
TimeStart uint64
|
||||
TimeStop uint64
|
||||
TimeOut uint32
|
||||
Labels []byte
|
||||
ProtoInfo ProtoInfo
|
||||
}
|
||||
|
||||
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
|
||||
// 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 labels=0x00000000050012ac4202010000000000 zone=100
|
||||
// start=2019-07-26 01:26:21.557800506 +0000 UTC stop=1970-01-01 00:00:00 +0000 UTC timeout=30(sec)
|
||||
start := time.Unix(0, int64(s.TimeStart))
|
||||
stop := time.Unix(0, int64(s.TimeStop))
|
||||
timeout := int32(s.TimeOut)
|
||||
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=0x%x start=%v stop=%v timeout=%d(sec)",
|
||||
res := 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=0x%x ",
|
||||
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, start, stop, timeout)
|
||||
s.Mark)
|
||||
if len(s.Labels) > 0 {
|
||||
res += fmt.Sprintf("labels=0x%x ", s.Labels)
|
||||
}
|
||||
if s.Zone != 0 {
|
||||
res += fmt.Sprintf("zone=%d ", s.Zone)
|
||||
}
|
||||
res += fmt.Sprintf("start=%v stop=%v timeout=%d(sec)", start, stop, timeout)
|
||||
return res
|
||||
}
|
||||
|
||||
// toNlData generates netlink messages representing the flow.
|
||||
func (s *ConntrackFlow) toNlData() ([]*nl.RtAttr, error) {
|
||||
var payload []*nl.RtAttr
|
||||
// The message structure is built as follows:
|
||||
// <len, NLA_F_NESTED|CTA_TUPLE_ORIG>
|
||||
// <len, NLA_F_NESTED|CTA_TUPLE_IP>
|
||||
// <len, [CTA_IP_V4_SRC|CTA_IP_V6_SRC]>
|
||||
// <IP>
|
||||
// <len, [CTA_IP_V4_DST|CTA_IP_V6_DST]>
|
||||
// <IP>
|
||||
// <len, NLA_F_NESTED|nl.CTA_TUPLE_PROTO>
|
||||
// <len, CTA_PROTO_NUM>
|
||||
// <uint8>
|
||||
// <len, CTA_PROTO_SRC_PORT>
|
||||
// <BEuint16>
|
||||
// <len, CTA_PROTO_DST_PORT>
|
||||
// <BEuint16>
|
||||
// <len, NLA_F_NESTED|CTA_TUPLE_REPLY>
|
||||
// <len, NLA_F_NESTED|CTA_TUPLE_IP>
|
||||
// <len, [CTA_IP_V4_SRC|CTA_IP_V6_SRC]>
|
||||
// <IP>
|
||||
// <len, [CTA_IP_V4_DST|CTA_IP_V6_DST]>
|
||||
// <IP>
|
||||
// <len, NLA_F_NESTED|nl.CTA_TUPLE_PROTO>
|
||||
// <len, CTA_PROTO_NUM>
|
||||
// <uint8>
|
||||
// <len, CTA_PROTO_SRC_PORT>
|
||||
// <BEuint16>
|
||||
// <len, CTA_PROTO_DST_PORT>
|
||||
// <BEuint16>
|
||||
// <len, CTA_STATUS>
|
||||
// <uint64>
|
||||
// <len, CTA_MARK>
|
||||
// <BEuint64>
|
||||
// <len, CTA_TIMEOUT>
|
||||
// <BEuint64>
|
||||
// <len, NLA_F_NESTED|CTA_PROTOINFO>
|
||||
|
||||
// CTA_TUPLE_ORIG
|
||||
ctTupleOrig := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_ORIG, nil)
|
||||
forwardFlowAttrs, err := s.Forward.toNlData(s.FamilyType)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't generate netlink data for conntrack forward flow: %w", err)
|
||||
}
|
||||
for _, a := range forwardFlowAttrs {
|
||||
ctTupleOrig.AddChild(a)
|
||||
}
|
||||
|
||||
// CTA_TUPLE_REPLY
|
||||
ctTupleReply := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_REPLY, nil)
|
||||
reverseFlowAttrs, err := s.Reverse.toNlData(s.FamilyType)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't generate netlink data for conntrack reverse flow: %w", err)
|
||||
}
|
||||
for _, a := range reverseFlowAttrs {
|
||||
ctTupleReply.AddChild(a)
|
||||
}
|
||||
|
||||
ctMark := nl.NewRtAttr(nl.CTA_MARK, nl.BEUint32Attr(s.Mark))
|
||||
ctTimeout := nl.NewRtAttr(nl.CTA_TIMEOUT, nl.BEUint32Attr(s.TimeOut))
|
||||
|
||||
payload = append(payload, ctTupleOrig, ctTupleReply, ctMark, ctTimeout)
|
||||
|
||||
if s.ProtoInfo != nil {
|
||||
switch p := s.ProtoInfo.(type) {
|
||||
case *ProtoInfoTCP:
|
||||
attrs, err := p.toNlData()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't generate netlink data for conntrack flow's TCP protoinfo: %w", err)
|
||||
}
|
||||
payload = append(payload, attrs...)
|
||||
default:
|
||||
return nil, errors.New("couldn't generate netlink data for conntrack: field 'ProtoInfo' only supports TCP or nil")
|
||||
}
|
||||
}
|
||||
|
||||
return payload, nil
|
||||
}
|
||||
|
||||
// This method parse the ip tuple structure
|
||||
@ -172,7 +394,7 @@ func (s *ConntrackFlow) String() string {
|
||||
// <len, NLA_F_NESTED|nl.CTA_TUPLE_PROTO, 1 byte for the protocol, 3 bytes of padding>
|
||||
// <len, CTA_PROTO_SRC_PORT, 2 bytes for the source port, 2 bytes of padding>
|
||||
// <len, CTA_PROTO_DST_PORT, 2 bytes for the source port, 2 bytes of padding>
|
||||
func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) uint8 {
|
||||
func parseIpTuple(reader *bytes.Reader, tpl *IPTuple) uint8 {
|
||||
for i := 0; i < 2; i++ {
|
||||
_, t, _, v := parseNfAttrTLV(reader)
|
||||
switch t {
|
||||
@ -191,7 +413,7 @@ func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) uint8 {
|
||||
tpl.Protocol = uint8(v[0])
|
||||
}
|
||||
// We only parse TCP & UDP headers. Skip the others.
|
||||
if tpl.Protocol != 6 && tpl.Protocol != 17 {
|
||||
if tpl.Protocol != unix.IPPROTO_TCP && tpl.Protocol != unix.IPPROTO_UDP {
|
||||
// skip the rest
|
||||
bytesRemaining := protoInfoTotalLen - protoInfoBytesRead
|
||||
reader.Seek(int64(bytesRemaining), seekCurrent)
|
||||
@ -240,9 +462,13 @@ func parseNfAttrTL(r *bytes.Reader) (isNested bool, attrType, len uint16) {
|
||||
return isNested, attrType, len
|
||||
}
|
||||
|
||||
func skipNfAttrValue(r *bytes.Reader, len uint16) {
|
||||
// skipNfAttrValue seeks `r` past attr of length `len`.
|
||||
// Maintains buffer alignment.
|
||||
// Returns length of the seek performed.
|
||||
func skipNfAttrValue(r *bytes.Reader, len uint16) uint16 {
|
||||
len = (len + nl.NLA_ALIGNTO - 1) & ^(nl.NLA_ALIGNTO - 1)
|
||||
r.Seek(int64(len), seekCurrent)
|
||||
return len
|
||||
}
|
||||
|
||||
func parseBERaw16(r *bytes.Reader, v *uint16) {
|
||||
@ -257,6 +483,10 @@ func parseBERaw64(r *bytes.Reader, v *uint64) {
|
||||
binary.Read(r, binary.BigEndian, v)
|
||||
}
|
||||
|
||||
func parseRaw32(r *bytes.Reader, v *uint32) {
|
||||
binary.Read(r, nl.NativeEndian(), v)
|
||||
}
|
||||
|
||||
func parseByteAndPacketCounters(r *bytes.Reader) (bytes, packets uint64) {
|
||||
for i := 0; i < 2; i++ {
|
||||
switch _, t, _ := parseNfAttrTL(r); t {
|
||||
@ -296,6 +526,60 @@ func parseTimeStamp(r *bytes.Reader, readSize uint16) (tstart, tstop uint64) {
|
||||
|
||||
}
|
||||
|
||||
func parseProtoInfoTCPState(r *bytes.Reader) (s uint8) {
|
||||
binary.Read(r, binary.BigEndian, &s)
|
||||
r.Seek(nl.SizeofNfattr - 1, seekCurrent)
|
||||
return s
|
||||
}
|
||||
|
||||
// parseProtoInfoTCP reads the entire nested protoinfo structure, but only parses the state attr.
|
||||
func parseProtoInfoTCP(r *bytes.Reader, attrLen uint16) (*ProtoInfoTCP) {
|
||||
p := new(ProtoInfoTCP)
|
||||
bytesRead := 0
|
||||
for bytesRead < int(attrLen) {
|
||||
_, t, l := parseNfAttrTL(r)
|
||||
bytesRead += nl.SizeofNfattr
|
||||
|
||||
switch t {
|
||||
case nl.CTA_PROTOINFO_TCP_STATE:
|
||||
p.State = parseProtoInfoTCPState(r)
|
||||
bytesRead += nl.SizeofNfattr
|
||||
default:
|
||||
bytesRead += int(skipNfAttrValue(r, l))
|
||||
}
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func parseProtoInfo(r *bytes.Reader, attrLen uint16) (p ProtoInfo) {
|
||||
bytesRead := 0
|
||||
for bytesRead < int(attrLen) {
|
||||
_, t, l := parseNfAttrTL(r)
|
||||
bytesRead += nl.SizeofNfattr
|
||||
|
||||
switch t {
|
||||
case nl.CTA_PROTOINFO_TCP:
|
||||
p = parseProtoInfoTCP(r, l)
|
||||
bytesRead += int(l)
|
||||
// No inner fields of DCCP / SCTP currently supported.
|
||||
case nl.CTA_PROTOINFO_DCCP:
|
||||
p = new(ProtoInfoDCCP)
|
||||
skipped := skipNfAttrValue(r, l)
|
||||
bytesRead += int(skipped)
|
||||
case nl.CTA_PROTOINFO_SCTP:
|
||||
p = new(ProtoInfoSCTP)
|
||||
skipped := skipNfAttrValue(r, l)
|
||||
bytesRead += int(skipped)
|
||||
default:
|
||||
skipped := skipNfAttrValue(r, l)
|
||||
bytesRead += int(skipped)
|
||||
}
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func parseTimeOut(r *bytes.Reader) (ttimeout uint32) {
|
||||
parseBERaw32(r, &ttimeout)
|
||||
return
|
||||
@ -306,6 +590,18 @@ func parseConnectionMark(r *bytes.Reader) (mark uint32) {
|
||||
return
|
||||
}
|
||||
|
||||
func parseConnectionLabels(r *bytes.Reader) (label []byte) {
|
||||
label = make([]byte, 16) // netfilter defines 128 bit labels value
|
||||
binary.Read(r, nl.NativeEndian(), &label)
|
||||
return
|
||||
}
|
||||
|
||||
func parseConnectionZone(r *bytes.Reader) (zone uint16) {
|
||||
parseBERaw16(r, &zone)
|
||||
r.Seek(2, seekCurrent)
|
||||
return
|
||||
}
|
||||
|
||||
func parseRawData(data []byte) *ConntrackFlow {
|
||||
s := &ConntrackFlow{}
|
||||
// First there is the Nfgenmsg header
|
||||
@ -343,7 +639,7 @@ func parseRawData(data []byte) *ConntrackFlow {
|
||||
case nl.CTA_TIMESTAMP:
|
||||
s.TimeStart, s.TimeStop = parseTimeStamp(reader, l)
|
||||
case nl.CTA_PROTOINFO:
|
||||
skipNfAttrValue(reader, l)
|
||||
s.ProtoInfo = parseProtoInfo(reader, l)
|
||||
default:
|
||||
skipNfAttrValue(reader, l)
|
||||
}
|
||||
@ -351,10 +647,14 @@ func parseRawData(data []byte) *ConntrackFlow {
|
||||
switch t {
|
||||
case nl.CTA_MARK:
|
||||
s.Mark = parseConnectionMark(reader)
|
||||
case nl.CTA_LABELS:
|
||||
s.Labels = parseConnectionLabels(reader)
|
||||
case nl.CTA_TIMEOUT:
|
||||
s.TimeOut = parseTimeOut(reader)
|
||||
case nl.CTA_STATUS, nl.CTA_USE, nl.CTA_ID:
|
||||
case nl.CTA_ID, nl.CTA_STATUS, nl.CTA_USE:
|
||||
skipNfAttrValue(reader, l)
|
||||
case nl.CTA_ZONE:
|
||||
s.Zone = parseConnectionZone(reader)
|
||||
default:
|
||||
skipNfAttrValue(reader, l)
|
||||
}
|
||||
@ -399,16 +699,18 @@ func parseRawData(data []byte) *ConntrackFlow {
|
||||
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
|
||||
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
|
||||
ConntrackMatchLabels // --label label1,label2 Labels used in entry
|
||||
ConntrackUnmatchLabels // --label label1,label2 Labels not used in entry
|
||||
ConntrackNatSrcIP = ConntrackReplySrcIP // deprecated use instead ConntrackReplySrcIP
|
||||
ConntrackNatDstIP = ConntrackReplyDstIP // deprecated use instead ConntrackReplyDstIP
|
||||
ConntrackNatAnyIP = ConntrackReplyAnyIP // deprecated use instead ConntrackReplyAnyIP
|
||||
)
|
||||
|
||||
type CustomConntrackFilter interface {
|
||||
@ -421,6 +723,8 @@ type ConntrackFilter struct {
|
||||
ipNetFilter map[ConntrackFilterType]*net.IPNet
|
||||
portFilter map[ConntrackFilterType]uint16
|
||||
protoFilter uint8
|
||||
labelFilter map[ConntrackFilterType][][]byte
|
||||
zoneFilter *uint16
|
||||
}
|
||||
|
||||
// AddIPNet adds a IP subnet to the conntrack filter
|
||||
@ -474,10 +778,43 @@ func (f *ConntrackFilter) AddProtocol(proto uint8) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddLabels adds the provided list (zero or more) of labels to the conntrack filter
|
||||
// ConntrackFilterType here can be either:
|
||||
// 1. ConntrackMatchLabels: This matches every flow that has a label value (len(flow.Labels) > 0)
|
||||
// against the list of provided labels. If `flow.Labels` contains ALL the provided labels
|
||||
// it is considered a match. This can be used when you want to match flows that contain
|
||||
// one or more labels.
|
||||
// 2. ConntrackUnmatchLabels: This matches every flow that has a label value (len(flow.Labels) > 0)
|
||||
// against the list of provided labels. If `flow.Labels` does NOT contain ALL the provided labels
|
||||
// it is considered a match. This can be used when you want to match flows that don't contain
|
||||
// one or more labels.
|
||||
func (f *ConntrackFilter) AddLabels(tp ConntrackFilterType, labels [][]byte) error {
|
||||
if len(labels) == 0 {
|
||||
return errors.New("Invalid length for provided labels")
|
||||
}
|
||||
if f.labelFilter == nil {
|
||||
f.labelFilter = make(map[ConntrackFilterType][][]byte)
|
||||
}
|
||||
if _, ok := f.labelFilter[tp]; ok {
|
||||
return errors.New("Filter attribute already present")
|
||||
}
|
||||
f.labelFilter[tp] = labels
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddZone adds a zone to the conntrack filter
|
||||
func (f *ConntrackFilter) AddZone(zone uint16) error {
|
||||
if f.zoneFilter != nil {
|
||||
return errors.New("Filter attribute already present")
|
||||
}
|
||||
f.zoneFilter = &zone
|
||||
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.ipNetFilter) == 0 && len(f.portFilter) == 0 && f.protoFilter == 0 {
|
||||
if len(f.ipNetFilter) == 0 && len(f.portFilter) == 0 && f.protoFilter == 0 && len(f.labelFilter) == 0 && f.zoneFilter == nil {
|
||||
// empty filter always not match
|
||||
return false
|
||||
}
|
||||
@ -488,6 +825,11 @@ func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Conntrack zone filter
|
||||
if f.zoneFilter != nil && *f.zoneFilter != flow.Zone {
|
||||
return false
|
||||
}
|
||||
|
||||
match := true
|
||||
|
||||
// IP conntrack filter
|
||||
@ -531,6 +873,29 @@ func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// Label filter
|
||||
if len(f.labelFilter) > 0 {
|
||||
if len(flow.Labels) > 0 {
|
||||
// --label label1,label2 in conn entry;
|
||||
// every label passed should be contained in flow.Labels for a match to be true
|
||||
if elem, found := f.labelFilter[ConntrackMatchLabels]; match && found {
|
||||
for _, label := range elem {
|
||||
match = match && (bytes.Contains(flow.Labels, label))
|
||||
}
|
||||
}
|
||||
// --label label1,label2 in conn entry;
|
||||
// every label passed should be not contained in flow.Labels for a match to be true
|
||||
if elem, found := f.labelFilter[ConntrackUnmatchLabels]; match && found {
|
||||
for _, label := range elem {
|
||||
match = match && !(bytes.Contains(flow.Labels, label))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// flow doesn't contain labels, so it doesn't contain or notContain any provided matches
|
||||
match = false
|
||||
}
|
||||
}
|
||||
|
||||
return match
|
||||
}
|
||||
|
||||
|
19
vendor/github.com/vishvananda/netlink/conntrack_unspecified.go
generated
vendored
19
vendor/github.com/vishvananda/netlink/conntrack_unspecified.go
generated
vendored
@ -11,6 +11,9 @@ type InetFamily uint8
|
||||
// ConntrackFlow placeholder
|
||||
type ConntrackFlow struct{}
|
||||
|
||||
// CustomConntrackFilter placeholder
|
||||
type CustomConntrackFilter struct{}
|
||||
|
||||
// ConntrackFilter placeholder
|
||||
type ConntrackFilter struct{}
|
||||
|
||||
@ -29,10 +32,18 @@ func ConntrackTableFlush(table ConntrackTableType) error {
|
||||
|
||||
// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter
|
||||
// conntrack -D [table] parameters Delete conntrack or expectation
|
||||
//
|
||||
// Deprecated: use [ConntrackDeleteFilter] instead.
|
||||
func ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter *ConntrackFilter) (uint, error) {
|
||||
return 0, ErrNotImplemented
|
||||
}
|
||||
|
||||
// ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters
|
||||
// conntrack -D [table] parameters Delete conntrack or expectation
|
||||
func ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (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) {
|
||||
@ -48,6 +59,14 @@ func (h *Handle) ConntrackTableFlush(table ConntrackTableType) error {
|
||||
|
||||
// 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
|
||||
//
|
||||
// Deprecated: use [Handle.ConntrackDeleteFilters] instead.
|
||||
func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter *ConntrackFilter) (uint, error) {
|
||||
return 0, ErrNotImplemented
|
||||
}
|
||||
|
||||
// ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters using the netlink handle passed
|
||||
// conntrack -D [table] parameters Delete conntrack or expectation
|
||||
func (h *Handle) ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (uint, error) {
|
||||
return 0, ErrNotImplemented
|
||||
}
|
||||
|
431
vendor/github.com/vishvananda/netlink/devlink_linux.go
generated
vendored
431
vendor/github.com/vishvananda/netlink/devlink_linux.go
generated
vendored
@ -84,6 +84,270 @@ type DevlinkDeviceInfo struct {
|
||||
FwUndi string
|
||||
}
|
||||
|
||||
// DevlinkResource represents a device resource
|
||||
type DevlinkResource struct {
|
||||
Name string
|
||||
ID uint64
|
||||
Size uint64
|
||||
SizeNew uint64
|
||||
SizeMin uint64
|
||||
SizeMax uint64
|
||||
SizeGranularity uint64
|
||||
PendingChange bool
|
||||
Unit uint8
|
||||
SizeValid bool
|
||||
OCCValid bool
|
||||
OCCSize uint64
|
||||
Parent *DevlinkResource
|
||||
Children []DevlinkResource
|
||||
}
|
||||
|
||||
// parseAttributes parses provided Netlink Attributes and populates DevlinkResource, returns error if occured
|
||||
func (dlr *DevlinkResource) parseAttributes(attrs map[uint16]syscall.NetlinkRouteAttr) error {
|
||||
var attr syscall.NetlinkRouteAttr
|
||||
var ok bool
|
||||
|
||||
// mandatory attributes
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_ID]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource id")
|
||||
}
|
||||
dlr.ID = native.Uint64(attr.Value)
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_NAME]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource name")
|
||||
}
|
||||
dlr.Name = nl.BytesToString(attr.Value)
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource size")
|
||||
}
|
||||
dlr.Size = native.Uint64(attr.Value)
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_GRAN]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource size granularity")
|
||||
}
|
||||
dlr.SizeGranularity = native.Uint64(attr.Value)
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_UNIT]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource unit")
|
||||
}
|
||||
dlr.Unit = uint8(attr.Value[0])
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_MIN]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource size min")
|
||||
}
|
||||
dlr.SizeMin = native.Uint64(attr.Value)
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_MAX]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource size max")
|
||||
}
|
||||
dlr.SizeMax = native.Uint64(attr.Value)
|
||||
|
||||
// optional attributes
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_OCC]
|
||||
if ok {
|
||||
dlr.OCCSize = native.Uint64(attr.Value)
|
||||
dlr.OCCValid = true
|
||||
}
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_VALID]
|
||||
if ok {
|
||||
dlr.SizeValid = uint8(attr.Value[0]) != 0
|
||||
}
|
||||
|
||||
dlr.SizeNew = dlr.Size
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_NEW]
|
||||
if ok {
|
||||
dlr.SizeNew = native.Uint64(attr.Value)
|
||||
}
|
||||
|
||||
dlr.PendingChange = dlr.Size != dlr.SizeNew
|
||||
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_LIST]
|
||||
if ok {
|
||||
// handle nested resoruces recursively
|
||||
subResources, err := nl.ParseRouteAttr(attr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, subresource := range subResources {
|
||||
resource := DevlinkResource{Parent: dlr}
|
||||
attrs, err := nl.ParseRouteAttrAsMap(subresource.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = resource.parseAttributes(attrs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse child resource, parent:%s. %w", dlr.Name, err)
|
||||
}
|
||||
dlr.Children = append(dlr.Children, resource)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DevlinkResources represents all devlink resources of a devlink device
|
||||
type DevlinkResources struct {
|
||||
Bus string
|
||||
Device string
|
||||
Resources []DevlinkResource
|
||||
}
|
||||
|
||||
// parseAttributes parses provided Netlink Attributes and populates DevlinkResources, returns error if occured
|
||||
func (dlrs *DevlinkResources) parseAttributes(attrs map[uint16]syscall.NetlinkRouteAttr) error {
|
||||
var attr syscall.NetlinkRouteAttr
|
||||
var ok bool
|
||||
|
||||
// Bus
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_BUS_NAME]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing bus name")
|
||||
}
|
||||
dlrs.Bus = nl.BytesToString(attr.Value)
|
||||
|
||||
// Device
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_DEV_NAME]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing device name")
|
||||
}
|
||||
dlrs.Device = nl.BytesToString(attr.Value)
|
||||
|
||||
// Resource List
|
||||
attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_LIST]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing resource list")
|
||||
}
|
||||
|
||||
resourceAttrs, err := nl.ParseRouteAttr(attr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, resourceAttr := range resourceAttrs {
|
||||
resource := DevlinkResource{}
|
||||
attrs, err := nl.ParseRouteAttrAsMap(resourceAttr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = resource.parseAttributes(attrs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse root resoruces, %w", err)
|
||||
}
|
||||
dlrs.Resources = append(dlrs.Resources, resource)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DevlinkParam represents parameter of the device
|
||||
type DevlinkParam struct {
|
||||
Name string
|
||||
IsGeneric bool
|
||||
Type uint8 // possible values are in nl.DEVLINK_PARAM_TYPE_* constants
|
||||
Values []DevlinkParamValue
|
||||
}
|
||||
|
||||
// DevlinkParamValue contains values of the parameter
|
||||
// Data field contains specific type which can be casted by unsing info from the DevlinkParam.Type field
|
||||
type DevlinkParamValue struct {
|
||||
rawData []byte
|
||||
Data interface{}
|
||||
CMODE uint8 // possible values are in nl.DEVLINK_PARAM_CMODE_* constants
|
||||
}
|
||||
|
||||
// parseAttributes parses provided Netlink Attributes and populates DevlinkParam, returns error if occured
|
||||
func (dlp *DevlinkParam) parseAttributes(attrs []syscall.NetlinkRouteAttr) error {
|
||||
var valuesList [][]syscall.NetlinkRouteAttr
|
||||
for _, attr := range attrs {
|
||||
switch attr.Attr.Type {
|
||||
case nl.DEVLINK_ATTR_PARAM:
|
||||
nattrs, err := nl.ParseRouteAttr(attr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, nattr := range nattrs {
|
||||
switch nattr.Attr.Type {
|
||||
case nl.DEVLINK_ATTR_PARAM_NAME:
|
||||
dlp.Name = nl.BytesToString(nattr.Value)
|
||||
case nl.DEVLINK_ATTR_PARAM_GENERIC:
|
||||
dlp.IsGeneric = true
|
||||
case nl.DEVLINK_ATTR_PARAM_TYPE:
|
||||
if len(nattr.Value) == 1 {
|
||||
dlp.Type = nattr.Value[0]
|
||||
}
|
||||
case nl.DEVLINK_ATTR_PARAM_VALUES_LIST:
|
||||
nnattrs, err := nl.ParseRouteAttr(nattr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
valuesList = append(valuesList, nnattrs)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, valAttr := range valuesList {
|
||||
v := DevlinkParamValue{}
|
||||
if err := v.parseAttributes(valAttr, dlp.Type); err != nil {
|
||||
return err
|
||||
}
|
||||
dlp.Values = append(dlp.Values, v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dlpv *DevlinkParamValue) parseAttributes(attrs []syscall.NetlinkRouteAttr, paramType uint8) error {
|
||||
for _, attr := range attrs {
|
||||
nattrs, err := nl.ParseRouteAttr(attr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var rawData []byte
|
||||
for _, nattr := range nattrs {
|
||||
switch nattr.Attr.Type {
|
||||
case nl.DEVLINK_ATTR_PARAM_VALUE_DATA:
|
||||
rawData = nattr.Value
|
||||
case nl.DEVLINK_ATTR_PARAM_VALUE_CMODE:
|
||||
if len(nattr.Value) == 1 {
|
||||
dlpv.CMODE = nattr.Value[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
switch paramType {
|
||||
case nl.DEVLINK_PARAM_TYPE_U8:
|
||||
dlpv.Data = uint8(0)
|
||||
if rawData != nil && len(rawData) == 1 {
|
||||
dlpv.Data = uint8(rawData[0])
|
||||
}
|
||||
case nl.DEVLINK_PARAM_TYPE_U16:
|
||||
dlpv.Data = uint16(0)
|
||||
if rawData != nil {
|
||||
dlpv.Data = native.Uint16(rawData)
|
||||
}
|
||||
case nl.DEVLINK_PARAM_TYPE_U32:
|
||||
dlpv.Data = uint32(0)
|
||||
if rawData != nil {
|
||||
dlpv.Data = native.Uint32(rawData)
|
||||
}
|
||||
case nl.DEVLINK_PARAM_TYPE_STRING:
|
||||
dlpv.Data = ""
|
||||
if rawData != nil {
|
||||
dlpv.Data = nl.BytesToString(rawData)
|
||||
}
|
||||
case nl.DEVLINK_PARAM_TYPE_BOOL:
|
||||
dlpv.Data = rawData != nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseDevLinkDeviceList(msgs [][]byte) ([]*DevlinkDevice, error) {
|
||||
devices := make([]*DevlinkDevice, 0, len(msgs))
|
||||
for _, m := range msgs {
|
||||
@ -443,6 +707,173 @@ func (h *Handle) DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint
|
||||
return port, err
|
||||
}
|
||||
|
||||
// DevlinkGetDeviceResources returns devlink device resources
|
||||
func DevlinkGetDeviceResources(bus string, device string) (*DevlinkResources, error) {
|
||||
return pkgHandle.DevlinkGetDeviceResources(bus, device)
|
||||
}
|
||||
|
||||
// DevlinkGetDeviceResources returns devlink device resources
|
||||
func (h *Handle) DevlinkGetDeviceResources(bus string, device string) (*DevlinkResources, error) {
|
||||
_, req, err := h.createCmdReq(nl.DEVLINK_CMD_RESOURCE_DUMP, bus, device)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resources DevlinkResources
|
||||
for _, m := range respmsg {
|
||||
attrs, err := nl.ParseRouteAttrAsMap(m[nl.SizeofGenlmsg:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resources.parseAttributes(attrs)
|
||||
}
|
||||
|
||||
return &resources, nil
|
||||
}
|
||||
|
||||
// DevlinkGetDeviceParams returns parameters for devlink device
|
||||
// Equivalent to: `devlink dev param show <bus>/<device>`
|
||||
func (h *Handle) DevlinkGetDeviceParams(bus string, device string) ([]*DevlinkParam, error) {
|
||||
_, req, err := h.createCmdReq(nl.DEVLINK_CMD_PARAM_GET, bus, device)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Flags |= unix.NLM_F_DUMP
|
||||
respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var params []*DevlinkParam
|
||||
for _, m := range respmsg {
|
||||
attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p := &DevlinkParam{}
|
||||
if err := p.parseAttributes(attrs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params = append(params, p)
|
||||
}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// DevlinkGetDeviceParams returns parameters for devlink device
|
||||
// Equivalent to: `devlink dev param show <bus>/<device>`
|
||||
func DevlinkGetDeviceParams(bus string, device string) ([]*DevlinkParam, error) {
|
||||
return pkgHandle.DevlinkGetDeviceParams(bus, device)
|
||||
}
|
||||
|
||||
// DevlinkGetDeviceParamByName returns specific parameter for devlink device
|
||||
// Equivalent to: `devlink dev param show <bus>/<device> name <param>`
|
||||
func (h *Handle) DevlinkGetDeviceParamByName(bus string, device string, param string) (*DevlinkParam, error) {
|
||||
_, req, err := h.createCmdReq(nl.DEVLINK_CMD_PARAM_GET, bus, device)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PARAM_NAME, nl.ZeroTerminated(param)))
|
||||
respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(respmsg) == 0 {
|
||||
return nil, fmt.Errorf("unexpected response")
|
||||
}
|
||||
attrs, err := nl.ParseRouteAttr(respmsg[0][nl.SizeofGenlmsg:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p := &DevlinkParam{}
|
||||
if err := p.parseAttributes(attrs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// DevlinkGetDeviceParamByName returns specific parameter for devlink device
|
||||
// Equivalent to: `devlink dev param show <bus>/<device> name <param>`
|
||||
func DevlinkGetDeviceParamByName(bus string, device string, param string) (*DevlinkParam, error) {
|
||||
return pkgHandle.DevlinkGetDeviceParamByName(bus, device, param)
|
||||
}
|
||||
|
||||
// DevlinkSetDeviceParam set specific parameter for devlink device
|
||||
// Equivalent to: `devlink dev param set <bus>/<device> name <param> cmode <cmode> value <value>`
|
||||
// cmode argument should contain valid cmode value as uint8, modes are define in nl.DEVLINK_PARAM_CMODE_* constants
|
||||
// value argument should have one of the following types: uint8, uint16, uint32, string, bool
|
||||
func (h *Handle) DevlinkSetDeviceParam(bus string, device string, param string, cmode uint8, value interface{}) error {
|
||||
// retrive the param type
|
||||
p, err := h.DevlinkGetDeviceParamByName(bus, device, param)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get device param: %v", err)
|
||||
}
|
||||
paramType := p.Type
|
||||
|
||||
_, req, err := h.createCmdReq(nl.DEVLINK_CMD_PARAM_SET, bus, device)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PARAM_TYPE, nl.Uint8Attr(paramType)))
|
||||
req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PARAM_NAME, nl.ZeroTerminated(param)))
|
||||
req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PARAM_VALUE_CMODE, nl.Uint8Attr(cmode)))
|
||||
|
||||
var valueAsBytes []byte
|
||||
switch paramType {
|
||||
case nl.DEVLINK_PARAM_TYPE_U8:
|
||||
v, ok := value.(uint8)
|
||||
if !ok {
|
||||
return fmt.Errorf("unepected value type required: uint8, actual: %T", value)
|
||||
}
|
||||
valueAsBytes = nl.Uint8Attr(v)
|
||||
case nl.DEVLINK_PARAM_TYPE_U16:
|
||||
v, ok := value.(uint16)
|
||||
if !ok {
|
||||
return fmt.Errorf("unepected value type required: uint16, actual: %T", value)
|
||||
}
|
||||
valueAsBytes = nl.Uint16Attr(v)
|
||||
case nl.DEVLINK_PARAM_TYPE_U32:
|
||||
v, ok := value.(uint32)
|
||||
if !ok {
|
||||
return fmt.Errorf("unepected value type required: uint32, actual: %T", value)
|
||||
}
|
||||
valueAsBytes = nl.Uint32Attr(v)
|
||||
case nl.DEVLINK_PARAM_TYPE_STRING:
|
||||
v, ok := value.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("unepected value type required: string, actual: %T", value)
|
||||
}
|
||||
valueAsBytes = nl.ZeroTerminated(v)
|
||||
case nl.DEVLINK_PARAM_TYPE_BOOL:
|
||||
v, ok := value.(bool)
|
||||
if !ok {
|
||||
return fmt.Errorf("unepected value type required: bool, actual: %T", value)
|
||||
}
|
||||
if v {
|
||||
valueAsBytes = []byte{}
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unsupported parameter type: %d", paramType)
|
||||
}
|
||||
if valueAsBytes != nil {
|
||||
req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PARAM_VALUE_DATA, valueAsBytes))
|
||||
}
|
||||
_, err = req.Execute(unix.NETLINK_GENERIC, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// DevlinkSetDeviceParam set specific parameter for devlink device
|
||||
// Equivalent to: `devlink dev param set <bus>/<device> name <param> cmode <cmode> value <value>`
|
||||
// cmode argument should contain valid cmode value as uint8, modes are define in nl.DEVLINK_PARAM_CMODE_* constants
|
||||
// value argument should have one of the following types: uint8, uint16, uint32, string, bool
|
||||
func DevlinkSetDeviceParam(bus string, device string, param string, cmode uint8, value interface{}) error {
|
||||
return pkgHandle.DevlinkSetDeviceParam(bus, device, param, cmode, value)
|
||||
}
|
||||
|
||||
// DevLinkGetPortByIndex provides a pointer to devlink portand nil error,
|
||||
// otherwise returns an error code.
|
||||
func DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint32) (*DevlinkPort, error) {
|
||||
|
80
vendor/github.com/vishvananda/netlink/filter.go
generated
vendored
80
vendor/github.com/vishvananda/netlink/filter.go
generated
vendored
@ -19,6 +19,7 @@ type FilterAttrs struct {
|
||||
Parent uint32
|
||||
Priority uint16 // lower is higher priority
|
||||
Protocol uint16 // unix.ETH_P_*
|
||||
Chain *uint32
|
||||
}
|
||||
|
||||
func (q FilterAttrs) String() string {
|
||||
@ -27,6 +28,11 @@ func (q FilterAttrs) String() string {
|
||||
|
||||
type TcAct int32
|
||||
|
||||
const (
|
||||
TC_ACT_EXT_SHIFT = 28
|
||||
TC_ACT_EXT_VAL_MASK = (1 << TC_ACT_EXT_SHIFT) - 1
|
||||
)
|
||||
|
||||
const (
|
||||
TC_ACT_UNSPEC TcAct = -1
|
||||
TC_ACT_OK TcAct = 0
|
||||
@ -40,6 +46,22 @@ const (
|
||||
TC_ACT_JUMP TcAct = 0x10000000
|
||||
)
|
||||
|
||||
func getTcActExt(local int32) int32 {
|
||||
return local << TC_ACT_EXT_SHIFT
|
||||
}
|
||||
|
||||
func getTcActGotoChain() TcAct {
|
||||
return TcAct(getTcActExt(2))
|
||||
}
|
||||
|
||||
func getTcActExtOpcode(combined int32) int32 {
|
||||
return combined & (^TC_ACT_EXT_VAL_MASK)
|
||||
}
|
||||
|
||||
func TcActExtCmp(combined int32, opcode int32) bool {
|
||||
return getTcActExtOpcode(combined) == opcode
|
||||
}
|
||||
|
||||
func (a TcAct) String() string {
|
||||
switch a {
|
||||
case TC_ACT_UNSPEC:
|
||||
@ -63,6 +85,9 @@ func (a TcAct) String() string {
|
||||
case TC_ACT_JUMP:
|
||||
return "jump"
|
||||
}
|
||||
if TcActExtCmp(int32(a), int32(getTcActGotoChain())) {
|
||||
return "goto"
|
||||
}
|
||||
return fmt.Sprintf("0x%x", int32(a))
|
||||
}
|
||||
|
||||
@ -93,17 +118,32 @@ func (a TcPolAct) String() string {
|
||||
}
|
||||
|
||||
type ActionAttrs struct {
|
||||
Index int
|
||||
Capab int
|
||||
Action TcAct
|
||||
Refcnt int
|
||||
Bindcnt int
|
||||
Index int
|
||||
Capab int
|
||||
Action TcAct
|
||||
Refcnt int
|
||||
Bindcnt int
|
||||
Statistics *ActionStatistic
|
||||
Timestamp *ActionTimestamp
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
type ActionTimestamp struct {
|
||||
Installed uint64
|
||||
LastUsed uint64
|
||||
Expires uint64
|
||||
FirstUsed uint64
|
||||
}
|
||||
|
||||
func (t ActionTimestamp) String() string {
|
||||
return fmt.Sprintf("Installed %d LastUsed %d Expires %d FirstUsed %d", t.Installed, t.LastUsed, t.Expires, t.FirstUsed)
|
||||
}
|
||||
|
||||
type ActionStatistic ClassStatistics
|
||||
|
||||
// Action represents an action in any supported filter.
|
||||
type Action interface {
|
||||
Attrs() *ActionAttrs
|
||||
@ -112,6 +152,7 @@ type Action interface {
|
||||
|
||||
type GenericAction struct {
|
||||
ActionAttrs
|
||||
Chain int32
|
||||
}
|
||||
|
||||
func (action *GenericAction) Type() string {
|
||||
@ -275,6 +316,7 @@ type SkbEditAction struct {
|
||||
PType *uint16
|
||||
Priority *uint32
|
||||
Mark *uint32
|
||||
Mask *uint32
|
||||
}
|
||||
|
||||
func (action *SkbEditAction) Type() string {
|
||||
@ -348,6 +390,7 @@ type FwFilter struct {
|
||||
InDev string
|
||||
Mask uint32
|
||||
Police *PoliceAction
|
||||
Actions []Action
|
||||
}
|
||||
|
||||
func (filter *FwFilter) Attrs() *FilterAttrs {
|
||||
@ -390,3 +433,30 @@ func (filter *GenericFilter) Attrs() *FilterAttrs {
|
||||
func (filter *GenericFilter) Type() string {
|
||||
return filter.FilterType
|
||||
}
|
||||
|
||||
type PeditAction struct {
|
||||
ActionAttrs
|
||||
Proto uint8
|
||||
SrcMacAddr net.HardwareAddr
|
||||
DstMacAddr net.HardwareAddr
|
||||
SrcIP net.IP
|
||||
DstIP net.IP
|
||||
SrcPort uint16
|
||||
DstPort uint16
|
||||
}
|
||||
|
||||
func (p *PeditAction) Attrs() *ActionAttrs {
|
||||
return &p.ActionAttrs
|
||||
}
|
||||
|
||||
func (p *PeditAction) Type() string {
|
||||
return "pedit"
|
||||
}
|
||||
|
||||
func NewPeditAction() *PeditAction {
|
||||
return &PeditAction{
|
||||
ActionAttrs: ActionAttrs{
|
||||
Action: TC_ACT_PIPE,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
187
vendor/github.com/vishvananda/netlink/filter_linux.go
generated
vendored
187
vendor/github.com/vishvananda/netlink/filter_linux.go
generated
vendored
@ -41,6 +41,7 @@ type U32 struct {
|
||||
RedirIndex int
|
||||
Sel *TcU32Sel
|
||||
Actions []Action
|
||||
Police *PoliceAction
|
||||
}
|
||||
|
||||
func (filter *U32) Attrs() *FilterAttrs {
|
||||
@ -64,6 +65,11 @@ type Flower struct {
|
||||
EncSrcIPMask net.IPMask
|
||||
EncDestPort uint16
|
||||
EncKeyId uint32
|
||||
SkipHw bool
|
||||
SkipSw bool
|
||||
IPProto *nl.IPProto
|
||||
DestPort uint16
|
||||
SrcPort uint16
|
||||
|
||||
Actions []Action
|
||||
}
|
||||
@ -129,6 +135,39 @@ func (filter *Flower) encode(parent *nl.RtAttr) error {
|
||||
if filter.EncKeyId != 0 {
|
||||
parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_KEY_ID, htonl(filter.EncKeyId))
|
||||
}
|
||||
if filter.IPProto != nil {
|
||||
ipproto := *filter.IPProto
|
||||
parent.AddRtAttr(nl.TCA_FLOWER_KEY_IP_PROTO, ipproto.Serialize())
|
||||
if filter.SrcPort != 0 {
|
||||
switch ipproto {
|
||||
case nl.IPPROTO_TCP:
|
||||
parent.AddRtAttr(nl.TCA_FLOWER_KEY_TCP_SRC, htons(filter.SrcPort))
|
||||
case nl.IPPROTO_UDP:
|
||||
parent.AddRtAttr(nl.TCA_FLOWER_KEY_UDP_SRC, htons(filter.SrcPort))
|
||||
case nl.IPPROTO_SCTP:
|
||||
parent.AddRtAttr(nl.TCA_FLOWER_KEY_SCTP_SRC, htons(filter.SrcPort))
|
||||
}
|
||||
}
|
||||
if filter.DestPort != 0 {
|
||||
switch ipproto {
|
||||
case nl.IPPROTO_TCP:
|
||||
parent.AddRtAttr(nl.TCA_FLOWER_KEY_TCP_DST, htons(filter.DestPort))
|
||||
case nl.IPPROTO_UDP:
|
||||
parent.AddRtAttr(nl.TCA_FLOWER_KEY_UDP_DST, htons(filter.DestPort))
|
||||
case nl.IPPROTO_SCTP:
|
||||
parent.AddRtAttr(nl.TCA_FLOWER_KEY_SCTP_DST, htons(filter.DestPort))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var flags uint32 = 0
|
||||
if filter.SkipHw {
|
||||
flags |= nl.TCA_CLS_FLAGS_SKIP_HW
|
||||
}
|
||||
if filter.SkipSw {
|
||||
flags |= nl.TCA_CLS_FLAGS_SKIP_SW
|
||||
}
|
||||
parent.AddRtAttr(nl.TCA_FLOWER_FLAGS, htonl(flags))
|
||||
|
||||
actionsAttr := parent.AddRtAttr(nl.TCA_FLOWER_ACT, nil)
|
||||
if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
|
||||
@ -162,6 +201,14 @@ func (filter *Flower) decode(data []syscall.NetlinkRouteAttr) error {
|
||||
filter.EncDestPort = ntohs(datum.Value)
|
||||
case nl.TCA_FLOWER_KEY_ENC_KEY_ID:
|
||||
filter.EncKeyId = ntohl(datum.Value)
|
||||
case nl.TCA_FLOWER_KEY_IP_PROTO:
|
||||
val := new(nl.IPProto)
|
||||
*val = nl.IPProto(datum.Value[0])
|
||||
filter.IPProto = val
|
||||
case nl.TCA_FLOWER_KEY_TCP_SRC, nl.TCA_FLOWER_KEY_UDP_SRC, nl.TCA_FLOWER_KEY_SCTP_SRC:
|
||||
filter.SrcPort = ntohs(datum.Value)
|
||||
case nl.TCA_FLOWER_KEY_TCP_DST, nl.TCA_FLOWER_KEY_UDP_DST, nl.TCA_FLOWER_KEY_SCTP_DST:
|
||||
filter.DestPort = ntohs(datum.Value)
|
||||
case nl.TCA_FLOWER_ACT:
|
||||
tables, err := nl.ParseRouteAttr(datum.Value)
|
||||
if err != nil {
|
||||
@ -171,6 +218,16 @@ func (filter *Flower) decode(data []syscall.NetlinkRouteAttr) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case nl.TCA_FLOWER_FLAGS:
|
||||
attr := nl.DeserializeUint32Bitfield(datum.Value)
|
||||
skipSw := attr.Value & nl.TCA_CLS_FLAGS_SKIP_HW
|
||||
skipHw := attr.Value & nl.TCA_CLS_FLAGS_SKIP_SW
|
||||
if skipSw != 0 {
|
||||
filter.SkipSw = true
|
||||
}
|
||||
if skipHw != 0 {
|
||||
filter.SkipHw = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -185,19 +242,7 @@ func FilterDel(filter Filter) error {
|
||||
// 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
|
||||
return h.filterModify(filter, unix.RTM_DELTFILTER, 0)
|
||||
}
|
||||
|
||||
// FilterAdd will add a filter to the system.
|
||||
@ -209,7 +254,7 @@ func FilterAdd(filter Filter) error {
|
||||
// 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)
|
||||
return h.filterModify(filter, unix.RTM_NEWTFILTER, unix.NLM_F_CREATE|unix.NLM_F_EXCL)
|
||||
}
|
||||
|
||||
// FilterReplace will replace a filter.
|
||||
@ -221,11 +266,11 @@ func FilterReplace(filter Filter) error {
|
||||
// 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)
|
||||
return h.filterModify(filter, unix.RTM_NEWTFILTER, unix.NLM_F_CREATE)
|
||||
}
|
||||
|
||||
func (h *Handle) filterModify(filter Filter, flags int) error {
|
||||
req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, flags|unix.NLM_F_ACK)
|
||||
func (h *Handle) filterModify(filter Filter, proto, flags int) error {
|
||||
req := h.newNetlinkRequest(proto, flags|unix.NLM_F_ACK)
|
||||
base := filter.Attrs()
|
||||
msg := &nl.TcMsg{
|
||||
Family: nl.FAMILY_ALL,
|
||||
@ -235,6 +280,9 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
|
||||
Info: MakeHandle(base.Priority, nl.Swap16(base.Protocol)),
|
||||
}
|
||||
req.AddData(msg)
|
||||
if filter.Attrs().Chain != nil {
|
||||
req.AddData(nl.NewRtAttr(nl.TCA_CHAIN, nl.Uint32Attr(*filter.Attrs().Chain)))
|
||||
}
|
||||
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(filter.Type())))
|
||||
|
||||
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
|
||||
@ -284,6 +332,12 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
|
||||
if filter.Link != 0 {
|
||||
options.AddRtAttr(nl.TCA_U32_LINK, nl.Uint32Attr(filter.Link))
|
||||
}
|
||||
if filter.Police != nil {
|
||||
police := options.AddRtAttr(nl.TCA_U32_POLICE, nil)
|
||||
if err := encodePolice(police, filter.Police); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
actionsAttr := options.AddRtAttr(nl.TCA_U32_ACT, nil)
|
||||
// backwards compatibility
|
||||
if filter.RedirIndex != 0 {
|
||||
@ -312,6 +366,10 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
|
||||
native.PutUint32(b, filter.ClassId)
|
||||
options.AddRtAttr(nl.TCA_FW_CLASSID, b)
|
||||
}
|
||||
actionsAttr := options.AddRtAttr(nl.TCA_FW_ACT, nil)
|
||||
if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
|
||||
return err
|
||||
}
|
||||
case *BpfFilter:
|
||||
var bpfFlags uint32
|
||||
if filter.ClassId != 0 {
|
||||
@ -340,7 +398,6 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
req.AddData(options)
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
@ -446,6 +503,10 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
|
||||
default:
|
||||
detailed = true
|
||||
}
|
||||
case nl.TCA_CHAIN:
|
||||
val := new(uint32)
|
||||
*val = native.Uint32(attr.Value)
|
||||
base.Chain = val
|
||||
}
|
||||
}
|
||||
// only return the detailed version of the filter
|
||||
@ -474,6 +535,14 @@ func toAttrs(tcgen *nl.TcGen, attrs *ActionAttrs) {
|
||||
attrs.Bindcnt = int(tcgen.Bindcnt)
|
||||
}
|
||||
|
||||
func toTimeStamp(tcf *nl.Tcf) *ActionTimestamp {
|
||||
return &ActionTimestamp{
|
||||
Installed: tcf.Install,
|
||||
LastUsed: tcf.LastUse,
|
||||
Expires: tcf.Expires,
|
||||
FirstUsed: tcf.FirstUse}
|
||||
}
|
||||
|
||||
func encodePolice(attr *nl.RtAttr, action *PoliceAction) error {
|
||||
var rtab [256]uint32
|
||||
var ptab [256]uint32
|
||||
@ -597,6 +666,9 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
||||
if action.Mark != nil {
|
||||
aopts.AddRtAttr(nl.TCA_SKBEDIT_MARK, nl.Uint32Attr(*action.Mark))
|
||||
}
|
||||
if action.Mask != nil {
|
||||
aopts.AddRtAttr(nl.TCA_SKBEDIT_MASK, nl.Uint32Attr(*action.Mask))
|
||||
}
|
||||
case *ConnmarkAction:
|
||||
table := attr.AddRtAttr(tabIndex, nil)
|
||||
tabIndex++
|
||||
@ -635,6 +707,29 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
||||
gen := nl.TcGen{}
|
||||
toTcGen(action.Attrs(), &gen)
|
||||
aopts.AddRtAttr(nl.TCA_GACT_PARMS, gen.Serialize())
|
||||
case *PeditAction:
|
||||
table := attr.AddRtAttr(tabIndex, nil)
|
||||
tabIndex++
|
||||
pedit := nl.TcPedit{}
|
||||
if action.SrcMacAddr != nil {
|
||||
pedit.SetEthSrc(action.SrcMacAddr)
|
||||
}
|
||||
if action.DstMacAddr != nil {
|
||||
pedit.SetEthDst(action.DstMacAddr)
|
||||
}
|
||||
if action.SrcIP != nil {
|
||||
pedit.SetSrcIP(action.SrcIP)
|
||||
}
|
||||
if action.DstIP != nil {
|
||||
pedit.SetDstIP(action.DstIP)
|
||||
}
|
||||
if action.SrcPort != 0 {
|
||||
pedit.SetSrcPort(action.SrcPort, action.Proto)
|
||||
}
|
||||
if action.DstPort != 0 {
|
||||
pedit.SetDstPort(action.DstPort, action.Proto)
|
||||
}
|
||||
pedit.Encode(table)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -668,6 +763,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||
for _, table := range tables {
|
||||
var action Action
|
||||
var actionType string
|
||||
var actionnStatistic *ActionStatistic
|
||||
var actionTimestamp *ActionTimestamp
|
||||
aattrs, err := nl.ParseRouteAttr(table.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -695,6 +792,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||
action = &SkbEditAction{}
|
||||
case "police":
|
||||
action = &PoliceAction{}
|
||||
case "pedit":
|
||||
action = &PeditAction{}
|
||||
default:
|
||||
break nextattr
|
||||
}
|
||||
@ -713,7 +812,11 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||
toAttrs(&mirred.TcGen, action.Attrs())
|
||||
action.(*MirredAction).Ifindex = int(mirred.Ifindex)
|
||||
action.(*MirredAction).MirredAction = MirredAct(mirred.Eaction)
|
||||
case nl.TCA_MIRRED_TM:
|
||||
tcTs := nl.DeserializeTcf(adatum.Value)
|
||||
actionTimestamp = toTimeStamp(tcTs)
|
||||
}
|
||||
|
||||
case "tunnel_key":
|
||||
switch adatum.Attr.Type {
|
||||
case nl.TCA_TUNNEL_KEY_PARMS:
|
||||
@ -729,6 +832,9 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||
action.(*TunnelKeyAction).DstAddr = adatum.Value[:]
|
||||
case nl.TCA_TUNNEL_KEY_ENC_DST_PORT:
|
||||
action.(*TunnelKeyAction).DestPort = ntohs(adatum.Value)
|
||||
case nl.TCA_TUNNEL_KEY_TM:
|
||||
tcTs := nl.DeserializeTcf(adatum.Value)
|
||||
actionTimestamp = toTimeStamp(tcTs)
|
||||
}
|
||||
case "skbedit":
|
||||
switch adatum.Attr.Type {
|
||||
@ -739,6 +845,9 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||
case nl.TCA_SKBEDIT_MARK:
|
||||
mark := native.Uint32(adatum.Value[0:4])
|
||||
action.(*SkbEditAction).Mark = &mark
|
||||
case nl.TCA_SKBEDIT_MASK:
|
||||
mask := native.Uint32(adatum.Value[0:4])
|
||||
action.(*SkbEditAction).Mask = &mask
|
||||
case nl.TCA_SKBEDIT_PRIORITY:
|
||||
priority := native.Uint32(adatum.Value[0:4])
|
||||
action.(*SkbEditAction).Priority = &priority
|
||||
@ -748,6 +857,9 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||
case nl.TCA_SKBEDIT_QUEUE_MAPPING:
|
||||
mapping := native.Uint16(adatum.Value[0:2])
|
||||
action.(*SkbEditAction).QueueMapping = &mapping
|
||||
case nl.TCA_SKBEDIT_TM:
|
||||
tcTs := nl.DeserializeTcf(adatum.Value)
|
||||
actionTimestamp = toTimeStamp(tcTs)
|
||||
}
|
||||
case "bpf":
|
||||
switch adatum.Attr.Type {
|
||||
@ -758,6 +870,9 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||
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 nl.TCA_ACT_BPF_TM:
|
||||
tcTs := nl.DeserializeTcf(adatum.Value)
|
||||
actionTimestamp = toTimeStamp(tcTs)
|
||||
}
|
||||
case "connmark":
|
||||
switch adatum.Attr.Type {
|
||||
@ -766,6 +881,9 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||
action.(*ConnmarkAction).ActionAttrs = ActionAttrs{}
|
||||
toAttrs(&connmark.TcGen, action.Attrs())
|
||||
action.(*ConnmarkAction).Zone = connmark.Zone
|
||||
case nl.TCA_CONNMARK_TM:
|
||||
tcTs := nl.DeserializeTcf(adatum.Value)
|
||||
actionTimestamp = toTimeStamp(tcTs)
|
||||
}
|
||||
case "csum":
|
||||
switch adatum.Attr.Type {
|
||||
@ -774,19 +892,36 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||
action.(*CsumAction).ActionAttrs = ActionAttrs{}
|
||||
toAttrs(&csum.TcGen, action.Attrs())
|
||||
action.(*CsumAction).UpdateFlags = CsumUpdateFlags(csum.UpdateFlags)
|
||||
case nl.TCA_CSUM_TM:
|
||||
tcTs := nl.DeserializeTcf(adatum.Value)
|
||||
actionTimestamp = toTimeStamp(tcTs)
|
||||
}
|
||||
case "gact":
|
||||
switch adatum.Attr.Type {
|
||||
case nl.TCA_GACT_PARMS:
|
||||
gen := *nl.DeserializeTcGen(adatum.Value)
|
||||
toAttrs(&gen, action.Attrs())
|
||||
if action.Attrs().Action.String() == "goto" {
|
||||
action.(*GenericAction).Chain = TC_ACT_EXT_VAL_MASK & gen.Action
|
||||
}
|
||||
case nl.TCA_GACT_TM:
|
||||
tcTs := nl.DeserializeTcf(adatum.Value)
|
||||
actionTimestamp = toTimeStamp(tcTs)
|
||||
}
|
||||
case "police":
|
||||
parsePolice(adatum, action.(*PoliceAction))
|
||||
}
|
||||
}
|
||||
case nl.TCA_ACT_STATS:
|
||||
s, err := parseTcStats2(aattr.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
actionnStatistic = (*ActionStatistic)(s)
|
||||
}
|
||||
}
|
||||
action.Attrs().Statistics = actionnStatistic
|
||||
action.Attrs().Timestamp = actionTimestamp
|
||||
actions = append(actions, action)
|
||||
}
|
||||
return actions, nil
|
||||
@ -824,6 +959,13 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
|
||||
u32.RedirIndex = int(action.Ifindex)
|
||||
}
|
||||
}
|
||||
case nl.TCA_U32_POLICE:
|
||||
var police PoliceAction
|
||||
adata, _ := nl.ParseRouteAttr(datum.Value)
|
||||
for _, aattr := range adata {
|
||||
parsePolice(aattr, &police)
|
||||
}
|
||||
u32.Police = &police
|
||||
case nl.TCA_U32_CLASSID:
|
||||
u32.ClassId = native.Uint32(datum.Value)
|
||||
case nl.TCA_U32_DIVISOR:
|
||||
@ -855,6 +997,15 @@ func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
||||
parsePolice(aattr, &police)
|
||||
}
|
||||
fw.Police = &police
|
||||
case nl.TCA_FW_ACT:
|
||||
tables, err := nl.ParseRouteAttr(datum.Value)
|
||||
if err != nil {
|
||||
return detailed, err
|
||||
}
|
||||
fw.Actions, err = parseActions(tables)
|
||||
if err != nil {
|
||||
return detailed, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return detailed, nil
|
||||
|
24
vendor/github.com/vishvananda/netlink/handle_unspecified.go
generated
vendored
24
vendor/github.com/vishvananda/netlink/handle_unspecified.go
generated
vendored
@ -79,6 +79,10 @@ func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *Handle) LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
@ -163,6 +167,22 @@ func (h *Handle) LinkSetGroup(link Link, group int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *Handle) LinkSetGSOMaxSize(link Link, maxSize int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *Handle) LinkSetGROMaxSize(link Link, maxSize int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *Handle) LinkSetGSOIPv4MaxSize(link Link, maxSize int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *Handle) LinkSetGROIPv4MaxSize(link Link, maxSize int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
@ -243,6 +263,10 @@ func (h *Handle) RouteAppend(route *Route) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *Handle) RouteChange(route *Route) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *Handle) RouteDel(route *Route) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
9
vendor/github.com/vishvananda/netlink/inet_diag.go
generated
vendored
9
vendor/github.com/vishvananda/netlink/inet_diag.go
generated
vendored
@ -21,6 +21,10 @@ const (
|
||||
INET_DIAG_BBRINFO
|
||||
INET_DIAG_CLASS_ID
|
||||
INET_DIAG_MD5SIG
|
||||
INET_DIAG_ULP_INFO
|
||||
INET_DIAG_SK_BPF_STORAGES
|
||||
INET_DIAG_CGROUP_ID
|
||||
INET_DIAG_SOCKOPT
|
||||
INET_DIAG_MAX
|
||||
)
|
||||
|
||||
@ -29,3 +33,8 @@ type InetDiagTCPInfoResp struct {
|
||||
TCPInfo *TCPInfo
|
||||
TCPBBRInfo *TCPBBRInfo
|
||||
}
|
||||
|
||||
type InetDiagUDPInfoResp struct {
|
||||
InetDiagMsg *Socket
|
||||
Memory *MemInfo
|
||||
}
|
||||
|
115
vendor/github.com/vishvananda/netlink/ipset_linux.go
generated
vendored
115
vendor/github.com/vishvananda/netlink/ipset_linux.go
generated
vendored
@ -67,11 +67,13 @@ type IpsetCreateOptions struct {
|
||||
Comments bool
|
||||
Skbinfo bool
|
||||
|
||||
Revision uint8
|
||||
IPFrom net.IP
|
||||
IPTo net.IP
|
||||
PortFrom uint16
|
||||
PortTo uint16
|
||||
Family uint8
|
||||
Revision uint8
|
||||
IPFrom net.IP
|
||||
IPTo net.IP
|
||||
PortFrom uint16
|
||||
PortTo uint16
|
||||
MaxElements uint32
|
||||
}
|
||||
|
||||
// IpsetProtocol returns the ipset protocol version from the kernel
|
||||
@ -94,6 +96,11 @@ func IpsetFlush(setname string) error {
|
||||
return pkgHandle.IpsetFlush(setname)
|
||||
}
|
||||
|
||||
// IpsetSwap swaps two ipsets.
|
||||
func IpsetSwap(setname, othersetname string) error {
|
||||
return pkgHandle.IpsetSwap(setname, othersetname)
|
||||
}
|
||||
|
||||
// IpsetList dumps an specific ipset.
|
||||
func IpsetList(setname string) (*IPSetResult, error) {
|
||||
return pkgHandle.IpsetList(setname)
|
||||
@ -114,6 +121,11 @@ func IpsetDel(setname string, entry *IPSetEntry) error {
|
||||
return pkgHandle.IpsetDel(setname, entry)
|
||||
}
|
||||
|
||||
// IpsetTest tests whether an entry is in a set or not.
|
||||
func IpsetTest(setname string, entry *IPSetEntry) (bool, error) {
|
||||
return pkgHandle.IpsetTest(setname, entry)
|
||||
}
|
||||
|
||||
func (h *Handle) IpsetProtocol() (protocol uint8, minVersion uint8, err error) {
|
||||
req := h.newIpsetRequest(nl.IPSET_CMD_PROTOCOL)
|
||||
msgs, err := req.Execute(unix.NETLINK_NETFILTER, 0)
|
||||
@ -153,11 +165,18 @@ func (h *Handle) IpsetCreate(setname, typename string, options IpsetCreateOption
|
||||
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_PORT_FROM|int(nl.NLA_F_NET_BYTEORDER), buf[:2]))
|
||||
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_PORT_TO|int(nl.NLA_F_NET_BYTEORDER), buf[2:]))
|
||||
default:
|
||||
family = unix.AF_INET
|
||||
family = options.Family
|
||||
if family == 0 {
|
||||
family = unix.AF_INET
|
||||
}
|
||||
}
|
||||
|
||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_FAMILY, nl.Uint8Attr(family)))
|
||||
|
||||
if options.MaxElements != 0 {
|
||||
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_MAXELEM | nl.NLA_F_NET_BYTEORDER, Value: options.MaxElements})
|
||||
}
|
||||
|
||||
if timeout := options.Timeout; timeout != nil {
|
||||
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_TIMEOUT | nl.NLA_F_NET_BYTEORDER, Value: *timeout})
|
||||
}
|
||||
@ -197,6 +216,14 @@ func (h *Handle) IpsetFlush(setname string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *Handle) IpsetSwap(setname, othersetname string) error {
|
||||
req := h.newIpsetRequest(nl.IPSET_CMD_SWAP)
|
||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
|
||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_TYPENAME, nl.ZeroTerminated(othersetname)))
|
||||
_, err := ipsetExecute(req)
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *Handle) IpsetList(name string) (*IPSetResult, error) {
|
||||
req := h.newIpsetRequest(nl.IPSET_CMD_LIST)
|
||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(name)))
|
||||
@ -236,18 +263,23 @@ func (h *Handle) IpsetDel(setname string, entry *IPSetEntry) error {
|
||||
return h.ipsetAddDel(nl.IPSET_CMD_DEL, setname, entry)
|
||||
}
|
||||
|
||||
func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error {
|
||||
req := h.newIpsetRequest(nlCmd)
|
||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
|
||||
|
||||
if entry.Comment != "" {
|
||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_COMMENT, nl.ZeroTerminated(entry.Comment)))
|
||||
func encodeIP(ip net.IP) (*nl.RtAttr, error) {
|
||||
typ := int(nl.NLA_F_NET_BYTEORDER)
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
typ |= nl.IPSET_ATTR_IPADDR_IPV4
|
||||
ip = ip4
|
||||
} else {
|
||||
typ |= nl.IPSET_ATTR_IPADDR_IPV6
|
||||
}
|
||||
|
||||
return nl.NewRtAttr(typ, ip), nil
|
||||
}
|
||||
|
||||
func buildEntryData(entry *IPSetEntry) (*nl.RtAttr, error) {
|
||||
data := nl.NewRtAttr(nl.IPSET_ATTR_DATA|int(nl.NLA_F_NESTED), nil)
|
||||
|
||||
if !entry.Replace {
|
||||
req.Flags |= unix.NLM_F_EXCL
|
||||
if entry.Comment != "" {
|
||||
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_COMMENT, nl.ZeroTerminated(entry.Comment)))
|
||||
}
|
||||
|
||||
if entry.Timeout != nil {
|
||||
@ -255,7 +287,10 @@ func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error
|
||||
}
|
||||
|
||||
if entry.IP != nil {
|
||||
nestedData := nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NET_BYTEORDER), entry.IP)
|
||||
nestedData, err := encodeIP(entry.IP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NESTED), nestedData.Serialize()))
|
||||
}
|
||||
|
||||
@ -268,7 +303,10 @@ func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error
|
||||
}
|
||||
|
||||
if entry.IP2 != nil {
|
||||
nestedData := nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NET_BYTEORDER), entry.IP2)
|
||||
nestedData, err := encodeIP(entry.IP2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_IP2|int(nl.NLA_F_NESTED), nestedData.Serialize()))
|
||||
}
|
||||
|
||||
@ -295,14 +333,53 @@ func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error
|
||||
if entry.Mark != nil {
|
||||
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_MARK | nl.NLA_F_NET_BYTEORDER, Value: *entry.Mark})
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error {
|
||||
req := h.newIpsetRequest(nlCmd)
|
||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
|
||||
|
||||
if !entry.Replace {
|
||||
req.Flags |= unix.NLM_F_EXCL
|
||||
}
|
||||
|
||||
data, err := buildEntryData(entry)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_LINENO | nl.NLA_F_NET_BYTEORDER, Value: 0})
|
||||
req.AddData(data)
|
||||
|
||||
_, err := ipsetExecute(req)
|
||||
_, err = ipsetExecute(req)
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *Handle) IpsetTest(setname string, entry *IPSetEntry) (bool, error) {
|
||||
req := h.newIpsetRequest(nl.IPSET_CMD_TEST)
|
||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
|
||||
|
||||
if !entry.Replace {
|
||||
req.Flags |= unix.NLM_F_EXCL
|
||||
}
|
||||
|
||||
data, err := buildEntryData(entry)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
req.AddData(data)
|
||||
|
||||
_, err = ipsetExecute(req)
|
||||
if err != nil {
|
||||
if err == nl.IPSetError(nl.IPSET_ERR_EXIST) {
|
||||
// not exist
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (h *Handle) newIpsetRequest(cmd int) *nl.NetlinkRequest {
|
||||
req := h.newNetlinkRequest(cmd|(unix.NFNL_SUBSYS_IPSET<<8), nl.GetIpsetFlags(cmd))
|
||||
|
||||
@ -466,7 +543,7 @@ func parseIPSetEntry(data []byte) (entry IPSetEntry) {
|
||||
case nl.IPSET_ATTR_IP | nl.NLA_F_NESTED:
|
||||
for attr := range nl.ParseAttributes(attr.Value) {
|
||||
switch attr.Type {
|
||||
case nl.IPSET_ATTR_IP:
|
||||
case nl.IPSET_ATTR_IPADDR_IPV4, nl.IPSET_ATTR_IPADDR_IPV6:
|
||||
entry.IP = net.IP(attr.Value)
|
||||
default:
|
||||
log.Printf("unknown nested ADT attribute from kernel: %+v", attr)
|
||||
@ -475,7 +552,7 @@ func parseIPSetEntry(data []byte) (entry IPSetEntry) {
|
||||
case nl.IPSET_ATTR_IP2 | nl.NLA_F_NESTED:
|
||||
for attr := range nl.ParseAttributes(attr.Value) {
|
||||
switch attr.Type {
|
||||
case nl.IPSET_ATTR_IP:
|
||||
case nl.IPSET_ATTR_IPADDR_IPV4, nl.IPSET_ATTR_IPADDR_IPV6:
|
||||
entry.IP2 = net.IP(attr.Value)
|
||||
default:
|
||||
log.Printf("unknown nested ADT attribute from kernel: %+v", attr)
|
||||
|
146
vendor/github.com/vishvananda/netlink/link.go
generated
vendored
146
vendor/github.com/vishvananda/netlink/link.go
generated
vendored
@ -22,34 +22,41 @@ type (
|
||||
|
||||
// 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
|
||||
Allmulti int
|
||||
Multi int
|
||||
Xdp *LinkXdp
|
||||
EncapType string
|
||||
Protinfo *Protinfo
|
||||
OperState LinkOperState
|
||||
PhysSwitchID int
|
||||
NetNsID int
|
||||
NumTxQueues int
|
||||
NumRxQueues int
|
||||
GSOMaxSize uint32
|
||||
GSOMaxSegs uint32
|
||||
Vfs []VfInfo // virtual functions available on link
|
||||
Group uint32
|
||||
Slave LinkSlave
|
||||
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
|
||||
AltNames []string
|
||||
Statistics *LinkStatistics
|
||||
Promisc int
|
||||
Allmulti int
|
||||
Multi int
|
||||
Xdp *LinkXdp
|
||||
EncapType string
|
||||
Protinfo *Protinfo
|
||||
OperState LinkOperState
|
||||
PhysSwitchID int
|
||||
NetNsID int
|
||||
NumTxQueues int
|
||||
NumRxQueues int
|
||||
TSOMaxSegs uint32
|
||||
TSOMaxSize uint32
|
||||
GSOMaxSegs uint32
|
||||
GSOMaxSize uint32
|
||||
GROMaxSize uint32
|
||||
GSOIPv4MaxSize uint32
|
||||
GROIPv4MaxSize uint32
|
||||
Vfs []VfInfo // virtual functions available on link
|
||||
Group uint32
|
||||
PermHWAddr net.HardwareAddr
|
||||
Slave LinkSlave
|
||||
}
|
||||
|
||||
// LinkSlave represents a slave device.
|
||||
@ -63,6 +70,7 @@ type VfInfo struct {
|
||||
Mac net.HardwareAddr
|
||||
Vlan int
|
||||
Qos int
|
||||
VlanProto int
|
||||
TxRate int // IFLA_VF_TX_RATE Max TxRate
|
||||
Spoofchk bool
|
||||
LinkState uint32
|
||||
@ -265,6 +273,8 @@ type Bridge struct {
|
||||
AgeingTime *uint32
|
||||
HelloTime *uint32
|
||||
VlanFiltering *bool
|
||||
VlanDefaultPVID *uint16
|
||||
GroupFwdMask *uint16
|
||||
}
|
||||
|
||||
func (bridge *Bridge) Attrs() *LinkAttrs {
|
||||
@ -308,6 +318,9 @@ type Macvlan struct {
|
||||
|
||||
// MACAddrs is only populated for Macvlan SOURCE links
|
||||
MACAddrs []net.HardwareAddr
|
||||
|
||||
BCQueueLen uint32
|
||||
UsedBCQueueLen uint32
|
||||
}
|
||||
|
||||
func (macvlan *Macvlan) Attrs() *LinkAttrs {
|
||||
@ -350,6 +363,46 @@ func (tuntap *Tuntap) Type() string {
|
||||
return "tuntap"
|
||||
}
|
||||
|
||||
type NetkitMode uint32
|
||||
|
||||
const (
|
||||
NETKIT_MODE_L2 NetkitMode = iota
|
||||
NETKIT_MODE_L3
|
||||
)
|
||||
|
||||
type NetkitPolicy int
|
||||
|
||||
const (
|
||||
NETKIT_POLICY_FORWARD NetkitPolicy = 0
|
||||
NETKIT_POLICY_BLACKHOLE NetkitPolicy = 2
|
||||
)
|
||||
|
||||
func (n *Netkit) IsPrimary() bool {
|
||||
return n.isPrimary
|
||||
}
|
||||
|
||||
// SetPeerAttrs will not take effect if trying to modify an existing netkit device
|
||||
func (n *Netkit) SetPeerAttrs(Attrs *LinkAttrs) {
|
||||
n.peerLinkAttrs = *Attrs
|
||||
}
|
||||
|
||||
type Netkit struct {
|
||||
LinkAttrs
|
||||
Mode NetkitMode
|
||||
Policy NetkitPolicy
|
||||
PeerPolicy NetkitPolicy
|
||||
isPrimary bool
|
||||
peerLinkAttrs LinkAttrs
|
||||
}
|
||||
|
||||
func (n *Netkit) Attrs() *LinkAttrs {
|
||||
return &n.LinkAttrs
|
||||
}
|
||||
|
||||
func (n *Netkit) Type() string {
|
||||
return "netkit"
|
||||
}
|
||||
|
||||
// Veth devices must specify PeerName on create
|
||||
type Veth struct {
|
||||
LinkAttrs
|
||||
@ -703,6 +756,7 @@ const (
|
||||
BOND_XMIT_HASH_POLICY_LAYER2_3
|
||||
BOND_XMIT_HASH_POLICY_ENCAP2_3
|
||||
BOND_XMIT_HASH_POLICY_ENCAP3_4
|
||||
BOND_XMIT_HASH_POLICY_VLAN_SRCMAC
|
||||
BOND_XMIT_HASH_POLICY_UNKNOWN
|
||||
)
|
||||
|
||||
@ -712,6 +766,7 @@ var bondXmitHashPolicyToString = map[BondXmitHashPolicy]string{
|
||||
BOND_XMIT_HASH_POLICY_LAYER2_3: "layer2+3",
|
||||
BOND_XMIT_HASH_POLICY_ENCAP2_3: "encap2+3",
|
||||
BOND_XMIT_HASH_POLICY_ENCAP3_4: "encap3+4",
|
||||
BOND_XMIT_HASH_POLICY_VLAN_SRCMAC: "vlan+srcmac",
|
||||
}
|
||||
var StringToBondXmitHashPolicyMap = map[string]BondXmitHashPolicy{
|
||||
"layer2": BOND_XMIT_HASH_POLICY_LAYER2,
|
||||
@ -719,6 +774,7 @@ var StringToBondXmitHashPolicyMap = map[string]BondXmitHashPolicy{
|
||||
"layer2+3": BOND_XMIT_HASH_POLICY_LAYER2_3,
|
||||
"encap2+3": BOND_XMIT_HASH_POLICY_ENCAP2_3,
|
||||
"encap3+4": BOND_XMIT_HASH_POLICY_ENCAP3_4,
|
||||
"vlan+srcmac": BOND_XMIT_HASH_POLICY_VLAN_SRCMAC,
|
||||
}
|
||||
|
||||
// BondLacpRate type
|
||||
@ -974,16 +1030,18 @@ func (v *VrfSlave) SlaveType() string {
|
||||
// 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
|
||||
ID uint32 // vni
|
||||
Remote net.IP
|
||||
Ttl uint8
|
||||
Tos uint8
|
||||
Dport uint16
|
||||
UdpCsum uint8
|
||||
UdpZeroCsum6Tx uint8
|
||||
UdpZeroCsum6Rx uint8
|
||||
Link uint32
|
||||
FlowBased bool
|
||||
InnerProtoInherit bool
|
||||
Df GeneveDf
|
||||
}
|
||||
|
||||
func (geneve *Geneve) Attrs() *LinkAttrs {
|
||||
@ -994,6 +1052,15 @@ func (geneve *Geneve) Type() string {
|
||||
return "geneve"
|
||||
}
|
||||
|
||||
type GeneveDf uint8
|
||||
|
||||
const (
|
||||
GENEVE_DF_UNSET GeneveDf = iota
|
||||
GENEVE_DF_SET
|
||||
GENEVE_DF_INHERIT
|
||||
GENEVE_DF_MAX
|
||||
)
|
||||
|
||||
// Gretap devices must specify LocalIP and RemoteIP on create
|
||||
type Gretap struct {
|
||||
LinkAttrs
|
||||
@ -1064,6 +1131,7 @@ type Ip6tnl struct {
|
||||
EncapFlags uint16
|
||||
EncapSport uint16
|
||||
EncapDport uint16
|
||||
FlowBased bool
|
||||
}
|
||||
|
||||
func (ip6tnl *Ip6tnl) Attrs() *LinkAttrs {
|
||||
@ -1165,6 +1233,7 @@ type Gretun struct {
|
||||
EncapFlags uint16
|
||||
EncapSport uint16
|
||||
EncapDport uint16
|
||||
FlowBased bool
|
||||
}
|
||||
|
||||
func (gretun *Gretun) Attrs() *LinkAttrs {
|
||||
@ -1208,6 +1277,7 @@ func (gtp *GTP) Type() string {
|
||||
}
|
||||
|
||||
// Virtual XFRM Interfaces
|
||||
//
|
||||
// Named "xfrmi" to prevent confusion with XFRM objects
|
||||
type Xfrmi struct {
|
||||
LinkAttrs
|
||||
|
584
vendor/github.com/vishvananda/netlink/link_linux.go
generated
vendored
584
vendor/github.com/vishvananda/netlink/link_linux.go
generated
vendored
@ -345,6 +345,16 @@ func (h *Handle) BridgeSetVlanFiltering(link Link, on bool) error {
|
||||
return h.linkModify(bridge, unix.NLM_F_ACK)
|
||||
}
|
||||
|
||||
func BridgeSetVlanDefaultPVID(link Link, pvid uint16) error {
|
||||
return pkgHandle.BridgeSetVlanDefaultPVID(link, pvid)
|
||||
}
|
||||
|
||||
func (h *Handle) BridgeSetVlanDefaultPVID(link Link, pvid uint16) error {
|
||||
bridge := link.(*Bridge)
|
||||
bridge.VlanDefaultPVID = &pvid
|
||||
return h.linkModify(bridge, unix.NLM_F_ACK)
|
||||
}
|
||||
|
||||
func SetPromiscOn(link Link) error {
|
||||
return pkgHandle.SetPromiscOn(link)
|
||||
}
|
||||
@ -487,6 +497,58 @@ func (h *Handle) LinkSetAlias(link Link, name string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkAddAltName adds a new alternative name for the link device.
|
||||
// Equivalent to: `ip link property add $link altname $name`
|
||||
func LinkAddAltName(link Link, name string) error {
|
||||
return pkgHandle.LinkAddAltName(link, name)
|
||||
}
|
||||
|
||||
// LinkAddAltName adds a new alternative name for the link device.
|
||||
// Equivalent to: `ip link property add $link altname $name`
|
||||
func (h *Handle) LinkAddAltName(link Link, name string) error {
|
||||
base := link.Attrs()
|
||||
h.ensureIndex(base)
|
||||
req := h.newNetlinkRequest(unix.RTM_NEWLINKPROP, unix.NLM_F_ACK)
|
||||
|
||||
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
||||
msg.Index = int32(base.Index)
|
||||
req.AddData(msg)
|
||||
|
||||
data := nl.NewRtAttr(unix.IFLA_PROP_LIST|unix.NLA_F_NESTED, nil)
|
||||
data.AddRtAttr(unix.IFLA_ALT_IFNAME, []byte(name))
|
||||
|
||||
req.AddData(data)
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkDelAltName delete an alternative name for the link device.
|
||||
// Equivalent to: `ip link property del $link altname $name`
|
||||
func LinkDelAltName(link Link, name string) error {
|
||||
return pkgHandle.LinkDelAltName(link, name)
|
||||
}
|
||||
|
||||
// LinkDelAltName delete an alternative name for the link device.
|
||||
// Equivalent to: `ip link property del $link altname $name`
|
||||
func (h *Handle) LinkDelAltName(link Link, name string) error {
|
||||
base := link.Attrs()
|
||||
h.ensureIndex(base)
|
||||
req := h.newNetlinkRequest(unix.RTM_DELLINKPROP, unix.NLM_F_ACK)
|
||||
|
||||
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
||||
msg.Index = int32(base.Index)
|
||||
req.AddData(msg)
|
||||
|
||||
data := nl.NewRtAttr(unix.IFLA_PROP_LIST|unix.NLA_F_NESTED, nil)
|
||||
data.AddRtAttr(unix.IFLA_ALT_IFNAME, []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 {
|
||||
@ -602,6 +664,43 @@ func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkSetVfVlanQosProto sets the vlan, qos and protocol of a vf for the link.
|
||||
// Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos proto $proto`
|
||||
func LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error {
|
||||
return pkgHandle.LinkSetVfVlanQosProto(link, vf, vlan, qos, proto)
|
||||
}
|
||||
|
||||
// LinkSetVfVlanQosProto sets the vlan, qos and protocol of a vf for the link.
|
||||
// Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos proto $proto`
|
||||
func (h *Handle) LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto 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)
|
||||
vfInfo := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
|
||||
vfVlanList := vfInfo.AddRtAttr(nl.IFLA_VF_VLAN_LIST, nil)
|
||||
|
||||
vfmsg := nl.VfVlanInfo{
|
||||
VfVlan: nl.VfVlan{
|
||||
Vf: uint32(vf),
|
||||
Vlan: uint32(vlan),
|
||||
Qos: uint32(qos),
|
||||
},
|
||||
VlanProto: (uint16(proto)>>8)&0xFF | (uint16(proto)&0xFF)<<8,
|
||||
}
|
||||
|
||||
vfVlanList.AddRtAttr(nl.IFLA_VF_VLAN_INFO, 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 {
|
||||
@ -946,6 +1045,141 @@ func LinkSetXdpFdWithFlags(link Link, fd, flags int) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkSetGSOMaxSegs sets the GSO maximum segment count of the link device.
|
||||
// Equivalent to: `ip link set $link gso_max_segs $maxSegs`
|
||||
func LinkSetGSOMaxSegs(link Link, maxSegs int) error {
|
||||
return pkgHandle.LinkSetGSOMaxSegs(link, maxSegs)
|
||||
}
|
||||
|
||||
// LinkSetGSOMaxSegs sets the GSO maximum segment count of the link device.
|
||||
// Equivalent to: `ip link set $link gso_max_segs $maxSegs`
|
||||
func (h *Handle) LinkSetGSOMaxSegs(link Link, maxSize 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(maxSize))
|
||||
|
||||
data := nl.NewRtAttr(unix.IFLA_GSO_MAX_SEGS, b)
|
||||
req.AddData(data)
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkSetGSOMaxSize sets the IPv6 GSO maximum size of the link device.
|
||||
// Equivalent to: `ip link set $link gso_max_size $maxSize`
|
||||
func LinkSetGSOMaxSize(link Link, maxSize int) error {
|
||||
return pkgHandle.LinkSetGSOMaxSize(link, maxSize)
|
||||
}
|
||||
|
||||
// LinkSetGSOMaxSize sets the IPv6 GSO maximum size of the link device.
|
||||
// Equivalent to: `ip link set $link gso_max_size $maxSize`
|
||||
func (h *Handle) LinkSetGSOMaxSize(link Link, maxSize 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(maxSize))
|
||||
|
||||
data := nl.NewRtAttr(unix.IFLA_GSO_MAX_SIZE, b)
|
||||
req.AddData(data)
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkSetGROMaxSize sets the IPv6 GRO maximum size of the link device.
|
||||
// Equivalent to: `ip link set $link gro_max_size $maxSize`
|
||||
func LinkSetGROMaxSize(link Link, maxSize int) error {
|
||||
return pkgHandle.LinkSetGROMaxSize(link, maxSize)
|
||||
}
|
||||
|
||||
// LinkSetGROMaxSize sets the IPv6 GRO maximum size of the link device.
|
||||
// Equivalent to: `ip link set $link gro_max_size $maxSize`
|
||||
func (h *Handle) LinkSetGROMaxSize(link Link, maxSize 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(maxSize))
|
||||
|
||||
data := nl.NewRtAttr(unix.IFLA_GRO_MAX_SIZE, b)
|
||||
req.AddData(data)
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkSetGSOIPv4MaxSize sets the IPv4 GSO maximum size of the link device.
|
||||
// Equivalent to: `ip link set $link gso_ipv4_max_size $maxSize`
|
||||
func LinkSetGSOIPv4MaxSize(link Link, maxSize int) error {
|
||||
return pkgHandle.LinkSetGSOIPv4MaxSize(link, maxSize)
|
||||
}
|
||||
|
||||
// LinkSetGSOIPv4MaxSize sets the IPv4 GSO maximum size of the link device.
|
||||
// Equivalent to: `ip link set $link gso_ipv4_max_size $maxSize`
|
||||
func (h *Handle) LinkSetGSOIPv4MaxSize(link Link, maxSize 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(maxSize))
|
||||
|
||||
data := nl.NewRtAttr(unix.IFLA_GSO_IPV4_MAX_SIZE, b)
|
||||
req.AddData(data)
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkSetGROIPv4MaxSize sets the IPv4 GRO maximum size of the link device.
|
||||
// Equivalent to: `ip link set $link gro_ipv4_max_size $maxSize`
|
||||
func LinkSetGROIPv4MaxSize(link Link, maxSize int) error {
|
||||
return pkgHandle.LinkSetGROIPv4MaxSize(link, maxSize)
|
||||
}
|
||||
|
||||
// LinkSetGROIPv4MaxSize sets the IPv4 GRO maximum size of the link device.
|
||||
// Equivalent to: `ip link set $link gro_ipv4_max_size $maxSize`
|
||||
func (h *Handle) LinkSetGROIPv4MaxSize(link Link, maxSize 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(maxSize))
|
||||
|
||||
data := nl.NewRtAttr(unix.IFLA_GRO_IPV4_MAX_SIZE, b)
|
||||
req.AddData(data)
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
func boolAttr(val bool) []byte {
|
||||
var v uint8
|
||||
if val {
|
||||
@ -1401,6 +1635,21 @@ func (h *Handle) linkModify(link Link, flags int) error {
|
||||
req.AddData(gsoAttr)
|
||||
}
|
||||
|
||||
if base.GROMaxSize > 0 {
|
||||
groAttr := nl.NewRtAttr(unix.IFLA_GRO_MAX_SIZE, nl.Uint32Attr(base.GROMaxSize))
|
||||
req.AddData(groAttr)
|
||||
}
|
||||
|
||||
if base.GSOIPv4MaxSize > 0 {
|
||||
gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_IPV4_MAX_SIZE, nl.Uint32Attr(base.GSOIPv4MaxSize))
|
||||
req.AddData(gsoAttr)
|
||||
}
|
||||
|
||||
if base.GROIPv4MaxSize > 0 {
|
||||
groAttr := nl.NewRtAttr(unix.IFLA_GRO_IPV4_MAX_SIZE, nl.Uint32Attr(base.GROIPv4MaxSize))
|
||||
req.AddData(groAttr)
|
||||
}
|
||||
|
||||
if base.Group > 0 {
|
||||
groupAttr := nl.NewRtAttr(unix.IFLA_GROUP, nl.Uint32Attr(base.Group))
|
||||
req.AddData(groupAttr)
|
||||
@ -1437,6 +1686,10 @@ func (h *Handle) linkModify(link Link, flags int) error {
|
||||
if link.VlanProtocol != VLAN_PROTOCOL_UNKNOWN {
|
||||
data.AddRtAttr(nl.IFLA_VLAN_PROTOCOL, htons(uint16(link.VlanProtocol)))
|
||||
}
|
||||
case *Netkit:
|
||||
if err := addNetkitAttrs(link, linkInfo, flags); err != nil {
|
||||
return err
|
||||
}
|
||||
case *Veth:
|
||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||
peer := data.AddRtAttr(nl.VETH_INFO_PEER, nil)
|
||||
@ -1480,15 +1733,9 @@ func (h *Handle) linkModify(link Link, flags int) error {
|
||||
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]))
|
||||
}
|
||||
addMacvlanAttrs(link, linkInfo)
|
||||
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]))
|
||||
}
|
||||
addMacvtapAttrs(link, linkInfo)
|
||||
case *Geneve:
|
||||
addGeneveAttrs(link, linkInfo)
|
||||
case *Gretap:
|
||||
@ -1569,6 +1816,13 @@ func (h *Handle) linkByNameDump(name string) (Link, error) {
|
||||
if link.Attrs().Name == name {
|
||||
return link, nil
|
||||
}
|
||||
|
||||
// support finding interfaces also via altnames
|
||||
for _, altName := range link.Attrs().AltNames {
|
||||
if altName == name {
|
||||
return link, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, LinkNotFoundError{fmt.Errorf("Link %s not found", name)}
|
||||
}
|
||||
@ -1607,6 +1861,9 @@ func (h *Handle) LinkByName(name string) (Link, error) {
|
||||
req.AddData(attr)
|
||||
|
||||
nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(name))
|
||||
if len(name) > 15 {
|
||||
nameData = nl.NewRtAttr(unix.IFLA_ALT_IFNAME, nl.ZeroTerminated(name))
|
||||
}
|
||||
req.AddData(nameData)
|
||||
|
||||
link, err := execGetLink(req)
|
||||
@ -1712,9 +1969,6 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
||||
base.Flags = linkFlags(msg.Flags)
|
||||
base.EncapType = msg.EncapType()
|
||||
base.NetNsID = -1
|
||||
if msg.Flags&unix.IFF_PROMISC != 0 {
|
||||
base.Promisc = 1
|
||||
}
|
||||
if msg.Flags&unix.IFF_ALLMULTI != 0 {
|
||||
base.Allmulti = 1
|
||||
}
|
||||
@ -1750,6 +2004,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
||||
link = &Bridge{}
|
||||
case "vlan":
|
||||
link = &Vlan{}
|
||||
case "netkit":
|
||||
link = &Netkit{}
|
||||
case "veth":
|
||||
link = &Veth{}
|
||||
case "wireguard":
|
||||
@ -1807,6 +2063,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
||||
return nil, err
|
||||
}
|
||||
switch linkType {
|
||||
case "netkit":
|
||||
parseNetkitData(link, data)
|
||||
case "vlan":
|
||||
parseVlanData(link, data)
|
||||
case "vxlan":
|
||||
@ -1897,6 +2155,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
||||
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_PROMISCUITY:
|
||||
base.Promisc = int(native.Uint32(attr.Value[0:4]))
|
||||
case unix.IFLA_LINK:
|
||||
base.ParentIndex = int(native.Uint32(attr.Value[0:4]))
|
||||
case unix.IFLA_MASTER:
|
||||
@ -1931,16 +2191,38 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
||||
protinfo := parseProtinfo(attrs)
|
||||
base.Protinfo = &protinfo
|
||||
}
|
||||
case unix.IFLA_PROP_LIST | unix.NLA_F_NESTED:
|
||||
attrs, err := nl.ParseRouteAttr(attr.Value[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
base.AltNames = []string{}
|
||||
for _, attr := range attrs {
|
||||
if attr.Attr.Type == unix.IFLA_ALT_IFNAME {
|
||||
base.AltNames = append(base.AltNames, nl.BytesToString(attr.Value))
|
||||
}
|
||||
}
|
||||
case unix.IFLA_OPERSTATE:
|
||||
base.OperState = LinkOperState(uint8(attr.Value[0]))
|
||||
case unix.IFLA_PHYS_SWITCH_ID:
|
||||
base.PhysSwitchID = int(native.Uint32(attr.Value[0:4]))
|
||||
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_TSO_MAX_SEGS:
|
||||
base.TSOMaxSegs = native.Uint32(attr.Value[0:4])
|
||||
case unix.IFLA_TSO_MAX_SIZE:
|
||||
base.TSOMaxSize = native.Uint32(attr.Value[0:4])
|
||||
case unix.IFLA_GSO_MAX_SEGS:
|
||||
base.GSOMaxSegs = native.Uint32(attr.Value[0:4])
|
||||
case unix.IFLA_GSO_MAX_SIZE:
|
||||
base.GSOMaxSize = native.Uint32(attr.Value[0:4])
|
||||
case unix.IFLA_GRO_MAX_SIZE:
|
||||
base.GROMaxSize = native.Uint32(attr.Value[0:4])
|
||||
case unix.IFLA_GSO_IPV4_MAX_SIZE:
|
||||
base.GSOIPv4MaxSize = native.Uint32(attr.Value[0:4])
|
||||
case unix.IFLA_GRO_IPV4_MAX_SIZE:
|
||||
base.GROIPv4MaxSize = native.Uint32(attr.Value[0:4])
|
||||
case unix.IFLA_VFINFO_LIST:
|
||||
data, err := nl.ParseRouteAttr(attr.Value)
|
||||
if err != nil {
|
||||
@ -1957,6 +2239,13 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
||||
base.NumRxQueues = int(native.Uint32(attr.Value[0:4]))
|
||||
case unix.IFLA_GROUP:
|
||||
base.Group = native.Uint32(attr.Value[0:4])
|
||||
case unix.IFLA_PERM_ADDRESS:
|
||||
for _, b := range attr.Value {
|
||||
if b != 0 {
|
||||
base.PermHWAddr = attr.Value[:]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2069,21 +2358,24 @@ type LinkUpdate struct {
|
||||
// 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)
|
||||
return linkSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0, 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)
|
||||
return linkSubscribeAt(ns, netns.None(), ch, done, nil, false, 0, nil, false)
|
||||
}
|
||||
|
||||
// LinkSubscribeOptions contains a set of options to use with
|
||||
// LinkSubscribeWithOptions.
|
||||
type LinkSubscribeOptions struct {
|
||||
Namespace *netns.NsHandle
|
||||
ErrorCallback func(error)
|
||||
ListExisting bool
|
||||
Namespace *netns.NsHandle
|
||||
ErrorCallback func(error)
|
||||
ListExisting bool
|
||||
ReceiveBufferSize int
|
||||
ReceiveBufferForceSize bool
|
||||
ReceiveTimeout *unix.Timeval
|
||||
}
|
||||
|
||||
// LinkSubscribeWithOptions work like LinkSubscribe but enable to
|
||||
@ -2094,14 +2386,27 @@ func LinkSubscribeWithOptions(ch chan<- LinkUpdate, done <-chan struct{}, option
|
||||
none := netns.None()
|
||||
options.Namespace = &none
|
||||
}
|
||||
return linkSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting)
|
||||
return linkSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting,
|
||||
options.ReceiveBufferSize, options.ReceiveTimeout, options.ReceiveBufferForceSize)
|
||||
}
|
||||
|
||||
func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error {
|
||||
func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}, cberr func(error), listExisting bool,
|
||||
rcvbuf int, rcvTimeout *unix.Timeval, rcvbufForce bool) error {
|
||||
s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_LINK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rcvTimeout != nil {
|
||||
if err := s.SetReceiveTimeout(rcvTimeout); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if rcvbuf != 0 {
|
||||
err = s.SetReceiveBufferSize(rcvbuf, rcvbufForce)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if done != nil {
|
||||
go func() {
|
||||
<-done
|
||||
@ -2182,6 +2487,16 @@ func (h *Handle) LinkSetGuard(link Link, mode bool) error {
|
||||
return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_GUARD)
|
||||
}
|
||||
|
||||
// LinkSetBRSlaveGroupFwdMask set the group_fwd_mask of a bridge slave interface
|
||||
func LinkSetBRSlaveGroupFwdMask(link Link, mask uint16) error {
|
||||
return pkgHandle.LinkSetBRSlaveGroupFwdMask(link, mask)
|
||||
}
|
||||
|
||||
// LinkSetBRSlaveGroupFwdMask set the group_fwd_mask of a bridge slave interface
|
||||
func (h *Handle) LinkSetBRSlaveGroupFwdMask(link Link, mask uint16) error {
|
||||
return h.setProtinfoAttrRawVal(link, nl.Uint16Attr(mask), nl.IFLA_BRPORT_GROUP_FWD_MASK)
|
||||
}
|
||||
|
||||
func LinkSetFastLeave(link Link, mode bool) error {
|
||||
return pkgHandle.LinkSetFastLeave(link, mode)
|
||||
}
|
||||
@ -2214,6 +2529,14 @@ func (h *Handle) LinkSetFlood(link Link, mode bool) error {
|
||||
return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_UNICAST_FLOOD)
|
||||
}
|
||||
|
||||
func LinkSetIsolated(link Link, mode bool) error {
|
||||
return pkgHandle.LinkSetIsolated(link, mode)
|
||||
}
|
||||
|
||||
func (h *Handle) LinkSetIsolated(link Link, mode bool) error {
|
||||
return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_ISOLATED)
|
||||
}
|
||||
|
||||
func LinkSetBrProxyArp(link Link, mode bool) error {
|
||||
return pkgHandle.LinkSetBrProxyArp(link, mode)
|
||||
}
|
||||
@ -2230,7 +2553,15 @@ 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 {
|
||||
func LinkSetBrNeighSuppress(link Link, mode bool) error {
|
||||
return pkgHandle.LinkSetBrNeighSuppress(link, mode)
|
||||
}
|
||||
|
||||
func (h *Handle) LinkSetBrNeighSuppress(link Link, mode bool) error {
|
||||
return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_NEIGH_SUPPRESS)
|
||||
}
|
||||
|
||||
func (h *Handle) setProtinfoAttrRawVal(link Link, val []byte, attr int) error {
|
||||
base := link.Attrs()
|
||||
h.ensureIndex(base)
|
||||
req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
|
||||
@ -2240,7 +2571,7 @@ func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
|
||||
req.AddData(msg)
|
||||
|
||||
br := nl.NewRtAttr(unix.IFLA_PROTINFO|unix.NLA_F_NESTED, nil)
|
||||
br.AddRtAttr(attr, boolToByte(mode))
|
||||
br.AddRtAttr(attr, val)
|
||||
req.AddData(br)
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
if err != nil {
|
||||
@ -2248,6 +2579,9 @@ func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
|
||||
return h.setProtinfoAttrRawVal(link, boolToByte(mode), attr)
|
||||
}
|
||||
|
||||
// LinkSetTxQLen sets the transaction queue length for the link.
|
||||
// Equivalent to: `ip link set $link txqlen $qlen`
|
||||
@ -2305,6 +2639,80 @@ func (h *Handle) LinkSetGroup(link Link, group int) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func addNetkitAttrs(nk *Netkit, linkInfo *nl.RtAttr, flag int) error {
|
||||
if nk.peerLinkAttrs.HardwareAddr != nil || nk.HardwareAddr != nil {
|
||||
return fmt.Errorf("netkit doesn't support setting Ethernet")
|
||||
}
|
||||
|
||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||
// Kernel will return error if trying to change the mode of an existing netkit device
|
||||
data.AddRtAttr(nl.IFLA_NETKIT_MODE, nl.Uint32Attr(uint32(nk.Mode)))
|
||||
data.AddRtAttr(nl.IFLA_NETKIT_POLICY, nl.Uint32Attr(uint32(nk.Policy)))
|
||||
data.AddRtAttr(nl.IFLA_NETKIT_PEER_POLICY, nl.Uint32Attr(uint32(nk.PeerPolicy)))
|
||||
|
||||
if (flag & unix.NLM_F_EXCL) == 0 {
|
||||
// Modifying peer link attributes will not take effect
|
||||
return nil
|
||||
}
|
||||
|
||||
peer := data.AddRtAttr(nl.IFLA_NETKIT_PEER_INFO, nil)
|
||||
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
||||
if nk.peerLinkAttrs.Flags&net.FlagUp != 0 {
|
||||
msg.Change = unix.IFF_UP
|
||||
msg.Flags = unix.IFF_UP
|
||||
}
|
||||
if nk.peerLinkAttrs.Index != 0 {
|
||||
msg.Index = int32(nk.peerLinkAttrs.Index)
|
||||
}
|
||||
peer.AddChild(msg)
|
||||
if nk.peerLinkAttrs.Name != "" {
|
||||
peer.AddRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(nk.peerLinkAttrs.Name))
|
||||
}
|
||||
if nk.peerLinkAttrs.MTU > 0 {
|
||||
peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(nk.peerLinkAttrs.MTU)))
|
||||
}
|
||||
if nk.peerLinkAttrs.GSOMaxSegs > 0 {
|
||||
peer.AddRtAttr(unix.IFLA_GSO_MAX_SEGS, nl.Uint32Attr(nk.peerLinkAttrs.GSOMaxSegs))
|
||||
}
|
||||
if nk.peerLinkAttrs.GSOMaxSize > 0 {
|
||||
peer.AddRtAttr(unix.IFLA_GSO_MAX_SIZE, nl.Uint32Attr(nk.peerLinkAttrs.GSOMaxSize))
|
||||
}
|
||||
if nk.peerLinkAttrs.GSOIPv4MaxSize > 0 {
|
||||
peer.AddRtAttr(unix.IFLA_GSO_IPV4_MAX_SIZE, nl.Uint32Attr(nk.peerLinkAttrs.GSOIPv4MaxSize))
|
||||
}
|
||||
if nk.peerLinkAttrs.GROIPv4MaxSize > 0 {
|
||||
peer.AddRtAttr(unix.IFLA_GRO_IPV4_MAX_SIZE, nl.Uint32Attr(nk.peerLinkAttrs.GROIPv4MaxSize))
|
||||
}
|
||||
if nk.peerLinkAttrs.Namespace != nil {
|
||||
switch ns := nk.peerLinkAttrs.Namespace.(type) {
|
||||
case NsPid:
|
||||
peer.AddRtAttr(unix.IFLA_NET_NS_PID, nl.Uint32Attr(uint32(ns)))
|
||||
case NsFd:
|
||||
peer.AddRtAttr(unix.IFLA_NET_NS_FD, nl.Uint32Attr(uint32(ns)))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseNetkitData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
netkit := link.(*Netkit)
|
||||
for _, datum := range data {
|
||||
switch datum.Attr.Type {
|
||||
case nl.IFLA_NETKIT_PRIMARY:
|
||||
isPrimary := datum.Value[0:1][0]
|
||||
if isPrimary != 0 {
|
||||
netkit.isPrimary = true
|
||||
}
|
||||
case nl.IFLA_NETKIT_MODE:
|
||||
netkit.Mode = NetkitMode(native.Uint32(datum.Value[0:4]))
|
||||
case nl.IFLA_NETKIT_POLICY:
|
||||
netkit.Policy = NetkitPolicy(native.Uint32(datum.Value[0:4]))
|
||||
case nl.IFLA_NETKIT_PEER_POLICY:
|
||||
netkit.PeerPolicy = NetkitPolicy(native.Uint32(datum.Value[0:4]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
vlan := link.(*Vlan)
|
||||
for _, datum := range data {
|
||||
@ -2539,11 +2947,30 @@ func parseIPVtapData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
}
|
||||
}
|
||||
|
||||
func addMacvtapAttrs(macvtap *Macvtap, linkInfo *nl.RtAttr) {
|
||||
addMacvlanAttrs(&macvtap.Macvlan, linkInfo)
|
||||
}
|
||||
|
||||
func parseMacvtapData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
macv := link.(*Macvtap)
|
||||
parseMacvlanData(&macv.Macvlan, data)
|
||||
}
|
||||
|
||||
func addMacvlanAttrs(macvlan *Macvlan, linkInfo *nl.RtAttr) {
|
||||
var data *nl.RtAttr
|
||||
|
||||
if macvlan.Mode != MACVLAN_MODE_DEFAULT || macvlan.BCQueueLen > 0 {
|
||||
data = linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||
}
|
||||
|
||||
if macvlan.Mode != MACVLAN_MODE_DEFAULT {
|
||||
data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[macvlan.Mode]))
|
||||
}
|
||||
if macvlan.BCQueueLen > 0 {
|
||||
data.AddRtAttr(nl.IFLA_MACVLAN_BC_QUEUE_LEN, nl.Uint32Attr(macvlan.BCQueueLen))
|
||||
}
|
||||
}
|
||||
|
||||
func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
macv := link.(*Macvlan)
|
||||
for _, datum := range data {
|
||||
@ -2571,6 +2998,10 @@ func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
for _, macDatum := range macs {
|
||||
macv.MACAddrs = append(macv.MACAddrs, net.HardwareAddr(macDatum.Value[0:6]))
|
||||
}
|
||||
case nl.IFLA_MACVLAN_BC_QUEUE_LEN:
|
||||
macv.BCQueueLen = native.Uint32(datum.Value[0:4])
|
||||
case nl.IFLA_MACVLAN_BC_QUEUE_LEN_USED:
|
||||
macv.UsedBCQueueLen = native.Uint32(datum.Value[0:4])
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2599,10 +3030,13 @@ func linkFlags(rawFlags uint32) net.Flags {
|
||||
func addGeneveAttrs(geneve *Geneve, linkInfo *nl.RtAttr) {
|
||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||
|
||||
if geneve.InnerProtoInherit {
|
||||
data.AddRtAttr(nl.IFLA_GENEVE_INNER_PROTO_INHERIT, []byte{})
|
||||
}
|
||||
|
||||
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
|
||||
geneve.ID = 0
|
||||
data.AddRtAttr(nl.IFLA_GENEVE_COLLECT_METADATA, []byte{})
|
||||
}
|
||||
|
||||
if ip := geneve.Remote; ip != nil {
|
||||
@ -2628,6 +3062,8 @@ func addGeneveAttrs(geneve *Geneve, linkInfo *nl.RtAttr) {
|
||||
if geneve.Tos != 0 {
|
||||
data.AddRtAttr(nl.IFLA_GENEVE_TOS, nl.Uint8Attr(geneve.Tos))
|
||||
}
|
||||
|
||||
data.AddRtAttr(nl.IFLA_GENEVE_DF, nl.Uint8Attr(uint8(geneve.Df)))
|
||||
}
|
||||
|
||||
func parseGeneveData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
@ -2644,6 +3080,10 @@ func parseGeneveData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
geneve.Ttl = uint8(datum.Value[0])
|
||||
case nl.IFLA_GENEVE_TOS:
|
||||
geneve.Tos = uint8(datum.Value[0])
|
||||
case nl.IFLA_GENEVE_COLLECT_METADATA:
|
||||
geneve.FlowBased = true
|
||||
case nl.IFLA_GENEVE_INNER_PROTO_INHERIT:
|
||||
geneve.InnerProtoInherit = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2653,7 +3093,7 @@ func addGretapAttrs(gretap *Gretap, linkInfo *nl.RtAttr) {
|
||||
|
||||
if gretap.FlowBased {
|
||||
// In flow based mode, no other attributes need to be configured
|
||||
data.AddRtAttr(nl.IFLA_GRE_COLLECT_METADATA, boolAttr(gretap.FlowBased))
|
||||
data.AddRtAttr(nl.IFLA_GRE_COLLECT_METADATA, []byte{})
|
||||
return
|
||||
}
|
||||
|
||||
@ -2736,6 +3176,12 @@ func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
func addGretunAttrs(gre *Gretun, linkInfo *nl.RtAttr) {
|
||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||
|
||||
if gre.FlowBased {
|
||||
// In flow based mode, no other attributes need to be configured
|
||||
data.AddRtAttr(nl.IFLA_GRE_COLLECT_METADATA, []byte{})
|
||||
return
|
||||
}
|
||||
|
||||
if ip := gre.Local; ip != nil {
|
||||
if ip.To4() != nil {
|
||||
ip = ip.To4()
|
||||
@ -2806,6 +3252,8 @@ func parseGretunData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
gre.EncapSport = ntohs(datum.Value[0:2])
|
||||
case nl.IFLA_GRE_ENCAP_DPORT:
|
||||
gre.EncapDport = ntohs(datum.Value[0:2])
|
||||
case nl.IFLA_GRE_COLLECT_METADATA:
|
||||
gre.FlowBased = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2846,14 +3294,14 @@ func parseLinkXdp(data []byte) (*LinkXdp, error) {
|
||||
}
|
||||
|
||||
func addIptunAttrs(iptun *Iptun, linkInfo *nl.RtAttr) {
|
||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||
|
||||
if iptun.FlowBased {
|
||||
// In flow based mode, no other attributes need to be configured
|
||||
linkInfo.AddRtAttr(nl.IFLA_IPTUN_COLLECT_METADATA, boolAttr(iptun.FlowBased))
|
||||
data.AddRtAttr(nl.IFLA_IPTUN_COLLECT_METADATA, []byte{})
|
||||
return
|
||||
}
|
||||
|
||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||
|
||||
ip := iptun.Local.To4()
|
||||
if ip != nil {
|
||||
data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip))
|
||||
@ -2880,10 +3328,6 @@ func addIptunAttrs(iptun *Iptun, linkInfo *nl.RtAttr) {
|
||||
func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
iptun := link.(*Iptun)
|
||||
for _, datum := range data {
|
||||
// NOTE: same with vxlan, ip tunnel may also has null datum.Value
|
||||
if len(datum.Value) == 0 {
|
||||
continue
|
||||
}
|
||||
switch datum.Attr.Type {
|
||||
case nl.IFLA_IPTUN_LOCAL:
|
||||
iptun.Local = net.IP(datum.Value[0:4])
|
||||
@ -2914,6 +3358,12 @@ func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
func addIp6tnlAttrs(ip6tnl *Ip6tnl, linkInfo *nl.RtAttr) {
|
||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||
|
||||
if ip6tnl.FlowBased {
|
||||
// In flow based mode, no other attributes need to be configured
|
||||
data.AddRtAttr(nl.IFLA_IPTUN_COLLECT_METADATA, []byte{})
|
||||
return
|
||||
}
|
||||
|
||||
if ip6tnl.Link != 0 {
|
||||
data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(ip6tnl.Link))
|
||||
}
|
||||
@ -2968,6 +3418,8 @@ func parseIp6tnlData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
ip6tnl.EncapSport = ntohs(datum.Value[0:2])
|
||||
case nl.IFLA_IPTUN_ENCAP_DPORT:
|
||||
ip6tnl.EncapDport = ntohs(datum.Value[0:2])
|
||||
case nl.IFLA_IPTUN_COLLECT_METADATA:
|
||||
ip6tnl.FlowBased = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3115,6 +3567,12 @@ func addBridgeAttrs(bridge *Bridge, linkInfo *nl.RtAttr) {
|
||||
if bridge.VlanFiltering != nil {
|
||||
data.AddRtAttr(nl.IFLA_BR_VLAN_FILTERING, boolToByte(*bridge.VlanFiltering))
|
||||
}
|
||||
if bridge.VlanDefaultPVID != nil {
|
||||
data.AddRtAttr(nl.IFLA_BR_VLAN_DEFAULT_PVID, nl.Uint16Attr(*bridge.VlanDefaultPVID))
|
||||
}
|
||||
if bridge.GroupFwdMask != nil {
|
||||
data.AddRtAttr(nl.IFLA_BR_GROUP_FWD_MASK, nl.Uint16Attr(*bridge.GroupFwdMask))
|
||||
}
|
||||
}
|
||||
|
||||
func parseBridgeData(bridge Link, data []syscall.NetlinkRouteAttr) {
|
||||
@ -3133,6 +3591,12 @@ func parseBridgeData(bridge Link, data []syscall.NetlinkRouteAttr) {
|
||||
case nl.IFLA_BR_VLAN_FILTERING:
|
||||
vlanFiltering := datum.Value[0] == 1
|
||||
br.VlanFiltering = &vlanFiltering
|
||||
case nl.IFLA_BR_VLAN_DEFAULT_PVID:
|
||||
vlanDefaultPVID := native.Uint16(datum.Value[0:2])
|
||||
br.VlanDefaultPVID = &vlanDefaultPVID
|
||||
case nl.IFLA_BR_GROUP_FWD_MASK:
|
||||
mask := native.Uint16(datum.Value[0:2])
|
||||
br.GroupFwdMask = &mask
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3174,12 +3638,17 @@ func parseVfInfoList(data []syscall.NetlinkRouteAttr) ([]VfInfo, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vfs = append(vfs, parseVfInfo(vfAttrs, i))
|
||||
|
||||
vf, err := parseVfInfo(vfAttrs, i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vfs = append(vfs, vf)
|
||||
}
|
||||
return vfs, nil
|
||||
}
|
||||
|
||||
func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) VfInfo {
|
||||
func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) (VfInfo, error) {
|
||||
vf := VfInfo{ID: id}
|
||||
for _, element := range data {
|
||||
switch element.Attr.Type {
|
||||
@ -3190,6 +3659,12 @@ func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) VfInfo {
|
||||
vl := nl.DeserializeVfVlan(element.Value[:])
|
||||
vf.Vlan = int(vl.Vlan)
|
||||
vf.Qos = int(vl.Qos)
|
||||
case nl.IFLA_VF_VLAN_LIST:
|
||||
vfVlanInfoList, err := nl.DeserializeVfVlanList(element.Value[:])
|
||||
if err != nil {
|
||||
return vf, err
|
||||
}
|
||||
vf.VlanProto = int(vfVlanInfoList[0].VlanProto)
|
||||
case nl.IFLA_VF_TX_RATE:
|
||||
txr := nl.DeserializeVfTxRate(element.Value[:])
|
||||
vf.TxRate = int(txr.Rate)
|
||||
@ -3223,7 +3698,7 @@ func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) VfInfo {
|
||||
vf.Trust = result.Setting
|
||||
}
|
||||
}
|
||||
return vf
|
||||
return vf, nil
|
||||
}
|
||||
|
||||
func addXfrmiAttrs(xfrmi *Xfrmi, linkInfo *nl.RtAttr) {
|
||||
@ -3246,8 +3721,7 @@ func parseXfrmiData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||
}
|
||||
}
|
||||
|
||||
// LinkSetBondSlave add slave to bond link via ioctl interface.
|
||||
func LinkSetBondSlave(link Link, master *Bond) error {
|
||||
func ioctlBondSlave(cmd uintptr, link Link, master *Bond) error {
|
||||
fd, err := getSocketUDP()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -3255,10 +3729,38 @@ func LinkSetBondSlave(link Link, master *Bond) error {
|
||||
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)))
|
||||
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), cmd, 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 fmt.Errorf("errno=%v", errno)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LinkSetBondSlaveActive sets specified slave to ACTIVE in an `active-backup` bond link via ioctl interface.
|
||||
//
|
||||
// Multiple calls keeps the status unchanged(shown in the unit test).
|
||||
func LinkSetBondSlaveActive(link Link, master *Bond) error {
|
||||
err := ioctlBondSlave(unix.SIOCBONDCHANGEACTIVE, link, master)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to set slave %q active in %q, %v", link.Attrs().Name, master.Attrs().Name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LinkSetBondSlave add slave to bond link via ioctl interface.
|
||||
func LinkSetBondSlave(link Link, master *Bond) error {
|
||||
err := ioctlBondSlave(unix.SIOCBONDENSLAVE, link, master)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to enslave %q to %q, %v", link.Attrs().Name, master.Attrs().Name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LinkSetBondSlave removes specified slave from bond link via ioctl interface.
|
||||
func LinkDelBondSlave(link Link, master *Bond) error {
|
||||
err := ioctlBondSlave(unix.SIOCBONDRELEASE, link, master)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to del slave %q from %q, %v", link.Attrs().Name, master.Attrs().Name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
39
vendor/github.com/vishvananda/netlink/neigh_linux.go
generated
vendored
39
vendor/github.com/vishvananda/netlink/neigh_linux.go
generated
vendored
@ -339,13 +339,13 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
|
||||
// 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)
|
||||
return neighSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0, 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)
|
||||
return neighSubscribeAt(ns, netns.None(), ch, done, nil, false, 0, nil, false)
|
||||
}
|
||||
|
||||
// NeighSubscribeOptions contains a set of options to use with
|
||||
@ -354,6 +354,11 @@ type NeighSubscribeOptions struct {
|
||||
Namespace *netns.NsHandle
|
||||
ErrorCallback func(error)
|
||||
ListExisting bool
|
||||
|
||||
// max size is based on value of /proc/sys/net/core/rmem_max
|
||||
ReceiveBufferSize int
|
||||
ReceiveBufferForceSize bool
|
||||
ReceiveTimeout *unix.Timeval
|
||||
}
|
||||
|
||||
// NeighSubscribeWithOptions work like NeighSubscribe but enable to
|
||||
@ -364,16 +369,17 @@ func NeighSubscribeWithOptions(ch chan<- NeighUpdate, done <-chan struct{}, opti
|
||||
none := netns.None()
|
||||
options.Namespace = &none
|
||||
}
|
||||
return neighSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting)
|
||||
return neighSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting,
|
||||
options.ReceiveBufferSize, options.ReceiveTimeout, options.ReceiveBufferForceSize)
|
||||
}
|
||||
|
||||
func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error {
|
||||
func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <-chan struct{}, cberr func(error), listExisting bool,
|
||||
rcvbuf int, rcvTimeout *unix.Timeval, rcvbufForce 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)
|
||||
req := pkgHandle.newNetlinkRequest(unix.RTM_GETNEIGH, unix.NLM_F_DUMP)
|
||||
ndmsg := &Ndmsg{Family: uint8(family)}
|
||||
req.AddData(ndmsg)
|
||||
if err := s.Send(req); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -382,6 +388,17 @@ func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rcvTimeout != nil {
|
||||
if err := s.SetReceiveTimeout(rcvTimeout); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if rcvbuf != 0 {
|
||||
err = s.SetReceiveBufferSize(rcvbuf, rcvbufForce)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if done != nil {
|
||||
go func() {
|
||||
<-done
|
||||
@ -427,12 +444,12 @@ func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <
|
||||
continue
|
||||
}
|
||||
if m.Header.Type == unix.NLMSG_ERROR {
|
||||
error := int32(native.Uint32(m.Data[0:4]))
|
||||
if error == 0 {
|
||||
nError := int32(native.Uint32(m.Data[0:4]))
|
||||
if nError == 0 {
|
||||
continue
|
||||
}
|
||||
if cberr != nil {
|
||||
cberr(syscall.Errno(-error))
|
||||
cberr(syscall.Errno(-nError))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
32
vendor/github.com/vishvananda/netlink/netlink_unspecified.go
generated
vendored
32
vendor/github.com/vishvananda/netlink/netlink_unspecified.go
generated
vendored
@ -52,6 +52,10 @@ func LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func LinkSetVfTxRate(link Link, vf, rate int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
@ -124,6 +128,22 @@ func LinkSetTxQLen(link Link, qlen int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func LinkSetGSOMaxSize(link Link, maxSize int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func LinkSetGROMaxSize(link Link, maxSize int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func LinkSetGSOIPv4MaxSize(link Link, maxSize int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func LinkSetGROIPv4MaxSize(link Link, maxSize int) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func LinkAdd(link Link) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
@ -184,6 +204,10 @@ func RouteAppend(route *Route) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func RouteChange(route *Route) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func RouteDel(route *Route) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
@ -216,6 +240,10 @@ func XfrmPolicyList(family int) ([]XfrmPolicy, error) {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
||||
func XfrmPolicyGet(policy *XfrmPolicy) (*XfrmPolicy, error) {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
||||
func XfrmStateAdd(policy *XfrmState) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
@ -255,3 +283,7 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
|
||||
func SocketGet(local, remote net.Addr) (*Socket, error) {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
||||
func SocketDestroy(local, remote net.Addr) (*Socket, error) {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
39
vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
generated
vendored
39
vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
generated
vendored
@ -15,6 +15,38 @@ var L4ProtoMap = map[uint8]string{
|
||||
17: "udp",
|
||||
}
|
||||
|
||||
// From https://git.netfilter.org/libnetfilter_conntrack/tree/include/libnetfilter_conntrack/libnetfilter_conntrack_tcp.h
|
||||
// enum tcp_state {
|
||||
// TCP_CONNTRACK_NONE,
|
||||
// TCP_CONNTRACK_SYN_SENT,
|
||||
// TCP_CONNTRACK_SYN_RECV,
|
||||
// TCP_CONNTRACK_ESTABLISHED,
|
||||
// TCP_CONNTRACK_FIN_WAIT,
|
||||
// TCP_CONNTRACK_CLOSE_WAIT,
|
||||
// TCP_CONNTRACK_LAST_ACK,
|
||||
// TCP_CONNTRACK_TIME_WAIT,
|
||||
// TCP_CONNTRACK_CLOSE,
|
||||
// TCP_CONNTRACK_LISTEN, /* obsolete */
|
||||
// #define TCP_CONNTRACK_SYN_SENT2 TCP_CONNTRACK_LISTEN
|
||||
// TCP_CONNTRACK_MAX,
|
||||
// TCP_CONNTRACK_IGNORE
|
||||
// };
|
||||
const (
|
||||
TCP_CONNTRACK_NONE = 0
|
||||
TCP_CONNTRACK_SYN_SENT = 1
|
||||
TCP_CONNTRACK_SYN_RECV = 2
|
||||
TCP_CONNTRACK_ESTABLISHED = 3
|
||||
TCP_CONNTRACK_FIN_WAIT = 4
|
||||
TCP_CONNTRACK_CLOSE_WAIT = 5
|
||||
TCP_CONNTRACK_LAST_ACK = 6
|
||||
TCP_CONNTRACK_TIME_WAIT = 7
|
||||
TCP_CONNTRACK_CLOSE = 8
|
||||
TCP_CONNTRACK_LISTEN = 9
|
||||
TCP_CONNTRACK_SYN_SENT2 = 9
|
||||
TCP_CONNTRACK_MAX = 10
|
||||
TCP_CONNTRACK_IGNORE = 11
|
||||
)
|
||||
|
||||
// All the following constants are coming from:
|
||||
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink_conntrack.h
|
||||
|
||||
@ -31,6 +63,7 @@ var L4ProtoMap = map[uint8]string{
|
||||
// IPCTNL_MSG_MAX
|
||||
// };
|
||||
const (
|
||||
IPCTNL_MSG_CT_NEW = 0
|
||||
IPCTNL_MSG_CT_GET = 1
|
||||
IPCTNL_MSG_CT_DELETE = 2
|
||||
)
|
||||
@ -88,7 +121,10 @@ const (
|
||||
CTA_COUNTERS_REPLY = 10
|
||||
CTA_USE = 11
|
||||
CTA_ID = 12
|
||||
CTA_ZONE = 18
|
||||
CTA_TIMESTAMP = 20
|
||||
CTA_LABELS = 22
|
||||
CTA_LABELS_MASK = 23
|
||||
)
|
||||
|
||||
// enum ctattr_tuple {
|
||||
@ -149,7 +185,10 @@ const (
|
||||
// };
|
||||
// #define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1)
|
||||
const (
|
||||
CTA_PROTOINFO_UNSPEC = 0
|
||||
CTA_PROTOINFO_TCP = 1
|
||||
CTA_PROTOINFO_DCCP = 2
|
||||
CTA_PROTOINFO_SCTP = 3
|
||||
)
|
||||
|
||||
// enum ctattr_protoinfo_tcp {
|
||||
|
106
vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
generated
vendored
106
vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
generated
vendored
@ -9,39 +9,56 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
DEVLINK_CMD_GET = 1
|
||||
DEVLINK_CMD_PORT_GET = 5
|
||||
DEVLINK_CMD_PORT_SET = 6
|
||||
DEVLINK_CMD_PORT_NEW = 7
|
||||
DEVLINK_CMD_PORT_DEL = 8
|
||||
DEVLINK_CMD_ESWITCH_GET = 29
|
||||
DEVLINK_CMD_ESWITCH_SET = 30
|
||||
DEVLINK_CMD_INFO_GET = 51
|
||||
DEVLINK_CMD_GET = 1
|
||||
DEVLINK_CMD_PORT_GET = 5
|
||||
DEVLINK_CMD_PORT_SET = 6
|
||||
DEVLINK_CMD_PORT_NEW = 7
|
||||
DEVLINK_CMD_PORT_DEL = 8
|
||||
DEVLINK_CMD_ESWITCH_GET = 29
|
||||
DEVLINK_CMD_ESWITCH_SET = 30
|
||||
DEVLINK_CMD_RESOURCE_DUMP = 36
|
||||
DEVLINK_CMD_PARAM_GET = 38
|
||||
DEVLINK_CMD_PARAM_SET = 39
|
||||
DEVLINK_CMD_INFO_GET = 51
|
||||
)
|
||||
|
||||
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
|
||||
DEVLINK_ATTR_INFO_DRIVER_NAME = 98
|
||||
DEVLINK_ATTR_INFO_SERIAL_NUMBER = 99
|
||||
DEVLINK_ATTR_INFO_VERSION_FIXED = 100
|
||||
DEVLINK_ATTR_INFO_VERSION_RUNNING = 101
|
||||
DEVLINK_ATTR_INFO_VERSION_STORED = 102
|
||||
DEVLINK_ATTR_INFO_VERSION_NAME = 103
|
||||
DEVLINK_ATTR_INFO_VERSION_VALUE = 104
|
||||
DEVLINK_ATTR_PORT_PCI_PF_NUMBER = 127
|
||||
DEVLINK_ATTR_PORT_FUNCTION = 145
|
||||
DEVLINK_ATTR_PORT_CONTROLLER_NUMBER = 150
|
||||
DEVLINK_ATTR_PORT_PCI_SF_NUMBER = 164
|
||||
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_RESOURCE_LIST = 63 /* nested */
|
||||
DEVLINK_ATTR_RESOURCE = 64 /* nested */
|
||||
DEVLINK_ATTR_RESOURCE_NAME = 65 /* string */
|
||||
DEVLINK_ATTR_RESOURCE_ID = 66 /* u64 */
|
||||
DEVLINK_ATTR_RESOURCE_SIZE = 67 /* u64 */
|
||||
DEVLINK_ATTR_RESOURCE_SIZE_NEW = 68 /* u64 */
|
||||
DEVLINK_ATTR_RESOURCE_SIZE_VALID = 69 /* u8 */
|
||||
DEVLINK_ATTR_RESOURCE_SIZE_MIN = 70 /* u64 */
|
||||
DEVLINK_ATTR_RESOURCE_SIZE_MAX = 71 /* u64 */
|
||||
DEVLINK_ATTR_RESOURCE_SIZE_GRAN = 72 /* u64 */
|
||||
DEVLINK_ATTR_RESOURCE_UNIT = 73 /* u8 */
|
||||
DEVLINK_ATTR_RESOURCE_OCC = 74 /* u64 */
|
||||
DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID = 75 /* u64 */
|
||||
DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS = 76 /* u64 */
|
||||
DEVLINK_ATTR_PORT_FLAVOUR = 77
|
||||
DEVLINK_ATTR_INFO_DRIVER_NAME = 98
|
||||
DEVLINK_ATTR_INFO_SERIAL_NUMBER = 99
|
||||
DEVLINK_ATTR_INFO_VERSION_FIXED = 100
|
||||
DEVLINK_ATTR_INFO_VERSION_RUNNING = 101
|
||||
DEVLINK_ATTR_INFO_VERSION_STORED = 102
|
||||
DEVLINK_ATTR_INFO_VERSION_NAME = 103
|
||||
DEVLINK_ATTR_INFO_VERSION_VALUE = 104
|
||||
DEVLINK_ATTR_PORT_PCI_PF_NUMBER = 127
|
||||
DEVLINK_ATTR_PORT_FUNCTION = 145
|
||||
DEVLINK_ATTR_PORT_CONTROLLER_NUMBER = 150
|
||||
DEVLINK_ATTR_PORT_PCI_SF_NUMBER = 164
|
||||
)
|
||||
|
||||
const (
|
||||
@ -94,3 +111,32 @@ const (
|
||||
DEVLINK_PORT_FN_OPSTATE_DETACHED = 0
|
||||
DEVLINK_PORT_FN_OPSTATE_ATTACHED = 1
|
||||
)
|
||||
|
||||
const (
|
||||
DEVLINK_RESOURCE_UNIT_ENTRY uint8 = 0
|
||||
)
|
||||
|
||||
const (
|
||||
DEVLINK_ATTR_PARAM = iota + 80 /* nested */
|
||||
DEVLINK_ATTR_PARAM_NAME /* string */
|
||||
DEVLINK_ATTR_PARAM_GENERIC /* flag */
|
||||
DEVLINK_ATTR_PARAM_TYPE /* u8 */
|
||||
DEVLINK_ATTR_PARAM_VALUES_LIST /* nested */
|
||||
DEVLINK_ATTR_PARAM_VALUE /* nested */
|
||||
DEVLINK_ATTR_PARAM_VALUE_DATA /* dynamic */
|
||||
DEVLINK_ATTR_PARAM_VALUE_CMODE /* u8 */
|
||||
)
|
||||
|
||||
const (
|
||||
DEVLINK_PARAM_TYPE_U8 = 1
|
||||
DEVLINK_PARAM_TYPE_U16 = 2
|
||||
DEVLINK_PARAM_TYPE_U32 = 3
|
||||
DEVLINK_PARAM_TYPE_STRING = 5
|
||||
DEVLINK_PARAM_TYPE_BOOL = 6
|
||||
)
|
||||
|
||||
const (
|
||||
DEVLINK_PARAM_CMODE_RUNTIME = iota
|
||||
DEVLINK_PARAM_CMODE_DRIVERINIT
|
||||
DEVLINK_PARAM_CMODE_PERMANENT
|
||||
)
|
||||
|
21
vendor/github.com/vishvananda/netlink/nl/ip6tnl_linux.go
generated
vendored
Normal file
21
vendor/github.com/vishvananda/netlink/nl/ip6tnl_linux.go
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
package nl
|
||||
|
||||
// id's of route attribute from https://elixir.bootlin.com/linux/v5.17.3/source/include/uapi/linux/lwtunnel.h#L38
|
||||
// the value's size are specified in https://elixir.bootlin.com/linux/v5.17.3/source/net/ipv4/ip_tunnel_core.c#L928
|
||||
|
||||
const (
|
||||
LWTUNNEL_IP6_UNSPEC = iota
|
||||
LWTUNNEL_IP6_ID
|
||||
LWTUNNEL_IP6_DST
|
||||
LWTUNNEL_IP6_SRC
|
||||
LWTUNNEL_IP6_HOPLIMIT
|
||||
LWTUNNEL_IP6_TC
|
||||
LWTUNNEL_IP6_FLAGS
|
||||
LWTUNNEL_IP6_PAD // not implemented
|
||||
LWTUNNEL_IP6_OPTS // not implemented
|
||||
__LWTUNNEL_IP6_MAX
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
5
vendor/github.com/vishvananda/netlink/nl/ipset_linux.go
generated
vendored
5
vendor/github.com/vishvananda/netlink/nl/ipset_linux.go
generated
vendored
@ -88,6 +88,11 @@ const (
|
||||
SET_ATTR_CREATE_MAX
|
||||
)
|
||||
|
||||
const (
|
||||
IPSET_ATTR_IPADDR_IPV4 = 1
|
||||
IPSET_ATTR_IPADDR_IPV6 = 2
|
||||
)
|
||||
|
||||
/* ADT specific attributes */
|
||||
const (
|
||||
IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + iota + 1
|
||||
|
106
vendor/github.com/vishvananda/netlink/nl/link_linux.go
generated
vendored
106
vendor/github.com/vishvananda/netlink/nl/link_linux.go
generated
vendored
@ -3,6 +3,7 @@ package nl
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@ -30,6 +31,16 @@ const (
|
||||
IFLA_VLAN_MAX = IFLA_VLAN_PROTOCOL
|
||||
)
|
||||
|
||||
const (
|
||||
IFLA_NETKIT_UNSPEC = iota
|
||||
IFLA_NETKIT_PEER_INFO
|
||||
IFLA_NETKIT_PRIMARY
|
||||
IFLA_NETKIT_POLICY
|
||||
IFLA_NETKIT_PEER_POLICY
|
||||
IFLA_NETKIT_MODE
|
||||
IFLA_NETKIT_MAX = IFLA_NETKIT_MODE
|
||||
)
|
||||
|
||||
const (
|
||||
VETH_INFO_UNSPEC = iota
|
||||
VETH_INFO_PEER
|
||||
@ -85,7 +96,37 @@ const (
|
||||
IFLA_BRPORT_PROXYARP
|
||||
IFLA_BRPORT_LEARNING_SYNC
|
||||
IFLA_BRPORT_PROXYARP_WIFI
|
||||
IFLA_BRPORT_MAX = IFLA_BRPORT_PROXYARP_WIFI
|
||||
IFLA_BRPORT_ROOT_ID
|
||||
IFLA_BRPORT_BRIDGE_ID
|
||||
IFLA_BRPORT_DESIGNATED_PORT
|
||||
IFLA_BRPORT_DESIGNATED_COST
|
||||
IFLA_BRPORT_ID
|
||||
IFLA_BRPORT_NO
|
||||
IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
|
||||
IFLA_BRPORT_CONFIG_PENDING
|
||||
IFLA_BRPORT_MESSAGE_AGE_TIMER
|
||||
IFLA_BRPORT_FORWARD_DELAY_TIMER
|
||||
IFLA_BRPORT_HOLD_TIMER
|
||||
IFLA_BRPORT_FLUSH
|
||||
IFLA_BRPORT_MULTICAST_ROUTER
|
||||
IFLA_BRPORT_PAD
|
||||
IFLA_BRPORT_MCAST_FLOOD
|
||||
IFLA_BRPORT_MCAST_TO_UCAST
|
||||
IFLA_BRPORT_VLAN_TUNNEL
|
||||
IFLA_BRPORT_BCAST_FLOOD
|
||||
IFLA_BRPORT_GROUP_FWD_MASK
|
||||
IFLA_BRPORT_NEIGH_SUPPRESS
|
||||
IFLA_BRPORT_ISOLATED
|
||||
IFLA_BRPORT_BACKUP_PORT
|
||||
IFLA_BRPORT_MRP_RING_OPEN
|
||||
IFLA_BRPORT_MRP_IN_OPEN
|
||||
IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT
|
||||
IFLA_BRPORT_MCAST_EHT_HOSTS_CNT
|
||||
IFLA_BRPORT_LOCKED
|
||||
IFLA_BRPORT_MAB
|
||||
IFLA_BRPORT_MCAST_N_GROUPS
|
||||
IFLA_BRPORT_MCAST_MAX_GROUPS
|
||||
IFLA_BRPORT_MAX = IFLA_BRPORT_MCAST_MAX_GROUPS
|
||||
)
|
||||
|
||||
const (
|
||||
@ -103,7 +144,9 @@ const (
|
||||
IFLA_MACVLAN_MACADDR
|
||||
IFLA_MACVLAN_MACADDR_DATA
|
||||
IFLA_MACVLAN_MACADDR_COUNT
|
||||
IFLA_MACVLAN_MAX = IFLA_MACVLAN_FLAGS
|
||||
IFLA_MACVLAN_BC_QUEUE_LEN
|
||||
IFLA_MACVLAN_BC_QUEUE_LEN_USED
|
||||
IFLA_MACVLAN_MAX = IFLA_MACVLAN_BC_QUEUE_LEN_USED
|
||||
)
|
||||
|
||||
const (
|
||||
@ -186,7 +229,10 @@ const (
|
||||
IFLA_GENEVE_UDP_ZERO_CSUM6_TX
|
||||
IFLA_GENEVE_UDP_ZERO_CSUM6_RX
|
||||
IFLA_GENEVE_LABEL
|
||||
IFLA_GENEVE_MAX = IFLA_GENEVE_LABEL
|
||||
IFLA_GENEVE_TTL_INHERIT
|
||||
IFLA_GENEVE_DF
|
||||
IFLA_GENEVE_INNER_PROTO_INHERIT
|
||||
IFLA_GENEVE_MAX = IFLA_GENEVE_INNER_PROTO_INHERIT
|
||||
)
|
||||
|
||||
const (
|
||||
@ -244,7 +290,15 @@ const (
|
||||
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
|
||||
IFLA_VF_VLAN_LIST /* nested list of vlans, option for QinQ */
|
||||
|
||||
IFLA_VF_MAX = IFLA_VF_IB_PORT_GUID
|
||||
)
|
||||
|
||||
const (
|
||||
IFLA_VF_VLAN_INFO_UNSPEC = iota
|
||||
IFLA_VF_VLAN_INFO /* VLAN ID, QoS and VLAN protocol */
|
||||
__IFLA_VF_VLAN_INFO_MAX
|
||||
)
|
||||
|
||||
const (
|
||||
@ -269,6 +323,7 @@ const (
|
||||
const (
|
||||
SizeofVfMac = 0x24
|
||||
SizeofVfVlan = 0x0c
|
||||
SizeofVfVlanInfo = 0x10
|
||||
SizeofVfTxRate = 0x08
|
||||
SizeofVfRate = 0x0c
|
||||
SizeofVfSpoofchk = 0x08
|
||||
@ -324,6 +379,49 @@ func (msg *VfVlan) Serialize() []byte {
|
||||
return (*(*[SizeofVfVlan]byte)(unsafe.Pointer(msg)))[:]
|
||||
}
|
||||
|
||||
func DeserializeVfVlanList(b []byte) ([]*VfVlanInfo, error) {
|
||||
var vfVlanInfoList []*VfVlanInfo
|
||||
attrs, err := ParseRouteAttr(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, element := range attrs {
|
||||
if element.Attr.Type == IFLA_VF_VLAN_INFO {
|
||||
vfVlanInfoList = append(vfVlanInfoList, DeserializeVfVlanInfo(element.Value))
|
||||
}
|
||||
}
|
||||
|
||||
if len(vfVlanInfoList) == 0 {
|
||||
return nil, fmt.Errorf("VF vlan list is defined but no vf vlan info elements were found")
|
||||
}
|
||||
|
||||
return vfVlanInfoList, nil
|
||||
}
|
||||
|
||||
// struct ifla_vf_vlan_info {
|
||||
// __u32 vf;
|
||||
// __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */
|
||||
// __u32 qos;
|
||||
// __be16 vlan_proto; /* VLAN protocol either 802.1Q or 802.1ad */
|
||||
// };
|
||||
|
||||
type VfVlanInfo struct {
|
||||
VfVlan
|
||||
VlanProto uint16
|
||||
}
|
||||
|
||||
func DeserializeVfVlanInfo(b []byte) *VfVlanInfo {
|
||||
return &VfVlanInfo{
|
||||
*(*VfVlan)(unsafe.Pointer(&b[0:SizeofVfVlan][0])),
|
||||
binary.BigEndian.Uint16(b[SizeofVfVlan:SizeofVfVlanInfo]),
|
||||
}
|
||||
}
|
||||
|
||||
func (msg *VfVlanInfo) Serialize() []byte {
|
||||
return (*(*[SizeofVfVlanInfo]byte)(unsafe.Pointer(msg)))[:]
|
||||
}
|
||||
|
||||
// struct ifla_vf_tx_rate {
|
||||
// __u32 vf;
|
||||
// __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */
|
||||
|
206
vendor/github.com/vishvananda/netlink/nl/nl_linux.go
generated
vendored
206
vendor/github.com/vishvananda/netlink/nl/nl_linux.go
generated
vendored
@ -6,6 +6,7 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@ -330,6 +331,19 @@ func NewIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg {
|
||||
return msg
|
||||
}
|
||||
|
||||
type Uint32Bitfield struct {
|
||||
Value uint32
|
||||
Selector uint32
|
||||
}
|
||||
|
||||
func (a *Uint32Bitfield) Serialize() []byte {
|
||||
return (*(*[SizeofUint32Bitfield]byte)(unsafe.Pointer(a)))[:]
|
||||
}
|
||||
|
||||
func DeserializeUint32Bitfield(data []byte) *Uint32Bitfield {
|
||||
return (*Uint32Bitfield)(unsafe.Pointer(&data[0:SizeofUint32Bitfield][0]))
|
||||
}
|
||||
|
||||
type Uint32Attribute struct {
|
||||
Type uint16
|
||||
Value uint32
|
||||
@ -475,10 +489,30 @@ func (req *NetlinkRequest) AddRawData(data []byte) {
|
||||
req.RawData = append(req.RawData, data...)
|
||||
}
|
||||
|
||||
// Execute the request against a the given sockType.
|
||||
// Execute the request against 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 res [][]byte
|
||||
err := req.ExecuteIter(sockType, resType, func(msg []byte) bool {
|
||||
res = append(res, msg)
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// ExecuteIter executes the request against the given sockType.
|
||||
// Calls the provided callback func once for each netlink message.
|
||||
// If the callback returns false, it is not called again, but
|
||||
// the remaining messages are consumed/discarded.
|
||||
//
|
||||
// Thread safety: ExecuteIter holds a lock on the socket until
|
||||
// it finishes iteration so the callback must not call back into
|
||||
// the netlink API.
|
||||
func (req *NetlinkRequest) ExecuteIter(sockType int, resType uint16, f func(msg []byte) bool) error {
|
||||
var (
|
||||
s *NetlinkSocket
|
||||
err error
|
||||
@ -495,18 +529,18 @@ func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, erro
|
||||
if s == nil {
|
||||
s, err = getNetlinkSocket(sockType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.SetSendTimeout(&SocketTimeoutTv); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
if err := s.SetReceiveTimeout(&SocketTimeoutTv); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
if EnableErrorMessageReporting {
|
||||
if err := s.SetExtAck(true); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -517,36 +551,44 @@ func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, erro
|
||||
}
|
||||
|
||||
if err := s.Send(req); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
pid, err := s.GetPid()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
var res [][]byte
|
||||
|
||||
done:
|
||||
for {
|
||||
msgs, from, err := s.Receive()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
if from.Pid != PidKernel {
|
||||
return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, PidKernel)
|
||||
return 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)
|
||||
return fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq)
|
||||
}
|
||||
if m.Header.Pid != pid {
|
||||
continue
|
||||
}
|
||||
|
||||
if m.Header.Flags&unix.NLM_F_DUMP_INTR != 0 {
|
||||
return syscall.Errno(unix.EINTR)
|
||||
}
|
||||
|
||||
if m.Header.Type == unix.NLMSG_DONE || m.Header.Type == unix.NLMSG_ERROR {
|
||||
// NLMSG_DONE might have no payload, if so assume no error.
|
||||
if m.Header.Type == unix.NLMSG_DONE && len(m.Data) == 0 {
|
||||
break done
|
||||
}
|
||||
|
||||
native := NativeEndian()
|
||||
errno := int32(native.Uint32(m.Data[0:4]))
|
||||
if errno == 0 {
|
||||
@ -556,7 +598,7 @@ done:
|
||||
err = syscall.Errno(-errno)
|
||||
|
||||
unreadData := m.Data[4:]
|
||||
if m.Header.Flags|unix.NLM_F_ACK_TLVS != 0 && len(unreadData) > syscall.SizeofNlMsghdr {
|
||||
if m.Header.Flags&unix.NLM_F_ACK_TLVS != 0 && len(unreadData) > syscall.SizeofNlMsghdr {
|
||||
// Skip the echoed request message.
|
||||
echoReqH := (*syscall.NlMsghdr)(unsafe.Pointer(&unreadData[0]))
|
||||
unreadData = unreadData[nlmAlignOf(int(echoReqH.Len)):]
|
||||
@ -568,8 +610,7 @@ done:
|
||||
|
||||
switch attr.Type {
|
||||
case NLMSGERR_ATTR_MSG:
|
||||
err = fmt.Errorf("%w: %s", err, string(attrData))
|
||||
|
||||
err = fmt.Errorf("%w: %s", err, unix.ByteSliceToString(attrData))
|
||||
default:
|
||||
// TODO: handle other NLMSGERR_ATTR types
|
||||
}
|
||||
@ -578,18 +619,26 @@ done:
|
||||
}
|
||||
}
|
||||
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
if resType != 0 && m.Header.Type != resType {
|
||||
continue
|
||||
}
|
||||
res = append(res, m.Data)
|
||||
if cont := f(m.Data); !cont {
|
||||
// Drain the rest of the messages from the kernel but don't
|
||||
// pass them to the iterator func.
|
||||
f = dummyMsgIterFunc
|
||||
}
|
||||
if m.Header.Flags&unix.NLM_F_MULTI == 0 {
|
||||
break done
|
||||
}
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func dummyMsgIterFunc(msg []byte) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Create a new netlink request from proto and flags
|
||||
@ -607,8 +656,9 @@ func NewNetlinkRequest(proto, flags int) *NetlinkRequest {
|
||||
}
|
||||
|
||||
type NetlinkSocket struct {
|
||||
fd int32
|
||||
lsa unix.SockaddrNetlink
|
||||
fd int32
|
||||
file *os.File
|
||||
lsa unix.SockaddrNetlink
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
@ -617,8 +667,13 @@ func getNetlinkSocket(protocol int) (*NetlinkSocket, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = unix.SetNonblock(fd, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s := &NetlinkSocket{
|
||||
fd: int32(fd),
|
||||
fd: int32(fd),
|
||||
file: os.NewFile(uintptr(fd), "netlink"),
|
||||
}
|
||||
s.lsa.Family = unix.AF_NETLINK
|
||||
if err := unix.Bind(fd, &s.lsa); err != nil {
|
||||
@ -649,12 +704,14 @@ func GetNetlinkSocketAt(newNs, curNs netns.NsHandle, protocol int) (*NetlinkSock
|
||||
// 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>
|
||||
// }
|
||||
//
|
||||
// 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 (
|
||||
@ -703,8 +760,13 @@ func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = unix.SetNonblock(fd, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s := &NetlinkSocket{
|
||||
fd: int32(fd),
|
||||
fd: int32(fd),
|
||||
file: os.NewFile(uintptr(fd), "netlink"),
|
||||
}
|
||||
s.lsa.Family = unix.AF_NETLINK
|
||||
|
||||
@ -733,33 +795,36 @@ func SubscribeAt(newNs, curNs netns.NsHandle, protocol int, groups ...uint) (*Ne
|
||||
}
|
||||
|
||||
func (s *NetlinkSocket) Close() {
|
||||
fd := int(atomic.SwapInt32(&s.fd, -1))
|
||||
unix.Close(fd)
|
||||
s.file.Close()
|
||||
}
|
||||
|
||||
func (s *NetlinkSocket) GetFd() int {
|
||||
return int(atomic.LoadInt32(&s.fd))
|
||||
return int(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
|
||||
return unix.Sendto(int(s.fd), request.Serialize(), 0, &s.lsa)
|
||||
}
|
||||
|
||||
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")
|
||||
rawConn, err := s.file.SyscallConn()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
var (
|
||||
fromAddr *unix.SockaddrNetlink
|
||||
rb [RECEIVE_BUFFER_SIZE]byte
|
||||
nr int
|
||||
from unix.Sockaddr
|
||||
innerErr error
|
||||
)
|
||||
err = rawConn.Read(func(fd uintptr) (done bool) {
|
||||
nr, from, innerErr = unix.Recvfrom(int(fd), rb[:], 0)
|
||||
return innerErr != unix.EWOULDBLOCK
|
||||
})
|
||||
if innerErr != nil {
|
||||
err = innerErr
|
||||
}
|
||||
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
|
||||
}
|
||||
@ -770,8 +835,9 @@ func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, *unix.SockaddrNetli
|
||||
if nr < unix.NLMSG_HDRLEN {
|
||||
return nil, nil, fmt.Errorf("Got short response from netlink")
|
||||
}
|
||||
rb2 := make([]byte, nr)
|
||||
copy(rb2, rb[:nr])
|
||||
msgLen := nlmAlignOf(nr)
|
||||
rb2 := make([]byte, msgLen)
|
||||
copy(rb2, rb[:msgLen])
|
||||
nl, err := syscall.ParseNetlinkMessage(rb2)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -793,6 +859,15 @@ func (s *NetlinkSocket) SetReceiveTimeout(timeout *unix.Timeval) error {
|
||||
return unix.SetsockoptTimeval(int(s.fd), unix.SOL_SOCKET, unix.SO_RCVTIMEO, timeout)
|
||||
}
|
||||
|
||||
// SetReceiveBufferSize allows to set a receive buffer size on the socket
|
||||
func (s *NetlinkSocket) SetReceiveBufferSize(size int, force bool) error {
|
||||
opt := unix.SO_RCVBUF
|
||||
if force {
|
||||
opt = unix.SO_RCVBUFFORCE
|
||||
}
|
||||
return unix.SetsockoptInt(int(s.fd), unix.SOL_SOCKET, opt, size)
|
||||
}
|
||||
|
||||
// SetExtAck requests error messages to be reported on the socket
|
||||
func (s *NetlinkSocket) SetExtAck(enable bool) error {
|
||||
var enableN int
|
||||
@ -804,8 +879,7 @@ func (s *NetlinkSocket) SetExtAck(enable bool) error {
|
||||
}
|
||||
|
||||
func (s *NetlinkSocket) GetPid() (uint32, error) {
|
||||
fd := int(atomic.LoadInt32(&s.fd))
|
||||
lsa, err := unix.Getsockname(fd)
|
||||
lsa, err := unix.Getsockname(int(s.fd))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -849,6 +923,12 @@ func Uint16Attr(v uint16) []byte {
|
||||
return bytes
|
||||
}
|
||||
|
||||
func BEUint16Attr(v uint16) []byte {
|
||||
bytes := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(bytes, v)
|
||||
return bytes
|
||||
}
|
||||
|
||||
func Uint32Attr(v uint32) []byte {
|
||||
native := NativeEndian()
|
||||
bytes := make([]byte, 4)
|
||||
@ -856,6 +936,12 @@ func Uint32Attr(v uint32) []byte {
|
||||
return bytes
|
||||
}
|
||||
|
||||
func BEUint32Attr(v uint32) []byte {
|
||||
bytes := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(bytes, v)
|
||||
return bytes
|
||||
}
|
||||
|
||||
func Uint64Attr(v uint64) []byte {
|
||||
native := NativeEndian()
|
||||
bytes := make([]byte, 8)
|
||||
@ -863,6 +949,12 @@ func Uint64Attr(v uint64) []byte {
|
||||
return bytes
|
||||
}
|
||||
|
||||
func BEUint64Attr(v uint64) []byte {
|
||||
bytes := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(bytes, v)
|
||||
return bytes
|
||||
}
|
||||
|
||||
func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) {
|
||||
var attrs []syscall.NetlinkRouteAttr
|
||||
for len(b) >= unix.SizeofRtAttr {
|
||||
@ -877,6 +969,22 @@ func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) {
|
||||
return attrs, nil
|
||||
}
|
||||
|
||||
// ParseRouteAttrAsMap parses provided buffer that contains raw RtAttrs and returns a map of parsed
|
||||
// atttributes indexed by attribute type or error if occured.
|
||||
func ParseRouteAttrAsMap(b []byte) (map[uint16]syscall.NetlinkRouteAttr, error) {
|
||||
attrMap := make(map[uint16]syscall.NetlinkRouteAttr)
|
||||
|
||||
attrs, err := ParseRouteAttr(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, attr := range attrs {
|
||||
attrMap[attr.Attr.Type] = attr
|
||||
}
|
||||
return attrMap, 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) {
|
||||
|
4
vendor/github.com/vishvananda/netlink/nl/route_linux.go
generated
vendored
4
vendor/github.com/vishvananda/netlink/nl/route_linux.go
generated
vendored
@ -48,7 +48,9 @@ type RtNexthop struct {
|
||||
}
|
||||
|
||||
func DeserializeRtNexthop(b []byte) *RtNexthop {
|
||||
return (*RtNexthop)(unsafe.Pointer(&b[0:unix.SizeofRtNexthop][0]))
|
||||
return &RtNexthop{
|
||||
RtNexthop: *((*unix.RtNexthop)(unsafe.Pointer(&b[0:unix.SizeofRtNexthop][0]))),
|
||||
}
|
||||
}
|
||||
|
||||
func (msg *RtNexthop) Len() int {
|
||||
|
4
vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go
generated
vendored
4
vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go
generated
vendored
@ -12,6 +12,7 @@ const (
|
||||
SEG6_LOCAL_NH6
|
||||
SEG6_LOCAL_IIF
|
||||
SEG6_LOCAL_OIF
|
||||
SEG6_LOCAL_BPF
|
||||
__SEG6_LOCAL_MAX
|
||||
)
|
||||
const (
|
||||
@ -34,6 +35,7 @@ const (
|
||||
SEG6_LOCAL_ACTION_END_S // 12
|
||||
SEG6_LOCAL_ACTION_END_AS // 13
|
||||
SEG6_LOCAL_ACTION_END_AM // 14
|
||||
SEG6_LOCAL_ACTION_END_BPF // 15
|
||||
__SEG6_LOCAL_ACTION_MAX
|
||||
)
|
||||
const (
|
||||
@ -71,6 +73,8 @@ func SEG6LocalActionString(action int) string {
|
||||
return "End.AS"
|
||||
case SEG6_LOCAL_ACTION_END_AM:
|
||||
return "End.AM"
|
||||
case SEG6_LOCAL_ACTION_END_BPF:
|
||||
return "End.BPF"
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
1
vendor/github.com/vishvananda/netlink/nl/syscall.go
generated
vendored
1
vendor/github.com/vishvananda/netlink/nl/syscall.go
generated
vendored
@ -46,6 +46,7 @@ const (
|
||||
// socket diags related
|
||||
const (
|
||||
SOCK_DIAG_BY_FAMILY = 20 /* linux.sock_diag.h */
|
||||
SOCK_DESTROY = 21
|
||||
TCPDIAG_NOCOOKIE = 0xFFFFFFFF /* TCPDIAG_NOCOOKIE in net/ipv4/tcp_diag.h*/
|
||||
)
|
||||
|
||||
|
544
vendor/github.com/vishvananda/netlink/nl/tc_linux.go
generated
vendored
544
vendor/github.com/vishvananda/netlink/nl/tc_linux.go
generated
vendored
@ -1,8 +1,13 @@
|
||||
package nl
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// LinkLayer
|
||||
@ -42,7 +47,14 @@ const (
|
||||
TCA_FCNT
|
||||
TCA_STATS2
|
||||
TCA_STAB
|
||||
TCA_MAX = TCA_STAB
|
||||
TCA_PAD
|
||||
TCA_DUMP_INVISIBLE
|
||||
TCA_CHAIN
|
||||
TCA_HW_OFFLOAD
|
||||
TCA_INGRESS_BLOCK
|
||||
TCA_EGRESS_BLOCK
|
||||
TCA_DUMP_FLAGS
|
||||
TCA_MAX = TCA_DUMP_FLAGS
|
||||
)
|
||||
|
||||
const (
|
||||
@ -56,6 +68,12 @@ const (
|
||||
TCA_ACT_OPTIONS
|
||||
TCA_ACT_INDEX
|
||||
TCA_ACT_STATS
|
||||
TCA_ACT_PAD
|
||||
TCA_ACT_COOKIE
|
||||
TCA_ACT_FLAGS
|
||||
TCA_ACT_HW_STATS
|
||||
TCA_ACT_USED_HW_STATS
|
||||
TCA_ACT_IN_HW_COUNT
|
||||
TCA_ACT_MAX
|
||||
)
|
||||
|
||||
@ -71,7 +89,11 @@ const (
|
||||
TCA_STATS_RATE_EST
|
||||
TCA_STATS_QUEUE
|
||||
TCA_STATS_APP
|
||||
TCA_STATS_MAX = TCA_STATS_APP
|
||||
TCA_STATS_RATE_EST64
|
||||
TCA_STATS_PAD
|
||||
TCA_STATS_BASIC_HW
|
||||
TCA_STATS_PKT64
|
||||
TCA_STATS_MAX = TCA_STATS_PKT64
|
||||
)
|
||||
|
||||
const (
|
||||
@ -83,12 +105,13 @@ const (
|
||||
SizeofTcNetemCorr = 0x0c
|
||||
SizeofTcNetemReorder = 0x08
|
||||
SizeofTcNetemCorrupt = 0x08
|
||||
SizeOfTcNetemRate = 0x10
|
||||
SizeofTcTbfQopt = 2*SizeofTcRateSpec + 0x0c
|
||||
SizeofTcHtbCopt = 2*SizeofTcRateSpec + 0x14
|
||||
SizeofTcHtbGlob = 0x14
|
||||
SizeofTcU32Key = 0x10
|
||||
SizeofTcU32Sel = 0x10 // without keys
|
||||
SizeofTcGen = 0x14
|
||||
SizeofTcGen = 0x16
|
||||
SizeofTcConnmark = SizeofTcGen + 0x04
|
||||
SizeofTcCsum = SizeofTcGen + 0x04
|
||||
SizeofTcMirred = SizeofTcGen + 0x08
|
||||
@ -98,6 +121,7 @@ const (
|
||||
SizeofTcSfqQopt = 0x0b
|
||||
SizeofTcSfqRedStats = 0x18
|
||||
SizeofTcSfqQoptV1 = SizeofTcSfqQopt + SizeofTcSfqRedStats + 0x1c
|
||||
SizeofUint32Bitfield = 0x8
|
||||
)
|
||||
|
||||
// struct tcmsg {
|
||||
@ -131,6 +155,18 @@ func (x *TcMsg) Serialize() []byte {
|
||||
return (*(*[SizeofTcMsg]byte)(unsafe.Pointer(x)))[:]
|
||||
}
|
||||
|
||||
type Tcf struct {
|
||||
Install uint64
|
||||
LastUse uint64
|
||||
Expires uint64
|
||||
FirstUse uint64
|
||||
}
|
||||
|
||||
func DeserializeTcf(b []byte) *Tcf {
|
||||
const size = int(unsafe.Sizeof(Tcf{}))
|
||||
return (*Tcf)(unsafe.Pointer(&b[0:size][0]))
|
||||
}
|
||||
|
||||
// struct tcamsg {
|
||||
// unsigned char tca_family;
|
||||
// unsigned char tca__pad1;
|
||||
@ -337,6 +373,26 @@ func (x *TcNetemCorrupt) Serialize() []byte {
|
||||
return (*(*[SizeofTcNetemCorrupt]byte)(unsafe.Pointer(x)))[:]
|
||||
}
|
||||
|
||||
// TcNetemRate is a struct that represents the rate of a netem qdisc
|
||||
type TcNetemRate struct {
|
||||
Rate uint32
|
||||
PacketOverhead int32
|
||||
CellSize uint32
|
||||
CellOverhead int32
|
||||
}
|
||||
|
||||
func (msg *TcNetemRate) Len() int {
|
||||
return SizeofTcRateSpec
|
||||
}
|
||||
|
||||
func DeserializeTcNetemRate(b []byte) *TcNetemRate {
|
||||
return (*TcNetemRate)(unsafe.Pointer(&b[0:SizeofTcRateSpec][0]))
|
||||
}
|
||||
|
||||
func (msg *TcNetemRate) Serialize() []byte {
|
||||
return (*(*[SizeOfTcNetemRate]byte)(unsafe.Pointer(msg)))[:]
|
||||
}
|
||||
|
||||
// struct tc_tbf_qopt {
|
||||
// struct tc_ratespec rate;
|
||||
// struct tc_ratespec peakrate;
|
||||
@ -804,7 +860,8 @@ const (
|
||||
TCA_SKBEDIT_MARK
|
||||
TCA_SKBEDIT_PAD
|
||||
TCA_SKBEDIT_PTYPE
|
||||
TCA_SKBEDIT_MAX = TCA_SKBEDIT_MARK
|
||||
TCA_SKBEDIT_MASK
|
||||
TCA_SKBEDIT_MAX
|
||||
)
|
||||
|
||||
type TcSkbEdit struct {
|
||||
@ -891,6 +948,10 @@ const (
|
||||
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
|
||||
TCA_FQ_CE_THRESHOLD // DCTCP-like CE-marking threshold
|
||||
TCA_FQ_TIMER_SLACK // timer slack
|
||||
TCA_FQ_HORIZON // time horizon in us
|
||||
TCA_FQ_HORIZON_DROP // drop packets beyond horizon, or cap their EDT
|
||||
)
|
||||
|
||||
const (
|
||||
@ -1018,6 +1079,9 @@ const (
|
||||
__TCA_FLOWER_MAX
|
||||
)
|
||||
|
||||
const TCA_CLS_FLAGS_SKIP_HW = 1 << 0 /* don't offload filter to HW */
|
||||
const TCA_CLS_FLAGS_SKIP_SW = 1 << 1 /* don't use filter in SW */
|
||||
|
||||
// struct tc_sfq_qopt {
|
||||
// unsigned quantum; /* Bytes per round allocated to flow */
|
||||
// int perturb_period; /* Period of hash perturbation */
|
||||
@ -1046,14 +1110,14 @@ 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 */
|
||||
// };
|
||||
// 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
|
||||
@ -1075,22 +1139,26 @@ 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;
|
||||
// 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 */
|
||||
//
|
||||
// __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;
|
||||
// };
|
||||
//
|
||||
// struct tc_sfqred_stats stats;
|
||||
// };
|
||||
type TcSfqQoptV1 struct {
|
||||
TcSfqQopt
|
||||
Depth uint32
|
||||
@ -1117,3 +1185,427 @@ func DeserializeTcSfqQoptV1(b []byte) *TcSfqQoptV1 {
|
||||
func (x *TcSfqQoptV1) Serialize() []byte {
|
||||
return (*(*[SizeofTcSfqQoptV1]byte)(unsafe.Pointer(x)))[:]
|
||||
}
|
||||
|
||||
// IPProto represents Flower ip_proto attribute
|
||||
type IPProto uint8
|
||||
|
||||
const (
|
||||
IPPROTO_TCP IPProto = unix.IPPROTO_TCP
|
||||
IPPROTO_UDP IPProto = unix.IPPROTO_UDP
|
||||
IPPROTO_SCTP IPProto = unix.IPPROTO_SCTP
|
||||
IPPROTO_ICMP IPProto = unix.IPPROTO_ICMP
|
||||
IPPROTO_ICMPV6 IPProto = unix.IPPROTO_ICMPV6
|
||||
)
|
||||
|
||||
func (i IPProto) Serialize() []byte {
|
||||
arr := make([]byte, 1)
|
||||
arr[0] = byte(i)
|
||||
return arr
|
||||
}
|
||||
|
||||
func (i IPProto) String() string {
|
||||
switch i {
|
||||
case IPPROTO_TCP:
|
||||
return "tcp"
|
||||
case IPPROTO_UDP:
|
||||
return "udp"
|
||||
case IPPROTO_SCTP:
|
||||
return "sctp"
|
||||
case IPPROTO_ICMP:
|
||||
return "icmp"
|
||||
case IPPROTO_ICMPV6:
|
||||
return "icmpv6"
|
||||
}
|
||||
return fmt.Sprintf("%d", i)
|
||||
}
|
||||
|
||||
const (
|
||||
MaxOffs = 128
|
||||
SizeOfPeditSel = 24
|
||||
SizeOfPeditKey = 24
|
||||
|
||||
TCA_PEDIT_KEY_EX_HTYPE = 1
|
||||
TCA_PEDIT_KEY_EX_CMD = 2
|
||||
)
|
||||
|
||||
const (
|
||||
TCA_PEDIT_UNSPEC = iota
|
||||
TCA_PEDIT_TM
|
||||
TCA_PEDIT_PARMS
|
||||
TCA_PEDIT_PAD
|
||||
TCA_PEDIT_PARMS_EX
|
||||
TCA_PEDIT_KEYS_EX
|
||||
TCA_PEDIT_KEY_EX
|
||||
)
|
||||
|
||||
// /* TCA_PEDIT_KEY_EX_HDR_TYPE_NETWROK is a special case for legacy users. It
|
||||
// * means no specific header type - offset is relative to the network layer
|
||||
// */
|
||||
type PeditHeaderType uint16
|
||||
|
||||
const (
|
||||
TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK = iota
|
||||
TCA_PEDIT_KEY_EX_HDR_TYPE_ETH
|
||||
TCA_PEDIT_KEY_EX_HDR_TYPE_IP4
|
||||
TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
|
||||
TCA_PEDIT_KEY_EX_HDR_TYPE_TCP
|
||||
TCA_PEDIT_KEY_EX_HDR_TYPE_UDP
|
||||
__PEDIT_HDR_TYPE_MAX
|
||||
)
|
||||
|
||||
type PeditCmd uint16
|
||||
|
||||
const (
|
||||
TCA_PEDIT_KEY_EX_CMD_SET = 0
|
||||
TCA_PEDIT_KEY_EX_CMD_ADD = 1
|
||||
)
|
||||
|
||||
type TcPeditSel struct {
|
||||
TcGen
|
||||
NKeys uint8
|
||||
Flags uint8
|
||||
}
|
||||
|
||||
func DeserializeTcPeditKey(b []byte) *TcPeditKey {
|
||||
return (*TcPeditKey)(unsafe.Pointer(&b[0:SizeOfPeditKey][0]))
|
||||
}
|
||||
|
||||
func DeserializeTcPedit(b []byte) (*TcPeditSel, []TcPeditKey) {
|
||||
x := &TcPeditSel{}
|
||||
copy((*(*[SizeOfPeditSel]byte)(unsafe.Pointer(x)))[:SizeOfPeditSel], b)
|
||||
|
||||
var keys []TcPeditKey
|
||||
|
||||
next := SizeOfPeditKey
|
||||
var i uint8
|
||||
for i = 0; i < x.NKeys; i++ {
|
||||
keys = append(keys, *DeserializeTcPeditKey(b[next:]))
|
||||
next += SizeOfPeditKey
|
||||
}
|
||||
|
||||
return x, keys
|
||||
}
|
||||
|
||||
type TcPeditKey struct {
|
||||
Mask uint32
|
||||
Val uint32
|
||||
Off uint32
|
||||
At uint32
|
||||
OffMask uint32
|
||||
Shift uint32
|
||||
}
|
||||
|
||||
type TcPeditKeyEx struct {
|
||||
HeaderType PeditHeaderType
|
||||
Cmd PeditCmd
|
||||
}
|
||||
|
||||
type TcPedit struct {
|
||||
Sel TcPeditSel
|
||||
Keys []TcPeditKey
|
||||
KeysEx []TcPeditKeyEx
|
||||
Extend uint8
|
||||
}
|
||||
|
||||
func (p *TcPedit) Encode(parent *RtAttr) {
|
||||
parent.AddRtAttr(TCA_ACT_KIND, ZeroTerminated("pedit"))
|
||||
actOpts := parent.AddRtAttr(TCA_ACT_OPTIONS, nil)
|
||||
|
||||
bbuf := bytes.NewBuffer(make([]byte, 0, int(unsafe.Sizeof(p.Sel)+unsafe.Sizeof(p.Keys))))
|
||||
|
||||
bbuf.Write((*(*[SizeOfPeditSel]byte)(unsafe.Pointer(&p.Sel)))[:])
|
||||
|
||||
for i := uint8(0); i < p.Sel.NKeys; i++ {
|
||||
bbuf.Write((*(*[SizeOfPeditKey]byte)(unsafe.Pointer(&p.Keys[i])))[:])
|
||||
}
|
||||
actOpts.AddRtAttr(TCA_PEDIT_PARMS_EX, bbuf.Bytes())
|
||||
|
||||
exAttrs := actOpts.AddRtAttr(int(TCA_PEDIT_KEYS_EX|NLA_F_NESTED), nil)
|
||||
for i := uint8(0); i < p.Sel.NKeys; i++ {
|
||||
keyAttr := exAttrs.AddRtAttr(int(TCA_PEDIT_KEY_EX|NLA_F_NESTED), nil)
|
||||
|
||||
htypeBuf := make([]byte, 2)
|
||||
cmdBuf := make([]byte, 2)
|
||||
|
||||
NativeEndian().PutUint16(htypeBuf, uint16(p.KeysEx[i].HeaderType))
|
||||
NativeEndian().PutUint16(cmdBuf, uint16(p.KeysEx[i].Cmd))
|
||||
|
||||
keyAttr.AddRtAttr(TCA_PEDIT_KEY_EX_HTYPE, htypeBuf)
|
||||
keyAttr.AddRtAttr(TCA_PEDIT_KEY_EX_CMD, cmdBuf)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *TcPedit) SetEthDst(mac net.HardwareAddr) {
|
||||
u32 := NativeEndian().Uint32(mac)
|
||||
u16 := NativeEndian().Uint16(mac[4:])
|
||||
|
||||
tKey := TcPeditKey{}
|
||||
tKeyEx := TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_ETH
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
p.Sel.NKeys++
|
||||
|
||||
tKey = TcPeditKey{}
|
||||
tKeyEx = TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = uint32(u16)
|
||||
tKey.Mask = 0xffff0000
|
||||
tKey.Off = 4
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_ETH
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
|
||||
p.Sel.NKeys++
|
||||
}
|
||||
|
||||
func (p *TcPedit) SetEthSrc(mac net.HardwareAddr) {
|
||||
u16 := NativeEndian().Uint16(mac)
|
||||
u32 := NativeEndian().Uint32(mac[2:])
|
||||
|
||||
tKey := TcPeditKey{}
|
||||
tKeyEx := TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = uint32(u16) << 16
|
||||
tKey.Mask = 0x0000ffff
|
||||
tKey.Off = 4
|
||||
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_ETH
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
p.Sel.NKeys++
|
||||
|
||||
tKey = TcPeditKey{}
|
||||
tKeyEx = TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Mask = 0
|
||||
tKey.Off = 8
|
||||
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_ETH
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
|
||||
p.Sel.NKeys++
|
||||
}
|
||||
|
||||
func (p *TcPedit) SetIPv6Src(ip6 net.IP) {
|
||||
u32 := NativeEndian().Uint32(ip6[:4])
|
||||
|
||||
tKey := TcPeditKey{}
|
||||
tKeyEx := TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 8
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
p.Sel.NKeys++
|
||||
|
||||
u32 = NativeEndian().Uint32(ip6[4:8])
|
||||
tKey = TcPeditKey{}
|
||||
tKeyEx = TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 12
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
|
||||
p.Sel.NKeys++
|
||||
|
||||
u32 = NativeEndian().Uint32(ip6[8:12])
|
||||
tKey = TcPeditKey{}
|
||||
tKeyEx = TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 16
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
|
||||
p.Sel.NKeys++
|
||||
|
||||
u32 = NativeEndian().Uint32(ip6[12:16])
|
||||
tKey = TcPeditKey{}
|
||||
tKeyEx = TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 20
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
|
||||
p.Sel.NKeys++
|
||||
}
|
||||
|
||||
func (p *TcPedit) SetDstIP(ip net.IP) {
|
||||
if ip.To4() != nil {
|
||||
p.SetIPv4Dst(ip)
|
||||
} else {
|
||||
p.SetIPv6Dst(ip)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *TcPedit) SetSrcIP(ip net.IP) {
|
||||
if ip.To4() != nil {
|
||||
p.SetIPv4Src(ip)
|
||||
} else {
|
||||
p.SetIPv6Src(ip)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *TcPedit) SetIPv6Dst(ip6 net.IP) {
|
||||
u32 := NativeEndian().Uint32(ip6[:4])
|
||||
|
||||
tKey := TcPeditKey{}
|
||||
tKeyEx := TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 24
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
p.Sel.NKeys++
|
||||
|
||||
u32 = NativeEndian().Uint32(ip6[4:8])
|
||||
tKey = TcPeditKey{}
|
||||
tKeyEx = TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 28
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
|
||||
p.Sel.NKeys++
|
||||
|
||||
u32 = NativeEndian().Uint32(ip6[8:12])
|
||||
tKey = TcPeditKey{}
|
||||
tKeyEx = TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 32
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
|
||||
p.Sel.NKeys++
|
||||
|
||||
u32 = NativeEndian().Uint32(ip6[12:16])
|
||||
tKey = TcPeditKey{}
|
||||
tKeyEx = TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 36
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
|
||||
p.Sel.NKeys++
|
||||
}
|
||||
|
||||
func (p *TcPedit) SetIPv4Src(ip net.IP) {
|
||||
u32 := NativeEndian().Uint32(ip[:4])
|
||||
|
||||
tKey := TcPeditKey{}
|
||||
tKeyEx := TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 12
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP4
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
p.Sel.NKeys++
|
||||
}
|
||||
|
||||
func (p *TcPedit) SetIPv4Dst(ip net.IP) {
|
||||
u32 := NativeEndian().Uint32(ip[:4])
|
||||
|
||||
tKey := TcPeditKey{}
|
||||
tKeyEx := TcPeditKeyEx{}
|
||||
|
||||
tKey.Val = u32
|
||||
tKey.Off = 16
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP4
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
p.Sel.NKeys++
|
||||
}
|
||||
|
||||
// SetDstPort only tcp and udp are supported to set port
|
||||
func (p *TcPedit) SetDstPort(dstPort uint16, protocol uint8) {
|
||||
tKey := TcPeditKey{}
|
||||
tKeyEx := TcPeditKeyEx{}
|
||||
|
||||
switch protocol {
|
||||
case unix.IPPROTO_TCP:
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_TCP
|
||||
case unix.IPPROTO_UDP:
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_UDP
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
tKey.Val = uint32(Swap16(dstPort)) << 16
|
||||
tKey.Mask = 0x0000ffff
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
p.Sel.NKeys++
|
||||
}
|
||||
|
||||
// SetSrcPort only tcp and udp are supported to set port
|
||||
func (p *TcPedit) SetSrcPort(srcPort uint16, protocol uint8) {
|
||||
tKey := TcPeditKey{}
|
||||
tKeyEx := TcPeditKeyEx{}
|
||||
|
||||
switch protocol {
|
||||
case unix.IPPROTO_TCP:
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_TCP
|
||||
case unix.IPPROTO_UDP:
|
||||
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_UDP
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
|
||||
|
||||
tKey.Val = uint32(Swap16(srcPort))
|
||||
tKey.Mask = 0xffff0000
|
||||
p.Keys = append(p.Keys, tKey)
|
||||
p.KeysEx = append(p.KeysEx, tKeyEx)
|
||||
p.Sel.NKeys++
|
||||
}
|
||||
|
41
vendor/github.com/vishvananda/netlink/nl/vdpa_linux.go
generated
vendored
Normal file
41
vendor/github.com/vishvananda/netlink/nl/vdpa_linux.go
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
package nl
|
||||
|
||||
const (
|
||||
VDPA_GENL_NAME = "vdpa"
|
||||
VDPA_GENL_VERSION = 0x1
|
||||
)
|
||||
|
||||
const (
|
||||
VDPA_CMD_UNSPEC = iota
|
||||
VDPA_CMD_MGMTDEV_NEW
|
||||
VDPA_CMD_MGMTDEV_GET /* can dump */
|
||||
VDPA_CMD_DEV_NEW
|
||||
VDPA_CMD_DEV_DEL
|
||||
VDPA_CMD_DEV_GET /* can dump */
|
||||
VDPA_CMD_DEV_CONFIG_GET /* can dump */
|
||||
VDPA_CMD_DEV_VSTATS_GET
|
||||
)
|
||||
|
||||
const (
|
||||
VDPA_ATTR_UNSPEC = iota
|
||||
VDPA_ATTR_MGMTDEV_BUS_NAME
|
||||
VDPA_ATTR_MGMTDEV_DEV_NAME
|
||||
VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES
|
||||
VDPA_ATTR_DEV_NAME
|
||||
VDPA_ATTR_DEV_ID
|
||||
VDPA_ATTR_DEV_VENDOR_ID
|
||||
VDPA_ATTR_DEV_MAX_VQS
|
||||
VDPA_ATTR_DEV_MAX_VQ_SIZE
|
||||
VDPA_ATTR_DEV_MIN_VQ_SIZE
|
||||
VDPA_ATTR_DEV_NET_CFG_MACADDR
|
||||
VDPA_ATTR_DEV_NET_STATUS
|
||||
VDPA_ATTR_DEV_NET_CFG_MAX_VQP
|
||||
VDPA_ATTR_DEV_NET_CFG_MTU
|
||||
VDPA_ATTR_DEV_NEGOTIATED_FEATURES
|
||||
VDPA_ATTR_DEV_MGMTDEV_MAX_VQS
|
||||
VDPA_ATTR_DEV_SUPPORTED_FEATURES
|
||||
VDPA_ATTR_DEV_QUEUE_INDEX
|
||||
VDPA_ATTR_DEV_VENDOR_ATTR_NAME
|
||||
VDPA_ATTR_DEV_VENDOR_ATTR_VALUE
|
||||
VDPA_ATTR_DEV_FEATURES
|
||||
)
|
10
vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go
generated
vendored
10
vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go
generated
vendored
@ -131,7 +131,15 @@ func (x *XfrmAddress) ToIP() net.IP {
|
||||
return ip
|
||||
}
|
||||
|
||||
func (x *XfrmAddress) ToIPNet(prefixlen uint8) *net.IPNet {
|
||||
// family is only used when x and prefixlen are both 0
|
||||
func (x *XfrmAddress) ToIPNet(prefixlen uint8, family uint16) *net.IPNet {
|
||||
empty := [SizeofXfrmAddress]byte{}
|
||||
if bytes.Equal(x[:], empty[:]) && prefixlen == 0 {
|
||||
if family == FAMILY_V6 {
|
||||
return &net.IPNet{IP: net.ParseIP("::"), Mask: net.CIDRMask(int(prefixlen), 128)}
|
||||
}
|
||||
return &net.IPNet{IP: net.ParseIP("0.0.0.0"), Mask: net.CIDRMask(int(prefixlen), 32)}
|
||||
}
|
||||
ip := x.ToIP()
|
||||
if GetIPFamily(ip) == FAMILY_V4 {
|
||||
return &net.IPNet{IP: ip, Mask: net.CIDRMask(int(prefixlen), 32)}
|
||||
|
27
vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go
generated
vendored
27
vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go
generated
vendored
@ -15,6 +15,7 @@ const (
|
||||
SizeofXfrmEncapTmpl = 0x18
|
||||
SizeofXfrmUsersaFlush = 0x1
|
||||
SizeofXfrmReplayStateEsn = 0x18
|
||||
SizeofXfrmReplayState = 0x0c
|
||||
)
|
||||
|
||||
const (
|
||||
@ -28,6 +29,11 @@ const (
|
||||
XFRM_STATE_ESN = 128
|
||||
)
|
||||
|
||||
const (
|
||||
XFRM_SA_XFLAG_DONT_ENCAP_DSCP = 1
|
||||
XFRM_SA_XFLAG_OSEQ_MAY_WRAP = 2
|
||||
)
|
||||
|
||||
// struct xfrm_usersa_id {
|
||||
// xfrm_address_t daddr;
|
||||
// __be32 spi;
|
||||
@ -103,6 +109,7 @@ func (msg *XfrmStats) Serialize() []byte {
|
||||
// };
|
||||
//
|
||||
// #define XFRM_SA_XFLAG_DONT_ENCAP_DSCP 1
|
||||
// #define XFRM_SA_XFLAG_OSEQ_MAY_WRAP 2
|
||||
//
|
||||
|
||||
type XfrmUsersaInfo struct {
|
||||
@ -332,3 +339,23 @@ func (msg *XfrmReplayStateEsn) Serialize() []byte {
|
||||
// We deliberately do not pass Bmp, as it gets set by the kernel.
|
||||
return (*(*[SizeofXfrmReplayStateEsn]byte)(unsafe.Pointer(msg)))[:]
|
||||
}
|
||||
|
||||
// struct xfrm_replay_state {
|
||||
// __u32 oseq;
|
||||
// __u32 seq;
|
||||
// __u32 bitmap;
|
||||
// };
|
||||
|
||||
type XfrmReplayState struct {
|
||||
OSeq uint32
|
||||
Seq uint32
|
||||
BitMap uint32
|
||||
}
|
||||
|
||||
func DeserializeXfrmReplayState(b []byte) *XfrmReplayState {
|
||||
return (*XfrmReplayState)(unsafe.Pointer(&b[0:SizeofXfrmReplayState][0]))
|
||||
}
|
||||
|
||||
func (msg *XfrmReplayState) Serialize() []byte {
|
||||
return (*(*[SizeofXfrmReplayState]byte)(unsafe.Pointer(msg)))[:]
|
||||
}
|
||||
|
9
vendor/github.com/vishvananda/netlink/proc_event_linux.go
generated
vendored
9
vendor/github.com/vishvananda/netlink/proc_event_linux.go
generated
vendored
@ -63,15 +63,6 @@ type ExitProcEvent struct {
|
||||
ParentTgid uint32
|
||||
}
|
||||
|
||||
type ExitProcEvent2 struct {
|
||||
ProcessPid uint32
|
||||
ProcessTgid uint32
|
||||
ExitCode uint32
|
||||
ExitSignal uint32
|
||||
ParentPid uint32
|
||||
ParentTgid uint32
|
||||
}
|
||||
|
||||
func (e *ExitProcEvent) Pid() uint32 {
|
||||
return e.ProcessPid
|
||||
}
|
||||
|
24
vendor/github.com/vishvananda/netlink/protinfo.go
generated
vendored
24
vendor/github.com/vishvananda/netlink/protinfo.go
generated
vendored
@ -6,14 +6,16 @@ import (
|
||||
|
||||
// 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
|
||||
Hairpin bool
|
||||
Guard bool
|
||||
FastLeave bool
|
||||
RootBlock bool
|
||||
Learning bool
|
||||
Flood bool
|
||||
ProxyArp bool
|
||||
ProxyArpWiFi bool
|
||||
Isolated bool
|
||||
NeighSuppress bool
|
||||
}
|
||||
|
||||
// String returns a list of enabled flags
|
||||
@ -47,6 +49,12 @@ func (prot *Protinfo) String() string {
|
||||
if prot.ProxyArpWiFi {
|
||||
boolStrings = append(boolStrings, "ProxyArpWiFi")
|
||||
}
|
||||
if prot.Isolated {
|
||||
boolStrings = append(boolStrings, "Isolated")
|
||||
}
|
||||
if prot.NeighSuppress {
|
||||
boolStrings = append(boolStrings, "NeighSuppress")
|
||||
}
|
||||
return strings.Join(boolStrings, " ")
|
||||
}
|
||||
|
||||
|
4
vendor/github.com/vishvananda/netlink/protinfo_linux.go
generated
vendored
4
vendor/github.com/vishvananda/netlink/protinfo_linux.go
generated
vendored
@ -68,6 +68,10 @@ func parseProtinfo(infos []syscall.NetlinkRouteAttr) (pi Protinfo) {
|
||||
pi.ProxyArp = byteToBool(info.Value[0])
|
||||
case nl.IFLA_BRPORT_PROXYARP_WIFI:
|
||||
pi.ProxyArpWiFi = byteToBool(info.Value[0])
|
||||
case nl.IFLA_BRPORT_ISOLATED:
|
||||
pi.Isolated = byteToBool(info.Value[0])
|
||||
case nl.IFLA_BRPORT_NEIGH_SUPPRESS:
|
||||
pi.NeighSuppress = byteToBool(info.Value[0])
|
||||
}
|
||||
}
|
||||
return
|
||||
|
52
vendor/github.com/vishvananda/netlink/qdisc.go
generated
vendored
52
vendor/github.com/vishvananda/netlink/qdisc.go
generated
vendored
@ -17,19 +17,29 @@ const (
|
||||
HANDLE_MIN_EGRESS = 0xFFFFFFF3
|
||||
)
|
||||
|
||||
const (
|
||||
HORIZON_DROP_POLICY_CAP = 0
|
||||
HORIZON_DROP_POLICY_DROP = 1
|
||||
HORIZON_DROP_POLICY_DEFAULT = 255
|
||||
)
|
||||
|
||||
type Qdisc interface {
|
||||
Attrs() *QdiscAttrs
|
||||
Type() string
|
||||
}
|
||||
|
||||
type QdiscStatistics ClassStatistics
|
||||
|
||||
// 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
|
||||
LinkIndex int
|
||||
Handle uint32
|
||||
Parent uint32
|
||||
Refcnt uint32 // read only
|
||||
IngressBlock *uint32
|
||||
Statistics *QdiscStatistics
|
||||
}
|
||||
|
||||
func (q QdiscAttrs) String() string {
|
||||
@ -113,6 +123,7 @@ type Htb struct {
|
||||
Defcls uint32
|
||||
Debug uint32
|
||||
DirectPkts uint32
|
||||
DirectQlen *uint32
|
||||
}
|
||||
|
||||
func NewHtb(attrs QdiscAttrs) *Htb {
|
||||
@ -123,6 +134,7 @@ func NewHtb(attrs QdiscAttrs) *Htb {
|
||||
Rate2Quantum: 10,
|
||||
Debug: 0,
|
||||
DirectPkts: 0,
|
||||
DirectQlen: nil,
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,6 +162,7 @@ type NetemQdiscAttrs struct {
|
||||
ReorderCorr float32 // in %
|
||||
CorruptProb float32 // in %
|
||||
CorruptCorr float32 // in %
|
||||
Rate64 uint64
|
||||
}
|
||||
|
||||
func (q NetemQdiscAttrs) String() string {
|
||||
@ -174,6 +187,7 @@ type Netem struct {
|
||||
ReorderCorr uint32
|
||||
CorruptProb uint32
|
||||
CorruptCorr uint32
|
||||
Rate64 uint64
|
||||
}
|
||||
|
||||
func (netem *Netem) String() string {
|
||||
@ -210,6 +224,19 @@ func (qdisc *Tbf) Type() string {
|
||||
return "tbf"
|
||||
}
|
||||
|
||||
// Clsact is a qdisc for adding filters
|
||||
type Clsact struct {
|
||||
QdiscAttrs
|
||||
}
|
||||
|
||||
func (qdisc *Clsact) Attrs() *QdiscAttrs {
|
||||
return &qdisc.QdiscAttrs
|
||||
}
|
||||
|
||||
func (qdisc *Clsact) Type() string {
|
||||
return "clsact"
|
||||
}
|
||||
|
||||
// Ingress is a qdisc for adding ingress filters
|
||||
type Ingress struct {
|
||||
QdiscAttrs
|
||||
@ -278,22 +305,25 @@ type Fq struct {
|
||||
FlowDefaultRate uint32
|
||||
FlowMaxRate uint32
|
||||
// called BucketsLog under the hood
|
||||
Buckets uint32
|
||||
FlowRefillDelay uint32
|
||||
LowRateThreshold uint32
|
||||
Buckets uint32
|
||||
FlowRefillDelay uint32
|
||||
LowRateThreshold uint32
|
||||
Horizon uint32
|
||||
HorizonDropPolicy uint8
|
||||
}
|
||||
|
||||
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,
|
||||
"{PacketLimit: %v, FlowPacketLimit: %v, Quantum: %v, InitialQuantum: %v, Pacing: %v, FlowDefaultRate: %v, FlowMaxRate: %v, Buckets: %v, FlowRefillDelay: %v, LowRateThreshold: %v, Horizon: %v, HorizonDropPolicy: %v}",
|
||||
fq.PacketLimit, fq.FlowPacketLimit, fq.Quantum, fq.InitialQuantum, fq.Pacing, fq.FlowDefaultRate, fq.FlowMaxRate, fq.Buckets, fq.FlowRefillDelay, fq.LowRateThreshold, fq.Horizon, fq.HorizonDropPolicy,
|
||||
)
|
||||
}
|
||||
|
||||
func NewFq(attrs QdiscAttrs) *Fq {
|
||||
return &Fq{
|
||||
QdiscAttrs: attrs,
|
||||
Pacing: 1,
|
||||
QdiscAttrs: attrs,
|
||||
Pacing: 1,
|
||||
HorizonDropPolicy: HORIZON_DROP_POLICY_DEFAULT,
|
||||
}
|
||||
}
|
||||
|
||||
|
82
vendor/github.com/vishvananda/netlink/qdisc_linux.go
generated
vendored
82
vendor/github.com/vishvananda/netlink/qdisc_linux.go
generated
vendored
@ -5,6 +5,7 @@ import (
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
@ -17,6 +18,7 @@ func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem {
|
||||
var lossCorr, delayCorr, duplicateCorr uint32
|
||||
var reorderProb, reorderCorr uint32
|
||||
var corruptProb, corruptCorr uint32
|
||||
var rate64 uint64
|
||||
|
||||
latency := nattrs.Latency
|
||||
loss := Percentage2u32(nattrs.Loss)
|
||||
@ -57,6 +59,7 @@ func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem {
|
||||
|
||||
corruptProb = Percentage2u32(nattrs.CorruptProb)
|
||||
corruptCorr = Percentage2u32(nattrs.CorruptCorr)
|
||||
rate64 = nattrs.Rate64
|
||||
|
||||
return &Netem{
|
||||
QdiscAttrs: attrs,
|
||||
@ -73,6 +76,7 @@ func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem {
|
||||
ReorderCorr: reorderCorr,
|
||||
CorruptProb: corruptProb,
|
||||
CorruptCorr: corruptCorr,
|
||||
Rate64: rate64,
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,6 +163,9 @@ func (h *Handle) qdiscModify(cmd, flags int, qdisc Qdisc) error {
|
||||
func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
|
||||
|
||||
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(qdisc.Type())))
|
||||
if qdisc.Attrs().IngressBlock != nil {
|
||||
req.AddData(nl.NewRtAttr(nl.TCA_INGRESS_BLOCK, nl.Uint32Attr(*qdisc.Attrs().IngressBlock)))
|
||||
}
|
||||
|
||||
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
|
||||
|
||||
@ -194,7 +201,9 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
|
||||
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())
|
||||
if qdisc.DirectQlen != nil {
|
||||
options.AddRtAttr(nl.TCA_HTB_DIRECT_QLEN, nl.Uint32Attr(*qdisc.DirectQlen))
|
||||
}
|
||||
case *Hfsc:
|
||||
opt := nl.TcHfscOpt{}
|
||||
opt.Defcls = qdisc.Defcls
|
||||
@ -231,6 +240,19 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
|
||||
if reorder.Probability > 0 {
|
||||
options.AddRtAttr(nl.TCA_NETEM_REORDER, reorder.Serialize())
|
||||
}
|
||||
// Rate
|
||||
if qdisc.Rate64 > 0 {
|
||||
rate := nl.TcNetemRate{}
|
||||
if qdisc.Rate64 >= uint64(1<<32) {
|
||||
options.AddRtAttr(nl.TCA_NETEM_RATE64, nl.Uint64Attr(qdisc.Rate64))
|
||||
rate.Rate = ^uint32(0)
|
||||
} else {
|
||||
rate.Rate = uint32(qdisc.Rate64)
|
||||
}
|
||||
options.AddRtAttr(nl.TCA_NETEM_RATE, rate.Serialize())
|
||||
}
|
||||
case *Clsact:
|
||||
options = nil
|
||||
case *Ingress:
|
||||
// ingress filters must use the proper handle
|
||||
if qdisc.Attrs().Parent != HANDLE_INGRESS {
|
||||
@ -265,6 +287,9 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
|
||||
if qdisc.Buckets > 0 {
|
||||
options.AddRtAttr(nl.TCA_FQ_BUCKETS_LOG, nl.Uint32Attr((uint32(qdisc.Buckets))))
|
||||
}
|
||||
if qdisc.PacketLimit > 0 {
|
||||
options.AddRtAttr(nl.TCA_FQ_PLIMIT, nl.Uint32Attr((uint32(qdisc.PacketLimit))))
|
||||
}
|
||||
if qdisc.LowRateThreshold > 0 {
|
||||
options.AddRtAttr(nl.TCA_FQ_LOW_RATE_THRESHOLD, nl.Uint32Attr((uint32(qdisc.LowRateThreshold))))
|
||||
}
|
||||
@ -286,6 +311,12 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
|
||||
if qdisc.FlowDefaultRate > 0 {
|
||||
options.AddRtAttr(nl.TCA_FQ_FLOW_DEFAULT_RATE, nl.Uint32Attr((uint32(qdisc.FlowDefaultRate))))
|
||||
}
|
||||
if qdisc.Horizon > 0 {
|
||||
options.AddRtAttr(nl.TCA_FQ_HORIZON, nl.Uint32Attr(qdisc.Horizon))
|
||||
}
|
||||
if qdisc.HorizonDropPolicy != HORIZON_DROP_POLICY_DEFAULT {
|
||||
options.AddRtAttr(nl.TCA_FQ_HORIZON_DROP, nl.Uint8Attr(qdisc.HorizonDropPolicy))
|
||||
}
|
||||
case *Sfq:
|
||||
opt := nl.TcSfqQoptV1{}
|
||||
opt.TcSfqQopt.Quantum = qdisc.Quantum
|
||||
@ -380,6 +411,8 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
|
||||
qdisc = &Netem{}
|
||||
case "sfq":
|
||||
qdisc = &Sfq{}
|
||||
case "clsact":
|
||||
qdisc = &Clsact{}
|
||||
default:
|
||||
qdisc = &GenericQdisc{QdiscType: qdiscType}
|
||||
}
|
||||
@ -442,6 +475,22 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
|
||||
|
||||
// no options for ingress
|
||||
}
|
||||
case nl.TCA_INGRESS_BLOCK:
|
||||
ingressBlock := new(uint32)
|
||||
*ingressBlock = native.Uint32(attr.Value)
|
||||
base.IngressBlock = ingressBlock
|
||||
case nl.TCA_STATS:
|
||||
s, err := parseTcStats(attr.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
base.Statistics = (*QdiscStatistics)(s)
|
||||
case nl.TCA_STATS2:
|
||||
s, err := parseTcStats2(attr.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
base.Statistics = (*QdiscStatistics)(s)
|
||||
}
|
||||
}
|
||||
*qdisc.Attrs() = base
|
||||
@ -479,8 +528,8 @@ func parseHtbData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
|
||||
htb.Debug = opt.Debug
|
||||
htb.DirectPkts = opt.DirectPkts
|
||||
case nl.TCA_HTB_DIRECT_QLEN:
|
||||
// TODO
|
||||
//htb.DirectQlen = native.uint32(datum.Value)
|
||||
directQlen := native.Uint32(datum.Value)
|
||||
htb.DirectQlen = &directQlen
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -546,6 +595,11 @@ func parseFqData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
|
||||
fq.FlowMaxRate = native.Uint32(datum.Value)
|
||||
case nl.TCA_FQ_FLOW_DEFAULT_RATE:
|
||||
fq.FlowDefaultRate = native.Uint32(datum.Value)
|
||||
case nl.TCA_FQ_HORIZON:
|
||||
fq.Horizon = native.Uint32(datum.Value)
|
||||
case nl.TCA_FQ_HORIZON_DROP:
|
||||
fq.HorizonDropPolicy = datum.Value[0]
|
||||
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -564,6 +618,8 @@ func parseNetemData(qdisc Qdisc, value []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var rate *nl.TcNetemRate
|
||||
var rate64 uint64
|
||||
for _, datum := range data {
|
||||
switch datum.Attr.Type {
|
||||
case nl.TCA_NETEM_CORR:
|
||||
@ -579,8 +635,19 @@ func parseNetemData(qdisc Qdisc, value []byte) error {
|
||||
opt := nl.DeserializeTcNetemReorder(datum.Value)
|
||||
netem.ReorderProb = opt.Probability
|
||||
netem.ReorderCorr = opt.Correlation
|
||||
case nl.TCA_NETEM_RATE:
|
||||
rate = nl.DeserializeTcNetemRate(datum.Value)
|
||||
case nl.TCA_NETEM_RATE64:
|
||||
rate64 = native.Uint64(datum.Value)
|
||||
}
|
||||
}
|
||||
if rate != nil {
|
||||
netem.Rate64 = uint64(rate.Rate)
|
||||
if rate64 > 0 {
|
||||
netem.Rate64 = rate64
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -624,6 +691,9 @@ var (
|
||||
tickInUsec float64
|
||||
clockFactor float64
|
||||
hz float64
|
||||
|
||||
// Without this, the go race detector may report races.
|
||||
initClockMutex sync.Mutex
|
||||
)
|
||||
|
||||
func initClock() {
|
||||
@ -658,6 +728,8 @@ func initClock() {
|
||||
}
|
||||
|
||||
func TickInUsec() float64 {
|
||||
initClockMutex.Lock()
|
||||
defer initClockMutex.Unlock()
|
||||
if tickInUsec == 0.0 {
|
||||
initClock()
|
||||
}
|
||||
@ -665,6 +737,8 @@ func TickInUsec() float64 {
|
||||
}
|
||||
|
||||
func ClockFactor() float64 {
|
||||
initClockMutex.Lock()
|
||||
defer initClockMutex.Unlock()
|
||||
if clockFactor == 0.0 {
|
||||
initClock()
|
||||
}
|
||||
@ -672,6 +746,8 @@ func ClockFactor() float64 {
|
||||
}
|
||||
|
||||
func Hz() float64 {
|
||||
initClockMutex.Lock()
|
||||
defer initClockMutex.Unlock()
|
||||
if hz == 0.0 {
|
||||
initClock()
|
||||
}
|
||||
|
9
vendor/github.com/vishvananda/netlink/route.go
generated
vendored
9
vendor/github.com/vishvananda/netlink/route.go
generated
vendored
@ -154,8 +154,15 @@ type flagString struct {
|
||||
}
|
||||
|
||||
// RouteUpdate is sent when a route changes - type is RTM_NEWROUTE or RTM_DELROUTE
|
||||
|
||||
// NlFlags is only non-zero for RTM_NEWROUTE, the following flags can be set:
|
||||
// - unix.NLM_F_REPLACE - Replace existing matching config object with this request
|
||||
// - unix.NLM_F_EXCL - Don't replace the config object if it already exists
|
||||
// - unix.NLM_F_CREATE - Create config object if it doesn't already exist
|
||||
// - unix.NLM_F_APPEND - Add to the end of the object list
|
||||
type RouteUpdate struct {
|
||||
Type uint16
|
||||
Type uint16
|
||||
NlFlags uint16
|
||||
Route
|
||||
}
|
||||
|
||||
|
428
vendor/github.com/vishvananda/netlink/route_linux.go
generated
vendored
428
vendor/github.com/vishvananda/netlink/route_linux.go
generated
vendored
@ -41,7 +41,6 @@ func (s Scope) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const (
|
||||
FLAG_ONLINK NextHopFlag = unix.RTNH_F_ONLINK
|
||||
FLAG_PERVASIVE NextHopFlag = unix.RTNH_F_PERVASIVE
|
||||
@ -274,6 +273,16 @@ type SEG6LocalEncap struct {
|
||||
In6Addr net.IP
|
||||
Iif int
|
||||
Oif int
|
||||
bpf bpfObj
|
||||
}
|
||||
|
||||
func (e *SEG6LocalEncap) SetProg(progFd int, progName string) error {
|
||||
if progFd <= 0 {
|
||||
return fmt.Errorf("seg6local bpf SetProg: invalid fd")
|
||||
}
|
||||
e.bpf.progFd = progFd
|
||||
e.bpf.progName = progName
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *SEG6LocalEncap) Type() int {
|
||||
@ -307,6 +316,22 @@ func (e *SEG6LocalEncap) Decode(buf []byte) error {
|
||||
case nl.SEG6_LOCAL_OIF:
|
||||
e.Oif = int(native.Uint32(attr.Value[0:4]))
|
||||
e.Flags[nl.SEG6_LOCAL_OIF] = true
|
||||
case nl.SEG6_LOCAL_BPF:
|
||||
var bpfAttrs []syscall.NetlinkRouteAttr
|
||||
bpfAttrs, err = nl.ParseRouteAttr(attr.Value)
|
||||
bpfobj := bpfObj{}
|
||||
for _, bpfAttr := range bpfAttrs {
|
||||
switch bpfAttr.Attr.Type {
|
||||
case nl.LWT_BPF_PROG_FD:
|
||||
bpfobj.progFd = int(native.Uint32(bpfAttr.Value))
|
||||
case nl.LWT_BPF_PROG_NAME:
|
||||
bpfobj.progName = string(bpfAttr.Value)
|
||||
default:
|
||||
err = fmt.Errorf("seg6local bpf decode: unknown attribute: Type %d", bpfAttr.Attr)
|
||||
}
|
||||
}
|
||||
e.bpf = bpfobj
|
||||
e.Flags[nl.SEG6_LOCAL_BPF] = true
|
||||
}
|
||||
}
|
||||
return err
|
||||
@ -368,6 +393,16 @@ func (e *SEG6LocalEncap) Encode() ([]byte, error) {
|
||||
native.PutUint32(attr[4:], uint32(e.Oif))
|
||||
res = append(res, attr...)
|
||||
}
|
||||
if e.Flags[nl.SEG6_LOCAL_BPF] {
|
||||
attr := nl.NewRtAttr(nl.SEG6_LOCAL_BPF, []byte{})
|
||||
if e.bpf.progFd != 0 {
|
||||
attr.AddRtAttr(nl.LWT_BPF_PROG_FD, nl.Uint32Attr(uint32(e.bpf.progFd)))
|
||||
}
|
||||
if e.bpf.progName != "" {
|
||||
attr.AddRtAttr(nl.LWT_BPF_PROG_NAME, nl.ZeroTerminated(e.bpf.progName))
|
||||
}
|
||||
res = append(res, attr.Serialize()...)
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
func (e *SEG6LocalEncap) String() string {
|
||||
@ -401,12 +436,15 @@ func (e *SEG6LocalEncap) String() string {
|
||||
}
|
||||
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.
|
||||
// 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, e.Segments[i-1].String())
|
||||
}
|
||||
strs = append(strs, fmt.Sprintf("segs %d [ %s ]", len(e.Segments), strings.Join(segs, " ")))
|
||||
}
|
||||
if e.Flags[nl.SEG6_LOCAL_BPF] {
|
||||
strs = append(strs, fmt.Sprintf("bpf %s[%d]", e.bpf.progName, e.bpf.progFd))
|
||||
}
|
||||
return strings.Join(strs, " ")
|
||||
}
|
||||
func (e *SEG6LocalEncap) Equal(x Encap) bool {
|
||||
@ -438,7 +476,7 @@ func (e *SEG6LocalEncap) Equal(x Encap) bool {
|
||||
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 {
|
||||
if e.Action != o.Action || e.Table != o.Table || e.Iif != o.Iif || e.Oif != o.Oif || e.bpf != o.bpf {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@ -590,6 +628,109 @@ func (e *BpfEncap) Equal(x Encap) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IP6tnlEncap definition
|
||||
type IP6tnlEncap struct {
|
||||
ID uint64
|
||||
Dst net.IP
|
||||
Src net.IP
|
||||
Hoplimit uint8
|
||||
TC uint8
|
||||
Flags uint16
|
||||
}
|
||||
|
||||
func (e *IP6tnlEncap) Type() int {
|
||||
return nl.LWTUNNEL_ENCAP_IP6
|
||||
}
|
||||
|
||||
func (e *IP6tnlEncap) Decode(buf []byte) error {
|
||||
attrs, err := nl.ParseRouteAttr(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, attr := range attrs {
|
||||
switch attr.Attr.Type {
|
||||
case nl.LWTUNNEL_IP6_ID:
|
||||
e.ID = uint64(native.Uint64(attr.Value[0:4]))
|
||||
case nl.LWTUNNEL_IP6_DST:
|
||||
e.Dst = net.IP(attr.Value[:])
|
||||
case nl.LWTUNNEL_IP6_SRC:
|
||||
e.Src = net.IP(attr.Value[:])
|
||||
case nl.LWTUNNEL_IP6_HOPLIMIT:
|
||||
e.Hoplimit = attr.Value[0]
|
||||
case nl.LWTUNNEL_IP6_TC:
|
||||
// e.TC = attr.Value[0]
|
||||
err = fmt.Errorf("decoding TC in IP6tnlEncap is not supported")
|
||||
case nl.LWTUNNEL_IP6_FLAGS:
|
||||
// e.Flags = uint16(native.Uint16(attr.Value[0:2]))
|
||||
err = fmt.Errorf("decoding FLAG in IP6tnlEncap is not supported")
|
||||
case nl.LWTUNNEL_IP6_PAD:
|
||||
err = fmt.Errorf("decoding PAD in IP6tnlEncap is not supported")
|
||||
case nl.LWTUNNEL_IP6_OPTS:
|
||||
err = fmt.Errorf("decoding OPTS in IP6tnlEncap is not supported")
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (e *IP6tnlEncap) Encode() ([]byte, error) {
|
||||
|
||||
final := []byte{}
|
||||
|
||||
resID := make([]byte, 12)
|
||||
native.PutUint16(resID, 12) // 2+2+8
|
||||
native.PutUint16(resID[2:], nl.LWTUNNEL_IP6_ID)
|
||||
native.PutUint64(resID[4:], 0)
|
||||
final = append(final, resID...)
|
||||
|
||||
resDst := make([]byte, 4)
|
||||
native.PutUint16(resDst, 20) // 2+2+16
|
||||
native.PutUint16(resDst[2:], nl.LWTUNNEL_IP6_DST)
|
||||
resDst = append(resDst, e.Dst...)
|
||||
final = append(final, resDst...)
|
||||
|
||||
resSrc := make([]byte, 4)
|
||||
native.PutUint16(resSrc, 20)
|
||||
native.PutUint16(resSrc[2:], nl.LWTUNNEL_IP6_SRC)
|
||||
resSrc = append(resSrc, e.Src...)
|
||||
final = append(final, resSrc...)
|
||||
|
||||
// resTc := make([]byte, 5)
|
||||
// native.PutUint16(resTc, 5)
|
||||
// native.PutUint16(resTc[2:], nl.LWTUNNEL_IP6_TC)
|
||||
// resTc[4] = e.TC
|
||||
// final = append(final,resTc...)
|
||||
|
||||
resHops := make([]byte, 5)
|
||||
native.PutUint16(resHops, 5)
|
||||
native.PutUint16(resHops[2:], nl.LWTUNNEL_IP6_HOPLIMIT)
|
||||
resHops[4] = e.Hoplimit
|
||||
final = append(final, resHops...)
|
||||
|
||||
// resFlags := make([]byte, 6)
|
||||
// native.PutUint16(resFlags, 6)
|
||||
// native.PutUint16(resFlags[2:], nl.LWTUNNEL_IP6_FLAGS)
|
||||
// native.PutUint16(resFlags[4:], e.Flags)
|
||||
// final = append(final,resFlags...)
|
||||
|
||||
return final, nil
|
||||
}
|
||||
|
||||
func (e *IP6tnlEncap) String() string {
|
||||
return fmt.Sprintf("id %d src %s dst %s hoplimit %d tc %d flags 0x%.4x", e.ID, e.Src, e.Dst, e.Hoplimit, e.TC, e.Flags)
|
||||
}
|
||||
|
||||
func (e *IP6tnlEncap) Equal(x Encap) bool {
|
||||
o, ok := x.(*IP6tnlEncap)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if e.ID != o.ID || e.Flags != o.Flags || e.Hoplimit != o.Hoplimit || e.Src.Equal(o.Src) || e.Dst.Equal(o.Dst) || e.TC != o.TC {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
type Via struct {
|
||||
AddrFamily int
|
||||
Addr net.IP
|
||||
@ -656,7 +797,8 @@ func RouteAdd(route *Route) error {
|
||||
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())
|
||||
_, err := h.routeHandle(route, req, nl.NewRtMsg())
|
||||
return err
|
||||
}
|
||||
|
||||
// RouteAppend will append a route to the system.
|
||||
@ -670,7 +812,8 @@ func RouteAppend(route *Route) error {
|
||||
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())
|
||||
_, err := h.routeHandle(route, req, nl.NewRtMsg())
|
||||
return err
|
||||
}
|
||||
|
||||
// RouteAddEcmp will add a route to the system.
|
||||
@ -682,7 +825,23 @@ func RouteAddEcmp(route *Route) error {
|
||||
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())
|
||||
_, err := h.routeHandle(route, req, nl.NewRtMsg())
|
||||
return err
|
||||
}
|
||||
|
||||
// RouteChange will change an existing route in the system.
|
||||
// Equivalent to: `ip route change $route`
|
||||
func RouteChange(route *Route) error {
|
||||
return pkgHandle.RouteChange(route)
|
||||
}
|
||||
|
||||
// RouteChange will change an existing route in the system.
|
||||
// Equivalent to: `ip route change $route`
|
||||
func (h *Handle) RouteChange(route *Route) error {
|
||||
flags := unix.NLM_F_REPLACE | unix.NLM_F_ACK
|
||||
req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
|
||||
_, err := h.routeHandle(route, req, nl.NewRtMsg())
|
||||
return err
|
||||
}
|
||||
|
||||
// RouteReplace will add a route to the system.
|
||||
@ -696,7 +855,8 @@ func RouteReplace(route *Route) error {
|
||||
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())
|
||||
_, err := h.routeHandle(route, req, nl.NewRtMsg())
|
||||
return err
|
||||
}
|
||||
|
||||
// RouteDel will delete a route from the system.
|
||||
@ -709,12 +869,27 @@ func RouteDel(route *Route) error {
|
||||
// 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())
|
||||
_, err := h.routeHandle(route, req, nl.NewRtDelMsg())
|
||||
return err
|
||||
}
|
||||
|
||||
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")
|
||||
func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) ([][]byte, error) {
|
||||
if err := h.prepareRouteReq(route, req, msg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
}
|
||||
|
||||
func (h *Handle) routeHandleIter(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg, f func(msg []byte) bool) error {
|
||||
if err := h.prepareRouteReq(route, req, msg); err != nil {
|
||||
return err
|
||||
}
|
||||
return req.ExecuteIter(unix.NETLINK_ROUTE, 0, f)
|
||||
}
|
||||
|
||||
func (h *Handle) prepareRouteReq(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error {
|
||||
if req.NlMsghdr.Type != unix.RTM_GETROUTE && (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil && route.MPLSDst == nil {
|
||||
return fmt.Errorf("either Dst.IP, Src.IP or Gw must be set")
|
||||
}
|
||||
|
||||
family := -1
|
||||
@ -968,19 +1143,21 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
|
||||
|
||||
msg.Flags = uint32(route.Flags)
|
||||
msg.Scope = uint8(route.Scope)
|
||||
msg.Family = uint8(family)
|
||||
// only overwrite family if it was not set in msg
|
||||
if msg.Family == 0 {
|
||||
msg.Family = uint8(family)
|
||||
}
|
||||
req.AddData(msg)
|
||||
for _, attr := range rtAttrs {
|
||||
req.AddData(attr)
|
||||
}
|
||||
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(route.LinkIndex))
|
||||
|
||||
req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
if (req.NlMsghdr.Type != unix.RTM_GETROUTE) || (req.NlMsghdr.Type == unix.RTM_GETROUTE && route.LinkIndex > 0) {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(route.LinkIndex))
|
||||
req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RouteList gets a list of routes in the system.
|
||||
@ -994,13 +1171,13 @@ func RouteList(link Link, family int) ([]Route, error) {
|
||||
// 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
|
||||
routeFilter := &Route{}
|
||||
if link != nil {
|
||||
routeFilter = &Route{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
}
|
||||
routeFilter.LinkIndex = link.Attrs().Index
|
||||
|
||||
return h.RouteListFiltered(family, routeFilter, RT_FILTER_OIF)
|
||||
}
|
||||
return h.RouteListFiltered(family, routeFilter, RT_FILTER_OIF)
|
||||
return h.RouteListFiltered(family, routeFilter, 0)
|
||||
}
|
||||
|
||||
// RouteListFiltered gets a list of routes in the system filtered with specified rules.
|
||||
@ -1012,68 +1189,94 @@ func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, e
|
||||
// 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)
|
||||
rtmsg := nl.NewRtMsg()
|
||||
rtmsg.Family = uint8(family)
|
||||
req.AddData(rtmsg)
|
||||
|
||||
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE)
|
||||
var res []Route
|
||||
err := h.RouteListFilteredIter(family, filter, filterMask, func(route Route) (cont bool) {
|
||||
res = append(res, route)
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
var res []Route
|
||||
for _, m := range msgs {
|
||||
// RouteListFilteredIter passes each route that matches the filter to the given iterator func. Iteration continues
|
||||
// until all routes are loaded or the func returns false.
|
||||
func RouteListFilteredIter(family int, filter *Route, filterMask uint64, f func(Route) (cont bool)) error {
|
||||
return pkgHandle.RouteListFilteredIter(family, filter, filterMask, f)
|
||||
}
|
||||
|
||||
func (h *Handle) RouteListFilteredIter(family int, filter *Route, filterMask uint64, f func(Route) (cont bool)) error {
|
||||
req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_DUMP)
|
||||
rtmsg := &nl.RtMsg{}
|
||||
rtmsg.Family = uint8(family)
|
||||
|
||||
var parseErr error
|
||||
err := h.routeHandleIter(filter, req, rtmsg, func(m []byte) bool {
|
||||
msg := nl.DeserializeRtMsg(m)
|
||||
if family != FAMILY_ALL && msg.Family != uint8(family) {
|
||||
// Ignore routes not matching requested family
|
||||
return true
|
||||
}
|
||||
if msg.Flags&unix.RTM_F_CLONED != 0 {
|
||||
// Ignore cloned routes
|
||||
continue
|
||||
return true
|
||||
}
|
||||
if msg.Table != unix.RT_TABLE_MAIN {
|
||||
if filter == nil || filter != nil && filterMask&RT_FILTER_TABLE == 0 {
|
||||
if filter == nil || filterMask&RT_FILTER_TABLE == 0 {
|
||||
// Ignore non-main tables
|
||||
continue
|
||||
return true
|
||||
}
|
||||
}
|
||||
route, err := deserializeRoute(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
parseErr = err
|
||||
return false
|
||||
}
|
||||
if filter != nil {
|
||||
switch {
|
||||
case filterMask&RT_FILTER_TABLE != 0 && filter.Table != unix.RT_TABLE_UNSPEC && route.Table != filter.Table:
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_PROTOCOL != 0 && route.Protocol != filter.Protocol:
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_SCOPE != 0 && route.Scope != filter.Scope:
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_TYPE != 0 && route.Type != filter.Type:
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_TOS != 0 && route.Tos != filter.Tos:
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_REALM != 0 && route.Realm != filter.Realm:
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_OIF != 0 && route.LinkIndex != filter.LinkIndex:
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_IIF != 0 && route.ILinkIndex != filter.ILinkIndex:
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_GW != 0 && !route.Gw.Equal(filter.Gw):
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_SRC != 0 && !route.Src.Equal(filter.Src):
|
||||
continue
|
||||
return true
|
||||
case filterMask&RT_FILTER_DST != 0:
|
||||
if filter.MPLSDst == nil || route.MPLSDst == nil || (*filter.MPLSDst) != (*route.MPLSDst) {
|
||||
if filter.Dst == nil {
|
||||
filter.Dst = genZeroIPNet(family)
|
||||
}
|
||||
if !ipNetEqual(route.Dst, filter.Dst) {
|
||||
continue
|
||||
return true
|
||||
}
|
||||
}
|
||||
case filterMask&RT_FILTER_HOPLIMIT != 0 && route.Hoplimit != filter.Hoplimit:
|
||||
continue
|
||||
return true
|
||||
}
|
||||
}
|
||||
res = append(res, route)
|
||||
return f(route)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return res, nil
|
||||
if parseErr != nil {
|
||||
return parseErr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// deserializeRoute decodes a binary netlink message into a Route struct
|
||||
@ -1257,6 +1460,27 @@ func deserializeRoute(m []byte) (Route, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Same logic to generate "default" dst with iproute2 implementation
|
||||
if route.Dst == nil {
|
||||
var addLen int
|
||||
var ip net.IP
|
||||
switch msg.Family {
|
||||
case FAMILY_V4:
|
||||
addLen = net.IPv4len
|
||||
ip = net.IPv4zero
|
||||
case FAMILY_V6:
|
||||
addLen = net.IPv6len
|
||||
ip = net.IPv6zero
|
||||
}
|
||||
|
||||
if addLen != 0 {
|
||||
route.Dst = &net.IPNet{
|
||||
IP: ip,
|
||||
Mask: net.CIDRMask(int(msg.Dst_len), 8*addLen),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(encap.Value) != 0 && len(encapType.Value) != 0 {
|
||||
typ := int(native.Uint16(encapType.Value[0:2]))
|
||||
var e Encap
|
||||
@ -1291,10 +1515,14 @@ func deserializeRoute(m []byte) (Route, error) {
|
||||
// RouteGetOptions contains a set of options to use with
|
||||
// RouteGetWithOptions
|
||||
type RouteGetOptions struct {
|
||||
Iif string
|
||||
Oif string
|
||||
VrfName string
|
||||
SrcAddr net.IP
|
||||
Iif string
|
||||
IifIndex int
|
||||
Oif string
|
||||
VrfName string
|
||||
SrcAddr net.IP
|
||||
UID *uint32
|
||||
Mark uint32
|
||||
FIBMatch bool
|
||||
}
|
||||
|
||||
// RouteGetWithOptions gets a route to a specific destination from the host system.
|
||||
@ -1330,6 +1558,9 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
|
||||
msg.Src_len = bitlen
|
||||
}
|
||||
msg.Flags = unix.RTM_F_LOOKUP_TABLE
|
||||
if options != nil && options.FIBMatch {
|
||||
msg.Flags |= unix.RTM_F_FIB_MATCH
|
||||
}
|
||||
req.AddData(msg)
|
||||
|
||||
rtaDst := nl.NewRtAttr(unix.RTA_DST, destinationData)
|
||||
@ -1337,7 +1568,7 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
|
||||
|
||||
if options != nil {
|
||||
if options.VrfName != "" {
|
||||
link, err := LinkByName(options.VrfName)
|
||||
link, err := h.LinkByName(options.VrfName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -1347,20 +1578,27 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
|
||||
req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
|
||||
}
|
||||
|
||||
iifIndex := 0
|
||||
if len(options.Iif) > 0 {
|
||||
link, err := LinkByName(options.Iif)
|
||||
link, err := h.LinkByName(options.Iif)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iifIndex = link.Attrs().Index
|
||||
} else if options.IifIndex > 0 {
|
||||
iifIndex = options.IifIndex
|
||||
}
|
||||
|
||||
if iifIndex > 0 {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(link.Attrs().Index))
|
||||
native.PutUint32(b, uint32(iifIndex))
|
||||
|
||||
req.AddData(nl.NewRtAttr(unix.RTA_IIF, b))
|
||||
}
|
||||
|
||||
if len(options.Oif) > 0 {
|
||||
link, err := LinkByName(options.Oif)
|
||||
link, err := h.LinkByName(options.Oif)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -1381,6 +1619,21 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
|
||||
|
||||
req.AddData(nl.NewRtAttr(unix.RTA_SRC, srcAddr))
|
||||
}
|
||||
|
||||
if options.UID != nil {
|
||||
uid := *options.UID
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uid)
|
||||
|
||||
req.AddData(nl.NewRtAttr(unix.RTA_UID, b))
|
||||
}
|
||||
|
||||
if options.Mark > 0 {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, options.Mark)
|
||||
|
||||
req.AddData(nl.NewRtAttr(unix.RTA_MARK, b))
|
||||
}
|
||||
}
|
||||
|
||||
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE)
|
||||
@ -1408,21 +1661,24 @@ func (h *Handle) RouteGet(destination net.IP) ([]Route, error) {
|
||||
// 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)
|
||||
return routeSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0, 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)
|
||||
return routeSubscribeAt(ns, netns.None(), ch, done, nil, false, 0, nil, false)
|
||||
}
|
||||
|
||||
// RouteSubscribeOptions contains a set of options to use with
|
||||
// RouteSubscribeWithOptions.
|
||||
type RouteSubscribeOptions struct {
|
||||
Namespace *netns.NsHandle
|
||||
ErrorCallback func(error)
|
||||
ListExisting bool
|
||||
Namespace *netns.NsHandle
|
||||
ErrorCallback func(error)
|
||||
ListExisting bool
|
||||
ReceiveBufferSize int
|
||||
ReceiveBufferForceSize bool
|
||||
ReceiveTimeout *unix.Timeval
|
||||
}
|
||||
|
||||
// RouteSubscribeWithOptions work like RouteSubscribe but enable to
|
||||
@ -1433,14 +1689,27 @@ func RouteSubscribeWithOptions(ch chan<- RouteUpdate, done <-chan struct{}, opti
|
||||
none := netns.None()
|
||||
options.Namespace = &none
|
||||
}
|
||||
return routeSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting)
|
||||
return routeSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting,
|
||||
options.ReceiveBufferSize, options.ReceiveTimeout, options.ReceiveBufferForceSize)
|
||||
}
|
||||
|
||||
func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error {
|
||||
func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}, cberr func(error), listExisting bool,
|
||||
rcvbuf int, rcvTimeout *unix.Timeval, rcvbufForce 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 rcvTimeout != nil {
|
||||
if err := s.SetReceiveTimeout(rcvTimeout); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if rcvbuf != 0 {
|
||||
err = s.SetReceiveBufferSize(rcvbuf, rcvbufForce)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if done != nil {
|
||||
go func() {
|
||||
<-done
|
||||
@ -1495,7 +1764,11 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <
|
||||
}
|
||||
continue
|
||||
}
|
||||
ch <- RouteUpdate{Type: m.Header.Type, Route: route}
|
||||
ch <- RouteUpdate{
|
||||
Type: m.Header.Type,
|
||||
NlFlags: m.Header.Flags & (unix.NLM_F_REPLACE | unix.NLM_F_EXCL | unix.NLM_F_CREATE | unix.NLM_F_APPEND),
|
||||
Route: route,
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
@ -1523,7 +1796,7 @@ func (p RouteProtocol) String() string {
|
||||
return "gated"
|
||||
case unix.RTPROT_ISIS:
|
||||
return "isis"
|
||||
//case unix.RTPROT_KEEPALIVED:
|
||||
// case unix.RTPROT_KEEPALIVED:
|
||||
// return "keepalived"
|
||||
case unix.RTPROT_KERNEL:
|
||||
return "kernel"
|
||||
@ -1553,3 +1826,24 @@ func (p RouteProtocol) String() string {
|
||||
return strconv.Itoa(int(p))
|
||||
}
|
||||
}
|
||||
|
||||
// genZeroIPNet returns 0.0.0.0/0 or ::/0 for IPv4 or IPv6, otherwise nil
|
||||
func genZeroIPNet(family int) *net.IPNet {
|
||||
var addLen int
|
||||
var ip net.IP
|
||||
switch family {
|
||||
case FAMILY_V4:
|
||||
addLen = net.IPv4len
|
||||
ip = net.IPv4zero
|
||||
case FAMILY_V6:
|
||||
addLen = net.IPv6len
|
||||
ip = net.IPv6zero
|
||||
}
|
||||
if addLen != 0 {
|
||||
return &net.IPNet{
|
||||
IP: ip,
|
||||
Mask: net.CIDRMask(0, 8*addLen),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
26
vendor/github.com/vishvananda/netlink/rule.go
generated
vendored
26
vendor/github.com/vishvananda/netlink/rule.go
generated
vendored
@ -10,8 +10,8 @@ type Rule struct {
|
||||
Priority int
|
||||
Family int
|
||||
Table int
|
||||
Mark int
|
||||
Mask int
|
||||
Mark uint32
|
||||
Mask *uint32
|
||||
Tos uint
|
||||
TunID uint
|
||||
Goto int
|
||||
@ -26,6 +26,9 @@ type Rule struct {
|
||||
Dport *RulePortRange
|
||||
Sport *RulePortRange
|
||||
IPProto int
|
||||
UIDRange *RuleUIDRange
|
||||
Protocol uint8
|
||||
Type uint8
|
||||
}
|
||||
|
||||
func (r Rule) String() string {
|
||||
@ -39,8 +42,8 @@ func (r Rule) String() string {
|
||||
to = r.Dst.String()
|
||||
}
|
||||
|
||||
return fmt.Sprintf("ip rule %d: from %s to %s table %d",
|
||||
r.Priority, from, to, r.Table)
|
||||
return fmt.Sprintf("ip rule %d: from %s to %s table %d %s",
|
||||
r.Priority, from, to, r.Table, r.typeString())
|
||||
}
|
||||
|
||||
// NewRule return empty rules.
|
||||
@ -49,8 +52,8 @@ func NewRule() *Rule {
|
||||
SuppressIfgroup: -1,
|
||||
SuppressPrefixlen: -1,
|
||||
Priority: -1,
|
||||
Mark: -1,
|
||||
Mask: -1,
|
||||
Mark: 0,
|
||||
Mask: nil,
|
||||
Goto: -1,
|
||||
Flow: -1,
|
||||
}
|
||||
@ -66,3 +69,14 @@ type RulePortRange struct {
|
||||
Start uint16
|
||||
End uint16
|
||||
}
|
||||
|
||||
// NewRuleUIDRange creates rule uid range.
|
||||
func NewRuleUIDRange(start, end uint32) *RuleUIDRange {
|
||||
return &RuleUIDRange{Start: start, End: end}
|
||||
}
|
||||
|
||||
// RuleUIDRange represents rule uid range.
|
||||
type RuleUIDRange struct {
|
||||
Start uint32
|
||||
End uint32
|
||||
}
|
||||
|
82
vendor/github.com/vishvananda/netlink/rule_linux.go
generated
vendored
82
vendor/github.com/vishvananda/netlink/rule_linux.go
generated
vendored
@ -43,8 +43,8 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
|
||||
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 = rule.Type // usually 0, same as unix.RTN_UNSPEC
|
||||
if msg.Type == 0 && req.NlMsghdr.Flags&unix.NLM_F_CREATE > 0 {
|
||||
msg.Type = unix.RTN_UNICAST
|
||||
}
|
||||
if rule.Invert {
|
||||
@ -102,14 +102,14 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
|
||||
native.PutUint32(b, uint32(rule.Priority))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_PRIORITY, b))
|
||||
}
|
||||
if rule.Mark >= 0 {
|
||||
if rule.Mark != 0 || rule.Mask != nil {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(rule.Mark))
|
||||
native.PutUint32(b, rule.Mark)
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_FWMARK, b))
|
||||
}
|
||||
if rule.Mask >= 0 {
|
||||
if rule.Mask != nil {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(rule.Mask))
|
||||
native.PutUint32(b, *rule.Mask)
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_FWMASK, b))
|
||||
}
|
||||
if rule.Flow >= 0 {
|
||||
@ -168,6 +168,15 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_SPORT_RANGE, b))
|
||||
}
|
||||
|
||||
if rule.UIDRange != nil {
|
||||
b := rule.UIDRange.toRtAttrData()
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_UID_RANGE, b))
|
||||
}
|
||||
|
||||
if rule.Protocol > 0 {
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_PROTOCOL, nl.Uint8Attr(rule.Protocol)))
|
||||
}
|
||||
|
||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
@ -212,8 +221,10 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) (
|
||||
}
|
||||
|
||||
rule := NewRule()
|
||||
rule.Priority = 0 // The default priority from kernel
|
||||
|
||||
rule.Invert = msg.Flags&FibRuleInvert > 0
|
||||
rule.Family = int(msg.Family)
|
||||
rule.Tos = uint(msg.Tos)
|
||||
|
||||
for j := range attrs {
|
||||
@ -231,9 +242,10 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) (
|
||||
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]))
|
||||
rule.Mark = native.Uint32(attrs[j].Value[0:4])
|
||||
case nl.FRA_FWMASK:
|
||||
rule.Mask = int(native.Uint32(attrs[j].Value[0:4]))
|
||||
mask := native.Uint32(attrs[j].Value[0:4])
|
||||
rule.Mask = &mask
|
||||
case nl.FRA_TUN_ID:
|
||||
rule.TunID = uint(native.Uint64(attrs[j].Value[0:8]))
|
||||
case nl.FRA_IIFNAME:
|
||||
@ -262,6 +274,10 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) (
|
||||
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]))
|
||||
case nl.FRA_UID_RANGE:
|
||||
rule.UIDRange = NewRuleUIDRange(native.Uint32(attrs[j].Value[0:4]), native.Uint32(attrs[j].Value[4:8]))
|
||||
case nl.FRA_PROTOCOL:
|
||||
rule.Protocol = uint8(attrs[j].Value[0])
|
||||
}
|
||||
}
|
||||
|
||||
@ -282,7 +298,7 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) (
|
||||
continue
|
||||
case filterMask&RT_FILTER_MARK != 0 && rule.Mark != filter.Mark:
|
||||
continue
|
||||
case filterMask&RT_FILTER_MASK != 0 && rule.Mask != filter.Mask:
|
||||
case filterMask&RT_FILTER_MASK != 0 && !ptrEqual(rule.Mask, filter.Mask):
|
||||
continue
|
||||
}
|
||||
}
|
||||
@ -299,3 +315,51 @@ func (pr *RulePortRange) toRtAttrData() []byte {
|
||||
native.PutUint16(b[1], pr.End)
|
||||
return bytes.Join(b, []byte{})
|
||||
}
|
||||
|
||||
func (pr *RuleUIDRange) toRtAttrData() []byte {
|
||||
b := [][]byte{make([]byte, 4), make([]byte, 4)}
|
||||
native.PutUint32(b[0], pr.Start)
|
||||
native.PutUint32(b[1], pr.End)
|
||||
return bytes.Join(b, []byte{})
|
||||
}
|
||||
|
||||
func ptrEqual(a, b *uint32) bool {
|
||||
if a == b {
|
||||
return true
|
||||
}
|
||||
if (a == nil) || (b == nil) {
|
||||
return false
|
||||
}
|
||||
return *a == *b
|
||||
}
|
||||
|
||||
func (r Rule) typeString() string {
|
||||
switch r.Type {
|
||||
case unix.RTN_UNSPEC: // zero
|
||||
return ""
|
||||
case unix.RTN_UNICAST:
|
||||
return ""
|
||||
case unix.RTN_LOCAL:
|
||||
return "local"
|
||||
case unix.RTN_BROADCAST:
|
||||
return "broadcast"
|
||||
case unix.RTN_ANYCAST:
|
||||
return "anycast"
|
||||
case unix.RTN_MULTICAST:
|
||||
return "multicast"
|
||||
case unix.RTN_BLACKHOLE:
|
||||
return "blackhole"
|
||||
case unix.RTN_UNREACHABLE:
|
||||
return "unreachable"
|
||||
case unix.RTN_PROHIBIT:
|
||||
return "prohibit"
|
||||
case unix.RTN_THROW:
|
||||
return "throw"
|
||||
case unix.RTN_NAT:
|
||||
return "nat"
|
||||
case unix.RTN_XRESOLVE:
|
||||
return "xresolve"
|
||||
default:
|
||||
return fmt.Sprintf("type(0x%x)", r.Type)
|
||||
}
|
||||
}
|
||||
|
8
vendor/github.com/vishvananda/netlink/rule_nonlinux.go
generated
vendored
Normal file
8
vendor/github.com/vishvananda/netlink/rule_nonlinux.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package netlink
|
||||
|
||||
func (r Rule) typeString() string {
|
||||
return ""
|
||||
}
|
77
vendor/github.com/vishvananda/netlink/socket.go
generated
vendored
77
vendor/github.com/vishvananda/netlink/socket.go
generated
vendored
@ -25,3 +25,80 @@ type Socket struct {
|
||||
UID uint32
|
||||
INode uint32
|
||||
}
|
||||
|
||||
// UnixSocket represents a netlink unix socket.
|
||||
type UnixSocket struct {
|
||||
Type uint8
|
||||
Family uint8
|
||||
State uint8
|
||||
pad uint8
|
||||
INode uint32
|
||||
Cookie [2]uint32
|
||||
}
|
||||
|
||||
// XDPSocket represents an XDP socket (and the common diagnosis part in
|
||||
// particular). Please note that in contrast to [UnixSocket] the XDPSocket type
|
||||
// does not feature “State” information.
|
||||
type XDPSocket struct {
|
||||
// xdp_diag_msg
|
||||
// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L21
|
||||
Family uint8
|
||||
Type uint8
|
||||
pad uint16
|
||||
Ino uint32
|
||||
Cookie [2]uint32
|
||||
}
|
||||
|
||||
type XDPInfo struct {
|
||||
// XDP_DIAG_INFO/xdp_diag_info
|
||||
// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L51
|
||||
Ifindex uint32
|
||||
QueueID uint32
|
||||
|
||||
// XDP_DIAG_UID
|
||||
UID uint32
|
||||
|
||||
// XDP_RX_RING
|
||||
// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L56
|
||||
RxRingEntries uint32
|
||||
TxRingEntries uint32
|
||||
UmemFillRingEntries uint32
|
||||
UmemCompletionRingEntries uint32
|
||||
|
||||
// XDR_DIAG_UMEM
|
||||
Umem *XDPDiagUmem
|
||||
|
||||
// XDR_DIAG_STATS
|
||||
Stats *XDPDiagStats
|
||||
}
|
||||
|
||||
const (
|
||||
XDP_DU_F_ZEROCOPY = 1 << iota
|
||||
)
|
||||
|
||||
// XDPDiagUmem describes the umem attached to an XDP socket.
|
||||
//
|
||||
// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L62
|
||||
type XDPDiagUmem struct {
|
||||
Size uint64
|
||||
ID uint32
|
||||
NumPages uint32
|
||||
ChunkSize uint32
|
||||
Headroom uint32
|
||||
Ifindex uint32
|
||||
QueueID uint32
|
||||
Flags uint32
|
||||
Refs uint32
|
||||
}
|
||||
|
||||
// XDPDiagStats contains ring statistics for an XDP socket.
|
||||
//
|
||||
// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L74
|
||||
type XDPDiagStats struct {
|
||||
RxDropped uint64
|
||||
RxInvalid uint64
|
||||
RxFull uint64
|
||||
FillRingEmpty uint64
|
||||
TxInvalid uint64
|
||||
TxRingEmpty uint64
|
||||
}
|
||||
|
507
vendor/github.com/vishvananda/netlink/socket_linux.go
generated
vendored
507
vendor/github.com/vishvananda/netlink/socket_linux.go
generated
vendored
@ -11,9 +11,11 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
sizeofSocketID = 0x30
|
||||
sizeofSocketRequest = sizeofSocketID + 0x8
|
||||
sizeofSocket = sizeofSocketID + 0x18
|
||||
sizeofSocketID = 0x30
|
||||
sizeofSocketRequest = sizeofSocketID + 0x8
|
||||
sizeofSocket = sizeofSocketID + 0x18
|
||||
sizeofUnixSocketRequest = 0x18 // 24 byte
|
||||
sizeofUnixSocket = 0x10 // 16 byte
|
||||
)
|
||||
|
||||
type socketRequest struct {
|
||||
@ -54,10 +56,8 @@ func (r *socketRequest) Serialize() []byte {
|
||||
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)
|
||||
copy(b.Next(16), r.ID.Source.To4())
|
||||
copy(b.Next(16), r.ID.Destination.To4())
|
||||
}
|
||||
native.PutUint32(b.Next(4), r.ID.Interface)
|
||||
native.PutUint32(b.Next(4), r.ID.Cookie[0])
|
||||
@ -67,6 +67,32 @@ func (r *socketRequest) Serialize() []byte {
|
||||
|
||||
func (r *socketRequest) Len() int { return sizeofSocketRequest }
|
||||
|
||||
// According to linux/include/uapi/linux/unix_diag.h
|
||||
type unixSocketRequest struct {
|
||||
Family uint8
|
||||
Protocol uint8
|
||||
pad uint16
|
||||
States uint32
|
||||
INode uint32
|
||||
Show uint32
|
||||
Cookie [2]uint32
|
||||
}
|
||||
|
||||
func (r *unixSocketRequest) Serialize() []byte {
|
||||
b := writeBuffer{Bytes: make([]byte, sizeofUnixSocketRequest)}
|
||||
b.Write(r.Family)
|
||||
b.Write(r.Protocol)
|
||||
native.PutUint16(b.Next(2), r.pad)
|
||||
native.PutUint32(b.Next(4), r.States)
|
||||
native.PutUint32(b.Next(4), r.INode)
|
||||
native.PutUint32(b.Next(4), r.Show)
|
||||
native.PutUint32(b.Next(4), r.Cookie[0])
|
||||
native.PutUint32(b.Next(4), r.Cookie[1])
|
||||
return b.Bytes
|
||||
}
|
||||
|
||||
func (r *unixSocketRequest) Len() int { return sizeofUnixSocketRequest }
|
||||
|
||||
type readBuffer struct {
|
||||
Bytes []byte
|
||||
pos int
|
||||
@ -115,31 +141,126 @@ func (s *Socket) deserialize(b []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *UnixSocket) deserialize(b []byte) error {
|
||||
if len(b) < sizeofUnixSocket {
|
||||
return fmt.Errorf("unix diag data short read (%d); want %d", len(b), sizeofUnixSocket)
|
||||
}
|
||||
rb := readBuffer{Bytes: b}
|
||||
u.Type = rb.Read()
|
||||
u.Family = rb.Read()
|
||||
u.State = rb.Read()
|
||||
u.pad = rb.Read()
|
||||
u.INode = native.Uint32(rb.Next(4))
|
||||
u.Cookie[0] = native.Uint32(rb.Next(4))
|
||||
u.Cookie[1] = native.Uint32(rb.Next(4))
|
||||
return nil
|
||||
}
|
||||
|
||||
// SocketGet returns the Socket identified by its local and remote addresses.
|
||||
func (h *Handle) SocketGet(local, remote net.Addr) (*Socket, error) {
|
||||
var protocol uint8
|
||||
var localIP, remoteIP net.IP
|
||||
var localPort, remotePort uint16
|
||||
switch l := local.(type) {
|
||||
case *net.TCPAddr:
|
||||
r, ok := remote.(*net.TCPAddr)
|
||||
if !ok {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
localIP = l.IP
|
||||
localPort = uint16(l.Port)
|
||||
remoteIP = r.IP
|
||||
remotePort = uint16(r.Port)
|
||||
protocol = unix.IPPROTO_TCP
|
||||
case *net.UDPAddr:
|
||||
r, ok := remote.(*net.UDPAddr)
|
||||
if !ok {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
localIP = l.IP
|
||||
localPort = uint16(l.Port)
|
||||
remoteIP = r.IP
|
||||
remotePort = uint16(r.Port)
|
||||
protocol = unix.IPPROTO_UDP
|
||||
default:
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
||||
var family uint8
|
||||
if localIP.To4() != nil && remoteIP.To4() != nil {
|
||||
family = unix.AF_INET
|
||||
}
|
||||
|
||||
if family == 0 && localIP.To16() != nil && remoteIP.To16() != nil {
|
||||
family = unix.AF_INET6
|
||||
}
|
||||
|
||||
if family == 0 {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
||||
req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
|
||||
req.AddData(&socketRequest{
|
||||
Family: family,
|
||||
Protocol: protocol,
|
||||
States: 0xffffffff,
|
||||
ID: SocketID{
|
||||
SourcePort: localPort,
|
||||
DestinationPort: remotePort,
|
||||
Source: localIP,
|
||||
Destination: remoteIP,
|
||||
Cookie: [2]uint32{nl.TCPDIAG_NOCOOKIE, nl.TCPDIAG_NOCOOKIE},
|
||||
},
|
||||
})
|
||||
|
||||
msgs, err := req.Execute(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
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]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sock, nil
|
||||
}
|
||||
|
||||
// SocketGet returns the Socket identified by its local and remote addresses.
|
||||
func SocketGet(local, remote net.Addr) (*Socket, error) {
|
||||
return pkgHandle.SocketGet(local, remote)
|
||||
}
|
||||
|
||||
// SocketDestroy kills the Socket identified by its local and remote addresses.
|
||||
func (h *Handle) SocketDestroy(local, remote net.Addr) error {
|
||||
localTCP, ok := local.(*net.TCPAddr)
|
||||
if !ok {
|
||||
return nil, ErrNotImplemented
|
||||
return ErrNotImplemented
|
||||
}
|
||||
remoteTCP, ok := remote.(*net.TCPAddr)
|
||||
if !ok {
|
||||
return nil, ErrNotImplemented
|
||||
return ErrNotImplemented
|
||||
}
|
||||
localIP := localTCP.IP.To4()
|
||||
if localIP == nil {
|
||||
return nil, ErrNotImplemented
|
||||
return ErrNotImplemented
|
||||
}
|
||||
remoteIP := remoteTCP.IP.To4()
|
||||
if remoteIP == nil {
|
||||
return nil, ErrNotImplemented
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
s, err := nl.Subscribe(unix.NETLINK_INET_DIAG)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
defer s.Close()
|
||||
req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, 0)
|
||||
req := h.newNetlinkRequest(nl.SOCK_DESTROY, unix.NLM_F_ACK)
|
||||
req.AddData(&socketRequest{
|
||||
Family: unix.AF_INET,
|
||||
Protocol: unix.IPPROTO_TCP,
|
||||
@ -151,47 +272,81 @@ func SocketGet(local, remote net.Addr) (*Socket, error) {
|
||||
Cookie: [2]uint32{nl.TCPDIAG_NOCOOKIE, nl.TCPDIAG_NOCOOKIE},
|
||||
},
|
||||
})
|
||||
s.Send(req)
|
||||
msgs, from, err := s.Receive()
|
||||
|
||||
_, err = req.Execute(unix.NETLINK_INET_DIAG, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// SocketDestroy kills the Socket identified by its local and remote addresses.
|
||||
func SocketDestroy(local, remote net.Addr) error {
|
||||
return pkgHandle.SocketDestroy(local, remote)
|
||||
}
|
||||
|
||||
// SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type and return with extension TCP info.
|
||||
func (h *Handle) SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) {
|
||||
// Construct the request
|
||||
req := h.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 states
|
||||
})
|
||||
|
||||
// Do the query and parse the result
|
||||
var result []*InetDiagTCPInfoResp
|
||||
var err error
|
||||
err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
|
||||
sockInfo := &Socket{}
|
||||
if err = sockInfo.deserialize(msg); err != nil {
|
||||
return false
|
||||
}
|
||||
var attrs []syscall.NetlinkRouteAttr
|
||||
if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var res *InetDiagTCPInfoResp
|
||||
if res, err = attrsToInetDiagTCPInfoResp(attrs, sockInfo); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
result = append(result, res)
|
||||
return true
|
||||
})
|
||||
|
||||
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
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type and return with extension TCP info.
|
||||
func SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) {
|
||||
var result []*InetDiagTCPInfoResp
|
||||
err := socketDiagTCPExecutor(family, func(m syscall.NetlinkMessage) error {
|
||||
return pkgHandle.SocketDiagTCPInfo(family)
|
||||
}
|
||||
|
||||
// SocketDiagTCP requests INET_DIAG_INFO for TCP protocol for specified family type and return related socket.
|
||||
func (h *Handle) SocketDiagTCP(family uint8) ([]*Socket, error) {
|
||||
// Construct the request
|
||||
req := h.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 states
|
||||
})
|
||||
|
||||
// Do the query and parse the result
|
||||
var result []*Socket
|
||||
var err error
|
||||
err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
|
||||
sockInfo := &Socket{}
|
||||
if err := sockInfo.deserialize(m.Data); err != nil {
|
||||
return err
|
||||
if err = sockInfo.deserialize(msg); err != nil {
|
||||
return false
|
||||
}
|
||||
attrs, err := nl.ParseRouteAttr(m.Data[sizeofSocket:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err := attrsToInetDiagTCPInfoResp(attrs, sockInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result = append(result, res)
|
||||
return nil
|
||||
result = append(result, sockInfo)
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -201,14 +356,46 @@ func SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) {
|
||||
|
||||
// SocketDiagTCP requests INET_DIAG_INFO for TCP protocol for specified family type and return related socket.
|
||||
func SocketDiagTCP(family uint8) ([]*Socket, error) {
|
||||
var result []*Socket
|
||||
err := socketDiagTCPExecutor(family, func(m syscall.NetlinkMessage) error {
|
||||
return pkgHandle.SocketDiagTCP(family)
|
||||
}
|
||||
|
||||
// SocketDiagUDPInfo requests INET_DIAG_INFO for UDP protocol for specified family type and return with extension info.
|
||||
func (h *Handle) SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) {
|
||||
// Construct the request
|
||||
var extensions uint8
|
||||
extensions = 1 << (INET_DIAG_VEGASINFO - 1)
|
||||
extensions |= 1 << (INET_DIAG_INFO - 1)
|
||||
extensions |= 1 << (INET_DIAG_MEMINFO - 1)
|
||||
|
||||
req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
|
||||
req.AddData(&socketRequest{
|
||||
Family: family,
|
||||
Protocol: unix.IPPROTO_UDP,
|
||||
Ext: extensions,
|
||||
States: uint32(0xfff), // all states
|
||||
})
|
||||
|
||||
// Do the query and parse the result
|
||||
var result []*InetDiagUDPInfoResp
|
||||
var err error
|
||||
err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
|
||||
sockInfo := &Socket{}
|
||||
if err := sockInfo.deserialize(m.Data); err != nil {
|
||||
return err
|
||||
if err = sockInfo.deserialize(msg); err != nil {
|
||||
return false
|
||||
}
|
||||
result = append(result, sockInfo)
|
||||
return nil
|
||||
|
||||
var attrs []syscall.NetlinkRouteAttr
|
||||
if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var res *InetDiagUDPInfoResp
|
||||
if res, err = attrsToInetDiagUDPInfoResp(attrs, sockInfo); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
result = append(result, res)
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -216,76 +403,188 @@ func SocketDiagTCP(family uint8) ([]*Socket, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// socketDiagTCPExecutor requests INET_DIAG_INFO for TCP protocol for specified family type.
|
||||
func socketDiagTCPExecutor(family uint8, receiver func(syscall.NetlinkMessage) error) error {
|
||||
s, err := nl.Subscribe(unix.NETLINK_INET_DIAG)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.Close()
|
||||
// SocketDiagUDPInfo requests INET_DIAG_INFO for UDP protocol for specified family type and return with extension info.
|
||||
func SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) {
|
||||
return pkgHandle.SocketDiagUDPInfo(family)
|
||||
}
|
||||
|
||||
req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
|
||||
// SocketDiagUDP requests INET_DIAG_INFO for UDP protocol for specified family type and return related socket.
|
||||
func (h *Handle) SocketDiagUDP(family uint8) ([]*Socket, error) {
|
||||
// Construct the request
|
||||
req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
|
||||
req.AddData(&socketRequest{
|
||||
Family: family,
|
||||
Protocol: unix.IPPROTO_TCP,
|
||||
Protocol: unix.IPPROTO_UDP,
|
||||
Ext: (1 << (INET_DIAG_VEGASINFO - 1)) | (1 << (INET_DIAG_INFO - 1)),
|
||||
States: uint32(0xfff), // All TCP states
|
||||
States: uint32(0xfff), // all states
|
||||
})
|
||||
s.Send(req)
|
||||
|
||||
loop:
|
||||
for {
|
||||
msgs, from, err := s.Receive()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if from.Pid != nl.PidKernel {
|
||||
return fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
|
||||
}
|
||||
if len(msgs) == 0 {
|
||||
return 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:
|
||||
error := int32(native.Uint32(m.Data[0:4]))
|
||||
return syscall.Errno(-error)
|
||||
}
|
||||
if err := receiver(m); err != nil {
|
||||
return err
|
||||
}
|
||||
// Do the query and parse the result
|
||||
var result []*Socket
|
||||
var err error
|
||||
err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
|
||||
sockInfo := &Socket{}
|
||||
if err = sockInfo.deserialize(msg); err != nil {
|
||||
return false
|
||||
}
|
||||
result = append(result, sockInfo)
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SocketDiagUDP requests INET_DIAG_INFO for UDP protocol for specified family type and return related socket.
|
||||
func SocketDiagUDP(family uint8) ([]*Socket, error) {
|
||||
return pkgHandle.SocketDiagUDP(family)
|
||||
}
|
||||
|
||||
// UnixSocketDiagInfo requests UNIX_DIAG_INFO for unix sockets and return with extension info.
|
||||
func (h *Handle) UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) {
|
||||
// Construct the request
|
||||
var extensions uint8
|
||||
extensions = 1 << UNIX_DIAG_NAME
|
||||
extensions |= 1 << UNIX_DIAG_PEER
|
||||
extensions |= 1 << UNIX_DIAG_RQLEN
|
||||
req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
|
||||
req.AddData(&unixSocketRequest{
|
||||
Family: unix.AF_UNIX,
|
||||
States: ^uint32(0), // all states
|
||||
Show: uint32(extensions),
|
||||
})
|
||||
|
||||
var result []*UnixDiagInfoResp
|
||||
var err error
|
||||
err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
|
||||
sockInfo := &UnixSocket{}
|
||||
if err = sockInfo.deserialize(msg); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Diagnosis also delivers sockets with AF_INET family, filter those
|
||||
if sockInfo.Family != unix.AF_UNIX {
|
||||
return false
|
||||
}
|
||||
|
||||
var attrs []syscall.NetlinkRouteAttr
|
||||
if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var res *UnixDiagInfoResp
|
||||
if res, err = attrsToUnixDiagInfoResp(attrs, sockInfo); err != nil {
|
||||
return false
|
||||
}
|
||||
result = append(result, res)
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// UnixSocketDiagInfo requests UNIX_DIAG_INFO for unix sockets and return with extension info.
|
||||
func UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) {
|
||||
return pkgHandle.UnixSocketDiagInfo()
|
||||
}
|
||||
|
||||
// UnixSocketDiag requests UNIX_DIAG_INFO for unix sockets.
|
||||
func (h *Handle) UnixSocketDiag() ([]*UnixSocket, error) {
|
||||
// Construct the request
|
||||
req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
|
||||
req.AddData(&unixSocketRequest{
|
||||
Family: unix.AF_UNIX,
|
||||
States: ^uint32(0), // all states
|
||||
})
|
||||
|
||||
var result []*UnixSocket
|
||||
var err error
|
||||
err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool {
|
||||
sockInfo := &UnixSocket{}
|
||||
if err = sockInfo.deserialize(msg); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Diagnosis also delivers sockets with AF_INET family, filter those
|
||||
if sockInfo.Family == unix.AF_UNIX {
|
||||
result = append(result, sockInfo)
|
||||
}
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// UnixSocketDiag requests UNIX_DIAG_INFO for unix sockets.
|
||||
func UnixSocketDiag() ([]*UnixSocket, error) {
|
||||
return pkgHandle.UnixSocketDiag()
|
||||
}
|
||||
|
||||
func attrsToInetDiagTCPInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *Socket) (*InetDiagTCPInfoResp, error) {
|
||||
var tcpInfo *TCPInfo
|
||||
var tcpBBRInfo *TCPBBRInfo
|
||||
info := &InetDiagTCPInfoResp{
|
||||
InetDiagMsg: sockInfo,
|
||||
}
|
||||
for _, a := range attrs {
|
||||
if a.Attr.Type == INET_DIAG_INFO {
|
||||
tcpInfo = &TCPInfo{}
|
||||
if err := tcpInfo.deserialize(a.Value); err != nil {
|
||||
switch a.Attr.Type {
|
||||
case INET_DIAG_INFO:
|
||||
info.TCPInfo = &TCPInfo{}
|
||||
if err := info.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 {
|
||||
case INET_DIAG_BBRINFO:
|
||||
info.TCPBBRInfo = &TCPBBRInfo{}
|
||||
if err := info.TCPBBRInfo.deserialize(a.Value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return &InetDiagTCPInfoResp{
|
||||
InetDiagMsg: sockInfo,
|
||||
TCPInfo: tcpInfo,
|
||||
TCPBBRInfo: tcpBBRInfo,
|
||||
}, nil
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func attrsToInetDiagUDPInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *Socket) (*InetDiagUDPInfoResp, error) {
|
||||
info := &InetDiagUDPInfoResp{
|
||||
InetDiagMsg: sockInfo,
|
||||
}
|
||||
for _, a := range attrs {
|
||||
switch a.Attr.Type {
|
||||
case INET_DIAG_MEMINFO:
|
||||
info.Memory = &MemInfo{}
|
||||
if err := info.Memory.deserialize(a.Value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func attrsToUnixDiagInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *UnixSocket) (*UnixDiagInfoResp, error) {
|
||||
info := &UnixDiagInfoResp{
|
||||
DiagMsg: sockInfo,
|
||||
}
|
||||
for _, a := range attrs {
|
||||
switch a.Attr.Type {
|
||||
case UNIX_DIAG_NAME:
|
||||
name := string(a.Value[:a.Attr.Len])
|
||||
info.Name = &name
|
||||
case UNIX_DIAG_PEER:
|
||||
peer := native.Uint32(a.Value)
|
||||
info.Peer = &peer
|
||||
case UNIX_DIAG_RQLEN:
|
||||
info.Queue = &QueueInfo{
|
||||
RQueue: native.Uint32(a.Value[:4]),
|
||||
WQueue: native.Uint32(a.Value[4:]),
|
||||
}
|
||||
// default:
|
||||
// fmt.Println("unknown unix attribute type", a.Attr.Type, "with data", a.Value)
|
||||
}
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
195
vendor/github.com/vishvananda/netlink/socket_xdp_linux.go
generated
vendored
Normal file
195
vendor/github.com/vishvananda/netlink/socket_xdp_linux.go
generated
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"syscall"
|
||||
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
sizeofXDPSocketRequest = 1 + 1 + 2 + 4 + 4 + 2*4
|
||||
sizeofXDPSocket = 0x10
|
||||
)
|
||||
|
||||
// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L12
|
||||
type xdpSocketRequest struct {
|
||||
Family uint8
|
||||
Protocol uint8
|
||||
pad uint16
|
||||
Ino uint32
|
||||
Show uint32
|
||||
Cookie [2]uint32
|
||||
}
|
||||
|
||||
func (r *xdpSocketRequest) Serialize() []byte {
|
||||
b := writeBuffer{Bytes: make([]byte, sizeofSocketRequest)}
|
||||
b.Write(r.Family)
|
||||
b.Write(r.Protocol)
|
||||
native.PutUint16(b.Next(2), r.pad)
|
||||
native.PutUint32(b.Next(4), r.Ino)
|
||||
native.PutUint32(b.Next(4), r.Show)
|
||||
native.PutUint32(b.Next(4), r.Cookie[0])
|
||||
native.PutUint32(b.Next(4), r.Cookie[1])
|
||||
return b.Bytes
|
||||
}
|
||||
|
||||
func (r *xdpSocketRequest) Len() int { return sizeofXDPSocketRequest }
|
||||
|
||||
func (s *XDPSocket) deserialize(b []byte) error {
|
||||
if len(b) < sizeofXDPSocket {
|
||||
return fmt.Errorf("XDP socket data short read (%d); want %d", len(b), sizeofXDPSocket)
|
||||
}
|
||||
rb := readBuffer{Bytes: b}
|
||||
s.Family = rb.Read()
|
||||
s.Type = rb.Read()
|
||||
s.pad = native.Uint16(rb.Next(2))
|
||||
s.Ino = native.Uint32(rb.Next(4))
|
||||
s.Cookie[0] = native.Uint32(rb.Next(4))
|
||||
s.Cookie[1] = native.Uint32(rb.Next(4))
|
||||
return nil
|
||||
}
|
||||
|
||||
// XDPSocketGet returns the XDP socket identified by its inode number and/or
|
||||
// socket cookie. Specify the cookie as SOCK_ANY_COOKIE if
|
||||
func SocketXDPGetInfo(ino uint32, cookie uint64) (*XDPDiagInfoResp, error) {
|
||||
// We have a problem here: dumping AF_XDP sockets currently does not support
|
||||
// filtering. We thus need to dump all XSKs and then only filter afterwards
|
||||
// :(
|
||||
xsks, err := SocketDiagXDP()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
checkCookie := cookie != SOCK_ANY_COOKIE && cookie != 0
|
||||
crumblingCookie := [2]uint32{uint32(cookie), uint32(cookie >> 32)}
|
||||
checkIno := ino != 0
|
||||
var xskinfo *XDPDiagInfoResp
|
||||
for _, xsk := range xsks {
|
||||
if checkIno && xsk.XDPDiagMsg.Ino != ino {
|
||||
continue
|
||||
}
|
||||
if checkCookie && xsk.XDPDiagMsg.Cookie != crumblingCookie {
|
||||
continue
|
||||
}
|
||||
if xskinfo != nil {
|
||||
return nil, errors.New("multiple matching XDP sockets")
|
||||
}
|
||||
xskinfo = xsk
|
||||
}
|
||||
if xskinfo == nil {
|
||||
return nil, errors.New("no matching XDP socket")
|
||||
}
|
||||
return xskinfo, nil
|
||||
}
|
||||
|
||||
// SocketDiagXDP requests XDP_DIAG_INFO for XDP family sockets.
|
||||
func SocketDiagXDP() ([]*XDPDiagInfoResp, error) {
|
||||
var result []*XDPDiagInfoResp
|
||||
err := socketDiagXDPExecutor(func(m syscall.NetlinkMessage) error {
|
||||
sockInfo := &XDPSocket{}
|
||||
if err := sockInfo.deserialize(m.Data); err != nil {
|
||||
return err
|
||||
}
|
||||
attrs, err := nl.ParseRouteAttr(m.Data[sizeofXDPSocket:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err := attrsToXDPDiagInfoResp(attrs, sockInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result = append(result, res)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// socketDiagXDPExecutor requests XDP_DIAG_INFO for XDP family sockets.
|
||||
func socketDiagXDPExecutor(receiver func(syscall.NetlinkMessage) error) error {
|
||||
s, err := nl.Subscribe(unix.NETLINK_INET_DIAG)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
|
||||
req.AddData(&xdpSocketRequest{
|
||||
Family: unix.AF_XDP,
|
||||
Show: XDP_SHOW_INFO | XDP_SHOW_RING_CFG | XDP_SHOW_UMEM | XDP_SHOW_STATS,
|
||||
})
|
||||
if err := s.Send(req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
loop:
|
||||
for {
|
||||
msgs, from, err := s.Receive()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if from.Pid != nl.PidKernel {
|
||||
return fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
|
||||
}
|
||||
if len(msgs) == 0 {
|
||||
return 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:
|
||||
error := int32(native.Uint32(m.Data[0:4]))
|
||||
return syscall.Errno(-error)
|
||||
}
|
||||
if err := receiver(m); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func attrsToXDPDiagInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *XDPSocket) (*XDPDiagInfoResp, error) {
|
||||
resp := &XDPDiagInfoResp{
|
||||
XDPDiagMsg: sockInfo,
|
||||
XDPInfo: &XDPInfo{},
|
||||
}
|
||||
for _, a := range attrs {
|
||||
switch a.Attr.Type {
|
||||
case XDP_DIAG_INFO:
|
||||
resp.XDPInfo.Ifindex = native.Uint32(a.Value[0:4])
|
||||
resp.XDPInfo.QueueID = native.Uint32(a.Value[4:8])
|
||||
case XDP_DIAG_UID:
|
||||
resp.XDPInfo.UID = native.Uint32(a.Value[0:4])
|
||||
case XDP_DIAG_RX_RING:
|
||||
resp.XDPInfo.RxRingEntries = native.Uint32(a.Value[0:4])
|
||||
case XDP_DIAG_TX_RING:
|
||||
resp.XDPInfo.TxRingEntries = native.Uint32(a.Value[0:4])
|
||||
case XDP_DIAG_UMEM_FILL_RING:
|
||||
resp.XDPInfo.UmemFillRingEntries = native.Uint32(a.Value[0:4])
|
||||
case XDP_DIAG_UMEM_COMPLETION_RING:
|
||||
resp.XDPInfo.UmemCompletionRingEntries = native.Uint32(a.Value[0:4])
|
||||
case XDP_DIAG_UMEM:
|
||||
umem := &XDPDiagUmem{}
|
||||
if err := umem.deserialize(a.Value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.XDPInfo.Umem = umem
|
||||
case XDP_DIAG_STATS:
|
||||
stats := &XDPDiagStats{}
|
||||
if err := stats.deserialize(a.Value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.XDPInfo.Stats = stats
|
||||
}
|
||||
}
|
||||
return resp, nil
|
||||
}
|
8
vendor/github.com/vishvananda/netlink/tcp.go
generated
vendored
8
vendor/github.com/vishvananda/netlink/tcp.go
generated
vendored
@ -82,3 +82,11 @@ type TCPBBRInfo struct {
|
||||
BBRPacingGain uint32
|
||||
BBRCwndGain uint32
|
||||
}
|
||||
|
||||
// According to https://man7.org/linux/man-pages/man7/sock_diag.7.html
|
||||
type MemInfo struct {
|
||||
RMem uint32
|
||||
WMem uint32
|
||||
FMem uint32
|
||||
TMem uint32
|
||||
}
|
||||
|
15
vendor/github.com/vishvananda/netlink/tcp_linux.go
generated
vendored
15
vendor/github.com/vishvananda/netlink/tcp_linux.go
generated
vendored
@ -8,6 +8,7 @@ import (
|
||||
|
||||
const (
|
||||
tcpBBRInfoLen = 20
|
||||
memInfoLen = 16
|
||||
)
|
||||
|
||||
func checkDeserErr(err error) error {
|
||||
@ -351,3 +352,17 @@ func (t *TCPBBRInfo) deserialize(b []byte) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MemInfo) deserialize(b []byte) error {
|
||||
if len(b) != memInfoLen {
|
||||
return errors.New("Invalid length")
|
||||
}
|
||||
|
||||
rb := bytes.NewBuffer(b)
|
||||
m.RMem = native.Uint32(rb.Next(4))
|
||||
m.WMem = native.Uint32(rb.Next(4))
|
||||
m.FMem = native.Uint32(rb.Next(4))
|
||||
m.TMem = native.Uint32(rb.Next(4))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
27
vendor/github.com/vishvananda/netlink/unix_diag.go
generated
vendored
Normal file
27
vendor/github.com/vishvananda/netlink/unix_diag.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
package netlink
|
||||
|
||||
// According to linux/include/uapi/linux/unix_diag.h
|
||||
const (
|
||||
UNIX_DIAG_NAME = iota
|
||||
UNIX_DIAG_VFS
|
||||
UNIX_DIAG_PEER
|
||||
UNIX_DIAG_ICONS
|
||||
UNIX_DIAG_RQLEN
|
||||
UNIX_DIAG_MEMINFO
|
||||
UNIX_DIAG_SHUTDOWN
|
||||
UNIX_DIAG_UID
|
||||
UNIX_DIAG_MAX
|
||||
)
|
||||
|
||||
type UnixDiagInfoResp struct {
|
||||
DiagMsg *UnixSocket
|
||||
Name *string
|
||||
Peer *uint32
|
||||
Queue *QueueInfo
|
||||
Shutdown *uint8
|
||||
}
|
||||
|
||||
type QueueInfo struct {
|
||||
RQueue uint32
|
||||
WQueue uint32
|
||||
}
|
463
vendor/github.com/vishvananda/netlink/vdpa_linux.go
generated
vendored
Normal file
463
vendor/github.com/vishvananda/netlink/vdpa_linux.go
generated
vendored
Normal file
@ -0,0 +1,463 @@
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
)
|
||||
|
||||
type vdpaDevID struct {
|
||||
Name string
|
||||
ID uint32
|
||||
}
|
||||
|
||||
// VDPADev contains info about VDPA device
|
||||
type VDPADev struct {
|
||||
vdpaDevID
|
||||
VendorID uint32
|
||||
MaxVQS uint32
|
||||
MaxVQSize uint16
|
||||
MinVQSize uint16
|
||||
}
|
||||
|
||||
// VDPADevConfig contains configuration of the VDPA device
|
||||
type VDPADevConfig struct {
|
||||
vdpaDevID
|
||||
Features uint64
|
||||
NegotiatedFeatures uint64
|
||||
Net VDPADevConfigNet
|
||||
}
|
||||
|
||||
// VDPADevVStats conatins vStats for the VDPA device
|
||||
type VDPADevVStats struct {
|
||||
vdpaDevID
|
||||
QueueIndex uint32
|
||||
Vendor []VDPADevVStatsVendor
|
||||
NegotiatedFeatures uint64
|
||||
}
|
||||
|
||||
// VDPADevVStatsVendor conatins name and value for vendor specific vstat option
|
||||
type VDPADevVStatsVendor struct {
|
||||
Name string
|
||||
Value uint64
|
||||
}
|
||||
|
||||
// VDPADevConfigNet conatins status and net config for the VDPA device
|
||||
type VDPADevConfigNet struct {
|
||||
Status VDPADevConfigNetStatus
|
||||
Cfg VDPADevConfigNetCfg
|
||||
}
|
||||
|
||||
// VDPADevConfigNetStatus contains info about net status
|
||||
type VDPADevConfigNetStatus struct {
|
||||
LinkUp bool
|
||||
Announce bool
|
||||
}
|
||||
|
||||
// VDPADevConfigNetCfg contains net config for the VDPA device
|
||||
type VDPADevConfigNetCfg struct {
|
||||
MACAddr net.HardwareAddr
|
||||
MaxVQP uint16
|
||||
MTU uint16
|
||||
}
|
||||
|
||||
// VDPAMGMTDev conatins info about VDPA management device
|
||||
type VDPAMGMTDev struct {
|
||||
BusName string
|
||||
DevName string
|
||||
SupportedClasses uint64
|
||||
SupportedFeatures uint64
|
||||
MaxVQS uint32
|
||||
}
|
||||
|
||||
// VDPANewDevParams contains parameters for new VDPA device
|
||||
// use SetBits to configure requried features for the device
|
||||
// example:
|
||||
//
|
||||
// VDPANewDevParams{Features: SetBits(0, VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_MAC_ADDR)}
|
||||
type VDPANewDevParams struct {
|
||||
MACAddr net.HardwareAddr
|
||||
MaxVQP uint16
|
||||
MTU uint16
|
||||
Features uint64
|
||||
}
|
||||
|
||||
// SetBits set provided bits in the uint64 input value
|
||||
// usage example:
|
||||
// features := SetBits(0, VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_MAC_ADDR)
|
||||
func SetBits(input uint64, pos ...int) uint64 {
|
||||
for _, p := range pos {
|
||||
input |= 1 << uint64(p)
|
||||
}
|
||||
return input
|
||||
}
|
||||
|
||||
// IsBitSet check if specific bit is set in the uint64 input value
|
||||
// usage example:
|
||||
// hasNetClass := IsBitSet(mgmtDev, VIRTIO_ID_NET)
|
||||
func IsBitSet(input uint64, pos int) bool {
|
||||
val := input & (1 << uint64(pos))
|
||||
return val > 0
|
||||
}
|
||||
|
||||
// VDPANewDev adds new VDPA device
|
||||
// Equivalent to: `vdpa dev add name <name> mgmtdev <mgmtBus>/mgmtName [params]`
|
||||
func VDPANewDev(name, mgmtBus, mgmtName string, params VDPANewDevParams) error {
|
||||
return pkgHandle.VDPANewDev(name, mgmtBus, mgmtName, params)
|
||||
}
|
||||
|
||||
// VDPADelDev removes VDPA device
|
||||
// Equivalent to: `vdpa dev del <name>`
|
||||
func VDPADelDev(name string) error {
|
||||
return pkgHandle.VDPADelDev(name)
|
||||
}
|
||||
|
||||
// VDPAGetDevList returns list of VDPA devices
|
||||
// Equivalent to: `vdpa dev show`
|
||||
func VDPAGetDevList() ([]*VDPADev, error) {
|
||||
return pkgHandle.VDPAGetDevList()
|
||||
}
|
||||
|
||||
// VDPAGetDevByName returns VDPA device selected by name
|
||||
// Equivalent to: `vdpa dev show <name>`
|
||||
func VDPAGetDevByName(name string) (*VDPADev, error) {
|
||||
return pkgHandle.VDPAGetDevByName(name)
|
||||
}
|
||||
|
||||
// VDPAGetDevConfigList returns list of VDPA devices configurations
|
||||
// Equivalent to: `vdpa dev config show`
|
||||
func VDPAGetDevConfigList() ([]*VDPADevConfig, error) {
|
||||
return pkgHandle.VDPAGetDevConfigList()
|
||||
}
|
||||
|
||||
// VDPAGetDevConfigByName returns VDPA device configuration selected by name
|
||||
// Equivalent to: `vdpa dev config show <name>`
|
||||
func VDPAGetDevConfigByName(name string) (*VDPADevConfig, error) {
|
||||
return pkgHandle.VDPAGetDevConfigByName(name)
|
||||
}
|
||||
|
||||
// VDPAGetDevVStats returns vstats for VDPA device
|
||||
// Equivalent to: `vdpa dev vstats show <name> qidx <queueIndex>`
|
||||
func VDPAGetDevVStats(name string, queueIndex uint32) (*VDPADevVStats, error) {
|
||||
return pkgHandle.VDPAGetDevVStats(name, queueIndex)
|
||||
}
|
||||
|
||||
// VDPAGetMGMTDevList returns list of mgmt devices
|
||||
// Equivalent to: `vdpa mgmtdev show`
|
||||
func VDPAGetMGMTDevList() ([]*VDPAMGMTDev, error) {
|
||||
return pkgHandle.VDPAGetMGMTDevList()
|
||||
}
|
||||
|
||||
// VDPAGetMGMTDevByBusAndName returns mgmt devices selected by bus and name
|
||||
// Equivalent to: `vdpa mgmtdev show <bus>/<name>`
|
||||
func VDPAGetMGMTDevByBusAndName(bus, name string) (*VDPAMGMTDev, error) {
|
||||
return pkgHandle.VDPAGetMGMTDevByBusAndName(bus, name)
|
||||
}
|
||||
|
||||
type vdpaNetlinkMessage []syscall.NetlinkRouteAttr
|
||||
|
||||
func (id *vdpaDevID) parseIDAttribute(attr syscall.NetlinkRouteAttr) {
|
||||
switch attr.Attr.Type {
|
||||
case nl.VDPA_ATTR_DEV_NAME:
|
||||
id.Name = nl.BytesToString(attr.Value)
|
||||
case nl.VDPA_ATTR_DEV_ID:
|
||||
id.ID = native.Uint32(attr.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func (netStatus *VDPADevConfigNetStatus) parseStatusAttribute(value []byte) {
|
||||
a := native.Uint16(value)
|
||||
netStatus.Announce = (a & VIRTIO_NET_S_ANNOUNCE) > 0
|
||||
netStatus.LinkUp = (a & VIRTIO_NET_S_LINK_UP) > 0
|
||||
}
|
||||
|
||||
func (d *VDPADev) parseAttributes(attrs vdpaNetlinkMessage) {
|
||||
for _, a := range attrs {
|
||||
d.parseIDAttribute(a)
|
||||
switch a.Attr.Type {
|
||||
case nl.VDPA_ATTR_DEV_VENDOR_ID:
|
||||
d.VendorID = native.Uint32(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_MAX_VQS:
|
||||
d.MaxVQS = native.Uint32(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_MAX_VQ_SIZE:
|
||||
d.MaxVQSize = native.Uint16(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_MIN_VQ_SIZE:
|
||||
d.MinVQSize = native.Uint16(a.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *VDPADevConfig) parseAttributes(attrs vdpaNetlinkMessage) {
|
||||
for _, a := range attrs {
|
||||
c.parseIDAttribute(a)
|
||||
switch a.Attr.Type {
|
||||
case nl.VDPA_ATTR_DEV_NET_CFG_MACADDR:
|
||||
c.Net.Cfg.MACAddr = a.Value
|
||||
case nl.VDPA_ATTR_DEV_NET_STATUS:
|
||||
c.Net.Status.parseStatusAttribute(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_NET_CFG_MAX_VQP:
|
||||
c.Net.Cfg.MaxVQP = native.Uint16(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_NET_CFG_MTU:
|
||||
c.Net.Cfg.MTU = native.Uint16(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_FEATURES:
|
||||
c.Features = native.Uint64(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_NEGOTIATED_FEATURES:
|
||||
c.NegotiatedFeatures = native.Uint64(a.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *VDPADevVStats) parseAttributes(attrs vdpaNetlinkMessage) {
|
||||
for _, a := range attrs {
|
||||
s.parseIDAttribute(a)
|
||||
switch a.Attr.Type {
|
||||
case nl.VDPA_ATTR_DEV_QUEUE_INDEX:
|
||||
s.QueueIndex = native.Uint32(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_VENDOR_ATTR_NAME:
|
||||
s.Vendor = append(s.Vendor, VDPADevVStatsVendor{Name: nl.BytesToString(a.Value)})
|
||||
case nl.VDPA_ATTR_DEV_VENDOR_ATTR_VALUE:
|
||||
if len(s.Vendor) == 0 {
|
||||
break
|
||||
}
|
||||
s.Vendor[len(s.Vendor)-1].Value = native.Uint64(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_NEGOTIATED_FEATURES:
|
||||
s.NegotiatedFeatures = native.Uint64(a.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *VDPAMGMTDev) parseAttributes(attrs vdpaNetlinkMessage) {
|
||||
for _, a := range attrs {
|
||||
switch a.Attr.Type {
|
||||
case nl.VDPA_ATTR_MGMTDEV_BUS_NAME:
|
||||
d.BusName = nl.BytesToString(a.Value)
|
||||
case nl.VDPA_ATTR_MGMTDEV_DEV_NAME:
|
||||
d.DevName = nl.BytesToString(a.Value)
|
||||
case nl.VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES:
|
||||
d.SupportedClasses = native.Uint64(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_SUPPORTED_FEATURES:
|
||||
d.SupportedFeatures = native.Uint64(a.Value)
|
||||
case nl.VDPA_ATTR_DEV_MGMTDEV_MAX_VQS:
|
||||
d.MaxVQS = native.Uint32(a.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handle) vdpaRequest(command uint8, extraFlags int, attrs []*nl.RtAttr) ([]vdpaNetlinkMessage, error) {
|
||||
f, err := h.GenlFamilyGet(nl.VDPA_GENL_NAME)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := h.newNetlinkRequest(int(f.ID), unix.NLM_F_ACK|extraFlags)
|
||||
req.AddData(&nl.Genlmsg{
|
||||
Command: command,
|
||||
Version: nl.VDPA_GENL_VERSION,
|
||||
})
|
||||
for _, a := range attrs {
|
||||
req.AddData(a)
|
||||
}
|
||||
|
||||
resp, err := req.Execute(unix.NETLINK_GENERIC, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
messages := make([]vdpaNetlinkMessage, 0, len(resp))
|
||||
for _, m := range resp {
|
||||
attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
messages = append(messages, attrs)
|
||||
}
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
// dump all devices if dev is nil
|
||||
func (h *Handle) vdpaDevGet(dev *string) ([]*VDPADev, error) {
|
||||
var extraFlags int
|
||||
var attrs []*nl.RtAttr
|
||||
if dev != nil {
|
||||
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(*dev)))
|
||||
} else {
|
||||
extraFlags = extraFlags | unix.NLM_F_DUMP
|
||||
}
|
||||
messages, err := h.vdpaRequest(nl.VDPA_CMD_DEV_GET, extraFlags, attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
devs := make([]*VDPADev, 0, len(messages))
|
||||
for _, m := range messages {
|
||||
d := &VDPADev{}
|
||||
d.parseAttributes(m)
|
||||
devs = append(devs, d)
|
||||
}
|
||||
return devs, nil
|
||||
}
|
||||
|
||||
// dump all devices if dev is nil
|
||||
func (h *Handle) vdpaDevConfigGet(dev *string) ([]*VDPADevConfig, error) {
|
||||
var extraFlags int
|
||||
var attrs []*nl.RtAttr
|
||||
if dev != nil {
|
||||
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(*dev)))
|
||||
} else {
|
||||
extraFlags = extraFlags | unix.NLM_F_DUMP
|
||||
}
|
||||
messages, err := h.vdpaRequest(nl.VDPA_CMD_DEV_CONFIG_GET, extraFlags, attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfgs := make([]*VDPADevConfig, 0, len(messages))
|
||||
for _, m := range messages {
|
||||
cfg := &VDPADevConfig{}
|
||||
cfg.parseAttributes(m)
|
||||
cfgs = append(cfgs, cfg)
|
||||
}
|
||||
return cfgs, nil
|
||||
}
|
||||
|
||||
// dump all devices if dev is nil
|
||||
func (h *Handle) vdpaMGMTDevGet(bus, dev *string) ([]*VDPAMGMTDev, error) {
|
||||
var extraFlags int
|
||||
var attrs []*nl.RtAttr
|
||||
if dev != nil {
|
||||
attrs = append(attrs,
|
||||
nl.NewRtAttr(nl.VDPA_ATTR_MGMTDEV_DEV_NAME, nl.ZeroTerminated(*dev)),
|
||||
)
|
||||
if bus != nil {
|
||||
attrs = append(attrs,
|
||||
nl.NewRtAttr(nl.VDPA_ATTR_MGMTDEV_BUS_NAME, nl.ZeroTerminated(*bus)),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
extraFlags = extraFlags | unix.NLM_F_DUMP
|
||||
}
|
||||
messages, err := h.vdpaRequest(nl.VDPA_CMD_MGMTDEV_GET, extraFlags, attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfgs := make([]*VDPAMGMTDev, 0, len(messages))
|
||||
for _, m := range messages {
|
||||
cfg := &VDPAMGMTDev{}
|
||||
cfg.parseAttributes(m)
|
||||
cfgs = append(cfgs, cfg)
|
||||
}
|
||||
return cfgs, nil
|
||||
}
|
||||
|
||||
// VDPANewDev adds new VDPA device
|
||||
// Equivalent to: `vdpa dev add name <name> mgmtdev <mgmtBus>/mgmtName [params]`
|
||||
func (h *Handle) VDPANewDev(name, mgmtBus, mgmtName string, params VDPANewDevParams) error {
|
||||
attrs := []*nl.RtAttr{
|
||||
nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(name)),
|
||||
nl.NewRtAttr(nl.VDPA_ATTR_MGMTDEV_DEV_NAME, nl.ZeroTerminated(mgmtName)),
|
||||
}
|
||||
if mgmtBus != "" {
|
||||
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_MGMTDEV_BUS_NAME, nl.ZeroTerminated(mgmtBus)))
|
||||
}
|
||||
if len(params.MACAddr) != 0 {
|
||||
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NET_CFG_MACADDR, params.MACAddr))
|
||||
}
|
||||
if params.MaxVQP > 0 {
|
||||
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NET_CFG_MAX_VQP, nl.Uint16Attr(params.MaxVQP)))
|
||||
}
|
||||
if params.MTU > 0 {
|
||||
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NET_CFG_MTU, nl.Uint16Attr(params.MTU)))
|
||||
}
|
||||
if params.Features > 0 {
|
||||
attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_FEATURES, nl.Uint64Attr(params.Features)))
|
||||
}
|
||||
_, err := h.vdpaRequest(nl.VDPA_CMD_DEV_NEW, 0, attrs)
|
||||
return err
|
||||
}
|
||||
|
||||
// VDPADelDev removes VDPA device
|
||||
// Equivalent to: `vdpa dev del <name>`
|
||||
func (h *Handle) VDPADelDev(name string) error {
|
||||
_, err := h.vdpaRequest(nl.VDPA_CMD_DEV_DEL, 0, []*nl.RtAttr{
|
||||
nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(name))})
|
||||
return err
|
||||
}
|
||||
|
||||
// VDPAGetDevList returns list of VDPA devices
|
||||
// Equivalent to: `vdpa dev show`
|
||||
func (h *Handle) VDPAGetDevList() ([]*VDPADev, error) {
|
||||
return h.vdpaDevGet(nil)
|
||||
}
|
||||
|
||||
// VDPAGetDevByName returns VDPA device selected by name
|
||||
// Equivalent to: `vdpa dev show <name>`
|
||||
func (h *Handle) VDPAGetDevByName(name string) (*VDPADev, error) {
|
||||
devs, err := h.vdpaDevGet(&name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(devs) == 0 {
|
||||
return nil, fmt.Errorf("device not found")
|
||||
}
|
||||
return devs[0], nil
|
||||
}
|
||||
|
||||
// VDPAGetDevConfigList returns list of VDPA devices configurations
|
||||
// Equivalent to: `vdpa dev config show`
|
||||
func (h *Handle) VDPAGetDevConfigList() ([]*VDPADevConfig, error) {
|
||||
return h.vdpaDevConfigGet(nil)
|
||||
}
|
||||
|
||||
// VDPAGetDevConfigByName returns VDPA device configuration selected by name
|
||||
// Equivalent to: `vdpa dev config show <name>`
|
||||
func (h *Handle) VDPAGetDevConfigByName(name string) (*VDPADevConfig, error) {
|
||||
cfgs, err := h.vdpaDevConfigGet(&name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(cfgs) == 0 {
|
||||
return nil, fmt.Errorf("configuration not found")
|
||||
}
|
||||
return cfgs[0], nil
|
||||
}
|
||||
|
||||
// VDPAGetDevVStats returns vstats for VDPA device
|
||||
// Equivalent to: `vdpa dev vstats show <name> qidx <queueIndex>`
|
||||
func (h *Handle) VDPAGetDevVStats(name string, queueIndex uint32) (*VDPADevVStats, error) {
|
||||
messages, err := h.vdpaRequest(nl.VDPA_CMD_DEV_VSTATS_GET, 0, []*nl.RtAttr{
|
||||
nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(name)),
|
||||
nl.NewRtAttr(nl.VDPA_ATTR_DEV_QUEUE_INDEX, nl.Uint32Attr(queueIndex)),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(messages) == 0 {
|
||||
return nil, fmt.Errorf("stats not found")
|
||||
}
|
||||
stats := &VDPADevVStats{}
|
||||
stats.parseAttributes(messages[0])
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
// VDPAGetMGMTDevList returns list of mgmt devices
|
||||
// Equivalent to: `vdpa mgmtdev show`
|
||||
func (h *Handle) VDPAGetMGMTDevList() ([]*VDPAMGMTDev, error) {
|
||||
return h.vdpaMGMTDevGet(nil, nil)
|
||||
}
|
||||
|
||||
// VDPAGetMGMTDevByBusAndName returns mgmt devices selected by bus and name
|
||||
// Equivalent to: `vdpa mgmtdev show <bus>/<name>`
|
||||
func (h *Handle) VDPAGetMGMTDevByBusAndName(bus, name string) (*VDPAMGMTDev, error) {
|
||||
var busPtr *string
|
||||
if bus != "" {
|
||||
busPtr = &bus
|
||||
}
|
||||
devs, err := h.vdpaMGMTDevGet(busPtr, &name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(devs) == 0 {
|
||||
return nil, fmt.Errorf("mgmtdev not found")
|
||||
}
|
||||
return devs[0], nil
|
||||
}
|
132
vendor/github.com/vishvananda/netlink/virtio.go
generated
vendored
Normal file
132
vendor/github.com/vishvananda/netlink/virtio.go
generated
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
package netlink
|
||||
|
||||
// features for virtio net
|
||||
const (
|
||||
VIRTIO_NET_F_CSUM = 0 // Host handles pkts w/ partial csum
|
||||
VIRTIO_NET_F_GUEST_CSUM = 1 // Guest handles pkts w/ partial csum
|
||||
VIRTIO_NET_F_CTRL_GUEST_OFFLOADS = 2 // Dynamic offload configuration.
|
||||
VIRTIO_NET_F_MTU = 3 // Initial MTU advice
|
||||
VIRTIO_NET_F_MAC = 5 // Host has given MAC address.
|
||||
VIRTIO_NET_F_GUEST_TSO4 = 7 // Guest can handle TSOv4 in.
|
||||
VIRTIO_NET_F_GUEST_TSO6 = 8 // Guest can handle TSOv6 in.
|
||||
VIRTIO_NET_F_GUEST_ECN = 9 // Guest can handle TSO[6] w/ ECN in.
|
||||
VIRTIO_NET_F_GUEST_UFO = 10 // Guest can handle UFO in.
|
||||
VIRTIO_NET_F_HOST_TSO4 = 11 // Host can handle TSOv4 in.
|
||||
VIRTIO_NET_F_HOST_TSO6 = 12 // Host can handle TSOv6 in.
|
||||
VIRTIO_NET_F_HOST_ECN = 13 // Host can handle TSO[6] w/ ECN in.
|
||||
VIRTIO_NET_F_HOST_UFO = 14 // Host can handle UFO in.
|
||||
VIRTIO_NET_F_MRG_RXBUF = 15 // Host can merge receive buffers.
|
||||
VIRTIO_NET_F_STATUS = 16 // virtio_net_config.status available
|
||||
VIRTIO_NET_F_CTRL_VQ = 17 // Control channel available
|
||||
VIRTIO_NET_F_CTRL_RX = 18 // Control channel RX mode support
|
||||
VIRTIO_NET_F_CTRL_VLAN = 19 // Control channel VLAN filtering
|
||||
VIRTIO_NET_F_CTRL_RX_EXTRA = 20 // Extra RX mode control support
|
||||
VIRTIO_NET_F_GUEST_ANNOUNCE = 21 // Guest can announce device on the* network
|
||||
VIRTIO_NET_F_MQ = 22 // Device supports Receive Flow Steering
|
||||
VIRTIO_NET_F_CTRL_MAC_ADDR = 23 // Set MAC address
|
||||
VIRTIO_NET_F_VQ_NOTF_COAL = 52 // Device supports virtqueue notification coalescing
|
||||
VIRTIO_NET_F_NOTF_COAL = 53 // Device supports notifications coalescing
|
||||
VIRTIO_NET_F_GUEST_USO4 = 54 // Guest can handle USOv4 in.
|
||||
VIRTIO_NET_F_GUEST_USO6 = 55 // Guest can handle USOv6 in.
|
||||
VIRTIO_NET_F_HOST_USO = 56 // Host can handle USO in.
|
||||
VIRTIO_NET_F_HASH_REPORT = 57 // Supports hash report
|
||||
VIRTIO_NET_F_GUEST_HDRLEN = 59 // Guest provides the exact hdr_len value.
|
||||
VIRTIO_NET_F_RSS = 60 // Supports RSS RX steering
|
||||
VIRTIO_NET_F_RSC_EXT = 61 // extended coalescing info
|
||||
VIRTIO_NET_F_STANDBY = 62 // Act as standby for another device with the same MAC.
|
||||
VIRTIO_NET_F_SPEED_DUPLEX = 63 // Device set linkspeed and duplex
|
||||
VIRTIO_NET_F_GSO = 6 // Host handles pkts any GSO type
|
||||
)
|
||||
|
||||
// virtio net status
|
||||
const (
|
||||
VIRTIO_NET_S_LINK_UP = 1 // Link is up
|
||||
VIRTIO_NET_S_ANNOUNCE = 2 // Announcement is needed
|
||||
)
|
||||
|
||||
// virtio config
|
||||
const (
|
||||
// Do we get callbacks when the ring is completely used, even if we've
|
||||
// suppressed them?
|
||||
VIRTIO_F_NOTIFY_ON_EMPTY = 24
|
||||
// Can the device handle any descriptor layout?
|
||||
VIRTIO_F_ANY_LAYOUT = 27
|
||||
// v1.0 compliant
|
||||
VIRTIO_F_VERSION_1 = 32
|
||||
// If clear - device has the platform DMA (e.g. IOMMU) bypass quirk feature.
|
||||
// If set - use platform DMA tools to access the memory.
|
||||
// Note the reverse polarity (compared to most other features),
|
||||
// this is for compatibility with legacy systems.
|
||||
VIRTIO_F_ACCESS_PLATFORM = 33
|
||||
// Legacy name for VIRTIO_F_ACCESS_PLATFORM (for compatibility with old userspace)
|
||||
VIRTIO_F_IOMMU_PLATFORM = VIRTIO_F_ACCESS_PLATFORM
|
||||
// This feature indicates support for the packed virtqueue layout.
|
||||
VIRTIO_F_RING_PACKED = 34
|
||||
// Inorder feature indicates that all buffers are used by the device
|
||||
// in the same order in which they have been made available.
|
||||
VIRTIO_F_IN_ORDER = 35
|
||||
// This feature indicates that memory accesses by the driver and the
|
||||
// device are ordered in a way described by the platform.
|
||||
VIRTIO_F_ORDER_PLATFORM = 36
|
||||
// Does the device support Single Root I/O Virtualization?
|
||||
VIRTIO_F_SR_IOV = 37
|
||||
// This feature indicates that the driver passes extra data (besides
|
||||
// identifying the virtqueue) in its device notifications.
|
||||
VIRTIO_F_NOTIFICATION_DATA = 38
|
||||
// This feature indicates that the driver uses the data provided by the device
|
||||
// as a virtqueue identifier in available buffer notifications.
|
||||
VIRTIO_F_NOTIF_CONFIG_DATA = 39
|
||||
// This feature indicates that the driver can reset a queue individually.
|
||||
VIRTIO_F_RING_RESET = 40
|
||||
)
|
||||
|
||||
// virtio device ids
|
||||
const (
|
||||
VIRTIO_ID_NET = 1 // virtio net
|
||||
VIRTIO_ID_BLOCK = 2 // virtio block
|
||||
VIRTIO_ID_CONSOLE = 3 // virtio console
|
||||
VIRTIO_ID_RNG = 4 // virtio rng
|
||||
VIRTIO_ID_BALLOON = 5 // virtio balloon
|
||||
VIRTIO_ID_IOMEM = 6 // virtio ioMemory
|
||||
VIRTIO_ID_RPMSG = 7 // virtio remote processor messaging
|
||||
VIRTIO_ID_SCSI = 8 // virtio scsi
|
||||
VIRTIO_ID_9P = 9 // 9p virtio console
|
||||
VIRTIO_ID_MAC80211_WLAN = 10 // virtio WLAN MAC
|
||||
VIRTIO_ID_RPROC_SERIAL = 11 // virtio remoteproc serial link
|
||||
VIRTIO_ID_CAIF = 12 // Virtio caif
|
||||
VIRTIO_ID_MEMORY_BALLOON = 13 // virtio memory balloon
|
||||
VIRTIO_ID_GPU = 16 // virtio GPU
|
||||
VIRTIO_ID_CLOCK = 17 // virtio clock/timer
|
||||
VIRTIO_ID_INPUT = 18 // virtio input
|
||||
VIRTIO_ID_VSOCK = 19 // virtio vsock transport
|
||||
VIRTIO_ID_CRYPTO = 20 // virtio crypto
|
||||
VIRTIO_ID_SIGNAL_DIST = 21 // virtio signal distribution device
|
||||
VIRTIO_ID_PSTORE = 22 // virtio pstore device
|
||||
VIRTIO_ID_IOMMU = 23 // virtio IOMMU
|
||||
VIRTIO_ID_MEM = 24 // virtio mem
|
||||
VIRTIO_ID_SOUND = 25 // virtio sound
|
||||
VIRTIO_ID_FS = 26 // virtio filesystem
|
||||
VIRTIO_ID_PMEM = 27 // virtio pmem
|
||||
VIRTIO_ID_RPMB = 28 // virtio rpmb
|
||||
VIRTIO_ID_MAC80211_HWSIM = 29 // virtio mac80211-hwsim
|
||||
VIRTIO_ID_VIDEO_ENCODER = 30 // virtio video encoder
|
||||
VIRTIO_ID_VIDEO_DECODER = 31 // virtio video decoder
|
||||
VIRTIO_ID_SCMI = 32 // virtio SCMI
|
||||
VIRTIO_ID_NITRO_SEC_MOD = 33 // virtio nitro secure module
|
||||
VIRTIO_ID_I2C_ADAPTER = 34 // virtio i2c adapter
|
||||
VIRTIO_ID_WATCHDOG = 35 // virtio watchdog
|
||||
VIRTIO_ID_CAN = 36 // virtio can
|
||||
VIRTIO_ID_DMABUF = 37 // virtio dmabuf
|
||||
VIRTIO_ID_PARAM_SERV = 38 // virtio parameter server
|
||||
VIRTIO_ID_AUDIO_POLICY = 39 // virtio audio policy
|
||||
VIRTIO_ID_BT = 40 // virtio bluetooth
|
||||
VIRTIO_ID_GPIO = 41 // virtio gpio
|
||||
// Virtio Transitional IDs
|
||||
VIRTIO_TRANS_ID_NET = 0x1000 // transitional virtio net
|
||||
VIRTIO_TRANS_ID_BLOCK = 0x1001 // transitional virtio block
|
||||
VIRTIO_TRANS_ID_BALLOON = 0x1002 // transitional virtio balloon
|
||||
VIRTIO_TRANS_ID_CONSOLE = 0x1003 // transitional virtio console
|
||||
VIRTIO_TRANS_ID_SCSI = 0x1004 // transitional virtio SCSI
|
||||
VIRTIO_TRANS_ID_RNG = 0x1005 // transitional virtio rng
|
||||
VIRTIO_TRANS_ID_9P = 0x1009 // transitional virtio 9p console
|
||||
)
|
34
vendor/github.com/vishvananda/netlink/xdp_diag.go
generated
vendored
Normal file
34
vendor/github.com/vishvananda/netlink/xdp_diag.go
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
package netlink
|
||||
|
||||
import "github.com/vishvananda/netlink/nl"
|
||||
|
||||
const SOCK_ANY_COOKIE = uint64(nl.TCPDIAG_NOCOOKIE)<<32 + uint64(nl.TCPDIAG_NOCOOKIE)
|
||||
|
||||
// XDP diagnosis show flag constants to request particular information elements.
|
||||
const (
|
||||
XDP_SHOW_INFO = 1 << iota
|
||||
XDP_SHOW_RING_CFG
|
||||
XDP_SHOW_UMEM
|
||||
XDP_SHOW_MEMINFO
|
||||
XDP_SHOW_STATS
|
||||
)
|
||||
|
||||
// XDP diag element constants
|
||||
const (
|
||||
XDP_DIAG_NONE = iota
|
||||
XDP_DIAG_INFO // when using XDP_SHOW_INFO
|
||||
XDP_DIAG_UID // when using XDP_SHOW_INFO
|
||||
XDP_DIAG_RX_RING // when using XDP_SHOW_RING_CFG
|
||||
XDP_DIAG_TX_RING // when using XDP_SHOW_RING_CFG
|
||||
XDP_DIAG_UMEM // when using XDP_SHOW_UMEM
|
||||
XDP_DIAG_UMEM_FILL_RING // when using XDP_SHOW_UMEM
|
||||
XDP_DIAG_UMEM_COMPLETION_RING // when using XDP_SHOW_UMEM
|
||||
XDP_DIAG_MEMINFO // when using XDP_SHOW_MEMINFO
|
||||
XDP_DIAG_STATS // when using XDP_SHOW_STATS
|
||||
)
|
||||
|
||||
// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L21
|
||||
type XDPDiagInfoResp struct {
|
||||
XDPDiagMsg *XDPSocket
|
||||
XDPInfo *XDPInfo
|
||||
}
|
46
vendor/github.com/vishvananda/netlink/xdp_linux.go
generated
vendored
Normal file
46
vendor/github.com/vishvananda/netlink/xdp_linux.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
xdrDiagUmemLen = 8 + 8*4
|
||||
xdrDiagStatsLen = 6 * 8
|
||||
)
|
||||
|
||||
func (x *XDPDiagUmem) deserialize(b []byte) error {
|
||||
if len(b) < xdrDiagUmemLen {
|
||||
return fmt.Errorf("XDP umem diagnosis data short read (%d); want %d", len(b), xdrDiagUmemLen)
|
||||
}
|
||||
|
||||
rb := bytes.NewBuffer(b)
|
||||
x.Size = native.Uint64(rb.Next(8))
|
||||
x.ID = native.Uint32(rb.Next(4))
|
||||
x.NumPages = native.Uint32(rb.Next(4))
|
||||
x.ChunkSize = native.Uint32(rb.Next(4))
|
||||
x.Headroom = native.Uint32(rb.Next(4))
|
||||
x.Ifindex = native.Uint32(rb.Next(4))
|
||||
x.QueueID = native.Uint32(rb.Next(4))
|
||||
x.Flags = native.Uint32(rb.Next(4))
|
||||
x.Refs = native.Uint32(rb.Next(4))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *XDPDiagStats) deserialize(b []byte) error {
|
||||
if len(b) < xdrDiagStatsLen {
|
||||
return fmt.Errorf("XDP diagnosis statistics short read (%d); want %d", len(b), xdrDiagStatsLen)
|
||||
}
|
||||
|
||||
rb := bytes.NewBuffer(b)
|
||||
x.RxDropped = native.Uint64(rb.Next(8))
|
||||
x.RxInvalid = native.Uint64(rb.Next(8))
|
||||
x.RxFull = native.Uint64(rb.Next(8))
|
||||
x.FillRingEmpty = native.Uint64(rb.Next(8))
|
||||
x.TxInvalid = native.Uint64(rb.Next(8))
|
||||
x.TxRingEmpty = native.Uint64(rb.Next(8))
|
||||
|
||||
return nil
|
||||
}
|
@ -14,7 +14,7 @@ const (
|
||||
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_COMP Proto = unix.IPPROTO_COMP
|
||||
XFRM_PROTO_IPSEC_ANY Proto = unix.IPPROTO_RAW
|
||||
)
|
||||
|
97
vendor/github.com/vishvananda/netlink/xfrm_policy.go
generated
vendored
97
vendor/github.com/vishvananda/netlink/xfrm_policy.go
generated
vendored
@ -1,97 +0,0 @@
|
||||
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)
|
||||
}
|
99
vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
generated
vendored
99
vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
generated
vendored
@ -1,10 +1,104 @@
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
func selFromPolicy(sel *nl.XfrmSelector, policy *XfrmPolicy) {
|
||||
sel.Family = uint16(nl.FAMILY_V4)
|
||||
if policy.Dst != nil {
|
||||
@ -75,6 +169,7 @@ func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
|
||||
userTmpl := nl.DeserializeXfrmUserTmpl(tmplData[start : start+nl.SizeofXfrmUserTmpl])
|
||||
userTmpl.XfrmId.Daddr.FromIP(tmpl.Dst)
|
||||
userTmpl.Saddr.FromIP(tmpl.Src)
|
||||
userTmpl.Family = uint16(nl.GetIPFamily(tmpl.Dst))
|
||||
userTmpl.XfrmId.Proto = uint8(tmpl.Proto)
|
||||
userTmpl.XfrmId.Spi = nl.Swap32(uint32(tmpl.Spi))
|
||||
userTmpl.Mode = uint8(tmpl.Mode)
|
||||
@ -223,8 +318,8 @@ func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
|
||||
|
||||
var policy XfrmPolicy
|
||||
|
||||
policy.Dst = msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD)
|
||||
policy.Src = msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS)
|
||||
policy.Dst = msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD, uint16(family))
|
||||
policy.Src = msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS, uint16(family))
|
||||
policy.Proto = Proto(msg.Sel.Proto)
|
||||
policy.DstPort = int(nl.Swap16(msg.Sel.Dport))
|
||||
policy.SrcPort = int(nl.Swap16(msg.Sel.Sport))
|
||||
|
131
vendor/github.com/vishvananda/netlink/xfrm_state.go
generated
vendored
131
vendor/github.com/vishvananda/netlink/xfrm_state.go
generated
vendored
@ -1,131 +0,0 @@
|
||||
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)
|
||||
}
|
199
vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
generated
vendored
199
vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
generated
vendored
@ -2,12 +2,154 @@ package netlink
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// XfrmReplayState represents the sequence number states for
|
||||
// "legacy" anti-replay mode.
|
||||
type XfrmReplayState struct {
|
||||
OSeq uint32
|
||||
Seq uint32
|
||||
BitMap uint32
|
||||
}
|
||||
|
||||
func (r XfrmReplayState) String() string {
|
||||
return fmt.Sprintf("{OSeq: 0x%x, Seq: 0x%x, BitMap: 0x%x}",
|
||||
r.OSeq, r.Seq, r.BitMap)
|
||||
}
|
||||
|
||||
// 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
|
||||
DontEncapDSCP bool
|
||||
OSeqMayWrap bool
|
||||
Replay *XfrmReplayState
|
||||
Selector *XfrmPolicy
|
||||
}
|
||||
|
||||
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, DontEncapDSCP: %t, OSeqMayWrap: %t, Replay: %v",
|
||||
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, sa.DontEncapDSCP, sa.OSeqMayWrap, sa.Replay)
|
||||
}
|
||||
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)
|
||||
}
|
||||
func writeStateAlgo(a *XfrmStateAlgo) []byte {
|
||||
algo := nl.XfrmAlgo{
|
||||
AlgKeyLen: uint32(len(a.Key) * 8),
|
||||
@ -77,6 +219,14 @@ func writeReplayEsn(replayWindow int) []byte {
|
||||
return replayEsn.Serialize()
|
||||
}
|
||||
|
||||
func writeReplay(r *XfrmReplayState) []byte {
|
||||
return (&nl.XfrmReplayState{
|
||||
OSeq: r.OSeq,
|
||||
Seq: r.Seq,
|
||||
BitMap: r.BitMap,
|
||||
}).Serialize()
|
||||
}
|
||||
|
||||
// XfrmStateAdd will add an xfrm state to the system.
|
||||
// Equivalent to: `ip xfrm state add $state`
|
||||
func XfrmStateAdd(state *XfrmState) error {
|
||||
@ -166,6 +316,21 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
|
||||
req.AddData(out)
|
||||
}
|
||||
}
|
||||
if state.OSeqMayWrap || state.DontEncapDSCP {
|
||||
var flags uint32
|
||||
if state.DontEncapDSCP {
|
||||
flags |= nl.XFRM_SA_XFLAG_DONT_ENCAP_DSCP
|
||||
}
|
||||
if state.OSeqMayWrap {
|
||||
flags |= nl.XFRM_SA_XFLAG_OSEQ_MAY_WRAP
|
||||
}
|
||||
out := nl.NewRtAttr(nl.XFRMA_SA_EXTRA_FLAGS, nl.Uint32Attr(flags))
|
||||
req.AddData(out)
|
||||
}
|
||||
if state.Replay != nil {
|
||||
out := nl.NewRtAttr(nl.XFRMA_REPLAY_VAL, writeReplay(state.Replay))
|
||||
req.AddData(out)
|
||||
}
|
||||
|
||||
if state.Ifid != 0 {
|
||||
ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid)))
|
||||
@ -186,7 +351,6 @@ func (h *Handle) xfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) {
|
||||
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)
|
||||
@ -314,7 +478,6 @@ 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)
|
||||
@ -324,20 +487,25 @@ func xfrmStateFromXfrmUsersaInfo(msg *nl.XfrmUsersaInfo) *XfrmState {
|
||||
state.ReplayWindow = int(msg.ReplayWindow)
|
||||
lftToLimits(&msg.Lft, &state.Limits)
|
||||
curToStats(&msg.Curlft, &msg.Stats, &state.Statistics)
|
||||
state.Selector = &XfrmPolicy{
|
||||
Dst: msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD, msg.Sel.Family),
|
||||
Src: msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS, msg.Sel.Family),
|
||||
Proto: Proto(msg.Sel.Proto),
|
||||
DstPort: int(nl.Swap16(msg.Sel.Dport)),
|
||||
SrcPort: int(nl.Swap16(msg.Sel.Sport)),
|
||||
Ifindex: int(msg.Sel.Ifindex),
|
||||
}
|
||||
|
||||
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
|
||||
@ -385,6 +553,14 @@ func parseXfrmState(m []byte, family int) (*XfrmState, error) {
|
||||
state.Mark = new(XfrmMark)
|
||||
state.Mark.Value = mark.Value
|
||||
state.Mark.Mask = mark.Mask
|
||||
case nl.XFRMA_SA_EXTRA_FLAGS:
|
||||
flags := native.Uint32(attr.Value)
|
||||
if (flags & nl.XFRM_SA_XFLAG_DONT_ENCAP_DSCP) != 0 {
|
||||
state.DontEncapDSCP = true
|
||||
}
|
||||
if (flags & nl.XFRM_SA_XFLAG_OSEQ_MAY_WRAP) != 0 {
|
||||
state.OSeqMayWrap = true
|
||||
}
|
||||
case nl.XFRMA_SET_MARK:
|
||||
if state.OutputMark == nil {
|
||||
state.OutputMark = new(XfrmMark)
|
||||
@ -400,6 +576,14 @@ func parseXfrmState(m []byte, family int) (*XfrmState, error) {
|
||||
}
|
||||
case nl.XFRMA_IF_ID:
|
||||
state.Ifid = int(native.Uint32(attr.Value))
|
||||
case nl.XFRMA_REPLAY_VAL:
|
||||
if state.Replay == nil {
|
||||
state.Replay = new(XfrmReplayState)
|
||||
}
|
||||
replay := nl.DeserializeXfrmReplayState(attr.Value[:])
|
||||
state.Replay.OSeq = replay.OSeq
|
||||
state.Replay.Seq = replay.Seq
|
||||
state.Replay.BitMap = replay.BitMap
|
||||
}
|
||||
}
|
||||
|
||||
@ -476,6 +660,9 @@ func xfrmUsersaInfoFromXfrmState(state *XfrmState) *nl.XfrmUsersaInfo {
|
||||
msg.Id.Spi = nl.Swap32(uint32(state.Spi))
|
||||
msg.Reqid = uint32(state.Reqid)
|
||||
msg.ReplayWindow = uint8(state.ReplayWindow)
|
||||
|
||||
msg.Sel = nl.XfrmSelector{}
|
||||
if state.Selector != nil {
|
||||
selFromPolicy(&msg.Sel, state.Selector)
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
7
vendor/github.com/vishvananda/netlink/xfrm_unspecified.go
generated
vendored
Normal file
7
vendor/github.com/vishvananda/netlink/xfrm_unspecified.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package netlink
|
||||
|
||||
type XfrmPolicy struct{}
|
||||
type XfrmState struct{}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user