diff --git a/README.md b/README.md index 2225f8e98..59c114d7c 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,9 @@ [![License](https://img.shields.io/badge/License-Apache_2.0-4EB1BA.svg)](https://opensource.org/licenses/Apache-2.0) -[![Slack](https://badgen.net/badge/Slack/Join/pink?icon=slack)](https://join.slack.com/t/koordinator-sh/shared_invite/zt-1756qoub4-Cn4~esfdlfAPsD7cwO2NzA) +[![codecov](https://codecov.io/github/koordinator-sh/koordinator/branch/main/graph/badge.svg?token=CPUKM09WJL)](https://codecov.io/github/koordinator-sh/koordinator) [![PRs Welcome](https://badgen.net/badge/PRs/Welcome/green?icon=https://api.iconify.design/octicon:git-pull-request.svg?color=white)](CONTRIBUTING.md) +[![Slack](https://badgen.net/badge/Slack/Join/4A154B?icon=slack)](https://join.slack.com/t/koordinator-sh/shared_invite/zt-1756qoub4-Cn4~esfdlfAPsD7cwO2NzA) ## Introduction diff --git a/go.mod b/go.mod index 44040d8b4..43e07dc08 100644 --- a/go.mod +++ b/go.mod @@ -11,12 +11,9 @@ require ( github.com/moby/moby v20.10.14+incompatible github.com/onsi/ginkgo v1.16.4 github.com/onsi/gomega v1.15.0 - github.com/prashantv/gostub v1.1.0 github.com/prometheus/client_golang v1.11.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.7.0 - github.com/vishvananda/netlink v1.1.0 - github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 go.uber.org/atomic v1.7.0 golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac google.golang.org/grpc v1.38.0 diff --git a/go.sum b/go.sum index b34b06c00..e3fd1ebf0 100644 --- a/go.sum +++ b/go.sum @@ -510,8 +510,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= -github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= @@ -605,12 +603,9 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= -github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= -github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= diff --git a/pkg/features/koordlet_features.go b/pkg/features/koordlet_features.go index 0d3d4d271..bf0ac8f79 100644 --- a/pkg/features/koordlet_features.go +++ b/pkg/features/koordlet_features.go @@ -28,6 +28,9 @@ const ( // AuditEventsHTTPHandler is used to get recent events from koordlet port AuditEventsHTTPHandler featuregate.Feature = "AuditEventsHTTPHandler" + // BECgroupReconcile sets cpu memory limit for best-effort pod + BECgroupReconcile featuregate.Feature = "BECgroupReconcile" + // BECPUSuppress suppresses for best-effort pod BECPUSuppress featuregate.Feature = "BECPUSuppress" @@ -46,6 +49,8 @@ var ( defaultKoordletFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{ AuditEvents: {Default: false, PreRelease: featuregate.Alpha}, AuditEventsHTTPHandler: {Default: false, PreRelease: featuregate.Alpha}, - BECPUSuppress: {Default: true, PreRelease: featuregate.Alpha}, + BECgroupReconcile: {Default: false, PreRelease: featuregate.Alpha}, + BECPUSuppress: {Default: false, PreRelease: featuregate.Alpha}, + BEMemoryEvict: {Default: false, PreRelease: featuregate.Alpha}, } ) diff --git a/pkg/koordlet/config/config.go b/pkg/koordlet/config/config.go index ffeb154f9..1bccc4d80 100644 --- a/pkg/koordlet/config/config.go +++ b/pkg/koordlet/config/config.go @@ -31,7 +31,7 @@ import ( "github.com/koordinator-sh/koordinator/pkg/koordlet/reporter" "github.com/koordinator-sh/koordinator/pkg/koordlet/resmanager" "github.com/koordinator-sh/koordinator/pkg/koordlet/statesinformer" - sysutil "github.com/koordinator-sh/koordinator/pkg/koordlet/util/system" + "github.com/koordinator-sh/koordinator/pkg/util/system" ) type Configuration struct { @@ -57,7 +57,7 @@ func NewConfiguration() *Configuration { } func (c *Configuration) InitFlags(fs *flag.FlagSet) { - sysutil.Conf.InitFlags(fs) + system.Conf.InitFlags(fs) c.StatesInformerConf.InitFlags(fs) c.ReporterConf.InitFlags(fs) c.CollectorConf.InitFlags(fs) diff --git a/pkg/koordlet/koordlet.go b/pkg/koordlet/koordlet.go index eaa09f975..539b27773 100644 --- a/pkg/koordlet/koordlet.go +++ b/pkg/koordlet/koordlet.go @@ -38,7 +38,7 @@ import ( "github.com/koordinator-sh/koordinator/pkg/koordlet/reporter" "github.com/koordinator-sh/koordinator/pkg/koordlet/resmanager" "github.com/koordinator-sh/koordinator/pkg/koordlet/statesinformer" - sysutil "github.com/koordinator-sh/koordinator/pkg/koordlet/util/system" + "github.com/koordinator-sh/koordinator/pkg/util/system" ) var ( @@ -70,20 +70,20 @@ func NewDaemon(config *config.Configuration) (Daemon, error) { klog.Infof("NODE_NAME is %v,start time %v", nodeName, float64(time.Now().Unix())) metrics.RecordKoordletStartTime(nodeName, float64(time.Now().Unix())) - klog.Infof("sysconf: %+v,agentMode:%v", sysutil.Conf, sysutil.AgentMode) - klog.Infof("kernel version INFO : %+v", sysutil.HostSystemInfo) + klog.Infof("sysconf: %+v,agentMode:%v", system.Conf, system.AgentMode) + klog.Infof("kernel version INFO : %+v", system.HostSystemInfo) // setup cgroup path formatter from cgroup driver type - var detectCgroupDriver sysutil.CgroupDriverType + var detectCgroupDriver system.CgroupDriverType if pollErr := wait.PollImmediate(time.Second*10, time.Minute, func() (bool, error) { - driver := sysutil.GuessCgroupDriverFromCgroupName() + driver := system.GuessCgroupDriverFromCgroupName() if driver.Validate() { detectCgroupDriver = driver return true, nil } klog.Infof("can not detect cgroup driver from 'kubepods' cgroup name") - if driver, err := sysutil.GuessCgroupDriverFromKubelet(); err == nil && driver.Validate() { + if driver, err := system.GuessCgroupDriverFromKubelet(); err == nil && driver.Validate() { detectCgroupDriver = driver return true, nil } else { @@ -93,13 +93,13 @@ func NewDaemon(config *config.Configuration) (Daemon, error) { }); pollErr != nil { return nil, fmt.Errorf("can not detect kubelet cgroup driver: %v", pollErr) } - sysutil.SetupCgroupPathFormatter(detectCgroupDriver) + system.SetupCgroupPathFormatter(detectCgroupDriver) klog.Infof("Node %s use '%s' as cgroup driver", nodeName, string(detectCgroupDriver)) kubeClient := clientset.NewForConfigOrDie(config.KubeRestConf) crdClient := clientsetbeta1.NewForConfigOrDie(config.KubeRestConf) - pleg, err := pleg.NewPLEG(sysutil.Conf.CgroupRootDir) + pleg, err := pleg.NewPLEG(system.Conf.CgroupRootDir) if err != nil { return nil, err } diff --git a/pkg/koordlet/metriccache/api.go b/pkg/koordlet/metriccache/api.go index 7aa41e0c8..a84b3bff6 100644 --- a/pkg/koordlet/metriccache/api.go +++ b/pkg/koordlet/metriccache/api.go @@ -19,7 +19,7 @@ package metriccache import ( "k8s.io/apimachinery/pkg/api/resource" - "github.com/koordinator-sh/koordinator/pkg/koordlet/util" + "github.com/koordinator-sh/koordinator/pkg/util" ) type CPUMetric struct { @@ -69,9 +69,9 @@ type ContainerResourceQueryResult struct { type NodeCPUInfo util.LocalCPUInfo type BECPUResourceMetric struct { - CPUUsed resource.Quantity //cpuUsed cores for BestEffort Cgroup - CPURealLimit resource.Quantity //suppressCPUQuantity: if suppress by cfs_quota then this value is cfs_quota/cfs_period - CPURequest resource.Quantity //sum(extendResources_Cpu:request) by all qos:BE pod + CPUUsed resource.Quantity // cpuUsed cores for BestEffort Cgroup + CPURealLimit resource.Quantity // suppressCPUQuantity: if suppress by cfs_quota then this value is cfs_quota/cfs_period + CPURequest resource.Quantity // sum(extendResources_Cpu:request) by all qos:BE pod } type BECPUResourceQueryResult struct { diff --git a/pkg/koordlet/metriccache/metric_cache_test.go b/pkg/koordlet/metriccache/metric_cache_test.go index 8e5d4e51c..381df72cc 100644 --- a/pkg/koordlet/metriccache/metric_cache_test.go +++ b/pkg/koordlet/metriccache/metric_cache_test.go @@ -23,7 +23,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" - "github.com/koordinator-sh/koordinator/pkg/koordlet/util" + "github.com/koordinator-sh/koordinator/pkg/util" ) func Test_metricCache_NodeResourceMetric_CRUD(t *testing.T) { diff --git a/pkg/koordlet/metricsadvisor/collector.go b/pkg/koordlet/metricsadvisor/collector.go index 35b01275c..5d4271f62 100644 --- a/pkg/koordlet/metricsadvisor/collector.go +++ b/pkg/koordlet/metricsadvisor/collector.go @@ -35,8 +35,8 @@ import ( "github.com/koordinator-sh/koordinator/pkg/koordlet/metriccache" "github.com/koordinator-sh/koordinator/pkg/koordlet/metrics" "github.com/koordinator-sh/koordinator/pkg/koordlet/statesinformer" - "github.com/koordinator-sh/koordinator/pkg/koordlet/util" - sysutil "github.com/koordinator-sh/koordinator/pkg/koordlet/util/system" + "github.com/koordinator-sh/koordinator/pkg/util" + "github.com/koordinator-sh/koordinator/pkg/util/system" ) const ( @@ -356,7 +356,7 @@ func (c *collector) collectPodThrottledInfo() { uid := string(pod.UID) // types.UID collectTime := time.Now() cgroupStatPath := util.GetPodCgroupCPUStatPath(meta.CgroupDir) - currentCPUStat, err := sysutil.GetCPUStatRaw(cgroupStatPath) + currentCPUStat, err := system.GetCPUStatRaw(cgroupStatPath) if err != nil || currentCPUStat == nil { if pod.Status.Phase == corev1.PodRunning { // print running pod collection error @@ -372,8 +372,8 @@ func (c *collector) collectPodThrottledInfo() { meta.Pod.Namespace, meta.Pod.Name, meta.Pod.UID) continue } - lastCPUThrottled := lastCPUThrottledValue.(*sysutil.CPUStatRaw) - cpuThrottledRatio := sysutil.CalcCPUThrottledRatio(currentCPUStat, lastCPUThrottled) + lastCPUThrottled := lastCPUThrottledValue.(*system.CPUStatRaw) + cpuThrottledRatio := system.CalcCPUThrottledRatio(currentCPUStat, lastCPUThrottled) klog.V(6).Infof("collect pod %s/%s, uid %s throttled finished, metric %v", meta.Pod.Namespace, meta.Pod.Name, meta.Pod.UID, cpuThrottledRatio) @@ -410,7 +410,7 @@ func (c *collector) collectContainerThrottledInfo(podMeta *statesinformer.PodMet pod.Namespace, pod.Name, containerStat.Name, err) continue } - currentCPUStat, err := sysutil.GetCPUStatRaw(containerCgroupPath) + currentCPUStat, err := system.GetCPUStatRaw(containerCgroupPath) if err != nil { klog.Infof("collect container %s/%s/%s cpu throttled failed, err %v, metric %v", pod.Namespace, pod.Name, containerStat.Name, err, currentCPUStat) @@ -423,8 +423,8 @@ func (c *collector) collectContainerThrottledInfo(podMeta *statesinformer.PodMet pod.Namespace, pod.Name, containerStat.Name) continue } - lastCPUThrottled := lastCPUThrottledValue.(*sysutil.CPUStatRaw) - cpuThrottledRatio := sysutil.CalcCPUThrottledRatio(currentCPUStat, lastCPUThrottled) + lastCPUThrottled := lastCPUThrottledValue.(*system.CPUStatRaw) + cpuThrottledRatio := system.CalcCPUThrottledRatio(currentCPUStat, lastCPUThrottled) containerMetric := &metriccache.ContainerThrottledMetric{ ContainerID: containerStat.ContainerID, diff --git a/pkg/koordlet/pleg/pleg.go b/pkg/koordlet/pleg/pleg.go index 70ceb7040..59265bc24 100644 --- a/pkg/koordlet/pleg/pleg.go +++ b/pkg/koordlet/pleg/pleg.go @@ -23,7 +23,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/klog/v2" - "github.com/koordinator-sh/koordinator/pkg/koordlet/util" + "github.com/koordinator-sh/koordinator/pkg/util" ) const ( diff --git a/pkg/koordlet/pleg/pleg_test.go b/pkg/koordlet/pleg/pleg_test.go index c15837519..b410f506a 100644 --- a/pkg/koordlet/pleg/pleg_test.go +++ b/pkg/koordlet/pleg/pleg_test.go @@ -23,7 +23,7 @@ import ( "github.com/stretchr/testify/assert" "k8s.io/utils/inotify" - sysutil "github.com/koordinator-sh/koordinator/pkg/koordlet/util/system" + "github.com/koordinator-sh/koordinator/pkg/util/system" ) func NewTestWatcher() (Watcher, error) { @@ -81,7 +81,7 @@ func (h *testHandler) OnContainerDeleted(podID, containerID string) { } func TestPlegHandlePodEvents(t *testing.T) { - sysutil.SetupCgroupPathFormatter(sysutil.Cgroupfs) + system.SetupCgroupPathFormatter(system.Cgroupfs) stopCh := make(chan struct{}) defer close(stopCh) @@ -152,7 +152,7 @@ func TestPlegHandlePodEvents(t *testing.T) { } func TestPlegHandleContainerEvents(t *testing.T) { - sysutil.SetupCgroupPathFormatter(sysutil.Cgroupfs) + system.SetupCgroupPathFormatter(system.Cgroupfs) stopCh := make(chan struct{}) defer close(stopCh) diff --git a/pkg/koordlet/resmanager/be_reconcile.go b/pkg/koordlet/resmanager/be_reconcile.go new file mode 100644 index 000000000..8b080aae3 --- /dev/null +++ b/pkg/koordlet/resmanager/be_reconcile.go @@ -0,0 +1,361 @@ +/* + Copyright 2022 The Koordinator 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 resmanager + +import ( + "io/ioutil" + "strconv" + + corev1 "k8s.io/api/core/v1" + "k8s.io/klog/v2" + + "github.com/koordinator-sh/koordinator/apis/extension" + "github.com/koordinator-sh/koordinator/apis/slo/v1alpha1" + "github.com/koordinator-sh/koordinator/pkg/koordlet/audit" + "github.com/koordinator-sh/koordinator/pkg/koordlet/statesinformer" + "github.com/koordinator-sh/koordinator/pkg/util" + "github.com/koordinator-sh/koordinator/pkg/util/system" +) + +func (r *resmanager) reconcileBECgroup() { + nodeSLO := r.getNodeSLOCopy() + podsMeta := r.statesInformer.GetAllPods() + for _, podMeta := range podsMeta { + if extension.GetPodQoSClass(podMeta.Pod) != extension.QoSBE { + continue + } + if getCPUSuppressPolicy(nodeSLO) != v1alpha1.CPUCfsQuotaPolicy { + reconcileBECPULimit(podMeta) + } + reconcileBECPUShare(podMeta) + reconcileBEMemLimit(podMeta) + } +} + +func reconcileBECPULimit(podMeta *statesinformer.PodMeta) { + needReconcilePod, err := needReconcilePodBECPULimit(podMeta) + if err != nil { + klog.Warningf("failed to check need reconcile cpu limit for pod %v/%v %v, error: %v", + podMeta.Pod.Namespace, podMeta.Pod.Name, podMeta.Pod.UID, err) + return + } + if needReconcilePod { + err = applyPodBECPULimitIfSpecified(podMeta) + if err != nil { + klog.Warningf("failed to apply cpu limit for pod %v/%v %v, error: %v", + podMeta.Pod.Namespace, podMeta.Pod.Name, podMeta.Pod.UID, err) + } else { + curCFS, err := util.GetPodCurCFSQuota(podMeta.CgroupDir) + klog.Infof("apply cpu limit for pod %v/%v %v succeed, current value %d, error: %v", + podMeta.Pod.Namespace, podMeta.Pod.Name, podMeta.Pod.UID, curCFS, err) + } + } + + containerMap := make(map[string]*corev1.Container, len(podMeta.Pod.Spec.Containers)) + for i := range podMeta.Pod.Spec.Containers { + container := &podMeta.Pod.Spec.Containers[i] + containerMap[container.Name] = container + } + + for _, containerStat := range podMeta.Pod.Status.ContainerStatuses { + container, exist := containerMap[containerStat.Name] + if !exist { + klog.Warningf("container %v/%v/%v lost during cpu limit reconcile", + podMeta.Pod.Namespace, podMeta.Pod.Name, containerStat.Name) + continue + } + needReconcileContainer, err := needReconcileContainerBECPULimit(podMeta, container, &containerStat) + if err != nil { + klog.Warningf("failed to check need reconcile cpu limit for container %v/%v/%v, error: %v", + podMeta.Pod.Namespace, podMeta.Pod.Name, containerStat.Name, err) + continue + } + if !needReconcileContainer { + continue + } + + if err := applyContainerBECPULimitIfSpecified(podMeta, container, &containerStat); err != nil { + klog.Warningf("failed to apply cpu limit for container %v/%v/%v, error: %v", + podMeta.Pod.Namespace, podMeta.Pod.Name, containerStat.Name, err) + } else { + curCFS, err := util.GetContainerCurCFSQuota(podMeta.CgroupDir, &containerStat) + klog.Infof("apply cpu limit for container %v/%v %v succeed, current value %v, error: %v", + podMeta.Pod.Namespace, podMeta.Pod.Name, podMeta.Pod.UID, curCFS, err) + } + } +} + +func reconcileBECPUShare(podMeta *statesinformer.PodMeta) { + needReconcilePod, err := needReconcilePodBECPUShare(podMeta) + if err != nil { + klog.Warningf("failed to check need reconcile cpu request for pod %v/%v %v, error: %v", + podMeta.Pod.Namespace, podMeta.Pod.Name, podMeta.Pod.UID, err) + return + } + if needReconcilePod { + err = applyPodBECPURequestIfSpecified(podMeta) + if err != nil { + klog.Warningf("failed to apply cpu request for pod %v/%v %v, error: %v", + podMeta.Pod.Namespace, podMeta.Pod.Name, podMeta.Pod.UID, err) + } else { + curShare, err := util.GetPodCurCPUShare(podMeta.CgroupDir) + klog.Infof("apply cpu request for pod %v/%v %v succeed, current value %d, error: %v", + podMeta.Pod.Namespace, podMeta.Pod.Name, podMeta.Pod.UID, curShare, err) + } + } + + containerMap := make(map[string]*corev1.Container, len(podMeta.Pod.Spec.Containers)) + for i := range podMeta.Pod.Spec.Containers { + container := &podMeta.Pod.Spec.Containers[i] + containerMap[container.Name] = container + } + for _, containerStat := range podMeta.Pod.Status.ContainerStatuses { + // reconcile containers + container, exist := containerMap[containerStat.Name] + if !exist { + klog.Warningf("container %v/%v/%v lost during reconcile cpu request", + podMeta.Pod.Namespace, podMeta.Pod.Name, containerStat.Name) + continue + } + needReconcileContainer, err := needReconcileContainerBECPUShare(podMeta, container, &containerStat) + if err != nil { + klog.Warningf("failed to check need reconcile cpu request for container %v/%v/%v, error: %v", + podMeta.Pod.Namespace, podMeta.Pod.Name, containerStat.Name, err) + continue + } + if !needReconcileContainer { + continue + } + err = applyContainerBECPUShareIfSpecified(podMeta, container, &containerStat) + if err != nil { + klog.Warningf("failed to apply cpu request for container %v/%v/%v, error: %v", + podMeta.Pod.Namespace, podMeta.Pod.Name, containerStat.Name, err) + } else { + curShare, err := util.GetContainerCurCPUShare(podMeta.CgroupDir, &containerStat) + klog.Infof("apply cpu request for pod %v/%v %v succeed, current value %d, error: %v", + podMeta.Pod.Namespace, podMeta.Pod.Name, containerStat.Name, curShare, err) + } + } +} + +func reconcileBEMemLimit(podMeta *statesinformer.PodMeta) { + needReconcilePod, err := needReconcilePodBEMemLimit(podMeta) + if err != nil { + klog.Warningf("failed to check need reconcile memory limit for pod %v/%v %v, error: %v", + podMeta.Pod.Namespace, podMeta.Pod.Name, podMeta.Pod.UID, err) + return + } + if needReconcilePod { + err = applyPodBEMemLimitIfSpecified(podMeta) + if err != nil { + klog.Warningf("failed to apply cpu memory for pod %v/%v %v, error: %v", + podMeta.Pod.Namespace, podMeta.Pod.Name, podMeta.Pod.UID, err) + } else { + curLimit, err := util.GetPodCurMemLimitBytes(podMeta.CgroupDir) + klog.Infof("apply cpu memory for pod %v/%v %v succeed, current value %d, error: %v", + podMeta.Pod.Namespace, podMeta.Pod.Name, podMeta.Pod.UID, curLimit, err) + } + } + + containerMap := make(map[string]*corev1.Container, len(podMeta.Pod.Spec.Containers)) + for i := range podMeta.Pod.Spec.Containers { + container := &podMeta.Pod.Spec.Containers[i] + containerMap[container.Name] = container + } + + for _, containerStat := range podMeta.Pod.Status.ContainerStatuses { + container, exist := containerMap[containerStat.Name] + if !exist { + klog.Warningf("container %v/%v/%v lost during memory limit reconcile", + podMeta.Pod.Namespace, podMeta.Pod.Name, containerStat.Name) + continue + } + needReconcileContainer, err := needReconcileContainerBEMemLimit(podMeta, container, &containerStat) + if err != nil { + klog.Warningf("failed to check need reconcile memory limit for container %v/%v/%v, error: %v", + podMeta.Pod.Namespace, podMeta.Pod.Name, containerStat.Name, err) + continue + } + if !needReconcileContainer { + continue + } + + if err := applyContainerBEMemLimitIfSpecified(podMeta, container, &containerStat); err != nil { + klog.Warningf("failed to apply memory limit for container %v/%v/%v, error: %v", + podMeta.Pod.Namespace, podMeta.Pod.Name, containerStat.Name, err) + } else { + curLimit, err := util.GetContainerCurMemLimitBytes(podMeta.CgroupDir, &containerStat) + klog.Infof("apply memory limit for container %v/%v %v succeed, current value %v, error: %v", + podMeta.Pod.Namespace, podMeta.Pod.Name, podMeta.Pod.UID, curLimit, err) + } + } +} + +func needReconcilePodBECPULimit(podMeta *statesinformer.PodMeta) (bool, error) { + if util.GetPodBEMilliCPULimit(podMeta.Pod) <= 0 { + return false, nil + } + + podCurCFSQuota, err := util.GetPodCurCFSQuota(podMeta.CgroupDir) + if err != nil { + return false, err + } + return podCurCFSQuota == system.CFSQuotaUnlimitedValue, nil +} + +func needReconcileContainerBECPULimit(podMeta *statesinformer.PodMeta, container *corev1.Container, containerStatus *corev1.ContainerStatus) (bool, error) { + if util.GetContainerBEMilliCPULimit(container) <= 0 { + return false, nil + } + + containerCurCFSQuota, err := util.GetContainerCurCFSQuota(podMeta.CgroupDir, containerStatus) + if err != nil { + return false, err + } + return containerCurCFSQuota == system.CFSQuotaUnlimitedValue, nil +} + +func needReconcilePodBECPUShare(podMeta *statesinformer.PodMeta) (bool, error) { + if util.GetPodBEMilliCPURequest(podMeta.Pod) <= 0 { + return false, nil + } + + podCurCPUShare, err := util.GetPodCurCPUShare(podMeta.CgroupDir) + if err != nil { + return false, err + } + return podCurCPUShare == system.CPUShareKubeBEValue, nil +} + +func needReconcileContainerBECPUShare(podMeta *statesinformer.PodMeta, container *corev1.Container, containerStatus *corev1.ContainerStatus) (bool, error) { + if util.GetContainerBEMilliCPURequest(container) <= 0 { + return false, nil + } + + containerCurCPUShare, err := util.GetContainerCurCPUShare(podMeta.CgroupDir, containerStatus) + if err != nil { + return false, err + } + return containerCurCPUShare == system.CPUShareKubeBEValue, nil +} + +func needReconcilePodBEMemLimit(podMeta *statesinformer.PodMeta) (bool, error) { + if util.GetPodBEMemoryByteLimit(podMeta.Pod) <= 0 { + return false, nil + } + + podCurMemLimit, err := util.GetPodCurMemLimitBytes(podMeta.CgroupDir) + if err != nil { + return false, err + } + // by default 9223372036854771712 , use 1024TB = 1024 * 1024 * 1024 * 1024 * 1024 for compatibility + return podCurMemLimit > 1024*1024*1024*1024*1024, nil +} + +func needReconcileContainerBEMemLimit(podMeta *statesinformer.PodMeta, container *corev1.Container, containerStatus *corev1.ContainerStatus) (bool, error) { + if util.GetContainerBEMemoryByteLimit(container) <= 0 { + return false, nil + } + + containerCurCFSQuota, err := util.GetContainerCurMemLimitBytes(podMeta.CgroupDir, containerStatus) + if err != nil { + return false, err + } + // by default 9223372036854771712 , use 1024TB = 1024 * 1024 * 1024 * 1024 * 1024 for compatibility + return containerCurCFSQuota > 1024*1024*1024*1024*1024, nil +} + +func applyPodBECPULimitIfSpecified(podMeta *statesinformer.PodMeta) error { + milliCPULimit := util.GetPodBEMilliCPULimit(podMeta.Pod) + if milliCPULimit <= 0 { + return nil + } + podCFSPeriod, err := util.GetPodCurCFSPeriod(podMeta.CgroupDir) + if err != nil { + return err + } + targetCFSQuota := int(float64(milliCPULimit*podCFSPeriod) / float64(1000)) + podCFSQuotaPath := util.GetPodCgroupCFSQuotaPath(podMeta.CgroupDir) + _ = audit.V(2).Pod(podMeta.Pod.Namespace, podMeta.Pod.Name).Reason(updateCPU).Message("set cfs_quota to %v", targetCFSQuota).Do() + return ioutil.WriteFile(podCFSQuotaPath, []byte(strconv.Itoa(targetCFSQuota)), 0644) +} + +func applyContainerBECPULimitIfSpecified(podMeta *statesinformer.PodMeta, container *corev1.Container, containerStatus *corev1.ContainerStatus) error { + milliCPULimit := util.GetContainerBEMilliCPULimit(container) + if milliCPULimit <= 0 { + return nil + } + containerCFSPeriod, err := util.GetContainerCurCFSPeriod(podMeta.CgroupDir, containerStatus) + if err != nil { + return err + } + targetCFSQuota := int(float64(milliCPULimit*containerCFSPeriod) / float64(1000)) + containerCFSQuotaPath, err := util.GetContainerCgroupCFSQuotaPath(podMeta.CgroupDir, containerStatus) + if err != nil { + return err + } + _ = audit.V(2).Pod(podMeta.Pod.Namespace, podMeta.Pod.Name).Container(container.Name).Reason(updateCPU).Message("set cfs_quota to %v", targetCFSQuota).Do() + return ioutil.WriteFile(containerCFSQuotaPath, []byte(strconv.Itoa(targetCFSQuota)), 0644) +} + +func applyPodBECPURequestIfSpecified(podMeta *statesinformer.PodMeta) error { + milliCPURequest := util.GetPodBEMilliCPURequest(podMeta.Pod) + if milliCPURequest <= 0 { + return nil + } + targetCPUShare := int(float64(milliCPURequest*system.CPUShareUnitValue) / float64(1000)) + podDir := util.GetPodCgroupDirWithKube(podMeta.CgroupDir) + _ = audit.V(2).Pod(podMeta.Pod.Namespace, podMeta.Pod.Name).Reason(updateCPU).Message("set cfs_shares to %v", targetCPUShare).Do() + return system.CgroupFileWrite(podDir, system.CPUShares, strconv.Itoa(targetCPUShare)) +} + +func applyContainerBECPUShareIfSpecified(podMeta *statesinformer.PodMeta, container *corev1.Container, containerStatus *corev1.ContainerStatus) error { + milliCPURequest := util.GetContainerBEMilliCPURequest(container) + if milliCPURequest <= 0 { + return nil + } + targetCPUShare := int(float64(milliCPURequest*system.CPUShareUnitValue) / float64(1000)) + containerCPUSharePath, err := util.GetContainerCgroupCPUSharePath(podMeta.CgroupDir, containerStatus) + if err != nil { + return err + } + _ = audit.V(2).Pod(podMeta.Pod.Namespace, podMeta.Pod.Name).Container(container.Name).Reason(updateCPU).Message("set cfs_shares to %v", targetCPUShare).Do() + return ioutil.WriteFile(containerCPUSharePath, []byte(strconv.Itoa(targetCPUShare)), 0644) +} + +func applyPodBEMemLimitIfSpecified(podMeta *statesinformer.PodMeta) error { + memoryLimit := util.GetPodBEMemoryByteLimit(podMeta.Pod) + if memoryLimit <= 0 { + return nil + } + podMemLimitPath := util.GetPodCgroupMemLimitPath(podMeta.CgroupDir) + _ = audit.V(2).Pod(podMeta.Pod.Namespace, podMeta.Pod.Name).Reason(updateMemory).Message("set memory.limits to %v", memoryLimit).Do() + return ioutil.WriteFile(podMemLimitPath, []byte(strconv.Itoa(int(memoryLimit))), 0644) +} + +func applyContainerBEMemLimitIfSpecified(podMeta *statesinformer.PodMeta, container *corev1.Container, containerStatus *corev1.ContainerStatus) error { + memoryLimit := util.GetContainerBEMemoryByteLimit(container) + if memoryLimit <= 0 { + return nil + } + containerMemLimitPath, err := util.GetContainerCgroupMemLimitPath(podMeta.CgroupDir, containerStatus) + if err != nil { + return err + } + _ = audit.V(2).Pod(podMeta.Pod.Namespace, podMeta.Pod.Name).Container(container.Name).Reason(updateMemory).Message("set memory.limits to %v", memoryLimit).Do() + return ioutil.WriteFile(containerMemLimitPath, []byte(strconv.Itoa(int(memoryLimit))), 0644) +} diff --git a/pkg/koordlet/resmanager/be_reconcile_test.go b/pkg/koordlet/resmanager/be_reconcile_test.go new file mode 100644 index 000000000..790989e9b --- /dev/null +++ b/pkg/koordlet/resmanager/be_reconcile_test.go @@ -0,0 +1,484 @@ +/* + Copyright 2022 The Koordinator 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 resmanager + +import ( + "bufio" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "syscall" + "testing" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/koordinator-sh/koordinator/apis/extension" + "github.com/koordinator-sh/koordinator/pkg/koordlet/statesinformer" + "github.com/koordinator-sh/koordinator/pkg/util" + "github.com/koordinator-sh/koordinator/pkg/util/system" +) + +const ( + defaultCFSPeriod = 100000 + defaultMemUnlimit = 9223372036854771712 +) + +func writeCgroupForTest(file string, data string) error { + if _, err := os.Create(file); err != nil { + return err + } + f, err := os.OpenFile(file, os.O_RDWR|syscall.O_NONBLOCK, 0644) + if err != nil { + return err + } + defer f.Close() + + _ = f.Sync() + w := bufio.NewWriter(f) + _, err = w.WriteString(data) + _ = w.Flush() + return err +} + +func initTestPodCFS(podMeta *statesinformer.PodMeta, podCurCFS int64, containerCurCFS map[string]int64) error { + podCFSQuotaPath := util.GetPodCgroupCFSQuotaPath(podMeta.CgroupDir) + podCFSPeriodPath := util.GetPodCgroupCFSPeriodPath(podMeta.CgroupDir) + podCFSDir := filepath.Dir(podCFSQuotaPath) + if err := os.MkdirAll(podCFSDir, 0755); err != nil { + return err + } + if err := writeCgroupForTest(podCFSPeriodPath, strconv.FormatInt(defaultCFSPeriod, 10)); err != nil { + return err + } + if err := writeCgroupForTest(podCFSQuotaPath, strconv.FormatInt(podCurCFS, 10)); err != nil { + return err + } + for _, containerStat := range podMeta.Pod.Status.ContainerStatuses { + if containerCFS, ok := containerCurCFS[containerStat.Name]; ok { + containerCFSQuotaPath, err := util.GetContainerCgroupCFSQuotaPath(podMeta.CgroupDir, &containerStat) + if err != nil { + return err + } + containerCFSPeriodPath, err := util.GetContainerCgroupCFSPeriodPath(podMeta.CgroupDir, &containerStat) + if err != nil { + return err + } + containerCFSDir := filepath.Dir(containerCFSQuotaPath) + if err := os.MkdirAll(containerCFSDir, 0755); err != nil { + return err + } + err = writeCgroupForTest(containerCFSPeriodPath, strconv.FormatInt(defaultCFSPeriod, 10)) + if err != nil { + return err + } + err = writeCgroupForTest(containerCFSQuotaPath, strconv.FormatInt(containerCFS, 10)) + if err != nil { + return err + } + } + } + return nil +} + +func initTestPodCPUShare(podMeta *statesinformer.PodMeta, podCurCPUShare int64, containerCurCPUShare map[string]int64) error { + podCPUSharePath := util.GetPodCgroupCPUSharePath(podMeta.CgroupDir) + podCPUShareDir := filepath.Dir(podCPUSharePath) + if err := os.MkdirAll(podCPUShareDir, 0755); err != nil { + return err + } + if err := writeCgroupForTest(podCPUSharePath, strconv.FormatInt(podCurCPUShare, 10)); err != nil { + return err + } + for _, containerStat := range podMeta.Pod.Status.ContainerStatuses { + if containerCPUShare, ok := containerCurCPUShare[containerStat.Name]; ok { + containerCPUSharePath, err := util.GetContainerCgroupCPUSharePath(podMeta.CgroupDir, &containerStat) + if err != nil { + return err + } + containerCPUShareDir := filepath.Dir(containerCPUSharePath) + if err := os.MkdirAll(containerCPUShareDir, 0755); err != nil { + return err + } + err = writeCgroupForTest(containerCPUSharePath, strconv.FormatInt(containerCPUShare, 10)) + if err != nil { + return err + } + } + } + return nil +} + +func initTestPodMemLimit(podMeta *statesinformer.PodMeta, podCurMemLimit int64, containerCurMemLimit map[string]int64) error { + podMemLimitPath := util.GetPodCgroupMemLimitPath(podMeta.CgroupDir) + podMemLimitDir := filepath.Dir(podMemLimitPath) + if err := os.MkdirAll(podMemLimitDir, 0755); err != nil { + return err + } + if err := writeCgroupForTest(podMemLimitPath, strconv.FormatInt(podCurMemLimit, 10)); err != nil { + return err + } + for _, containerStat := range podMeta.Pod.Status.ContainerStatuses { + if containerMemLimit, ok := containerCurMemLimit[containerStat.Name]; ok { + containerMemLimitPath, err := util.GetContainerCgroupMemLimitPath(podMeta.CgroupDir, &containerStat) + if err != nil { + return err + } + containerMemLimitDir := filepath.Dir(containerMemLimitPath) + if err := os.MkdirAll(containerMemLimitDir, 0755); err != nil { + return err + } + err = writeCgroupForTest(containerMemLimitPath, strconv.FormatInt(containerMemLimit, 10)) + if err != nil { + return err + } + } + } + return nil +} + +func Test_reconcileBECPULimit(t *testing.T) { + type args struct { + podMeta *statesinformer.PodMeta + podCurCFS int64 + containerCurCFS map[string]int64 + wantPodCFSQuota int64 + wantContainerCFSQuota map[string]int64 + } + tests := []struct { + name string + args args + }{ + { + name: "set-be-cpu-limit", + args: args{ + podMeta: &statesinformer.PodMeta{ + Pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-ns", + Name: "test-name", + UID: "test-pod-uid", + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "test-container-1", + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + extension.BatchCPU: *resource.NewQuantity(500, resource.DecimalSI), + }, + Requests: corev1.ResourceList{ + extension.BatchCPU: *resource.NewQuantity(500, resource.DecimalSI), + }, + }, + }, + { + Name: "test-container-2", + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + extension.BatchCPU: *resource.NewQuantity(1000, resource.DecimalSI), + }, + Requests: corev1.ResourceList{ + extension.BatchCPU: *resource.NewQuantity(1000, resource.DecimalSI), + }, + }, + }, + }, + }, + Status: corev1.PodStatus{ + ContainerStatuses: []corev1.ContainerStatus{ + { + Name: "test-container-1", + ContainerID: "docker://testcontainer1hashid", + }, + { + Name: "test-container-2", + ContainerID: "docker://testcontainer2hashid", + }, + }, + }, + }, + CgroupDir: "kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-podtest_pod_uid.slice", + }, + podCurCFS: -1, + containerCurCFS: map[string]int64{ + "test-container-1": -1, + "test-container-2": -1, + }, + wantPodCFSQuota: 150000, + wantContainerCFSQuota: map[string]int64{ + "test-container-1": 50000, + "test-container-2": 100000, + }, + }, + }, + } + for _, tt := range tests { + system.Conf = system.NewDsModeConfig() + system.Conf.CgroupRootDir, _ = ioutil.TempDir("/tmp", "koordlet-test") + err := initTestPodCFS(tt.args.podMeta, tt.args.podCurCFS, tt.args.containerCurCFS) + if err != nil { + t.Errorf("init cfs quota failed, error: %v", err) + } + t.Run(tt.name, func(t *testing.T) { + reconcileBECPULimit(tt.args.podMeta) + podCFSResult, err := util.GetPodCurCFSQuota(tt.args.podMeta.CgroupDir) + if err != nil { + t.Errorf("get pod cfs quota result failed, error %v", err) + } + if podCFSResult != tt.args.wantPodCFSQuota { + t.Errorf("pod cfs quota result not equal, want %v, got %v", tt.args.wantPodCFSQuota, podCFSResult) + } + for _, containerStat := range tt.args.podMeta.Pod.Status.ContainerStatuses { + containerCFSResult, err := util.GetContainerCurCFSQuota(tt.args.podMeta.CgroupDir, &containerStat) + if err != nil { + t.Errorf("get container %v cfs quota result failed, error %v", containerStat.Name, err) + } + wantContainerCFSquota, exist := tt.args.wantContainerCFSQuota[containerStat.Name] + if !exist { + t.Errorf("container %v want cfs quota not exist", containerStat.Name) + } + if containerCFSResult != wantContainerCFSquota { + t.Errorf("container %v cfs quota result not equal, want %v, got %v", + containerStat.Name, wantContainerCFSquota, containerCFSResult) + } + } + }) + } +} + +func Test_reconcileBECPUShare(t *testing.T) { + type args struct { + podMeta *statesinformer.PodMeta + podCurCPUShare int64 + containerCurCPUShare map[string]int64 + wantPodCPUShare int64 + wantContainerCPUShare map[string]int64 + } + tests := []struct { + name string + args args + }{ + { + name: "set-cpu-share", + args: args{ + podMeta: &statesinformer.PodMeta{ + Pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-ns", + Name: "test-name", + UID: "test-pod-uid", + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "test-container-1", + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + extension.BatchCPU: *resource.NewQuantity(500, resource.DecimalSI), + }, + Requests: corev1.ResourceList{ + extension.BatchCPU: *resource.NewQuantity(500, resource.DecimalSI), + }, + }, + }, + { + Name: "test-container-2", + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + extension.BatchCPU: *resource.NewQuantity(1000, resource.DecimalSI), + }, + Requests: corev1.ResourceList{ + extension.BatchCPU: *resource.NewQuantity(1000, resource.DecimalSI), + }, + }, + }, + }, + }, + Status: corev1.PodStatus{ + ContainerStatuses: []corev1.ContainerStatus{ + { + Name: "test-container-1", + ContainerID: "docker://testcontainer1hashid", + }, + { + Name: "test-container-2", + ContainerID: "docker://testcontainer2hashid", + }, + }, + }, + }, + CgroupDir: "kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-podtest_pod_uid.slice", + }, + podCurCPUShare: 2, + containerCurCPUShare: map[string]int64{ + "test-container-1": 2, + "test-container-2": 2, + }, + wantPodCPUShare: 1536, + wantContainerCPUShare: map[string]int64{ + "test-container-1": 512, + "test-container-2": 1024, + }, + }, + }, + } + for _, tt := range tests { + system.Conf = system.NewDsModeConfig() + system.Conf.CgroupRootDir, _ = ioutil.TempDir("/tmp", "koordlet-test") + err := initTestPodCPUShare(tt.args.podMeta, tt.args.podCurCPUShare, tt.args.containerCurCPUShare) + if err != nil { + t.Errorf("init cpu share failed, error: %v", err) + } + t.Run(tt.name, func(t *testing.T) { + reconcileBECPUShare(tt.args.podMeta) + podCPUShareResult, err := util.GetPodCurCPUShare(tt.args.podMeta.CgroupDir) + if err != nil { + t.Errorf("get pod cpu share result failed, error %v", err) + } + if podCPUShareResult != tt.args.wantPodCPUShare { + t.Errorf("pod cpu share result not equal, want %v, got %v", tt.args.wantPodCPUShare, podCPUShareResult) + } + for _, containerStat := range tt.args.podMeta.Pod.Status.ContainerStatuses { + containerCPUShareResult, err := util.GetContainerCurCPUShare(tt.args.podMeta.CgroupDir, &containerStat) + if err != nil { + t.Errorf("get container %v cpu share result failed, error %v", containerStat.Name, err) + } + wantContainerCPUShare, exist := tt.args.wantContainerCPUShare[containerStat.Name] + if !exist { + t.Errorf("container %v want cpu share quota not exist", containerStat.Name) + } + if containerCPUShareResult != wantContainerCPUShare { + t.Errorf("container %v cpu share result not equal, want %v, got %v", + containerStat.Name, wantContainerCPUShare, containerCPUShareResult) + } + } + }) + } +} + +func Test_reconcileBEMemLimit(t *testing.T) { + type args struct { + podMeta *statesinformer.PodMeta + podCurMemLimit int64 + containerCurMemLimit map[string]int64 + wantPodMemLimit int64 + wantContainerMemLimit map[string]int64 + } + tests := []struct { + name string + args args + }{ + { + name: "set-mem-limit", + args: args{ + podMeta: &statesinformer.PodMeta{ + Pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-ns", + Name: "test-name", + UID: "test-pod-uid", + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "test-container-1", + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + extension.BatchMemory: *resource.NewQuantity(512, resource.BinarySI), + }, + Requests: corev1.ResourceList{ + extension.BatchMemory: *resource.NewQuantity(512, resource.BinarySI), + }, + }, + }, + { + Name: "test-container-2", + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + extension.BatchMemory: *resource.NewQuantity(1024, resource.BinarySI), + }, + Requests: corev1.ResourceList{ + extension.BatchMemory: *resource.NewQuantity(1024, resource.BinarySI), + }, + }, + }, + }, + }, + Status: corev1.PodStatus{ + ContainerStatuses: []corev1.ContainerStatus{ + { + Name: "test-container-1", + ContainerID: "docker://testcontainer1hashid", + }, + { + Name: "test-container-2", + ContainerID: "docker://testcontainer2hashid", + }, + }, + }, + }, + CgroupDir: "kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-podtest_pod_uid.slice", + }, + podCurMemLimit: defaultMemUnlimit, + containerCurMemLimit: map[string]int64{ + "test-container-1": defaultMemUnlimit, + "test-container-2": defaultMemUnlimit, + }, + wantPodMemLimit: 1536, + wantContainerMemLimit: map[string]int64{ + "test-container-1": 512, + "test-container-2": 1024, + }, + }, + }, + } + for _, tt := range tests { + system.Conf = system.NewDsModeConfig() + system.Conf.CgroupRootDir, _ = ioutil.TempDir("/tmp", "koordlet-test") + err := initTestPodMemLimit(tt.args.podMeta, tt.args.podCurMemLimit, tt.args.containerCurMemLimit) + if err != nil { + t.Errorf("init cpu share failed, error: %v", err) + } + t.Run(tt.name, func(t *testing.T) { + reconcileBEMemLimit(tt.args.podMeta) + podMemLimitResult, err := util.GetPodCurMemLimitBytes(tt.args.podMeta.CgroupDir) + if err != nil { + t.Errorf("get pod mem limit result failed, error %v", err) + } + if podMemLimitResult != tt.args.wantPodMemLimit { + t.Errorf("pod mem limit result not equal, want %v, got %v", tt.args.wantPodMemLimit, podMemLimitResult) + } + for _, containerStat := range tt.args.podMeta.Pod.Status.ContainerStatuses { + containerMemLimitResult, err := util.GetContainerCurMemLimitBytes(tt.args.podMeta.CgroupDir, &containerStat) + if err != nil { + t.Errorf("get container %v mem limit result failed, error %v", containerStat.Name, err) + } + wantContainerMemLimit, exist := tt.args.wantContainerMemLimit[containerStat.Name] + if !exist { + t.Errorf("container %v want mem limit not exist", containerStat.Name) + } + if containerMemLimitResult != wantContainerMemLimit { + t.Errorf("container %v mem limit result not equal, want %v, got %v", + containerStat.Name, wantContainerMemLimit, containerMemLimitResult) + } + } + }) + } +} diff --git a/pkg/koordlet/resmanager/cpu_suppress.go b/pkg/koordlet/resmanager/cpu_suppress.go index 68a9796db..3a10de39e 100644 --- a/pkg/koordlet/resmanager/cpu_suppress.go +++ b/pkg/koordlet/resmanager/cpu_suppress.go @@ -35,8 +35,8 @@ import ( "github.com/koordinator-sh/koordinator/pkg/koordlet/metriccache" "github.com/koordinator-sh/koordinator/pkg/koordlet/metrics" "github.com/koordinator-sh/koordinator/pkg/koordlet/statesinformer" - koordletutil "github.com/koordinator-sh/koordinator/pkg/koordlet/util" - sysutil "github.com/koordinator-sh/koordinator/pkg/koordlet/util/system" + "github.com/koordinator-sh/koordinator/pkg/util" + "github.com/koordinator-sh/koordinator/pkg/util/system" ) var ( @@ -73,7 +73,7 @@ func getPodMetricCPUUsage(info *metriccache.PodResourceMetric) *resource.Quantit // getBECgroupCPUSetPathsRecursive gets all the be cpuset groups' paths recusively from upper to lower func getBECgroupCPUSetPathsRecursive() ([]string, error) { // walk from root path to lower nodes - rootCgroupPath := koordletutil.GetRootCgroupCPUSetDir(corev1.PodQOSBestEffort) + rootCgroupPath := util.GetRootCgroupCPUSetDir(corev1.PodQOSBestEffort) _, err := os.Stat(rootCgroupPath) if err != nil { // make sure the rootCgroupPath is available @@ -95,7 +95,7 @@ func getBECgroupCPUSetPathsRecursive() ([]string, error) { func writeBECgroupsCPUSet(paths []string, cpusetStr string, isReversed bool) { if isReversed { for i := len(paths) - 1; i >= 0; i-- { - err := koordletutil.WriteCgroupCPUSet(paths[i], cpusetStr) + err := util.WriteCgroupCPUSet(paths[i], cpusetStr) if err != nil { klog.Warningf("failed to write be cgroup cpuset: path %s, err %s", paths[i], err) } @@ -103,7 +103,7 @@ func writeBECgroupsCPUSet(paths []string, cpusetStr string, isReversed bool) { return } for i := range paths { - err := koordletutil.WriteCgroupCPUSet(paths[i], cpusetStr) + err := util.WriteCgroupCPUSet(paths[i], cpusetStr) if err != nil { klog.Warningf("failed to write be cgroup cpuset: path %s, err %s", paths[i], err) } @@ -131,7 +131,7 @@ func (r *CPUSuppress) calculateBESuppressCPU(node *corev1.Node, nodeMetric *metr if !ok { klog.Warningf("podMetric not included in the podMetas %v", podMetric.PodUID) } - if !ok || (apiext.GetPodQoSClass(podMeta.Pod) != apiext.QoSBE && koordletutil.GetKubeQosClass(podMeta.Pod) != corev1.PodQOSBestEffort) { + if !ok || (apiext.GetPodQoSClass(podMeta.Pod) != apiext.QoSBE && util.GetKubeQosClass(podMeta.Pod) != corev1.PodQOSBestEffort) { // NOTE: consider non-BE pods and podMeta-missing pods as LS podLSUsedCPU.Add(*getPodMetricCPUUsage(podMetric)) } @@ -190,7 +190,7 @@ func calculateBESuppressCPUSetPolicy(cpusetQuantity *resource.Quantity, oldCPUSe }) // getNodeIndex is a function to calculate an index for every numa node or socket - getNodeIndex := func(info koordletutil.ProcessorInfo) int32 { + getNodeIndex := func(info util.ProcessorInfo) int32 { return (info.NodeID + numProcessors) * (info.SocketID + 1) } @@ -270,14 +270,14 @@ func applyBESuppressCPUSetPolicy(cpuset []int32, oldCPUSet []int32) error { } // write a loose cpuset for all be cgroups before applying the real policy - mergedCPUSet := koordletutil.MergeCPUSet(oldCPUSet, cpuset) - mergedCPUSetStr := koordletutil.GenerateCPUSetStr(mergedCPUSet) + mergedCPUSet := util.MergeCPUSet(oldCPUSet, cpuset) + mergedCPUSetStr := util.GenerateCPUSetStr(mergedCPUSet) klog.V(6).Infof("applyBESuppressPolicy temporarily writes cpuset from upper cgroup to lower, cpuset %v", mergedCPUSet) writeBECgroupsCPUSet(cpusetCgroupPaths, mergedCPUSetStr, false) // apply the suppress policy from lower to upper - cpusetStr := koordletutil.GenerateCPUSetStr(cpuset) + cpusetStr := util.GenerateCPUSetStr(cpuset) klog.V(6).Infof("applyBESuppressPolicy writes suppressed cpuset from lower cgroup to upper, cpuset %v", cpuset) writeBECgroupsCPUSet(cpusetCgroupPaths, cpusetStr, true) @@ -346,7 +346,7 @@ func (r *CPUSuppress) suppressBECPU() { } func adjustByCPUSet(cpusetQuantity *resource.Quantity, nodeCPUInfo *metriccache.NodeCPUInfo) { - oldCPUSet, err := koordletutil.GetRootCgroupCurCPUSet(corev1.PodQOSBestEffort) + oldCPUSet, err := util.GetRootCgroupCurCPUSet(corev1.PodQOSBestEffort) if err != nil { klog.Warningf("applyBESuppressPolicy failed to get current best-effort cgroup cpuset, err: %s", err) return @@ -372,7 +372,7 @@ func (r *CPUSuppress) recoverCPUSetIfNeed() { return } - rootCPUSet, err := koordletutil.GetRootCgroupCurCPUSet(corev1.PodQOSGuaranteed) + rootCPUSet, err := util.GetRootCgroupCurCPUSet(corev1.PodQOSGuaranteed) if err != nil { klog.Warningf("recover bestEffort cpuset failed, get current root cgroup cpuset err: %s", err) return @@ -383,7 +383,7 @@ func (r *CPUSuppress) recoverCPUSetIfNeed() { return } - cpusetStr := koordletutil.GenerateCPUSetStr(rootCPUSet) + cpusetStr := util.GenerateCPUSetStr(rootCPUSet) klog.V(6).Infof("recover bestEffort cpuset, cpuset %v", rootCPUSet) writeBECgroupsCPUSet(cpusetCgroupPaths, cpusetStr, false) r.suppressPolicyStatuses[string(slov1alpha1.CPUSetPolicy)] = policyRecovered @@ -393,9 +393,9 @@ func adjustByCfsQuota(cpuQuantity *resource.Quantity, node *corev1.Node) { newBeQuota := cpuQuantity.MilliValue() * cfsPeriod / 1000 newBeQuota = int64(math.Max(float64(newBeQuota), float64(beMinQuota))) - beCgroupPath := koordletutil.GetKubeQosRelativePath(corev1.PodQOSBestEffort) + beCgroupPath := util.GetKubeQosRelativePath(corev1.PodQOSBestEffort) // read current offline quota - currentBeQuota, err := sysutil.CgroupFileReadInt(beCgroupPath, sysutil.CPUCFSQuota) + currentBeQuota, err := system.CgroupFileReadInt(beCgroupPath, system.CPUCFSQuota) if err != nil { klog.Warningf("suppressBECPU fail:get currentBeQuota fail,error: %v", err) return @@ -414,7 +414,7 @@ func adjustByCfsQuota(cpuQuantity *resource.Quantity, node *corev1.Node) { newBeQuota = *currentBeQuota + int64(beMaxIncreaseCPUQuota) } - if err := sysutil.CgroupFileWrite(beCgroupPath, sysutil.CPUCFSQuota, strconv.FormatInt(newBeQuota, 10)); err != nil { + if err := system.CgroupFileWrite(beCgroupPath, system.CPUCFSQuota, strconv.FormatInt(newBeQuota, 10)); err != nil { klog.Errorf("suppressBECPU: failed to write cfs_quota_us for offline pods, error: %v", err) return } @@ -429,10 +429,18 @@ func (r *CPUSuppress) recoverCFSQuotaIfNeed() { return } - beCgroupPath := koordletutil.GetKubeQosRelativePath(corev1.PodQOSBestEffort) - if err := sysutil.CgroupFileWrite(beCgroupPath, sysutil.CPUCFSQuota, "-1"); err != nil { + beCgroupPath := util.GetKubeQosRelativePath(corev1.PodQOSBestEffort) + if err := system.CgroupFileWrite(beCgroupPath, system.CPUCFSQuota, "-1"); err != nil { klog.Errorf("recover bestEffort cfsQuota error: %v", err) return } r.suppressPolicyStatuses[string(slov1alpha1.CPUCfsQuotaPolicy)] = policyRecovered } + +func getCPUSuppressPolicy(nodeSLO *slov1alpha1.NodeSLO) slov1alpha1.CPUSuppressPolicy { + if nodeSLO == nil || nodeSLO.Spec.ResourceUsedThresholdWithBE == nil || + nodeSLO.Spec.ResourceUsedThresholdWithBE.CPUSuppressPolicy == "" { + return util.DefaultResourceThresholdStrategy().CPUSuppressPolicy + } + return nodeSLO.Spec.ResourceUsedThresholdWithBE.CPUSuppressPolicy +} diff --git a/pkg/koordlet/resmanager/reason.go b/pkg/koordlet/resmanager/reason.go index 0abff2879..e5ae7dc40 100644 --- a/pkg/koordlet/resmanager/reason.go +++ b/pkg/koordlet/resmanager/reason.go @@ -17,6 +17,9 @@ limitations under the License. package resmanager const ( + updateCPU = "UpdateCPU" + updateMemory = "UpdateMemory" + adjustBEByNodeCPUUsage = "AdjustBEByNodeCPUUsage" evictPodByNodeMemoryUsage = "EvictPodByNodeMemoryUsage" diff --git a/pkg/koordlet/resmanager/resmanager.go b/pkg/koordlet/resmanager/resmanager.go index 1f1fa01dd..db48dcad7 100644 --- a/pkg/koordlet/resmanager/resmanager.go +++ b/pkg/koordlet/resmanager/resmanager.go @@ -45,7 +45,6 @@ import ( "github.com/koordinator-sh/koordinator/pkg/koordlet/metriccache" "github.com/koordinator-sh/koordinator/pkg/koordlet/metrics" "github.com/koordinator-sh/koordinator/pkg/koordlet/statesinformer" - koordletutil "github.com/koordinator-sh/koordinator/pkg/koordlet/util" "github.com/koordinator-sh/koordinator/pkg/runtime" "github.com/koordinator-sh/koordinator/pkg/util" ) @@ -253,11 +252,13 @@ func (r *resmanager) Run(stopCh <-chan struct{}) error { return fmt.Errorf("time out waiting for sync NodeSLO") } + util.RunFeature(r.reconcileBECgroup, []featuregate.Feature{features.BECgroupReconcile}, r.config.ReconcileIntervalSeconds, stopCh) + cpuSuppress := NewCPUSuppress(r) - koordletutil.RunFeature(cpuSuppress.suppressBECPU, []featuregate.Feature{features.BECPUSuppress}, r.config.CPUSuppressIntervalSeconds, stopCh) + util.RunFeature(cpuSuppress.suppressBECPU, []featuregate.Feature{features.BECPUSuppress}, r.config.CPUSuppressIntervalSeconds, stopCh) memoryEvictor := NewMemoryEvictor(r) - koordletutil.RunFeature(memoryEvictor.memoryEvict, []featuregate.Feature{features.BEMemoryEvict}, r.config.MemoryEvictIntervalSeconds, stopCh) + util.RunFeature(memoryEvictor.memoryEvict, []featuregate.Feature{features.BEMemoryEvict}, r.config.MemoryEvictIntervalSeconds, stopCh) klog.Info("Starting resmanager successfully") <-stopCh diff --git a/pkg/koordlet/statesinformer/kubelet_stub.go b/pkg/koordlet/statesinformer/kubelet_stub.go index e8990f768..de6d4553f 100644 --- a/pkg/koordlet/statesinformer/kubelet_stub.go +++ b/pkg/koordlet/statesinformer/kubelet_stub.go @@ -22,7 +22,7 @@ import ( corev1 "k8s.io/api/core/v1" - "github.com/koordinator-sh/koordinator/pkg/koordlet/util" + "github.com/koordinator-sh/koordinator/pkg/util" ) type KubeletStub interface { diff --git a/pkg/koordlet/statesinformer/states_informer.go b/pkg/koordlet/statesinformer/states_informer.go index 0a72ecebc..3aed8efad 100644 --- a/pkg/koordlet/statesinformer/states_informer.go +++ b/pkg/koordlet/statesinformer/states_informer.go @@ -36,7 +36,7 @@ import ( "github.com/koordinator-sh/koordinator/pkg/koordlet/metrics" "github.com/koordinator-sh/koordinator/pkg/koordlet/pleg" - "github.com/koordinator-sh/koordinator/pkg/koordlet/util" + "github.com/koordinator-sh/koordinator/pkg/util" ) type StatesInformer interface { diff --git a/pkg/koordlet/statesinformer/states_informer_test.go b/pkg/koordlet/statesinformer/states_informer_test.go index 00d2cc3cd..1cab843c7 100644 --- a/pkg/koordlet/statesinformer/states_informer_test.go +++ b/pkg/koordlet/statesinformer/states_informer_test.go @@ -24,12 +24,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/koordinator-sh/koordinator/pkg/koordlet/metrics" - sysutil "github.com/koordinator-sh/koordinator/pkg/koordlet/util/system" + "github.com/koordinator-sh/koordinator/pkg/util/system" ) func Test_genPodCgroupParentDirWithSystemdDriver(t *testing.T) { - sysutil.SetupCgroupPathFormatter(sysutil.Systemd) - defer sysutil.SetupCgroupPathFormatter(sysutil.Systemd) + system.SetupCgroupPathFormatter(system.Systemd) + defer system.SetupCgroupPathFormatter(system.Systemd) tests := []struct { name string args *corev1.Pod @@ -83,8 +83,8 @@ func Test_genPodCgroupParentDirWithSystemdDriver(t *testing.T) { } func Test_genPodCgroupParentDirWithCgroupfsDriver(t *testing.T) { - sysutil.SetupCgroupPathFormatter(sysutil.Cgroupfs) - defer sysutil.SetupCgroupPathFormatter(sysutil.Systemd) + system.SetupCgroupPathFormatter(system.Cgroupfs) + defer system.SetupCgroupPathFormatter(system.Systemd) tests := []struct { name string args *corev1.Pod diff --git a/pkg/koordlet/util/container.go b/pkg/koordlet/util/container.go deleted file mode 100644 index 4320d6ac3..000000000 --- a/pkg/koordlet/util/container.go +++ /dev/null @@ -1,234 +0,0 @@ -/* -Copyright 2022 The Koordinator 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 util - -import ( - "fmt" - "io/ioutil" - "path" - "strconv" - "strings" - - corev1 "k8s.io/api/core/v1" - - sysutil "github.com/koordinator-sh/koordinator/pkg/koordlet/util/system" -) - -const ( - Docker = "docker" - Containerd = "containerd" -) - -// @parentDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ -// @return kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/****.scope -func GetContainerCgroupPathWithKube(podParentDir string, c *corev1.ContainerStatus) (string, error) { - containerDir, err := sysutil.CgroupPathFormatter.ContainerDirFn(c) - if err != nil { - return "", err - } - return path.Join( - GetPodCgroupDirWithKube(podParentDir), - containerDir, - ), nil -} - -func GetContainerCgroupCPUAcctProcStatPath(podParentDir string, c *corev1.ContainerStatus) (string, error) { - containerPath, err := GetContainerCgroupPathWithKube(podParentDir, c) - if err != nil { - return "", err - } - return sysutil.GetCgroupFilePath(containerPath, sysutil.CpuacctStat), nil -} - -func GetContainerCgroupMemStatPath(podParentDir string, c *corev1.ContainerStatus) (string, error) { - containerPath, err := GetContainerCgroupPathWithKube(podParentDir, c) - if err != nil { - return "", err - } - return sysutil.GetCgroupFilePath(containerPath, sysutil.MemStat), nil -} - -func GetContainerBaseCFSQuota(container *corev1.Container) int64 { - cpuMilliLimit := GetContainerMilliCPULimit(container) - if cpuMilliLimit <= 0 { - return -1 - } else { - return cpuMilliLimit * sysutil.CFSBasePeriodValue / 1000 - } -} - -func GetContainerMilliCPULimit(c *corev1.Container) int64 { - if cpuLimit, ok := c.Resources.Limits[corev1.ResourceCPU]; ok { - return cpuLimit.MilliValue() - } - return -1 -} - -func GetContainerMemoryByteLimit(c *corev1.Container) int64 { - if memLimit, ok := c.Resources.Limits[corev1.ResourceMemory]; ok { - return memLimit.Value() - } - return -1 -} - -func GetContainerCgroupCPUSharePath(podParentDir string, c *corev1.ContainerStatus) (string, error) { - containerPath, err := GetContainerCgroupPathWithKube(podParentDir, c) - if err != nil { - return "", err - } - return sysutil.GetCgroupFilePath(containerPath, sysutil.CPUShares), nil -} - -func GetContainerCgroupCFSPeriodPath(podParentDir string, c *corev1.ContainerStatus) (string, error) { - containerPath, err := GetContainerCgroupPathWithKube(podParentDir, c) - if err != nil { - return "", err - } - return sysutil.GetCgroupFilePath(containerPath, sysutil.CPUCFSPeriod), nil -} - -func GetContainerCgroupCFSQuotaPath(podParentDir string, c *corev1.ContainerStatus) (string, error) { - containerPath, err := GetContainerCgroupPathWithKube(podParentDir, c) - if err != nil { - return "", err - } - return sysutil.GetCgroupFilePath(containerPath, sysutil.CPUCFSQuota), nil -} - -func GetContainerCgroupCFSBurstPath(podParentDir string, c *corev1.ContainerStatus) (string, error) { - containerPath, err := GetContainerCgroupPathWithKube(podParentDir, c) - if err != nil { - return "", err - } - return sysutil.GetCgroupFilePath(containerPath, sysutil.CPUBurst), nil -} - -func GetContainerCurTasksPath(podParentDir string, c *corev1.ContainerStatus) (string, error) { - containerPath, err := GetContainerCgroupPathWithKube(podParentDir, c) - if err != nil { - return "", err - } - return sysutil.GetCgroupFilePath(containerPath, sysutil.CPUTask), nil -} - -func GetContainerCgroupMemLimitPath(podParentDir string, c *corev1.ContainerStatus) (string, error) { - containerPath, err := GetContainerCgroupPathWithKube(podParentDir, c) - if err != nil { - return "", err - } - return sysutil.GetCgroupFilePath(containerPath, sysutil.MemoryLimit), nil -} - -func GetContainerCgroupCPUStatPath(podParentDir string, c *corev1.ContainerStatus) (string, error) { - containerPath, err := GetContainerCgroupPathWithKube(podParentDir, c) - if err != nil { - return "", err - } - return sysutil.GetCgroupFilePath(containerPath, sysutil.CPUStat), nil -} - -func GetContainerCurCPUShare(podParentDir string, c *corev1.ContainerStatus) (int64, error) { - cgroupPath, err := GetContainerCgroupCPUSharePath(podParentDir, c) - if err != nil { - return 0, err - } - rawContent, err := ioutil.ReadFile(cgroupPath) - if err != nil { - return 0, err - } - return strconv.ParseInt(strings.TrimSpace(string(rawContent)), 10, 64) -} - -func GetContainerCurCFSPeriod(podParentDir string, c *corev1.ContainerStatus) (int64, error) { - cgroupPath, err := GetContainerCgroupCFSPeriodPath(podParentDir, c) - if err != nil { - return 0, err - } - rawContent, err := ioutil.ReadFile(cgroupPath) - if err != nil { - return 0, err - } - return strconv.ParseInt(strings.TrimSpace(string(rawContent)), 10, 64) -} - -func GetContainerCurCFSQuota(podParentDir string, c *corev1.ContainerStatus) (int64, error) { - cgroupPath, err := GetContainerCgroupCFSQuotaPath(podParentDir, c) - if err != nil { - return 0, err - } - rawContent, err := ioutil.ReadFile(cgroupPath) - if err != nil { - return 0, err - } - return strconv.ParseInt(strings.TrimSpace(string(rawContent)), 10, 64) -} - -func GetContainerCurMemLimitBytes(podParentDir string, c *corev1.ContainerStatus) (int64, error) { - cgroupPath, err := GetContainerCgroupMemLimitPath(podParentDir, c) - if err != nil { - return 0, err - } - rawContent, err := ioutil.ReadFile(cgroupPath) - if err != nil { - return 0, err - } - return strconv.ParseInt(strings.TrimSpace(string(rawContent)), 10, 64) -} - -func GetContainerCurTasks(podParentDir string, c *corev1.ContainerStatus) ([]int, error) { - cgroupPath, err := GetContainerCurTasksPath(podParentDir, c) - if err != nil { - return nil, err - } - return sysutil.GetCgroupCurTasks(cgroupPath) -} - -func FindContainerIdAndStatusByName(status *corev1.PodStatus, name string) (string, *corev1.ContainerStatus, error) { - allStatuses := status.InitContainerStatuses - allStatuses = append(allStatuses, status.ContainerStatuses...) - for _, container := range allStatuses { - if container.Name == name && container.ContainerID != "" { - _, cID, err := ParseContainerId(container.ContainerID) - if err != nil { - return "", nil, err - } - return cID, &container, nil - } - } - return "", nil, fmt.Errorf("unable to find ID for container with name %v in pod status (it may not be running)", name) -} - -func FindContainerStatusByID(pod *corev1.Pod, containerID string) *corev1.ContainerStatus { - for _, containerStatus := range pod.Status.ContainerStatuses { - _, cID, _ := ParseContainerId(containerStatus.ContainerID) - if containerID == cID { - return &containerStatus - } - } - return nil -} - -func ParseContainerId(data string) (cType, cID string, err error) { - // Trim the quotes and split the type and ID. - parts := strings.Split(strings.Trim(data, "\""), "://") - if len(parts) != 2 { - err = fmt.Errorf("invalid container ID: %q", data) - return - } - cType, cID = parts[0], parts[1] - return -} diff --git a/pkg/koordlet/util/node.go b/pkg/koordlet/util/node.go deleted file mode 100644 index bb0af8de2..000000000 --- a/pkg/koordlet/util/node.go +++ /dev/null @@ -1,65 +0,0 @@ -/* -Copyright 2022 The Koordinator 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 util - -import ( - "path" - "strconv" - "strings" - - corev1 "k8s.io/api/core/v1" - - sysutil "github.com/koordinator-sh/koordinator/pkg/koordlet/util/system" -) - -// @output like kubepods.slice/kubepods-besteffort.slice/ -func GetKubeQosRelativePath(qosClass corev1.PodQOSClass) string { - return GetPodCgroupDirWithKube(sysutil.CgroupPathFormatter.QOSDirFn(qosClass)) -} - -// GetRootCgroupCPUSetDir gets the cpuset parent directory of the specified podQos' root cgroup -// @output /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-besteffort.slice -func GetRootCgroupCPUSetDir(qosClass corev1.PodQOSClass) string { - rootCgroupParentDir := GetKubeQosRelativePath(qosClass) - return path.Join(sysutil.Conf.CgroupRootDir, sysutil.CgroupCPUSetDir, rootCgroupParentDir) -} - -// GetRootCgroupCurCPUSet gets the current cpuset of the specified podQos' root cgroup -func GetRootCgroupCurCPUSet(qosClass corev1.PodQOSClass) ([]int32, error) { - rawContent, err := sysutil.CgroupFileRead(GetKubeQosRelativePath(qosClass), sysutil.CPUSet) - if err != nil { - return nil, err - } - - return ParseCPUSetStr(rawContent) -} - -func GetRootCgroupCurCFSPeriod(qosClass corev1.PodQOSClass) (int64, error) { - rawContent, err := sysutil.CgroupFileRead(GetKubeQosRelativePath(qosClass), sysutil.CPUCFSPeriod) - if err != nil { - return 0, err - } - return strconv.ParseInt(strings.TrimSpace(rawContent), 10, 64) -} - -func GetRootCgroupCurCFQuota(qosClass corev1.PodQOSClass) (int64, error) { - rawContent, err := sysutil.CgroupFileRead(GetKubeQosRelativePath(qosClass), sysutil.CPUCFSQuota) - if err != nil { - return 0, err - } - return strconv.ParseInt(strings.TrimSpace(rawContent), 10, 64) -} diff --git a/pkg/koordlet/util/node_test.go b/pkg/koordlet/util/node_test.go deleted file mode 100644 index d89915cd6..000000000 --- a/pkg/koordlet/util/node_test.go +++ /dev/null @@ -1,49 +0,0 @@ -/* -Copyright 2022 The Koordinator 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 util - -import ( - "path" - "testing" - - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - - sysutil "github.com/koordinator-sh/koordinator/pkg/koordlet/util/system" -) - -func Test_GetKubeQosRelativePath(t *testing.T) { - - guaranteedPathSystemd := GetKubeQosRelativePath(corev1.PodQOSGuaranteed) - assert.Equal(t, path.Clean(sysutil.KubeRootNameSystemd), guaranteedPathSystemd) - - burstablePathSystemd := GetKubeQosRelativePath(corev1.PodQOSBurstable) - assert.Equal(t, path.Join(sysutil.KubeRootNameSystemd, sysutil.KubeBurstableNameSystemd), burstablePathSystemd) - - besteffortPathSystemd := GetKubeQosRelativePath(corev1.PodQOSBestEffort) - assert.Equal(t, path.Join(sysutil.KubeRootNameSystemd, sysutil.KubeBesteffortNameSystemd), besteffortPathSystemd) - - sysutil.SetupCgroupPathFormatter(sysutil.Cgroupfs) - guaranteedPathCgroupfs := GetKubeQosRelativePath(corev1.PodQOSGuaranteed) - assert.Equal(t, path.Clean(sysutil.KubeRootNameCgroupfs), guaranteedPathCgroupfs) - - burstablePathCgroupfs := GetKubeQosRelativePath(corev1.PodQOSBurstable) - assert.Equal(t, path.Join(sysutil.KubeRootNameCgroupfs, sysutil.KubeBurstableNameCgroupfs), burstablePathCgroupfs) - - besteffortPathCgroupfs := GetKubeQosRelativePath(corev1.PodQOSBestEffort) - assert.Equal(t, path.Join(sysutil.KubeRootNameCgroupfs, sysutil.KubeBesteffortNameCgroupfs), besteffortPathCgroupfs) -} diff --git a/pkg/koordlet/util/pod.go b/pkg/koordlet/util/pod.go deleted file mode 100644 index ae8ed3a41..000000000 --- a/pkg/koordlet/util/pod.go +++ /dev/null @@ -1,245 +0,0 @@ -/* -Copyright 2022 The Koordinator 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 util - -import ( - "io/ioutil" - "path" - "strconv" - "strings" - - corev1 "k8s.io/api/core/v1" - resources "k8s.io/apiserver/pkg/quota/v1" - "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos" - - sysutil "github.com/koordinator-sh/koordinator/pkg/koordlet/util/system" -) - -// @kubeRelativeDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ -// @return kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ -func GetPodCgroupDirWithKube(podKubeRelativeDir string) string { - return path.Join(sysutil.CgroupPathFormatter.ParentDir, podKubeRelativeDir) -} - -// @return like kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ -func GetPodKubeRelativePath(pod *corev1.Pod) string { - qosClass := GetKubeQosClass(pod) - return path.Join( - sysutil.CgroupPathFormatter.QOSDirFn(qosClass), - sysutil.CgroupPathFormatter.PodDirFn(qosClass, string(pod.UID)), - ) -} - -// @podParentDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ -// @output /sys/fs/cgroup/cpuacct/kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/cpuacct.proc_stat -func GetPodCgroupCPUAcctProcStatPath(podParentDir string) string { - podPath := GetPodCgroupDirWithKube(podParentDir) - return sysutil.GetCgroupFilePath(podPath, sysutil.CpuacctStat) -} - -// @podParentDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ -// @output /sys/fs/cgroup/cpu/kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/cpu.shares -func GetPodCgroupCPUSharePath(podParentDir string) string { - podPath := GetPodCgroupDirWithKube(podParentDir) - return sysutil.GetCgroupFilePath(podPath, sysutil.CPUShares) -} - -// @podParentDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ -// @output /sys/fs/cgroup/cpu/kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/cpu.cfs_period_us -func GetPodCgroupCFSPeriodPath(podParentDir string) string { - podPath := GetPodCgroupDirWithKube(podParentDir) - return sysutil.GetCgroupFilePath(podPath, sysutil.CPUCFSPeriod) -} - -// @podParentDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ -// @output /sys/fs/cgroup/cpu/kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/cpu.cfs_quota_us -func GetPodCgroupCFSQuotaPath(podParentDir string) string { - podPath := GetPodCgroupDirWithKube(podParentDir) - return sysutil.GetCgroupFilePath(podPath, sysutil.CPUCFSQuota) -} - -// @podParentDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ -// @output /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/cpuset.cpus -func GetPodCgroupCPUSetPath(podParentDir string) string { - podPath := GetPodCgroupDirWithKube(podParentDir) - return sysutil.GetCgroupFilePath(podPath, sysutil.CPUSet) -} - -// @podParentDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ -// @output /sys/fs/cgroup/cpuacct/kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/cpuacct.proc_stat -func GetPodCgroupMemStatPath(podParentDir string) string { - podPath := GetPodCgroupDirWithKube(podParentDir) - return sysutil.GetCgroupFilePath(podPath, sysutil.MemStat) -} - -// @podParentDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ -// @output /sys/fs/cgroup/memory/kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/memory.limit_in_bytes -func GetPodCgroupMemLimitPath(podParentDir string) string { - podPath := GetPodCgroupDirWithKube(podParentDir) - return sysutil.GetCgroupFilePath(podPath, sysutil.MemoryLimit) -} - -// @podParentDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ -// @output /sys/fs/cgroup/cpu/kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/cpu.bvt_warp_ns -func GetPodCgroupCPUBvtPath(podParentDir string) string { - podPath := GetPodCgroupDirWithKube(podParentDir) - return sysutil.GetCgroupFilePath(podPath, sysutil.CPUBVTWarpNs) -} - -// @podParentDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ -// @output /sys/fs/cgroup/cpu/kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/cpu.stat -func GetPodCgroupCPUStatPath(podParentDir string) string { - podPath := GetPodCgroupDirWithKube(podParentDir) - return sysutil.GetCgroupFilePath(podPath, sysutil.CPUStat) -} - -func GetPodMilliCPULimit(pod *corev1.Pod) int64 { - podCPUMilliLimit := int64(0) - for _, container := range pod.Spec.Containers { - containerCPUMilliLimit := GetContainerMilliCPULimit(&container) - if containerCPUMilliLimit <= 0 { - return -1 - } - podCPUMilliLimit += containerCPUMilliLimit - } - for _, container := range pod.Spec.InitContainers { - containerCPUMilliLimit := GetContainerMilliCPULimit(&container) - if containerCPUMilliLimit <= 0 { - return -1 - } - podCPUMilliLimit = MaxInt64(podCPUMilliLimit, containerCPUMilliLimit) - } - if podCPUMilliLimit <= 0 { - return -1 - } - return podCPUMilliLimit -} - -func GetPodMemoryByteLimit(pod *corev1.Pod) int64 { - podMemoryByteLimit := int64(0) - for _, container := range pod.Spec.Containers { - containerMemByteLimit := GetContainerMemoryByteLimit(&container) - if containerMemByteLimit <= 0 { - return -1 - } - podMemoryByteLimit += containerMemByteLimit - } - for _, container := range pod.Spec.InitContainers { - containerMemByteLimit := GetContainerMemoryByteLimit(&container) - if containerMemByteLimit <= 0 { - return -1 - } - podMemoryByteLimit = MaxInt64(podMemoryByteLimit, containerMemByteLimit) - } - if podMemoryByteLimit <= 0 { - return -1 - } - return podMemoryByteLimit -} - -func GetPodCurCPUShare(podParentDir string) (int64, error) { - cgroupPath := GetPodCgroupCPUSharePath(podParentDir) - rawContent, err := ioutil.ReadFile(cgroupPath) - if err != nil { - return 0, err - } - return strconv.ParseInt(strings.TrimSpace(string(rawContent)), 10, 64) -} - -func GetPodCurCFSPeriod(podParentDir string) (int64, error) { - cgroupPath := GetPodCgroupCFSPeriodPath(podParentDir) - rawContent, err := ioutil.ReadFile(cgroupPath) - if err != nil { - return 0, err - } - return strconv.ParseInt(strings.TrimSpace(string(rawContent)), 10, 64) -} - -func GetPodCurCFSQuota(podParentDir string) (int64, error) { - cgroupPath := GetPodCgroupCFSQuotaPath(podParentDir) - rawContent, err := ioutil.ReadFile(cgroupPath) - if err != nil { - return 0, err - } - return strconv.ParseInt(strings.TrimSpace(string(rawContent)), 10, 64) -} - -func GetPodCurMemLimitBytes(podParentDir string) (int64, error) { - cgroupPath := GetPodCgroupMemLimitPath(podParentDir) - rawContent, err := ioutil.ReadFile(cgroupPath) - if err != nil { - return 0, err - } - return strconv.ParseInt(strings.TrimSpace(string(rawContent)), 10, 64) -} - -func GetPodCurBvtValue(podParentDir string) (int64, error) { - cgroupPath := GetPodCgroupCPUBvtPath(podParentDir) - rawContent, err := ioutil.ReadFile(cgroupPath) - if err != nil { - return 0, err - } - return strconv.ParseInt(strings.TrimSpace(string(rawContent)), 10, 64) -} - -// getPodRequestFromContainers get pod request by summarizing pod containers' requests -func getPodRequestFromContainers(pod *corev1.Pod) corev1.ResourceList { - result := corev1.ResourceList{} - for _, container := range pod.Spec.Containers { - result = resources.Add(result, container.Resources.Requests) - } - // take max_resource(sum_pod, any_init_container) - for _, container := range pod.Spec.InitContainers { - result = resources.Max(result, container.Resources.Requests) - } - // add pod overhead if it exists - if pod.Spec.Overhead != nil { - result = resources.Add(result, pod.Spec.Overhead) - } - return resources.Mask(result, []corev1.ResourceName{corev1.ResourceCPU, corev1.ResourceMemory}) -} - -// GetPodRequest get pod request resource -func GetPodRequest(pod *corev1.Pod) corev1.ResourceList { - return getPodRequestFromContainers(pod) -} - -func GetKubeQosClass(pod *corev1.Pod) corev1.PodQOSClass { - qosClass := pod.Status.QOSClass - if qosClass == "" { - qosClass = qos.GetPodQOS(pod) - } - return qosClass -} - -// @return like kubepods.slice/kubepods-burstable.slice/ -func GetPodQoSRelativePath(qosClass corev1.PodQOSClass) string { - return path.Join( - sysutil.CgroupPathFormatter.ParentDir, - sysutil.CgroupPathFormatter.QOSDirFn(qosClass), - ) -} - -// @return 7712555c_ce62_454a_9e18_9ff0217b8941 from kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice -func ParsePodID(basename string) (string, error) { - return sysutil.CgroupPathFormatter.PodIDParser(basename) -} - -// @return 7712555c_ce62_454a_9e18_9ff0217b8941 from docker-7712555c_ce62_454a_9e18_9ff0217b8941.scope -func ParseContainerID(basename string) (string, error) { - return sysutil.CgroupPathFormatter.ContainerIDParser(basename) -} diff --git a/pkg/koordlet/util/system/cgroup_resource.go b/pkg/koordlet/util/system/cgroup_resource.go deleted file mode 100644 index 51028860d..000000000 --- a/pkg/koordlet/util/system/cgroup_resource.go +++ /dev/null @@ -1,150 +0,0 @@ -/* -Copyright 2022 The Koordinator 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 system - -import ( - "math" - - "k8s.io/klog/v2" -) - -const ( - /** subfs name */ - CgroupCPUDir string = "cpu/" - CgroupCPUSetDir string = "cpuset/" - CgroupCPUacctDir string = "cpuacct/" - CgroupMemDir string = "memory/" - CgroupBlkioDir string = "blkio/" - CgroupNetClsDir string = "net_cls/" - Devices string = "devices/" -) - -const ( - CFSBasePeriodValue int64 = 100000 - MemoryUnlimitValue int64 = -1 - - CPUStatFileName = "cpu.stat" - CPUSharesFileName = "cpu.shares" - CPUCFSQuotaName = "cpu.cfs_quota_us" - CPUCFSPeriodName = "cpu.cfs_period_us" - CPUBVTWarpNsName = "cpu.bvt_warp_ns" - CPUBurstName = "cpu.cfs_burst_us" - CPUSFileName = "cpuset.cpus" - CPUTaskFileName = "tasks" - - CpuacctStatFileName = "cpuacct.stat" - CpuacctProcStatFileName = "cpuacct.proc_stat" - CpuacctProcStatV2FileName = "cpuacct.proc_stat_v2" - - MemWmarkRatioFileName = "memory.wmark_ratio" - MemWmarkScaleFactorFileName = "memory.wmark_scale_factor" - MemDroppableFileName = "memory.droppable" - MemFlagsFileName = "memory.coldpgs.flags" - MemPriorityFileName = "memory.priority" - MemUsePriorityOomFileName = "memory.use_priority_oom" - MemOomGroupFileName = "memory.oom.group" - MemWmarkMinAdjFileName = "memory.wmark_min_adj" - MemMinFileName = "memory.min" - MemLowFileName = "memory.low" - MemHighFileName = "memory.high" - MemoryLimitFileName = "memory.limit_in_bytes" - MemorySWLimitFileName = "memory.memsw.limit_in_bytes" - MemStatFileName = "memory.stat" - - NetClsIDFileName = "net_cls.classid" - - BlkioTRIopsFileName = "blkio.throttle.read_iops_device" - BlkioTRBpsFileName = "blkio.throttle.read_bps_device" - BlkioTWIopsFileName = "blkio.throttle.write_iops_device" - BlkioTWBpsFileName = "blkio.throttle.write_bps_device" -) - -var ( - MemWmarkRatioValidator = &RangeValidator{name: MemWmarkRatioFileName, min: 0, max: 100} - MemPriorityValidator = &RangeValidator{name: MemPriorityFileName, min: 0, max: 12} - MemOomGroupValidator = &RangeValidator{name: MemOomGroupFileName, min: 0, max: 1} - MemUsePriorityOomValidator = &RangeValidator{name: MemUsePriorityOomFileName, min: 0, max: 1} - MemWmarkMinAdjValidator = &RangeValidator{name: MemWmarkMinAdjFileName, min: -50, max: 50} - MemWmarkScaleFactorFileNameValidator = &RangeValidator{name: MemWmarkScaleFactorFileName, min: 1, max: 1000} - MemDroppableValidator = &RangeValidator{name: MemDroppableFileName, min: 0, max: 1} - MemMinValidator = &RangeValidator{name: MemMinFileName, min: 0, max: math.MaxInt64} - MemLowValidator = &RangeValidator{name: MemLowFileName, min: 0, max: math.MaxInt64} - MemHighValidator = &RangeValidator{name: MemHighFileName, min: 0, max: math.MaxInt64} // write value(>node.total) -> read "max" - CPUBvtWarpNsValidator = &RangeValidator{name: CPUBVTWarpNsName, min: -1, max: 2} - CPUBurstValidator = &RangeValidator{name: CPUBurstName, min: 0, max: 100 * 10 * 100000} -) - -var ( - CPUStat = CgroupFile{ResourceFileName: CPUStatFileName, Subfs: CgroupCPUDir, IsAliOS: false} - CPUShares = CgroupFile{ResourceFileName: CPUSharesFileName, Subfs: CgroupCPUDir, IsAliOS: false} - CPUCFSQuota = CgroupFile{ResourceFileName: CPUCFSQuotaName, Subfs: CgroupCPUDir, IsAliOS: false} - CPUCFSPeriod = CgroupFile{ResourceFileName: CPUCFSPeriodName, Subfs: CgroupCPUDir, IsAliOS: false} - CPUTask = CgroupFile{ResourceFileName: CPUTaskFileName, Subfs: CgroupCPUDir, IsAliOS: false} - CPUBVTWarpNs = CgroupFile{ResourceFileName: CPUBVTWarpNsName, Subfs: CgroupCPUDir, IsAliOS: true, Validator: CPUBvtWarpNsValidator} - CPUBurst = CgroupFile{ResourceFileName: CPUBurstName, Subfs: CgroupCPUDir, IsAliOS: true, Validator: CPUBurstValidator} - - CPUSet = CgroupFile{ResourceFileName: CPUSFileName, Subfs: CgroupCPUSetDir, IsAliOS: false} - - CpuacctStat = CgroupFile{ResourceFileName: CpuacctStatFileName, Subfs: CgroupCPUacctDir, IsAliOS: false} - CpuacctProcStat = CgroupFile{ResourceFileName: CpuacctProcStatFileName, Subfs: CgroupCPUacctDir, IsAliOS: true} - CpuacctProcStatV2 = CgroupFile{ResourceFileName: CpuacctProcStatV2FileName, Subfs: CgroupCPUacctDir, IsAliOS: true} - - MemWmarkRatio = CgroupFile{ResourceFileName: MemWmarkRatioFileName, Subfs: CgroupMemDir, IsAliOS: true, Validator: MemWmarkRatioValidator} - MemDroppable = CgroupFile{ResourceFileName: MemDroppableFileName, Subfs: CgroupMemDir, IsAliOS: true, Validator: MemDroppableValidator} - MemFlags = CgroupFile{ResourceFileName: MemFlagsFileName, Subfs: CgroupMemDir, IsAliOS: true} - MemPriority = CgroupFile{ResourceFileName: MemPriorityFileName, Subfs: CgroupMemDir, IsAliOS: true, Validator: MemPriorityValidator} - MemUsePriorityOom = CgroupFile{ResourceFileName: MemUsePriorityOomFileName, Subfs: CgroupMemDir, IsAliOS: true, Validator: MemUsePriorityOomValidator} - MemOomGroup = CgroupFile{ResourceFileName: MemOomGroupFileName, Subfs: CgroupMemDir, IsAliOS: true, Validator: MemOomGroupValidator} - MemWmarkMinAdj = CgroupFile{ResourceFileName: MemWmarkMinAdjFileName, Subfs: CgroupMemDir, IsAliOS: true, Validator: MemWmarkMinAdjValidator} - MemWmarkScaleFactor = CgroupFile{ResourceFileName: MemWmarkScaleFactorFileName, Subfs: CgroupMemDir, IsAliOS: true, Validator: MemWmarkScaleFactorFileNameValidator} - MemMin = CgroupFile{ResourceFileName: MemMinFileName, Subfs: CgroupMemDir, IsAliOS: true, Validator: MemMinValidator} - MemLow = CgroupFile{ResourceFileName: MemLowFileName, Subfs: CgroupMemDir, IsAliOS: true, Validator: MemLowValidator} - MemHigh = CgroupFile{ResourceFileName: MemHighFileName, Subfs: CgroupMemDir, IsAliOS: true, Validator: MemHighValidator} - MemoryLimit = CgroupFile{ResourceFileName: MemoryLimitFileName, Subfs: CgroupMemDir, IsAliOS: false} - MemorySWLimit = CgroupFile{ResourceFileName: MemorySWLimitFileName, Subfs: CgroupMemDir, IsAliOS: false} - MemStat = CgroupFile{ResourceFileName: MemStatFileName, Subfs: CgroupMemDir, IsAliOS: false} - - NetClsID = CgroupFile{ResourceFileName: NetClsIDFileName, Subfs: CgroupNetClsDir, IsAliOS: false} - - BlkioReadIops = CgroupFile{ResourceFileName: BlkioTRIopsFileName, Subfs: CgroupBlkioDir, IsAliOS: false} - BlkioReadBps = CgroupFile{ResourceFileName: BlkioTRBpsFileName, Subfs: CgroupBlkioDir, IsAliOS: false} - BlkioWriteIops = CgroupFile{ResourceFileName: BlkioTWIopsFileName, Subfs: CgroupBlkioDir, IsAliOS: false} - BlkioWriteBps = CgroupFile{ResourceFileName: BlkioTWBpsFileName, Subfs: CgroupBlkioDir, IsAliOS: false} -) - -type CgroupFile struct { - ResourceFileName string - Subfs string - IsAliOS bool - Validator Validate -} - -func ValidateCgroupValue(value *int64, parentDir string, file CgroupFile) bool { - if value == nil { - klog.V(5).Infof("validate fail, dir:%s, file:%s, value is nil!", parentDir, file.ResourceFileName) - return false - } - if file.Validator != nil { - valid, msg := file.Validator.Validate(value) - if !valid { - klog.Warningf("validate fail! dir:%s, msg:%s", parentDir, msg) - } - return valid - } - - return true -} diff --git a/pkg/koordlet/util/system/network.go b/pkg/koordlet/util/system/network.go deleted file mode 100644 index 963d885ed..000000000 --- a/pkg/koordlet/util/system/network.go +++ /dev/null @@ -1,45 +0,0 @@ -/* -Copyright 2022 The Koordinator 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 system - -const ( - GoldNetClsID = 0xab5a2010 // net_priority(3) - GoldDSCP = 18 - SilverNetClsID = 0xab5a2020 // net_priority(5) - SilverDSCP = 17 - CopperNetClsID = 0xab5a2030 // net_priority(7) - CopperDSCP = 16 -) - -type BandwidthConfig struct { - GatewayIfaceName string - GatewayLimit uint64 - - RootLimit uint64 - - GoldRequest uint64 - GoldLimit uint64 - GoldDSCP uint64 - - SilverRequest uint64 - SilverLimit uint64 - SilverDSCP uint64 - - CopperRequest uint64 - CopperLimit uint64 - CopperDSCP uint64 -} diff --git a/pkg/koordlet/util/system/network_linux.go b/pkg/koordlet/util/system/network_linux.go deleted file mode 100644 index a2c8c2260..000000000 --- a/pkg/koordlet/util/system/network_linux.go +++ /dev/null @@ -1,194 +0,0 @@ -//go:build linux -// +build linux - -/* -Copyright 2022 The Koordinator 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 system - -import ( - "fmt" - "net" - "path" - "regexp" - "strconv" - "strings" - "syscall" - - "github.com/vishvananda/netlink" - "k8s.io/klog/v2" -) - -var ( - QosctlKModsRegex = []*regexp.Regexp{ - regexp.MustCompile(`sch_sfq\s`), - regexp.MustCompile(`sch_dsmark\s`), - regexp.MustCompile(`sch_htb\s`), - } -) - -const ( - QosctlPackageName = "aqos" - QosctlBinaryPath = "/home/admin/aqos/qosctl" -) - -var EnsureQosctlReady = ensureQosctlReadyFn - -// TODO: -// - 'rpm' and 'lsmod' command not found -func ensureQosctlReadyFn(defaultIface *net.Interface) error { - // if RPM is not installed, return false - if _, _, err := ExecCmdOnHost([]string{"rpm", "-q", QosctlPackageName}); err != nil { - return fmt.Errorf("qosctl.rpm not installed: %v", err) - } - - // if KMods are loaded, return true - // else try to install lazy-loading KMods - out, _, err := ExecCmdOnHost([]string{"lsmod"}) - if err != nil { - return err - } - if isKModLoaded := func(sysKMods string) bool { - for _, reg := range QosctlKModsRegex { - if !reg.MatchString(sysKMods) { - klog.Warningf("Qosctl need KMod %s", reg.String()) - return false - } - } - return true - }(string(out)); isKModLoaded { - return nil - } - klog.Infof("Qosctl KMod is lazy-loading, try to install it") - - if HasBandwidthCtrlSetup(defaultIface) { - return fmt.Errorf("bandwidth control has already setup, but KMods are not loaded") - } - return nil -} - -// for unit test -var ( - netLinkByIndexFn = netlink.LinkByIndex - netLinkQdiscListFn = netlink.QdiscList - netLinkQdiscDelFn = netlink.QdiscDel - netLinkRouteListFn = netlink.RouteList -) - -// htb * 1 + dsmark * 3 + sfq * 3 -const BandwidthCtrlQdiscCount = 7 - -// TODO: 'aqos' add sub command to check itself setup -func HasBandwidthCtrlSetup(iface *net.Interface) bool { - ifLink, err := netLinkByIndexFn(iface.Index) - if err != nil { - klog.Errorf("iface(%s) not exist: %v", iface.Name, err) - return false - } - qdiscs, err := netLinkQdiscListFn(ifLink) - if err != nil { - klog.Errorf("qdisc of iface(%s) not exist: %v", iface.Name, err) - return false - } - return len(qdiscs) == BandwidthCtrlQdiscCount -} - -func ResetBandwidthCtrl(iface *net.Interface) { - defaultLink, err := netLinkByIndexFn(iface.Index) - if err != nil { - klog.Errorf("iface(%s) not exist: %v", iface.Name, err) - return - } - qdiscs, err := netLinkQdiscListFn(defaultLink) - if err != nil { - klog.Errorf("qdisc of iface(%s) not exist: %v", iface.Name, err) - return - } - for _, qdisc := range qdiscs { - if qdisc.Attrs().Parent == netlink.HANDLE_ROOT { - if err := netLinkQdiscDelFn(qdisc); err != nil { - klog.Errorf("del root qdisc of iface(%s) failed: %v", iface.Name, err) - } - break - } - } -} - -var SetupBandwidthCtrl = setupBandwidthCtrlFn - -func setupBandwidthCtrlFn(cfg *BandwidthConfig) error { - _, _, err := ExecCmdOnHost([]string{ - QosctlBinaryPath, "init", "--dev", cfg.GatewayIfaceName, - "--dmb", fmt.Sprintf("%d", cfg.GatewayLimit), "--fmb", fmt.Sprintf("%d", cfg.RootLimit), - "--cb", fmt.Sprintf("%d,%d,%d", cfg.GoldRequest, cfg.SilverRequest, cfg.CopperRequest), - "--cc", fmt.Sprintf("%d,%d,%d", cfg.GoldLimit, cfg.SilverLimit, cfg.CopperLimit), - "--cd", fmt.Sprintf("%d,%d,%d", cfg.GoldDSCP, cfg.SilverDSCP, cfg.CopperDSCP), - }) - return err -} - -var GetHostDefaultIface = getHostDefaultIfaceFn - -// find NIC in default route. -// MUST executed in host network namespace -func getHostDefaultIfaceFn() *net.Interface { - routes, err := netLinkRouteListFn(nil, syscall.AF_INET) - if err != nil { - klog.Errorf("Command('ip route show') failed: %v", err) - return nil - } - - for _, route := range routes { - if route.Dst == nil || route.Dst.String() == "0.0.0.0/0" { - if route.LinkIndex <= 0 { - klog.Errorf("Find default route, but interface index <= 0") - return nil - } - if iface, err := net.InterfaceByIndex(route.LinkIndex); err != nil { - klog.Errorf("Find default route, but interface index is invalid: %v", err) - return nil - } else { - return iface - } - } - } - return nil -} - -const ( - // 1000 Mbit/s - DefaultIfaceBandwidth = 1000 -) - -var GetIfaceSpeedMbit = getIfaceSpeedMbitFn - -// /sys/class/net/${iface}/speed = xxx Mbit/s. -// Kernel version >= v2.6.x -func getIfaceSpeedMbitFn(iface *net.Interface) uint64 { - speedCmds := []string{"cat", path.Join(Conf.SysRootDir, "/class/net", iface.Name, "/speed")} - speedOut, _, err := ExecCmdOnHost(speedCmds) - if err != nil { - klog.Errorf("Command('%s') failed: %v", strings.Join(speedCmds, " "), err) - return DefaultIfaceBandwidth - } - speedStr := strings.TrimSpace(string(speedOut)) - speed, err := strconv.ParseInt(speedStr, 10, 64) - if err != nil || speed < 0 { - klog.Errorf("Invalid speed(%s): %v", speedStr, err) - return DefaultIfaceBandwidth - } - return uint64(speed) -} diff --git a/pkg/koordlet/util/system/network_linux_test.go b/pkg/koordlet/util/system/network_linux_test.go deleted file mode 100644 index ba6bbe15b..000000000 --- a/pkg/koordlet/util/system/network_linux_test.go +++ /dev/null @@ -1,163 +0,0 @@ -//go:build linux -// +build linux - -/* -Copyright 2022 The Koordinator 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 system - -import ( - "fmt" - "net" - "testing" - - "github.com/prashantv/gostub" - "github.com/stretchr/testify/assert" - "github.com/vishvananda/netlink" -) - -func Test_EnsureQosctlReady(t *testing.T) { - type args struct { - mockCmdFn func(cmds []string) ([]byte, int, error) - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "rpm is not installed", - args: args{ - mockCmdFn: func(cmds []string) ([]byte, int, error) { - if cmds[0] == "rpm" { - return []byte("未安装软件包"), 1, fmt.Errorf("not installed") - } - return nil, 0, nil - }, - }, - wantErr: true, - }, - { - name: "rpm is installed and KMods are loaded", - args: args{ - mockCmdFn: func(cmds []string) ([]byte, int, error) { - if cmds[0] == "rpm" { - return []byte("aqos"), 0, nil - } else if cmds[0] == "lsmod" { - return []byte(`sch_sfq 24576 0 -sch_dsmark 20480 0 -sch_htb 24576 0`), 0, nil - } - return nil, 0, nil - }, - }, - wantErr: false, - }, - { - name: "rpm is installed and KMods are not loaded", - args: args{ - mockCmdFn: func(cmds []string) ([]byte, int, error) { - if cmds[0] == "rpm" { - return []byte("aqos"), 0, nil - } else if cmds[0] == "lsmod" { - return []byte(""), 0, nil - } - return nil, 0, nil - }, - }, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - stubs := gostub.Stub(&ExecCmdOnHost, tt.args.mockCmdFn) - defer stubs.Reset() - assert.Equal(t, tt.wantErr, EnsureQosctlReady(&net.Interface{}) != nil) - }) - } -} - -func Test_HasBandwidthCtrlSetup(t *testing.T) { - dummyIndex := 24 - dummyLink := netlink.Dummy{ - LinkAttrs: netlink.LinkAttrs{ - Index: dummyIndex, - }, - } - t.Run("bandwidth control not setup", func(t *testing.T) { - stubs := gostub.Stub(&netLinkByIndexFn, func(index int) (netlink.Link, error) { - return &dummyLink, nil - }) - stubs.Stub(&netLinkQdiscListFn, func(link netlink.Link) ([]netlink.Qdisc, error) { - return nil, fmt.Errorf("qdisc not exist") - }) - defer stubs.Reset() - - assert.Equal(t, false, HasBandwidthCtrlSetup(&net.Interface{ - Index: dummyIndex, - })) - }) - - t.Run("bandwidth control is setup", func(t *testing.T) { - stubs := gostub.Stub(&netLinkByIndexFn, func(index int) (netlink.Link, error) { - return &dummyLink, nil - }) - stubs.Stub(&netLinkQdiscListFn, func(link netlink.Link) ([]netlink.Qdisc, error) { - return make([]netlink.Qdisc, BandwidthCtrlQdiscCount), nil - }) - defer stubs.Reset() - - assert.Equal(t, true, HasBandwidthCtrlSetup(&net.Interface{ - Index: dummyIndex, - })) - }) - -} - -func Test_ResetBandwidthCtrl(t *testing.T) { - helper := NewNetworkTestUtil(t) - defer helper.Cleanup() - - dummyLink := helper.SetupDummyLinkWithAddr() - ResetBandwidthCtrl(&net.Interface{ - Index: dummyLink.Index, - }) - - afterQdiscs, err := netlink.QdiscList(dummyLink) - assert.NoError(t, err) - assert.Equal(t, 1, len(afterQdiscs)) -} - -func Test_GetHostDefaultIface(t *testing.T) { - helper := NewNetworkTestUtil(t) - defer helper.Cleanup() - - dummyLink := helper.SetupDummyLinkWithAddr() - netlink.RouteAdd(&netlink.Route{ - LinkIndex: dummyLink.Index, - Scope: netlink.SCOPE_UNIVERSE, - Dst: &net.IPNet{ - IP: net.IPv4zero, - Mask: net.CIDRMask(0, 32), - }, - }) - - findIface := GetHostDefaultIface() - assert.NotNil(t, findIface) - - expectLink, _ := netlink.LinkByName(dummyLink.Name) - assert.Equal(t, expectLink.Attrs().Index, findIface.Index) -} diff --git a/pkg/koordlet/util/system/network_unsupported.go b/pkg/koordlet/util/system/network_unsupported.go deleted file mode 100644 index a6c62c3c1..000000000 --- a/pkg/koordlet/util/system/network_unsupported.go +++ /dev/null @@ -1,58 +0,0 @@ -//go:build !linux -// +build !linux - -/* -Copyright 2022 The Koordinator 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 system - -import ( - "fmt" - "net" -) - -var EnsureQosctlReady = ensureQosctlReadyFn - -func ensureQosctlReadyFn(defaultIface *net.Interface) error { - return fmt.Errorf("only support linux") -} - -func HasBandwidthCtrlSetup(iface *net.Interface) bool { - return false -} - -func ResetBandwidthCtrl(iface *net.Interface) { -} - -var SetupBandwidthCtrl = setupBandwidthCtrlFn - -func setupBandwidthCtrlFn(cfg *BandwidthConfig) error { - return fmt.Errorf("only support linux") -} - -var GetHostDefaultIface = getHostDefaultIfaceFn - -func getHostDefaultIfaceFn() *net.Interface { - return &net.Interface{ - Name: "eth0", - } -} - -var GetIfaceSpeedMbit = getIfaceSpeedMbitFn - -func getIfaceSpeedMbitFn(iface *net.Interface) uint64 { - return 0 -} diff --git a/pkg/koordlet/util/system/resctrl.go b/pkg/koordlet/util/system/resctrl.go deleted file mode 100644 index e179a8588..000000000 --- a/pkg/koordlet/util/system/resctrl.go +++ /dev/null @@ -1,142 +0,0 @@ -/* -Copyright 2022 The Koordinator 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 system - -import ( - "fmt" - "io/ioutil" - "os" - "path" - "strconv" - "strings" - - "k8s.io/klog/v2" -) - -const ( - ResctrlDir string = "resctrl/" - RdtInfoDir string = "info" - L3CatDir string = "L3" - - SchemataFileName string = "schemata" - CbmMaskFileName string = "cbm_mask" - ResctrlTaskFileName string = "tasks" - - ResctrlName string = "resctrl" -) - -// @return /sys/fs/resctrl -func GetResctrlSubsystemDirPath() string { - return path.Join(Conf.SysFSRootDir, ResctrlDir) -} - -// @groupPath BE -// @return /sys/fs/resctrl/BE -func GetResctrlGroupRootDirPath(groupPath string) string { - return path.Join(Conf.SysFSRootDir, ResctrlDir, groupPath) -} - -// @return /sys/fs/resctrl/info/L3/cbm_mask -func GetResctrlL3CbmFilePath() string { - return path.Join(Conf.SysFSRootDir, ResctrlDir, RdtInfoDir, L3CatDir, CbmMaskFileName) -} - -// @groupPath BE -// @return /sys/fs/resctrl/BE/schemata -func GetResctrlSchemataFilePath(groupPath string) string { - return path.Join(Conf.SysFSRootDir, ResctrlDir, groupPath, SchemataFileName) -} - -// @groupPath BE -// @return /sys/fs/resctrl/BE/tasks -func GetResctrlTasksFilePath(groupPath string) string { - return path.Join(Conf.SysFSRootDir, ResctrlDir, groupPath, ResctrlTaskFileName) -} - -// ReadCatL3Cbm reads and returns the value of cat l3 cbm_mask -func ReadCatL3Cbm() (uint, error) { - out, err := ReadCatL3CbmString() - if err != nil { - return 0, err - } - cbmValue, err := strconv.ParseUint(out, 16, 32) - if err != nil { - return 0, err - } - return uint(cbmValue), nil -} - -// ReadCatL3Cbm reads and returns the value of cat l3 cbm_mask -func ReadCatL3CbmString() (string, error) { - cbmFile := GetResctrlL3CbmFilePath() - out, err := ioutil.ReadFile(cbmFile) - if err != nil { - return "", err - } - return strings.TrimSpace(string(out)), nil -} - -// ReadResctrlTasksMap reads and returns the map of given resctrl group's task ids -func ReadResctrlTasksMap(groupPath string) (map[int]struct{}, error) { - tasksPath := GetResctrlTasksFilePath(groupPath) - rawContent, err := ioutil.ReadFile(tasksPath) - if err != nil { - return nil, err - } - - tasksMap := map[int]struct{}{} - - lines := strings.Split(string(rawContent), "\n") - for _, line := range lines { - line = strings.TrimSpace(line) - if len(line) <= 0 { - continue - } - task, err := strconv.Atoi(line) - if err != nil { - return nil, err - } - tasksMap[task] = struct{}{} - } - return tasksMap, nil -} - -// CheckAndTryEnableResctrlCat checks if resctrl and l3_cat are enabled; if not, try to enable the features by mount -// resctrl subsystem; See MountResctrlSubsystem() for the detail. -// It returns whether the resctrl cat is enabled, and the error if failed to enable or to check resctrl interfaces -func CheckAndTryEnableResctrlCat() error { - // resctrl cat is correctly enabled: l3_cbm path exists - l3CbmFilePath := GetResctrlL3CbmFilePath() - _, err := os.Stat(l3CbmFilePath) - if err == nil { - return nil - } - newMount, err := MountResctrlSubsystem() - if err != nil { - return err - } - if newMount { - klog.Infof("mount resctrl successfully, resctrl enabled") - } - // double check l3_cbm path to ensure both resctrl and cat are correctly enabled - l3CbmFilePath = GetResctrlL3CbmFilePath() - _, err = os.Stat(l3CbmFilePath) - if err != nil { - return fmt.Errorf("resctrl cat is not enabled, err: %s", err) - } - return nil -} diff --git a/pkg/koordlet/util/system/resctrl_linux.go b/pkg/koordlet/util/system/resctrl_linux.go deleted file mode 100644 index c69bc6d79..000000000 --- a/pkg/koordlet/util/system/resctrl_linux.go +++ /dev/null @@ -1,50 +0,0 @@ -//go:build linux -// +build linux - -/* -Copyright 2022 The Koordinator 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 system - -import ( - "fmt" - "os" - "syscall" -) - -// MountResctrlSubsystem mounts resctrl fs under the sysFSRoot to enable the kernel feature on supported environment -// NOTE: linux kernel (Alibaba Cloud Linux 2, >= 4.10), Intel cpu and bare-mental host are required; Also, Intel RDT -// features should be enabled in kernel configurations and kernel commandline. -// For more info, please see https://github.com/intel/intel-cmt-cat/wiki/resctrl or -func MountResctrlSubsystem() (bool, error) { - schemataPath := GetResctrlSchemataFilePath("") - // use schemata path to check since the subsystem root dir could keep exist when unmounted - _, err := os.Stat(schemataPath) - if err == nil { - return false, nil - } - subsystemPath := GetResctrlSubsystemDirPath() - err = syscall.Mount(ResctrlName, subsystemPath, ResctrlName, syscall.MS_RELATIME, "") - if err != nil { - return false, err - } - _, err = os.Stat(schemataPath) - if err != nil { - return false, fmt.Errorf("resctrl subsystem is mounted, but path %s does not exist, err: %s", - subsystemPath, err) - } - return true, nil -} diff --git a/pkg/koordlet/util/system/resctrl_test.go b/pkg/koordlet/util/system/resctrl_test.go deleted file mode 100644 index 6aced17f0..000000000 --- a/pkg/koordlet/util/system/resctrl_test.go +++ /dev/null @@ -1,259 +0,0 @@ -/* -Copyright 2022 The Koordinator 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 system - -import ( - "io/ioutil" - "os" - "path/filepath" - "runtime" - "testing" - - "github.com/stretchr/testify/assert" -) - -func Test_ReadCatL3Cbm(t *testing.T) { - type fields struct { - cbmStr string - invalidPath bool - } - tests := []struct { - name string - fields fields - want uint - wantErr bool - }{ - { - name: "do not panic but throw an error for empty input", - want: 0, - wantErr: true, - }, - { - name: "invalid path", - fields: fields{invalidPath: true}, - want: 0, - wantErr: true, - }, - { - name: "cbm is not an unsigned integer", - fields: fields{cbmStr: "-1"}, - want: 0, - wantErr: true, - }, - { - name: "cbm is too large", - fields: fields{cbmStr: "99999999999"}, - want: 0, - wantErr: true, - }, - { - name: "parse cbm successfully", - fields: fields{cbmStr: "ff"}, - want: 255, - wantErr: false, - }, - { - name: "parse cbm successfully 1", - fields: fields{cbmStr: "3f\n"}, - want: 63, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - var sysFSRootDir string - sysFSRootDir, _ = ioutil.TempDir("", "ReadCatL3Cbm") - resctrlDir := filepath.Join(sysFSRootDir, ResctrlDir) - l3CatDir := filepath.Join(resctrlDir, RdtInfoDir, L3CatDir) - err := os.MkdirAll(l3CatDir, 0700) - assert.NoError(t, err) - - cbmPath := filepath.Join(l3CatDir, CbmMaskFileName) - err = ioutil.WriteFile(cbmPath, []byte(tt.fields.cbmStr), 0666) - assert.NoError(t, err) - - defer os.RemoveAll(sysFSRootDir) - - Conf = &Config{ - SysFSRootDir: sysFSRootDir, - } - if tt.fields.invalidPath { - Conf.SysFSRootDir = "invalidPath" - } - - got, err := ReadCatL3Cbm() - assert.Equal(t, tt.wantErr, err != nil) - assert.Equal(t, tt.want, got) - }) - } -} - -func Test_ReadResctrlTasksMap(t *testing.T) { - type args struct { - groupPath string - } - type fields struct { - tasksStr string - invalidPath bool - } - tests := []struct { - name string - args args - fields fields - want map[int]struct{} - wantErr bool - }{ - { - name: "do not panic but throw an error for empty input", - want: map[int]struct{}{}, - wantErr: false, - }, - { - name: "invalid path", - fields: fields{invalidPath: true}, - want: nil, - wantErr: true, - }, - { - name: "parse correctly", - fields: fields{tasksStr: "101\n111\n"}, - want: map[int]struct{}{101: {}, 111: {}}, - wantErr: false, - }, - { - name: "parse correctly 1", - args: args{groupPath: "BE"}, - fields: fields{tasksStr: "101\n111\n"}, - want: map[int]struct{}{101: {}, 111: {}}, - wantErr: false, - }, - { - name: "parse error for invalid task str", - fields: fields{tasksStr: "101\n1aa\n"}, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - var sysFSRootDir string - sysFSRootDir, _ = ioutil.TempDir("", "ReadResctrlTasksMap") - resctrlDir := filepath.Join(sysFSRootDir, ResctrlDir, tt.args.groupPath) - err := os.MkdirAll(resctrlDir, 0700) - assert.NoError(t, err) - - tasksPath := filepath.Join(resctrlDir, ResctrlTaskFileName) - err = ioutil.WriteFile(tasksPath, []byte(tt.fields.tasksStr), 0666) - assert.NoError(t, err) - - defer os.RemoveAll(sysFSRootDir) - - Conf = &Config{ - SysFSRootDir: sysFSRootDir, - } - if tt.fields.invalidPath { - Conf.SysFSRootDir = "invalidPath" - } - - got, err := ReadResctrlTasksMap(tt.args.groupPath) - assert.Equal(t, tt.wantErr, err != nil) - assert.Equal(t, tt.want, got) - }) - } - -} - -func Test_CheckAndTryEnableResctrlCat(t *testing.T) { - type fields struct { - cbmStr string - invalidPath bool - } - tests := []struct { - name string - fields fields - wantErr bool - }{ - { - name: "return disabled for a invalid path", - fields: fields{invalidPath: true}, - wantErr: true, - }, - { - name: "return enabled for a valid l3_cbm", - fields: fields{cbmStr: "3f"}, - wantErr: false, - }, - // TODO: add mount case - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - var sysFSRootDir string - sysFSRootDir, _ = ioutil.TempDir("", "CheckAndTryEnableResctrlCat") - defer os.RemoveAll(sysFSRootDir) - resctrlDir := filepath.Join(sysFSRootDir, ResctrlDir) - l3CatDir := filepath.Join(resctrlDir, RdtInfoDir, L3CatDir) - err := os.MkdirAll(l3CatDir, 0700) - assert.NoError(t, err) - - cbmPath := filepath.Join(l3CatDir, CbmMaskFileName) - err = ioutil.WriteFile(cbmPath, []byte(tt.fields.cbmStr), 0666) - assert.NoError(t, err) - - Conf = &Config{ - SysFSRootDir: sysFSRootDir, - } - if tt.fields.invalidPath { - Conf.SysFSRootDir = "invalidPath" - } - - gotErr := CheckAndTryEnableResctrlCat() - - assert.Equal(t, tt.wantErr, gotErr != nil) - }) - } -} - -func Test_MountResctrlSubsystem(t *testing.T) { - t.Run("test not panic", func(t *testing.T) { - var sysFSRootDir string - sysFSRootDir, _ = ioutil.TempDir("", "MountResctrlSubsystem") - defer os.RemoveAll(sysFSRootDir) - resctrlDir := filepath.Join(sysFSRootDir, ResctrlDir) - err := os.MkdirAll(resctrlDir, 0700) - assert.NoError(t, err) - - schemataPath := filepath.Join(resctrlDir, SchemataFileName) - err = ioutil.WriteFile(schemataPath, []byte(" L3:0=ff;1=ff\n MB:0=100;1=100\n"), 0666) - assert.NoError(t, err) - - Conf = &Config{ - SysFSRootDir: sysFSRootDir, - } - - got, err := MountResctrlSubsystem() - - // resctrl is only supported by linux - if runtime.GOOS != "linux" { - assert.Equal(t, false, got) - assert.EqualError(t, err, "only support linux") - return - } - - assert.Equal(t, false, got) - assert.NoError(t, err) - }) -} diff --git a/pkg/koordlet/util/system/system_file.go b/pkg/koordlet/util/system/system_file.go deleted file mode 100644 index fa75db377..000000000 --- a/pkg/koordlet/util/system/system_file.go +++ /dev/null @@ -1,73 +0,0 @@ -/* -Copyright 2022 The Koordinator 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 system - -import ( - "path" - - "k8s.io/klog/v2" -) - -const ( - ProcSysVmRelativePath = "sys/vm/" - - MinFreeKbytesFileName = "min_free_kbytes" - WatermarkScaleFactorFileName = "watermark_scale_factor" - ProcStatFileName = "stat" -) - -type SystemFile struct { - File string - Validator Validate -} - -var ( - MinFreeKbytesValidator = &RangeValidator{name: MinFreeKbytesFileName, min: 10, max: 400} - WatermarkScaleFactorValidator = &RangeValidator{name: WatermarkScaleFactorFileName, min: 10, max: 400} -) - -var ( - MinFreeKbytesFile SystemFile - WatermarkScaleFactorFile SystemFile - ProcStatFile SystemFile -) - -func init() { - initFilePath() -} - -func initFilePath() { - MinFreeKbytesFile = SystemFile{File: path.Join(Conf.ProcRootDir, ProcSysVmRelativePath, MinFreeKbytesFileName), Validator: MinFreeKbytesValidator} - WatermarkScaleFactorFile = SystemFile{File: path.Join(Conf.ProcRootDir, ProcSysVmRelativePath, WatermarkScaleFactorFileName), Validator: WatermarkScaleFactorValidator} - ProcStatFile = SystemFile{File: path.Join(Conf.ProcRootDir, ProcStatFileName)} -} - -func ValidateValue(value *int64, file SystemFile) bool { - if value == nil { - klog.V(5).Infof("validate fail,file:%s , value is nil!", file.File) - return false - } - if file.Validator != nil { - valid, msg := file.Validator.Validate(value) - if !valid { - klog.Warningf("validate fail!msg: %s", msg) - } - return valid - } - - return true -} diff --git a/pkg/koordlet/util/util.go b/pkg/koordlet/util/util.go deleted file mode 100644 index 1b9604353..000000000 --- a/pkg/koordlet/util/util.go +++ /dev/null @@ -1,119 +0,0 @@ -/* -Copyright 2022 The Koordinator 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 util - -import ( - "fmt" - "io/ioutil" - "path/filepath" - "sort" - "strconv" - "strings" - - sysutil "github.com/koordinator-sh/koordinator/pkg/koordlet/util/system" -) - -// MergeCPUSet merges the old cpuset with the new one, and also deduplicate and keeps a desc order by processor ids -// e.g. [1,0], [3,2,2,1] => [3,2,1,0] -func MergeCPUSet(old, new []int32) []int32 { - cpuMap := map[int32]struct{}{} - - for _, id := range old { - cpuMap[id] = struct{}{} - } - for _, id := range new { - cpuMap[id] = struct{}{} - } - - var merged []int32 - for id := range cpuMap { - merged = append(merged, id) - } - sort.Slice(merged, func(i, j int) bool { - return merged[i] > merged[j] - }) - - return merged -} - -// ParseCPUSetStr parses cpuset string into a slice -// eg. "0-5,34,46-48" => [0,1,2,3,4,5,34,46,47,48] -func ParseCPUSetStr(cpusetStr string) ([]int32, error) { - cpusetStr = strings.Trim(strings.TrimSpace(cpusetStr), "\n") - if cpusetStr == "" { - return nil, nil - } - - // split CPU list string - // eg. "0-5,34,46-48" => ["0-5", "34", "46-48"] - ranges := strings.Split(cpusetStr, ",") - - var cpuset []int32 - for _, r := range ranges { - boundaries := strings.Split(r, "-") - if len(boundaries) == 1 { - // only one element case, eg. "46" - elem, err := strconv.Atoi(boundaries[0]) - if err != nil { - return nil, err - } - cpuset = append(cpuset, int32(elem)) - } else if len(boundaries) == 2 { - // multi-element case, eg. "0-5" - start, err := strconv.Atoi(boundaries[0]) - if err != nil { - return nil, err - } - end, err := strconv.Atoi(boundaries[1]) - if err != nil { - return nil, err - } - // add all elements to the result. - // e.g. "0-5" => [0, 1, 2, 3, 4, 5] - for e := start; e <= end; e++ { - cpuset = append(cpuset, int32(e)) - } - } - } - - return cpuset, nil -} - -// GenerateCPUSetStr generates the cpuset string from the cpuset slice -// eg. [3,2,1,0] => "3,2,1,0" -func GenerateCPUSetStr(cpuset []int32) string { - return strings.Trim(strings.Join(strings.Fields(fmt.Sprint(cpuset)), ","), "[]") -} - -// WriteCgroupCPUSet writes the cgroup cpuset file according to the specified cgroup dir -func WriteCgroupCPUSet(cgroupFileDir, cpusetStr string) error { - return ioutil.WriteFile(filepath.Join(cgroupFileDir, sysutil.CPUSFileName), []byte(cpusetStr), 0644) -} - -func MinInt64(i, j int64) int64 { - if i < j { - return i - } - return j -} - -func MaxInt64(i, j int64) int64 { - if i > j { - return i - } - return j -} diff --git a/pkg/slo-controller/config/config.go b/pkg/slo-controller/config/config.go index a63fa614e..6858e1a68 100644 --- a/pkg/slo-controller/config/config.go +++ b/pkg/slo-controller/config/config.go @@ -133,18 +133,3 @@ func GetNodeColocationStrategy(cfg *ColocationCfg, node *corev1.Node) *Colocatio } return strategy } - -// DefaultNodeSLOSpecConfig defines the default config of the nodeSLOSpec, which would be used by the resmgr -func DefaultNodeSLOSpecConfig() slov1alpha1.NodeSLOSpec { - return slov1alpha1.NodeSLOSpec{ - ResourceUsedThresholdWithBE: DefaultResourceThresholdStrategy(), - } -} - -func DefaultResourceThresholdStrategy() *slov1alpha1.ResourceThresholdStrategy { - return &slov1alpha1.ResourceThresholdStrategy{ - Enable: pointer.BoolPtr(false), - CPUSuppressThresholdPercent: pointer.Int64Ptr(65), - CPUSuppressPolicy: slov1alpha1.CPUSetPolicy, - } -} diff --git a/pkg/slo-controller/nodeslo/nodeslo_controller.go b/pkg/slo-controller/nodeslo/nodeslo_controller.go index ebb80afe3..daed16af1 100644 --- a/pkg/slo-controller/nodeslo/nodeslo_controller.go +++ b/pkg/slo-controller/nodeslo/nodeslo_controller.go @@ -25,6 +25,7 @@ import ( "github.com/koordinator-sh/koordinator/pkg/slo-controller/nodemetric" "github.com/koordinator-sh/koordinator/pkg/slo-controller/noderesource" + "github.com/koordinator-sh/koordinator/pkg/util" "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" @@ -76,7 +77,7 @@ func (r *NodeSLOReconciler) getNodeSLOSpec(node *corev1.Node, oldSpec *slov1alph } nodeSLOSpec := &slov1alpha1.NodeSLOSpec{ - ResourceUsedThresholdWithBE: config.DefaultResourceThresholdStrategy(), + ResourceUsedThresholdWithBE: util.DefaultResourceThresholdStrategy(), } // TODO: record an event about the failure reason on configmap/crd when failed to load the config diff --git a/pkg/slo-controller/nodeslo/nodeslo_controller_test.go b/pkg/slo-controller/nodeslo/nodeslo_controller_test.go index 9a843a6a2..4fa86657f 100644 --- a/pkg/slo-controller/nodeslo/nodeslo_controller_test.go +++ b/pkg/slo-controller/nodeslo/nodeslo_controller_test.go @@ -35,10 +35,11 @@ import ( slov1alpha1 "github.com/koordinator-sh/koordinator/apis/slo/v1alpha1" "github.com/koordinator-sh/koordinator/pkg/slo-controller/config" + "github.com/koordinator-sh/koordinator/pkg/util" ) func TestNodeSLOReconciler_initNodeSLO(t *testing.T) { - testingResourceThresholdStrategy := config.DefaultResourceThresholdStrategy() + testingResourceThresholdStrategy := util.DefaultResourceThresholdStrategy() testingResourceThresholdStrategy.Enable = pointer.BoolPtr(true) testingResourceThresholdStrategy.CPUSuppressThresholdPercent = pointer.Int64Ptr(60) type args struct { @@ -73,7 +74,7 @@ func TestNodeSLOReconciler_initNodeSLO(t *testing.T) { }, fields: fields{client: fake.NewClientBuilder().Build()}, want: &slov1alpha1.NodeSLOSpec{ - ResourceUsedThresholdWithBE: config.DefaultResourceThresholdStrategy(), + ResourceUsedThresholdWithBE: util.DefaultResourceThresholdStrategy(), }, wantErr: false, }, @@ -98,7 +99,7 @@ func TestNodeSLOReconciler_initNodeSLO(t *testing.T) { }, }).Build()}, want: &slov1alpha1.NodeSLOSpec{ - ResourceUsedThresholdWithBE: config.DefaultResourceThresholdStrategy(), + ResourceUsedThresholdWithBE: util.DefaultResourceThresholdStrategy(), }, wantErr: false, }, @@ -216,7 +217,7 @@ func TestNodeSLOReconciler_Reconcile(t *testing.T) { config.ResourceThresholdConfigKey: "{\"clusterStrategy\":{\"enable\":false,\"cpuSuppressThresholdPercent\":60}}", }, } - testingResourceThresholdStrategy := config.DefaultResourceThresholdStrategy() + testingResourceThresholdStrategy := util.DefaultResourceThresholdStrategy() testingResourceThresholdStrategy.CPUSuppressThresholdPercent = pointer.Int64Ptr(60) nodeSLOSpec := &slov1alpha1.NodeSLOSpec{ diff --git a/pkg/slo-controller/nodeslo/resource_strategy.go b/pkg/slo-controller/nodeslo/resource_strategy.go index b4825cda7..752b5e8e8 100644 --- a/pkg/slo-controller/nodeslo/resource_strategy.go +++ b/pkg/slo-controller/nodeslo/resource_strategy.go @@ -31,7 +31,7 @@ import ( ) func getResourceThresholdSpec(node *corev1.Node, configMap *corev1.ConfigMap) (*slov1alpha1.ResourceThresholdStrategy, error) { - mergedStrategy := config.DefaultResourceThresholdStrategy() + mergedStrategy := util.DefaultResourceThresholdStrategy() // When the custom parameter is missing, return to the default value cfgStr, ok := configMap.Data[config.ResourceThresholdConfigKey] if !ok { diff --git a/pkg/slo-controller/nodeslo/resource_strategy_test.go b/pkg/slo-controller/nodeslo/resource_strategy_test.go index f23414078..7fada06fa 100644 --- a/pkg/slo-controller/nodeslo/resource_strategy_test.go +++ b/pkg/slo-controller/nodeslo/resource_strategy_test.go @@ -29,6 +29,7 @@ import ( slov1alpha1 "github.com/koordinator-sh/koordinator/apis/slo/v1alpha1" "github.com/koordinator-sh/koordinator/pkg/slo-controller/config" + "github.com/koordinator-sh/koordinator/pkg/util" ) func Test_getResourceThresholdSpec(t *testing.T) { @@ -104,7 +105,7 @@ func Test_getResourceThresholdSpec(t *testing.T) { node: &corev1.Node{}, configMap: &corev1.ConfigMap{}, }, - want: config.DefaultResourceThresholdStrategy(), + want: util.DefaultResourceThresholdStrategy(), wantErr: false, }, { @@ -210,10 +211,10 @@ func Test_getResourceThresholdSpec(t *testing.T) { func Test_generateThresholdCfg(t *testing.T) { cfg := config.ResourceThresholdCfg{} - cfg.ClusterStrategy = config.DefaultResourceThresholdStrategy() + cfg.ClusterStrategy = util.DefaultResourceThresholdStrategy() labelSelector := &metav1.LabelSelector{MatchLabels: map[string]string{}} labelSelector.MatchLabels["machineType"] = "F53" - selectCfg := config.NodeResourceThresholdStrategy{NodeSelector: labelSelector, ResourceThresholdStrategy: config.DefaultResourceThresholdStrategy()} + selectCfg := config.NodeResourceThresholdStrategy{NodeSelector: labelSelector, ResourceThresholdStrategy: util.DefaultResourceThresholdStrategy()} cfg.NodeStrategies = []config.NodeResourceThresholdStrategy{selectCfg} cfgJson, _ := json.MarshalIndent(cfg, "", " ") diff --git a/pkg/util/config.go b/pkg/util/config.go index 2459dca1c..8b5ed429f 100644 --- a/pkg/util/config.go +++ b/pkg/util/config.go @@ -31,7 +31,7 @@ func DefaultNodeSLOSpecConfig() slov1alpha1.NodeSLOSpec { func DefaultResourceThresholdStrategy() *slov1alpha1.ResourceThresholdStrategy { return &slov1alpha1.ResourceThresholdStrategy{ - Enable: pointer.BoolPtr(true), + Enable: pointer.BoolPtr(false), CPUSuppressThresholdPercent: pointer.Int64Ptr(65), CPUSuppressPolicy: slov1alpha1.CPUSetPolicy, } diff --git a/pkg/util/container.go b/pkg/util/container.go index 90ab4a0d1..ea6a2ca88 100644 --- a/pkg/util/container.go +++ b/pkg/util/container.go @@ -18,11 +18,155 @@ package util import ( "fmt" + "io/ioutil" + "path" + "strconv" "strings" corev1 "k8s.io/api/core/v1" + + "github.com/koordinator-sh/koordinator/apis/extension" + "github.com/koordinator-sh/koordinator/pkg/util/system" ) +// @parentDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ +// @return kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/****.scope +func GetContainerCgroupPathWithKube(podParentDir string, c *corev1.ContainerStatus) (string, error) { + containerDir, err := system.CgroupPathFormatter.ContainerDirFn(c) + if err != nil { + return "", err + } + return path.Join( + GetPodCgroupDirWithKube(podParentDir), + containerDir, + ), nil +} + +func GetContainerCgroupCPUAcctProcStatPath(podParentDir string, c *corev1.ContainerStatus) (string, error) { + containerPath, err := GetContainerCgroupPathWithKube(podParentDir, c) + if err != nil { + return "", err + } + return system.GetCgroupFilePath(containerPath, system.CpuacctStat), nil +} + +func GetContainerCgroupMemStatPath(podParentDir string, c *corev1.ContainerStatus) (string, error) { + containerPath, err := GetContainerCgroupPathWithKube(podParentDir, c) + if err != nil { + return "", err + } + return system.GetCgroupFilePath(containerPath, system.MemStat), nil +} + +func GetContainerCgroupCPUStatPath(podParentDir string, c *corev1.ContainerStatus) (string, error) { + containerPath, err := GetContainerCgroupPathWithKube(podParentDir, c) + if err != nil { + return "", err + } + return system.GetCgroupFilePath(containerPath, system.CPUStat), nil +} + +func GetContainerCgroupMemLimitPath(podParentDir string, c *corev1.ContainerStatus) (string, error) { + containerPath, err := GetContainerCgroupPathWithKube(podParentDir, c) + if err != nil { + return "", err + } + return system.GetCgroupFilePath(containerPath, system.MemoryLimit), nil +} + +func GetContainerBEMilliCPURequest(c *corev1.Container) int64 { + if cpuRequest, ok := c.Resources.Requests[extension.BatchCPU]; ok { + return cpuRequest.Value() + } + return -1 +} + +func GetContainerBEMilliCPULimit(c *corev1.Container) int64 { + if cpuRequest, ok := c.Resources.Limits[extension.BatchCPU]; ok { + return cpuRequest.Value() + } + return -1 +} + +func GetContainerBEMemoryByteLimit(c *corev1.Container) int64 { + if memLimit, ok := c.Resources.Limits[extension.BatchMemory]; ok { + return memLimit.Value() + } + return -1 +} + +func GetContainerCgroupCPUSharePath(podParentDir string, c *corev1.ContainerStatus) (string, error) { + containerPath, err := GetContainerCgroupPathWithKube(podParentDir, c) + if err != nil { + return "", err + } + return system.GetCgroupFilePath(containerPath, system.CPUShares), nil +} + +func GetContainerCgroupCFSPeriodPath(podParentDir string, c *corev1.ContainerStatus) (string, error) { + containerPath, err := GetContainerCgroupPathWithKube(podParentDir, c) + if err != nil { + return "", err + } + return system.GetCgroupFilePath(containerPath, system.CPUCFSPeriod), nil +} + +func GetContainerCgroupCFSQuotaPath(podParentDir string, c *corev1.ContainerStatus) (string, error) { + containerPath, err := GetContainerCgroupPathWithKube(podParentDir, c) + if err != nil { + return "", err + } + return system.GetCgroupFilePath(containerPath, system.CPUCFSQuota), nil +} + +func GetContainerCurCPUShare(podParentDir string, c *corev1.ContainerStatus) (int64, error) { + cgroupPath, err := GetContainerCgroupCPUSharePath(podParentDir, c) + if err != nil { + return 0, err + } + rawContent, err := ioutil.ReadFile(cgroupPath) + if err != nil { + return 0, err + } + return strconv.ParseInt(strings.TrimSpace(string(rawContent)), 10, 64) +} + +func GetContainerCurCFSPeriod(podParentDir string, c *corev1.ContainerStatus) (int64, error) { + cgroupPath, err := GetContainerCgroupCFSPeriodPath(podParentDir, c) + if err != nil { + return 0, err + } + rawContent, err := ioutil.ReadFile(cgroupPath) + if err != nil { + return 0, err + } + return strconv.ParseInt(strings.TrimSpace(string(rawContent)), 10, 64) +} + +func GetContainerCurCFSQuota(podParentDir string, c *corev1.ContainerStatus) (int64, error) { + cgroupPath, err := GetContainerCgroupCFSQuotaPath(podParentDir, c) + if err != nil { + return 0, err + } + rawContent, err := ioutil.ReadFile(cgroupPath) + if err != nil { + return 0, err + } + return strconv.ParseInt(strings.TrimSpace(string(rawContent)), 10, 64) +} + +func GetContainerCurMemLimitBytes(podParentDir string, c *corev1.ContainerStatus) (int64, error) { + cgroupPath, err := GetContainerCgroupMemLimitPath(podParentDir, c) + if err != nil { + return 0, err + } + rawContent, err := ioutil.ReadFile(cgroupPath) + if err != nil { + return 0, err + } + return strconv.ParseInt(strings.TrimSpace(string(rawContent)), 10, 64) +} + func FindContainerIdAndStatusByName(status *corev1.PodStatus, name string) (string, *corev1.ContainerStatus, error) { allStatuses := status.InitContainerStatuses allStatuses = append(allStatuses, status.ContainerStatuses...) diff --git a/pkg/koordlet/util/container_test.go b/pkg/util/container_test.go similarity index 64% rename from pkg/koordlet/util/container_test.go rename to pkg/util/container_test.go index 51b5a1c52..6fac22e74 100644 --- a/pkg/koordlet/util/container_test.go +++ b/pkg/util/container_test.go @@ -1,32 +1,29 @@ /* -Copyright 2022 The Koordinator 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. -*/ + * Copyright 2022 The Koordinator 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 util import ( "fmt" - "io/ioutil" - "os" - "path/filepath" "testing" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" - "github.com/koordinator-sh/koordinator/pkg/koordlet/util/system" + "github.com/koordinator-sh/koordinator/pkg/util/system" ) func Test_getContainerCgroupPathWithSystemdDriver(t *testing.T) { @@ -175,125 +172,6 @@ func Test_getContainerCgroupPathWithCgroupfsDriver(t *testing.T) { } } -func Test_GetContainerCurTasks(t *testing.T) { - type args struct { - podParentDir string - c *corev1.ContainerStatus - } - type field struct { - containerParentDir string - tasksFileStr string - invalidPath bool - } - tests := []struct { - name string - args args - field field - want []int - wantErr bool - }{ - { - name: "throw an error for empty input", - args: args{ - c: &corev1.ContainerStatus{}, - }, - want: nil, - wantErr: true, - }, - { - name: "parse tasks correctly", - field: field{ - containerParentDir: "pod0/cri-containerd-1.scope", - tasksFileStr: "22264\n22265\n22266\n22267\n29925\n29926\n37587\n41340\n45169\n", - }, - args: args{ - podParentDir: "pod0", - c: &corev1.ContainerStatus{ - ContainerID: "containerd://1", - }, - }, - want: []int{22264, 22265, 22266, 22267, 29925, 29926, 37587, 41340, 45169}, - wantErr: false, - }, - { - name: "throw an error for invalid path", - field: field{ - containerParentDir: "pod0/cri-containerd-1.scope", - tasksFileStr: "22264\n22265\n22266\n22267\n29925\n29926\n37587\n41340\n45169\n", - invalidPath: true, - }, - args: args{ - podParentDir: "pod0", - c: &corev1.ContainerStatus{ - ContainerID: "containerd://1", - }, - }, - want: nil, - wantErr: true, - }, - { - name: "parse error", - field: field{ - containerParentDir: "pod0/cri-containerd-1.scope", - tasksFileStr: "22264\n22265\n22266\n22587\nabs", - }, - args: args{ - podParentDir: "pod0", - c: &corev1.ContainerStatus{ - ContainerID: "containerd://1", - }, - }, - want: nil, - wantErr: true, - }, - { - name: "parse empty", - field: field{ - containerParentDir: "pod0/cri-containerd-1.scope", - tasksFileStr: "", - }, - args: args{ - podParentDir: "pod0", - c: &corev1.ContainerStatus{ - ContainerID: "containerd://1", - }, - }, - want: nil, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - var cgroupRootDir string - cgroupRootDir, _ = ioutil.TempDir("", "GetContainerCurTasks") - defer os.RemoveAll(cgroupRootDir) - - dname := filepath.Join(cgroupRootDir, system.CgroupCPUDir, tt.field.containerParentDir) - err := os.MkdirAll(dname, 0700) - assert.NoError(t, err) - fname := filepath.Join(dname, system.CPUTaskFileName) - _ = ioutil.WriteFile(fname, []byte(tt.field.tasksFileStr), 0666) - - system.Conf = &system.Config{ - CgroupRootDir: cgroupRootDir, - } - // reset Formatter after testing - rawParentDir := system.CgroupPathFormatter.ParentDir - system.CgroupPathFormatter.ParentDir = "" - defer func() { - system.CgroupPathFormatter.ParentDir = rawParentDir - }() - if tt.field.invalidPath { - system.Conf.CgroupRootDir = "invalidPath" - } - - got, err := GetContainerCurTasks(tt.args.podParentDir, tt.args.c) - assert.Equal(t, tt.wantErr, err != nil) - assert.Equal(t, tt.want, got) - }) - } -} - func Test_FindContainerIdAndStatusByName(t *testing.T) { type args struct { diff --git a/pkg/koordlet/util/cpuinfo.go b/pkg/util/cpuinfo.go similarity index 87% rename from pkg/koordlet/util/cpuinfo.go rename to pkg/util/cpuinfo.go index 3bc83af52..9a8e976f3 100644 --- a/pkg/koordlet/util/cpuinfo.go +++ b/pkg/util/cpuinfo.go @@ -1,18 +1,18 @@ /* -Copyright 2022 The Koordinator 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. -*/ + * Copyright 2022 The Koordinator 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 util @@ -27,8 +27,6 @@ import ( "time" "k8s.io/klog/v2" - - "github.com/koordinator-sh/koordinator/pkg/koordlet/util/system" ) const cpuCmdTimeout = 3 * time.Second @@ -36,9 +34,6 @@ const cpuCmdTimeout = 3 * time.Second // CPUBasicInfo describes the cpu basic features and status type CPUBasicInfo struct { HyperThreadEnabled bool `json:"hyperThreadEnabled,omitempty"` - // may support intel turbo in the future - - CatL3CbmMask string `json:"catL3CbmMask,omitempty"` } // ProcessorInfo describes the processor topology information of a single logic cpu, including the core, socket and numa @@ -114,9 +109,6 @@ func getCPUBasicInfo() (*CPUBasicInfo, error) { if cpuBasicInfo.HyperThreadEnabled, err = getHyperThreadEnabled(); err != nil { klog.V(5).Infof("get hyperthreadEnabled info error: %v", err) } - if cpuBasicInfo.CatL3CbmMask, err = system.ReadCatL3CbmString(); err != nil { - klog.V(5).Infof("get l3 cache bit mask error: %v", err) - } return cpuBasicInfo, nil } diff --git a/pkg/koordlet/util/cpuinfo_test.go b/pkg/util/cpuinfo_test.go similarity index 97% rename from pkg/koordlet/util/cpuinfo_test.go rename to pkg/util/cpuinfo_test.go index 39241bcfd..f4f96cf91 100644 --- a/pkg/koordlet/util/cpuinfo_test.go +++ b/pkg/util/cpuinfo_test.go @@ -1,18 +1,18 @@ /* -Copyright 2022 The Koordinator 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. -*/ + * Copyright 2022 The Koordinator 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 util diff --git a/pkg/koordlet/util/feature.go b/pkg/util/feature.go similarity index 100% rename from pkg/koordlet/util/feature.go rename to pkg/util/feature.go diff --git a/pkg/koordlet/util/http.go b/pkg/util/http.go similarity index 100% rename from pkg/koordlet/util/http.go rename to pkg/util/http.go diff --git a/pkg/koordlet/util/meminfo.go b/pkg/util/meminfo.go similarity index 89% rename from pkg/koordlet/util/meminfo.go rename to pkg/util/meminfo.go index 0bc15539e..9c89f0cae 100644 --- a/pkg/koordlet/util/meminfo.go +++ b/pkg/util/meminfo.go @@ -1,18 +1,18 @@ /* -Copyright 2022 The Koordinator 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. -*/ + * Copyright 2022 The Koordinator 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 util diff --git a/pkg/koordlet/util/meminfo_test.go b/pkg/util/meminfo_test.go similarity index 90% rename from pkg/koordlet/util/meminfo_test.go rename to pkg/util/meminfo_test.go index 140593d52..62f9bbc67 100644 --- a/pkg/koordlet/util/meminfo_test.go +++ b/pkg/util/meminfo_test.go @@ -1,18 +1,18 @@ /* -Copyright 2022 The Koordinator 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. -*/ + * Copyright 2022 The Koordinator 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 util @@ -23,11 +23,10 @@ import ( "runtime" "testing" - corev1 "k8s.io/api/core/v1" - "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" - "github.com/koordinator-sh/koordinator/pkg/koordlet/util/system" + "github.com/koordinator-sh/koordinator/pkg/util/system" ) func Test_readMemInfo(t *testing.T) { diff --git a/pkg/util/node.go b/pkg/util/node.go index 9f66e3edd..c45dd254d 100644 --- a/pkg/util/node.go +++ b/pkg/util/node.go @@ -1,27 +1,29 @@ /* -Copyright 2022 The Koordinator 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. -*/ + * Copyright 2022 The Koordinator 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 util import ( "fmt" + "path" corev1 "k8s.io/api/core/v1" slov1alpha1 "github.com/koordinator-sh/koordinator/apis/slo/v1alpha1" + "github.com/koordinator-sh/koordinator/pkg/util/system" ) // GetNodeKey returns a generated key with given node @@ -33,3 +35,25 @@ func GetNodeKey(node *corev1.Node) string { func GetNodeMetricKey(nodeMetric *slov1alpha1.NodeMetric) string { return fmt.Sprintf("%v/%v", nodeMetric.GetNamespace(), nodeMetric.GetName()) } + +// @output like kubepods.slice/kubepods-besteffort.slice/ +func GetKubeQosRelativePath(qosClass corev1.PodQOSClass) string { + return GetPodCgroupDirWithKube(system.CgroupPathFormatter.QOSDirFn(qosClass)) +} + +// GetRootCgroupCPUSetDir gets the cpuset parent directory of the specified podQos' root cgroup +// @output /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-besteffort.slice +func GetRootCgroupCPUSetDir(qosClass corev1.PodQOSClass) string { + rootCgroupParentDir := GetKubeQosRelativePath(qosClass) + return path.Join(system.Conf.CgroupRootDir, system.CgroupCPUSetDir, rootCgroupParentDir) +} + +// GetRootCgroupCurCPUSet gets the current cpuset of the specified podQos' root cgroup +func GetRootCgroupCurCPUSet(qosClass corev1.PodQOSClass) ([]int32, error) { + rawContent, err := system.CgroupFileRead(GetKubeQosRelativePath(qosClass), system.CPUSet) + if err != nil { + return nil, err + } + + return ParseCPUSetStr(rawContent) +} diff --git a/pkg/util/node_test.go b/pkg/util/node_test.go new file mode 100644 index 000000000..fa82e3782 --- /dev/null +++ b/pkg/util/node_test.go @@ -0,0 +1,49 @@ +/* + * Copyright 2022 The Koordinator 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 util + +import ( + "path" + "testing" + + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + + "github.com/koordinator-sh/koordinator/pkg/util/system" +) + +func Test_GetKubeQosRelativePath(t *testing.T) { + + guaranteedPathSystemd := GetKubeQosRelativePath(corev1.PodQOSGuaranteed) + assert.Equal(t, path.Clean(system.KubeRootNameSystemd), guaranteedPathSystemd) + + burstablePathSystemd := GetKubeQosRelativePath(corev1.PodQOSBurstable) + assert.Equal(t, path.Join(system.KubeRootNameSystemd, system.KubeBurstableNameSystemd), burstablePathSystemd) + + besteffortPathSystemd := GetKubeQosRelativePath(corev1.PodQOSBestEffort) + assert.Equal(t, path.Join(system.KubeRootNameSystemd, system.KubeBesteffortNameSystemd), besteffortPathSystemd) + + system.SetupCgroupPathFormatter(system.Cgroupfs) + guaranteedPathCgroupfs := GetKubeQosRelativePath(corev1.PodQOSGuaranteed) + assert.Equal(t, path.Clean(system.KubeRootNameCgroupfs), guaranteedPathCgroupfs) + + burstablePathCgroupfs := GetKubeQosRelativePath(corev1.PodQOSBurstable) + assert.Equal(t, path.Join(system.KubeRootNameCgroupfs, system.KubeBurstableNameCgroupfs), burstablePathCgroupfs) + + besteffortPathCgroupfs := GetKubeQosRelativePath(corev1.PodQOSBestEffort) + assert.Equal(t, path.Join(system.KubeRootNameCgroupfs, system.KubeBesteffortNameCgroupfs), besteffortPathCgroupfs) +} diff --git a/pkg/util/pod.go b/pkg/util/pod.go index cdaaa9695..c0938bb23 100644 --- a/pkg/util/pod.go +++ b/pkg/util/pod.go @@ -1,30 +1,205 @@ /* -Copyright 2022 The Koordinator 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. -*/ + * Copyright 2022 The Koordinator 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 util import ( "fmt" + "io/ioutil" + "path" + "strconv" + "strings" corev1 "k8s.io/api/core/v1" quotav1 "k8s.io/apiserver/pkg/quota/v1" + "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos" slov1alpha1 "github.com/koordinator-sh/koordinator/apis/slo/v1alpha1" + "github.com/koordinator-sh/koordinator/pkg/util/system" ) +// @kubeRelativeDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ +// @return kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ +func GetPodCgroupDirWithKube(podKubeRelativeDir string) string { + return path.Join(system.CgroupPathFormatter.ParentDir, podKubeRelativeDir) +} + +// @return like kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ +func GetPodKubeRelativePath(pod *corev1.Pod) string { + qosClass := GetKubeQosClass(pod) + return path.Join( + system.CgroupPathFormatter.QOSDirFn(qosClass), + system.CgroupPathFormatter.PodDirFn(qosClass, string(pod.UID)), + ) +} + +// @podParentDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ +// @output /sys/fs/cgroup/cpuacct/kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/cpuacct.proc_stat +func GetPodCgroupCPUAcctProcStatPath(podParentDir string) string { + podPath := GetPodCgroupDirWithKube(podParentDir) + return system.GetCgroupFilePath(podPath, system.CpuacctStat) +} + +// @podParentDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ +// @output /sys/fs/cgroup/cpu/kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/cpu.shares +func GetPodCgroupCPUSharePath(podParentDir string) string { + podPath := GetPodCgroupDirWithKube(podParentDir) + return system.GetCgroupFilePath(podPath, system.CPUShares) +} + +func GetPodCgroupCFSPeriodPath(podParentDir string) string { + podPath := GetPodCgroupDirWithKube(podParentDir) + return system.GetCgroupFilePath(podPath, system.CPUCFSPeriod) +} + +// @podParentDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ +// @output /sys/fs/cgroup/cpu/kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/cpu.cfs_quota_us +func GetPodCgroupCFSQuotaPath(podParentDir string) string { + podPath := GetPodCgroupDirWithKube(podParentDir) + return system.GetCgroupFilePath(podPath, system.CPUCFSQuota) +} + +// @podParentDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ +// @output /sys/fs/cgroup/cpuacct/kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/cpuacct.proc_stat +func GetPodCgroupMemStatPath(podParentDir string) string { + podPath := GetPodCgroupDirWithKube(podParentDir) + return system.GetCgroupFilePath(podPath, system.MemStat) +} + +// @podParentDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ +// @output /sys/fs/cgroup/memory/kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/memory.limit_in_bytes +func GetPodCgroupMemLimitPath(podParentDir string) string { + podPath := GetPodCgroupDirWithKube(podParentDir) + return system.GetCgroupFilePath(podPath, system.MemoryLimit) +} + +// @podParentDir kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/ +// @output /sys/fs/cgroup/cpu/kubepods.slice/kubepods-burstable.slice/kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice/cpu.stat +func GetPodCgroupCPUStatPath(podParentDir string) string { + podPath := GetPodCgroupDirWithKube(podParentDir) + return system.GetCgroupFilePath(podPath, system.CPUStat) +} + +func GetKubeQosClass(pod *corev1.Pod) corev1.PodQOSClass { + qosClass := pod.Status.QOSClass + if qosClass == "" { + qosClass = qos.GetPodQOS(pod) + } + return qosClass +} + +func GetPodBEMilliCPURequest(pod *corev1.Pod) int64 { + podCPUMilliReq := int64(0) + for _, container := range pod.Spec.Containers { + containerCPUMilliReq := GetContainerBEMilliCPURequest(&container) + if containerCPUMilliReq <= 0 { + return -1 + } + podCPUMilliReq += containerCPUMilliReq + } + if podCPUMilliReq <= 0 { + return -1 + } + return podCPUMilliReq +} + +func GetPodBEMilliCPULimit(pod *corev1.Pod) int64 { + podCPUMilliLimit := int64(0) + for _, container := range pod.Spec.Containers { + containerCPUMilliLimit := GetContainerBEMilliCPULimit(&container) + if containerCPUMilliLimit <= 0 { + return -1 + } + podCPUMilliLimit += containerCPUMilliLimit + } + if podCPUMilliLimit <= 0 { + return -1 + } + return podCPUMilliLimit +} + +func GetPodBEMemoryByteLimit(pod *corev1.Pod) int64 { + podMemoryByteLimit := int64(0) + for _, container := range pod.Spec.Containers { + containerMemByteLimit := GetContainerBEMemoryByteLimit(&container) + if containerMemByteLimit <= 0 { + return -1 + } + podMemoryByteLimit += containerMemByteLimit + } + if podMemoryByteLimit <= 0 { + return -1 + } + return podMemoryByteLimit +} + +func GetPodCurCPUShare(podParentDir string) (int64, error) { + cgroupPath := GetPodCgroupCPUSharePath(podParentDir) + rawContent, err := ioutil.ReadFile(cgroupPath) + if err != nil { + return 0, err + } + return strconv.ParseInt(strings.TrimSpace(string(rawContent)), 10, 64) +} + +func GetPodCurCFSPeriod(podParentDir string) (int64, error) { + cgroupPath := GetPodCgroupCFSPeriodPath(podParentDir) + rawContent, err := ioutil.ReadFile(cgroupPath) + if err != nil { + return 0, err + } + return strconv.ParseInt(strings.TrimSpace(string(rawContent)), 10, 64) +} + +func GetPodCurCFSQuota(podParentDir string) (int64, error) { + cgroupPath := GetPodCgroupCFSQuotaPath(podParentDir) + rawContent, err := ioutil.ReadFile(cgroupPath) + if err != nil { + return 0, err + } + return strconv.ParseInt(strings.TrimSpace(string(rawContent)), 10, 64) +} + +func GetPodCurMemLimitBytes(podParentDir string) (int64, error) { + cgroupPath := GetPodCgroupMemLimitPath(podParentDir) + rawContent, err := ioutil.ReadFile(cgroupPath) + if err != nil { + return 0, err + } + return strconv.ParseInt(strings.TrimSpace(string(rawContent)), 10, 64) +} + +// @return like kubepods.slice/kubepods-burstable.slice/ +func GetPodQoSRelativePath(qosClass corev1.PodQOSClass) string { + return path.Join( + system.CgroupPathFormatter.ParentDir, + system.CgroupPathFormatter.QOSDirFn(qosClass), + ) +} + +// @return 7712555c_ce62_454a_9e18_9ff0217b8941 from kubepods-pod7712555c_ce62_454a_9e18_9ff0217b8941.slice +func ParsePodID(basename string) (string, error) { + return system.CgroupPathFormatter.PodIDParser(basename) +} + +// @return 7712555c_ce62_454a_9e18_9ff0217b8941 from docker-7712555c_ce62_454a_9e18_9ff0217b8941.scope +func ParseContainerID(basename string) (string, error) { + return system.CgroupPathFormatter.ContainerIDParser(basename) +} + func GetPodKey(pod *corev1.Pod) string { return fmt.Sprintf("%v/%v", pod.GetNamespace(), pod.GetName()) } diff --git a/pkg/koordlet/util/pod_test.go b/pkg/util/pod_test.go similarity index 78% rename from pkg/koordlet/util/pod_test.go rename to pkg/util/pod_test.go index 59ad6ee8b..dae84c0db 100644 --- a/pkg/koordlet/util/pod_test.go +++ b/pkg/util/pod_test.go @@ -1,18 +1,18 @@ /* -Copyright 2022 The Koordinator 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. -*/ + * Copyright 2022 The Koordinator 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 util @@ -26,12 +26,12 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" - sysutil "github.com/koordinator-sh/koordinator/pkg/koordlet/util/system" + "github.com/koordinator-sh/koordinator/pkg/util/system" ) func Test_GetRootCgroupCPUSetDirWithSystemdDriver(t *testing.T) { - sysutil.SetupCgroupPathFormatter(sysutil.Systemd) - defer sysutil.SetupCgroupPathFormatter(sysutil.Systemd) + system.SetupCgroupPathFormatter(system.Systemd) + defer system.SetupCgroupPathFormatter(system.Systemd) tests := []struct { name string args corev1.PodQOSClass @@ -59,7 +59,7 @@ func Test_GetRootCgroupCPUSetDirWithSystemdDriver(t *testing.T) { }, } for _, tt := range tests { - sysutil.Conf = sysutil.NewDsModeConfig() + system.Conf = system.NewDsModeConfig() t.Run(tt.name, func(t *testing.T) { got := GetRootCgroupCPUSetDir(tt.args) if tt.want != got { @@ -70,8 +70,8 @@ func Test_GetRootCgroupCPUSetDirWithSystemdDriver(t *testing.T) { } func Test_GetRootCgroupCPUSetDirWithCgroupfsDriver(t *testing.T) { - sysutil.SetupCgroupPathFormatter(sysutil.Cgroupfs) - defer sysutil.SetupCgroupPathFormatter(sysutil.Systemd) + system.SetupCgroupPathFormatter(system.Cgroupfs) + defer system.SetupCgroupPathFormatter(system.Systemd) tests := []struct { name string args corev1.PodQOSClass @@ -99,7 +99,7 @@ func Test_GetRootCgroupCPUSetDirWithCgroupfsDriver(t *testing.T) { }, } for _, tt := range tests { - sysutil.Conf = sysutil.NewDsModeConfig() + system.Conf = system.NewDsModeConfig() t.Run(tt.name, func(t *testing.T) { got := GetRootCgroupCPUSetDir(tt.args) if tt.want != got { @@ -182,23 +182,23 @@ func Test_GetRootCgroupCurCPUSet(t *testing.T) { // prepare testing tmp files var cgroupRootDir string cgroupRootDir, _ = ioutil.TempDir("", "GetRootCgroupCurCPUSet") - dname := filepath.Join(cgroupRootDir, sysutil.CgroupCPUSetDir) + dname := filepath.Join(cgroupRootDir, system.CgroupCPUSetDir) err := os.MkdirAll(dname, 0700) if err != nil { t.Errorf("failed to prepare tmpdir in %v, err: %v", "GetRootCgroupCurCPUSet", err) return } - fname := filepath.Join(dname, sysutil.CPUSFileName) + fname := filepath.Join(dname, system.CPUSFileName) _ = ioutil.WriteFile(fname, []byte{'1', ',', '2'}, 0666) - sysutil.Conf = &sysutil.Config{ + system.Conf = &system.Config{ CgroupRootDir: cgroupRootDir, } // reset Formatter after testing - rawParentDir := sysutil.CgroupPathFormatter.ParentDir - sysutil.CgroupPathFormatter.ParentDir = "" + rawParentDir := system.CgroupPathFormatter.ParentDir + system.CgroupPathFormatter.ParentDir = "" defer func() { - sysutil.CgroupPathFormatter.ParentDir = rawParentDir + system.CgroupPathFormatter.ParentDir = rawParentDir }() wantCPUSet := []int32{1, 2} diff --git a/pkg/koordlet/util/stat.go b/pkg/util/stat.go similarity index 71% rename from pkg/koordlet/util/stat.go rename to pkg/util/stat.go index 1b2876149..b0c1cb6dc 100644 --- a/pkg/koordlet/util/stat.go +++ b/pkg/util/stat.go @@ -1,18 +1,18 @@ /* -Copyright 2022 The Koordinator 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. -*/ + * Copyright 2022 The Koordinator 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 util @@ -25,7 +25,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/sets" - sysutil "github.com/koordinator-sh/koordinator/pkg/koordlet/util/system" + "github.com/koordinator-sh/koordinator/pkg/util/system" ) var ( @@ -62,7 +62,7 @@ func readTotalCPUStat(statPath string) (uint64, error) { // GetCPUStatUsageTicks returns the node's CPU usage ticks func GetCPUStatUsageTicks() (uint64, error) { - return readTotalCPUStat(sysutil.ProcStatFile.File) + return readTotalCPUStat(system.ProcStatFile.File) } func readCPUAcctStatUsageTicks(statPath string) (uint64, error) { @@ -100,9 +100,3 @@ func GetContainerCPUStatUsageTicks(podCgroupDir string, c *corev1.ContainerStatu } return readCPUAcctStatUsageTicks(containerStatPath) } - -func GetRootCgroupCPUStatUsageTicks(qosClass corev1.PodQOSClass) (uint64, error) { - rootCgroupParentDir := GetKubeQosRelativePath(qosClass) - statPath := sysutil.GetCgroupFilePath(rootCgroupParentDir, sysutil.CpuacctStat) - return readCPUAcctStatUsageTicks(statPath) -} diff --git a/pkg/koordlet/util/stat_test.go b/pkg/util/stat_test.go similarity index 76% rename from pkg/koordlet/util/stat_test.go rename to pkg/util/stat_test.go index ec77a1584..0ddb5de22 100644 --- a/pkg/koordlet/util/stat_test.go +++ b/pkg/util/stat_test.go @@ -1,18 +1,18 @@ /* -Copyright 2022 The Koordinator 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. -*/ + * Copyright 2022 The Koordinator 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 util @@ -23,11 +23,10 @@ import ( "runtime" "testing" - corev1 "k8s.io/api/core/v1" - "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" - sysutil "github.com/koordinator-sh/koordinator/pkg/koordlet/util/system" + "github.com/koordinator-sh/koordinator/pkg/util/system" ) func Test_readTotalCPUStat(t *testing.T) { @@ -92,7 +91,7 @@ func Test_GetCPUStatUsageTicks(t *testing.T) { t.Log("Ignore non-Linux environment") return } - sysutil.SetConf(*sysutil.NewHostModeConfig()) + system.SetConf(*system.NewHostModeConfig()) cpuStatUsage, err := GetCPUStatUsageTicks() if err != nil { t.Error("failed to get CPU stat usage: ", err) @@ -107,7 +106,7 @@ func Test_readPodCPUStatUsageTicks(t *testing.T) { t.Error(err) } tempInvalidPodCgroupDir := filepath.Join(tempDir, "no_cgroup") - tempPodStatPath := filepath.Join(tempDir, sysutil.CpuacctStatFileName) + tempPodStatPath := filepath.Join(tempDir, system.CpuacctStatFileName) statContentStr := getStatContents() err = ioutil.WriteFile(tempPodStatPath, []byte(statContentStr), 0666) if err != nil { @@ -154,20 +153,11 @@ func Test_GetPodCPUStatUsageTicks(t *testing.T) { if err != nil { t.Error(err) } - sysutil.Conf = sysutil.NewDsModeConfig() + system.Conf = system.NewDsModeConfig() _, err = GetPodCPUStatUsageTicks(tempDir) assert.NotNil(t, err) } -func Test_GetRootCgroupCPUStatUsageTicks(t *testing.T) { - helper := sysutil.NewFileTestUtil(t) - defer helper.Cleanup() - helper.WriteCgroupFileContents(GetKubeQosRelativePath(corev1.PodQOSBestEffort), sysutil.CpuacctStat, getStatContents()) - got, err := GetRootCgroupCPUStatUsageTicks(corev1.PodQOSBestEffort) - assert.NoError(t, err) - assert.Equal(t, uint64(1356232), got) -} - func getStatContents() string { return "user 407232\nnice 60223\nsystem 888777\nidle 3710549851\niowait 7638\nirq 0\nsoftirq 0\n" + "steal 1115801\nguest 0\nload average(1min) 5\nload average(5min) 1\nload average(15min) 0\n" + @@ -175,7 +165,7 @@ func getStatContents() string { } func TestGetContainerCPUStatUsageTicks(t *testing.T) { - helper := sysutil.NewFileTestUtil(t) + helper := system.NewFileTestUtil(t) defer helper.Cleanup() podCgroupDir := "pod-cgroup-dir" container := &corev1.ContainerStatus{ @@ -183,7 +173,7 @@ func TestGetContainerCPUStatUsageTicks(t *testing.T) { ContainerID: "docker://test-container-id", } containerDir, _ := GetContainerCgroupPathWithKube(podCgroupDir, container) - helper.WriteCgroupFileContents(containerDir, sysutil.CpuacctStat, getStatContents()) + helper.WriteCgroupFileContents(containerDir, system.CpuacctStat, getStatContents()) got, err := GetContainerCPUStatUsageTicks(podCgroupDir, container) assert.NoError(t, err) assert.Equal(t, uint64(1356232), got) diff --git a/pkg/koordlet/util/system/cgroup.go b/pkg/util/system/cgroup.go similarity index 72% rename from pkg/koordlet/util/system/cgroup.go rename to pkg/util/system/cgroup.go index e6e05d470..545dc021b 100644 --- a/pkg/koordlet/util/system/cgroup.go +++ b/pkg/util/system/cgroup.go @@ -20,7 +20,6 @@ import ( "fmt" "io/ioutil" "math" - "os" "path" "strconv" "strings" @@ -32,14 +31,12 @@ const ( CPUShareKubeBEValue int64 = 2 CPUShareUnitValue int64 = 1024 CFSQuotaUnlimitedValue int64 = -1 - CPUBvtLSValue int64 = 2 - CPUBvtBEValue int64 = -1 - CgroupMaxSymbolStr string = "max" // currently only appear in `memory.high`, we consider the value as MaxInt64 - CgroupMaxValueStr string = "9223372036854775807" // math.MaxInt64; writing `memory.high` with this do the same as set as "max" + // CgroupMaxSymbolStr only appears in `memory.high`, we consider the value as MaxInt64 + CgroupMaxSymbolStr string = "max" ) -const EmptyValueError = "EmptyValueError" +const EmptyValueError string = "EmptyValueError" type CPUStatRaw struct { NrPeriod int64 @@ -47,20 +44,6 @@ type CPUStatRaw struct { ThrottledNanoSeconds int64 } -func CgroupFileWriteIfDifferent(cgroupTaskDir string, file CgroupFile, value string) error { - currentValue, currentErr := CgroupFileRead(cgroupTaskDir, file) - if currentErr != nil { - return currentErr - } - if value == currentValue || value == CgroupMaxValueStr && currentValue == CgroupMaxSymbolStr { - // compatible with cgroup valued "max" - klog.V(6).Infof("read before write %s %s and got str value, considered as MaxInt64", cgroupTaskDir, - file.ResourceFileName) - return nil - } - return CgroupFileWrite(cgroupTaskDir, file, value) -} - func CgroupFileReadInt(cgroupTaskDir string, file CgroupFile) (*int64, error) { if file.IsAliOS && !HostSystemInfo.IsAliOS { return nil, fmt.Errorf("read cgroup config : %s fail, need alios kernel", file.ResourceFileName) @@ -116,41 +99,6 @@ func GetCgroupFilePath(cgroupTaskDir string, file CgroupFile) string { return path.Join(Conf.CgroupRootDir, file.Subfs, cgroupTaskDir, file.ResourceFileName) } -func CPUIdentityEnabled() (bool, error) { - rootBvtFilePath := GetCgroupFilePath("/", CPUBVTWarpNs) - _, err := os.Stat(rootBvtFilePath) - if err == nil { - // file exist, cpu identity enabled - return true, nil - } else if os.IsNotExist(err) { - // file not exist, cpu identity disabled - return false, nil - } else { - return false, fmt.Errorf("check cpu identity enabled failed %v", err) - } -} - -func GetCgroupCurTasks(cgroupPath string) ([]int, error) { - var tasks []int - rawContent, err := ioutil.ReadFile(cgroupPath) - if err != nil { - return nil, err - } - lines := strings.Split(string(rawContent), "\n") - for _, line := range lines { - line = strings.TrimSpace(line) - if len(line) <= 0 { - continue - } - task, err := strconv.Atoi(line) - if err != nil { - return nil, err - } - tasks = append(tasks, task) - } - return tasks, nil -} - func GetCPUStatRaw(cgroupPath string) (*CPUStatRaw, error) { content, err := ioutil.ReadFile(cgroupPath) if err != nil { diff --git a/pkg/koordlet/util/system/cgroup_driver.go b/pkg/util/system/cgroup_driver.go similarity index 100% rename from pkg/koordlet/util/system/cgroup_driver.go rename to pkg/util/system/cgroup_driver.go diff --git a/pkg/koordlet/util/system/cgroup_driver_linux.go b/pkg/util/system/cgroup_driver_linux.go similarity index 100% rename from pkg/koordlet/util/system/cgroup_driver_linux.go rename to pkg/util/system/cgroup_driver_linux.go diff --git a/pkg/koordlet/util/system/cgroup_driver_linux_test.go b/pkg/util/system/cgroup_driver_linux_test.go similarity index 70% rename from pkg/koordlet/util/system/cgroup_driver_linux_test.go rename to pkg/util/system/cgroup_driver_linux_test.go index fa8b54a70..0cafbef6f 100644 --- a/pkg/koordlet/util/system/cgroup_driver_linux_test.go +++ b/pkg/util/system/cgroup_driver_linux_test.go @@ -2,20 +2,20 @@ // +build linux /* -Copyright 2022 The Koordinator 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. -*/ + * Copyright 2022 The Koordinator 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 system diff --git a/pkg/koordlet/util/system/cgroup_driver_test.go b/pkg/util/system/cgroup_driver_test.go similarity index 100% rename from pkg/koordlet/util/system/cgroup_driver_test.go rename to pkg/util/system/cgroup_driver_test.go diff --git a/pkg/koordlet/util/system/cgroup_driver_unsupported.go b/pkg/util/system/cgroup_driver_unsupported.go similarity index 100% rename from pkg/koordlet/util/system/cgroup_driver_unsupported.go rename to pkg/util/system/cgroup_driver_unsupported.go diff --git a/pkg/util/system/cgroup_resource.go b/pkg/util/system/cgroup_resource.go new file mode 100644 index 000000000..2f8b94ba7 --- /dev/null +++ b/pkg/util/system/cgroup_resource.go @@ -0,0 +1,69 @@ +/* +Copyright 2022 The Koordinator 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 system + +import "math" + +const ( + // subfs name + CgroupCPUDir string = "cpu/" + CgroupCPUSetDir string = "cpuset/" + CgroupCPUacctDir string = "cpuacct/" + CgroupMemDir string = "memory/" +) + +const ( + CPUStatFileName = "cpu.stat" + CPUSharesFileName = "cpu.shares" + CPUCFSQuotaName = "cpu.cfs_quota_us" + CPUCFSPeriodName = "cpu.cfs_period_us" + CPUBVTWarpNsName = "cpu.bvt_warp_ns" + CPUSFileName = "cpuset.cpus" + + CpuacctStatFileName = "cpuacct.stat" + + MemWmarkRatioFileName = "memory.wmark_ratio" + MemHighFileName = "memory.high" + MemoryLimitFileName = "memory.limit_in_bytes" + MemStatFileName = "memory.stat" +) + +var ( + MemHighValidator = &RangeValidator{name: MemHighFileName, min: 0, max: math.MaxInt64} +) + +var ( + CPUStat = CgroupFile{ResourceFileName: CPUStatFileName, Subfs: CgroupCPUDir, IsAliOS: false} + CPUShares = CgroupFile{ResourceFileName: CPUSharesFileName, Subfs: CgroupCPUDir, IsAliOS: false} + CPUCFSQuota = CgroupFile{ResourceFileName: CPUCFSQuotaName, Subfs: CgroupCPUDir, IsAliOS: false} + CPUCFSPeriod = CgroupFile{ResourceFileName: CPUCFSPeriodName, Subfs: CgroupCPUDir, IsAliOS: false} + + CPUSet = CgroupFile{ResourceFileName: CPUSFileName, Subfs: CgroupCPUSetDir, IsAliOS: false} + + CpuacctStat = CgroupFile{ResourceFileName: CpuacctStatFileName, Subfs: CgroupCPUacctDir, IsAliOS: false} + + MemStat = CgroupFile{ResourceFileName: MemStatFileName, Subfs: CgroupMemDir, IsAliOS: false} + MemHigh = CgroupFile{ResourceFileName: MemHighFileName, Subfs: CgroupMemDir, IsAliOS: true, Validator: MemHighValidator} + MemoryLimit = CgroupFile{ResourceFileName: MemoryLimitFileName, Subfs: CgroupMemDir, IsAliOS: false} +) + +type CgroupFile struct { + ResourceFileName string + Subfs string + IsAliOS bool + Validator Validate +} diff --git a/pkg/koordlet/util/system/cgroup_test.go b/pkg/util/system/cgroup_test.go similarity index 68% rename from pkg/koordlet/util/system/cgroup_test.go rename to pkg/util/system/cgroup_test.go index 628f29fb2..d472f6a25 100644 --- a/pkg/koordlet/util/system/cgroup_test.go +++ b/pkg/util/system/cgroup_test.go @@ -23,75 +23,6 @@ import ( "github.com/stretchr/testify/assert" ) -func TestCgroupFileWriteUintIfDifferent(t *testing.T) { - taskDir := "/" - - type args struct { - file CgroupFile - oldValue string - newValue string - } - - tests := []struct { - name string - args args - expectOld string - expectNew string - }{ - { - name: "test_diffent_value", - args: args{ - file: CPUShares, - oldValue: "1024", - newValue: "2", - }, - expectOld: "1024", - expectNew: "2", - }, - { - name: "test_equal_value", - args: args{ - file: CPUShares, - oldValue: "2", - newValue: "2", - }, - expectOld: "2", - expectNew: "2", - }, - { - name: "test_equal_value_for_max_str", - args: args{ - file: MemHigh, - oldValue: CgroupMaxSymbolStr, - newValue: CgroupMaxValueStr, - }, - expectOld: CgroupMaxSymbolStr, - expectNew: CgroupMaxSymbolStr, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - helper := NewFileTestUtil(t) - defer helper.Cleanup() - helper.CreateCgroupFile(taskDir, tt.args.file) - - err := CgroupFileWriteIfDifferent(taskDir, tt.args.file, tt.args.oldValue) - assert.NoError(t, err) - - gotOld, _ := CgroupFileRead(taskDir, tt.args.file) - assert.Equal(t, tt.expectOld, gotOld) - - err = CgroupFileWriteIfDifferent(taskDir, tt.args.file, tt.args.newValue) - assert.NoError(t, err) - gotNew, _ := CgroupFileRead(taskDir, tt.args.file) - assert.Equal(t, tt.expectNew, gotNew) - - }) - } - -} - func TestCgroupFileReadInt(t *testing.T) { taskDir := "/" testingInt64 := int64(1024) @@ -153,38 +84,6 @@ func TestCgroupFileReadInt(t *testing.T) { } -func Test_CPUIdentityEnabled(t *testing.T) { - tests := []struct { - name string - cgroupFile CgroupFile - expect bool - }{ - { - name: "alios_bvt_test", - cgroupFile: CPUBVTWarpNs, - expect: true, - }, - { - name: "not_alios_test", - cgroupFile: CPUShares, - expect: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - helper := NewFileTestUtil(t) - defer helper.Cleanup() - helper.CreateCgroupFile("/", tt.cgroupFile) - - enable, _ := CPUIdentityEnabled() - assert.Equal(t, tt.expect, enable) - - }) - } - -} - func genCPUStatContent() string { return "nr_periods 18491717\n" + "nr_throttled 12\n" + diff --git a/pkg/koordlet/util/system/common.go b/pkg/util/system/common.go similarity index 64% rename from pkg/koordlet/util/system/common.go rename to pkg/util/system/common.go index ec354c953..9b28d2c6d 100644 --- a/pkg/koordlet/util/system/common.go +++ b/pkg/util/system/common.go @@ -20,41 +20,8 @@ import ( "io" "io/ioutil" "os" - "path" - "strings" - - "k8s.io/klog/v2" -) - -var ( - CommonRootDir = "" // for uni-test ) -func CommonFileRead(file string) (string, error) { - file = path.Join(CommonRootDir, file) - klog.V(5).Infof("read %s", file) - data, err := ioutil.ReadFile(file) - return strings.Trim(string(data), "\n"), err -} - -func CommonFileWriteIfDifferent(file string, value string) error { - currentValue, err := CommonFileRead(file) - if err != nil { - return err - } - if value == currentValue { - klog.Infof("resource currentValue equal newValue, skip update resource! file:%s, value %s", file, value) - return nil - } - return CommonFileWrite(file, value) -} - -func CommonFileWrite(file string, data string) error { - file = path.Join(CommonRootDir, file) - klog.V(5).Infof("write %s [%s]", file, data) - return ioutil.WriteFile(file, []byte(data), 0644) -} - // ReadFileNoStat uses ioutil.ReadAll to read contents of entire file. // This is similar to ioutil.ReadFile but without the call to os.Stat, because // many files in /proc and /sys report incorrect file sizes (either 0 or 4096). diff --git a/pkg/koordlet/util/system/common_linux.go b/pkg/util/system/common_linux.go similarity index 84% rename from pkg/koordlet/util/system/common_linux.go rename to pkg/util/system/common_linux.go index c5509ed9c..83b328c44 100644 --- a/pkg/koordlet/util/system/common_linux.go +++ b/pkg/util/system/common_linux.go @@ -2,20 +2,20 @@ // +build linux /* -Copyright 2022 The Koordinator 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. -*/ + * Copyright 2022 The Koordinator 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 system diff --git a/pkg/koordlet/util/system/common_linux_test.go b/pkg/util/system/common_linux_test.go similarity index 66% rename from pkg/koordlet/util/system/common_linux_test.go rename to pkg/util/system/common_linux_test.go index b4bce8c11..28ac25393 100644 --- a/pkg/koordlet/util/system/common_linux_test.go +++ b/pkg/util/system/common_linux_test.go @@ -2,20 +2,20 @@ // +build linux /* -Copyright 2022 The Koordinator 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. -*/ + * Copyright 2022 The Koordinator 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 system diff --git a/pkg/koordlet/util/system/common_test.go b/pkg/util/system/common_test.go similarity index 52% rename from pkg/koordlet/util/system/common_test.go rename to pkg/util/system/common_test.go index 3ac30c2fd..1476e9a65 100644 --- a/pkg/koordlet/util/system/common_test.go +++ b/pkg/util/system/common_test.go @@ -21,12 +21,6 @@ import ( "reflect" "testing" "time" - - "github.com/stretchr/testify/assert" -) - -var ( - minFreeKbytesFile = "/proc/sys/vm/min_free_kbytes" ) type TestMetric struct { @@ -58,59 +52,3 @@ func Test_reflect(t *testing.T) { } printMetrics(metrics) } - -func Test_CommonFileWriteIfDifferent(t *testing.T) { - - type args struct { - file string - oldValue string - newValue string - } - - tests := []struct { - name string - args args - expectOld string - expectNew string - }{ - { - name: "test_diffent_value", - args: args{ - file: minFreeKbytesFile, - oldValue: "10000000", - newValue: "20000000", - }, - expectOld: "10000000", - expectNew: "20000000", - }, - { - name: "test_equal_value", - args: args{ - file: minFreeKbytesFile, - oldValue: "10000000", - newValue: "10000000", - }, - expectOld: "10000000", - expectNew: "10000000", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - helper := NewFileTestUtil(t) - defer helper.Cleanup() - helper.CreateFile(tt.args.file) - - CommonFileWriteIfDifferent(tt.args.file, tt.args.oldValue) - - gotOld, _ := CommonFileRead(tt.args.file) - assert.Equal(t, tt.expectOld, gotOld) - - CommonFileWriteIfDifferent(tt.args.file, tt.args.newValue) - gotNew, _ := CommonFileRead(tt.args.file) - assert.Equal(t, tt.expectNew, gotNew) - - }) - } - -} diff --git a/pkg/koordlet/util/system/common_unsupported.go b/pkg/util/system/common_unsupported.go similarity index 100% rename from pkg/koordlet/util/system/common_unsupported.go rename to pkg/util/system/common_unsupported.go diff --git a/pkg/koordlet/util/system/config.go b/pkg/util/system/config.go similarity index 100% rename from pkg/koordlet/util/system/config.go rename to pkg/util/system/config.go diff --git a/pkg/koordlet/util/system/resctrl_unsupported.go b/pkg/util/system/system_file.go similarity index 67% rename from pkg/koordlet/util/system/resctrl_unsupported.go rename to pkg/util/system/system_file.go index f23dd46af..6d7616e9e 100644 --- a/pkg/koordlet/util/system/resctrl_unsupported.go +++ b/pkg/util/system/system_file.go @@ -1,6 +1,3 @@ -//go:build !linux -// +build !linux - /* Copyright 2022 The Koordinator Authors. @@ -19,9 +16,27 @@ limitations under the License. package system -import "fmt" +import ( + "path" +) + +const ( + ProcStatFileName = "stat" +) + +type SystemFile struct { + File string + Validator Validate +} + +var ( + ProcStatFile SystemFile +) + +func init() { + initFilePath() +} -// MountResctrlSubsystem is not supported for non-linux os -func MountResctrlSubsystem() (bool, error) { - return false, fmt.Errorf("only support linux") +func initFilePath() { + ProcStatFile = SystemFile{File: path.Join(Conf.ProcRootDir, ProcStatFileName)} } diff --git a/pkg/koordlet/util/system/util_test_tool.go b/pkg/util/system/util_test_tool.go similarity index 68% rename from pkg/koordlet/util/system/util_test_tool.go rename to pkg/util/system/util_test_tool.go index 3c12a1d9f..9170c962c 100644 --- a/pkg/koordlet/util/system/util_test_tool.go +++ b/pkg/util/system/util_test_tool.go @@ -20,11 +20,7 @@ import ( "io/ioutil" "os" "path" - "runtime" "testing" - - "github.com/vishvananda/netlink" - "github.com/vishvananda/netns" ) type FileTestUtil struct { @@ -46,7 +42,6 @@ func NewFileTestUtil(t *testing.T) *FileTestUtil { Conf.ProcRootDir = path.Join(tempDir, "proc") os.MkdirAll(Conf.ProcRootDir, 0777) Conf.CgroupRootDir = tempDir - CommonRootDir = tempDir return &FileTestUtil{TempDir: tempDir, t: t} } @@ -55,15 +50,6 @@ func (c *FileTestUtil) Cleanup() { os.RemoveAll(c.TempDir) } -func (c *FileTestUtil) CreateFiles(files []string) { - for _, file := range files { - filePath := path.Join(c.TempDir, file) - if _, err := os.Create(filePath); err != nil { - c.t.Fatal(err) - } - } -} - func (c *FileTestUtil) MkDirAll(dirRelativePath string) { dir := path.Join(c.TempDir, dirRelativePath) if err := os.MkdirAll(dir, 0777); err != nil { @@ -99,17 +85,6 @@ func (c *FileTestUtil) ReadFileContents(fileRelativePath string) string { return string(contents) } -func (c *FileTestUtil) GetAbsoluteFilePath(fileRelativePath string) string { - return path.Join(c.TempDir, fileRelativePath) -} - -func (c *FileTestUtil) MkProcSubDirAll(dirRelativePath string) { - dir := path.Join(Conf.ProcRootDir, dirRelativePath) - if err := os.MkdirAll(dir, 0777); err != nil { - c.t.Fatal(err) - } -} - func (c *FileTestUtil) CreateProcSubFile(fileRelativePath string) { file := path.Join(Conf.ProcRootDir, fileRelativePath) dir, _ := path.Split(file) @@ -170,51 +145,3 @@ func (c *FileTestUtil) ReadCgroupFileContents(taskDir string, file CgroupFile) s } return contents } - -type NetworkTestUtil struct { - t *testing.T - ns netns.NsHandle -} - -func NewNetworkTestUtil(t *testing.T) *NetworkTestUtil { - if os.Getuid() != 0 { - t.Skip("Test requires root privileges.") - } - - // new temporary namespace so we don't pollute the host - // lock thread since the namespace is thread local - runtime.LockOSThread() - var err error - ns, err := netns.New() - if err != nil { - t.Fatal("Failed to create newns", ns) - } - - return &NetworkTestUtil{t: t, ns: ns} -} - -func (n *NetworkTestUtil) Cleanup() { - n.ns.Close() - runtime.UnlockOSThread() -} - -func (n *NetworkTestUtil) SetupDummyLinkWithAddr() *netlink.Dummy { - dummyLink := netlink.Dummy{ - LinkAttrs: netlink.LinkAttrs{ - Index: 24, - Name: "foo", - }, - } - dummyAddr, _ := netlink.ParseAddr("192.168.10.1/24") - - if err := netlink.LinkAdd(&dummyLink); err != nil { - n.t.Fatal("Failed to create link", err) - } - if err := netlink.LinkSetUp(&dummyLink); err != nil { - n.t.Fatal("Failed to up link", err) - } - if err := netlink.AddrAdd(&dummyLink, dummyAddr); err != nil { - n.t.Fatal("Failed to add address to link", err) - } - return &dummyLink -} diff --git a/pkg/koordlet/util/system/util_test_tool_test.go b/pkg/util/system/util_test_tool_test.go similarity index 100% rename from pkg/koordlet/util/system/util_test_tool_test.go rename to pkg/util/system/util_test_tool_test.go diff --git a/pkg/koordlet/util/system/validator.go b/pkg/util/system/validator.go similarity index 91% rename from pkg/koordlet/util/system/validator.go rename to pkg/util/system/validator.go index 28d6fb80f..6403f693d 100644 --- a/pkg/koordlet/util/system/validator.go +++ b/pkg/util/system/validator.go @@ -40,8 +40,3 @@ func (r *RangeValidator) Validate(value *int64) (isValid bool, msg string) { } return } - -// Int64Ptr returns a int64 pointer for given value -func Int64Ptr(v int64) *int64 { - return &v -} diff --git a/pkg/koordlet/util/system/validator_test.go b/pkg/util/system/validator_test.go similarity index 90% rename from pkg/koordlet/util/system/validator_test.go rename to pkg/util/system/validator_test.go index b4b5b0818..f1f4f6f6c 100644 --- a/pkg/koordlet/util/system/validator_test.go +++ b/pkg/util/system/validator_test.go @@ -20,6 +20,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "k8s.io/utils/pointer" ) func Test_RangeValidate(t *testing.T) { @@ -41,25 +43,25 @@ func Test_RangeValidate(t *testing.T) { { name: "test_validate_invalid", validator: &RangeValidator{min: 0, max: 100, name: "wmarkRatio"}, - value: Int64Ptr(120), + value: pointer.Int64Ptr(120), expect: false, }, { name: "test_validate_valid_min", validator: &RangeValidator{min: 0, max: 100, name: "wmarkRatio"}, - value: Int64Ptr(0), + value: pointer.Int64Ptr(0), expect: true, }, { name: "test_validate_valid_max", validator: &RangeValidator{min: 0, max: 100, name: "wmarkRatio"}, - value: Int64Ptr(100), + value: pointer.Int64Ptr(100), expect: true, }, { name: "test_validate_valid", validator: &RangeValidator{min: 0, max: 100, name: "wmarkRatio"}, - value: Int64Ptr(20), + value: pointer.Int64Ptr(20), expect: true, }, } diff --git a/pkg/koordlet/util/system/version.go b/pkg/util/system/version.go similarity index 100% rename from pkg/koordlet/util/system/version.go rename to pkg/util/system/version.go diff --git a/pkg/koordlet/util/system/version_test.go b/pkg/util/system/version_test.go similarity index 100% rename from pkg/koordlet/util/system/version_test.go rename to pkg/util/system/version_test.go diff --git a/pkg/util/utils.go b/pkg/util/utils.go index d5cf3862d..c58b4d5e4 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -19,7 +19,14 @@ package util import ( "encoding/json" "fmt" + "io/ioutil" + "path/filepath" "reflect" + "sort" + "strconv" + "strings" + + "github.com/koordinator-sh/koordinator/pkg/util/system" ) // MergeCfg returns a merged interface. Value in new will @@ -44,3 +51,80 @@ func MergeCfg(old, new interface{}) (interface{}, error) { return old, nil } + +// MergeCPUSet merges the old cpuset with the new one, and also deduplicate and keeps a desc order by processor ids +// e.g. [1,0], [3,2,2,1] => [3,2,1,0] +func MergeCPUSet(old, new []int32) []int32 { + cpuMap := map[int32]struct{}{} + + for _, id := range old { + cpuMap[id] = struct{}{} + } + for _, id := range new { + cpuMap[id] = struct{}{} + } + + var merged []int32 + for id := range cpuMap { + merged = append(merged, id) + } + sort.Slice(merged, func(i, j int) bool { + return merged[i] > merged[j] + }) + + return merged +} + +// ParseCPUSetStr parses cpuset string into a slice +// eg. "0-5,34,46-48" => [0,1,2,3,4,5,34,46,47,48] +func ParseCPUSetStr(cpusetStr string) ([]int32, error) { + cpusetStr = strings.Trim(strings.TrimSpace(cpusetStr), "\n") + if cpusetStr == "" { + return nil, nil + } + + // split CPU list string + // eg. "0-5,34,46-48" => ["0-5", "34", "46-48"] + ranges := strings.Split(cpusetStr, ",") + + var cpuset []int32 + for _, r := range ranges { + boundaries := strings.Split(r, "-") + if len(boundaries) == 1 { + // only one element case, eg. "46" + elem, err := strconv.Atoi(boundaries[0]) + if err != nil { + return nil, err + } + cpuset = append(cpuset, int32(elem)) + } else if len(boundaries) == 2 { + // multi-element case, eg. "0-5" + start, err := strconv.Atoi(boundaries[0]) + if err != nil { + return nil, err + } + end, err := strconv.Atoi(boundaries[1]) + if err != nil { + return nil, err + } + // add all elements to the result. + // e.g. "0-5" => [0, 1, 2, 3, 4, 5] + for e := start; e <= end; e++ { + cpuset = append(cpuset, int32(e)) + } + } + } + + return cpuset, nil +} + +// GenerateCPUSetStr generates the cpuset string from the cpuset slice +// eg. [3,2,1,0] => "3,2,1,0" +func GenerateCPUSetStr(cpuset []int32) string { + return strings.Trim(strings.Join(strings.Fields(fmt.Sprint(cpuset)), ","), "[]") +} + +// WriteCgroupCPUSet writes the cgroup cpuset file according to the specified cgroup dir +func WriteCgroupCPUSet(cgroupFileDir, cpusetStr string) error { + return ioutil.WriteFile(filepath.Join(cgroupFileDir, system.CPUSFileName), []byte(cpusetStr), 0644) +} diff --git a/pkg/koordlet/util/util_test.go b/pkg/util/utils_test.go similarity index 95% rename from pkg/koordlet/util/util_test.go rename to pkg/util/utils_test.go index 5b9991d84..154883efe 100644 --- a/pkg/koordlet/util/util_test.go +++ b/pkg/util/utils_test.go @@ -24,7 +24,7 @@ import ( "github.com/stretchr/testify/assert" - sysutil "github.com/koordinator-sh/koordinator/pkg/koordlet/util/system" + "github.com/koordinator-sh/koordinator/pkg/util/system" ) func Test_MergeCPUSet(t *testing.T) { @@ -162,7 +162,7 @@ func Test_UtilCgroupCPUSet(t *testing.T) { err = WriteCgroupCPUSet(dname, cpusetStr) assert.NoError(t, err) - rawContent, err := ioutil.ReadFile(filepath.Join(dname, sysutil.CPUSFileName)) + rawContent, err := ioutil.ReadFile(filepath.Join(dname, system.CPUSFileName)) assert.NoError(t, err) gotCPUSetStr := string(rawContent) diff --git a/vendor/github.com/prashantv/gostub/.gitignore b/vendor/github.com/prashantv/gostub/.gitignore deleted file mode 100644 index daf913b1b..000000000 --- a/vendor/github.com/prashantv/gostub/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# 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 diff --git a/vendor/github.com/prashantv/gostub/.travis.yml b/vendor/github.com/prashantv/gostub/.travis.yml deleted file mode 100644 index 52f99ae7f..000000000 --- a/vendor/github.com/prashantv/gostub/.travis.yml +++ /dev/null @@ -1,21 +0,0 @@ -language: go -sudo: false - -go: - - 1.9.x - - 1.10.x - - 1.11.x - - 1.12.x - - 1.13.x - - tip - -before_install: - - go get github.com/axw/gocov/gocov - - go get github.com/mattn/goveralls - - if ! go get github.com/golang/tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi -script: - - $HOME/gopath/bin/goveralls -service=travis-ci - -matrix: - allow_failures: - - go: tip diff --git a/vendor/github.com/prashantv/gostub/CHANGELOG.md b/vendor/github.com/prashantv/gostub/CHANGELOG.md deleted file mode 100644 index ff7ea13ab..000000000 --- a/vendor/github.com/prashantv/gostub/CHANGELOG.md +++ /dev/null @@ -1,14 +0,0 @@ -# Changelog -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## 1.1.0 - 2021-12-11 -### Changed -- Use Go modules to track dependencies - -## 1.0.0 - 2018-11-09 -### Added -- Initial release with APIs to stub and reset values for testing. -- Supports stubbing Go variables, and environment variables. diff --git a/vendor/github.com/prashantv/gostub/LICENSE.md b/vendor/github.com/prashantv/gostub/LICENSE.md deleted file mode 100644 index 528318bf9..000000000 --- a/vendor/github.com/prashantv/gostub/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Prashant Varanasi - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/prashantv/gostub/README.md b/vendor/github.com/prashantv/gostub/README.md deleted file mode 100644 index b0cb32ce0..000000000 --- a/vendor/github.com/prashantv/gostub/README.md +++ /dev/null @@ -1,122 +0,0 @@ -# gostub - -[![Build Status](https://travis-ci.org/prashantv/gostub.svg?branch=master)](https://travis-ci.org/prashantv/gostub) -[![GoDoc](https://godoc.org/github.com/prashantv/gostub?status.svg)](https://godoc.org/github.com/prashantv/gostub) -[![Coverage Status](https://coveralls.io/repos/github/prashantv/gostub/badge.svg?branch=master)](https://coveralls.io/github/prashantv/gostub?branch=master) - -gostub is a library to make stubbing in unit tests easy. - -## Getting started - -Import the following package: -`github.com/prashantv/gostub` - -Click [here](https://godoc.org/github.com/prashantv/gostub) to read the [API documentation](https://godoc.org/github.com/prashantv/gostub). - -## Package overview - -Package gostub is used for stubbing variables in tests, and resetting the -original value once the test has been run. - -This can be used to stub static variables as well as static functions. To stub a -static variable, use the Stub function: - -```go -var configFile = "config.json" - -func GetConfig() ([]byte, error) { - return ioutil.ReadFile(configFile) -} - -// Test code -stubs := gostub.Stub(&configFile, "/tmp/test.config") - -data, err := GetConfig() -// data will now return contents of the /tmp/test.config file -``` - -gostub can also stub static functions in a test by using a variable to reference -the static function, and using that local variable to call the static function: - -```go -var timeNow = time.Now - -func GetDate() int { - return timeNow().Day() -} -``` - -You can test this by using gostub to stub the timeNow variable: - -```go -stubs := gostub.Stub(&timeNow, func() time.Time { - return time.Date(2015, 6, 1, 0, 0, 0, 0, time.UTC) -}) -defer stubs.Reset() - -// Test can check that GetDate returns 6 -``` - -If you are stubbing a function to return a constant value like in the above -test, you can use StubFunc instead: - -```go -stubs := gostub.StubFunc(&timeNow, time.Date(2015, 6, 1, 0, 0, 0, 0, time.UTC)) -defer stubs.Reset() -``` - -StubFunc can also be used to stub functions that return multiple values: - -```go -var osHostname = osHostname -// [...] production code using osHostname to call it. - -// Test code: -stubs := gostub.StubFunc(&osHostname, "fakehost", nil) -defer stubs.Reset() -``` -StubEnv can be used to setup environment variables for tests, and the -environment values are reset to their original values upon Reset: - -```go -stubs := gostub.New() -stubs.SetEnv("GOSTUB_VAR", "test_value") -defer stubs.Reset() -``` - -The Reset method should be deferred to run at the end of the test to reset all -stubbed variables back to their original values. - -You can set up multiple stubs by calling Stub again: - -```go -stubs := gostub.Stub(&v1, 1) -stubs.Stub(&v2, 2) -defer stubs.Reset() -``` - -For simple cases where you are only setting up simple stubs, you can condense -the setup and cleanup into a single line: - -```go -defer gostub.Stub(&v1, 1).Stub(&v2, 2).Reset() -``` - -This sets up the stubs and then defers the Reset call. - -You should keep the return argument from the Stub call if you need to change -stubs or add more stubs during test execution: - -```go -stubs := gostub.Stub(&v1, 1) -defer stubs.Reset() - -// Do some testing -stubs.Stub(&v1, 5) - -// More testing -stubs.Stub(&b2, 6) -``` - -The Stub call must be passed a pointer to the variable that should be stubbed, -and a value which can be assigned to the variable. diff --git a/vendor/github.com/prashantv/gostub/README.md.tmpl b/vendor/github.com/prashantv/gostub/README.md.tmpl deleted file mode 100644 index 39f1c1513..000000000 --- a/vendor/github.com/prashantv/gostub/README.md.tmpl +++ /dev/null @@ -1,18 +0,0 @@ -# gostub - -[![Build Status](https://travis-ci.org/prashantv/gostub.svg?branch=master)](https://travis-ci.org/prashantv/gostub) -[![GoDoc](https://godoc.org/github.com/prashantv/gostub?status.svg)](https://godoc.org/github.com/prashantv/gostub) -[![Coverage Status](https://coveralls.io/repos/github/prashantv/gostub/badge.svg?branch=master)](https://coveralls.io/github/prashantv/gostub?branch=master) - -gostub is a library to make stubbing in unit tests easy. - -## Getting started - -Import the following package: -`{{ .ImportPath }}` - -Click [here](https://godoc.org/github.com/prashantv/gostub) to read the [API documentation](https://godoc.org/github.com/prashantv/gostub). - -## Package overview - -{{ .EmitSynopsis }} diff --git a/vendor/github.com/prashantv/gostub/doc.go b/vendor/github.com/prashantv/gostub/doc.go deleted file mode 100644 index c19bb9cc6..000000000 --- a/vendor/github.com/prashantv/gostub/doc.go +++ /dev/null @@ -1,87 +0,0 @@ -/* -Package gostub is used for stubbing variables in tests, and resetting the -original value once the test has been run. - -This can be used to stub static variables as well as static functions. To -stub a static variable, use the Stub function: - - var configFile = "config.json" - - func GetConfig() ([]byte, error) { - return ioutil.ReadFile(configFile) - } - - // Test code - stubs := gostub.Stub(&configFile, "/tmp/test.config") - - data, err := GetConfig() - // data will now return contents of the /tmp/test.config file - -gostub can also stub static functions in a test by using a variable -to reference the static function, and using that local variable to call -the static function: - var timeNow = time.Now - - func GetDate() int { - return timeNow().Day() - } - -You can test this by using gostub to stub the timeNow variable: - stubs := gostub.Stub(&timeNow, func() time.Time { - return time.Date(2015, 6, 1, 0, 0, 0, 0, time.UTC) - }) - defer stubs.Reset() - - // Test can check that GetDate returns 6 - -If you are stubbing a function to return a constant value like in -the above test, you can use StubFunc instead: - stubs := gostub.StubFunc(&timeNow, time.Date(2015, 6, 1, 0, 0, 0, 0, time.UTC)) - defer stubs.Reset() - -StubFunc can also be used to stub functions that return multiple values: - var osHostname = osHostname - // [...] production code using osHostname to call it. - - // Test code: - stubs := gostub.StubFunc(&osHostname, "fakehost", nil) - defer stubs.Reset() - -StubEnv can be used to setup environment variables for tests, and the environment -values are reset to their original values upon Reset: - - stubs := gostub.New() - stubs.SetEnv("GOSTUB_VAR", "test_value") - defer stubs.Reset() - -The Reset method should be deferred to run at the end of the test to reset -all stubbed variables back to their original values. - -You can set up multiple stubs by calling Stub again: - stubs := gostub.Stub(&v1, 1) - stubs.Stub(&v2, 2) - defer stubs.Reset() - -For simple cases where you are only setting up simple stubs, you can condense -the setup and cleanup into a single line: - defer gostub.Stub(&v1, 1).Stub(&v2, 2).Reset() -This sets up the stubs and then defers the Reset call. - -You should keep the return argument from the Stub call if you need to change -stubs or add more stubs during test execution: - stubs := gostub.Stub(&v1, 1) - defer stubs.Reset() - - // Do some testing - stubs.Stub(&v1, 5) - - // More testing - stubs.Stub(&b2, 6) - -The Stub call must be passed a pointer to the variable that should be stubbed, -and a value which can be assigned to the variable. -*/ -package gostub - -// FIXME: godocdown no longer works with go syntax highlighting. -//go:generate godocdown -template README.md.tmpl --output=README.md diff --git a/vendor/github.com/prashantv/gostub/env.go b/vendor/github.com/prashantv/gostub/env.go deleted file mode 100644 index 9315e051f..000000000 --- a/vendor/github.com/prashantv/gostub/env.go +++ /dev/null @@ -1,36 +0,0 @@ -package gostub - -import "os" - -func (s *Stubs) checkEnvKey(k string) { - if _, ok := s.origEnv[k]; !ok { - v, ok := os.LookupEnv(k) - s.origEnv[k] = envVal{v, ok} - } -} - -// SetEnv the specified environent variable to the specified value. -func (s *Stubs) SetEnv(k, v string) *Stubs { - s.checkEnvKey(k) - - os.Setenv(k, v) - return s -} - -// UnsetEnv unsets the specified environent variable. -func (s *Stubs) UnsetEnv(k string) *Stubs { - s.checkEnvKey(k) - - os.Unsetenv(k) - return s -} - -func (s *Stubs) resetEnv() { - for k, v := range s.origEnv { - if v.ok { - os.Setenv(k, v.val) - } else { - os.Unsetenv(k) - } - } -} diff --git a/vendor/github.com/prashantv/gostub/gostub.go b/vendor/github.com/prashantv/gostub/gostub.go deleted file mode 100644 index ce9fd8404..000000000 --- a/vendor/github.com/prashantv/gostub/gostub.go +++ /dev/null @@ -1,126 +0,0 @@ -package gostub - -import ( - "fmt" - "reflect" -) - -// Stub replaces the value stored at varToStub with stubVal. -// varToStub must be a pointer to the variable. stubVal should have a type -// that is assignable to the variable. -func Stub(varToStub interface{}, stubVal interface{}) *Stubs { - return New().Stub(varToStub, stubVal) -} - -// StubFunc replaces a function variable with a function that returns stubVal. -// funcVarToStub must be a pointer to a function variable. If the function -// returns multiple values, then multiple values should be passed to stubFunc. -// The values must match be assignable to the return values' types. -func StubFunc(funcVarToStub interface{}, stubVal ...interface{}) *Stubs { - return New().StubFunc(funcVarToStub, stubVal...) -} - -type envVal struct { - val string - ok bool -} - -// Stubs represents a set of stubbed variables that can be reset. -type Stubs struct { - // stubs is a map from the variable pointer (being stubbed) to the original value. - stubs map[reflect.Value]reflect.Value - origEnv map[string]envVal -} - -// New returns Stubs that can be used to stub out variables. -func New() *Stubs { - return &Stubs{ - stubs: make(map[reflect.Value]reflect.Value), - origEnv: make(map[string]envVal), - } -} - -// Stub replaces the value stored at varToStub with stubVal. -// varToStub must be a pointer to the variable. stubVal should have a type -// that is assignable to the variable. -func (s *Stubs) Stub(varToStub interface{}, stubVal interface{}) *Stubs { - v := reflect.ValueOf(varToStub) - stub := reflect.ValueOf(stubVal) - - // Ensure varToStub is a pointer to the variable. - if v.Type().Kind() != reflect.Ptr { - panic("variable to stub is expected to be a pointer") - } - - if _, ok := s.stubs[v]; !ok { - // Store the original value if this is the first time varPtr is being stubbed. - s.stubs[v] = reflect.ValueOf(v.Elem().Interface()) - } - - // *varToStub = stubVal - v.Elem().Set(stub) - return s -} - -// StubFunc replaces a function variable with a function that returns stubVal. -// funcVarToStub must be a pointer to a function variable. If the function -// returns multiple values, then multiple values should be passed to stubFunc. -// The values must match be assignable to the return values' types. -func (s *Stubs) StubFunc(funcVarToStub interface{}, stubVal ...interface{}) *Stubs { - funcPtrType := reflect.TypeOf(funcVarToStub) - if funcPtrType.Kind() != reflect.Ptr || - funcPtrType.Elem().Kind() != reflect.Func { - panic("func variable to stub must be a pointer to a function") - } - funcType := funcPtrType.Elem() - if funcType.NumOut() != len(stubVal) { - panic(fmt.Sprintf("func type has %v return values, but only %v stub values provided", - funcType.NumOut(), len(stubVal))) - } - - return s.Stub(funcVarToStub, FuncReturning(funcPtrType.Elem(), stubVal...).Interface()) -} - -// FuncReturning creates a new function with type funcType that returns results. -func FuncReturning(funcType reflect.Type, results ...interface{}) reflect.Value { - var resultValues []reflect.Value - for i, r := range results { - var retValue reflect.Value - if r == nil { - // We can't use reflect.ValueOf(nil), so we need to create the zero value. - retValue = reflect.Zero(funcType.Out(i)) - } else { - // We cannot simply use reflect.ValueOf(r) as that does not work for - // interface types, as reflect.ValueOf receives the dynamic type, which - // is the underlying type. e.g. for an error, it may *errors.errorString. - // Instead, we make the return type's expected interface value using - // reflect.New, and set the data to the passed in value. - tempV := reflect.New(funcType.Out(i)) - tempV.Elem().Set(reflect.ValueOf(r)) - retValue = tempV.Elem() - } - resultValues = append(resultValues, retValue) - } - return reflect.MakeFunc(funcType, func(_ []reflect.Value) []reflect.Value { - return resultValues - }) -} - -// Reset resets all stubbed variables back to their original values. -func (s *Stubs) Reset() { - for v, originalVal := range s.stubs { - v.Elem().Set(originalVal) - } - s.resetEnv() -} - -// ResetSingle resets a single stubbed variable back to its original value. -func (s *Stubs) ResetSingle(varToStub interface{}) { - v := reflect.ValueOf(varToStub) - originalVal, ok := s.stubs[v] - if !ok { - panic("cannot reset variable as it has not been stubbed yet") - } - - v.Elem().Set(originalVal) -} diff --git a/vendor/github.com/prashantv/gostub/version.go b/vendor/github.com/prashantv/gostub/version.go deleted file mode 100644 index 61bc152e7..000000000 --- a/vendor/github.com/prashantv/gostub/version.go +++ /dev/null @@ -1,4 +0,0 @@ -package gostub - -// Version contains the package version. -const Version = "1.1.0" diff --git a/vendor/github.com/vishvananda/netlink/.gitignore b/vendor/github.com/vishvananda/netlink/.gitignore deleted file mode 100644 index 9f11b755a..000000000 --- a/vendor/github.com/vishvananda/netlink/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.idea/ diff --git a/vendor/github.com/vishvananda/netlink/.travis.yml b/vendor/github.com/vishvananda/netlink/.travis.yml deleted file mode 100644 index 7d14af4d6..000000000 --- a/vendor/github.com/vishvananda/netlink/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: go -go: - - "1.10.x" - - "1.11.x" - - "1.12.x" -before_script: - # make sure we keep path in tact when we sudo - - sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers - # modprobe ip_gre or else the first gre device can't be deleted - - sudo modprobe ip_gre - # modprobe nf_conntrack for the conntrack testing - - sudo modprobe nf_conntrack - - sudo modprobe nf_conntrack_netlink - - sudo modprobe nf_conntrack_ipv4 - - sudo modprobe nf_conntrack_ipv6 - - sudo modprobe sch_hfsc -install: - - go get github.com/vishvananda/netns -go_import_path: github.com/vishvananda/netlink diff --git a/vendor/github.com/vishvananda/netlink/CHANGELOG.md b/vendor/github.com/vishvananda/netlink/CHANGELOG.md deleted file mode 100644 index b11e59ff6..000000000 --- a/vendor/github.com/vishvananda/netlink/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -# Changelog - -## 1.0.0 (2018-03-15) - -Initial release tagging \ No newline at end of file diff --git a/vendor/github.com/vishvananda/netlink/LICENSE b/vendor/github.com/vishvananda/netlink/LICENSE deleted file mode 100644 index 9f64db858..000000000 --- a/vendor/github.com/vishvananda/netlink/LICENSE +++ /dev/null @@ -1,192 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2014 Vishvananda Ishaya. - Copyright 2014 Docker, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/vishvananda/netlink/Makefile b/vendor/github.com/vishvananda/netlink/Makefile deleted file mode 100644 index a0e68e7a9..000000000 --- a/vendor/github.com/vishvananda/netlink/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -DIRS := \ - . \ - nl - -DEPS = \ - github.com/vishvananda/netns \ - golang.org/x/sys/unix - -uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) -testdirs = $(call uniq,$(foreach d,$(1),$(dir $(wildcard $(d)/*_test.go)))) -goroot = $(addprefix ../../../,$(1)) -unroot = $(subst ../../../,,$(1)) -fmt = $(addprefix fmt-,$(1)) - -all: test - -$(call goroot,$(DEPS)): - go get $(call unroot,$@) - -.PHONY: $(call testdirs,$(DIRS)) -$(call testdirs,$(DIRS)): - go test -test.exec sudo -test.parallel 4 -timeout 60s -test.v github.com/vishvananda/netlink/$@ - -$(call fmt,$(call testdirs,$(DIRS))): - ! gofmt -l $(subst fmt-,,$@)/*.go | grep -q . - -.PHONY: fmt -fmt: $(call fmt,$(call testdirs,$(DIRS))) - -test: fmt $(call goroot,$(DEPS)) $(call testdirs,$(DIRS)) diff --git a/vendor/github.com/vishvananda/netlink/README.md b/vendor/github.com/vishvananda/netlink/README.md deleted file mode 100644 index a88e2f418..000000000 --- a/vendor/github.com/vishvananda/netlink/README.md +++ /dev/null @@ -1,92 +0,0 @@ -# netlink - netlink library for go # - -[![Build Status](https://travis-ci.org/vishvananda/netlink.png?branch=master)](https://travis-ci.org/vishvananda/netlink) [![GoDoc](https://godoc.org/github.com/vishvananda/netlink?status.svg)](https://godoc.org/github.com/vishvananda/netlink) - -The netlink package provides a simple netlink library for go. Netlink -is the interface a user-space program in linux uses to communicate with -the kernel. It can be used to add and remove interfaces, set ip addresses -and routes, and configure ipsec. Netlink communication requires elevated -privileges, so in most cases this code needs to be run as root. Since -low-level netlink messages are inscrutable at best, the library attempts -to provide an api that is loosely modeled on the CLI provided by iproute2. -Actions like `ip link add` will be accomplished via a similarly named -function like AddLink(). This library began its life as a fork of the -netlink functionality in -[docker/libcontainer](https://github.com/docker/libcontainer) but was -heavily rewritten to improve testability, performance, and to add new -functionality like ipsec xfrm handling. - -## Local Build and Test ## - -You can use go get command: - - go get github.com/vishvananda/netlink - -Testing dependencies: - - go get github.com/vishvananda/netns - -Testing (requires root): - - sudo -E go test github.com/vishvananda/netlink - -## Examples ## - -Add a new bridge and add eth1 into it: - -```go -package main - -import ( - "fmt" - "github.com/vishvananda/netlink" -) - -func main() { - la := netlink.NewLinkAttrs() - la.Name = "foo" - mybridge := &netlink.Bridge{LinkAttrs: la} - err := netlink.LinkAdd(mybridge) - if err != nil { - fmt.Printf("could not add %s: %v\n", la.Name, err) - } - eth1, _ := netlink.LinkByName("eth1") - netlink.LinkSetMaster(eth1, mybridge) -} - -``` -Note `NewLinkAttrs` constructor, it sets default values in structure. For now -it sets only `TxQLen` to `-1`, so kernel will set default by itself. If you're -using simple initialization(`LinkAttrs{Name: "foo"}`) `TxQLen` will be set to -`0` unless you specify it like `LinkAttrs{Name: "foo", TxQLen: 1000}`. - -Add a new ip address to loopback: - -```go -package main - -import ( - "github.com/vishvananda/netlink" -) - -func main() { - lo, _ := netlink.LinkByName("lo") - addr, _ := netlink.ParseAddr("169.254.169.254/32") - netlink.AddrAdd(lo, addr) -} - -``` - -## Future Work ## - -Many pieces of netlink are not yet fully supported in the high-level -interface. Aspects of virtually all of the high-level objects don't exist. -Many of the underlying primitives are there, so its a matter of putting -the right fields into the high-level objects and making sure that they -are serialized and deserialized correctly in the Add and List methods. - -There are also a few pieces of low level netlink functionality that still -need to be implemented. Routing rules are not in place and some of the -more advanced link types. Hopefully there is decent structure and testing -in place to make these fairly straightforward to add. - diff --git a/vendor/github.com/vishvananda/netlink/addr.go b/vendor/github.com/vishvananda/netlink/addr.go deleted file mode 100644 index f08c95696..000000000 --- a/vendor/github.com/vishvananda/netlink/addr.go +++ /dev/null @@ -1,56 +0,0 @@ -package netlink - -import ( - "fmt" - "net" - "strings" -) - -// Addr represents an IP address from netlink. Netlink ip addresses -// include a mask, so it stores the address as a net.IPNet. -type Addr struct { - *net.IPNet - Label string - Flags int - Scope int - Peer *net.IPNet - Broadcast net.IP - PreferedLft int - ValidLft int -} - -// String returns $ip/$netmask $label -func (a Addr) String() string { - return strings.TrimSpace(fmt.Sprintf("%s %s", a.IPNet, a.Label)) -} - -// ParseAddr parses the string representation of an address in the -// form $ip/$netmask $label. The label portion is optional -func ParseAddr(s string) (*Addr, error) { - label := "" - parts := strings.Split(s, " ") - if len(parts) > 1 { - s = parts[0] - label = parts[1] - } - m, err := ParseIPNet(s) - if err != nil { - return nil, err - } - return &Addr{IPNet: m, Label: label}, nil -} - -// Equal returns true if both Addrs have the same net.IPNet value. -func (a Addr) Equal(x Addr) bool { - sizea, _ := a.Mask.Size() - sizeb, _ := x.Mask.Size() - // ignore label for comparison - return a.IP.Equal(x.IP) && sizea == sizeb -} - -func (a Addr) PeerEqual(x Addr) bool { - sizea, _ := a.Peer.Mask.Size() - sizeb, _ := x.Peer.Mask.Size() - // ignore label for comparison - return a.Peer.IP.Equal(x.Peer.IP) && sizea == sizeb -} diff --git a/vendor/github.com/vishvananda/netlink/addr_linux.go b/vendor/github.com/vishvananda/netlink/addr_linux.go deleted file mode 100644 index 28746d5af..000000000 --- a/vendor/github.com/vishvananda/netlink/addr_linux.go +++ /dev/null @@ -1,417 +0,0 @@ -package netlink - -import ( - "fmt" - "net" - "strings" - "syscall" - - "github.com/vishvananda/netlink/nl" - "github.com/vishvananda/netns" - "golang.org/x/sys/unix" -) - -// IFA_FLAGS is a u32 attribute. -const IFA_FLAGS = 0x8 - -// AddrAdd will add an IP address to a link device. -// -// Equivalent to: `ip addr add $addr dev $link` -// -// If `addr` is an IPv4 address and the broadcast address is not given, it -// will be automatically computed based on the IP mask if /30 or larger. -func AddrAdd(link Link, addr *Addr) error { - return pkgHandle.AddrAdd(link, addr) -} - -// AddrAdd will add an IP address to a link device. -// -// Equivalent to: `ip addr add $addr dev $link` -// -// If `addr` is an IPv4 address and the broadcast address is not given, it -// will be automatically computed based on the IP mask if /30 or larger. -func (h *Handle) AddrAdd(link Link, addr *Addr) error { - req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) - return h.addrHandle(link, addr, req) -} - -// AddrReplace will replace (or, if not present, add) an IP address on a link device. -// -// Equivalent to: `ip addr replace $addr dev $link` -// -// If `addr` is an IPv4 address and the broadcast address is not given, it -// will be automatically computed based on the IP mask if /30 or larger. -func AddrReplace(link Link, addr *Addr) error { - return pkgHandle.AddrReplace(link, addr) -} - -// AddrReplace will replace (or, if not present, add) an IP address on a link device. -// -// Equivalent to: `ip addr replace $addr dev $link` -// -// If `addr` is an IPv4 address and the broadcast address is not given, it -// will be automatically computed based on the IP mask if /30 or larger. -func (h *Handle) AddrReplace(link Link, addr *Addr) error { - req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_REPLACE|unix.NLM_F_ACK) - return h.addrHandle(link, addr, req) -} - -// AddrDel will delete an IP address from a link device. -// -// Equivalent to: `ip addr del $addr dev $link` -// -// If `addr` is an IPv4 address and the broadcast address is not given, it -// will be automatically computed based on the IP mask if /30 or larger. -func AddrDel(link Link, addr *Addr) error { - return pkgHandle.AddrDel(link, addr) -} - -// AddrDel will delete an IP address from a link device. -// Equivalent to: `ip addr del $addr dev $link` -// -// If `addr` is an IPv4 address and the broadcast address is not given, it -// will be automatically computed based on the IP mask if /30 or larger. -func (h *Handle) AddrDel(link Link, addr *Addr) error { - req := h.newNetlinkRequest(unix.RTM_DELADDR, unix.NLM_F_ACK) - return h.addrHandle(link, addr, req) -} - -func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error { - base := link.Attrs() - if addr.Label != "" && !strings.HasPrefix(addr.Label, base.Name) { - return fmt.Errorf("label must begin with interface name") - } - h.ensureIndex(base) - - family := nl.GetIPFamily(addr.IP) - - msg := nl.NewIfAddrmsg(family) - msg.Index = uint32(base.Index) - msg.Scope = uint8(addr.Scope) - mask := addr.Mask - if addr.Peer != nil { - mask = addr.Peer.Mask - } - prefixlen, masklen := mask.Size() - msg.Prefixlen = uint8(prefixlen) - req.AddData(msg) - - var localAddrData []byte - if family == FAMILY_V4 { - localAddrData = addr.IP.To4() - } else { - localAddrData = addr.IP.To16() - } - - localData := nl.NewRtAttr(unix.IFA_LOCAL, localAddrData) - req.AddData(localData) - var peerAddrData []byte - if addr.Peer != nil { - if family == FAMILY_V4 { - peerAddrData = addr.Peer.IP.To4() - } else { - peerAddrData = addr.Peer.IP.To16() - } - } else { - peerAddrData = localAddrData - } - - addressData := nl.NewRtAttr(unix.IFA_ADDRESS, peerAddrData) - req.AddData(addressData) - - if addr.Flags != 0 { - if addr.Flags <= 0xff { - msg.IfAddrmsg.Flags = uint8(addr.Flags) - } else { - b := make([]byte, 4) - native.PutUint32(b, uint32(addr.Flags)) - flagsData := nl.NewRtAttr(IFA_FLAGS, b) - req.AddData(flagsData) - } - } - - if family == FAMILY_V4 { - // Automatically set the broadcast address if it is unset and the - // subnet is large enough to sensibly have one (/30 or larger). - // See: RFC 3021 - if addr.Broadcast == nil && prefixlen < 31 { - calcBroadcast := make(net.IP, masklen/8) - for i := range localAddrData { - calcBroadcast[i] = localAddrData[i] | ^mask[i] - } - addr.Broadcast = calcBroadcast - } - - if addr.Broadcast != nil { - req.AddData(nl.NewRtAttr(unix.IFA_BROADCAST, addr.Broadcast)) - } - - if addr.Label != "" { - labelData := nl.NewRtAttr(unix.IFA_LABEL, nl.ZeroTerminated(addr.Label)) - req.AddData(labelData) - } - } - - // 0 is the default value for these attributes. However, 0 means "expired", while the least-surprising default - // value should be "forever". To compensate for that, only add the attributes if at least one of the values is - // non-zero, which means the caller has explicitly set them - if addr.ValidLft > 0 || addr.PreferedLft > 0 { - cachedata := nl.IfaCacheInfo{ - IfaValid: uint32(addr.ValidLft), - IfaPrefered: uint32(addr.PreferedLft), - } - req.AddData(nl.NewRtAttr(unix.IFA_CACHEINFO, cachedata.Serialize())) - } - - _, err := req.Execute(unix.NETLINK_ROUTE, 0) - return err -} - -// AddrList gets a list of IP addresses in the system. -// Equivalent to: `ip addr show`. -// The list can be filtered by link and ip family. -func AddrList(link Link, family int) ([]Addr, error) { - return pkgHandle.AddrList(link, family) -} - -// AddrList gets a list of IP addresses in the system. -// Equivalent to: `ip addr show`. -// The list can be filtered by link and ip family. -func (h *Handle) AddrList(link Link, family int) ([]Addr, error) { - req := h.newNetlinkRequest(unix.RTM_GETADDR, unix.NLM_F_DUMP) - msg := nl.NewIfInfomsg(family) - req.AddData(msg) - - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWADDR) - if err != nil { - return nil, err - } - - indexFilter := 0 - if link != nil { - base := link.Attrs() - h.ensureIndex(base) - indexFilter = base.Index - } - - var res []Addr - for _, m := range msgs { - addr, msgFamily, ifindex, err := parseAddr(m) - if err != nil { - return res, err - } - - if link != nil && ifindex != indexFilter { - // Ignore messages from other interfaces - continue - } - - if family != FAMILY_ALL && msgFamily != family { - continue - } - - res = append(res, addr) - } - - return res, nil -} - -func parseAddr(m []byte) (addr Addr, family, index int, err error) { - msg := nl.DeserializeIfAddrmsg(m) - - family = -1 - index = -1 - - attrs, err1 := nl.ParseRouteAttr(m[msg.Len():]) - if err1 != nil { - err = err1 - return - } - - family = int(msg.Family) - index = int(msg.Index) - - var local, dst *net.IPNet - for _, attr := range attrs { - switch attr.Attr.Type { - case unix.IFA_ADDRESS: - dst = &net.IPNet{ - IP: attr.Value, - Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)), - } - case unix.IFA_LOCAL: - // iproute2 manual: - // If a peer address is specified, the local address - // cannot have a prefix length. The network prefix is - // associated with the peer rather than with the local - // address. - n := 8 * len(attr.Value) - local = &net.IPNet{ - IP: attr.Value, - Mask: net.CIDRMask(n, n), - } - case unix.IFA_BROADCAST: - addr.Broadcast = attr.Value - case unix.IFA_LABEL: - addr.Label = string(attr.Value[:len(attr.Value)-1]) - case IFA_FLAGS: - addr.Flags = int(native.Uint32(attr.Value[0:4])) - case nl.IFA_CACHEINFO: - ci := nl.DeserializeIfaCacheInfo(attr.Value) - addr.PreferedLft = int(ci.IfaPrefered) - addr.ValidLft = int(ci.IfaValid) - } - } - - // libnl addr.c comment: - // IPv6 sends the local address as IFA_ADDRESS with no - // IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS - // with IFA_ADDRESS being the peer address if they differ - // - // But obviously, as there are IPv6 PtP addresses, too, - // IFA_LOCAL should also be handled for IPv6. - if local != nil { - if family == FAMILY_V4 && local.IP.Equal(dst.IP) { - addr.IPNet = dst - } else { - addr.IPNet = local - addr.Peer = dst - } - } else { - addr.IPNet = dst - } - - addr.Scope = int(msg.Scope) - - return -} - -type AddrUpdate struct { - LinkAddress net.IPNet - LinkIndex int - Flags int - Scope int - PreferedLft int - ValidLft int - NewAddr bool // true=added false=deleted -} - -// AddrSubscribe takes a chan down which notifications will be sent -// when addresses change. Close the 'done' chan to stop subscription. -func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error { - return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0) -} - -// AddrSubscribeAt works like AddrSubscribe plus it allows the caller -// to choose the network namespace in which to subscribe (ns). -func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error { - return addrSubscribeAt(ns, netns.None(), ch, done, nil, false, 0) -} - -// AddrSubscribeOptions contains a set of options to use with -// AddrSubscribeWithOptions. -type AddrSubscribeOptions struct { - Namespace *netns.NsHandle - ErrorCallback func(error) - ListExisting bool - ReceiveBufferSize int -} - -// AddrSubscribeWithOptions work like AddrSubscribe but enable to -// provide additional options to modify the behavior. Currently, the -// namespace can be provided as well as an error callback. -func AddrSubscribeWithOptions(ch chan<- AddrUpdate, done <-chan struct{}, options AddrSubscribeOptions) error { - if options.Namespace == nil { - none := netns.None() - options.Namespace = &none - } - return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting, options.ReceiveBufferSize) -} - -func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool, rcvbuf int) error { - s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_IFADDR, unix.RTNLGRP_IPV6_IFADDR) - if err != nil { - return err - } - if done != nil { - go func() { - <-done - s.Close() - }() - } - if rcvbuf != 0 { - err = pkgHandle.SetSocketReceiveBufferSize(rcvbuf, false) - if err != nil { - return err - } - } - if listExisting { - req := pkgHandle.newNetlinkRequest(unix.RTM_GETADDR, - unix.NLM_F_DUMP) - infmsg := nl.NewIfInfomsg(unix.AF_UNSPEC) - req.AddData(infmsg) - if err := s.Send(req); err != nil { - return err - } - } - go func() { - defer close(ch) - for { - msgs, from, err := s.Receive() - if err != nil { - if cberr != nil { - cberr(err) - } - return - } - if from.Pid != nl.PidKernel { - if cberr != nil { - cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)) - } - continue - } - for _, m := range msgs { - if m.Header.Type == unix.NLMSG_DONE { - continue - } - if m.Header.Type == unix.NLMSG_ERROR { - native := nl.NativeEndian() - error := int32(native.Uint32(m.Data[0:4])) - if error == 0 { - continue - } - if cberr != nil { - cberr(fmt.Errorf("error message: %v", - syscall.Errno(-error))) - } - continue - } - msgType := m.Header.Type - if msgType != unix.RTM_NEWADDR && msgType != unix.RTM_DELADDR { - if cberr != nil { - cberr(fmt.Errorf("bad message type: %d", msgType)) - } - continue - } - - addr, _, ifindex, err := parseAddr(m.Data) - if err != nil { - if cberr != nil { - cberr(fmt.Errorf("could not parse address: %v", err)) - } - continue - } - - ch <- AddrUpdate{LinkAddress: *addr.IPNet, - LinkIndex: ifindex, - NewAddr: msgType == unix.RTM_NEWADDR, - Flags: addr.Flags, - Scope: addr.Scope, - PreferedLft: addr.PreferedLft, - ValidLft: addr.ValidLft} - } - } - }() - - return nil -} diff --git a/vendor/github.com/vishvananda/netlink/bpf_linux.go b/vendor/github.com/vishvananda/netlink/bpf_linux.go deleted file mode 100644 index 6631626bf..000000000 --- a/vendor/github.com/vishvananda/netlink/bpf_linux.go +++ /dev/null @@ -1,53 +0,0 @@ -package netlink - -import ( - "unsafe" - - "golang.org/x/sys/unix" -) - -type BpfProgType uint32 - -const ( - BPF_PROG_TYPE_UNSPEC BpfProgType = iota - BPF_PROG_TYPE_SOCKET_FILTER - BPF_PROG_TYPE_KPROBE - BPF_PROG_TYPE_SCHED_CLS - BPF_PROG_TYPE_SCHED_ACT - BPF_PROG_TYPE_TRACEPOINT - BPF_PROG_TYPE_XDP -) - -type BPFAttr struct { - ProgType uint32 - InsnCnt uint32 - Insns uintptr - License uintptr - LogLevel uint32 - LogSize uint32 - LogBuf uintptr - KernVersion uint32 -} - -// loadSimpleBpf loads a trivial bpf program for testing purposes. -func loadSimpleBpf(progType BpfProgType, ret uint32) (int, error) { - insns := []uint64{ - 0x00000000000000b7 | (uint64(ret) << 32), - 0x0000000000000095, - } - license := []byte{'A', 'S', 'L', '2', '\x00'} - attr := BPFAttr{ - ProgType: uint32(progType), - InsnCnt: uint32(len(insns)), - Insns: uintptr(unsafe.Pointer(&insns[0])), - License: uintptr(unsafe.Pointer(&license[0])), - } - fd, _, errno := unix.Syscall(unix.SYS_BPF, - 5, /* bpf cmd */ - uintptr(unsafe.Pointer(&attr)), - unsafe.Sizeof(attr)) - if errno != 0 { - return 0, errno - } - return int(fd), nil -} diff --git a/vendor/github.com/vishvananda/netlink/bridge_linux.go b/vendor/github.com/vishvananda/netlink/bridge_linux.go deleted file mode 100644 index 6e1224c47..000000000 --- a/vendor/github.com/vishvananda/netlink/bridge_linux.go +++ /dev/null @@ -1,112 +0,0 @@ -package netlink - -import ( - "fmt" - - "github.com/vishvananda/netlink/nl" - "golang.org/x/sys/unix" -) - -// BridgeVlanList gets a map of device id to bridge vlan infos. -// Equivalent to: `bridge vlan show` -func BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) { - return pkgHandle.BridgeVlanList() -} - -// BridgeVlanList gets a map of device id to bridge vlan infos. -// Equivalent to: `bridge vlan show` -func (h *Handle) BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) { - req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP) - msg := nl.NewIfInfomsg(unix.AF_BRIDGE) - req.AddData(msg) - req.AddData(nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(uint32(nl.RTEXT_FILTER_BRVLAN)))) - - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK) - if err != nil { - return nil, err - } - ret := make(map[int32][]*nl.BridgeVlanInfo) - for _, m := range msgs { - msg := nl.DeserializeIfInfomsg(m) - - attrs, err := nl.ParseRouteAttr(m[msg.Len():]) - if err != nil { - return nil, err - } - for _, attr := range attrs { - switch attr.Attr.Type { - case unix.IFLA_AF_SPEC: - //nested attr - nestAttrs, err := nl.ParseRouteAttr(attr.Value) - if err != nil { - return nil, fmt.Errorf("failed to parse nested attr %v", err) - } - for _, nestAttr := range nestAttrs { - switch nestAttr.Attr.Type { - case nl.IFLA_BRIDGE_VLAN_INFO: - vlanInfo := nl.DeserializeBridgeVlanInfo(nestAttr.Value) - ret[msg.Index] = append(ret[msg.Index], vlanInfo) - } - } - } - } - } - return ret, nil -} - -// BridgeVlanAdd adds a new vlan filter entry -// Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]` -func BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error { - return pkgHandle.BridgeVlanAdd(link, vid, pvid, untagged, self, master) -} - -// BridgeVlanAdd adds a new vlan filter entry -// Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]` -func (h *Handle) BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error { - return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, pvid, untagged, self, master) -} - -// BridgeVlanDel adds a new vlan filter entry -// Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]` -func BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error { - return pkgHandle.BridgeVlanDel(link, vid, pvid, untagged, self, master) -} - -// BridgeVlanDel adds a new vlan filter entry -// Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]` -func (h *Handle) BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error { - return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, pvid, untagged, self, master) -} - -func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged, self, master bool) error { - base := link.Attrs() - h.ensureIndex(base) - req := h.newNetlinkRequest(cmd, unix.NLM_F_ACK) - - msg := nl.NewIfInfomsg(unix.AF_BRIDGE) - msg.Index = int32(base.Index) - req.AddData(msg) - - br := nl.NewRtAttr(unix.IFLA_AF_SPEC, nil) - var flags uint16 - if self { - flags |= nl.BRIDGE_FLAGS_SELF - } - if master { - flags |= nl.BRIDGE_FLAGS_MASTER - } - if flags > 0 { - br.AddRtAttr(nl.IFLA_BRIDGE_FLAGS, nl.Uint16Attr(flags)) - } - vlanInfo := &nl.BridgeVlanInfo{Vid: vid} - if pvid { - vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_PVID - } - if untagged { - vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_UNTAGGED - } - br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize()) - req.AddData(br) - _, err := req.Execute(unix.NETLINK_ROUTE, 0) - return err -} diff --git a/vendor/github.com/vishvananda/netlink/class.go b/vendor/github.com/vishvananda/netlink/class.go deleted file mode 100644 index dcc22d9e9..000000000 --- a/vendor/github.com/vishvananda/netlink/class.go +++ /dev/null @@ -1,211 +0,0 @@ -package netlink - -import ( - "fmt" -) - -// Class interfaces for all classes -type Class interface { - Attrs() *ClassAttrs - Type() string -} - -// Generic networking statistics for netlink users. -// This file contains "gnet_" prefixed structs and relevant functions. -// See Documentation/networking/getn_stats.txt in Linux source code for more details. - -// GnetStatsBasic Ref: struct gnet_stats_basic { ... } -type GnetStatsBasic struct { - Bytes uint64 // number of seen bytes - Packets uint32 // number of seen packets -} - -// GnetStatsRateEst Ref: struct gnet_stats_rate_est { ... } -type GnetStatsRateEst struct { - Bps uint32 // current byte rate - Pps uint32 // current packet rate -} - -// GnetStatsRateEst64 Ref: struct gnet_stats_rate_est64 { ... } -type GnetStatsRateEst64 struct { - Bps uint64 // current byte rate - Pps uint64 // current packet rate -} - -// GnetStatsQueue Ref: struct gnet_stats_queue { ... } -type GnetStatsQueue struct { - Qlen uint32 // queue length - Backlog uint32 // backlog size of queue - Drops uint32 // number of dropped packets - Requeues uint32 // number of requues - Overlimits uint32 // number of enqueues over the limit -} - -// ClassStatistics representation based on generic networking statistics for netlink. -// See Documentation/networking/gen_stats.txt in Linux source code for more details. -type ClassStatistics struct { - Basic *GnetStatsBasic - Queue *GnetStatsQueue - RateEst *GnetStatsRateEst -} - -// NewClassStatistics Construct a ClassStatistics struct which fields are all initialized by 0. -func NewClassStatistics() *ClassStatistics { - return &ClassStatistics{ - Basic: &GnetStatsBasic{}, - Queue: &GnetStatsQueue{}, - RateEst: &GnetStatsRateEst{}, - } -} - -// ClassAttrs represents a netlink class. A filter is associated with a link, -// has a handle and a parent. The root filter of a device should have a -// parent == HANDLE_ROOT. -type ClassAttrs struct { - LinkIndex int - Handle uint32 - Parent uint32 - Leaf uint32 - Statistics *ClassStatistics -} - -func (q ClassAttrs) String() string { - return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Leaf: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Leaf) -} - -// HtbClassAttrs stores the attributes of HTB class -type HtbClassAttrs struct { - // TODO handle all attributes - Rate uint64 - Ceil uint64 - Buffer uint32 - Cbuffer uint32 - Quantum uint32 - Level uint32 - Prio uint32 -} - -func (q HtbClassAttrs) String() string { - return fmt.Sprintf("{Rate: %d, Ceil: %d, Buffer: %d, Cbuffer: %d}", q.Rate, q.Ceil, q.Buffer, q.Cbuffer) -} - -// HtbClass represents an Htb class -type HtbClass struct { - ClassAttrs - Rate uint64 - Ceil uint64 - Buffer uint32 - Cbuffer uint32 - Quantum uint32 - Level uint32 - Prio uint32 -} - -func (q HtbClass) String() string { - return fmt.Sprintf("{Rate: %d, Ceil: %d, Buffer: %d, Cbuffer: %d}", q.Rate, q.Ceil, q.Buffer, q.Cbuffer) -} - -// Attrs returns the class attributes -func (q *HtbClass) Attrs() *ClassAttrs { - return &q.ClassAttrs -} - -// Type return the class type -func (q *HtbClass) Type() string { - return "htb" -} - -// GenericClass classes represent types that are not currently understood -// by this netlink library. -type GenericClass struct { - ClassAttrs - ClassType string -} - -// Attrs return the class attributes -func (class *GenericClass) Attrs() *ClassAttrs { - return &class.ClassAttrs -} - -// Type return the class type -func (class *GenericClass) Type() string { - return class.ClassType -} - -// ServiceCurve is the way the HFSC curve are represented -type ServiceCurve struct { - m1 uint32 - d uint32 - m2 uint32 -} - -// Attrs return the parameters of the service curve -func (c *ServiceCurve) Attrs() (uint32, uint32, uint32) { - return c.m1, c.d, c.m2 -} - -// HfscClass is a representation of the HFSC class -type HfscClass struct { - ClassAttrs - Rsc ServiceCurve - Fsc ServiceCurve - Usc ServiceCurve -} - -// SetUsc sets the Usc curve -func (hfsc *HfscClass) SetUsc(m1 uint32, d uint32, m2 uint32) { - hfsc.Usc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8} -} - -// SetFsc sets the Fsc curve -func (hfsc *HfscClass) SetFsc(m1 uint32, d uint32, m2 uint32) { - hfsc.Fsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8} -} - -// SetRsc sets the Rsc curve -func (hfsc *HfscClass) SetRsc(m1 uint32, d uint32, m2 uint32) { - hfsc.Rsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8} -} - -// SetSC implements the SC from the tc CLI -func (hfsc *HfscClass) SetSC(m1 uint32, d uint32, m2 uint32) { - hfsc.Rsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8} - hfsc.Fsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8} -} - -// SetUL implements the UL from the tc CLI -func (hfsc *HfscClass) SetUL(m1 uint32, d uint32, m2 uint32) { - hfsc.Usc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8} -} - -// SetLS implements the LS from the tc CLI -func (hfsc *HfscClass) SetLS(m1 uint32, d uint32, m2 uint32) { - hfsc.Fsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8} -} - -// NewHfscClass returns a new HFSC struct with the set parameters -func NewHfscClass(attrs ClassAttrs) *HfscClass { - return &HfscClass{ - ClassAttrs: attrs, - Rsc: ServiceCurve{}, - Fsc: ServiceCurve{}, - Usc: ServiceCurve{}, - } -} - -func (hfsc *HfscClass) String() string { - return fmt.Sprintf( - "{%s -- {RSC: {m1=%d d=%d m2=%d}} {FSC: {m1=%d d=%d m2=%d}} {USC: {m1=%d d=%d m2=%d}}}", - hfsc.Attrs(), hfsc.Rsc.m1*8, hfsc.Rsc.d, hfsc.Rsc.m2*8, hfsc.Fsc.m1*8, hfsc.Fsc.d, hfsc.Fsc.m2*8, hfsc.Usc.m1*8, hfsc.Usc.d, hfsc.Usc.m2*8, - ) -} - -// Attrs return the Hfsc parameters -func (hfsc *HfscClass) Attrs() *ClassAttrs { - return &hfsc.ClassAttrs -} - -// Type return the type of the class -func (hfsc *HfscClass) Type() string { - return "hfsc" -} diff --git a/vendor/github.com/vishvananda/netlink/class_linux.go b/vendor/github.com/vishvananda/netlink/class_linux.go deleted file mode 100644 index 31091e501..000000000 --- a/vendor/github.com/vishvananda/netlink/class_linux.go +++ /dev/null @@ -1,384 +0,0 @@ -package netlink - -import ( - "bytes" - "encoding/binary" - "encoding/hex" - "errors" - "fmt" - "syscall" - - "github.com/vishvananda/netlink/nl" - "golang.org/x/sys/unix" -) - -// Internal tc_stats representation in Go struct. -// This is for internal uses only to deserialize the payload of rtattr. -// After the deserialization, this should be converted into the canonical stats -// struct, ClassStatistics, in case of statistics of a class. -// Ref: struct tc_stats { ... } -type tcStats struct { - Bytes uint64 // Number of enqueued bytes - Packets uint32 // Number of enqueued packets - Drops uint32 // Packets dropped because of lack of resources - Overlimits uint32 // Number of throttle events when this flow goes out of allocated bandwidth - Bps uint32 // Current flow byte rate - Pps uint32 // Current flow packet rate - Qlen uint32 - Backlog uint32 -} - -// NewHtbClass NOTE: function is in here because it uses other linux functions -func NewHtbClass(attrs ClassAttrs, cattrs HtbClassAttrs) *HtbClass { - mtu := 1600 - rate := cattrs.Rate / 8 - ceil := cattrs.Ceil / 8 - buffer := cattrs.Buffer - cbuffer := cattrs.Cbuffer - - if ceil == 0 { - ceil = rate - } - - if buffer == 0 { - buffer = uint32(float64(rate)/Hz() + float64(mtu)) - } - buffer = uint32(Xmittime(rate, buffer)) - - if cbuffer == 0 { - cbuffer = uint32(float64(ceil)/Hz() + float64(mtu)) - } - cbuffer = uint32(Xmittime(ceil, cbuffer)) - - return &HtbClass{ - ClassAttrs: attrs, - Rate: rate, - Ceil: ceil, - Buffer: buffer, - Cbuffer: cbuffer, - Quantum: 10, - Level: 0, - Prio: 0, - } -} - -// ClassDel will delete a class from the system. -// Equivalent to: `tc class del $class` -func ClassDel(class Class) error { - return pkgHandle.ClassDel(class) -} - -// ClassDel will delete a class from the system. -// Equivalent to: `tc class del $class` -func (h *Handle) ClassDel(class Class) error { - return h.classModify(unix.RTM_DELTCLASS, 0, class) -} - -// ClassChange will change a class in place -// Equivalent to: `tc class change $class` -// The parent and handle MUST NOT be changed. -func ClassChange(class Class) error { - return pkgHandle.ClassChange(class) -} - -// ClassChange will change a class in place -// Equivalent to: `tc class change $class` -// The parent and handle MUST NOT be changed. -func (h *Handle) ClassChange(class Class) error { - return h.classModify(unix.RTM_NEWTCLASS, 0, class) -} - -// ClassReplace will replace a class to the system. -// quivalent to: `tc class replace $class` -// The handle MAY be changed. -// If a class already exist with this parent/handle pair, the class is changed. -// If a class does not already exist with this parent/handle, a new class is created. -func ClassReplace(class Class) error { - return pkgHandle.ClassReplace(class) -} - -// ClassReplace will replace a class to the system. -// quivalent to: `tc class replace $class` -// The handle MAY be changed. -// If a class already exist with this parent/handle pair, the class is changed. -// If a class does not already exist with this parent/handle, a new class is created. -func (h *Handle) ClassReplace(class Class) error { - return h.classModify(unix.RTM_NEWTCLASS, unix.NLM_F_CREATE, class) -} - -// ClassAdd will add a class to the system. -// Equivalent to: `tc class add $class` -func ClassAdd(class Class) error { - return pkgHandle.ClassAdd(class) -} - -// ClassAdd will add a class to the system. -// Equivalent to: `tc class add $class` -func (h *Handle) ClassAdd(class Class) error { - return h.classModify( - unix.RTM_NEWTCLASS, - unix.NLM_F_CREATE|unix.NLM_F_EXCL, - class, - ) -} - -func (h *Handle) classModify(cmd, flags int, class Class) error { - req := h.newNetlinkRequest(cmd, flags|unix.NLM_F_ACK) - base := class.Attrs() - msg := &nl.TcMsg{ - Family: nl.FAMILY_ALL, - Ifindex: int32(base.LinkIndex), - Handle: base.Handle, - Parent: base.Parent, - } - req.AddData(msg) - - if cmd != unix.RTM_DELTCLASS { - if err := classPayload(req, class); err != nil { - return err - } - } - _, err := req.Execute(unix.NETLINK_ROUTE, 0) - return err -} - -func classPayload(req *nl.NetlinkRequest, class Class) error { - req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(class.Type()))) - - options := nl.NewRtAttr(nl.TCA_OPTIONS, nil) - switch class.Type() { - case "htb": - htb := class.(*HtbClass) - opt := nl.TcHtbCopt{} - opt.Buffer = htb.Buffer - opt.Cbuffer = htb.Cbuffer - opt.Quantum = htb.Quantum - opt.Level = htb.Level - opt.Prio = htb.Prio - // TODO: Handle Debug properly. For now default to 0 - /* Calculate {R,C}Tab and set Rate and Ceil */ - cellLog := -1 - ccellLog := -1 - linklayer := nl.LINKLAYER_ETHERNET - mtu := 1600 - var rtab [256]uint32 - var ctab [256]uint32 - tcrate := nl.TcRateSpec{Rate: uint32(htb.Rate)} - if CalcRtable(&tcrate, rtab[:], cellLog, uint32(mtu), linklayer) < 0 { - return errors.New("HTB: failed to calculate rate table") - } - opt.Rate = tcrate - tcceil := nl.TcRateSpec{Rate: uint32(htb.Ceil)} - if CalcRtable(&tcceil, ctab[:], ccellLog, uint32(mtu), linklayer) < 0 { - return errors.New("HTB: failed to calculate ceil rate table") - } - opt.Ceil = tcceil - options.AddRtAttr(nl.TCA_HTB_PARMS, opt.Serialize()) - options.AddRtAttr(nl.TCA_HTB_RTAB, SerializeRtab(rtab)) - options.AddRtAttr(nl.TCA_HTB_CTAB, SerializeRtab(ctab)) - case "hfsc": - hfsc := class.(*HfscClass) - opt := nl.HfscCopt{} - opt.Rsc.Set(hfsc.Rsc.Attrs()) - opt.Fsc.Set(hfsc.Fsc.Attrs()) - opt.Usc.Set(hfsc.Usc.Attrs()) - options.AddRtAttr(nl.TCA_HFSC_RSC, nl.SerializeHfscCurve(&opt.Rsc)) - options.AddRtAttr(nl.TCA_HFSC_FSC, nl.SerializeHfscCurve(&opt.Fsc)) - options.AddRtAttr(nl.TCA_HFSC_USC, nl.SerializeHfscCurve(&opt.Usc)) - } - req.AddData(options) - return nil -} - -// ClassList gets a list of classes in the system. -// Equivalent to: `tc class show`. -// Generally returns nothing if link and parent are not specified. -func ClassList(link Link, parent uint32) ([]Class, error) { - return pkgHandle.ClassList(link, parent) -} - -// ClassList gets a list of classes in the system. -// Equivalent to: `tc class show`. -// Generally returns nothing if link and parent are not specified. -func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) { - req := h.newNetlinkRequest(unix.RTM_GETTCLASS, unix.NLM_F_DUMP) - msg := &nl.TcMsg{ - Family: nl.FAMILY_ALL, - Parent: parent, - } - if link != nil { - base := link.Attrs() - h.ensureIndex(base) - msg.Ifindex = int32(base.Index) - } - req.AddData(msg) - - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTCLASS) - if err != nil { - return nil, err - } - - var res []Class - for _, m := range msgs { - msg := nl.DeserializeTcMsg(m) - - attrs, err := nl.ParseRouteAttr(m[msg.Len():]) - if err != nil { - return nil, err - } - - base := ClassAttrs{ - LinkIndex: int(msg.Ifindex), - Handle: msg.Handle, - Parent: msg.Parent, - Statistics: nil, - } - - var class Class - classType := "" - for _, attr := range attrs { - switch attr.Attr.Type { - case nl.TCA_KIND: - classType = string(attr.Value[:len(attr.Value)-1]) - switch classType { - case "htb": - class = &HtbClass{} - case "hfsc": - class = &HfscClass{} - default: - class = &GenericClass{ClassType: classType} - } - case nl.TCA_OPTIONS: - switch classType { - case "htb": - data, err := nl.ParseRouteAttr(attr.Value) - if err != nil { - return nil, err - } - _, err = parseHtbClassData(class, data) - if err != nil { - return nil, err - } - case "hfsc": - data, err := nl.ParseRouteAttr(attr.Value) - if err != nil { - return nil, err - } - _, err = parseHfscClassData(class, data) - if err != nil { - return nil, err - } - } - // For backward compatibility. - case nl.TCA_STATS: - base.Statistics, err = parseTcStats(attr.Value) - if err != nil { - return nil, err - } - case nl.TCA_STATS2: - base.Statistics, err = parseTcStats2(attr.Value) - if err != nil { - return nil, err - } - } - } - *class.Attrs() = base - res = append(res, class) - } - - return res, nil -} - -func parseHtbClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, error) { - htb := class.(*HtbClass) - detailed := false - for _, datum := range data { - switch datum.Attr.Type { - case nl.TCA_HTB_PARMS: - opt := nl.DeserializeTcHtbCopt(datum.Value) - htb.Rate = uint64(opt.Rate.Rate) - htb.Ceil = uint64(opt.Ceil.Rate) - htb.Buffer = opt.Buffer - htb.Cbuffer = opt.Cbuffer - htb.Quantum = opt.Quantum - htb.Level = opt.Level - htb.Prio = opt.Prio - } - } - return detailed, nil -} - -func parseHfscClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, error) { - hfsc := class.(*HfscClass) - detailed := false - for _, datum := range data { - m1, d, m2 := nl.DeserializeHfscCurve(datum.Value).Attrs() - switch datum.Attr.Type { - case nl.TCA_HFSC_RSC: - hfsc.Rsc = ServiceCurve{m1: m1, d: d, m2: m2} - case nl.TCA_HFSC_FSC: - hfsc.Fsc = ServiceCurve{m1: m1, d: d, m2: m2} - case nl.TCA_HFSC_USC: - hfsc.Usc = ServiceCurve{m1: m1, d: d, m2: m2} - } - } - return detailed, nil -} - -func parseTcStats(data []byte) (*ClassStatistics, error) { - buf := &bytes.Buffer{} - buf.Write(data) - native := nl.NativeEndian() - tcStats := &tcStats{} - if err := binary.Read(buf, native, tcStats); err != nil { - return nil, err - } - - stats := NewClassStatistics() - stats.Basic.Bytes = tcStats.Bytes - stats.Basic.Packets = tcStats.Packets - stats.Queue.Qlen = tcStats.Qlen - stats.Queue.Backlog = tcStats.Backlog - stats.Queue.Drops = tcStats.Drops - stats.Queue.Overlimits = tcStats.Overlimits - stats.RateEst.Bps = tcStats.Bps - stats.RateEst.Pps = tcStats.Pps - - return stats, nil -} - -func parseGnetStats(data []byte, gnetStats interface{}) error { - buf := &bytes.Buffer{} - buf.Write(data) - native := nl.NativeEndian() - return binary.Read(buf, native, gnetStats) -} - -func parseTcStats2(data []byte) (*ClassStatistics, error) { - rtAttrs, err := nl.ParseRouteAttr(data) - if err != nil { - return nil, err - } - stats := NewClassStatistics() - for _, datum := range rtAttrs { - switch datum.Attr.Type { - case nl.TCA_STATS_BASIC: - if err := parseGnetStats(datum.Value, stats.Basic); err != nil { - return nil, fmt.Errorf("Failed to parse ClassStatistics.Basic with: %v\n%s", - err, hex.Dump(datum.Value)) - } - case nl.TCA_STATS_QUEUE: - if err := parseGnetStats(datum.Value, stats.Queue); err != nil { - return nil, fmt.Errorf("Failed to parse ClassStatistics.Queue with: %v\n%s", - err, hex.Dump(datum.Value)) - } - case nl.TCA_STATS_RATE_EST: - if err := parseGnetStats(datum.Value, stats.RateEst); err != nil { - return nil, fmt.Errorf("Failed to parse ClassStatistics.RateEst with: %v\n%s", - err, hex.Dump(datum.Value)) - } - } - } - - return stats, nil -} diff --git a/vendor/github.com/vishvananda/netlink/conntrack_linux.go b/vendor/github.com/vishvananda/netlink/conntrack_linux.go deleted file mode 100644 index 4bff0dcba..000000000 --- a/vendor/github.com/vishvananda/netlink/conntrack_linux.go +++ /dev/null @@ -1,394 +0,0 @@ -package netlink - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - "net" - - "github.com/vishvananda/netlink/nl" - "golang.org/x/sys/unix" -) - -// ConntrackTableType Conntrack table for the netlink operation -type ConntrackTableType uint8 - -const ( - // ConntrackTable Conntrack table - // https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink.h -> #define NFNL_SUBSYS_CTNETLINK 1 - ConntrackTable = 1 - // ConntrackExpectTable Conntrack expect table - // https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink.h -> #define NFNL_SUBSYS_CTNETLINK_EXP 2 - ConntrackExpectTable = 2 -) - -const ( - // backward compatibility with golang 1.6 which does not have io.SeekCurrent - seekCurrent = 1 -) - -// InetFamily Family type -type InetFamily uint8 - -// -L [table] [options] List conntrack or expectation table -// -G [table] parameters Get conntrack or expectation - -// -I [table] parameters Create a conntrack or expectation -// -U [table] parameters Update a conntrack -// -E [table] [options] Show events - -// -C [table] Show counter -// -S Show statistics - -// ConntrackTableList returns the flow list of a table of a specific family -// conntrack -L [table] [options] List conntrack or expectation table -func ConntrackTableList(table ConntrackTableType, family InetFamily) ([]*ConntrackFlow, error) { - return pkgHandle.ConntrackTableList(table, family) -} - -// ConntrackTableFlush flushes all the flows of a specified table -// conntrack -F [table] Flush table -// The flush operation applies to all the family types -func ConntrackTableFlush(table ConntrackTableType) error { - return pkgHandle.ConntrackTableFlush(table) -} - -// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter -// conntrack -D [table] parameters Delete conntrack or expectation -func ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter CustomConntrackFilter) (uint, error) { - return pkgHandle.ConntrackDeleteFilter(table, family, filter) -} - -// ConntrackTableList returns the flow list of a table of a specific family using the netlink handle passed -// conntrack -L [table] [options] List conntrack or expectation table -func (h *Handle) ConntrackTableList(table ConntrackTableType, family InetFamily) ([]*ConntrackFlow, error) { - res, err := h.dumpConntrackTable(table, family) - if err != nil { - return nil, err - } - - // Deserialize all the flows - var result []*ConntrackFlow - for _, dataRaw := range res { - result = append(result, parseRawData(dataRaw)) - } - - return result, nil -} - -// ConntrackTableFlush flushes all the flows of a specified table using the netlink handle passed -// conntrack -F [table] Flush table -// The flush operation applies to all the family types -func (h *Handle) ConntrackTableFlush(table ConntrackTableType) error { - req := h.newConntrackRequest(table, unix.AF_INET, nl.IPCTNL_MSG_CT_DELETE, unix.NLM_F_ACK) - _, err := req.Execute(unix.NETLINK_NETFILTER, 0) - return err -} - -// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter using the netlink handle passed -// conntrack -D [table] parameters Delete conntrack or expectation -func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter CustomConntrackFilter) (uint, error) { - res, err := h.dumpConntrackTable(table, family) - if err != nil { - return 0, err - } - - var matched uint - for _, dataRaw := range res { - flow := parseRawData(dataRaw) - if match := filter.MatchConntrackFlow(flow); match { - req2 := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_DELETE, unix.NLM_F_ACK) - // skip the first 4 byte that are the netfilter header, the newConntrackRequest is adding it already - req2.AddRawData(dataRaw[4:]) - req2.Execute(unix.NETLINK_NETFILTER, 0) - matched++ - } - } - - return matched, nil -} - -func (h *Handle) newConntrackRequest(table ConntrackTableType, family InetFamily, operation, flags int) *nl.NetlinkRequest { - // Create the Netlink request object - req := h.newNetlinkRequest((int(table)<<8)|operation, flags) - // Add the netfilter header - msg := &nl.Nfgenmsg{ - NfgenFamily: uint8(family), - Version: nl.NFNETLINK_V0, - ResId: 0, - } - req.AddData(msg) - return req -} - -func (h *Handle) dumpConntrackTable(table ConntrackTableType, family InetFamily) ([][]byte, error) { - req := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_GET, unix.NLM_F_DUMP) - return req.Execute(unix.NETLINK_NETFILTER, 0) -} - -// The full conntrack flow structure is very complicated and can be found in the file: -// http://git.netfilter.org/libnetfilter_conntrack/tree/include/internal/object.h -// For the time being, the structure below allows to parse and extract the base information of a flow -type ipTuple struct { - Bytes uint64 - DstIP net.IP - DstPort uint16 - Packets uint64 - Protocol uint8 - SrcIP net.IP - SrcPort uint16 -} - -type ConntrackFlow struct { - FamilyType uint8 - Forward ipTuple - Reverse ipTuple - Mark uint32 -} - -func (s *ConntrackFlow) String() string { - // conntrack cmd output: - // udp 17 src=127.0.0.1 dst=127.0.0.1 sport=4001 dport=1234 packets=5 bytes=532 [UNREPLIED] src=127.0.0.1 dst=127.0.0.1 sport=1234 dport=4001 packets=10 bytes=1078 mark=0 - return fmt.Sprintf("%s\t%d src=%s dst=%s sport=%d dport=%d packets=%d bytes=%d\tsrc=%s dst=%s sport=%d dport=%d packets=%d bytes=%d mark=%d", - nl.L4ProtoMap[s.Forward.Protocol], s.Forward.Protocol, - s.Forward.SrcIP.String(), s.Forward.DstIP.String(), s.Forward.SrcPort, s.Forward.DstPort, s.Forward.Packets, s.Forward.Bytes, - s.Reverse.SrcIP.String(), s.Reverse.DstIP.String(), s.Reverse.SrcPort, s.Reverse.DstPort, s.Reverse.Packets, s.Reverse.Bytes, - s.Mark) -} - -// This method parse the ip tuple structure -// The message structure is the following: -// -// -// -// -// -func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) uint8 { - for i := 0; i < 2; i++ { - _, t, _, v := parseNfAttrTLV(reader) - switch t { - case nl.CTA_IP_V4_SRC, nl.CTA_IP_V6_SRC: - tpl.SrcIP = v - case nl.CTA_IP_V4_DST, nl.CTA_IP_V6_DST: - tpl.DstIP = v - } - } - // Skip the next 4 bytes nl.NLA_F_NESTED|nl.CTA_TUPLE_PROTO - reader.Seek(4, seekCurrent) - _, t, _, v := parseNfAttrTLV(reader) - if t == nl.CTA_PROTO_NUM { - tpl.Protocol = uint8(v[0]) - } - // Skip some padding 3 bytes - reader.Seek(3, seekCurrent) - for i := 0; i < 2; i++ { - _, t, _ := parseNfAttrTL(reader) - switch t { - case nl.CTA_PROTO_SRC_PORT: - parseBERaw16(reader, &tpl.SrcPort) - case nl.CTA_PROTO_DST_PORT: - parseBERaw16(reader, &tpl.DstPort) - } - // Skip some padding 2 byte - reader.Seek(2, seekCurrent) - } - return tpl.Protocol -} - -func parseNfAttrTLV(r *bytes.Reader) (isNested bool, attrType, len uint16, value []byte) { - isNested, attrType, len = parseNfAttrTL(r) - - value = make([]byte, len) - binary.Read(r, binary.BigEndian, &value) - return isNested, attrType, len, value -} - -func parseNfAttrTL(r *bytes.Reader) (isNested bool, attrType, len uint16) { - binary.Read(r, nl.NativeEndian(), &len) - len -= nl.SizeofNfattr - - binary.Read(r, nl.NativeEndian(), &attrType) - isNested = (attrType & nl.NLA_F_NESTED) == nl.NLA_F_NESTED - attrType = attrType & (nl.NLA_F_NESTED - 1) - - return isNested, attrType, len -} - -func parseBERaw16(r *bytes.Reader, v *uint16) { - binary.Read(r, binary.BigEndian, v) -} - -func parseBERaw32(r *bytes.Reader, v *uint32) { - binary.Read(r, binary.BigEndian, v) -} - -func parseBERaw64(r *bytes.Reader, v *uint64) { - binary.Read(r, binary.BigEndian, v) -} - -func parseByteAndPacketCounters(r *bytes.Reader) (bytes, packets uint64) { - for i := 0; i < 2; i++ { - switch _, t, _ := parseNfAttrTL(r); t { - case nl.CTA_COUNTERS_BYTES: - parseBERaw64(r, &bytes) - case nl.CTA_COUNTERS_PACKETS: - parseBERaw64(r, &packets) - default: - return - } - } - return -} - -func parseConnectionMark(r *bytes.Reader) (mark uint32) { - parseBERaw32(r, &mark) - return -} - -func parseRawData(data []byte) *ConntrackFlow { - s := &ConntrackFlow{} - // First there is the Nfgenmsg header - // consume only the family field - reader := bytes.NewReader(data) - binary.Read(reader, nl.NativeEndian(), &s.FamilyType) - - // skip rest of the Netfilter header - reader.Seek(3, seekCurrent) - // The message structure is the following: - // 4 bytes - // 4 bytes - // flow information of the forward flow - // 4 bytes - // 4 bytes - // flow information of the reverse flow - for reader.Len() > 0 { - if nested, t, l := parseNfAttrTL(reader); nested { - switch t { - case nl.CTA_TUPLE_ORIG: - if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP { - parseIpTuple(reader, &s.Forward) - } - case nl.CTA_TUPLE_REPLY: - if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP { - parseIpTuple(reader, &s.Reverse) - } else { - // Header not recognized skip it - reader.Seek(int64(l), seekCurrent) - } - case nl.CTA_COUNTERS_ORIG: - s.Forward.Bytes, s.Forward.Packets = parseByteAndPacketCounters(reader) - case nl.CTA_COUNTERS_REPLY: - s.Reverse.Bytes, s.Reverse.Packets = parseByteAndPacketCounters(reader) - } - } else { - switch t { - case nl.CTA_MARK: - s.Mark = parseConnectionMark(reader) - } - } - } - return s -} - -// Conntrack parameters and options: -// -n, --src-nat ip source NAT ip -// -g, --dst-nat ip destination NAT ip -// -j, --any-nat ip source or destination NAT ip -// -m, --mark mark Set mark -// -c, --secmark secmark Set selinux secmark -// -e, --event-mask eventmask Event mask, eg. NEW,DESTROY -// -z, --zero Zero counters while listing -// -o, --output type[,...] Output format, eg. xml -// -l, --label label[,...] conntrack labels - -// Common parameters and options: -// -s, --src, --orig-src ip Source address from original direction -// -d, --dst, --orig-dst ip Destination address from original direction -// -r, --reply-src ip Source address from reply direction -// -q, --reply-dst ip Destination address from reply direction -// -p, --protonum proto Layer 4 Protocol, eg. 'tcp' -// -f, --family proto Layer 3 Protocol, eg. 'ipv6' -// -t, --timeout timeout Set timeout -// -u, --status status Set status, eg. ASSURED -// -w, --zone value Set conntrack zone -// --orig-zone value Set zone for original direction -// --reply-zone value Set zone for reply direction -// -b, --buffer-size Netlink socket buffer size -// --mask-src ip Source mask address -// --mask-dst ip Destination mask address - -// Filter types -type ConntrackFilterType uint8 - -const ( - ConntrackOrigSrcIP = iota // -orig-src ip Source address from original direction - ConntrackOrigDstIP // -orig-dst ip Destination address from original direction - ConntrackReplySrcIP // --reply-src ip Reply Source IP - ConntrackReplyDstIP // --reply-dst ip Reply Destination IP - ConntrackReplyAnyIP // Match source or destination reply IP - ConntrackNatSrcIP = ConntrackReplySrcIP // deprecated use instead ConntrackReplySrcIP - ConntrackNatDstIP = ConntrackReplyDstIP // deprecated use instead ConntrackReplyDstIP - ConntrackNatAnyIP = ConntrackReplyAnyIP // deprecated use instaed ConntrackReplyAnyIP -) - -type CustomConntrackFilter interface { - // MatchConntrackFlow applies the filter to the flow and returns true if the flow matches - // the filter or false otherwise - MatchConntrackFlow(flow *ConntrackFlow) bool -} - -type ConntrackFilter struct { - ipFilter map[ConntrackFilterType]net.IP -} - -// AddIP adds an IP to the conntrack filter -func (f *ConntrackFilter) AddIP(tp ConntrackFilterType, ip net.IP) error { - if f.ipFilter == nil { - f.ipFilter = make(map[ConntrackFilterType]net.IP) - } - if _, ok := f.ipFilter[tp]; ok { - return errors.New("Filter attribute already present") - } - f.ipFilter[tp] = ip - return nil -} - -// MatchConntrackFlow applies the filter to the flow and returns true if the flow matches the filter -// false otherwise -func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool { - if len(f.ipFilter) == 0 { - // empty filter always not match - return false - } - - match := true - // -orig-src ip Source address from original direction - if elem, found := f.ipFilter[ConntrackOrigSrcIP]; found { - match = match && elem.Equal(flow.Forward.SrcIP) - } - - // -orig-dst ip Destination address from original direction - if elem, found := f.ipFilter[ConntrackOrigDstIP]; match && found { - match = match && elem.Equal(flow.Forward.DstIP) - } - - // -src-nat ip Source NAT ip - if elem, found := f.ipFilter[ConntrackReplySrcIP]; match && found { - match = match && elem.Equal(flow.Reverse.SrcIP) - } - - // -dst-nat ip Destination NAT ip - if elem, found := f.ipFilter[ConntrackReplyDstIP]; match && found { - match = match && elem.Equal(flow.Reverse.DstIP) - } - - // Match source or destination reply IP - if elem, found := f.ipFilter[ConntrackReplyAnyIP]; match && found { - match = match && (elem.Equal(flow.Reverse.SrcIP) || elem.Equal(flow.Reverse.DstIP)) - } - - return match -} - -var _ CustomConntrackFilter = (*ConntrackFilter)(nil) diff --git a/vendor/github.com/vishvananda/netlink/conntrack_unspecified.go b/vendor/github.com/vishvananda/netlink/conntrack_unspecified.go deleted file mode 100644 index af7af799e..000000000 --- a/vendor/github.com/vishvananda/netlink/conntrack_unspecified.go +++ /dev/null @@ -1,53 +0,0 @@ -// +build !linux - -package netlink - -// ConntrackTableType Conntrack table for the netlink operation -type ConntrackTableType uint8 - -// InetFamily Family type -type InetFamily uint8 - -// ConntrackFlow placeholder -type ConntrackFlow struct{} - -// ConntrackFilter placeholder -type ConntrackFilter struct{} - -// ConntrackTableList returns the flow list of a table of a specific family -// conntrack -L [table] [options] List conntrack or expectation table -func ConntrackTableList(table ConntrackTableType, family InetFamily) ([]*ConntrackFlow, error) { - return nil, ErrNotImplemented -} - -// ConntrackTableFlush flushes all the flows of a specified table -// conntrack -F [table] Flush table -// The flush operation applies to all the family types -func ConntrackTableFlush(table ConntrackTableType) error { - return ErrNotImplemented -} - -// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter -// conntrack -D [table] parameters Delete conntrack or expectation -func ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter *ConntrackFilter) (uint, error) { - return 0, ErrNotImplemented -} - -// ConntrackTableList returns the flow list of a table of a specific family using the netlink handle passed -// conntrack -L [table] [options] List conntrack or expectation table -func (h *Handle) ConntrackTableList(table ConntrackTableType, family InetFamily) ([]*ConntrackFlow, error) { - return nil, ErrNotImplemented -} - -// ConntrackTableFlush flushes all the flows of a specified table using the netlink handle passed -// conntrack -F [table] Flush table -// The flush operation applies to all the family types -func (h *Handle) ConntrackTableFlush(table ConntrackTableType) error { - return ErrNotImplemented -} - -// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter using the netlink handle passed -// conntrack -D [table] parameters Delete conntrack or expectation -func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter *ConntrackFilter) (uint, error) { - return 0, ErrNotImplemented -} diff --git a/vendor/github.com/vishvananda/netlink/devlink_linux.go b/vendor/github.com/vishvananda/netlink/devlink_linux.go deleted file mode 100644 index 29b3f8ec1..000000000 --- a/vendor/github.com/vishvananda/netlink/devlink_linux.go +++ /dev/null @@ -1,272 +0,0 @@ -package netlink - -import ( - "syscall" - - "fmt" - "github.com/vishvananda/netlink/nl" - "golang.org/x/sys/unix" -) - -// DevlinkDevEswitchAttr represents device's eswitch attributes -type DevlinkDevEswitchAttr struct { - Mode string - InlineMode string - EncapMode string -} - -// DevlinkDevAttrs represents device attributes -type DevlinkDevAttrs struct { - Eswitch DevlinkDevEswitchAttr -} - -// DevlinkDevice represents device and its attributes -type DevlinkDevice struct { - BusName string - DeviceName string - Attrs DevlinkDevAttrs -} - -func parseDevLinkDeviceList(msgs [][]byte) ([]*DevlinkDevice, error) { - devices := make([]*DevlinkDevice, 0, len(msgs)) - for _, m := range msgs { - attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:]) - if err != nil { - return nil, err - } - dev := &DevlinkDevice{} - if err = dev.parseAttributes(attrs); err != nil { - return nil, err - } - devices = append(devices, dev) - } - return devices, nil -} - -func eswitchStringToMode(modeName string) (uint16, error) { - if modeName == "legacy" { - return nl.DEVLINK_ESWITCH_MODE_LEGACY, nil - } else if modeName == "switchdev" { - return nl.DEVLINK_ESWITCH_MODE_SWITCHDEV, nil - } else { - return 0xffff, fmt.Errorf("invalid switchdev mode") - } -} - -func parseEswitchMode(mode uint16) string { - var eswitchMode = map[uint16]string{ - nl.DEVLINK_ESWITCH_MODE_LEGACY: "legacy", - nl.DEVLINK_ESWITCH_MODE_SWITCHDEV: "switchdev", - } - if eswitchMode[mode] == "" { - return "unknown" - } else { - return eswitchMode[mode] - } -} - -func parseEswitchInlineMode(inlinemode uint8) string { - var eswitchInlineMode = map[uint8]string{ - nl.DEVLINK_ESWITCH_INLINE_MODE_NONE: "none", - nl.DEVLINK_ESWITCH_INLINE_MODE_LINK: "link", - nl.DEVLINK_ESWITCH_INLINE_MODE_NETWORK: "network", - nl.DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT: "transport", - } - if eswitchInlineMode[inlinemode] == "" { - return "unknown" - } else { - return eswitchInlineMode[inlinemode] - } -} - -func parseEswitchEncapMode(encapmode uint8) string { - var eswitchEncapMode = map[uint8]string{ - nl.DEVLINK_ESWITCH_ENCAP_MODE_NONE: "disable", - nl.DEVLINK_ESWITCH_ENCAP_MODE_BASIC: "enable", - } - if eswitchEncapMode[encapmode] == "" { - return "unknown" - } else { - return eswitchEncapMode[encapmode] - } -} - -func (d *DevlinkDevice) parseAttributes(attrs []syscall.NetlinkRouteAttr) error { - for _, a := range attrs { - switch a.Attr.Type { - case nl.DEVLINK_ATTR_BUS_NAME: - d.BusName = string(a.Value) - case nl.DEVLINK_ATTR_DEV_NAME: - d.DeviceName = string(a.Value) - case nl.DEVLINK_ATTR_ESWITCH_MODE: - d.Attrs.Eswitch.Mode = parseEswitchMode(native.Uint16(a.Value)) - case nl.DEVLINK_ATTR_ESWITCH_INLINE_MODE: - d.Attrs.Eswitch.InlineMode = parseEswitchInlineMode(uint8(a.Value[0])) - case nl.DEVLINK_ATTR_ESWITCH_ENCAP_MODE: - d.Attrs.Eswitch.EncapMode = parseEswitchEncapMode(uint8(a.Value[0])) - } - } - return nil -} - -func (dev *DevlinkDevice) parseEswitchAttrs(msgs [][]byte) { - m := msgs[0] - attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:]) - if err != nil { - return - } - dev.parseAttributes(attrs) -} - -func (h *Handle) getEswitchAttrs(family *GenlFamily, dev *DevlinkDevice) { - msg := &nl.Genlmsg{ - Command: nl.DEVLINK_CMD_ESWITCH_GET, - Version: nl.GENL_DEVLINK_VERSION, - } - req := h.newNetlinkRequest(int(family.ID), unix.NLM_F_REQUEST|unix.NLM_F_ACK) - req.AddData(msg) - - b := make([]byte, len(dev.BusName)) - copy(b, dev.BusName) - data := nl.NewRtAttr(nl.DEVLINK_ATTR_BUS_NAME, b) - req.AddData(data) - - b = make([]byte, len(dev.DeviceName)) - copy(b, dev.DeviceName) - data = nl.NewRtAttr(nl.DEVLINK_ATTR_DEV_NAME, b) - req.AddData(data) - - msgs, err := req.Execute(unix.NETLINK_GENERIC, 0) - if err != nil { - return - } - dev.parseEswitchAttrs(msgs) -} - -// DevLinkGetDeviceList provides a pointer to devlink devices and nil error, -// otherwise returns an error code. -func (h *Handle) DevLinkGetDeviceList() ([]*DevlinkDevice, error) { - f, err := h.GenlFamilyGet(nl.GENL_DEVLINK_NAME) - if err != nil { - return nil, err - } - msg := &nl.Genlmsg{ - Command: nl.DEVLINK_CMD_GET, - Version: nl.GENL_DEVLINK_VERSION, - } - req := h.newNetlinkRequest(int(f.ID), - unix.NLM_F_REQUEST|unix.NLM_F_ACK|unix.NLM_F_DUMP) - req.AddData(msg) - msgs, err := req.Execute(unix.NETLINK_GENERIC, 0) - if err != nil { - return nil, err - } - devices, err := parseDevLinkDeviceList(msgs) - if err != nil { - return nil, err - } - for _, d := range devices { - h.getEswitchAttrs(f, d) - } - return devices, nil -} - -// DevLinkGetDeviceList provides a pointer to devlink devices and nil error, -// otherwise returns an error code. -func DevLinkGetDeviceList() ([]*DevlinkDevice, error) { - return pkgHandle.DevLinkGetDeviceList() -} - -func parseDevlinkDevice(msgs [][]byte) (*DevlinkDevice, error) { - m := msgs[0] - attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:]) - if err != nil { - return nil, err - } - dev := &DevlinkDevice{} - if err = dev.parseAttributes(attrs); err != nil { - return nil, err - } - return dev, nil -} - -func (h *Handle) createCmdReq(cmd uint8, bus string, device string) (*GenlFamily, *nl.NetlinkRequest, error) { - f, err := h.GenlFamilyGet(nl.GENL_DEVLINK_NAME) - if err != nil { - return nil, nil, err - } - - msg := &nl.Genlmsg{ - Command: cmd, - Version: nl.GENL_DEVLINK_VERSION, - } - req := h.newNetlinkRequest(int(f.ID), - unix.NLM_F_REQUEST|unix.NLM_F_ACK) - req.AddData(msg) - - b := make([]byte, len(bus)+1) - copy(b, bus) - data := nl.NewRtAttr(nl.DEVLINK_ATTR_BUS_NAME, b) - req.AddData(data) - - b = make([]byte, len(device)+1) - copy(b, device) - data = nl.NewRtAttr(nl.DEVLINK_ATTR_DEV_NAME, b) - req.AddData(data) - - return f, req, nil -} - -// DevlinkGetDeviceByName provides a pointer to devlink device and nil error, -// otherwise returns an error code. -func (h *Handle) DevLinkGetDeviceByName(Bus string, Device string) (*DevlinkDevice, error) { - f, req, err := h.createCmdReq(nl.DEVLINK_CMD_GET, Bus, Device) - if err != nil { - return nil, err - } - - respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0) - if err != nil { - return nil, err - } - dev, err := parseDevlinkDevice(respmsg) - if err == nil { - h.getEswitchAttrs(f, dev) - } - return dev, err -} - -// DevlinkGetDeviceByName provides a pointer to devlink device and nil error, -// otherwise returns an error code. -func DevLinkGetDeviceByName(Bus string, Device string) (*DevlinkDevice, error) { - return pkgHandle.DevLinkGetDeviceByName(Bus, Device) -} - -// DevLinkSetEswitchMode sets eswitch mode if able to set successfully or -// returns an error code. -// Equivalent to: `devlink dev eswitch set $dev mode switchdev` -// Equivalent to: `devlink dev eswitch set $dev mode legacy` -func (h *Handle) DevLinkSetEswitchMode(Dev *DevlinkDevice, NewMode string) error { - mode, err := eswitchStringToMode(NewMode) - if err != nil { - return err - } - - _, req, err := h.createCmdReq(nl.DEVLINK_CMD_ESWITCH_SET, Dev.BusName, Dev.DeviceName) - if err != nil { - return err - } - - req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_ESWITCH_MODE, nl.Uint16Attr(mode))) - - _, err = req.Execute(unix.NETLINK_GENERIC, 0) - return err -} - -// DevLinkSetEswitchMode sets eswitch mode if able to set successfully or -// returns an error code. -// Equivalent to: `devlink dev eswitch set $dev mode switchdev` -// Equivalent to: `devlink dev eswitch set $dev mode legacy` -func DevLinkSetEswitchMode(Dev *DevlinkDevice, NewMode string) error { - return pkgHandle.DevLinkSetEswitchMode(Dev, NewMode) -} diff --git a/vendor/github.com/vishvananda/netlink/filter.go b/vendor/github.com/vishvananda/netlink/filter.go deleted file mode 100644 index 88792eab0..000000000 --- a/vendor/github.com/vishvananda/netlink/filter.go +++ /dev/null @@ -1,324 +0,0 @@ -package netlink - -import ( - "fmt" - "net" -) - -type Filter interface { - Attrs() *FilterAttrs - Type() string -} - -// FilterAttrs represents a netlink filter. A filter is associated with a link, -// has a handle and a parent. The root filter of a device should have a -// parent == HANDLE_ROOT. -type FilterAttrs struct { - LinkIndex int - Handle uint32 - Parent uint32 - Priority uint16 // lower is higher priority - Protocol uint16 // unix.ETH_P_* -} - -func (q FilterAttrs) String() string { - return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Priority: %d, Protocol: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Priority, q.Protocol) -} - -type TcAct int32 - -const ( - TC_ACT_UNSPEC TcAct = -1 - TC_ACT_OK TcAct = 0 - TC_ACT_RECLASSIFY TcAct = 1 - TC_ACT_SHOT TcAct = 2 - TC_ACT_PIPE TcAct = 3 - TC_ACT_STOLEN TcAct = 4 - TC_ACT_QUEUED TcAct = 5 - TC_ACT_REPEAT TcAct = 6 - TC_ACT_REDIRECT TcAct = 7 - TC_ACT_JUMP TcAct = 0x10000000 -) - -func (a TcAct) String() string { - switch a { - case TC_ACT_UNSPEC: - return "unspec" - case TC_ACT_OK: - return "ok" - case TC_ACT_RECLASSIFY: - return "reclassify" - case TC_ACT_SHOT: - return "shot" - case TC_ACT_PIPE: - return "pipe" - case TC_ACT_STOLEN: - return "stolen" - case TC_ACT_QUEUED: - return "queued" - case TC_ACT_REPEAT: - return "repeat" - case TC_ACT_REDIRECT: - return "redirect" - case TC_ACT_JUMP: - return "jump" - } - return fmt.Sprintf("0x%x", int32(a)) -} - -type TcPolAct int32 - -const ( - TC_POLICE_UNSPEC TcPolAct = TcPolAct(TC_ACT_UNSPEC) - TC_POLICE_OK TcPolAct = TcPolAct(TC_ACT_OK) - TC_POLICE_RECLASSIFY TcPolAct = TcPolAct(TC_ACT_RECLASSIFY) - TC_POLICE_SHOT TcPolAct = TcPolAct(TC_ACT_SHOT) - TC_POLICE_PIPE TcPolAct = TcPolAct(TC_ACT_PIPE) -) - -func (a TcPolAct) String() string { - switch a { - case TC_POLICE_UNSPEC: - return "unspec" - case TC_POLICE_OK: - return "ok" - case TC_POLICE_RECLASSIFY: - return "reclassify" - case TC_POLICE_SHOT: - return "shot" - case TC_POLICE_PIPE: - return "pipe" - } - return fmt.Sprintf("0x%x", int32(a)) -} - -type ActionAttrs struct { - Index int - Capab int - Action TcAct - Refcnt int - Bindcnt int -} - -func (q ActionAttrs) String() string { - return fmt.Sprintf("{Index: %d, Capab: %x, Action: %s, Refcnt: %d, Bindcnt: %d}", q.Index, q.Capab, q.Action.String(), q.Refcnt, q.Bindcnt) -} - -// Action represents an action in any supported filter. -type Action interface { - Attrs() *ActionAttrs - Type() string -} - -type GenericAction struct { - ActionAttrs -} - -func (action *GenericAction) Type() string { - return "generic" -} - -func (action *GenericAction) Attrs() *ActionAttrs { - return &action.ActionAttrs -} - -type BpfAction struct { - ActionAttrs - Fd int - Name string -} - -func (action *BpfAction) Type() string { - return "bpf" -} - -func (action *BpfAction) Attrs() *ActionAttrs { - return &action.ActionAttrs -} - -type ConnmarkAction struct { - ActionAttrs - Zone uint16 -} - -func (action *ConnmarkAction) Type() string { - return "connmark" -} - -func (action *ConnmarkAction) Attrs() *ActionAttrs { - return &action.ActionAttrs -} - -func NewConnmarkAction() *ConnmarkAction { - return &ConnmarkAction{ - ActionAttrs: ActionAttrs{ - Action: TC_ACT_PIPE, - }, - } -} - -type MirredAct uint8 - -func (a MirredAct) String() string { - switch a { - case TCA_EGRESS_REDIR: - return "egress redir" - case TCA_EGRESS_MIRROR: - return "egress mirror" - case TCA_INGRESS_REDIR: - return "ingress redir" - case TCA_INGRESS_MIRROR: - return "ingress mirror" - } - return "unknown" -} - -const ( - TCA_EGRESS_REDIR MirredAct = 1 /* packet redirect to EGRESS*/ - TCA_EGRESS_MIRROR MirredAct = 2 /* mirror packet to EGRESS */ - TCA_INGRESS_REDIR MirredAct = 3 /* packet redirect to INGRESS*/ - TCA_INGRESS_MIRROR MirredAct = 4 /* mirror packet to INGRESS */ -) - -type MirredAction struct { - ActionAttrs - MirredAction MirredAct - Ifindex int -} - -func (action *MirredAction) Type() string { - return "mirred" -} - -func (action *MirredAction) Attrs() *ActionAttrs { - return &action.ActionAttrs -} - -func NewMirredAction(redirIndex int) *MirredAction { - return &MirredAction{ - ActionAttrs: ActionAttrs{ - Action: TC_ACT_STOLEN, - }, - MirredAction: TCA_EGRESS_REDIR, - Ifindex: redirIndex, - } -} - -type TunnelKeyAct int8 - -const ( - TCA_TUNNEL_KEY_SET TunnelKeyAct = 1 // set tunnel key - TCA_TUNNEL_KEY_UNSET TunnelKeyAct = 2 // unset tunnel key -) - -type TunnelKeyAction struct { - ActionAttrs - Action TunnelKeyAct - SrcAddr net.IP - DstAddr net.IP - KeyID uint32 -} - -func (action *TunnelKeyAction) Type() string { - return "tunnel_key" -} - -func (action *TunnelKeyAction) Attrs() *ActionAttrs { - return &action.ActionAttrs -} - -func NewTunnelKeyAction() *TunnelKeyAction { - return &TunnelKeyAction{ - ActionAttrs: ActionAttrs{ - Action: TC_ACT_PIPE, - }, - } -} - -type SkbEditAction struct { - ActionAttrs - QueueMapping *uint16 - PType *uint16 - Priority *uint32 - Mark *uint32 -} - -func (action *SkbEditAction) Type() string { - return "skbedit" -} - -func (action *SkbEditAction) Attrs() *ActionAttrs { - return &action.ActionAttrs -} - -func NewSkbEditAction() *SkbEditAction { - return &SkbEditAction{ - ActionAttrs: ActionAttrs{ - Action: TC_ACT_PIPE, - }, - } -} - -// MatchAll filters match all packets -type MatchAll struct { - FilterAttrs - ClassId uint32 - Actions []Action -} - -func (filter *MatchAll) Attrs() *FilterAttrs { - return &filter.FilterAttrs -} - -func (filter *MatchAll) Type() string { - return "matchall" -} - -type FilterFwAttrs struct { - ClassId uint32 - InDev string - Mask uint32 - Index uint32 - Buffer uint32 - Mtu uint32 - Mpu uint16 - Rate uint32 - AvRate uint32 - PeakRate uint32 - Action TcPolAct - Overhead uint16 - LinkLayer int -} - -type BpfFilter struct { - FilterAttrs - ClassId uint32 - Fd int - Name string - DirectAction bool - Id int - Tag string -} - -func (filter *BpfFilter) Type() string { - return "bpf" -} - -func (filter *BpfFilter) Attrs() *FilterAttrs { - return &filter.FilterAttrs -} - -// GenericFilter filters represent types that are not currently understood -// by this netlink library. -type GenericFilter struct { - FilterAttrs - FilterType string -} - -func (filter *GenericFilter) Attrs() *FilterAttrs { - return &filter.FilterAttrs -} - -func (filter *GenericFilter) Type() string { - return filter.FilterType -} diff --git a/vendor/github.com/vishvananda/netlink/filter_linux.go b/vendor/github.com/vishvananda/netlink/filter_linux.go deleted file mode 100644 index c56f314cd..000000000 --- a/vendor/github.com/vishvananda/netlink/filter_linux.go +++ /dev/null @@ -1,807 +0,0 @@ -package netlink - -import ( - "bytes" - "encoding/binary" - "encoding/hex" - "errors" - "fmt" - "net" - "syscall" - - "github.com/vishvananda/netlink/nl" - "golang.org/x/sys/unix" -) - -// Constants used in TcU32Sel.Flags. -const ( - TC_U32_TERMINAL = nl.TC_U32_TERMINAL - TC_U32_OFFSET = nl.TC_U32_OFFSET - TC_U32_VAROFFSET = nl.TC_U32_VAROFFSET - TC_U32_EAT = nl.TC_U32_EAT -) - -// Sel of the U32 filters that contains multiple TcU32Key. This is the type -// alias and the frontend representation of nl.TcU32Sel. It is serialized into -// canonical nl.TcU32Sel with the appropriate endianness. -type TcU32Sel = nl.TcU32Sel - -// TcU32Key contained of Sel in the U32 filters. This is the type alias and the -// frontend representation of nl.TcU32Key. It is serialized into chanonical -// nl.TcU32Sel with the appropriate endianness. -type TcU32Key = nl.TcU32Key - -// U32 filters on many packet related properties -type U32 struct { - FilterAttrs - ClassId uint32 - Divisor uint32 // Divisor MUST be power of 2. - Hash uint32 - RedirIndex int - Sel *TcU32Sel - Actions []Action -} - -func (filter *U32) Attrs() *FilterAttrs { - return &filter.FilterAttrs -} - -func (filter *U32) Type() string { - return "u32" -} - -// Fw filter filters on firewall marks -// NOTE: this is in filter_linux because it refers to nl.TcPolice which -// is defined in nl/tc_linux.go -type Fw struct { - FilterAttrs - ClassId uint32 - // TODO remove nl type from interface - Police nl.TcPolice - InDev string - // TODO Action - Mask uint32 - AvRate uint32 - Rtab [256]uint32 - Ptab [256]uint32 -} - -func NewFw(attrs FilterAttrs, fattrs FilterFwAttrs) (*Fw, error) { - var rtab [256]uint32 - var ptab [256]uint32 - rcellLog := -1 - pcellLog := -1 - avrate := fattrs.AvRate / 8 - police := nl.TcPolice{} - police.Rate.Rate = fattrs.Rate / 8 - police.PeakRate.Rate = fattrs.PeakRate / 8 - buffer := fattrs.Buffer - linklayer := nl.LINKLAYER_ETHERNET - - if fattrs.LinkLayer != nl.LINKLAYER_UNSPEC { - linklayer = fattrs.LinkLayer - } - - police.Action = int32(fattrs.Action) - if police.Rate.Rate != 0 { - police.Rate.Mpu = fattrs.Mpu - police.Rate.Overhead = fattrs.Overhead - if CalcRtable(&police.Rate, rtab[:], rcellLog, fattrs.Mtu, linklayer) < 0 { - return nil, errors.New("TBF: failed to calculate rate table") - } - police.Burst = uint32(Xmittime(uint64(police.Rate.Rate), uint32(buffer))) - } - police.Mtu = fattrs.Mtu - if police.PeakRate.Rate != 0 { - police.PeakRate.Mpu = fattrs.Mpu - police.PeakRate.Overhead = fattrs.Overhead - if CalcRtable(&police.PeakRate, ptab[:], pcellLog, fattrs.Mtu, linklayer) < 0 { - return nil, errors.New("POLICE: failed to calculate peak rate table") - } - } - - return &Fw{ - FilterAttrs: attrs, - ClassId: fattrs.ClassId, - InDev: fattrs.InDev, - Mask: fattrs.Mask, - Police: police, - AvRate: avrate, - Rtab: rtab, - Ptab: ptab, - }, nil -} - -func (filter *Fw) Attrs() *FilterAttrs { - return &filter.FilterAttrs -} - -func (filter *Fw) Type() string { - return "fw" -} - -// FilterDel will delete a filter from the system. -// Equivalent to: `tc filter del $filter` -func FilterDel(filter Filter) error { - return pkgHandle.FilterDel(filter) -} - -// FilterDel will delete a filter from the system. -// Equivalent to: `tc filter del $filter` -func (h *Handle) FilterDel(filter Filter) error { - req := h.newNetlinkRequest(unix.RTM_DELTFILTER, unix.NLM_F_ACK) - base := filter.Attrs() - msg := &nl.TcMsg{ - Family: nl.FAMILY_ALL, - Ifindex: int32(base.LinkIndex), - Handle: base.Handle, - Parent: base.Parent, - Info: MakeHandle(base.Priority, nl.Swap16(base.Protocol)), - } - req.AddData(msg) - - _, err := req.Execute(unix.NETLINK_ROUTE, 0) - return err -} - -// FilterAdd will add a filter to the system. -// Equivalent to: `tc filter add $filter` -func FilterAdd(filter Filter) error { - return pkgHandle.FilterAdd(filter) -} - -// FilterAdd will add a filter to the system. -// Equivalent to: `tc filter add $filter` -func (h *Handle) FilterAdd(filter Filter) error { - return h.filterModify(filter, unix.NLM_F_CREATE|unix.NLM_F_EXCL) -} - -// FilterReplace will replace a filter. -// Equivalent to: `tc filter replace $filter` -func FilterReplace(filter Filter) error { - return pkgHandle.FilterReplace(filter) -} - -// FilterReplace will replace a filter. -// Equivalent to: `tc filter replace $filter` -func (h *Handle) FilterReplace(filter Filter) error { - return h.filterModify(filter, unix.NLM_F_CREATE) -} - -func (h *Handle) filterModify(filter Filter, flags int) error { - native = nl.NativeEndian() - req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, flags|unix.NLM_F_ACK) - base := filter.Attrs() - msg := &nl.TcMsg{ - Family: nl.FAMILY_ALL, - Ifindex: int32(base.LinkIndex), - Handle: base.Handle, - Parent: base.Parent, - Info: MakeHandle(base.Priority, nl.Swap16(base.Protocol)), - } - req.AddData(msg) - req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(filter.Type()))) - - options := nl.NewRtAttr(nl.TCA_OPTIONS, nil) - - switch filter := filter.(type) { - case *U32: - sel := filter.Sel - if sel == nil { - // match all - sel = &nl.TcU32Sel{ - Nkeys: 1, - Flags: nl.TC_U32_TERMINAL, - } - sel.Keys = append(sel.Keys, nl.TcU32Key{}) - } - - if native != networkOrder { - // Copy TcU32Sel. - cSel := *sel - keys := make([]nl.TcU32Key, cap(sel.Keys)) - copy(keys, sel.Keys) - cSel.Keys = keys - sel = &cSel - - // Handle the endianness of attributes - sel.Offmask = native.Uint16(htons(sel.Offmask)) - sel.Hmask = native.Uint32(htonl(sel.Hmask)) - for i, key := range sel.Keys { - sel.Keys[i].Mask = native.Uint32(htonl(key.Mask)) - sel.Keys[i].Val = native.Uint32(htonl(key.Val)) - } - } - sel.Nkeys = uint8(len(sel.Keys)) - options.AddRtAttr(nl.TCA_U32_SEL, sel.Serialize()) - if filter.ClassId != 0 { - options.AddRtAttr(nl.TCA_U32_CLASSID, nl.Uint32Attr(filter.ClassId)) - } - if filter.Divisor != 0 { - if (filter.Divisor-1)&filter.Divisor != 0 { - return fmt.Errorf("illegal divisor %d. Must be a power of 2", filter.Divisor) - } - options.AddRtAttr(nl.TCA_U32_DIVISOR, nl.Uint32Attr(filter.Divisor)) - } - if filter.Hash != 0 { - options.AddRtAttr(nl.TCA_U32_HASH, nl.Uint32Attr(filter.Hash)) - } - actionsAttr := options.AddRtAttr(nl.TCA_U32_ACT, nil) - // backwards compatibility - if filter.RedirIndex != 0 { - filter.Actions = append([]Action{NewMirredAction(filter.RedirIndex)}, filter.Actions...) - } - if err := EncodeActions(actionsAttr, filter.Actions); err != nil { - return err - } - case *Fw: - if filter.Mask != 0 { - b := make([]byte, 4) - native.PutUint32(b, filter.Mask) - options.AddRtAttr(nl.TCA_FW_MASK, b) - } - if filter.InDev != "" { - options.AddRtAttr(nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev)) - } - if (filter.Police != nl.TcPolice{}) { - - police := options.AddRtAttr(nl.TCA_FW_POLICE, nil) - police.AddRtAttr(nl.TCA_POLICE_TBF, filter.Police.Serialize()) - if (filter.Police.Rate != nl.TcRateSpec{}) { - payload := SerializeRtab(filter.Rtab) - police.AddRtAttr(nl.TCA_POLICE_RATE, payload) - } - if (filter.Police.PeakRate != nl.TcRateSpec{}) { - payload := SerializeRtab(filter.Ptab) - police.AddRtAttr(nl.TCA_POLICE_PEAKRATE, payload) - } - } - if filter.ClassId != 0 { - b := make([]byte, 4) - native.PutUint32(b, filter.ClassId) - options.AddRtAttr(nl.TCA_FW_CLASSID, b) - } - case *BpfFilter: - var bpfFlags uint32 - if filter.ClassId != 0 { - options.AddRtAttr(nl.TCA_BPF_CLASSID, nl.Uint32Attr(filter.ClassId)) - } - if filter.Fd >= 0 { - options.AddRtAttr(nl.TCA_BPF_FD, nl.Uint32Attr((uint32(filter.Fd)))) - } - if filter.Name != "" { - options.AddRtAttr(nl.TCA_BPF_NAME, nl.ZeroTerminated(filter.Name)) - } - if filter.DirectAction { - bpfFlags |= nl.TCA_BPF_FLAG_ACT_DIRECT - } - options.AddRtAttr(nl.TCA_BPF_FLAGS, nl.Uint32Attr(bpfFlags)) - case *MatchAll: - actionsAttr := options.AddRtAttr(nl.TCA_MATCHALL_ACT, nil) - if err := EncodeActions(actionsAttr, filter.Actions); err != nil { - return err - } - if filter.ClassId != 0 { - options.AddRtAttr(nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId)) - } - } - - req.AddData(options) - _, err := req.Execute(unix.NETLINK_ROUTE, 0) - return err -} - -// FilterList gets a list of filters in the system. -// Equivalent to: `tc filter show`. -// Generally returns nothing if link and parent are not specified. -func FilterList(link Link, parent uint32) ([]Filter, error) { - return pkgHandle.FilterList(link, parent) -} - -// FilterList gets a list of filters in the system. -// Equivalent to: `tc filter show`. -// Generally returns nothing if link and parent are not specified. -func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) { - req := h.newNetlinkRequest(unix.RTM_GETTFILTER, unix.NLM_F_DUMP) - msg := &nl.TcMsg{ - Family: nl.FAMILY_ALL, - Parent: parent, - } - if link != nil { - base := link.Attrs() - h.ensureIndex(base) - msg.Ifindex = int32(base.Index) - } - req.AddData(msg) - - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTFILTER) - if err != nil { - return nil, err - } - - var res []Filter - for _, m := range msgs { - msg := nl.DeserializeTcMsg(m) - - attrs, err := nl.ParseRouteAttr(m[msg.Len():]) - if err != nil { - return nil, err - } - - base := FilterAttrs{ - LinkIndex: int(msg.Ifindex), - Handle: msg.Handle, - Parent: msg.Parent, - } - base.Priority, base.Protocol = MajorMinor(msg.Info) - base.Protocol = nl.Swap16(base.Protocol) - - var filter Filter - filterType := "" - detailed := false - for _, attr := range attrs { - switch attr.Attr.Type { - case nl.TCA_KIND: - filterType = string(attr.Value[:len(attr.Value)-1]) - switch filterType { - case "u32": - filter = &U32{} - case "fw": - filter = &Fw{} - case "bpf": - filter = &BpfFilter{} - case "matchall": - filter = &MatchAll{} - default: - filter = &GenericFilter{FilterType: filterType} - } - case nl.TCA_OPTIONS: - data, err := nl.ParseRouteAttr(attr.Value) - if err != nil { - return nil, err - } - switch filterType { - case "u32": - detailed, err = parseU32Data(filter, data) - if err != nil { - return nil, err - } - case "fw": - detailed, err = parseFwData(filter, data) - if err != nil { - return nil, err - } - case "bpf": - detailed, err = parseBpfData(filter, data) - if err != nil { - return nil, err - } - case "matchall": - detailed, err = parseMatchAllData(filter, data) - if err != nil { - return nil, err - } - default: - detailed = true - } - } - } - // only return the detailed version of the filter - if detailed { - *filter.Attrs() = base - res = append(res, filter) - } - } - - return res, nil -} - -func toTcGen(attrs *ActionAttrs, tcgen *nl.TcGen) { - tcgen.Index = uint32(attrs.Index) - tcgen.Capab = uint32(attrs.Capab) - tcgen.Action = int32(attrs.Action) - tcgen.Refcnt = int32(attrs.Refcnt) - tcgen.Bindcnt = int32(attrs.Bindcnt) -} - -func toAttrs(tcgen *nl.TcGen, attrs *ActionAttrs) { - attrs.Index = int(tcgen.Index) - attrs.Capab = int(tcgen.Capab) - attrs.Action = TcAct(tcgen.Action) - attrs.Refcnt = int(tcgen.Refcnt) - attrs.Bindcnt = int(tcgen.Bindcnt) -} - -func EncodeActions(attr *nl.RtAttr, actions []Action) error { - tabIndex := int(nl.TCA_ACT_TAB) - - for _, action := range actions { - switch action := action.(type) { - default: - return fmt.Errorf("unknown action type %s", action.Type()) - case *MirredAction: - table := attr.AddRtAttr(tabIndex, nil) - tabIndex++ - table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("mirred")) - aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) - mirred := nl.TcMirred{ - Eaction: int32(action.MirredAction), - Ifindex: uint32(action.Ifindex), - } - toTcGen(action.Attrs(), &mirred.TcGen) - aopts.AddRtAttr(nl.TCA_MIRRED_PARMS, mirred.Serialize()) - case *TunnelKeyAction: - table := attr.AddRtAttr(tabIndex, nil) - tabIndex++ - table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("tunnel_key")) - aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) - tun := nl.TcTunnelKey{ - Action: int32(action.Action), - } - toTcGen(action.Attrs(), &tun.TcGen) - aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_PARMS, tun.Serialize()) - if action.Action == TCA_TUNNEL_KEY_SET { - aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_KEY_ID, htonl(action.KeyID)) - if v4 := action.SrcAddr.To4(); v4 != nil { - aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV4_SRC, v4[:]) - } else if v6 := action.SrcAddr.To16(); v6 != nil { - aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV6_SRC, v6[:]) - } else { - return fmt.Errorf("invalid src addr %s for tunnel_key action", action.SrcAddr) - } - if v4 := action.DstAddr.To4(); v4 != nil { - aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV4_DST, v4[:]) - } else if v6 := action.DstAddr.To16(); v6 != nil { - aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV6_DST, v6[:]) - } else { - return fmt.Errorf("invalid dst addr %s for tunnel_key action", action.DstAddr) - } - } - case *SkbEditAction: - table := attr.AddRtAttr(tabIndex, nil) - tabIndex++ - table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("skbedit")) - aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) - skbedit := nl.TcSkbEdit{} - toTcGen(action.Attrs(), &skbedit.TcGen) - aopts.AddRtAttr(nl.TCA_SKBEDIT_PARMS, skbedit.Serialize()) - if action.QueueMapping != nil { - aopts.AddRtAttr(nl.TCA_SKBEDIT_QUEUE_MAPPING, nl.Uint16Attr(*action.QueueMapping)) - } - if action.Priority != nil { - aopts.AddRtAttr(nl.TCA_SKBEDIT_PRIORITY, nl.Uint32Attr(*action.Priority)) - } - if action.PType != nil { - aopts.AddRtAttr(nl.TCA_SKBEDIT_PTYPE, nl.Uint16Attr(*action.PType)) - } - if action.Mark != nil { - aopts.AddRtAttr(nl.TCA_SKBEDIT_MARK, nl.Uint32Attr(*action.Mark)) - } - case *ConnmarkAction: - table := attr.AddRtAttr(tabIndex, nil) - tabIndex++ - table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("connmark")) - aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) - connmark := nl.TcConnmark{ - Zone: action.Zone, - } - toTcGen(action.Attrs(), &connmark.TcGen) - aopts.AddRtAttr(nl.TCA_CONNMARK_PARMS, connmark.Serialize()) - case *BpfAction: - table := attr.AddRtAttr(tabIndex, nil) - tabIndex++ - table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("bpf")) - aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) - gen := nl.TcGen{} - toTcGen(action.Attrs(), &gen) - aopts.AddRtAttr(nl.TCA_ACT_BPF_PARMS, gen.Serialize()) - aopts.AddRtAttr(nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd))) - aopts.AddRtAttr(nl.TCA_ACT_BPF_NAME, nl.ZeroTerminated(action.Name)) - case *GenericAction: - table := attr.AddRtAttr(tabIndex, nil) - tabIndex++ - table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("gact")) - aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) - gen := nl.TcGen{} - toTcGen(action.Attrs(), &gen) - aopts.AddRtAttr(nl.TCA_GACT_PARMS, gen.Serialize()) - } - } - return nil -} - -func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) { - var actions []Action - for _, table := range tables { - var action Action - var actionType string - aattrs, err := nl.ParseRouteAttr(table.Value) - if err != nil { - return nil, err - } - nextattr: - for _, aattr := range aattrs { - switch aattr.Attr.Type { - case nl.TCA_KIND: - actionType = string(aattr.Value[:len(aattr.Value)-1]) - // only parse if the action is mirred or bpf - switch actionType { - case "mirred": - action = &MirredAction{} - case "bpf": - action = &BpfAction{} - case "connmark": - action = &ConnmarkAction{} - case "gact": - action = &GenericAction{} - case "tunnel_key": - action = &TunnelKeyAction{} - case "skbedit": - action = &SkbEditAction{} - default: - break nextattr - } - case nl.TCA_OPTIONS: - adata, err := nl.ParseRouteAttr(aattr.Value) - if err != nil { - return nil, err - } - for _, adatum := range adata { - switch actionType { - case "mirred": - switch adatum.Attr.Type { - case nl.TCA_MIRRED_PARMS: - mirred := *nl.DeserializeTcMirred(adatum.Value) - action.(*MirredAction).ActionAttrs = ActionAttrs{} - toAttrs(&mirred.TcGen, action.Attrs()) - action.(*MirredAction).Ifindex = int(mirred.Ifindex) - action.(*MirredAction).MirredAction = MirredAct(mirred.Eaction) - } - case "tunnel_key": - switch adatum.Attr.Type { - case nl.TCA_TUNNEL_KEY_PARMS: - tun := *nl.DeserializeTunnelKey(adatum.Value) - action.(*TunnelKeyAction).ActionAttrs = ActionAttrs{} - toAttrs(&tun.TcGen, action.Attrs()) - action.(*TunnelKeyAction).Action = TunnelKeyAct(tun.Action) - case nl.TCA_TUNNEL_KEY_ENC_KEY_ID: - action.(*TunnelKeyAction).KeyID = networkOrder.Uint32(adatum.Value[0:4]) - case nl.TCA_TUNNEL_KEY_ENC_IPV6_SRC: - case nl.TCA_TUNNEL_KEY_ENC_IPV4_SRC: - action.(*TunnelKeyAction).SrcAddr = net.IP(adatum.Value[:]) - case nl.TCA_TUNNEL_KEY_ENC_IPV6_DST: - case nl.TCA_TUNNEL_KEY_ENC_IPV4_DST: - action.(*TunnelKeyAction).DstAddr = net.IP(adatum.Value[:]) - } - case "skbedit": - switch adatum.Attr.Type { - case nl.TCA_SKBEDIT_PARMS: - skbedit := *nl.DeserializeSkbEdit(adatum.Value) - action.(*SkbEditAction).ActionAttrs = ActionAttrs{} - toAttrs(&skbedit.TcGen, action.Attrs()) - case nl.TCA_SKBEDIT_MARK: - mark := native.Uint32(adatum.Value[0:4]) - action.(*SkbEditAction).Mark = &mark - case nl.TCA_SKBEDIT_PRIORITY: - priority := native.Uint32(adatum.Value[0:4]) - action.(*SkbEditAction).Priority = &priority - case nl.TCA_SKBEDIT_PTYPE: - ptype := native.Uint16(adatum.Value[0:2]) - action.(*SkbEditAction).PType = &ptype - case nl.TCA_SKBEDIT_QUEUE_MAPPING: - mapping := native.Uint16(adatum.Value[0:2]) - action.(*SkbEditAction).QueueMapping = &mapping - } - case "bpf": - switch adatum.Attr.Type { - case nl.TCA_ACT_BPF_PARMS: - gen := *nl.DeserializeTcGen(adatum.Value) - toAttrs(&gen, action.Attrs()) - case nl.TCA_ACT_BPF_FD: - action.(*BpfAction).Fd = int(native.Uint32(adatum.Value[0:4])) - case nl.TCA_ACT_BPF_NAME: - action.(*BpfAction).Name = string(adatum.Value[:len(adatum.Value)-1]) - } - case "connmark": - switch adatum.Attr.Type { - case nl.TCA_CONNMARK_PARMS: - connmark := *nl.DeserializeTcConnmark(adatum.Value) - action.(*ConnmarkAction).ActionAttrs = ActionAttrs{} - toAttrs(&connmark.TcGen, action.Attrs()) - action.(*ConnmarkAction).Zone = connmark.Zone - } - case "gact": - switch adatum.Attr.Type { - case nl.TCA_GACT_PARMS: - gen := *nl.DeserializeTcGen(adatum.Value) - toAttrs(&gen, action.Attrs()) - } - } - } - } - } - actions = append(actions, action) - } - return actions, nil -} - -func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { - native = nl.NativeEndian() - u32 := filter.(*U32) - detailed := false - for _, datum := range data { - switch datum.Attr.Type { - case nl.TCA_U32_SEL: - detailed = true - sel := nl.DeserializeTcU32Sel(datum.Value) - u32.Sel = sel - if native != networkOrder { - // Handle the endianness of attributes - u32.Sel.Offmask = native.Uint16(htons(sel.Offmask)) - u32.Sel.Hmask = native.Uint32(htonl(sel.Hmask)) - for i, key := range u32.Sel.Keys { - u32.Sel.Keys[i].Mask = native.Uint32(htonl(key.Mask)) - u32.Sel.Keys[i].Val = native.Uint32(htonl(key.Val)) - } - } - case nl.TCA_U32_ACT: - tables, err := nl.ParseRouteAttr(datum.Value) - if err != nil { - return detailed, err - } - u32.Actions, err = parseActions(tables) - if err != nil { - return detailed, err - } - for _, action := range u32.Actions { - if action, ok := action.(*MirredAction); ok { - u32.RedirIndex = int(action.Ifindex) - } - } - case nl.TCA_U32_CLASSID: - u32.ClassId = native.Uint32(datum.Value) - case nl.TCA_U32_DIVISOR: - u32.Divisor = native.Uint32(datum.Value) - case nl.TCA_U32_HASH: - u32.Hash = native.Uint32(datum.Value) - } - } - return detailed, nil -} - -func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { - native = nl.NativeEndian() - fw := filter.(*Fw) - detailed := true - for _, datum := range data { - switch datum.Attr.Type { - case nl.TCA_FW_MASK: - fw.Mask = native.Uint32(datum.Value[0:4]) - case nl.TCA_FW_CLASSID: - fw.ClassId = native.Uint32(datum.Value[0:4]) - case nl.TCA_FW_INDEV: - fw.InDev = string(datum.Value[:len(datum.Value)-1]) - case nl.TCA_FW_POLICE: - adata, _ := nl.ParseRouteAttr(datum.Value) - for _, aattr := range adata { - switch aattr.Attr.Type { - case nl.TCA_POLICE_TBF: - fw.Police = *nl.DeserializeTcPolice(aattr.Value) - case nl.TCA_POLICE_RATE: - fw.Rtab = DeserializeRtab(aattr.Value) - case nl.TCA_POLICE_PEAKRATE: - fw.Ptab = DeserializeRtab(aattr.Value) - } - } - } - } - return detailed, nil -} - -func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { - native = nl.NativeEndian() - bpf := filter.(*BpfFilter) - detailed := true - for _, datum := range data { - switch datum.Attr.Type { - case nl.TCA_BPF_FD: - bpf.Fd = int(native.Uint32(datum.Value[0:4])) - case nl.TCA_BPF_NAME: - bpf.Name = string(datum.Value[:len(datum.Value)-1]) - case nl.TCA_BPF_CLASSID: - bpf.ClassId = native.Uint32(datum.Value[0:4]) - case nl.TCA_BPF_FLAGS: - flags := native.Uint32(datum.Value[0:4]) - if (flags & nl.TCA_BPF_FLAG_ACT_DIRECT) != 0 { - bpf.DirectAction = true - } - case nl.TCA_BPF_ID: - bpf.Id = int(native.Uint32(datum.Value[0:4])) - case nl.TCA_BPF_TAG: - bpf.Tag = hex.EncodeToString(datum.Value[:len(datum.Value)-1]) - } - } - return detailed, nil -} - -func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { - native = nl.NativeEndian() - matchall := filter.(*MatchAll) - detailed := true - for _, datum := range data { - switch datum.Attr.Type { - case nl.TCA_MATCHALL_CLASSID: - matchall.ClassId = native.Uint32(datum.Value[0:4]) - case nl.TCA_MATCHALL_ACT: - tables, err := nl.ParseRouteAttr(datum.Value) - if err != nil { - return detailed, err - } - matchall.Actions, err = parseActions(tables) - if err != nil { - return detailed, err - } - } - } - return detailed, nil -} - -func AlignToAtm(size uint) uint { - var linksize, cells int - cells = int(size / nl.ATM_CELL_PAYLOAD) - if (size % nl.ATM_CELL_PAYLOAD) > 0 { - cells++ - } - linksize = cells * nl.ATM_CELL_SIZE - return uint(linksize) -} - -func AdjustSize(sz uint, mpu uint, linklayer int) uint { - if sz < mpu { - sz = mpu - } - switch linklayer { - case nl.LINKLAYER_ATM: - return AlignToAtm(sz) - default: - return sz - } -} - -func CalcRtable(rate *nl.TcRateSpec, rtab []uint32, cellLog int, mtu uint32, linklayer int) int { - bps := rate.Rate - mpu := rate.Mpu - var sz uint - if mtu == 0 { - mtu = 2047 - } - if cellLog < 0 { - cellLog = 0 - for (mtu >> uint(cellLog)) > 255 { - cellLog++ - } - } - for i := 0; i < 256; i++ { - sz = AdjustSize(uint((i+1)< 0 { - data.AddRtAttr(nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(uint32(vxlan.Age))) - } - if vxlan.Limit > 0 { - data.AddRtAttr(nl.IFLA_VXLAN_LIMIT, nl.Uint32Attr(uint32(vxlan.Limit))) - } - if vxlan.Port > 0 { - data.AddRtAttr(nl.IFLA_VXLAN_PORT, htons(uint16(vxlan.Port))) - } - if vxlan.PortLow > 0 || vxlan.PortHigh > 0 { - pr := vxlanPortRange{uint16(vxlan.PortLow), uint16(vxlan.PortHigh)} - - buf := new(bytes.Buffer) - binary.Write(buf, binary.BigEndian, &pr) - - data.AddRtAttr(nl.IFLA_VXLAN_PORT_RANGE, buf.Bytes()) - } -} - -func addBondAttrs(bond *Bond, linkInfo *nl.RtAttr) { - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - if bond.Mode >= 0 { - data.AddRtAttr(nl.IFLA_BOND_MODE, nl.Uint8Attr(uint8(bond.Mode))) - } - if bond.ActiveSlave >= 0 { - data.AddRtAttr(nl.IFLA_BOND_ACTIVE_SLAVE, nl.Uint32Attr(uint32(bond.ActiveSlave))) - } - if bond.Miimon >= 0 { - data.AddRtAttr(nl.IFLA_BOND_MIIMON, nl.Uint32Attr(uint32(bond.Miimon))) - } - if bond.UpDelay >= 0 { - data.AddRtAttr(nl.IFLA_BOND_UPDELAY, nl.Uint32Attr(uint32(bond.UpDelay))) - } - if bond.DownDelay >= 0 { - data.AddRtAttr(nl.IFLA_BOND_DOWNDELAY, nl.Uint32Attr(uint32(bond.DownDelay))) - } - if bond.UseCarrier >= 0 { - data.AddRtAttr(nl.IFLA_BOND_USE_CARRIER, nl.Uint8Attr(uint8(bond.UseCarrier))) - } - if bond.ArpInterval >= 0 { - data.AddRtAttr(nl.IFLA_BOND_ARP_INTERVAL, nl.Uint32Attr(uint32(bond.ArpInterval))) - } - if bond.ArpIpTargets != nil { - msg := data.AddRtAttr(nl.IFLA_BOND_ARP_IP_TARGET, nil) - for i := range bond.ArpIpTargets { - ip := bond.ArpIpTargets[i].To4() - if ip != nil { - msg.AddRtAttr(i, []byte(ip)) - continue - } - ip = bond.ArpIpTargets[i].To16() - if ip != nil { - msg.AddRtAttr(i, []byte(ip)) - } - } - } - if bond.ArpValidate >= 0 { - data.AddRtAttr(nl.IFLA_BOND_ARP_VALIDATE, nl.Uint32Attr(uint32(bond.ArpValidate))) - } - if bond.ArpAllTargets >= 0 { - data.AddRtAttr(nl.IFLA_BOND_ARP_ALL_TARGETS, nl.Uint32Attr(uint32(bond.ArpAllTargets))) - } - if bond.Primary >= 0 { - data.AddRtAttr(nl.IFLA_BOND_PRIMARY, nl.Uint32Attr(uint32(bond.Primary))) - } - if bond.PrimaryReselect >= 0 { - data.AddRtAttr(nl.IFLA_BOND_PRIMARY_RESELECT, nl.Uint8Attr(uint8(bond.PrimaryReselect))) - } - if bond.FailOverMac >= 0 { - data.AddRtAttr(nl.IFLA_BOND_FAIL_OVER_MAC, nl.Uint8Attr(uint8(bond.FailOverMac))) - } - if bond.XmitHashPolicy >= 0 { - data.AddRtAttr(nl.IFLA_BOND_XMIT_HASH_POLICY, nl.Uint8Attr(uint8(bond.XmitHashPolicy))) - } - if bond.ResendIgmp >= 0 { - data.AddRtAttr(nl.IFLA_BOND_RESEND_IGMP, nl.Uint32Attr(uint32(bond.ResendIgmp))) - } - if bond.NumPeerNotif >= 0 { - data.AddRtAttr(nl.IFLA_BOND_NUM_PEER_NOTIF, nl.Uint8Attr(uint8(bond.NumPeerNotif))) - } - if bond.AllSlavesActive >= 0 { - data.AddRtAttr(nl.IFLA_BOND_ALL_SLAVES_ACTIVE, nl.Uint8Attr(uint8(bond.AllSlavesActive))) - } - if bond.MinLinks >= 0 { - data.AddRtAttr(nl.IFLA_BOND_MIN_LINKS, nl.Uint32Attr(uint32(bond.MinLinks))) - } - if bond.LpInterval >= 0 { - data.AddRtAttr(nl.IFLA_BOND_LP_INTERVAL, nl.Uint32Attr(uint32(bond.LpInterval))) - } - if bond.PackersPerSlave >= 0 { - data.AddRtAttr(nl.IFLA_BOND_PACKETS_PER_SLAVE, nl.Uint32Attr(uint32(bond.PackersPerSlave))) - } - if bond.LacpRate >= 0 { - data.AddRtAttr(nl.IFLA_BOND_AD_LACP_RATE, nl.Uint8Attr(uint8(bond.LacpRate))) - } - if bond.AdSelect >= 0 { - data.AddRtAttr(nl.IFLA_BOND_AD_SELECT, nl.Uint8Attr(uint8(bond.AdSelect))) - } - if bond.AdActorSysPrio >= 0 { - data.AddRtAttr(nl.IFLA_BOND_AD_ACTOR_SYS_PRIO, nl.Uint16Attr(uint16(bond.AdActorSysPrio))) - } - if bond.AdUserPortKey >= 0 { - data.AddRtAttr(nl.IFLA_BOND_AD_USER_PORT_KEY, nl.Uint16Attr(uint16(bond.AdUserPortKey))) - } - if bond.AdActorSystem != nil { - data.AddRtAttr(nl.IFLA_BOND_AD_ACTOR_SYSTEM, []byte(bond.AdActorSystem)) - } - if bond.TlbDynamicLb >= 0 { - data.AddRtAttr(nl.IFLA_BOND_TLB_DYNAMIC_LB, nl.Uint8Attr(uint8(bond.TlbDynamicLb))) - } -} - -func cleanupFds(fds []*os.File) { - for _, f := range fds { - f.Close() - } -} - -// LinkAdd adds a new link device. The type and features of the device -// are taken from the parameters in the link object. -// Equivalent to: `ip link add $link` -func LinkAdd(link Link) error { - return pkgHandle.LinkAdd(link) -} - -// LinkAdd adds a new link device. The type and features of the device -// are taken from the parameters in the link object. -// Equivalent to: `ip link add $link` -func (h *Handle) LinkAdd(link Link) error { - return h.linkModify(link, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) -} - -func (h *Handle) linkModify(link Link, flags int) error { - // TODO: support extra data for macvlan - base := link.Attrs() - - // if tuntap, then the name can be empty, OS will provide a name - tuntap, isTuntap := link.(*Tuntap) - - if base.Name == "" && !isTuntap { - return fmt.Errorf("LinkAttrs.Name cannot be empty") - } - - if isTuntap { - // TODO: support user - // TODO: support group - if tuntap.Mode < unix.IFF_TUN || tuntap.Mode > unix.IFF_TAP { - return fmt.Errorf("Tuntap.Mode %v unknown", tuntap.Mode) - } - - queues := tuntap.Queues - - var fds []*os.File - var req ifReq - copy(req.Name[:15], base.Name) - - req.Flags = uint16(tuntap.Flags) - - if queues == 0 { //Legacy compatibility - queues = 1 - if tuntap.Flags == 0 { - req.Flags = uint16(TUNTAP_DEFAULTS) - } - } else { - // For best peformance set Flags to TUNTAP_MULTI_QUEUE_DEFAULTS | TUNTAP_VNET_HDR - // when a) KVM has support for this ABI and - // b) the value of the flag is queryable using the TUNGETIFF ioctl - if tuntap.Flags == 0 { - req.Flags = uint16(TUNTAP_MULTI_QUEUE_DEFAULTS) - } - } - - req.Flags |= uint16(tuntap.Mode) - - for i := 0; i < queues; i++ { - localReq := req - file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0) - if err != nil { - cleanupFds(fds) - return err - } - - fds = append(fds, file) - _, _, errno := unix.Syscall(unix.SYS_IOCTL, file.Fd(), uintptr(unix.TUNSETIFF), uintptr(unsafe.Pointer(&localReq))) - if errno != 0 { - cleanupFds(fds) - return fmt.Errorf("Tuntap IOCTL TUNSETIFF failed [%d], errno %v", i, errno) - } - // 1) we only care for the name of the first tap in the multi queue set - // 2) if the original name was empty, the localReq has now the actual name - // - // In addition: - // This ensures that the link name is always identical to what the kernel returns. - // Not only in case of an empty name, but also when using name templates. - // e.g. when the provided name is "tap%d", the kernel replaces %d with the next available number. - if i == 0 { - link.Attrs().Name = strings.Trim(string(localReq.Name[:]), "\x00") - } - } - - // only persist interface if NonPersist is NOT set - if !tuntap.NonPersist { - _, _, errno := unix.Syscall(unix.SYS_IOCTL, fds[0].Fd(), uintptr(unix.TUNSETPERSIST), 1) - if errno != 0 { - cleanupFds(fds) - return fmt.Errorf("Tuntap IOCTL TUNSETPERSIST failed, errno %v", errno) - } - } - - h.ensureIndex(base) - - // can't set master during create, so set it afterwards - if base.MasterIndex != 0 { - // TODO: verify MasterIndex is actually a bridge? - err := h.LinkSetMasterByIndex(link, base.MasterIndex) - if err != nil { - // un-persist (e.g. allow the interface to be removed) the tuntap - // should not hurt if not set prior, condition might be not needed - if !tuntap.NonPersist { - _, _, _ = unix.Syscall(unix.SYS_IOCTL, fds[0].Fd(), uintptr(unix.TUNSETPERSIST), 0) - } - cleanupFds(fds) - return err - } - } - - if tuntap.Queues == 0 { - cleanupFds(fds) - } else { - tuntap.Fds = fds - } - - return nil - } - - req := h.newNetlinkRequest(unix.RTM_NEWLINK, flags) - - msg := nl.NewIfInfomsg(unix.AF_UNSPEC) - // TODO: make it shorter - if base.Flags&net.FlagUp != 0 { - msg.Change = unix.IFF_UP - msg.Flags = unix.IFF_UP - } - if base.Flags&net.FlagBroadcast != 0 { - msg.Change |= unix.IFF_BROADCAST - msg.Flags |= unix.IFF_BROADCAST - } - if base.Flags&net.FlagLoopback != 0 { - msg.Change |= unix.IFF_LOOPBACK - msg.Flags |= unix.IFF_LOOPBACK - } - if base.Flags&net.FlagPointToPoint != 0 { - msg.Change |= unix.IFF_POINTOPOINT - msg.Flags |= unix.IFF_POINTOPOINT - } - if base.Flags&net.FlagMulticast != 0 { - msg.Change |= unix.IFF_MULTICAST - msg.Flags |= unix.IFF_MULTICAST - } - if base.Index != 0 { - msg.Index = int32(base.Index) - } - - req.AddData(msg) - - if base.ParentIndex != 0 { - b := make([]byte, 4) - native.PutUint32(b, uint32(base.ParentIndex)) - data := nl.NewRtAttr(unix.IFLA_LINK, b) - req.AddData(data) - } else if link.Type() == "ipvlan" || link.Type() == "ipoib" { - return fmt.Errorf("Can't create %s link without ParentIndex", link.Type()) - } - - nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(base.Name)) - req.AddData(nameData) - - if base.MTU > 0 { - mtu := nl.NewRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU))) - req.AddData(mtu) - } - - if base.TxQLen >= 0 { - qlen := nl.NewRtAttr(unix.IFLA_TXQLEN, nl.Uint32Attr(uint32(base.TxQLen))) - req.AddData(qlen) - } - - if base.HardwareAddr != nil { - hwaddr := nl.NewRtAttr(unix.IFLA_ADDRESS, []byte(base.HardwareAddr)) - req.AddData(hwaddr) - } - - if base.NumTxQueues > 0 { - txqueues := nl.NewRtAttr(unix.IFLA_NUM_TX_QUEUES, nl.Uint32Attr(uint32(base.NumTxQueues))) - req.AddData(txqueues) - } - - if base.NumRxQueues > 0 { - rxqueues := nl.NewRtAttr(unix.IFLA_NUM_RX_QUEUES, nl.Uint32Attr(uint32(base.NumRxQueues))) - req.AddData(rxqueues) - } - - if base.GSOMaxSegs > 0 { - gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_MAX_SEGS, nl.Uint32Attr(base.GSOMaxSegs)) - req.AddData(gsoAttr) - } - - if base.GSOMaxSize > 0 { - gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_MAX_SIZE, nl.Uint32Attr(base.GSOMaxSize)) - req.AddData(gsoAttr) - } - - if base.Group > 0 { - groupAttr := nl.NewRtAttr(unix.IFLA_GROUP, nl.Uint32Attr(base.Group)) - req.AddData(groupAttr) - } - - if base.Namespace != nil { - var attr *nl.RtAttr - switch ns := base.Namespace.(type) { - case NsPid: - val := nl.Uint32Attr(uint32(ns)) - attr = nl.NewRtAttr(unix.IFLA_NET_NS_PID, val) - case NsFd: - val := nl.Uint32Attr(uint32(ns)) - attr = nl.NewRtAttr(unix.IFLA_NET_NS_FD, val) - } - - req.AddData(attr) - } - - if base.Xdp != nil { - addXdpAttrs(base.Xdp, req) - } - - linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil) - linkInfo.AddRtAttr(nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type())) - - switch link := link.(type) { - case *Vlan: - b := make([]byte, 2) - native.PutUint16(b, uint16(link.VlanId)) - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - data.AddRtAttr(nl.IFLA_VLAN_ID, b) - - if link.VlanProtocol != VLAN_PROTOCOL_UNKNOWN { - data.AddRtAttr(nl.IFLA_VLAN_PROTOCOL, htons(uint16(link.VlanProtocol))) - } - case *Veth: - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - peer := data.AddRtAttr(nl.VETH_INFO_PEER, nil) - nl.NewIfInfomsgChild(peer, unix.AF_UNSPEC) - peer.AddRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(link.PeerName)) - if base.TxQLen >= 0 { - peer.AddRtAttr(unix.IFLA_TXQLEN, nl.Uint32Attr(uint32(base.TxQLen))) - } - if base.MTU > 0 { - peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU))) - } - if link.PeerHardwareAddr != nil { - peer.AddRtAttr(unix.IFLA_ADDRESS, []byte(link.PeerHardwareAddr)) - } - case *Vxlan: - addVxlanAttrs(link, linkInfo) - case *Bond: - addBondAttrs(link, linkInfo) - case *IPVlan: - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode))) - data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag))) - case *Macvlan: - if link.Mode != MACVLAN_MODE_DEFAULT { - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode])) - } - case *Macvtap: - if link.Mode != MACVLAN_MODE_DEFAULT { - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode])) - } - case *Gretap: - addGretapAttrs(link, linkInfo) - case *Iptun: - addIptunAttrs(link, linkInfo) - case *Ip6tnl: - addIp6tnlAttrs(link, linkInfo) - case *Sittun: - addSittunAttrs(link, linkInfo) - case *Gretun: - addGretunAttrs(link, linkInfo) - case *Vti: - addVtiAttrs(link, linkInfo) - case *Vrf: - addVrfAttrs(link, linkInfo) - case *Bridge: - addBridgeAttrs(link, linkInfo) - case *GTP: - addGTPAttrs(link, linkInfo) - case *Xfrmi: - addXfrmiAttrs(link, linkInfo) - case *IPoIB: - addIPoIBAttrs(link, linkInfo) - } - - req.AddData(linkInfo) - - _, err := req.Execute(unix.NETLINK_ROUTE, 0) - if err != nil { - return err - } - - h.ensureIndex(base) - - // can't set master during create, so set it afterwards - if base.MasterIndex != 0 { - // TODO: verify MasterIndex is actually a bridge? - return h.LinkSetMasterByIndex(link, base.MasterIndex) - } - return nil -} - -// LinkDel deletes link device. Either Index or Name must be set in -// the link object for it to be deleted. The other values are ignored. -// Equivalent to: `ip link del $link` -func LinkDel(link Link) error { - return pkgHandle.LinkDel(link) -} - -// LinkDel deletes link device. Either Index or Name must be set in -// the link object for it to be deleted. The other values are ignored. -// Equivalent to: `ip link del $link` -func (h *Handle) LinkDel(link Link) error { - base := link.Attrs() - - h.ensureIndex(base) - - req := h.newNetlinkRequest(unix.RTM_DELLINK, unix.NLM_F_ACK) - - msg := nl.NewIfInfomsg(unix.AF_UNSPEC) - msg.Index = int32(base.Index) - req.AddData(msg) - - _, err := req.Execute(unix.NETLINK_ROUTE, 0) - return err -} - -func (h *Handle) linkByNameDump(name string) (Link, error) { - links, err := h.LinkList() - if err != nil { - return nil, err - } - - for _, link := range links { - if link.Attrs().Name == name { - return link, nil - } - } - return nil, LinkNotFoundError{fmt.Errorf("Link %s not found", name)} -} - -func (h *Handle) linkByAliasDump(alias string) (Link, error) { - links, err := h.LinkList() - if err != nil { - return nil, err - } - - for _, link := range links { - if link.Attrs().Alias == alias { - return link, nil - } - } - return nil, LinkNotFoundError{fmt.Errorf("Link alias %s not found", alias)} -} - -// LinkByName finds a link by name and returns a pointer to the object. -func LinkByName(name string) (Link, error) { - return pkgHandle.LinkByName(name) -} - -// LinkByName finds a link by name and returns a pointer to the object. -func (h *Handle) LinkByName(name string) (Link, error) { - if h.lookupByDump { - return h.linkByNameDump(name) - } - - req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_ACK) - - msg := nl.NewIfInfomsg(unix.AF_UNSPEC) - req.AddData(msg) - - attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF)) - req.AddData(attr) - - nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(name)) - req.AddData(nameData) - - link, err := execGetLink(req) - if err == unix.EINVAL { - // older kernels don't support looking up via IFLA_IFNAME - // so fall back to dumping all links - h.lookupByDump = true - return h.linkByNameDump(name) - } - - return link, err -} - -// LinkByAlias finds a link by its alias and returns a pointer to the object. -// If there are multiple links with the alias it returns the first one -func LinkByAlias(alias string) (Link, error) { - return pkgHandle.LinkByAlias(alias) -} - -// LinkByAlias finds a link by its alias and returns a pointer to the object. -// If there are multiple links with the alias it returns the first one -func (h *Handle) LinkByAlias(alias string) (Link, error) { - if h.lookupByDump { - return h.linkByAliasDump(alias) - } - - req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_ACK) - - msg := nl.NewIfInfomsg(unix.AF_UNSPEC) - req.AddData(msg) - - attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF)) - req.AddData(attr) - - nameData := nl.NewRtAttr(unix.IFLA_IFALIAS, nl.ZeroTerminated(alias)) - req.AddData(nameData) - - link, err := execGetLink(req) - if err == unix.EINVAL { - // older kernels don't support looking up via IFLA_IFALIAS - // so fall back to dumping all links - h.lookupByDump = true - return h.linkByAliasDump(alias) - } - - return link, err -} - -// LinkByIndex finds a link by index and returns a pointer to the object. -func LinkByIndex(index int) (Link, error) { - return pkgHandle.LinkByIndex(index) -} - -// LinkByIndex finds a link by index and returns a pointer to the object. -func (h *Handle) LinkByIndex(index int) (Link, error) { - req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_ACK) - - msg := nl.NewIfInfomsg(unix.AF_UNSPEC) - msg.Index = int32(index) - req.AddData(msg) - attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF)) - req.AddData(attr) - - return execGetLink(req) -} - -func execGetLink(req *nl.NetlinkRequest) (Link, error) { - msgs, err := req.Execute(unix.NETLINK_ROUTE, 0) - if err != nil { - if errno, ok := err.(syscall.Errno); ok { - if errno == unix.ENODEV { - return nil, LinkNotFoundError{fmt.Errorf("Link not found")} - } - } - return nil, err - } - - switch { - case len(msgs) == 0: - return nil, LinkNotFoundError{fmt.Errorf("Link not found")} - - case len(msgs) == 1: - return LinkDeserialize(nil, msgs[0]) - - default: - return nil, fmt.Errorf("More than one link found") - } -} - -// linkDeserialize deserializes a raw message received from netlink into -// a link object. -func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) { - msg := nl.DeserializeIfInfomsg(m) - - attrs, err := nl.ParseRouteAttr(m[msg.Len():]) - if err != nil { - return nil, err - } - - base := LinkAttrs{Index: int(msg.Index), RawFlags: msg.Flags, Flags: linkFlags(msg.Flags), EncapType: msg.EncapType()} - if msg.Flags&unix.IFF_PROMISC != 0 { - base.Promisc = 1 - } - var ( - link Link - stats32 *LinkStatistics32 - stats64 *LinkStatistics64 - linkType string - linkSlave LinkSlave - slaveType string - ) - for _, attr := range attrs { - switch attr.Attr.Type { - case unix.IFLA_LINKINFO: - infos, err := nl.ParseRouteAttr(attr.Value) - if err != nil { - return nil, err - } - for _, info := range infos { - switch info.Attr.Type { - case nl.IFLA_INFO_KIND: - linkType = string(info.Value[:len(info.Value)-1]) - switch linkType { - case "dummy": - link = &Dummy{} - case "ifb": - link = &Ifb{} - case "bridge": - link = &Bridge{} - case "vlan": - link = &Vlan{} - case "veth": - link = &Veth{} - case "vxlan": - link = &Vxlan{} - case "bond": - link = &Bond{} - case "ipvlan": - link = &IPVlan{} - case "macvlan": - link = &Macvlan{} - case "macvtap": - link = &Macvtap{} - case "gretap": - link = &Gretap{} - case "ip6gretap": - link = &Gretap{} - case "ipip": - link = &Iptun{} - case "ip6tnl": - link = &Ip6tnl{} - case "sit": - link = &Sittun{} - case "gre": - link = &Gretun{} - case "ip6gre": - link = &Gretun{} - case "vti", "vti6": - link = &Vti{} - case "vrf": - link = &Vrf{} - case "gtp": - link = >P{} - case "xfrm": - link = &Xfrmi{} - case "tun": - link = &Tuntap{} - case "ipoib": - link = &IPoIB{} - default: - link = &GenericLink{LinkType: linkType} - } - case nl.IFLA_INFO_DATA: - data, err := nl.ParseRouteAttr(info.Value) - if err != nil { - return nil, err - } - switch linkType { - case "vlan": - parseVlanData(link, data) - case "vxlan": - parseVxlanData(link, data) - case "bond": - parseBondData(link, data) - case "ipvlan": - parseIPVlanData(link, data) - case "macvlan": - parseMacvlanData(link, data) - case "macvtap": - parseMacvtapData(link, data) - case "gretap": - parseGretapData(link, data) - case "ip6gretap": - parseGretapData(link, data) - case "ipip": - parseIptunData(link, data) - case "ip6tnl": - parseIp6tnlData(link, data) - case "sit": - parseSittunData(link, data) - case "gre": - parseGretunData(link, data) - case "ip6gre": - parseGretunData(link, data) - case "vti", "vti6": - parseVtiData(link, data) - case "vrf": - parseVrfData(link, data) - case "bridge": - parseBridgeData(link, data) - case "gtp": - parseGTPData(link, data) - case "xfrm": - parseXfrmiData(link, data) - case "tun": - parseTuntapData(link, data) - case "ipoib": - parseIPoIBData(link, data) - } - case nl.IFLA_INFO_SLAVE_KIND: - slaveType = string(info.Value[:len(info.Value)-1]) - switch slaveType { - case "bond": - linkSlave = &BondSlave{} - } - case nl.IFLA_INFO_SLAVE_DATA: - switch slaveType { - case "bond": - data, err := nl.ParseRouteAttr(info.Value) - if err != nil { - return nil, err - } - parseBondSlaveData(linkSlave, data) - } - } - } - case unix.IFLA_ADDRESS: - var nonzero bool - for _, b := range attr.Value { - if b != 0 { - nonzero = true - } - } - if nonzero { - base.HardwareAddr = attr.Value[:] - } - case unix.IFLA_IFNAME: - base.Name = string(attr.Value[:len(attr.Value)-1]) - case unix.IFLA_MTU: - base.MTU = int(native.Uint32(attr.Value[0:4])) - case unix.IFLA_LINK: - base.ParentIndex = int(native.Uint32(attr.Value[0:4])) - case unix.IFLA_MASTER: - base.MasterIndex = int(native.Uint32(attr.Value[0:4])) - case unix.IFLA_TXQLEN: - base.TxQLen = int(native.Uint32(attr.Value[0:4])) - case unix.IFLA_IFALIAS: - base.Alias = string(attr.Value[:len(attr.Value)-1]) - case unix.IFLA_STATS: - stats32 = new(LinkStatistics32) - if err := binary.Read(bytes.NewBuffer(attr.Value[:]), nl.NativeEndian(), stats32); err != nil { - return nil, err - } - case unix.IFLA_STATS64: - stats64 = new(LinkStatistics64) - if err := binary.Read(bytes.NewBuffer(attr.Value[:]), nl.NativeEndian(), stats64); err != nil { - return nil, err - } - case unix.IFLA_XDP: - xdp, err := parseLinkXdp(attr.Value[:]) - if err != nil { - return nil, err - } - base.Xdp = xdp - case unix.IFLA_PROTINFO | unix.NLA_F_NESTED: - if hdr != nil && hdr.Type == unix.RTM_NEWLINK && - msg.Family == unix.AF_BRIDGE { - attrs, err := nl.ParseRouteAttr(attr.Value[:]) - if err != nil { - return nil, err - } - protinfo := parseProtinfo(attrs) - base.Protinfo = &protinfo - } - case unix.IFLA_OPERSTATE: - base.OperState = LinkOperState(uint8(attr.Value[0])) - case unix.IFLA_LINK_NETNSID: - base.NetNsID = int(native.Uint32(attr.Value[0:4])) - case unix.IFLA_GSO_MAX_SIZE: - base.GSOMaxSize = native.Uint32(attr.Value[0:4]) - case unix.IFLA_GSO_MAX_SEGS: - base.GSOMaxSegs = native.Uint32(attr.Value[0:4]) - case unix.IFLA_VFINFO_LIST: - data, err := nl.ParseRouteAttr(attr.Value) - if err != nil { - return nil, err - } - vfs, err := parseVfInfoList(data) - if err != nil { - return nil, err - } - base.Vfs = vfs - case unix.IFLA_NUM_TX_QUEUES: - base.NumTxQueues = int(native.Uint32(attr.Value[0:4])) - case unix.IFLA_NUM_RX_QUEUES: - base.NumRxQueues = int(native.Uint32(attr.Value[0:4])) - case unix.IFLA_GROUP: - base.Group = native.Uint32(attr.Value[0:4]) - } - } - - if stats64 != nil { - base.Statistics = (*LinkStatistics)(stats64) - } else if stats32 != nil { - base.Statistics = (*LinkStatistics)(stats32.to64()) - } - - // Links that don't have IFLA_INFO_KIND are hardware devices - if link == nil { - link = &Device{} - } - *link.Attrs() = base - link.Attrs().Slave = linkSlave - - // If the tuntap attributes are not updated by netlink due to - // an older driver, use sysfs - if link != nil && linkType == "tun" { - tuntap := link.(*Tuntap) - - if tuntap.Mode == 0 { - ifname := tuntap.Attrs().Name - if flags, err := readSysPropAsInt64(ifname, "tun_flags"); err == nil { - - if flags&unix.IFF_TUN != 0 { - tuntap.Mode = unix.IFF_TUN - } else if flags&unix.IFF_TAP != 0 { - tuntap.Mode = unix.IFF_TAP - } - - tuntap.NonPersist = false - if flags&unix.IFF_PERSIST == 0 { - tuntap.NonPersist = true - } - } - - // The sysfs interface for owner/group returns -1 for root user, instead of returning 0. - // So explicitly check for negative value, before assigning the owner uid/gid. - if owner, err := readSysPropAsInt64(ifname, "owner"); err == nil && owner > 0 { - tuntap.Owner = uint32(owner) - } - - if group, err := readSysPropAsInt64(ifname, "group"); err == nil && group > 0 { - tuntap.Group = uint32(group) - } - } - } - - return link, nil -} - -func readSysPropAsInt64(ifname, prop string) (int64, error) { - fname := fmt.Sprintf("/sys/class/net/%s/%s", ifname, prop) - contents, err := ioutil.ReadFile(fname) - if err != nil { - return 0, err - } - - num, err := strconv.ParseInt(strings.TrimSpace(string(contents)), 0, 64) - if err == nil { - return num, nil - } - - return 0, err -} - -// LinkList gets a list of link devices. -// Equivalent to: `ip link show` -func LinkList() ([]Link, error) { - return pkgHandle.LinkList() -} - -// LinkList gets a list of link devices. -// Equivalent to: `ip link show` -func (h *Handle) LinkList() ([]Link, error) { - // NOTE(vish): This duplicates functionality in net/iface_linux.go, but we need - // to get the message ourselves to parse link type. - req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP) - - msg := nl.NewIfInfomsg(unix.AF_UNSPEC) - req.AddData(msg) - attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF)) - req.AddData(attr) - - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK) - if err != nil { - return nil, err - } - - var res []Link - for _, m := range msgs { - link, err := LinkDeserialize(nil, m) - if err != nil { - return nil, err - } - res = append(res, link) - } - - return res, nil -} - -// LinkUpdate is used to pass information back from LinkSubscribe() -type LinkUpdate struct { - nl.IfInfomsg - Header unix.NlMsghdr - Link -} - -// LinkSubscribe takes a chan down which notifications will be sent -// when links change. Close the 'done' chan to stop subscription. -func LinkSubscribe(ch chan<- LinkUpdate, done <-chan struct{}) error { - return linkSubscribeAt(netns.None(), netns.None(), ch, done, nil, false) -} - -// LinkSubscribeAt works like LinkSubscribe plus it allows the caller -// to choose the network namespace in which to subscribe (ns). -func LinkSubscribeAt(ns netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}) error { - return linkSubscribeAt(ns, netns.None(), ch, done, nil, false) -} - -// LinkSubscribeOptions contains a set of options to use with -// LinkSubscribeWithOptions. -type LinkSubscribeOptions struct { - Namespace *netns.NsHandle - ErrorCallback func(error) - ListExisting bool -} - -// LinkSubscribeWithOptions work like LinkSubscribe but enable to -// provide additional options to modify the behavior. Currently, the -// namespace can be provided as well as an error callback. -func LinkSubscribeWithOptions(ch chan<- LinkUpdate, done <-chan struct{}, options LinkSubscribeOptions) error { - if options.Namespace == nil { - none := netns.None() - options.Namespace = &none - } - return linkSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting) -} - -func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error { - s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_LINK) - if err != nil { - return err - } - if done != nil { - go func() { - <-done - s.Close() - }() - } - if listExisting { - req := pkgHandle.newNetlinkRequest(unix.RTM_GETLINK, - unix.NLM_F_DUMP) - msg := nl.NewIfInfomsg(unix.AF_UNSPEC) - req.AddData(msg) - if err := s.Send(req); err != nil { - return err - } - } - go func() { - defer close(ch) - for { - msgs, from, err := s.Receive() - if err != nil { - if cberr != nil { - cberr(err) - } - return - } - if from.Pid != nl.PidKernel { - if cberr != nil { - cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)) - } - continue - } - for _, m := range msgs { - if m.Header.Type == unix.NLMSG_DONE { - continue - } - if m.Header.Type == unix.NLMSG_ERROR { - native := nl.NativeEndian() - error := int32(native.Uint32(m.Data[0:4])) - if error == 0 { - continue - } - if cberr != nil { - cberr(syscall.Errno(-error)) - } - return - } - ifmsg := nl.DeserializeIfInfomsg(m.Data) - header := unix.NlMsghdr(m.Header) - link, err := LinkDeserialize(&header, m.Data) - if err != nil { - if cberr != nil { - cberr(err) - } - return - } - ch <- LinkUpdate{IfInfomsg: *ifmsg, Header: header, Link: link} - } - } - }() - - return nil -} - -func LinkSetHairpin(link Link, mode bool) error { - return pkgHandle.LinkSetHairpin(link, mode) -} - -func (h *Handle) LinkSetHairpin(link Link, mode bool) error { - return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_MODE) -} - -func LinkSetGuard(link Link, mode bool) error { - return pkgHandle.LinkSetGuard(link, mode) -} - -func (h *Handle) LinkSetGuard(link Link, mode bool) error { - return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_GUARD) -} - -func LinkSetFastLeave(link Link, mode bool) error { - return pkgHandle.LinkSetFastLeave(link, mode) -} - -func (h *Handle) LinkSetFastLeave(link Link, mode bool) error { - return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_FAST_LEAVE) -} - -func LinkSetLearning(link Link, mode bool) error { - return pkgHandle.LinkSetLearning(link, mode) -} - -func (h *Handle) LinkSetLearning(link Link, mode bool) error { - return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_LEARNING) -} - -func LinkSetRootBlock(link Link, mode bool) error { - return pkgHandle.LinkSetRootBlock(link, mode) -} - -func (h *Handle) LinkSetRootBlock(link Link, mode bool) error { - return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROTECT) -} - -func LinkSetFlood(link Link, mode bool) error { - return pkgHandle.LinkSetFlood(link, mode) -} - -func (h *Handle) LinkSetFlood(link Link, mode bool) error { - return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_UNICAST_FLOOD) -} - -func LinkSetBrProxyArp(link Link, mode bool) error { - return pkgHandle.LinkSetBrProxyArp(link, mode) -} - -func (h *Handle) LinkSetBrProxyArp(link Link, mode bool) error { - return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROXYARP) -} - -func LinkSetBrProxyArpWiFi(link Link, mode bool) error { - return pkgHandle.LinkSetBrProxyArpWiFi(link, mode) -} - -func (h *Handle) LinkSetBrProxyArpWiFi(link Link, mode bool) error { - return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROXYARP_WIFI) -} - -func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error { - base := link.Attrs() - h.ensureIndex(base) - req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) - - msg := nl.NewIfInfomsg(unix.AF_BRIDGE) - msg.Index = int32(base.Index) - req.AddData(msg) - - br := nl.NewRtAttr(unix.IFLA_PROTINFO|unix.NLA_F_NESTED, nil) - br.AddRtAttr(attr, boolToByte(mode)) - req.AddData(br) - _, err := req.Execute(unix.NETLINK_ROUTE, 0) - if err != nil { - return err - } - return nil -} - -// LinkSetTxQLen sets the transaction queue length for the link. -// Equivalent to: `ip link set $link txqlen $qlen` -func LinkSetTxQLen(link Link, qlen int) error { - return pkgHandle.LinkSetTxQLen(link, qlen) -} - -// LinkSetTxQLen sets the transaction queue length for the link. -// Equivalent to: `ip link set $link txqlen $qlen` -func (h *Handle) LinkSetTxQLen(link Link, qlen int) error { - base := link.Attrs() - h.ensureIndex(base) - req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) - - msg := nl.NewIfInfomsg(unix.AF_UNSPEC) - msg.Index = int32(base.Index) - req.AddData(msg) - - b := make([]byte, 4) - native.PutUint32(b, uint32(qlen)) - - data := nl.NewRtAttr(unix.IFLA_TXQLEN, b) - req.AddData(data) - - _, err := req.Execute(unix.NETLINK_ROUTE, 0) - return err -} - -// LinkSetGroup sets the link group id which can be used to perform mass actions -// with iproute2 as well use it as a reference in nft filters. -// Equivalent to: `ip link set $link group $id` -func LinkSetGroup(link Link, group int) error { - return pkgHandle.LinkSetGroup(link, group) -} - -// LinkSetGroup sets the link group id which can be used to perform mass actions -// with iproute2 as well use it as a reference in nft filters. -// Equivalent to: `ip link set $link group $id` -func (h *Handle) LinkSetGroup(link Link, group int) error { - base := link.Attrs() - h.ensureIndex(base) - req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) - - msg := nl.NewIfInfomsg(unix.AF_UNSPEC) - msg.Index = int32(base.Index) - req.AddData(msg) - - b := make([]byte, 4) - native.PutUint32(b, uint32(group)) - - data := nl.NewRtAttr(unix.IFLA_GROUP, b) - req.AddData(data) - - _, err := req.Execute(unix.NETLINK_ROUTE, 0) - return err -} - -func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) { - vlan := link.(*Vlan) - for _, datum := range data { - switch datum.Attr.Type { - case nl.IFLA_VLAN_ID: - vlan.VlanId = int(native.Uint16(datum.Value[0:2])) - case nl.IFLA_VLAN_PROTOCOL: - vlan.VlanProtocol = VlanProtocol(int(ntohs(datum.Value[0:2]))) - } - } -} - -func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) { - vxlan := link.(*Vxlan) - for _, datum := range data { - switch datum.Attr.Type { - case nl.IFLA_VXLAN_ID: - vxlan.VxlanId = int(native.Uint32(datum.Value[0:4])) - case nl.IFLA_VXLAN_LINK: - vxlan.VtepDevIndex = int(native.Uint32(datum.Value[0:4])) - case nl.IFLA_VXLAN_LOCAL: - vxlan.SrcAddr = net.IP(datum.Value[0:4]) - case nl.IFLA_VXLAN_LOCAL6: - vxlan.SrcAddr = net.IP(datum.Value[0:16]) - case nl.IFLA_VXLAN_GROUP: - vxlan.Group = net.IP(datum.Value[0:4]) - case nl.IFLA_VXLAN_GROUP6: - vxlan.Group = net.IP(datum.Value[0:16]) - case nl.IFLA_VXLAN_TTL: - vxlan.TTL = int(datum.Value[0]) - case nl.IFLA_VXLAN_TOS: - vxlan.TOS = int(datum.Value[0]) - case nl.IFLA_VXLAN_LEARNING: - vxlan.Learning = int8(datum.Value[0]) != 0 - case nl.IFLA_VXLAN_PROXY: - vxlan.Proxy = int8(datum.Value[0]) != 0 - case nl.IFLA_VXLAN_RSC: - vxlan.RSC = int8(datum.Value[0]) != 0 - case nl.IFLA_VXLAN_L2MISS: - vxlan.L2miss = int8(datum.Value[0]) != 0 - case nl.IFLA_VXLAN_L3MISS: - vxlan.L3miss = int8(datum.Value[0]) != 0 - case nl.IFLA_VXLAN_UDP_CSUM: - vxlan.UDPCSum = int8(datum.Value[0]) != 0 - case nl.IFLA_VXLAN_UDP_ZERO_CSUM6_TX: - vxlan.UDP6ZeroCSumTx = int8(datum.Value[0]) != 0 - case nl.IFLA_VXLAN_UDP_ZERO_CSUM6_RX: - vxlan.UDP6ZeroCSumRx = int8(datum.Value[0]) != 0 - case nl.IFLA_VXLAN_GBP: - vxlan.GBP = true - case nl.IFLA_VXLAN_FLOWBASED: - vxlan.FlowBased = int8(datum.Value[0]) != 0 - case nl.IFLA_VXLAN_AGEING: - vxlan.Age = int(native.Uint32(datum.Value[0:4])) - vxlan.NoAge = vxlan.Age == 0 - case nl.IFLA_VXLAN_LIMIT: - vxlan.Limit = int(native.Uint32(datum.Value[0:4])) - case nl.IFLA_VXLAN_PORT: - vxlan.Port = int(ntohs(datum.Value[0:2])) - case nl.IFLA_VXLAN_PORT_RANGE: - buf := bytes.NewBuffer(datum.Value[0:4]) - var pr vxlanPortRange - if binary.Read(buf, binary.BigEndian, &pr) != nil { - vxlan.PortLow = int(pr.Lo) - vxlan.PortHigh = int(pr.Hi) - } - } - } -} - -func parseBondData(link Link, data []syscall.NetlinkRouteAttr) { - bond := link.(*Bond) - for i := range data { - switch data[i].Attr.Type { - case nl.IFLA_BOND_MODE: - bond.Mode = BondMode(data[i].Value[0]) - case nl.IFLA_BOND_ACTIVE_SLAVE: - bond.ActiveSlave = int(native.Uint32(data[i].Value[0:4])) - case nl.IFLA_BOND_MIIMON: - bond.Miimon = int(native.Uint32(data[i].Value[0:4])) - case nl.IFLA_BOND_UPDELAY: - bond.UpDelay = int(native.Uint32(data[i].Value[0:4])) - case nl.IFLA_BOND_DOWNDELAY: - bond.DownDelay = int(native.Uint32(data[i].Value[0:4])) - case nl.IFLA_BOND_USE_CARRIER: - bond.UseCarrier = int(data[i].Value[0]) - case nl.IFLA_BOND_ARP_INTERVAL: - bond.ArpInterval = int(native.Uint32(data[i].Value[0:4])) - case nl.IFLA_BOND_ARP_IP_TARGET: - bond.ArpIpTargets = parseBondArpIpTargets(data[i].Value) - case nl.IFLA_BOND_ARP_VALIDATE: - bond.ArpValidate = BondArpValidate(native.Uint32(data[i].Value[0:4])) - case nl.IFLA_BOND_ARP_ALL_TARGETS: - bond.ArpAllTargets = BondArpAllTargets(native.Uint32(data[i].Value[0:4])) - case nl.IFLA_BOND_PRIMARY: - bond.Primary = int(native.Uint32(data[i].Value[0:4])) - case nl.IFLA_BOND_PRIMARY_RESELECT: - bond.PrimaryReselect = BondPrimaryReselect(data[i].Value[0]) - case nl.IFLA_BOND_FAIL_OVER_MAC: - bond.FailOverMac = BondFailOverMac(data[i].Value[0]) - case nl.IFLA_BOND_XMIT_HASH_POLICY: - bond.XmitHashPolicy = BondXmitHashPolicy(data[i].Value[0]) - case nl.IFLA_BOND_RESEND_IGMP: - bond.ResendIgmp = int(native.Uint32(data[i].Value[0:4])) - case nl.IFLA_BOND_NUM_PEER_NOTIF: - bond.NumPeerNotif = int(data[i].Value[0]) - case nl.IFLA_BOND_ALL_SLAVES_ACTIVE: - bond.AllSlavesActive = int(data[i].Value[0]) - case nl.IFLA_BOND_MIN_LINKS: - bond.MinLinks = int(native.Uint32(data[i].Value[0:4])) - case nl.IFLA_BOND_LP_INTERVAL: - bond.LpInterval = int(native.Uint32(data[i].Value[0:4])) - case nl.IFLA_BOND_PACKETS_PER_SLAVE: - bond.PackersPerSlave = int(native.Uint32(data[i].Value[0:4])) - case nl.IFLA_BOND_AD_LACP_RATE: - bond.LacpRate = BondLacpRate(data[i].Value[0]) - case nl.IFLA_BOND_AD_SELECT: - bond.AdSelect = BondAdSelect(data[i].Value[0]) - case nl.IFLA_BOND_AD_INFO: - // TODO: implement - case nl.IFLA_BOND_AD_ACTOR_SYS_PRIO: - bond.AdActorSysPrio = int(native.Uint16(data[i].Value[0:2])) - case nl.IFLA_BOND_AD_USER_PORT_KEY: - bond.AdUserPortKey = int(native.Uint16(data[i].Value[0:2])) - case nl.IFLA_BOND_AD_ACTOR_SYSTEM: - bond.AdActorSystem = net.HardwareAddr(data[i].Value[0:6]) - case nl.IFLA_BOND_TLB_DYNAMIC_LB: - bond.TlbDynamicLb = int(data[i].Value[0]) - } - } -} - -func parseBondArpIpTargets(value []byte) []net.IP { - data, err := nl.ParseRouteAttr(value) - if err != nil { - return nil - } - - targets := []net.IP{} - for i := range data { - target := net.IP(data[i].Value) - if ip := target.To4(); ip != nil { - targets = append(targets, ip) - continue - } - if ip := target.To16(); ip != nil { - targets = append(targets, ip) - } - } - - return targets -} - -func addBondSlaveAttrs(bondSlave *BondSlave, linkInfo *nl.RtAttr) { - data := linkInfo.AddRtAttr(nl.IFLA_INFO_SLAVE_DATA, nil) - - data.AddRtAttr(nl.IFLA_BOND_SLAVE_STATE, nl.Uint8Attr(uint8(bondSlave.State))) - data.AddRtAttr(nl.IFLA_BOND_SLAVE_MII_STATUS, nl.Uint8Attr(uint8(bondSlave.MiiStatus))) - data.AddRtAttr(nl.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT, nl.Uint32Attr(bondSlave.LinkFailureCount)) - data.AddRtAttr(nl.IFLA_BOND_SLAVE_QUEUE_ID, nl.Uint16Attr(bondSlave.QueueId)) - data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, nl.Uint16Attr(bondSlave.AggregatorId)) - data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE, nl.Uint8Attr(bondSlave.AdActorOperPortState)) - data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE, nl.Uint16Attr(bondSlave.AdPartnerOperPortState)) - - if mac := bondSlave.PermHardwareAddr; mac != nil { - data.AddRtAttr(nl.IFLA_BOND_SLAVE_PERM_HWADDR, []byte(mac)) - } -} - -func parseBondSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) { - bondSlave := slave.(*BondSlave) - for i := range data { - switch data[i].Attr.Type { - case nl.IFLA_BOND_SLAVE_STATE: - bondSlave.State = BondSlaveState(data[i].Value[0]) - case nl.IFLA_BOND_SLAVE_MII_STATUS: - bondSlave.MiiStatus = BondSlaveMiiStatus(data[i].Value[0]) - case nl.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT: - bondSlave.LinkFailureCount = native.Uint32(data[i].Value[0:4]) - case nl.IFLA_BOND_SLAVE_PERM_HWADDR: - bondSlave.PermHardwareAddr = net.HardwareAddr(data[i].Value[0:6]) - case nl.IFLA_BOND_SLAVE_QUEUE_ID: - bondSlave.QueueId = native.Uint16(data[i].Value[0:2]) - case nl.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID: - bondSlave.AggregatorId = native.Uint16(data[i].Value[0:2]) - case nl.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE: - bondSlave.AdActorOperPortState = uint8(data[i].Value[0]) - case nl.IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE: - bondSlave.AdPartnerOperPortState = native.Uint16(data[i].Value[0:2]) - } - } -} - -func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) { - ipv := link.(*IPVlan) - for _, datum := range data { - switch datum.Attr.Type { - case nl.IFLA_IPVLAN_MODE: - ipv.Mode = IPVlanMode(native.Uint32(datum.Value[0:4])) - case nl.IFLA_IPVLAN_FLAG: - ipv.Flag = IPVlanFlag(native.Uint32(datum.Value[0:4])) - } - } -} - -func parseMacvtapData(link Link, data []syscall.NetlinkRouteAttr) { - macv := link.(*Macvtap) - parseMacvlanData(&macv.Macvlan, data) -} - -func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) { - macv := link.(*Macvlan) - for _, datum := range data { - switch datum.Attr.Type { - case nl.IFLA_MACVLAN_MODE: - switch native.Uint32(datum.Value[0:4]) { - case nl.MACVLAN_MODE_PRIVATE: - macv.Mode = MACVLAN_MODE_PRIVATE - case nl.MACVLAN_MODE_VEPA: - macv.Mode = MACVLAN_MODE_VEPA - case nl.MACVLAN_MODE_BRIDGE: - macv.Mode = MACVLAN_MODE_BRIDGE - case nl.MACVLAN_MODE_PASSTHRU: - macv.Mode = MACVLAN_MODE_PASSTHRU - case nl.MACVLAN_MODE_SOURCE: - macv.Mode = MACVLAN_MODE_SOURCE - } - case nl.IFLA_MACVLAN_MACADDR_COUNT: - macv.MACAddrs = make([]net.HardwareAddr, 0, int(native.Uint32(datum.Value[0:4]))) - case nl.IFLA_MACVLAN_MACADDR_DATA: - macs, err := nl.ParseRouteAttr(datum.Value[:]) - if err != nil { - panic(fmt.Sprintf("failed to ParseRouteAttr for IFLA_MACVLAN_MACADDR_DATA: %v", err)) - } - for _, macDatum := range macs { - macv.MACAddrs = append(macv.MACAddrs, net.HardwareAddr(macDatum.Value[0:6])) - } - } - } -} - -// copied from pkg/net_linux.go -func linkFlags(rawFlags uint32) net.Flags { - var f net.Flags - if rawFlags&unix.IFF_UP != 0 { - f |= net.FlagUp - } - if rawFlags&unix.IFF_BROADCAST != 0 { - f |= net.FlagBroadcast - } - if rawFlags&unix.IFF_LOOPBACK != 0 { - f |= net.FlagLoopback - } - if rawFlags&unix.IFF_POINTOPOINT != 0 { - f |= net.FlagPointToPoint - } - if rawFlags&unix.IFF_MULTICAST != 0 { - f |= net.FlagMulticast - } - return f -} - -func addGretapAttrs(gretap *Gretap, linkInfo *nl.RtAttr) { - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - - if gretap.FlowBased { - // In flow based mode, no other attributes need to be configured - data.AddRtAttr(nl.IFLA_GRE_COLLECT_METADATA, boolAttr(gretap.FlowBased)) - return - } - - if ip := gretap.Local; ip != nil { - if ip.To4() != nil { - ip = ip.To4() - } - data.AddRtAttr(nl.IFLA_GRE_LOCAL, []byte(ip)) - } - - if ip := gretap.Remote; ip != nil { - if ip.To4() != nil { - ip = ip.To4() - } - data.AddRtAttr(nl.IFLA_GRE_REMOTE, []byte(ip)) - } - - if gretap.IKey != 0 { - data.AddRtAttr(nl.IFLA_GRE_IKEY, htonl(gretap.IKey)) - gretap.IFlags |= uint16(nl.GRE_KEY) - } - - if gretap.OKey != 0 { - data.AddRtAttr(nl.IFLA_GRE_OKEY, htonl(gretap.OKey)) - gretap.OFlags |= uint16(nl.GRE_KEY) - } - - data.AddRtAttr(nl.IFLA_GRE_IFLAGS, htons(gretap.IFlags)) - data.AddRtAttr(nl.IFLA_GRE_OFLAGS, htons(gretap.OFlags)) - - if gretap.Link != 0 { - data.AddRtAttr(nl.IFLA_GRE_LINK, nl.Uint32Attr(gretap.Link)) - } - - data.AddRtAttr(nl.IFLA_GRE_PMTUDISC, nl.Uint8Attr(gretap.PMtuDisc)) - data.AddRtAttr(nl.IFLA_GRE_TTL, nl.Uint8Attr(gretap.Ttl)) - data.AddRtAttr(nl.IFLA_GRE_TOS, nl.Uint8Attr(gretap.Tos)) - data.AddRtAttr(nl.IFLA_GRE_ENCAP_TYPE, nl.Uint16Attr(gretap.EncapType)) - data.AddRtAttr(nl.IFLA_GRE_ENCAP_FLAGS, nl.Uint16Attr(gretap.EncapFlags)) - data.AddRtAttr(nl.IFLA_GRE_ENCAP_SPORT, htons(gretap.EncapSport)) - data.AddRtAttr(nl.IFLA_GRE_ENCAP_DPORT, htons(gretap.EncapDport)) -} - -func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) { - gre := link.(*Gretap) - for _, datum := range data { - switch datum.Attr.Type { - case nl.IFLA_GRE_OKEY: - gre.IKey = ntohl(datum.Value[0:4]) - case nl.IFLA_GRE_IKEY: - gre.OKey = ntohl(datum.Value[0:4]) - case nl.IFLA_GRE_LOCAL: - gre.Local = net.IP(datum.Value) - case nl.IFLA_GRE_REMOTE: - gre.Remote = net.IP(datum.Value) - case nl.IFLA_GRE_ENCAP_SPORT: - gre.EncapSport = ntohs(datum.Value[0:2]) - case nl.IFLA_GRE_ENCAP_DPORT: - gre.EncapDport = ntohs(datum.Value[0:2]) - case nl.IFLA_GRE_IFLAGS: - gre.IFlags = ntohs(datum.Value[0:2]) - case nl.IFLA_GRE_OFLAGS: - gre.OFlags = ntohs(datum.Value[0:2]) - case nl.IFLA_GRE_TTL: - gre.Ttl = uint8(datum.Value[0]) - case nl.IFLA_GRE_TOS: - gre.Tos = uint8(datum.Value[0]) - case nl.IFLA_GRE_PMTUDISC: - gre.PMtuDisc = uint8(datum.Value[0]) - case nl.IFLA_GRE_ENCAP_TYPE: - gre.EncapType = native.Uint16(datum.Value[0:2]) - case nl.IFLA_GRE_ENCAP_FLAGS: - gre.EncapFlags = native.Uint16(datum.Value[0:2]) - case nl.IFLA_GRE_COLLECT_METADATA: - gre.FlowBased = true - } - } -} - -func addGretunAttrs(gre *Gretun, linkInfo *nl.RtAttr) { - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - - if ip := gre.Local; ip != nil { - if ip.To4() != nil { - ip = ip.To4() - } - data.AddRtAttr(nl.IFLA_GRE_LOCAL, []byte(ip)) - } - - if ip := gre.Remote; ip != nil { - if ip.To4() != nil { - ip = ip.To4() - } - data.AddRtAttr(nl.IFLA_GRE_REMOTE, []byte(ip)) - } - - if gre.IKey != 0 { - data.AddRtAttr(nl.IFLA_GRE_IKEY, htonl(gre.IKey)) - gre.IFlags |= uint16(nl.GRE_KEY) - } - - if gre.OKey != 0 { - data.AddRtAttr(nl.IFLA_GRE_OKEY, htonl(gre.OKey)) - gre.OFlags |= uint16(nl.GRE_KEY) - } - - data.AddRtAttr(nl.IFLA_GRE_IFLAGS, htons(gre.IFlags)) - data.AddRtAttr(nl.IFLA_GRE_OFLAGS, htons(gre.OFlags)) - - if gre.Link != 0 { - data.AddRtAttr(nl.IFLA_GRE_LINK, nl.Uint32Attr(gre.Link)) - } - - data.AddRtAttr(nl.IFLA_GRE_PMTUDISC, nl.Uint8Attr(gre.PMtuDisc)) - data.AddRtAttr(nl.IFLA_GRE_TTL, nl.Uint8Attr(gre.Ttl)) - data.AddRtAttr(nl.IFLA_GRE_TOS, nl.Uint8Attr(gre.Tos)) - data.AddRtAttr(nl.IFLA_GRE_ENCAP_TYPE, nl.Uint16Attr(gre.EncapType)) - data.AddRtAttr(nl.IFLA_GRE_ENCAP_FLAGS, nl.Uint16Attr(gre.EncapFlags)) - data.AddRtAttr(nl.IFLA_GRE_ENCAP_SPORT, htons(gre.EncapSport)) - data.AddRtAttr(nl.IFLA_GRE_ENCAP_DPORT, htons(gre.EncapDport)) -} - -func parseGretunData(link Link, data []syscall.NetlinkRouteAttr) { - gre := link.(*Gretun) - for _, datum := range data { - switch datum.Attr.Type { - case nl.IFLA_GRE_IKEY: - gre.IKey = ntohl(datum.Value[0:4]) - case nl.IFLA_GRE_OKEY: - gre.OKey = ntohl(datum.Value[0:4]) - case nl.IFLA_GRE_LOCAL: - gre.Local = net.IP(datum.Value) - case nl.IFLA_GRE_REMOTE: - gre.Remote = net.IP(datum.Value) - case nl.IFLA_GRE_IFLAGS: - gre.IFlags = ntohs(datum.Value[0:2]) - case nl.IFLA_GRE_OFLAGS: - gre.OFlags = ntohs(datum.Value[0:2]) - case nl.IFLA_GRE_TTL: - gre.Ttl = uint8(datum.Value[0]) - case nl.IFLA_GRE_TOS: - gre.Tos = uint8(datum.Value[0]) - case nl.IFLA_GRE_PMTUDISC: - gre.PMtuDisc = uint8(datum.Value[0]) - case nl.IFLA_GRE_ENCAP_TYPE: - gre.EncapType = native.Uint16(datum.Value[0:2]) - case nl.IFLA_GRE_ENCAP_FLAGS: - gre.EncapFlags = native.Uint16(datum.Value[0:2]) - case nl.IFLA_GRE_ENCAP_SPORT: - gre.EncapSport = ntohs(datum.Value[0:2]) - case nl.IFLA_GRE_ENCAP_DPORT: - gre.EncapDport = ntohs(datum.Value[0:2]) - } - } -} - -func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) { - attrs := nl.NewRtAttr(unix.IFLA_XDP|unix.NLA_F_NESTED, nil) - b := make([]byte, 4) - native.PutUint32(b, uint32(xdp.Fd)) - attrs.AddRtAttr(nl.IFLA_XDP_FD, b) - if xdp.Flags != 0 { - b := make([]byte, 4) - native.PutUint32(b, xdp.Flags) - attrs.AddRtAttr(nl.IFLA_XDP_FLAGS, b) - } - req.AddData(attrs) -} - -func parseLinkXdp(data []byte) (*LinkXdp, error) { - attrs, err := nl.ParseRouteAttr(data) - if err != nil { - return nil, err - } - xdp := &LinkXdp{} - for _, attr := range attrs { - switch attr.Attr.Type { - case nl.IFLA_XDP_FD: - xdp.Fd = int(native.Uint32(attr.Value[0:4])) - case nl.IFLA_XDP_ATTACHED: - xdp.Attached = attr.Value[0] != 0 - case nl.IFLA_XDP_FLAGS: - xdp.Flags = native.Uint32(attr.Value[0:4]) - case nl.IFLA_XDP_PROG_ID: - xdp.ProgId = native.Uint32(attr.Value[0:4]) - } - } - return xdp, nil -} - -func addIptunAttrs(iptun *Iptun, linkInfo *nl.RtAttr) { - if iptun.FlowBased { - // In flow based mode, no other attributes need to be configured - linkInfo.AddRtAttr(nl.IFLA_IPTUN_COLLECT_METADATA, boolAttr(iptun.FlowBased)) - return - } - - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - - ip := iptun.Local.To4() - if ip != nil { - data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip)) - } - - ip = iptun.Remote.To4() - if ip != nil { - data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip)) - } - - if iptun.Link != 0 { - data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(iptun.Link)) - } - data.AddRtAttr(nl.IFLA_IPTUN_PMTUDISC, nl.Uint8Attr(iptun.PMtuDisc)) - data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(iptun.Ttl)) - data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(iptun.Tos)) - data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(iptun.EncapType)) - data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(iptun.EncapFlags)) - data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(iptun.EncapSport)) - data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_DPORT, htons(iptun.EncapDport)) -} - -func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) { - iptun := link.(*Iptun) - for _, datum := range data { - switch datum.Attr.Type { - case nl.IFLA_IPTUN_LOCAL: - iptun.Local = net.IP(datum.Value[0:4]) - case nl.IFLA_IPTUN_REMOTE: - iptun.Remote = net.IP(datum.Value[0:4]) - case nl.IFLA_IPTUN_TTL: - iptun.Ttl = uint8(datum.Value[0]) - case nl.IFLA_IPTUN_TOS: - iptun.Tos = uint8(datum.Value[0]) - case nl.IFLA_IPTUN_PMTUDISC: - iptun.PMtuDisc = uint8(datum.Value[0]) - case nl.IFLA_IPTUN_ENCAP_SPORT: - iptun.EncapSport = ntohs(datum.Value[0:2]) - case nl.IFLA_IPTUN_ENCAP_DPORT: - iptun.EncapDport = ntohs(datum.Value[0:2]) - case nl.IFLA_IPTUN_ENCAP_TYPE: - iptun.EncapType = native.Uint16(datum.Value[0:2]) - case nl.IFLA_IPTUN_ENCAP_FLAGS: - iptun.EncapFlags = native.Uint16(datum.Value[0:2]) - case nl.IFLA_IPTUN_COLLECT_METADATA: - iptun.FlowBased = int8(datum.Value[0]) != 0 - } - } -} - -func addIp6tnlAttrs(ip6tnl *Ip6tnl, linkInfo *nl.RtAttr) { - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - - if ip6tnl.Link != 0 { - data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(ip6tnl.Link)) - } - - ip := ip6tnl.Local.To16() - if ip != nil { - data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip)) - } - - ip = ip6tnl.Remote.To16() - if ip != nil { - data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip)) - } - - data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(ip6tnl.Ttl)) - data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(ip6tnl.Tos)) - data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_LIMIT, nl.Uint8Attr(ip6tnl.EncapLimit)) - data.AddRtAttr(nl.IFLA_IPTUN_FLAGS, nl.Uint32Attr(ip6tnl.Flags)) - data.AddRtAttr(nl.IFLA_IPTUN_PROTO, nl.Uint8Attr(ip6tnl.Proto)) - data.AddRtAttr(nl.IFLA_IPTUN_FLOWINFO, nl.Uint32Attr(ip6tnl.FlowInfo)) -} - -func parseIp6tnlData(link Link, data []syscall.NetlinkRouteAttr) { - ip6tnl := link.(*Ip6tnl) - for _, datum := range data { - switch datum.Attr.Type { - case nl.IFLA_IPTUN_LOCAL: - ip6tnl.Local = net.IP(datum.Value[:16]) - case nl.IFLA_IPTUN_REMOTE: - ip6tnl.Remote = net.IP(datum.Value[:16]) - case nl.IFLA_IPTUN_TTL: - ip6tnl.Ttl = uint8(datum.Value[0]) - case nl.IFLA_IPTUN_TOS: - ip6tnl.Tos = uint8(datum.Value[0]) - case nl.IFLA_IPTUN_ENCAP_LIMIT: - ip6tnl.EncapLimit = uint8(datum.Value[0]) - case nl.IFLA_IPTUN_FLAGS: - ip6tnl.Flags = native.Uint32(datum.Value[:4]) - case nl.IFLA_IPTUN_PROTO: - ip6tnl.Proto = uint8(datum.Value[0]) - case nl.IFLA_IPTUN_FLOWINFO: - ip6tnl.FlowInfo = native.Uint32(datum.Value[:4]) - } - } -} - -func addSittunAttrs(sittun *Sittun, linkInfo *nl.RtAttr) { - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - - if sittun.Link != 0 { - data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(sittun.Link)) - } - - ip := sittun.Local.To4() - if ip != nil { - data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip)) - } - - ip = sittun.Remote.To4() - if ip != nil { - data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip)) - } - - if sittun.Ttl > 0 { - // Would otherwise fail on 3.10 kernel - data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(sittun.Ttl)) - } - - data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(sittun.Tos)) - data.AddRtAttr(nl.IFLA_IPTUN_PMTUDISC, nl.Uint8Attr(sittun.PMtuDisc)) - data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(sittun.EncapType)) - data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(sittun.EncapFlags)) - data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(sittun.EncapSport)) - data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_DPORT, htons(sittun.EncapDport)) -} - -func parseSittunData(link Link, data []syscall.NetlinkRouteAttr) { - sittun := link.(*Sittun) - for _, datum := range data { - switch datum.Attr.Type { - case nl.IFLA_IPTUN_LOCAL: - sittun.Local = net.IP(datum.Value[0:4]) - case nl.IFLA_IPTUN_REMOTE: - sittun.Remote = net.IP(datum.Value[0:4]) - case nl.IFLA_IPTUN_TTL: - sittun.Ttl = uint8(datum.Value[0]) - case nl.IFLA_IPTUN_TOS: - sittun.Tos = uint8(datum.Value[0]) - case nl.IFLA_IPTUN_PMTUDISC: - sittun.PMtuDisc = uint8(datum.Value[0]) - case nl.IFLA_IPTUN_ENCAP_TYPE: - sittun.EncapType = native.Uint16(datum.Value[0:2]) - case nl.IFLA_IPTUN_ENCAP_FLAGS: - sittun.EncapFlags = native.Uint16(datum.Value[0:2]) - case nl.IFLA_IPTUN_ENCAP_SPORT: - sittun.EncapSport = ntohs(datum.Value[0:2]) - case nl.IFLA_IPTUN_ENCAP_DPORT: - sittun.EncapDport = ntohs(datum.Value[0:2]) - } - } -} - -func addVtiAttrs(vti *Vti, linkInfo *nl.RtAttr) { - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - - family := FAMILY_V4 - if vti.Local.To4() == nil { - family = FAMILY_V6 - } - - var ip net.IP - - if family == FAMILY_V4 { - ip = vti.Local.To4() - } else { - ip = vti.Local - } - if ip != nil { - data.AddRtAttr(nl.IFLA_VTI_LOCAL, []byte(ip)) - } - - if family == FAMILY_V4 { - ip = vti.Remote.To4() - } else { - ip = vti.Remote - } - if ip != nil { - data.AddRtAttr(nl.IFLA_VTI_REMOTE, []byte(ip)) - } - - if vti.Link != 0 { - data.AddRtAttr(nl.IFLA_VTI_LINK, nl.Uint32Attr(vti.Link)) - } - - data.AddRtAttr(nl.IFLA_VTI_IKEY, htonl(vti.IKey)) - data.AddRtAttr(nl.IFLA_VTI_OKEY, htonl(vti.OKey)) -} - -func parseVtiData(link Link, data []syscall.NetlinkRouteAttr) { - vti := link.(*Vti) - for _, datum := range data { - switch datum.Attr.Type { - case nl.IFLA_VTI_LOCAL: - vti.Local = net.IP(datum.Value) - case nl.IFLA_VTI_REMOTE: - vti.Remote = net.IP(datum.Value) - case nl.IFLA_VTI_IKEY: - vti.IKey = ntohl(datum.Value[0:4]) - case nl.IFLA_VTI_OKEY: - vti.OKey = ntohl(datum.Value[0:4]) - } - } -} - -func addVrfAttrs(vrf *Vrf, linkInfo *nl.RtAttr) { - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - b := make([]byte, 4) - native.PutUint32(b, uint32(vrf.Table)) - data.AddRtAttr(nl.IFLA_VRF_TABLE, b) -} - -func parseVrfData(link Link, data []syscall.NetlinkRouteAttr) { - vrf := link.(*Vrf) - for _, datum := range data { - switch datum.Attr.Type { - case nl.IFLA_VRF_TABLE: - vrf.Table = native.Uint32(datum.Value[0:4]) - } - } -} - -func addBridgeAttrs(bridge *Bridge, linkInfo *nl.RtAttr) { - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - if bridge.MulticastSnooping != nil { - data.AddRtAttr(nl.IFLA_BR_MCAST_SNOOPING, boolToByte(*bridge.MulticastSnooping)) - } - if bridge.HelloTime != nil { - data.AddRtAttr(nl.IFLA_BR_HELLO_TIME, nl.Uint32Attr(*bridge.HelloTime)) - } - if bridge.VlanFiltering != nil { - data.AddRtAttr(nl.IFLA_BR_VLAN_FILTERING, boolToByte(*bridge.VlanFiltering)) - } -} - -func parseBridgeData(bridge Link, data []syscall.NetlinkRouteAttr) { - br := bridge.(*Bridge) - for _, datum := range data { - switch datum.Attr.Type { - case nl.IFLA_BR_HELLO_TIME: - helloTime := native.Uint32(datum.Value[0:4]) - br.HelloTime = &helloTime - case nl.IFLA_BR_MCAST_SNOOPING: - mcastSnooping := datum.Value[0] == 1 - br.MulticastSnooping = &mcastSnooping - case nl.IFLA_BR_VLAN_FILTERING: - vlanFiltering := datum.Value[0] == 1 - br.VlanFiltering = &vlanFiltering - } - } -} - -func addGTPAttrs(gtp *GTP, linkInfo *nl.RtAttr) { - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - data.AddRtAttr(nl.IFLA_GTP_FD0, nl.Uint32Attr(uint32(gtp.FD0))) - data.AddRtAttr(nl.IFLA_GTP_FD1, nl.Uint32Attr(uint32(gtp.FD1))) - data.AddRtAttr(nl.IFLA_GTP_PDP_HASHSIZE, nl.Uint32Attr(131072)) - if gtp.Role != nl.GTP_ROLE_GGSN { - data.AddRtAttr(nl.IFLA_GTP_ROLE, nl.Uint32Attr(uint32(gtp.Role))) - } -} - -func parseGTPData(link Link, data []syscall.NetlinkRouteAttr) { - gtp := link.(*GTP) - for _, datum := range data { - switch datum.Attr.Type { - case nl.IFLA_GTP_FD0: - gtp.FD0 = int(native.Uint32(datum.Value)) - case nl.IFLA_GTP_FD1: - gtp.FD1 = int(native.Uint32(datum.Value)) - case nl.IFLA_GTP_PDP_HASHSIZE: - gtp.PDPHashsize = int(native.Uint32(datum.Value)) - case nl.IFLA_GTP_ROLE: - gtp.Role = int(native.Uint32(datum.Value)) - } - } -} - -func parseVfInfoList(data []syscall.NetlinkRouteAttr) ([]VfInfo, error) { - var vfs []VfInfo - - for i, element := range data { - if element.Attr.Type != nl.IFLA_VF_INFO { - return nil, fmt.Errorf("Incorrect element type in vf info list: %d", element.Attr.Type) - } - vfAttrs, err := nl.ParseRouteAttr(element.Value) - if err != nil { - return nil, err - } - vfs = append(vfs, parseVfInfo(vfAttrs, i)) - } - return vfs, nil -} - -func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) VfInfo { - vf := VfInfo{ID: id} - for _, element := range data { - switch element.Attr.Type { - case nl.IFLA_VF_MAC: - mac := nl.DeserializeVfMac(element.Value[:]) - vf.Mac = mac.Mac[:6] - case nl.IFLA_VF_VLAN: - vl := nl.DeserializeVfVlan(element.Value[:]) - vf.Vlan = int(vl.Vlan) - vf.Qos = int(vl.Qos) - case nl.IFLA_VF_TX_RATE: - txr := nl.DeserializeVfTxRate(element.Value[:]) - vf.TxRate = int(txr.Rate) - case nl.IFLA_VF_SPOOFCHK: - sp := nl.DeserializeVfSpoofchk(element.Value[:]) - vf.Spoofchk = sp.Setting != 0 - case nl.IFLA_VF_LINK_STATE: - ls := nl.DeserializeVfLinkState(element.Value[:]) - vf.LinkState = ls.LinkState - case nl.IFLA_VF_RATE: - vfr := nl.DeserializeVfRate(element.Value[:]) - vf.MaxTxRate = vfr.MaxTxRate - vf.MinTxRate = vfr.MinTxRate - } - } - return vf -} - -func addXfrmiAttrs(xfrmi *Xfrmi, linkInfo *nl.RtAttr) { - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - data.AddRtAttr(nl.IFLA_XFRM_LINK, nl.Uint32Attr(uint32(xfrmi.ParentIndex))) - data.AddRtAttr(nl.IFLA_XFRM_IF_ID, nl.Uint32Attr(xfrmi.Ifid)) - -} - -func parseXfrmiData(link Link, data []syscall.NetlinkRouteAttr) { - xfrmi := link.(*Xfrmi) - for _, datum := range data { - switch datum.Attr.Type { - case nl.IFLA_XFRM_LINK: - xfrmi.ParentIndex = int(native.Uint32(datum.Value)) - case nl.IFLA_XFRM_IF_ID: - xfrmi.Ifid = native.Uint32(datum.Value) - } - } -} - -// LinkSetBondSlave add slave to bond link via ioctl interface. -func LinkSetBondSlave(link Link, master *Bond) error { - fd, err := getSocketUDP() - if err != nil { - return err - } - defer syscall.Close(fd) - - ifreq := newIocltSlaveReq(link.Attrs().Name, master.Attrs().Name) - - _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), unix.SIOCBONDENSLAVE, uintptr(unsafe.Pointer(ifreq))) - if errno != 0 { - return fmt.Errorf("Failed to enslave %q to %q, errno=%v", link.Attrs().Name, master.Attrs().Name, errno) - } - return nil -} - -// LinkSetBondSlaveQueueId modify bond slave queue-id. -func (h *Handle) LinkSetBondSlaveQueueId(link Link, queueId uint16) error { - base := link.Attrs() - h.ensureIndex(base) - req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) - - msg := nl.NewIfInfomsg(unix.AF_UNSPEC) - msg.Index = int32(base.Index) - req.AddData(msg) - - linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil) - data := linkInfo.AddRtAttr(nl.IFLA_INFO_SLAVE_DATA, nil) - data.AddRtAttr(nl.IFLA_BOND_SLAVE_QUEUE_ID, nl.Uint16Attr(queueId)) - - req.AddData(linkInfo) - _, err := req.Execute(unix.NETLINK_ROUTE, 0) - return err -} - -// LinkSetBondSlaveQueueId modify bond slave queue-id. -func LinkSetBondSlaveQueueId(link Link, queueId uint16) error { - return pkgHandle.LinkSetBondSlaveQueueId(link, queueId) -} - -func vethStatsSerialize(stats ethtoolStats) ([]byte, error) { - statsSize := int(unsafe.Sizeof(stats)) + int(stats.nStats)*int(unsafe.Sizeof(uint64(0))) - b := make([]byte, 0, statsSize) - buf := bytes.NewBuffer(b) - err := binary.Write(buf, nl.NativeEndian(), stats) - return buf.Bytes()[:statsSize], err -} - -type vethEthtoolStats struct { - Cmd uint32 - NStats uint32 - Peer uint64 - // Newer kernels have XDP stats in here, but we only care - // to extract the peer ifindex here. -} - -func vethStatsDeserialize(b []byte) (vethEthtoolStats, error) { - var stats = vethEthtoolStats{} - err := binary.Read(bytes.NewReader(b), nl.NativeEndian(), &stats) - return stats, err -} - -// VethPeerIndex get veth peer index. -func VethPeerIndex(link *Veth) (int, error) { - fd, err := getSocketUDP() - if err != nil { - return -1, err - } - defer syscall.Close(fd) - - ifreq, sSet := newIocltStringSetReq(link.Name) - _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), SIOCETHTOOL, uintptr(unsafe.Pointer(ifreq))) - if errno != 0 { - return -1, fmt.Errorf("SIOCETHTOOL request for %q failed, errno=%v", link.Attrs().Name, errno) - } - - stats := ethtoolStats{ - cmd: ETHTOOL_GSTATS, - nStats: sSet.data[0], - } - - buffer, err := vethStatsSerialize(stats) - if err != nil { - return -1, err - } - - ifreq.Data = uintptr(unsafe.Pointer(&buffer[0])) - _, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), SIOCETHTOOL, uintptr(unsafe.Pointer(ifreq))) - if errno != 0 { - return -1, fmt.Errorf("SIOCETHTOOL request for %q failed, errno=%v", link.Attrs().Name, errno) - } - - vstats, err := vethStatsDeserialize(buffer) - if err != nil { - return -1, err - } - - return int(vstats.Peer), nil -} - -func parseTuntapData(link Link, data []syscall.NetlinkRouteAttr) { - tuntap := link.(*Tuntap) - for _, datum := range data { - switch datum.Attr.Type { - case nl.IFLA_TUN_OWNER: - tuntap.Owner = native.Uint32(datum.Value) - case nl.IFLA_TUN_GROUP: - tuntap.Group = native.Uint32(datum.Value) - case nl.IFLA_TUN_TYPE: - tuntap.Mode = TuntapMode(uint8(datum.Value[0])) - case nl.IFLA_TUN_PERSIST: - tuntap.NonPersist = false - if uint8(datum.Value[0]) == 0 { - tuntap.NonPersist = true - } - } - } -} - -func parseIPoIBData(link Link, data []syscall.NetlinkRouteAttr) { - ipoib := link.(*IPoIB) - for _, datum := range data { - switch datum.Attr.Type { - case nl.IFLA_IPOIB_PKEY: - ipoib.Pkey = uint16(native.Uint16(datum.Value)) - case nl.IFLA_IPOIB_MODE: - ipoib.Mode = IPoIBMode(native.Uint16(datum.Value)) - case nl.IFLA_IPOIB_UMCAST: - ipoib.Umcast = uint16(native.Uint16(datum.Value)) - } - } -} - -func addIPoIBAttrs(ipoib *IPoIB, linkInfo *nl.RtAttr) { - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - data.AddRtAttr(nl.IFLA_IPOIB_PKEY, nl.Uint16Attr(uint16(ipoib.Pkey))) - data.AddRtAttr(nl.IFLA_IPOIB_MODE, nl.Uint16Attr(uint16(ipoib.Mode))) - data.AddRtAttr(nl.IFLA_IPOIB_UMCAST, nl.Uint16Attr(uint16(ipoib.Umcast))) -} diff --git a/vendor/github.com/vishvananda/netlink/link_tuntap_linux.go b/vendor/github.com/vishvananda/netlink/link_tuntap_linux.go deleted file mode 100644 index 310bd33d8..000000000 --- a/vendor/github.com/vishvananda/netlink/link_tuntap_linux.go +++ /dev/null @@ -1,14 +0,0 @@ -package netlink - -// ideally golang.org/x/sys/unix would define IfReq but it only has -// IFNAMSIZ, hence this minimalistic implementation -const ( - SizeOfIfReq = 40 - IFNAMSIZ = 16 -) - -type ifReq struct { - Name [IFNAMSIZ]byte - Flags uint16 - pad [SizeOfIfReq - IFNAMSIZ - 2]byte -} diff --git a/vendor/github.com/vishvananda/netlink/neigh.go b/vendor/github.com/vishvananda/netlink/neigh.go deleted file mode 100644 index 379e5655f..000000000 --- a/vendor/github.com/vishvananda/netlink/neigh.go +++ /dev/null @@ -1,32 +0,0 @@ -package netlink - -import ( - "fmt" - "net" -) - -// Neigh represents a link layer neighbor from netlink. -type Neigh struct { - LinkIndex int - Family int - State int - Type int - Flags int - IP net.IP - HardwareAddr net.HardwareAddr - LLIPAddr net.IP //Used in the case of NHRP - Vlan int - VNI int - MasterIndex int -} - -// String returns $ip/$hwaddr $label -func (neigh *Neigh) String() string { - return fmt.Sprintf("%s %s", neigh.IP, neigh.HardwareAddr) -} - -// NeighUpdate is sent when a neighbor changes - type is RTM_NEWNEIGH or RTM_DELNEIGH. -type NeighUpdate struct { - Type uint16 - Neigh -} diff --git a/vendor/github.com/vishvananda/netlink/neigh_linux.go b/vendor/github.com/vishvananda/netlink/neigh_linux.go deleted file mode 100644 index cb3b55d35..000000000 --- a/vendor/github.com/vishvananda/netlink/neigh_linux.go +++ /dev/null @@ -1,422 +0,0 @@ -package netlink - -import ( - "fmt" - "net" - "syscall" - "unsafe" - - "github.com/vishvananda/netlink/nl" - "github.com/vishvananda/netns" - "golang.org/x/sys/unix" -) - -const ( - NDA_UNSPEC = iota - NDA_DST - NDA_LLADDR - NDA_CACHEINFO - NDA_PROBES - NDA_VLAN - NDA_PORT - NDA_VNI - NDA_IFINDEX - NDA_MASTER - NDA_LINK_NETNSID - NDA_SRC_VNI - NDA_MAX = NDA_SRC_VNI -) - -// Neighbor Cache Entry States. -const ( - NUD_NONE = 0x00 - NUD_INCOMPLETE = 0x01 - NUD_REACHABLE = 0x02 - NUD_STALE = 0x04 - NUD_DELAY = 0x08 - NUD_PROBE = 0x10 - NUD_FAILED = 0x20 - NUD_NOARP = 0x40 - NUD_PERMANENT = 0x80 -) - -// Neighbor Flags -const ( - NTF_USE = 0x01 - NTF_SELF = 0x02 - NTF_MASTER = 0x04 - NTF_PROXY = 0x08 - NTF_ROUTER = 0x80 -) - -// Ndmsg is for adding, removing or receiving information about a neighbor table entry -type Ndmsg struct { - Family uint8 - Index uint32 - State uint16 - Flags uint8 - Type uint8 -} - -func deserializeNdmsg(b []byte) *Ndmsg { - var dummy Ndmsg - return (*Ndmsg)(unsafe.Pointer(&b[0:unsafe.Sizeof(dummy)][0])) -} - -func (msg *Ndmsg) Serialize() []byte { - return (*(*[unsafe.Sizeof(*msg)]byte)(unsafe.Pointer(msg)))[:] -} - -func (msg *Ndmsg) Len() int { - return int(unsafe.Sizeof(*msg)) -} - -// NeighAdd will add an IP to MAC mapping to the ARP table -// Equivalent to: `ip neigh add ....` -func NeighAdd(neigh *Neigh) error { - return pkgHandle.NeighAdd(neigh) -} - -// NeighAdd will add an IP to MAC mapping to the ARP table -// Equivalent to: `ip neigh add ....` -func (h *Handle) NeighAdd(neigh *Neigh) error { - return h.neighAdd(neigh, unix.NLM_F_CREATE|unix.NLM_F_EXCL) -} - -// NeighSet will add or replace an IP to MAC mapping to the ARP table -// Equivalent to: `ip neigh replace....` -func NeighSet(neigh *Neigh) error { - return pkgHandle.NeighSet(neigh) -} - -// NeighSet will add or replace an IP to MAC mapping to the ARP table -// Equivalent to: `ip neigh replace....` -func (h *Handle) NeighSet(neigh *Neigh) error { - return h.neighAdd(neigh, unix.NLM_F_CREATE|unix.NLM_F_REPLACE) -} - -// NeighAppend will append an entry to FDB -// Equivalent to: `bridge fdb append...` -func NeighAppend(neigh *Neigh) error { - return pkgHandle.NeighAppend(neigh) -} - -// NeighAppend will append an entry to FDB -// Equivalent to: `bridge fdb append...` -func (h *Handle) NeighAppend(neigh *Neigh) error { - return h.neighAdd(neigh, unix.NLM_F_CREATE|unix.NLM_F_APPEND) -} - -// NeighAppend will append an entry to FDB -// Equivalent to: `bridge fdb append...` -func neighAdd(neigh *Neigh, mode int) error { - return pkgHandle.neighAdd(neigh, mode) -} - -// NeighAppend will append an entry to FDB -// Equivalent to: `bridge fdb append...` -func (h *Handle) neighAdd(neigh *Neigh, mode int) error { - req := h.newNetlinkRequest(unix.RTM_NEWNEIGH, mode|unix.NLM_F_ACK) - return neighHandle(neigh, req) -} - -// NeighDel will delete an IP address from a link device. -// Equivalent to: `ip addr del $addr dev $link` -func NeighDel(neigh *Neigh) error { - return pkgHandle.NeighDel(neigh) -} - -// NeighDel will delete an IP address from a link device. -// Equivalent to: `ip addr del $addr dev $link` -func (h *Handle) NeighDel(neigh *Neigh) error { - req := h.newNetlinkRequest(unix.RTM_DELNEIGH, unix.NLM_F_ACK) - return neighHandle(neigh, req) -} - -func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error { - var family int - - if neigh.Family > 0 { - family = neigh.Family - } else { - family = nl.GetIPFamily(neigh.IP) - } - - msg := Ndmsg{ - Family: uint8(family), - Index: uint32(neigh.LinkIndex), - State: uint16(neigh.State), - Type: uint8(neigh.Type), - Flags: uint8(neigh.Flags), - } - req.AddData(&msg) - - ipData := neigh.IP.To4() - if ipData == nil { - ipData = neigh.IP.To16() - } - - dstData := nl.NewRtAttr(NDA_DST, ipData) - req.AddData(dstData) - - if neigh.LLIPAddr != nil { - llIPData := nl.NewRtAttr(NDA_LLADDR, neigh.LLIPAddr.To4()) - req.AddData(llIPData) - } else if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil { - hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr)) - req.AddData(hwData) - } - - if neigh.Vlan != 0 { - vlanData := nl.NewRtAttr(NDA_VLAN, nl.Uint16Attr(uint16(neigh.Vlan))) - req.AddData(vlanData) - } - - if neigh.VNI != 0 { - vniData := nl.NewRtAttr(NDA_VNI, nl.Uint32Attr(uint32(neigh.VNI))) - req.AddData(vniData) - } - - if neigh.MasterIndex != 0 { - masterData := nl.NewRtAttr(NDA_MASTER, nl.Uint32Attr(uint32(neigh.MasterIndex))) - req.AddData(masterData) - } - - _, err := req.Execute(unix.NETLINK_ROUTE, 0) - return err -} - -// NeighList returns a list of IP-MAC mappings in the system (ARP table). -// Equivalent to: `ip neighbor show`. -// The list can be filtered by link and ip family. -func NeighList(linkIndex, family int) ([]Neigh, error) { - return pkgHandle.NeighList(linkIndex, family) -} - -// NeighProxyList returns a list of neighbor proxies in the system. -// Equivalent to: `ip neighbor show proxy`. -// The list can be filtered by link and ip family. -func NeighProxyList(linkIndex, family int) ([]Neigh, error) { - return pkgHandle.NeighProxyList(linkIndex, family) -} - -// NeighList returns a list of IP-MAC mappings in the system (ARP table). -// Equivalent to: `ip neighbor show`. -// The list can be filtered by link and ip family. -func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) { - return h.NeighListExecute(Ndmsg{ - Family: uint8(family), - Index: uint32(linkIndex), - }) -} - -// NeighProxyList returns a list of neighbor proxies in the system. -// Equivalent to: `ip neighbor show proxy`. -// The list can be filtered by link, ip family. -func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) { - return h.NeighListExecute(Ndmsg{ - Family: uint8(family), - Index: uint32(linkIndex), - Flags: NTF_PROXY, - }) -} - -// NeighListExecute returns a list of neighbour entries filtered by link, ip family, flag and state. -func NeighListExecute(msg Ndmsg) ([]Neigh, error) { - return pkgHandle.NeighListExecute(msg) -} - -// NeighListExecute returns a list of neighbour entries filtered by link, ip family, flag and state. -func (h *Handle) NeighListExecute(msg Ndmsg) ([]Neigh, error) { - req := h.newNetlinkRequest(unix.RTM_GETNEIGH, unix.NLM_F_DUMP) - req.AddData(&msg) - - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNEIGH) - if err != nil { - return nil, err - } - - var res []Neigh - for _, m := range msgs { - ndm := deserializeNdmsg(m) - if msg.Index != 0 && ndm.Index != msg.Index { - // Ignore messages from other interfaces - continue - } - - neigh, err := NeighDeserialize(m) - if err != nil { - continue - } - - res = append(res, *neigh) - } - - return res, nil -} - -func NeighDeserialize(m []byte) (*Neigh, error) { - msg := deserializeNdmsg(m) - - neigh := Neigh{ - LinkIndex: int(msg.Index), - Family: int(msg.Family), - State: int(msg.State), - Type: int(msg.Type), - Flags: int(msg.Flags), - } - - attrs, err := nl.ParseRouteAttr(m[msg.Len():]) - if err != nil { - return nil, err - } - - for _, attr := range attrs { - switch attr.Attr.Type { - case NDA_DST: - neigh.IP = net.IP(attr.Value) - case NDA_LLADDR: - // BUG: Is this a bug in the netlink library? - // #define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len)) - // #define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0)) - attrLen := attr.Attr.Len - unix.SizeofRtAttr - if attrLen == 4 { - neigh.LLIPAddr = net.IP(attr.Value) - } else if attrLen == 16 { - // Can be IPv6 or FireWire HWAddr - link, err := LinkByIndex(neigh.LinkIndex) - if err == nil && link.Attrs().EncapType == "tunnel6" { - neigh.IP = net.IP(attr.Value) - } else { - neigh.HardwareAddr = net.HardwareAddr(attr.Value) - } - } else { - neigh.HardwareAddr = net.HardwareAddr(attr.Value) - } - case NDA_VLAN: - neigh.Vlan = int(native.Uint16(attr.Value[0:2])) - case NDA_VNI: - neigh.VNI = int(native.Uint32(attr.Value[0:4])) - case NDA_MASTER: - neigh.MasterIndex = int(native.Uint32(attr.Value[0:4])) - } - } - - return &neigh, nil -} - -// NeighSubscribe takes a chan down which notifications will be sent -// when neighbors are added or deleted. Close the 'done' chan to stop subscription. -func NeighSubscribe(ch chan<- NeighUpdate, done <-chan struct{}) error { - return neighSubscribeAt(netns.None(), netns.None(), ch, done, nil, false) -} - -// NeighSubscribeAt works like NeighSubscribe plus it allows the caller -// to choose the network namespace in which to subscribe (ns). -func NeighSubscribeAt(ns netns.NsHandle, ch chan<- NeighUpdate, done <-chan struct{}) error { - return neighSubscribeAt(ns, netns.None(), ch, done, nil, false) -} - -// NeighSubscribeOptions contains a set of options to use with -// NeighSubscribeWithOptions. -type NeighSubscribeOptions struct { - Namespace *netns.NsHandle - ErrorCallback func(error) - ListExisting bool -} - -// NeighSubscribeWithOptions work like NeighSubscribe but enable to -// provide additional options to modify the behavior. Currently, the -// namespace can be provided as well as an error callback. -func NeighSubscribeWithOptions(ch chan<- NeighUpdate, done <-chan struct{}, options NeighSubscribeOptions) error { - if options.Namespace == nil { - none := netns.None() - options.Namespace = &none - } - return neighSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting) -} - -func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error { - s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_NEIGH) - makeRequest := func(family int) error { - req := pkgHandle.newNetlinkRequest(unix.RTM_GETNEIGH, - unix.NLM_F_DUMP) - infmsg := nl.NewIfInfomsg(family) - req.AddData(infmsg) - if err := s.Send(req); err != nil { - return err - } - return nil - } - if err != nil { - return err - } - if done != nil { - go func() { - <-done - s.Close() - }() - } - if listExisting { - if err := makeRequest(unix.AF_UNSPEC); err != nil { - return err - } - // We have to wait for NLMSG_DONE before making AF_BRIDGE request - } - go func() { - defer close(ch) - for { - msgs, from, err := s.Receive() - if err != nil { - if cberr != nil { - cberr(err) - } - return - } - if from.Pid != nl.PidKernel { - if cberr != nil { - cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)) - } - continue - } - for _, m := range msgs { - if m.Header.Type == unix.NLMSG_DONE { - if listExisting { - // This will be called after handling AF_UNSPEC - // list request, we have to wait for NLMSG_DONE - // before making another request - if err := makeRequest(unix.AF_BRIDGE); err != nil { - if cberr != nil { - cberr(err) - } - return - } - listExisting = false - } - continue - } - if m.Header.Type == unix.NLMSG_ERROR { - native := nl.NativeEndian() - error := int32(native.Uint32(m.Data[0:4])) - if error == 0 { - continue - } - if cberr != nil { - cberr(syscall.Errno(-error)) - } - return - } - neigh, err := NeighDeserialize(m.Data) - if err != nil { - if cberr != nil { - cberr(err) - } - return - } - ch <- NeighUpdate{Type: m.Header.Type, Neigh: *neigh} - } - } - }() - - return nil -} diff --git a/vendor/github.com/vishvananda/netlink/netlink.go b/vendor/github.com/vishvananda/netlink/netlink.go deleted file mode 100644 index 9cb685dc8..000000000 --- a/vendor/github.com/vishvananda/netlink/netlink.go +++ /dev/null @@ -1,40 +0,0 @@ -// Package netlink provides a simple library for netlink. Netlink is -// the interface a user-space program in linux uses to communicate with -// the kernel. It can be used to add and remove interfaces, set up ip -// addresses and routes, and confiugre ipsec. Netlink communication -// requires elevated privileges, so in most cases this code needs to -// be run as root. The low level primitives for netlink are contained -// in the nl subpackage. This package attempts to provide a high-level -// interface that is loosly modeled on the iproute2 cli. -package netlink - -import ( - "errors" - "net" -) - -var ( - // ErrNotImplemented is returned when a requested feature is not implemented. - ErrNotImplemented = errors.New("not implemented") -) - -// ParseIPNet parses a string in ip/net format and returns a net.IPNet. -// This is valuable because addresses in netlink are often IPNets and -// ParseCIDR returns an IPNet with the IP part set to the base IP of the -// range. -func ParseIPNet(s string) (*net.IPNet, error) { - ip, ipNet, err := net.ParseCIDR(s) - if err != nil { - return nil, err - } - ipNet.IP = ip - return ipNet, nil -} - -// NewIPNet generates an IPNet from an ip address using a netmask of 32 or 128. -func NewIPNet(ip net.IP) *net.IPNet { - if ip.To4() != nil { - return &net.IPNet{IP: ip, Mask: net.CIDRMask(32, 32)} - } - return &net.IPNet{IP: ip, Mask: net.CIDRMask(128, 128)} -} diff --git a/vendor/github.com/vishvananda/netlink/netlink_linux.go b/vendor/github.com/vishvananda/netlink/netlink_linux.go deleted file mode 100644 index a20d293d8..000000000 --- a/vendor/github.com/vishvananda/netlink/netlink_linux.go +++ /dev/null @@ -1,11 +0,0 @@ -package netlink - -import "github.com/vishvananda/netlink/nl" - -// Family type definitions -const ( - FAMILY_ALL = nl.FAMILY_ALL - FAMILY_V4 = nl.FAMILY_V4 - FAMILY_V6 = nl.FAMILY_V6 - FAMILY_MPLS = nl.FAMILY_MPLS -) diff --git a/vendor/github.com/vishvananda/netlink/netlink_unspecified.go b/vendor/github.com/vishvananda/netlink/netlink_unspecified.go deleted file mode 100644 index 42d3acf91..000000000 --- a/vendor/github.com/vishvananda/netlink/netlink_unspecified.go +++ /dev/null @@ -1,237 +0,0 @@ -// +build !linux - -package netlink - -import "net" - -func LinkSetUp(link Link) error { - return ErrNotImplemented -} - -func LinkSetDown(link Link) error { - return ErrNotImplemented -} - -func LinkSetMTU(link Link, mtu int) error { - return ErrNotImplemented -} - -func LinkSetMaster(link Link, master *Bridge) error { - return ErrNotImplemented -} - -func LinkSetNsPid(link Link, nspid int) error { - return ErrNotImplemented -} - -func LinkSetNsFd(link Link, fd int) error { - return ErrNotImplemented -} - -func LinkSetName(link Link, name string) error { - return ErrNotImplemented -} - -func LinkSetAlias(link Link, name string) error { - return ErrNotImplemented -} - -func LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error { - return ErrNotImplemented -} - -func LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error { - return ErrNotImplemented -} - -func LinkSetVfVlan(link Link, vf, vlan int) error { - return ErrNotImplemented -} - -func LinkSetVfVlanQos(link Link, vf, vlan, qos int) error { - return ErrNotImplemented -} - -func LinkSetVfTxRate(link Link, vf, rate int) error { - return ErrNotImplemented -} - -func LinkSetVfRate(link Link, vf, minRate, maxRate int) error { - return ErrNotImplemented -} - -func LinkSetNoMaster(link Link) error { - return ErrNotImplemented -} - -func LinkSetMasterByIndex(link Link, masterIndex int) error { - return ErrNotImplemented -} - -func LinkSetXdpFd(link Link, fd int) error { - return ErrNotImplemented -} - -func LinkSetARPOff(link Link) error { - return ErrNotImplemented -} - -func LinkSetARPOn(link Link) error { - return ErrNotImplemented -} - -func LinkByName(name string) (Link, error) { - return nil, ErrNotImplemented -} - -func LinkByAlias(alias string) (Link, error) { - return nil, ErrNotImplemented -} - -func LinkByIndex(index int) (Link, error) { - return nil, ErrNotImplemented -} - -func LinkSetHairpin(link Link, mode bool) error { - return ErrNotImplemented -} - -func LinkSetGuard(link Link, mode bool) error { - return ErrNotImplemented -} - -func LinkSetFastLeave(link Link, mode bool) error { - return ErrNotImplemented -} - -func LinkSetLearning(link Link, mode bool) error { - return ErrNotImplemented -} - -func LinkSetRootBlock(link Link, mode bool) error { - return ErrNotImplemented -} - -func LinkSetFlood(link Link, mode bool) error { - return ErrNotImplemented -} - -func LinkSetTxQLen(link Link, qlen int) error { - return ErrNotImplemented -} - -func LinkAdd(link Link) error { - return ErrNotImplemented -} - -func LinkDel(link Link) error { - return ErrNotImplemented -} - -func SetHairpin(link Link, mode bool) error { - return ErrNotImplemented -} - -func SetGuard(link Link, mode bool) error { - return ErrNotImplemented -} - -func SetFastLeave(link Link, mode bool) error { - return ErrNotImplemented -} - -func SetLearning(link Link, mode bool) error { - return ErrNotImplemented -} - -func SetRootBlock(link Link, mode bool) error { - return ErrNotImplemented -} - -func SetFlood(link Link, mode bool) error { - return ErrNotImplemented -} - -func LinkList() ([]Link, error) { - return nil, ErrNotImplemented -} - -func AddrAdd(link Link, addr *Addr) error { - return ErrNotImplemented -} - -func AddrReplace(link Link, addr *Addr) error { - return ErrNotImplemented -} - -func AddrDel(link Link, addr *Addr) error { - return ErrNotImplemented -} - -func AddrList(link Link, family int) ([]Addr, error) { - return nil, ErrNotImplemented -} - -func RouteAdd(route *Route) error { - return ErrNotImplemented -} - -func RouteDel(route *Route) error { - return ErrNotImplemented -} - -func RouteList(link Link, family int) ([]Route, error) { - return nil, ErrNotImplemented -} - -func XfrmPolicyAdd(policy *XfrmPolicy) error { - return ErrNotImplemented -} - -func XfrmPolicyDel(policy *XfrmPolicy) error { - return ErrNotImplemented -} - -func XfrmPolicyList(family int) ([]XfrmPolicy, error) { - return nil, ErrNotImplemented -} - -func XfrmStateAdd(policy *XfrmState) error { - return ErrNotImplemented -} - -func XfrmStateDel(policy *XfrmState) error { - return ErrNotImplemented -} - -func XfrmStateList(family int) ([]XfrmState, error) { - return nil, ErrNotImplemented -} - -func NeighAdd(neigh *Neigh) error { - return ErrNotImplemented -} - -func NeighSet(neigh *Neigh) error { - return ErrNotImplemented -} - -func NeighAppend(neigh *Neigh) error { - return ErrNotImplemented -} - -func NeighDel(neigh *Neigh) error { - return ErrNotImplemented -} - -func NeighList(linkIndex, family int) ([]Neigh, error) { - return nil, ErrNotImplemented -} - -func NeighDeserialize(m []byte) (*Neigh, error) { - return nil, ErrNotImplemented -} - -func SocketGet(local, remote net.Addr) (*Socket, error) { - return nil, ErrNotImplemented -} diff --git a/vendor/github.com/vishvananda/netlink/netns_linux.go b/vendor/github.com/vishvananda/netlink/netns_linux.go deleted file mode 100644 index 77cf6f469..000000000 --- a/vendor/github.com/vishvananda/netlink/netns_linux.go +++ /dev/null @@ -1,141 +0,0 @@ -package netlink - -// Network namespace ID functions -// -// The kernel has a weird concept called the network namespace ID. -// This is different from the file reference in proc (and any bind-mounted -// namespaces, etc.) -// -// Instead, namespaces can be assigned a numeric ID at any time. Once set, -// the ID is fixed. The ID can either be set manually by the user, or -// automatically, triggered by certain kernel actions. The most common kernel -// action that triggers namespace ID creation is moving one end of a veth pair -// in to that namespace. - -import ( - "fmt" - - "github.com/vishvananda/netlink/nl" - "golang.org/x/sys/unix" -) - -// These can be replaced by the values from sys/unix when it is next released. -const ( - _ = iota - NETNSA_NSID - NETNSA_PID - NETNSA_FD -) - -// GetNetNsIdByPid looks up the network namespace ID for a given pid (really thread id). -// Returns -1 if the namespace does not have an ID set. -func (h *Handle) GetNetNsIdByPid(pid int) (int, error) { - return h.getNetNsId(NETNSA_PID, uint32(pid)) -} - -// GetNetNsIdByPid looks up the network namespace ID for a given pid (really thread id). -// Returns -1 if the namespace does not have an ID set. -func GetNetNsIdByPid(pid int) (int, error) { - return pkgHandle.GetNetNsIdByPid(pid) -} - -// SetNetNSIdByPid sets the ID of the network namespace for a given pid (really thread id). -// The ID can only be set for namespaces without an ID already set. -func (h *Handle) SetNetNsIdByPid(pid, nsid int) error { - return h.setNetNsId(NETNSA_PID, uint32(pid), uint32(nsid)) -} - -// SetNetNSIdByPid sets the ID of the network namespace for a given pid (really thread id). -// The ID can only be set for namespaces without an ID already set. -func SetNetNsIdByPid(pid, nsid int) error { - return pkgHandle.SetNetNsIdByPid(pid, nsid) -} - -// GetNetNsIdByFd looks up the network namespace ID for a given fd. -// fd must be an open file descriptor to a namespace file. -// Returns -1 if the namespace does not have an ID set. -func (h *Handle) GetNetNsIdByFd(fd int) (int, error) { - return h.getNetNsId(NETNSA_FD, uint32(fd)) -} - -// GetNetNsIdByFd looks up the network namespace ID for a given fd. -// fd must be an open file descriptor to a namespace file. -// Returns -1 if the namespace does not have an ID set. -func GetNetNsIdByFd(fd int) (int, error) { - return pkgHandle.GetNetNsIdByFd(fd) -} - -// SetNetNSIdByFd sets the ID of the network namespace for a given fd. -// fd must be an open file descriptor to a namespace file. -// The ID can only be set for namespaces without an ID already set. -func (h *Handle) SetNetNsIdByFd(fd, nsid int) error { - return h.setNetNsId(NETNSA_FD, uint32(fd), uint32(nsid)) -} - -// SetNetNSIdByFd sets the ID of the network namespace for a given fd. -// fd must be an open file descriptor to a namespace file. -// The ID can only be set for namespaces without an ID already set. -func SetNetNsIdByFd(fd, nsid int) error { - return pkgHandle.SetNetNsIdByFd(fd, nsid) -} - -// getNetNsId requests the netnsid for a given type-val pair -// type should be either NETNSA_PID or NETNSA_FD -func (h *Handle) getNetNsId(attrType int, val uint32) (int, error) { - req := h.newNetlinkRequest(unix.RTM_GETNSID, unix.NLM_F_REQUEST) - - rtgen := nl.NewRtGenMsg() - req.AddData(rtgen) - - b := make([]byte, 4, 4) - native.PutUint32(b, val) - attr := nl.NewRtAttr(attrType, b) - req.AddData(attr) - - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNSID) - - if err != nil { - return 0, err - } - - for _, m := range msgs { - msg := nl.DeserializeRtGenMsg(m) - - attrs, err := nl.ParseRouteAttr(m[msg.Len():]) - if err != nil { - return 0, err - } - - for _, attr := range attrs { - switch attr.Attr.Type { - case NETNSA_NSID: - return int(int32(native.Uint32(attr.Value))), nil - } - } - } - - return 0, fmt.Errorf("unexpected empty result") -} - -// setNetNsId sets the netnsid for a given type-val pair -// type should be either NETNSA_PID or NETNSA_FD -// The ID can only be set for namespaces without an ID already set -func (h *Handle) setNetNsId(attrType int, val uint32, newnsid uint32) error { - req := h.newNetlinkRequest(unix.RTM_NEWNSID, unix.NLM_F_REQUEST|unix.NLM_F_ACK) - - rtgen := nl.NewRtGenMsg() - req.AddData(rtgen) - - b := make([]byte, 4, 4) - native.PutUint32(b, val) - attr := nl.NewRtAttr(attrType, b) - req.AddData(attr) - - b1 := make([]byte, 4, 4) - native.PutUint32(b1, newnsid) - attr1 := nl.NewRtAttr(NETNSA_NSID, b1) - req.AddData(attr1) - - _, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNSID) - return err -} diff --git a/vendor/github.com/vishvananda/netlink/netns_unspecified.go b/vendor/github.com/vishvananda/netlink/netns_unspecified.go deleted file mode 100644 index 5c5899e36..000000000 --- a/vendor/github.com/vishvananda/netlink/netns_unspecified.go +++ /dev/null @@ -1,19 +0,0 @@ -// +build !linux - -package netlink - -func GetNetNsIdByPid(pid int) (int, error) { - return 0, ErrNotImplemented -} - -func SetNetNsIdByPid(pid, nsid int) error { - return ErrNotImplemented -} - -func GetNetNsIdByFd(fd int) (int, error) { - return 0, ErrNotImplemented -} - -func SetNetNsIdByFd(fd, nsid int) error { - return ErrNotImplemented -} diff --git a/vendor/github.com/vishvananda/netlink/nl/addr_linux.go b/vendor/github.com/vishvananda/netlink/nl/addr_linux.go deleted file mode 100644 index 50db3b4cd..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/addr_linux.go +++ /dev/null @@ -1,77 +0,0 @@ -package nl - -import ( - "unsafe" - - "golang.org/x/sys/unix" -) - -type IfAddrmsg struct { - unix.IfAddrmsg -} - -func NewIfAddrmsg(family int) *IfAddrmsg { - return &IfAddrmsg{ - IfAddrmsg: unix.IfAddrmsg{ - Family: uint8(family), - }, - } -} - -// struct ifaddrmsg { -// __u8 ifa_family; -// __u8 ifa_prefixlen; /* The prefix length */ -// __u8 ifa_flags; /* Flags */ -// __u8 ifa_scope; /* Address scope */ -// __u32 ifa_index; /* Link index */ -// }; - -// type IfAddrmsg struct { -// Family uint8 -// Prefixlen uint8 -// Flags uint8 -// Scope uint8 -// Index uint32 -// } -// SizeofIfAddrmsg = 0x8 - -func DeserializeIfAddrmsg(b []byte) *IfAddrmsg { - return (*IfAddrmsg)(unsafe.Pointer(&b[0:unix.SizeofIfAddrmsg][0])) -} - -func (msg *IfAddrmsg) Serialize() []byte { - return (*(*[unix.SizeofIfAddrmsg]byte)(unsafe.Pointer(msg)))[:] -} - -func (msg *IfAddrmsg) Len() int { - return unix.SizeofIfAddrmsg -} - -// struct ifa_cacheinfo { -// __u32 ifa_prefered; -// __u32 ifa_valid; -// __u32 cstamp; /* created timestamp, hundredths of seconds */ -// __u32 tstamp; /* updated timestamp, hundredths of seconds */ -// }; - -const IFA_CACHEINFO = 6 -const SizeofIfaCacheInfo = 0x10 - -type IfaCacheInfo struct { - IfaPrefered uint32 - IfaValid uint32 - Cstamp uint32 - Tstamp uint32 -} - -func (msg *IfaCacheInfo) Len() int { - return SizeofIfaCacheInfo -} - -func DeserializeIfaCacheInfo(b []byte) *IfaCacheInfo { - return (*IfaCacheInfo)(unsafe.Pointer(&b[0:SizeofIfaCacheInfo][0])) -} - -func (msg *IfaCacheInfo) Serialize() []byte { - return (*(*[SizeofIfaCacheInfo]byte)(unsafe.Pointer(msg)))[:] -} diff --git a/vendor/github.com/vishvananda/netlink/nl/bridge_linux.go b/vendor/github.com/vishvananda/netlink/nl/bridge_linux.go deleted file mode 100644 index 34e78ba8d..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/bridge_linux.go +++ /dev/null @@ -1,74 +0,0 @@ -package nl - -import ( - "fmt" - "unsafe" -) - -const ( - SizeofBridgeVlanInfo = 0x04 -) - -/* Bridge Flags */ -const ( - BRIDGE_FLAGS_MASTER = iota + 1 /* Bridge command to/from master */ - BRIDGE_FLAGS_SELF /* Bridge command to/from lowerdev */ -) - -/* Bridge management nested attributes - * [IFLA_AF_SPEC] = { - * [IFLA_BRIDGE_FLAGS] - * [IFLA_BRIDGE_MODE] - * [IFLA_BRIDGE_VLAN_INFO] - * } - */ -const ( - IFLA_BRIDGE_FLAGS = iota - IFLA_BRIDGE_MODE - IFLA_BRIDGE_VLAN_INFO -) - -const ( - BRIDGE_VLAN_INFO_MASTER = 1 << iota - BRIDGE_VLAN_INFO_PVID - BRIDGE_VLAN_INFO_UNTAGGED - BRIDGE_VLAN_INFO_RANGE_BEGIN - BRIDGE_VLAN_INFO_RANGE_END -) - -// struct bridge_vlan_info { -// __u16 flags; -// __u16 vid; -// }; - -type BridgeVlanInfo struct { - Flags uint16 - Vid uint16 -} - -func (b *BridgeVlanInfo) Serialize() []byte { - return (*(*[SizeofBridgeVlanInfo]byte)(unsafe.Pointer(b)))[:] -} - -func DeserializeBridgeVlanInfo(b []byte) *BridgeVlanInfo { - return (*BridgeVlanInfo)(unsafe.Pointer(&b[0:SizeofBridgeVlanInfo][0])) -} - -func (b *BridgeVlanInfo) PortVID() bool { - return b.Flags&BRIDGE_VLAN_INFO_PVID > 0 -} - -func (b *BridgeVlanInfo) EngressUntag() bool { - return b.Flags&BRIDGE_VLAN_INFO_UNTAGGED > 0 -} - -func (b *BridgeVlanInfo) String() string { - return fmt.Sprintf("%+v", *b) -} - -/* New extended info filters for IFLA_EXT_MASK */ -const ( - RTEXT_FILTER_VF = 1 << iota - RTEXT_FILTER_BRVLAN - RTEXT_FILTER_BRVLAN_COMPRESSED -) diff --git a/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go b/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go deleted file mode 100644 index 79d2b6b89..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go +++ /dev/null @@ -1,217 +0,0 @@ -package nl - -import "unsafe" - -// Track the message sizes for the correct serialization/deserialization -const ( - SizeofNfgenmsg = 4 - SizeofNfattr = 4 - SizeofNfConntrack = 376 - SizeofNfctTupleHead = 52 -) - -var L4ProtoMap = map[uint8]string{ - 6: "tcp", - 17: "udp", -} - -// All the following constants are coming from: -// https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink_conntrack.h - -// enum cntl_msg_types { -// IPCTNL_MSG_CT_NEW, -// IPCTNL_MSG_CT_GET, -// IPCTNL_MSG_CT_DELETE, -// IPCTNL_MSG_CT_GET_CTRZERO, -// IPCTNL_MSG_CT_GET_STATS_CPU, -// IPCTNL_MSG_CT_GET_STATS, -// IPCTNL_MSG_CT_GET_DYING, -// IPCTNL_MSG_CT_GET_UNCONFIRMED, -// -// IPCTNL_MSG_MAX -// }; -const ( - IPCTNL_MSG_CT_GET = 1 - IPCTNL_MSG_CT_DELETE = 2 -) - -// #define NFNETLINK_V0 0 -const ( - NFNETLINK_V0 = 0 -) - -// #define NLA_F_NESTED (1 << 15) -const ( - NLA_F_NESTED = (1 << 15) -) - -// enum ctattr_type { -// CTA_UNSPEC, -// CTA_TUPLE_ORIG, -// CTA_TUPLE_REPLY, -// CTA_STATUS, -// CTA_PROTOINFO, -// CTA_HELP, -// CTA_NAT_SRC, -// #define CTA_NAT CTA_NAT_SRC /* backwards compatibility */ -// CTA_TIMEOUT, -// CTA_MARK, -// CTA_COUNTERS_ORIG, -// CTA_COUNTERS_REPLY, -// CTA_USE, -// CTA_ID, -// CTA_NAT_DST, -// CTA_TUPLE_MASTER, -// CTA_SEQ_ADJ_ORIG, -// CTA_NAT_SEQ_ADJ_ORIG = CTA_SEQ_ADJ_ORIG, -// CTA_SEQ_ADJ_REPLY, -// CTA_NAT_SEQ_ADJ_REPLY = CTA_SEQ_ADJ_REPLY, -// CTA_SECMARK, /* obsolete */ -// CTA_ZONE, -// CTA_SECCTX, -// CTA_TIMESTAMP, -// CTA_MARK_MASK, -// CTA_LABELS, -// CTA_LABELS_MASK, -// __CTA_MAX -// }; -const ( - CTA_TUPLE_ORIG = 1 - CTA_TUPLE_REPLY = 2 - CTA_STATUS = 3 - CTA_PROTOINFO = 4 - CTA_TIMEOUT = 7 - CTA_MARK = 8 - CTA_COUNTERS_ORIG = 9 - CTA_COUNTERS_REPLY = 10 - CTA_USE = 11 - CTA_ID = 12 - CTA_TIMESTAMP = 20 -) - -// enum ctattr_tuple { -// CTA_TUPLE_UNSPEC, -// CTA_TUPLE_IP, -// CTA_TUPLE_PROTO, -// CTA_TUPLE_ZONE, -// __CTA_TUPLE_MAX -// }; -// #define CTA_TUPLE_MAX (__CTA_TUPLE_MAX - 1) -const ( - CTA_TUPLE_IP = 1 - CTA_TUPLE_PROTO = 2 -) - -// enum ctattr_ip { -// CTA_IP_UNSPEC, -// CTA_IP_V4_SRC, -// CTA_IP_V4_DST, -// CTA_IP_V6_SRC, -// CTA_IP_V6_DST, -// __CTA_IP_MAX -// }; -// #define CTA_IP_MAX (__CTA_IP_MAX - 1) -const ( - CTA_IP_V4_SRC = 1 - CTA_IP_V4_DST = 2 - CTA_IP_V6_SRC = 3 - CTA_IP_V6_DST = 4 -) - -// enum ctattr_l4proto { -// CTA_PROTO_UNSPEC, -// CTA_PROTO_NUM, -// CTA_PROTO_SRC_PORT, -// CTA_PROTO_DST_PORT, -// CTA_PROTO_ICMP_ID, -// CTA_PROTO_ICMP_TYPE, -// CTA_PROTO_ICMP_CODE, -// CTA_PROTO_ICMPV6_ID, -// CTA_PROTO_ICMPV6_TYPE, -// CTA_PROTO_ICMPV6_CODE, -// __CTA_PROTO_MAX -// }; -// #define CTA_PROTO_MAX (__CTA_PROTO_MAX - 1) -const ( - CTA_PROTO_NUM = 1 - CTA_PROTO_SRC_PORT = 2 - CTA_PROTO_DST_PORT = 3 -) - -// enum ctattr_protoinfo { -// CTA_PROTOINFO_UNSPEC, -// CTA_PROTOINFO_TCP, -// CTA_PROTOINFO_DCCP, -// CTA_PROTOINFO_SCTP, -// __CTA_PROTOINFO_MAX -// }; -// #define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1) -const ( - CTA_PROTOINFO_TCP = 1 -) - -// enum ctattr_protoinfo_tcp { -// CTA_PROTOINFO_TCP_UNSPEC, -// CTA_PROTOINFO_TCP_STATE, -// CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, -// CTA_PROTOINFO_TCP_WSCALE_REPLY, -// CTA_PROTOINFO_TCP_FLAGS_ORIGINAL, -// CTA_PROTOINFO_TCP_FLAGS_REPLY, -// __CTA_PROTOINFO_TCP_MAX -// }; -// #define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1) -const ( - CTA_PROTOINFO_TCP_STATE = 1 - CTA_PROTOINFO_TCP_WSCALE_ORIGINAL = 2 - CTA_PROTOINFO_TCP_WSCALE_REPLY = 3 - CTA_PROTOINFO_TCP_FLAGS_ORIGINAL = 4 - CTA_PROTOINFO_TCP_FLAGS_REPLY = 5 -) - -// enum ctattr_counters { -// CTA_COUNTERS_UNSPEC, -// CTA_COUNTERS_PACKETS, /* 64bit counters */ -// CTA_COUNTERS_BYTES, /* 64bit counters */ -// CTA_COUNTERS32_PACKETS, /* old 32bit counters, unused */ -// CTA_COUNTERS32_BYTES, /* old 32bit counters, unused */ -// CTA_COUNTERS_PAD, -// __CTA_COUNTERS_M -// }; -// #define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1) -const ( - CTA_COUNTERS_PACKETS = 1 - CTA_COUNTERS_BYTES = 2 -) - -// enum CTA TIMESTAMP TLVs -// CTA_TIMESTAMP_START /* 64bit value */ -// CTA_TIMESTAMP_STOP /* 64bit value */ -const ( - CTA_TIMESTAMP_START = 1 - CTA_TIMESTAMP_STOP = 2 -) - -// /* General form of address family dependent message. -// */ -// struct nfgenmsg { -// __u8 nfgen_family; /* AF_xxx */ -// __u8 version; /* nfnetlink version */ -// __be16 res_id; /* resource id */ -// }; -type Nfgenmsg struct { - NfgenFamily uint8 - Version uint8 - ResId uint16 // big endian -} - -func (msg *Nfgenmsg) Len() int { - return SizeofNfgenmsg -} - -func DeserializeNfgenmsg(b []byte) *Nfgenmsg { - return (*Nfgenmsg)(unsafe.Pointer(&b[0:SizeofNfgenmsg][0])) -} - -func (msg *Nfgenmsg) Serialize() []byte { - return (*(*[SizeofNfgenmsg]byte)(unsafe.Pointer(msg)))[:] -} diff --git a/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go b/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go deleted file mode 100644 index db66faaad..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go +++ /dev/null @@ -1,40 +0,0 @@ -package nl - -// All the following constants are coming from: -// https://github.com/torvalds/linux/blob/master/include/uapi/linux/devlink.h - -const ( - GENL_DEVLINK_VERSION = 1 - GENL_DEVLINK_NAME = "devlink" -) - -const ( - DEVLINK_CMD_GET = 1 - DEVLINK_CMD_ESWITCH_GET = 29 - DEVLINK_CMD_ESWITCH_SET = 30 -) - -const ( - DEVLINK_ATTR_BUS_NAME = 1 - DEVLINK_ATTR_DEV_NAME = 2 - DEVLINK_ATTR_ESWITCH_MODE = 25 - DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26 - DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62 -) - -const ( - DEVLINK_ESWITCH_MODE_LEGACY = 0 - DEVLINK_ESWITCH_MODE_SWITCHDEV = 1 -) - -const ( - DEVLINK_ESWITCH_INLINE_MODE_NONE = 0 - DEVLINK_ESWITCH_INLINE_MODE_LINK = 1 - DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 2 - DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 3 -) - -const ( - DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0 - DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 1 -) diff --git a/vendor/github.com/vishvananda/netlink/nl/genetlink_linux.go b/vendor/github.com/vishvananda/netlink/nl/genetlink_linux.go deleted file mode 100644 index 81b46f2c7..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/genetlink_linux.go +++ /dev/null @@ -1,89 +0,0 @@ -package nl - -import ( - "unsafe" -) - -const SizeofGenlmsg = 4 - -const ( - GENL_ID_CTRL = 0x10 - GENL_CTRL_VERSION = 2 - GENL_CTRL_NAME = "nlctrl" -) - -const ( - GENL_CTRL_CMD_GETFAMILY = 3 -) - -const ( - GENL_CTRL_ATTR_UNSPEC = iota - GENL_CTRL_ATTR_FAMILY_ID - GENL_CTRL_ATTR_FAMILY_NAME - GENL_CTRL_ATTR_VERSION - GENL_CTRL_ATTR_HDRSIZE - GENL_CTRL_ATTR_MAXATTR - GENL_CTRL_ATTR_OPS - GENL_CTRL_ATTR_MCAST_GROUPS -) - -const ( - GENL_CTRL_ATTR_OP_UNSPEC = iota - GENL_CTRL_ATTR_OP_ID - GENL_CTRL_ATTR_OP_FLAGS -) - -const ( - GENL_ADMIN_PERM = 1 << iota - GENL_CMD_CAP_DO - GENL_CMD_CAP_DUMP - GENL_CMD_CAP_HASPOL -) - -const ( - GENL_CTRL_ATTR_MCAST_GRP_UNSPEC = iota - GENL_CTRL_ATTR_MCAST_GRP_NAME - GENL_CTRL_ATTR_MCAST_GRP_ID -) - -const ( - GENL_GTP_VERSION = 0 - GENL_GTP_NAME = "gtp" -) - -const ( - GENL_GTP_CMD_NEWPDP = iota - GENL_GTP_CMD_DELPDP - GENL_GTP_CMD_GETPDP -) - -const ( - GENL_GTP_ATTR_UNSPEC = iota - GENL_GTP_ATTR_LINK - GENL_GTP_ATTR_VERSION - GENL_GTP_ATTR_TID - GENL_GTP_ATTR_PEER_ADDRESS - GENL_GTP_ATTR_MS_ADDRESS - GENL_GTP_ATTR_FLOW - GENL_GTP_ATTR_NET_NS_FD - GENL_GTP_ATTR_I_TEI - GENL_GTP_ATTR_O_TEI - GENL_GTP_ATTR_PAD -) - -type Genlmsg struct { - Command uint8 - Version uint8 -} - -func (msg *Genlmsg) Len() int { - return SizeofGenlmsg -} - -func DeserializeGenlmsg(b []byte) *Genlmsg { - return (*Genlmsg)(unsafe.Pointer(&b[0:SizeofGenlmsg][0])) -} - -func (msg *Genlmsg) Serialize() []byte { - return (*(*[SizeofGenlmsg]byte)(unsafe.Pointer(msg)))[:] -} diff --git a/vendor/github.com/vishvananda/netlink/nl/link_linux.go b/vendor/github.com/vishvananda/netlink/nl/link_linux.go deleted file mode 100644 index afb16a9c1..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/link_linux.go +++ /dev/null @@ -1,610 +0,0 @@ -package nl - -import ( - "unsafe" -) - -const ( - DEFAULT_CHANGE = 0xFFFFFFFF -) - -const ( - IFLA_INFO_UNSPEC = iota - IFLA_INFO_KIND - IFLA_INFO_DATA - IFLA_INFO_XSTATS - IFLA_INFO_SLAVE_KIND - IFLA_INFO_SLAVE_DATA - IFLA_INFO_MAX = IFLA_INFO_SLAVE_DATA -) - -const ( - IFLA_VLAN_UNSPEC = iota - IFLA_VLAN_ID - IFLA_VLAN_FLAGS - IFLA_VLAN_EGRESS_QOS - IFLA_VLAN_INGRESS_QOS - IFLA_VLAN_PROTOCOL - IFLA_VLAN_MAX = IFLA_VLAN_PROTOCOL -) - -const ( - VETH_INFO_UNSPEC = iota - VETH_INFO_PEER - VETH_INFO_MAX = VETH_INFO_PEER -) - -const ( - IFLA_VXLAN_UNSPEC = iota - IFLA_VXLAN_ID - IFLA_VXLAN_GROUP - IFLA_VXLAN_LINK - IFLA_VXLAN_LOCAL - IFLA_VXLAN_TTL - IFLA_VXLAN_TOS - IFLA_VXLAN_LEARNING - IFLA_VXLAN_AGEING - IFLA_VXLAN_LIMIT - IFLA_VXLAN_PORT_RANGE - IFLA_VXLAN_PROXY - IFLA_VXLAN_RSC - IFLA_VXLAN_L2MISS - IFLA_VXLAN_L3MISS - IFLA_VXLAN_PORT - IFLA_VXLAN_GROUP6 - IFLA_VXLAN_LOCAL6 - IFLA_VXLAN_UDP_CSUM - IFLA_VXLAN_UDP_ZERO_CSUM6_TX - IFLA_VXLAN_UDP_ZERO_CSUM6_RX - IFLA_VXLAN_REMCSUM_TX - IFLA_VXLAN_REMCSUM_RX - IFLA_VXLAN_GBP - IFLA_VXLAN_REMCSUM_NOPARTIAL - IFLA_VXLAN_FLOWBASED - IFLA_VXLAN_MAX = IFLA_VXLAN_FLOWBASED -) - -const ( - BRIDGE_MODE_UNSPEC = iota - BRIDGE_MODE_HAIRPIN -) - -const ( - IFLA_BRPORT_UNSPEC = iota - IFLA_BRPORT_STATE - IFLA_BRPORT_PRIORITY - IFLA_BRPORT_COST - IFLA_BRPORT_MODE - IFLA_BRPORT_GUARD - IFLA_BRPORT_PROTECT - IFLA_BRPORT_FAST_LEAVE - IFLA_BRPORT_LEARNING - IFLA_BRPORT_UNICAST_FLOOD - IFLA_BRPORT_PROXYARP - IFLA_BRPORT_LEARNING_SYNC - IFLA_BRPORT_PROXYARP_WIFI - IFLA_BRPORT_MAX = IFLA_BRPORT_PROXYARP_WIFI -) - -const ( - IFLA_IPVLAN_UNSPEC = iota - IFLA_IPVLAN_MODE - IFLA_IPVLAN_FLAG - IFLA_IPVLAN_MAX = IFLA_IPVLAN_FLAG -) - -const ( - IFLA_MACVLAN_UNSPEC = iota - IFLA_MACVLAN_MODE - IFLA_MACVLAN_FLAGS - IFLA_MACVLAN_MACADDR_MODE - IFLA_MACVLAN_MACADDR - IFLA_MACVLAN_MACADDR_DATA - IFLA_MACVLAN_MACADDR_COUNT - IFLA_MACVLAN_MAX = IFLA_MACVLAN_FLAGS -) - -const ( - MACVLAN_MODE_PRIVATE = 1 - MACVLAN_MODE_VEPA = 2 - MACVLAN_MODE_BRIDGE = 4 - MACVLAN_MODE_PASSTHRU = 8 - MACVLAN_MODE_SOURCE = 16 -) - -const ( - MACVLAN_MACADDR_ADD = iota - MACVLAN_MACADDR_DEL - MACVLAN_MACADDR_FLUSH - MACVLAN_MACADDR_SET -) - -const ( - IFLA_BOND_UNSPEC = iota - IFLA_BOND_MODE - IFLA_BOND_ACTIVE_SLAVE - IFLA_BOND_MIIMON - IFLA_BOND_UPDELAY - IFLA_BOND_DOWNDELAY - IFLA_BOND_USE_CARRIER - IFLA_BOND_ARP_INTERVAL - IFLA_BOND_ARP_IP_TARGET - IFLA_BOND_ARP_VALIDATE - IFLA_BOND_ARP_ALL_TARGETS - IFLA_BOND_PRIMARY - IFLA_BOND_PRIMARY_RESELECT - IFLA_BOND_FAIL_OVER_MAC - IFLA_BOND_XMIT_HASH_POLICY - IFLA_BOND_RESEND_IGMP - IFLA_BOND_NUM_PEER_NOTIF - IFLA_BOND_ALL_SLAVES_ACTIVE - IFLA_BOND_MIN_LINKS - IFLA_BOND_LP_INTERVAL - IFLA_BOND_PACKETS_PER_SLAVE - IFLA_BOND_AD_LACP_RATE - IFLA_BOND_AD_SELECT - IFLA_BOND_AD_INFO - IFLA_BOND_AD_ACTOR_SYS_PRIO - IFLA_BOND_AD_USER_PORT_KEY - IFLA_BOND_AD_ACTOR_SYSTEM - IFLA_BOND_TLB_DYNAMIC_LB -) - -const ( - IFLA_BOND_AD_INFO_UNSPEC = iota - IFLA_BOND_AD_INFO_AGGREGATOR - IFLA_BOND_AD_INFO_NUM_PORTS - IFLA_BOND_AD_INFO_ACTOR_KEY - IFLA_BOND_AD_INFO_PARTNER_KEY - IFLA_BOND_AD_INFO_PARTNER_MAC -) - -const ( - IFLA_BOND_SLAVE_UNSPEC = iota - IFLA_BOND_SLAVE_STATE - IFLA_BOND_SLAVE_MII_STATUS - IFLA_BOND_SLAVE_LINK_FAILURE_COUNT - IFLA_BOND_SLAVE_PERM_HWADDR - IFLA_BOND_SLAVE_QUEUE_ID - IFLA_BOND_SLAVE_AD_AGGREGATOR_ID - IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE - IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE -) - -const ( - IFLA_GRE_UNSPEC = iota - IFLA_GRE_LINK - IFLA_GRE_IFLAGS - IFLA_GRE_OFLAGS - IFLA_GRE_IKEY - IFLA_GRE_OKEY - IFLA_GRE_LOCAL - IFLA_GRE_REMOTE - IFLA_GRE_TTL - IFLA_GRE_TOS - IFLA_GRE_PMTUDISC - IFLA_GRE_ENCAP_LIMIT - IFLA_GRE_FLOWINFO - IFLA_GRE_FLAGS - IFLA_GRE_ENCAP_TYPE - IFLA_GRE_ENCAP_FLAGS - IFLA_GRE_ENCAP_SPORT - IFLA_GRE_ENCAP_DPORT - IFLA_GRE_COLLECT_METADATA - IFLA_GRE_MAX = IFLA_GRE_COLLECT_METADATA -) - -const ( - GRE_CSUM = 0x8000 - GRE_ROUTING = 0x4000 - GRE_KEY = 0x2000 - GRE_SEQ = 0x1000 - GRE_STRICT = 0x0800 - GRE_REC = 0x0700 - GRE_FLAGS = 0x00F8 - GRE_VERSION = 0x0007 -) - -const ( - IFLA_VF_INFO_UNSPEC = iota - IFLA_VF_INFO - IFLA_VF_INFO_MAX = IFLA_VF_INFO -) - -const ( - IFLA_VF_UNSPEC = iota - IFLA_VF_MAC /* Hardware queue specific attributes */ - IFLA_VF_VLAN - IFLA_VF_TX_RATE /* Max TX Bandwidth Allocation */ - IFLA_VF_SPOOFCHK /* Spoof Checking on/off switch */ - IFLA_VF_LINK_STATE /* link state enable/disable/auto switch */ - IFLA_VF_RATE /* Min and Max TX Bandwidth Allocation */ - IFLA_VF_RSS_QUERY_EN /* RSS Redirection Table and Hash Key query - * on/off switch - */ - IFLA_VF_STATS /* network device statistics */ - IFLA_VF_TRUST /* Trust state of VF */ - IFLA_VF_IB_NODE_GUID /* VF Infiniband node GUID */ - IFLA_VF_IB_PORT_GUID /* VF Infiniband port GUID */ - IFLA_VF_MAX = IFLA_VF_IB_PORT_GUID -) - -const ( - IFLA_VF_LINK_STATE_AUTO = iota /* link state of the uplink */ - IFLA_VF_LINK_STATE_ENABLE /* link always up */ - IFLA_VF_LINK_STATE_DISABLE /* link always down */ - IFLA_VF_LINK_STATE_MAX = IFLA_VF_LINK_STATE_DISABLE -) - -const ( - IFLA_VF_STATS_RX_PACKETS = iota - IFLA_VF_STATS_TX_PACKETS - IFLA_VF_STATS_RX_BYTES - IFLA_VF_STATS_TX_BYTES - IFLA_VF_STATS_BROADCAST - IFLA_VF_STATS_MULTICAST - IFLA_VF_STATS_MAX = IFLA_VF_STATS_MULTICAST -) - -const ( - SizeofVfMac = 0x24 - SizeofVfVlan = 0x0c - SizeofVfTxRate = 0x08 - SizeofVfRate = 0x0c - SizeofVfSpoofchk = 0x08 - SizeofVfLinkState = 0x08 - SizeofVfRssQueryEn = 0x08 - SizeofVfTrust = 0x08 - SizeofVfGUID = 0x10 -) - -// struct ifla_vf_mac { -// __u32 vf; -// __u8 mac[32]; /* MAX_ADDR_LEN */ -// }; - -type VfMac struct { - Vf uint32 - Mac [32]byte -} - -func (msg *VfMac) Len() int { - return SizeofVfMac -} - -func DeserializeVfMac(b []byte) *VfMac { - return (*VfMac)(unsafe.Pointer(&b[0:SizeofVfMac][0])) -} - -func (msg *VfMac) Serialize() []byte { - return (*(*[SizeofVfMac]byte)(unsafe.Pointer(msg)))[:] -} - -// struct ifla_vf_vlan { -// __u32 vf; -// __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */ -// __u32 qos; -// }; - -type VfVlan struct { - Vf uint32 - Vlan uint32 - Qos uint32 -} - -func (msg *VfVlan) Len() int { - return SizeofVfVlan -} - -func DeserializeVfVlan(b []byte) *VfVlan { - return (*VfVlan)(unsafe.Pointer(&b[0:SizeofVfVlan][0])) -} - -func (msg *VfVlan) Serialize() []byte { - return (*(*[SizeofVfVlan]byte)(unsafe.Pointer(msg)))[:] -} - -// struct ifla_vf_tx_rate { -// __u32 vf; -// __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */ -// }; - -type VfTxRate struct { - Vf uint32 - Rate uint32 -} - -func (msg *VfTxRate) Len() int { - return SizeofVfTxRate -} - -func DeserializeVfTxRate(b []byte) *VfTxRate { - return (*VfTxRate)(unsafe.Pointer(&b[0:SizeofVfTxRate][0])) -} - -func (msg *VfTxRate) Serialize() []byte { - return (*(*[SizeofVfTxRate]byte)(unsafe.Pointer(msg)))[:] -} - -// struct ifla_vf_rate { -// __u32 vf; -// __u32 min_tx_rate; /* Min Bandwidth in Mbps */ -// __u32 max_tx_rate; /* Max Bandwidth in Mbps */ -// }; - -type VfRate struct { - Vf uint32 - MinTxRate uint32 - MaxTxRate uint32 -} - -func (msg *VfRate) Len() int { - return SizeofVfRate -} - -func DeserializeVfRate(b []byte) *VfRate { - return (*VfRate)(unsafe.Pointer(&b[0:SizeofVfRate][0])) -} - -func (msg *VfRate) Serialize() []byte { - return (*(*[SizeofVfRate]byte)(unsafe.Pointer(msg)))[:] -} - -// struct ifla_vf_spoofchk { -// __u32 vf; -// __u32 setting; -// }; - -type VfSpoofchk struct { - Vf uint32 - Setting uint32 -} - -func (msg *VfSpoofchk) Len() int { - return SizeofVfSpoofchk -} - -func DeserializeVfSpoofchk(b []byte) *VfSpoofchk { - return (*VfSpoofchk)(unsafe.Pointer(&b[0:SizeofVfSpoofchk][0])) -} - -func (msg *VfSpoofchk) Serialize() []byte { - return (*(*[SizeofVfSpoofchk]byte)(unsafe.Pointer(msg)))[:] -} - -// struct ifla_vf_link_state { -// __u32 vf; -// __u32 link_state; -// }; - -type VfLinkState struct { - Vf uint32 - LinkState uint32 -} - -func (msg *VfLinkState) Len() int { - return SizeofVfLinkState -} - -func DeserializeVfLinkState(b []byte) *VfLinkState { - return (*VfLinkState)(unsafe.Pointer(&b[0:SizeofVfLinkState][0])) -} - -func (msg *VfLinkState) Serialize() []byte { - return (*(*[SizeofVfLinkState]byte)(unsafe.Pointer(msg)))[:] -} - -// struct ifla_vf_rss_query_en { -// __u32 vf; -// __u32 setting; -// }; - -type VfRssQueryEn struct { - Vf uint32 - Setting uint32 -} - -func (msg *VfRssQueryEn) Len() int { - return SizeofVfRssQueryEn -} - -func DeserializeVfRssQueryEn(b []byte) *VfRssQueryEn { - return (*VfRssQueryEn)(unsafe.Pointer(&b[0:SizeofVfRssQueryEn][0])) -} - -func (msg *VfRssQueryEn) Serialize() []byte { - return (*(*[SizeofVfRssQueryEn]byte)(unsafe.Pointer(msg)))[:] -} - -// struct ifla_vf_trust { -// __u32 vf; -// __u32 setting; -// }; - -type VfTrust struct { - Vf uint32 - Setting uint32 -} - -func (msg *VfTrust) Len() int { - return SizeofVfTrust -} - -func DeserializeVfTrust(b []byte) *VfTrust { - return (*VfTrust)(unsafe.Pointer(&b[0:SizeofVfTrust][0])) -} - -func (msg *VfTrust) Serialize() []byte { - return (*(*[SizeofVfTrust]byte)(unsafe.Pointer(msg)))[:] -} - -// struct ifla_vf_guid { -// __u32 vf; -// __u32 rsvd; -// __u64 guid; -// }; - -type VfGUID struct { - Vf uint32 - Rsvd uint32 - GUID uint64 -} - -func (msg *VfGUID) Len() int { - return SizeofVfGUID -} - -func DeserializeVfGUID(b []byte) *VfGUID { - return (*VfGUID)(unsafe.Pointer(&b[0:SizeofVfGUID][0])) -} - -func (msg *VfGUID) Serialize() []byte { - return (*(*[SizeofVfGUID]byte)(unsafe.Pointer(msg)))[:] -} - -const ( - XDP_FLAGS_UPDATE_IF_NOEXIST = 1 << iota - XDP_FLAGS_SKB_MODE - XDP_FLAGS_DRV_MODE - XDP_FLAGS_MASK = XDP_FLAGS_UPDATE_IF_NOEXIST | XDP_FLAGS_SKB_MODE | XDP_FLAGS_DRV_MODE -) - -const ( - IFLA_XDP_UNSPEC = iota - IFLA_XDP_FD /* fd of xdp program to attach, or -1 to remove */ - IFLA_XDP_ATTACHED /* read-only bool indicating if prog is attached */ - IFLA_XDP_FLAGS /* xdp prog related flags */ - IFLA_XDP_PROG_ID /* xdp prog id */ - IFLA_XDP_MAX = IFLA_XDP_PROG_ID -) - -const ( - IFLA_IPTUN_UNSPEC = iota - IFLA_IPTUN_LINK - IFLA_IPTUN_LOCAL - IFLA_IPTUN_REMOTE - IFLA_IPTUN_TTL - IFLA_IPTUN_TOS - IFLA_IPTUN_ENCAP_LIMIT - IFLA_IPTUN_FLOWINFO - IFLA_IPTUN_FLAGS - IFLA_IPTUN_PROTO - IFLA_IPTUN_PMTUDISC - IFLA_IPTUN_6RD_PREFIX - IFLA_IPTUN_6RD_RELAY_PREFIX - IFLA_IPTUN_6RD_PREFIXLEN - IFLA_IPTUN_6RD_RELAY_PREFIXLEN - IFLA_IPTUN_ENCAP_TYPE - IFLA_IPTUN_ENCAP_FLAGS - IFLA_IPTUN_ENCAP_SPORT - IFLA_IPTUN_ENCAP_DPORT - IFLA_IPTUN_COLLECT_METADATA - IFLA_IPTUN_MAX = IFLA_IPTUN_COLLECT_METADATA -) - -const ( - IFLA_VTI_UNSPEC = iota - IFLA_VTI_LINK - IFLA_VTI_IKEY - IFLA_VTI_OKEY - IFLA_VTI_LOCAL - IFLA_VTI_REMOTE - IFLA_VTI_MAX = IFLA_VTI_REMOTE -) - -const ( - IFLA_VRF_UNSPEC = iota - IFLA_VRF_TABLE -) - -const ( - IFLA_BR_UNSPEC = iota - IFLA_BR_FORWARD_DELAY - IFLA_BR_HELLO_TIME - IFLA_BR_MAX_AGE - IFLA_BR_AGEING_TIME - IFLA_BR_STP_STATE - IFLA_BR_PRIORITY - IFLA_BR_VLAN_FILTERING - IFLA_BR_VLAN_PROTOCOL - IFLA_BR_GROUP_FWD_MASK - IFLA_BR_ROOT_ID - IFLA_BR_BRIDGE_ID - IFLA_BR_ROOT_PORT - IFLA_BR_ROOT_PATH_COST - IFLA_BR_TOPOLOGY_CHANGE - IFLA_BR_TOPOLOGY_CHANGE_DETECTED - IFLA_BR_HELLO_TIMER - IFLA_BR_TCN_TIMER - IFLA_BR_TOPOLOGY_CHANGE_TIMER - IFLA_BR_GC_TIMER - IFLA_BR_GROUP_ADDR - IFLA_BR_FDB_FLUSH - IFLA_BR_MCAST_ROUTER - IFLA_BR_MCAST_SNOOPING - IFLA_BR_MCAST_QUERY_USE_IFADDR - IFLA_BR_MCAST_QUERIER - IFLA_BR_MCAST_HASH_ELASTICITY - IFLA_BR_MCAST_HASH_MAX - IFLA_BR_MCAST_LAST_MEMBER_CNT - IFLA_BR_MCAST_STARTUP_QUERY_CNT - IFLA_BR_MCAST_LAST_MEMBER_INTVL - IFLA_BR_MCAST_MEMBERSHIP_INTVL - IFLA_BR_MCAST_QUERIER_INTVL - IFLA_BR_MCAST_QUERY_INTVL - IFLA_BR_MCAST_QUERY_RESPONSE_INTVL - IFLA_BR_MCAST_STARTUP_QUERY_INTVL - IFLA_BR_NF_CALL_IPTABLES - IFLA_BR_NF_CALL_IP6TABLES - IFLA_BR_NF_CALL_ARPTABLES - IFLA_BR_VLAN_DEFAULT_PVID - IFLA_BR_PAD - IFLA_BR_VLAN_STATS_ENABLED - IFLA_BR_MCAST_STATS_ENABLED - IFLA_BR_MCAST_IGMP_VERSION - IFLA_BR_MCAST_MLD_VERSION - IFLA_BR_MAX = IFLA_BR_MCAST_MLD_VERSION -) - -const ( - IFLA_GTP_UNSPEC = iota - IFLA_GTP_FD0 - IFLA_GTP_FD1 - IFLA_GTP_PDP_HASHSIZE - IFLA_GTP_ROLE -) - -const ( - GTP_ROLE_GGSN = iota - GTP_ROLE_SGSN -) - -const ( - IFLA_XFRM_UNSPEC = iota - IFLA_XFRM_LINK - IFLA_XFRM_IF_ID - - IFLA_XFRM_MAX = iota - 1 -) - -const ( - IFLA_TUN_UNSPEC = iota - IFLA_TUN_OWNER - IFLA_TUN_GROUP - IFLA_TUN_TYPE - IFLA_TUN_PI - IFLA_TUN_VNET_HDR - IFLA_TUN_PERSIST - IFLA_TUN_MULTI_QUEUE - IFLA_TUN_NUM_QUEUES - IFLA_TUN_NUM_DISABLED_QUEUES - IFLA_TUN_MAX = IFLA_TUN_NUM_DISABLED_QUEUES -) - -const ( - IFLA_IPOIB_UNSPEC = iota - IFLA_IPOIB_PKEY - IFLA_IPOIB_MODE - IFLA_IPOIB_UMCAST - IFLA_IPOIB_MAX = IFLA_IPOIB_UMCAST -) diff --git a/vendor/github.com/vishvananda/netlink/nl/mpls_linux.go b/vendor/github.com/vishvananda/netlink/nl/mpls_linux.go deleted file mode 100644 index 3915b7eec..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/mpls_linux.go +++ /dev/null @@ -1,36 +0,0 @@ -package nl - -import "encoding/binary" - -const ( - MPLS_LS_LABEL_SHIFT = 12 - MPLS_LS_S_SHIFT = 8 -) - -func EncodeMPLSStack(labels ...int) []byte { - b := make([]byte, 4*len(labels)) - for idx, label := range labels { - l := label << MPLS_LS_LABEL_SHIFT - if idx == len(labels)-1 { - l |= 1 << MPLS_LS_S_SHIFT - } - binary.BigEndian.PutUint32(b[idx*4:], uint32(l)) - } - return b -} - -func DecodeMPLSStack(buf []byte) []int { - if len(buf)%4 != 0 { - return nil - } - stack := make([]int, 0, len(buf)/4) - for len(buf) > 0 { - l := binary.BigEndian.Uint32(buf[:4]) - buf = buf[4:] - stack = append(stack, int(l)>>MPLS_LS_LABEL_SHIFT) - if (l>>MPLS_LS_S_SHIFT)&1 > 0 { - break - } - } - return stack -} diff --git a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go deleted file mode 100644 index aaf56c671..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go +++ /dev/null @@ -1,760 +0,0 @@ -// Package nl has low level primitives for making Netlink calls. -package nl - -import ( - "bytes" - "encoding/binary" - "fmt" - "net" - "runtime" - "sync" - "sync/atomic" - "syscall" - "unsafe" - - "github.com/vishvananda/netns" - "golang.org/x/sys/unix" -) - -const ( - // Family type definitions - FAMILY_ALL = unix.AF_UNSPEC - FAMILY_V4 = unix.AF_INET - FAMILY_V6 = unix.AF_INET6 - FAMILY_MPLS = unix.AF_MPLS - // Arbitrary set value (greater than default 4k) to allow receiving - // from kernel more verbose messages e.g. for statistics, - // tc rules or filters, or other more memory requiring data. - RECEIVE_BUFFER_SIZE = 65536 - // Kernel netlink pid - PidKernel uint32 = 0 -) - -// SupportedNlFamilies contains the list of netlink families this netlink package supports -var SupportedNlFamilies = []int{unix.NETLINK_ROUTE, unix.NETLINK_XFRM, unix.NETLINK_NETFILTER} - -var nextSeqNr uint32 - -// GetIPFamily returns the family type of a net.IP. -func GetIPFamily(ip net.IP) int { - if len(ip) <= net.IPv4len { - return FAMILY_V4 - } - if ip.To4() != nil { - return FAMILY_V4 - } - return FAMILY_V6 -} - -var nativeEndian binary.ByteOrder - -// NativeEndian gets native endianness for the system -func NativeEndian() binary.ByteOrder { - if nativeEndian == nil { - var x uint32 = 0x01020304 - if *(*byte)(unsafe.Pointer(&x)) == 0x01 { - nativeEndian = binary.BigEndian - } else { - nativeEndian = binary.LittleEndian - } - } - return nativeEndian -} - -// Byte swap a 16 bit value if we aren't big endian -func Swap16(i uint16) uint16 { - if NativeEndian() == binary.BigEndian { - return i - } - return (i&0xff00)>>8 | (i&0xff)<<8 -} - -// Byte swap a 32 bit value if aren't big endian -func Swap32(i uint32) uint32 { - if NativeEndian() == binary.BigEndian { - return i - } - return (i&0xff000000)>>24 | (i&0xff0000)>>8 | (i&0xff00)<<8 | (i&0xff)<<24 -} - -type NetlinkRequestData interface { - Len() int - Serialize() []byte -} - -// IfInfomsg is related to links, but it is used for list requests as well -type IfInfomsg struct { - unix.IfInfomsg -} - -// Create an IfInfomsg with family specified -func NewIfInfomsg(family int) *IfInfomsg { - return &IfInfomsg{ - IfInfomsg: unix.IfInfomsg{ - Family: uint8(family), - }, - } -} - -func DeserializeIfInfomsg(b []byte) *IfInfomsg { - return (*IfInfomsg)(unsafe.Pointer(&b[0:unix.SizeofIfInfomsg][0])) -} - -func (msg *IfInfomsg) Serialize() []byte { - return (*(*[unix.SizeofIfInfomsg]byte)(unsafe.Pointer(msg)))[:] -} - -func (msg *IfInfomsg) Len() int { - return unix.SizeofIfInfomsg -} - -func (msg *IfInfomsg) EncapType() string { - switch msg.Type { - case 0: - return "generic" - case unix.ARPHRD_ETHER: - return "ether" - case unix.ARPHRD_EETHER: - return "eether" - case unix.ARPHRD_AX25: - return "ax25" - case unix.ARPHRD_PRONET: - return "pronet" - case unix.ARPHRD_CHAOS: - return "chaos" - case unix.ARPHRD_IEEE802: - return "ieee802" - case unix.ARPHRD_ARCNET: - return "arcnet" - case unix.ARPHRD_APPLETLK: - return "atalk" - case unix.ARPHRD_DLCI: - return "dlci" - case unix.ARPHRD_ATM: - return "atm" - case unix.ARPHRD_METRICOM: - return "metricom" - case unix.ARPHRD_IEEE1394: - return "ieee1394" - case unix.ARPHRD_INFINIBAND: - return "infiniband" - case unix.ARPHRD_SLIP: - return "slip" - case unix.ARPHRD_CSLIP: - return "cslip" - case unix.ARPHRD_SLIP6: - return "slip6" - case unix.ARPHRD_CSLIP6: - return "cslip6" - case unix.ARPHRD_RSRVD: - return "rsrvd" - case unix.ARPHRD_ADAPT: - return "adapt" - case unix.ARPHRD_ROSE: - return "rose" - case unix.ARPHRD_X25: - return "x25" - case unix.ARPHRD_HWX25: - return "hwx25" - case unix.ARPHRD_PPP: - return "ppp" - case unix.ARPHRD_HDLC: - return "hdlc" - case unix.ARPHRD_LAPB: - return "lapb" - case unix.ARPHRD_DDCMP: - return "ddcmp" - case unix.ARPHRD_RAWHDLC: - return "rawhdlc" - case unix.ARPHRD_TUNNEL: - return "ipip" - case unix.ARPHRD_TUNNEL6: - return "tunnel6" - case unix.ARPHRD_FRAD: - return "frad" - case unix.ARPHRD_SKIP: - return "skip" - case unix.ARPHRD_LOOPBACK: - return "loopback" - case unix.ARPHRD_LOCALTLK: - return "ltalk" - case unix.ARPHRD_FDDI: - return "fddi" - case unix.ARPHRD_BIF: - return "bif" - case unix.ARPHRD_SIT: - return "sit" - case unix.ARPHRD_IPDDP: - return "ip/ddp" - case unix.ARPHRD_IPGRE: - return "gre" - case unix.ARPHRD_PIMREG: - return "pimreg" - case unix.ARPHRD_HIPPI: - return "hippi" - case unix.ARPHRD_ASH: - return "ash" - case unix.ARPHRD_ECONET: - return "econet" - case unix.ARPHRD_IRDA: - return "irda" - case unix.ARPHRD_FCPP: - return "fcpp" - case unix.ARPHRD_FCAL: - return "fcal" - case unix.ARPHRD_FCPL: - return "fcpl" - case unix.ARPHRD_FCFABRIC: - return "fcfb0" - case unix.ARPHRD_FCFABRIC + 1: - return "fcfb1" - case unix.ARPHRD_FCFABRIC + 2: - return "fcfb2" - case unix.ARPHRD_FCFABRIC + 3: - return "fcfb3" - case unix.ARPHRD_FCFABRIC + 4: - return "fcfb4" - case unix.ARPHRD_FCFABRIC + 5: - return "fcfb5" - case unix.ARPHRD_FCFABRIC + 6: - return "fcfb6" - case unix.ARPHRD_FCFABRIC + 7: - return "fcfb7" - case unix.ARPHRD_FCFABRIC + 8: - return "fcfb8" - case unix.ARPHRD_FCFABRIC + 9: - return "fcfb9" - case unix.ARPHRD_FCFABRIC + 10: - return "fcfb10" - case unix.ARPHRD_FCFABRIC + 11: - return "fcfb11" - case unix.ARPHRD_FCFABRIC + 12: - return "fcfb12" - case unix.ARPHRD_IEEE802_TR: - return "tr" - case unix.ARPHRD_IEEE80211: - return "ieee802.11" - case unix.ARPHRD_IEEE80211_PRISM: - return "ieee802.11/prism" - case unix.ARPHRD_IEEE80211_RADIOTAP: - return "ieee802.11/radiotap" - case unix.ARPHRD_IEEE802154: - return "ieee802.15.4" - - case 65534: - return "none" - case 65535: - return "void" - } - return fmt.Sprintf("unknown%d", msg.Type) -} - -func rtaAlignOf(attrlen int) int { - return (attrlen + unix.RTA_ALIGNTO - 1) & ^(unix.RTA_ALIGNTO - 1) -} - -func NewIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg { - msg := NewIfInfomsg(family) - parent.children = append(parent.children, msg) - return msg -} - -// Extend RtAttr to handle data and children -type RtAttr struct { - unix.RtAttr - Data []byte - children []NetlinkRequestData -} - -// Create a new Extended RtAttr object -func NewRtAttr(attrType int, data []byte) *RtAttr { - return &RtAttr{ - RtAttr: unix.RtAttr{ - Type: uint16(attrType), - }, - children: []NetlinkRequestData{}, - Data: data, - } -} - -// NewRtAttrChild adds an RtAttr as a child to the parent and returns the new attribute -// -// Deprecated: Use AddRtAttr() on the parent object -func NewRtAttrChild(parent *RtAttr, attrType int, data []byte) *RtAttr { - return parent.AddRtAttr(attrType, data) -} - -// AddRtAttr adds an RtAttr as a child and returns the new attribute -func (a *RtAttr) AddRtAttr(attrType int, data []byte) *RtAttr { - attr := NewRtAttr(attrType, data) - a.children = append(a.children, attr) - return attr -} - -// AddChild adds an existing NetlinkRequestData as a child. -func (a *RtAttr) AddChild(attr NetlinkRequestData) { - a.children = append(a.children, attr) -} - -func (a *RtAttr) Len() int { - if len(a.children) == 0 { - return (unix.SizeofRtAttr + len(a.Data)) - } - - l := 0 - for _, child := range a.children { - l += rtaAlignOf(child.Len()) - } - l += unix.SizeofRtAttr - return rtaAlignOf(l + len(a.Data)) -} - -// Serialize the RtAttr into a byte array -// This can't just unsafe.cast because it must iterate through children. -func (a *RtAttr) Serialize() []byte { - native := NativeEndian() - - length := a.Len() - buf := make([]byte, rtaAlignOf(length)) - - next := 4 - if a.Data != nil { - copy(buf[next:], a.Data) - next += rtaAlignOf(len(a.Data)) - } - if len(a.children) > 0 { - for _, child := range a.children { - childBuf := child.Serialize() - copy(buf[next:], childBuf) - next += rtaAlignOf(len(childBuf)) - } - } - - if l := uint16(length); l != 0 { - native.PutUint16(buf[0:2], l) - } - native.PutUint16(buf[2:4], a.Type) - return buf -} - -type NetlinkRequest struct { - unix.NlMsghdr - Data []NetlinkRequestData - RawData []byte - Sockets map[int]*SocketHandle -} - -// Serialize the Netlink Request into a byte array -func (req *NetlinkRequest) Serialize() []byte { - length := unix.SizeofNlMsghdr - dataBytes := make([][]byte, len(req.Data)) - for i, data := range req.Data { - dataBytes[i] = data.Serialize() - length = length + len(dataBytes[i]) - } - length += len(req.RawData) - - req.Len = uint32(length) - b := make([]byte, length) - hdr := (*(*[unix.SizeofNlMsghdr]byte)(unsafe.Pointer(req)))[:] - next := unix.SizeofNlMsghdr - copy(b[0:next], hdr) - for _, data := range dataBytes { - for _, dataByte := range data { - b[next] = dataByte - next = next + 1 - } - } - // Add the raw data if any - if len(req.RawData) > 0 { - copy(b[next:length], req.RawData) - } - return b -} - -func (req *NetlinkRequest) AddData(data NetlinkRequestData) { - req.Data = append(req.Data, data) -} - -// AddRawData adds raw bytes to the end of the NetlinkRequest object during serialization -func (req *NetlinkRequest) AddRawData(data []byte) { - req.RawData = append(req.RawData, data...) -} - -// Execute the request against a the given sockType. -// Returns a list of netlink messages in serialized format, optionally filtered -// by resType. -func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, error) { - var ( - s *NetlinkSocket - err error - ) - - if req.Sockets != nil { - if sh, ok := req.Sockets[sockType]; ok { - s = sh.Socket - req.Seq = atomic.AddUint32(&sh.Seq, 1) - } - } - sharedSocket := s != nil - - if s == nil { - s, err = getNetlinkSocket(sockType) - if err != nil { - return nil, err - } - defer s.Close() - } else { - s.Lock() - defer s.Unlock() - } - - if err := s.Send(req); err != nil { - return nil, err - } - - pid, err := s.GetPid() - if err != nil { - return nil, err - } - - var res [][]byte - -done: - for { - msgs, from, err := s.Receive() - if err != nil { - return nil, err - } - if from.Pid != PidKernel { - return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, PidKernel) - } - for _, m := range msgs { - if m.Header.Seq != req.Seq { - if sharedSocket { - continue - } - return nil, fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq) - } - if m.Header.Pid != pid { - continue - } - if m.Header.Type == unix.NLMSG_DONE { - break done - } - if m.Header.Type == unix.NLMSG_ERROR { - native := NativeEndian() - error := int32(native.Uint32(m.Data[0:4])) - if error == 0 { - break done - } - return nil, syscall.Errno(-error) - } - if resType != 0 && m.Header.Type != resType { - continue - } - res = append(res, m.Data) - if m.Header.Flags&unix.NLM_F_MULTI == 0 { - break done - } - } - } - return res, nil -} - -// Create a new netlink request from proto and flags -// Note the Len value will be inaccurate once data is added until -// the message is serialized -func NewNetlinkRequest(proto, flags int) *NetlinkRequest { - return &NetlinkRequest{ - NlMsghdr: unix.NlMsghdr{ - Len: uint32(unix.SizeofNlMsghdr), - Type: uint16(proto), - Flags: unix.NLM_F_REQUEST | uint16(flags), - Seq: atomic.AddUint32(&nextSeqNr, 1), - }, - } -} - -type NetlinkSocket struct { - fd int32 - lsa unix.SockaddrNetlink - sync.Mutex -} - -func getNetlinkSocket(protocol int) (*NetlinkSocket, error) { - fd, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW|unix.SOCK_CLOEXEC, protocol) - if err != nil { - return nil, err - } - s := &NetlinkSocket{ - fd: int32(fd), - } - s.lsa.Family = unix.AF_NETLINK - if err := unix.Bind(fd, &s.lsa); err != nil { - unix.Close(fd) - return nil, err - } - - return s, nil -} - -// GetNetlinkSocketAt opens a netlink socket in the network namespace newNs -// and positions the thread back into the network namespace specified by curNs, -// when done. If curNs is close, the function derives the current namespace and -// moves back into it when done. If newNs is close, the socket will be opened -// in the current network namespace. -func GetNetlinkSocketAt(newNs, curNs netns.NsHandle, protocol int) (*NetlinkSocket, error) { - c, err := executeInNetns(newNs, curNs) - if err != nil { - return nil, err - } - defer c() - return getNetlinkSocket(protocol) -} - -// executeInNetns sets execution of the code following this call to the -// network namespace newNs, then moves the thread back to curNs if open, -// otherwise to the current netns at the time the function was invoked -// In case of success, the caller is expected to execute the returned function -// at the end of the code that needs to be executed in the network namespace. -// Example: -// func jobAt(...) error { -// d, err := executeInNetns(...) -// if err != nil { return err} -// defer d() -// < code which needs to be executed in specific netns> -// } -// TODO: his function probably belongs to netns pkg. -func executeInNetns(newNs, curNs netns.NsHandle) (func(), error) { - var ( - err error - moveBack func(netns.NsHandle) error - closeNs func() error - unlockThd func() - ) - restore := func() { - // order matters - if moveBack != nil { - moveBack(curNs) - } - if closeNs != nil { - closeNs() - } - if unlockThd != nil { - unlockThd() - } - } - if newNs.IsOpen() { - runtime.LockOSThread() - unlockThd = runtime.UnlockOSThread - if !curNs.IsOpen() { - if curNs, err = netns.Get(); err != nil { - restore() - return nil, fmt.Errorf("could not get current namespace while creating netlink socket: %v", err) - } - closeNs = curNs.Close - } - if err := netns.Set(newNs); err != nil { - restore() - return nil, fmt.Errorf("failed to set into network namespace %d while creating netlink socket: %v", newNs, err) - } - moveBack = netns.Set - } - return restore, nil -} - -// Create a netlink socket with a given protocol (e.g. NETLINK_ROUTE) -// and subscribe it to multicast groups passed in variable argument list. -// Returns the netlink socket on which Receive() method can be called -// to retrieve the messages from the kernel. -func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) { - fd, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW, protocol) - if err != nil { - return nil, err - } - s := &NetlinkSocket{ - fd: int32(fd), - } - s.lsa.Family = unix.AF_NETLINK - - for _, g := range groups { - s.lsa.Groups |= (1 << (g - 1)) - } - - if err := unix.Bind(fd, &s.lsa); err != nil { - unix.Close(fd) - return nil, err - } - - return s, nil -} - -// SubscribeAt works like Subscribe plus let's the caller choose the network -// namespace in which the socket would be opened (newNs). Then control goes back -// to curNs if open, otherwise to the netns at the time this function was called. -func SubscribeAt(newNs, curNs netns.NsHandle, protocol int, groups ...uint) (*NetlinkSocket, error) { - c, err := executeInNetns(newNs, curNs) - if err != nil { - return nil, err - } - defer c() - return Subscribe(protocol, groups...) -} - -func (s *NetlinkSocket) Close() { - fd := int(atomic.SwapInt32(&s.fd, -1)) - unix.Close(fd) -} - -func (s *NetlinkSocket) GetFd() int { - return int(atomic.LoadInt32(&s.fd)) -} - -func (s *NetlinkSocket) Send(request *NetlinkRequest) error { - fd := int(atomic.LoadInt32(&s.fd)) - if fd < 0 { - return fmt.Errorf("Send called on a closed socket") - } - if err := unix.Sendto(fd, request.Serialize(), 0, &s.lsa); err != nil { - return err - } - return nil -} - -func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, *unix.SockaddrNetlink, error) { - fd := int(atomic.LoadInt32(&s.fd)) - if fd < 0 { - return nil, nil, fmt.Errorf("Receive called on a closed socket") - } - var fromAddr *unix.SockaddrNetlink - var rb [RECEIVE_BUFFER_SIZE]byte - nr, from, err := unix.Recvfrom(fd, rb[:], 0) - if err != nil { - return nil, nil, err - } - fromAddr, ok := from.(*unix.SockaddrNetlink) - if !ok { - return nil, nil, fmt.Errorf("Error converting to netlink sockaddr") - } - if nr < unix.NLMSG_HDRLEN { - return nil, nil, fmt.Errorf("Got short response from netlink") - } - rb2 := make([]byte, nr) - copy(rb2, rb[:nr]) - nl, err := syscall.ParseNetlinkMessage(rb2) - if err != nil { - return nil, nil, err - } - return nl, fromAddr, nil -} - -// SetSendTimeout allows to set a send timeout on the socket -func (s *NetlinkSocket) SetSendTimeout(timeout *unix.Timeval) error { - // Set a send timeout of SOCKET_SEND_TIMEOUT, this will allow the Send to periodically unblock and avoid that a routine - // remains stuck on a send on a closed fd - return unix.SetsockoptTimeval(int(s.fd), unix.SOL_SOCKET, unix.SO_SNDTIMEO, timeout) -} - -// SetReceiveTimeout allows to set a receive timeout on the socket -func (s *NetlinkSocket) SetReceiveTimeout(timeout *unix.Timeval) error { - // Set a read timeout of SOCKET_READ_TIMEOUT, this will allow the Read to periodically unblock and avoid that a routine - // remains stuck on a recvmsg on a closed fd - return unix.SetsockoptTimeval(int(s.fd), unix.SOL_SOCKET, unix.SO_RCVTIMEO, timeout) -} - -func (s *NetlinkSocket) GetPid() (uint32, error) { - fd := int(atomic.LoadInt32(&s.fd)) - lsa, err := unix.Getsockname(fd) - if err != nil { - return 0, err - } - switch v := lsa.(type) { - case *unix.SockaddrNetlink: - return v.Pid, nil - } - return 0, fmt.Errorf("Wrong socket type") -} - -func ZeroTerminated(s string) []byte { - bytes := make([]byte, len(s)+1) - for i := 0; i < len(s); i++ { - bytes[i] = s[i] - } - bytes[len(s)] = 0 - return bytes -} - -func NonZeroTerminated(s string) []byte { - bytes := make([]byte, len(s)) - for i := 0; i < len(s); i++ { - bytes[i] = s[i] - } - return bytes -} - -func BytesToString(b []byte) string { - n := bytes.Index(b, []byte{0}) - return string(b[:n]) -} - -func Uint8Attr(v uint8) []byte { - return []byte{byte(v)} -} - -func Uint16Attr(v uint16) []byte { - native := NativeEndian() - bytes := make([]byte, 2) - native.PutUint16(bytes, v) - return bytes -} - -func Uint32Attr(v uint32) []byte { - native := NativeEndian() - bytes := make([]byte, 4) - native.PutUint32(bytes, v) - return bytes -} - -func Uint64Attr(v uint64) []byte { - native := NativeEndian() - bytes := make([]byte, 8) - native.PutUint64(bytes, v) - return bytes -} - -func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) { - var attrs []syscall.NetlinkRouteAttr - for len(b) >= unix.SizeofRtAttr { - a, vbuf, alen, err := netlinkRouteAttrAndValue(b) - if err != nil { - return nil, err - } - ra := syscall.NetlinkRouteAttr{Attr: syscall.RtAttr(*a), Value: vbuf[:int(a.Len)-unix.SizeofRtAttr]} - attrs = append(attrs, ra) - b = b[alen:] - } - return attrs, nil -} - -func netlinkRouteAttrAndValue(b []byte) (*unix.RtAttr, []byte, int, error) { - a := (*unix.RtAttr)(unsafe.Pointer(&b[0])) - if int(a.Len) < unix.SizeofRtAttr || int(a.Len) > len(b) { - return nil, nil, 0, unix.EINVAL - } - return a, b[unix.SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil -} - -// SocketHandle contains the netlink socket and the associated -// sequence counter for a specific netlink family -type SocketHandle struct { - Seq uint32 - Socket *NetlinkSocket -} - -// Close closes the netlink socket -func (sh *SocketHandle) Close() { - if sh.Socket != nil { - sh.Socket.Close() - } -} diff --git a/vendor/github.com/vishvananda/netlink/nl/nl_unspecified.go b/vendor/github.com/vishvananda/netlink/nl/nl_unspecified.go deleted file mode 100644 index dfc0be660..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/nl_unspecified.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build !linux - -package nl - -import "encoding/binary" - -var SupportedNlFamilies = []int{} - -func NativeEndian() binary.ByteOrder { - return nil -} diff --git a/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go b/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go deleted file mode 100644 index 1224b747d..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go +++ /dev/null @@ -1,35 +0,0 @@ -package nl - -const ( - RDMA_NL_GET_CLIENT_SHIFT = 10 -) - -const ( - RDMA_NL_NLDEV = 5 -) - -const ( - RDMA_NLDEV_CMD_GET = 1 - RDMA_NLDEV_CMD_SET = 2 - RDMA_NLDEV_CMD_SYS_GET = 6 - RDMA_NLDEV_CMD_SYS_SET = 7 -) - -const ( - RDMA_NLDEV_ATTR_DEV_INDEX = 1 - RDMA_NLDEV_ATTR_DEV_NAME = 2 - RDMA_NLDEV_ATTR_PORT_INDEX = 3 - RDMA_NLDEV_ATTR_CAP_FLAGS = 4 - RDMA_NLDEV_ATTR_FW_VERSION = 5 - RDMA_NLDEV_ATTR_NODE_GUID = 6 - RDMA_NLDEV_ATTR_SYS_IMAGE_GUID = 7 - RDMA_NLDEV_ATTR_SUBNET_PREFIX = 8 - RDMA_NLDEV_ATTR_LID = 9 - RDMA_NLDEV_ATTR_SM_LID = 10 - RDMA_NLDEV_ATTR_LMC = 11 - RDMA_NLDEV_ATTR_PORT_STATE = 12 - RDMA_NLDEV_ATTR_PORT_PHYS_STATE = 13 - RDMA_NLDEV_ATTR_DEV_NODE_TYPE = 14 - RDMA_NLDEV_SYS_ATTR_NETNS_MODE = 66 - RDMA_NLDEV_NET_NS_FD = 68 -) diff --git a/vendor/github.com/vishvananda/netlink/nl/route_linux.go b/vendor/github.com/vishvananda/netlink/nl/route_linux.go deleted file mode 100644 index 03c1900ff..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/route_linux.go +++ /dev/null @@ -1,107 +0,0 @@ -package nl - -import ( - "unsafe" - - "golang.org/x/sys/unix" -) - -type RtMsg struct { - unix.RtMsg -} - -func NewRtMsg() *RtMsg { - return &RtMsg{ - RtMsg: unix.RtMsg{ - Table: unix.RT_TABLE_MAIN, - Scope: unix.RT_SCOPE_UNIVERSE, - Protocol: unix.RTPROT_BOOT, - Type: unix.RTN_UNICAST, - }, - } -} - -func NewRtDelMsg() *RtMsg { - return &RtMsg{ - RtMsg: unix.RtMsg{ - Table: unix.RT_TABLE_MAIN, - Scope: unix.RT_SCOPE_NOWHERE, - }, - } -} - -func (msg *RtMsg) Len() int { - return unix.SizeofRtMsg -} - -func DeserializeRtMsg(b []byte) *RtMsg { - return (*RtMsg)(unsafe.Pointer(&b[0:unix.SizeofRtMsg][0])) -} - -func (msg *RtMsg) Serialize() []byte { - return (*(*[unix.SizeofRtMsg]byte)(unsafe.Pointer(msg)))[:] -} - -type RtNexthop struct { - unix.RtNexthop - Children []NetlinkRequestData -} - -func DeserializeRtNexthop(b []byte) *RtNexthop { - return (*RtNexthop)(unsafe.Pointer(&b[0:unix.SizeofRtNexthop][0])) -} - -func (msg *RtNexthop) Len() int { - if len(msg.Children) == 0 { - return unix.SizeofRtNexthop - } - - l := 0 - for _, child := range msg.Children { - l += rtaAlignOf(child.Len()) - } - l += unix.SizeofRtNexthop - return rtaAlignOf(l) -} - -func (msg *RtNexthop) Serialize() []byte { - length := msg.Len() - msg.RtNexthop.Len = uint16(length) - buf := make([]byte, length) - copy(buf, (*(*[unix.SizeofRtNexthop]byte)(unsafe.Pointer(msg)))[:]) - next := rtaAlignOf(unix.SizeofRtNexthop) - if len(msg.Children) > 0 { - for _, child := range msg.Children { - childBuf := child.Serialize() - copy(buf[next:], childBuf) - next += rtaAlignOf(len(childBuf)) - } - } - return buf -} - -type RtGenMsg struct { - unix.RtGenmsg -} - -func NewRtGenMsg() *RtGenMsg { - return &RtGenMsg{ - RtGenmsg: unix.RtGenmsg{ - Family: unix.AF_UNSPEC, - }, - } -} - -func (msg *RtGenMsg) Len() int { - return rtaAlignOf(unix.SizeofRtGenmsg) -} - -func DeserializeRtGenMsg(b []byte) *RtGenMsg { - return &RtGenMsg{RtGenmsg: unix.RtGenmsg{Family: b[0]}} -} - -func (msg *RtGenMsg) Serialize() []byte { - out := make([]byte, msg.Len()) - out[0] = msg.Family - return out -} diff --git a/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go b/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go deleted file mode 100644 index 5774cbb15..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go +++ /dev/null @@ -1,154 +0,0 @@ -package nl - -import ( - "errors" - "fmt" - "net" -) - -type IPv6SrHdr struct { - nextHdr uint8 - hdrLen uint8 - routingType uint8 - segmentsLeft uint8 - firstSegment uint8 - flags uint8 - reserved uint16 - - Segments []net.IP -} - -func (s1 *IPv6SrHdr) Equal(s2 IPv6SrHdr) bool { - if len(s1.Segments) != len(s2.Segments) { - return false - } - for i := range s1.Segments { - if s1.Segments[i].Equal(s2.Segments[i]) != true { - return false - } - } - return s1.nextHdr == s2.nextHdr && - s1.hdrLen == s2.hdrLen && - s1.routingType == s2.routingType && - s1.segmentsLeft == s2.segmentsLeft && - s1.firstSegment == s2.firstSegment && - s1.flags == s2.flags - // reserved doesn't need to be identical. -} - -// seg6 encap mode -const ( - SEG6_IPTUN_MODE_INLINE = iota - SEG6_IPTUN_MODE_ENCAP -) - -// number of nested RTATTR -// from include/uapi/linux/seg6_iptunnel.h -const ( - SEG6_IPTUNNEL_UNSPEC = iota - SEG6_IPTUNNEL_SRH - __SEG6_IPTUNNEL_MAX -) -const ( - SEG6_IPTUNNEL_MAX = __SEG6_IPTUNNEL_MAX - 1 -) - -func EncodeSEG6Encap(mode int, segments []net.IP) ([]byte, error) { - nsegs := len(segments) // nsegs: number of segments - if nsegs == 0 { - return nil, errors.New("EncodeSEG6Encap: No Segment in srh") - } - b := make([]byte, 12, 12+len(segments)*16) - native := NativeEndian() - native.PutUint32(b, uint32(mode)) - b[4] = 0 // srh.nextHdr (0 when calling netlink) - b[5] = uint8(16 * nsegs >> 3) // srh.hdrLen (in 8-octets unit) - b[6] = IPV6_SRCRT_TYPE_4 // srh.routingType (assigned by IANA) - b[7] = uint8(nsegs - 1) // srh.segmentsLeft - b[8] = uint8(nsegs - 1) // srh.firstSegment - b[9] = 0 // srh.flags (SR6_FLAG1_HMAC for srh_hmac) - // srh.reserved: Defined as "Tag" in draft-ietf-6man-segment-routing-header-07 - native.PutUint16(b[10:], 0) // srh.reserved - for _, netIP := range segments { - b = append(b, netIP...) // srh.Segments - } - return b, nil -} - -func DecodeSEG6Encap(buf []byte) (int, []net.IP, error) { - native := NativeEndian() - mode := int(native.Uint32(buf)) - srh := IPv6SrHdr{ - nextHdr: buf[4], - hdrLen: buf[5], - routingType: buf[6], - segmentsLeft: buf[7], - firstSegment: buf[8], - flags: buf[9], - reserved: native.Uint16(buf[10:12]), - } - buf = buf[12:] - if len(buf)%16 != 0 { - err := fmt.Errorf("DecodeSEG6Encap: error parsing Segment List (buf len: %d)\n", len(buf)) - return mode, nil, err - } - for len(buf) > 0 { - srh.Segments = append(srh.Segments, net.IP(buf[:16])) - buf = buf[16:] - } - return mode, srh.Segments, nil -} - -func DecodeSEG6Srh(buf []byte) ([]net.IP, error) { - native := NativeEndian() - srh := IPv6SrHdr{ - nextHdr: buf[0], - hdrLen: buf[1], - routingType: buf[2], - segmentsLeft: buf[3], - firstSegment: buf[4], - flags: buf[5], - reserved: native.Uint16(buf[6:8]), - } - buf = buf[8:] - if len(buf)%16 != 0 { - err := fmt.Errorf("DecodeSEG6Srh: error parsing Segment List (buf len: %d)", len(buf)) - return nil, err - } - for len(buf) > 0 { - srh.Segments = append(srh.Segments, net.IP(buf[:16])) - buf = buf[16:] - } - return srh.Segments, nil -} -func EncodeSEG6Srh(segments []net.IP) ([]byte, error) { - nsegs := len(segments) // nsegs: number of segments - if nsegs == 0 { - return nil, errors.New("EncodeSEG6Srh: No Segments") - } - b := make([]byte, 8, 8+len(segments)*16) - native := NativeEndian() - b[0] = 0 // srh.nextHdr (0 when calling netlink) - b[1] = uint8(16 * nsegs >> 3) // srh.hdrLen (in 8-octets unit) - b[2] = IPV6_SRCRT_TYPE_4 // srh.routingType (assigned by IANA) - b[3] = uint8(nsegs - 1) // srh.segmentsLeft - b[4] = uint8(nsegs - 1) // srh.firstSegment - b[5] = 0 // srh.flags (SR6_FLAG1_HMAC for srh_hmac) - // srh.reserved: Defined as "Tag" in draft-ietf-6man-segment-routing-header-07 - native.PutUint16(b[6:], 0) // srh.reserved - for _, netIP := range segments { - b = append(b, netIP...) // srh.Segments - } - return b, nil -} - -// Helper functions -func SEG6EncapModeString(mode int) string { - switch mode { - case SEG6_IPTUN_MODE_INLINE: - return "inline" - case SEG6_IPTUN_MODE_ENCAP: - return "encap" - } - return "unknown" -} diff --git a/vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go b/vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go deleted file mode 100644 index 150017726..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go +++ /dev/null @@ -1,76 +0,0 @@ -package nl - -import () - -// seg6local parameters -const ( - SEG6_LOCAL_UNSPEC = iota - SEG6_LOCAL_ACTION - SEG6_LOCAL_SRH - SEG6_LOCAL_TABLE - SEG6_LOCAL_NH4 - SEG6_LOCAL_NH6 - SEG6_LOCAL_IIF - SEG6_LOCAL_OIF - __SEG6_LOCAL_MAX -) -const ( - SEG6_LOCAL_MAX = __SEG6_LOCAL_MAX -) - -// seg6local actions -const ( - SEG6_LOCAL_ACTION_END = iota + 1 // 1 - SEG6_LOCAL_ACTION_END_X // 2 - SEG6_LOCAL_ACTION_END_T // 3 - SEG6_LOCAL_ACTION_END_DX2 // 4 - SEG6_LOCAL_ACTION_END_DX6 // 5 - SEG6_LOCAL_ACTION_END_DX4 // 6 - SEG6_LOCAL_ACTION_END_DT6 // 7 - SEG6_LOCAL_ACTION_END_DT4 // 8 - SEG6_LOCAL_ACTION_END_B6 // 9 - SEG6_LOCAL_ACTION_END_B6_ENCAPS // 10 - SEG6_LOCAL_ACTION_END_BM // 11 - SEG6_LOCAL_ACTION_END_S // 12 - SEG6_LOCAL_ACTION_END_AS // 13 - SEG6_LOCAL_ACTION_END_AM // 14 - __SEG6_LOCAL_ACTION_MAX -) -const ( - SEG6_LOCAL_ACTION_MAX = __SEG6_LOCAL_ACTION_MAX - 1 -) - -// Helper functions -func SEG6LocalActionString(action int) string { - switch action { - case SEG6_LOCAL_ACTION_END: - return "End" - case SEG6_LOCAL_ACTION_END_X: - return "End.X" - case SEG6_LOCAL_ACTION_END_T: - return "End.T" - case SEG6_LOCAL_ACTION_END_DX2: - return "End.DX2" - case SEG6_LOCAL_ACTION_END_DX6: - return "End.DX6" - case SEG6_LOCAL_ACTION_END_DX4: - return "End.DX4" - case SEG6_LOCAL_ACTION_END_DT6: - return "End.DT6" - case SEG6_LOCAL_ACTION_END_DT4: - return "End.DT4" - case SEG6_LOCAL_ACTION_END_B6: - return "End.B6" - case SEG6_LOCAL_ACTION_END_B6_ENCAPS: - return "End.B6.Encaps" - case SEG6_LOCAL_ACTION_END_BM: - return "End.BM" - case SEG6_LOCAL_ACTION_END_S: - return "End.S" - case SEG6_LOCAL_ACTION_END_AS: - return "End.AS" - case SEG6_LOCAL_ACTION_END_AM: - return "End.AM" - } - return "unknown" -} diff --git a/vendor/github.com/vishvananda/netlink/nl/syscall.go b/vendor/github.com/vishvananda/netlink/nl/syscall.go deleted file mode 100644 index f7f7f92e6..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/syscall.go +++ /dev/null @@ -1,69 +0,0 @@ -package nl - -// syscall package lack of rule atributes type. -// Thus there are defined below -const ( - FRA_UNSPEC = iota - FRA_DST /* destination address */ - FRA_SRC /* source address */ - FRA_IIFNAME /* interface name */ - FRA_GOTO /* target to jump to (FR_ACT_GOTO) */ - FRA_UNUSED2 - FRA_PRIORITY /* priority/preference */ - FRA_UNUSED3 - FRA_UNUSED4 - FRA_UNUSED5 - FRA_FWMARK /* mark */ - FRA_FLOW /* flow/class id */ - FRA_TUN_ID - FRA_SUPPRESS_IFGROUP - FRA_SUPPRESS_PREFIXLEN - FRA_TABLE /* Extended table id */ - FRA_FWMASK /* mask for netfilter mark */ - FRA_OIFNAME -) - -// ip rule netlink request types -const ( - FR_ACT_UNSPEC = iota - FR_ACT_TO_TBL /* Pass to fixed table */ - FR_ACT_GOTO /* Jump to another rule */ - FR_ACT_NOP /* No operation */ - FR_ACT_RES3 - FR_ACT_RES4 - FR_ACT_BLACKHOLE /* Drop without notification */ - FR_ACT_UNREACHABLE /* Drop with ENETUNREACH */ - FR_ACT_PROHIBIT /* Drop with EACCES */ -) - -// socket diags related -const ( - SOCK_DIAG_BY_FAMILY = 20 /* linux.sock_diag.h */ - TCPDIAG_NOCOOKIE = 0xFFFFFFFF /* TCPDIAG_NOCOOKIE in net/ipv4/tcp_diag.h*/ -) - -// RTA_ENCAP subtype -const ( - MPLS_IPTUNNEL_UNSPEC = iota - MPLS_IPTUNNEL_DST -) - -// light weight tunnel encap types -const ( - LWTUNNEL_ENCAP_NONE = iota - LWTUNNEL_ENCAP_MPLS - LWTUNNEL_ENCAP_IP - LWTUNNEL_ENCAP_ILA - LWTUNNEL_ENCAP_IP6 - LWTUNNEL_ENCAP_SEG6 - LWTUNNEL_ENCAP_BPF - LWTUNNEL_ENCAP_SEG6_LOCAL -) - -// routing header types -const ( - IPV6_SRCRT_STRICT = 0x01 // Deprecated; will be removed - IPV6_SRCRT_TYPE_0 = 0 // Deprecated; will be removed - IPV6_SRCRT_TYPE_2 = 2 // IPv6 type 2 Routing Header - IPV6_SRCRT_TYPE_4 = 4 // Segment Routing with IPv6 -) diff --git a/vendor/github.com/vishvananda/netlink/nl/tc_linux.go b/vendor/github.com/vishvananda/netlink/nl/tc_linux.go deleted file mode 100644 index 501f554b2..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/tc_linux.go +++ /dev/null @@ -1,874 +0,0 @@ -package nl - -import ( - "encoding/binary" - "unsafe" -) - -// LinkLayer -const ( - LINKLAYER_UNSPEC = iota - LINKLAYER_ETHERNET - LINKLAYER_ATM -) - -// ATM -const ( - ATM_CELL_PAYLOAD = 48 - ATM_CELL_SIZE = 53 -) - -const TC_LINKLAYER_MASK = 0x0F - -// Police -const ( - TCA_POLICE_UNSPEC = iota - TCA_POLICE_TBF - TCA_POLICE_RATE - TCA_POLICE_PEAKRATE - TCA_POLICE_AVRATE - TCA_POLICE_RESULT - TCA_POLICE_MAX = TCA_POLICE_RESULT -) - -// Message types -const ( - TCA_UNSPEC = iota - TCA_KIND - TCA_OPTIONS - TCA_STATS - TCA_XSTATS - TCA_RATE - TCA_FCNT - TCA_STATS2 - TCA_STAB - TCA_MAX = TCA_STAB -) - -const ( - TCA_ACT_TAB = 1 - TCAA_MAX = 1 -) - -const ( - TCA_ACT_UNSPEC = iota - TCA_ACT_KIND - TCA_ACT_OPTIONS - TCA_ACT_INDEX - TCA_ACT_STATS - TCA_ACT_MAX -) - -const ( - TCA_PRIO_UNSPEC = iota - TCA_PRIO_MQ - TCA_PRIO_MAX = TCA_PRIO_MQ -) - -const ( - TCA_STATS_UNSPEC = iota - TCA_STATS_BASIC - TCA_STATS_RATE_EST - TCA_STATS_QUEUE - TCA_STATS_APP - TCA_STATS_MAX = TCA_STATS_APP -) - -const ( - SizeofTcMsg = 0x14 - SizeofTcActionMsg = 0x04 - SizeofTcPrioMap = 0x14 - SizeofTcRateSpec = 0x0c - SizeofTcNetemQopt = 0x18 - SizeofTcNetemCorr = 0x0c - SizeofTcNetemReorder = 0x08 - SizeofTcNetemCorrupt = 0x08 - SizeofTcTbfQopt = 2*SizeofTcRateSpec + 0x0c - SizeofTcHtbCopt = 2*SizeofTcRateSpec + 0x14 - SizeofTcHtbGlob = 0x14 - SizeofTcU32Key = 0x10 - SizeofTcU32Sel = 0x10 // without keys - SizeofTcGen = 0x14 - SizeofTcConnmark = SizeofTcGen + 0x04 - SizeofTcMirred = SizeofTcGen + 0x08 - SizeofTcTunnelKey = SizeofTcGen + 0x04 - SizeofTcSkbEdit = SizeofTcGen - SizeofTcPolice = 2*SizeofTcRateSpec + 0x20 -) - -// struct tcmsg { -// unsigned char tcm_family; -// unsigned char tcm__pad1; -// unsigned short tcm__pad2; -// int tcm_ifindex; -// __u32 tcm_handle; -// __u32 tcm_parent; -// __u32 tcm_info; -// }; - -type TcMsg struct { - Family uint8 - Pad [3]byte - Ifindex int32 - Handle uint32 - Parent uint32 - Info uint32 -} - -func (msg *TcMsg) Len() int { - return SizeofTcMsg -} - -func DeserializeTcMsg(b []byte) *TcMsg { - return (*TcMsg)(unsafe.Pointer(&b[0:SizeofTcMsg][0])) -} - -func (x *TcMsg) Serialize() []byte { - return (*(*[SizeofTcMsg]byte)(unsafe.Pointer(x)))[:] -} - -// struct tcamsg { -// unsigned char tca_family; -// unsigned char tca__pad1; -// unsigned short tca__pad2; -// }; - -type TcActionMsg struct { - Family uint8 - Pad [3]byte -} - -func (msg *TcActionMsg) Len() int { - return SizeofTcActionMsg -} - -func DeserializeTcActionMsg(b []byte) *TcActionMsg { - return (*TcActionMsg)(unsafe.Pointer(&b[0:SizeofTcActionMsg][0])) -} - -func (x *TcActionMsg) Serialize() []byte { - return (*(*[SizeofTcActionMsg]byte)(unsafe.Pointer(x)))[:] -} - -const ( - TC_PRIO_MAX = 15 -) - -// struct tc_prio_qopt { -// int bands; /* Number of bands */ -// __u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */ -// }; - -type TcPrioMap struct { - Bands int32 - Priomap [TC_PRIO_MAX + 1]uint8 -} - -func (msg *TcPrioMap) Len() int { - return SizeofTcPrioMap -} - -func DeserializeTcPrioMap(b []byte) *TcPrioMap { - return (*TcPrioMap)(unsafe.Pointer(&b[0:SizeofTcPrioMap][0])) -} - -func (x *TcPrioMap) Serialize() []byte { - return (*(*[SizeofTcPrioMap]byte)(unsafe.Pointer(x)))[:] -} - -const ( - TCA_TBF_UNSPEC = iota - TCA_TBF_PARMS - TCA_TBF_RTAB - TCA_TBF_PTAB - TCA_TBF_RATE64 - TCA_TBF_PRATE64 - TCA_TBF_BURST - TCA_TBF_PBURST - TCA_TBF_MAX = TCA_TBF_PBURST -) - -// struct tc_ratespec { -// unsigned char cell_log; -// __u8 linklayer; /* lower 4 bits */ -// unsigned short overhead; -// short cell_align; -// unsigned short mpu; -// __u32 rate; -// }; - -type TcRateSpec struct { - CellLog uint8 - Linklayer uint8 - Overhead uint16 - CellAlign int16 - Mpu uint16 - Rate uint32 -} - -func (msg *TcRateSpec) Len() int { - return SizeofTcRateSpec -} - -func DeserializeTcRateSpec(b []byte) *TcRateSpec { - return (*TcRateSpec)(unsafe.Pointer(&b[0:SizeofTcRateSpec][0])) -} - -func (x *TcRateSpec) Serialize() []byte { - return (*(*[SizeofTcRateSpec]byte)(unsafe.Pointer(x)))[:] -} - -/** -* NETEM - */ - -const ( - TCA_NETEM_UNSPEC = iota - TCA_NETEM_CORR - TCA_NETEM_DELAY_DIST - TCA_NETEM_REORDER - TCA_NETEM_CORRUPT - TCA_NETEM_LOSS - TCA_NETEM_RATE - TCA_NETEM_ECN - TCA_NETEM_RATE64 - TCA_NETEM_MAX = TCA_NETEM_RATE64 -) - -// struct tc_netem_qopt { -// __u32 latency; /* added delay (us) */ -// __u32 limit; /* fifo limit (packets) */ -// __u32 loss; /* random packet loss (0=none ~0=100%) */ -// __u32 gap; /* re-ordering gap (0 for none) */ -// __u32 duplicate; /* random packet dup (0=none ~0=100%) */ -// __u32 jitter; /* random jitter in latency (us) */ -// }; - -type TcNetemQopt struct { - Latency uint32 - Limit uint32 - Loss uint32 - Gap uint32 - Duplicate uint32 - Jitter uint32 -} - -func (msg *TcNetemQopt) Len() int { - return SizeofTcNetemQopt -} - -func DeserializeTcNetemQopt(b []byte) *TcNetemQopt { - return (*TcNetemQopt)(unsafe.Pointer(&b[0:SizeofTcNetemQopt][0])) -} - -func (x *TcNetemQopt) Serialize() []byte { - return (*(*[SizeofTcNetemQopt]byte)(unsafe.Pointer(x)))[:] -} - -// struct tc_netem_corr { -// __u32 delay_corr; /* delay correlation */ -// __u32 loss_corr; /* packet loss correlation */ -// __u32 dup_corr; /* duplicate correlation */ -// }; - -type TcNetemCorr struct { - DelayCorr uint32 - LossCorr uint32 - DupCorr uint32 -} - -func (msg *TcNetemCorr) Len() int { - return SizeofTcNetemCorr -} - -func DeserializeTcNetemCorr(b []byte) *TcNetemCorr { - return (*TcNetemCorr)(unsafe.Pointer(&b[0:SizeofTcNetemCorr][0])) -} - -func (x *TcNetemCorr) Serialize() []byte { - return (*(*[SizeofTcNetemCorr]byte)(unsafe.Pointer(x)))[:] -} - -// struct tc_netem_reorder { -// __u32 probability; -// __u32 correlation; -// }; - -type TcNetemReorder struct { - Probability uint32 - Correlation uint32 -} - -func (msg *TcNetemReorder) Len() int { - return SizeofTcNetemReorder -} - -func DeserializeTcNetemReorder(b []byte) *TcNetemReorder { - return (*TcNetemReorder)(unsafe.Pointer(&b[0:SizeofTcNetemReorder][0])) -} - -func (x *TcNetemReorder) Serialize() []byte { - return (*(*[SizeofTcNetemReorder]byte)(unsafe.Pointer(x)))[:] -} - -// struct tc_netem_corrupt { -// __u32 probability; -// __u32 correlation; -// }; - -type TcNetemCorrupt struct { - Probability uint32 - Correlation uint32 -} - -func (msg *TcNetemCorrupt) Len() int { - return SizeofTcNetemCorrupt -} - -func DeserializeTcNetemCorrupt(b []byte) *TcNetemCorrupt { - return (*TcNetemCorrupt)(unsafe.Pointer(&b[0:SizeofTcNetemCorrupt][0])) -} - -func (x *TcNetemCorrupt) Serialize() []byte { - return (*(*[SizeofTcNetemCorrupt]byte)(unsafe.Pointer(x)))[:] -} - -// struct tc_tbf_qopt { -// struct tc_ratespec rate; -// struct tc_ratespec peakrate; -// __u32 limit; -// __u32 buffer; -// __u32 mtu; -// }; - -type TcTbfQopt struct { - Rate TcRateSpec - Peakrate TcRateSpec - Limit uint32 - Buffer uint32 - Mtu uint32 -} - -func (msg *TcTbfQopt) Len() int { - return SizeofTcTbfQopt -} - -func DeserializeTcTbfQopt(b []byte) *TcTbfQopt { - return (*TcTbfQopt)(unsafe.Pointer(&b[0:SizeofTcTbfQopt][0])) -} - -func (x *TcTbfQopt) Serialize() []byte { - return (*(*[SizeofTcTbfQopt]byte)(unsafe.Pointer(x)))[:] -} - -const ( - TCA_HTB_UNSPEC = iota - TCA_HTB_PARMS - TCA_HTB_INIT - TCA_HTB_CTAB - TCA_HTB_RTAB - TCA_HTB_DIRECT_QLEN - TCA_HTB_RATE64 - TCA_HTB_CEIL64 - TCA_HTB_MAX = TCA_HTB_CEIL64 -) - -//struct tc_htb_opt { -// struct tc_ratespec rate; -// struct tc_ratespec ceil; -// __u32 buffer; -// __u32 cbuffer; -// __u32 quantum; -// __u32 level; /* out only */ -// __u32 prio; -//}; - -type TcHtbCopt struct { - Rate TcRateSpec - Ceil TcRateSpec - Buffer uint32 - Cbuffer uint32 - Quantum uint32 - Level uint32 - Prio uint32 -} - -func (msg *TcHtbCopt) Len() int { - return SizeofTcHtbCopt -} - -func DeserializeTcHtbCopt(b []byte) *TcHtbCopt { - return (*TcHtbCopt)(unsafe.Pointer(&b[0:SizeofTcHtbCopt][0])) -} - -func (x *TcHtbCopt) Serialize() []byte { - return (*(*[SizeofTcHtbCopt]byte)(unsafe.Pointer(x)))[:] -} - -type TcHtbGlob struct { - Version uint32 - Rate2Quantum uint32 - Defcls uint32 - Debug uint32 - DirectPkts uint32 -} - -func (msg *TcHtbGlob) Len() int { - return SizeofTcHtbGlob -} - -func DeserializeTcHtbGlob(b []byte) *TcHtbGlob { - return (*TcHtbGlob)(unsafe.Pointer(&b[0:SizeofTcHtbGlob][0])) -} - -func (x *TcHtbGlob) Serialize() []byte { - return (*(*[SizeofTcHtbGlob]byte)(unsafe.Pointer(x)))[:] -} - -// HFSC - -type Curve struct { - m1 uint32 - d uint32 - m2 uint32 -} - -type HfscCopt struct { - Rsc Curve - Fsc Curve - Usc Curve -} - -func (c *Curve) Attrs() (uint32, uint32, uint32) { - return c.m1, c.d, c.m2 -} - -func (c *Curve) Set(m1 uint32, d uint32, m2 uint32) { - c.m1 = m1 - c.d = d - c.m2 = m2 -} - -func DeserializeHfscCurve(b []byte) *Curve { - return &Curve{ - m1: binary.LittleEndian.Uint32(b[0:4]), - d: binary.LittleEndian.Uint32(b[4:8]), - m2: binary.LittleEndian.Uint32(b[8:12]), - } -} - -func SerializeHfscCurve(c *Curve) (b []byte) { - t := make([]byte, binary.MaxVarintLen32) - binary.LittleEndian.PutUint32(t, c.m1) - b = append(b, t[:4]...) - binary.LittleEndian.PutUint32(t, c.d) - b = append(b, t[:4]...) - binary.LittleEndian.PutUint32(t, c.m2) - b = append(b, t[:4]...) - return b -} - -type TcHfscOpt struct { - Defcls uint16 -} - -func (x *TcHfscOpt) Serialize() []byte { - return (*(*[2]byte)(unsafe.Pointer(x)))[:] -} - -const ( - TCA_U32_UNSPEC = iota - TCA_U32_CLASSID - TCA_U32_HASH - TCA_U32_LINK - TCA_U32_DIVISOR - TCA_U32_SEL - TCA_U32_POLICE - TCA_U32_ACT - TCA_U32_INDEV - TCA_U32_PCNT - TCA_U32_MARK - TCA_U32_MAX = TCA_U32_MARK -) - -// struct tc_u32_key { -// __be32 mask; -// __be32 val; -// int off; -// int offmask; -// }; - -type TcU32Key struct { - Mask uint32 // big endian - Val uint32 // big endian - Off int32 - OffMask int32 -} - -func (msg *TcU32Key) Len() int { - return SizeofTcU32Key -} - -func DeserializeTcU32Key(b []byte) *TcU32Key { - return (*TcU32Key)(unsafe.Pointer(&b[0:SizeofTcU32Key][0])) -} - -func (x *TcU32Key) Serialize() []byte { - return (*(*[SizeofTcU32Key]byte)(unsafe.Pointer(x)))[:] -} - -// struct tc_u32_sel { -// unsigned char flags; -// unsigned char offshift; -// unsigned char nkeys; -// -// __be16 offmask; -// __u16 off; -// short offoff; -// -// short hoff; -// __be32 hmask; -// struct tc_u32_key keys[0]; -// }; - -const ( - TC_U32_TERMINAL = 1 << iota - TC_U32_OFFSET = 1 << iota - TC_U32_VAROFFSET = 1 << iota - TC_U32_EAT = 1 << iota -) - -type TcU32Sel struct { - Flags uint8 - Offshift uint8 - Nkeys uint8 - Pad uint8 - Offmask uint16 // big endian - Off uint16 - Offoff int16 - Hoff int16 - Hmask uint32 // big endian - Keys []TcU32Key -} - -func (msg *TcU32Sel) Len() int { - return SizeofTcU32Sel + int(msg.Nkeys)*SizeofTcU32Key -} - -func DeserializeTcU32Sel(b []byte) *TcU32Sel { - x := &TcU32Sel{} - copy((*(*[SizeofTcU32Sel]byte)(unsafe.Pointer(x)))[:], b) - next := SizeofTcU32Sel - var i uint8 - for i = 0; i < x.Nkeys; i++ { - x.Keys = append(x.Keys, *DeserializeTcU32Key(b[next:])) - next += SizeofTcU32Key - } - return x -} - -func (x *TcU32Sel) Serialize() []byte { - // This can't just unsafe.cast because it must iterate through keys. - buf := make([]byte, x.Len()) - copy(buf, (*(*[SizeofTcU32Sel]byte)(unsafe.Pointer(x)))[:]) - next := SizeofTcU32Sel - for _, key := range x.Keys { - keyBuf := key.Serialize() - copy(buf[next:], keyBuf) - next += SizeofTcU32Key - } - return buf -} - -type TcGen struct { - Index uint32 - Capab uint32 - Action int32 - Refcnt int32 - Bindcnt int32 -} - -func (msg *TcGen) Len() int { - return SizeofTcGen -} - -func DeserializeTcGen(b []byte) *TcGen { - return (*TcGen)(unsafe.Pointer(&b[0:SizeofTcGen][0])) -} - -func (x *TcGen) Serialize() []byte { - return (*(*[SizeofTcGen]byte)(unsafe.Pointer(x)))[:] -} - -// #define tc_gen \ -// __u32 index; \ -// __u32 capab; \ -// int action; \ -// int refcnt; \ -// int bindcnt - -const ( - TCA_ACT_GACT = 5 -) - -const ( - TCA_GACT_UNSPEC = iota - TCA_GACT_TM - TCA_GACT_PARMS - TCA_GACT_PROB - TCA_GACT_MAX = TCA_GACT_PROB -) - -type TcGact TcGen - -const ( - TCA_ACT_BPF = 13 -) - -const ( - TCA_ACT_BPF_UNSPEC = iota - TCA_ACT_BPF_TM - TCA_ACT_BPF_PARMS - TCA_ACT_BPF_OPS_LEN - TCA_ACT_BPF_OPS - TCA_ACT_BPF_FD - TCA_ACT_BPF_NAME - TCA_ACT_BPF_MAX = TCA_ACT_BPF_NAME -) - -const ( - TCA_BPF_FLAG_ACT_DIRECT uint32 = 1 << iota -) - -const ( - TCA_BPF_UNSPEC = iota - TCA_BPF_ACT - TCA_BPF_POLICE - TCA_BPF_CLASSID - TCA_BPF_OPS_LEN - TCA_BPF_OPS - TCA_BPF_FD - TCA_BPF_NAME - TCA_BPF_FLAGS - TCA_BPF_FLAGS_GEN - TCA_BPF_TAG - TCA_BPF_ID - TCA_BPF_MAX = TCA_BPF_ID -) - -type TcBpf TcGen - -const ( - TCA_ACT_CONNMARK = 14 -) - -const ( - TCA_CONNMARK_UNSPEC = iota - TCA_CONNMARK_PARMS - TCA_CONNMARK_TM - TCA_CONNMARK_MAX = TCA_CONNMARK_TM -) - -// struct tc_connmark { -// tc_gen; -// __u16 zone; -// }; - -type TcConnmark struct { - TcGen - Zone uint16 -} - -func (msg *TcConnmark) Len() int { - return SizeofTcConnmark -} - -func DeserializeTcConnmark(b []byte) *TcConnmark { - return (*TcConnmark)(unsafe.Pointer(&b[0:SizeofTcConnmark][0])) -} - -func (x *TcConnmark) Serialize() []byte { - return (*(*[SizeofTcConnmark]byte)(unsafe.Pointer(x)))[:] -} - -const ( - TCA_ACT_MIRRED = 8 -) - -const ( - TCA_MIRRED_UNSPEC = iota - TCA_MIRRED_TM - TCA_MIRRED_PARMS - TCA_MIRRED_MAX = TCA_MIRRED_PARMS -) - -// struct tc_mirred { -// tc_gen; -// int eaction; /* one of IN/EGRESS_MIRROR/REDIR */ -// __u32 ifindex; /* ifindex of egress port */ -// }; - -type TcMirred struct { - TcGen - Eaction int32 - Ifindex uint32 -} - -func (msg *TcMirred) Len() int { - return SizeofTcMirred -} - -func DeserializeTcMirred(b []byte) *TcMirred { - return (*TcMirred)(unsafe.Pointer(&b[0:SizeofTcMirred][0])) -} - -func (x *TcMirred) Serialize() []byte { - return (*(*[SizeofTcMirred]byte)(unsafe.Pointer(x)))[:] -} - -const ( - TCA_TUNNEL_KEY_UNSPEC = iota - TCA_TUNNEL_KEY_TM - TCA_TUNNEL_KEY_PARMS - TCA_TUNNEL_KEY_ENC_IPV4_SRC - TCA_TUNNEL_KEY_ENC_IPV4_DST - TCA_TUNNEL_KEY_ENC_IPV6_SRC - TCA_TUNNEL_KEY_ENC_IPV6_DST - TCA_TUNNEL_KEY_ENC_KEY_ID - TCA_TUNNEL_KEY_MAX = TCA_TUNNEL_KEY_ENC_KEY_ID -) - -type TcTunnelKey struct { - TcGen - Action int32 -} - -func (x *TcTunnelKey) Len() int { - return SizeofTcTunnelKey -} - -func DeserializeTunnelKey(b []byte) *TcTunnelKey { - return (*TcTunnelKey)(unsafe.Pointer(&b[0:SizeofTcTunnelKey][0])) -} - -func (x *TcTunnelKey) Serialize() []byte { - return (*(*[SizeofTcTunnelKey]byte)(unsafe.Pointer(x)))[:] -} - -const ( - TCA_SKBEDIT_UNSPEC = iota - TCA_SKBEDIT_TM - TCA_SKBEDIT_PARMS - TCA_SKBEDIT_PRIORITY - TCA_SKBEDIT_QUEUE_MAPPING - TCA_SKBEDIT_MARK - TCA_SKBEDIT_PAD - TCA_SKBEDIT_PTYPE - TCA_SKBEDIT_MAX = TCA_SKBEDIT_MARK -) - -type TcSkbEdit struct { - TcGen -} - -func (x *TcSkbEdit) Len() int { - return SizeofTcSkbEdit -} - -func DeserializeSkbEdit(b []byte) *TcSkbEdit { - return (*TcSkbEdit)(unsafe.Pointer(&b[0:SizeofTcSkbEdit][0])) -} - -func (x *TcSkbEdit) Serialize() []byte { - return (*(*[SizeofTcSkbEdit]byte)(unsafe.Pointer(x)))[:] -} - -// struct tc_police { -// __u32 index; -// int action; -// __u32 limit; -// __u32 burst; -// __u32 mtu; -// struct tc_ratespec rate; -// struct tc_ratespec peakrate; -// int refcnt; -// int bindcnt; -// __u32 capab; -// }; - -type TcPolice struct { - Index uint32 - Action int32 - Limit uint32 - Burst uint32 - Mtu uint32 - Rate TcRateSpec - PeakRate TcRateSpec - Refcnt int32 - Bindcnt int32 - Capab uint32 -} - -func (msg *TcPolice) Len() int { - return SizeofTcPolice -} - -func DeserializeTcPolice(b []byte) *TcPolice { - return (*TcPolice)(unsafe.Pointer(&b[0:SizeofTcPolice][0])) -} - -func (x *TcPolice) Serialize() []byte { - return (*(*[SizeofTcPolice]byte)(unsafe.Pointer(x)))[:] -} - -const ( - TCA_FW_UNSPEC = iota - TCA_FW_CLASSID - TCA_FW_POLICE - TCA_FW_INDEV - TCA_FW_ACT - TCA_FW_MASK - TCA_FW_MAX = TCA_FW_MASK -) - -const ( - TCA_MATCHALL_UNSPEC = iota - TCA_MATCHALL_CLASSID - TCA_MATCHALL_ACT - TCA_MATCHALL_FLAGS -) - -const ( - TCA_FQ_UNSPEC = iota - TCA_FQ_PLIMIT // limit of total number of packets in queue - TCA_FQ_FLOW_PLIMIT // limit of packets per flow - TCA_FQ_QUANTUM // RR quantum - TCA_FQ_INITIAL_QUANTUM // RR quantum for new flow - TCA_FQ_RATE_ENABLE // enable/disable rate limiting - TCA_FQ_FLOW_DEFAULT_RATE // obsolete do not use - TCA_FQ_FLOW_MAX_RATE // per flow max rate - TCA_FQ_BUCKETS_LOG // log2(number of buckets) - TCA_FQ_FLOW_REFILL_DELAY // flow credit refill delay in usec - TCA_FQ_ORPHAN_MASK // mask applied to orphaned skb hashes - TCA_FQ_LOW_RATE_THRESHOLD // per packet delay under this rate -) - -const ( - TCA_FQ_CODEL_UNSPEC = iota - TCA_FQ_CODEL_TARGET - TCA_FQ_CODEL_LIMIT - TCA_FQ_CODEL_INTERVAL - TCA_FQ_CODEL_ECN - TCA_FQ_CODEL_FLOWS - TCA_FQ_CODEL_QUANTUM - TCA_FQ_CODEL_CE_THRESHOLD - TCA_FQ_CODEL_DROP_BATCH_SIZE - TCA_FQ_CODEL_MEMORY_LIMIT -) - -const ( - TCA_HFSC_UNSPEC = iota - TCA_HFSC_RSC - TCA_HFSC_FSC - TCA_HFSC_USC -) diff --git a/vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go b/vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go deleted file mode 100644 index dce9073f7..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go +++ /dev/null @@ -1,306 +0,0 @@ -package nl - -import ( - "bytes" - "net" - "unsafe" -) - -// Infinity for packet and byte counts -const ( - XFRM_INF = ^uint64(0) -) - -type XfrmMsgType uint8 - -type XfrmMsg interface { - Type() XfrmMsgType -} - -// Message Types -const ( - XFRM_MSG_BASE XfrmMsgType = 0x10 - XFRM_MSG_NEWSA = 0x10 - XFRM_MSG_DELSA = 0x11 - XFRM_MSG_GETSA = 0x12 - XFRM_MSG_NEWPOLICY = 0x13 - XFRM_MSG_DELPOLICY = 0x14 - XFRM_MSG_GETPOLICY = 0x15 - XFRM_MSG_ALLOCSPI = 0x16 - XFRM_MSG_ACQUIRE = 0x17 - XFRM_MSG_EXPIRE = 0x18 - XFRM_MSG_UPDPOLICY = 0x19 - XFRM_MSG_UPDSA = 0x1a - XFRM_MSG_POLEXPIRE = 0x1b - XFRM_MSG_FLUSHSA = 0x1c - XFRM_MSG_FLUSHPOLICY = 0x1d - XFRM_MSG_NEWAE = 0x1e - XFRM_MSG_GETAE = 0x1f - XFRM_MSG_REPORT = 0x20 - XFRM_MSG_MIGRATE = 0x21 - XFRM_MSG_NEWSADINFO = 0x22 - XFRM_MSG_GETSADINFO = 0x23 - XFRM_MSG_NEWSPDINFO = 0x24 - XFRM_MSG_GETSPDINFO = 0x25 - XFRM_MSG_MAPPING = 0x26 - XFRM_MSG_MAX = 0x26 - XFRM_NR_MSGTYPES = 0x17 -) - -// Attribute types -const ( - /* Netlink message attributes. */ - XFRMA_UNSPEC = iota - XFRMA_ALG_AUTH /* struct xfrm_algo */ - XFRMA_ALG_CRYPT /* struct xfrm_algo */ - XFRMA_ALG_COMP /* struct xfrm_algo */ - XFRMA_ENCAP /* struct xfrm_algo + struct xfrm_encap_tmpl */ - XFRMA_TMPL /* 1 or more struct xfrm_user_tmpl */ - XFRMA_SA /* struct xfrm_usersa_info */ - XFRMA_POLICY /* struct xfrm_userpolicy_info */ - XFRMA_SEC_CTX /* struct xfrm_sec_ctx */ - XFRMA_LTIME_VAL - XFRMA_REPLAY_VAL - XFRMA_REPLAY_THRESH - XFRMA_ETIMER_THRESH - XFRMA_SRCADDR /* xfrm_address_t */ - XFRMA_COADDR /* xfrm_address_t */ - XFRMA_LASTUSED /* unsigned long */ - XFRMA_POLICY_TYPE /* struct xfrm_userpolicy_type */ - XFRMA_MIGRATE - XFRMA_ALG_AEAD /* struct xfrm_algo_aead */ - XFRMA_KMADDRESS /* struct xfrm_user_kmaddress */ - XFRMA_ALG_AUTH_TRUNC /* struct xfrm_algo_auth */ - XFRMA_MARK /* struct xfrm_mark */ - XFRMA_TFCPAD /* __u32 */ - XFRMA_REPLAY_ESN_VAL /* struct xfrm_replay_esn */ - XFRMA_SA_EXTRA_FLAGS /* __u32 */ - XFRMA_PROTO /* __u8 */ - XFRMA_ADDRESS_FILTER /* struct xfrm_address_filter */ - XFRMA_PAD - XFRMA_OFFLOAD_DEV /* struct xfrm_state_offload */ - XFRMA_SET_MARK /* __u32 */ - XFRMA_SET_MARK_MASK /* __u32 */ - XFRMA_IF_ID /* __u32 */ - - XFRMA_MAX = iota - 1 -) - -const XFRMA_OUTPUT_MARK = XFRMA_SET_MARK - -const ( - SizeofXfrmAddress = 0x10 - SizeofXfrmSelector = 0x38 - SizeofXfrmLifetimeCfg = 0x40 - SizeofXfrmLifetimeCur = 0x20 - SizeofXfrmId = 0x18 - SizeofXfrmMark = 0x08 -) - -// Netlink groups -const ( - XFRMNLGRP_NONE = 0x0 - XFRMNLGRP_ACQUIRE = 0x1 - XFRMNLGRP_EXPIRE = 0x2 - XFRMNLGRP_SA = 0x3 - XFRMNLGRP_POLICY = 0x4 - XFRMNLGRP_AEVENTS = 0x5 - XFRMNLGRP_REPORT = 0x6 - XFRMNLGRP_MIGRATE = 0x7 - XFRMNLGRP_MAPPING = 0x8 - __XFRMNLGRP_MAX = 0x9 -) - -// typedef union { -// __be32 a4; -// __be32 a6[4]; -// } xfrm_address_t; - -type XfrmAddress [SizeofXfrmAddress]byte - -func (x *XfrmAddress) ToIP() net.IP { - var empty = [12]byte{} - ip := make(net.IP, net.IPv6len) - if bytes.Equal(x[4:16], empty[:]) { - ip[10] = 0xff - ip[11] = 0xff - copy(ip[12:16], x[0:4]) - } else { - copy(ip[:], x[:]) - } - return ip -} - -func (x *XfrmAddress) ToIPNet(prefixlen uint8) *net.IPNet { - ip := x.ToIP() - if GetIPFamily(ip) == FAMILY_V4 { - return &net.IPNet{IP: ip, Mask: net.CIDRMask(int(prefixlen), 32)} - } - return &net.IPNet{IP: ip, Mask: net.CIDRMask(int(prefixlen), 128)} -} - -func (x *XfrmAddress) FromIP(ip net.IP) { - var empty = [16]byte{} - if len(ip) < net.IPv4len { - copy(x[4:16], empty[:]) - } else if GetIPFamily(ip) == FAMILY_V4 { - copy(x[0:4], ip.To4()[0:4]) - copy(x[4:16], empty[:12]) - } else { - copy(x[0:16], ip.To16()[0:16]) - } -} - -func DeserializeXfrmAddress(b []byte) *XfrmAddress { - return (*XfrmAddress)(unsafe.Pointer(&b[0:SizeofXfrmAddress][0])) -} - -func (x *XfrmAddress) Serialize() []byte { - return (*(*[SizeofXfrmAddress]byte)(unsafe.Pointer(x)))[:] -} - -// struct xfrm_selector { -// xfrm_address_t daddr; -// xfrm_address_t saddr; -// __be16 dport; -// __be16 dport_mask; -// __be16 sport; -// __be16 sport_mask; -// __u16 family; -// __u8 prefixlen_d; -// __u8 prefixlen_s; -// __u8 proto; -// int ifindex; -// __kernel_uid32_t user; -// }; - -type XfrmSelector struct { - Daddr XfrmAddress - Saddr XfrmAddress - Dport uint16 // big endian - DportMask uint16 // big endian - Sport uint16 // big endian - SportMask uint16 // big endian - Family uint16 - PrefixlenD uint8 - PrefixlenS uint8 - Proto uint8 - Pad [3]byte - Ifindex int32 - User uint32 -} - -func (msg *XfrmSelector) Len() int { - return SizeofXfrmSelector -} - -func DeserializeXfrmSelector(b []byte) *XfrmSelector { - return (*XfrmSelector)(unsafe.Pointer(&b[0:SizeofXfrmSelector][0])) -} - -func (msg *XfrmSelector) Serialize() []byte { - return (*(*[SizeofXfrmSelector]byte)(unsafe.Pointer(msg)))[:] -} - -// struct xfrm_lifetime_cfg { -// __u64 soft_byte_limit; -// __u64 hard_byte_limit; -// __u64 soft_packet_limit; -// __u64 hard_packet_limit; -// __u64 soft_add_expires_seconds; -// __u64 hard_add_expires_seconds; -// __u64 soft_use_expires_seconds; -// __u64 hard_use_expires_seconds; -// }; -// - -type XfrmLifetimeCfg struct { - SoftByteLimit uint64 - HardByteLimit uint64 - SoftPacketLimit uint64 - HardPacketLimit uint64 - SoftAddExpiresSeconds uint64 - HardAddExpiresSeconds uint64 - SoftUseExpiresSeconds uint64 - HardUseExpiresSeconds uint64 -} - -func (msg *XfrmLifetimeCfg) Len() int { - return SizeofXfrmLifetimeCfg -} - -func DeserializeXfrmLifetimeCfg(b []byte) *XfrmLifetimeCfg { - return (*XfrmLifetimeCfg)(unsafe.Pointer(&b[0:SizeofXfrmLifetimeCfg][0])) -} - -func (msg *XfrmLifetimeCfg) Serialize() []byte { - return (*(*[SizeofXfrmLifetimeCfg]byte)(unsafe.Pointer(msg)))[:] -} - -// struct xfrm_lifetime_cur { -// __u64 bytes; -// __u64 packets; -// __u64 add_time; -// __u64 use_time; -// }; - -type XfrmLifetimeCur struct { - Bytes uint64 - Packets uint64 - AddTime uint64 - UseTime uint64 -} - -func (msg *XfrmLifetimeCur) Len() int { - return SizeofXfrmLifetimeCur -} - -func DeserializeXfrmLifetimeCur(b []byte) *XfrmLifetimeCur { - return (*XfrmLifetimeCur)(unsafe.Pointer(&b[0:SizeofXfrmLifetimeCur][0])) -} - -func (msg *XfrmLifetimeCur) Serialize() []byte { - return (*(*[SizeofXfrmLifetimeCur]byte)(unsafe.Pointer(msg)))[:] -} - -// struct xfrm_id { -// xfrm_address_t daddr; -// __be32 spi; -// __u8 proto; -// }; - -type XfrmId struct { - Daddr XfrmAddress - Spi uint32 // big endian - Proto uint8 - Pad [3]byte -} - -func (msg *XfrmId) Len() int { - return SizeofXfrmId -} - -func DeserializeXfrmId(b []byte) *XfrmId { - return (*XfrmId)(unsafe.Pointer(&b[0:SizeofXfrmId][0])) -} - -func (msg *XfrmId) Serialize() []byte { - return (*(*[SizeofXfrmId]byte)(unsafe.Pointer(msg)))[:] -} - -type XfrmMark struct { - Value uint32 - Mask uint32 -} - -func (msg *XfrmMark) Len() int { - return SizeofXfrmMark -} - -func DeserializeXfrmMark(b []byte) *XfrmMark { - return (*XfrmMark)(unsafe.Pointer(&b[0:SizeofXfrmMark][0])) -} - -func (msg *XfrmMark) Serialize() []byte { - return (*(*[SizeofXfrmMark]byte)(unsafe.Pointer(msg)))[:] -} diff --git a/vendor/github.com/vishvananda/netlink/nl/xfrm_monitor_linux.go b/vendor/github.com/vishvananda/netlink/nl/xfrm_monitor_linux.go deleted file mode 100644 index 715df4cc5..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/xfrm_monitor_linux.go +++ /dev/null @@ -1,32 +0,0 @@ -package nl - -import ( - "unsafe" -) - -const ( - SizeofXfrmUserExpire = 0xe8 -) - -// struct xfrm_user_expire { -// struct xfrm_usersa_info state; -// __u8 hard; -// }; - -type XfrmUserExpire struct { - XfrmUsersaInfo XfrmUsersaInfo - Hard uint8 - Pad [7]byte -} - -func (msg *XfrmUserExpire) Len() int { - return SizeofXfrmUserExpire -} - -func DeserializeXfrmUserExpire(b []byte) *XfrmUserExpire { - return (*XfrmUserExpire)(unsafe.Pointer(&b[0:SizeofXfrmUserExpire][0])) -} - -func (msg *XfrmUserExpire) Serialize() []byte { - return (*(*[SizeofXfrmUserExpire]byte)(unsafe.Pointer(msg)))[:] -} diff --git a/vendor/github.com/vishvananda/netlink/nl/xfrm_policy_linux.go b/vendor/github.com/vishvananda/netlink/nl/xfrm_policy_linux.go deleted file mode 100644 index 66f7e03d2..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/xfrm_policy_linux.go +++ /dev/null @@ -1,119 +0,0 @@ -package nl - -import ( - "unsafe" -) - -const ( - SizeofXfrmUserpolicyId = 0x40 - SizeofXfrmUserpolicyInfo = 0xa8 - SizeofXfrmUserTmpl = 0x40 -) - -// struct xfrm_userpolicy_id { -// struct xfrm_selector sel; -// __u32 index; -// __u8 dir; -// }; -// - -type XfrmUserpolicyId struct { - Sel XfrmSelector - Index uint32 - Dir uint8 - Pad [3]byte -} - -func (msg *XfrmUserpolicyId) Len() int { - return SizeofXfrmUserpolicyId -} - -func DeserializeXfrmUserpolicyId(b []byte) *XfrmUserpolicyId { - return (*XfrmUserpolicyId)(unsafe.Pointer(&b[0:SizeofXfrmUserpolicyId][0])) -} - -func (msg *XfrmUserpolicyId) Serialize() []byte { - return (*(*[SizeofXfrmUserpolicyId]byte)(unsafe.Pointer(msg)))[:] -} - -// struct xfrm_userpolicy_info { -// struct xfrm_selector sel; -// struct xfrm_lifetime_cfg lft; -// struct xfrm_lifetime_cur curlft; -// __u32 priority; -// __u32 index; -// __u8 dir; -// __u8 action; -// #define XFRM_POLICY_ALLOW 0 -// #define XFRM_POLICY_BLOCK 1 -// __u8 flags; -// #define XFRM_POLICY_LOCALOK 1 /* Allow user to override global policy */ -// /* Automatically expand selector to include matching ICMP payloads. */ -// #define XFRM_POLICY_ICMP 2 -// __u8 share; -// }; - -type XfrmUserpolicyInfo struct { - Sel XfrmSelector - Lft XfrmLifetimeCfg - Curlft XfrmLifetimeCur - Priority uint32 - Index uint32 - Dir uint8 - Action uint8 - Flags uint8 - Share uint8 - Pad [4]byte -} - -func (msg *XfrmUserpolicyInfo) Len() int { - return SizeofXfrmUserpolicyInfo -} - -func DeserializeXfrmUserpolicyInfo(b []byte) *XfrmUserpolicyInfo { - return (*XfrmUserpolicyInfo)(unsafe.Pointer(&b[0:SizeofXfrmUserpolicyInfo][0])) -} - -func (msg *XfrmUserpolicyInfo) Serialize() []byte { - return (*(*[SizeofXfrmUserpolicyInfo]byte)(unsafe.Pointer(msg)))[:] -} - -// struct xfrm_user_tmpl { -// struct xfrm_id id; -// __u16 family; -// xfrm_address_t saddr; -// __u32 reqid; -// __u8 mode; -// __u8 share; -// __u8 optional; -// __u32 aalgos; -// __u32 ealgos; -// __u32 calgos; -// } - -type XfrmUserTmpl struct { - XfrmId XfrmId - Family uint16 - Pad1 [2]byte - Saddr XfrmAddress - Reqid uint32 - Mode uint8 - Share uint8 - Optional uint8 - Pad2 byte - Aalgos uint32 - Ealgos uint32 - Calgos uint32 -} - -func (msg *XfrmUserTmpl) Len() int { - return SizeofXfrmUserTmpl -} - -func DeserializeXfrmUserTmpl(b []byte) *XfrmUserTmpl { - return (*XfrmUserTmpl)(unsafe.Pointer(&b[0:SizeofXfrmUserTmpl][0])) -} - -func (msg *XfrmUserTmpl) Serialize() []byte { - return (*(*[SizeofXfrmUserTmpl]byte)(unsafe.Pointer(msg)))[:] -} diff --git a/vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go b/vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go deleted file mode 100644 index b6290fd54..000000000 --- a/vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go +++ /dev/null @@ -1,334 +0,0 @@ -package nl - -import ( - "unsafe" -) - -const ( - SizeofXfrmUsersaId = 0x18 - SizeofXfrmStats = 0x0c - SizeofXfrmUsersaInfo = 0xe0 - SizeofXfrmUserSpiInfo = 0xe8 - SizeofXfrmAlgo = 0x44 - SizeofXfrmAlgoAuth = 0x48 - SizeofXfrmAlgoAEAD = 0x48 - SizeofXfrmEncapTmpl = 0x18 - SizeofXfrmUsersaFlush = 0x8 - SizeofXfrmReplayStateEsn = 0x18 -) - -const ( - XFRM_STATE_NOECN = 1 - XFRM_STATE_DECAP_DSCP = 2 - XFRM_STATE_NOPMTUDISC = 4 - XFRM_STATE_WILDRECV = 8 - XFRM_STATE_ICMP = 16 - XFRM_STATE_AF_UNSPEC = 32 - XFRM_STATE_ALIGN4 = 64 - XFRM_STATE_ESN = 128 -) - -// struct xfrm_usersa_id { -// xfrm_address_t daddr; -// __be32 spi; -// __u16 family; -// __u8 proto; -// }; - -type XfrmUsersaId struct { - Daddr XfrmAddress - Spi uint32 // big endian - Family uint16 - Proto uint8 - Pad byte -} - -func (msg *XfrmUsersaId) Len() int { - return SizeofXfrmUsersaId -} - -func DeserializeXfrmUsersaId(b []byte) *XfrmUsersaId { - return (*XfrmUsersaId)(unsafe.Pointer(&b[0:SizeofXfrmUsersaId][0])) -} - -func (msg *XfrmUsersaId) Serialize() []byte { - return (*(*[SizeofXfrmUsersaId]byte)(unsafe.Pointer(msg)))[:] -} - -// struct xfrm_stats { -// __u32 replay_window; -// __u32 replay; -// __u32 integrity_failed; -// }; - -type XfrmStats struct { - ReplayWindow uint32 - Replay uint32 - IntegrityFailed uint32 -} - -func (msg *XfrmStats) Len() int { - return SizeofXfrmStats -} - -func DeserializeXfrmStats(b []byte) *XfrmStats { - return (*XfrmStats)(unsafe.Pointer(&b[0:SizeofXfrmStats][0])) -} - -func (msg *XfrmStats) Serialize() []byte { - return (*(*[SizeofXfrmStats]byte)(unsafe.Pointer(msg)))[:] -} - -// struct xfrm_usersa_info { -// struct xfrm_selector sel; -// struct xfrm_id id; -// xfrm_address_t saddr; -// struct xfrm_lifetime_cfg lft; -// struct xfrm_lifetime_cur curlft; -// struct xfrm_stats stats; -// __u32 seq; -// __u32 reqid; -// __u16 family; -// __u8 mode; /* XFRM_MODE_xxx */ -// __u8 replay_window; -// __u8 flags; -// #define XFRM_STATE_NOECN 1 -// #define XFRM_STATE_DECAP_DSCP 2 -// #define XFRM_STATE_NOPMTUDISC 4 -// #define XFRM_STATE_WILDRECV 8 -// #define XFRM_STATE_ICMP 16 -// #define XFRM_STATE_AF_UNSPEC 32 -// #define XFRM_STATE_ALIGN4 64 -// #define XFRM_STATE_ESN 128 -// }; -// -// #define XFRM_SA_XFLAG_DONT_ENCAP_DSCP 1 -// - -type XfrmUsersaInfo struct { - Sel XfrmSelector - Id XfrmId - Saddr XfrmAddress - Lft XfrmLifetimeCfg - Curlft XfrmLifetimeCur - Stats XfrmStats - Seq uint32 - Reqid uint32 - Family uint16 - Mode uint8 - ReplayWindow uint8 - Flags uint8 - Pad [7]byte -} - -func (msg *XfrmUsersaInfo) Len() int { - return SizeofXfrmUsersaInfo -} - -func DeserializeXfrmUsersaInfo(b []byte) *XfrmUsersaInfo { - return (*XfrmUsersaInfo)(unsafe.Pointer(&b[0:SizeofXfrmUsersaInfo][0])) -} - -func (msg *XfrmUsersaInfo) Serialize() []byte { - return (*(*[SizeofXfrmUsersaInfo]byte)(unsafe.Pointer(msg)))[:] -} - -// struct xfrm_userspi_info { -// struct xfrm_usersa_info info; -// __u32 min; -// __u32 max; -// }; - -type XfrmUserSpiInfo struct { - XfrmUsersaInfo XfrmUsersaInfo - Min uint32 - Max uint32 -} - -func (msg *XfrmUserSpiInfo) Len() int { - return SizeofXfrmUserSpiInfo -} - -func DeserializeXfrmUserSpiInfo(b []byte) *XfrmUserSpiInfo { - return (*XfrmUserSpiInfo)(unsafe.Pointer(&b[0:SizeofXfrmUserSpiInfo][0])) -} - -func (msg *XfrmUserSpiInfo) Serialize() []byte { - return (*(*[SizeofXfrmUserSpiInfo]byte)(unsafe.Pointer(msg)))[:] -} - -// struct xfrm_algo { -// char alg_name[64]; -// unsigned int alg_key_len; /* in bits */ -// char alg_key[0]; -// }; - -type XfrmAlgo struct { - AlgName [64]byte - AlgKeyLen uint32 - AlgKey []byte -} - -func (msg *XfrmAlgo) Len() int { - return SizeofXfrmAlgo + int(msg.AlgKeyLen/8) -} - -func DeserializeXfrmAlgo(b []byte) *XfrmAlgo { - ret := XfrmAlgo{} - copy(ret.AlgName[:], b[0:64]) - ret.AlgKeyLen = *(*uint32)(unsafe.Pointer(&b[64])) - ret.AlgKey = b[68:ret.Len()] - return &ret -} - -func (msg *XfrmAlgo) Serialize() []byte { - b := make([]byte, msg.Len()) - copy(b[0:64], msg.AlgName[:]) - copy(b[64:68], (*(*[4]byte)(unsafe.Pointer(&msg.AlgKeyLen)))[:]) - copy(b[68:msg.Len()], msg.AlgKey[:]) - return b -} - -// struct xfrm_algo_auth { -// char alg_name[64]; -// unsigned int alg_key_len; /* in bits */ -// unsigned int alg_trunc_len; /* in bits */ -// char alg_key[0]; -// }; - -type XfrmAlgoAuth struct { - AlgName [64]byte - AlgKeyLen uint32 - AlgTruncLen uint32 - AlgKey []byte -} - -func (msg *XfrmAlgoAuth) Len() int { - return SizeofXfrmAlgoAuth + int(msg.AlgKeyLen/8) -} - -func DeserializeXfrmAlgoAuth(b []byte) *XfrmAlgoAuth { - ret := XfrmAlgoAuth{} - copy(ret.AlgName[:], b[0:64]) - ret.AlgKeyLen = *(*uint32)(unsafe.Pointer(&b[64])) - ret.AlgTruncLen = *(*uint32)(unsafe.Pointer(&b[68])) - ret.AlgKey = b[72:ret.Len()] - return &ret -} - -func (msg *XfrmAlgoAuth) Serialize() []byte { - b := make([]byte, msg.Len()) - copy(b[0:64], msg.AlgName[:]) - copy(b[64:68], (*(*[4]byte)(unsafe.Pointer(&msg.AlgKeyLen)))[:]) - copy(b[68:72], (*(*[4]byte)(unsafe.Pointer(&msg.AlgTruncLen)))[:]) - copy(b[72:msg.Len()], msg.AlgKey[:]) - return b -} - -// struct xfrm_algo_aead { -// char alg_name[64]; -// unsigned int alg_key_len; /* in bits */ -// unsigned int alg_icv_len; /* in bits */ -// char alg_key[0]; -// } - -type XfrmAlgoAEAD struct { - AlgName [64]byte - AlgKeyLen uint32 - AlgICVLen uint32 - AlgKey []byte -} - -func (msg *XfrmAlgoAEAD) Len() int { - return SizeofXfrmAlgoAEAD + int(msg.AlgKeyLen/8) -} - -func DeserializeXfrmAlgoAEAD(b []byte) *XfrmAlgoAEAD { - ret := XfrmAlgoAEAD{} - copy(ret.AlgName[:], b[0:64]) - ret.AlgKeyLen = *(*uint32)(unsafe.Pointer(&b[64])) - ret.AlgICVLen = *(*uint32)(unsafe.Pointer(&b[68])) - ret.AlgKey = b[72:ret.Len()] - return &ret -} - -func (msg *XfrmAlgoAEAD) Serialize() []byte { - b := make([]byte, msg.Len()) - copy(b[0:64], msg.AlgName[:]) - copy(b[64:68], (*(*[4]byte)(unsafe.Pointer(&msg.AlgKeyLen)))[:]) - copy(b[68:72], (*(*[4]byte)(unsafe.Pointer(&msg.AlgICVLen)))[:]) - copy(b[72:msg.Len()], msg.AlgKey[:]) - return b -} - -// struct xfrm_encap_tmpl { -// __u16 encap_type; -// __be16 encap_sport; -// __be16 encap_dport; -// xfrm_address_t encap_oa; -// }; - -type XfrmEncapTmpl struct { - EncapType uint16 - EncapSport uint16 // big endian - EncapDport uint16 // big endian - Pad [2]byte - EncapOa XfrmAddress -} - -func (msg *XfrmEncapTmpl) Len() int { - return SizeofXfrmEncapTmpl -} - -func DeserializeXfrmEncapTmpl(b []byte) *XfrmEncapTmpl { - return (*XfrmEncapTmpl)(unsafe.Pointer(&b[0:SizeofXfrmEncapTmpl][0])) -} - -func (msg *XfrmEncapTmpl) Serialize() []byte { - return (*(*[SizeofXfrmEncapTmpl]byte)(unsafe.Pointer(msg)))[:] -} - -// struct xfrm_usersa_flush { -// __u8 proto; -// }; - -type XfrmUsersaFlush struct { - Proto uint8 -} - -func (msg *XfrmUsersaFlush) Len() int { - return SizeofXfrmUsersaFlush -} - -func DeserializeXfrmUsersaFlush(b []byte) *XfrmUsersaFlush { - return (*XfrmUsersaFlush)(unsafe.Pointer(&b[0:SizeofXfrmUsersaFlush][0])) -} - -func (msg *XfrmUsersaFlush) Serialize() []byte { - return (*(*[SizeofXfrmUsersaFlush]byte)(unsafe.Pointer(msg)))[:] -} - -// struct xfrm_replay_state_esn { -// unsigned int bmp_len; -// __u32 oseq; -// __u32 seq; -// __u32 oseq_hi; -// __u32 seq_hi; -// __u32 replay_window; -// __u32 bmp[0]; -// }; - -type XfrmReplayStateEsn struct { - BmpLen uint32 - OSeq uint32 - Seq uint32 - OSeqHi uint32 - SeqHi uint32 - ReplayWindow uint32 - Bmp []uint32 -} - -func (msg *XfrmReplayStateEsn) Serialize() []byte { - // We deliberately do not pass Bmp, as it gets set by the kernel. - return (*(*[SizeofXfrmReplayStateEsn]byte)(unsafe.Pointer(msg)))[:] -} diff --git a/vendor/github.com/vishvananda/netlink/order.go b/vendor/github.com/vishvananda/netlink/order.go deleted file mode 100644 index e28e153a1..000000000 --- a/vendor/github.com/vishvananda/netlink/order.go +++ /dev/null @@ -1,32 +0,0 @@ -package netlink - -import ( - "encoding/binary" - - "github.com/vishvananda/netlink/nl" -) - -var ( - native = nl.NativeEndian() - networkOrder = binary.BigEndian -) - -func htonl(val uint32) []byte { - bytes := make([]byte, 4) - binary.BigEndian.PutUint32(bytes, val) - return bytes -} - -func htons(val uint16) []byte { - bytes := make([]byte, 2) - binary.BigEndian.PutUint16(bytes, val) - return bytes -} - -func ntohl(buf []byte) uint32 { - return binary.BigEndian.Uint32(buf) -} - -func ntohs(buf []byte) uint16 { - return binary.BigEndian.Uint16(buf) -} diff --git a/vendor/github.com/vishvananda/netlink/protinfo.go b/vendor/github.com/vishvananda/netlink/protinfo.go deleted file mode 100644 index 60b23b374..000000000 --- a/vendor/github.com/vishvananda/netlink/protinfo.go +++ /dev/null @@ -1,62 +0,0 @@ -package netlink - -import ( - "strings" -) - -// Protinfo represents bridge flags from netlink. -type Protinfo struct { - Hairpin bool - Guard bool - FastLeave bool - RootBlock bool - Learning bool - Flood bool - ProxyArp bool - ProxyArpWiFi bool -} - -// String returns a list of enabled flags -func (prot *Protinfo) String() string { - if prot == nil { - return "" - } - - var boolStrings []string - if prot.Hairpin { - boolStrings = append(boolStrings, "Hairpin") - } - if prot.Guard { - boolStrings = append(boolStrings, "Guard") - } - if prot.FastLeave { - boolStrings = append(boolStrings, "FastLeave") - } - if prot.RootBlock { - boolStrings = append(boolStrings, "RootBlock") - } - if prot.Learning { - boolStrings = append(boolStrings, "Learning") - } - if prot.Flood { - boolStrings = append(boolStrings, "Flood") - } - if prot.ProxyArp { - boolStrings = append(boolStrings, "ProxyArp") - } - if prot.ProxyArpWiFi { - boolStrings = append(boolStrings, "ProxyArpWiFi") - } - return strings.Join(boolStrings, " ") -} - -func boolToByte(x bool) []byte { - if x { - return []byte{1} - } - return []byte{0} -} - -func byteToBool(x byte) bool { - return uint8(x) != 0 -} diff --git a/vendor/github.com/vishvananda/netlink/protinfo_linux.go b/vendor/github.com/vishvananda/netlink/protinfo_linux.go deleted file mode 100644 index 15b65123c..000000000 --- a/vendor/github.com/vishvananda/netlink/protinfo_linux.go +++ /dev/null @@ -1,74 +0,0 @@ -package netlink - -import ( - "fmt" - "syscall" - - "github.com/vishvananda/netlink/nl" - "golang.org/x/sys/unix" -) - -func LinkGetProtinfo(link Link) (Protinfo, error) { - return pkgHandle.LinkGetProtinfo(link) -} - -func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) { - base := link.Attrs() - h.ensureIndex(base) - var pi Protinfo - req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP) - msg := nl.NewIfInfomsg(unix.AF_BRIDGE) - req.AddData(msg) - msgs, err := req.Execute(unix.NETLINK_ROUTE, 0) - if err != nil { - return pi, err - } - - for _, m := range msgs { - ans := nl.DeserializeIfInfomsg(m) - if int(ans.Index) != base.Index { - continue - } - attrs, err := nl.ParseRouteAttr(m[ans.Len():]) - if err != nil { - return pi, err - } - for _, attr := range attrs { - if attr.Attr.Type != unix.IFLA_PROTINFO|unix.NLA_F_NESTED { - continue - } - infos, err := nl.ParseRouteAttr(attr.Value) - if err != nil { - return pi, err - } - pi = parseProtinfo(infos) - - return pi, nil - } - } - return pi, fmt.Errorf("Device with index %d not found", base.Index) -} - -func parseProtinfo(infos []syscall.NetlinkRouteAttr) (pi Protinfo) { - for _, info := range infos { - switch info.Attr.Type { - case nl.IFLA_BRPORT_MODE: - pi.Hairpin = byteToBool(info.Value[0]) - case nl.IFLA_BRPORT_GUARD: - pi.Guard = byteToBool(info.Value[0]) - case nl.IFLA_BRPORT_FAST_LEAVE: - pi.FastLeave = byteToBool(info.Value[0]) - case nl.IFLA_BRPORT_PROTECT: - pi.RootBlock = byteToBool(info.Value[0]) - case nl.IFLA_BRPORT_LEARNING: - pi.Learning = byteToBool(info.Value[0]) - case nl.IFLA_BRPORT_UNICAST_FLOOD: - pi.Flood = byteToBool(info.Value[0]) - case nl.IFLA_BRPORT_PROXYARP: - pi.ProxyArp = byteToBool(info.Value[0]) - case nl.IFLA_BRPORT_PROXYARP_WIFI: - pi.ProxyArpWiFi = byteToBool(info.Value[0]) - } - } - return -} diff --git a/vendor/github.com/vishvananda/netlink/qdisc.go b/vendor/github.com/vishvananda/netlink/qdisc.go deleted file mode 100644 index af78305ac..000000000 --- a/vendor/github.com/vishvananda/netlink/qdisc.go +++ /dev/null @@ -1,340 +0,0 @@ -package netlink - -import ( - "fmt" - "math" -) - -const ( - HANDLE_NONE = 0 - HANDLE_INGRESS = 0xFFFFFFF1 - HANDLE_CLSACT = HANDLE_INGRESS - HANDLE_ROOT = 0xFFFFFFFF - PRIORITY_MAP_LEN = 16 -) -const ( - HANDLE_MIN_INGRESS = 0xFFFFFFF2 - HANDLE_MIN_EGRESS = 0xFFFFFFF3 -) - -type Qdisc interface { - Attrs() *QdiscAttrs - Type() string -} - -// QdiscAttrs represents a netlink qdisc. A qdisc is associated with a link, -// has a handle, a parent and a refcnt. The root qdisc of a device should -// have parent == HANDLE_ROOT. -type QdiscAttrs struct { - LinkIndex int - Handle uint32 - Parent uint32 - Refcnt uint32 // read only -} - -func (q QdiscAttrs) String() string { - return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Refcnt: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Refcnt) -} - -func MakeHandle(major, minor uint16) uint32 { - return (uint32(major) << 16) | uint32(minor) -} - -func MajorMinor(handle uint32) (uint16, uint16) { - return uint16((handle & 0xFFFF0000) >> 16), uint16(handle & 0x0000FFFFF) -} - -func HandleStr(handle uint32) string { - switch handle { - case HANDLE_NONE: - return "none" - case HANDLE_INGRESS: - return "ingress" - case HANDLE_ROOT: - return "root" - default: - major, minor := MajorMinor(handle) - return fmt.Sprintf("%x:%x", major, minor) - } -} - -func Percentage2u32(percentage float32) uint32 { - // FIXME this is most likely not the best way to convert from % to uint32 - if percentage == 100 { - return math.MaxUint32 - } - return uint32(math.MaxUint32 * (percentage / 100)) -} - -// PfifoFast is the default qdisc created by the kernel if one has not -// been defined for the interface -type PfifoFast struct { - QdiscAttrs - Bands uint8 - PriorityMap [PRIORITY_MAP_LEN]uint8 -} - -func (qdisc *PfifoFast) Attrs() *QdiscAttrs { - return &qdisc.QdiscAttrs -} - -func (qdisc *PfifoFast) Type() string { - return "pfifo_fast" -} - -// Prio is a basic qdisc that works just like PfifoFast -type Prio struct { - QdiscAttrs - Bands uint8 - PriorityMap [PRIORITY_MAP_LEN]uint8 -} - -func NewPrio(attrs QdiscAttrs) *Prio { - return &Prio{ - QdiscAttrs: attrs, - Bands: 3, - PriorityMap: [PRIORITY_MAP_LEN]uint8{1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, - } -} - -func (qdisc *Prio) Attrs() *QdiscAttrs { - return &qdisc.QdiscAttrs -} - -func (qdisc *Prio) Type() string { - return "prio" -} - -// Htb is a classful qdisc that rate limits based on tokens -type Htb struct { - QdiscAttrs - Version uint32 - Rate2Quantum uint32 - Defcls uint32 - Debug uint32 - DirectPkts uint32 -} - -func NewHtb(attrs QdiscAttrs) *Htb { - return &Htb{ - QdiscAttrs: attrs, - Version: 3, - Defcls: 0, - Rate2Quantum: 10, - Debug: 0, - DirectPkts: 0, - } -} - -func (qdisc *Htb) Attrs() *QdiscAttrs { - return &qdisc.QdiscAttrs -} - -func (qdisc *Htb) Type() string { - return "htb" -} - -// Netem is a classless qdisc that rate limits based on tokens - -type NetemQdiscAttrs struct { - Latency uint32 // in us - DelayCorr float32 // in % - Limit uint32 - Loss float32 // in % - LossCorr float32 // in % - Gap uint32 - Duplicate float32 // in % - DuplicateCorr float32 // in % - Jitter uint32 // in us - ReorderProb float32 // in % - ReorderCorr float32 // in % - CorruptProb float32 // in % - CorruptCorr float32 // in % -} - -func (q NetemQdiscAttrs) String() string { - return fmt.Sprintf( - "{Latency: %d, Limit: %d, Loss: %f, Gap: %d, Duplicate: %f, Jitter: %d}", - q.Latency, q.Limit, q.Loss, q.Gap, q.Duplicate, q.Jitter, - ) -} - -type Netem struct { - QdiscAttrs - Latency uint32 - DelayCorr uint32 - Limit uint32 - Loss uint32 - LossCorr uint32 - Gap uint32 - Duplicate uint32 - DuplicateCorr uint32 - Jitter uint32 - ReorderProb uint32 - ReorderCorr uint32 - CorruptProb uint32 - CorruptCorr uint32 -} - -func (netem *Netem) String() string { - return fmt.Sprintf( - "{Latency: %v, Limit: %v, Loss: %v, Gap: %v, Duplicate: %v, Jitter: %v}", - netem.Latency, netem.Limit, netem.Loss, netem.Gap, netem.Duplicate, netem.Jitter, - ) -} - -func (qdisc *Netem) Attrs() *QdiscAttrs { - return &qdisc.QdiscAttrs -} - -func (qdisc *Netem) Type() string { - return "netem" -} - -// Tbf is a classless qdisc that rate limits based on tokens -type Tbf struct { - QdiscAttrs - Rate uint64 - Limit uint32 - Buffer uint32 - Peakrate uint64 - Minburst uint32 - // TODO: handle other settings -} - -func (qdisc *Tbf) Attrs() *QdiscAttrs { - return &qdisc.QdiscAttrs -} - -func (qdisc *Tbf) Type() string { - return "tbf" -} - -// Ingress is a qdisc for adding ingress filters -type Ingress struct { - QdiscAttrs -} - -func (qdisc *Ingress) Attrs() *QdiscAttrs { - return &qdisc.QdiscAttrs -} - -func (qdisc *Ingress) Type() string { - return "ingress" -} - -// GenericQdisc qdiscs represent types that are not currently understood -// by this netlink library. -type GenericQdisc struct { - QdiscAttrs - QdiscType string -} - -func (qdisc *GenericQdisc) Attrs() *QdiscAttrs { - return &qdisc.QdiscAttrs -} - -func (qdisc *GenericQdisc) Type() string { - return qdisc.QdiscType -} - -type Hfsc struct { - QdiscAttrs - Defcls uint16 -} - -func NewHfsc(attrs QdiscAttrs) *Hfsc { - return &Hfsc{ - QdiscAttrs: attrs, - Defcls: 1, - } -} - -func (hfsc *Hfsc) Attrs() *QdiscAttrs { - return &hfsc.QdiscAttrs -} - -func (hfsc *Hfsc) Type() string { - return "hfsc" -} - -func (hfsc *Hfsc) String() string { - return fmt.Sprintf( - "{%v -- default: %d}", - hfsc.Attrs(), hfsc.Defcls, - ) -} - -// Fq is a classless packet scheduler meant to be mostly used for locally generated traffic. -type Fq struct { - QdiscAttrs - PacketLimit uint32 - FlowPacketLimit uint32 - // In bytes - Quantum uint32 - InitialQuantum uint32 - // called RateEnable under the hood - Pacing uint32 - FlowDefaultRate uint32 - FlowMaxRate uint32 - // called BucketsLog under the hood - Buckets uint32 - FlowRefillDelay uint32 - LowRateThreshold uint32 -} - -func (fq *Fq) String() string { - return fmt.Sprintf( - "{PacketLimit: %v, FlowPacketLimit: %v, Quantum: %v, InitialQuantum: %v, Pacing: %v, FlowDefaultRate: %v, FlowMaxRate: %v, Buckets: %v, FlowRefillDelay: %v, LowRateThreshold: %v}", - fq.PacketLimit, fq.FlowPacketLimit, fq.Quantum, fq.InitialQuantum, fq.Pacing, fq.FlowDefaultRate, fq.FlowMaxRate, fq.Buckets, fq.FlowRefillDelay, fq.LowRateThreshold, - ) -} - -func NewFq(attrs QdiscAttrs) *Fq { - return &Fq{ - QdiscAttrs: attrs, - Pacing: 1, - } -} - -func (qdisc *Fq) Attrs() *QdiscAttrs { - return &qdisc.QdiscAttrs -} - -func (qdisc *Fq) Type() string { - return "fq" -} - -// FQ_Codel (Fair Queuing Controlled Delay) is queuing discipline that combines Fair Queuing with the CoDel AQM scheme. -type FqCodel struct { - QdiscAttrs - Target uint32 - Limit uint32 - Interval uint32 - ECN uint32 - Flows uint32 - Quantum uint32 - // There are some more attributes here, but support for them seems not ubiquitous -} - -func (fqcodel *FqCodel) String() string { - return fmt.Sprintf( - "{%v -- Target: %v, Limit: %v, Interval: %v, ECM: %v, Flows: %v, Quantum: %v}", - fqcodel.Attrs(), fqcodel.Target, fqcodel.Limit, fqcodel.Interval, fqcodel.ECN, fqcodel.Flows, fqcodel.Quantum, - ) -} - -func NewFqCodel(attrs QdiscAttrs) *FqCodel { - return &FqCodel{ - QdiscAttrs: attrs, - ECN: 1, - } -} - -func (qdisc *FqCodel) Attrs() *QdiscAttrs { - return &qdisc.QdiscAttrs -} - -func (qdisc *FqCodel) Type() string { - return "fq_codel" -} diff --git a/vendor/github.com/vishvananda/netlink/qdisc_linux.go b/vendor/github.com/vishvananda/netlink/qdisc_linux.go deleted file mode 100644 index e9eee5908..000000000 --- a/vendor/github.com/vishvananda/netlink/qdisc_linux.go +++ /dev/null @@ -1,668 +0,0 @@ -package netlink - -import ( - "fmt" - "io/ioutil" - "strconv" - "strings" - "syscall" - - "github.com/vishvananda/netlink/nl" - "golang.org/x/sys/unix" -) - -// NOTE function is here because it uses other linux functions -func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem { - var limit uint32 = 1000 - var lossCorr, delayCorr, duplicateCorr uint32 - var reorderProb, reorderCorr uint32 - var corruptProb, corruptCorr uint32 - - latency := nattrs.Latency - loss := Percentage2u32(nattrs.Loss) - gap := nattrs.Gap - duplicate := Percentage2u32(nattrs.Duplicate) - jitter := nattrs.Jitter - - // Correlation - if latency > 0 && jitter > 0 { - delayCorr = Percentage2u32(nattrs.DelayCorr) - } - if loss > 0 { - lossCorr = Percentage2u32(nattrs.LossCorr) - } - if duplicate > 0 { - duplicateCorr = Percentage2u32(nattrs.DuplicateCorr) - } - // FIXME should validate values(like loss/duplicate are percentages...) - latency = time2Tick(latency) - - if nattrs.Limit != 0 { - limit = nattrs.Limit - } - // Jitter is only value if latency is > 0 - if latency > 0 { - jitter = time2Tick(jitter) - } - - reorderProb = Percentage2u32(nattrs.ReorderProb) - reorderCorr = Percentage2u32(nattrs.ReorderCorr) - - if reorderProb > 0 { - // ERROR if lantency == 0 - if gap == 0 { - gap = 1 - } - } - - corruptProb = Percentage2u32(nattrs.CorruptProb) - corruptCorr = Percentage2u32(nattrs.CorruptCorr) - - return &Netem{ - QdiscAttrs: attrs, - Latency: latency, - DelayCorr: delayCorr, - Limit: limit, - Loss: loss, - LossCorr: lossCorr, - Gap: gap, - Duplicate: duplicate, - DuplicateCorr: duplicateCorr, - Jitter: jitter, - ReorderProb: reorderProb, - ReorderCorr: reorderCorr, - CorruptProb: corruptProb, - CorruptCorr: corruptCorr, - } -} - -// QdiscDel will delete a qdisc from the system. -// Equivalent to: `tc qdisc del $qdisc` -func QdiscDel(qdisc Qdisc) error { - return pkgHandle.QdiscDel(qdisc) -} - -// QdiscDel will delete a qdisc from the system. -// Equivalent to: `tc qdisc del $qdisc` -func (h *Handle) QdiscDel(qdisc Qdisc) error { - return h.qdiscModify(unix.RTM_DELQDISC, 0, qdisc) -} - -// QdiscChange will change a qdisc in place -// Equivalent to: `tc qdisc change $qdisc` -// The parent and handle MUST NOT be changed. -func QdiscChange(qdisc Qdisc) error { - return pkgHandle.QdiscChange(qdisc) -} - -// QdiscChange will change a qdisc in place -// Equivalent to: `tc qdisc change $qdisc` -// The parent and handle MUST NOT be changed. -func (h *Handle) QdiscChange(qdisc Qdisc) error { - return h.qdiscModify(unix.RTM_NEWQDISC, 0, qdisc) -} - -// QdiscReplace will replace a qdisc to the system. -// Equivalent to: `tc qdisc replace $qdisc` -// The handle MUST change. -func QdiscReplace(qdisc Qdisc) error { - return pkgHandle.QdiscReplace(qdisc) -} - -// QdiscReplace will replace a qdisc to the system. -// Equivalent to: `tc qdisc replace $qdisc` -// The handle MUST change. -func (h *Handle) QdiscReplace(qdisc Qdisc) error { - return h.qdiscModify( - unix.RTM_NEWQDISC, - unix.NLM_F_CREATE|unix.NLM_F_REPLACE, - qdisc) -} - -// QdiscAdd will add a qdisc to the system. -// Equivalent to: `tc qdisc add $qdisc` -func QdiscAdd(qdisc Qdisc) error { - return pkgHandle.QdiscAdd(qdisc) -} - -// QdiscAdd will add a qdisc to the system. -// Equivalent to: `tc qdisc add $qdisc` -func (h *Handle) QdiscAdd(qdisc Qdisc) error { - return h.qdiscModify( - unix.RTM_NEWQDISC, - unix.NLM_F_CREATE|unix.NLM_F_EXCL, - qdisc) -} - -func (h *Handle) qdiscModify(cmd, flags int, qdisc Qdisc) error { - req := h.newNetlinkRequest(cmd, flags|unix.NLM_F_ACK) - base := qdisc.Attrs() - msg := &nl.TcMsg{ - Family: nl.FAMILY_ALL, - Ifindex: int32(base.LinkIndex), - Handle: base.Handle, - Parent: base.Parent, - } - req.AddData(msg) - - // When deleting don't bother building the rest of the netlink payload - if cmd != unix.RTM_DELQDISC { - if err := qdiscPayload(req, qdisc); err != nil { - return err - } - } - - _, err := req.Execute(unix.NETLINK_ROUTE, 0) - return err -} - -func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error { - - req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(qdisc.Type()))) - - options := nl.NewRtAttr(nl.TCA_OPTIONS, nil) - - switch qdisc := qdisc.(type) { - case *Prio: - tcmap := nl.TcPrioMap{ - Bands: int32(qdisc.Bands), - Priomap: qdisc.PriorityMap, - } - options = nl.NewRtAttr(nl.TCA_OPTIONS, tcmap.Serialize()) - case *Tbf: - opt := nl.TcTbfQopt{} - opt.Rate.Rate = uint32(qdisc.Rate) - opt.Peakrate.Rate = uint32(qdisc.Peakrate) - opt.Limit = qdisc.Limit - opt.Buffer = qdisc.Buffer - options.AddRtAttr(nl.TCA_TBF_PARMS, opt.Serialize()) - if qdisc.Rate >= uint64(1<<32) { - options.AddRtAttr(nl.TCA_TBF_RATE64, nl.Uint64Attr(qdisc.Rate)) - } - if qdisc.Peakrate >= uint64(1<<32) { - options.AddRtAttr(nl.TCA_TBF_PRATE64, nl.Uint64Attr(qdisc.Peakrate)) - } - if qdisc.Peakrate > 0 { - options.AddRtAttr(nl.TCA_TBF_PBURST, nl.Uint32Attr(qdisc.Minburst)) - } - case *Htb: - opt := nl.TcHtbGlob{} - opt.Version = qdisc.Version - opt.Rate2Quantum = qdisc.Rate2Quantum - opt.Defcls = qdisc.Defcls - // TODO: Handle Debug properly. For now default to 0 - opt.Debug = qdisc.Debug - opt.DirectPkts = qdisc.DirectPkts - options.AddRtAttr(nl.TCA_HTB_INIT, opt.Serialize()) - // options.AddRtAttr(nl.TCA_HTB_DIRECT_QLEN, opt.Serialize()) - case *Hfsc: - opt := nl.TcHfscOpt{} - opt.Defcls = qdisc.Defcls - options = nl.NewRtAttr(nl.TCA_OPTIONS, opt.Serialize()) - case *Netem: - opt := nl.TcNetemQopt{} - opt.Latency = qdisc.Latency - opt.Limit = qdisc.Limit - opt.Loss = qdisc.Loss - opt.Gap = qdisc.Gap - opt.Duplicate = qdisc.Duplicate - opt.Jitter = qdisc.Jitter - options = nl.NewRtAttr(nl.TCA_OPTIONS, opt.Serialize()) - // Correlation - corr := nl.TcNetemCorr{} - corr.DelayCorr = qdisc.DelayCorr - corr.LossCorr = qdisc.LossCorr - corr.DupCorr = qdisc.DuplicateCorr - - if corr.DelayCorr > 0 || corr.LossCorr > 0 || corr.DupCorr > 0 { - options.AddRtAttr(nl.TCA_NETEM_CORR, corr.Serialize()) - } - // Corruption - corruption := nl.TcNetemCorrupt{} - corruption.Probability = qdisc.CorruptProb - corruption.Correlation = qdisc.CorruptCorr - if corruption.Probability > 0 { - options.AddRtAttr(nl.TCA_NETEM_CORRUPT, corruption.Serialize()) - } - // Reorder - reorder := nl.TcNetemReorder{} - reorder.Probability = qdisc.ReorderProb - reorder.Correlation = qdisc.ReorderCorr - if reorder.Probability > 0 { - options.AddRtAttr(nl.TCA_NETEM_REORDER, reorder.Serialize()) - } - case *Ingress: - // ingress filters must use the proper handle - if qdisc.Attrs().Parent != HANDLE_INGRESS { - return fmt.Errorf("Ingress filters must set Parent to HANDLE_INGRESS") - } - case *FqCodel: - options.AddRtAttr(nl.TCA_FQ_CODEL_ECN, nl.Uint32Attr((uint32(qdisc.ECN)))) - if qdisc.Limit > 0 { - options.AddRtAttr(nl.TCA_FQ_CODEL_LIMIT, nl.Uint32Attr((uint32(qdisc.Limit)))) - } - if qdisc.Interval > 0 { - options.AddRtAttr(nl.TCA_FQ_CODEL_INTERVAL, nl.Uint32Attr((uint32(qdisc.Interval)))) - } - if qdisc.Flows > 0 { - options.AddRtAttr(nl.TCA_FQ_CODEL_FLOWS, nl.Uint32Attr((uint32(qdisc.Flows)))) - } - if qdisc.Quantum > 0 { - options.AddRtAttr(nl.TCA_FQ_CODEL_QUANTUM, nl.Uint32Attr((uint32(qdisc.Quantum)))) - } - - case *Fq: - options.AddRtAttr(nl.TCA_FQ_RATE_ENABLE, nl.Uint32Attr((uint32(qdisc.Pacing)))) - - if qdisc.Buckets > 0 { - options.AddRtAttr(nl.TCA_FQ_BUCKETS_LOG, nl.Uint32Attr((uint32(qdisc.Buckets)))) - } - if qdisc.LowRateThreshold > 0 { - options.AddRtAttr(nl.TCA_FQ_LOW_RATE_THRESHOLD, nl.Uint32Attr((uint32(qdisc.LowRateThreshold)))) - } - if qdisc.Quantum > 0 { - options.AddRtAttr(nl.TCA_FQ_QUANTUM, nl.Uint32Attr((uint32(qdisc.Quantum)))) - } - if qdisc.InitialQuantum > 0 { - options.AddRtAttr(nl.TCA_FQ_INITIAL_QUANTUM, nl.Uint32Attr((uint32(qdisc.InitialQuantum)))) - } - if qdisc.FlowRefillDelay > 0 { - options.AddRtAttr(nl.TCA_FQ_FLOW_REFILL_DELAY, nl.Uint32Attr((uint32(qdisc.FlowRefillDelay)))) - } - if qdisc.FlowPacketLimit > 0 { - options.AddRtAttr(nl.TCA_FQ_FLOW_PLIMIT, nl.Uint32Attr((uint32(qdisc.FlowPacketLimit)))) - } - if qdisc.FlowMaxRate > 0 { - options.AddRtAttr(nl.TCA_FQ_FLOW_MAX_RATE, nl.Uint32Attr((uint32(qdisc.FlowMaxRate)))) - } - if qdisc.FlowDefaultRate > 0 { - options.AddRtAttr(nl.TCA_FQ_FLOW_DEFAULT_RATE, nl.Uint32Attr((uint32(qdisc.FlowDefaultRate)))) - } - default: - options = nil - } - - if options != nil { - req.AddData(options) - } - return nil -} - -// QdiscList gets a list of qdiscs in the system. -// Equivalent to: `tc qdisc show`. -// The list can be filtered by link. -func QdiscList(link Link) ([]Qdisc, error) { - return pkgHandle.QdiscList(link) -} - -// QdiscList gets a list of qdiscs in the system. -// Equivalent to: `tc qdisc show`. -// The list can be filtered by link. -func (h *Handle) QdiscList(link Link) ([]Qdisc, error) { - req := h.newNetlinkRequest(unix.RTM_GETQDISC, unix.NLM_F_DUMP) - index := int32(0) - if link != nil { - base := link.Attrs() - h.ensureIndex(base) - index = int32(base.Index) - } - msg := &nl.TcMsg{ - Family: nl.FAMILY_ALL, - Ifindex: index, - } - req.AddData(msg) - - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWQDISC) - if err != nil { - return nil, err - } - - var res []Qdisc - for _, m := range msgs { - msg := nl.DeserializeTcMsg(m) - - attrs, err := nl.ParseRouteAttr(m[msg.Len():]) - if err != nil { - return nil, err - } - - // skip qdiscs from other interfaces - if link != nil && msg.Ifindex != index { - continue - } - - base := QdiscAttrs{ - LinkIndex: int(msg.Ifindex), - Handle: msg.Handle, - Parent: msg.Parent, - Refcnt: msg.Info, - } - var qdisc Qdisc - qdiscType := "" - for _, attr := range attrs { - switch attr.Attr.Type { - case nl.TCA_KIND: - qdiscType = string(attr.Value[:len(attr.Value)-1]) - switch qdiscType { - case "pfifo_fast": - qdisc = &PfifoFast{} - case "prio": - qdisc = &Prio{} - case "tbf": - qdisc = &Tbf{} - case "ingress": - qdisc = &Ingress{} - case "htb": - qdisc = &Htb{} - case "fq": - qdisc = &Fq{} - case "hfsc": - qdisc = &Hfsc{} - case "fq_codel": - qdisc = &FqCodel{} - case "netem": - qdisc = &Netem{} - default: - qdisc = &GenericQdisc{QdiscType: qdiscType} - } - case nl.TCA_OPTIONS: - switch qdiscType { - case "pfifo_fast": - // pfifo returns TcPrioMap directly without wrapping it in rtattr - if err := parsePfifoFastData(qdisc, attr.Value); err != nil { - return nil, err - } - case "prio": - // prio returns TcPrioMap directly without wrapping it in rtattr - if err := parsePrioData(qdisc, attr.Value); err != nil { - return nil, err - } - case "tbf": - data, err := nl.ParseRouteAttr(attr.Value) - if err != nil { - return nil, err - } - if err := parseTbfData(qdisc, data); err != nil { - return nil, err - } - case "hfsc": - if err := parseHfscData(qdisc, attr.Value); err != nil { - return nil, err - } - case "htb": - data, err := nl.ParseRouteAttr(attr.Value) - if err != nil { - return nil, err - } - if err := parseHtbData(qdisc, data); err != nil { - return nil, err - } - case "fq": - data, err := nl.ParseRouteAttr(attr.Value) - if err != nil { - return nil, err - } - if err := parseFqData(qdisc, data); err != nil { - return nil, err - } - case "fq_codel": - data, err := nl.ParseRouteAttr(attr.Value) - if err != nil { - return nil, err - } - if err := parseFqCodelData(qdisc, data); err != nil { - return nil, err - } - case "netem": - if err := parseNetemData(qdisc, attr.Value); err != nil { - return nil, err - } - - // no options for ingress - } - } - } - *qdisc.Attrs() = base - res = append(res, qdisc) - } - - return res, nil -} - -func parsePfifoFastData(qdisc Qdisc, value []byte) error { - pfifo := qdisc.(*PfifoFast) - tcmap := nl.DeserializeTcPrioMap(value) - pfifo.PriorityMap = tcmap.Priomap - pfifo.Bands = uint8(tcmap.Bands) - return nil -} - -func parsePrioData(qdisc Qdisc, value []byte) error { - prio := qdisc.(*Prio) - tcmap := nl.DeserializeTcPrioMap(value) - prio.PriorityMap = tcmap.Priomap - prio.Bands = uint8(tcmap.Bands) - return nil -} - -func parseHtbData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { - native = nl.NativeEndian() - htb := qdisc.(*Htb) - for _, datum := range data { - switch datum.Attr.Type { - case nl.TCA_HTB_INIT: - opt := nl.DeserializeTcHtbGlob(datum.Value) - htb.Version = opt.Version - htb.Rate2Quantum = opt.Rate2Quantum - htb.Defcls = opt.Defcls - htb.Debug = opt.Debug - htb.DirectPkts = opt.DirectPkts - case nl.TCA_HTB_DIRECT_QLEN: - // TODO - //htb.DirectQlen = native.uint32(datum.Value) - } - } - return nil -} - -func parseFqCodelData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { - native = nl.NativeEndian() - fqCodel := qdisc.(*FqCodel) - for _, datum := range data { - - switch datum.Attr.Type { - case nl.TCA_FQ_CODEL_TARGET: - fqCodel.Target = native.Uint32(datum.Value) - case nl.TCA_FQ_CODEL_LIMIT: - fqCodel.Limit = native.Uint32(datum.Value) - case nl.TCA_FQ_CODEL_INTERVAL: - fqCodel.Interval = native.Uint32(datum.Value) - case nl.TCA_FQ_CODEL_ECN: - fqCodel.ECN = native.Uint32(datum.Value) - case nl.TCA_FQ_CODEL_FLOWS: - fqCodel.Flows = native.Uint32(datum.Value) - case nl.TCA_FQ_CODEL_QUANTUM: - fqCodel.Quantum = native.Uint32(datum.Value) - } - } - return nil -} - -func parseHfscData(qdisc Qdisc, data []byte) error { - Hfsc := qdisc.(*Hfsc) - native = nl.NativeEndian() - Hfsc.Defcls = native.Uint16(data) - return nil -} - -func parseFqData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { - native = nl.NativeEndian() - fq := qdisc.(*Fq) - for _, datum := range data { - switch datum.Attr.Type { - case nl.TCA_FQ_BUCKETS_LOG: - fq.Buckets = native.Uint32(datum.Value) - case nl.TCA_FQ_LOW_RATE_THRESHOLD: - fq.LowRateThreshold = native.Uint32(datum.Value) - case nl.TCA_FQ_QUANTUM: - fq.Quantum = native.Uint32(datum.Value) - case nl.TCA_FQ_RATE_ENABLE: - fq.Pacing = native.Uint32(datum.Value) - case nl.TCA_FQ_INITIAL_QUANTUM: - fq.InitialQuantum = native.Uint32(datum.Value) - case nl.TCA_FQ_ORPHAN_MASK: - // TODO - case nl.TCA_FQ_FLOW_REFILL_DELAY: - fq.FlowRefillDelay = native.Uint32(datum.Value) - case nl.TCA_FQ_FLOW_PLIMIT: - fq.FlowPacketLimit = native.Uint32(datum.Value) - case nl.TCA_FQ_PLIMIT: - fq.PacketLimit = native.Uint32(datum.Value) - case nl.TCA_FQ_FLOW_MAX_RATE: - fq.FlowMaxRate = native.Uint32(datum.Value) - case nl.TCA_FQ_FLOW_DEFAULT_RATE: - fq.FlowDefaultRate = native.Uint32(datum.Value) - } - } - return nil -} - -func parseNetemData(qdisc Qdisc, value []byte) error { - netem := qdisc.(*Netem) - opt := nl.DeserializeTcNetemQopt(value) - netem.Latency = opt.Latency - netem.Limit = opt.Limit - netem.Loss = opt.Loss - netem.Gap = opt.Gap - netem.Duplicate = opt.Duplicate - netem.Jitter = opt.Jitter - data, err := nl.ParseRouteAttr(value[nl.SizeofTcNetemQopt:]) - if err != nil { - return err - } - for _, datum := range data { - switch datum.Attr.Type { - case nl.TCA_NETEM_CORR: - opt := nl.DeserializeTcNetemCorr(datum.Value) - netem.DelayCorr = opt.DelayCorr - netem.LossCorr = opt.LossCorr - netem.DuplicateCorr = opt.DupCorr - case nl.TCA_NETEM_CORRUPT: - opt := nl.DeserializeTcNetemCorrupt(datum.Value) - netem.CorruptProb = opt.Probability - netem.CorruptCorr = opt.Correlation - case nl.TCA_NETEM_REORDER: - opt := nl.DeserializeTcNetemReorder(datum.Value) - netem.ReorderProb = opt.Probability - netem.ReorderCorr = opt.Correlation - } - } - return nil -} - -func parseTbfData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { - native = nl.NativeEndian() - tbf := qdisc.(*Tbf) - for _, datum := range data { - switch datum.Attr.Type { - case nl.TCA_TBF_PARMS: - opt := nl.DeserializeTcTbfQopt(datum.Value) - tbf.Rate = uint64(opt.Rate.Rate) - tbf.Peakrate = uint64(opt.Peakrate.Rate) - tbf.Limit = opt.Limit - tbf.Buffer = opt.Buffer - case nl.TCA_TBF_RATE64: - tbf.Rate = native.Uint64(datum.Value[0:8]) - case nl.TCA_TBF_PRATE64: - tbf.Peakrate = native.Uint64(datum.Value[0:8]) - case nl.TCA_TBF_PBURST: - tbf.Minburst = native.Uint32(datum.Value[0:4]) - } - } - return nil -} - -const ( - TIME_UNITS_PER_SEC = 1000000 -) - -var ( - tickInUsec float64 - clockFactor float64 - hz float64 -) - -func initClock() { - data, err := ioutil.ReadFile("/proc/net/psched") - if err != nil { - return - } - parts := strings.Split(strings.TrimSpace(string(data)), " ") - if len(parts) < 3 { - return - } - var vals [3]uint64 - for i := range vals { - val, err := strconv.ParseUint(parts[i], 16, 32) - if err != nil { - return - } - vals[i] = val - } - // compatibility - if vals[2] == 1000000000 { - vals[0] = vals[1] - } - clockFactor = float64(vals[2]) / TIME_UNITS_PER_SEC - tickInUsec = float64(vals[0]) / float64(vals[1]) * clockFactor - hz = float64(vals[0]) -} - -func TickInUsec() float64 { - if tickInUsec == 0.0 { - initClock() - } - return tickInUsec -} - -func ClockFactor() float64 { - if clockFactor == 0.0 { - initClock() - } - return clockFactor -} - -func Hz() float64 { - if hz == 0.0 { - initClock() - } - return hz -} - -func time2Tick(time uint32) uint32 { - return uint32(float64(time) * TickInUsec()) -} - -func tick2Time(tick uint32) uint32 { - return uint32(float64(tick) / TickInUsec()) -} - -func time2Ktime(time uint32) uint32 { - return uint32(float64(time) * ClockFactor()) -} - -func ktime2Time(ktime uint32) uint32 { - return uint32(float64(ktime) / ClockFactor()) -} - -func burst(rate uint64, buffer uint32) uint32 { - return uint32(float64(rate) * float64(tick2Time(buffer)) / TIME_UNITS_PER_SEC) -} - -func latency(rate uint64, limit, buffer uint32) float64 { - return TIME_UNITS_PER_SEC*(float64(limit)/float64(rate)) - float64(tick2Time(buffer)) -} - -func Xmittime(rate uint64, size uint32) float64 { - return TickInUsec() * TIME_UNITS_PER_SEC * (float64(size) / float64(rate)) -} diff --git a/vendor/github.com/vishvananda/netlink/rdma_link_linux.go b/vendor/github.com/vishvananda/netlink/rdma_link_linux.go deleted file mode 100644 index 2d0bdc8c3..000000000 --- a/vendor/github.com/vishvananda/netlink/rdma_link_linux.go +++ /dev/null @@ -1,264 +0,0 @@ -package netlink - -import ( - "bytes" - "encoding/binary" - "fmt" - "net" - - "github.com/vishvananda/netlink/nl" - "golang.org/x/sys/unix" -) - -// LinkAttrs represents data shared by most link types -type RdmaLinkAttrs struct { - Index uint32 - Name string - FirmwareVersion string - NodeGuid string - SysImageGuid string -} - -// Link represents a rdma device from netlink. -type RdmaLink struct { - Attrs RdmaLinkAttrs -} - -func getProtoField(clientType int, op int) int { - return ((clientType << nl.RDMA_NL_GET_CLIENT_SHIFT) | op) -} - -func uint64ToGuidString(guid uint64) string { - //Convert to byte array - sysGuidBytes := new(bytes.Buffer) - binary.Write(sysGuidBytes, binary.LittleEndian, guid) - - //Convert to HardwareAddr - sysGuidNet := net.HardwareAddr(sysGuidBytes.Bytes()) - - //Get the String - return sysGuidNet.String() -} - -func executeOneGetRdmaLink(data []byte) (*RdmaLink, error) { - - link := RdmaLink{} - - reader := bytes.NewReader(data) - for reader.Len() >= 4 { - _, attrType, len, value := parseNfAttrTLV(reader) - - switch attrType { - case nl.RDMA_NLDEV_ATTR_DEV_INDEX: - var Index uint32 - r := bytes.NewReader(value) - binary.Read(r, nl.NativeEndian(), &Index) - link.Attrs.Index = Index - case nl.RDMA_NLDEV_ATTR_DEV_NAME: - link.Attrs.Name = string(value[0 : len-1]) - case nl.RDMA_NLDEV_ATTR_FW_VERSION: - link.Attrs.FirmwareVersion = string(value[0 : len-1]) - case nl.RDMA_NLDEV_ATTR_NODE_GUID: - var guid uint64 - r := bytes.NewReader(value) - binary.Read(r, nl.NativeEndian(), &guid) - link.Attrs.NodeGuid = uint64ToGuidString(guid) - case nl.RDMA_NLDEV_ATTR_SYS_IMAGE_GUID: - var sysGuid uint64 - r := bytes.NewReader(value) - binary.Read(r, nl.NativeEndian(), &sysGuid) - link.Attrs.SysImageGuid = uint64ToGuidString(sysGuid) - } - if (len % 4) != 0 { - // Skip pad bytes - reader.Seek(int64(4-(len%4)), seekCurrent) - } - } - return &link, nil -} - -func execRdmaGetLink(req *nl.NetlinkRequest, name string) (*RdmaLink, error) { - - msgs, err := req.Execute(unix.NETLINK_RDMA, 0) - if err != nil { - return nil, err - } - for _, m := range msgs { - link, err := executeOneGetRdmaLink(m) - if err != nil { - return nil, err - } - if link.Attrs.Name == name { - return link, nil - } - } - return nil, fmt.Errorf("Rdma device %v not found", name) -} - -func execRdmaSetLink(req *nl.NetlinkRequest) error { - - _, err := req.Execute(unix.NETLINK_RDMA, 0) - return err -} - -// RdmaLinkByName finds a link by name and returns a pointer to the object if -// found and nil error, otherwise returns error code. -func RdmaLinkByName(name string) (*RdmaLink, error) { - return pkgHandle.RdmaLinkByName(name) -} - -// RdmaLinkByName finds a link by name and returns a pointer to the object if -// found and nil error, otherwise returns error code. -func (h *Handle) RdmaLinkByName(name string) (*RdmaLink, error) { - - proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_GET) - req := h.newNetlinkRequest(proto, unix.NLM_F_ACK|unix.NLM_F_DUMP) - - return execRdmaGetLink(req, name) -} - -// RdmaLinkSetName sets the name of the rdma link device. Return nil on success -// or error otherwise. -// Equivalent to: `rdma dev set $old_devname name $name` -func RdmaLinkSetName(link *RdmaLink, name string) error { - return pkgHandle.RdmaLinkSetName(link, name) -} - -// RdmaLinkSetName sets the name of the rdma link device. Return nil on success -// or error otherwise. -// Equivalent to: `rdma dev set $old_devname name $name` -func (h *Handle) RdmaLinkSetName(link *RdmaLink, name string) error { - proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_SET) - req := h.newNetlinkRequest(proto, unix.NLM_F_ACK) - - b := make([]byte, 4) - native.PutUint32(b, uint32(link.Attrs.Index)) - data := nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_INDEX, b) - req.AddData(data) - - b = make([]byte, len(name)+1) - copy(b, name) - data = nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_NAME, b) - req.AddData(data) - - return execRdmaSetLink(req) -} - -func netnsModeToString(mode uint8) string { - switch mode { - case 0: - return "exclusive" - case 1: - return "shared" - default: - return "unknown" - } -} - -func executeOneGetRdmaNetnsMode(data []byte) (string, error) { - reader := bytes.NewReader(data) - for reader.Len() >= 4 { - _, attrType, len, value := parseNfAttrTLV(reader) - - switch attrType { - case nl.RDMA_NLDEV_SYS_ATTR_NETNS_MODE: - var mode uint8 - r := bytes.NewReader(value) - binary.Read(r, nl.NativeEndian(), &mode) - return netnsModeToString(mode), nil - } - if (len % 4) != 0 { - // Skip pad bytes - reader.Seek(int64(4-(len%4)), seekCurrent) - } - } - return "", fmt.Errorf("Invalid netns mode") -} - -// RdmaSystemGetNetnsMode gets the net namespace mode for RDMA subsystem -// Returns mode string and error status as nil on success or returns error -// otherwise. -// Equivalent to: `rdma system show netns' -func RdmaSystemGetNetnsMode() (string, error) { - return pkgHandle.RdmaSystemGetNetnsMode() -} - -// RdmaSystemGetNetnsMode gets the net namespace mode for RDMA subsystem -// Returns mode string and error status as nil on success or returns error -// otherwise. -// Equivalent to: `rdma system show netns' -func (h *Handle) RdmaSystemGetNetnsMode() (string, error) { - - proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_SYS_GET) - req := h.newNetlinkRequest(proto, unix.NLM_F_ACK) - - msgs, err := req.Execute(unix.NETLINK_RDMA, 0) - if err != nil { - return "", err - } - if len(msgs) == 0 { - return "", fmt.Errorf("No valid response from kernel") - } - return executeOneGetRdmaNetnsMode(msgs[0]) -} - -func netnsModeStringToUint8(mode string) (uint8, error) { - switch mode { - case "exclusive": - return 0, nil - case "shared": - return 1, nil - default: - return 0, fmt.Errorf("Invalid mode; %q", mode) - } -} - -// RdmaSystemSetNetnsMode sets the net namespace mode for RDMA subsystem -// Returns nil on success or appropriate error code. -// Equivalent to: `rdma system set netns { shared | exclusive }' -func RdmaSystemSetNetnsMode(NewMode string) error { - return pkgHandle.RdmaSystemSetNetnsMode(NewMode) -} - -// RdmaSystemSetNetnsMode sets the net namespace mode for RDMA subsystem -// Returns nil on success or appropriate error code. -// Equivalent to: `rdma system set netns { shared | exclusive }' -func (h *Handle) RdmaSystemSetNetnsMode(NewMode string) error { - value, err := netnsModeStringToUint8(NewMode) - if err != nil { - return err - } - - proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_SYS_SET) - req := h.newNetlinkRequest(proto, unix.NLM_F_ACK) - - data := nl.NewRtAttr(nl.RDMA_NLDEV_SYS_ATTR_NETNS_MODE, []byte{value}) - req.AddData(data) - - _, err = req.Execute(unix.NETLINK_RDMA, 0) - return err -} - -// RdmaLinkSetNsFd puts the RDMA device into a new network namespace. The -// fd must be an open file descriptor to a network namespace. -// Similar to: `rdma dev set $dev netns $ns` -func RdmaLinkSetNsFd(link *RdmaLink, fd uint32) error { - return pkgHandle.RdmaLinkSetNsFd(link, fd) -} - -// RdmaLinkSetNsFd puts the RDMA device into a new network namespace. The -// fd must be an open file descriptor to a network namespace. -// Similar to: `rdma dev set $dev netns $ns` -func (h *Handle) RdmaLinkSetNsFd(link *RdmaLink, fd uint32) error { - proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_SET) - req := h.newNetlinkRequest(proto, unix.NLM_F_ACK) - - data := nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_INDEX, - nl.Uint32Attr(link.Attrs.Index)) - req.AddData(data) - - data = nl.NewRtAttr(nl.RDMA_NLDEV_NET_NS_FD, nl.Uint32Attr(fd)) - req.AddData(data) - - return execRdmaSetLink(req) -} diff --git a/vendor/github.com/vishvananda/netlink/route.go b/vendor/github.com/vishvananda/netlink/route.go deleted file mode 100644 index 58ff1af60..000000000 --- a/vendor/github.com/vishvananda/netlink/route.go +++ /dev/null @@ -1,180 +0,0 @@ -package netlink - -import ( - "fmt" - "net" - "strings" -) - -// Scope is an enum representing a route scope. -type Scope uint8 - -type NextHopFlag int - -type Destination interface { - Family() int - Decode([]byte) error - Encode() ([]byte, error) - String() string - Equal(Destination) bool -} - -type Encap interface { - Type() int - Decode([]byte) error - Encode() ([]byte, error) - String() string - Equal(Encap) bool -} - -// Route represents a netlink route. -type Route struct { - LinkIndex int - ILinkIndex int - Scope Scope - Dst *net.IPNet - Src net.IP - Gw net.IP - MultiPath []*NexthopInfo - Protocol int - Priority int - Table int - Type int - Tos int - Flags int - MPLSDst *int - NewDst Destination - Encap Encap - MTU int - AdvMSS int - Hoplimit int -} - -func (r Route) String() string { - elems := []string{} - if len(r.MultiPath) == 0 { - elems = append(elems, fmt.Sprintf("Ifindex: %d", r.LinkIndex)) - } - if r.MPLSDst != nil { - elems = append(elems, fmt.Sprintf("Dst: %d", r.MPLSDst)) - } else { - elems = append(elems, fmt.Sprintf("Dst: %s", r.Dst)) - } - if r.NewDst != nil { - elems = append(elems, fmt.Sprintf("NewDst: %s", r.NewDst)) - } - if r.Encap != nil { - elems = append(elems, fmt.Sprintf("Encap: %s", r.Encap)) - } - elems = append(elems, fmt.Sprintf("Src: %s", r.Src)) - if len(r.MultiPath) > 0 { - elems = append(elems, fmt.Sprintf("Gw: %s", r.MultiPath)) - } else { - elems = append(elems, fmt.Sprintf("Gw: %s", r.Gw)) - } - elems = append(elems, fmt.Sprintf("Flags: %s", r.ListFlags())) - elems = append(elems, fmt.Sprintf("Table: %d", r.Table)) - return fmt.Sprintf("{%s}", strings.Join(elems, " ")) -} - -func (r Route) Equal(x Route) bool { - return r.LinkIndex == x.LinkIndex && - r.ILinkIndex == x.ILinkIndex && - r.Scope == x.Scope && - ipNetEqual(r.Dst, x.Dst) && - r.Src.Equal(x.Src) && - r.Gw.Equal(x.Gw) && - nexthopInfoSlice(r.MultiPath).Equal(x.MultiPath) && - r.Protocol == x.Protocol && - r.Priority == x.Priority && - r.Table == x.Table && - r.Type == x.Type && - r.Tos == x.Tos && - r.Hoplimit == x.Hoplimit && - r.Flags == x.Flags && - (r.MPLSDst == x.MPLSDst || (r.MPLSDst != nil && x.MPLSDst != nil && *r.MPLSDst == *x.MPLSDst)) && - (r.NewDst == x.NewDst || (r.NewDst != nil && r.NewDst.Equal(x.NewDst))) && - (r.Encap == x.Encap || (r.Encap != nil && r.Encap.Equal(x.Encap))) -} - -func (r *Route) SetFlag(flag NextHopFlag) { - r.Flags |= int(flag) -} - -func (r *Route) ClearFlag(flag NextHopFlag) { - r.Flags &^= int(flag) -} - -type flagString struct { - f NextHopFlag - s string -} - -// RouteUpdate is sent when a route changes - type is RTM_NEWROUTE or RTM_DELROUTE -type RouteUpdate struct { - Type uint16 - Route -} - -type NexthopInfo struct { - LinkIndex int - Hops int - Gw net.IP - Flags int - NewDst Destination - Encap Encap -} - -func (n *NexthopInfo) String() string { - elems := []string{} - elems = append(elems, fmt.Sprintf("Ifindex: %d", n.LinkIndex)) - if n.NewDst != nil { - elems = append(elems, fmt.Sprintf("NewDst: %s", n.NewDst)) - } - if n.Encap != nil { - elems = append(elems, fmt.Sprintf("Encap: %s", n.Encap)) - } - elems = append(elems, fmt.Sprintf("Weight: %d", n.Hops+1)) - elems = append(elems, fmt.Sprintf("Gw: %s", n.Gw)) - elems = append(elems, fmt.Sprintf("Flags: %s", n.ListFlags())) - return fmt.Sprintf("{%s}", strings.Join(elems, " ")) -} - -func (n NexthopInfo) Equal(x NexthopInfo) bool { - return n.LinkIndex == x.LinkIndex && - n.Hops == x.Hops && - n.Gw.Equal(x.Gw) && - n.Flags == x.Flags && - (n.NewDst == x.NewDst || (n.NewDst != nil && n.NewDst.Equal(x.NewDst))) && - (n.Encap == x.Encap || (n.Encap != nil && n.Encap.Equal(x.Encap))) -} - -type nexthopInfoSlice []*NexthopInfo - -func (n nexthopInfoSlice) Equal(x []*NexthopInfo) bool { - if len(n) != len(x) { - return false - } - for i := range n { - if n[i] == nil || x[i] == nil { - return false - } - if !n[i].Equal(*x[i]) { - return false - } - } - return true -} - -// ipNetEqual returns true iff both IPNet are equal -func ipNetEqual(ipn1 *net.IPNet, ipn2 *net.IPNet) bool { - if ipn1 == ipn2 { - return true - } - if ipn1 == nil || ipn2 == nil { - return false - } - m1, _ := ipn1.Mask.Size() - m2, _ := ipn2.Mask.Size() - return m1 == m2 && ipn1.IP.Equal(ipn2.IP) -} diff --git a/vendor/github.com/vishvananda/netlink/route_linux.go b/vendor/github.com/vishvananda/netlink/route_linux.go deleted file mode 100644 index c69c595ed..000000000 --- a/vendor/github.com/vishvananda/netlink/route_linux.go +++ /dev/null @@ -1,1081 +0,0 @@ -package netlink - -import ( - "fmt" - "net" - "strings" - "syscall" - - "github.com/vishvananda/netlink/nl" - "github.com/vishvananda/netns" - "golang.org/x/sys/unix" -) - -// RtAttr is shared so it is in netlink_linux.go - -const ( - SCOPE_UNIVERSE Scope = unix.RT_SCOPE_UNIVERSE - SCOPE_SITE Scope = unix.RT_SCOPE_SITE - SCOPE_LINK Scope = unix.RT_SCOPE_LINK - SCOPE_HOST Scope = unix.RT_SCOPE_HOST - SCOPE_NOWHERE Scope = unix.RT_SCOPE_NOWHERE -) - -const ( - RT_FILTER_PROTOCOL uint64 = 1 << (1 + iota) - RT_FILTER_SCOPE - RT_FILTER_TYPE - RT_FILTER_TOS - RT_FILTER_IIF - RT_FILTER_OIF - RT_FILTER_DST - RT_FILTER_SRC - RT_FILTER_GW - RT_FILTER_TABLE - RT_FILTER_HOPLIMIT -) - -const ( - FLAG_ONLINK NextHopFlag = unix.RTNH_F_ONLINK - FLAG_PERVASIVE NextHopFlag = unix.RTNH_F_PERVASIVE -) - -var testFlags = []flagString{ - {f: FLAG_ONLINK, s: "onlink"}, - {f: FLAG_PERVASIVE, s: "pervasive"}, -} - -func listFlags(flag int) []string { - var flags []string - for _, tf := range testFlags { - if flag&int(tf.f) != 0 { - flags = append(flags, tf.s) - } - } - return flags -} - -func (r *Route) ListFlags() []string { - return listFlags(r.Flags) -} - -func (n *NexthopInfo) ListFlags() []string { - return listFlags(n.Flags) -} - -type MPLSDestination struct { - Labels []int -} - -func (d *MPLSDestination) Family() int { - return nl.FAMILY_MPLS -} - -func (d *MPLSDestination) Decode(buf []byte) error { - d.Labels = nl.DecodeMPLSStack(buf) - return nil -} - -func (d *MPLSDestination) Encode() ([]byte, error) { - return nl.EncodeMPLSStack(d.Labels...), nil -} - -func (d *MPLSDestination) String() string { - s := make([]string, 0, len(d.Labels)) - for _, l := range d.Labels { - s = append(s, fmt.Sprintf("%d", l)) - } - return strings.Join(s, "/") -} - -func (d *MPLSDestination) Equal(x Destination) bool { - o, ok := x.(*MPLSDestination) - if !ok { - return false - } - if d == nil && o == nil { - return true - } - if d == nil || o == nil { - return false - } - if d.Labels == nil && o.Labels == nil { - return true - } - if d.Labels == nil || o.Labels == nil { - return false - } - if len(d.Labels) != len(o.Labels) { - return false - } - for i := range d.Labels { - if d.Labels[i] != o.Labels[i] { - return false - } - } - return true -} - -type MPLSEncap struct { - Labels []int -} - -func (e *MPLSEncap) Type() int { - return nl.LWTUNNEL_ENCAP_MPLS -} - -func (e *MPLSEncap) Decode(buf []byte) error { - if len(buf) < 4 { - return fmt.Errorf("lack of bytes") - } - native := nl.NativeEndian() - l := native.Uint16(buf) - if len(buf) < int(l) { - return fmt.Errorf("lack of bytes") - } - buf = buf[:l] - typ := native.Uint16(buf[2:]) - if typ != nl.MPLS_IPTUNNEL_DST { - return fmt.Errorf("unknown MPLS Encap Type: %d", typ) - } - e.Labels = nl.DecodeMPLSStack(buf[4:]) - return nil -} - -func (e *MPLSEncap) Encode() ([]byte, error) { - s := nl.EncodeMPLSStack(e.Labels...) - native := nl.NativeEndian() - hdr := make([]byte, 4) - native.PutUint16(hdr, uint16(len(s)+4)) - native.PutUint16(hdr[2:], nl.MPLS_IPTUNNEL_DST) - return append(hdr, s...), nil -} - -func (e *MPLSEncap) String() string { - s := make([]string, 0, len(e.Labels)) - for _, l := range e.Labels { - s = append(s, fmt.Sprintf("%d", l)) - } - return strings.Join(s, "/") -} - -func (e *MPLSEncap) Equal(x Encap) bool { - o, ok := x.(*MPLSEncap) - if !ok { - return false - } - if e == nil && o == nil { - return true - } - if e == nil || o == nil { - return false - } - if e.Labels == nil && o.Labels == nil { - return true - } - if e.Labels == nil || o.Labels == nil { - return false - } - if len(e.Labels) != len(o.Labels) { - return false - } - for i := range e.Labels { - if e.Labels[i] != o.Labels[i] { - return false - } - } - return true -} - -// SEG6 definitions -type SEG6Encap struct { - Mode int - Segments []net.IP -} - -func (e *SEG6Encap) Type() int { - return nl.LWTUNNEL_ENCAP_SEG6 -} -func (e *SEG6Encap) Decode(buf []byte) error { - if len(buf) < 4 { - return fmt.Errorf("lack of bytes") - } - native := nl.NativeEndian() - // Get Length(l) & Type(typ) : 2 + 2 bytes - l := native.Uint16(buf) - if len(buf) < int(l) { - return fmt.Errorf("lack of bytes") - } - buf = buf[:l] // make sure buf size upper limit is Length - typ := native.Uint16(buf[2:]) - // LWTUNNEL_ENCAP_SEG6 has only one attr type SEG6_IPTUNNEL_SRH - if typ != nl.SEG6_IPTUNNEL_SRH { - return fmt.Errorf("unknown SEG6 Type: %d", typ) - } - - var err error - e.Mode, e.Segments, err = nl.DecodeSEG6Encap(buf[4:]) - - return err -} -func (e *SEG6Encap) Encode() ([]byte, error) { - s, err := nl.EncodeSEG6Encap(e.Mode, e.Segments) - native := nl.NativeEndian() - hdr := make([]byte, 4) - native.PutUint16(hdr, uint16(len(s)+4)) - native.PutUint16(hdr[2:], nl.SEG6_IPTUNNEL_SRH) - return append(hdr, s...), err -} -func (e *SEG6Encap) String() string { - segs := make([]string, 0, len(e.Segments)) - // append segment backwards (from n to 0) since seg#0 is the last segment. - for i := len(e.Segments); i > 0; i-- { - segs = append(segs, fmt.Sprintf("%s", e.Segments[i-1])) - } - str := fmt.Sprintf("mode %s segs %d [ %s ]", nl.SEG6EncapModeString(e.Mode), - len(e.Segments), strings.Join(segs, " ")) - return str -} -func (e *SEG6Encap) Equal(x Encap) bool { - o, ok := x.(*SEG6Encap) - if !ok { - return false - } - if e == o { - return true - } - if e == nil || o == nil { - return false - } - if e.Mode != o.Mode { - return false - } - if len(e.Segments) != len(o.Segments) { - return false - } - for i := range e.Segments { - if !e.Segments[i].Equal(o.Segments[i]) { - return false - } - } - return true -} - -// SEG6LocalEncap definitions -type SEG6LocalEncap struct { - Flags [nl.SEG6_LOCAL_MAX]bool - Action int - Segments []net.IP // from SRH in seg6_local_lwt - Table int // table id for End.T and End.DT6 - InAddr net.IP - In6Addr net.IP - Iif int - Oif int -} - -func (e *SEG6LocalEncap) Type() int { - return nl.LWTUNNEL_ENCAP_SEG6_LOCAL -} -func (e *SEG6LocalEncap) Decode(buf []byte) error { - attrs, err := nl.ParseRouteAttr(buf) - if err != nil { - return err - } - native := nl.NativeEndian() - for _, attr := range attrs { - switch attr.Attr.Type { - case nl.SEG6_LOCAL_ACTION: - e.Action = int(native.Uint32(attr.Value[0:4])) - e.Flags[nl.SEG6_LOCAL_ACTION] = true - case nl.SEG6_LOCAL_SRH: - e.Segments, err = nl.DecodeSEG6Srh(attr.Value[:]) - e.Flags[nl.SEG6_LOCAL_SRH] = true - case nl.SEG6_LOCAL_TABLE: - e.Table = int(native.Uint32(attr.Value[0:4])) - e.Flags[nl.SEG6_LOCAL_TABLE] = true - case nl.SEG6_LOCAL_NH4: - e.InAddr = net.IP(attr.Value[0:4]) - e.Flags[nl.SEG6_LOCAL_NH4] = true - case nl.SEG6_LOCAL_NH6: - e.In6Addr = net.IP(attr.Value[0:16]) - e.Flags[nl.SEG6_LOCAL_NH6] = true - case nl.SEG6_LOCAL_IIF: - e.Iif = int(native.Uint32(attr.Value[0:4])) - e.Flags[nl.SEG6_LOCAL_IIF] = true - case nl.SEG6_LOCAL_OIF: - e.Oif = int(native.Uint32(attr.Value[0:4])) - e.Flags[nl.SEG6_LOCAL_OIF] = true - } - } - return err -} -func (e *SEG6LocalEncap) Encode() ([]byte, error) { - var err error - native := nl.NativeEndian() - res := make([]byte, 8) - native.PutUint16(res, 8) // length - native.PutUint16(res[2:], nl.SEG6_LOCAL_ACTION) - native.PutUint32(res[4:], uint32(e.Action)) - if e.Flags[nl.SEG6_LOCAL_SRH] { - srh, err := nl.EncodeSEG6Srh(e.Segments) - if err != nil { - return nil, err - } - attr := make([]byte, 4) - native.PutUint16(attr, uint16(len(srh)+4)) - native.PutUint16(attr[2:], nl.SEG6_LOCAL_SRH) - attr = append(attr, srh...) - res = append(res, attr...) - } - if e.Flags[nl.SEG6_LOCAL_TABLE] { - attr := make([]byte, 8) - native.PutUint16(attr, 8) - native.PutUint16(attr[2:], nl.SEG6_LOCAL_TABLE) - native.PutUint32(attr[4:], uint32(e.Table)) - res = append(res, attr...) - } - if e.Flags[nl.SEG6_LOCAL_NH4] { - attr := make([]byte, 4) - native.PutUint16(attr, 8) - native.PutUint16(attr[2:], nl.SEG6_LOCAL_NH4) - ipv4 := e.InAddr.To4() - if ipv4 == nil { - err = fmt.Errorf("SEG6_LOCAL_NH4 has invalid IPv4 address") - return nil, err - } - attr = append(attr, ipv4...) - res = append(res, attr...) - } - if e.Flags[nl.SEG6_LOCAL_NH6] { - attr := make([]byte, 4) - native.PutUint16(attr, 20) - native.PutUint16(attr[2:], nl.SEG6_LOCAL_NH6) - attr = append(attr, e.In6Addr...) - res = append(res, attr...) - } - if e.Flags[nl.SEG6_LOCAL_IIF] { - attr := make([]byte, 8) - native.PutUint16(attr, 8) - native.PutUint16(attr[2:], nl.SEG6_LOCAL_IIF) - native.PutUint32(attr[4:], uint32(e.Iif)) - res = append(res, attr...) - } - if e.Flags[nl.SEG6_LOCAL_OIF] { - attr := make([]byte, 8) - native.PutUint16(attr, 8) - native.PutUint16(attr[2:], nl.SEG6_LOCAL_OIF) - native.PutUint32(attr[4:], uint32(e.Oif)) - res = append(res, attr...) - } - return res, err -} -func (e *SEG6LocalEncap) String() string { - strs := make([]string, 0, nl.SEG6_LOCAL_MAX) - strs = append(strs, fmt.Sprintf("action %s", nl.SEG6LocalActionString(e.Action))) - - if e.Flags[nl.SEG6_LOCAL_TABLE] { - strs = append(strs, fmt.Sprintf("table %d", e.Table)) - } - if e.Flags[nl.SEG6_LOCAL_NH4] { - strs = append(strs, fmt.Sprintf("nh4 %s", e.InAddr)) - } - if e.Flags[nl.SEG6_LOCAL_NH6] { - strs = append(strs, fmt.Sprintf("nh6 %s", e.In6Addr)) - } - if e.Flags[nl.SEG6_LOCAL_IIF] { - link, err := LinkByIndex(e.Iif) - if err != nil { - strs = append(strs, fmt.Sprintf("iif %d", e.Iif)) - } else { - strs = append(strs, fmt.Sprintf("iif %s", link.Attrs().Name)) - } - } - if e.Flags[nl.SEG6_LOCAL_OIF] { - link, err := LinkByIndex(e.Oif) - if err != nil { - strs = append(strs, fmt.Sprintf("oif %d", e.Oif)) - } else { - strs = append(strs, fmt.Sprintf("oif %s", link.Attrs().Name)) - } - } - if e.Flags[nl.SEG6_LOCAL_SRH] { - segs := make([]string, 0, len(e.Segments)) - //append segment backwards (from n to 0) since seg#0 is the last segment. - for i := len(e.Segments); i > 0; i-- { - segs = append(segs, fmt.Sprintf("%s", e.Segments[i-1])) - } - strs = append(strs, fmt.Sprintf("segs %d [ %s ]", len(e.Segments), strings.Join(segs, " "))) - } - return strings.Join(strs, " ") -} -func (e *SEG6LocalEncap) Equal(x Encap) bool { - o, ok := x.(*SEG6LocalEncap) - if !ok { - return false - } - if e == o { - return true - } - if e == nil || o == nil { - return false - } - // compare all arrays first - for i := range e.Flags { - if e.Flags[i] != o.Flags[i] { - return false - } - } - if len(e.Segments) != len(o.Segments) { - return false - } - for i := range e.Segments { - if !e.Segments[i].Equal(o.Segments[i]) { - return false - } - } - // compare values - if !e.InAddr.Equal(o.InAddr) || !e.In6Addr.Equal(o.In6Addr) { - return false - } - if e.Action != o.Action || e.Table != o.Table || e.Iif != o.Iif || e.Oif != o.Oif { - return false - } - return true -} - -// RouteAdd will add a route to the system. -// Equivalent to: `ip route add $route` -func RouteAdd(route *Route) error { - return pkgHandle.RouteAdd(route) -} - -// RouteAdd will add a route to the system. -// Equivalent to: `ip route add $route` -func (h *Handle) RouteAdd(route *Route) error { - flags := unix.NLM_F_CREATE | unix.NLM_F_EXCL | unix.NLM_F_ACK - req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags) - return h.routeHandle(route, req, nl.NewRtMsg()) -} - -// RouteReplace will add a route to the system. -// Equivalent to: `ip route replace $route` -func RouteReplace(route *Route) error { - return pkgHandle.RouteReplace(route) -} - -// RouteReplace will add a route to the system. -// Equivalent to: `ip route replace $route` -func (h *Handle) RouteReplace(route *Route) error { - flags := unix.NLM_F_CREATE | unix.NLM_F_REPLACE | unix.NLM_F_ACK - req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags) - return h.routeHandle(route, req, nl.NewRtMsg()) -} - -// RouteDel will delete a route from the system. -// Equivalent to: `ip route del $route` -func RouteDel(route *Route) error { - return pkgHandle.RouteDel(route) -} - -// RouteDel will delete a route from the system. -// Equivalent to: `ip route del $route` -func (h *Handle) RouteDel(route *Route) error { - req := h.newNetlinkRequest(unix.RTM_DELROUTE, unix.NLM_F_ACK) - return h.routeHandle(route, req, nl.NewRtDelMsg()) -} - -func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error { - if (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil && route.MPLSDst == nil { - return fmt.Errorf("one of Dst.IP, Src, or Gw must not be nil") - } - - family := -1 - var rtAttrs []*nl.RtAttr - - if route.Dst != nil && route.Dst.IP != nil { - dstLen, _ := route.Dst.Mask.Size() - msg.Dst_len = uint8(dstLen) - dstFamily := nl.GetIPFamily(route.Dst.IP) - family = dstFamily - var dstData []byte - if dstFamily == FAMILY_V4 { - dstData = route.Dst.IP.To4() - } else { - dstData = route.Dst.IP.To16() - } - rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, dstData)) - } else if route.MPLSDst != nil { - family = nl.FAMILY_MPLS - msg.Dst_len = uint8(20) - msg.Type = unix.RTN_UNICAST - rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, nl.EncodeMPLSStack(*route.MPLSDst))) - } - - if route.NewDst != nil { - if family != -1 && family != route.NewDst.Family() { - return fmt.Errorf("new destination and destination are not the same address family") - } - buf, err := route.NewDst.Encode() - if err != nil { - return err - } - rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_NEWDST, buf)) - } - - if route.Encap != nil { - buf := make([]byte, 2) - native.PutUint16(buf, uint16(route.Encap.Type())) - rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP_TYPE, buf)) - buf, err := route.Encap.Encode() - if err != nil { - return err - } - rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP, buf)) - } - - if route.Src != nil { - srcFamily := nl.GetIPFamily(route.Src) - if family != -1 && family != srcFamily { - return fmt.Errorf("source and destination ip are not the same IP family") - } - family = srcFamily - var srcData []byte - if srcFamily == FAMILY_V4 { - srcData = route.Src.To4() - } else { - srcData = route.Src.To16() - } - // The commonly used src ip for routes is actually PREFSRC - rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_PREFSRC, srcData)) - } - - if route.Gw != nil { - gwFamily := nl.GetIPFamily(route.Gw) - if family != -1 && family != gwFamily { - return fmt.Errorf("gateway, source, and destination ip are not the same IP family") - } - family = gwFamily - var gwData []byte - if gwFamily == FAMILY_V4 { - gwData = route.Gw.To4() - } else { - gwData = route.Gw.To16() - } - rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_GATEWAY, gwData)) - } - - if len(route.MultiPath) > 0 { - buf := []byte{} - for _, nh := range route.MultiPath { - rtnh := &nl.RtNexthop{ - RtNexthop: unix.RtNexthop{ - Hops: uint8(nh.Hops), - Ifindex: int32(nh.LinkIndex), - Flags: uint8(nh.Flags), - }, - } - children := []nl.NetlinkRequestData{} - if nh.Gw != nil { - gwFamily := nl.GetIPFamily(nh.Gw) - if family != -1 && family != gwFamily { - return fmt.Errorf("gateway, source, and destination ip are not the same IP family") - } - if gwFamily == FAMILY_V4 { - children = append(children, nl.NewRtAttr(unix.RTA_GATEWAY, []byte(nh.Gw.To4()))) - } else { - children = append(children, nl.NewRtAttr(unix.RTA_GATEWAY, []byte(nh.Gw.To16()))) - } - } - if nh.NewDst != nil { - if family != -1 && family != nh.NewDst.Family() { - return fmt.Errorf("new destination and destination are not the same address family") - } - buf, err := nh.NewDst.Encode() - if err != nil { - return err - } - children = append(children, nl.NewRtAttr(unix.RTA_NEWDST, buf)) - } - if nh.Encap != nil { - buf := make([]byte, 2) - native.PutUint16(buf, uint16(nh.Encap.Type())) - children = append(children, nl.NewRtAttr(unix.RTA_ENCAP_TYPE, buf)) - buf, err := nh.Encap.Encode() - if err != nil { - return err - } - children = append(children, nl.NewRtAttr(unix.RTA_ENCAP, buf)) - } - rtnh.Children = children - buf = append(buf, rtnh.Serialize()...) - } - rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_MULTIPATH, buf)) - } - - if route.Table > 0 { - if route.Table >= 256 { - msg.Table = unix.RT_TABLE_UNSPEC - b := make([]byte, 4) - native.PutUint32(b, uint32(route.Table)) - rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_TABLE, b)) - } else { - msg.Table = uint8(route.Table) - } - } - - if route.Priority > 0 { - b := make([]byte, 4) - native.PutUint32(b, uint32(route.Priority)) - rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_PRIORITY, b)) - } - if route.Tos > 0 { - msg.Tos = uint8(route.Tos) - } - if route.Protocol > 0 { - msg.Protocol = uint8(route.Protocol) - } - if route.Type > 0 { - msg.Type = uint8(route.Type) - } - - var metrics []*nl.RtAttr - // TODO: support other rta_metric values - if route.MTU > 0 { - b := nl.Uint32Attr(uint32(route.MTU)) - metrics = append(metrics, nl.NewRtAttr(unix.RTAX_MTU, b)) - } - if route.AdvMSS > 0 { - b := nl.Uint32Attr(uint32(route.AdvMSS)) - metrics = append(metrics, nl.NewRtAttr(unix.RTAX_ADVMSS, b)) - } - if route.Hoplimit > 0 { - b := nl.Uint32Attr(uint32(route.Hoplimit)) - metrics = append(metrics, nl.NewRtAttr(unix.RTAX_HOPLIMIT, b)) - } - - if metrics != nil { - attr := nl.NewRtAttr(unix.RTA_METRICS, nil) - for _, metric := range metrics { - attr.AddChild(metric) - } - rtAttrs = append(rtAttrs, attr) - } - - msg.Flags = uint32(route.Flags) - msg.Scope = uint8(route.Scope) - msg.Family = uint8(family) - req.AddData(msg) - for _, attr := range rtAttrs { - req.AddData(attr) - } - - var ( - b = make([]byte, 4) - native = nl.NativeEndian() - ) - native.PutUint32(b, uint32(route.LinkIndex)) - - req.AddData(nl.NewRtAttr(unix.RTA_OIF, b)) - - _, err := req.Execute(unix.NETLINK_ROUTE, 0) - return err -} - -// RouteList gets a list of routes in the system. -// Equivalent to: `ip route show`. -// The list can be filtered by link and ip family. -func RouteList(link Link, family int) ([]Route, error) { - return pkgHandle.RouteList(link, family) -} - -// RouteList gets a list of routes in the system. -// Equivalent to: `ip route show`. -// The list can be filtered by link and ip family. -func (h *Handle) RouteList(link Link, family int) ([]Route, error) { - var routeFilter *Route - if link != nil { - routeFilter = &Route{ - LinkIndex: link.Attrs().Index, - } - } - return h.RouteListFiltered(family, routeFilter, RT_FILTER_OIF) -} - -// RouteListFiltered gets a list of routes in the system filtered with specified rules. -// All rules must be defined in RouteFilter struct -func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) { - return pkgHandle.RouteListFiltered(family, filter, filterMask) -} - -// RouteListFiltered gets a list of routes in the system filtered with specified rules. -// All rules must be defined in RouteFilter struct -func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) { - req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_DUMP) - infmsg := nl.NewIfInfomsg(family) - req.AddData(infmsg) - - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE) - if err != nil { - return nil, err - } - - var res []Route - for _, m := range msgs { - msg := nl.DeserializeRtMsg(m) - if msg.Flags&unix.RTM_F_CLONED != 0 { - // Ignore cloned routes - continue - } - if msg.Table != unix.RT_TABLE_MAIN { - if filter == nil || filter != nil && filterMask&RT_FILTER_TABLE == 0 { - // Ignore non-main tables - continue - } - } - route, err := deserializeRoute(m) - if err != nil { - return nil, err - } - if filter != nil { - switch { - case filterMask&RT_FILTER_TABLE != 0 && filter.Table != unix.RT_TABLE_UNSPEC && route.Table != filter.Table: - continue - case filterMask&RT_FILTER_PROTOCOL != 0 && route.Protocol != filter.Protocol: - continue - case filterMask&RT_FILTER_SCOPE != 0 && route.Scope != filter.Scope: - continue - case filterMask&RT_FILTER_TYPE != 0 && route.Type != filter.Type: - continue - case filterMask&RT_FILTER_TOS != 0 && route.Tos != filter.Tos: - continue - case filterMask&RT_FILTER_OIF != 0 && route.LinkIndex != filter.LinkIndex: - continue - case filterMask&RT_FILTER_IIF != 0 && route.ILinkIndex != filter.ILinkIndex: - continue - case filterMask&RT_FILTER_GW != 0 && !route.Gw.Equal(filter.Gw): - continue - case filterMask&RT_FILTER_SRC != 0 && !route.Src.Equal(filter.Src): - continue - case filterMask&RT_FILTER_DST != 0: - if filter.MPLSDst == nil || route.MPLSDst == nil || (*filter.MPLSDst) != (*route.MPLSDst) { - if !ipNetEqual(route.Dst, filter.Dst) { - continue - } - } - case filterMask&RT_FILTER_HOPLIMIT != 0 && route.Hoplimit != filter.Hoplimit: - continue - } - } - res = append(res, route) - } - return res, nil -} - -// deserializeRoute decodes a binary netlink message into a Route struct -func deserializeRoute(m []byte) (Route, error) { - msg := nl.DeserializeRtMsg(m) - attrs, err := nl.ParseRouteAttr(m[msg.Len():]) - if err != nil { - return Route{}, err - } - route := Route{ - Scope: Scope(msg.Scope), - Protocol: int(msg.Protocol), - Table: int(msg.Table), - Type: int(msg.Type), - Tos: int(msg.Tos), - Flags: int(msg.Flags), - } - - native := nl.NativeEndian() - var encap, encapType syscall.NetlinkRouteAttr - for _, attr := range attrs { - switch attr.Attr.Type { - case unix.RTA_GATEWAY: - route.Gw = net.IP(attr.Value) - case unix.RTA_PREFSRC: - route.Src = net.IP(attr.Value) - case unix.RTA_DST: - if msg.Family == nl.FAMILY_MPLS { - stack := nl.DecodeMPLSStack(attr.Value) - if len(stack) == 0 || len(stack) > 1 { - return route, fmt.Errorf("invalid MPLS RTA_DST") - } - route.MPLSDst = &stack[0] - } else { - route.Dst = &net.IPNet{ - IP: attr.Value, - Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)), - } - } - case unix.RTA_OIF: - route.LinkIndex = int(native.Uint32(attr.Value[0:4])) - case unix.RTA_IIF: - route.ILinkIndex = int(native.Uint32(attr.Value[0:4])) - case unix.RTA_PRIORITY: - route.Priority = int(native.Uint32(attr.Value[0:4])) - case unix.RTA_TABLE: - route.Table = int(native.Uint32(attr.Value[0:4])) - case unix.RTA_MULTIPATH: - parseRtNexthop := func(value []byte) (*NexthopInfo, []byte, error) { - if len(value) < unix.SizeofRtNexthop { - return nil, nil, fmt.Errorf("lack of bytes") - } - nh := nl.DeserializeRtNexthop(value) - if len(value) < int(nh.RtNexthop.Len) { - return nil, nil, fmt.Errorf("lack of bytes") - } - info := &NexthopInfo{ - LinkIndex: int(nh.RtNexthop.Ifindex), - Hops: int(nh.RtNexthop.Hops), - Flags: int(nh.RtNexthop.Flags), - } - attrs, err := nl.ParseRouteAttr(value[unix.SizeofRtNexthop:int(nh.RtNexthop.Len)]) - if err != nil { - return nil, nil, err - } - var encap, encapType syscall.NetlinkRouteAttr - for _, attr := range attrs { - switch attr.Attr.Type { - case unix.RTA_GATEWAY: - info.Gw = net.IP(attr.Value) - case unix.RTA_NEWDST: - var d Destination - switch msg.Family { - case nl.FAMILY_MPLS: - d = &MPLSDestination{} - } - if err := d.Decode(attr.Value); err != nil { - return nil, nil, err - } - info.NewDst = d - case unix.RTA_ENCAP_TYPE: - encapType = attr - case unix.RTA_ENCAP: - encap = attr - } - } - - if len(encap.Value) != 0 && len(encapType.Value) != 0 { - typ := int(native.Uint16(encapType.Value[0:2])) - var e Encap - switch typ { - case nl.LWTUNNEL_ENCAP_MPLS: - e = &MPLSEncap{} - if err := e.Decode(encap.Value); err != nil { - return nil, nil, err - } - } - info.Encap = e - } - - return info, value[int(nh.RtNexthop.Len):], nil - } - rest := attr.Value - for len(rest) > 0 { - info, buf, err := parseRtNexthop(rest) - if err != nil { - return route, err - } - route.MultiPath = append(route.MultiPath, info) - rest = buf - } - case unix.RTA_NEWDST: - var d Destination - switch msg.Family { - case nl.FAMILY_MPLS: - d = &MPLSDestination{} - } - if err := d.Decode(attr.Value); err != nil { - return route, err - } - route.NewDst = d - case unix.RTA_ENCAP_TYPE: - encapType = attr - case unix.RTA_ENCAP: - encap = attr - case unix.RTA_METRICS: - metrics, err := nl.ParseRouteAttr(attr.Value) - if err != nil { - return route, err - } - for _, metric := range metrics { - switch metric.Attr.Type { - case unix.RTAX_MTU: - route.MTU = int(native.Uint32(metric.Value[0:4])) - case unix.RTAX_ADVMSS: - route.AdvMSS = int(native.Uint32(metric.Value[0:4])) - case unix.RTAX_HOPLIMIT: - route.Hoplimit = int(native.Uint32(metric.Value[0:4])) - } - } - } - } - - if len(encap.Value) != 0 && len(encapType.Value) != 0 { - typ := int(native.Uint16(encapType.Value[0:2])) - var e Encap - switch typ { - case nl.LWTUNNEL_ENCAP_MPLS: - e = &MPLSEncap{} - if err := e.Decode(encap.Value); err != nil { - return route, err - } - case nl.LWTUNNEL_ENCAP_SEG6: - e = &SEG6Encap{} - if err := e.Decode(encap.Value); err != nil { - return route, err - } - case nl.LWTUNNEL_ENCAP_SEG6_LOCAL: - e = &SEG6LocalEncap{} - if err := e.Decode(encap.Value); err != nil { - return route, err - } - } - route.Encap = e - } - - return route, nil -} - -// RouteGet gets a route to a specific destination from the host system. -// Equivalent to: 'ip route get'. -func RouteGet(destination net.IP) ([]Route, error) { - return pkgHandle.RouteGet(destination) -} - -// RouteGet gets a route to a specific destination from the host system. -// Equivalent to: 'ip route get'. -func (h *Handle) RouteGet(destination net.IP) ([]Route, error) { - req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_REQUEST) - family := nl.GetIPFamily(destination) - var destinationData []byte - var bitlen uint8 - if family == FAMILY_V4 { - destinationData = destination.To4() - bitlen = 32 - } else { - destinationData = destination.To16() - bitlen = 128 - } - msg := &nl.RtMsg{} - msg.Family = uint8(family) - msg.Dst_len = bitlen - req.AddData(msg) - - rtaDst := nl.NewRtAttr(unix.RTA_DST, destinationData) - req.AddData(rtaDst) - - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE) - if err != nil { - return nil, err - } - - var res []Route - for _, m := range msgs { - route, err := deserializeRoute(m) - if err != nil { - return nil, err - } - res = append(res, route) - } - return res, nil - -} - -// RouteSubscribe takes a chan down which notifications will be sent -// when routes are added or deleted. Close the 'done' chan to stop subscription. -func RouteSubscribe(ch chan<- RouteUpdate, done <-chan struct{}) error { - return routeSubscribeAt(netns.None(), netns.None(), ch, done, nil, false) -} - -// RouteSubscribeAt works like RouteSubscribe plus it allows the caller -// to choose the network namespace in which to subscribe (ns). -func RouteSubscribeAt(ns netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}) error { - return routeSubscribeAt(ns, netns.None(), ch, done, nil, false) -} - -// RouteSubscribeOptions contains a set of options to use with -// RouteSubscribeWithOptions. -type RouteSubscribeOptions struct { - Namespace *netns.NsHandle - ErrorCallback func(error) - ListExisting bool -} - -// RouteSubscribeWithOptions work like RouteSubscribe but enable to -// provide additional options to modify the behavior. Currently, the -// namespace can be provided as well as an error callback. -func RouteSubscribeWithOptions(ch chan<- RouteUpdate, done <-chan struct{}, options RouteSubscribeOptions) error { - if options.Namespace == nil { - none := netns.None() - options.Namespace = &none - } - return routeSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting) -} - -func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error { - s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_ROUTE, unix.RTNLGRP_IPV6_ROUTE) - if err != nil { - return err - } - if done != nil { - go func() { - <-done - s.Close() - }() - } - if listExisting { - req := pkgHandle.newNetlinkRequest(unix.RTM_GETROUTE, - unix.NLM_F_DUMP) - infmsg := nl.NewIfInfomsg(unix.AF_UNSPEC) - req.AddData(infmsg) - if err := s.Send(req); err != nil { - return err - } - } - go func() { - defer close(ch) - for { - msgs, from, err := s.Receive() - if err != nil { - if cberr != nil { - cberr(err) - } - return - } - if from.Pid != nl.PidKernel { - if cberr != nil { - cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)) - } - continue - } - for _, m := range msgs { - if m.Header.Type == unix.NLMSG_DONE { - continue - } - if m.Header.Type == unix.NLMSG_ERROR { - native := nl.NativeEndian() - error := int32(native.Uint32(m.Data[0:4])) - if error == 0 { - continue - } - if cberr != nil { - cberr(syscall.Errno(-error)) - } - return - } - route, err := deserializeRoute(m.Data) - if err != nil { - if cberr != nil { - cberr(err) - } - return - } - ch <- RouteUpdate{Type: m.Header.Type, Route: route} - } - } - }() - - return nil -} diff --git a/vendor/github.com/vishvananda/netlink/route_unspecified.go b/vendor/github.com/vishvananda/netlink/route_unspecified.go deleted file mode 100644 index 2701862b4..000000000 --- a/vendor/github.com/vishvananda/netlink/route_unspecified.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build !linux - -package netlink - -func (r *Route) ListFlags() []string { - return []string{} -} - -func (n *NexthopInfo) ListFlags() []string { - return []string{} -} diff --git a/vendor/github.com/vishvananda/netlink/rule.go b/vendor/github.com/vishvananda/netlink/rule.go deleted file mode 100644 index 7fc8ae5df..000000000 --- a/vendor/github.com/vishvananda/netlink/rule.go +++ /dev/null @@ -1,42 +0,0 @@ -package netlink - -import ( - "fmt" - "net" -) - -// Rule represents a netlink rule. -type Rule struct { - Priority int - Family int - Table int - Mark int - Mask int - TunID uint - Goto int - Src *net.IPNet - Dst *net.IPNet - Flow int - IifName string - OifName string - SuppressIfgroup int - SuppressPrefixlen int - Invert bool -} - -func (r Rule) String() string { - return fmt.Sprintf("ip rule %d: from %s table %d", r.Priority, r.Src, r.Table) -} - -// NewRule return empty rules. -func NewRule() *Rule { - return &Rule{ - SuppressIfgroup: -1, - SuppressPrefixlen: -1, - Priority: -1, - Mark: -1, - Mask: -1, - Goto: -1, - Flow: -1, - } -} diff --git a/vendor/github.com/vishvananda/netlink/rule_linux.go b/vendor/github.com/vishvananda/netlink/rule_linux.go deleted file mode 100644 index e12569fe4..000000000 --- a/vendor/github.com/vishvananda/netlink/rule_linux.go +++ /dev/null @@ -1,234 +0,0 @@ -package netlink - -import ( - "fmt" - "net" - - "github.com/vishvananda/netlink/nl" - "golang.org/x/sys/unix" -) - -const FibRuleInvert = 0x2 - -// RuleAdd adds a rule to the system. -// Equivalent to: ip rule add -func RuleAdd(rule *Rule) error { - return pkgHandle.RuleAdd(rule) -} - -// RuleAdd adds a rule to the system. -// Equivalent to: ip rule add -func (h *Handle) RuleAdd(rule *Rule) error { - req := h.newNetlinkRequest(unix.RTM_NEWRULE, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) - return ruleHandle(rule, req) -} - -// RuleDel deletes a rule from the system. -// Equivalent to: ip rule del -func RuleDel(rule *Rule) error { - return pkgHandle.RuleDel(rule) -} - -// RuleDel deletes a rule from the system. -// Equivalent to: ip rule del -func (h *Handle) RuleDel(rule *Rule) error { - req := h.newNetlinkRequest(unix.RTM_DELRULE, unix.NLM_F_ACK) - return ruleHandle(rule, req) -} - -func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error { - msg := nl.NewRtMsg() - msg.Family = unix.AF_INET - msg.Protocol = unix.RTPROT_BOOT - msg.Scope = unix.RT_SCOPE_UNIVERSE - msg.Table = unix.RT_TABLE_UNSPEC - msg.Type = unix.RTN_UNSPEC - if req.NlMsghdr.Flags&unix.NLM_F_CREATE > 0 { - msg.Type = unix.RTN_UNICAST - } - if rule.Invert { - msg.Flags |= FibRuleInvert - } - if rule.Family != 0 { - msg.Family = uint8(rule.Family) - } - if rule.Table >= 0 && rule.Table < 256 { - msg.Table = uint8(rule.Table) - } - - var dstFamily uint8 - var rtAttrs []*nl.RtAttr - if rule.Dst != nil && rule.Dst.IP != nil { - dstLen, _ := rule.Dst.Mask.Size() - msg.Dst_len = uint8(dstLen) - msg.Family = uint8(nl.GetIPFamily(rule.Dst.IP)) - dstFamily = msg.Family - var dstData []byte - if msg.Family == unix.AF_INET { - dstData = rule.Dst.IP.To4() - } else { - dstData = rule.Dst.IP.To16() - } - rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, dstData)) - } - - if rule.Src != nil && rule.Src.IP != nil { - msg.Family = uint8(nl.GetIPFamily(rule.Src.IP)) - if dstFamily != 0 && dstFamily != msg.Family { - return fmt.Errorf("source and destination ip are not the same IP family") - } - srcLen, _ := rule.Src.Mask.Size() - msg.Src_len = uint8(srcLen) - var srcData []byte - if msg.Family == unix.AF_INET { - srcData = rule.Src.IP.To4() - } else { - srcData = rule.Src.IP.To16() - } - rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_SRC, srcData)) - } - - req.AddData(msg) - for i := range rtAttrs { - req.AddData(rtAttrs[i]) - } - - native := nl.NativeEndian() - - if rule.Priority >= 0 { - b := make([]byte, 4) - native.PutUint32(b, uint32(rule.Priority)) - req.AddData(nl.NewRtAttr(nl.FRA_PRIORITY, b)) - } - if rule.Mark >= 0 { - b := make([]byte, 4) - native.PutUint32(b, uint32(rule.Mark)) - req.AddData(nl.NewRtAttr(nl.FRA_FWMARK, b)) - } - if rule.Mask >= 0 { - b := make([]byte, 4) - native.PutUint32(b, uint32(rule.Mask)) - req.AddData(nl.NewRtAttr(nl.FRA_FWMASK, b)) - } - if rule.Flow >= 0 { - b := make([]byte, 4) - native.PutUint32(b, uint32(rule.Flow)) - req.AddData(nl.NewRtAttr(nl.FRA_FLOW, b)) - } - if rule.TunID > 0 { - b := make([]byte, 4) - native.PutUint32(b, uint32(rule.TunID)) - req.AddData(nl.NewRtAttr(nl.FRA_TUN_ID, b)) - } - if rule.Table >= 256 { - b := make([]byte, 4) - native.PutUint32(b, uint32(rule.Table)) - req.AddData(nl.NewRtAttr(nl.FRA_TABLE, b)) - } - if msg.Table > 0 { - if rule.SuppressPrefixlen >= 0 { - b := make([]byte, 4) - native.PutUint32(b, uint32(rule.SuppressPrefixlen)) - req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_PREFIXLEN, b)) - } - if rule.SuppressIfgroup >= 0 { - b := make([]byte, 4) - native.PutUint32(b, uint32(rule.SuppressIfgroup)) - req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_IFGROUP, b)) - } - } - if rule.IifName != "" { - req.AddData(nl.NewRtAttr(nl.FRA_IIFNAME, []byte(rule.IifName))) - } - if rule.OifName != "" { - req.AddData(nl.NewRtAttr(nl.FRA_OIFNAME, []byte(rule.OifName))) - } - if rule.Goto >= 0 { - msg.Type = nl.FR_ACT_GOTO - b := make([]byte, 4) - native.PutUint32(b, uint32(rule.Goto)) - req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b)) - } - - _, err := req.Execute(unix.NETLINK_ROUTE, 0) - return err -} - -// RuleList lists rules in the system. -// Equivalent to: ip rule list -func RuleList(family int) ([]Rule, error) { - return pkgHandle.RuleList(family) -} - -// RuleList lists rules in the system. -// Equivalent to: ip rule list -func (h *Handle) RuleList(family int) ([]Rule, error) { - req := h.newNetlinkRequest(unix.RTM_GETRULE, unix.NLM_F_DUMP|unix.NLM_F_REQUEST) - msg := nl.NewIfInfomsg(family) - req.AddData(msg) - - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWRULE) - if err != nil { - return nil, err - } - - native := nl.NativeEndian() - var res = make([]Rule, 0) - for i := range msgs { - msg := nl.DeserializeRtMsg(msgs[i]) - attrs, err := nl.ParseRouteAttr(msgs[i][msg.Len():]) - if err != nil { - return nil, err - } - - rule := NewRule() - - rule.Invert = msg.Flags&FibRuleInvert > 0 - - for j := range attrs { - switch attrs[j].Attr.Type { - case unix.RTA_TABLE: - rule.Table = int(native.Uint32(attrs[j].Value[0:4])) - case nl.FRA_SRC: - rule.Src = &net.IPNet{ - IP: attrs[j].Value, - Mask: net.CIDRMask(int(msg.Src_len), 8*len(attrs[j].Value)), - } - case nl.FRA_DST: - rule.Dst = &net.IPNet{ - IP: attrs[j].Value, - Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attrs[j].Value)), - } - case nl.FRA_FWMARK: - rule.Mark = int(native.Uint32(attrs[j].Value[0:4])) - case nl.FRA_FWMASK: - rule.Mask = int(native.Uint32(attrs[j].Value[0:4])) - case nl.FRA_TUN_ID: - rule.TunID = uint(native.Uint64(attrs[j].Value[0:4])) - case nl.FRA_IIFNAME: - rule.IifName = string(attrs[j].Value[:len(attrs[j].Value)-1]) - case nl.FRA_OIFNAME: - rule.OifName = string(attrs[j].Value[:len(attrs[j].Value)-1]) - case nl.FRA_SUPPRESS_PREFIXLEN: - i := native.Uint32(attrs[j].Value[0:4]) - if i != 0xffffffff { - rule.SuppressPrefixlen = int(i) - } - case nl.FRA_SUPPRESS_IFGROUP: - i := native.Uint32(attrs[j].Value[0:4]) - if i != 0xffffffff { - rule.SuppressIfgroup = int(i) - } - case nl.FRA_FLOW: - rule.Flow = int(native.Uint32(attrs[j].Value[0:4])) - case nl.FRA_GOTO: - rule.Goto = int(native.Uint32(attrs[j].Value[0:4])) - case nl.FRA_PRIORITY: - rule.Priority = int(native.Uint32(attrs[j].Value[0:4])) - } - } - res = append(res, *rule) - } - - return res, nil -} diff --git a/vendor/github.com/vishvananda/netlink/socket.go b/vendor/github.com/vishvananda/netlink/socket.go deleted file mode 100644 index 41aa72624..000000000 --- a/vendor/github.com/vishvananda/netlink/socket.go +++ /dev/null @@ -1,27 +0,0 @@ -package netlink - -import "net" - -// SocketID identifies a single socket. -type SocketID struct { - SourcePort uint16 - DestinationPort uint16 - Source net.IP - Destination net.IP - Interface uint32 - Cookie [2]uint32 -} - -// Socket represents a netlink socket. -type Socket struct { - Family uint8 - State uint8 - Timer uint8 - Retrans uint8 - ID SocketID - Expires uint32 - RQueue uint32 - WQueue uint32 - UID uint32 - INode uint32 -} diff --git a/vendor/github.com/vishvananda/netlink/socket_linux.go b/vendor/github.com/vishvananda/netlink/socket_linux.go deleted file mode 100644 index c4d89c17e..000000000 --- a/vendor/github.com/vishvananda/netlink/socket_linux.go +++ /dev/null @@ -1,162 +0,0 @@ -package netlink - -import ( - "errors" - "fmt" - "net" - - "github.com/vishvananda/netlink/nl" - "golang.org/x/sys/unix" -) - -const ( - sizeofSocketID = 0x30 - sizeofSocketRequest = sizeofSocketID + 0x8 - sizeofSocket = sizeofSocketID + 0x18 -) - -type socketRequest struct { - Family uint8 - Protocol uint8 - Ext uint8 - pad uint8 - States uint32 - ID SocketID -} - -type writeBuffer struct { - Bytes []byte - pos int -} - -func (b *writeBuffer) Write(c byte) { - b.Bytes[b.pos] = c - b.pos++ -} - -func (b *writeBuffer) Next(n int) []byte { - s := b.Bytes[b.pos : b.pos+n] - b.pos += n - return s -} - -func (r *socketRequest) Serialize() []byte { - b := writeBuffer{Bytes: make([]byte, sizeofSocketRequest)} - b.Write(r.Family) - b.Write(r.Protocol) - b.Write(r.Ext) - b.Write(r.pad) - native.PutUint32(b.Next(4), r.States) - networkOrder.PutUint16(b.Next(2), r.ID.SourcePort) - networkOrder.PutUint16(b.Next(2), r.ID.DestinationPort) - copy(b.Next(4), r.ID.Source.To4()) - b.Next(12) - copy(b.Next(4), r.ID.Destination.To4()) - b.Next(12) - native.PutUint32(b.Next(4), r.ID.Interface) - native.PutUint32(b.Next(4), r.ID.Cookie[0]) - native.PutUint32(b.Next(4), r.ID.Cookie[1]) - return b.Bytes -} - -func (r *socketRequest) Len() int { return sizeofSocketRequest } - -type readBuffer struct { - Bytes []byte - pos int -} - -func (b *readBuffer) Read() byte { - c := b.Bytes[b.pos] - b.pos++ - return c -} - -func (b *readBuffer) Next(n int) []byte { - s := b.Bytes[b.pos : b.pos+n] - b.pos += n - return s -} - -func (s *Socket) deserialize(b []byte) error { - if len(b) < sizeofSocket { - return fmt.Errorf("socket data short read (%d); want %d", len(b), sizeofSocket) - } - rb := readBuffer{Bytes: b} - s.Family = rb.Read() - s.State = rb.Read() - s.Timer = rb.Read() - s.Retrans = rb.Read() - s.ID.SourcePort = networkOrder.Uint16(rb.Next(2)) - s.ID.DestinationPort = networkOrder.Uint16(rb.Next(2)) - s.ID.Source = net.IPv4(rb.Read(), rb.Read(), rb.Read(), rb.Read()) - rb.Next(12) - s.ID.Destination = net.IPv4(rb.Read(), rb.Read(), rb.Read(), rb.Read()) - rb.Next(12) - s.ID.Interface = native.Uint32(rb.Next(4)) - s.ID.Cookie[0] = native.Uint32(rb.Next(4)) - s.ID.Cookie[1] = native.Uint32(rb.Next(4)) - s.Expires = native.Uint32(rb.Next(4)) - s.RQueue = native.Uint32(rb.Next(4)) - s.WQueue = native.Uint32(rb.Next(4)) - s.UID = native.Uint32(rb.Next(4)) - s.INode = native.Uint32(rb.Next(4)) - return nil -} - -// SocketGet returns the Socket identified by its local and remote addresses. -func SocketGet(local, remote net.Addr) (*Socket, error) { - localTCP, ok := local.(*net.TCPAddr) - if !ok { - return nil, ErrNotImplemented - } - remoteTCP, ok := remote.(*net.TCPAddr) - if !ok { - return nil, ErrNotImplemented - } - localIP := localTCP.IP.To4() - if localIP == nil { - return nil, ErrNotImplemented - } - remoteIP := remoteTCP.IP.To4() - if remoteIP == nil { - return nil, ErrNotImplemented - } - - s, err := nl.Subscribe(unix.NETLINK_INET_DIAG) - if err != nil { - return nil, err - } - defer s.Close() - req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, 0) - req.AddData(&socketRequest{ - Family: unix.AF_INET, - Protocol: unix.IPPROTO_TCP, - ID: SocketID{ - SourcePort: uint16(localTCP.Port), - DestinationPort: uint16(remoteTCP.Port), - Source: localIP, - Destination: remoteIP, - Cookie: [2]uint32{nl.TCPDIAG_NOCOOKIE, nl.TCPDIAG_NOCOOKIE}, - }, - }) - s.Send(req) - msgs, from, err := s.Receive() - if err != nil { - return nil, err - } - if from.Pid != nl.PidKernel { - return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel) - } - if len(msgs) == 0 { - return nil, errors.New("no message nor error from netlink") - } - if len(msgs) > 2 { - return nil, fmt.Errorf("multiple (%d) matching sockets", len(msgs)) - } - sock := &Socket{} - if err := sock.deserialize(msgs[0].Data); err != nil { - return nil, err - } - return sock, nil -} diff --git a/vendor/github.com/vishvananda/netlink/xfrm.go b/vendor/github.com/vishvananda/netlink/xfrm.go deleted file mode 100644 index 02b41842e..000000000 --- a/vendor/github.com/vishvananda/netlink/xfrm.go +++ /dev/null @@ -1,75 +0,0 @@ -package netlink - -import ( - "fmt" - - "golang.org/x/sys/unix" -) - -// Proto is an enum representing an ipsec protocol. -type Proto uint8 - -const ( - XFRM_PROTO_ROUTE2 Proto = unix.IPPROTO_ROUTING - XFRM_PROTO_ESP Proto = unix.IPPROTO_ESP - XFRM_PROTO_AH Proto = unix.IPPROTO_AH - XFRM_PROTO_HAO Proto = unix.IPPROTO_DSTOPTS - XFRM_PROTO_COMP Proto = 0x6c // NOTE not defined on darwin - XFRM_PROTO_IPSEC_ANY Proto = unix.IPPROTO_RAW -) - -func (p Proto) String() string { - switch p { - case XFRM_PROTO_ROUTE2: - return "route2" - case XFRM_PROTO_ESP: - return "esp" - case XFRM_PROTO_AH: - return "ah" - case XFRM_PROTO_HAO: - return "hao" - case XFRM_PROTO_COMP: - return "comp" - case XFRM_PROTO_IPSEC_ANY: - return "ipsec-any" - } - return fmt.Sprintf("%d", p) -} - -// Mode is an enum representing an ipsec transport. -type Mode uint8 - -const ( - XFRM_MODE_TRANSPORT Mode = iota - XFRM_MODE_TUNNEL - XFRM_MODE_ROUTEOPTIMIZATION - XFRM_MODE_IN_TRIGGER - XFRM_MODE_BEET - XFRM_MODE_MAX -) - -func (m Mode) String() string { - switch m { - case XFRM_MODE_TRANSPORT: - return "transport" - case XFRM_MODE_TUNNEL: - return "tunnel" - case XFRM_MODE_ROUTEOPTIMIZATION: - return "ro" - case XFRM_MODE_IN_TRIGGER: - return "in_trigger" - case XFRM_MODE_BEET: - return "beet" - } - return fmt.Sprintf("%d", m) -} - -// XfrmMark represents the mark associated to the state or policy -type XfrmMark struct { - Value uint32 - Mask uint32 -} - -func (m *XfrmMark) String() string { - return fmt.Sprintf("(0x%x,0x%x)", m.Value, m.Mask) -} diff --git a/vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go deleted file mode 100644 index 985d3a915..000000000 --- a/vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go +++ /dev/null @@ -1,101 +0,0 @@ -package netlink - -import ( - "fmt" - - "github.com/vishvananda/netlink/nl" - "github.com/vishvananda/netns" - "golang.org/x/sys/unix" -) - -type XfrmMsg interface { - Type() nl.XfrmMsgType -} - -type XfrmMsgExpire struct { - XfrmState *XfrmState - Hard bool -} - -func (ue *XfrmMsgExpire) Type() nl.XfrmMsgType { - return nl.XFRM_MSG_EXPIRE -} - -func parseXfrmMsgExpire(b []byte) *XfrmMsgExpire { - var e XfrmMsgExpire - - msg := nl.DeserializeXfrmUserExpire(b) - e.XfrmState = xfrmStateFromXfrmUsersaInfo(&msg.XfrmUsersaInfo) - e.Hard = msg.Hard == 1 - - return &e -} - -func XfrmMonitor(ch chan<- XfrmMsg, done <-chan struct{}, errorChan chan<- error, - types ...nl.XfrmMsgType) error { - - groups, err := xfrmMcastGroups(types) - if err != nil { - return nil - } - s, err := nl.SubscribeAt(netns.None(), netns.None(), unix.NETLINK_XFRM, groups...) - if err != nil { - return err - } - - if done != nil { - go func() { - <-done - s.Close() - }() - - } - - go func() { - defer close(ch) - for { - msgs, from, err := s.Receive() - if err != nil { - errorChan <- err - return - } - if from.Pid != nl.PidKernel { - errorChan <- fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel) - return - } - for _, m := range msgs { - switch m.Header.Type { - case nl.XFRM_MSG_EXPIRE: - ch <- parseXfrmMsgExpire(m.Data) - default: - errorChan <- fmt.Errorf("unsupported msg type: %x", m.Header.Type) - } - } - } - }() - - return nil -} - -func xfrmMcastGroups(types []nl.XfrmMsgType) ([]uint, error) { - groups := make([]uint, 0) - - if len(types) == 0 { - return nil, fmt.Errorf("no xfrm msg type specified") - } - - for _, t := range types { - var group uint - - switch t { - case nl.XFRM_MSG_EXPIRE: - group = nl.XFRMNLGRP_EXPIRE - default: - return nil, fmt.Errorf("unsupported group: %x", t) - } - - groups = append(groups, group) - } - - return groups, nil -} diff --git a/vendor/github.com/vishvananda/netlink/xfrm_policy.go b/vendor/github.com/vishvananda/netlink/xfrm_policy.go deleted file mode 100644 index 6219d2772..000000000 --- a/vendor/github.com/vishvananda/netlink/xfrm_policy.go +++ /dev/null @@ -1,96 +0,0 @@ -package netlink - -import ( - "fmt" - "net" -) - -// Dir is an enum representing an ipsec template direction. -type Dir uint8 - -const ( - XFRM_DIR_IN Dir = iota - XFRM_DIR_OUT - XFRM_DIR_FWD - XFRM_SOCKET_IN - XFRM_SOCKET_OUT - XFRM_SOCKET_FWD -) - -func (d Dir) String() string { - switch d { - case XFRM_DIR_IN: - return "dir in" - case XFRM_DIR_OUT: - return "dir out" - case XFRM_DIR_FWD: - return "dir fwd" - case XFRM_SOCKET_IN: - return "socket in" - case XFRM_SOCKET_OUT: - return "socket out" - case XFRM_SOCKET_FWD: - return "socket fwd" - } - return fmt.Sprintf("socket %d", d-XFRM_SOCKET_IN) -} - -// PolicyAction is an enum representing an ipsec policy action. -type PolicyAction uint8 - -const ( - XFRM_POLICY_ALLOW PolicyAction = 0 - XFRM_POLICY_BLOCK PolicyAction = 1 -) - -func (a PolicyAction) String() string { - switch a { - case XFRM_POLICY_ALLOW: - return "allow" - case XFRM_POLICY_BLOCK: - return "block" - default: - return fmt.Sprintf("action %d", a) - } -} - -// XfrmPolicyTmpl encapsulates a rule for the base addresses of an ipsec -// policy. These rules are matched with XfrmState to determine encryption -// and authentication algorithms. -type XfrmPolicyTmpl struct { - Dst net.IP - Src net.IP - Proto Proto - Mode Mode - Spi int - Reqid int -} - -func (t XfrmPolicyTmpl) String() string { - return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, Mode: %s, Spi: 0x%x, Reqid: 0x%x}", - t.Dst, t.Src, t.Proto, t.Mode, t.Spi, t.Reqid) -} - -// XfrmPolicy represents an ipsec policy. It represents the overlay network -// and has a list of XfrmPolicyTmpls representing the base addresses of -// the policy. -type XfrmPolicy struct { - Dst *net.IPNet - Src *net.IPNet - Proto Proto - DstPort int - SrcPort int - Dir Dir - Priority int - Index int - Action PolicyAction - Ifindex int - Ifid int - Mark *XfrmMark - Tmpls []XfrmPolicyTmpl -} - -func (p XfrmPolicy) String() string { - return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, DstPort: %d, SrcPort: %d, Dir: %s, Priority: %d, Index: %d, Action: %s, Ifindex: %d, Ifid: %d, Mark: %s, Tmpls: %s}", - p.Dst, p.Src, p.Proto, p.DstPort, p.SrcPort, p.Dir, p.Priority, p.Index, p.Action, p.Ifindex, p.Ifid, p.Mark, p.Tmpls) -} diff --git a/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go deleted file mode 100644 index a4e132ef5..000000000 --- a/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go +++ /dev/null @@ -1,263 +0,0 @@ -package netlink - -import ( - "github.com/vishvananda/netlink/nl" - "golang.org/x/sys/unix" -) - -func selFromPolicy(sel *nl.XfrmSelector, policy *XfrmPolicy) { - sel.Family = uint16(nl.FAMILY_V4) - if policy.Dst != nil { - sel.Family = uint16(nl.GetIPFamily(policy.Dst.IP)) - sel.Daddr.FromIP(policy.Dst.IP) - prefixlenD, _ := policy.Dst.Mask.Size() - sel.PrefixlenD = uint8(prefixlenD) - } - if policy.Src != nil { - sel.Saddr.FromIP(policy.Src.IP) - prefixlenS, _ := policy.Src.Mask.Size() - sel.PrefixlenS = uint8(prefixlenS) - } - sel.Proto = uint8(policy.Proto) - sel.Dport = nl.Swap16(uint16(policy.DstPort)) - sel.Sport = nl.Swap16(uint16(policy.SrcPort)) - if sel.Dport != 0 { - sel.DportMask = ^uint16(0) - } - if sel.Sport != 0 { - sel.SportMask = ^uint16(0) - } - sel.Ifindex = int32(policy.Ifindex) -} - -// XfrmPolicyAdd will add an xfrm policy to the system. -// Equivalent to: `ip xfrm policy add $policy` -func XfrmPolicyAdd(policy *XfrmPolicy) error { - return pkgHandle.XfrmPolicyAdd(policy) -} - -// XfrmPolicyAdd will add an xfrm policy to the system. -// Equivalent to: `ip xfrm policy add $policy` -func (h *Handle) XfrmPolicyAdd(policy *XfrmPolicy) error { - return h.xfrmPolicyAddOrUpdate(policy, nl.XFRM_MSG_NEWPOLICY) -} - -// XfrmPolicyUpdate will update an xfrm policy to the system. -// Equivalent to: `ip xfrm policy update $policy` -func XfrmPolicyUpdate(policy *XfrmPolicy) error { - return pkgHandle.XfrmPolicyUpdate(policy) -} - -// XfrmPolicyUpdate will update an xfrm policy to the system. -// Equivalent to: `ip xfrm policy update $policy` -func (h *Handle) XfrmPolicyUpdate(policy *XfrmPolicy) error { - return h.xfrmPolicyAddOrUpdate(policy, nl.XFRM_MSG_UPDPOLICY) -} - -func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error { - req := h.newNetlinkRequest(nlProto, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) - - msg := &nl.XfrmUserpolicyInfo{} - selFromPolicy(&msg.Sel, policy) - msg.Priority = uint32(policy.Priority) - msg.Index = uint32(policy.Index) - msg.Dir = uint8(policy.Dir) - msg.Action = uint8(policy.Action) - msg.Lft.SoftByteLimit = nl.XFRM_INF - msg.Lft.HardByteLimit = nl.XFRM_INF - msg.Lft.SoftPacketLimit = nl.XFRM_INF - msg.Lft.HardPacketLimit = nl.XFRM_INF - req.AddData(msg) - - tmplData := make([]byte, nl.SizeofXfrmUserTmpl*len(policy.Tmpls)) - for i, tmpl := range policy.Tmpls { - start := i * nl.SizeofXfrmUserTmpl - userTmpl := nl.DeserializeXfrmUserTmpl(tmplData[start : start+nl.SizeofXfrmUserTmpl]) - userTmpl.XfrmId.Daddr.FromIP(tmpl.Dst) - userTmpl.Saddr.FromIP(tmpl.Src) - userTmpl.XfrmId.Proto = uint8(tmpl.Proto) - userTmpl.XfrmId.Spi = nl.Swap32(uint32(tmpl.Spi)) - userTmpl.Mode = uint8(tmpl.Mode) - userTmpl.Reqid = uint32(tmpl.Reqid) - userTmpl.Aalgos = ^uint32(0) - userTmpl.Ealgos = ^uint32(0) - userTmpl.Calgos = ^uint32(0) - } - if len(tmplData) > 0 { - tmpls := nl.NewRtAttr(nl.XFRMA_TMPL, tmplData) - req.AddData(tmpls) - } - if policy.Mark != nil { - out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(policy.Mark)) - req.AddData(out) - } - - ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(policy.Ifid))) - req.AddData(ifId) - - _, err := req.Execute(unix.NETLINK_XFRM, 0) - return err -} - -// XfrmPolicyDel will delete an xfrm policy from the system. Note that -// the Tmpls are ignored when matching the policy to delete. -// Equivalent to: `ip xfrm policy del $policy` -func XfrmPolicyDel(policy *XfrmPolicy) error { - return pkgHandle.XfrmPolicyDel(policy) -} - -// XfrmPolicyDel will delete an xfrm policy from the system. Note that -// the Tmpls are ignored when matching the policy to delete. -// Equivalent to: `ip xfrm policy del $policy` -func (h *Handle) XfrmPolicyDel(policy *XfrmPolicy) error { - _, err := h.xfrmPolicyGetOrDelete(policy, nl.XFRM_MSG_DELPOLICY) - return err -} - -// XfrmPolicyList gets a list of xfrm policies in the system. -// Equivalent to: `ip xfrm policy show`. -// The list can be filtered by ip family. -func XfrmPolicyList(family int) ([]XfrmPolicy, error) { - return pkgHandle.XfrmPolicyList(family) -} - -// XfrmPolicyList gets a list of xfrm policies in the system. -// Equivalent to: `ip xfrm policy show`. -// The list can be filtered by ip family. -func (h *Handle) XfrmPolicyList(family int) ([]XfrmPolicy, error) { - req := h.newNetlinkRequest(nl.XFRM_MSG_GETPOLICY, unix.NLM_F_DUMP) - - msg := nl.NewIfInfomsg(family) - req.AddData(msg) - - msgs, err := req.Execute(unix.NETLINK_XFRM, nl.XFRM_MSG_NEWPOLICY) - if err != nil { - return nil, err - } - - var res []XfrmPolicy - for _, m := range msgs { - if policy, err := parseXfrmPolicy(m, family); err == nil { - res = append(res, *policy) - } else if err == familyError { - continue - } else { - return nil, err - } - } - return res, nil -} - -// XfrmPolicyGet gets a the policy described by the index or selector, if found. -// Equivalent to: `ip xfrm policy get { SELECTOR | index INDEX } dir DIR [ctx CTX ] [ mark MARK [ mask MASK ] ] [ ptype PTYPE ]`. -func XfrmPolicyGet(policy *XfrmPolicy) (*XfrmPolicy, error) { - return pkgHandle.XfrmPolicyGet(policy) -} - -// XfrmPolicyGet gets a the policy described by the index or selector, if found. -// Equivalent to: `ip xfrm policy get { SELECTOR | index INDEX } dir DIR [ctx CTX ] [ mark MARK [ mask MASK ] ] [ ptype PTYPE ]`. -func (h *Handle) XfrmPolicyGet(policy *XfrmPolicy) (*XfrmPolicy, error) { - return h.xfrmPolicyGetOrDelete(policy, nl.XFRM_MSG_GETPOLICY) -} - -// XfrmPolicyFlush will flush the policies on the system. -// Equivalent to: `ip xfrm policy flush` -func XfrmPolicyFlush() error { - return pkgHandle.XfrmPolicyFlush() -} - -// XfrmPolicyFlush will flush the policies on the system. -// Equivalent to: `ip xfrm policy flush` -func (h *Handle) XfrmPolicyFlush() error { - req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHPOLICY, unix.NLM_F_ACK) - _, err := req.Execute(unix.NETLINK_XFRM, 0) - return err -} - -func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPolicy, error) { - req := h.newNetlinkRequest(nlProto, unix.NLM_F_ACK) - - msg := &nl.XfrmUserpolicyId{} - selFromPolicy(&msg.Sel, policy) - msg.Index = uint32(policy.Index) - msg.Dir = uint8(policy.Dir) - req.AddData(msg) - - if policy.Mark != nil { - out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(policy.Mark)) - req.AddData(out) - } - - ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(policy.Ifid))) - req.AddData(ifId) - - resType := nl.XFRM_MSG_NEWPOLICY - if nlProto == nl.XFRM_MSG_DELPOLICY { - resType = 0 - } - - msgs, err := req.Execute(unix.NETLINK_XFRM, uint16(resType)) - if err != nil { - return nil, err - } - - if nlProto == nl.XFRM_MSG_DELPOLICY { - return nil, err - } - - return parseXfrmPolicy(msgs[0], FAMILY_ALL) -} - -func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) { - msg := nl.DeserializeXfrmUserpolicyInfo(m) - - // This is mainly for the policy dump - if family != FAMILY_ALL && family != int(msg.Sel.Family) { - return nil, familyError - } - - var policy XfrmPolicy - - policy.Dst = msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD) - policy.Src = msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS) - policy.Proto = Proto(msg.Sel.Proto) - policy.DstPort = int(nl.Swap16(msg.Sel.Dport)) - policy.SrcPort = int(nl.Swap16(msg.Sel.Sport)) - policy.Ifindex = int(msg.Sel.Ifindex) - policy.Priority = int(msg.Priority) - policy.Index = int(msg.Index) - policy.Dir = Dir(msg.Dir) - policy.Action = PolicyAction(msg.Action) - - attrs, err := nl.ParseRouteAttr(m[msg.Len():]) - if err != nil { - return nil, err - } - - for _, attr := range attrs { - switch attr.Attr.Type { - case nl.XFRMA_TMPL: - max := len(attr.Value) - for i := 0; i < max; i += nl.SizeofXfrmUserTmpl { - var resTmpl XfrmPolicyTmpl - tmpl := nl.DeserializeXfrmUserTmpl(attr.Value[i : i+nl.SizeofXfrmUserTmpl]) - resTmpl.Dst = tmpl.XfrmId.Daddr.ToIP() - resTmpl.Src = tmpl.Saddr.ToIP() - resTmpl.Proto = Proto(tmpl.XfrmId.Proto) - resTmpl.Mode = Mode(tmpl.Mode) - resTmpl.Spi = int(nl.Swap32(tmpl.XfrmId.Spi)) - resTmpl.Reqid = int(tmpl.Reqid) - policy.Tmpls = append(policy.Tmpls, resTmpl) - } - case nl.XFRMA_MARK: - mark := nl.DeserializeXfrmMark(attr.Value[:]) - policy.Mark = new(XfrmMark) - policy.Mark.Value = mark.Value - policy.Mark.Mask = mark.Mask - case nl.XFRMA_IF_ID: - policy.Ifid = int(native.Uint32(attr.Value)) - } - } - - return &policy, nil -} diff --git a/vendor/github.com/vishvananda/netlink/xfrm_state.go b/vendor/github.com/vishvananda/netlink/xfrm_state.go deleted file mode 100644 index 483d8934a..000000000 --- a/vendor/github.com/vishvananda/netlink/xfrm_state.go +++ /dev/null @@ -1,131 +0,0 @@ -package netlink - -import ( - "fmt" - "net" - "time" -) - -// XfrmStateAlgo represents the algorithm to use for the ipsec encryption. -type XfrmStateAlgo struct { - Name string - Key []byte - TruncateLen int // Auth only - ICVLen int // AEAD only -} - -func (a XfrmStateAlgo) String() string { - base := fmt.Sprintf("{Name: %s, Key: 0x%x", a.Name, a.Key) - if a.TruncateLen != 0 { - base = fmt.Sprintf("%s, Truncate length: %d", base, a.TruncateLen) - } - if a.ICVLen != 0 { - base = fmt.Sprintf("%s, ICV length: %d", base, a.ICVLen) - } - return fmt.Sprintf("%s}", base) -} - -// EncapType is an enum representing the optional packet encapsulation. -type EncapType uint8 - -const ( - XFRM_ENCAP_ESPINUDP_NONIKE EncapType = iota + 1 - XFRM_ENCAP_ESPINUDP -) - -func (e EncapType) String() string { - switch e { - case XFRM_ENCAP_ESPINUDP_NONIKE: - return "espinudp-non-ike" - case XFRM_ENCAP_ESPINUDP: - return "espinudp" - } - return "unknown" -} - -// XfrmStateEncap represents the encapsulation to use for the ipsec encryption. -type XfrmStateEncap struct { - Type EncapType - SrcPort int - DstPort int - OriginalAddress net.IP -} - -func (e XfrmStateEncap) String() string { - return fmt.Sprintf("{Type: %s, Srcport: %d, DstPort: %d, OriginalAddress: %v}", - e.Type, e.SrcPort, e.DstPort, e.OriginalAddress) -} - -// XfrmStateLimits represents the configured limits for the state. -type XfrmStateLimits struct { - ByteSoft uint64 - ByteHard uint64 - PacketSoft uint64 - PacketHard uint64 - TimeSoft uint64 - TimeHard uint64 - TimeUseSoft uint64 - TimeUseHard uint64 -} - -// XfrmStateStats represents the current number of bytes/packets -// processed by this State, the State's installation and first use -// time and the replay window counters. -type XfrmStateStats struct { - ReplayWindow uint32 - Replay uint32 - Failed uint32 - Bytes uint64 - Packets uint64 - AddTime uint64 - UseTime uint64 -} - -// XfrmState represents the state of an ipsec policy. It optionally -// contains an XfrmStateAlgo for encryption and one for authentication. -type XfrmState struct { - Dst net.IP - Src net.IP - Proto Proto - Mode Mode - Spi int - Reqid int - ReplayWindow int - Limits XfrmStateLimits - Statistics XfrmStateStats - Mark *XfrmMark - OutputMark int - Ifid int - Auth *XfrmStateAlgo - Crypt *XfrmStateAlgo - Aead *XfrmStateAlgo - Encap *XfrmStateEncap - ESN bool -} - -func (sa XfrmState) String() string { - return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, OutputMark: %d, Ifid: %d, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t", - sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.OutputMark, sa.Ifid, sa.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN) -} -func (sa XfrmState) Print(stats bool) string { - if !stats { - return sa.String() - } - at := time.Unix(int64(sa.Statistics.AddTime), 0).Format(time.UnixDate) - ut := "-" - if sa.Statistics.UseTime > 0 { - ut = time.Unix(int64(sa.Statistics.UseTime), 0).Format(time.UnixDate) - } - return fmt.Sprintf("%s, ByteSoft: %s, ByteHard: %s, PacketSoft: %s, PacketHard: %s, TimeSoft: %d, TimeHard: %d, TimeUseSoft: %d, TimeUseHard: %d, Bytes: %d, Packets: %d, "+ - "AddTime: %s, UseTime: %s, ReplayWindow: %d, Replay: %d, Failed: %d", - sa.String(), printLimit(sa.Limits.ByteSoft), printLimit(sa.Limits.ByteHard), printLimit(sa.Limits.PacketSoft), printLimit(sa.Limits.PacketHard), - sa.Limits.TimeSoft, sa.Limits.TimeHard, sa.Limits.TimeUseSoft, sa.Limits.TimeUseHard, sa.Statistics.Bytes, sa.Statistics.Packets, at, ut, - sa.Statistics.ReplayWindow, sa.Statistics.Replay, sa.Statistics.Failed) -} - -func printLimit(lmt uint64) string { - if lmt == ^uint64(0) { - return "(INF)" - } - return fmt.Sprintf("%d", lmt) -} diff --git a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go deleted file mode 100644 index 66c99423c..000000000 --- a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go +++ /dev/null @@ -1,462 +0,0 @@ -package netlink - -import ( - "fmt" - "unsafe" - - "github.com/vishvananda/netlink/nl" - "golang.org/x/sys/unix" -) - -func writeStateAlgo(a *XfrmStateAlgo) []byte { - algo := nl.XfrmAlgo{ - AlgKeyLen: uint32(len(a.Key) * 8), - AlgKey: a.Key, - } - end := len(a.Name) - if end > 64 { - end = 64 - } - copy(algo.AlgName[:end], a.Name) - return algo.Serialize() -} - -func writeStateAlgoAuth(a *XfrmStateAlgo) []byte { - algo := nl.XfrmAlgoAuth{ - AlgKeyLen: uint32(len(a.Key) * 8), - AlgTruncLen: uint32(a.TruncateLen), - AlgKey: a.Key, - } - end := len(a.Name) - if end > 64 { - end = 64 - } - copy(algo.AlgName[:end], a.Name) - return algo.Serialize() -} - -func writeStateAlgoAead(a *XfrmStateAlgo) []byte { - algo := nl.XfrmAlgoAEAD{ - AlgKeyLen: uint32(len(a.Key) * 8), - AlgICVLen: uint32(a.ICVLen), - AlgKey: a.Key, - } - end := len(a.Name) - if end > 64 { - end = 64 - } - copy(algo.AlgName[:end], a.Name) - return algo.Serialize() -} - -func writeMark(m *XfrmMark) []byte { - mark := &nl.XfrmMark{ - Value: m.Value, - Mask: m.Mask, - } - if mark.Mask == 0 { - mark.Mask = ^uint32(0) - } - return mark.Serialize() -} - -func writeReplayEsn(replayWindow int) []byte { - replayEsn := &nl.XfrmReplayStateEsn{ - OSeq: 0, - Seq: 0, - OSeqHi: 0, - SeqHi: 0, - ReplayWindow: uint32(replayWindow), - } - - // Linux stores the bitmap to identify the already received sequence packets in blocks of uint32 elements. - // Therefore bitmap length is the minimum number of uint32 elements needed. The following is a ceiling operation. - bytesPerElem := int(unsafe.Sizeof(replayEsn.BmpLen)) // Any uint32 variable is good for this - replayEsn.BmpLen = uint32((replayWindow + (bytesPerElem * 8) - 1) / (bytesPerElem * 8)) - - return replayEsn.Serialize() -} - -// XfrmStateAdd will add an xfrm state to the system. -// Equivalent to: `ip xfrm state add $state` -func XfrmStateAdd(state *XfrmState) error { - return pkgHandle.XfrmStateAdd(state) -} - -// XfrmStateAdd will add an xfrm state to the system. -// Equivalent to: `ip xfrm state add $state` -func (h *Handle) XfrmStateAdd(state *XfrmState) error { - return h.xfrmStateAddOrUpdate(state, nl.XFRM_MSG_NEWSA) -} - -// XfrmStateAllocSpi will allocate an xfrm state in the system. -// Equivalent to: `ip xfrm state allocspi` -func XfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) { - return pkgHandle.xfrmStateAllocSpi(state) -} - -// XfrmStateUpdate will update an xfrm state to the system. -// Equivalent to: `ip xfrm state update $state` -func XfrmStateUpdate(state *XfrmState) error { - return pkgHandle.XfrmStateUpdate(state) -} - -// XfrmStateUpdate will update an xfrm state to the system. -// Equivalent to: `ip xfrm state update $state` -func (h *Handle) XfrmStateUpdate(state *XfrmState) error { - return h.xfrmStateAddOrUpdate(state, nl.XFRM_MSG_UPDSA) -} - -func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error { - - // A state with spi 0 can't be deleted so don't allow it to be set - if state.Spi == 0 { - return fmt.Errorf("Spi must be set when adding xfrm state.") - } - req := h.newNetlinkRequest(nlProto, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) - - msg := xfrmUsersaInfoFromXfrmState(state) - - if state.ESN { - if state.ReplayWindow == 0 { - return fmt.Errorf("ESN flag set without ReplayWindow") - } - msg.Flags |= nl.XFRM_STATE_ESN - msg.ReplayWindow = 0 - } - - limitsToLft(state.Limits, &msg.Lft) - req.AddData(msg) - - if state.Auth != nil { - out := nl.NewRtAttr(nl.XFRMA_ALG_AUTH_TRUNC, writeStateAlgoAuth(state.Auth)) - req.AddData(out) - } - if state.Crypt != nil { - out := nl.NewRtAttr(nl.XFRMA_ALG_CRYPT, writeStateAlgo(state.Crypt)) - req.AddData(out) - } - if state.Aead != nil { - out := nl.NewRtAttr(nl.XFRMA_ALG_AEAD, writeStateAlgoAead(state.Aead)) - req.AddData(out) - } - if state.Encap != nil { - encapData := make([]byte, nl.SizeofXfrmEncapTmpl) - encap := nl.DeserializeXfrmEncapTmpl(encapData) - encap.EncapType = uint16(state.Encap.Type) - encap.EncapSport = nl.Swap16(uint16(state.Encap.SrcPort)) - encap.EncapDport = nl.Swap16(uint16(state.Encap.DstPort)) - encap.EncapOa.FromIP(state.Encap.OriginalAddress) - out := nl.NewRtAttr(nl.XFRMA_ENCAP, encapData) - req.AddData(out) - } - if state.Mark != nil { - out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark)) - req.AddData(out) - } - if state.ESN { - out := nl.NewRtAttr(nl.XFRMA_REPLAY_ESN_VAL, writeReplayEsn(state.ReplayWindow)) - req.AddData(out) - } - if state.OutputMark != 0 { - out := nl.NewRtAttr(nl.XFRMA_OUTPUT_MARK, nl.Uint32Attr(uint32(state.OutputMark))) - req.AddData(out) - } - - ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid))) - req.AddData(ifId) - - _, err := req.Execute(unix.NETLINK_XFRM, 0) - return err -} - -func (h *Handle) xfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) { - req := h.newNetlinkRequest(nl.XFRM_MSG_ALLOCSPI, - unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) - - msg := &nl.XfrmUserSpiInfo{} - msg.XfrmUsersaInfo = *(xfrmUsersaInfoFromXfrmState(state)) - // 1-255 is reserved by IANA for future use - msg.Min = 0x100 - msg.Max = 0xffffffff - req.AddData(msg) - - if state.Mark != nil { - out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark)) - req.AddData(out) - } - - msgs, err := req.Execute(unix.NETLINK_XFRM, 0) - if err != nil { - return nil, err - } - - return parseXfrmState(msgs[0], FAMILY_ALL) -} - -// XfrmStateDel will delete an xfrm state from the system. Note that -// the Algos are ignored when matching the state to delete. -// Equivalent to: `ip xfrm state del $state` -func XfrmStateDel(state *XfrmState) error { - return pkgHandle.XfrmStateDel(state) -} - -// XfrmStateDel will delete an xfrm state from the system. Note that -// the Algos are ignored when matching the state to delete. -// Equivalent to: `ip xfrm state del $state` -func (h *Handle) XfrmStateDel(state *XfrmState) error { - _, err := h.xfrmStateGetOrDelete(state, nl.XFRM_MSG_DELSA) - return err -} - -// XfrmStateList gets a list of xfrm states in the system. -// Equivalent to: `ip [-4|-6] xfrm state show`. -// The list can be filtered by ip family. -func XfrmStateList(family int) ([]XfrmState, error) { - return pkgHandle.XfrmStateList(family) -} - -// XfrmStateList gets a list of xfrm states in the system. -// Equivalent to: `ip xfrm state show`. -// The list can be filtered by ip family. -func (h *Handle) XfrmStateList(family int) ([]XfrmState, error) { - req := h.newNetlinkRequest(nl.XFRM_MSG_GETSA, unix.NLM_F_DUMP) - - msgs, err := req.Execute(unix.NETLINK_XFRM, nl.XFRM_MSG_NEWSA) - if err != nil { - return nil, err - } - - var res []XfrmState - for _, m := range msgs { - if state, err := parseXfrmState(m, family); err == nil { - res = append(res, *state) - } else if err == familyError { - continue - } else { - return nil, err - } - } - return res, nil -} - -// XfrmStateGet gets the xfrm state described by the ID, if found. -// Equivalent to: `ip xfrm state get ID [ mark MARK [ mask MASK ] ]`. -// Only the fields which constitue the SA ID must be filled in: -// ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM-PROTO ] [ spi SPI ] -// mark is optional -func XfrmStateGet(state *XfrmState) (*XfrmState, error) { - return pkgHandle.XfrmStateGet(state) -} - -// XfrmStateGet gets the xfrm state described by the ID, if found. -// Equivalent to: `ip xfrm state get ID [ mark MARK [ mask MASK ] ]`. -// Only the fields which constitue the SA ID must be filled in: -// ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM-PROTO ] [ spi SPI ] -// mark is optional -func (h *Handle) XfrmStateGet(state *XfrmState) (*XfrmState, error) { - return h.xfrmStateGetOrDelete(state, nl.XFRM_MSG_GETSA) -} - -func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState, error) { - req := h.newNetlinkRequest(nlProto, unix.NLM_F_ACK) - - msg := &nl.XfrmUsersaId{} - msg.Family = uint16(nl.GetIPFamily(state.Dst)) - msg.Daddr.FromIP(state.Dst) - msg.Proto = uint8(state.Proto) - msg.Spi = nl.Swap32(uint32(state.Spi)) - req.AddData(msg) - - if state.Mark != nil { - out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark)) - req.AddData(out) - } - if state.Src != nil { - out := nl.NewRtAttr(nl.XFRMA_SRCADDR, state.Src.To16()) - req.AddData(out) - } - - ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid))) - req.AddData(ifId) - - resType := nl.XFRM_MSG_NEWSA - if nlProto == nl.XFRM_MSG_DELSA { - resType = 0 - } - - msgs, err := req.Execute(unix.NETLINK_XFRM, uint16(resType)) - if err != nil { - return nil, err - } - - if nlProto == nl.XFRM_MSG_DELSA { - return nil, nil - } - - s, err := parseXfrmState(msgs[0], FAMILY_ALL) - if err != nil { - return nil, err - } - - return s, nil -} - -var familyError = fmt.Errorf("family error") - -func xfrmStateFromXfrmUsersaInfo(msg *nl.XfrmUsersaInfo) *XfrmState { - var state XfrmState - - state.Dst = msg.Id.Daddr.ToIP() - state.Src = msg.Saddr.ToIP() - state.Proto = Proto(msg.Id.Proto) - state.Mode = Mode(msg.Mode) - state.Spi = int(nl.Swap32(msg.Id.Spi)) - state.Reqid = int(msg.Reqid) - state.ReplayWindow = int(msg.ReplayWindow) - lftToLimits(&msg.Lft, &state.Limits) - curToStats(&msg.Curlft, &msg.Stats, &state.Statistics) - - return &state -} - -func parseXfrmState(m []byte, family int) (*XfrmState, error) { - msg := nl.DeserializeXfrmUsersaInfo(m) - - // This is mainly for the state dump - if family != FAMILY_ALL && family != int(msg.Family) { - return nil, familyError - } - - state := xfrmStateFromXfrmUsersaInfo(msg) - - attrs, err := nl.ParseRouteAttr(m[nl.SizeofXfrmUsersaInfo:]) - if err != nil { - return nil, err - } - - for _, attr := range attrs { - switch attr.Attr.Type { - case nl.XFRMA_ALG_AUTH, nl.XFRMA_ALG_CRYPT: - var resAlgo *XfrmStateAlgo - if attr.Attr.Type == nl.XFRMA_ALG_AUTH { - if state.Auth == nil { - state.Auth = new(XfrmStateAlgo) - } - resAlgo = state.Auth - } else { - state.Crypt = new(XfrmStateAlgo) - resAlgo = state.Crypt - } - algo := nl.DeserializeXfrmAlgo(attr.Value[:]) - (*resAlgo).Name = nl.BytesToString(algo.AlgName[:]) - (*resAlgo).Key = algo.AlgKey - case nl.XFRMA_ALG_AUTH_TRUNC: - if state.Auth == nil { - state.Auth = new(XfrmStateAlgo) - } - algo := nl.DeserializeXfrmAlgoAuth(attr.Value[:]) - state.Auth.Name = nl.BytesToString(algo.AlgName[:]) - state.Auth.Key = algo.AlgKey - state.Auth.TruncateLen = int(algo.AlgTruncLen) - case nl.XFRMA_ALG_AEAD: - state.Aead = new(XfrmStateAlgo) - algo := nl.DeserializeXfrmAlgoAEAD(attr.Value[:]) - state.Aead.Name = nl.BytesToString(algo.AlgName[:]) - state.Aead.Key = algo.AlgKey - state.Aead.ICVLen = int(algo.AlgICVLen) - case nl.XFRMA_ENCAP: - encap := nl.DeserializeXfrmEncapTmpl(attr.Value[:]) - state.Encap = new(XfrmStateEncap) - state.Encap.Type = EncapType(encap.EncapType) - state.Encap.SrcPort = int(nl.Swap16(encap.EncapSport)) - state.Encap.DstPort = int(nl.Swap16(encap.EncapDport)) - state.Encap.OriginalAddress = encap.EncapOa.ToIP() - case nl.XFRMA_MARK: - mark := nl.DeserializeXfrmMark(attr.Value[:]) - state.Mark = new(XfrmMark) - state.Mark.Value = mark.Value - state.Mark.Mask = mark.Mask - case nl.XFRMA_OUTPUT_MARK: - state.OutputMark = int(native.Uint32(attr.Value)) - case nl.XFRMA_IF_ID: - state.Ifid = int(native.Uint32(attr.Value)) - } - } - - return state, nil -} - -// XfrmStateFlush will flush the xfrm state on the system. -// proto = 0 means any transformation protocols -// Equivalent to: `ip xfrm state flush [ proto XFRM-PROTO ]` -func XfrmStateFlush(proto Proto) error { - return pkgHandle.XfrmStateFlush(proto) -} - -// XfrmStateFlush will flush the xfrm state on the system. -// proto = 0 means any transformation protocols -// Equivalent to: `ip xfrm state flush [ proto XFRM-PROTO ]` -func (h *Handle) XfrmStateFlush(proto Proto) error { - req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHSA, unix.NLM_F_ACK) - - req.AddData(&nl.XfrmUsersaFlush{Proto: uint8(proto)}) - - _, err := req.Execute(unix.NETLINK_XFRM, 0) - return err -} - -func limitsToLft(lmts XfrmStateLimits, lft *nl.XfrmLifetimeCfg) { - if lmts.ByteSoft != 0 { - lft.SoftByteLimit = lmts.ByteSoft - } else { - lft.SoftByteLimit = nl.XFRM_INF - } - if lmts.ByteHard != 0 { - lft.HardByteLimit = lmts.ByteHard - } else { - lft.HardByteLimit = nl.XFRM_INF - } - if lmts.PacketSoft != 0 { - lft.SoftPacketLimit = lmts.PacketSoft - } else { - lft.SoftPacketLimit = nl.XFRM_INF - } - if lmts.PacketHard != 0 { - lft.HardPacketLimit = lmts.PacketHard - } else { - lft.HardPacketLimit = nl.XFRM_INF - } - lft.SoftAddExpiresSeconds = lmts.TimeSoft - lft.HardAddExpiresSeconds = lmts.TimeHard - lft.SoftUseExpiresSeconds = lmts.TimeUseSoft - lft.HardUseExpiresSeconds = lmts.TimeUseHard -} - -func lftToLimits(lft *nl.XfrmLifetimeCfg, lmts *XfrmStateLimits) { - *lmts = *(*XfrmStateLimits)(unsafe.Pointer(lft)) -} - -func curToStats(cur *nl.XfrmLifetimeCur, wstats *nl.XfrmStats, stats *XfrmStateStats) { - stats.Bytes = cur.Bytes - stats.Packets = cur.Packets - stats.AddTime = cur.AddTime - stats.UseTime = cur.UseTime - stats.ReplayWindow = wstats.ReplayWindow - stats.Replay = wstats.Replay - stats.Failed = wstats.IntegrityFailed -} - -func xfrmUsersaInfoFromXfrmState(state *XfrmState) *nl.XfrmUsersaInfo { - msg := &nl.XfrmUsersaInfo{} - msg.Family = uint16(nl.GetIPFamily(state.Dst)) - msg.Id.Daddr.FromIP(state.Dst) - msg.Saddr.FromIP(state.Src) - msg.Id.Proto = uint8(state.Proto) - msg.Mode = uint8(state.Mode) - msg.Id.Spi = nl.Swap32(uint32(state.Spi)) - msg.Reqid = uint32(state.Reqid) - msg.ReplayWindow = uint8(state.ReplayWindow) - - return msg -} diff --git a/vendor/github.com/vishvananda/netns/LICENSE b/vendor/github.com/vishvananda/netns/LICENSE deleted file mode 100644 index 9f64db858..000000000 --- a/vendor/github.com/vishvananda/netns/LICENSE +++ /dev/null @@ -1,192 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2014 Vishvananda Ishaya. - Copyright 2014 Docker, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/vishvananda/netns/README.md b/vendor/github.com/vishvananda/netns/README.md deleted file mode 100644 index 1fdb2d3e4..000000000 --- a/vendor/github.com/vishvananda/netns/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# netns - network namespaces in go # - -The netns package provides an ultra-simple interface for handling -network namespaces in go. Changing namespaces requires elevated -privileges, so in most cases this code needs to be run as root. - -## Local Build and Test ## - -You can use go get command: - - go get github.com/vishvananda/netns - -Testing (requires root): - - sudo -E go test github.com/vishvananda/netns - -## Example ## - -```go -package main - -import ( - "fmt" - "net" - "runtime" - "github.com/vishvananda/netns" -) - -func main() { - // Lock the OS Thread so we don't accidentally switch namespaces - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - // Save the current network namespace - origns, _ := netns.Get() - defer origns.Close() - - // Create a new network namespace - newns, _ := netns.New() - defer newns.Close() - - // Do something with the network namespace - ifaces, _ := net.Interfaces() - fmt.Printf("Interfaces: %v\n", ifaces) - - // Switch back to the original namespace - netns.Set(origns) -} - -``` - -## NOTE - -The library can be safely used only with Go >= 1.10 due to [golang/go#20676](https://github.com/golang/go/issues/20676). - -After locking a goroutine to its current OS thread with `runtime.LockOSThread()` -and changing its network namespace, any new subsequent goroutine won't be -scheduled on that thread while it's locked. Therefore, the new goroutine -will run in a different namespace leading to unexpected results. - -See [here](https://www.weave.works/blog/linux-namespaces-golang-followup) for more details. diff --git a/vendor/github.com/vishvananda/netns/netns.go b/vendor/github.com/vishvananda/netns/netns.go deleted file mode 100644 index 116befd54..000000000 --- a/vendor/github.com/vishvananda/netns/netns.go +++ /dev/null @@ -1,81 +0,0 @@ -// Package netns allows ultra-simple network namespace handling. NsHandles -// can be retrieved and set. Note that the current namespace is thread -// local so actions that set and reset namespaces should use LockOSThread -// to make sure the namespace doesn't change due to a goroutine switch. -// It is best to close NsHandles when you are done with them. This can be -// accomplished via a `defer ns.Close()` on the handle. Changing namespaces -// requires elevated privileges, so in most cases this code needs to be run -// as root. -package netns - -import ( - "fmt" - - "golang.org/x/sys/unix" -) - -// NsHandle is a handle to a network namespace. It can be cast directly -// to an int and used as a file descriptor. -type NsHandle int - -// Equal determines if two network handles refer to the same network -// namespace. This is done by comparing the device and inode that the -// file descriptors point to. -func (ns NsHandle) Equal(other NsHandle) bool { - if ns == other { - return true - } - var s1, s2 unix.Stat_t - if err := unix.Fstat(int(ns), &s1); err != nil { - return false - } - if err := unix.Fstat(int(other), &s2); err != nil { - return false - } - return (s1.Dev == s2.Dev) && (s1.Ino == s2.Ino) -} - -// String shows the file descriptor number and its dev and inode. -func (ns NsHandle) String() string { - if ns == -1 { - return "NS(None)" - } - var s unix.Stat_t - if err := unix.Fstat(int(ns), &s); err != nil { - return fmt.Sprintf("NS(%d: unknown)", ns) - } - return fmt.Sprintf("NS(%d: %d, %d)", ns, s.Dev, s.Ino) -} - -// UniqueId returns a string which uniquely identifies the namespace -// associated with the network handle. -func (ns NsHandle) UniqueId() string { - if ns == -1 { - return "NS(none)" - } - var s unix.Stat_t - if err := unix.Fstat(int(ns), &s); err != nil { - return "NS(unknown)" - } - return fmt.Sprintf("NS(%d:%d)", s.Dev, s.Ino) -} - -// IsOpen returns true if Close() has not been called. -func (ns NsHandle) IsOpen() bool { - return ns != -1 -} - -// Close closes the NsHandle and resets its file descriptor to -1. -// It is not safe to use an NsHandle after Close() is called. -func (ns *NsHandle) Close() error { - if err := unix.Close(int(*ns)); err != nil { - return err - } - (*ns) = -1 - return nil -} - -// None gets an empty (closed) NsHandle. -func None() NsHandle { - return NsHandle(-1) -} diff --git a/vendor/github.com/vishvananda/netns/netns_linux.go b/vendor/github.com/vishvananda/netns/netns_linux.go deleted file mode 100644 index 6be5c55c1..000000000 --- a/vendor/github.com/vishvananda/netns/netns_linux.go +++ /dev/null @@ -1,283 +0,0 @@ -//go:build linux && go1.10 -// +build linux,go1.10 - -package netns - -import ( - "fmt" - "io/ioutil" - "os" - "path" - "path/filepath" - "strconv" - "strings" - "syscall" - - "golang.org/x/sys/unix" -) - -// Deprecated: use syscall pkg instead (go >= 1.5 needed). -const ( - CLONE_NEWUTS = 0x04000000 /* New utsname group? */ - CLONE_NEWIPC = 0x08000000 /* New ipcs */ - CLONE_NEWUSER = 0x10000000 /* New user namespace */ - CLONE_NEWPID = 0x20000000 /* New pid namespace */ - CLONE_NEWNET = 0x40000000 /* New network namespace */ - CLONE_IO = 0x80000000 /* Get io context */ - bindMountPath = "/run/netns" /* Bind mount path for named netns */ -) - -// Setns sets namespace using syscall. Note that this should be a method -// in syscall but it has not been added. -func Setns(ns NsHandle, nstype int) (err error) { - return unix.Setns(int(ns), nstype) -} - -// Set sets the current network namespace to the namespace represented -// by NsHandle. -func Set(ns NsHandle) (err error) { - return Setns(ns, CLONE_NEWNET) -} - -// New creates a new network namespace, sets it as current and returns -// a handle to it. -func New() (ns NsHandle, err error) { - if err := unix.Unshare(CLONE_NEWNET); err != nil { - return -1, err - } - return Get() -} - -// NewNamed creates a new named network namespace and returns a handle to it -func NewNamed(name string) (NsHandle, error) { - if _, err := os.Stat(bindMountPath); os.IsNotExist(err) { - err = os.MkdirAll(bindMountPath, 0755) - if err != nil { - return None(), err - } - } - - newNs, err := New() - if err != nil { - return None(), err - } - - namedPath := path.Join(bindMountPath, name) - - f, err := os.OpenFile(namedPath, os.O_CREATE|os.O_EXCL, 0444) - if err != nil { - return None(), err - } - f.Close() - - nsPath := fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), syscall.Gettid()) - err = syscall.Mount(nsPath, namedPath, "bind", syscall.MS_BIND, "") - if err != nil { - return None(), err - } - - return newNs, nil -} - -// DeleteNamed deletes a named network namespace -func DeleteNamed(name string) error { - namedPath := path.Join(bindMountPath, name) - - err := syscall.Unmount(namedPath, syscall.MNT_DETACH) - if err != nil { - return err - } - - return os.Remove(namedPath) -} - -// Get gets a handle to the current threads network namespace. -func Get() (NsHandle, error) { - return GetFromThread(os.Getpid(), unix.Gettid()) -} - -// GetFromPath gets a handle to a network namespace -// identified by the path -func GetFromPath(path string) (NsHandle, error) { - fd, err := unix.Open(path, unix.O_RDONLY|unix.O_CLOEXEC, 0) - if err != nil { - return -1, err - } - return NsHandle(fd), nil -} - -// GetFromName gets a handle to a named network namespace such as one -// created by `ip netns add`. -func GetFromName(name string) (NsHandle, error) { - return GetFromPath(fmt.Sprintf("/var/run/netns/%s", name)) -} - -// GetFromPid gets a handle to the network namespace of a given pid. -func GetFromPid(pid int) (NsHandle, error) { - return GetFromPath(fmt.Sprintf("/proc/%d/ns/net", pid)) -} - -// GetFromThread gets a handle to the network namespace of a given pid and tid. -func GetFromThread(pid, tid int) (NsHandle, error) { - return GetFromPath(fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid)) -} - -// GetFromDocker gets a handle to the network namespace of a docker container. -// Id is prefixed matched against the running docker containers, so a short -// identifier can be used as long as it isn't ambiguous. -func GetFromDocker(id string) (NsHandle, error) { - pid, err := getPidForContainer(id) - if err != nil { - return -1, err - } - return GetFromPid(pid) -} - -// borrowed from docker/utils/utils.go -func findCgroupMountpoint(cgroupType string) (int, string, error) { - output, err := ioutil.ReadFile("/proc/mounts") - if err != nil { - return -1, "", err - } - - // /proc/mounts has 6 fields per line, one mount per line, e.g. - // cgroup /sys/fs/cgroup/devices cgroup rw,relatime,devices 0 0 - for _, line := range strings.Split(string(output), "\n") { - parts := strings.Split(line, " ") - if len(parts) == 6 { - switch parts[2] { - case "cgroup2": - return 2, parts[1], nil - case "cgroup": - for _, opt := range strings.Split(parts[3], ",") { - if opt == cgroupType { - return 1, parts[1], nil - } - } - } - } - } - - return -1, "", fmt.Errorf("cgroup mountpoint not found for %s", cgroupType) -} - -// Returns the relative path to the cgroup docker is running in. -// borrowed from docker/utils/utils.go -// modified to get the docker pid instead of using /proc/self -func getDockerCgroup(cgroupVer int, cgroupType string) (string, error) { - dockerpid, err := ioutil.ReadFile("/var/run/docker.pid") - if err != nil { - return "", err - } - result := strings.Split(string(dockerpid), "\n") - if len(result) == 0 || len(result[0]) == 0 { - return "", fmt.Errorf("docker pid not found in /var/run/docker.pid") - } - pid, err := strconv.Atoi(result[0]) - if err != nil { - return "", err - } - output, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cgroup", pid)) - if err != nil { - return "", err - } - for _, line := range strings.Split(string(output), "\n") { - parts := strings.Split(line, ":") - // any type used by docker should work - if (cgroupVer == 1 && parts[1] == cgroupType) || - (cgroupVer == 2 && parts[1] == "") { - return parts[2], nil - } - } - return "", fmt.Errorf("cgroup '%s' not found in /proc/%d/cgroup", cgroupType, pid) -} - -// Returns the first pid in a container. -// borrowed from docker/utils/utils.go -// modified to only return the first pid -// modified to glob with id -// modified to search for newer docker containers -// modified to look for cgroups v2 -func getPidForContainer(id string) (int, error) { - pid := 0 - - // memory is chosen randomly, any cgroup used by docker works - cgroupType := "memory" - - cgroupVer, cgroupRoot, err := findCgroupMountpoint(cgroupType) - if err != nil { - return pid, err - } - - cgroupDocker, err := getDockerCgroup(cgroupVer, cgroupType) - if err != nil { - return pid, err - } - - id += "*" - - var pidFile string - if cgroupVer == 1 { - pidFile = "tasks" - } else if cgroupVer == 2 { - pidFile = "cgroup.procs" - } else { - return -1, fmt.Errorf("Invalid cgroup version '%d'", cgroupVer) - } - - attempts := []string{ - filepath.Join(cgroupRoot, cgroupDocker, id, pidFile), - // With more recent lxc versions use, cgroup will be in lxc/ - filepath.Join(cgroupRoot, cgroupDocker, "lxc", id, pidFile), - // With more recent docker, cgroup will be in docker/ - filepath.Join(cgroupRoot, cgroupDocker, "docker", id, pidFile), - // Even more recent docker versions under systemd use docker-.scope/ - filepath.Join(cgroupRoot, "system.slice", "docker-"+id+".scope", pidFile), - // Even more recent docker versions under cgroup/systemd/docker// - filepath.Join(cgroupRoot, "..", "systemd", "docker", id, pidFile), - // Kubernetes with docker and CNI is even more different. Works for BestEffort and Burstable QoS - filepath.Join(cgroupRoot, "..", "systemd", "kubepods", "*", "pod*", id, pidFile), - // Same as above but for Guaranteed QoS - filepath.Join(cgroupRoot, "..", "systemd", "kubepods", "pod*", id, pidFile), - // Another flavor of containers location in recent kubernetes 1.11+. Works for BestEffort and Burstable QoS - filepath.Join(cgroupRoot, cgroupDocker, "kubepods.slice", "*.slice", "*", "docker-"+id+".scope", pidFile), - // Same as above but for Guaranteed QoS - filepath.Join(cgroupRoot, cgroupDocker, "kubepods.slice", "*", "docker-"+id+".scope", pidFile), - // When runs inside of a container with recent kubernetes 1.11+. Works for BestEffort and Burstable QoS - filepath.Join(cgroupRoot, "kubepods.slice", "*.slice", "*", "docker-"+id+".scope", pidFile), - // Same as above but for Guaranteed QoS - filepath.Join(cgroupRoot, "kubepods.slice", "*", "docker-"+id+".scope", pidFile), - } - - var filename string - for _, attempt := range attempts { - filenames, _ := filepath.Glob(attempt) - if len(filenames) > 1 { - return pid, fmt.Errorf("Ambiguous id supplied: %v", filenames) - } else if len(filenames) == 1 { - filename = filenames[0] - break - } - } - - if filename == "" { - return pid, fmt.Errorf("Unable to find container: %v", id[:len(id)-1]) - } - - output, err := ioutil.ReadFile(filename) - if err != nil { - return pid, err - } - - result := strings.Split(string(output), "\n") - if len(result) == 0 || len(result[0]) == 0 { - return pid, fmt.Errorf("No pid found for container") - } - - pid, err = strconv.Atoi(result[0]) - if err != nil { - return pid, fmt.Errorf("Invalid pid '%s': %s", result[0], err) - } - - return pid, nil -} diff --git a/vendor/github.com/vishvananda/netns/netns_unspecified.go b/vendor/github.com/vishvananda/netns/netns_unspecified.go deleted file mode 100644 index d06af62b6..000000000 --- a/vendor/github.com/vishvananda/netns/netns_unspecified.go +++ /dev/null @@ -1,43 +0,0 @@ -// +build !linux - -package netns - -import ( - "errors" -) - -var ( - ErrNotImplemented = errors.New("not implemented") -) - -func Set(ns NsHandle) (err error) { - return ErrNotImplemented -} - -func New() (ns NsHandle, err error) { - return -1, ErrNotImplemented -} - -func Get() (NsHandle, error) { - return -1, ErrNotImplemented -} - -func GetFromPath(path string) (NsHandle, error) { - return -1, ErrNotImplemented -} - -func GetFromName(name string) (NsHandle, error) { - return -1, ErrNotImplemented -} - -func GetFromPid(pid int) (NsHandle, error) { - return -1, ErrNotImplemented -} - -func GetFromThread(pid, tid int) (NsHandle, error) { - return -1, ErrNotImplemented -} - -func GetFromDocker(id string) (NsHandle, error) { - return -1, ErrNotImplemented -} diff --git a/vendor/modules.txt b/vendor/modules.txt index b0019609c..ebe6d1d50 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -265,9 +265,6 @@ github.com/pkg/errors # github.com/pmezard/go-difflib v1.0.0 ## explicit github.com/pmezard/go-difflib/difflib -# github.com/prashantv/gostub v1.1.0 -## explicit; go 1.17 -github.com/prashantv/gostub # github.com/prometheus/client_golang v1.11.0 ## explicit; go 1.13 github.com/prometheus/client_golang/prometheus @@ -302,13 +299,6 @@ github.com/spf13/pflag # github.com/stretchr/testify v1.7.0 ## explicit; go 1.13 github.com/stretchr/testify/assert -# github.com/vishvananda/netlink v1.1.0 -## explicit; go 1.12 -github.com/vishvananda/netlink -github.com/vishvananda/netlink/nl -# github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 -## explicit; go 1.12 -github.com/vishvananda/netns # go.etcd.io/etcd/api/v3 v3.5.0 ## explicit; go 1.16 go.etcd.io/etcd/api/v3/authpb