Compare commits
15 Commits
v1.2.0
...
dependabot
Author | SHA1 | Date | |
---|---|---|---|
284d8c6996 | |||
fb92605570 | |||
01d0031487 | |||
98e01b7c80 | |||
9a2f763345 | |||
98359ff8b4 | |||
29e6486154 | |||
bbf47c1083 | |||
5d02d91c96 | |||
755714d716 | |||
e2e14ee46f | |||
fb5d195fc5 | |||
ac7cf82531 | |||
c798f80912 | |||
9fa80036d3 |
10
go.mod
10
go.mod
@ -16,14 +16,16 @@ require (
|
||||
github.com/mattn/go-shellwords v1.0.12
|
||||
github.com/networkplumbing/go-nft v0.2.0
|
||||
github.com/onsi/ginkgo v1.16.5
|
||||
github.com/onsi/gomega v1.24.2
|
||||
github.com/onsi/gomega v1.26.0
|
||||
github.com/opencontainers/selinux v1.8.2
|
||||
github.com/safchain/ethtool v0.2.0
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2
|
||||
golang.org/x/sys v0.4.0
|
||||
golang.org/x/sys v0.5.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Microsoft/go-winio v0.4.17 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.2.0 // indirect
|
||||
github.com/containerd/cgroups v1.0.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
@ -34,8 +36,8 @@ require (
|
||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
|
||||
go.opencensus.io v0.22.3 // indirect
|
||||
golang.org/x/net v0.4.0 // indirect
|
||||
golang.org/x/text v0.5.0 // indirect
|
||||
golang.org/x/net v0.7.0 // indirect
|
||||
golang.org/x/text v0.7.0 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
24
go.sum
24
go.sum
@ -82,6 +82,7 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
||||
github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA=
|
||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
@ -509,8 +510,8 @@ github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7
|
||||
github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0=
|
||||
github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo=
|
||||
github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw=
|
||||
github.com/onsi/ginkgo/v2 v2.6.1 h1:1xQPCjcqYw/J5LchOcp4/2q/jzJFjiAOc25chhnDw+Q=
|
||||
github.com/onsi/ginkgo/v2 v2.6.1/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo=
|
||||
github.com/onsi/ginkgo/v2 v2.7.0 h1:/XxtEV3I3Eif/HobnVx9YmJgk8ENdRsuUmM+fLCFNow=
|
||||
github.com/onsi/ginkgo/v2 v2.7.0/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo=
|
||||
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
@ -526,8 +527,8 @@ github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8lu
|
||||
github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM=
|
||||
github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
|
||||
github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
|
||||
github.com/onsi/gomega v1.24.2 h1:J/tulyYK6JwBldPViHJReihxxZ+22FHs0piGjQAvoUE=
|
||||
github.com/onsi/gomega v1.24.2/go.mod h1:gs3J10IS7Z7r7eXRoNJIrNqU4ToQukCJhFtKrWgHWnk=
|
||||
github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q=
|
||||
github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
|
||||
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
@ -550,6 +551,7 @@ github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.m
|
||||
github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
||||
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
|
||||
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
|
||||
github.com/opencontainers/selinux v1.8.2 h1:c4ca10UMgRcvZ6h0K4HtS15UaVSBEaE+iln2LVpAuGc=
|
||||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
@ -791,8 +793,9 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
|
||||
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@ -890,13 +893,16 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -906,8 +912,10 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
|
||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
@ -36,9 +36,10 @@ import (
|
||||
|
||||
type NetConf struct {
|
||||
types.NetConf
|
||||
Master string `json:"master"`
|
||||
Mode string `json:"mode"`
|
||||
MTU int `json:"mtu"`
|
||||
Master string `json:"master"`
|
||||
Mode string `json:"mode"`
|
||||
MTU int `json:"mtu"`
|
||||
LinkContNs bool `json:"linkInContainer,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
@ -48,9 +49,9 @@ func init() {
|
||||
runtime.LockOSThread()
|
||||
}
|
||||
|
||||
func loadConf(bytes []byte, cmdCheck bool) (*NetConf, string, error) {
|
||||
func loadConf(args *skel.CmdArgs, cmdCheck bool) (*NetConf, string, error) {
|
||||
n := &NetConf{}
|
||||
if err := json.Unmarshal(bytes, n); err != nil {
|
||||
if err := json.Unmarshal(args.StdinData, n); err != nil {
|
||||
return nil, "", fmt.Errorf("failed to load netconf: %v", err)
|
||||
}
|
||||
|
||||
@ -73,8 +74,8 @@ func loadConf(bytes []byte, cmdCheck bool) (*NetConf, string, error) {
|
||||
}
|
||||
if n.Master == "" {
|
||||
if result == nil {
|
||||
defaultRouteInterface, err := getDefaultRouteInterfaceName()
|
||||
|
||||
var defaultRouteInterface string
|
||||
defaultRouteInterface, err = getNamespacedDefaultRouteInterfaceName(args.Netns, n.LinkContNs)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
@ -124,7 +125,15 @@ func createIpvlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interf
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m, err := netlink.LinkByName(conf.Master)
|
||||
var m netlink.Link
|
||||
if conf.LinkContNs {
|
||||
err = netns.Do(func(_ ns.NetNS) error {
|
||||
m, err = netlink.LinkByName(conf.Master)
|
||||
return err
|
||||
})
|
||||
} else {
|
||||
m, err = netlink.LinkByName(conf.Master)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to lookup master %q: %v", conf.Master, err)
|
||||
}
|
||||
@ -146,8 +155,14 @@ func createIpvlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interf
|
||||
Mode: mode,
|
||||
}
|
||||
|
||||
if err := netlink.LinkAdd(mv); err != nil {
|
||||
return nil, fmt.Errorf("failed to create ipvlan: %v", err)
|
||||
if conf.LinkContNs {
|
||||
err = netns.Do(func(_ ns.NetNS) error {
|
||||
return netlink.LinkAdd(mv)
|
||||
})
|
||||
} else {
|
||||
if err := netlink.LinkAdd(mv); err != nil {
|
||||
return nil, fmt.Errorf("failed to create ipvlan: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
err = netns.Do(func(_ ns.NetNS) error {
|
||||
@ -193,8 +208,31 @@ func getDefaultRouteInterfaceName() (string, error) {
|
||||
return "", fmt.Errorf("no default route interface found")
|
||||
}
|
||||
|
||||
func getNamespacedDefaultRouteInterfaceName(namespace string, inContainer bool) (string, error) {
|
||||
if !inContainer {
|
||||
return getDefaultRouteInterfaceName()
|
||||
}
|
||||
netns, err := ns.GetNS(namespace)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to open netns %q: %v", netns, err)
|
||||
}
|
||||
defer netns.Close()
|
||||
var defaultRouteInterface string
|
||||
err = netns.Do(func(_ ns.NetNS) error {
|
||||
defaultRouteInterface, err = getDefaultRouteInterfaceName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return defaultRouteInterface, nil
|
||||
}
|
||||
|
||||
func cmdAdd(args *skel.CmdArgs) error {
|
||||
n, cniVersion, err := loadConf(args.StdinData, false)
|
||||
n, cniVersion, err := loadConf(args, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -272,7 +310,7 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
func cmdDel(args *skel.CmdArgs) error {
|
||||
n, _, err := loadConf(args.StdinData, false)
|
||||
n, _, err := loadConf(args, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -320,7 +358,7 @@ func main() {
|
||||
|
||||
func cmdCheck(args *skel.CmdArgs) error {
|
||||
|
||||
n, _, err := loadConf(args.StdinData, true)
|
||||
n, _, err := loadConf(args, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -369,7 +407,16 @@ func cmdCheck(args *skel.CmdArgs) error {
|
||||
contMap.Sandbox, args.Netns)
|
||||
}
|
||||
|
||||
m, err := netlink.LinkByName(n.Master)
|
||||
var m netlink.Link
|
||||
if n.LinkContNs {
|
||||
err = netns.Do(func(_ ns.NetNS) error {
|
||||
m, err = netlink.LinkByName(n.Master)
|
||||
return err
|
||||
})
|
||||
} else {
|
||||
m, err = netlink.LinkByName(n.Master)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to lookup master %q: %v", n.Master, err)
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ import (
|
||||
)
|
||||
|
||||
const MASTER_NAME = "eth0"
|
||||
const MASTER_NAME_INCONTAINER = "eth1"
|
||||
|
||||
type Net struct {
|
||||
Name string `json:"name"`
|
||||
@ -49,6 +50,7 @@ type Net struct {
|
||||
DNS types.DNS `json:"dns"`
|
||||
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
|
||||
PrevResult types100.Result `json:"-"`
|
||||
LinkContNs bool `json:"linkInContainer"`
|
||||
}
|
||||
|
||||
func buildOneConfig(cniVersion string, master string, orig *Net, prevResult types.Result) (*Net, error) {
|
||||
@ -289,6 +291,22 @@ var _ = Describe("ipvlan Operations", func() {
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
// Add master
|
||||
err = netlink.LinkAdd(&netlink.Dummy{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: MASTER_NAME_INCONTAINER,
|
||||
},
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
_, err = netlink.LinkByName(MASTER_NAME_INCONTAINER)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
@ -301,67 +319,77 @@ var _ = Describe("ipvlan Operations", func() {
|
||||
Expect(testutils.UnmountNS(targetNS)).To(Succeed())
|
||||
})
|
||||
|
||||
for _, ver := range testutils.AllSpecVersions {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
for _, inContainer := range []bool{false, true} {
|
||||
masterInterface := MASTER_NAME
|
||||
if inContainer {
|
||||
masterInterface = MASTER_NAME_INCONTAINER
|
||||
}
|
||||
//for _, ver := range testutils.AllSpecVersions {
|
||||
for _, ver := range [...]string{"1.0.0"} {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
isInContainer := inContainer // Tests need a local var with constant value
|
||||
|
||||
It(fmt.Sprintf("[%s] creates an ipvlan link in a non-default namespace", ver), func() {
|
||||
conf := &NetConf{
|
||||
NetConf: types.NetConf{
|
||||
CNIVersion: ver,
|
||||
Name: "testConfig",
|
||||
Type: "ipvlan",
|
||||
},
|
||||
Master: MASTER_NAME,
|
||||
Mode: "l2",
|
||||
MTU: 1500,
|
||||
}
|
||||
It(fmt.Sprintf("[%s] creates an ipvlan link in a non-default namespace", ver), func() {
|
||||
conf := &NetConf{
|
||||
NetConf: types.NetConf{
|
||||
CNIVersion: ver,
|
||||
Name: "testConfig",
|
||||
Type: "ipvlan",
|
||||
},
|
||||
Master: masterInterface,
|
||||
Mode: "l2",
|
||||
MTU: 1500,
|
||||
LinkContNs: isInContainer,
|
||||
}
|
||||
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
_, err := createIpvlan(conf, "foobar0", targetNS)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
|
||||
_, err := createIpvlan(conf, "foobar0", targetNS)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
|
||||
// Make sure ipvlan link exists in the target namespace
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName("foobar0")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal("foobar0"))
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure ipvlan link exists in the target namespace
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName("foobar0")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal("foobar0"))
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures an iplvan link with ADD/DEL", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures an iplvan link with ADD/DEL", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "%s",
|
||||
"linkInContainer": %t,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`, ver, MASTER_NAME, dataDir)
|
||||
}`, ver, masterInterface, isInContainer, dataDir)
|
||||
|
||||
ipvlanAddCheckDelTest(conf, "", originalNS, targetNS)
|
||||
})
|
||||
ipvlanAddCheckDelTest(conf, "", originalNS, targetNS)
|
||||
})
|
||||
|
||||
if testutils.SpecVersionHasChaining(ver) {
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures an iplvan link with ADD/DEL when chained", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
if testutils.SpecVersionHasChaining(ver) {
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures an iplvan link with ADD/DEL when chained", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"linkInContainer": %t,
|
||||
"prevResult": {
|
||||
"interfaces": [
|
||||
{
|
||||
@ -378,84 +406,91 @@ var _ = Describe("ipvlan Operations", func() {
|
||||
],
|
||||
"routes": []
|
||||
}
|
||||
}`, ver, MASTER_NAME)
|
||||
}`, ver, isInContainer, masterInterface)
|
||||
|
||||
ipvlanAddCheckDelTest(conf, MASTER_NAME, originalNS, targetNS)
|
||||
})
|
||||
}
|
||||
ipvlanAddCheckDelTest(conf, masterInterface, originalNS, targetNS)
|
||||
})
|
||||
}
|
||||
|
||||
It(fmt.Sprintf("[%s] deconfigures an unconfigured ipvlan link with DEL", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
It(fmt.Sprintf("[%s] deconfigures an unconfigured ipvlan link with DEL", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "%s",
|
||||
"linkInContainer": %t,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`, ver, MASTER_NAME, dataDir)
|
||||
}`, ver, masterInterface, isInContainer, dataDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
IfName: "ipvl0",
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
IfName: "ipvl0",
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
err := testutils.CmdDelWithArgs(args, func() error {
|
||||
return cmdDel(args)
|
||||
err := testutils.CmdDelWithArgs(args, func() error {
|
||||
return cmdDel(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures a ipvlan link with ADD/DEL, without master config", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures a ipvlan link with ADD/DEL, without master config", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"linkInContainer": %t,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`, ver, dataDir)
|
||||
}`, ver, isInContainer, dataDir)
|
||||
|
||||
// Make MASTER_NAME as default route interface
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(MASTER_NAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
err = netlink.LinkSetUp(link)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
var address = &net.IPNet{IP: net.IPv4(192, 0, 0, 1), Mask: net.CIDRMask(24, 32)}
|
||||
var addr = &netlink.Addr{IPNet: address}
|
||||
err = netlink.AddrAdd(link, addr)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// add default gateway into MASTER
|
||||
dst := &net.IPNet{
|
||||
IP: net.IPv4(0, 0, 0, 0),
|
||||
Mask: net.CIDRMask(0, 0),
|
||||
// Make MASTER_NAME as default route interface
|
||||
currentNs := originalNS
|
||||
if isInContainer {
|
||||
currentNs = targetNS
|
||||
}
|
||||
ip := net.IPv4(192, 0, 0, 254)
|
||||
route := netlink.Route{LinkIndex: link.Attrs().Index, Dst: dst, Gw: ip}
|
||||
err = netlink.RouteAdd(&route)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
err := currentNs.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
ipvlanAddCheckDelTest(conf, MASTER_NAME, originalNS, targetNS)
|
||||
})
|
||||
link, err := netlink.LinkByName(masterInterface)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
err = netlink.LinkSetUp(link)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
var address = &net.IPNet{IP: net.IPv4(192, 0, 0, 1), Mask: net.CIDRMask(24, 32)}
|
||||
var addr = &netlink.Addr{IPNet: address}
|
||||
err = netlink.AddrAdd(link, addr)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// add default gateway into MASTER
|
||||
dst := &net.IPNet{
|
||||
IP: net.IPv4(0, 0, 0, 0),
|
||||
Mask: net.CIDRMask(0, 0),
|
||||
}
|
||||
ip := net.IPv4(192, 0, 0, 254)
|
||||
route := netlink.Route{LinkIndex: link.Attrs().Index, Dst: dst, Gw: ip}
|
||||
err = netlink.RouteAdd(&route)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
ipvlanAddCheckDelTest(conf, masterInterface, originalNS, targetNS)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -37,10 +37,11 @@ import (
|
||||
|
||||
type NetConf struct {
|
||||
types.NetConf
|
||||
Master string `json:"master"`
|
||||
Mode string `json:"mode"`
|
||||
MTU int `json:"mtu"`
|
||||
Mac string `json:"mac,omitempty"`
|
||||
Master string `json:"master"`
|
||||
Mode string `json:"mode"`
|
||||
MTU int `json:"mtu"`
|
||||
Mac string `json:"mac,omitempty"`
|
||||
LinkContNs bool `json:"linkInContainer,omitempty"`
|
||||
|
||||
RuntimeConfig struct {
|
||||
Mac string `json:"mac,omitempty"`
|
||||
@ -79,13 +80,36 @@ func getDefaultRouteInterfaceName() (string, error) {
|
||||
return "", fmt.Errorf("no default route interface found")
|
||||
}
|
||||
|
||||
func loadConf(bytes []byte, envArgs string) (*NetConf, string, error) {
|
||||
func getNamespacedDefaultRouteInterfaceName(namespace string, inContainer bool) (string, error) {
|
||||
if !inContainer {
|
||||
return getDefaultRouteInterfaceName()
|
||||
}
|
||||
netns, err := ns.GetNS(namespace)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to open netns %q: %v", netns, err)
|
||||
}
|
||||
defer netns.Close()
|
||||
var defaultRouteInterface string
|
||||
err = netns.Do(func(_ ns.NetNS) error {
|
||||
defaultRouteInterface, err = getDefaultRouteInterfaceName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return defaultRouteInterface, nil
|
||||
}
|
||||
|
||||
func loadConf(args *skel.CmdArgs, envArgs string) (*NetConf, string, error) {
|
||||
n := &NetConf{}
|
||||
if err := json.Unmarshal(bytes, n); err != nil {
|
||||
if err := json.Unmarshal(args.StdinData, n); err != nil {
|
||||
return nil, "", fmt.Errorf("failed to load netconf: %v", err)
|
||||
}
|
||||
if n.Master == "" {
|
||||
defaultRouteInterface, err := getDefaultRouteInterfaceName()
|
||||
defaultRouteInterface, err := getNamespacedDefaultRouteInterfaceName(args.Netns, n.LinkContNs)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
@ -93,7 +117,7 @@ func loadConf(bytes []byte, envArgs string) (*NetConf, string, error) {
|
||||
}
|
||||
|
||||
// check existing and MTU of master interface
|
||||
masterMTU, err := getMTUByName(n.Master)
|
||||
masterMTU, err := getMTUByName(n.Master, args.Netns, n.LinkContNs)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
@ -120,8 +144,23 @@ func loadConf(bytes []byte, envArgs string) (*NetConf, string, error) {
|
||||
return n, n.CNIVersion, nil
|
||||
}
|
||||
|
||||
func getMTUByName(ifName string) (int, error) {
|
||||
link, err := netlink.LinkByName(ifName)
|
||||
func getMTUByName(ifName string, namespace string, inContainer bool) (int, error) {
|
||||
var link netlink.Link
|
||||
var err error
|
||||
if inContainer {
|
||||
netns, err := ns.GetNS(namespace)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to open netns %q: %v", netns, err)
|
||||
}
|
||||
defer netns.Close()
|
||||
|
||||
err = netns.Do(func(_ ns.NetNS) error {
|
||||
link, err = netlink.LinkByName(ifName)
|
||||
return err
|
||||
})
|
||||
} else {
|
||||
link, err = netlink.LinkByName(ifName)
|
||||
}
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -166,7 +205,15 @@ func createMacvlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Inter
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m, err := netlink.LinkByName(conf.Master)
|
||||
var m netlink.Link
|
||||
if conf.LinkContNs {
|
||||
err = netns.Do(func(_ ns.NetNS) error {
|
||||
m, err = netlink.LinkByName(conf.Master)
|
||||
return err
|
||||
})
|
||||
} else {
|
||||
m, err = netlink.LinkByName(conf.Master)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to lookup master %q: %v", conf.Master, err)
|
||||
}
|
||||
@ -198,7 +245,16 @@ func createMacvlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Inter
|
||||
Mode: mode,
|
||||
}
|
||||
|
||||
if err := netlink.LinkAdd(mv); err != nil {
|
||||
if conf.LinkContNs {
|
||||
err = netns.Do(func(_ ns.NetNS) error {
|
||||
return netlink.LinkAdd(mv)
|
||||
})
|
||||
} else {
|
||||
if err = netlink.LinkAdd(mv); err != nil {
|
||||
return nil, fmt.Errorf("failed to create macvlan: %v", err)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create macvlan: %v", err)
|
||||
}
|
||||
|
||||
@ -228,7 +284,7 @@ func createMacvlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Inter
|
||||
}
|
||||
|
||||
func cmdAdd(args *skel.CmdArgs) error {
|
||||
n, cniVersion, err := loadConf(args.StdinData, args.Args)
|
||||
n, cniVersion, err := loadConf(args, args.Args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -329,7 +385,7 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
func cmdDel(args *skel.CmdArgs) error {
|
||||
n, _, err := loadConf(args.StdinData, args.Args)
|
||||
n, _, err := loadConf(args, args.Args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -378,7 +434,7 @@ func main() {
|
||||
|
||||
func cmdCheck(args *skel.CmdArgs) error {
|
||||
|
||||
n, _, err := loadConf(args.StdinData, args.Args)
|
||||
n, _, err := loadConf(args, args.Args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -429,7 +485,15 @@ func cmdCheck(args *skel.CmdArgs) error {
|
||||
contMap.Sandbox, args.Netns)
|
||||
}
|
||||
|
||||
m, err := netlink.LinkByName(n.Master)
|
||||
var m netlink.Link
|
||||
if n.LinkContNs {
|
||||
err = netns.Do(func(_ ns.NetNS) error {
|
||||
m, err = netlink.LinkByName(n.Master)
|
||||
return err
|
||||
})
|
||||
} else {
|
||||
m, err = netlink.LinkByName(n.Master)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to lookup master %q: %v", n.Master, err)
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
454
plugins/main/tap/tap.go
Normal file
454
plugins/main/tap/tap.go
Normal file
@ -0,0 +1,454 @@
|
||||
// Copyright 2022 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"github.com/opencontainers/selinux/go-selinux"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
"github.com/vishvananda/netlink"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ip"
|
||||
"github.com/containernetworking/plugins/pkg/ipam"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
|
||||
"github.com/containernetworking/plugins/pkg/utils/sysctl"
|
||||
)
|
||||
|
||||
type NetConf struct {
|
||||
types.NetConf
|
||||
MultiQueue bool `json:"multiQueue"`
|
||||
MTU int `json:"mtu"`
|
||||
Mac string `json:"mac,omitempty"`
|
||||
Owner *uint32 `json:"owner,omitempty"`
|
||||
Group *uint32 `json:"group,omitempty"`
|
||||
SelinuxContext string `json:"selinuxContext,omitempty"`
|
||||
Args *struct {
|
||||
} `json:"args,omitempty"`
|
||||
RuntimeConfig struct {
|
||||
Mac string `json:"mac,omitempty"`
|
||||
} `json:"runtimeConfig,omitempty"`
|
||||
}
|
||||
|
||||
// MacEnvArgs represents CNI_ARG
|
||||
type MacEnvArgs struct {
|
||||
types.CommonArgs
|
||||
MAC types.UnmarshallableString `json:"mac,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
// this ensures that main runs only on main thread (thread group leader).
|
||||
// since namespace ops (unshare, setns) are done for a single thread, we
|
||||
// must ensure that the goroutine does not jump from OS thread to thread
|
||||
runtime.LockOSThread()
|
||||
}
|
||||
|
||||
func loadConf(args *skel.CmdArgs) (*NetConf, string, error) {
|
||||
n := &NetConf{}
|
||||
if err := json.Unmarshal(args.StdinData, n); err != nil {
|
||||
return nil, "", fmt.Errorf("failed to load netconf: %v", err)
|
||||
}
|
||||
if args.Args != "" {
|
||||
e := MacEnvArgs{}
|
||||
err := types.LoadArgs(args.Args, &e)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
if e.MAC != "" {
|
||||
n.Mac = string(e.MAC)
|
||||
}
|
||||
}
|
||||
|
||||
if n.RuntimeConfig.Mac != "" {
|
||||
n.Mac = n.RuntimeConfig.Mac
|
||||
}
|
||||
|
||||
return n, n.CNIVersion, nil
|
||||
}
|
||||
|
||||
// We want to share the parent process std{in|out|err} - fds 0 through 2.
|
||||
// Since the FDs are inherited on fork / exec, we close on exec all others.
|
||||
func closeFileDescriptorsOnExec() {
|
||||
minFDToCloseOnExec := 3
|
||||
maxFDToCloseOnExec := 256
|
||||
for fd := minFDToCloseOnExec; fd < maxFDToCloseOnExec; fd++ {
|
||||
syscall.CloseOnExec(fd)
|
||||
}
|
||||
}
|
||||
|
||||
// Due to issues with the vishvananda/netlink library (fix pending) it is not possible to create an ownerless/groupless
|
||||
// tap device. Until the issue is fixed, the workaround for creating a tap device with no owner/group is to use the iptool
|
||||
func createTapWithIptool(tmpName string, mtu int, multiqueue bool, mac string, owner *uint32, group *uint32) error {
|
||||
closeFileDescriptorsOnExec()
|
||||
|
||||
tapDeviceArgs := []string{"tuntap", "add", "mode", "tap", "name", tmpName}
|
||||
if multiqueue {
|
||||
tapDeviceArgs = append(tapDeviceArgs, "multi_queue")
|
||||
}
|
||||
|
||||
if owner != nil {
|
||||
tapDeviceArgs = append(tapDeviceArgs, "user", fmt.Sprintf("%d", *owner))
|
||||
}
|
||||
if group != nil {
|
||||
tapDeviceArgs = append(tapDeviceArgs, "group", fmt.Sprintf("%d", *group))
|
||||
}
|
||||
output, err := exec.Command("ip", tapDeviceArgs...).CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to run command %s: %v", output, err)
|
||||
}
|
||||
|
||||
tapDeviceArgs = []string{"link", "set", tmpName}
|
||||
if mtu != 0 {
|
||||
tapDeviceArgs = append(tapDeviceArgs, "mtu", strconv.Itoa(mtu))
|
||||
}
|
||||
if mac != "" {
|
||||
tapDeviceArgs = append(tapDeviceArgs, "address", mac)
|
||||
}
|
||||
output, err = exec.Command("ip", tapDeviceArgs...).CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to run command %s: %v", output, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createLinkWithNetlink(tmpName string, mtu int, nsFd int, multiqueue bool, mac string, owner *uint32, group *uint32) error {
|
||||
linkAttrs := netlink.LinkAttrs{
|
||||
Name: tmpName,
|
||||
Namespace: netlink.NsFd(nsFd),
|
||||
}
|
||||
if mtu != 0 {
|
||||
linkAttrs.MTU = mtu
|
||||
}
|
||||
mv := &netlink.Tuntap{
|
||||
LinkAttrs: linkAttrs,
|
||||
Mode: netlink.TUNTAP_MODE_TAP,
|
||||
}
|
||||
|
||||
if owner != nil {
|
||||
mv.Owner = *owner
|
||||
}
|
||||
if group != nil {
|
||||
mv.Group = *group
|
||||
}
|
||||
|
||||
if mac != "" {
|
||||
addr, err := net.ParseMAC(mac)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid args %v for MAC addr: %v", mac, err)
|
||||
}
|
||||
linkAttrs.HardwareAddr = addr
|
||||
}
|
||||
mv.Flags = netlink.TUNTAP_VNET_HDR | unix.IFF_TAP
|
||||
if multiqueue {
|
||||
mv.Flags = netlink.TUNTAP_MULTI_QUEUE_DEFAULTS | mv.Flags
|
||||
}
|
||||
if err := netlink.LinkAdd(mv); err != nil {
|
||||
return fmt.Errorf("failed to create tap: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createLink(tmpName string, conf *NetConf, netns ns.NetNS) error {
|
||||
if conf.SelinuxContext != "" {
|
||||
if err := selinux.SetExecLabel(conf.SelinuxContext); err != nil {
|
||||
return fmt.Errorf("failed set socket label: %v", err)
|
||||
}
|
||||
return createTapWithIptool(tmpName, conf.MTU, conf.MultiQueue, conf.Mac, conf.Owner, conf.Group)
|
||||
} else if conf.Owner == nil || conf.Group == nil {
|
||||
return createTapWithIptool(tmpName, conf.MTU, conf.MultiQueue, conf.Mac, conf.Owner, conf.Group)
|
||||
} else {
|
||||
return createLinkWithNetlink(tmpName, conf.MTU, int(netns.Fd()), conf.MultiQueue, conf.Mac, conf.Owner, conf.Group)
|
||||
}
|
||||
}
|
||||
|
||||
func createTap(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interface, error) {
|
||||
tap := ¤t.Interface{}
|
||||
// due to kernel bug we have to create with tmpName or it might
|
||||
// collide with the name on the host and error out
|
||||
tmpName, err := ip.RandomVethName()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = netns.Do(func(_ ns.NetNS) error {
|
||||
err := createLink(tmpName, conf, netns)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = ip.RenameLink(tmpName, ifName); err != nil {
|
||||
link, err := netlink.LinkByName(tmpName)
|
||||
if err != nil {
|
||||
netlink.LinkDel(link)
|
||||
return fmt.Errorf("failed to rename tap to %q: %v", ifName, err)
|
||||
}
|
||||
}
|
||||
tap.Name = ifName
|
||||
|
||||
// Re-fetch link to get all properties/attributes
|
||||
link, err := netlink.LinkByName(ifName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to refetch tap %q: %v", ifName, err)
|
||||
}
|
||||
|
||||
err = netlink.LinkSetUp(link)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set tap interface up: %v", err)
|
||||
}
|
||||
|
||||
tap.Mac = link.Attrs().HardwareAddr.String()
|
||||
tap.Sandbox = netns.Path()
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tap, nil
|
||||
}
|
||||
|
||||
func cmdAdd(args *skel.CmdArgs) error {
|
||||
n, cniVersion, err := loadConf(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
isLayer3 := n.IPAM.Type != ""
|
||||
|
||||
netns, err := ns.GetNS(args.Netns)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open netns %q: %v", netns, err)
|
||||
}
|
||||
defer netns.Close()
|
||||
|
||||
tapInterface, err := createTap(n, args.IfName, netns)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete link if err to avoid link leak in this ns
|
||||
defer func() {
|
||||
if err != nil {
|
||||
netns.Do(func(_ ns.NetNS) error {
|
||||
return ip.DelLinkByName(args.IfName)
|
||||
})
|
||||
}
|
||||
}()
|
||||
|
||||
// Assume L2 interface only
|
||||
result := ¤t.Result{
|
||||
CNIVersion: current.ImplementedSpecVersion,
|
||||
Interfaces: []*current.Interface{tapInterface},
|
||||
}
|
||||
|
||||
if isLayer3 {
|
||||
// run the IPAM plugin and get back the config to apply
|
||||
r, err := ipam.ExecAdd(n.IPAM.Type, args.StdinData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Invoke ipam del if err to avoid ip leak
|
||||
defer func() {
|
||||
if err != nil {
|
||||
ipam.ExecDel(n.IPAM.Type, args.StdinData)
|
||||
}
|
||||
}()
|
||||
|
||||
// Convert whatever the IPAM result was into the current Result type
|
||||
ipamResult, err := current.NewResultFromResult(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(ipamResult.IPs) == 0 {
|
||||
return errors.New("IPAM plugin returned missing IP config")
|
||||
}
|
||||
|
||||
result.IPs = ipamResult.IPs
|
||||
result.Routes = ipamResult.Routes
|
||||
|
||||
for _, ipc := range result.IPs {
|
||||
// All addresses apply to the container tap interface
|
||||
ipc.Interface = current.Int(0)
|
||||
}
|
||||
|
||||
err = netns.Do(func(_ ns.NetNS) error {
|
||||
_, _ = sysctl.Sysctl(fmt.Sprintf("net/ipv4/conf/%s/arp_notify", args.IfName), "1")
|
||||
|
||||
if err := ipam.ConfigureIface(args.IfName, result); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// For L2 just change interface status to up
|
||||
err = netns.Do(func(_ ns.NetNS) error {
|
||||
tapInterfaceLink, err := netlink.LinkByName(args.IfName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find interface name %q: %v", tapInterface.Name, err)
|
||||
}
|
||||
if err := netlink.LinkSetUp(tapInterfaceLink); err != nil {
|
||||
return fmt.Errorf("failed to set %q UP: %v", args.IfName, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
result.DNS = n.DNS
|
||||
return types.PrintResult(result, cniVersion)
|
||||
}
|
||||
|
||||
func cmdDel(args *skel.CmdArgs) error {
|
||||
n, _, err := loadConf(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
isLayer3 := n.IPAM.Type != ""
|
||||
|
||||
if isLayer3 {
|
||||
err = ipam.ExecDel(n.IPAM.Type, args.StdinData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if args.Netns == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// There is a netns so try to clean up. Delete can be called multiple times
|
||||
// so don't return an error if the device is already removed.
|
||||
err = ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
|
||||
if err := ip.DelLinkByName(args.IfName); err != nil {
|
||||
if err != ip.ErrLinkNotFound {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
// if NetNs is passed down by the Cloud Orchestration Engine, or if it called multiple times
|
||||
// so don't return an error if the device is already removed.
|
||||
// https://github.com/kubernetes/kubernetes/issues/43014#issuecomment-287164444
|
||||
_, ok := err.(ns.NSPathNotExistErr)
|
||||
if ok {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func main() {
|
||||
skel.PluginMain(cmdAdd, cmdCheck, cmdDel, version.All, bv.BuildString("tap"))
|
||||
}
|
||||
|
||||
func cmdCheck(args *skel.CmdArgs) error {
|
||||
n, _, err := loadConf(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
isLayer3 := n.IPAM.Type != ""
|
||||
|
||||
netns, err := ns.GetNS(args.Netns)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open netns %q: %v", args.Netns, err)
|
||||
}
|
||||
defer netns.Close()
|
||||
|
||||
if isLayer3 {
|
||||
// run the IPAM plugin and get back the config to apply
|
||||
err = ipam.ExecCheck(n.IPAM.Type, args.StdinData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Parse previous result.
|
||||
if n.NetConf.RawPrevResult == nil {
|
||||
return fmt.Errorf("Required prevResult missing")
|
||||
}
|
||||
|
||||
if err := version.ParsePrevResult(&n.NetConf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result, err := current.NewResultFromResult(n.PrevResult)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var contMap current.Interface
|
||||
// Find interfaces for names whe know, tap device name inside container
|
||||
for _, intf := range result.Interfaces {
|
||||
if args.IfName == intf.Name {
|
||||
if args.Netns == intf.Sandbox {
|
||||
contMap = *intf
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The namespace must be the same as what was configured
|
||||
if args.Netns != contMap.Sandbox {
|
||||
return fmt.Errorf("Sandbox in prevResult %s doesn't match configured netns: %s",
|
||||
contMap.Sandbox, args.Netns)
|
||||
}
|
||||
|
||||
// Check prevResults for ips, routes and dns against values found in the container
|
||||
if err := netns.Do(func(_ ns.NetNS) error {
|
||||
err = ip.ValidateExpectedInterfaceIPs(args.IfName, result.IPs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = ip.ValidateExpectedRoute(result.Routes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
27
plugins/main/tap/tap_suite_test.go
Normal file
27
plugins/main/tap/tap_suite_test.go
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2022 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func TestTap(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "plugins/meta/tap")
|
||||
}
|
319
plugins/main/tap/tap_test.go
Normal file
319
plugins/main/tap/tap_test.go
Normal file
@ -0,0 +1,319 @@
|
||||
// Copyright 2022 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
types020 "github.com/containernetworking/cni/pkg/types/020"
|
||||
types040 "github.com/containernetworking/cni/pkg/types/040"
|
||||
types100 "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator"
|
||||
)
|
||||
|
||||
const (
|
||||
TYPETAP = "tuntap"
|
||||
IFNAME = "tapifc"
|
||||
)
|
||||
|
||||
type Net struct {
|
||||
Name string `json:"name"`
|
||||
CNIVersion string `json:"cniVersion"`
|
||||
Type string `json:"type,omitempty"`
|
||||
IPAM *allocator.IPAMConfig `json:"ipam"`
|
||||
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
|
||||
PrevResult types100.Result `json:"-"`
|
||||
}
|
||||
|
||||
func buildOneConfig(netName string, cniVersion string, orig *Net, prevResult types.Result) (*Net, error) {
|
||||
var err error
|
||||
|
||||
inject := map[string]interface{}{
|
||||
"name": netName,
|
||||
"cniVersion": cniVersion,
|
||||
}
|
||||
// Add previous plugin result
|
||||
if prevResult != nil {
|
||||
inject["prevResult"] = prevResult
|
||||
}
|
||||
|
||||
// Ensure every config uses the same name and version
|
||||
config := make(map[string]interface{})
|
||||
|
||||
confBytes, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(confBytes, &config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unmarshal existing network bytes: %s", err)
|
||||
}
|
||||
|
||||
for key, value := range inject {
|
||||
config[key] = value
|
||||
}
|
||||
|
||||
newBytes, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
conf := &Net{}
|
||||
if err := json.Unmarshal(newBytes, &conf); err != nil {
|
||||
return nil, fmt.Errorf("error parsing configuration: %s", err)
|
||||
}
|
||||
|
||||
return conf, nil
|
||||
|
||||
}
|
||||
|
||||
type tester interface {
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
verifyResult(result types.Result, name string) string
|
||||
}
|
||||
|
||||
type testerBase struct{}
|
||||
|
||||
type testerV10x testerBase
|
||||
type testerV04x testerBase
|
||||
type testerV03x testerBase
|
||||
type testerV01xOr02x testerBase
|
||||
|
||||
func newTesterByVersion(version string) tester {
|
||||
switch {
|
||||
case strings.HasPrefix(version, "1.0."):
|
||||
return &testerV10x{}
|
||||
case strings.HasPrefix(version, "0.4."):
|
||||
return &testerV04x{}
|
||||
case strings.HasPrefix(version, "0.3."):
|
||||
return &testerV03x{}
|
||||
default:
|
||||
return &testerV01xOr02x{}
|
||||
}
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
func (t *testerV10x) verifyResult(result types.Result, name string) string {
|
||||
r, err := types100.GetResult(result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(r.Interfaces)).To(Equal(1))
|
||||
Expect(r.Interfaces[0].Name).To(Equal(name))
|
||||
Expect(len(r.IPs)).To(Equal(1))
|
||||
|
||||
return r.Interfaces[0].Mac
|
||||
}
|
||||
|
||||
func verify0403(result types.Result, name string) string {
|
||||
r, err := types040.GetResult(result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(r.Interfaces)).To(Equal(1))
|
||||
Expect(r.Interfaces[0].Name).To(Equal(name))
|
||||
Expect(len(r.IPs)).To(Equal(1))
|
||||
|
||||
return r.Interfaces[0].Mac
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
func (t *testerV04x) verifyResult(result types.Result, name string) string {
|
||||
return verify0403(result, name)
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
func (t *testerV03x) verifyResult(result types.Result, name string) string {
|
||||
return verify0403(result, name)
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
func (t *testerV01xOr02x) verifyResult(result types.Result, name string) string {
|
||||
r, err := types020.GetResult(result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(r.IP4.IP.IP).NotTo(BeNil())
|
||||
Expect(r.IP6).To(BeNil())
|
||||
|
||||
// 0.2 and earlier don't return MAC address
|
||||
return ""
|
||||
}
|
||||
|
||||
// Note: the tests might not work with some security modules (like selinux) enabled
|
||||
// To test with security modules enabled please provide an appropriate plugin for creating the tap device
|
||||
var _ = Describe("Add, check, remove tap plugin", func() {
|
||||
var originalNS, targetNS ns.NetNS
|
||||
var dataDir string
|
||||
|
||||
BeforeEach(func() {
|
||||
// Create a new NetNS so we don't modify the host
|
||||
var err error
|
||||
originalNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
targetNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
dataDir, err = ioutil.TempDir("", "dummy")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
Expect(os.RemoveAll(dataDir)).To(Succeed())
|
||||
Expect(originalNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(originalNS)).To(Succeed())
|
||||
Expect(targetNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(targetNS)).To(Succeed())
|
||||
})
|
||||
|
||||
for _, ver := range testutils.AllSpecVersions {
|
||||
ver := ver
|
||||
|
||||
It(fmt.Sprintf("[%s] add, check and remove a tap device run correctly", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "tapTest",
|
||||
"type": "tap",
|
||||
"owner": 0,
|
||||
"group": 0,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`, ver, dataDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
t := newTesterByVersion(ver)
|
||||
|
||||
var result types.Result
|
||||
var macAddress string
|
||||
var err error
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
result, _, err = testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
macAddress = t.verifyResult(result, IFNAME)
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By("Make sure the tap link exists in the target namespace")
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal(IFNAME))
|
||||
Expect(link.Type()).To(Equal(TYPETAP))
|
||||
|
||||
if macAddress != "" {
|
||||
hwaddr, err := net.ParseMAC(macAddress)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
|
||||
}
|
||||
addrs, err := netlink.AddrList(link, syscall.AF_INET)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(len(addrs)).To(Equal(1))
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By("Running cmdCheck")
|
||||
n := &Net{}
|
||||
err = json.Unmarshal([]byte(conf), &n)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
n.IPAM, _, err = allocator.LoadIPAMConfig([]byte(conf), "")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
newConf, err := buildOneConfig("tapTest", ver, n, result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
confString, err := json.Marshal(newConf)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
args.StdinData = confString
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
return testutils.CmdCheckWithArgs(args, func() error { return cmdCheck(args) })
|
||||
})
|
||||
|
||||
if testutils.SpecVersionHasCHECK(ver) {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
} else {
|
||||
Expect(err).To(MatchError("config version does not allow CHECK"))
|
||||
}
|
||||
|
||||
By("Running cmdDel")
|
||||
args.StdinData = []byte(conf)
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
err = testutils.CmdDelWithArgs(args, func() error {
|
||||
return cmdDel(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(link).To(BeNil())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By("Running cmdDel more than once without error")
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
err = testutils.CmdDelWithArgs(args, func() error {
|
||||
return cmdDel(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
}
|
||||
})
|
@ -20,12 +20,11 @@ import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
"github.com/vishvananda/netlink"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ip"
|
||||
"github.com/containernetworking/plugins/pkg/ipam"
|
||||
@ -35,9 +34,10 @@ import (
|
||||
|
||||
type NetConf struct {
|
||||
types.NetConf
|
||||
Master string `json:"master"`
|
||||
VlanId int `json:"vlanId"`
|
||||
MTU int `json:"mtu,omitempty"`
|
||||
Master string `json:"master"`
|
||||
VlanId int `json:"vlanId"`
|
||||
MTU int `json:"mtu,omitempty"`
|
||||
LinkContNs bool `json:"linkInContainer,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
@ -47,9 +47,9 @@ func init() {
|
||||
runtime.LockOSThread()
|
||||
}
|
||||
|
||||
func loadConf(bytes []byte) (*NetConf, string, error) {
|
||||
func loadConf(args *skel.CmdArgs) (*NetConf, string, error) {
|
||||
n := &NetConf{}
|
||||
if err := json.Unmarshal(bytes, n); err != nil {
|
||||
if err := json.Unmarshal(args.StdinData, n); err != nil {
|
||||
return nil, "", fmt.Errorf("failed to load netconf: %v", err)
|
||||
}
|
||||
if n.Master == "" {
|
||||
@ -60,19 +60,34 @@ func loadConf(bytes []byte) (*NetConf, string, error) {
|
||||
}
|
||||
|
||||
// check existing and MTU of master interface
|
||||
masterMTU, err := getMTUByName(n.Master)
|
||||
masterMTU, err := getMTUByName(n.Master, args.Netns, n.LinkContNs)
|
||||
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if n.MTU < 0 || n.MTU > masterMTU {
|
||||
return nil, "", fmt.Errorf("invalid MTU %d, must be [0, master MTU(%d)]", n.MTU, masterMTU)
|
||||
}
|
||||
|
||||
return n, n.CNIVersion, nil
|
||||
}
|
||||
|
||||
func getMTUByName(ifName string) (int, error) {
|
||||
link, err := netlink.LinkByName(ifName)
|
||||
func getMTUByName(ifName string, namespace string, inContainer bool) (int, error) {
|
||||
var link netlink.Link
|
||||
var err error
|
||||
if inContainer {
|
||||
netns, err := ns.GetNS(namespace)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to open netns %q: %v", netns, err)
|
||||
}
|
||||
defer netns.Close()
|
||||
|
||||
err = netns.Do(func(_ ns.NetNS) error {
|
||||
link, err = netlink.LinkByName(ifName)
|
||||
return err
|
||||
})
|
||||
} else {
|
||||
link, err = netlink.LinkByName(ifName)
|
||||
}
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -82,7 +97,17 @@ func getMTUByName(ifName string) (int, error) {
|
||||
func createVlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interface, error) {
|
||||
vlan := ¤t.Interface{}
|
||||
|
||||
m, err := netlink.LinkByName(conf.Master)
|
||||
var m netlink.Link
|
||||
var err error
|
||||
if conf.LinkContNs {
|
||||
err = netns.Do(func(_ ns.NetNS) error {
|
||||
m, err = netlink.LinkByName(conf.Master)
|
||||
return err
|
||||
})
|
||||
} else {
|
||||
m, err = netlink.LinkByName(conf.Master)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to lookup master %q: %v", conf.Master, err)
|
||||
}
|
||||
@ -104,7 +129,14 @@ func createVlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interfac
|
||||
VlanId: conf.VlanId,
|
||||
}
|
||||
|
||||
if err := netlink.LinkAdd(v); err != nil {
|
||||
if conf.LinkContNs {
|
||||
err = netns.Do(func(_ ns.NetNS) error {
|
||||
return netlink.LinkAdd(v)
|
||||
})
|
||||
} else {
|
||||
err = netlink.LinkAdd(v)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create vlan: %v", err)
|
||||
}
|
||||
|
||||
@ -133,7 +165,7 @@ func createVlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Interfac
|
||||
}
|
||||
|
||||
func cmdAdd(args *skel.CmdArgs) error {
|
||||
n, cniVersion, err := loadConf(args.StdinData)
|
||||
n, cniVersion, err := loadConf(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -191,7 +223,7 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
func cmdDel(args *skel.CmdArgs) error {
|
||||
n, _, err := loadConf(args.StdinData)
|
||||
n, _, err := loadConf(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -276,8 +308,16 @@ func cmdCheck(args *skel.CmdArgs) error {
|
||||
return fmt.Errorf("Sandbox in prevResult %s doesn't match configured netns: %s",
|
||||
contMap.Sandbox, args.Netns)
|
||||
}
|
||||
var m netlink.Link
|
||||
if conf.LinkContNs {
|
||||
err = netns.Do(func(_ ns.NetNS) error {
|
||||
m, err = netlink.LinkByName(conf.Master)
|
||||
return err
|
||||
})
|
||||
} else {
|
||||
m, err = netlink.LinkByName(conf.Master)
|
||||
}
|
||||
|
||||
m, err := netlink.LinkByName(conf.Master)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to lookup master %q: %v", conf.Master, err)
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ import (
|
||||
)
|
||||
|
||||
const MASTER_NAME = "eth0"
|
||||
const MASTER_NAME_INCONTAINER = "eth1"
|
||||
|
||||
type Net struct {
|
||||
Name string `json:"name"`
|
||||
@ -50,6 +51,7 @@ type Net struct {
|
||||
DNS types.DNS `json:"dns"`
|
||||
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
|
||||
PrevResult types100.Result `json:"-"`
|
||||
LinkContNs bool `json:"linkInContainer"`
|
||||
}
|
||||
|
||||
func buildOneConfig(netName string, cniVersion string, orig *Net, prevResult types.Result) (*Net, error) {
|
||||
@ -197,6 +199,24 @@ var _ = Describe("vlan Operations", func() {
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
// Add master
|
||||
err = netlink.LinkAdd(&netlink.Dummy{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: MASTER_NAME_INCONTAINER,
|
||||
},
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
m, err := netlink.LinkByName(MASTER_NAME_INCONTAINER)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
err = netlink.LinkSetUp(m)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
@ -207,283 +227,308 @@ var _ = Describe("vlan Operations", func() {
|
||||
Expect(testutils.UnmountNS(targetNS)).To(Succeed())
|
||||
})
|
||||
|
||||
for _, ver := range testutils.AllSpecVersions {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
for _, inContainer := range []bool{false, true} {
|
||||
masterInterface := MASTER_NAME
|
||||
if inContainer {
|
||||
masterInterface = MASTER_NAME_INCONTAINER
|
||||
}
|
||||
isInContainer := inContainer // Tests need a local var with constant value
|
||||
|
||||
It(fmt.Sprintf("[%s] creates an vlan link in a non-default namespace with given MTU", ver), func() {
|
||||
conf := &NetConf{
|
||||
NetConf: types.NetConf{
|
||||
CNIVersion: ver,
|
||||
Name: "testConfig",
|
||||
Type: "vlan",
|
||||
},
|
||||
Master: MASTER_NAME,
|
||||
VlanId: 33,
|
||||
MTU: 1500,
|
||||
}
|
||||
for _, ver := range testutils.AllSpecVersions {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
|
||||
// Create vlan in other namespace
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
It(fmt.Sprintf("[%s] creates an vlan link in a non-default namespace with given MTU", ver), func() {
|
||||
conf := &NetConf{
|
||||
NetConf: types.NetConf{
|
||||
CNIVersion: ver,
|
||||
Name: "testConfig",
|
||||
Type: "vlan",
|
||||
},
|
||||
Master: masterInterface,
|
||||
VlanId: 33,
|
||||
MTU: 1500,
|
||||
LinkContNs: isInContainer,
|
||||
}
|
||||
|
||||
_, err := createVlan(conf, "foobar0", targetNS)
|
||||
// Create vlan in other namespace
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
_, err := createVlan(conf, "foobar0", targetNS)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure vlan link exists in the target namespace
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName("foobar0")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal("foobar0"))
|
||||
Expect(link.Attrs().MTU).To(Equal(1500))
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure vlan link exists in the target namespace
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
It(fmt.Sprintf("[%s] creates an vlan link in a non-default namespace with master's MTU", ver), func() {
|
||||
conf := &NetConf{
|
||||
NetConf: types.NetConf{
|
||||
CNIVersion: ver,
|
||||
Name: "testConfig",
|
||||
Type: "vlan",
|
||||
},
|
||||
Master: masterInterface,
|
||||
VlanId: 33,
|
||||
LinkContNs: isInContainer,
|
||||
}
|
||||
|
||||
link, err := netlink.LinkByName("foobar0")
|
||||
// Create vlan in other namespace
|
||||
otherNs := originalNS
|
||||
if isInContainer {
|
||||
otherNs = targetNS
|
||||
}
|
||||
|
||||
err := otherNs.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
m, err := netlink.LinkByName(masterInterface)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
err = netlink.LinkSetMTU(m, 1200)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, err = createVlan(conf, "foobar0", targetNS)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure vlan link exists in the target namespace
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName("foobar0")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal("foobar0"))
|
||||
Expect(link.Attrs().MTU).To(Equal(1200))
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal("foobar0"))
|
||||
Expect(link.Attrs().MTU).To(Equal(1500))
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It(fmt.Sprintf("[%s] creates an vlan link in a non-default namespace with master's MTU", ver), func() {
|
||||
conf := &NetConf{
|
||||
NetConf: types.NetConf{
|
||||
CNIVersion: ver,
|
||||
Name: "testConfig",
|
||||
Type: "vlan",
|
||||
},
|
||||
Master: MASTER_NAME,
|
||||
VlanId: 33,
|
||||
}
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures a vlan link with ADD/CHECK/DEL", ver), func() {
|
||||
const IFNAME = "ethX"
|
||||
|
||||
// Create vlan in other namespace
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
m, err := netlink.LinkByName(MASTER_NAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
err = netlink.LinkSetMTU(m, 1200)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, err = createVlan(conf, "foobar0", targetNS)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure vlan link exists in the target namespace
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName("foobar0")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal("foobar0"))
|
||||
Expect(link.Attrs().MTU).To(Equal(1200))
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures a vlan link with ADD/CHECK/DEL", ver), func() {
|
||||
const IFNAME = "eth0"
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "vlanTestv4",
|
||||
"type": "vlan",
|
||||
"master": "%s",
|
||||
"vlanId": 1234,
|
||||
"linkInContainer": %t,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`, ver, MASTER_NAME, dataDir)
|
||||
}`, ver, masterInterface, isInContainer, dataDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
t := newTesterByVersion(ver)
|
||||
|
||||
var result types.Result
|
||||
var macAddress string
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
var err error
|
||||
result, _, err = testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
macAddress = t.verifyResult(result, IFNAME)
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure vlan link exists in the target namespace
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal(IFNAME))
|
||||
|
||||
if macAddress != "" {
|
||||
hwaddr, err := net.ParseMAC(macAddress)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
addrs, err := netlink.AddrList(link, syscall.AF_INET)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(len(addrs)).To(Equal(1))
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
t := newTesterByVersion(ver)
|
||||
|
||||
// call CmdCheck
|
||||
n := &Net{}
|
||||
err = json.Unmarshal([]byte(conf), &n)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
var result types.Result
|
||||
var macAddress string
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
n.IPAM, _, err = allocator.LoadIPAMConfig([]byte(conf), "")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
var err error
|
||||
result, _, err = testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
newConf, err := buildOneConfig("vlanTestv4", ver, n, result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
confString, err := json.Marshal(newConf)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args.StdinData = confString
|
||||
|
||||
// CNI Check host-device in the target namespace
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
return testutils.CmdCheckWithArgs(args, func() error { return cmdCheck(args) })
|
||||
})
|
||||
if testutils.SpecVersionHasCHECK(ver) {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
} else {
|
||||
Expect(err).To(MatchError("config version does not allow CHECK"))
|
||||
}
|
||||
|
||||
args.StdinData = []byte(conf)
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
err = testutils.CmdDelWithArgs(args, func() error {
|
||||
return cmdDel(args)
|
||||
macAddress = t.verifyResult(result, IFNAME)
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure vlan link has been deleted
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
// Make sure vlan link exists in the target namespace
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(link).To(BeNil())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal(IFNAME))
|
||||
|
||||
// DEL can be called multiple times, make sure no error is returned
|
||||
// if the device is already removed.
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
if macAddress != "" {
|
||||
hwaddr, err := net.ParseMAC(macAddress)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
|
||||
}
|
||||
|
||||
err = testutils.CmdDelWithArgs(args, func() error {
|
||||
return cmdDel(args)
|
||||
addrs, err := netlink.AddrList(link, syscall.AF_INET)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(len(addrs)).To(Equal(1))
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
Describe("fails to create vlan link with invalid MTU", func() {
|
||||
const confFmt = `{
|
||||
// call CmdCheck
|
||||
n := &Net{}
|
||||
err = json.Unmarshal([]byte(conf), &n)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
n.IPAM, _, err = allocator.LoadIPAMConfig([]byte(conf), "")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
newConf, err := buildOneConfig("vlanTestv4", ver, n, result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if isInContainer {
|
||||
newConf.LinkContNs = true
|
||||
}
|
||||
|
||||
confString, err := json.Marshal(newConf)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args.StdinData = confString
|
||||
|
||||
// CNI Check host-device in the target namespace
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
return testutils.CmdCheckWithArgs(args, func() error { return cmdCheck(args) })
|
||||
})
|
||||
|
||||
if testutils.SpecVersionHasCHECK(ver) {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
} else {
|
||||
Expect(err).To(MatchError("config version does not allow CHECK"))
|
||||
}
|
||||
|
||||
args.StdinData = []byte(conf)
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
err = testutils.CmdDelWithArgs(args, func() error {
|
||||
return cmdDel(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure vlan link has been deleted
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(link).To(BeNil())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// DEL can be called multiple times, make sure no error is returned
|
||||
// if the device is already removed.
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
err = testutils.CmdDelWithArgs(args, func() error {
|
||||
return cmdDel(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
Describe("fails to create vlan link with invalid MTU", func() {
|
||||
const confFmt = `{
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "vlan",
|
||||
"master": "%s",
|
||||
"mtu": %d,
|
||||
"linkInContainer": %t,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`
|
||||
}`
|
||||
|
||||
BeforeEach(func() {
|
||||
var err error
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
BeforeEach(func() {
|
||||
var err error
|
||||
sourceNS := originalNS
|
||||
if isInContainer {
|
||||
sourceNS = targetNS
|
||||
}
|
||||
|
||||
// set master link's MTU to 1500
|
||||
link, err := netlink.LinkByName(MASTER_NAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
err = netlink.LinkSetMTU(link, 1500)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
err = sourceNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
// set master link's MTU to 1500
|
||||
link, err := netlink.LinkByName(masterInterface)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
err = netlink.LinkSetMTU(link, 1500)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
It(fmt.Sprintf("[%s] fails to create vlan link with greater MTU than master interface", ver), func() {
|
||||
var err error
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: "/var/run/netns/test",
|
||||
IfName: "eth0",
|
||||
StdinData: []byte(fmt.Sprintf(confFmt, ver, MASTER_NAME, 1600, dataDir)),
|
||||
}
|
||||
|
||||
_ = originalNS.Do(func(netNS ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
_, _, err = testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
return nil
|
||||
})
|
||||
Expect(err).To(Equal(fmt.Errorf("invalid MTU 1600, must be [0, master MTU(1500)]")))
|
||||
return nil
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
It(fmt.Sprintf("[%s] fails to create vlan link with negative MTU", ver), func() {
|
||||
var err error
|
||||
It(fmt.Sprintf("[%s] fails to create vlan link with greater MTU than master interface", ver), func() {
|
||||
var err error
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
IfName: "ethX",
|
||||
StdinData: []byte(fmt.Sprintf(confFmt, ver, masterInterface, 1600, isInContainer, dataDir)),
|
||||
}
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: "/var/run/netns/test",
|
||||
IfName: "eth0",
|
||||
StdinData: []byte(fmt.Sprintf(confFmt, ver, MASTER_NAME, -100, dataDir)),
|
||||
}
|
||||
_ = originalNS.Do(func(netNS ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
_ = originalNS.Do(func(netNS ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
_, _, err = testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
_, _, err = testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).To(Equal(fmt.Errorf("invalid MTU 1600, must be [0, master MTU(1500)]")))
|
||||
return nil
|
||||
})
|
||||
})
|
||||
|
||||
It(fmt.Sprintf("[%s] fails to create vlan link with negative MTU", ver), func() {
|
||||
var err error
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
IfName: "ethX",
|
||||
StdinData: []byte(fmt.Sprintf(confFmt, ver, masterInterface, -100, isInContainer, dataDir)),
|
||||
}
|
||||
|
||||
_ = originalNS.Do(func(netNS ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
_, _, err = testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).To(Equal(fmt.Errorf("invalid MTU -100, must be [0, master MTU(1500)]")))
|
||||
return nil
|
||||
})
|
||||
Expect(err).To(Equal(fmt.Errorf("invalid MTU -100, must be [0, master MTU(1500)]")))
|
||||
return nil
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -117,11 +117,22 @@ func forwardPorts(config *PortMapConf, containerNet net.IPNet) error {
|
||||
}
|
||||
|
||||
func checkPorts(config *PortMapConf, containerNet net.IPNet) error {
|
||||
isV6 := (containerNet.IP.To4() == nil)
|
||||
dnatChain := genDnatChain(config.Name, config.ContainerID)
|
||||
fillDnatRules(&dnatChain, config, containerNet)
|
||||
|
||||
ip4t, err4 := maybeGetIptables(false)
|
||||
ip6t, err6 := maybeGetIptables(true)
|
||||
// check is called for each address, not once for all addresses
|
||||
var ip4t *iptables.IPTables
|
||||
var err4 error
|
||||
var ip6t *iptables.IPTables
|
||||
var err6 error
|
||||
|
||||
if isV6 {
|
||||
ip6t, err6 = maybeGetIptables(true)
|
||||
} else {
|
||||
ip4t, err4 = maybeGetIptables(false)
|
||||
}
|
||||
|
||||
if ip4t == nil && ip6t == nil {
|
||||
err := fmt.Errorf("neither iptables nor ip6tables is usable")
|
||||
err = fmt.Errorf("%v, (iptables) %v", err, err4)
|
||||
|
26
vendor/github.com/bits-and-blooms/bitset/.gitignore
generated
vendored
Normal file
26
vendor/github.com/bits-and-blooms/bitset/.gitignore
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
||||
|
||||
target
|
37
vendor/github.com/bits-and-blooms/bitset/.travis.yml
generated
vendored
Normal file
37
vendor/github.com/bits-and-blooms/bitset/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
language: go
|
||||
|
||||
sudo: false
|
||||
|
||||
branches:
|
||||
except:
|
||||
- release
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- travis
|
||||
|
||||
go:
|
||||
- "1.11.x"
|
||||
- tip
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
||||
before_install:
|
||||
- if [ -n "$GH_USER" ]; then git config --global github.user ${GH_USER}; fi;
|
||||
- if [ -n "$GH_TOKEN" ]; then git config --global github.token ${GH_TOKEN}; fi;
|
||||
- go get github.com/mattn/goveralls
|
||||
|
||||
before_script:
|
||||
- make deps
|
||||
|
||||
script:
|
||||
- make qa
|
||||
|
||||
after_failure:
|
||||
- cat ./target/test/report.xml
|
||||
|
||||
after_success:
|
||||
- if [ "$TRAVIS_GO_VERSION" = "1.11.1" ]; then $HOME/gopath/bin/goveralls -covermode=count -coverprofile=target/report/coverage.out -service=travis-ci; fi;
|
27
vendor/github.com/bits-and-blooms/bitset/LICENSE
generated
vendored
Normal file
27
vendor/github.com/bits-and-blooms/bitset/LICENSE
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright (c) 2014 Will Fitzgerald. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
93
vendor/github.com/bits-and-blooms/bitset/README.md
generated
vendored
Normal file
93
vendor/github.com/bits-and-blooms/bitset/README.md
generated
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
# bitset
|
||||
|
||||
*Go language library to map between non-negative integers and boolean values*
|
||||
|
||||
[](https://github.com/willf/bitset/actions?query=workflow%3ATest)
|
||||
[](https://goreportcard.com/report/github.com/willf/bitset)
|
||||
[](https://pkg.go.dev/github.com/bits-and-blooms/bitset?tab=doc)
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
Package bitset implements bitsets, a mapping between non-negative integers and boolean values.
|
||||
It should be more efficient than map[uint] bool.
|
||||
|
||||
It provides methods for setting, clearing, flipping, and testing individual integers.
|
||||
|
||||
But it also provides set intersection, union, difference, complement, and symmetric operations, as well as tests to check whether any, all, or no bits are set, and querying a bitset's current length and number of positive bits.
|
||||
|
||||
BitSets are expanded to the size of the largest set bit; the memory allocation is approximately Max bits, where Max is the largest set bit. BitSets are never shrunk. On creation, a hint can be given for the number of bits that will be used.
|
||||
|
||||
Many of the methods, including Set, Clear, and Flip, return a BitSet pointer, which allows for chaining.
|
||||
|
||||
### Example use:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
|
||||
"github.com/bits-and-blooms/bitset"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Printf("Hello from BitSet!\n")
|
||||
var b bitset.BitSet
|
||||
// play some Go Fish
|
||||
for i := 0; i < 100; i++ {
|
||||
card1 := uint(rand.Intn(52))
|
||||
card2 := uint(rand.Intn(52))
|
||||
b.Set(card1)
|
||||
if b.Test(card2) {
|
||||
fmt.Println("Go Fish!")
|
||||
}
|
||||
b.Clear(card1)
|
||||
}
|
||||
|
||||
// Chaining
|
||||
b.Set(10).Set(11)
|
||||
|
||||
for i, e := b.NextSet(0); e; i, e = b.NextSet(i + 1) {
|
||||
fmt.Println("The following bit is set:", i)
|
||||
}
|
||||
if b.Intersection(bitset.New(100).Set(10)).Count() == 1 {
|
||||
fmt.Println("Intersection works.")
|
||||
} else {
|
||||
fmt.Println("Intersection doesn't work???")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
As an alternative to BitSets, one should check out the 'big' package, which provides a (less set-theoretical) view of bitsets.
|
||||
|
||||
Package documentation is at: https://pkg.go.dev/github.com/bits-and-blooms/bitset?tab=doc
|
||||
|
||||
## Memory Usage
|
||||
|
||||
The memory usage of a bitset using N bits is at least N/8 bytes. The number of bits in a bitset is at least as large as one plus the greatest bit index you have accessed. Thus it is possible to run out of memory while using a bitset. If you have lots of bits, you might prefer compressed bitsets, like the [Roaring bitmaps](http://roaringbitmap.org) and its [Go implementation](https://github.com/RoaringBitmap/roaring).
|
||||
|
||||
## Implementation Note
|
||||
|
||||
Go 1.9 introduced a native `math/bits` library. We provide backward compatibility to Go 1.7, which might be removed.
|
||||
|
||||
It is possible that a later version will match the `math/bits` return signature for counts (which is `int`, rather than our library's `unit64`). If so, the version will be bumped.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
go get github.com/bits-and-blooms/bitset
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
If you wish to contribute to this project, please branch and issue a pull request against master ("[GitHub Flow](https://guides.github.com/introduction/flow/)")
|
||||
|
||||
## Running all tests
|
||||
|
||||
Before committing the code, please check if it passes tests, has adequate coverage, etc.
|
||||
```bash
|
||||
go test
|
||||
go test -cover
|
||||
```
|
39
vendor/github.com/bits-and-blooms/bitset/azure-pipelines.yml
generated
vendored
Normal file
39
vendor/github.com/bits-and-blooms/bitset/azure-pipelines.yml
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
# Go
|
||||
# Build your Go project.
|
||||
# Add steps that test, save build artifacts, deploy, and more:
|
||||
# https://docs.microsoft.com/azure/devops/pipelines/languages/go
|
||||
|
||||
trigger:
|
||||
- master
|
||||
|
||||
pool:
|
||||
vmImage: 'Ubuntu-16.04'
|
||||
|
||||
variables:
|
||||
GOBIN: '$(GOPATH)/bin' # Go binaries path
|
||||
GOROOT: '/usr/local/go1.11' # Go installation path
|
||||
GOPATH: '$(system.defaultWorkingDirectory)/gopath' # Go workspace path
|
||||
modulePath: '$(GOPATH)/src/github.com/$(build.repository.name)' # Path to the module's code
|
||||
|
||||
steps:
|
||||
- script: |
|
||||
mkdir -p '$(GOBIN)'
|
||||
mkdir -p '$(GOPATH)/pkg'
|
||||
mkdir -p '$(modulePath)'
|
||||
shopt -s extglob
|
||||
shopt -s dotglob
|
||||
mv !(gopath) '$(modulePath)'
|
||||
echo '##vso[task.prependpath]$(GOBIN)'
|
||||
echo '##vso[task.prependpath]$(GOROOT)/bin'
|
||||
displayName: 'Set up the Go workspace'
|
||||
|
||||
- script: |
|
||||
go version
|
||||
go get -v -t -d ./...
|
||||
if [ -f Gopkg.toml ]; then
|
||||
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
|
||||
dep ensure
|
||||
fi
|
||||
go build -v .
|
||||
workingDirectory: '$(modulePath)'
|
||||
displayName: 'Get dependencies, then build'
|
952
vendor/github.com/bits-and-blooms/bitset/bitset.go
generated
vendored
Normal file
952
vendor/github.com/bits-and-blooms/bitset/bitset.go
generated
vendored
Normal file
@ -0,0 +1,952 @@
|
||||
/*
|
||||
Package bitset implements bitsets, a mapping
|
||||
between non-negative integers and boolean values. It should be more
|
||||
efficient than map[uint] bool.
|
||||
|
||||
It provides methods for setting, clearing, flipping, and testing
|
||||
individual integers.
|
||||
|
||||
But it also provides set intersection, union, difference,
|
||||
complement, and symmetric operations, as well as tests to
|
||||
check whether any, all, or no bits are set, and querying a
|
||||
bitset's current length and number of positive bits.
|
||||
|
||||
BitSets are expanded to the size of the largest set bit; the
|
||||
memory allocation is approximately Max bits, where Max is
|
||||
the largest set bit. BitSets are never shrunk. On creation,
|
||||
a hint can be given for the number of bits that will be used.
|
||||
|
||||
Many of the methods, including Set,Clear, and Flip, return
|
||||
a BitSet pointer, which allows for chaining.
|
||||
|
||||
Example use:
|
||||
|
||||
import "bitset"
|
||||
var b BitSet
|
||||
b.Set(10).Set(11)
|
||||
if b.Test(1000) {
|
||||
b.Clear(1000)
|
||||
}
|
||||
if B.Intersection(bitset.New(100).Set(10)).Count() > 1 {
|
||||
fmt.Println("Intersection works.")
|
||||
}
|
||||
|
||||
As an alternative to BitSets, one should check out the 'big' package,
|
||||
which provides a (less set-theoretical) view of bitsets.
|
||||
|
||||
*/
|
||||
package bitset
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// the wordSize of a bit set
|
||||
const wordSize = uint(64)
|
||||
|
||||
// log2WordSize is lg(wordSize)
|
||||
const log2WordSize = uint(6)
|
||||
|
||||
// allBits has every bit set
|
||||
const allBits uint64 = 0xffffffffffffffff
|
||||
|
||||
// default binary BigEndian
|
||||
var binaryOrder binary.ByteOrder = binary.BigEndian
|
||||
|
||||
// default json encoding base64.URLEncoding
|
||||
var base64Encoding = base64.URLEncoding
|
||||
|
||||
// Base64StdEncoding Marshal/Unmarshal BitSet with base64.StdEncoding(Default: base64.URLEncoding)
|
||||
func Base64StdEncoding() { base64Encoding = base64.StdEncoding }
|
||||
|
||||
// LittleEndian Marshal/Unmarshal Binary as Little Endian(Default: binary.BigEndian)
|
||||
func LittleEndian() { binaryOrder = binary.LittleEndian }
|
||||
|
||||
// A BitSet is a set of bits. The zero value of a BitSet is an empty set of length 0.
|
||||
type BitSet struct {
|
||||
length uint
|
||||
set []uint64
|
||||
}
|
||||
|
||||
// Error is used to distinguish errors (panics) generated in this package.
|
||||
type Error string
|
||||
|
||||
// safeSet will fixup b.set to be non-nil and return the field value
|
||||
func (b *BitSet) safeSet() []uint64 {
|
||||
if b.set == nil {
|
||||
b.set = make([]uint64, wordsNeeded(0))
|
||||
}
|
||||
return b.set
|
||||
}
|
||||
|
||||
// From is a constructor used to create a BitSet from an array of integers
|
||||
func From(buf []uint64) *BitSet {
|
||||
return &BitSet{uint(len(buf)) * 64, buf}
|
||||
}
|
||||
|
||||
// Bytes returns the bitset as array of integers
|
||||
func (b *BitSet) Bytes() []uint64 {
|
||||
return b.set
|
||||
}
|
||||
|
||||
// wordsNeeded calculates the number of words needed for i bits
|
||||
func wordsNeeded(i uint) int {
|
||||
if i > (Cap() - wordSize + 1) {
|
||||
return int(Cap() >> log2WordSize)
|
||||
}
|
||||
return int((i + (wordSize - 1)) >> log2WordSize)
|
||||
}
|
||||
|
||||
// New creates a new BitSet with a hint that length bits will be required
|
||||
func New(length uint) (bset *BitSet) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
bset = &BitSet{
|
||||
0,
|
||||
make([]uint64, 0),
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
bset = &BitSet{
|
||||
length,
|
||||
make([]uint64, wordsNeeded(length)),
|
||||
}
|
||||
|
||||
return bset
|
||||
}
|
||||
|
||||
// Cap returns the total possible capacity, or number of bits
|
||||
func Cap() uint {
|
||||
return ^uint(0)
|
||||
}
|
||||
|
||||
// Len returns the number of bits in the BitSet.
|
||||
// Note the difference to method Count, see example.
|
||||
func (b *BitSet) Len() uint {
|
||||
return b.length
|
||||
}
|
||||
|
||||
// extendSetMaybe adds additional words to incorporate new bits if needed
|
||||
func (b *BitSet) extendSetMaybe(i uint) {
|
||||
if i >= b.length { // if we need more bits, make 'em
|
||||
if i >= Cap() {
|
||||
panic("You are exceeding the capacity")
|
||||
}
|
||||
nsize := wordsNeeded(i + 1)
|
||||
if b.set == nil {
|
||||
b.set = make([]uint64, nsize)
|
||||
} else if cap(b.set) >= nsize {
|
||||
b.set = b.set[:nsize] // fast resize
|
||||
} else if len(b.set) < nsize {
|
||||
newset := make([]uint64, nsize, 2*nsize) // increase capacity 2x
|
||||
copy(newset, b.set)
|
||||
b.set = newset
|
||||
}
|
||||
b.length = i + 1
|
||||
}
|
||||
}
|
||||
|
||||
// Test whether bit i is set.
|
||||
func (b *BitSet) Test(i uint) bool {
|
||||
if i >= b.length {
|
||||
return false
|
||||
}
|
||||
return b.set[i>>log2WordSize]&(1<<(i&(wordSize-1))) != 0
|
||||
}
|
||||
|
||||
// Set bit i to 1, the capacity of the bitset is automatically
|
||||
// increased accordingly.
|
||||
// If i>= Cap(), this function will panic.
|
||||
// Warning: using a very large value for 'i'
|
||||
// may lead to a memory shortage and a panic: the caller is responsible
|
||||
// for providing sensible parameters in line with their memory capacity.
|
||||
func (b *BitSet) Set(i uint) *BitSet {
|
||||
b.extendSetMaybe(i)
|
||||
b.set[i>>log2WordSize] |= 1 << (i & (wordSize - 1))
|
||||
return b
|
||||
}
|
||||
|
||||
// Clear bit i to 0
|
||||
func (b *BitSet) Clear(i uint) *BitSet {
|
||||
if i >= b.length {
|
||||
return b
|
||||
}
|
||||
b.set[i>>log2WordSize] &^= 1 << (i & (wordSize - 1))
|
||||
return b
|
||||
}
|
||||
|
||||
// SetTo sets bit i to value.
|
||||
// If i>= Cap(), this function will panic.
|
||||
// Warning: using a very large value for 'i'
|
||||
// may lead to a memory shortage and a panic: the caller is responsible
|
||||
// for providing sensible parameters in line with their memory capacity.
|
||||
func (b *BitSet) SetTo(i uint, value bool) *BitSet {
|
||||
if value {
|
||||
return b.Set(i)
|
||||
}
|
||||
return b.Clear(i)
|
||||
}
|
||||
|
||||
// Flip bit at i.
|
||||
// If i>= Cap(), this function will panic.
|
||||
// Warning: using a very large value for 'i'
|
||||
// may lead to a memory shortage and a panic: the caller is responsible
|
||||
// for providing sensible parameters in line with their memory capacity.
|
||||
func (b *BitSet) Flip(i uint) *BitSet {
|
||||
if i >= b.length {
|
||||
return b.Set(i)
|
||||
}
|
||||
b.set[i>>log2WordSize] ^= 1 << (i & (wordSize - 1))
|
||||
return b
|
||||
}
|
||||
|
||||
// FlipRange bit in [start, end).
|
||||
// If end>= Cap(), this function will panic.
|
||||
// Warning: using a very large value for 'end'
|
||||
// may lead to a memory shortage and a panic: the caller is responsible
|
||||
// for providing sensible parameters in line with their memory capacity.
|
||||
func (b *BitSet) FlipRange(start, end uint) *BitSet {
|
||||
if start >= end {
|
||||
return b
|
||||
}
|
||||
|
||||
b.extendSetMaybe(end - 1)
|
||||
var startWord uint = start >> log2WordSize
|
||||
var endWord uint = end >> log2WordSize
|
||||
b.set[startWord] ^= ^(^uint64(0) << (start & (wordSize - 1)))
|
||||
for i := startWord; i < endWord; i++ {
|
||||
b.set[i] = ^b.set[i]
|
||||
}
|
||||
b.set[endWord] ^= ^uint64(0) >> (-end & (wordSize - 1))
|
||||
return b
|
||||
}
|
||||
|
||||
// Shrink shrinks BitSet so that the provided value is the last possible
|
||||
// set value. It clears all bits > the provided index and reduces the size
|
||||
// and length of the set.
|
||||
//
|
||||
// Note that the parameter value is not the new length in bits: it is the
|
||||
// maximal value that can be stored in the bitset after the function call.
|
||||
// The new length in bits is the parameter value + 1. Thus it is not possible
|
||||
// to use this function to set the length to 0, the minimal value of the length
|
||||
// after this function call is 1.
|
||||
//
|
||||
// A new slice is allocated to store the new bits, so you may see an increase in
|
||||
// memory usage until the GC runs. Normally this should not be a problem, but if you
|
||||
// have an extremely large BitSet its important to understand that the old BitSet will
|
||||
// remain in memory until the GC frees it.
|
||||
func (b *BitSet) Shrink(lastbitindex uint) *BitSet {
|
||||
length := lastbitindex + 1
|
||||
idx := wordsNeeded(length)
|
||||
if idx > len(b.set) {
|
||||
return b
|
||||
}
|
||||
shrunk := make([]uint64, idx)
|
||||
copy(shrunk, b.set[:idx])
|
||||
b.set = shrunk
|
||||
b.length = length
|
||||
b.set[idx-1] &= (allBits >> (uint64(64) - uint64(length&(wordSize-1))))
|
||||
return b
|
||||
}
|
||||
|
||||
// Compact shrinks BitSet to so that we preserve all set bits, while minimizing
|
||||
// memory usage. Compact calls Shrink.
|
||||
func (b *BitSet) Compact() *BitSet {
|
||||
idx := len(b.set) - 1
|
||||
for ; idx >= 0 && b.set[idx] == 0; idx-- {
|
||||
}
|
||||
newlength := uint((idx + 1) << log2WordSize)
|
||||
if newlength >= b.length {
|
||||
return b // nothing to do
|
||||
}
|
||||
if newlength > 0 {
|
||||
return b.Shrink(newlength - 1)
|
||||
}
|
||||
// We preserve one word
|
||||
return b.Shrink(63)
|
||||
}
|
||||
|
||||
// InsertAt takes an index which indicates where a bit should be
|
||||
// inserted. Then it shifts all the bits in the set to the left by 1, starting
|
||||
// from the given index position, and sets the index position to 0.
|
||||
//
|
||||
// Depending on the size of your BitSet, and where you are inserting the new entry,
|
||||
// this method could be extremely slow and in some cases might cause the entire BitSet
|
||||
// to be recopied.
|
||||
func (b *BitSet) InsertAt(idx uint) *BitSet {
|
||||
insertAtElement := (idx >> log2WordSize)
|
||||
|
||||
// if length of set is a multiple of wordSize we need to allocate more space first
|
||||
if b.isLenExactMultiple() {
|
||||
b.set = append(b.set, uint64(0))
|
||||
}
|
||||
|
||||
var i uint
|
||||
for i = uint(len(b.set) - 1); i > insertAtElement; i-- {
|
||||
// all elements above the position where we want to insert can simply by shifted
|
||||
b.set[i] <<= 1
|
||||
|
||||
// we take the most significant bit of the previous element and set it as
|
||||
// the least significant bit of the current element
|
||||
b.set[i] |= (b.set[i-1] & 0x8000000000000000) >> 63
|
||||
}
|
||||
|
||||
// generate a mask to extract the data that we need to shift left
|
||||
// within the element where we insert a bit
|
||||
dataMask := ^(uint64(1)<<uint64(idx&(wordSize-1)) - 1)
|
||||
|
||||
// extract that data that we'll shift
|
||||
data := b.set[i] & dataMask
|
||||
|
||||
// set the positions of the data mask to 0 in the element where we insert
|
||||
b.set[i] &= ^dataMask
|
||||
|
||||
// shift data mask to the left and insert its data to the slice element
|
||||
b.set[i] |= data << 1
|
||||
|
||||
// add 1 to length of BitSet
|
||||
b.length++
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
// String creates a string representation of the Bitmap
|
||||
func (b *BitSet) String() string {
|
||||
// follows code from https://github.com/RoaringBitmap/roaring
|
||||
var buffer bytes.Buffer
|
||||
start := []byte("{")
|
||||
buffer.Write(start)
|
||||
counter := 0
|
||||
i, e := b.NextSet(0)
|
||||
for e {
|
||||
counter = counter + 1
|
||||
// to avoid exhausting the memory
|
||||
if counter > 0x40000 {
|
||||
buffer.WriteString("...")
|
||||
break
|
||||
}
|
||||
buffer.WriteString(strconv.FormatInt(int64(i), 10))
|
||||
i, e = b.NextSet(i + 1)
|
||||
if e {
|
||||
buffer.WriteString(",")
|
||||
}
|
||||
}
|
||||
buffer.WriteString("}")
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// DeleteAt deletes the bit at the given index position from
|
||||
// within the bitset
|
||||
// All the bits residing on the left of the deleted bit get
|
||||
// shifted right by 1
|
||||
// The running time of this operation may potentially be
|
||||
// relatively slow, O(length)
|
||||
func (b *BitSet) DeleteAt(i uint) *BitSet {
|
||||
// the index of the slice element where we'll delete a bit
|
||||
deleteAtElement := i >> log2WordSize
|
||||
|
||||
// generate a mask for the data that needs to be shifted right
|
||||
// within that slice element that gets modified
|
||||
dataMask := ^((uint64(1) << (i & (wordSize - 1))) - 1)
|
||||
|
||||
// extract the data that we'll shift right from the slice element
|
||||
data := b.set[deleteAtElement] & dataMask
|
||||
|
||||
// set the masked area to 0 while leaving the rest as it is
|
||||
b.set[deleteAtElement] &= ^dataMask
|
||||
|
||||
// shift the previously extracted data to the right and then
|
||||
// set it in the previously masked area
|
||||
b.set[deleteAtElement] |= (data >> 1) & dataMask
|
||||
|
||||
// loop over all the consecutive slice elements to copy each
|
||||
// lowest bit into the highest position of the previous element,
|
||||
// then shift the entire content to the right by 1
|
||||
for i := int(deleteAtElement) + 1; i < len(b.set); i++ {
|
||||
b.set[i-1] |= (b.set[i] & 1) << 63
|
||||
b.set[i] >>= 1
|
||||
}
|
||||
|
||||
b.length = b.length - 1
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
// NextSet returns the next bit set from the specified index,
|
||||
// including possibly the current index
|
||||
// along with an error code (true = valid, false = no set bit found)
|
||||
// for i,e := v.NextSet(0); e; i,e = v.NextSet(i + 1) {...}
|
||||
//
|
||||
// Users concerned with performance may want to use NextSetMany to
|
||||
// retrieve several values at once.
|
||||
func (b *BitSet) NextSet(i uint) (uint, bool) {
|
||||
x := int(i >> log2WordSize)
|
||||
if x >= len(b.set) {
|
||||
return 0, false
|
||||
}
|
||||
w := b.set[x]
|
||||
w = w >> (i & (wordSize - 1))
|
||||
if w != 0 {
|
||||
return i + trailingZeroes64(w), true
|
||||
}
|
||||
x = x + 1
|
||||
for x < len(b.set) {
|
||||
if b.set[x] != 0 {
|
||||
return uint(x)*wordSize + trailingZeroes64(b.set[x]), true
|
||||
}
|
||||
x = x + 1
|
||||
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// NextSetMany returns many next bit sets from the specified index,
|
||||
// including possibly the current index and up to cap(buffer).
|
||||
// If the returned slice has len zero, then no more set bits were found
|
||||
//
|
||||
// buffer := make([]uint, 256) // this should be reused
|
||||
// j := uint(0)
|
||||
// j, buffer = bitmap.NextSetMany(j, buffer)
|
||||
// for ; len(buffer) > 0; j, buffer = bitmap.NextSetMany(j,buffer) {
|
||||
// for k := range buffer {
|
||||
// do something with buffer[k]
|
||||
// }
|
||||
// j += 1
|
||||
// }
|
||||
//
|
||||
//
|
||||
// It is possible to retrieve all set bits as follow:
|
||||
//
|
||||
// indices := make([]uint, bitmap.Count())
|
||||
// bitmap.NextSetMany(0, indices)
|
||||
//
|
||||
// However if bitmap.Count() is large, it might be preferable to
|
||||
// use several calls to NextSetMany, for performance reasons.
|
||||
func (b *BitSet) NextSetMany(i uint, buffer []uint) (uint, []uint) {
|
||||
myanswer := buffer
|
||||
capacity := cap(buffer)
|
||||
x := int(i >> log2WordSize)
|
||||
if x >= len(b.set) || capacity == 0 {
|
||||
return 0, myanswer[:0]
|
||||
}
|
||||
skip := i & (wordSize - 1)
|
||||
word := b.set[x] >> skip
|
||||
myanswer = myanswer[:capacity]
|
||||
size := int(0)
|
||||
for word != 0 {
|
||||
r := trailingZeroes64(word)
|
||||
t := word & ((^word) + 1)
|
||||
myanswer[size] = r + i
|
||||
size++
|
||||
if size == capacity {
|
||||
goto End
|
||||
}
|
||||
word = word ^ t
|
||||
}
|
||||
x++
|
||||
for idx, word := range b.set[x:] {
|
||||
for word != 0 {
|
||||
r := trailingZeroes64(word)
|
||||
t := word & ((^word) + 1)
|
||||
myanswer[size] = r + (uint(x+idx) << 6)
|
||||
size++
|
||||
if size == capacity {
|
||||
goto End
|
||||
}
|
||||
word = word ^ t
|
||||
}
|
||||
}
|
||||
End:
|
||||
if size > 0 {
|
||||
return myanswer[size-1], myanswer[:size]
|
||||
}
|
||||
return 0, myanswer[:0]
|
||||
}
|
||||
|
||||
// NextClear returns the next clear bit from the specified index,
|
||||
// including possibly the current index
|
||||
// along with an error code (true = valid, false = no bit found i.e. all bits are set)
|
||||
func (b *BitSet) NextClear(i uint) (uint, bool) {
|
||||
x := int(i >> log2WordSize)
|
||||
if x >= len(b.set) {
|
||||
return 0, false
|
||||
}
|
||||
w := b.set[x]
|
||||
w = w >> (i & (wordSize - 1))
|
||||
wA := allBits >> (i & (wordSize - 1))
|
||||
index := i + trailingZeroes64(^w)
|
||||
if w != wA && index < b.length {
|
||||
return index, true
|
||||
}
|
||||
x++
|
||||
for x < len(b.set) {
|
||||
index = uint(x)*wordSize + trailingZeroes64(^b.set[x])
|
||||
if b.set[x] != allBits && index < b.length {
|
||||
return index, true
|
||||
}
|
||||
x++
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// ClearAll clears the entire BitSet
|
||||
func (b *BitSet) ClearAll() *BitSet {
|
||||
if b != nil && b.set != nil {
|
||||
for i := range b.set {
|
||||
b.set[i] = 0
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// wordCount returns the number of words used in a bit set
|
||||
func (b *BitSet) wordCount() int {
|
||||
return len(b.set)
|
||||
}
|
||||
|
||||
// Clone this BitSet
|
||||
func (b *BitSet) Clone() *BitSet {
|
||||
c := New(b.length)
|
||||
if b.set != nil { // Clone should not modify current object
|
||||
copy(c.set, b.set)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// Copy into a destination BitSet
|
||||
// Returning the size of the destination BitSet
|
||||
// like array copy
|
||||
func (b *BitSet) Copy(c *BitSet) (count uint) {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
if b.set != nil { // Copy should not modify current object
|
||||
copy(c.set, b.set)
|
||||
}
|
||||
count = c.length
|
||||
if b.length < c.length {
|
||||
count = b.length
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Count (number of set bits).
|
||||
// Also known as "popcount" or "population count".
|
||||
func (b *BitSet) Count() uint {
|
||||
if b != nil && b.set != nil {
|
||||
return uint(popcntSlice(b.set))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Equal tests the equivalence of two BitSets.
|
||||
// False if they are of different sizes, otherwise true
|
||||
// only if all the same bits are set
|
||||
func (b *BitSet) Equal(c *BitSet) bool {
|
||||
if c == nil || b == nil {
|
||||
return c == b
|
||||
}
|
||||
if b.length != c.length {
|
||||
return false
|
||||
}
|
||||
if b.length == 0 { // if they have both length == 0, then could have nil set
|
||||
return true
|
||||
}
|
||||
// testing for equality shoud not transform the bitset (no call to safeSet)
|
||||
|
||||
for p, v := range b.set {
|
||||
if c.set[p] != v {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func panicIfNull(b *BitSet) {
|
||||
if b == nil {
|
||||
panic(Error("BitSet must not be null"))
|
||||
}
|
||||
}
|
||||
|
||||
// Difference of base set and other set
|
||||
// This is the BitSet equivalent of &^ (and not)
|
||||
func (b *BitSet) Difference(compare *BitSet) (result *BitSet) {
|
||||
panicIfNull(b)
|
||||
panicIfNull(compare)
|
||||
result = b.Clone() // clone b (in case b is bigger than compare)
|
||||
l := int(compare.wordCount())
|
||||
if l > int(b.wordCount()) {
|
||||
l = int(b.wordCount())
|
||||
}
|
||||
for i := 0; i < l; i++ {
|
||||
result.set[i] = b.set[i] &^ compare.set[i]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DifferenceCardinality computes the cardinality of the differnce
|
||||
func (b *BitSet) DifferenceCardinality(compare *BitSet) uint {
|
||||
panicIfNull(b)
|
||||
panicIfNull(compare)
|
||||
l := int(compare.wordCount())
|
||||
if l > int(b.wordCount()) {
|
||||
l = int(b.wordCount())
|
||||
}
|
||||
cnt := uint64(0)
|
||||
cnt += popcntMaskSlice(b.set[:l], compare.set[:l])
|
||||
cnt += popcntSlice(b.set[l:])
|
||||
return uint(cnt)
|
||||
}
|
||||
|
||||
// InPlaceDifference computes the difference of base set and other set
|
||||
// This is the BitSet equivalent of &^ (and not)
|
||||
func (b *BitSet) InPlaceDifference(compare *BitSet) {
|
||||
panicIfNull(b)
|
||||
panicIfNull(compare)
|
||||
l := int(compare.wordCount())
|
||||
if l > int(b.wordCount()) {
|
||||
l = int(b.wordCount())
|
||||
}
|
||||
for i := 0; i < l; i++ {
|
||||
b.set[i] &^= compare.set[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience function: return two bitsets ordered by
|
||||
// increasing length. Note: neither can be nil
|
||||
func sortByLength(a *BitSet, b *BitSet) (ap *BitSet, bp *BitSet) {
|
||||
if a.length <= b.length {
|
||||
ap, bp = a, b
|
||||
} else {
|
||||
ap, bp = b, a
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Intersection of base set and other set
|
||||
// This is the BitSet equivalent of & (and)
|
||||
func (b *BitSet) Intersection(compare *BitSet) (result *BitSet) {
|
||||
panicIfNull(b)
|
||||
panicIfNull(compare)
|
||||
b, compare = sortByLength(b, compare)
|
||||
result = New(b.length)
|
||||
for i, word := range b.set {
|
||||
result.set[i] = word & compare.set[i]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// IntersectionCardinality computes the cardinality of the union
|
||||
func (b *BitSet) IntersectionCardinality(compare *BitSet) uint {
|
||||
panicIfNull(b)
|
||||
panicIfNull(compare)
|
||||
b, compare = sortByLength(b, compare)
|
||||
cnt := popcntAndSlice(b.set, compare.set)
|
||||
return uint(cnt)
|
||||
}
|
||||
|
||||
// InPlaceIntersection destructively computes the intersection of
|
||||
// base set and the compare set.
|
||||
// This is the BitSet equivalent of & (and)
|
||||
func (b *BitSet) InPlaceIntersection(compare *BitSet) {
|
||||
panicIfNull(b)
|
||||
panicIfNull(compare)
|
||||
l := int(compare.wordCount())
|
||||
if l > int(b.wordCount()) {
|
||||
l = int(b.wordCount())
|
||||
}
|
||||
for i := 0; i < l; i++ {
|
||||
b.set[i] &= compare.set[i]
|
||||
}
|
||||
for i := l; i < len(b.set); i++ {
|
||||
b.set[i] = 0
|
||||
}
|
||||
if compare.length > 0 {
|
||||
b.extendSetMaybe(compare.length - 1)
|
||||
}
|
||||
}
|
||||
|
||||
// Union of base set and other set
|
||||
// This is the BitSet equivalent of | (or)
|
||||
func (b *BitSet) Union(compare *BitSet) (result *BitSet) {
|
||||
panicIfNull(b)
|
||||
panicIfNull(compare)
|
||||
b, compare = sortByLength(b, compare)
|
||||
result = compare.Clone()
|
||||
for i, word := range b.set {
|
||||
result.set[i] = word | compare.set[i]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UnionCardinality computes the cardinality of the uniton of the base set
|
||||
// and the compare set.
|
||||
func (b *BitSet) UnionCardinality(compare *BitSet) uint {
|
||||
panicIfNull(b)
|
||||
panicIfNull(compare)
|
||||
b, compare = sortByLength(b, compare)
|
||||
cnt := popcntOrSlice(b.set, compare.set)
|
||||
if len(compare.set) > len(b.set) {
|
||||
cnt += popcntSlice(compare.set[len(b.set):])
|
||||
}
|
||||
return uint(cnt)
|
||||
}
|
||||
|
||||
// InPlaceUnion creates the destructive union of base set and compare set.
|
||||
// This is the BitSet equivalent of | (or).
|
||||
func (b *BitSet) InPlaceUnion(compare *BitSet) {
|
||||
panicIfNull(b)
|
||||
panicIfNull(compare)
|
||||
l := int(compare.wordCount())
|
||||
if l > int(b.wordCount()) {
|
||||
l = int(b.wordCount())
|
||||
}
|
||||
if compare.length > 0 {
|
||||
b.extendSetMaybe(compare.length - 1)
|
||||
}
|
||||
for i := 0; i < l; i++ {
|
||||
b.set[i] |= compare.set[i]
|
||||
}
|
||||
if len(compare.set) > l {
|
||||
for i := l; i < len(compare.set); i++ {
|
||||
b.set[i] = compare.set[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SymmetricDifference of base set and other set
|
||||
// This is the BitSet equivalent of ^ (xor)
|
||||
func (b *BitSet) SymmetricDifference(compare *BitSet) (result *BitSet) {
|
||||
panicIfNull(b)
|
||||
panicIfNull(compare)
|
||||
b, compare = sortByLength(b, compare)
|
||||
// compare is bigger, so clone it
|
||||
result = compare.Clone()
|
||||
for i, word := range b.set {
|
||||
result.set[i] = word ^ compare.set[i]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SymmetricDifferenceCardinality computes the cardinality of the symmetric difference
|
||||
func (b *BitSet) SymmetricDifferenceCardinality(compare *BitSet) uint {
|
||||
panicIfNull(b)
|
||||
panicIfNull(compare)
|
||||
b, compare = sortByLength(b, compare)
|
||||
cnt := popcntXorSlice(b.set, compare.set)
|
||||
if len(compare.set) > len(b.set) {
|
||||
cnt += popcntSlice(compare.set[len(b.set):])
|
||||
}
|
||||
return uint(cnt)
|
||||
}
|
||||
|
||||
// InPlaceSymmetricDifference creates the destructive SymmetricDifference of base set and other set
|
||||
// This is the BitSet equivalent of ^ (xor)
|
||||
func (b *BitSet) InPlaceSymmetricDifference(compare *BitSet) {
|
||||
panicIfNull(b)
|
||||
panicIfNull(compare)
|
||||
l := int(compare.wordCount())
|
||||
if l > int(b.wordCount()) {
|
||||
l = int(b.wordCount())
|
||||
}
|
||||
if compare.length > 0 {
|
||||
b.extendSetMaybe(compare.length - 1)
|
||||
}
|
||||
for i := 0; i < l; i++ {
|
||||
b.set[i] ^= compare.set[i]
|
||||
}
|
||||
if len(compare.set) > l {
|
||||
for i := l; i < len(compare.set); i++ {
|
||||
b.set[i] = compare.set[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Is the length an exact multiple of word sizes?
|
||||
func (b *BitSet) isLenExactMultiple() bool {
|
||||
return b.length%wordSize == 0
|
||||
}
|
||||
|
||||
// Clean last word by setting unused bits to 0
|
||||
func (b *BitSet) cleanLastWord() {
|
||||
if !b.isLenExactMultiple() {
|
||||
b.set[len(b.set)-1] &= allBits >> (wordSize - b.length%wordSize)
|
||||
}
|
||||
}
|
||||
|
||||
// Complement computes the (local) complement of a biset (up to length bits)
|
||||
func (b *BitSet) Complement() (result *BitSet) {
|
||||
panicIfNull(b)
|
||||
result = New(b.length)
|
||||
for i, word := range b.set {
|
||||
result.set[i] = ^word
|
||||
}
|
||||
result.cleanLastWord()
|
||||
return
|
||||
}
|
||||
|
||||
// All returns true if all bits are set, false otherwise. Returns true for
|
||||
// empty sets.
|
||||
func (b *BitSet) All() bool {
|
||||
panicIfNull(b)
|
||||
return b.Count() == b.length
|
||||
}
|
||||
|
||||
// None returns true if no bit is set, false otherwise. Returns true for
|
||||
// empty sets.
|
||||
func (b *BitSet) None() bool {
|
||||
panicIfNull(b)
|
||||
if b != nil && b.set != nil {
|
||||
for _, word := range b.set {
|
||||
if word > 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Any returns true if any bit is set, false otherwise
|
||||
func (b *BitSet) Any() bool {
|
||||
panicIfNull(b)
|
||||
return !b.None()
|
||||
}
|
||||
|
||||
// IsSuperSet returns true if this is a superset of the other set
|
||||
func (b *BitSet) IsSuperSet(other *BitSet) bool {
|
||||
for i, e := other.NextSet(0); e; i, e = other.NextSet(i + 1) {
|
||||
if !b.Test(i) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// IsStrictSuperSet returns true if this is a strict superset of the other set
|
||||
func (b *BitSet) IsStrictSuperSet(other *BitSet) bool {
|
||||
return b.Count() > other.Count() && b.IsSuperSet(other)
|
||||
}
|
||||
|
||||
// DumpAsBits dumps a bit set as a string of bits
|
||||
func (b *BitSet) DumpAsBits() string {
|
||||
if b.set == nil {
|
||||
return "."
|
||||
}
|
||||
buffer := bytes.NewBufferString("")
|
||||
i := len(b.set) - 1
|
||||
for ; i >= 0; i-- {
|
||||
fmt.Fprintf(buffer, "%064b.", b.set[i])
|
||||
}
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// BinaryStorageSize returns the binary storage requirements
|
||||
func (b *BitSet) BinaryStorageSize() int {
|
||||
return binary.Size(uint64(0)) + binary.Size(b.set)
|
||||
}
|
||||
|
||||
// WriteTo writes a BitSet to a stream
|
||||
func (b *BitSet) WriteTo(stream io.Writer) (int64, error) {
|
||||
length := uint64(b.length)
|
||||
|
||||
// Write length
|
||||
err := binary.Write(stream, binaryOrder, length)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Write set
|
||||
err = binary.Write(stream, binaryOrder, b.set)
|
||||
return int64(b.BinaryStorageSize()), err
|
||||
}
|
||||
|
||||
// ReadFrom reads a BitSet from a stream written using WriteTo
|
||||
func (b *BitSet) ReadFrom(stream io.Reader) (int64, error) {
|
||||
var length uint64
|
||||
|
||||
// Read length first
|
||||
err := binary.Read(stream, binaryOrder, &length)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
newset := New(uint(length))
|
||||
|
||||
if uint64(newset.length) != length {
|
||||
return 0, errors.New("unmarshalling error: type mismatch")
|
||||
}
|
||||
|
||||
// Read remaining bytes as set
|
||||
err = binary.Read(stream, binaryOrder, newset.set)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
*b = *newset
|
||||
return int64(b.BinaryStorageSize()), nil
|
||||
}
|
||||
|
||||
// MarshalBinary encodes a BitSet into a binary form and returns the result.
|
||||
func (b *BitSet) MarshalBinary() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
writer := bufio.NewWriter(&buf)
|
||||
|
||||
_, err := b.WriteTo(writer)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
|
||||
err = writer.Flush()
|
||||
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes the binary form generated by MarshalBinary.
|
||||
func (b *BitSet) UnmarshalBinary(data []byte) error {
|
||||
buf := bytes.NewReader(data)
|
||||
reader := bufio.NewReader(buf)
|
||||
|
||||
_, err := b.ReadFrom(reader)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// MarshalJSON marshals a BitSet as a JSON structure
|
||||
func (b *BitSet) MarshalJSON() ([]byte, error) {
|
||||
buffer := bytes.NewBuffer(make([]byte, 0, b.BinaryStorageSize()))
|
||||
_, err := b.WriteTo(buffer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// URLEncode all bytes
|
||||
return json.Marshal(base64Encoding.EncodeToString(buffer.Bytes()))
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals a BitSet from JSON created using MarshalJSON
|
||||
func (b *BitSet) UnmarshalJSON(data []byte) error {
|
||||
// Unmarshal as string
|
||||
var s string
|
||||
err := json.Unmarshal(data, &s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// URLDecode string
|
||||
buf, err := base64Encoding.DecodeString(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = b.ReadFrom(bytes.NewReader(buf))
|
||||
return err
|
||||
}
|
53
vendor/github.com/bits-and-blooms/bitset/popcnt.go
generated
vendored
Normal file
53
vendor/github.com/bits-and-blooms/bitset/popcnt.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
package bitset
|
||||
|
||||
// bit population count, take from
|
||||
// https://code.google.com/p/go/issues/detail?id=4988#c11
|
||||
// credit: https://code.google.com/u/arnehormann/
|
||||
func popcount(x uint64) (n uint64) {
|
||||
x -= (x >> 1) & 0x5555555555555555
|
||||
x = (x>>2)&0x3333333333333333 + x&0x3333333333333333
|
||||
x += x >> 4
|
||||
x &= 0x0f0f0f0f0f0f0f0f
|
||||
x *= 0x0101010101010101
|
||||
return x >> 56
|
||||
}
|
||||
|
||||
func popcntSliceGo(s []uint64) uint64 {
|
||||
cnt := uint64(0)
|
||||
for _, x := range s {
|
||||
cnt += popcount(x)
|
||||
}
|
||||
return cnt
|
||||
}
|
||||
|
||||
func popcntMaskSliceGo(s, m []uint64) uint64 {
|
||||
cnt := uint64(0)
|
||||
for i := range s {
|
||||
cnt += popcount(s[i] &^ m[i])
|
||||
}
|
||||
return cnt
|
||||
}
|
||||
|
||||
func popcntAndSliceGo(s, m []uint64) uint64 {
|
||||
cnt := uint64(0)
|
||||
for i := range s {
|
||||
cnt += popcount(s[i] & m[i])
|
||||
}
|
||||
return cnt
|
||||
}
|
||||
|
||||
func popcntOrSliceGo(s, m []uint64) uint64 {
|
||||
cnt := uint64(0)
|
||||
for i := range s {
|
||||
cnt += popcount(s[i] | m[i])
|
||||
}
|
||||
return cnt
|
||||
}
|
||||
|
||||
func popcntXorSliceGo(s, m []uint64) uint64 {
|
||||
cnt := uint64(0)
|
||||
for i := range s {
|
||||
cnt += popcount(s[i] ^ m[i])
|
||||
}
|
||||
return cnt
|
||||
}
|
45
vendor/github.com/bits-and-blooms/bitset/popcnt_19.go
generated
vendored
Normal file
45
vendor/github.com/bits-and-blooms/bitset/popcnt_19.go
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
// +build go1.9
|
||||
|
||||
package bitset
|
||||
|
||||
import "math/bits"
|
||||
|
||||
func popcntSlice(s []uint64) uint64 {
|
||||
var cnt int
|
||||
for _, x := range s {
|
||||
cnt += bits.OnesCount64(x)
|
||||
}
|
||||
return uint64(cnt)
|
||||
}
|
||||
|
||||
func popcntMaskSlice(s, m []uint64) uint64 {
|
||||
var cnt int
|
||||
for i := range s {
|
||||
cnt += bits.OnesCount64(s[i] &^ m[i])
|
||||
}
|
||||
return uint64(cnt)
|
||||
}
|
||||
|
||||
func popcntAndSlice(s, m []uint64) uint64 {
|
||||
var cnt int
|
||||
for i := range s {
|
||||
cnt += bits.OnesCount64(s[i] & m[i])
|
||||
}
|
||||
return uint64(cnt)
|
||||
}
|
||||
|
||||
func popcntOrSlice(s, m []uint64) uint64 {
|
||||
var cnt int
|
||||
for i := range s {
|
||||
cnt += bits.OnesCount64(s[i] | m[i])
|
||||
}
|
||||
return uint64(cnt)
|
||||
}
|
||||
|
||||
func popcntXorSlice(s, m []uint64) uint64 {
|
||||
var cnt int
|
||||
for i := range s {
|
||||
cnt += bits.OnesCount64(s[i] ^ m[i])
|
||||
}
|
||||
return uint64(cnt)
|
||||
}
|
68
vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.go
generated
vendored
Normal file
68
vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.go
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
// +build !go1.9
|
||||
// +build amd64,!appengine
|
||||
|
||||
package bitset
|
||||
|
||||
// *** the following functions are defined in popcnt_amd64.s
|
||||
|
||||
//go:noescape
|
||||
|
||||
func hasAsm() bool
|
||||
|
||||
// useAsm is a flag used to select the GO or ASM implementation of the popcnt function
|
||||
var useAsm = hasAsm()
|
||||
|
||||
//go:noescape
|
||||
|
||||
func popcntSliceAsm(s []uint64) uint64
|
||||
|
||||
//go:noescape
|
||||
|
||||
func popcntMaskSliceAsm(s, m []uint64) uint64
|
||||
|
||||
//go:noescape
|
||||
|
||||
func popcntAndSliceAsm(s, m []uint64) uint64
|
||||
|
||||
//go:noescape
|
||||
|
||||
func popcntOrSliceAsm(s, m []uint64) uint64
|
||||
|
||||
//go:noescape
|
||||
|
||||
func popcntXorSliceAsm(s, m []uint64) uint64
|
||||
|
||||
func popcntSlice(s []uint64) uint64 {
|
||||
if useAsm {
|
||||
return popcntSliceAsm(s)
|
||||
}
|
||||
return popcntSliceGo(s)
|
||||
}
|
||||
|
||||
func popcntMaskSlice(s, m []uint64) uint64 {
|
||||
if useAsm {
|
||||
return popcntMaskSliceAsm(s, m)
|
||||
}
|
||||
return popcntMaskSliceGo(s, m)
|
||||
}
|
||||
|
||||
func popcntAndSlice(s, m []uint64) uint64 {
|
||||
if useAsm {
|
||||
return popcntAndSliceAsm(s, m)
|
||||
}
|
||||
return popcntAndSliceGo(s, m)
|
||||
}
|
||||
|
||||
func popcntOrSlice(s, m []uint64) uint64 {
|
||||
if useAsm {
|
||||
return popcntOrSliceAsm(s, m)
|
||||
}
|
||||
return popcntOrSliceGo(s, m)
|
||||
}
|
||||
|
||||
func popcntXorSlice(s, m []uint64) uint64 {
|
||||
if useAsm {
|
||||
return popcntXorSliceAsm(s, m)
|
||||
}
|
||||
return popcntXorSliceGo(s, m)
|
||||
}
|
104
vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.s
generated
vendored
Normal file
104
vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.s
generated
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
// +build !go1.9
|
||||
// +build amd64,!appengine
|
||||
|
||||
TEXT ·hasAsm(SB),4,$0-1
|
||||
MOVQ $1, AX
|
||||
CPUID
|
||||
SHRQ $23, CX
|
||||
ANDQ $1, CX
|
||||
MOVB CX, ret+0(FP)
|
||||
RET
|
||||
|
||||
#define POPCNTQ_DX_DX BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0xd2
|
||||
|
||||
TEXT ·popcntSliceAsm(SB),4,$0-32
|
||||
XORQ AX, AX
|
||||
MOVQ s+0(FP), SI
|
||||
MOVQ s_len+8(FP), CX
|
||||
TESTQ CX, CX
|
||||
JZ popcntSliceEnd
|
||||
popcntSliceLoop:
|
||||
BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0x16 // POPCNTQ (SI), DX
|
||||
ADDQ DX, AX
|
||||
ADDQ $8, SI
|
||||
LOOP popcntSliceLoop
|
||||
popcntSliceEnd:
|
||||
MOVQ AX, ret+24(FP)
|
||||
RET
|
||||
|
||||
TEXT ·popcntMaskSliceAsm(SB),4,$0-56
|
||||
XORQ AX, AX
|
||||
MOVQ s+0(FP), SI
|
||||
MOVQ s_len+8(FP), CX
|
||||
TESTQ CX, CX
|
||||
JZ popcntMaskSliceEnd
|
||||
MOVQ m+24(FP), DI
|
||||
popcntMaskSliceLoop:
|
||||
MOVQ (DI), DX
|
||||
NOTQ DX
|
||||
ANDQ (SI), DX
|
||||
POPCNTQ_DX_DX
|
||||
ADDQ DX, AX
|
||||
ADDQ $8, SI
|
||||
ADDQ $8, DI
|
||||
LOOP popcntMaskSliceLoop
|
||||
popcntMaskSliceEnd:
|
||||
MOVQ AX, ret+48(FP)
|
||||
RET
|
||||
|
||||
TEXT ·popcntAndSliceAsm(SB),4,$0-56
|
||||
XORQ AX, AX
|
||||
MOVQ s+0(FP), SI
|
||||
MOVQ s_len+8(FP), CX
|
||||
TESTQ CX, CX
|
||||
JZ popcntAndSliceEnd
|
||||
MOVQ m+24(FP), DI
|
||||
popcntAndSliceLoop:
|
||||
MOVQ (DI), DX
|
||||
ANDQ (SI), DX
|
||||
POPCNTQ_DX_DX
|
||||
ADDQ DX, AX
|
||||
ADDQ $8, SI
|
||||
ADDQ $8, DI
|
||||
LOOP popcntAndSliceLoop
|
||||
popcntAndSliceEnd:
|
||||
MOVQ AX, ret+48(FP)
|
||||
RET
|
||||
|
||||
TEXT ·popcntOrSliceAsm(SB),4,$0-56
|
||||
XORQ AX, AX
|
||||
MOVQ s+0(FP), SI
|
||||
MOVQ s_len+8(FP), CX
|
||||
TESTQ CX, CX
|
||||
JZ popcntOrSliceEnd
|
||||
MOVQ m+24(FP), DI
|
||||
popcntOrSliceLoop:
|
||||
MOVQ (DI), DX
|
||||
ORQ (SI), DX
|
||||
POPCNTQ_DX_DX
|
||||
ADDQ DX, AX
|
||||
ADDQ $8, SI
|
||||
ADDQ $8, DI
|
||||
LOOP popcntOrSliceLoop
|
||||
popcntOrSliceEnd:
|
||||
MOVQ AX, ret+48(FP)
|
||||
RET
|
||||
|
||||
TEXT ·popcntXorSliceAsm(SB),4,$0-56
|
||||
XORQ AX, AX
|
||||
MOVQ s+0(FP), SI
|
||||
MOVQ s_len+8(FP), CX
|
||||
TESTQ CX, CX
|
||||
JZ popcntXorSliceEnd
|
||||
MOVQ m+24(FP), DI
|
||||
popcntXorSliceLoop:
|
||||
MOVQ (DI), DX
|
||||
XORQ (SI), DX
|
||||
POPCNTQ_DX_DX
|
||||
ADDQ DX, AX
|
||||
ADDQ $8, SI
|
||||
ADDQ $8, DI
|
||||
LOOP popcntXorSliceLoop
|
||||
popcntXorSliceEnd:
|
||||
MOVQ AX, ret+48(FP)
|
||||
RET
|
24
vendor/github.com/bits-and-blooms/bitset/popcnt_generic.go
generated
vendored
Normal file
24
vendor/github.com/bits-and-blooms/bitset/popcnt_generic.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
// +build !go1.9
|
||||
// +build !amd64 appengine
|
||||
|
||||
package bitset
|
||||
|
||||
func popcntSlice(s []uint64) uint64 {
|
||||
return popcntSliceGo(s)
|
||||
}
|
||||
|
||||
func popcntMaskSlice(s, m []uint64) uint64 {
|
||||
return popcntMaskSliceGo(s, m)
|
||||
}
|
||||
|
||||
func popcntAndSlice(s, m []uint64) uint64 {
|
||||
return popcntAndSliceGo(s, m)
|
||||
}
|
||||
|
||||
func popcntOrSlice(s, m []uint64) uint64 {
|
||||
return popcntOrSliceGo(s, m)
|
||||
}
|
||||
|
||||
func popcntXorSlice(s, m []uint64) uint64 {
|
||||
return popcntXorSliceGo(s, m)
|
||||
}
|
14
vendor/github.com/bits-and-blooms/bitset/trailing_zeros_18.go
generated
vendored
Normal file
14
vendor/github.com/bits-and-blooms/bitset/trailing_zeros_18.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
// +build !go1.9
|
||||
|
||||
package bitset
|
||||
|
||||
var deBruijn = [...]byte{
|
||||
0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4,
|
||||
62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5,
|
||||
63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11,
|
||||
54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6,
|
||||
}
|
||||
|
||||
func trailingZeroes64(v uint64) uint {
|
||||
return uint(deBruijn[((v&-v)*0x03f79d71b4ca8b09)>>58])
|
||||
}
|
9
vendor/github.com/bits-and-blooms/bitset/trailing_zeros_19.go
generated
vendored
Normal file
9
vendor/github.com/bits-and-blooms/bitset/trailing_zeros_19.go
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
// +build go1.9
|
||||
|
||||
package bitset
|
||||
|
||||
import "math/bits"
|
||||
|
||||
func trailingZeroes64(v uint64) uint {
|
||||
return uint(bits.TrailingZeros64(v))
|
||||
}
|
3
vendor/github.com/onsi/gomega/.gitignore
generated
vendored
3
vendor/github.com/onsi/gomega/.gitignore
generated
vendored
@ -3,4 +3,5 @@
|
||||
.
|
||||
.idea
|
||||
gomega.iml
|
||||
TODO.md
|
||||
TODO.md
|
||||
.vscode
|
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.26.0
|
||||
|
||||
### Features
|
||||
- When a polled function returns an error, keep track of the actual and report on the matcher state of the last non-errored actual [21f3090]
|
||||
- improve eventually failure message output [c530fb3]
|
||||
|
||||
### Fixes
|
||||
- fix several documentation spelling issues [e2eff1f]
|
||||
|
||||
|
||||
## 1.25.0
|
||||
|
||||
### Features
|
||||
- add `MustPassRepeatedly(int)` to asyncAssertion (#619) [4509f72]
|
||||
- compare unwrapped errors using DeepEqual (#617) [aaeaa5d]
|
||||
|
||||
### Maintenance
|
||||
- Bump golang.org/x/net from 0.4.0 to 0.5.0 (#614) [c7cfea4]
|
||||
- Bump github.com/onsi/ginkgo/v2 from 2.6.1 to 2.7.0 (#615) [71b8adb]
|
||||
- Docs: Fix typo "MUltiple" -> "Multiple" (#616) [9351dda]
|
||||
- clean up go.sum [cd1dc1d]
|
||||
|
||||
## 1.24.2
|
||||
|
||||
### Fixes
|
||||
|
12
vendor/github.com/onsi/gomega/gomega_dsl.go
generated
vendored
12
vendor/github.com/onsi/gomega/gomega_dsl.go
generated
vendored
@ -22,7 +22,7 @@ import (
|
||||
"github.com/onsi/gomega/types"
|
||||
)
|
||||
|
||||
const GOMEGA_VERSION = "1.24.2"
|
||||
const GOMEGA_VERSION = "1.26.0"
|
||||
|
||||
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().
|
||||
@ -360,6 +360,16 @@ You can also pass additional arugments to functions that take a Gomega. The onl
|
||||
g.Expect(elements).To(ConsistOf(expected))
|
||||
}).WithContext(ctx).WithArguments("/names", "Joe", "Jane", "Sam").Should(Succeed())
|
||||
|
||||
You can ensure that you get a number of consecutive successful tries before succeeding using `MustPassRepeatedly(int)`. For Example:
|
||||
|
||||
int count := 0
|
||||
Eventually(func() bool {
|
||||
count++
|
||||
return count > 2
|
||||
}).MustPassRepeatedly(2).Should(BeTrue())
|
||||
// Because we had to wait for 2 calls that returned true
|
||||
Expect(count).To(Equal(3))
|
||||
|
||||
Finally, in addition to passing timeouts and a context to Eventually you can be more explicit with Eventually's chaining configuration methods:
|
||||
|
||||
Eventually(..., "1s", "2s", ctx).Should(...)
|
||||
|
198
vendor/github.com/onsi/gomega/internal/async_assertion.go
generated
vendored
198
vendor/github.com/onsi/gomega/internal/async_assertion.go
generated
vendored
@ -2,6 +2,7 @@ package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"runtime"
|
||||
@ -16,6 +17,22 @@ var errInterface = reflect.TypeOf((*error)(nil)).Elem()
|
||||
var gomegaType = reflect.TypeOf((*types.Gomega)(nil)).Elem()
|
||||
var contextType = reflect.TypeOf(new(context.Context)).Elem()
|
||||
|
||||
type formattedGomegaError interface {
|
||||
FormattedGomegaError() string
|
||||
}
|
||||
|
||||
type asyncPolledActualError struct {
|
||||
message string
|
||||
}
|
||||
|
||||
func (err *asyncPolledActualError) Error() string {
|
||||
return err.message
|
||||
}
|
||||
|
||||
func (err *asyncPolledActualError) FormattedGomegaError() string {
|
||||
return err.message
|
||||
}
|
||||
|
||||
type contextWithAttachProgressReporter interface {
|
||||
AttachProgressReporter(func() string) func()
|
||||
}
|
||||
@ -55,21 +72,23 @@ type AsyncAssertion struct {
|
||||
actual interface{}
|
||||
argsToForward []interface{}
|
||||
|
||||
timeoutInterval time.Duration
|
||||
pollingInterval time.Duration
|
||||
ctx context.Context
|
||||
offset int
|
||||
g *Gomega
|
||||
timeoutInterval time.Duration
|
||||
pollingInterval time.Duration
|
||||
mustPassRepeatedly int
|
||||
ctx context.Context
|
||||
offset int
|
||||
g *Gomega
|
||||
}
|
||||
|
||||
func NewAsyncAssertion(asyncType AsyncAssertionType, actualInput interface{}, g *Gomega, timeoutInterval time.Duration, pollingInterval time.Duration, ctx context.Context, offset int) *AsyncAssertion {
|
||||
func NewAsyncAssertion(asyncType AsyncAssertionType, actualInput interface{}, g *Gomega, timeoutInterval time.Duration, pollingInterval time.Duration, mustPassRepeatedly int, ctx context.Context, offset int) *AsyncAssertion {
|
||||
out := &AsyncAssertion{
|
||||
asyncType: asyncType,
|
||||
timeoutInterval: timeoutInterval,
|
||||
pollingInterval: pollingInterval,
|
||||
offset: offset,
|
||||
ctx: ctx,
|
||||
g: g,
|
||||
asyncType: asyncType,
|
||||
timeoutInterval: timeoutInterval,
|
||||
pollingInterval: pollingInterval,
|
||||
mustPassRepeatedly: mustPassRepeatedly,
|
||||
offset: offset,
|
||||
ctx: ctx,
|
||||
g: g,
|
||||
}
|
||||
|
||||
out.actual = actualInput
|
||||
@ -115,6 +134,11 @@ func (assertion *AsyncAssertion) WithArguments(argsToForward ...interface{}) typ
|
||||
return assertion
|
||||
}
|
||||
|
||||
func (assertion *AsyncAssertion) MustPassRepeatedly(count int) types.AsyncAssertion {
|
||||
assertion.mustPassRepeatedly = count
|
||||
return assertion
|
||||
}
|
||||
|
||||
func (assertion *AsyncAssertion) Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
||||
assertion.g.THelper()
|
||||
vetOptionalDescription("Asynchronous assertion", optionalDescription...)
|
||||
@ -141,7 +165,9 @@ func (assertion *AsyncAssertion) buildDescription(optionalDescription ...interfa
|
||||
|
||||
func (assertion *AsyncAssertion) processReturnValues(values []reflect.Value) (interface{}, error) {
|
||||
if len(values) == 0 {
|
||||
return nil, fmt.Errorf("No values were returned by the function passed to Gomega")
|
||||
return nil, &asyncPolledActualError{
|
||||
message: fmt.Sprintf("The function passed to %s did not return any values", assertion.asyncType),
|
||||
}
|
||||
}
|
||||
|
||||
actual := values[0].Interface()
|
||||
@ -164,10 +190,12 @@ func (assertion *AsyncAssertion) processReturnValues(values []reflect.Value) (in
|
||||
continue
|
||||
}
|
||||
if i == len(values)-2 && extraType.Implements(errInterface) {
|
||||
err = fmt.Errorf("function returned error: %w", extra.(error))
|
||||
err = extra.(error)
|
||||
}
|
||||
if err == nil {
|
||||
err = fmt.Errorf("Unexpected non-nil/non-zero return value at index %d:\n\t<%T>: %#v", i+1, extra, extra)
|
||||
err = &asyncPolledActualError{
|
||||
message: fmt.Sprintf("The function passed to %s had an unexpected non-nil/non-zero return value at index %d:\n%s", assertion.asyncType, i+1, format.Object(extra, 1)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,6 +230,13 @@ You can learn more at https://onsi.github.io/gomega/#eventually
|
||||
`, assertion.asyncType, t, t.NumIn(), numProvided, have, assertion.asyncType)
|
||||
}
|
||||
|
||||
func (assertion *AsyncAssertion) invalidMustPassRepeatedlyError(reason string) error {
|
||||
return fmt.Errorf(`Invalid use of MustPassRepeatedly with %s %s
|
||||
|
||||
You can learn more at https://onsi.github.io/gomega/#eventually
|
||||
`, assertion.asyncType, reason)
|
||||
}
|
||||
|
||||
func (assertion *AsyncAssertion) buildActualPoller() (func() (interface{}, error), error) {
|
||||
if !assertion.actualIsFunc {
|
||||
return func() (interface{}, error) { return assertion.actual, nil }, nil
|
||||
@ -239,7 +274,9 @@ func (assertion *AsyncAssertion) buildActualPoller() (func() (interface{}, error
|
||||
skip = callerSkip[0]
|
||||
}
|
||||
_, file, line, _ := runtime.Caller(skip + 1)
|
||||
assertionFailure = fmt.Errorf("Assertion in callback at %s:%d failed:\n%s", file, line, message)
|
||||
assertionFailure = &asyncPolledActualError{
|
||||
message: fmt.Sprintf("The function passed to %s failed at %s:%d with:\n%s", assertion.asyncType, file, line, message),
|
||||
}
|
||||
// we throw an asyncGomegaHaltExecutionError so that defer GinkgoRecover() can catch this error if the user makes an assertion in a goroutine
|
||||
panic(asyncGomegaHaltExecutionError{})
|
||||
})))
|
||||
@ -257,6 +294,13 @@ func (assertion *AsyncAssertion) buildActualPoller() (func() (interface{}, error
|
||||
return nil, assertion.argumentMismatchError(actualType, len(inValues))
|
||||
}
|
||||
|
||||
if assertion.mustPassRepeatedly != 1 && assertion.asyncType != AsyncAssertionTypeEventually {
|
||||
return nil, assertion.invalidMustPassRepeatedlyError("it can only be used with Eventually")
|
||||
}
|
||||
if assertion.mustPassRepeatedly < 1 {
|
||||
return nil, assertion.invalidMustPassRepeatedlyError("parameter can't be < 1")
|
||||
}
|
||||
|
||||
return func() (actual interface{}, err error) {
|
||||
var values []reflect.Value
|
||||
assertionFailure = nil
|
||||
@ -338,22 +382,39 @@ func (assertion *AsyncAssertion) match(matcher types.GomegaMatcher, desiredMatch
|
||||
timeout := assertion.afterTimeout()
|
||||
lock := sync.Mutex{}
|
||||
|
||||
var matches bool
|
||||
var err error
|
||||
var matches, hasLastValidActual bool
|
||||
var actual, lastValidActual interface{}
|
||||
var actualErr, matcherErr error
|
||||
var oracleMatcherSaysStop bool
|
||||
|
||||
assertion.g.THelper()
|
||||
|
||||
pollActual, err := assertion.buildActualPoller()
|
||||
if err != nil {
|
||||
assertion.g.Fail(err.Error(), 2+assertion.offset)
|
||||
pollActual, buildActualPollerErr := assertion.buildActualPoller()
|
||||
if buildActualPollerErr != nil {
|
||||
assertion.g.Fail(buildActualPollerErr.Error(), 2+assertion.offset)
|
||||
return false
|
||||
}
|
||||
|
||||
value, err := pollActual()
|
||||
if err == nil {
|
||||
oracleMatcherSaysStop = assertion.matcherSaysStopTrying(matcher, value)
|
||||
matches, err = assertion.pollMatcher(matcher, value)
|
||||
actual, actualErr = pollActual()
|
||||
if actualErr == nil {
|
||||
lastValidActual = actual
|
||||
hasLastValidActual = true
|
||||
oracleMatcherSaysStop = assertion.matcherSaysStopTrying(matcher, actual)
|
||||
matches, matcherErr = assertion.pollMatcher(matcher, actual)
|
||||
}
|
||||
|
||||
renderError := func(preamble string, err error) string {
|
||||
message := ""
|
||||
if pollingSignalErr, ok := AsPollingSignalError(err); ok {
|
||||
message = err.Error()
|
||||
for _, attachment := range pollingSignalErr.Attachments {
|
||||
message += fmt.Sprintf("\n%s:\n", attachment.Description)
|
||||
message += format.Object(attachment.Object, 1)
|
||||
}
|
||||
} else {
|
||||
message = preamble + "\n" + err.Error() + "\n" + format.Object(err, 1)
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
messageGenerator := func() string {
|
||||
@ -361,23 +422,45 @@ func (assertion *AsyncAssertion) match(matcher types.GomegaMatcher, desiredMatch
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
message := ""
|
||||
if err != nil {
|
||||
if pollingSignalErr, ok := AsPollingSignalError(err); ok && pollingSignalErr.IsStopTrying() {
|
||||
message = err.Error()
|
||||
for _, attachment := range pollingSignalErr.Attachments {
|
||||
message += fmt.Sprintf("\n%s:\n", attachment.Description)
|
||||
message += format.Object(attachment.Object, 1)
|
||||
|
||||
if actualErr == nil {
|
||||
if matcherErr == nil {
|
||||
if desiredMatch {
|
||||
message += matcher.FailureMessage(actual)
|
||||
} else {
|
||||
message += matcher.NegatedFailureMessage(actual)
|
||||
}
|
||||
} else {
|
||||
message = "Error: " + err.Error() + "\n" + format.Object(err, 1)
|
||||
var fgErr formattedGomegaError
|
||||
if errors.As(actualErr, &fgErr) {
|
||||
message += fgErr.FormattedGomegaError() + "\n"
|
||||
} else {
|
||||
message += renderError(fmt.Sprintf("The matcher passed to %s returned the following error:", assertion.asyncType), matcherErr)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if desiredMatch {
|
||||
message = matcher.FailureMessage(value)
|
||||
var fgErr formattedGomegaError
|
||||
if errors.As(actualErr, &fgErr) {
|
||||
message += fgErr.FormattedGomegaError() + "\n"
|
||||
} else {
|
||||
message = matcher.NegatedFailureMessage(value)
|
||||
message += renderError(fmt.Sprintf("The function passed to %s returned the following error:", assertion.asyncType), actualErr)
|
||||
}
|
||||
if hasLastValidActual {
|
||||
message += fmt.Sprintf("\nAt one point, however, the function did return successfully.\nYet, %s failed because", assertion.asyncType)
|
||||
_, e := matcher.Match(lastValidActual)
|
||||
if e != nil {
|
||||
message += renderError(" the matcher returned the following error:", e)
|
||||
} else {
|
||||
message += " the matcher was not satisfied:\n"
|
||||
if desiredMatch {
|
||||
message += matcher.FailureMessage(lastValidActual)
|
||||
} else {
|
||||
message += matcher.NegatedFailureMessage(lastValidActual)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
description := assertion.buildDescription(optionalDescription...)
|
||||
return fmt.Sprintf("%s%s", description, message)
|
||||
}
|
||||
@ -396,30 +479,39 @@ func (assertion *AsyncAssertion) match(matcher types.GomegaMatcher, desiredMatch
|
||||
}
|
||||
}
|
||||
|
||||
// Used to count the number of times in a row a step passed
|
||||
passedRepeatedlyCount := 0
|
||||
for {
|
||||
var nextPoll <-chan time.Time = nil
|
||||
var isTryAgainAfterError = false
|
||||
|
||||
if pollingSignalErr, ok := AsPollingSignalError(err); ok {
|
||||
if pollingSignalErr.IsStopTrying() {
|
||||
fail("Told to stop trying")
|
||||
return false
|
||||
}
|
||||
if pollingSignalErr.IsTryAgainAfter() {
|
||||
nextPoll = time.After(pollingSignalErr.TryAgainDuration())
|
||||
isTryAgainAfterError = true
|
||||
for _, err := range []error{actualErr, matcherErr} {
|
||||
if pollingSignalErr, ok := AsPollingSignalError(err); ok {
|
||||
if pollingSignalErr.IsStopTrying() {
|
||||
fail("Told to stop trying")
|
||||
return false
|
||||
}
|
||||
if pollingSignalErr.IsTryAgainAfter() {
|
||||
nextPoll = time.After(pollingSignalErr.TryAgainDuration())
|
||||
isTryAgainAfterError = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err == nil && matches == desiredMatch {
|
||||
if actualErr == nil && matcherErr == nil && matches == desiredMatch {
|
||||
if assertion.asyncType == AsyncAssertionTypeEventually {
|
||||
return true
|
||||
passedRepeatedlyCount += 1
|
||||
if passedRepeatedlyCount == assertion.mustPassRepeatedly {
|
||||
return true
|
||||
}
|
||||
}
|
||||
} else if !isTryAgainAfterError {
|
||||
if assertion.asyncType == AsyncAssertionTypeConsistently {
|
||||
fail("Failed")
|
||||
return false
|
||||
}
|
||||
// Reset the consecutive pass count
|
||||
passedRepeatedlyCount = 0
|
||||
}
|
||||
|
||||
if oracleMatcherSaysStop {
|
||||
@ -437,15 +529,19 @@ func (assertion *AsyncAssertion) match(matcher types.GomegaMatcher, desiredMatch
|
||||
|
||||
select {
|
||||
case <-nextPoll:
|
||||
v, e := pollActual()
|
||||
a, e := pollActual()
|
||||
lock.Lock()
|
||||
value, err = v, e
|
||||
actual, actualErr = a, e
|
||||
lock.Unlock()
|
||||
if err == nil {
|
||||
oracleMatcherSaysStop = assertion.matcherSaysStopTrying(matcher, value)
|
||||
m, e := assertion.pollMatcher(matcher, value)
|
||||
if actualErr == nil {
|
||||
lock.Lock()
|
||||
matches, err = m, e
|
||||
lastValidActual = actual
|
||||
hasLastValidActual = true
|
||||
lock.Unlock()
|
||||
oracleMatcherSaysStop = assertion.matcherSaysStopTrying(matcher, actual)
|
||||
m, e := assertion.pollMatcher(matcher, actual)
|
||||
lock.Lock()
|
||||
matches, matcherErr = m, e
|
||||
lock.Unlock()
|
||||
}
|
||||
case <-contextDone:
|
||||
|
2
vendor/github.com/onsi/gomega/internal/gomega.go
generated
vendored
2
vendor/github.com/onsi/gomega/internal/gomega.go
generated
vendored
@ -109,7 +109,7 @@ func (g *Gomega) makeAsyncAssertion(asyncAssertionType AsyncAssertionType, offse
|
||||
}
|
||||
}
|
||||
|
||||
return NewAsyncAssertion(asyncAssertionType, actual, g, timeoutInterval, pollingInterval, ctx, offset)
|
||||
return NewAsyncAssertion(asyncAssertionType, actual, g, timeoutInterval, pollingInterval, 1, ctx, offset)
|
||||
}
|
||||
|
||||
func (g *Gomega) SetDefaultEventuallyTimeout(t time.Duration) {
|
||||
|
12
vendor/github.com/onsi/gomega/matchers/match_error_matcher.go
generated
vendored
12
vendor/github.com/onsi/gomega/matchers/match_error_matcher.go
generated
vendored
@ -25,7 +25,17 @@ func (matcher *MatchErrorMatcher) Match(actual interface{}) (success bool, err e
|
||||
expected := matcher.Expected
|
||||
|
||||
if isError(expected) {
|
||||
return reflect.DeepEqual(actualErr, expected) || errors.Is(actualErr, expected.(error)), nil
|
||||
// first try the built-in errors.Is
|
||||
if errors.Is(actualErr, expected.(error)) {
|
||||
return true, nil
|
||||
}
|
||||
// if not, try DeepEqual along the error chain
|
||||
for unwrapped := actualErr; unwrapped != nil; unwrapped = errors.Unwrap(unwrapped) {
|
||||
if reflect.DeepEqual(unwrapped, expected) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if isString(expected) {
|
||||
|
9
vendor/github.com/onsi/gomega/matchers/succeed_matcher.go
generated
vendored
9
vendor/github.com/onsi/gomega/matchers/succeed_matcher.go
generated
vendored
@ -1,11 +1,16 @@
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
type formattedGomegaError interface {
|
||||
FormattedGomegaError() string
|
||||
}
|
||||
|
||||
type SucceedMatcher struct {
|
||||
}
|
||||
|
||||
@ -25,6 +30,10 @@ func (matcher *SucceedMatcher) Match(actual interface{}) (success bool, err erro
|
||||
}
|
||||
|
||||
func (matcher *SucceedMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
var fgErr formattedGomegaError
|
||||
if errors.As(actual.(error), &fgErr) {
|
||||
return fgErr.FormattedGomegaError()
|
||||
}
|
||||
return fmt.Sprintf("Expected success, but got an error:\n%s\n%s", format.Object(actual, 1), format.IndentString(actual.(error).Error(), 1))
|
||||
}
|
||||
|
||||
|
1
vendor/github.com/onsi/gomega/types/types.go
generated
vendored
1
vendor/github.com/onsi/gomega/types/types.go
generated
vendored
@ -75,6 +75,7 @@ type AsyncAssertion interface {
|
||||
ProbeEvery(interval time.Duration) AsyncAssertion
|
||||
WithContext(ctx context.Context) AsyncAssertion
|
||||
WithArguments(argsToForward ...interface{}) AsyncAssertion
|
||||
MustPassRepeatedly(count int) AsyncAssertion
|
||||
}
|
||||
|
||||
// Assertions are returned by Ω and Expect and enable assertions against Gomega matchers
|
||||
|
201
vendor/github.com/opencontainers/selinux/LICENSE
generated
vendored
Normal file
201
vendor/github.com/opencontainers/selinux/LICENSE
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
14
vendor/github.com/opencontainers/selinux/go-selinux/doc.go
generated
vendored
Normal file
14
vendor/github.com/opencontainers/selinux/go-selinux/doc.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
Package selinux provides a high-level interface for interacting with selinux.
|
||||
|
||||
Usage:
|
||||
|
||||
import "github.com/opencontainers/selinux/go-selinux"
|
||||
|
||||
// Ensure that selinux is enforcing mode.
|
||||
if selinux.EnforceMode() != selinux.Enforcing {
|
||||
selinux.SetEnforceMode(selinux.Enforcing)
|
||||
}
|
||||
|
||||
*/
|
||||
package selinux
|
284
vendor/github.com/opencontainers/selinux/go-selinux/selinux.go
generated
vendored
Normal file
284
vendor/github.com/opencontainers/selinux/go-selinux/selinux.go
generated
vendored
Normal file
@ -0,0 +1,284 @@
|
||||
package selinux
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
// Enforcing constant indicate SELinux is in enforcing mode
|
||||
Enforcing = 1
|
||||
// Permissive constant to indicate SELinux is in permissive mode
|
||||
Permissive = 0
|
||||
// Disabled constant to indicate SELinux is disabled
|
||||
Disabled = -1
|
||||
// maxCategory is the maximum number of categories used within containers
|
||||
maxCategory = 1024
|
||||
// DefaultCategoryRange is the upper bound on the category range
|
||||
DefaultCategoryRange = uint32(maxCategory)
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrMCSAlreadyExists is returned when trying to allocate a duplicate MCS.
|
||||
ErrMCSAlreadyExists = errors.New("MCS label already exists")
|
||||
// ErrEmptyPath is returned when an empty path has been specified.
|
||||
ErrEmptyPath = errors.New("empty path")
|
||||
|
||||
// InvalidLabel is returned when an invalid label is specified.
|
||||
InvalidLabel = errors.New("Invalid Label")
|
||||
|
||||
// ErrIncomparable is returned two levels are not comparable
|
||||
ErrIncomparable = errors.New("incomparable levels")
|
||||
// ErrLevelSyntax is returned when a sensitivity or category do not have correct syntax in a level
|
||||
ErrLevelSyntax = errors.New("invalid level syntax")
|
||||
|
||||
// ErrContextMissing is returned if a requested context is not found in a file.
|
||||
ErrContextMissing = errors.New("context does not have a match")
|
||||
// ErrVerifierNil is returned when a context verifier function is nil.
|
||||
ErrVerifierNil = errors.New("verifier function is nil")
|
||||
|
||||
// CategoryRange allows the upper bound on the category range to be adjusted
|
||||
CategoryRange = DefaultCategoryRange
|
||||
)
|
||||
|
||||
// Context is a representation of the SELinux label broken into 4 parts
|
||||
type Context map[string]string
|
||||
|
||||
// SetDisabled disables SELinux support for the package
|
||||
func SetDisabled() {
|
||||
setDisabled()
|
||||
}
|
||||
|
||||
// GetEnabled returns whether SELinux is currently enabled.
|
||||
func GetEnabled() bool {
|
||||
return getEnabled()
|
||||
}
|
||||
|
||||
// ClassIndex returns the int index for an object class in the loaded policy,
|
||||
// or -1 and an error
|
||||
func ClassIndex(class string) (int, error) {
|
||||
return classIndex(class)
|
||||
}
|
||||
|
||||
// SetFileLabel sets the SELinux label for this path or returns an error.
|
||||
func SetFileLabel(fpath string, label string) error {
|
||||
return setFileLabel(fpath, label)
|
||||
}
|
||||
|
||||
// FileLabel returns the SELinux label for this path or returns an error.
|
||||
func FileLabel(fpath string) (string, error) {
|
||||
return fileLabel(fpath)
|
||||
}
|
||||
|
||||
// SetFSCreateLabel tells the kernel what label to use for all file system objects
|
||||
// created by this task.
|
||||
// Set the label to an empty string to return to the default label. Calls to SetFSCreateLabel
|
||||
// should be wrapped in runtime.LockOSThread()/runtime.UnlockOSThread() until file system
|
||||
// objects created by this task are finished to guarantee another goroutine does not migrate
|
||||
// to the current thread before execution is complete.
|
||||
func SetFSCreateLabel(label string) error {
|
||||
return setFSCreateLabel(label)
|
||||
}
|
||||
|
||||
// FSCreateLabel returns the default label the kernel which the kernel is using
|
||||
// for file system objects created by this task. "" indicates default.
|
||||
func FSCreateLabel() (string, error) {
|
||||
return fsCreateLabel()
|
||||
}
|
||||
|
||||
// CurrentLabel returns the SELinux label of the current process thread, or an error.
|
||||
func CurrentLabel() (string, error) {
|
||||
return currentLabel()
|
||||
}
|
||||
|
||||
// PidLabel returns the SELinux label of the given pid, or an error.
|
||||
func PidLabel(pid int) (string, error) {
|
||||
return pidLabel(pid)
|
||||
}
|
||||
|
||||
// ExecLabel returns the SELinux label that the kernel will use for any programs
|
||||
// that are executed by the current process thread, or an error.
|
||||
func ExecLabel() (string, error) {
|
||||
return execLabel()
|
||||
}
|
||||
|
||||
// CanonicalizeContext takes a context string and writes it to the kernel
|
||||
// the function then returns the context that the kernel will use. Use this
|
||||
// function to check if two contexts are equivalent
|
||||
func CanonicalizeContext(val string) (string, error) {
|
||||
return canonicalizeContext(val)
|
||||
}
|
||||
|
||||
// ComputeCreateContext requests the type transition from source to target for
|
||||
// class from the kernel.
|
||||
func ComputeCreateContext(source string, target string, class string) (string, error) {
|
||||
return computeCreateContext(source, target, class)
|
||||
}
|
||||
|
||||
// CalculateGlbLub computes the glb (greatest lower bound) and lub (least upper bound)
|
||||
// of a source and target range.
|
||||
// The glblub is calculated as the greater of the low sensitivities and
|
||||
// the lower of the high sensitivities and the and of each category bitset.
|
||||
func CalculateGlbLub(sourceRange, targetRange string) (string, error) {
|
||||
return calculateGlbLub(sourceRange, targetRange)
|
||||
}
|
||||
|
||||
// SetExecLabel sets the SELinux label that the kernel will use for any programs
|
||||
// that are executed by the current process thread, or an error. Calls to SetExecLabel
|
||||
// should be wrapped in runtime.LockOSThread()/runtime.UnlockOSThread() until execution
|
||||
// of the program is finished to guarantee another goroutine does not migrate to the current
|
||||
// thread before execution is complete.
|
||||
func SetExecLabel(label string) error {
|
||||
return setExecLabel(label)
|
||||
}
|
||||
|
||||
// SetTaskLabel sets the SELinux label for the current thread, or an error.
|
||||
// This requires the dyntransition permission. Calls to SetTaskLabel should
|
||||
// be wrapped in runtime.LockOSThread()/runtime.UnlockOSThread() to guarantee
|
||||
// the current thread does not run in a new mislabeled thread.
|
||||
func SetTaskLabel(label string) error {
|
||||
return setTaskLabel(label)
|
||||
}
|
||||
|
||||
// SetSocketLabel takes a process label and tells the kernel to assign the
|
||||
// label to the next socket that gets created. Calls to SetSocketLabel
|
||||
// should be wrapped in runtime.LockOSThread()/runtime.UnlockOSThread() until
|
||||
// the the socket is created to guarantee another goroutine does not migrate
|
||||
// to the current thread before execution is complete.
|
||||
func SetSocketLabel(label string) error {
|
||||
return setSocketLabel(label)
|
||||
}
|
||||
|
||||
// SocketLabel retrieves the current socket label setting
|
||||
func SocketLabel() (string, error) {
|
||||
return socketLabel()
|
||||
}
|
||||
|
||||
// PeerLabel retrieves the label of the client on the other side of a socket
|
||||
func PeerLabel(fd uintptr) (string, error) {
|
||||
return peerLabel(fd)
|
||||
}
|
||||
|
||||
// SetKeyLabel takes a process label and tells the kernel to assign the
|
||||
// label to the next kernel keyring that gets created. Calls to SetKeyLabel
|
||||
// should be wrapped in runtime.LockOSThread()/runtime.UnlockOSThread() until
|
||||
// the kernel keyring is created to guarantee another goroutine does not migrate
|
||||
// to the current thread before execution is complete.
|
||||
func SetKeyLabel(label string) error {
|
||||
return setKeyLabel(label)
|
||||
}
|
||||
|
||||
// KeyLabel retrieves the current kernel keyring label setting
|
||||
func KeyLabel() (string, error) {
|
||||
return keyLabel()
|
||||
}
|
||||
|
||||
// Get returns the Context as a string
|
||||
func (c Context) Get() string {
|
||||
return c.get()
|
||||
}
|
||||
|
||||
// NewContext creates a new Context struct from the specified label
|
||||
func NewContext(label string) (Context, error) {
|
||||
return newContext(label)
|
||||
}
|
||||
|
||||
// ClearLabels clears all reserved labels
|
||||
func ClearLabels() {
|
||||
clearLabels()
|
||||
}
|
||||
|
||||
// ReserveLabel reserves the MLS/MCS level component of the specified label
|
||||
func ReserveLabel(label string) {
|
||||
reserveLabel(label)
|
||||
}
|
||||
|
||||
// EnforceMode returns the current SELinux mode Enforcing, Permissive, Disabled
|
||||
func EnforceMode() int {
|
||||
return enforceMode()
|
||||
}
|
||||
|
||||
// SetEnforceMode sets the current SELinux mode Enforcing, Permissive.
|
||||
// Disabled is not valid, since this needs to be set at boot time.
|
||||
func SetEnforceMode(mode int) error {
|
||||
return setEnforceMode(mode)
|
||||
}
|
||||
|
||||
// DefaultEnforceMode returns the systems default SELinux mode Enforcing,
|
||||
// Permissive or Disabled. Note this is is just the default at boot time.
|
||||
// EnforceMode tells you the systems current mode.
|
||||
func DefaultEnforceMode() int {
|
||||
return defaultEnforceMode()
|
||||
}
|
||||
|
||||
// ReleaseLabel un-reserves the MLS/MCS Level field of the specified label,
|
||||
// allowing it to be used by another process.
|
||||
func ReleaseLabel(label string) {
|
||||
releaseLabel(label)
|
||||
}
|
||||
|
||||
// ROFileLabel returns the specified SELinux readonly file label
|
||||
func ROFileLabel() string {
|
||||
return roFileLabel()
|
||||
}
|
||||
|
||||
// KVMContainerLabels returns the default processLabel and mountLabel to be used
|
||||
// for kvm containers by the calling process.
|
||||
func KVMContainerLabels() (string, string) {
|
||||
return kvmContainerLabels()
|
||||
}
|
||||
|
||||
// InitContainerLabels returns the default processLabel and file labels to be
|
||||
// used for containers running an init system like systemd by the calling process.
|
||||
func InitContainerLabels() (string, string) {
|
||||
return initContainerLabels()
|
||||
}
|
||||
|
||||
// ContainerLabels returns an allocated processLabel and fileLabel to be used for
|
||||
// container labeling by the calling process.
|
||||
func ContainerLabels() (processLabel string, fileLabel string) {
|
||||
return containerLabels()
|
||||
}
|
||||
|
||||
// SecurityCheckContext validates that the SELinux label is understood by the kernel
|
||||
func SecurityCheckContext(val string) error {
|
||||
return securityCheckContext(val)
|
||||
}
|
||||
|
||||
// CopyLevel returns a label with the MLS/MCS level from src label replaced on
|
||||
// the dest label.
|
||||
func CopyLevel(src, dest string) (string, error) {
|
||||
return copyLevel(src, dest)
|
||||
}
|
||||
|
||||
// Chcon changes the fpath file object to the SELinux label label.
|
||||
// If fpath is a directory and recurse is true, then Chcon walks the
|
||||
// directory tree setting the label.
|
||||
func Chcon(fpath string, label string, recurse bool) error {
|
||||
return chcon(fpath, label, recurse)
|
||||
}
|
||||
|
||||
// DupSecOpt takes an SELinux process label and returns security options that
|
||||
// can be used to set the SELinux Type and Level for future container processes.
|
||||
func DupSecOpt(src string) ([]string, error) {
|
||||
return dupSecOpt(src)
|
||||
}
|
||||
|
||||
// DisableSecOpt returns a security opt that can be used to disable SELinux
|
||||
// labeling support for future container processes.
|
||||
func DisableSecOpt() []string {
|
||||
return disableSecOpt()
|
||||
}
|
||||
|
||||
// GetDefaultContextWithLevel gets a single context for the specified SELinux user
|
||||
// identity that is reachable from the specified scon context. The context is based
|
||||
// on the per-user /etc/selinux/{SELINUXTYPE}/contexts/users/<username> if it exists,
|
||||
// and falls back to the global /etc/selinux/{SELINUXTYPE}/contexts/default_contexts
|
||||
// file.
|
||||
func GetDefaultContextWithLevel(user, level, scon string) (string, error) {
|
||||
return getDefaultContextWithLevel(user, level, scon)
|
||||
}
|
||||
|
||||
// PrivContainerMountLabel returns mount label for privileged containers
|
||||
func PrivContainerMountLabel() string {
|
||||
return privContainerMountLabel
|
||||
}
|
1212
vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
generated
vendored
Normal file
1212
vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
154
vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
generated
vendored
Normal file
154
vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
generated
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
// +build !linux
|
||||
|
||||
package selinux
|
||||
|
||||
const privContainerMountLabel = ""
|
||||
|
||||
func setDisabled() {
|
||||
}
|
||||
|
||||
func getEnabled() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func classIndex(class string) (int, error) {
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func setFileLabel(fpath string, label string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func fileLabel(fpath string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func setFSCreateLabel(label string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func fsCreateLabel() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func currentLabel() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func pidLabel(pid int) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func execLabel() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func canonicalizeContext(val string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func computeCreateContext(source string, target string, class string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func calculateGlbLub(sourceRange, targetRange string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func setExecLabel(label string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setTaskLabel(label string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setSocketLabel(label string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func socketLabel() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func peerLabel(fd uintptr) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func setKeyLabel(label string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func keyLabel() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (c Context) get() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func newContext(label string) (Context, error) {
|
||||
c := make(Context)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func clearLabels() {
|
||||
}
|
||||
|
||||
func reserveLabel(label string) {
|
||||
}
|
||||
|
||||
func enforceMode() int {
|
||||
return Disabled
|
||||
}
|
||||
|
||||
func setEnforceMode(mode int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func defaultEnforceMode() int {
|
||||
return Disabled
|
||||
}
|
||||
|
||||
func releaseLabel(label string) {
|
||||
}
|
||||
|
||||
func roFileLabel() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func kvmContainerLabels() (string, string) {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
func initContainerLabels() (string, string) {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
func containerLabels() (processLabel string, fileLabel string) {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
func securityCheckContext(val string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyLevel(src, dest string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func chcon(fpath string, label string, recurse bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func dupSecOpt(src string) ([]string, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func disableSecOpt() []string {
|
||||
return []string{"disable"}
|
||||
}
|
||||
|
||||
func getDefaultContextWithLevel(user, level, scon string) (string, error) {
|
||||
return "", nil
|
||||
}
|
38
vendor/github.com/opencontainers/selinux/go-selinux/xattrs_linux.go
generated
vendored
Normal file
38
vendor/github.com/opencontainers/selinux/go-selinux/xattrs_linux.go
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
package selinux
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// lgetxattr returns a []byte slice containing the value of
|
||||
// an extended attribute attr set for path.
|
||||
func lgetxattr(path, attr string) ([]byte, error) {
|
||||
// Start with a 128 length byte array
|
||||
dest := make([]byte, 128)
|
||||
sz, errno := doLgetxattr(path, attr, dest)
|
||||
for errno == unix.ERANGE {
|
||||
// Buffer too small, use zero-sized buffer to get the actual size
|
||||
sz, errno = doLgetxattr(path, attr, []byte{})
|
||||
if errno != nil {
|
||||
return nil, errno
|
||||
}
|
||||
|
||||
dest = make([]byte, sz)
|
||||
sz, errno = doLgetxattr(path, attr, dest)
|
||||
}
|
||||
if errno != nil {
|
||||
return nil, errno
|
||||
}
|
||||
|
||||
return dest[:sz], nil
|
||||
}
|
||||
|
||||
// doLgetxattr is a wrapper that retries on EINTR
|
||||
func doLgetxattr(path, attr string, dest []byte) (int, error) {
|
||||
for {
|
||||
sz, err := unix.Lgetxattr(path, attr, dest)
|
||||
if err != unix.EINTR {
|
||||
return sz, err
|
||||
}
|
||||
}
|
||||
}
|
42
vendor/github.com/opencontainers/selinux/pkg/pwalk/README.md
generated
vendored
Normal file
42
vendor/github.com/opencontainers/selinux/pkg/pwalk/README.md
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
## pwalk: parallel implementation of filepath.Walk
|
||||
|
||||
This is a wrapper for [filepath.Walk](https://pkg.go.dev/path/filepath?tab=doc#Walk)
|
||||
which may speed it up by calling multiple callback functions (WalkFunc) in parallel,
|
||||
utilizing goroutines.
|
||||
|
||||
By default, it utilizes 2\*runtime.NumCPU() goroutines for callbacks.
|
||||
This can be changed by using WalkN function which has the additional
|
||||
parameter, specifying the number of goroutines (concurrency).
|
||||
|
||||
### Caveats
|
||||
|
||||
Please note the following limitations of this code:
|
||||
|
||||
* Unlike filepath.Walk, the order of calls is non-deterministic;
|
||||
|
||||
* Only primitive error handling is supported:
|
||||
|
||||
* filepath.SkipDir is not supported;
|
||||
|
||||
* no errors are ever passed to WalkFunc;
|
||||
|
||||
* once any error is returned from any WalkFunc instance, no more new calls
|
||||
to WalkFunc are made, and the error is returned to the caller of Walk;
|
||||
|
||||
* if more than one walkFunc instance will return an error, only one
|
||||
of such errors will be propagated and returned by Walk, others
|
||||
will be silently discarded.
|
||||
|
||||
### Documentation
|
||||
|
||||
For the official documentation, see
|
||||
https://pkg.go.dev/github.com/opencontainers/selinux/pkg/pwalk?tab=doc
|
||||
|
||||
### Benchmarks
|
||||
|
||||
For a WalkFunc that consists solely of the return statement, this
|
||||
implementation is about 10% slower than the standard library's
|
||||
filepath.Walk.
|
||||
|
||||
Otherwise (if a WalkFunc is doing something) this is usually faster,
|
||||
except when the WalkN(..., 1) is used.
|
104
vendor/github.com/opencontainers/selinux/pkg/pwalk/pwalk.go
generated
vendored
Normal file
104
vendor/github.com/opencontainers/selinux/pkg/pwalk/pwalk.go
generated
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
package pwalk
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type WalkFunc = filepath.WalkFunc
|
||||
|
||||
// Walk is a wrapper for filepath.Walk which can call multiple walkFn
|
||||
// in parallel, allowing to handle each item concurrently. A maximum of
|
||||
// twice the runtime.NumCPU() walkFn will be called at any one time.
|
||||
// If you want to change the maximum, use WalkN instead.
|
||||
//
|
||||
// The order of calls is non-deterministic.
|
||||
//
|
||||
// Note that this implementation only supports primitive error handling:
|
||||
//
|
||||
// - no errors are ever passed to WalkFn;
|
||||
//
|
||||
// - once a walkFn returns any error, all further processing stops
|
||||
// and the error is returned to the caller of Walk;
|
||||
//
|
||||
// - filepath.SkipDir is not supported;
|
||||
//
|
||||
// - if more than one walkFn instance will return an error, only one
|
||||
// of such errors will be propagated and returned by Walk, others
|
||||
// will be silently discarded.
|
||||
func Walk(root string, walkFn WalkFunc) error {
|
||||
return WalkN(root, walkFn, runtime.NumCPU()*2)
|
||||
}
|
||||
|
||||
// WalkN is a wrapper for filepath.Walk which can call multiple walkFn
|
||||
// in parallel, allowing to handle each item concurrently. A maximum of
|
||||
// num walkFn will be called at any one time.
|
||||
//
|
||||
// Please see Walk documentation for caveats of using this function.
|
||||
func WalkN(root string, walkFn WalkFunc, num int) error {
|
||||
// make sure limit is sensible
|
||||
if num < 1 {
|
||||
return errors.Errorf("walk(%q): num must be > 0", root)
|
||||
}
|
||||
|
||||
files := make(chan *walkArgs, 2*num)
|
||||
errCh := make(chan error, 1) // get the first error, ignore others
|
||||
|
||||
// Start walking a tree asap
|
||||
var (
|
||||
err error
|
||||
wg sync.WaitGroup
|
||||
)
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
err = filepath.Walk(root, func(p string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
close(files)
|
||||
return err
|
||||
}
|
||||
// add a file to the queue unless a callback sent an error
|
||||
select {
|
||||
case e := <-errCh:
|
||||
close(files)
|
||||
return e
|
||||
default:
|
||||
files <- &walkArgs{path: p, info: &info}
|
||||
return nil
|
||||
}
|
||||
})
|
||||
if err == nil {
|
||||
close(files)
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
wg.Add(num)
|
||||
for i := 0; i < num; i++ {
|
||||
go func() {
|
||||
for file := range files {
|
||||
if e := walkFn(file.path, *file.info, nil); e != nil {
|
||||
select {
|
||||
case errCh <- e: // sent ok
|
||||
default: // buffer full
|
||||
}
|
||||
}
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// walkArgs holds the arguments that were passed to the Walk or WalkLimit
|
||||
// functions.
|
||||
type walkArgs struct {
|
||||
path string
|
||||
info *os.FileInfo
|
||||
}
|
2
vendor/golang.org/x/net/html/parse.go
generated
vendored
2
vendor/golang.org/x/net/html/parse.go
generated
vendored
@ -184,7 +184,7 @@ func (p *parser) clearStackToContext(s scope) {
|
||||
}
|
||||
}
|
||||
|
||||
// parseGenericRawTextElements implements the generic raw text element parsing
|
||||
// parseGenericRawTextElement implements the generic raw text element parsing
|
||||
// algorithm defined in 12.2.6.2.
|
||||
// https://html.spec.whatwg.org/multipage/parsing.html#parsing-elements-that-contain-only-text
|
||||
// TODO: Since both RAWTEXT and RCDATA states are treated as tokenizer's part
|
||||
|
49
vendor/golang.org/x/net/html/token.go
generated
vendored
49
vendor/golang.org/x/net/html/token.go
generated
vendored
@ -598,6 +598,11 @@ scriptDataDoubleEscapeEnd:
|
||||
// readComment reads the next comment token starting with "<!--". The opening
|
||||
// "<!--" has already been consumed.
|
||||
func (z *Tokenizer) readComment() {
|
||||
// When modifying this function, consider manually increasing the suffixLen
|
||||
// constant in func TestComments, from 6 to e.g. 9 or more. That increase
|
||||
// should only be temporary, not committed, as it exponentially affects the
|
||||
// test running time.
|
||||
|
||||
z.data.start = z.raw.end
|
||||
defer func() {
|
||||
if z.data.end < z.data.start {
|
||||
@ -611,11 +616,7 @@ func (z *Tokenizer) readComment() {
|
||||
for {
|
||||
c := z.readByte()
|
||||
if z.err != nil {
|
||||
// Ignore up to two dashes at EOF.
|
||||
if dashCount > 2 {
|
||||
dashCount = 2
|
||||
}
|
||||
z.data.end = z.raw.end - dashCount
|
||||
z.data.end = z.calculateAbruptCommentDataEnd()
|
||||
return
|
||||
}
|
||||
switch c {
|
||||
@ -631,12 +632,15 @@ func (z *Tokenizer) readComment() {
|
||||
if dashCount >= 2 {
|
||||
c = z.readByte()
|
||||
if z.err != nil {
|
||||
z.data.end = z.raw.end
|
||||
z.data.end = z.calculateAbruptCommentDataEnd()
|
||||
return
|
||||
}
|
||||
if c == '>' {
|
||||
} else if c == '>' {
|
||||
z.data.end = z.raw.end - len("--!>")
|
||||
return
|
||||
} else if c == '-' {
|
||||
dashCount = 1
|
||||
beginning = false
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -645,6 +649,35 @@ func (z *Tokenizer) readComment() {
|
||||
}
|
||||
}
|
||||
|
||||
func (z *Tokenizer) calculateAbruptCommentDataEnd() int {
|
||||
raw := z.Raw()
|
||||
const prefixLen = len("<!--")
|
||||
if len(raw) >= prefixLen {
|
||||
raw = raw[prefixLen:]
|
||||
if hasSuffix(raw, "--!") {
|
||||
return z.raw.end - 3
|
||||
} else if hasSuffix(raw, "--") {
|
||||
return z.raw.end - 2
|
||||
} else if hasSuffix(raw, "-") {
|
||||
return z.raw.end - 1
|
||||
}
|
||||
}
|
||||
return z.raw.end
|
||||
}
|
||||
|
||||
func hasSuffix(b []byte, suffix string) bool {
|
||||
if len(b) < len(suffix) {
|
||||
return false
|
||||
}
|
||||
b = b[len(b)-len(suffix):]
|
||||
for i := range b {
|
||||
if b[i] != suffix[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// readUntilCloseAngle reads until the next ">".
|
||||
func (z *Tokenizer) readUntilCloseAngle() {
|
||||
z.data.start = z.raw.end
|
||||
|
4
vendor/golang.org/x/sys/unix/gccgo_c.c
generated
vendored
4
vendor/golang.org/x/sys/unix/gccgo_c.c
generated
vendored
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build gccgo,!hurd
|
||||
// +build !aix,!hurd
|
||||
//go:build gccgo && !aix && !hurd
|
||||
// +build gccgo,!aix,!hurd
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
1
vendor/golang.org/x/sys/unix/syscall_darwin.go
generated
vendored
1
vendor/golang.org/x/sys/unix/syscall_darwin.go
generated
vendored
@ -230,6 +230,7 @@ func direntNamlen(buf []byte) (uint64, bool) {
|
||||
|
||||
func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) }
|
||||
func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) }
|
||||
func PtraceDenyAttach() (err error) { return ptrace(PT_DENY_ATTACH, 0, 0, 0) }
|
||||
|
||||
//sysnb pipe(p *[2]int32) (err error)
|
||||
|
||||
|
9
vendor/golang.org/x/sys/unix/syscall_freebsd_386.go
generated
vendored
9
vendor/golang.org/x/sys/unix/syscall_freebsd_386.go
generated
vendored
@ -60,8 +60,13 @@ func PtraceGetFsBase(pid int, fsbase *int64) (err error) {
|
||||
return ptrace(PT_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
|
||||
}
|
||||
|
||||
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
||||
ioDesc := PtraceIoDesc{Op: int32(req), Offs: uintptr(unsafe.Pointer(addr)), Addr: uintptr(unsafe.Pointer(&out[0])), Len: uint32(countin)}
|
||||
func PtraceIO(req int, pid int, offs uintptr, out []byte, countin int) (count int, err error) {
|
||||
ioDesc := PtraceIoDesc{
|
||||
Op: int32(req),
|
||||
Offs: offs,
|
||||
Addr: uintptr(unsafe.Pointer(&out[0])), // TODO(#58351): this is not safe.
|
||||
Len: uint32(countin),
|
||||
}
|
||||
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||
return int(ioDesc.Len), err
|
||||
}
|
||||
|
9
vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go
generated
vendored
9
vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go
generated
vendored
@ -60,8 +60,13 @@ func PtraceGetFsBase(pid int, fsbase *int64) (err error) {
|
||||
return ptrace(PT_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
|
||||
}
|
||||
|
||||
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
||||
ioDesc := PtraceIoDesc{Op: int32(req), Offs: uintptr(unsafe.Pointer(addr)), Addr: uintptr(unsafe.Pointer(&out[0])), Len: uint64(countin)}
|
||||
func PtraceIO(req int, pid int, offs uintptr, out []byte, countin int) (count int, err error) {
|
||||
ioDesc := PtraceIoDesc{
|
||||
Op: int32(req),
|
||||
Offs: offs,
|
||||
Addr: uintptr(unsafe.Pointer(&out[0])), // TODO(#58351): this is not safe.
|
||||
Len: uint64(countin),
|
||||
}
|
||||
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||
return int(ioDesc.Len), err
|
||||
}
|
||||
|
9
vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go
generated
vendored
9
vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go
generated
vendored
@ -56,8 +56,13 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||
|
||||
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
|
||||
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
||||
ioDesc := PtraceIoDesc{Op: int32(req), Offs: uintptr(unsafe.Pointer(addr)), Addr: uintptr(unsafe.Pointer(&out[0])), Len: uint32(countin)}
|
||||
func PtraceIO(req int, pid int, offs uintptr, out []byte, countin int) (count int, err error) {
|
||||
ioDesc := PtraceIoDesc{
|
||||
Op: int32(req),
|
||||
Offs: offs,
|
||||
Addr: uintptr(unsafe.Pointer(&out[0])), // TODO(#58351): this is not safe.
|
||||
Len: uint32(countin),
|
||||
}
|
||||
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||
return int(ioDesc.Len), err
|
||||
}
|
||||
|
9
vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go
generated
vendored
9
vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go
generated
vendored
@ -56,8 +56,13 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||
|
||||
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
|
||||
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
||||
ioDesc := PtraceIoDesc{Op: int32(req), Offs: uintptr(unsafe.Pointer(addr)), Addr: uintptr(unsafe.Pointer(&out[0])), Len: uint64(countin)}
|
||||
func PtraceIO(req int, pid int, offs uintptr, out []byte, countin int) (count int, err error) {
|
||||
ioDesc := PtraceIoDesc{
|
||||
Op: int32(req),
|
||||
Offs: offs,
|
||||
Addr: uintptr(unsafe.Pointer(&out[0])), // TODO(#58351): this is not safe.
|
||||
Len: uint64(countin),
|
||||
}
|
||||
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||
return int(ioDesc.Len), err
|
||||
}
|
||||
|
9
vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go
generated
vendored
9
vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go
generated
vendored
@ -56,8 +56,13 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||
|
||||
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
|
||||
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
||||
ioDesc := PtraceIoDesc{Op: int32(req), Offs: uintptr(unsafe.Pointer(addr)), Addr: uintptr(unsafe.Pointer(&out[0])), Len: uint64(countin)}
|
||||
func PtraceIO(req int, pid int, offs uintptr, out []byte, countin int) (count int, err error) {
|
||||
ioDesc := PtraceIoDesc{
|
||||
Op: int32(req),
|
||||
Offs: offs,
|
||||
Addr: uintptr(unsafe.Pointer(&out[0])), // TODO(#58351): this is not safe.
|
||||
Len: uint64(countin),
|
||||
}
|
||||
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||
return int(ioDesc.Len), err
|
||||
}
|
||||
|
3
vendor/golang.org/x/sys/unix/syscall_linux.go
generated
vendored
3
vendor/golang.org/x/sys/unix/syscall_linux.go
generated
vendored
@ -1800,6 +1800,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||
//sysnb Capset(hdr *CapUserHeader, data *CapUserData) (err error)
|
||||
//sys Chdir(path string) (err error)
|
||||
//sys Chroot(path string) (err error)
|
||||
//sys ClockAdjtime(clockid int32, buf *Timex) (state int, err error)
|
||||
//sys ClockGetres(clockid int32, res *Timespec) (err error)
|
||||
//sys ClockGettime(clockid int32, time *Timespec) (err error)
|
||||
//sys ClockNanosleep(clockid int32, flags int, request *Timespec, remain *Timespec) (err error)
|
||||
@ -1999,7 +2000,7 @@ func appendBytes(vecs []Iovec, bs [][]byte) []Iovec {
|
||||
// offs2lohi splits offs into its low and high order bits.
|
||||
func offs2lohi(offs int64) (lo, hi uintptr) {
|
||||
const longBits = SizeofLong * 8
|
||||
return uintptr(offs), uintptr(uint64(offs) >> longBits)
|
||||
return uintptr(offs), uintptr(uint64(offs) >> (longBits - 1) >> 1) // two shifts to avoid false positive in vet
|
||||
}
|
||||
|
||||
func Readv(fd int, iovs [][]byte) (n int, err error) {
|
||||
|
2
vendor/golang.org/x/sys/unix/syscall_unix.go
generated
vendored
2
vendor/golang.org/x/sys/unix/syscall_unix.go
generated
vendored
@ -578,7 +578,7 @@ func Lutimes(path string, tv []Timeval) error {
|
||||
return UtimesNanoAt(AT_FDCWD, path, ts, AT_SYMLINK_NOFOLLOW)
|
||||
}
|
||||
|
||||
// emptyIovec reports whether there are no bytes in the slice of Iovec.
|
||||
// emptyIovecs reports whether there are no bytes in the slice of Iovec.
|
||||
func emptyIovecs(iov []Iovec) bool {
|
||||
for i := range iov {
|
||||
if iov[i].Len > 0 {
|
||||
|
2
vendor/golang.org/x/sys/unix/timestruct.go
generated
vendored
2
vendor/golang.org/x/sys/unix/timestruct.go
generated
vendored
@ -9,7 +9,7 @@ package unix
|
||||
|
||||
import "time"
|
||||
|
||||
// TimespecToNSec returns the time stored in ts as nanoseconds.
|
||||
// TimespecToNsec returns the time stored in ts as nanoseconds.
|
||||
func TimespecToNsec(ts Timespec) int64 { return ts.Nano() }
|
||||
|
||||
// NsecToTimespec converts a number of nanoseconds into a Timespec.
|
||||
|
9
vendor/golang.org/x/sys/unix/xattr_bsd.go
generated
vendored
9
vendor/golang.org/x/sys/unix/xattr_bsd.go
generated
vendored
@ -36,9 +36,14 @@ func xattrnamespace(fullattr string) (ns int, attr string, err error) {
|
||||
func initxattrdest(dest []byte, idx int) (d unsafe.Pointer) {
|
||||
if len(dest) > idx {
|
||||
return unsafe.Pointer(&dest[idx])
|
||||
} else {
|
||||
return unsafe.Pointer(_zero)
|
||||
}
|
||||
if dest != nil {
|
||||
// extattr_get_file and extattr_list_file treat NULL differently from
|
||||
// a non-NULL pointer of length zero. Preserve the property of nilness,
|
||||
// even if we can't use dest directly.
|
||||
return unsafe.Pointer(&_zero)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FreeBSD and NetBSD implement their own syscalls to handle extended attributes
|
||||
|
30
vendor/golang.org/x/sys/unix/zerrors_linux.go
generated
vendored
30
vendor/golang.org/x/sys/unix/zerrors_linux.go
generated
vendored
@ -457,7 +457,6 @@ const (
|
||||
B600 = 0x8
|
||||
B75 = 0x2
|
||||
B9600 = 0xd
|
||||
BALLOON_KVM_MAGIC = 0x13661366
|
||||
BDEVFS_MAGIC = 0x62646576
|
||||
BINDERFS_SUPER_MAGIC = 0x6c6f6f70
|
||||
BINFMTFS_MAGIC = 0x42494e4d
|
||||
@ -563,6 +562,7 @@ const (
|
||||
BUS_USB = 0x3
|
||||
BUS_VIRTUAL = 0x6
|
||||
CAN_BCM = 0x2
|
||||
CAN_BUS_OFF_THRESHOLD = 0x100
|
||||
CAN_CTRLMODE_3_SAMPLES = 0x4
|
||||
CAN_CTRLMODE_BERR_REPORTING = 0x10
|
||||
CAN_CTRLMODE_CC_LEN8_DLC = 0x100
|
||||
@ -577,9 +577,12 @@ const (
|
||||
CAN_EFF_FLAG = 0x80000000
|
||||
CAN_EFF_ID_BITS = 0x1d
|
||||
CAN_EFF_MASK = 0x1fffffff
|
||||
CAN_ERROR_PASSIVE_THRESHOLD = 0x80
|
||||
CAN_ERROR_WARNING_THRESHOLD = 0x60
|
||||
CAN_ERR_ACK = 0x20
|
||||
CAN_ERR_BUSERROR = 0x80
|
||||
CAN_ERR_BUSOFF = 0x40
|
||||
CAN_ERR_CNT = 0x200
|
||||
CAN_ERR_CRTL = 0x4
|
||||
CAN_ERR_CRTL_ACTIVE = 0x40
|
||||
CAN_ERR_CRTL_RX_OVERFLOW = 0x1
|
||||
@ -820,9 +823,9 @@ const (
|
||||
DM_UUID_FLAG = 0x4000
|
||||
DM_UUID_LEN = 0x81
|
||||
DM_VERSION = 0xc138fd00
|
||||
DM_VERSION_EXTRA = "-ioctl (2022-02-22)"
|
||||
DM_VERSION_EXTRA = "-ioctl (2022-07-28)"
|
||||
DM_VERSION_MAJOR = 0x4
|
||||
DM_VERSION_MINOR = 0x2e
|
||||
DM_VERSION_MINOR = 0x2f
|
||||
DM_VERSION_PATCHLEVEL = 0x0
|
||||
DT_BLK = 0x6
|
||||
DT_CHR = 0x2
|
||||
@ -1049,6 +1052,7 @@ const (
|
||||
ETH_P_CAIF = 0xf7
|
||||
ETH_P_CAN = 0xc
|
||||
ETH_P_CANFD = 0xd
|
||||
ETH_P_CANXL = 0xe
|
||||
ETH_P_CFM = 0x8902
|
||||
ETH_P_CONTROL = 0x16
|
||||
ETH_P_CUST = 0x6006
|
||||
@ -1060,6 +1064,7 @@ const (
|
||||
ETH_P_DNA_RT = 0x6003
|
||||
ETH_P_DSA = 0x1b
|
||||
ETH_P_DSA_8021Q = 0xdadb
|
||||
ETH_P_DSA_A5PSW = 0xe001
|
||||
ETH_P_ECONET = 0x18
|
||||
ETH_P_EDSA = 0xdada
|
||||
ETH_P_ERSPAN = 0x88be
|
||||
@ -1194,8 +1199,10 @@ const (
|
||||
FAN_MARK_EVICTABLE = 0x200
|
||||
FAN_MARK_FILESYSTEM = 0x100
|
||||
FAN_MARK_FLUSH = 0x80
|
||||
FAN_MARK_IGNORE = 0x400
|
||||
FAN_MARK_IGNORED_MASK = 0x20
|
||||
FAN_MARK_IGNORED_SURV_MODIFY = 0x40
|
||||
FAN_MARK_IGNORE_SURV = 0x440
|
||||
FAN_MARK_INODE = 0x0
|
||||
FAN_MARK_MOUNT = 0x10
|
||||
FAN_MARK_ONLYDIR = 0x8
|
||||
@ -1253,6 +1260,7 @@ const (
|
||||
FSCRYPT_MODE_AES_128_CBC = 0x5
|
||||
FSCRYPT_MODE_AES_128_CTS = 0x6
|
||||
FSCRYPT_MODE_AES_256_CTS = 0x4
|
||||
FSCRYPT_MODE_AES_256_HCTR2 = 0xa
|
||||
FSCRYPT_MODE_AES_256_XTS = 0x1
|
||||
FSCRYPT_POLICY_FLAGS_PAD_16 = 0x2
|
||||
FSCRYPT_POLICY_FLAGS_PAD_32 = 0x3
|
||||
@ -1430,6 +1438,7 @@ const (
|
||||
IFF_NOARP = 0x80
|
||||
IFF_NOFILTER = 0x1000
|
||||
IFF_NOTRAILERS = 0x20
|
||||
IFF_NO_CARRIER = 0x40
|
||||
IFF_NO_PI = 0x1000
|
||||
IFF_ONE_QUEUE = 0x2000
|
||||
IFF_PERSIST = 0x800
|
||||
@ -1805,6 +1814,7 @@ const (
|
||||
MADV_DONTDUMP = 0x10
|
||||
MADV_DONTFORK = 0xa
|
||||
MADV_DONTNEED = 0x4
|
||||
MADV_DONTNEED_LOCKED = 0x18
|
||||
MADV_FREE = 0x8
|
||||
MADV_HUGEPAGE = 0xe
|
||||
MADV_HWPOISON = 0x64
|
||||
@ -1846,7 +1856,7 @@ const (
|
||||
MFD_ALLOW_SEALING = 0x2
|
||||
MFD_CLOEXEC = 0x1
|
||||
MFD_HUGETLB = 0x4
|
||||
MFD_HUGE_16GB = -0x78000000
|
||||
MFD_HUGE_16GB = 0x88000000
|
||||
MFD_HUGE_16MB = 0x60000000
|
||||
MFD_HUGE_1GB = 0x78000000
|
||||
MFD_HUGE_1MB = 0x50000000
|
||||
@ -2212,6 +2222,11 @@ const (
|
||||
PERF_AUX_FLAG_PARTIAL = 0x4
|
||||
PERF_AUX_FLAG_PMU_FORMAT_TYPE_MASK = 0xff00
|
||||
PERF_AUX_FLAG_TRUNCATED = 0x1
|
||||
PERF_BR_ARM64_DEBUG_DATA = 0x7
|
||||
PERF_BR_ARM64_DEBUG_EXIT = 0x5
|
||||
PERF_BR_ARM64_DEBUG_HALT = 0x4
|
||||
PERF_BR_ARM64_DEBUG_INST = 0x6
|
||||
PERF_BR_ARM64_FIQ = 0x3
|
||||
PERF_FLAG_FD_CLOEXEC = 0x8
|
||||
PERF_FLAG_FD_NO_GROUP = 0x1
|
||||
PERF_FLAG_FD_OUTPUT = 0x2
|
||||
@ -2232,6 +2247,8 @@ const (
|
||||
PERF_MEM_LOCK_NA = 0x1
|
||||
PERF_MEM_LOCK_SHIFT = 0x18
|
||||
PERF_MEM_LVLNUM_ANY_CACHE = 0xb
|
||||
PERF_MEM_LVLNUM_CXL = 0x9
|
||||
PERF_MEM_LVLNUM_IO = 0xa
|
||||
PERF_MEM_LVLNUM_L1 = 0x1
|
||||
PERF_MEM_LVLNUM_L2 = 0x2
|
||||
PERF_MEM_LVLNUM_L3 = 0x3
|
||||
@ -2265,6 +2282,7 @@ const (
|
||||
PERF_MEM_REMOTE_REMOTE = 0x1
|
||||
PERF_MEM_REMOTE_SHIFT = 0x25
|
||||
PERF_MEM_SNOOPX_FWD = 0x1
|
||||
PERF_MEM_SNOOPX_PEER = 0x2
|
||||
PERF_MEM_SNOOPX_SHIFT = 0x26
|
||||
PERF_MEM_SNOOP_HIT = 0x4
|
||||
PERF_MEM_SNOOP_HITM = 0x10
|
||||
@ -2301,7 +2319,6 @@ const (
|
||||
PERF_SAMPLE_BRANCH_PLM_ALL = 0x7
|
||||
PERF_SAMPLE_WEIGHT_TYPE = 0x1004000
|
||||
PIPEFS_MAGIC = 0x50495045
|
||||
PPC_CMM_MAGIC = 0xc7571590
|
||||
PPPIOCGNPMODE = 0xc008744c
|
||||
PPPIOCNEWUNIT = 0xc004743e
|
||||
PRIO_PGRP = 0x1
|
||||
@ -2999,6 +3016,7 @@ const (
|
||||
STATX_BLOCKS = 0x400
|
||||
STATX_BTIME = 0x800
|
||||
STATX_CTIME = 0x80
|
||||
STATX_DIOALIGN = 0x2000
|
||||
STATX_GID = 0x10
|
||||
STATX_INO = 0x100
|
||||
STATX_MNT_ID = 0x1000
|
||||
@ -3392,9 +3410,7 @@ const (
|
||||
XDP_ZEROCOPY = 0x4
|
||||
XENFS_SUPER_MAGIC = 0xabba1974
|
||||
XFS_SUPER_MAGIC = 0x58465342
|
||||
Z3FOLD_MAGIC = 0x33
|
||||
ZONEFS_MAGIC = 0x5a4f4653
|
||||
ZSMALLOC_MAGIC = 0x58295829
|
||||
_HIDIOCGRAWNAME_LEN = 0x80
|
||||
_HIDIOCGRAWPHYS_LEN = 0x40
|
||||
_HIDIOCGRAWUNIQ_LEN = 0x40
|
||||
|
1
vendor/golang.org/x/sys/unix/zerrors_linux_386.go
generated
vendored
1
vendor/golang.org/x/sys/unix/zerrors_linux_386.go
generated
vendored
@ -133,6 +133,7 @@ const (
|
||||
MEMGETREGIONCOUNT = 0x80044d07
|
||||
MEMISLOCKED = 0x80084d17
|
||||
MEMLOCK = 0x40084d05
|
||||
MEMREAD = 0xc03c4d1a
|
||||
MEMREADOOB = 0xc00c4d04
|
||||
MEMSETBADBLOCK = 0x40084d0c
|
||||
MEMUNLOCK = 0x40084d06
|
||||
|
1
vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
generated
vendored
1
vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
generated
vendored
@ -133,6 +133,7 @@ const (
|
||||
MEMGETREGIONCOUNT = 0x80044d07
|
||||
MEMISLOCKED = 0x80084d17
|
||||
MEMLOCK = 0x40084d05
|
||||
MEMREAD = 0xc0404d1a
|
||||
MEMREADOOB = 0xc0104d04
|
||||
MEMSETBADBLOCK = 0x40084d0c
|
||||
MEMUNLOCK = 0x40084d06
|
||||
|
1
vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
generated
vendored
1
vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
generated
vendored
@ -131,6 +131,7 @@ const (
|
||||
MEMGETREGIONCOUNT = 0x80044d07
|
||||
MEMISLOCKED = 0x80084d17
|
||||
MEMLOCK = 0x40084d05
|
||||
MEMREAD = 0xc0404d1a
|
||||
MEMREADOOB = 0xc00c4d04
|
||||
MEMSETBADBLOCK = 0x40084d0c
|
||||
MEMUNLOCK = 0x40084d06
|
||||
|
1
vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
generated
vendored
1
vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
generated
vendored
@ -134,6 +134,7 @@ const (
|
||||
MEMGETREGIONCOUNT = 0x80044d07
|
||||
MEMISLOCKED = 0x80084d17
|
||||
MEMLOCK = 0x40084d05
|
||||
MEMREAD = 0xc0404d1a
|
||||
MEMREADOOB = 0xc0104d04
|
||||
MEMSETBADBLOCK = 0x40084d0c
|
||||
MEMUNLOCK = 0x40084d06
|
||||
|
1
vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go
generated
vendored
1
vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go
generated
vendored
@ -132,6 +132,7 @@ const (
|
||||
MEMGETREGIONCOUNT = 0x80044d07
|
||||
MEMISLOCKED = 0x80084d17
|
||||
MEMLOCK = 0x40084d05
|
||||
MEMREAD = 0xc0404d1a
|
||||
MEMREADOOB = 0xc0104d04
|
||||
MEMSETBADBLOCK = 0x40084d0c
|
||||
MEMUNLOCK = 0x40084d06
|
||||
|
1
vendor/golang.org/x/sys/unix/zerrors_linux_mips.go
generated
vendored
1
vendor/golang.org/x/sys/unix/zerrors_linux_mips.go
generated
vendored
@ -131,6 +131,7 @@ const (
|
||||
MEMGETREGIONCOUNT = 0x40044d07
|
||||
MEMISLOCKED = 0x40084d17
|
||||
MEMLOCK = 0x80084d05
|
||||
MEMREAD = 0xc0404d1a
|
||||
MEMREADOOB = 0xc00c4d04
|
||||
MEMSETBADBLOCK = 0x80084d0c
|
||||
MEMUNLOCK = 0x80084d06
|
||||
|
1
vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
generated
vendored
1
vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
generated
vendored
@ -131,6 +131,7 @@ const (
|
||||
MEMGETREGIONCOUNT = 0x40044d07
|
||||
MEMISLOCKED = 0x40084d17
|
||||
MEMLOCK = 0x80084d05
|
||||
MEMREAD = 0xc0404d1a
|
||||
MEMREADOOB = 0xc0104d04
|
||||
MEMSETBADBLOCK = 0x80084d0c
|
||||
MEMUNLOCK = 0x80084d06
|
||||
|
1
vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
generated
vendored
1
vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
generated
vendored
@ -131,6 +131,7 @@ const (
|
||||
MEMGETREGIONCOUNT = 0x40044d07
|
||||
MEMISLOCKED = 0x40084d17
|
||||
MEMLOCK = 0x80084d05
|
||||
MEMREAD = 0xc0404d1a
|
||||
MEMREADOOB = 0xc0104d04
|
||||
MEMSETBADBLOCK = 0x80084d0c
|
||||
MEMUNLOCK = 0x80084d06
|
||||
|
1
vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go
generated
vendored
1
vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go
generated
vendored
@ -131,6 +131,7 @@ const (
|
||||
MEMGETREGIONCOUNT = 0x40044d07
|
||||
MEMISLOCKED = 0x40084d17
|
||||
MEMLOCK = 0x80084d05
|
||||
MEMREAD = 0xc0404d1a
|
||||
MEMREADOOB = 0xc00c4d04
|
||||
MEMSETBADBLOCK = 0x80084d0c
|
||||
MEMUNLOCK = 0x80084d06
|
||||
|
1
vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go
generated
vendored
1
vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go
generated
vendored
@ -131,6 +131,7 @@ const (
|
||||
MEMGETREGIONCOUNT = 0x40044d07
|
||||
MEMISLOCKED = 0x40084d17
|
||||
MEMLOCK = 0x80084d05
|
||||
MEMREAD = 0xc0404d1a
|
||||
MEMREADOOB = 0xc00c4d04
|
||||
MEMSETBADBLOCK = 0x80084d0c
|
||||
MEMUNLOCK = 0x80084d06
|
||||
|
1
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
generated
vendored
1
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
generated
vendored
@ -131,6 +131,7 @@ const (
|
||||
MEMGETREGIONCOUNT = 0x40044d07
|
||||
MEMISLOCKED = 0x40084d17
|
||||
MEMLOCK = 0x80084d05
|
||||
MEMREAD = 0xc0404d1a
|
||||
MEMREADOOB = 0xc0104d04
|
||||
MEMSETBADBLOCK = 0x80084d0c
|
||||
MEMUNLOCK = 0x80084d06
|
||||
|
1
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
generated
vendored
1
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
generated
vendored
@ -131,6 +131,7 @@ const (
|
||||
MEMGETREGIONCOUNT = 0x40044d07
|
||||
MEMISLOCKED = 0x40084d17
|
||||
MEMLOCK = 0x80084d05
|
||||
MEMREAD = 0xc0404d1a
|
||||
MEMREADOOB = 0xc0104d04
|
||||
MEMSETBADBLOCK = 0x80084d0c
|
||||
MEMUNLOCK = 0x80084d06
|
||||
|
1
vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go
generated
vendored
1
vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go
generated
vendored
@ -131,6 +131,7 @@ const (
|
||||
MEMGETREGIONCOUNT = 0x80044d07
|
||||
MEMISLOCKED = 0x80084d17
|
||||
MEMLOCK = 0x40084d05
|
||||
MEMREAD = 0xc0404d1a
|
||||
MEMREADOOB = 0xc0104d04
|
||||
MEMSETBADBLOCK = 0x40084d0c
|
||||
MEMUNLOCK = 0x40084d06
|
||||
|
1
vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
generated
vendored
1
vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
generated
vendored
@ -131,6 +131,7 @@ const (
|
||||
MEMGETREGIONCOUNT = 0x80044d07
|
||||
MEMISLOCKED = 0x80084d17
|
||||
MEMLOCK = 0x40084d05
|
||||
MEMREAD = 0xc0404d1a
|
||||
MEMREADOOB = 0xc0104d04
|
||||
MEMSETBADBLOCK = 0x40084d0c
|
||||
MEMUNLOCK = 0x40084d06
|
||||
|
1
vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go
generated
vendored
1
vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go
generated
vendored
@ -136,6 +136,7 @@ const (
|
||||
MEMGETREGIONCOUNT = 0x40044d07
|
||||
MEMISLOCKED = 0x40084d17
|
||||
MEMLOCK = 0x80084d05
|
||||
MEMREAD = 0xc0404d1a
|
||||
MEMREADOOB = 0xc0104d04
|
||||
MEMSETBADBLOCK = 0x80084d0c
|
||||
MEMUNLOCK = 0x80084d06
|
||||
|
11
vendor/golang.org/x/sys/unix/zsyscall_linux.go
generated
vendored
11
vendor/golang.org/x/sys/unix/zsyscall_linux.go
generated
vendored
@ -537,6 +537,17 @@ func Chroot(path string) (err error) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func ClockAdjtime(clockid int32, buf *Timex) (state int, err error) {
|
||||
r0, _, e1 := Syscall(SYS_CLOCK_ADJTIME, uintptr(clockid), uintptr(unsafe.Pointer(buf)), 0)
|
||||
state = int(r0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func ClockGetres(clockid int32, res *Timespec) (err error) {
|
||||
_, _, e1 := Syscall(SYS_CLOCK_GETRES, uintptr(clockid), uintptr(unsafe.Pointer(res)), 0)
|
||||
if e1 != 0 {
|
||||
|
217
vendor/golang.org/x/sys/unix/ztypes_linux.go
generated
vendored
217
vendor/golang.org/x/sys/unix/ztypes_linux.go
generated
vendored
@ -29,6 +29,41 @@ type Itimerval struct {
|
||||
Value Timeval
|
||||
}
|
||||
|
||||
const (
|
||||
ADJ_OFFSET = 0x1
|
||||
ADJ_FREQUENCY = 0x2
|
||||
ADJ_MAXERROR = 0x4
|
||||
ADJ_ESTERROR = 0x8
|
||||
ADJ_STATUS = 0x10
|
||||
ADJ_TIMECONST = 0x20
|
||||
ADJ_TAI = 0x80
|
||||
ADJ_SETOFFSET = 0x100
|
||||
ADJ_MICRO = 0x1000
|
||||
ADJ_NANO = 0x2000
|
||||
ADJ_TICK = 0x4000
|
||||
ADJ_OFFSET_SINGLESHOT = 0x8001
|
||||
ADJ_OFFSET_SS_READ = 0xa001
|
||||
)
|
||||
|
||||
const (
|
||||
STA_PLL = 0x1
|
||||
STA_PPSFREQ = 0x2
|
||||
STA_PPSTIME = 0x4
|
||||
STA_FLL = 0x8
|
||||
STA_INS = 0x10
|
||||
STA_DEL = 0x20
|
||||
STA_UNSYNC = 0x40
|
||||
STA_FREQHOLD = 0x80
|
||||
STA_PPSSIGNAL = 0x100
|
||||
STA_PPSJITTER = 0x200
|
||||
STA_PPSWANDER = 0x400
|
||||
STA_PPSERROR = 0x800
|
||||
STA_CLOCKERR = 0x1000
|
||||
STA_NANO = 0x2000
|
||||
STA_MODE = 0x4000
|
||||
STA_CLK = 0x8000
|
||||
)
|
||||
|
||||
const (
|
||||
TIME_OK = 0x0
|
||||
TIME_INS = 0x1
|
||||
@ -53,29 +88,30 @@ type StatxTimestamp struct {
|
||||
}
|
||||
|
||||
type Statx_t struct {
|
||||
Mask uint32
|
||||
Blksize uint32
|
||||
Attributes uint64
|
||||
Nlink uint32
|
||||
Uid uint32
|
||||
Gid uint32
|
||||
Mode uint16
|
||||
_ [1]uint16
|
||||
Ino uint64
|
||||
Size uint64
|
||||
Blocks uint64
|
||||
Attributes_mask uint64
|
||||
Atime StatxTimestamp
|
||||
Btime StatxTimestamp
|
||||
Ctime StatxTimestamp
|
||||
Mtime StatxTimestamp
|
||||
Rdev_major uint32
|
||||
Rdev_minor uint32
|
||||
Dev_major uint32
|
||||
Dev_minor uint32
|
||||
Mnt_id uint64
|
||||
_ uint64
|
||||
_ [12]uint64
|
||||
Mask uint32
|
||||
Blksize uint32
|
||||
Attributes uint64
|
||||
Nlink uint32
|
||||
Uid uint32
|
||||
Gid uint32
|
||||
Mode uint16
|
||||
_ [1]uint16
|
||||
Ino uint64
|
||||
Size uint64
|
||||
Blocks uint64
|
||||
Attributes_mask uint64
|
||||
Atime StatxTimestamp
|
||||
Btime StatxTimestamp
|
||||
Ctime StatxTimestamp
|
||||
Mtime StatxTimestamp
|
||||
Rdev_major uint32
|
||||
Rdev_minor uint32
|
||||
Dev_major uint32
|
||||
Dev_minor uint32
|
||||
Mnt_id uint64
|
||||
Dio_mem_align uint32
|
||||
Dio_offset_align uint32
|
||||
_ [12]uint64
|
||||
}
|
||||
|
||||
type Fsid struct {
|
||||
@ -1099,7 +1135,8 @@ const (
|
||||
PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT = 0xf
|
||||
PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT = 0x10
|
||||
PERF_SAMPLE_BRANCH_HW_INDEX_SHIFT = 0x11
|
||||
PERF_SAMPLE_BRANCH_MAX_SHIFT = 0x12
|
||||
PERF_SAMPLE_BRANCH_PRIV_SAVE_SHIFT = 0x12
|
||||
PERF_SAMPLE_BRANCH_MAX_SHIFT = 0x13
|
||||
PERF_SAMPLE_BRANCH_USER = 0x1
|
||||
PERF_SAMPLE_BRANCH_KERNEL = 0x2
|
||||
PERF_SAMPLE_BRANCH_HV = 0x4
|
||||
@ -1118,7 +1155,8 @@ const (
|
||||
PERF_SAMPLE_BRANCH_NO_CYCLES = 0x8000
|
||||
PERF_SAMPLE_BRANCH_TYPE_SAVE = 0x10000
|
||||
PERF_SAMPLE_BRANCH_HW_INDEX = 0x20000
|
||||
PERF_SAMPLE_BRANCH_MAX = 0x40000
|
||||
PERF_SAMPLE_BRANCH_PRIV_SAVE = 0x40000
|
||||
PERF_SAMPLE_BRANCH_MAX = 0x80000
|
||||
PERF_BR_UNKNOWN = 0x0
|
||||
PERF_BR_COND = 0x1
|
||||
PERF_BR_UNCOND = 0x2
|
||||
@ -1132,7 +1170,10 @@ const (
|
||||
PERF_BR_COND_RET = 0xa
|
||||
PERF_BR_ERET = 0xb
|
||||
PERF_BR_IRQ = 0xc
|
||||
PERF_BR_MAX = 0xd
|
||||
PERF_BR_SERROR = 0xd
|
||||
PERF_BR_NO_TX = 0xe
|
||||
PERF_BR_EXTEND_ABI = 0xf
|
||||
PERF_BR_MAX = 0x10
|
||||
PERF_SAMPLE_REGS_ABI_NONE = 0x0
|
||||
PERF_SAMPLE_REGS_ABI_32 = 0x1
|
||||
PERF_SAMPLE_REGS_ABI_64 = 0x2
|
||||
@ -1151,7 +1192,8 @@ const (
|
||||
PERF_FORMAT_TOTAL_TIME_RUNNING = 0x2
|
||||
PERF_FORMAT_ID = 0x4
|
||||
PERF_FORMAT_GROUP = 0x8
|
||||
PERF_FORMAT_MAX = 0x10
|
||||
PERF_FORMAT_LOST = 0x10
|
||||
PERF_FORMAT_MAX = 0x20
|
||||
PERF_IOC_FLAG_GROUP = 0x1
|
||||
PERF_RECORD_MMAP = 0x1
|
||||
PERF_RECORD_LOST = 0x2
|
||||
@ -2979,7 +3021,16 @@ const (
|
||||
DEVLINK_CMD_TRAP_POLICER_NEW = 0x47
|
||||
DEVLINK_CMD_TRAP_POLICER_DEL = 0x48
|
||||
DEVLINK_CMD_HEALTH_REPORTER_TEST = 0x49
|
||||
DEVLINK_CMD_MAX = 0x51
|
||||
DEVLINK_CMD_RATE_GET = 0x4a
|
||||
DEVLINK_CMD_RATE_SET = 0x4b
|
||||
DEVLINK_CMD_RATE_NEW = 0x4c
|
||||
DEVLINK_CMD_RATE_DEL = 0x4d
|
||||
DEVLINK_CMD_LINECARD_GET = 0x4e
|
||||
DEVLINK_CMD_LINECARD_SET = 0x4f
|
||||
DEVLINK_CMD_LINECARD_NEW = 0x50
|
||||
DEVLINK_CMD_LINECARD_DEL = 0x51
|
||||
DEVLINK_CMD_SELFTESTS_GET = 0x52
|
||||
DEVLINK_CMD_MAX = 0x53
|
||||
DEVLINK_PORT_TYPE_NOTSET = 0x0
|
||||
DEVLINK_PORT_TYPE_AUTO = 0x1
|
||||
DEVLINK_PORT_TYPE_ETH = 0x2
|
||||
@ -3208,7 +3259,13 @@ const (
|
||||
DEVLINK_ATTR_RATE_NODE_NAME = 0xa8
|
||||
DEVLINK_ATTR_RATE_PARENT_NODE_NAME = 0xa9
|
||||
DEVLINK_ATTR_REGION_MAX_SNAPSHOTS = 0xaa
|
||||
DEVLINK_ATTR_MAX = 0xae
|
||||
DEVLINK_ATTR_LINECARD_INDEX = 0xab
|
||||
DEVLINK_ATTR_LINECARD_STATE = 0xac
|
||||
DEVLINK_ATTR_LINECARD_TYPE = 0xad
|
||||
DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES = 0xae
|
||||
DEVLINK_ATTR_NESTED_DEVLINK = 0xaf
|
||||
DEVLINK_ATTR_SELFTESTS = 0xb0
|
||||
DEVLINK_ATTR_MAX = 0xb0
|
||||
DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0
|
||||
DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1
|
||||
DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0
|
||||
@ -3317,7 +3374,8 @@ const (
|
||||
LWTUNNEL_ENCAP_SEG6_LOCAL = 0x7
|
||||
LWTUNNEL_ENCAP_RPL = 0x8
|
||||
LWTUNNEL_ENCAP_IOAM6 = 0x9
|
||||
LWTUNNEL_ENCAP_MAX = 0x9
|
||||
LWTUNNEL_ENCAP_XFRM = 0xa
|
||||
LWTUNNEL_ENCAP_MAX = 0xa
|
||||
|
||||
MPLS_IPTUNNEL_UNSPEC = 0x0
|
||||
MPLS_IPTUNNEL_DST = 0x1
|
||||
@ -3512,7 +3570,9 @@ const (
|
||||
ETHTOOL_MSG_PHC_VCLOCKS_GET = 0x21
|
||||
ETHTOOL_MSG_MODULE_GET = 0x22
|
||||
ETHTOOL_MSG_MODULE_SET = 0x23
|
||||
ETHTOOL_MSG_USER_MAX = 0x23
|
||||
ETHTOOL_MSG_PSE_GET = 0x24
|
||||
ETHTOOL_MSG_PSE_SET = 0x25
|
||||
ETHTOOL_MSG_USER_MAX = 0x25
|
||||
ETHTOOL_MSG_KERNEL_NONE = 0x0
|
||||
ETHTOOL_MSG_STRSET_GET_REPLY = 0x1
|
||||
ETHTOOL_MSG_LINKINFO_GET_REPLY = 0x2
|
||||
@ -3550,7 +3610,8 @@ const (
|
||||
ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY = 0x22
|
||||
ETHTOOL_MSG_MODULE_GET_REPLY = 0x23
|
||||
ETHTOOL_MSG_MODULE_NTF = 0x24
|
||||
ETHTOOL_MSG_KERNEL_MAX = 0x24
|
||||
ETHTOOL_MSG_PSE_GET_REPLY = 0x25
|
||||
ETHTOOL_MSG_KERNEL_MAX = 0x25
|
||||
ETHTOOL_A_HEADER_UNSPEC = 0x0
|
||||
ETHTOOL_A_HEADER_DEV_INDEX = 0x1
|
||||
ETHTOOL_A_HEADER_DEV_NAME = 0x2
|
||||
@ -3609,7 +3670,8 @@ const (
|
||||
ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG = 0x7
|
||||
ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE = 0x8
|
||||
ETHTOOL_A_LINKMODES_LANES = 0x9
|
||||
ETHTOOL_A_LINKMODES_MAX = 0x9
|
||||
ETHTOOL_A_LINKMODES_RATE_MATCHING = 0xa
|
||||
ETHTOOL_A_LINKMODES_MAX = 0xa
|
||||
ETHTOOL_A_LINKSTATE_UNSPEC = 0x0
|
||||
ETHTOOL_A_LINKSTATE_HEADER = 0x1
|
||||
ETHTOOL_A_LINKSTATE_LINK = 0x2
|
||||
@ -4201,6 +4263,9 @@ const (
|
||||
NL80211_ACL_POLICY_DENY_UNLESS_LISTED = 0x1
|
||||
NL80211_AC_VI = 0x1
|
||||
NL80211_AC_VO = 0x0
|
||||
NL80211_AP_SETTINGS_EXTERNAL_AUTH_SUPPORT = 0x1
|
||||
NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT = 0x2
|
||||
NL80211_AP_SME_SA_QUERY_OFFLOAD = 0x1
|
||||
NL80211_ATTR_4ADDR = 0x53
|
||||
NL80211_ATTR_ACK = 0x5c
|
||||
NL80211_ATTR_ACK_SIGNAL = 0x107
|
||||
@ -4209,6 +4274,7 @@ const (
|
||||
NL80211_ATTR_AIRTIME_WEIGHT = 0x112
|
||||
NL80211_ATTR_AKM_SUITES = 0x4c
|
||||
NL80211_ATTR_AP_ISOLATE = 0x60
|
||||
NL80211_ATTR_AP_SETTINGS_FLAGS = 0x135
|
||||
NL80211_ATTR_AUTH_DATA = 0x9c
|
||||
NL80211_ATTR_AUTH_TYPE = 0x35
|
||||
NL80211_ATTR_BANDS = 0xef
|
||||
@ -4240,6 +4306,9 @@ const (
|
||||
NL80211_ATTR_COALESCE_RULE_DELAY = 0x1
|
||||
NL80211_ATTR_COALESCE_RULE_MAX = 0x3
|
||||
NL80211_ATTR_COALESCE_RULE_PKT_PATTERN = 0x3
|
||||
NL80211_ATTR_COLOR_CHANGE_COLOR = 0x130
|
||||
NL80211_ATTR_COLOR_CHANGE_COUNT = 0x12f
|
||||
NL80211_ATTR_COLOR_CHANGE_ELEMS = 0x131
|
||||
NL80211_ATTR_CONN_FAILED_REASON = 0x9b
|
||||
NL80211_ATTR_CONTROL_PORT = 0x44
|
||||
NL80211_ATTR_CONTROL_PORT_ETHERTYPE = 0x66
|
||||
@ -4266,6 +4335,7 @@ const (
|
||||
NL80211_ATTR_DEVICE_AP_SME = 0x8d
|
||||
NL80211_ATTR_DFS_CAC_TIME = 0x7
|
||||
NL80211_ATTR_DFS_REGION = 0x92
|
||||
NL80211_ATTR_DISABLE_EHT = 0x137
|
||||
NL80211_ATTR_DISABLE_HE = 0x12d
|
||||
NL80211_ATTR_DISABLE_HT = 0x93
|
||||
NL80211_ATTR_DISABLE_VHT = 0xaf
|
||||
@ -4273,6 +4343,8 @@ const (
|
||||
NL80211_ATTR_DONT_WAIT_FOR_ACK = 0x8e
|
||||
NL80211_ATTR_DTIM_PERIOD = 0xd
|
||||
NL80211_ATTR_DURATION = 0x57
|
||||
NL80211_ATTR_EHT_CAPABILITY = 0x136
|
||||
NL80211_ATTR_EML_CAPABILITY = 0x13d
|
||||
NL80211_ATTR_EXT_CAPA = 0xa9
|
||||
NL80211_ATTR_EXT_CAPA_MASK = 0xaa
|
||||
NL80211_ATTR_EXTERNAL_AUTH_ACTION = 0x104
|
||||
@ -4337,10 +4409,11 @@ const (
|
||||
NL80211_ATTR_MAC_HINT = 0xc8
|
||||
NL80211_ATTR_MAC_MASK = 0xd7
|
||||
NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca
|
||||
NL80211_ATTR_MAX = 0x137
|
||||
NL80211_ATTR_MAX = 0x140
|
||||
NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4
|
||||
NL80211_ATTR_MAX_CSA_COUNTERS = 0xce
|
||||
NL80211_ATTR_MAX_MATCH_SETS = 0x85
|
||||
NL80211_ATTR_MAX_NUM_AKM_SUITES = 0x13c
|
||||
NL80211_ATTR_MAX_NUM_PMKIDS = 0x56
|
||||
NL80211_ATTR_MAX_NUM_SCAN_SSIDS = 0x2b
|
||||
NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS = 0xde
|
||||
@ -4350,6 +4423,8 @@ const (
|
||||
NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL = 0xdf
|
||||
NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS = 0xe0
|
||||
NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN = 0x7c
|
||||
NL80211_ATTR_MBSSID_CONFIG = 0x132
|
||||
NL80211_ATTR_MBSSID_ELEMS = 0x133
|
||||
NL80211_ATTR_MCAST_RATE = 0x6b
|
||||
NL80211_ATTR_MDID = 0xb1
|
||||
NL80211_ATTR_MEASUREMENT_DURATION = 0xeb
|
||||
@ -4359,6 +4434,11 @@ const (
|
||||
NL80211_ATTR_MESH_PEER_AID = 0xed
|
||||
NL80211_ATTR_MESH_SETUP = 0x70
|
||||
NL80211_ATTR_MGMT_SUBTYPE = 0x29
|
||||
NL80211_ATTR_MLD_ADDR = 0x13a
|
||||
NL80211_ATTR_MLD_CAPA_AND_OPS = 0x13e
|
||||
NL80211_ATTR_MLO_LINK_ID = 0x139
|
||||
NL80211_ATTR_MLO_LINKS = 0x138
|
||||
NL80211_ATTR_MLO_SUPPORT = 0x13b
|
||||
NL80211_ATTR_MNTR_FLAGS = 0x17
|
||||
NL80211_ATTR_MPATH_INFO = 0x1b
|
||||
NL80211_ATTR_MPATH_NEXT_HOP = 0x1a
|
||||
@ -4371,6 +4451,7 @@ const (
|
||||
NL80211_ATTR_NETNS_FD = 0xdb
|
||||
NL80211_ATTR_NOACK_MAP = 0x95
|
||||
NL80211_ATTR_NSS = 0x106
|
||||
NL80211_ATTR_OBSS_COLOR_BITMAP = 0x12e
|
||||
NL80211_ATTR_OFFCHANNEL_TX_OK = 0x6c
|
||||
NL80211_ATTR_OPER_CLASS = 0xd6
|
||||
NL80211_ATTR_OPMODE_NOTIF = 0xc2
|
||||
@ -4397,6 +4478,7 @@ const (
|
||||
NL80211_ATTR_PROTOCOL_FEATURES = 0xad
|
||||
NL80211_ATTR_PS_STATE = 0x5d
|
||||
NL80211_ATTR_QOS_MAP = 0xc7
|
||||
NL80211_ATTR_RADAR_BACKGROUND = 0x134
|
||||
NL80211_ATTR_RADAR_EVENT = 0xa8
|
||||
NL80211_ATTR_REASON_CODE = 0x36
|
||||
NL80211_ATTR_RECEIVE_MULTICAST = 0x121
|
||||
@ -4412,6 +4494,7 @@ const (
|
||||
NL80211_ATTR_RESP_IE = 0x4e
|
||||
NL80211_ATTR_ROAM_SUPPORT = 0x83
|
||||
NL80211_ATTR_RX_FRAME_TYPES = 0x64
|
||||
NL80211_ATTR_RX_HW_TIMESTAMP = 0x140
|
||||
NL80211_ATTR_RXMGMT_FLAGS = 0xbc
|
||||
NL80211_ATTR_RX_SIGNAL_DBM = 0x97
|
||||
NL80211_ATTR_S1G_CAPABILITY = 0x128
|
||||
@ -4484,6 +4567,7 @@ const (
|
||||
NL80211_ATTR_TSID = 0xd2
|
||||
NL80211_ATTR_TWT_RESPONDER = 0x116
|
||||
NL80211_ATTR_TX_FRAME_TYPES = 0x63
|
||||
NL80211_ATTR_TX_HW_TIMESTAMP = 0x13f
|
||||
NL80211_ATTR_TX_NO_CCK_RATE = 0x87
|
||||
NL80211_ATTR_TXQ_LIMIT = 0x10a
|
||||
NL80211_ATTR_TXQ_MEMORY_LIMIT = 0x10b
|
||||
@ -4557,6 +4641,10 @@ const (
|
||||
NL80211_BAND_ATTR_RATES = 0x2
|
||||
NL80211_BAND_ATTR_VHT_CAPA = 0x8
|
||||
NL80211_BAND_ATTR_VHT_MCS_SET = 0x7
|
||||
NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC = 0x8
|
||||
NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET = 0xa
|
||||
NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY = 0x9
|
||||
NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE = 0xb
|
||||
NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA = 0x6
|
||||
NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC = 0x2
|
||||
NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET = 0x4
|
||||
@ -4564,6 +4652,8 @@ const (
|
||||
NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE = 0x5
|
||||
NL80211_BAND_IFTYPE_ATTR_IFTYPES = 0x1
|
||||
NL80211_BAND_IFTYPE_ATTR_MAX = 0xb
|
||||
NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS = 0x7
|
||||
NL80211_BAND_LC = 0x5
|
||||
NL80211_BAND_S1GHZ = 0x4
|
||||
NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE = 0x2
|
||||
NL80211_BITRATE_ATTR_MAX = 0x2
|
||||
@ -4584,7 +4674,9 @@ const (
|
||||
NL80211_BSS_FREQUENCY_OFFSET = 0x14
|
||||
NL80211_BSS_INFORMATION_ELEMENTS = 0x6
|
||||
NL80211_BSS_LAST_SEEN_BOOTTIME = 0xf
|
||||
NL80211_BSS_MAX = 0x14
|
||||
NL80211_BSS_MAX = 0x16
|
||||
NL80211_BSS_MLD_ADDR = 0x16
|
||||
NL80211_BSS_MLO_LINK_ID = 0x15
|
||||
NL80211_BSS_PAD = 0x10
|
||||
NL80211_BSS_PARENT_BSSID = 0x12
|
||||
NL80211_BSS_PARENT_TSF = 0x11
|
||||
@ -4612,6 +4704,7 @@ const (
|
||||
NL80211_CHAN_WIDTH_20 = 0x1
|
||||
NL80211_CHAN_WIDTH_20_NOHT = 0x0
|
||||
NL80211_CHAN_WIDTH_2 = 0x9
|
||||
NL80211_CHAN_WIDTH_320 = 0xd
|
||||
NL80211_CHAN_WIDTH_40 = 0x2
|
||||
NL80211_CHAN_WIDTH_4 = 0xa
|
||||
NL80211_CHAN_WIDTH_5 = 0x6
|
||||
@ -4621,8 +4714,11 @@ const (
|
||||
NL80211_CMD_ABORT_SCAN = 0x72
|
||||
NL80211_CMD_ACTION = 0x3b
|
||||
NL80211_CMD_ACTION_TX_STATUS = 0x3c
|
||||
NL80211_CMD_ADD_LINK = 0x94
|
||||
NL80211_CMD_ADD_LINK_STA = 0x96
|
||||
NL80211_CMD_ADD_NAN_FUNCTION = 0x75
|
||||
NL80211_CMD_ADD_TX_TS = 0x69
|
||||
NL80211_CMD_ASSOC_COMEBACK = 0x93
|
||||
NL80211_CMD_ASSOCIATE = 0x26
|
||||
NL80211_CMD_AUTHENTICATE = 0x25
|
||||
NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL = 0x38
|
||||
@ -4630,6 +4726,10 @@ const (
|
||||
NL80211_CMD_CHANNEL_SWITCH = 0x66
|
||||
NL80211_CMD_CH_SWITCH_NOTIFY = 0x58
|
||||
NL80211_CMD_CH_SWITCH_STARTED_NOTIFY = 0x6e
|
||||
NL80211_CMD_COLOR_CHANGE_ABORTED = 0x90
|
||||
NL80211_CMD_COLOR_CHANGE_COMPLETED = 0x91
|
||||
NL80211_CMD_COLOR_CHANGE_REQUEST = 0x8e
|
||||
NL80211_CMD_COLOR_CHANGE_STARTED = 0x8f
|
||||
NL80211_CMD_CONNECT = 0x2e
|
||||
NL80211_CMD_CONN_FAILED = 0x5b
|
||||
NL80211_CMD_CONTROL_PORT_FRAME = 0x81
|
||||
@ -4678,8 +4778,9 @@ const (
|
||||
NL80211_CMD_LEAVE_IBSS = 0x2c
|
||||
NL80211_CMD_LEAVE_MESH = 0x45
|
||||
NL80211_CMD_LEAVE_OCB = 0x6d
|
||||
NL80211_CMD_MAX = 0x93
|
||||
NL80211_CMD_MAX = 0x98
|
||||
NL80211_CMD_MICHAEL_MIC_FAILURE = 0x29
|
||||
NL80211_CMD_MODIFY_LINK_STA = 0x97
|
||||
NL80211_CMD_NAN_MATCH = 0x78
|
||||
NL80211_CMD_NEW_BEACON = 0xf
|
||||
NL80211_CMD_NEW_INTERFACE = 0x7
|
||||
@ -4692,6 +4793,7 @@ const (
|
||||
NL80211_CMD_NEW_WIPHY = 0x3
|
||||
NL80211_CMD_NOTIFY_CQM = 0x40
|
||||
NL80211_CMD_NOTIFY_RADAR = 0x86
|
||||
NL80211_CMD_OBSS_COLOR_COLLISION = 0x8d
|
||||
NL80211_CMD_PEER_MEASUREMENT_COMPLETE = 0x85
|
||||
NL80211_CMD_PEER_MEASUREMENT_RESULT = 0x84
|
||||
NL80211_CMD_PEER_MEASUREMENT_START = 0x83
|
||||
@ -4707,6 +4809,8 @@ const (
|
||||
NL80211_CMD_REGISTER_FRAME = 0x3a
|
||||
NL80211_CMD_RELOAD_REGDB = 0x7e
|
||||
NL80211_CMD_REMAIN_ON_CHANNEL = 0x37
|
||||
NL80211_CMD_REMOVE_LINK = 0x95
|
||||
NL80211_CMD_REMOVE_LINK_STA = 0x98
|
||||
NL80211_CMD_REQ_SET_REG = 0x1b
|
||||
NL80211_CMD_ROAM = 0x2f
|
||||
NL80211_CMD_SCAN_ABORTED = 0x23
|
||||
@ -4717,6 +4821,7 @@ const (
|
||||
NL80211_CMD_SET_CHANNEL = 0x41
|
||||
NL80211_CMD_SET_COALESCE = 0x65
|
||||
NL80211_CMD_SET_CQM = 0x3f
|
||||
NL80211_CMD_SET_FILS_AAD = 0x92
|
||||
NL80211_CMD_SET_INTERFACE = 0x6
|
||||
NL80211_CMD_SET_KEY = 0xa
|
||||
NL80211_CMD_SET_MAC_ACL = 0x5d
|
||||
@ -4791,6 +4896,8 @@ const (
|
||||
NL80211_EDMG_BW_CONFIG_MIN = 0x4
|
||||
NL80211_EDMG_CHANNELS_MAX = 0x3c
|
||||
NL80211_EDMG_CHANNELS_MIN = 0x1
|
||||
NL80211_EHT_MAX_CAPABILITY_LEN = 0x33
|
||||
NL80211_EHT_MIN_CAPABILITY_LEN = 0xd
|
||||
NL80211_EXTERNAL_AUTH_ABORT = 0x1
|
||||
NL80211_EXTERNAL_AUTH_START = 0x0
|
||||
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK = 0x32
|
||||
@ -4807,6 +4914,7 @@ const (
|
||||
NL80211_EXT_FEATURE_BEACON_RATE_HT = 0x7
|
||||
NL80211_EXT_FEATURE_BEACON_RATE_LEGACY = 0x6
|
||||
NL80211_EXT_FEATURE_BEACON_RATE_VHT = 0x8
|
||||
NL80211_EXT_FEATURE_BSS_COLOR = 0x3a
|
||||
NL80211_EXT_FEATURE_BSS_PARENT_TSF = 0x4
|
||||
NL80211_EXT_FEATURE_CAN_REPLACE_PTK0 = 0x1f
|
||||
NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH = 0x2a
|
||||
@ -4818,6 +4926,7 @@ const (
|
||||
NL80211_EXT_FEATURE_DFS_OFFLOAD = 0x19
|
||||
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER = 0x20
|
||||
NL80211_EXT_FEATURE_EXT_KEY_ID = 0x24
|
||||
NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD = 0x3b
|
||||
NL80211_EXT_FEATURE_FILS_DISCOVERY = 0x34
|
||||
NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME = 0x11
|
||||
NL80211_EXT_FEATURE_FILS_SK_OFFLOAD = 0xe
|
||||
@ -4833,8 +4942,10 @@ const (
|
||||
NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION = 0x14
|
||||
NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE = 0x13
|
||||
NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION = 0x31
|
||||
NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE = 0x3d
|
||||
NL80211_EXT_FEATURE_PROTECTED_TWT = 0x2b
|
||||
NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE = 0x39
|
||||
NL80211_EXT_FEATURE_RADAR_BACKGROUND = 0x3c
|
||||
NL80211_EXT_FEATURE_RRM = 0x1
|
||||
NL80211_EXT_FEATURE_SAE_OFFLOAD_AP = 0x33
|
||||
NL80211_EXT_FEATURE_SAE_OFFLOAD = 0x26
|
||||
@ -4906,7 +5017,9 @@ const (
|
||||
NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11
|
||||
NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc
|
||||
NL80211_FREQUENCY_ATTR_NO_20MHZ = 0x10
|
||||
NL80211_FREQUENCY_ATTR_NO_320MHZ = 0x1a
|
||||
NL80211_FREQUENCY_ATTR_NO_80MHZ = 0xb
|
||||
NL80211_FREQUENCY_ATTR_NO_EHT = 0x1b
|
||||
NL80211_FREQUENCY_ATTR_NO_HE = 0x13
|
||||
NL80211_FREQUENCY_ATTR_NO_HT40_MINUS = 0x9
|
||||
NL80211_FREQUENCY_ATTR_NO_HT40_PLUS = 0xa
|
||||
@ -5006,6 +5119,12 @@ const (
|
||||
NL80211_MAX_SUPP_HT_RATES = 0x4d
|
||||
NL80211_MAX_SUPP_RATES = 0x20
|
||||
NL80211_MAX_SUPP_REG_RULES = 0x80
|
||||
NL80211_MBSSID_CONFIG_ATTR_EMA = 0x5
|
||||
NL80211_MBSSID_CONFIG_ATTR_INDEX = 0x3
|
||||
NL80211_MBSSID_CONFIG_ATTR_MAX = 0x5
|
||||
NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY = 0x2
|
||||
NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES = 0x1
|
||||
NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX = 0x4
|
||||
NL80211_MESHCONF_ATTR_MAX = 0x1f
|
||||
NL80211_MESHCONF_AUTO_OPEN_PLINKS = 0x7
|
||||
NL80211_MESHCONF_AWAKE_WINDOW = 0x1b
|
||||
@ -5168,6 +5287,7 @@ const (
|
||||
NL80211_PMSR_FTM_FAILURE_UNSPECIFIED = 0x0
|
||||
NL80211_PMSR_FTM_FAILURE_WRONG_CHANNEL = 0x3
|
||||
NL80211_PMSR_FTM_REQ_ATTR_ASAP = 0x1
|
||||
NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR = 0xd
|
||||
NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION = 0x5
|
||||
NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD = 0x4
|
||||
NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST = 0x6
|
||||
@ -5244,12 +5364,36 @@ const (
|
||||
NL80211_RADAR_PRE_CAC_EXPIRED = 0x4
|
||||
NL80211_RATE_INFO_10_MHZ_WIDTH = 0xb
|
||||
NL80211_RATE_INFO_160_MHZ_WIDTH = 0xa
|
||||
NL80211_RATE_INFO_320_MHZ_WIDTH = 0x12
|
||||
NL80211_RATE_INFO_40_MHZ_WIDTH = 0x3
|
||||
NL80211_RATE_INFO_5_MHZ_WIDTH = 0xc
|
||||
NL80211_RATE_INFO_80_MHZ_WIDTH = 0x8
|
||||
NL80211_RATE_INFO_80P80_MHZ_WIDTH = 0x9
|
||||
NL80211_RATE_INFO_BITRATE32 = 0x5
|
||||
NL80211_RATE_INFO_BITRATE = 0x1
|
||||
NL80211_RATE_INFO_EHT_GI_0_8 = 0x0
|
||||
NL80211_RATE_INFO_EHT_GI_1_6 = 0x1
|
||||
NL80211_RATE_INFO_EHT_GI_3_2 = 0x2
|
||||
NL80211_RATE_INFO_EHT_GI = 0x15
|
||||
NL80211_RATE_INFO_EHT_MCS = 0x13
|
||||
NL80211_RATE_INFO_EHT_NSS = 0x14
|
||||
NL80211_RATE_INFO_EHT_RU_ALLOC_106 = 0x3
|
||||
NL80211_RATE_INFO_EHT_RU_ALLOC_106P26 = 0x4
|
||||
NL80211_RATE_INFO_EHT_RU_ALLOC_242 = 0x5
|
||||
NL80211_RATE_INFO_EHT_RU_ALLOC_26 = 0x0
|
||||
NL80211_RATE_INFO_EHT_RU_ALLOC_2x996 = 0xb
|
||||
NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484 = 0xc
|
||||
NL80211_RATE_INFO_EHT_RU_ALLOC_3x996 = 0xd
|
||||
NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484 = 0xe
|
||||
NL80211_RATE_INFO_EHT_RU_ALLOC_484 = 0x6
|
||||
NL80211_RATE_INFO_EHT_RU_ALLOC_484P242 = 0x7
|
||||
NL80211_RATE_INFO_EHT_RU_ALLOC_4x996 = 0xf
|
||||
NL80211_RATE_INFO_EHT_RU_ALLOC_52 = 0x1
|
||||
NL80211_RATE_INFO_EHT_RU_ALLOC_52P26 = 0x2
|
||||
NL80211_RATE_INFO_EHT_RU_ALLOC_996 = 0x8
|
||||
NL80211_RATE_INFO_EHT_RU_ALLOC_996P484 = 0x9
|
||||
NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242 = 0xa
|
||||
NL80211_RATE_INFO_EHT_RU_ALLOC = 0x16
|
||||
NL80211_RATE_INFO_HE_1XLTF = 0x0
|
||||
NL80211_RATE_INFO_HE_2XLTF = 0x1
|
||||
NL80211_RATE_INFO_HE_4XLTF = 0x2
|
||||
@ -5292,6 +5436,7 @@ const (
|
||||
NL80211_RRF_GO_CONCURRENT = 0x1000
|
||||
NL80211_RRF_IR_CONCURRENT = 0x1000
|
||||
NL80211_RRF_NO_160MHZ = 0x10000
|
||||
NL80211_RRF_NO_320MHZ = 0x40000
|
||||
NL80211_RRF_NO_80MHZ = 0x8000
|
||||
NL80211_RRF_NO_CCK = 0x2
|
||||
NL80211_RRF_NO_HE = 0x20000
|
||||
|
14
vendor/golang.org/x/sys/windows/syscall_windows.go
generated
vendored
14
vendor/golang.org/x/sys/windows/syscall_windows.go
generated
vendored
@ -10,7 +10,6 @@ import (
|
||||
errorspkg "errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
@ -87,22 +86,13 @@ func StringToUTF16(s string) []uint16 {
|
||||
// s, with a terminating NUL added. If s contains a NUL byte at any
|
||||
// location, it returns (nil, syscall.EINVAL).
|
||||
func UTF16FromString(s string) ([]uint16, error) {
|
||||
if strings.IndexByte(s, 0) != -1 {
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
return utf16.Encode([]rune(s + "\x00")), nil
|
||||
return syscall.UTF16FromString(s)
|
||||
}
|
||||
|
||||
// UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s,
|
||||
// with a terminating NUL and any bytes after the NUL removed.
|
||||
func UTF16ToString(s []uint16) string {
|
||||
for i, v := range s {
|
||||
if v == 0 {
|
||||
s = s[:i]
|
||||
break
|
||||
}
|
||||
}
|
||||
return string(utf16.Decode(s))
|
||||
return syscall.UTF16ToString(s)
|
||||
}
|
||||
|
||||
// StringToUTF16Ptr is deprecated. Use UTF16PtrFromString instead.
|
||||
|
2
vendor/golang.org/x/text/internal/language/compact/language.go
generated
vendored
2
vendor/golang.org/x/text/internal/language/compact/language.go
generated
vendored
@ -118,7 +118,7 @@ func (t Tag) Parent() Tag {
|
||||
return Tag{language: lang, locale: lang}
|
||||
}
|
||||
|
||||
// returns token t and the rest of the string.
|
||||
// nextToken returns token t and the rest of the string.
|
||||
func nextToken(s string) (t, tail string) {
|
||||
p := strings.Index(s[1:], "-")
|
||||
if p == -1 {
|
||||
|
2
vendor/golang.org/x/text/internal/language/language.go
generated
vendored
2
vendor/golang.org/x/text/internal/language/language.go
generated
vendored
@ -409,7 +409,7 @@ func (t Tag) SetTypeForKey(key, value string) (Tag, error) {
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// findKeyAndType returns the start and end position for the type corresponding
|
||||
// findTypeForKey returns the start and end position for the type corresponding
|
||||
// to key or the point at which to insert the key-value pair if the type
|
||||
// wasn't found. The hasExt return value reports whether an -u extension was present.
|
||||
// Note: the extensions are typically very small and are likely to contain
|
||||
|
2
vendor/golang.org/x/text/language/language.go
generated
vendored
2
vendor/golang.org/x/text/language/language.go
generated
vendored
@ -344,7 +344,7 @@ func (t Tag) Parent() Tag {
|
||||
return Tag(compact.Tag(t).Parent())
|
||||
}
|
||||
|
||||
// returns token t and the rest of the string.
|
||||
// nextToken returns token t and the rest of the string.
|
||||
func nextToken(s string) (t, tail string) {
|
||||
p := strings.Index(s[1:], "-")
|
||||
if p == -1 {
|
||||
|
15
vendor/modules.txt
vendored
15
vendor/modules.txt
vendored
@ -35,6 +35,9 @@ github.com/Microsoft/hcsshim/osversion
|
||||
# github.com/alexflint/go-filemutex v1.2.0
|
||||
## explicit; go 1.13
|
||||
github.com/alexflint/go-filemutex
|
||||
# github.com/bits-and-blooms/bitset v1.2.0
|
||||
## explicit; go 1.14
|
||||
github.com/bits-and-blooms/bitset
|
||||
# github.com/buger/jsonparser v1.1.1
|
||||
## explicit; go 1.13
|
||||
github.com/buger/jsonparser
|
||||
@ -131,7 +134,7 @@ github.com/onsi/ginkgo/reporters/stenographer
|
||||
github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable
|
||||
github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty
|
||||
github.com/onsi/ginkgo/types
|
||||
# github.com/onsi/gomega v1.24.2
|
||||
# github.com/onsi/gomega v1.26.0
|
||||
## explicit; go 1.18
|
||||
github.com/onsi/gomega
|
||||
github.com/onsi/gomega/format
|
||||
@ -145,6 +148,10 @@ github.com/onsi/gomega/matchers/support/goraph/edge
|
||||
github.com/onsi/gomega/matchers/support/goraph/node
|
||||
github.com/onsi/gomega/matchers/support/goraph/util
|
||||
github.com/onsi/gomega/types
|
||||
# github.com/opencontainers/selinux v1.8.2
|
||||
## explicit; go 1.13
|
||||
github.com/opencontainers/selinux/go-selinux
|
||||
github.com/opencontainers/selinux/pkg/pwalk
|
||||
# github.com/pkg/errors v0.9.1
|
||||
## explicit
|
||||
github.com/pkg/errors
|
||||
@ -168,7 +175,7 @@ go.opencensus.io/internal
|
||||
go.opencensus.io/trace
|
||||
go.opencensus.io/trace/internal
|
||||
go.opencensus.io/trace/tracestate
|
||||
# golang.org/x/net v0.4.0
|
||||
# golang.org/x/net v0.7.0
|
||||
## explicit; go 1.17
|
||||
golang.org/x/net/bpf
|
||||
golang.org/x/net/html
|
||||
@ -177,13 +184,13 @@ golang.org/x/net/html/charset
|
||||
golang.org/x/net/internal/iana
|
||||
golang.org/x/net/internal/socket
|
||||
golang.org/x/net/ipv4
|
||||
# golang.org/x/sys v0.4.0
|
||||
# golang.org/x/sys v0.5.0
|
||||
## explicit; go 1.17
|
||||
golang.org/x/sys/internal/unsafeheader
|
||||
golang.org/x/sys/unix
|
||||
golang.org/x/sys/windows
|
||||
golang.org/x/sys/windows/registry
|
||||
# golang.org/x/text v0.5.0
|
||||
# golang.org/x/text v0.7.0
|
||||
## explicit; go 1.17
|
||||
golang.org/x/text/encoding
|
||||
golang.org/x/text/encoding/charmap
|
||||
|
Reference in New Issue
Block a user