mirror of
https://github.com/openfaas/faasd.git
synced 2025-06-19 04:26:34 +00:00
Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
d49011702b | |||
eb369fbb16 | |||
040b426a19 | |||
251cb2d08a | |||
5c48ac1a70 | |||
7c166979c9 | |||
36843ad1d4 | |||
3bc041ba04 | |||
dd3f9732b4 | |||
6c10d18f59 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,3 +6,4 @@ hosts
|
|||||||
basic-auth-user
|
basic-auth-user
|
||||||
basic-auth-password
|
basic-auth-password
|
||||||
/bin
|
/bin
|
||||||
|
/secrets
|
||||||
|
15
Gopkg.lock
generated
15
Gopkg.lock
generated
@ -227,14 +227,6 @@
|
|||||||
revision = "6c65a5562fc06764971b7c5d05c76c75e84bdbf7"
|
revision = "6c65a5562fc06764971b7c5d05c76c75e84bdbf7"
|
||||||
version = "v1.3.2"
|
version = "v1.3.2"
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
digest = "1:582b704bebaa06b48c29b0cec224a6058a09c86883aaddabde889cd1a5f73e1b"
|
|
||||||
name = "github.com/google/uuid"
|
|
||||||
packages = ["."]
|
|
||||||
pruneopts = "UT"
|
|
||||||
revision = "0cd6bf5da1e1c83f8b45653022c74f71af0538a4"
|
|
||||||
version = "v1.1.1"
|
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:cbec35fe4d5a4fba369a656a8cd65e244ea2c743007d8f6c1ccb132acf9d1296"
|
digest = "1:cbec35fe4d5a4fba369a656a8cd65e244ea2c743007d8f6c1ccb132acf9d1296"
|
||||||
name = "github.com/gorilla/mux"
|
name = "github.com/gorilla/mux"
|
||||||
@ -375,15 +367,15 @@
|
|||||||
revision = "d98352740cb2c55f81556b63d4a1ec64c5a319c2"
|
revision = "d98352740cb2c55f81556b63d4a1ec64c5a319c2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:2d9d06cb9d46dacfdbb45f8575b39fc0126d083841a29d4fbf8d97708f43107e"
|
digest = "1:1314b5ef1c0b25257ea02e454291bf042478a48407cfe3ffea7e20323bbf5fdf"
|
||||||
name = "github.com/vishvananda/netlink"
|
name = "github.com/vishvananda/netlink"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
"nl",
|
"nl",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "a2ad57a690f3caf3015351d2d6e1c0b95c349752"
|
revision = "f049be6f391489d3f374498fe0c8df8449258372"
|
||||||
version = "v1.0.0"
|
version = "v1.1.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
@ -534,7 +526,6 @@
|
|||||||
"github.com/containerd/containerd/namespaces",
|
"github.com/containerd/containerd/namespaces",
|
||||||
"github.com/containerd/containerd/oci",
|
"github.com/containerd/containerd/oci",
|
||||||
"github.com/containerd/go-cni",
|
"github.com/containerd/go-cni",
|
||||||
"github.com/google/uuid",
|
|
||||||
"github.com/gorilla/mux",
|
"github.com/gorilla/mux",
|
||||||
"github.com/morikuni/aec",
|
"github.com/morikuni/aec",
|
||||||
"github.com/opencontainers/runtime-spec/specs-go",
|
"github.com/opencontainers/runtime-spec/specs-go",
|
||||||
|
@ -41,7 +41,3 @@
|
|||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/openfaas/faas-provider"
|
name = "github.com/openfaas/faas-provider"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/google/uuid"
|
|
||||||
version = "1.1.1"
|
|
||||||
|
38
README.md
38
README.md
@ -1,6 +1,8 @@
|
|||||||
# faasd - serverless with containerd
|
# faasd - serverless with containerd
|
||||||
|
|
||||||
[](https://travis-ci.com/alexellis/faasd)
|
[](https://travis-ci.com/alexellis/faasd)
|
||||||
|
[](https://opensource.org/licenses/MIT)
|
||||||
|
[](https://www.openfaas.com)
|
||||||
|
|
||||||
faasd is a Golang supervisor that bundles OpenFaaS for use with containerd instead of a container orchestrator like Kubernetes or Docker Swarm.
|
faasd is a Golang supervisor that bundles OpenFaaS for use with containerd instead of a container orchestrator like Kubernetes or Docker Swarm.
|
||||||
|
|
||||||
@ -10,6 +12,10 @@ faasd is a Golang supervisor that bundles OpenFaaS for use with containerd inste
|
|||||||
* faasd is multi-arch, so works on `x86_64`, armhf and arm64
|
* faasd is multi-arch, so works on `x86_64`, armhf and arm64
|
||||||
* faasd downloads, starts and supervises the core components to run OpenFaaS
|
* faasd downloads, starts and supervises the core components to run OpenFaaS
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
> Demo of faasd running in KVM
|
||||||
|
|
||||||
## What does faasd deploy?
|
## What does faasd deploy?
|
||||||
|
|
||||||
* faasd - itself, and its [faas-provider](https://github.com/openfaas/faas-provider)
|
* faasd - itself, and its [faas-provider](https://github.com/openfaas/faas-provider)
|
||||||
@ -60,6 +66,8 @@ Other operations are pending development in the provider such as:
|
|||||||
|
|
||||||
Pending:
|
Pending:
|
||||||
|
|
||||||
|
* [ ] Add support for using container images in third-party public registries
|
||||||
|
* [ ] Add support for using container images in private third-party registries
|
||||||
* [ ] Monitor and restart any of the core components at runtime if the container stops
|
* [ ] Monitor and restart any of the core components at runtime if the container stops
|
||||||
* [ ] Bundle/package/automate installation of containerd - [see bootstrap from k3s](https://github.com/rancher/k3s)
|
* [ ] Bundle/package/automate installation of containerd - [see bootstrap from k3s](https://github.com/rancher/k3s)
|
||||||
* [ ] Provide ufw rules / example for blocking access to everything but a reverse proxy to the gateway container
|
* [ ] Provide ufw rules / example for blocking access to everything but a reverse proxy to the gateway container
|
||||||
@ -84,7 +92,13 @@ You can run this tutorial on your Raspberry Pi, or adapt the steps for a regular
|
|||||||
|
|
||||||
* [faasd - lightweight Serverless for your Raspberry Pi](https://blog.alexellis.io/faasd-for-lightweight-serverless/)
|
* [faasd - lightweight Serverless for your Raspberry Pi](https://blog.alexellis.io/faasd-for-lightweight-serverless/)
|
||||||
|
|
||||||
## Get containerd
|
## Tutorial: Multipass & KVM for MacOS/Linux, or Windows (with cloud-config)
|
||||||
|
|
||||||
|
* [Get up and running with your own faasd installation on your Mac/Ubuntu or Windows with cloud-config](https://gist.github.com/alexellis/6d297e678c9243d326c151028a3ad7b9)
|
||||||
|
|
||||||
|
## Tutorial: Manual installation
|
||||||
|
|
||||||
|
### Get containerd
|
||||||
|
|
||||||
You have three options - binaries for PC, binaries for armhf, or build from source.
|
You have three options - binaries for PC, binaries for armhf, or build from source.
|
||||||
|
|
||||||
@ -136,7 +150,7 @@ Start containerd in a new terminal:
|
|||||||
```sh
|
```sh
|
||||||
sudo containerd &
|
sudo containerd &
|
||||||
```
|
```
|
||||||
### Enable forwarding
|
#### Enable forwarding
|
||||||
|
|
||||||
> This is required to allow containers in containerd to access the Internet via your computer's primary network interface.
|
> This is required to allow containers in containerd to access the Internet via your computer's primary network interface.
|
||||||
|
|
||||||
@ -150,9 +164,9 @@ Make the setting permanent:
|
|||||||
echo "net.ipv4.conf.all.forwarding=1" | sudo tee -a /etc/sysctl.conf
|
echo "net.ipv4.conf.all.forwarding=1" | sudo tee -a /etc/sysctl.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
## Hacking (build from source)
|
### Hacking (build from source)
|
||||||
|
|
||||||
### Get build packages
|
#### Get build packages
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo apt update \
|
sudo apt update \
|
||||||
@ -163,7 +177,7 @@ sudo apt update \
|
|||||||
|
|
||||||
You may find alternatives for CentOS and other distributions.
|
You may find alternatives for CentOS and other distributions.
|
||||||
|
|
||||||
### Install Go 1.13 (x86_64)
|
#### Install Go 1.13 (x86_64)
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl -sSLf https://dl.google.com/go/go1.13.6.linux-amd64.tar.gz > go.tgz
|
curl -sSLf https://dl.google.com/go/go1.13.6.linux-amd64.tar.gz > go.tgz
|
||||||
@ -177,7 +191,7 @@ export PATH=$PATH:/usr/local/go/bin/
|
|||||||
go version
|
go version
|
||||||
```
|
```
|
||||||
|
|
||||||
### Or on Raspberry Pi (armhf)
|
#### Or on Raspberry Pi (armhf)
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl -SLsf https://dl.google.com/go/go1.13.6.linux-armv6l.tar.gz > go.tgz
|
curl -SLsf https://dl.google.com/go/go1.13.6.linux-armv6l.tar.gz > go.tgz
|
||||||
@ -191,7 +205,7 @@ export PATH=$PATH:/usr/local/go/bin/
|
|||||||
go version
|
go version
|
||||||
```
|
```
|
||||||
|
|
||||||
### Install the CNI plugins:
|
#### Install the CNI plugins:
|
||||||
|
|
||||||
* For PC run `export ARCH=amd64`
|
* For PC run `export ARCH=amd64`
|
||||||
* For RPi/armhf run `export ARCH=arm`
|
* For RPi/armhf run `export ARCH=arm`
|
||||||
@ -220,26 +234,26 @@ go build
|
|||||||
# sudo ./faasd up
|
# sudo ./faasd up
|
||||||
```
|
```
|
||||||
|
|
||||||
### Build and run `faasd` (binaries)
|
#### Build and run `faasd` (binaries)
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# For x86_64
|
# For x86_64
|
||||||
sudo curl -fSLs "https://github.com/alexellis/faasd/releases/download/0.4.4/faasd" \
|
sudo curl -fSLs "https://github.com/alexellis/faasd/releases/download/0.6.2/faasd" \
|
||||||
-o "/usr/local/bin/faasd" \
|
-o "/usr/local/bin/faasd" \
|
||||||
&& sudo chmod a+x "/usr/local/bin/faasd"
|
&& sudo chmod a+x "/usr/local/bin/faasd"
|
||||||
|
|
||||||
# armhf
|
# armhf
|
||||||
sudo curl -fSLs "https://github.com/alexellis/faasd/releases/download/0.4.4/faasd-armhf" \
|
sudo curl -fSLs "https://github.com/alexellis/faasd/releases/download/0.6.2/faasd-armhf" \
|
||||||
-o "/usr/local/bin/faasd" \
|
-o "/usr/local/bin/faasd" \
|
||||||
&& sudo chmod a+x "/usr/local/bin/faasd"
|
&& sudo chmod a+x "/usr/local/bin/faasd"
|
||||||
|
|
||||||
# arm64
|
# arm64
|
||||||
sudo curl -fSLs "https://github.com/alexellis/faasd/releases/download/0.4.4/faasd-arm64" \
|
sudo curl -fSLs "https://github.com/alexellis/faasd/releases/download/0.6.2/faasd-arm64" \
|
||||||
-o "/usr/local/bin/faasd" \
|
-o "/usr/local/bin/faasd" \
|
||||||
&& sudo chmod a+x "/usr/local/bin/faasd"
|
&& sudo chmod a+x "/usr/local/bin/faasd"
|
||||||
```
|
```
|
||||||
|
|
||||||
### At run-time
|
#### At run-time
|
||||||
|
|
||||||
Look in `hosts` in the current working folder or in `/var/lib/faasd/` to get the IP for the gateway or Prometheus
|
Look in `hosts` in the current working folder or in `/var/lib/faasd/` to get the IP for the gateway or Prometheus
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ runcmd:
|
|||||||
- curl -sSL https://github.com/containernetworking/plugins/releases/download/v0.8.5/cni-plugins-linux-amd64-v0.8.5.tgz | tar -xz -C /opt/cni/bin
|
- curl -sSL https://github.com/containernetworking/plugins/releases/download/v0.8.5/cni-plugins-linux-amd64-v0.8.5.tgz | tar -xz -C /opt/cni/bin
|
||||||
- mkdir -p /go/src/github.com/alexellis/
|
- mkdir -p /go/src/github.com/alexellis/
|
||||||
- cd /go/src/github.com/alexellis/ && git clone https://github.com/alexellis/faasd
|
- cd /go/src/github.com/alexellis/ && git clone https://github.com/alexellis/faasd
|
||||||
- curl -fSLs "https://github.com/alexellis/faasd/releases/download/0.6.1/faasd" --output "/usr/local/bin/faasd" && chmod a+x "/usr/local/bin/faasd"
|
- curl -fSLs "https://github.com/alexellis/faasd/releases/download/0.7.1/faasd" --output "/usr/local/bin/faasd" && chmod a+x "/usr/local/bin/faasd"
|
||||||
- cd /go/src/github.com/alexellis/faasd/ && /usr/local/bin/faasd install
|
- cd /go/src/github.com/alexellis/faasd/ && /usr/local/bin/faasd install
|
||||||
- systemctl status -l containerd --no-pager
|
- systemctl status -l containerd --no-pager
|
||||||
- journalctl -u faasd-provider --no-pager
|
- journalctl -u faasd-provider --no-pager
|
||||||
|
@ -18,7 +18,10 @@ var installCmd = &cobra.Command{
|
|||||||
RunE: runInstall,
|
RunE: runInstall,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const workingDirectoryPermission = 0644
|
||||||
|
|
||||||
const faasdwd = "/var/lib/faasd"
|
const faasdwd = "/var/lib/faasd"
|
||||||
|
|
||||||
const faasdProviderWd = "/var/lib/faasd-provider"
|
const faasdProviderWd = "/var/lib/faasd-provider"
|
||||||
|
|
||||||
func runInstall(_ *cobra.Command, _ []string) error {
|
func runInstall(_ *cobra.Command, _ []string) error {
|
||||||
@ -102,7 +105,7 @@ func binExists(folder, name string) error {
|
|||||||
|
|
||||||
func ensureWorkingDir(folder string) error {
|
func ensureWorkingDir(folder string) error {
|
||||||
if _, err := os.Stat(folder); err != nil {
|
if _, err := os.Stat(folder); err != nil {
|
||||||
err = os.MkdirAll(folder, 0600)
|
err = os.MkdirAll(folder, workingDirectoryPermission)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
|
"github.com/alexellis/faasd/pkg/cninetwork"
|
||||||
"github.com/alexellis/faasd/pkg/provider/config"
|
"github.com/alexellis/faasd/pkg/provider/config"
|
||||||
"github.com/alexellis/faasd/pkg/provider/handlers"
|
"github.com/alexellis/faasd/pkg/provider/handlers"
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
@ -39,20 +40,20 @@ func runProvider(_ *cobra.Command, _ []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
writeHostsErr := ioutil.WriteFile(path.Join(wd, "hosts"),
|
writeHostsErr := ioutil.WriteFile(path.Join(wd, "hosts"),
|
||||||
[]byte(`127.0.0.1 localhost`), 0644)
|
[]byte(`127.0.0.1 localhost`), workingDirectoryPermission)
|
||||||
|
|
||||||
if writeHostsErr != nil {
|
if writeHostsErr != nil {
|
||||||
return fmt.Errorf("cannot write hosts file: %s", writeHostsErr)
|
return fmt.Errorf("cannot write hosts file: %s", writeHostsErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
writeResolvErr := ioutil.WriteFile(path.Join(wd, "resolv.conf"),
|
writeResolvErr := ioutil.WriteFile(path.Join(wd, "resolv.conf"),
|
||||||
[]byte(`nameserver 8.8.8.8`), 0644)
|
[]byte(`nameserver 8.8.8.8`), workingDirectoryPermission)
|
||||||
|
|
||||||
if writeResolvErr != nil {
|
if writeResolvErr != nil {
|
||||||
return fmt.Errorf("cannot write resolv.conf file: %s", writeResolvErr)
|
return fmt.Errorf("cannot write resolv.conf file: %s", writeResolvErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
cni, err := handlers.InitNetwork()
|
cni, err := cninetwork.InitNetwork()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -66,17 +67,20 @@ func runProvider(_ *cobra.Command, _ []string) error {
|
|||||||
|
|
||||||
invokeResolver := handlers.NewInvokeResolver(client)
|
invokeResolver := handlers.NewInvokeResolver(client)
|
||||||
|
|
||||||
|
userSecretPath := path.Join(wd, "secrets")
|
||||||
|
|
||||||
bootstrapHandlers := types.FaaSHandlers{
|
bootstrapHandlers := types.FaaSHandlers{
|
||||||
FunctionProxy: proxy.NewHandlerFunc(*config, invokeResolver),
|
FunctionProxy: proxy.NewHandlerFunc(*config, invokeResolver),
|
||||||
DeleteHandler: handlers.MakeDeleteHandler(client, cni),
|
DeleteHandler: handlers.MakeDeleteHandler(client, cni),
|
||||||
DeployHandler: handlers.MakeDeployHandler(client, cni),
|
DeployHandler: handlers.MakeDeployHandler(client, cni, userSecretPath),
|
||||||
FunctionReader: handlers.MakeReadHandler(client),
|
FunctionReader: handlers.MakeReadHandler(client),
|
||||||
ReplicaReader: handlers.MakeReplicaReaderHandler(client),
|
ReplicaReader: handlers.MakeReplicaReaderHandler(client),
|
||||||
ReplicaUpdater: handlers.MakeReplicaUpdateHandler(client, cni),
|
ReplicaUpdater: handlers.MakeReplicaUpdateHandler(client, cni),
|
||||||
UpdateHandler: handlers.MakeUpdateHandler(client, cni),
|
UpdateHandler: handlers.MakeUpdateHandler(client, cni, userSecretPath),
|
||||||
HealthHandler: func(w http.ResponseWriter, r *http.Request) {},
|
HealthHandler: func(w http.ResponseWriter, r *http.Request) {},
|
||||||
InfoHandler: handlers.MakeInfoHandler(Version, GitCommit),
|
InfoHandler: handlers.MakeInfoHandler(Version, GitCommit),
|
||||||
ListNamespaceHandler: listNamespaces(),
|
ListNamespaceHandler: listNamespaces(),
|
||||||
|
SecretHandler: handlers.MakeSecretHandler(client, userSecretPath),
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Listening on TCP port: %d\n", *config.TCPPort)
|
log.Printf("Listening on TCP port: %d\n", *config.TCPPort)
|
||||||
|
86
cmd/up.go
86
cmd/up.go
@ -2,7 +2,6 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@ -27,32 +26,6 @@ var upCmd = &cobra.Command{
|
|||||||
RunE: runUp,
|
RunE: runUp,
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultCNIConf is a CNI configuration that enables network access to containers (docker-bridge style)
|
|
||||||
var defaultCNIConf = fmt.Sprintf(`
|
|
||||||
{
|
|
||||||
"cniVersion": "0.4.0",
|
|
||||||
"name": "%s",
|
|
||||||
"plugins": [
|
|
||||||
{
|
|
||||||
"type": "bridge",
|
|
||||||
"bridge": "%s",
|
|
||||||
"isGateway": true,
|
|
||||||
"ipMasq": true,
|
|
||||||
"ipam": {
|
|
||||||
"type": "host-local",
|
|
||||||
"subnet": "%s",
|
|
||||||
"routes": [
|
|
||||||
{ "dst": "0.0.0.0/0" }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "firewall"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`, pkg.DefaultNetworkName, pkg.DefaultBridgeName, pkg.DefaultSubnet)
|
|
||||||
|
|
||||||
const containerSecretMountDir = "/run/secrets"
|
const containerSecretMountDir = "/run/secrets"
|
||||||
|
|
||||||
func runUp(_ *cobra.Command, _ []string) error {
|
func runUp(_ *cobra.Command, _ []string) error {
|
||||||
@ -80,10 +53,6 @@ func runUp(_ *cobra.Command, _ []string) error {
|
|||||||
return errors.Wrap(basicAuthErr, "cannot create basic-auth-* files")
|
return errors.Wrap(basicAuthErr, "cannot create basic-auth-* files")
|
||||||
}
|
}
|
||||||
|
|
||||||
if makeNetworkErr := makeNetworkConfig(); makeNetworkErr != nil {
|
|
||||||
return errors.Wrap(makeNetworkErr, "error creating network config")
|
|
||||||
}
|
|
||||||
|
|
||||||
services := makeServiceDefinitions(clientSuffix)
|
services := makeServiceDefinitions(clientSuffix)
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
@ -193,7 +162,7 @@ func makeFile(filePath, fileContents string) error {
|
|||||||
return nil
|
return nil
|
||||||
} else if os.IsNotExist(err) {
|
} else if os.IsNotExist(err) {
|
||||||
log.Printf("Writing to: %q\n", filePath)
|
log.Printf("Writing to: %q\n", filePath)
|
||||||
return ioutil.WriteFile(filePath, []byte(fileContents), 0644)
|
return ioutil.WriteFile(filePath, []byte(fileContents), workingDirectoryPermission)
|
||||||
} else {
|
} else {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -301,56 +270,3 @@ func makeServiceDefinitions(archSuffix string) []pkg.Service {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeNetworkConfig() error {
|
|
||||||
netConfig := path.Join(pkg.CNIConfDir, pkg.DefaultCNIConfFilename)
|
|
||||||
log.Printf("Writing network config...\n")
|
|
||||||
|
|
||||||
if !dirExists(pkg.CNIConfDir) {
|
|
||||||
if err := os.MkdirAll(pkg.CNIConfDir, 0755); err != nil {
|
|
||||||
return fmt.Errorf("cannot create directory: %s", pkg.CNIConfDir)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ioutil.WriteFile(netConfig, []byte(defaultCNIConf), 644); err != nil {
|
|
||||||
return fmt.Errorf("cannot write network config: %s", pkg.DefaultCNIConfFilename)
|
|
||||||
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func dirEmpty(dirname string) (b bool) {
|
|
||||||
if !dirExists(dirname) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.Open(dirname)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer func() { _ = f.Close() }()
|
|
||||||
|
|
||||||
// If the first file is EOF, the directory is empty
|
|
||||||
if _, err = f.Readdir(1); err == io.EOF {
|
|
||||||
b = true
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func dirExists(dirname string) bool {
|
|
||||||
exists, info := pathExists(dirname)
|
|
||||||
if !exists {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return info.IsDir()
|
|
||||||
}
|
|
||||||
|
|
||||||
func pathExists(path string) (bool, os.FileInfo) {
|
|
||||||
info, err := os.Stat(path)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, info
|
|
||||||
}
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package handlers
|
package cninetwork
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -23,7 +23,8 @@ const (
|
|||||||
CNIConfDir = "/etc/cni/net.d"
|
CNIConfDir = "/etc/cni/net.d"
|
||||||
// NetNSPathFmt gives the path to the a process network namespace, given the pid
|
// NetNSPathFmt gives the path to the a process network namespace, given the pid
|
||||||
NetNSPathFmt = "/proc/%d/ns/net"
|
NetNSPathFmt = "/proc/%d/ns/net"
|
||||||
|
// CNIResultsDir is the directory CNI stores allocated IP for containers
|
||||||
|
CNIResultsDir = "/var/lib/cni/results"
|
||||||
// defaultCNIConfFilename is the vanity filename of default CNI configuration file
|
// defaultCNIConfFilename is the vanity filename of default CNI configuration file
|
||||||
defaultCNIConfFilename = "10-openfaas.conflist"
|
defaultCNIConfFilename = "10-openfaas.conflist"
|
||||||
// defaultNetworkName names the "docker-bridge"-like CNI plugin-chain installed when no other CNI configuration is present.
|
// defaultNetworkName names the "docker-bridge"-like CNI plugin-chain installed when no other CNI configuration is present.
|
||||||
@ -94,8 +95,8 @@ func InitNetwork() (gocni.CNI, error) {
|
|||||||
|
|
||||||
// CreateCNINetwork creates a CNI network interface and attaches it to the context
|
// CreateCNINetwork creates a CNI network interface and attaches it to the context
|
||||||
func CreateCNINetwork(ctx context.Context, cni gocni.CNI, task containerd.Task, labels map[string]string) (*gocni.CNIResult, error) {
|
func CreateCNINetwork(ctx context.Context, cni gocni.CNI, task containerd.Task, labels map[string]string) (*gocni.CNIResult, error) {
|
||||||
id := NetID(task)
|
id := netID(task)
|
||||||
netns := NetNamespace(task)
|
netns := netNamespace(task)
|
||||||
result, err := cni.Setup(ctx, id, netns, gocni.WithLabels(labels))
|
result, err := cni.Setup(ctx, id, netns, gocni.WithLabels(labels))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "Failed to setup network for task %q: %v", id, err)
|
return nil, errors.Wrapf(err, "Failed to setup network for task %q: %v", id, err)
|
||||||
@ -116,8 +117,8 @@ func DeleteCNINetwork(ctx context.Context, cni gocni.CNI, client *containerd.Cli
|
|||||||
|
|
||||||
log.Printf("[Delete] removing CNI network for: %s\n", task.ID())
|
log.Printf("[Delete] removing CNI network for: %s\n", task.ID())
|
||||||
|
|
||||||
id := NetID(task)
|
id := netID(task)
|
||||||
netns := NetNamespace(task)
|
netns := netNamespace(task)
|
||||||
|
|
||||||
if err := cni.Remove(ctx, id, netns); err != nil {
|
if err := cni.Remove(ctx, id, netns); err != nil {
|
||||||
return errors.Wrapf(err, "Failed to remove network for task: %q, %v", id, err)
|
return errors.Wrapf(err, "Failed to remove network for task: %q, %v", id, err)
|
||||||
@ -135,7 +136,7 @@ func GetIPAddress(result *gocni.CNIResult, task containerd.Task) (net.IP, error)
|
|||||||
// Get the IP of the created interface
|
// Get the IP of the created interface
|
||||||
var ip net.IP
|
var ip net.IP
|
||||||
for ifName, config := range result.Interfaces {
|
for ifName, config := range result.Interfaces {
|
||||||
if config.Sandbox == NetNamespace(task) {
|
if config.Sandbox == netNamespace(task) {
|
||||||
for _, ipConfig := range config.IPConfigs {
|
for _, ipConfig := range config.IPConfigs {
|
||||||
if ifName != "lo" && ipConfig.IP.To4() != nil {
|
if ifName != "lo" && ipConfig.IP.To4() != nil {
|
||||||
ip = ipConfig.IP
|
ip = ipConfig.IP
|
||||||
@ -169,13 +170,24 @@ func GetIPfromPID(pid int) (*net.IP, error) {
|
|||||||
return nil, fmt.Errorf("no IP found for function")
|
return nil, fmt.Errorf("no IP found for function")
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetID generates the network IF based on task name and task PID
|
// CNIGateway returns the gateway for default subnet
|
||||||
func NetID(task containerd.Task) string {
|
func CNIGateway() (string, error) {
|
||||||
|
ip, _, err := net.ParseCIDR(defaultSubnet)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error formatting gateway for network %s", defaultSubnet)
|
||||||
|
}
|
||||||
|
ip = ip.To4()
|
||||||
|
ip[3] = 1
|
||||||
|
return ip.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// netID generates the network IF based on task name and task PID
|
||||||
|
func netID(task containerd.Task) string {
|
||||||
return fmt.Sprintf("%s-%d", task.ID(), task.Pid())
|
return fmt.Sprintf("%s-%d", task.ID(), task.Pid())
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetNamespace generates the namespace path based on task PID.
|
// netNamespace generates the namespace path based on task PID.
|
||||||
func NetNamespace(task containerd.Task) string {
|
func netNamespace(task containerd.Task) string {
|
||||||
return fmt.Sprintf(NetNSPathFmt, task.Pid())
|
return fmt.Sprintf(NetNSPathFmt, task.Pid())
|
||||||
}
|
}
|
||||||
|
|
@ -3,7 +3,7 @@
|
|||||||
// Copyright Weaveworks
|
// Copyright Weaveworks
|
||||||
// github.com/weaveworks/weave/net
|
// github.com/weaveworks/weave/net
|
||||||
|
|
||||||
package handlers
|
package cninetwork
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
@ -1,7 +1,7 @@
|
|||||||
// Copyright Weaveworks
|
// Copyright Weaveworks
|
||||||
// github.com/weaveworks/weave/net
|
// github.com/weaveworks/weave/net
|
||||||
|
|
||||||
package weave
|
package cninetwork
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
@ -8,6 +8,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
cninetwork "github.com/alexellis/faasd/pkg/cninetwork"
|
||||||
"github.com/alexellis/faasd/pkg/service"
|
"github.com/alexellis/faasd/pkg/service"
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
@ -52,7 +53,7 @@ func MakeDeleteHandler(client *containerd.Client, cni gocni.CNI) func(w http.Res
|
|||||||
|
|
||||||
// TODO: this needs to still happen if the task is paused
|
// TODO: this needs to still happen if the task is paused
|
||||||
if function.replicas != 0 {
|
if function.replicas != 0 {
|
||||||
err = DeleteCNINetwork(ctx, cni, client, name)
|
err = cninetwork.DeleteCNINetwork(ctx, cni, client, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[Delete] error removing CNI network for %s, %s\n", name, err)
|
log.Printf("[Delete] error removing CNI network for %s, %s\n", name, err)
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
cninetwork "github.com/alexellis/faasd/pkg/cninetwork"
|
||||||
"github.com/alexellis/faasd/pkg/service"
|
"github.com/alexellis/faasd/pkg/service"
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/cio"
|
"github.com/containerd/containerd/cio"
|
||||||
@ -22,7 +23,7 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func MakeDeployHandler(client *containerd.Client, cni gocni.CNI) func(w http.ResponseWriter, r *http.Request) {
|
func MakeDeployHandler(client *containerd.Client, cni gocni.CNI, secretMountPath string) func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
@ -45,11 +46,15 @@ func MakeDeployHandler(client *containerd.Client, cni gocni.CNI) func(w http.Res
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
name := req.Service
|
err = validateSecrets(secretMountPath, req.Secrets)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
name := req.Service
|
||||||
ctx := namespaces.WithNamespace(context.Background(), FunctionNamespace)
|
ctx := namespaces.WithNamespace(context.Background(), FunctionNamespace)
|
||||||
|
|
||||||
deployErr := deploy(ctx, req, client, cni)
|
deployErr := deploy(ctx, req, client, cni, secretMountPath)
|
||||||
if deployErr != nil {
|
if deployErr != nil {
|
||||||
log.Printf("[Deploy] error deploying %s, error: %s\n", name, deployErr)
|
log.Printf("[Deploy] error deploying %s, error: %s\n", name, deployErr)
|
||||||
http.Error(w, deployErr.Error(), http.StatusBadRequest)
|
http.Error(w, deployErr.Error(), http.StatusBadRequest)
|
||||||
@ -58,7 +63,7 @@ func MakeDeployHandler(client *containerd.Client, cni gocni.CNI) func(w http.Res
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func deploy(ctx context.Context, req types.FunctionDeployment, client *containerd.Client, cni gocni.CNI) error {
|
func deploy(ctx context.Context, req types.FunctionDeployment, client *containerd.Client, cni gocni.CNI, secretMountPath string) error {
|
||||||
|
|
||||||
imgRef := "docker.io/" + req.Image
|
imgRef := "docker.io/" + req.Image
|
||||||
if strings.Index(req.Image, ":") == -1 {
|
if strings.Index(req.Image, ":") == -1 {
|
||||||
@ -81,6 +86,15 @@ func deploy(ctx context.Context, req types.FunctionDeployment, client *container
|
|||||||
envs := prepareEnv(req.EnvProcess, req.EnvVars)
|
envs := prepareEnv(req.EnvProcess, req.EnvVars)
|
||||||
mounts := getMounts()
|
mounts := getMounts()
|
||||||
|
|
||||||
|
for _, secret := range req.Secrets {
|
||||||
|
mounts = append(mounts, specs.Mount{
|
||||||
|
Destination: path.Join("/var/openfaas/secrets", secret),
|
||||||
|
Type: "bind",
|
||||||
|
Source: path.Join(secretMountPath, secret),
|
||||||
|
Options: []string{"rbind", "ro"},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
name := req.Service
|
name := req.Service
|
||||||
|
|
||||||
container, err := client.NewContainer(
|
container, err := client.NewContainer(
|
||||||
@ -88,7 +102,7 @@ func deploy(ctx context.Context, req types.FunctionDeployment, client *container
|
|||||||
name,
|
name,
|
||||||
containerd.WithImage(image),
|
containerd.WithImage(image),
|
||||||
containerd.WithSnapshotter(snapshotter),
|
containerd.WithSnapshotter(snapshotter),
|
||||||
containerd.WithNewSnapshot(req.Service+"-snapshot", image),
|
containerd.WithNewSnapshot(name+"-snapshot", image),
|
||||||
containerd.WithNewSpec(oci.WithImageConfig(image),
|
containerd.WithNewSpec(oci.WithImageConfig(image),
|
||||||
oci.WithCapabilities([]string{"CAP_NET_RAW"}),
|
oci.WithCapabilities([]string{"CAP_NET_RAW"}),
|
||||||
oci.WithMounts(mounts),
|
oci.WithMounts(mounts),
|
||||||
@ -114,13 +128,13 @@ func createTask(ctx context.Context, client *containerd.Client, container contai
|
|||||||
log.Printf("Container ID: %s\tTask ID %s:\tTask PID: %d\t\n", name, task.ID(), task.Pid())
|
log.Printf("Container ID: %s\tTask ID %s:\tTask PID: %d\t\n", name, task.ID(), task.Pid())
|
||||||
|
|
||||||
labels := map[string]string{}
|
labels := map[string]string{}
|
||||||
network, err := CreateCNINetwork(ctx, cni, task, labels)
|
network, err := cninetwork.CreateCNINetwork(ctx, cni, task, labels)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ip, err := GetIPAddress(network, task)
|
ip, err := cninetwork.GetIPAddress(network, task)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -177,3 +191,12 @@ func getMounts() []specs.Mount {
|
|||||||
})
|
})
|
||||||
return mounts
|
return mounts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateSecrets(secretMountPath string, secrets []string) error {
|
||||||
|
for _, secret := range secrets {
|
||||||
|
if _, err := os.Stat(path.Join(secretMountPath, secret)); err != nil {
|
||||||
|
return fmt.Errorf("unable to find secret: %s", secret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/alexellis/faasd/pkg/cninetwork"
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
)
|
)
|
||||||
@ -62,11 +63,10 @@ func GetFunction(client *containerd.Client, name string) (Function, error) {
|
|||||||
f.pid = task.Pid()
|
f.pid = task.Pid()
|
||||||
|
|
||||||
// Get container IP address
|
// Get container IP address
|
||||||
ip, getIPErr := GetIPfromPID(int(task.Pid()))
|
ip, err := cninetwork.GetIPfromPID(int(task.Pid()))
|
||||||
if getIPErr != nil {
|
if err != nil {
|
||||||
return Function{}, getIPErr
|
return Function{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
f.IP = ip.String()
|
f.IP = ip.String()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
111
pkg/provider/handlers/secret.go
Normal file
111
pkg/provider/handlers/secret.go
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd"
|
||||||
|
"github.com/openfaas/faas-provider/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const secretFilePermission = 0644
|
||||||
|
|
||||||
|
func MakeSecretHandler(c *containerd.Client, mountPath string) func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
err := os.MkdirAll(mountPath, secretFilePermission)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Creating path: %s, error: %s\n", mountPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Body != nil {
|
||||||
|
defer r.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch r.Method {
|
||||||
|
case http.MethodGet:
|
||||||
|
listSecrets(c, w, r, mountPath)
|
||||||
|
case http.MethodPost:
|
||||||
|
createSecret(c, w, r, mountPath)
|
||||||
|
case http.MethodPut:
|
||||||
|
createSecret(c, w, r, mountPath)
|
||||||
|
case http.MethodDelete:
|
||||||
|
deleteSecret(c, w, r, mountPath)
|
||||||
|
default:
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func listSecrets(c *containerd.Client, w http.ResponseWriter, r *http.Request, mountPath string) {
|
||||||
|
files, err := ioutil.ReadDir(mountPath)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
secrets := []types.Secret{}
|
||||||
|
for _, f := range files {
|
||||||
|
secrets = append(secrets, types.Secret{Name: f.Name()})
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesOut, _ := json.Marshal(secrets)
|
||||||
|
w.Write(bytesOut)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createSecret(c *containerd.Client, w http.ResponseWriter, r *http.Request, mountPath string) {
|
||||||
|
secret, err := parseSecret(r)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[secret] error %s", err.Error())
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(path.Join(mountPath, secret.Name), []byte(secret.Value), secretFilePermission)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[secret] error %s", err.Error())
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSecret(r *http.Request) (types.Secret, error) {
|
||||||
|
secret := types.Secret{}
|
||||||
|
bytesOut, err := ioutil.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
return secret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(bytesOut, &secret)
|
||||||
|
return secret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteSecret(c *containerd.Client, w http.ResponseWriter, r *http.Request, mountPath string) {
|
||||||
|
secret, err := parseSecret(r)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[secret] error %s", err.Error())
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[secret] error %s", err.Error())
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.Remove(path.Join(mountPath, secret.Name))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[secret] error %s", err.Error())
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/alexellis/faasd/pkg/cninetwork"
|
||||||
"github.com/alexellis/faasd/pkg/service"
|
"github.com/alexellis/faasd/pkg/service"
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
@ -15,7 +16,7 @@ import (
|
|||||||
"github.com/openfaas/faas-provider/types"
|
"github.com/openfaas/faas-provider/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func MakeUpdateHandler(client *containerd.Client, cni gocni.CNI) func(w http.ResponseWriter, r *http.Request) {
|
func MakeUpdateHandler(client *containerd.Client, cni gocni.CNI, secretMountPath string) func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
@ -47,9 +48,14 @@ func MakeUpdateHandler(client *containerd.Client, cni gocni.CNI) func(w http.Res
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = validateSecrets(secretMountPath, req.Secrets)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
ctx := namespaces.WithNamespace(context.Background(), FunctionNamespace)
|
ctx := namespaces.WithNamespace(context.Background(), FunctionNamespace)
|
||||||
if function.replicas != 0 {
|
if function.replicas != 0 {
|
||||||
err = DeleteCNINetwork(ctx, cni, client, name)
|
err = cninetwork.DeleteCNINetwork(ctx, cni, client, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[Update] error removing CNI network for %s, %s\n", name, err)
|
log.Printf("[Update] error removing CNI network for %s, %s\n", name, err)
|
||||||
}
|
}
|
||||||
@ -62,7 +68,7 @@ func MakeUpdateHandler(client *containerd.Client, cni gocni.CNI) func(w http.Res
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
deployErr := deploy(ctx, req, client, cni)
|
deployErr := deploy(ctx, req, client, cni, secretMountPath)
|
||||||
if deployErr != nil {
|
if deployErr != nil {
|
||||||
log.Printf("[Update] error deploying %s, error: %s\n", name, deployErr)
|
log.Printf("[Update] error deploying %s, error: %s\n", name, deployErr)
|
||||||
http.Error(w, deployErr.Error(), http.StatusBadRequest)
|
http.Error(w, deployErr.Error(), http.StatusBadRequest)
|
||||||
|
@ -1,131 +0,0 @@
|
|||||||
// Copyright Weaveworks
|
|
||||||
// github.com/weaveworks/weave/net
|
|
||||||
|
|
||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/vishvananda/netlink"
|
|
||||||
"github.com/vishvananda/netns"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Dev struct {
|
|
||||||
Name string `json:"Name,omitempty"`
|
|
||||||
MAC net.HardwareAddr `json:"MAC,omitempty"`
|
|
||||||
CIDRs []*net.IPNet `json:"CIDRs,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func linkToNetDev(link netlink.Link) (Dev, error) {
|
|
||||||
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
|
|
||||||
if err != nil {
|
|
||||||
return Dev{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
netDev := Dev{Name: link.Attrs().Name, MAC: link.Attrs().HardwareAddr}
|
|
||||||
for _, addr := range addrs {
|
|
||||||
netDev.CIDRs = append(netDev.CIDRs, addr.IPNet)
|
|
||||||
}
|
|
||||||
return netDev, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConnectedToBridgeVethPeerIds returns peer indexes of veth links connected to
|
|
||||||
// the given bridge. The peer index is used to query from a container netns
|
|
||||||
// whether the container is connected to the bridge.
|
|
||||||
func ConnectedToBridgeVethPeerIds(bridgeName string) ([]int, error) {
|
|
||||||
var ids []int
|
|
||||||
|
|
||||||
br, err := netlink.LinkByName(bridgeName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
links, err := netlink.LinkList()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, link := range links {
|
|
||||||
if _, isveth := link.(*netlink.Veth); isveth && link.Attrs().MasterIndex == br.Attrs().Index {
|
|
||||||
peerID := link.Attrs().ParentIndex
|
|
||||||
if peerID == 0 {
|
|
||||||
// perhaps running on an older kernel where ParentIndex doesn't work.
|
|
||||||
// as fall-back, assume the peers are consecutive
|
|
||||||
peerID = link.Attrs().Index - 1
|
|
||||||
}
|
|
||||||
ids = append(ids, peerID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ids, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lookup the weave interface of a container
|
|
||||||
func GetWeaveNetDevs(processID int) ([]Dev, error) {
|
|
||||||
peerIDs, err := ConnectedToBridgeVethPeerIds("weave")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetNetDevsByVethPeerIds(processID, peerIDs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetNetDevsByVethPeerIds(processID int, peerIDs []int) ([]Dev, error) {
|
|
||||||
// Bail out if this container is running in the root namespace
|
|
||||||
netnsRoot, err := netns.GetFromPid(1)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("unable to open root namespace: %s", err)
|
|
||||||
}
|
|
||||||
defer netnsRoot.Close()
|
|
||||||
netnsContainer, err := netns.GetFromPid(processID)
|
|
||||||
if err != nil {
|
|
||||||
// Unable to find a namespace for this process - just return nothing
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("unable to open process %d namespace: %s", processID, err)
|
|
||||||
}
|
|
||||||
defer netnsContainer.Close()
|
|
||||||
if netnsRoot.Equal(netnsContainer) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert list of peerIDs into a map for faster lookup
|
|
||||||
indexes := make(map[int]struct{})
|
|
||||||
for _, id := range peerIDs {
|
|
||||||
indexes[id] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
var netdevs []Dev
|
|
||||||
err = WithNetNS(netnsContainer, func() error {
|
|
||||||
links, err := netlink.LinkList()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, link := range links {
|
|
||||||
if _, found := indexes[link.Attrs().Index]; found {
|
|
||||||
netdev, err := linkToNetDev(link)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
netdevs = append(netdevs, netdev)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
return netdevs, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the weave bridge interface.
|
|
||||||
// NB: Should be called from the root network namespace.
|
|
||||||
func GetBridgeNetDev(bridgeName string) (Dev, error) {
|
|
||||||
link, err := netlink.LinkByName(bridgeName)
|
|
||||||
if err != nil {
|
|
||||||
return Dev{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return linkToNetDev(link)
|
|
||||||
}
|
|
@ -5,48 +5,31 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
|
"github.com/alexellis/faasd/pkg/cninetwork"
|
||||||
"github.com/alexellis/faasd/pkg/service"
|
"github.com/alexellis/faasd/pkg/service"
|
||||||
"github.com/alexellis/faasd/pkg/weave"
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/cio"
|
"github.com/containerd/containerd/cio"
|
||||||
"github.com/containerd/containerd/containers"
|
"github.com/containerd/containerd/containers"
|
||||||
|
"github.com/containerd/containerd/oci"
|
||||||
gocni "github.com/containerd/go-cni"
|
gocni "github.com/containerd/go-cni"
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
"github.com/containerd/containerd/oci"
|
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultSnapshotter = "overlayfs"
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// TODO: CNIBinDir and CNIConfDir should maybe be globally configurable?
|
defaultSnapshotter = "overlayfs"
|
||||||
// CNIBinDir describes the directory where the CNI binaries are stored
|
workingDirectoryPermission = 0644
|
||||||
CNIBinDir = "/opt/cni/bin"
|
// faasdNamespace is the containerd namespace services are created
|
||||||
// CNIConfDir describes the directory where the CNI plugin's configuration is stored
|
faasdNamespace = "default"
|
||||||
CNIConfDir = "/etc/cni/net.d"
|
|
||||||
// netNSPathFmt gives the path to the a process network namespace, given the pid
|
|
||||||
NetNSPathFmt = "/proc/%d/ns/net"
|
|
||||||
// defaultCNIConfFilename is the vanity filename of default CNI configuration file
|
|
||||||
DefaultCNIConfFilename = "10-openfaas.conflist"
|
|
||||||
// defaultNetworkName names the "docker-bridge"-like CNI plugin-chain installed when no other CNI configuration is present.
|
|
||||||
// This value appears in iptables comments created by CNI.
|
|
||||||
DefaultNetworkName = "openfaas-cni-bridge"
|
|
||||||
// defaultBridgeName is the default bridge device name used in the defaultCNIConf
|
|
||||||
DefaultBridgeName = "openfaas0"
|
|
||||||
// defaultSubnet is the default subnet used in the defaultCNIConf -- this value is set to not collide with common container networking subnets:
|
|
||||||
DefaultSubnet = "10.62.0.0/16"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Supervisor struct {
|
type Supervisor struct {
|
||||||
client *containerd.Client
|
client *containerd.Client
|
||||||
|
cni gocni.CNI
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSupervisor(sock string) (*Supervisor, error) {
|
func NewSupervisor(sock string) (*Supervisor, error) {
|
||||||
@ -55,8 +38,14 @@ func NewSupervisor(sock string) (*Supervisor, error) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cni, err := cninetwork.InitNetwork()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
return &Supervisor{
|
return &Supervisor{
|
||||||
client: client,
|
client: client,
|
||||||
|
cni: cni,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,10 +54,16 @@ func (s *Supervisor) Close() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Supervisor) Remove(svcs []Service) error {
|
func (s *Supervisor) Remove(svcs []Service) error {
|
||||||
ctx := namespaces.WithNamespace(context.Background(), "default")
|
ctx := namespaces.WithNamespace(context.Background(), faasdNamespace)
|
||||||
|
|
||||||
for _, svc := range svcs {
|
for _, svc := range svcs {
|
||||||
err := service.Remove(ctx, s.client, svc.Name)
|
err := cninetwork.DeleteCNINetwork(ctx, s.cni, s.client, svc.Name)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[Delete] error removing CNI network for %s, %s\n", svc.Name, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = service.Remove(ctx, s.client, svc.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -77,20 +72,20 @@ func (s *Supervisor) Remove(svcs []Service) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Supervisor) Start(svcs []Service) error {
|
func (s *Supervisor) Start(svcs []Service) error {
|
||||||
ctx := namespaces.WithNamespace(context.Background(), "default")
|
ctx := namespaces.WithNamespace(context.Background(), faasdNamespace)
|
||||||
|
|
||||||
wd, _ := os.Getwd()
|
wd, _ := os.Getwd()
|
||||||
|
|
||||||
ip, _, _ := net.ParseCIDR(DefaultSubnet)
|
gw, err := cninetwork.CNIGateway()
|
||||||
ip = ip.To4()
|
if err != nil {
|
||||||
ip[3] = 1
|
return err
|
||||||
ip.String()
|
}
|
||||||
hosts := fmt.Sprintf(`
|
hosts := fmt.Sprintf(`
|
||||||
127.0.0.1 localhost
|
127.0.0.1 localhost
|
||||||
%s faas-containerd`, ip)
|
%s faas-containerd`, gw)
|
||||||
|
|
||||||
writeHostsErr := ioutil.WriteFile(path.Join(wd, "hosts"),
|
writeHostsErr := ioutil.WriteFile(path.Join(wd, "hosts"),
|
||||||
[]byte(hosts), 0644)
|
[]byte(hosts), workingDirectoryPermission)
|
||||||
|
|
||||||
if writeHostsErr != nil {
|
if writeHostsErr != nil {
|
||||||
return fmt.Errorf("cannot write hosts file: %s", writeHostsErr)
|
return fmt.Errorf("cannot write hosts file: %s", writeHostsErr)
|
||||||
@ -173,40 +168,25 @@ func (s *Supervisor) Start(svcs []Service) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
id := uuid.New().String()
|
|
||||||
netns := fmt.Sprintf(NetNSPathFmt, task.Pid())
|
|
||||||
|
|
||||||
cni, err := gocni.New(gocni.WithPluginConfDir(CNIConfDir),
|
|
||||||
gocni.WithPluginDir([]string{CNIBinDir}))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "error creating CNI instance")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the cni configuration
|
|
||||||
if err := cni.Load(gocni.WithLoNetwork, gocni.WithConfListFile(filepath.Join(CNIConfDir, DefaultCNIConfFilename))); err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to load cni configuration: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
labels := map[string]string{}
|
labels := map[string]string{}
|
||||||
|
network, err := cninetwork.CreateCNINetwork(ctx, s.cni, task, labels)
|
||||||
|
|
||||||
_, err = cni.Setup(ctx, id, netns, gocni.WithLabels(labels))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "failed to setup network for namespace %q: %v", id, err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the IP of the default interface.
|
ip, err := cninetwork.GetIPAddress(network, task)
|
||||||
// defaultInterface := gocni.DefaultPrefix + "0"
|
if err != nil {
|
||||||
// ip := &result.Interfaces[defaultInterface].IPConfigs[0].IP
|
return err
|
||||||
ip := getIP(newContainer.ID(), task.Pid())
|
}
|
||||||
log.Printf("%s has IP: %s\n", newContainer.ID(), ip)
|
log.Printf("%s has IP: %s\n", newContainer.ID(), ip.String())
|
||||||
|
|
||||||
hosts, _ := ioutil.ReadFile("hosts")
|
hosts, _ := ioutil.ReadFile("hosts")
|
||||||
|
|
||||||
hosts = []byte(string(hosts) + fmt.Sprintf(`
|
hosts = []byte(string(hosts) + fmt.Sprintf(`
|
||||||
%s %s
|
%s %s
|
||||||
`, ip, svc.Name))
|
`, ip, svc.Name))
|
||||||
writeErr := ioutil.WriteFile("hosts", hosts, 0644)
|
writeErr := ioutil.WriteFile("hosts", hosts, workingDirectoryPermission)
|
||||||
|
|
||||||
if writeErr != nil {
|
if writeErr != nil {
|
||||||
log.Printf("Error writing file %s %s\n", "hosts", writeErr)
|
log.Printf("Error writing file %s %s\n", "hosts", writeErr)
|
||||||
@ -231,23 +211,14 @@ func (s *Supervisor) Start(svcs []Service) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getIP(containerID string, taskPID uint32) string {
|
func withOCIArgs(args []string) oci.SpecOpts {
|
||||||
// https://github.com/weaveworks/weave/blob/master/net/netdev.go
|
if len(args) > 0 {
|
||||||
|
return oci.WithProcessArgs(args...)
|
||||||
peerIDs, err := weave.ConnectedToBridgeVethPeerIds(DefaultBridgeName)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addrs, addrsErr := weave.GetNetDevsByVethPeerIds(int(taskPID), peerIDs)
|
return func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error {
|
||||||
if addrsErr != nil {
|
return nil
|
||||||
log.Fatal(addrsErr)
|
|
||||||
}
|
}
|
||||||
if len(addrs) > 0 {
|
|
||||||
return addrs[0].CIDRs[0].IP.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
@ -263,15 +234,3 @@ type Mount struct {
|
|||||||
Src string
|
Src string
|
||||||
Dest string
|
Dest string
|
||||||
}
|
}
|
||||||
|
|
||||||
func withOCIArgs(args []string) oci.SpecOpts {
|
|
||||||
if len(args) > 0 {
|
|
||||||
return oci.WithProcessArgs(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error {
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
// +build go1.10
|
|
||||||
|
|
||||||
// Copyright Weaveworks
|
|
||||||
// github.com/weaveworks/weave/net
|
|
||||||
|
|
||||||
package weave
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/vishvananda/netlink"
|
|
||||||
"github.com/vishvananda/netns"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ErrLinkNotFound = errors.New("Link not found")
|
|
||||||
|
|
||||||
func WithNetNS(ns netns.NsHandle, work func() error) error {
|
|
||||||
runtime.LockOSThread()
|
|
||||||
defer runtime.UnlockOSThread()
|
|
||||||
|
|
||||||
oldNs, err := netns.Get()
|
|
||||||
if err == nil {
|
|
||||||
defer oldNs.Close()
|
|
||||||
|
|
||||||
err = netns.Set(ns)
|
|
||||||
if err == nil {
|
|
||||||
defer netns.Set(oldNs)
|
|
||||||
|
|
||||||
err = work()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func WithNetNSLink(ns netns.NsHandle, ifName string, work func(link netlink.Link) error) error {
|
|
||||||
return WithNetNS(ns, func() error {
|
|
||||||
link, err := netlink.LinkByName(ifName)
|
|
||||||
if err != nil {
|
|
||||||
if err.Error() == errors.New("Link not found").Error() {
|
|
||||||
return ErrLinkNotFound
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return work(link)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func WithNetNSByPath(path string, work func() error) error {
|
|
||||||
ns, err := netns.GetFromPath(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return WithNetNS(ns, work)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NSPathByPid(pid int) string {
|
|
||||||
return NSPathByPidWithRoot("/", pid)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NSPathByPidWithRoot(root string, pid int) string {
|
|
||||||
return filepath.Join(root, fmt.Sprintf("/proc/%d/ns/net", pid))
|
|
||||||
}
|
|
9
vendor/github.com/google/uuid/.travis.yml
generated
vendored
9
vendor/github.com/google/uuid/.travis.yml
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.4.3
|
|
||||||
- 1.5.3
|
|
||||||
- tip
|
|
||||||
|
|
||||||
script:
|
|
||||||
- go test -v ./...
|
|
10
vendor/github.com/google/uuid/CONTRIBUTING.md
generated
vendored
10
vendor/github.com/google/uuid/CONTRIBUTING.md
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
# How to contribute
|
|
||||||
|
|
||||||
We definitely welcome patches and contribution to this project!
|
|
||||||
|
|
||||||
### Legal requirements
|
|
||||||
|
|
||||||
In order to protect both you and ourselves, you will need to sign the
|
|
||||||
[Contributor License Agreement](https://cla.developers.google.com/clas).
|
|
||||||
|
|
||||||
You may have already signed it for other Google projects.
|
|
9
vendor/github.com/google/uuid/CONTRIBUTORS
generated
vendored
9
vendor/github.com/google/uuid/CONTRIBUTORS
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
Paul Borman <borman@google.com>
|
|
||||||
bmatsuo
|
|
||||||
shawnps
|
|
||||||
theory
|
|
||||||
jboverfelt
|
|
||||||
dsymonds
|
|
||||||
cd1
|
|
||||||
wallclockbuilder
|
|
||||||
dansouza
|
|
27
vendor/github.com/google/uuid/LICENSE
generated
vendored
27
vendor/github.com/google/uuid/LICENSE
generated
vendored
@ -1,27 +0,0 @@
|
|||||||
Copyright (c) 2009,2014 Google Inc. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
19
vendor/github.com/google/uuid/README.md
generated
vendored
19
vendor/github.com/google/uuid/README.md
generated
vendored
@ -1,19 +0,0 @@
|
|||||||
# uuid 
|
|
||||||
The uuid package generates and inspects UUIDs based on
|
|
||||||
[RFC 4122](http://tools.ietf.org/html/rfc4122)
|
|
||||||
and DCE 1.1: Authentication and Security Services.
|
|
||||||
|
|
||||||
This package is based on the github.com/pborman/uuid package (previously named
|
|
||||||
code.google.com/p/go-uuid). It differs from these earlier packages in that
|
|
||||||
a UUID is a 16 byte array rather than a byte slice. One loss due to this
|
|
||||||
change is the ability to represent an invalid UUID (vs a NIL UUID).
|
|
||||||
|
|
||||||
###### Install
|
|
||||||
`go get github.com/google/uuid`
|
|
||||||
|
|
||||||
###### Documentation
|
|
||||||
[](http://godoc.org/github.com/google/uuid)
|
|
||||||
|
|
||||||
Full `go doc` style documentation for the package can be viewed online without
|
|
||||||
installing this package by using the GoDoc site here:
|
|
||||||
http://godoc.org/github.com/google/uuid
|
|
80
vendor/github.com/google/uuid/dce.go
generated
vendored
80
vendor/github.com/google/uuid/dce.go
generated
vendored
@ -1,80 +0,0 @@
|
|||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Domain represents a Version 2 domain
|
|
||||||
type Domain byte
|
|
||||||
|
|
||||||
// Domain constants for DCE Security (Version 2) UUIDs.
|
|
||||||
const (
|
|
||||||
Person = Domain(0)
|
|
||||||
Group = Domain(1)
|
|
||||||
Org = Domain(2)
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewDCESecurity returns a DCE Security (Version 2) UUID.
|
|
||||||
//
|
|
||||||
// The domain should be one of Person, Group or Org.
|
|
||||||
// On a POSIX system the id should be the users UID for the Person
|
|
||||||
// domain and the users GID for the Group. The meaning of id for
|
|
||||||
// the domain Org or on non-POSIX systems is site defined.
|
|
||||||
//
|
|
||||||
// For a given domain/id pair the same token may be returned for up to
|
|
||||||
// 7 minutes and 10 seconds.
|
|
||||||
func NewDCESecurity(domain Domain, id uint32) (UUID, error) {
|
|
||||||
uuid, err := NewUUID()
|
|
||||||
if err == nil {
|
|
||||||
uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2
|
|
||||||
uuid[9] = byte(domain)
|
|
||||||
binary.BigEndian.PutUint32(uuid[0:], id)
|
|
||||||
}
|
|
||||||
return uuid, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDCEPerson returns a DCE Security (Version 2) UUID in the person
|
|
||||||
// domain with the id returned by os.Getuid.
|
|
||||||
//
|
|
||||||
// NewDCESecurity(Person, uint32(os.Getuid()))
|
|
||||||
func NewDCEPerson() (UUID, error) {
|
|
||||||
return NewDCESecurity(Person, uint32(os.Getuid()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDCEGroup returns a DCE Security (Version 2) UUID in the group
|
|
||||||
// domain with the id returned by os.Getgid.
|
|
||||||
//
|
|
||||||
// NewDCESecurity(Group, uint32(os.Getgid()))
|
|
||||||
func NewDCEGroup() (UUID, error) {
|
|
||||||
return NewDCESecurity(Group, uint32(os.Getgid()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Domain returns the domain for a Version 2 UUID. Domains are only defined
|
|
||||||
// for Version 2 UUIDs.
|
|
||||||
func (uuid UUID) Domain() Domain {
|
|
||||||
return Domain(uuid[9])
|
|
||||||
}
|
|
||||||
|
|
||||||
// ID returns the id for a Version 2 UUID. IDs are only defined for Version 2
|
|
||||||
// UUIDs.
|
|
||||||
func (uuid UUID) ID() uint32 {
|
|
||||||
return binary.BigEndian.Uint32(uuid[0:4])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d Domain) String() string {
|
|
||||||
switch d {
|
|
||||||
case Person:
|
|
||||||
return "Person"
|
|
||||||
case Group:
|
|
||||||
return "Group"
|
|
||||||
case Org:
|
|
||||||
return "Org"
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("Domain%d", int(d))
|
|
||||||
}
|
|
12
vendor/github.com/google/uuid/doc.go
generated
vendored
12
vendor/github.com/google/uuid/doc.go
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package uuid generates and inspects UUIDs.
|
|
||||||
//
|
|
||||||
// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security
|
|
||||||
// Services.
|
|
||||||
//
|
|
||||||
// A UUID is a 16 byte (128 bit) array. UUIDs may be used as keys to
|
|
||||||
// maps or compared directly.
|
|
||||||
package uuid
|
|
1
vendor/github.com/google/uuid/go.mod
generated
vendored
1
vendor/github.com/google/uuid/go.mod
generated
vendored
@ -1 +0,0 @@
|
|||||||
module github.com/google/uuid
|
|
53
vendor/github.com/google/uuid/hash.go
generated
vendored
53
vendor/github.com/google/uuid/hash.go
generated
vendored
@ -1,53 +0,0 @@
|
|||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/md5"
|
|
||||||
"crypto/sha1"
|
|
||||||
"hash"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Well known namespace IDs and UUIDs
|
|
||||||
var (
|
|
||||||
NameSpaceDNS = Must(Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
|
|
||||||
NameSpaceURL = Must(Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8"))
|
|
||||||
NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8"))
|
|
||||||
NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8"))
|
|
||||||
Nil UUID // empty UUID, all zeros
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewHash returns a new UUID derived from the hash of space concatenated with
|
|
||||||
// data generated by h. The hash should be at least 16 byte in length. The
|
|
||||||
// first 16 bytes of the hash are used to form the UUID. The version of the
|
|
||||||
// UUID will be the lower 4 bits of version. NewHash is used to implement
|
|
||||||
// NewMD5 and NewSHA1.
|
|
||||||
func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID {
|
|
||||||
h.Reset()
|
|
||||||
h.Write(space[:])
|
|
||||||
h.Write(data)
|
|
||||||
s := h.Sum(nil)
|
|
||||||
var uuid UUID
|
|
||||||
copy(uuid[:], s)
|
|
||||||
uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4)
|
|
||||||
uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant
|
|
||||||
return uuid
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMD5 returns a new MD5 (Version 3) UUID based on the
|
|
||||||
// supplied name space and data. It is the same as calling:
|
|
||||||
//
|
|
||||||
// NewHash(md5.New(), space, data, 3)
|
|
||||||
func NewMD5(space UUID, data []byte) UUID {
|
|
||||||
return NewHash(md5.New(), space, data, 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSHA1 returns a new SHA1 (Version 5) UUID based on the
|
|
||||||
// supplied name space and data. It is the same as calling:
|
|
||||||
//
|
|
||||||
// NewHash(sha1.New(), space, data, 5)
|
|
||||||
func NewSHA1(space UUID, data []byte) UUID {
|
|
||||||
return NewHash(sha1.New(), space, data, 5)
|
|
||||||
}
|
|
37
vendor/github.com/google/uuid/marshal.go
generated
vendored
37
vendor/github.com/google/uuid/marshal.go
generated
vendored
@ -1,37 +0,0 @@
|
|||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// MarshalText implements encoding.TextMarshaler.
|
|
||||||
func (uuid UUID) MarshalText() ([]byte, error) {
|
|
||||||
var js [36]byte
|
|
||||||
encodeHex(js[:], uuid)
|
|
||||||
return js[:], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalText implements encoding.TextUnmarshaler.
|
|
||||||
func (uuid *UUID) UnmarshalText(data []byte) error {
|
|
||||||
id, err := ParseBytes(data)
|
|
||||||
if err == nil {
|
|
||||||
*uuid = id
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalBinary implements encoding.BinaryMarshaler.
|
|
||||||
func (uuid UUID) MarshalBinary() ([]byte, error) {
|
|
||||||
return uuid[:], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalBinary implements encoding.BinaryUnmarshaler.
|
|
||||||
func (uuid *UUID) UnmarshalBinary(data []byte) error {
|
|
||||||
if len(data) != 16 {
|
|
||||||
return fmt.Errorf("invalid UUID (got %d bytes)", len(data))
|
|
||||||
}
|
|
||||||
copy(uuid[:], data)
|
|
||||||
return nil
|
|
||||||
}
|
|
90
vendor/github.com/google/uuid/node.go
generated
vendored
90
vendor/github.com/google/uuid/node.go
generated
vendored
@ -1,90 +0,0 @@
|
|||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
nodeMu sync.Mutex
|
|
||||||
ifname string // name of interface being used
|
|
||||||
nodeID [6]byte // hardware for version 1 UUIDs
|
|
||||||
zeroID [6]byte // nodeID with only 0's
|
|
||||||
)
|
|
||||||
|
|
||||||
// NodeInterface returns the name of the interface from which the NodeID was
|
|
||||||
// derived. The interface "user" is returned if the NodeID was set by
|
|
||||||
// SetNodeID.
|
|
||||||
func NodeInterface() string {
|
|
||||||
defer nodeMu.Unlock()
|
|
||||||
nodeMu.Lock()
|
|
||||||
return ifname
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs.
|
|
||||||
// If name is "" then the first usable interface found will be used or a random
|
|
||||||
// Node ID will be generated. If a named interface cannot be found then false
|
|
||||||
// is returned.
|
|
||||||
//
|
|
||||||
// SetNodeInterface never fails when name is "".
|
|
||||||
func SetNodeInterface(name string) bool {
|
|
||||||
defer nodeMu.Unlock()
|
|
||||||
nodeMu.Lock()
|
|
||||||
return setNodeInterface(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setNodeInterface(name string) bool {
|
|
||||||
iname, addr := getHardwareInterface(name) // null implementation for js
|
|
||||||
if iname != "" && addr != nil {
|
|
||||||
ifname = iname
|
|
||||||
copy(nodeID[:], addr)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// We found no interfaces with a valid hardware address. If name
|
|
||||||
// does not specify a specific interface generate a random Node ID
|
|
||||||
// (section 4.1.6)
|
|
||||||
if name == "" {
|
|
||||||
ifname = "random"
|
|
||||||
randomBits(nodeID[:])
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// NodeID returns a slice of a copy of the current Node ID, setting the Node ID
|
|
||||||
// if not already set.
|
|
||||||
func NodeID() []byte {
|
|
||||||
defer nodeMu.Unlock()
|
|
||||||
nodeMu.Lock()
|
|
||||||
if nodeID == zeroID {
|
|
||||||
setNodeInterface("")
|
|
||||||
}
|
|
||||||
nid := nodeID
|
|
||||||
return nid[:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes
|
|
||||||
// of id are used. If id is less than 6 bytes then false is returned and the
|
|
||||||
// Node ID is not set.
|
|
||||||
func SetNodeID(id []byte) bool {
|
|
||||||
if len(id) < 6 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
defer nodeMu.Unlock()
|
|
||||||
nodeMu.Lock()
|
|
||||||
copy(nodeID[:], id)
|
|
||||||
ifname = "user"
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is
|
|
||||||
// not valid. The NodeID is only well defined for version 1 and 2 UUIDs.
|
|
||||||
func (uuid UUID) NodeID() []byte {
|
|
||||||
var node [6]byte
|
|
||||||
copy(node[:], uuid[10:])
|
|
||||||
return node[:]
|
|
||||||
}
|
|
12
vendor/github.com/google/uuid/node_js.go
generated
vendored
12
vendor/github.com/google/uuid/node_js.go
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
// Copyright 2017 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build js
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
// getHardwareInterface returns nil values for the JS version of the code.
|
|
||||||
// This remvoves the "net" dependency, because it is not used in the browser.
|
|
||||||
// Using the "net" library inflates the size of the transpiled JS code by 673k bytes.
|
|
||||||
func getHardwareInterface(name string) (string, []byte) { return "", nil }
|
|
33
vendor/github.com/google/uuid/node_net.go
generated
vendored
33
vendor/github.com/google/uuid/node_net.go
generated
vendored
@ -1,33 +0,0 @@
|
|||||||
// Copyright 2017 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build !js
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
var interfaces []net.Interface // cached list of interfaces
|
|
||||||
|
|
||||||
// getHardwareInterface returns the name and hardware address of interface name.
|
|
||||||
// If name is "" then the name and hardware address of one of the system's
|
|
||||||
// interfaces is returned. If no interfaces are found (name does not exist or
|
|
||||||
// there are no interfaces) then "", nil is returned.
|
|
||||||
//
|
|
||||||
// Only addresses of at least 6 bytes are returned.
|
|
||||||
func getHardwareInterface(name string) (string, []byte) {
|
|
||||||
if interfaces == nil {
|
|
||||||
var err error
|
|
||||||
interfaces, err = net.Interfaces()
|
|
||||||
if err != nil {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, ifs := range interfaces {
|
|
||||||
if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) {
|
|
||||||
return ifs.Name, ifs.HardwareAddr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", nil
|
|
||||||
}
|
|
59
vendor/github.com/google/uuid/sql.go
generated
vendored
59
vendor/github.com/google/uuid/sql.go
generated
vendored
@ -1,59 +0,0 @@
|
|||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql/driver"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Scan implements sql.Scanner so UUIDs can be read from databases transparently
|
|
||||||
// Currently, database types that map to string and []byte are supported. Please
|
|
||||||
// consult database-specific driver documentation for matching types.
|
|
||||||
func (uuid *UUID) Scan(src interface{}) error {
|
|
||||||
switch src := src.(type) {
|
|
||||||
case nil:
|
|
||||||
return nil
|
|
||||||
|
|
||||||
case string:
|
|
||||||
// if an empty UUID comes from a table, we return a null UUID
|
|
||||||
if src == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// see Parse for required string format
|
|
||||||
u, err := Parse(src)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Scan: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
*uuid = u
|
|
||||||
|
|
||||||
case []byte:
|
|
||||||
// if an empty UUID comes from a table, we return a null UUID
|
|
||||||
if len(src) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// assumes a simple slice of bytes if 16 bytes
|
|
||||||
// otherwise attempts to parse
|
|
||||||
if len(src) != 16 {
|
|
||||||
return uuid.Scan(string(src))
|
|
||||||
}
|
|
||||||
copy((*uuid)[:], src)
|
|
||||||
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Scan: unable to scan type %T into UUID", src)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value implements sql.Valuer so that UUIDs can be written to databases
|
|
||||||
// transparently. Currently, UUIDs map to strings. Please consult
|
|
||||||
// database-specific driver documentation for matching types.
|
|
||||||
func (uuid UUID) Value() (driver.Value, error) {
|
|
||||||
return uuid.String(), nil
|
|
||||||
}
|
|
123
vendor/github.com/google/uuid/time.go
generated
vendored
123
vendor/github.com/google/uuid/time.go
generated
vendored
@ -1,123 +0,0 @@
|
|||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Time represents a time as the number of 100's of nanoseconds since 15 Oct
|
|
||||||
// 1582.
|
|
||||||
type Time int64
|
|
||||||
|
|
||||||
const (
|
|
||||||
lillian = 2299160 // Julian day of 15 Oct 1582
|
|
||||||
unix = 2440587 // Julian day of 1 Jan 1970
|
|
||||||
epoch = unix - lillian // Days between epochs
|
|
||||||
g1582 = epoch * 86400 // seconds between epochs
|
|
||||||
g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
timeMu sync.Mutex
|
|
||||||
lasttime uint64 // last time we returned
|
|
||||||
clockSeq uint16 // clock sequence for this run
|
|
||||||
|
|
||||||
timeNow = time.Now // for testing
|
|
||||||
)
|
|
||||||
|
|
||||||
// UnixTime converts t the number of seconds and nanoseconds using the Unix
|
|
||||||
// epoch of 1 Jan 1970.
|
|
||||||
func (t Time) UnixTime() (sec, nsec int64) {
|
|
||||||
sec = int64(t - g1582ns100)
|
|
||||||
nsec = (sec % 10000000) * 100
|
|
||||||
sec /= 10000000
|
|
||||||
return sec, nsec
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and
|
|
||||||
// clock sequence as well as adjusting the clock sequence as needed. An error
|
|
||||||
// is returned if the current time cannot be determined.
|
|
||||||
func GetTime() (Time, uint16, error) {
|
|
||||||
defer timeMu.Unlock()
|
|
||||||
timeMu.Lock()
|
|
||||||
return getTime()
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTime() (Time, uint16, error) {
|
|
||||||
t := timeNow()
|
|
||||||
|
|
||||||
// If we don't have a clock sequence already, set one.
|
|
||||||
if clockSeq == 0 {
|
|
||||||
setClockSequence(-1)
|
|
||||||
}
|
|
||||||
now := uint64(t.UnixNano()/100) + g1582ns100
|
|
||||||
|
|
||||||
// If time has gone backwards with this clock sequence then we
|
|
||||||
// increment the clock sequence
|
|
||||||
if now <= lasttime {
|
|
||||||
clockSeq = ((clockSeq + 1) & 0x3fff) | 0x8000
|
|
||||||
}
|
|
||||||
lasttime = now
|
|
||||||
return Time(now), clockSeq, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClockSequence returns the current clock sequence, generating one if not
|
|
||||||
// already set. The clock sequence is only used for Version 1 UUIDs.
|
|
||||||
//
|
|
||||||
// The uuid package does not use global static storage for the clock sequence or
|
|
||||||
// the last time a UUID was generated. Unless SetClockSequence is used, a new
|
|
||||||
// random clock sequence is generated the first time a clock sequence is
|
|
||||||
// requested by ClockSequence, GetTime, or NewUUID. (section 4.2.1.1)
|
|
||||||
func ClockSequence() int {
|
|
||||||
defer timeMu.Unlock()
|
|
||||||
timeMu.Lock()
|
|
||||||
return clockSequence()
|
|
||||||
}
|
|
||||||
|
|
||||||
func clockSequence() int {
|
|
||||||
if clockSeq == 0 {
|
|
||||||
setClockSequence(-1)
|
|
||||||
}
|
|
||||||
return int(clockSeq & 0x3fff)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetClockSequence sets the clock sequence to the lower 14 bits of seq. Setting to
|
|
||||||
// -1 causes a new sequence to be generated.
|
|
||||||
func SetClockSequence(seq int) {
|
|
||||||
defer timeMu.Unlock()
|
|
||||||
timeMu.Lock()
|
|
||||||
setClockSequence(seq)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setClockSequence(seq int) {
|
|
||||||
if seq == -1 {
|
|
||||||
var b [2]byte
|
|
||||||
randomBits(b[:]) // clock sequence
|
|
||||||
seq = int(b[0])<<8 | int(b[1])
|
|
||||||
}
|
|
||||||
oldSeq := clockSeq
|
|
||||||
clockSeq = uint16(seq&0x3fff) | 0x8000 // Set our variant
|
|
||||||
if oldSeq != clockSeq {
|
|
||||||
lasttime = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
|
|
||||||
// uuid. The time is only defined for version 1 and 2 UUIDs.
|
|
||||||
func (uuid UUID) Time() Time {
|
|
||||||
time := int64(binary.BigEndian.Uint32(uuid[0:4]))
|
|
||||||
time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
|
|
||||||
time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
|
|
||||||
return Time(time)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClockSequence returns the clock sequence encoded in uuid.
|
|
||||||
// The clock sequence is only well defined for version 1 and 2 UUIDs.
|
|
||||||
func (uuid UUID) ClockSequence() int {
|
|
||||||
return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff
|
|
||||||
}
|
|
43
vendor/github.com/google/uuid/util.go
generated
vendored
43
vendor/github.com/google/uuid/util.go
generated
vendored
@ -1,43 +0,0 @@
|
|||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// randomBits completely fills slice b with random data.
|
|
||||||
func randomBits(b []byte) {
|
|
||||||
if _, err := io.ReadFull(rander, b); err != nil {
|
|
||||||
panic(err.Error()) // rand should never fail
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// xvalues returns the value of a byte as a hexadecimal digit or 255.
|
|
||||||
var xvalues = [256]byte{
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
}
|
|
||||||
|
|
||||||
// xtob converts hex characters x1 and x2 into a byte.
|
|
||||||
func xtob(x1, x2 byte) (byte, bool) {
|
|
||||||
b1 := xvalues[x1]
|
|
||||||
b2 := xvalues[x2]
|
|
||||||
return (b1 << 4) | b2, b1 != 255 && b2 != 255
|
|
||||||
}
|
|
245
vendor/github.com/google/uuid/uuid.go
generated
vendored
245
vendor/github.com/google/uuid/uuid.go
generated
vendored
@ -1,245 +0,0 @@
|
|||||||
// Copyright 2018 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
|
|
||||||
// 4122.
|
|
||||||
type UUID [16]byte
|
|
||||||
|
|
||||||
// A Version represents a UUID's version.
|
|
||||||
type Version byte
|
|
||||||
|
|
||||||
// A Variant represents a UUID's variant.
|
|
||||||
type Variant byte
|
|
||||||
|
|
||||||
// Constants returned by Variant.
|
|
||||||
const (
|
|
||||||
Invalid = Variant(iota) // Invalid UUID
|
|
||||||
RFC4122 // The variant specified in RFC4122
|
|
||||||
Reserved // Reserved, NCS backward compatibility.
|
|
||||||
Microsoft // Reserved, Microsoft Corporation backward compatibility.
|
|
||||||
Future // Reserved for future definition.
|
|
||||||
)
|
|
||||||
|
|
||||||
var rander = rand.Reader // random function
|
|
||||||
|
|
||||||
// Parse decodes s into a UUID or returns an error. Both the standard UUID
|
|
||||||
// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
|
|
||||||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the
|
|
||||||
// Microsoft encoding {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} and the raw hex
|
|
||||||
// encoding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
|
|
||||||
func Parse(s string) (UUID, error) {
|
|
||||||
var uuid UUID
|
|
||||||
switch len(s) {
|
|
||||||
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
case 36:
|
|
||||||
|
|
||||||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
case 36 + 9:
|
|
||||||
if strings.ToLower(s[:9]) != "urn:uuid:" {
|
|
||||||
return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9])
|
|
||||||
}
|
|
||||||
s = s[9:]
|
|
||||||
|
|
||||||
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
|
||||||
case 36 + 2:
|
|
||||||
s = s[1:]
|
|
||||||
|
|
||||||
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
case 32:
|
|
||||||
var ok bool
|
|
||||||
for i := range uuid {
|
|
||||||
uuid[i], ok = xtob(s[i*2], s[i*2+1])
|
|
||||||
if !ok {
|
|
||||||
return uuid, errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return uuid, nil
|
|
||||||
default:
|
|
||||||
return uuid, fmt.Errorf("invalid UUID length: %d", len(s))
|
|
||||||
}
|
|
||||||
// s is now at least 36 bytes long
|
|
||||||
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
|
|
||||||
return uuid, errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
for i, x := range [16]int{
|
|
||||||
0, 2, 4, 6,
|
|
||||||
9, 11,
|
|
||||||
14, 16,
|
|
||||||
19, 21,
|
|
||||||
24, 26, 28, 30, 32, 34} {
|
|
||||||
v, ok := xtob(s[x], s[x+1])
|
|
||||||
if !ok {
|
|
||||||
return uuid, errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
uuid[i] = v
|
|
||||||
}
|
|
||||||
return uuid, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseBytes is like Parse, except it parses a byte slice instead of a string.
|
|
||||||
func ParseBytes(b []byte) (UUID, error) {
|
|
||||||
var uuid UUID
|
|
||||||
switch len(b) {
|
|
||||||
case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) {
|
|
||||||
return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9])
|
|
||||||
}
|
|
||||||
b = b[9:]
|
|
||||||
case 36 + 2: // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
|
||||||
b = b[1:]
|
|
||||||
case 32: // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
var ok bool
|
|
||||||
for i := 0; i < 32; i += 2 {
|
|
||||||
uuid[i/2], ok = xtob(b[i], b[i+1])
|
|
||||||
if !ok {
|
|
||||||
return uuid, errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return uuid, nil
|
|
||||||
default:
|
|
||||||
return uuid, fmt.Errorf("invalid UUID length: %d", len(b))
|
|
||||||
}
|
|
||||||
// s is now at least 36 bytes long
|
|
||||||
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' {
|
|
||||||
return uuid, errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
for i, x := range [16]int{
|
|
||||||
0, 2, 4, 6,
|
|
||||||
9, 11,
|
|
||||||
14, 16,
|
|
||||||
19, 21,
|
|
||||||
24, 26, 28, 30, 32, 34} {
|
|
||||||
v, ok := xtob(b[x], b[x+1])
|
|
||||||
if !ok {
|
|
||||||
return uuid, errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
uuid[i] = v
|
|
||||||
}
|
|
||||||
return uuid, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustParse is like Parse but panics if the string cannot be parsed.
|
|
||||||
// It simplifies safe initialization of global variables holding compiled UUIDs.
|
|
||||||
func MustParse(s string) UUID {
|
|
||||||
uuid, err := Parse(s)
|
|
||||||
if err != nil {
|
|
||||||
panic(`uuid: Parse(` + s + `): ` + err.Error())
|
|
||||||
}
|
|
||||||
return uuid
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromBytes creates a new UUID from a byte slice. Returns an error if the slice
|
|
||||||
// does not have a length of 16. The bytes are copied from the slice.
|
|
||||||
func FromBytes(b []byte) (uuid UUID, err error) {
|
|
||||||
err = uuid.UnmarshalBinary(b)
|
|
||||||
return uuid, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must returns uuid if err is nil and panics otherwise.
|
|
||||||
func Must(uuid UUID, err error) UUID {
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return uuid
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
// , or "" if uuid is invalid.
|
|
||||||
func (uuid UUID) String() string {
|
|
||||||
var buf [36]byte
|
|
||||||
encodeHex(buf[:], uuid)
|
|
||||||
return string(buf[:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// URN returns the RFC 2141 URN form of uuid,
|
|
||||||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid.
|
|
||||||
func (uuid UUID) URN() string {
|
|
||||||
var buf [36 + 9]byte
|
|
||||||
copy(buf[:], "urn:uuid:")
|
|
||||||
encodeHex(buf[9:], uuid)
|
|
||||||
return string(buf[:])
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeHex(dst []byte, uuid UUID) {
|
|
||||||
hex.Encode(dst, uuid[:4])
|
|
||||||
dst[8] = '-'
|
|
||||||
hex.Encode(dst[9:13], uuid[4:6])
|
|
||||||
dst[13] = '-'
|
|
||||||
hex.Encode(dst[14:18], uuid[6:8])
|
|
||||||
dst[18] = '-'
|
|
||||||
hex.Encode(dst[19:23], uuid[8:10])
|
|
||||||
dst[23] = '-'
|
|
||||||
hex.Encode(dst[24:], uuid[10:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variant returns the variant encoded in uuid.
|
|
||||||
func (uuid UUID) Variant() Variant {
|
|
||||||
switch {
|
|
||||||
case (uuid[8] & 0xc0) == 0x80:
|
|
||||||
return RFC4122
|
|
||||||
case (uuid[8] & 0xe0) == 0xc0:
|
|
||||||
return Microsoft
|
|
||||||
case (uuid[8] & 0xe0) == 0xe0:
|
|
||||||
return Future
|
|
||||||
default:
|
|
||||||
return Reserved
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Version returns the version of uuid.
|
|
||||||
func (uuid UUID) Version() Version {
|
|
||||||
return Version(uuid[6] >> 4)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v Version) String() string {
|
|
||||||
if v > 15 {
|
|
||||||
return fmt.Sprintf("BAD_VERSION_%d", v)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("VERSION_%d", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v Variant) String() string {
|
|
||||||
switch v {
|
|
||||||
case RFC4122:
|
|
||||||
return "RFC4122"
|
|
||||||
case Reserved:
|
|
||||||
return "Reserved"
|
|
||||||
case Microsoft:
|
|
||||||
return "Microsoft"
|
|
||||||
case Future:
|
|
||||||
return "Future"
|
|
||||||
case Invalid:
|
|
||||||
return "Invalid"
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("BadVariant%d", int(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetRand sets the random number generator to r, which implements io.Reader.
|
|
||||||
// If r.Read returns an error when the package requests random data then
|
|
||||||
// a panic will be issued.
|
|
||||||
//
|
|
||||||
// Calling SetRand with nil sets the random number generator to the default
|
|
||||||
// generator.
|
|
||||||
func SetRand(r io.Reader) {
|
|
||||||
if r == nil {
|
|
||||||
rander = rand.Reader
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rander = r
|
|
||||||
}
|
|
44
vendor/github.com/google/uuid/version1.go
generated
vendored
44
vendor/github.com/google/uuid/version1.go
generated
vendored
@ -1,44 +0,0 @@
|
|||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewUUID returns a Version 1 UUID based on the current NodeID and clock
|
|
||||||
// sequence, and the current time. If the NodeID has not been set by SetNodeID
|
|
||||||
// or SetNodeInterface then it will be set automatically. If the NodeID cannot
|
|
||||||
// be set NewUUID returns nil. If clock sequence has not been set by
|
|
||||||
// SetClockSequence then it will be set automatically. If GetTime fails to
|
|
||||||
// return the current NewUUID returns nil and an error.
|
|
||||||
//
|
|
||||||
// In most cases, New should be used.
|
|
||||||
func NewUUID() (UUID, error) {
|
|
||||||
nodeMu.Lock()
|
|
||||||
if nodeID == zeroID {
|
|
||||||
setNodeInterface("")
|
|
||||||
}
|
|
||||||
nodeMu.Unlock()
|
|
||||||
|
|
||||||
var uuid UUID
|
|
||||||
now, seq, err := GetTime()
|
|
||||||
if err != nil {
|
|
||||||
return uuid, err
|
|
||||||
}
|
|
||||||
|
|
||||||
timeLow := uint32(now & 0xffffffff)
|
|
||||||
timeMid := uint16((now >> 32) & 0xffff)
|
|
||||||
timeHi := uint16((now >> 48) & 0x0fff)
|
|
||||||
timeHi |= 0x1000 // Version 1
|
|
||||||
|
|
||||||
binary.BigEndian.PutUint32(uuid[0:], timeLow)
|
|
||||||
binary.BigEndian.PutUint16(uuid[4:], timeMid)
|
|
||||||
binary.BigEndian.PutUint16(uuid[6:], timeHi)
|
|
||||||
binary.BigEndian.PutUint16(uuid[8:], seq)
|
|
||||||
copy(uuid[10:], nodeID[:])
|
|
||||||
|
|
||||||
return uuid, nil
|
|
||||||
}
|
|
38
vendor/github.com/google/uuid/version4.go
generated
vendored
38
vendor/github.com/google/uuid/version4.go
generated
vendored
@ -1,38 +0,0 @@
|
|||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import "io"
|
|
||||||
|
|
||||||
// New creates a new random UUID or panics. New is equivalent to
|
|
||||||
// the expression
|
|
||||||
//
|
|
||||||
// uuid.Must(uuid.NewRandom())
|
|
||||||
func New() UUID {
|
|
||||||
return Must(NewRandom())
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRandom returns a Random (Version 4) UUID.
|
|
||||||
//
|
|
||||||
// The strength of the UUIDs is based on the strength of the crypto/rand
|
|
||||||
// package.
|
|
||||||
//
|
|
||||||
// A note about uniqueness derived from the UUID Wikipedia entry:
|
|
||||||
//
|
|
||||||
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
|
|
||||||
// hit by a meteorite is estimated to be one chance in 17 billion, that
|
|
||||||
// means the probability is about 0.00000000006 (6 × 10−11),
|
|
||||||
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
|
|
||||||
// year and having one duplicate.
|
|
||||||
func NewRandom() (UUID, error) {
|
|
||||||
var uuid UUID
|
|
||||||
_, err := io.ReadFull(rander, uuid[:])
|
|
||||||
if err != nil {
|
|
||||||
return Nil, err
|
|
||||||
}
|
|
||||||
uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
|
|
||||||
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
|
|
||||||
return uuid, nil
|
|
||||||
}
|
|
1
vendor/github.com/vishvananda/netlink/.gitignore
generated
vendored
Normal file
1
vendor/github.com/vishvananda/netlink/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.idea/
|
6
vendor/github.com/vishvananda/netlink/.travis.yml
generated
vendored
6
vendor/github.com/vishvananda/netlink/.travis.yml
generated
vendored
@ -1,4 +1,8 @@
|
|||||||
language: go
|
language: go
|
||||||
|
go:
|
||||||
|
- "1.10.x"
|
||||||
|
- "1.11.x"
|
||||||
|
- "1.12.x"
|
||||||
before_script:
|
before_script:
|
||||||
# make sure we keep path in tact when we sudo
|
# make sure we keep path in tact when we sudo
|
||||||
- sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers
|
- sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers
|
||||||
@ -9,5 +13,7 @@ before_script:
|
|||||||
- sudo modprobe nf_conntrack_netlink
|
- sudo modprobe nf_conntrack_netlink
|
||||||
- sudo modprobe nf_conntrack_ipv4
|
- sudo modprobe nf_conntrack_ipv4
|
||||||
- sudo modprobe nf_conntrack_ipv6
|
- sudo modprobe nf_conntrack_ipv6
|
||||||
|
- sudo modprobe sch_hfsc
|
||||||
install:
|
install:
|
||||||
- go get github.com/vishvananda/netns
|
- go get github.com/vishvananda/netns
|
||||||
|
go_import_path: github.com/vishvananda/netlink
|
||||||
|
105
vendor/github.com/vishvananda/netlink/addr_linux.go
generated
vendored
105
vendor/github.com/vishvananda/netlink/addr_linux.go
generated
vendored
@ -15,39 +15,62 @@ import (
|
|||||||
const IFA_FLAGS = 0x8
|
const IFA_FLAGS = 0x8
|
||||||
|
|
||||||
// AddrAdd will add an IP address to a link device.
|
// AddrAdd will add an IP address to a link device.
|
||||||
|
//
|
||||||
// Equivalent to: `ip addr add $addr dev $link`
|
// 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 {
|
func AddrAdd(link Link, addr *Addr) error {
|
||||||
return pkgHandle.AddrAdd(link, addr)
|
return pkgHandle.AddrAdd(link, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddrAdd will add an IP address to a link device.
|
// AddrAdd will add an IP address to a link device.
|
||||||
|
//
|
||||||
// Equivalent to: `ip addr add $addr dev $link`
|
// 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 {
|
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)
|
req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
|
||||||
return h.addrHandle(link, addr, req)
|
return h.addrHandle(link, addr, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddrReplace will replace (or, if not present, add) an IP address on a link device.
|
// AddrReplace will replace (or, if not present, add) an IP address on a link device.
|
||||||
|
//
|
||||||
// Equivalent to: `ip addr replace $addr dev $link`
|
// 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 {
|
func AddrReplace(link Link, addr *Addr) error {
|
||||||
return pkgHandle.AddrReplace(link, addr)
|
return pkgHandle.AddrReplace(link, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddrReplace will replace (or, if not present, add) an IP address on a link device.
|
// AddrReplace will replace (or, if not present, add) an IP address on a link device.
|
||||||
|
//
|
||||||
// Equivalent to: `ip addr replace $addr dev $link`
|
// 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 {
|
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)
|
req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_REPLACE|unix.NLM_F_ACK)
|
||||||
return h.addrHandle(link, addr, req)
|
return h.addrHandle(link, addr, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddrDel will delete an IP address from a link device.
|
// AddrDel will delete an IP address from a link device.
|
||||||
|
//
|
||||||
// Equivalent to: `ip addr del $addr dev $link`
|
// 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 {
|
func AddrDel(link Link, addr *Addr) error {
|
||||||
return pkgHandle.AddrDel(link, addr)
|
return pkgHandle.AddrDel(link, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddrDel will delete an IP address from a link device.
|
// AddrDel will delete an IP address from a link device.
|
||||||
// Equivalent to: `ip addr del $addr dev $link`
|
// 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 {
|
func (h *Handle) AddrDel(link Link, addr *Addr) error {
|
||||||
req := h.newNetlinkRequest(unix.RTM_DELADDR, unix.NLM_F_ACK)
|
req := h.newNetlinkRequest(unix.RTM_DELADDR, unix.NLM_F_ACK)
|
||||||
return h.addrHandle(link, addr, req)
|
return h.addrHandle(link, addr, req)
|
||||||
@ -65,7 +88,11 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
|
|||||||
msg := nl.NewIfAddrmsg(family)
|
msg := nl.NewIfAddrmsg(family)
|
||||||
msg.Index = uint32(base.Index)
|
msg.Index = uint32(base.Index)
|
||||||
msg.Scope = uint8(addr.Scope)
|
msg.Scope = uint8(addr.Scope)
|
||||||
prefixlen, masklen := addr.Mask.Size()
|
mask := addr.Mask
|
||||||
|
if addr.Peer != nil {
|
||||||
|
mask = addr.Peer.Mask
|
||||||
|
}
|
||||||
|
prefixlen, masklen := mask.Size()
|
||||||
msg.Prefixlen = uint8(prefixlen)
|
msg.Prefixlen = uint8(prefixlen)
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
|
|
||||||
@ -104,14 +131,20 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
if family == FAMILY_V4 {
|
if family == FAMILY_V4 {
|
||||||
if addr.Broadcast == nil {
|
// 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)
|
calcBroadcast := make(net.IP, masklen/8)
|
||||||
for i := range localAddrData {
|
for i := range localAddrData {
|
||||||
calcBroadcast[i] = localAddrData[i] | ^addr.Mask[i]
|
calcBroadcast[i] = localAddrData[i] | ^mask[i]
|
||||||
}
|
}
|
||||||
addr.Broadcast = calcBroadcast
|
addr.Broadcast = calcBroadcast
|
||||||
}
|
}
|
||||||
req.AddData(nl.NewRtAttr(unix.IFA_BROADCAST, addr.Broadcast))
|
|
||||||
|
if addr.Broadcast != nil {
|
||||||
|
req.AddData(nl.NewRtAttr(unix.IFA_BROADCAST, addr.Broadcast))
|
||||||
|
}
|
||||||
|
|
||||||
if addr.Label != "" {
|
if addr.Label != "" {
|
||||||
labelData := nl.NewRtAttr(unix.IFA_LABEL, nl.ZeroTerminated(addr.Label))
|
labelData := nl.NewRtAttr(unix.IFA_LABEL, nl.ZeroTerminated(addr.Label))
|
||||||
@ -206,13 +239,17 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) {
|
|||||||
IP: attr.Value,
|
IP: attr.Value,
|
||||||
Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
|
Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
|
||||||
}
|
}
|
||||||
addr.Peer = dst
|
|
||||||
case unix.IFA_LOCAL:
|
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{
|
local = &net.IPNet{
|
||||||
IP: attr.Value,
|
IP: attr.Value,
|
||||||
Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
|
Mask: net.CIDRMask(n, n),
|
||||||
}
|
}
|
||||||
addr.IPNet = local
|
|
||||||
case unix.IFA_BROADCAST:
|
case unix.IFA_BROADCAST:
|
||||||
addr.Broadcast = attr.Value
|
addr.Broadcast = attr.Value
|
||||||
case unix.IFA_LABEL:
|
case unix.IFA_LABEL:
|
||||||
@ -226,12 +263,24 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IFA_LOCAL should be there but if not, fall back to IFA_ADDRESS
|
// 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 local != nil {
|
||||||
addr.IPNet = local
|
if family == FAMILY_V4 && local.IP.Equal(dst.IP) {
|
||||||
|
addr.IPNet = dst
|
||||||
|
} else {
|
||||||
|
addr.IPNet = local
|
||||||
|
addr.Peer = dst
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
addr.IPNet = dst
|
addr.IPNet = dst
|
||||||
}
|
}
|
||||||
|
|
||||||
addr.Scope = int(msg.Scope)
|
addr.Scope = int(msg.Scope)
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -250,21 +299,22 @@ type AddrUpdate struct {
|
|||||||
// AddrSubscribe takes a chan down which notifications will be sent
|
// AddrSubscribe takes a chan down which notifications will be sent
|
||||||
// when addresses change. Close the 'done' chan to stop subscription.
|
// when addresses change. Close the 'done' chan to stop subscription.
|
||||||
func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error {
|
func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error {
|
||||||
return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false)
|
return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddrSubscribeAt works like AddrSubscribe plus it allows the caller
|
// AddrSubscribeAt works like AddrSubscribe plus it allows the caller
|
||||||
// to choose the network namespace in which to subscribe (ns).
|
// to choose the network namespace in which to subscribe (ns).
|
||||||
func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error {
|
func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error {
|
||||||
return addrSubscribeAt(ns, netns.None(), ch, done, nil, false)
|
return addrSubscribeAt(ns, netns.None(), ch, done, nil, false, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddrSubscribeOptions contains a set of options to use with
|
// AddrSubscribeOptions contains a set of options to use with
|
||||||
// AddrSubscribeWithOptions.
|
// AddrSubscribeWithOptions.
|
||||||
type AddrSubscribeOptions struct {
|
type AddrSubscribeOptions struct {
|
||||||
Namespace *netns.NsHandle
|
Namespace *netns.NsHandle
|
||||||
ErrorCallback func(error)
|
ErrorCallback func(error)
|
||||||
ListExisting bool
|
ListExisting bool
|
||||||
|
ReceiveBufferSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddrSubscribeWithOptions work like AddrSubscribe but enable to
|
// AddrSubscribeWithOptions work like AddrSubscribe but enable to
|
||||||
@ -275,10 +325,10 @@ func AddrSubscribeWithOptions(ch chan<- AddrUpdate, done <-chan struct{}, option
|
|||||||
none := netns.None()
|
none := netns.None()
|
||||||
options.Namespace = &none
|
options.Namespace = &none
|
||||||
}
|
}
|
||||||
return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting)
|
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) error {
|
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)
|
s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_IFADDR, unix.RTNLGRP_IPV6_IFADDR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -289,6 +339,12 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
|
|||||||
s.Close()
|
s.Close()
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
if rcvbuf != 0 {
|
||||||
|
err = pkgHandle.SetSocketReceiveBufferSize(rcvbuf, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
if listExisting {
|
if listExisting {
|
||||||
req := pkgHandle.newNetlinkRequest(unix.RTM_GETADDR,
|
req := pkgHandle.newNetlinkRequest(unix.RTM_GETADDR,
|
||||||
unix.NLM_F_DUMP)
|
unix.NLM_F_DUMP)
|
||||||
@ -301,13 +357,19 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
|
|||||||
go func() {
|
go func() {
|
||||||
defer close(ch)
|
defer close(ch)
|
||||||
for {
|
for {
|
||||||
msgs, err := s.Receive()
|
msgs, from, err := s.Receive()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if cberr != nil {
|
if cberr != nil {
|
||||||
cberr(err)
|
cberr(err)
|
||||||
}
|
}
|
||||||
return
|
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 {
|
for _, m := range msgs {
|
||||||
if m.Header.Type == unix.NLMSG_DONE {
|
if m.Header.Type == unix.NLMSG_DONE {
|
||||||
continue
|
continue
|
||||||
@ -319,16 +381,17 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if cberr != nil {
|
if cberr != nil {
|
||||||
cberr(syscall.Errno(-error))
|
cberr(fmt.Errorf("error message: %v",
|
||||||
|
syscall.Errno(-error)))
|
||||||
}
|
}
|
||||||
return
|
continue
|
||||||
}
|
}
|
||||||
msgType := m.Header.Type
|
msgType := m.Header.Type
|
||||||
if msgType != unix.RTM_NEWADDR && msgType != unix.RTM_DELADDR {
|
if msgType != unix.RTM_NEWADDR && msgType != unix.RTM_DELADDR {
|
||||||
if cberr != nil {
|
if cberr != nil {
|
||||||
cberr(fmt.Errorf("bad message type: %d", msgType))
|
cberr(fmt.Errorf("bad message type: %d", msgType))
|
||||||
}
|
}
|
||||||
return
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
addr, _, ifindex, err := parseAddr(m.Data)
|
addr, _, ifindex, err := parseAddr(m.Data)
|
||||||
@ -336,7 +399,7 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
|
|||||||
if cberr != nil {
|
if cberr != nil {
|
||||||
cberr(fmt.Errorf("could not parse address: %v", err))
|
cberr(fmt.Errorf("could not parse address: %v", err))
|
||||||
}
|
}
|
||||||
return
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
ch <- AddrUpdate{LinkAddress: *addr.IPNet,
|
ch <- AddrUpdate{LinkAddress: *addr.IPNet,
|
||||||
|
9
vendor/github.com/vishvananda/netlink/bridge_linux.go
generated
vendored
9
vendor/github.com/vishvananda/netlink/bridge_linux.go
generated
vendored
@ -96,7 +96,7 @@ func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged
|
|||||||
flags |= nl.BRIDGE_FLAGS_MASTER
|
flags |= nl.BRIDGE_FLAGS_MASTER
|
||||||
}
|
}
|
||||||
if flags > 0 {
|
if flags > 0 {
|
||||||
nl.NewRtAttrChild(br, nl.IFLA_BRIDGE_FLAGS, nl.Uint16Attr(flags))
|
br.AddRtAttr(nl.IFLA_BRIDGE_FLAGS, nl.Uint16Attr(flags))
|
||||||
}
|
}
|
||||||
vlanInfo := &nl.BridgeVlanInfo{Vid: vid}
|
vlanInfo := &nl.BridgeVlanInfo{Vid: vid}
|
||||||
if pvid {
|
if pvid {
|
||||||
@ -105,11 +105,8 @@ func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged
|
|||||||
if untagged {
|
if untagged {
|
||||||
vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_UNTAGGED
|
vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_UNTAGGED
|
||||||
}
|
}
|
||||||
nl.NewRtAttrChild(br, nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
|
br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
|
||||||
req.AddData(br)
|
req.AddData(br)
|
||||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
141
vendor/github.com/vishvananda/netlink/class.go
generated
vendored
141
vendor/github.com/vishvananda/netlink/class.go
generated
vendored
@ -4,25 +4,76 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Class interfaces for all classes
|
||||||
type Class interface {
|
type Class interface {
|
||||||
Attrs() *ClassAttrs
|
Attrs() *ClassAttrs
|
||||||
Type() string
|
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,
|
// 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
|
// has a handle and a parent. The root filter of a device should have a
|
||||||
// parent == HANDLE_ROOT.
|
// parent == HANDLE_ROOT.
|
||||||
type ClassAttrs struct {
|
type ClassAttrs struct {
|
||||||
LinkIndex int
|
LinkIndex int
|
||||||
Handle uint32
|
Handle uint32
|
||||||
Parent uint32
|
Parent uint32
|
||||||
Leaf uint32
|
Leaf uint32
|
||||||
|
Statistics *ClassStatistics
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q ClassAttrs) String() string {
|
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)
|
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 {
|
type HtbClassAttrs struct {
|
||||||
// TODO handle all attributes
|
// TODO handle all attributes
|
||||||
Rate uint64
|
Rate uint64
|
||||||
@ -54,10 +105,12 @@ func (q HtbClass) String() string {
|
|||||||
return fmt.Sprintf("{Rate: %d, Ceil: %d, Buffer: %d, Cbuffer: %d}", q.Rate, q.Ceil, q.Buffer, q.Cbuffer)
|
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 {
|
func (q *HtbClass) Attrs() *ClassAttrs {
|
||||||
return &q.ClassAttrs
|
return &q.ClassAttrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Type return the class type
|
||||||
func (q *HtbClass) Type() string {
|
func (q *HtbClass) Type() string {
|
||||||
return "htb"
|
return "htb"
|
||||||
}
|
}
|
||||||
@ -69,10 +122,90 @@ type GenericClass struct {
|
|||||||
ClassType string
|
ClassType string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attrs return the class attributes
|
||||||
func (class *GenericClass) Attrs() *ClassAttrs {
|
func (class *GenericClass) Attrs() *ClassAttrs {
|
||||||
return &class.ClassAttrs
|
return &class.ClassAttrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Type return the class type
|
||||||
func (class *GenericClass) Type() string {
|
func (class *GenericClass) Type() string {
|
||||||
return class.ClassType
|
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"
|
||||||
|
}
|
||||||
|
145
vendor/github.com/vishvananda/netlink/class_linux.go
generated
vendored
145
vendor/github.com/vishvananda/netlink/class_linux.go
generated
vendored
@ -1,14 +1,34 @@
|
|||||||
package netlink
|
package netlink
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NOTE: function is in here because it uses other linux functions
|
// 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 {
|
func NewHtbClass(attrs ClassAttrs, cattrs HtbClassAttrs) *HtbClass {
|
||||||
mtu := 1600
|
mtu := 1600
|
||||||
rate := cattrs.Rate / 8
|
rate := cattrs.Rate / 8
|
||||||
@ -126,7 +146,9 @@ func classPayload(req *nl.NetlinkRequest, class Class) error {
|
|||||||
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(class.Type())))
|
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(class.Type())))
|
||||||
|
|
||||||
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
|
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
|
||||||
if htb, ok := class.(*HtbClass); ok {
|
switch class.Type() {
|
||||||
|
case "htb":
|
||||||
|
htb := class.(*HtbClass)
|
||||||
opt := nl.TcHtbCopt{}
|
opt := nl.TcHtbCopt{}
|
||||||
opt.Buffer = htb.Buffer
|
opt.Buffer = htb.Buffer
|
||||||
opt.Cbuffer = htb.Cbuffer
|
opt.Cbuffer = htb.Cbuffer
|
||||||
@ -151,9 +173,18 @@ func classPayload(req *nl.NetlinkRequest, class Class) error {
|
|||||||
return errors.New("HTB: failed to calculate ceil rate table")
|
return errors.New("HTB: failed to calculate ceil rate table")
|
||||||
}
|
}
|
||||||
opt.Ceil = tcceil
|
opt.Ceil = tcceil
|
||||||
nl.NewRtAttrChild(options, nl.TCA_HTB_PARMS, opt.Serialize())
|
options.AddRtAttr(nl.TCA_HTB_PARMS, opt.Serialize())
|
||||||
nl.NewRtAttrChild(options, nl.TCA_HTB_RTAB, SerializeRtab(rtab))
|
options.AddRtAttr(nl.TCA_HTB_RTAB, SerializeRtab(rtab))
|
||||||
nl.NewRtAttrChild(options, nl.TCA_HTB_CTAB, SerializeRtab(ctab))
|
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)
|
req.AddData(options)
|
||||||
return nil
|
return nil
|
||||||
@ -197,9 +228,10 @@ func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
base := ClassAttrs{
|
base := ClassAttrs{
|
||||||
LinkIndex: int(msg.Ifindex),
|
LinkIndex: int(msg.Ifindex),
|
||||||
Handle: msg.Handle,
|
Handle: msg.Handle,
|
||||||
Parent: msg.Parent,
|
Parent: msg.Parent,
|
||||||
|
Statistics: nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
var class Class
|
var class Class
|
||||||
@ -211,6 +243,8 @@ func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) {
|
|||||||
switch classType {
|
switch classType {
|
||||||
case "htb":
|
case "htb":
|
||||||
class = &HtbClass{}
|
class = &HtbClass{}
|
||||||
|
case "hfsc":
|
||||||
|
class = &HfscClass{}
|
||||||
default:
|
default:
|
||||||
class = &GenericClass{ClassType: classType}
|
class = &GenericClass{ClassType: classType}
|
||||||
}
|
}
|
||||||
@ -225,6 +259,26 @@ func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -253,3 +307,78 @@ func parseHtbClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, erro
|
|||||||
}
|
}
|
||||||
return detailed, nil
|
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
|
||||||
|
}
|
||||||
|
121
vendor/github.com/vishvananda/netlink/conntrack_linux.go
generated
vendored
121
vendor/github.com/vishvananda/netlink/conntrack_linux.go
generated
vendored
@ -22,11 +22,7 @@ const (
|
|||||||
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink.h -> #define NFNL_SUBSYS_CTNETLINK_EXP 2
|
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink.h -> #define NFNL_SUBSYS_CTNETLINK_EXP 2
|
||||||
ConntrackExpectTable = 2
|
ConntrackExpectTable = 2
|
||||||
)
|
)
|
||||||
const (
|
|
||||||
// For Parsing Mark
|
|
||||||
TCP_PROTO = 6
|
|
||||||
UDP_PROTO = 17
|
|
||||||
)
|
|
||||||
const (
|
const (
|
||||||
// backward compatibility with golang 1.6 which does not have io.SeekCurrent
|
// backward compatibility with golang 1.6 which does not have io.SeekCurrent
|
||||||
seekCurrent = 1
|
seekCurrent = 1
|
||||||
@ -135,11 +131,13 @@ func (h *Handle) dumpConntrackTable(table ConntrackTableType, family InetFamily)
|
|||||||
// http://git.netfilter.org/libnetfilter_conntrack/tree/include/internal/object.h
|
// 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
|
// For the time being, the structure below allows to parse and extract the base information of a flow
|
||||||
type ipTuple struct {
|
type ipTuple struct {
|
||||||
SrcIP net.IP
|
Bytes uint64
|
||||||
DstIP net.IP
|
DstIP net.IP
|
||||||
Protocol uint8
|
|
||||||
SrcPort uint16
|
|
||||||
DstPort uint16
|
DstPort uint16
|
||||||
|
Packets uint64
|
||||||
|
Protocol uint8
|
||||||
|
SrcIP net.IP
|
||||||
|
SrcPort uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConntrackFlow struct {
|
type ConntrackFlow struct {
|
||||||
@ -151,11 +149,12 @@ type ConntrackFlow struct {
|
|||||||
|
|
||||||
func (s *ConntrackFlow) String() string {
|
func (s *ConntrackFlow) String() string {
|
||||||
// conntrack cmd output:
|
// conntrack cmd output:
|
||||||
// udp 17 src=127.0.0.1 dst=127.0.0.1 sport=4001 dport=1234 [UNREPLIED] src=127.0.0.1 dst=127.0.0.1 sport=1234 dport=4001 mark=0
|
// udp 17 src=127.0.0.1 dst=127.0.0.1 sport=4001 dport=1234 packets=5 bytes=532 [UNREPLIED] src=127.0.0.1 dst=127.0.0.1 sport=1234 dport=4001 packets=10 bytes=1078 mark=0
|
||||||
return fmt.Sprintf("%s\t%d src=%s dst=%s sport=%d dport=%d\tsrc=%s dst=%s sport=%d dport=%d mark=%d",
|
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,
|
nl.L4ProtoMap[s.Forward.Protocol], s.Forward.Protocol,
|
||||||
s.Forward.SrcIP.String(), s.Forward.DstIP.String(), s.Forward.SrcPort, s.Forward.DstPort,
|
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.Mark)
|
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
|
// This method parse the ip tuple structure
|
||||||
@ -220,9 +219,35 @@ func parseBERaw16(r *bytes.Reader, v *uint16) {
|
|||||||
binary.Read(r, binary.BigEndian, v)
|
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 {
|
func parseRawData(data []byte) *ConntrackFlow {
|
||||||
s := &ConntrackFlow{}
|
s := &ConntrackFlow{}
|
||||||
var proto uint8
|
|
||||||
// First there is the Nfgenmsg header
|
// First there is the Nfgenmsg header
|
||||||
// consume only the family field
|
// consume only the family field
|
||||||
reader := bytes.NewReader(data)
|
reader := bytes.NewReader(data)
|
||||||
@ -238,36 +263,31 @@ func parseRawData(data []byte) *ConntrackFlow {
|
|||||||
// <len, NLA_F_NESTED|CTA_TUPLE_IP> 4 bytes
|
// <len, NLA_F_NESTED|CTA_TUPLE_IP> 4 bytes
|
||||||
// flow information of the reverse flow
|
// flow information of the reverse flow
|
||||||
for reader.Len() > 0 {
|
for reader.Len() > 0 {
|
||||||
nested, t, l := parseNfAttrTL(reader)
|
if nested, t, l := parseNfAttrTL(reader); nested {
|
||||||
if nested && t == nl.CTA_TUPLE_ORIG {
|
switch t {
|
||||||
if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
|
case nl.CTA_TUPLE_ORIG:
|
||||||
proto = parseIpTuple(reader, &s.Forward)
|
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 if nested && t == nl.CTA_TUPLE_REPLY {
|
} else {
|
||||||
if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
|
switch t {
|
||||||
parseIpTuple(reader, &s.Reverse)
|
case nl.CTA_MARK:
|
||||||
|
s.Mark = parseConnectionMark(reader)
|
||||||
// Got all the useful information stop parsing
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
// Header not recognized skip it
|
|
||||||
reader.Seek(int64(l), seekCurrent)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if proto == TCP_PROTO {
|
|
||||||
reader.Seek(64, seekCurrent)
|
|
||||||
_, t, _, v := parseNfAttrTLV(reader)
|
|
||||||
if t == nl.CTA_MARK {
|
|
||||||
s.Mark = uint32(v[3])
|
|
||||||
}
|
|
||||||
} else if proto == UDP_PROTO {
|
|
||||||
reader.Seek(16, seekCurrent)
|
|
||||||
_, t, _, v := parseNfAttrTLV(reader)
|
|
||||||
if t == nl.CTA_MARK {
|
|
||||||
s.Mark = uint32(v[3])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,7 +305,7 @@ func parseRawData(data []byte) *ConntrackFlow {
|
|||||||
// Common parameters and options:
|
// Common parameters and options:
|
||||||
// -s, --src, --orig-src ip Source address from original direction
|
// -s, --src, --orig-src ip Source address from original direction
|
||||||
// -d, --dst, --orig-dst ip Destination address from original direction
|
// -d, --dst, --orig-dst ip Destination address from original direction
|
||||||
// -r, --reply-src ip Source addres from reply direction
|
// -r, --reply-src ip Source address from reply direction
|
||||||
// -q, --reply-dst ip Destination address from reply direction
|
// -q, --reply-dst ip Destination address from reply direction
|
||||||
// -p, --protonum proto Layer 4 Protocol, eg. 'tcp'
|
// -p, --protonum proto Layer 4 Protocol, eg. 'tcp'
|
||||||
// -f, --family proto Layer 3 Protocol, eg. 'ipv6'
|
// -f, --family proto Layer 3 Protocol, eg. 'ipv6'
|
||||||
@ -302,11 +322,14 @@ func parseRawData(data []byte) *ConntrackFlow {
|
|||||||
type ConntrackFilterType uint8
|
type ConntrackFilterType uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ConntrackOrigSrcIP = iota // -orig-src ip Source address from original direction
|
ConntrackOrigSrcIP = iota // -orig-src ip Source address from original direction
|
||||||
ConntrackOrigDstIP // -orig-dst ip Destination address from original direction
|
ConntrackOrigDstIP // -orig-dst ip Destination address from original direction
|
||||||
ConntrackNatSrcIP // -src-nat ip Source NAT ip
|
ConntrackReplySrcIP // --reply-src ip Reply Source IP
|
||||||
ConntrackNatDstIP // -dst-nat ip Destination NAT ip
|
ConntrackReplyDstIP // --reply-dst ip Reply Destination IP
|
||||||
ConntrackNatAnyIP // -any-nat ip Source or destination NAT 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 {
|
type CustomConntrackFilter interface {
|
||||||
@ -351,17 +374,17 @@ func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -src-nat ip Source NAT ip
|
// -src-nat ip Source NAT ip
|
||||||
if elem, found := f.ipFilter[ConntrackNatSrcIP]; match && found {
|
if elem, found := f.ipFilter[ConntrackReplySrcIP]; match && found {
|
||||||
match = match && elem.Equal(flow.Reverse.SrcIP)
|
match = match && elem.Equal(flow.Reverse.SrcIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -dst-nat ip Destination NAT ip
|
// -dst-nat ip Destination NAT ip
|
||||||
if elem, found := f.ipFilter[ConntrackNatDstIP]; match && found {
|
if elem, found := f.ipFilter[ConntrackReplyDstIP]; match && found {
|
||||||
match = match && elem.Equal(flow.Reverse.DstIP)
|
match = match && elem.Equal(flow.Reverse.DstIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -any-nat ip Source or destination NAT ip
|
// Match source or destination reply IP
|
||||||
if elem, found := f.ipFilter[ConntrackNatAnyIP]; match && found {
|
if elem, found := f.ipFilter[ConntrackReplyAnyIP]; match && found {
|
||||||
match = match && (elem.Equal(flow.Reverse.SrcIP) || elem.Equal(flow.Reverse.DstIP))
|
match = match && (elem.Equal(flow.Reverse.SrcIP) || elem.Equal(flow.Reverse.DstIP))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
272
vendor/github.com/vishvananda/netlink/devlink_linux.go
generated
vendored
Normal file
272
vendor/github.com/vishvananda/netlink/devlink_linux.go
generated
vendored
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
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)
|
||||||
|
}
|
102
vendor/github.com/vishvananda/netlink/filter.go
generated
vendored
102
vendor/github.com/vishvananda/netlink/filter.go
generated
vendored
@ -2,6 +2,7 @@ package netlink
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Filter interface {
|
type Filter interface {
|
||||||
@ -135,6 +136,27 @@ func (action *BpfAction) Attrs() *ActionAttrs {
|
|||||||
return &action.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
|
type MirredAct uint8
|
||||||
|
|
||||||
func (a MirredAct) String() string {
|
func (a MirredAct) String() string {
|
||||||
@ -182,47 +204,59 @@ func NewMirredAction(redirIndex int) *MirredAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sel of the U32 filters that contains multiple TcU32Key. This is the copy
|
type TunnelKeyAct int8
|
||||||
// and the frontend representation of nl.TcU32Sel. It is serialized into canonical
|
|
||||||
// nl.TcU32Sel with the appropriate endianness.
|
const (
|
||||||
type TcU32Sel struct {
|
TCA_TUNNEL_KEY_SET TunnelKeyAct = 1 // set tunnel key
|
||||||
Flags uint8
|
TCA_TUNNEL_KEY_UNSET TunnelKeyAct = 2 // unset tunnel key
|
||||||
Offshift uint8
|
)
|
||||||
Nkeys uint8
|
|
||||||
Pad uint8
|
type TunnelKeyAction struct {
|
||||||
Offmask uint16
|
ActionAttrs
|
||||||
Off uint16
|
Action TunnelKeyAct
|
||||||
Offoff int16
|
SrcAddr net.IP
|
||||||
Hoff int16
|
DstAddr net.IP
|
||||||
Hmask uint32
|
KeyID uint32
|
||||||
Keys []TcU32Key
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TcU32Key contained of Sel in the U32 filters. This is the copy and the frontend
|
func (action *TunnelKeyAction) Type() string {
|
||||||
// representation of nl.TcU32Key. It is serialized into chanonical nl.TcU32Sel
|
return "tunnel_key"
|
||||||
// with the appropriate endianness.
|
|
||||||
type TcU32Key struct {
|
|
||||||
Mask uint32
|
|
||||||
Val uint32
|
|
||||||
Off int32
|
|
||||||
OffMask int32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// U32 filters on many packet related properties
|
func (action *TunnelKeyAction) Attrs() *ActionAttrs {
|
||||||
type U32 struct {
|
return &action.ActionAttrs
|
||||||
FilterAttrs
|
|
||||||
ClassId uint32
|
|
||||||
RedirIndex int
|
|
||||||
Sel *TcU32Sel
|
|
||||||
Actions []Action
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (filter *U32) Attrs() *FilterAttrs {
|
func NewTunnelKeyAction() *TunnelKeyAction {
|
||||||
return &filter.FilterAttrs
|
return &TunnelKeyAction{
|
||||||
|
ActionAttrs: ActionAttrs{
|
||||||
|
Action: TC_ACT_PIPE,
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (filter *U32) Type() string {
|
type SkbEditAction struct {
|
||||||
return "u32"
|
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
|
// MatchAll filters match all packets
|
||||||
@ -262,6 +296,8 @@ type BpfFilter struct {
|
|||||||
Fd int
|
Fd int
|
||||||
Name string
|
Name string
|
||||||
DirectAction bool
|
DirectAction bool
|
||||||
|
Id int
|
||||||
|
Tag string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (filter *BpfFilter) Type() string {
|
func (filter *BpfFilter) Type() string {
|
||||||
|
240
vendor/github.com/vishvananda/netlink/filter_linux.go
generated
vendored
240
vendor/github.com/vishvananda/netlink/filter_linux.go
generated
vendored
@ -3,10 +3,11 @@ package netlink
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
@ -20,6 +21,35 @@ const (
|
|||||||
TC_U32_EAT = nl.TC_U32_EAT
|
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
|
// Fw filter filters on firewall marks
|
||||||
// NOTE: this is in filter_linux because it refers to nl.TcPolice which
|
// NOTE: this is in filter_linux because it refers to nl.TcPolice which
|
||||||
// is defined in nl/tc_linux.go
|
// is defined in nl/tc_linux.go
|
||||||
@ -123,8 +153,24 @@ func FilterAdd(filter Filter) error {
|
|||||||
// FilterAdd will add a filter to the system.
|
// FilterAdd will add a filter to the system.
|
||||||
// Equivalent to: `tc filter add $filter`
|
// Equivalent to: `tc filter add $filter`
|
||||||
func (h *Handle) FilterAdd(filter Filter) error {
|
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()
|
native = nl.NativeEndian()
|
||||||
req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
|
req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, flags|unix.NLM_F_ACK)
|
||||||
base := filter.Attrs()
|
base := filter.Attrs()
|
||||||
msg := &nl.TcMsg{
|
msg := &nl.TcMsg{
|
||||||
Family: nl.FAMILY_ALL,
|
Family: nl.FAMILY_ALL,
|
||||||
@ -140,8 +186,7 @@ func (h *Handle) FilterAdd(filter Filter) error {
|
|||||||
|
|
||||||
switch filter := filter.(type) {
|
switch filter := filter.(type) {
|
||||||
case *U32:
|
case *U32:
|
||||||
// Convert TcU32Sel into nl.TcU32Sel as it is without copy.
|
sel := filter.Sel
|
||||||
sel := (*nl.TcU32Sel)(unsafe.Pointer(filter.Sel))
|
|
||||||
if sel == nil {
|
if sel == nil {
|
||||||
// match all
|
// match all
|
||||||
sel = &nl.TcU32Sel{
|
sel = &nl.TcU32Sel{
|
||||||
@ -168,11 +213,20 @@ func (h *Handle) FilterAdd(filter Filter) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sel.Nkeys = uint8(len(sel.Keys))
|
sel.Nkeys = uint8(len(sel.Keys))
|
||||||
nl.NewRtAttrChild(options, nl.TCA_U32_SEL, sel.Serialize())
|
options.AddRtAttr(nl.TCA_U32_SEL, sel.Serialize())
|
||||||
if filter.ClassId != 0 {
|
if filter.ClassId != 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_U32_CLASSID, nl.Uint32Attr(filter.ClassId))
|
options.AddRtAttr(nl.TCA_U32_CLASSID, nl.Uint32Attr(filter.ClassId))
|
||||||
}
|
}
|
||||||
actionsAttr := nl.NewRtAttrChild(options, nl.TCA_U32_ACT, nil)
|
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
|
// backwards compatibility
|
||||||
if filter.RedirIndex != 0 {
|
if filter.RedirIndex != 0 {
|
||||||
filter.Actions = append([]Action{NewMirredAction(filter.RedirIndex)}, filter.Actions...)
|
filter.Actions = append([]Action{NewMirredAction(filter.RedirIndex)}, filter.Actions...)
|
||||||
@ -184,51 +238,51 @@ func (h *Handle) FilterAdd(filter Filter) error {
|
|||||||
if filter.Mask != 0 {
|
if filter.Mask != 0 {
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
native.PutUint32(b, filter.Mask)
|
native.PutUint32(b, filter.Mask)
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FW_MASK, b)
|
options.AddRtAttr(nl.TCA_FW_MASK, b)
|
||||||
}
|
}
|
||||||
if filter.InDev != "" {
|
if filter.InDev != "" {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev))
|
options.AddRtAttr(nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev))
|
||||||
}
|
}
|
||||||
if (filter.Police != nl.TcPolice{}) {
|
if (filter.Police != nl.TcPolice{}) {
|
||||||
|
|
||||||
police := nl.NewRtAttrChild(options, nl.TCA_FW_POLICE, nil)
|
police := options.AddRtAttr(nl.TCA_FW_POLICE, nil)
|
||||||
nl.NewRtAttrChild(police, nl.TCA_POLICE_TBF, filter.Police.Serialize())
|
police.AddRtAttr(nl.TCA_POLICE_TBF, filter.Police.Serialize())
|
||||||
if (filter.Police.Rate != nl.TcRateSpec{}) {
|
if (filter.Police.Rate != nl.TcRateSpec{}) {
|
||||||
payload := SerializeRtab(filter.Rtab)
|
payload := SerializeRtab(filter.Rtab)
|
||||||
nl.NewRtAttrChild(police, nl.TCA_POLICE_RATE, payload)
|
police.AddRtAttr(nl.TCA_POLICE_RATE, payload)
|
||||||
}
|
}
|
||||||
if (filter.Police.PeakRate != nl.TcRateSpec{}) {
|
if (filter.Police.PeakRate != nl.TcRateSpec{}) {
|
||||||
payload := SerializeRtab(filter.Ptab)
|
payload := SerializeRtab(filter.Ptab)
|
||||||
nl.NewRtAttrChild(police, nl.TCA_POLICE_PEAKRATE, payload)
|
police.AddRtAttr(nl.TCA_POLICE_PEAKRATE, payload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if filter.ClassId != 0 {
|
if filter.ClassId != 0 {
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
native.PutUint32(b, filter.ClassId)
|
native.PutUint32(b, filter.ClassId)
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FW_CLASSID, b)
|
options.AddRtAttr(nl.TCA_FW_CLASSID, b)
|
||||||
}
|
}
|
||||||
case *BpfFilter:
|
case *BpfFilter:
|
||||||
var bpfFlags uint32
|
var bpfFlags uint32
|
||||||
if filter.ClassId != 0 {
|
if filter.ClassId != 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_BPF_CLASSID, nl.Uint32Attr(filter.ClassId))
|
options.AddRtAttr(nl.TCA_BPF_CLASSID, nl.Uint32Attr(filter.ClassId))
|
||||||
}
|
}
|
||||||
if filter.Fd >= 0 {
|
if filter.Fd >= 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_BPF_FD, nl.Uint32Attr((uint32(filter.Fd))))
|
options.AddRtAttr(nl.TCA_BPF_FD, nl.Uint32Attr((uint32(filter.Fd))))
|
||||||
}
|
}
|
||||||
if filter.Name != "" {
|
if filter.Name != "" {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_BPF_NAME, nl.ZeroTerminated(filter.Name))
|
options.AddRtAttr(nl.TCA_BPF_NAME, nl.ZeroTerminated(filter.Name))
|
||||||
}
|
}
|
||||||
if filter.DirectAction {
|
if filter.DirectAction {
|
||||||
bpfFlags |= nl.TCA_BPF_FLAG_ACT_DIRECT
|
bpfFlags |= nl.TCA_BPF_FLAG_ACT_DIRECT
|
||||||
}
|
}
|
||||||
nl.NewRtAttrChild(options, nl.TCA_BPF_FLAGS, nl.Uint32Attr(bpfFlags))
|
options.AddRtAttr(nl.TCA_BPF_FLAGS, nl.Uint32Attr(bpfFlags))
|
||||||
case *MatchAll:
|
case *MatchAll:
|
||||||
actionsAttr := nl.NewRtAttrChild(options, nl.TCA_MATCHALL_ACT, nil)
|
actionsAttr := options.AddRtAttr(nl.TCA_MATCHALL_ACT, nil)
|
||||||
if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
|
if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if filter.ClassId != 0 {
|
if filter.ClassId != 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId))
|
options.AddRtAttr(nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,34 +420,91 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
|||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown action type %s", action.Type())
|
return fmt.Errorf("unknown action type %s", action.Type())
|
||||||
case *MirredAction:
|
case *MirredAction:
|
||||||
table := nl.NewRtAttrChild(attr, tabIndex, nil)
|
table := attr.AddRtAttr(tabIndex, nil)
|
||||||
tabIndex++
|
tabIndex++
|
||||||
nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("mirred"))
|
table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("mirred"))
|
||||||
aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil)
|
aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
|
||||||
mirred := nl.TcMirred{
|
mirred := nl.TcMirred{
|
||||||
Eaction: int32(action.MirredAction),
|
Eaction: int32(action.MirredAction),
|
||||||
Ifindex: uint32(action.Ifindex),
|
Ifindex: uint32(action.Ifindex),
|
||||||
}
|
}
|
||||||
toTcGen(action.Attrs(), &mirred.TcGen)
|
toTcGen(action.Attrs(), &mirred.TcGen)
|
||||||
nl.NewRtAttrChild(aopts, nl.TCA_MIRRED_PARMS, mirred.Serialize())
|
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:
|
case *BpfAction:
|
||||||
table := nl.NewRtAttrChild(attr, tabIndex, nil)
|
table := attr.AddRtAttr(tabIndex, nil)
|
||||||
tabIndex++
|
tabIndex++
|
||||||
nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("bpf"))
|
table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("bpf"))
|
||||||
aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil)
|
aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
|
||||||
gen := nl.TcGen{}
|
gen := nl.TcGen{}
|
||||||
toTcGen(action.Attrs(), &gen)
|
toTcGen(action.Attrs(), &gen)
|
||||||
nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_PARMS, gen.Serialize())
|
aopts.AddRtAttr(nl.TCA_ACT_BPF_PARMS, gen.Serialize())
|
||||||
nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd)))
|
aopts.AddRtAttr(nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd)))
|
||||||
nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_NAME, nl.ZeroTerminated(action.Name))
|
aopts.AddRtAttr(nl.TCA_ACT_BPF_NAME, nl.ZeroTerminated(action.Name))
|
||||||
case *GenericAction:
|
case *GenericAction:
|
||||||
table := nl.NewRtAttrChild(attr, tabIndex, nil)
|
table := attr.AddRtAttr(tabIndex, nil)
|
||||||
tabIndex++
|
tabIndex++
|
||||||
nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("gact"))
|
table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("gact"))
|
||||||
aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil)
|
aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
|
||||||
gen := nl.TcGen{}
|
gen := nl.TcGen{}
|
||||||
toTcGen(action.Attrs(), &gen)
|
toTcGen(action.Attrs(), &gen)
|
||||||
nl.NewRtAttrChild(aopts, nl.TCA_GACT_PARMS, gen.Serialize())
|
aopts.AddRtAttr(nl.TCA_GACT_PARMS, gen.Serialize())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -419,8 +530,14 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|||||||
action = &MirredAction{}
|
action = &MirredAction{}
|
||||||
case "bpf":
|
case "bpf":
|
||||||
action = &BpfAction{}
|
action = &BpfAction{}
|
||||||
|
case "connmark":
|
||||||
|
action = &ConnmarkAction{}
|
||||||
case "gact":
|
case "gact":
|
||||||
action = &GenericAction{}
|
action = &GenericAction{}
|
||||||
|
case "tunnel_key":
|
||||||
|
action = &TunnelKeyAction{}
|
||||||
|
case "skbedit":
|
||||||
|
action = &SkbEditAction{}
|
||||||
default:
|
default:
|
||||||
break nextattr
|
break nextattr
|
||||||
}
|
}
|
||||||
@ -435,11 +552,46 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|||||||
switch adatum.Attr.Type {
|
switch adatum.Attr.Type {
|
||||||
case nl.TCA_MIRRED_PARMS:
|
case nl.TCA_MIRRED_PARMS:
|
||||||
mirred := *nl.DeserializeTcMirred(adatum.Value)
|
mirred := *nl.DeserializeTcMirred(adatum.Value)
|
||||||
toAttrs(&mirred.TcGen, action.Attrs())
|
|
||||||
action.(*MirredAction).ActionAttrs = ActionAttrs{}
|
action.(*MirredAction).ActionAttrs = ActionAttrs{}
|
||||||
|
toAttrs(&mirred.TcGen, action.Attrs())
|
||||||
action.(*MirredAction).Ifindex = int(mirred.Ifindex)
|
action.(*MirredAction).Ifindex = int(mirred.Ifindex)
|
||||||
action.(*MirredAction).MirredAction = MirredAct(mirred.Eaction)
|
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":
|
case "bpf":
|
||||||
switch adatum.Attr.Type {
|
switch adatum.Attr.Type {
|
||||||
case nl.TCA_ACT_BPF_PARMS:
|
case nl.TCA_ACT_BPF_PARMS:
|
||||||
@ -450,6 +602,14 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|||||||
case nl.TCA_ACT_BPF_NAME:
|
case nl.TCA_ACT_BPF_NAME:
|
||||||
action.(*BpfAction).Name = string(adatum.Value[:len(adatum.Value)-1])
|
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":
|
case "gact":
|
||||||
switch adatum.Attr.Type {
|
switch adatum.Attr.Type {
|
||||||
case nl.TCA_GACT_PARMS:
|
case nl.TCA_GACT_PARMS:
|
||||||
@ -474,7 +634,7 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
|
|||||||
case nl.TCA_U32_SEL:
|
case nl.TCA_U32_SEL:
|
||||||
detailed = true
|
detailed = true
|
||||||
sel := nl.DeserializeTcU32Sel(datum.Value)
|
sel := nl.DeserializeTcU32Sel(datum.Value)
|
||||||
u32.Sel = (*TcU32Sel)(unsafe.Pointer(sel))
|
u32.Sel = sel
|
||||||
if native != networkOrder {
|
if native != networkOrder {
|
||||||
// Handle the endianness of attributes
|
// Handle the endianness of attributes
|
||||||
u32.Sel.Offmask = native.Uint16(htons(sel.Offmask))
|
u32.Sel.Offmask = native.Uint16(htons(sel.Offmask))
|
||||||
@ -500,6 +660,10 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
|
|||||||
}
|
}
|
||||||
case nl.TCA_U32_CLASSID:
|
case nl.TCA_U32_CLASSID:
|
||||||
u32.ClassId = native.Uint32(datum.Value)
|
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
|
return detailed, nil
|
||||||
@ -551,6 +715,10 @@ func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
|
|||||||
if (flags & nl.TCA_BPF_FLAG_ACT_DIRECT) != 0 {
|
if (flags & nl.TCA_BPF_FLAG_ACT_DIRECT) != 0 {
|
||||||
bpf.DirectAction = true
|
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
|
return detailed, nil
|
||||||
|
6
vendor/github.com/vishvananda/netlink/fou_linux.go
generated
vendored
6
vendor/github.com/vishvananda/netlink/fou_linux.go
generated
vendored
@ -90,11 +90,7 @@ func (h *Handle) FouAdd(f Fou) error {
|
|||||||
req.AddRawData(raw)
|
req.AddRawData(raw)
|
||||||
|
|
||||||
_, err = req.Execute(unix.NETLINK_GENERIC, 0)
|
_, err = req.Execute(unix.NETLINK_GENERIC, 0)
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func FouDel(f Fou) error {
|
func FouDel(f Fou) error {
|
||||||
|
3
vendor/github.com/vishvananda/netlink/genetlink_linux.go
generated
vendored
3
vendor/github.com/vishvananda/netlink/genetlink_linux.go
generated
vendored
@ -157,6 +157,9 @@ func (h *Handle) GenlFamilyGet(name string) (*GenlFamily, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
families, err := parseFamilies(msgs)
|
families, err := parseFamilies(msgs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if len(families) != 1 {
|
if len(families) != 1 {
|
||||||
return nil, fmt.Errorf("invalid response for GENL_CTRL_CMD_GETFAMILY")
|
return nil, fmt.Errorf("invalid response for GENL_CTRL_CMD_GETFAMILY")
|
||||||
}
|
}
|
||||||
|
8
vendor/github.com/vishvananda/netlink/go.mod
generated
vendored
Normal file
8
vendor/github.com/vishvananda/netlink/go.mod
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
module github.com/vishvananda/netlink
|
||||||
|
|
||||||
|
go 1.12
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df
|
||||||
|
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444
|
||||||
|
)
|
4
vendor/github.com/vishvananda/netlink/go.sum
generated
vendored
Normal file
4
vendor/github.com/vishvananda/netlink/go.sum
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k=
|
||||||
|
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||||
|
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444 h1:/d2cWp6PSamH4jDPFLyO150psQdqvtoNX8Zjg3AQ31g=
|
||||||
|
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
2
vendor/github.com/vishvananda/netlink/handle_linux.go
generated
vendored
2
vendor/github.com/vishvananda/netlink/handle_linux.go
generated
vendored
@ -91,7 +91,7 @@ func (h *Handle) GetSocketReceiveBufferSize() ([]int, error) {
|
|||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHandle returns a netlink handle on the network namespace
|
// NewHandleAt returns a netlink handle on the network namespace
|
||||||
// specified by ns. If ns=netns.None(), current network namespace
|
// specified by ns. If ns=netns.None(), current network namespace
|
||||||
// will be assumed
|
// will be assumed
|
||||||
func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) {
|
func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) {
|
||||||
|
12
vendor/github.com/vishvananda/netlink/handle_unspecified.go
generated
vendored
12
vendor/github.com/vishvananda/netlink/handle_unspecified.go
generated
vendored
@ -73,10 +73,18 @@ func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error {
|
|||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error {
|
func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error {
|
||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handle) LinkSetVfRate(link Link, vf, minRate, maxRate int) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handle) LinkSetMaster(link Link, master *Bridge) error {
|
func (h *Handle) LinkSetMaster(link Link, master *Bridge) error {
|
||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
@ -149,6 +157,10 @@ func (h *Handle) LinkSetTxQLen(link Link, qlen int) error {
|
|||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handle) LinkSetGroup(link Link, group int) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
|
func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
|
||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
10
vendor/github.com/vishvananda/netlink/ioctl_linux.go
generated
vendored
10
vendor/github.com/vishvananda/netlink/ioctl_linux.go
generated
vendored
@ -56,18 +56,10 @@ type ethtoolSset struct {
|
|||||||
data [1]uint32
|
data [1]uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// ethtoolGstrings is string set for data tagging
|
|
||||||
type ethtoolGstrings struct {
|
|
||||||
cmd uint32
|
|
||||||
stringSet uint32
|
|
||||||
length uint32
|
|
||||||
data [32]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type ethtoolStats struct {
|
type ethtoolStats struct {
|
||||||
cmd uint32
|
cmd uint32
|
||||||
nStats uint32
|
nStats uint32
|
||||||
data [1]uint64
|
// Followed by nStats * []uint64.
|
||||||
}
|
}
|
||||||
|
|
||||||
// newIocltSlaveReq returns filled IfreqSlave with proper interface names
|
// newIocltSlaveReq returns filled IfreqSlave with proper interface names
|
||||||
|
242
vendor/github.com/vishvananda/netlink/link.go
generated
vendored
242
vendor/github.com/vishvananda/netlink/link.go
generated
vendored
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Link represents a link device from netlink. Shared link attributes
|
// Link represents a link device from netlink. Shared link attributes
|
||||||
@ -41,6 +42,29 @@ type LinkAttrs struct {
|
|||||||
NetNsID int
|
NetNsID int
|
||||||
NumTxQueues int
|
NumTxQueues int
|
||||||
NumRxQueues int
|
NumRxQueues int
|
||||||
|
GSOMaxSize uint32
|
||||||
|
GSOMaxSegs uint32
|
||||||
|
Vfs []VfInfo // virtual functions available on link
|
||||||
|
Group uint32
|
||||||
|
Slave LinkSlave
|
||||||
|
}
|
||||||
|
|
||||||
|
// LinkSlave represents a slave device.
|
||||||
|
type LinkSlave interface {
|
||||||
|
SlaveType() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// VfInfo represents configuration of virtual function
|
||||||
|
type VfInfo struct {
|
||||||
|
ID int
|
||||||
|
Mac net.HardwareAddr
|
||||||
|
Vlan int
|
||||||
|
Qos int
|
||||||
|
TxRate int // IFLA_VF_TX_RATE Max TxRate
|
||||||
|
Spoofchk bool
|
||||||
|
LinkState uint32
|
||||||
|
MaxTxRate uint32 // IFLA_VF_RATE Max TxRate
|
||||||
|
MinTxRate uint32 // IFLA_VF_RATE Min TxRate
|
||||||
}
|
}
|
||||||
|
|
||||||
// LinkOperState represents the values of the IFLA_OPERSTATE link
|
// LinkOperState represents the values of the IFLA_OPERSTATE link
|
||||||
@ -223,6 +247,7 @@ type Bridge struct {
|
|||||||
LinkAttrs
|
LinkAttrs
|
||||||
MulticastSnooping *bool
|
MulticastSnooping *bool
|
||||||
HelloTime *uint32
|
HelloTime *uint32
|
||||||
|
VlanFiltering *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bridge *Bridge) Attrs() *LinkAttrs {
|
func (bridge *Bridge) Attrs() *LinkAttrs {
|
||||||
@ -236,7 +261,8 @@ func (bridge *Bridge) Type() string {
|
|||||||
// Vlan links have ParentIndex set in their Attrs()
|
// Vlan links have ParentIndex set in their Attrs()
|
||||||
type Vlan struct {
|
type Vlan struct {
|
||||||
LinkAttrs
|
LinkAttrs
|
||||||
VlanId int
|
VlanId int
|
||||||
|
VlanProtocol VlanProtocol
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vlan *Vlan) Attrs() *LinkAttrs {
|
func (vlan *Vlan) Attrs() *LinkAttrs {
|
||||||
@ -290,10 +316,13 @@ type TuntapFlag uint16
|
|||||||
// Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
|
// Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
|
||||||
type Tuntap struct {
|
type Tuntap struct {
|
||||||
LinkAttrs
|
LinkAttrs
|
||||||
Mode TuntapMode
|
Mode TuntapMode
|
||||||
Flags TuntapFlag
|
Flags TuntapFlag
|
||||||
Queues int
|
NonPersist bool
|
||||||
Fds []*os.File
|
Queues int
|
||||||
|
Fds []*os.File
|
||||||
|
Owner uint32
|
||||||
|
Group uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tuntap *Tuntap) Attrs() *LinkAttrs {
|
func (tuntap *Tuntap) Attrs() *LinkAttrs {
|
||||||
@ -307,7 +336,8 @@ func (tuntap *Tuntap) Type() string {
|
|||||||
// Veth devices must specify PeerName on create
|
// Veth devices must specify PeerName on create
|
||||||
type Veth struct {
|
type Veth struct {
|
||||||
LinkAttrs
|
LinkAttrs
|
||||||
PeerName string // veth on create only
|
PeerName string // veth on create only
|
||||||
|
PeerHardwareAddr net.HardwareAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (veth *Veth) Attrs() *LinkAttrs {
|
func (veth *Veth) Attrs() *LinkAttrs {
|
||||||
@ -376,9 +406,18 @@ const (
|
|||||||
IPVLAN_MODE_MAX
|
IPVLAN_MODE_MAX
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type IPVlanFlag uint16
|
||||||
|
|
||||||
|
const (
|
||||||
|
IPVLAN_FLAG_BRIDGE IPVlanFlag = iota
|
||||||
|
IPVLAN_FLAG_PRIVATE
|
||||||
|
IPVLAN_FLAG_VEPA
|
||||||
|
)
|
||||||
|
|
||||||
type IPVlan struct {
|
type IPVlan struct {
|
||||||
LinkAttrs
|
LinkAttrs
|
||||||
Mode IPVlanMode
|
Mode IPVlanMode
|
||||||
|
Flag IPVlanFlag
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ipvlan *IPVlan) Attrs() *LinkAttrs {
|
func (ipvlan *IPVlan) Attrs() *LinkAttrs {
|
||||||
@ -389,6 +428,43 @@ func (ipvlan *IPVlan) Type() string {
|
|||||||
return "ipvlan"
|
return "ipvlan"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VlanProtocol type
|
||||||
|
type VlanProtocol int
|
||||||
|
|
||||||
|
func (p VlanProtocol) String() string {
|
||||||
|
s, ok := VlanProtocolToString[p]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Sprintf("VlanProtocol(%d)", p)
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToVlanProtocol returns vlan protocol, or unknown is the s is invalid.
|
||||||
|
func StringToVlanProtocol(s string) VlanProtocol {
|
||||||
|
mode, ok := StringToVlanProtocolMap[s]
|
||||||
|
if !ok {
|
||||||
|
return VLAN_PROTOCOL_UNKNOWN
|
||||||
|
}
|
||||||
|
return mode
|
||||||
|
}
|
||||||
|
|
||||||
|
// VlanProtocol possible values
|
||||||
|
const (
|
||||||
|
VLAN_PROTOCOL_UNKNOWN VlanProtocol = 0
|
||||||
|
VLAN_PROTOCOL_8021Q VlanProtocol = 0x8100
|
||||||
|
VLAN_PROTOCOL_8021AD VlanProtocol = 0x88A8
|
||||||
|
)
|
||||||
|
|
||||||
|
var VlanProtocolToString = map[VlanProtocol]string{
|
||||||
|
VLAN_PROTOCOL_8021Q: "802.1q",
|
||||||
|
VLAN_PROTOCOL_8021AD: "802.1ad",
|
||||||
|
}
|
||||||
|
|
||||||
|
var StringToVlanProtocolMap = map[string]VlanProtocol{
|
||||||
|
"802.1q": VLAN_PROTOCOL_8021Q,
|
||||||
|
"802.1ad": VLAN_PROTOCOL_8021AD,
|
||||||
|
}
|
||||||
|
|
||||||
// BondMode type
|
// BondMode type
|
||||||
type BondMode int
|
type BondMode int
|
||||||
|
|
||||||
@ -400,7 +476,7 @@ func (b BondMode) String() string {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToBondMode returns bond mode, or uknonw is the s is invalid.
|
// StringToBondMode returns bond mode, or unknown is the s is invalid.
|
||||||
func StringToBondMode(s string) BondMode {
|
func StringToBondMode(s string) BondMode {
|
||||||
mode, ok := StringToBondModeMap[s]
|
mode, ok := StringToBondModeMap[s]
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -491,7 +567,7 @@ func (b BondXmitHashPolicy) String() string {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToBondXmitHashPolicy returns bond lacp arte, or uknonw is the s is invalid.
|
// StringToBondXmitHashPolicy returns bond lacp arte, or unknown is the s is invalid.
|
||||||
func StringToBondXmitHashPolicy(s string) BondXmitHashPolicy {
|
func StringToBondXmitHashPolicy(s string) BondXmitHashPolicy {
|
||||||
lacp, ok := StringToBondXmitHashPolicyMap[s]
|
lacp, ok := StringToBondXmitHashPolicyMap[s]
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -536,7 +612,7 @@ func (b BondLacpRate) String() string {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringToBondLacpRate returns bond lacp arte, or uknonw is the s is invalid.
|
// StringToBondLacpRate returns bond lacp arte, or unknown is the s is invalid.
|
||||||
func StringToBondLacpRate(s string) BondLacpRate {
|
func StringToBondLacpRate(s string) BondLacpRate {
|
||||||
lacp, ok := StringToBondLacpRateMap[s]
|
lacp, ok := StringToBondLacpRateMap[s]
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -680,6 +756,67 @@ func (bond *Bond) Type() string {
|
|||||||
return "bond"
|
return "bond"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BondSlaveState represents the values of the IFLA_BOND_SLAVE_STATE bond slave
|
||||||
|
// attribute, which contains the state of the bond slave.
|
||||||
|
type BondSlaveState uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
BondStateActive = iota // Link is active.
|
||||||
|
BondStateBackup // Link is backup.
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s BondSlaveState) String() string {
|
||||||
|
switch s {
|
||||||
|
case BondStateActive:
|
||||||
|
return "ACTIVE"
|
||||||
|
case BondStateBackup:
|
||||||
|
return "BACKUP"
|
||||||
|
default:
|
||||||
|
return strconv.Itoa(int(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BondSlaveState represents the values of the IFLA_BOND_SLAVE_MII_STATUS bond slave
|
||||||
|
// attribute, which contains the status of MII link monitoring
|
||||||
|
type BondSlaveMiiStatus uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
BondLinkUp = iota // link is up and running.
|
||||||
|
BondLinkFail // link has just gone down.
|
||||||
|
BondLinkDown // link has been down for too long time.
|
||||||
|
BondLinkBack // link is going back.
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s BondSlaveMiiStatus) String() string {
|
||||||
|
switch s {
|
||||||
|
case BondLinkUp:
|
||||||
|
return "UP"
|
||||||
|
case BondLinkFail:
|
||||||
|
return "GOING_DOWN"
|
||||||
|
case BondLinkDown:
|
||||||
|
return "DOWN"
|
||||||
|
case BondLinkBack:
|
||||||
|
return "GOING_BACK"
|
||||||
|
default:
|
||||||
|
return strconv.Itoa(int(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type BondSlave struct {
|
||||||
|
State BondSlaveState
|
||||||
|
MiiStatus BondSlaveMiiStatus
|
||||||
|
LinkFailureCount uint32
|
||||||
|
PermHardwareAddr net.HardwareAddr
|
||||||
|
QueueId uint16
|
||||||
|
AggregatorId uint16
|
||||||
|
AdActorOperPortState uint8
|
||||||
|
AdPartnerOperPortState uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BondSlave) SlaveType() string {
|
||||||
|
return "bond"
|
||||||
|
}
|
||||||
|
|
||||||
// Gretap devices must specify LocalIP and RemoteIP on create
|
// Gretap devices must specify LocalIP and RemoteIP on create
|
||||||
type Gretap struct {
|
type Gretap struct {
|
||||||
LinkAttrs
|
LinkAttrs
|
||||||
@ -734,6 +871,27 @@ func (iptun *Iptun) Type() string {
|
|||||||
return "ipip"
|
return "ipip"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Ip6tnl struct {
|
||||||
|
LinkAttrs
|
||||||
|
Link uint32
|
||||||
|
Local net.IP
|
||||||
|
Remote net.IP
|
||||||
|
Ttl uint8
|
||||||
|
Tos uint8
|
||||||
|
EncapLimit uint8
|
||||||
|
Flags uint32
|
||||||
|
Proto uint8
|
||||||
|
FlowInfo uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ip6tnl *Ip6tnl) Attrs() *LinkAttrs {
|
||||||
|
return &ip6tnl.LinkAttrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ip6tnl *Ip6tnl) Type() string {
|
||||||
|
return "ip6tnl"
|
||||||
|
}
|
||||||
|
|
||||||
type Sittun struct {
|
type Sittun struct {
|
||||||
LinkAttrs
|
LinkAttrs
|
||||||
Link uint32
|
Link uint32
|
||||||
@ -769,7 +927,10 @@ func (vti *Vti) Attrs() *LinkAttrs {
|
|||||||
return &vti.LinkAttrs
|
return &vti.LinkAttrs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iptun *Vti) Type() string {
|
func (vti *Vti) Type() string {
|
||||||
|
if vti.Local.To4() == nil {
|
||||||
|
return "vti6"
|
||||||
|
}
|
||||||
return "vti"
|
return "vti"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -831,11 +992,68 @@ func (gtp *GTP) Type() string {
|
|||||||
return "gtp"
|
return "gtp"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Virtual XFRM Interfaces
|
||||||
|
// Named "xfrmi" to prevent confusion with XFRM objects
|
||||||
|
type Xfrmi struct {
|
||||||
|
LinkAttrs
|
||||||
|
Ifid uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (xfrm *Xfrmi) Attrs() *LinkAttrs {
|
||||||
|
return &xfrm.LinkAttrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (xfrm *Xfrmi) Type() string {
|
||||||
|
return "xfrm"
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPoIB interface
|
||||||
|
|
||||||
|
type IPoIBMode uint16
|
||||||
|
|
||||||
|
func (m *IPoIBMode) String() string {
|
||||||
|
str, ok := iPoIBModeToString[*m]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Sprintf("mode(%d)", *m)
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
IPOIB_MODE_DATAGRAM = iota
|
||||||
|
IPOIB_MODE_CONNECTED
|
||||||
|
)
|
||||||
|
|
||||||
|
var iPoIBModeToString = map[IPoIBMode]string{
|
||||||
|
IPOIB_MODE_DATAGRAM: "datagram",
|
||||||
|
IPOIB_MODE_CONNECTED: "connected",
|
||||||
|
}
|
||||||
|
|
||||||
|
var StringToIPoIBMode = map[string]IPoIBMode{
|
||||||
|
"datagram": IPOIB_MODE_DATAGRAM,
|
||||||
|
"connected": IPOIB_MODE_CONNECTED,
|
||||||
|
}
|
||||||
|
|
||||||
|
type IPoIB struct {
|
||||||
|
LinkAttrs
|
||||||
|
Pkey uint16
|
||||||
|
Mode IPoIBMode
|
||||||
|
Umcast uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ipoib *IPoIB) Attrs() *LinkAttrs {
|
||||||
|
return &ipoib.LinkAttrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ipoib *IPoIB) Type() string {
|
||||||
|
return "ipoib"
|
||||||
|
}
|
||||||
|
|
||||||
// iproute2 supported devices;
|
// iproute2 supported devices;
|
||||||
// vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
|
// vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
|
||||||
// bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |
|
// bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |
|
||||||
// gre | gretap | ip6gre | ip6gretap | vti | nlmon |
|
// gre | gretap | ip6gre | ip6gretap | vti | vti6 | nlmon |
|
||||||
// bond_slave | ipvlan
|
// bond_slave | ipvlan | xfrm
|
||||||
|
|
||||||
// LinkNotFoundError wraps the various not found errors when
|
// LinkNotFoundError wraps the various not found errors when
|
||||||
// getting/reading links. This is intended for better error
|
// getting/reading links. This is intended for better error
|
||||||
|
1124
vendor/github.com/vishvananda/netlink/link_linux.go
generated
vendored
1124
vendor/github.com/vishvananda/netlink/link_linux.go
generated
vendored
File diff suppressed because it is too large
Load Diff
7
vendor/github.com/vishvananda/netlink/neigh.go
generated
vendored
7
vendor/github.com/vishvananda/netlink/neigh.go
generated
vendored
@ -17,9 +17,16 @@ type Neigh struct {
|
|||||||
LLIPAddr net.IP //Used in the case of NHRP
|
LLIPAddr net.IP //Used in the case of NHRP
|
||||||
Vlan int
|
Vlan int
|
||||||
VNI int
|
VNI int
|
||||||
|
MasterIndex int
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns $ip/$hwaddr $label
|
// String returns $ip/$hwaddr $label
|
||||||
func (neigh *Neigh) String() string {
|
func (neigh *Neigh) String() string {
|
||||||
return fmt.Sprintf("%s %s", neigh.IP, neigh.HardwareAddr)
|
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
|
||||||
|
}
|
||||||
|
191
vendor/github.com/vishvananda/netlink/neigh_linux.go
generated
vendored
191
vendor/github.com/vishvananda/netlink/neigh_linux.go
generated
vendored
@ -1,10 +1,13 @@
|
|||||||
package netlink
|
package netlink
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
"github.com/vishvananda/netns"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,7 +21,10 @@ const (
|
|||||||
NDA_PORT
|
NDA_PORT
|
||||||
NDA_VNI
|
NDA_VNI
|
||||||
NDA_IFINDEX
|
NDA_IFINDEX
|
||||||
NDA_MAX = NDA_IFINDEX
|
NDA_MASTER
|
||||||
|
NDA_LINK_NETNSID
|
||||||
|
NDA_SRC_VNI
|
||||||
|
NDA_MAX = NDA_SRC_VNI
|
||||||
)
|
)
|
||||||
|
|
||||||
// Neighbor Cache Entry States.
|
// Neighbor Cache Entry States.
|
||||||
@ -43,6 +49,7 @@ const (
|
|||||||
NTF_ROUTER = 0x80
|
NTF_ROUTER = 0x80
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Ndmsg is for adding, removing or receiving information about a neighbor table entry
|
||||||
type Ndmsg struct {
|
type Ndmsg struct {
|
||||||
Family uint8
|
Family uint8
|
||||||
Index uint32
|
Index uint32
|
||||||
@ -170,45 +177,58 @@ func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
|
|||||||
req.AddData(vniData)
|
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)
|
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// NeighList gets a list of IP-MAC mappings in the system (ARP table).
|
// NeighList returns a list of IP-MAC mappings in the system (ARP table).
|
||||||
// Equivalent to: `ip neighbor show`.
|
// Equivalent to: `ip neighbor show`.
|
||||||
// The list can be filtered by link and ip family.
|
// The list can be filtered by link and ip family.
|
||||||
func NeighList(linkIndex, family int) ([]Neigh, error) {
|
func NeighList(linkIndex, family int) ([]Neigh, error) {
|
||||||
return pkgHandle.NeighList(linkIndex, family)
|
return pkgHandle.NeighList(linkIndex, family)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NeighProxyList gets a list of neighbor proxies in the system.
|
// NeighProxyList returns a list of neighbor proxies in the system.
|
||||||
// Equivalent to: `ip neighbor show proxy`.
|
// Equivalent to: `ip neighbor show proxy`.
|
||||||
// The list can be filtered by link and ip family.
|
// The list can be filtered by link and ip family.
|
||||||
func NeighProxyList(linkIndex, family int) ([]Neigh, error) {
|
func NeighProxyList(linkIndex, family int) ([]Neigh, error) {
|
||||||
return pkgHandle.NeighProxyList(linkIndex, family)
|
return pkgHandle.NeighProxyList(linkIndex, family)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NeighList gets a list of IP-MAC mappings in the system (ARP table).
|
// NeighList returns a list of IP-MAC mappings in the system (ARP table).
|
||||||
// Equivalent to: `ip neighbor show`.
|
// Equivalent to: `ip neighbor show`.
|
||||||
// The list can be filtered by link and ip family.
|
// The list can be filtered by link and ip family.
|
||||||
func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) {
|
func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) {
|
||||||
return h.neighList(linkIndex, family, 0)
|
return h.NeighListExecute(Ndmsg{
|
||||||
|
Family: uint8(family),
|
||||||
|
Index: uint32(linkIndex),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// NeighProxyList gets a list of neighbor proxies in the system.
|
// NeighProxyList returns a list of neighbor proxies in the system.
|
||||||
// Equivalent to: `ip neighbor show proxy`.
|
// Equivalent to: `ip neighbor show proxy`.
|
||||||
// The list can be filtered by link, ip family.
|
// The list can be filtered by link, ip family.
|
||||||
func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) {
|
func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) {
|
||||||
return h.neighList(linkIndex, family, NTF_PROXY)
|
return h.NeighListExecute(Ndmsg{
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) {
|
|
||||||
req := h.newNetlinkRequest(unix.RTM_GETNEIGH, unix.NLM_F_DUMP)
|
|
||||||
msg := Ndmsg{
|
|
||||||
Family: uint8(family),
|
Family: uint8(family),
|
||||||
Index: uint32(linkIndex),
|
Index: uint32(linkIndex),
|
||||||
Flags: uint8(flags),
|
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)
|
req.AddData(&msg)
|
||||||
|
|
||||||
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNEIGH)
|
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNEIGH)
|
||||||
@ -219,7 +239,7 @@ func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) {
|
|||||||
var res []Neigh
|
var res []Neigh
|
||||||
for _, m := range msgs {
|
for _, m := range msgs {
|
||||||
ndm := deserializeNdmsg(m)
|
ndm := deserializeNdmsg(m)
|
||||||
if linkIndex != 0 && int(ndm.Index) != linkIndex {
|
if msg.Index != 0 && ndm.Index != msg.Index {
|
||||||
// Ignore messages from other interfaces
|
// Ignore messages from other interfaces
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -251,14 +271,6 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should be cached for perfomance
|
|
||||||
// once per table dump
|
|
||||||
link, err := LinkByIndex(neigh.LinkIndex)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
encapType := link.Attrs().EncapType
|
|
||||||
|
|
||||||
for _, attr := range attrs {
|
for _, attr := range attrs {
|
||||||
switch attr.Attr.Type {
|
switch attr.Attr.Type {
|
||||||
case NDA_DST:
|
case NDA_DST:
|
||||||
@ -268,13 +280,16 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
|
|||||||
// #define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len))
|
// #define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len))
|
||||||
// #define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0))
|
// #define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0))
|
||||||
attrLen := attr.Attr.Len - unix.SizeofRtAttr
|
attrLen := attr.Attr.Len - unix.SizeofRtAttr
|
||||||
if attrLen == 4 && (encapType == "ipip" ||
|
if attrLen == 4 {
|
||||||
encapType == "sit" ||
|
|
||||||
encapType == "gre") {
|
|
||||||
neigh.LLIPAddr = net.IP(attr.Value)
|
neigh.LLIPAddr = net.IP(attr.Value)
|
||||||
} else if attrLen == 16 &&
|
} else if attrLen == 16 {
|
||||||
encapType == "tunnel6" {
|
// Can be IPv6 or FireWire HWAddr
|
||||||
neigh.IP = net.IP(attr.Value)
|
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 {
|
} else {
|
||||||
neigh.HardwareAddr = net.HardwareAddr(attr.Value)
|
neigh.HardwareAddr = net.HardwareAddr(attr.Value)
|
||||||
}
|
}
|
||||||
@ -282,8 +297,126 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
|
|||||||
neigh.Vlan = int(native.Uint16(attr.Value[0:2]))
|
neigh.Vlan = int(native.Uint16(attr.Value[0:2]))
|
||||||
case NDA_VNI:
|
case NDA_VNI:
|
||||||
neigh.VNI = int(native.Uint32(attr.Value[0:4]))
|
neigh.VNI = int(native.Uint32(attr.Value[0:4]))
|
||||||
|
case NDA_MASTER:
|
||||||
|
neigh.MasterIndex = int(native.Uint32(attr.Value[0:4]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &neigh, nil
|
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
|
||||||
|
}
|
||||||
|
3
vendor/github.com/vishvananda/netlink/netlink.go
generated
vendored
3
vendor/github.com/vishvananda/netlink/netlink.go
generated
vendored
@ -27,7 +27,8 @@ func ParseIPNet(s string) (*net.IPNet, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &net.IPNet{IP: ip, Mask: ipNet.Mask}, nil
|
ipNet.IP = ip
|
||||||
|
return ipNet, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIPNet generates an IPNet from an ip address using a netmask of 32 or 128.
|
// NewIPNet generates an IPNet from an ip address using a netmask of 32 or 128.
|
||||||
|
12
vendor/github.com/vishvananda/netlink/netlink_unspecified.go
generated
vendored
12
vendor/github.com/vishvananda/netlink/netlink_unspecified.go
generated
vendored
@ -48,10 +48,18 @@ func LinkSetVfVlan(link Link, vf, vlan int) error {
|
|||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
func LinkSetVfTxRate(link Link, vf, rate int) error {
|
func LinkSetVfTxRate(link Link, vf, rate int) error {
|
||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LinkSetVfRate(link Link, vf, minRate, maxRate int) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
func LinkSetNoMaster(link Link) error {
|
func LinkSetNoMaster(link Link) error {
|
||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
@ -152,6 +160,10 @@ func AddrAdd(link Link, addr *Addr) error {
|
|||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AddrReplace(link Link, addr *Addr) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
func AddrDel(link Link, addr *Addr) error {
|
func AddrDel(link Link, addr *Addr) error {
|
||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
141
vendor/github.com/vishvananda/netlink/netns_linux.go
generated
vendored
Normal file
141
vendor/github.com/vishvananda/netlink/netns_linux.go
generated
vendored
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
package netlink
|
||||||
|
|
||||||
|
// Network namespace ID functions
|
||||||
|
//
|
||||||
|
// The kernel has a weird concept called the network namespace ID.
|
||||||
|
// This is different from the file reference in proc (and any bind-mounted
|
||||||
|
// namespaces, etc.)
|
||||||
|
//
|
||||||
|
// Instead, namespaces can be assigned a numeric ID at any time. Once set,
|
||||||
|
// the ID is fixed. The ID can either be set manually by the user, or
|
||||||
|
// automatically, triggered by certain kernel actions. The most common kernel
|
||||||
|
// action that triggers namespace ID creation is moving one end of a veth pair
|
||||||
|
// in to that namespace.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// These can be replaced by the values from sys/unix when it is next released.
|
||||||
|
const (
|
||||||
|
_ = iota
|
||||||
|
NETNSA_NSID
|
||||||
|
NETNSA_PID
|
||||||
|
NETNSA_FD
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetNetNsIdByPid looks up the network namespace ID for a given pid (really thread id).
|
||||||
|
// Returns -1 if the namespace does not have an ID set.
|
||||||
|
func (h *Handle) GetNetNsIdByPid(pid int) (int, error) {
|
||||||
|
return h.getNetNsId(NETNSA_PID, uint32(pid))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNetNsIdByPid looks up the network namespace ID for a given pid (really thread id).
|
||||||
|
// Returns -1 if the namespace does not have an ID set.
|
||||||
|
func GetNetNsIdByPid(pid int) (int, error) {
|
||||||
|
return pkgHandle.GetNetNsIdByPid(pid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNetNSIdByPid sets the ID of the network namespace for a given pid (really thread id).
|
||||||
|
// The ID can only be set for namespaces without an ID already set.
|
||||||
|
func (h *Handle) SetNetNsIdByPid(pid, nsid int) error {
|
||||||
|
return h.setNetNsId(NETNSA_PID, uint32(pid), uint32(nsid))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNetNSIdByPid sets the ID of the network namespace for a given pid (really thread id).
|
||||||
|
// The ID can only be set for namespaces without an ID already set.
|
||||||
|
func SetNetNsIdByPid(pid, nsid int) error {
|
||||||
|
return pkgHandle.SetNetNsIdByPid(pid, nsid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNetNsIdByFd looks up the network namespace ID for a given fd.
|
||||||
|
// fd must be an open file descriptor to a namespace file.
|
||||||
|
// Returns -1 if the namespace does not have an ID set.
|
||||||
|
func (h *Handle) GetNetNsIdByFd(fd int) (int, error) {
|
||||||
|
return h.getNetNsId(NETNSA_FD, uint32(fd))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNetNsIdByFd looks up the network namespace ID for a given fd.
|
||||||
|
// fd must be an open file descriptor to a namespace file.
|
||||||
|
// Returns -1 if the namespace does not have an ID set.
|
||||||
|
func GetNetNsIdByFd(fd int) (int, error) {
|
||||||
|
return pkgHandle.GetNetNsIdByFd(fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNetNSIdByFd sets the ID of the network namespace for a given fd.
|
||||||
|
// fd must be an open file descriptor to a namespace file.
|
||||||
|
// The ID can only be set for namespaces without an ID already set.
|
||||||
|
func (h *Handle) SetNetNsIdByFd(fd, nsid int) error {
|
||||||
|
return h.setNetNsId(NETNSA_FD, uint32(fd), uint32(nsid))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNetNSIdByFd sets the ID of the network namespace for a given fd.
|
||||||
|
// fd must be an open file descriptor to a namespace file.
|
||||||
|
// The ID can only be set for namespaces without an ID already set.
|
||||||
|
func SetNetNsIdByFd(fd, nsid int) error {
|
||||||
|
return pkgHandle.SetNetNsIdByFd(fd, nsid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getNetNsId requests the netnsid for a given type-val pair
|
||||||
|
// type should be either NETNSA_PID or NETNSA_FD
|
||||||
|
func (h *Handle) getNetNsId(attrType int, val uint32) (int, error) {
|
||||||
|
req := h.newNetlinkRequest(unix.RTM_GETNSID, unix.NLM_F_REQUEST)
|
||||||
|
|
||||||
|
rtgen := nl.NewRtGenMsg()
|
||||||
|
req.AddData(rtgen)
|
||||||
|
|
||||||
|
b := make([]byte, 4, 4)
|
||||||
|
native.PutUint32(b, val)
|
||||||
|
attr := nl.NewRtAttr(attrType, b)
|
||||||
|
req.AddData(attr)
|
||||||
|
|
||||||
|
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNSID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, m := range msgs {
|
||||||
|
msg := nl.DeserializeRtGenMsg(m)
|
||||||
|
|
||||||
|
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, attr := range attrs {
|
||||||
|
switch attr.Attr.Type {
|
||||||
|
case NETNSA_NSID:
|
||||||
|
return int(int32(native.Uint32(attr.Value))), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, fmt.Errorf("unexpected empty result")
|
||||||
|
}
|
||||||
|
|
||||||
|
// setNetNsId sets the netnsid for a given type-val pair
|
||||||
|
// type should be either NETNSA_PID or NETNSA_FD
|
||||||
|
// The ID can only be set for namespaces without an ID already set
|
||||||
|
func (h *Handle) setNetNsId(attrType int, val uint32, newnsid uint32) error {
|
||||||
|
req := h.newNetlinkRequest(unix.RTM_NEWNSID, unix.NLM_F_REQUEST|unix.NLM_F_ACK)
|
||||||
|
|
||||||
|
rtgen := nl.NewRtGenMsg()
|
||||||
|
req.AddData(rtgen)
|
||||||
|
|
||||||
|
b := make([]byte, 4, 4)
|
||||||
|
native.PutUint32(b, val)
|
||||||
|
attr := nl.NewRtAttr(attrType, b)
|
||||||
|
req.AddData(attr)
|
||||||
|
|
||||||
|
b1 := make([]byte, 4, 4)
|
||||||
|
native.PutUint32(b1, newnsid)
|
||||||
|
attr1 := nl.NewRtAttr(NETNSA_NSID, b1)
|
||||||
|
req.AddData(attr1)
|
||||||
|
|
||||||
|
_, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNSID)
|
||||||
|
return err
|
||||||
|
}
|
19
vendor/github.com/vishvananda/netlink/netns_unspecified.go
generated
vendored
Normal file
19
vendor/github.com/vishvananda/netlink/netns_unspecified.go
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package netlink
|
||||||
|
|
||||||
|
func GetNetNsIdByPid(pid int) (int, error) {
|
||||||
|
return 0, ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetNetNsIdByPid(pid, nsid int) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetNetNsIdByFd(fd int) (int, error) {
|
||||||
|
return 0, ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetNetNsIdByFd(fd, nsid int) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
4
vendor/github.com/vishvananda/netlink/nl/bridge_linux.go
generated
vendored
4
vendor/github.com/vishvananda/netlink/nl/bridge_linux.go
generated
vendored
@ -11,8 +11,8 @@ const (
|
|||||||
|
|
||||||
/* Bridge Flags */
|
/* Bridge Flags */
|
||||||
const (
|
const (
|
||||||
BRIDGE_FLAGS_MASTER = iota /* Bridge command to/from master */
|
BRIDGE_FLAGS_MASTER = iota + 1 /* Bridge command to/from master */
|
||||||
BRIDGE_FLAGS_SELF /* Bridge command to/from lowerdev */
|
BRIDGE_FLAGS_SELF /* Bridge command to/from lowerdev */
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Bridge management nested attributes
|
/* Bridge management nested attributes
|
||||||
|
40
vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
generated
vendored
40
vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
generated
vendored
@ -76,12 +76,17 @@ const (
|
|||||||
// __CTA_MAX
|
// __CTA_MAX
|
||||||
// };
|
// };
|
||||||
const (
|
const (
|
||||||
CTA_TUPLE_ORIG = 1
|
CTA_TUPLE_ORIG = 1
|
||||||
CTA_TUPLE_REPLY = 2
|
CTA_TUPLE_REPLY = 2
|
||||||
CTA_STATUS = 3
|
CTA_STATUS = 3
|
||||||
CTA_TIMEOUT = 7
|
CTA_PROTOINFO = 4
|
||||||
CTA_MARK = 8
|
CTA_TIMEOUT = 7
|
||||||
CTA_PROTOINFO = 4
|
CTA_MARK = 8
|
||||||
|
CTA_COUNTERS_ORIG = 9
|
||||||
|
CTA_COUNTERS_REPLY = 10
|
||||||
|
CTA_USE = 11
|
||||||
|
CTA_ID = 12
|
||||||
|
CTA_TIMESTAMP = 20
|
||||||
)
|
)
|
||||||
|
|
||||||
// enum ctattr_tuple {
|
// enum ctattr_tuple {
|
||||||
@ -163,6 +168,29 @@ const (
|
|||||||
CTA_PROTOINFO_TCP_FLAGS_REPLY = 5
|
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.
|
// /* General form of address family dependent message.
|
||||||
// */
|
// */
|
||||||
// struct nfgenmsg {
|
// struct nfgenmsg {
|
||||||
|
40
vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
generated
vendored
Normal file
40
vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
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
|
||||||
|
)
|
72
vendor/github.com/vishvananda/netlink/nl/link_linux.go
generated
vendored
72
vendor/github.com/vishvananda/netlink/nl/link_linux.go
generated
vendored
@ -13,7 +13,9 @@ const (
|
|||||||
IFLA_INFO_KIND
|
IFLA_INFO_KIND
|
||||||
IFLA_INFO_DATA
|
IFLA_INFO_DATA
|
||||||
IFLA_INFO_XSTATS
|
IFLA_INFO_XSTATS
|
||||||
IFLA_INFO_MAX = IFLA_INFO_XSTATS
|
IFLA_INFO_SLAVE_KIND
|
||||||
|
IFLA_INFO_SLAVE_DATA
|
||||||
|
IFLA_INFO_MAX = IFLA_INFO_SLAVE_DATA
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -87,7 +89,8 @@ const (
|
|||||||
const (
|
const (
|
||||||
IFLA_IPVLAN_UNSPEC = iota
|
IFLA_IPVLAN_UNSPEC = iota
|
||||||
IFLA_IPVLAN_MODE
|
IFLA_IPVLAN_MODE
|
||||||
IFLA_IPVLAN_MAX = IFLA_IPVLAN_MODE
|
IFLA_IPVLAN_FLAG
|
||||||
|
IFLA_IPVLAN_MAX = IFLA_IPVLAN_FLAG
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -164,6 +167,8 @@ const (
|
|||||||
IFLA_BOND_SLAVE_PERM_HWADDR
|
IFLA_BOND_SLAVE_PERM_HWADDR
|
||||||
IFLA_BOND_SLAVE_QUEUE_ID
|
IFLA_BOND_SLAVE_QUEUE_ID
|
||||||
IFLA_BOND_SLAVE_AD_AGGREGATOR_ID
|
IFLA_BOND_SLAVE_AD_AGGREGATOR_ID
|
||||||
|
IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE
|
||||||
|
IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -217,9 +222,11 @@ const (
|
|||||||
IFLA_VF_RSS_QUERY_EN /* RSS Redirection Table and Hash Key query
|
IFLA_VF_RSS_QUERY_EN /* RSS Redirection Table and Hash Key query
|
||||||
* on/off switch
|
* on/off switch
|
||||||
*/
|
*/
|
||||||
IFLA_VF_STATS /* network device statistics */
|
IFLA_VF_STATS /* network device statistics */
|
||||||
IFLA_VF_TRUST /* Trust state of VF */
|
IFLA_VF_TRUST /* Trust state of VF */
|
||||||
IFLA_VF_MAX = IFLA_VF_TRUST
|
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 (
|
const (
|
||||||
@ -248,6 +255,7 @@ const (
|
|||||||
SizeofVfLinkState = 0x08
|
SizeofVfLinkState = 0x08
|
||||||
SizeofVfRssQueryEn = 0x08
|
SizeofVfRssQueryEn = 0x08
|
||||||
SizeofVfTrust = 0x08
|
SizeofVfTrust = 0x08
|
||||||
|
SizeofVfGUID = 0x10
|
||||||
)
|
)
|
||||||
|
|
||||||
// struct ifla_vf_mac {
|
// struct ifla_vf_mac {
|
||||||
@ -430,6 +438,30 @@ func (msg *VfTrust) Serialize() []byte {
|
|||||||
return (*(*[SizeofVfTrust]byte)(unsafe.Pointer(msg)))[:]
|
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 (
|
const (
|
||||||
XDP_FLAGS_UPDATE_IF_NOEXIST = 1 << iota
|
XDP_FLAGS_UPDATE_IF_NOEXIST = 1 << iota
|
||||||
XDP_FLAGS_SKB_MODE
|
XDP_FLAGS_SKB_MODE
|
||||||
@ -546,3 +578,33 @@ const (
|
|||||||
GTP_ROLE_GGSN = iota
|
GTP_ROLE_GGSN = iota
|
||||||
GTP_ROLE_SGSN
|
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
|
||||||
|
)
|
||||||
|
66
vendor/github.com/vishvananda/netlink/nl/nl_linux.go
generated
vendored
66
vendor/github.com/vishvananda/netlink/nl/nl_linux.go
generated
vendored
@ -21,7 +21,13 @@ const (
|
|||||||
FAMILY_ALL = unix.AF_UNSPEC
|
FAMILY_ALL = unix.AF_UNSPEC
|
||||||
FAMILY_V4 = unix.AF_INET
|
FAMILY_V4 = unix.AF_INET
|
||||||
FAMILY_V6 = unix.AF_INET6
|
FAMILY_V6 = unix.AF_INET6
|
||||||
FAMILY_MPLS = AF_MPLS
|
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
|
// SupportedNlFamilies contains the list of netlink families this netlink package supports
|
||||||
@ -42,7 +48,7 @@ func GetIPFamily(ip net.IP) int {
|
|||||||
|
|
||||||
var nativeEndian binary.ByteOrder
|
var nativeEndian binary.ByteOrder
|
||||||
|
|
||||||
// Get native endianness for the system
|
// NativeEndian gets native endianness for the system
|
||||||
func NativeEndian() binary.ByteOrder {
|
func NativeEndian() binary.ByteOrder {
|
||||||
if nativeEndian == nil {
|
if nativeEndian == nil {
|
||||||
var x uint32 = 0x01020304
|
var x uint32 = 0x01020304
|
||||||
@ -271,15 +277,22 @@ func NewRtAttr(attrType int, data []byte) *RtAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new RtAttr obj anc add it as a child of an existing object
|
// 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 {
|
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)
|
attr := NewRtAttr(attrType, data)
|
||||||
parent.children = append(parent.children, attr)
|
a.children = append(a.children, attr)
|
||||||
return attr
|
return attr
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddChild adds an existing RtAttr as a child.
|
// AddChild adds an existing NetlinkRequestData as a child.
|
||||||
func (a *RtAttr) AddChild(attr *RtAttr) {
|
func (a *RtAttr) AddChild(attr NetlinkRequestData) {
|
||||||
a.children = append(a.children, attr)
|
a.children = append(a.children, attr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -360,16 +373,12 @@ func (req *NetlinkRequest) Serialize() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (req *NetlinkRequest) AddData(data NetlinkRequestData) {
|
func (req *NetlinkRequest) AddData(data NetlinkRequestData) {
|
||||||
if data != nil {
|
req.Data = append(req.Data, data)
|
||||||
req.Data = append(req.Data, data)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddRawData adds raw bytes to the end of the NetlinkRequest object during serialization
|
// AddRawData adds raw bytes to the end of the NetlinkRequest object during serialization
|
||||||
func (req *NetlinkRequest) AddRawData(data []byte) {
|
func (req *NetlinkRequest) AddRawData(data []byte) {
|
||||||
if data != nil {
|
req.RawData = append(req.RawData, data...)
|
||||||
req.RawData = append(req.RawData, data...)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the request against a the given sockType.
|
// Execute the request against a the given sockType.
|
||||||
@ -413,10 +422,13 @@ func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, erro
|
|||||||
|
|
||||||
done:
|
done:
|
||||||
for {
|
for {
|
||||||
msgs, err := s.Receive()
|
msgs, from, err := s.Receive()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if from.Pid != PidKernel {
|
||||||
|
return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, PidKernel)
|
||||||
|
}
|
||||||
for _, m := range msgs {
|
for _, m := range msgs {
|
||||||
if m.Header.Seq != req.Seq {
|
if m.Header.Seq != req.Seq {
|
||||||
if sharedSocket {
|
if sharedSocket {
|
||||||
@ -425,7 +437,7 @@ done:
|
|||||||
return nil, fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq)
|
return nil, fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq)
|
||||||
}
|
}
|
||||||
if m.Header.Pid != pid {
|
if m.Header.Pid != pid {
|
||||||
return nil, fmt.Errorf("Wrong pid %d, expected %d", m.Header.Pid, pid)
|
continue
|
||||||
}
|
}
|
||||||
if m.Header.Type == unix.NLMSG_DONE {
|
if m.Header.Type == unix.NLMSG_DONE {
|
||||||
break done
|
break done
|
||||||
@ -610,21 +622,31 @@ func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) {
|
func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, *unix.SockaddrNetlink, error) {
|
||||||
fd := int(atomic.LoadInt32(&s.fd))
|
fd := int(atomic.LoadInt32(&s.fd))
|
||||||
if fd < 0 {
|
if fd < 0 {
|
||||||
return nil, fmt.Errorf("Receive called on a closed socket")
|
return nil, nil, fmt.Errorf("Receive called on a closed socket")
|
||||||
}
|
}
|
||||||
rb := make([]byte, unix.Getpagesize())
|
var fromAddr *unix.SockaddrNetlink
|
||||||
nr, _, err := unix.Recvfrom(fd, rb, 0)
|
var rb [RECEIVE_BUFFER_SIZE]byte
|
||||||
|
nr, from, err := unix.Recvfrom(fd, rb[:], 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
if nr < unix.NLMSG_HDRLEN {
|
||||||
return nil, fmt.Errorf("Got short response from netlink")
|
return nil, nil, fmt.Errorf("Got short response from netlink")
|
||||||
}
|
}
|
||||||
rb = rb[:nr]
|
rb2 := make([]byte, nr)
|
||||||
return syscall.ParseNetlinkMessage(rb)
|
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
|
// SetSendTimeout allows to set a send timeout on the socket
|
||||||
|
35
vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go
generated
vendored
Normal file
35
vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package nl
|
||||||
|
|
||||||
|
const (
|
||||||
|
RDMA_NL_GET_CLIENT_SHIFT = 10
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
RDMA_NL_NLDEV = 5
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
RDMA_NLDEV_CMD_GET = 1
|
||||||
|
RDMA_NLDEV_CMD_SET = 2
|
||||||
|
RDMA_NLDEV_CMD_SYS_GET = 6
|
||||||
|
RDMA_NLDEV_CMD_SYS_SET = 7
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
RDMA_NLDEV_ATTR_DEV_INDEX = 1
|
||||||
|
RDMA_NLDEV_ATTR_DEV_NAME = 2
|
||||||
|
RDMA_NLDEV_ATTR_PORT_INDEX = 3
|
||||||
|
RDMA_NLDEV_ATTR_CAP_FLAGS = 4
|
||||||
|
RDMA_NLDEV_ATTR_FW_VERSION = 5
|
||||||
|
RDMA_NLDEV_ATTR_NODE_GUID = 6
|
||||||
|
RDMA_NLDEV_ATTR_SYS_IMAGE_GUID = 7
|
||||||
|
RDMA_NLDEV_ATTR_SUBNET_PREFIX = 8
|
||||||
|
RDMA_NLDEV_ATTR_LID = 9
|
||||||
|
RDMA_NLDEV_ATTR_SM_LID = 10
|
||||||
|
RDMA_NLDEV_ATTR_LMC = 11
|
||||||
|
RDMA_NLDEV_ATTR_PORT_STATE = 12
|
||||||
|
RDMA_NLDEV_ATTR_PORT_PHYS_STATE = 13
|
||||||
|
RDMA_NLDEV_ATTR_DEV_NODE_TYPE = 14
|
||||||
|
RDMA_NLDEV_SYS_ATTR_NETNS_MODE = 66
|
||||||
|
RDMA_NLDEV_NET_NS_FD = 68
|
||||||
|
)
|
26
vendor/github.com/vishvananda/netlink/nl/route_linux.go
generated
vendored
26
vendor/github.com/vishvananda/netlink/nl/route_linux.go
generated
vendored
@ -79,3 +79,29 @@ func (msg *RtNexthop) Serialize() []byte {
|
|||||||
}
|
}
|
||||||
return buf
|
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
|
||||||
|
}
|
||||||
|
43
vendor/github.com/vishvananda/netlink/nl/seg6_linux.go
generated
vendored
43
vendor/github.com/vishvananda/netlink/nl/seg6_linux.go
generated
vendored
@ -99,6 +99,49 @@ func DecodeSEG6Encap(buf []byte) (int, []net.IP, error) {
|
|||||||
return mode, srh.Segments, nil
|
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
|
// Helper functions
|
||||||
func SEG6EncapModeString(mode int) string {
|
func SEG6EncapModeString(mode int) string {
|
||||||
switch mode {
|
switch mode {
|
||||||
|
76
vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go
generated
vendored
Normal file
76
vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package nl
|
||||||
|
|
||||||
|
import ()
|
||||||
|
|
||||||
|
// seg6local parameters
|
||||||
|
const (
|
||||||
|
SEG6_LOCAL_UNSPEC = iota
|
||||||
|
SEG6_LOCAL_ACTION
|
||||||
|
SEG6_LOCAL_SRH
|
||||||
|
SEG6_LOCAL_TABLE
|
||||||
|
SEG6_LOCAL_NH4
|
||||||
|
SEG6_LOCAL_NH6
|
||||||
|
SEG6_LOCAL_IIF
|
||||||
|
SEG6_LOCAL_OIF
|
||||||
|
__SEG6_LOCAL_MAX
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
SEG6_LOCAL_MAX = __SEG6_LOCAL_MAX
|
||||||
|
)
|
||||||
|
|
||||||
|
// seg6local actions
|
||||||
|
const (
|
||||||
|
SEG6_LOCAL_ACTION_END = iota + 1 // 1
|
||||||
|
SEG6_LOCAL_ACTION_END_X // 2
|
||||||
|
SEG6_LOCAL_ACTION_END_T // 3
|
||||||
|
SEG6_LOCAL_ACTION_END_DX2 // 4
|
||||||
|
SEG6_LOCAL_ACTION_END_DX6 // 5
|
||||||
|
SEG6_LOCAL_ACTION_END_DX4 // 6
|
||||||
|
SEG6_LOCAL_ACTION_END_DT6 // 7
|
||||||
|
SEG6_LOCAL_ACTION_END_DT4 // 8
|
||||||
|
SEG6_LOCAL_ACTION_END_B6 // 9
|
||||||
|
SEG6_LOCAL_ACTION_END_B6_ENCAPS // 10
|
||||||
|
SEG6_LOCAL_ACTION_END_BM // 11
|
||||||
|
SEG6_LOCAL_ACTION_END_S // 12
|
||||||
|
SEG6_LOCAL_ACTION_END_AS // 13
|
||||||
|
SEG6_LOCAL_ACTION_END_AM // 14
|
||||||
|
__SEG6_LOCAL_ACTION_MAX
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
SEG6_LOCAL_ACTION_MAX = __SEG6_LOCAL_ACTION_MAX - 1
|
||||||
|
)
|
||||||
|
|
||||||
|
// Helper functions
|
||||||
|
func SEG6LocalActionString(action int) string {
|
||||||
|
switch action {
|
||||||
|
case SEG6_LOCAL_ACTION_END:
|
||||||
|
return "End"
|
||||||
|
case SEG6_LOCAL_ACTION_END_X:
|
||||||
|
return "End.X"
|
||||||
|
case SEG6_LOCAL_ACTION_END_T:
|
||||||
|
return "End.T"
|
||||||
|
case SEG6_LOCAL_ACTION_END_DX2:
|
||||||
|
return "End.DX2"
|
||||||
|
case SEG6_LOCAL_ACTION_END_DX6:
|
||||||
|
return "End.DX6"
|
||||||
|
case SEG6_LOCAL_ACTION_END_DX4:
|
||||||
|
return "End.DX4"
|
||||||
|
case SEG6_LOCAL_ACTION_END_DT6:
|
||||||
|
return "End.DT6"
|
||||||
|
case SEG6_LOCAL_ACTION_END_DT4:
|
||||||
|
return "End.DT4"
|
||||||
|
case SEG6_LOCAL_ACTION_END_B6:
|
||||||
|
return "End.B6"
|
||||||
|
case SEG6_LOCAL_ACTION_END_B6_ENCAPS:
|
||||||
|
return "End.B6.Encaps"
|
||||||
|
case SEG6_LOCAL_ACTION_END_BM:
|
||||||
|
return "End.BM"
|
||||||
|
case SEG6_LOCAL_ACTION_END_S:
|
||||||
|
return "End.S"
|
||||||
|
case SEG6_LOCAL_ACTION_END_AS:
|
||||||
|
return "End.AS"
|
||||||
|
case SEG6_LOCAL_ACTION_END_AM:
|
||||||
|
return "End.AM"
|
||||||
|
}
|
||||||
|
return "unknown"
|
||||||
|
}
|
11
vendor/github.com/vishvananda/netlink/nl/syscall.go
generated
vendored
11
vendor/github.com/vishvananda/netlink/nl/syscall.go
generated
vendored
@ -42,16 +42,6 @@ const (
|
|||||||
TCPDIAG_NOCOOKIE = 0xFFFFFFFF /* TCPDIAG_NOCOOKIE in net/ipv4/tcp_diag.h*/
|
TCPDIAG_NOCOOKIE = 0xFFFFFFFF /* TCPDIAG_NOCOOKIE in net/ipv4/tcp_diag.h*/
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
AF_MPLS = 28
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
RTA_NEWDST = 0x13
|
|
||||||
RTA_ENCAP_TYPE = 0x15
|
|
||||||
RTA_ENCAP = 0x16
|
|
||||||
)
|
|
||||||
|
|
||||||
// RTA_ENCAP subtype
|
// RTA_ENCAP subtype
|
||||||
const (
|
const (
|
||||||
MPLS_IPTUNNEL_UNSPEC = iota
|
MPLS_IPTUNNEL_UNSPEC = iota
|
||||||
@ -67,6 +57,7 @@ const (
|
|||||||
LWTUNNEL_ENCAP_IP6
|
LWTUNNEL_ENCAP_IP6
|
||||||
LWTUNNEL_ENCAP_SEG6
|
LWTUNNEL_ENCAP_SEG6
|
||||||
LWTUNNEL_ENCAP_BPF
|
LWTUNNEL_ENCAP_BPF
|
||||||
|
LWTUNNEL_ENCAP_SEG6_LOCAL
|
||||||
)
|
)
|
||||||
|
|
||||||
// routing header types
|
// routing header types
|
||||||
|
166
vendor/github.com/vishvananda/netlink/nl/tc_linux.go
generated
vendored
166
vendor/github.com/vishvananda/netlink/nl/tc_linux.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
package nl
|
package nl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -64,6 +65,15 @@ const (
|
|||||||
TCA_PRIO_MAX = 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 (
|
const (
|
||||||
SizeofTcMsg = 0x14
|
SizeofTcMsg = 0x14
|
||||||
SizeofTcActionMsg = 0x04
|
SizeofTcActionMsg = 0x04
|
||||||
@ -79,7 +89,10 @@ const (
|
|||||||
SizeofTcU32Key = 0x10
|
SizeofTcU32Key = 0x10
|
||||||
SizeofTcU32Sel = 0x10 // without keys
|
SizeofTcU32Sel = 0x10 // without keys
|
||||||
SizeofTcGen = 0x14
|
SizeofTcGen = 0x14
|
||||||
|
SizeofTcConnmark = SizeofTcGen + 0x04
|
||||||
SizeofTcMirred = SizeofTcGen + 0x08
|
SizeofTcMirred = SizeofTcGen + 0x08
|
||||||
|
SizeofTcTunnelKey = SizeofTcGen + 0x04
|
||||||
|
SizeofTcSkbEdit = SizeofTcGen
|
||||||
SizeofTcPolice = 2*SizeofTcRateSpec + 0x20
|
SizeofTcPolice = 2*SizeofTcRateSpec + 0x20
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -412,6 +425,57 @@ func (x *TcHtbGlob) Serialize() []byte {
|
|||||||
return (*(*[SizeofTcHtbGlob]byte)(unsafe.Pointer(x)))[:]
|
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 (
|
const (
|
||||||
TCA_U32_UNSPEC = iota
|
TCA_U32_UNSPEC = iota
|
||||||
TCA_U32_CLASSID
|
TCA_U32_CLASSID
|
||||||
@ -586,11 +650,47 @@ const (
|
|||||||
TCA_BPF_FD
|
TCA_BPF_FD
|
||||||
TCA_BPF_NAME
|
TCA_BPF_NAME
|
||||||
TCA_BPF_FLAGS
|
TCA_BPF_FLAGS
|
||||||
TCA_BPF_MAX = TCA_BPF_FLAGS
|
TCA_BPF_FLAGS_GEN
|
||||||
|
TCA_BPF_TAG
|
||||||
|
TCA_BPF_ID
|
||||||
|
TCA_BPF_MAX = TCA_BPF_ID
|
||||||
)
|
)
|
||||||
|
|
||||||
type TcBpf TcGen
|
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 (
|
const (
|
||||||
TCA_ACT_MIRRED = 8
|
TCA_ACT_MIRRED = 8
|
||||||
)
|
)
|
||||||
@ -626,6 +726,63 @@ func (x *TcMirred) Serialize() []byte {
|
|||||||
return (*(*[SizeofTcMirred]byte)(unsafe.Pointer(x)))[:]
|
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 {
|
// struct tc_police {
|
||||||
// __u32 index;
|
// __u32 index;
|
||||||
// int action;
|
// int action;
|
||||||
@ -708,3 +865,10 @@ const (
|
|||||||
TCA_FQ_CODEL_DROP_BATCH_SIZE
|
TCA_FQ_CODEL_DROP_BATCH_SIZE
|
||||||
TCA_FQ_CODEL_MEMORY_LIMIT
|
TCA_FQ_CODEL_MEMORY_LIMIT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TCA_HFSC_UNSPEC = iota
|
||||||
|
TCA_HFSC_RSC
|
||||||
|
TCA_HFSC_FSC
|
||||||
|
TCA_HFSC_USC
|
||||||
|
)
|
||||||
|
62
vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go
generated
vendored
62
vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go
generated
vendored
@ -50,34 +50,44 @@ const (
|
|||||||
// Attribute types
|
// Attribute types
|
||||||
const (
|
const (
|
||||||
/* Netlink message attributes. */
|
/* Netlink message attributes. */
|
||||||
XFRMA_UNSPEC = 0x00
|
XFRMA_UNSPEC = iota
|
||||||
XFRMA_ALG_AUTH = 0x01 /* struct xfrm_algo */
|
XFRMA_ALG_AUTH /* struct xfrm_algo */
|
||||||
XFRMA_ALG_CRYPT = 0x02 /* struct xfrm_algo */
|
XFRMA_ALG_CRYPT /* struct xfrm_algo */
|
||||||
XFRMA_ALG_COMP = 0x03 /* struct xfrm_algo */
|
XFRMA_ALG_COMP /* struct xfrm_algo */
|
||||||
XFRMA_ENCAP = 0x04 /* struct xfrm_algo + struct xfrm_encap_tmpl */
|
XFRMA_ENCAP /* struct xfrm_algo + struct xfrm_encap_tmpl */
|
||||||
XFRMA_TMPL = 0x05 /* 1 or more struct xfrm_user_tmpl */
|
XFRMA_TMPL /* 1 or more struct xfrm_user_tmpl */
|
||||||
XFRMA_SA = 0x06 /* struct xfrm_usersa_info */
|
XFRMA_SA /* struct xfrm_usersa_info */
|
||||||
XFRMA_POLICY = 0x07 /* struct xfrm_userpolicy_info */
|
XFRMA_POLICY /* struct xfrm_userpolicy_info */
|
||||||
XFRMA_SEC_CTX = 0x08 /* struct xfrm_sec_ctx */
|
XFRMA_SEC_CTX /* struct xfrm_sec_ctx */
|
||||||
XFRMA_LTIME_VAL = 0x09
|
XFRMA_LTIME_VAL
|
||||||
XFRMA_REPLAY_VAL = 0x0a
|
XFRMA_REPLAY_VAL
|
||||||
XFRMA_REPLAY_THRESH = 0x0b
|
XFRMA_REPLAY_THRESH
|
||||||
XFRMA_ETIMER_THRESH = 0x0c
|
XFRMA_ETIMER_THRESH
|
||||||
XFRMA_SRCADDR = 0x0d /* xfrm_address_t */
|
XFRMA_SRCADDR /* xfrm_address_t */
|
||||||
XFRMA_COADDR = 0x0e /* xfrm_address_t */
|
XFRMA_COADDR /* xfrm_address_t */
|
||||||
XFRMA_LASTUSED = 0x0f /* unsigned long */
|
XFRMA_LASTUSED /* unsigned long */
|
||||||
XFRMA_POLICY_TYPE = 0x10 /* struct xfrm_userpolicy_type */
|
XFRMA_POLICY_TYPE /* struct xfrm_userpolicy_type */
|
||||||
XFRMA_MIGRATE = 0x11
|
XFRMA_MIGRATE
|
||||||
XFRMA_ALG_AEAD = 0x12 /* struct xfrm_algo_aead */
|
XFRMA_ALG_AEAD /* struct xfrm_algo_aead */
|
||||||
XFRMA_KMADDRESS = 0x13 /* struct xfrm_user_kmaddress */
|
XFRMA_KMADDRESS /* struct xfrm_user_kmaddress */
|
||||||
XFRMA_ALG_AUTH_TRUNC = 0x14 /* struct xfrm_algo_auth */
|
XFRMA_ALG_AUTH_TRUNC /* struct xfrm_algo_auth */
|
||||||
XFRMA_MARK = 0x15 /* struct xfrm_mark */
|
XFRMA_MARK /* struct xfrm_mark */
|
||||||
XFRMA_TFCPAD = 0x16 /* __u32 */
|
XFRMA_TFCPAD /* __u32 */
|
||||||
XFRMA_REPLAY_ESN_VAL = 0x17 /* struct xfrm_replay_esn */
|
XFRMA_REPLAY_ESN_VAL /* struct xfrm_replay_esn */
|
||||||
XFRMA_SA_EXTRA_FLAGS = 0x18 /* __u32 */
|
XFRMA_SA_EXTRA_FLAGS /* __u32 */
|
||||||
XFRMA_MAX = 0x18
|
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 (
|
const (
|
||||||
SizeofXfrmAddress = 0x10
|
SizeofXfrmAddress = 0x10
|
||||||
SizeofXfrmSelector = 0x38
|
SizeofXfrmSelector = 0x38
|
||||||
|
4
vendor/github.com/vishvananda/netlink/protinfo.go
generated
vendored
4
vendor/github.com/vishvananda/netlink/protinfo.go
generated
vendored
@ -18,6 +18,10 @@ type Protinfo struct {
|
|||||||
|
|
||||||
// String returns a list of enabled flags
|
// String returns a list of enabled flags
|
||||||
func (prot *Protinfo) String() string {
|
func (prot *Protinfo) String() string {
|
||||||
|
if prot == nil {
|
||||||
|
return "<nil>"
|
||||||
|
}
|
||||||
|
|
||||||
var boolStrings []string
|
var boolStrings []string
|
||||||
if prot.Hairpin {
|
if prot.Hairpin {
|
||||||
boolStrings = append(boolStrings, "Hairpin")
|
boolStrings = append(boolStrings, "Hairpin")
|
||||||
|
7
vendor/github.com/vishvananda/netlink/protinfo_linux.go
generated
vendored
7
vendor/github.com/vishvananda/netlink/protinfo_linux.go
generated
vendored
@ -41,7 +41,7 @@ func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return pi, err
|
return pi, err
|
||||||
}
|
}
|
||||||
pi = *parseProtinfo(infos)
|
pi = parseProtinfo(infos)
|
||||||
|
|
||||||
return pi, nil
|
return pi, nil
|
||||||
}
|
}
|
||||||
@ -49,8 +49,7 @@ func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) {
|
|||||||
return pi, fmt.Errorf("Device with index %d not found", base.Index)
|
return pi, fmt.Errorf("Device with index %d not found", base.Index)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseProtinfo(infos []syscall.NetlinkRouteAttr) *Protinfo {
|
func parseProtinfo(infos []syscall.NetlinkRouteAttr) (pi Protinfo) {
|
||||||
var pi Protinfo
|
|
||||||
for _, info := range infos {
|
for _, info := range infos {
|
||||||
switch info.Attr.Type {
|
switch info.Attr.Type {
|
||||||
case nl.IFLA_BRPORT_MODE:
|
case nl.IFLA_BRPORT_MODE:
|
||||||
@ -71,5 +70,5 @@ func parseProtinfo(infos []syscall.NetlinkRouteAttr) *Protinfo {
|
|||||||
pi.ProxyArpWiFi = byteToBool(info.Value[0])
|
pi.ProxyArpWiFi = byteToBool(info.Value[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &pi
|
return
|
||||||
}
|
}
|
||||||
|
48
vendor/github.com/vishvananda/netlink/qdisc.go
generated
vendored
48
vendor/github.com/vishvananda/netlink/qdisc.go
generated
vendored
@ -176,6 +176,13 @@ type Netem struct {
|
|||||||
CorruptCorr 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 {
|
func (qdisc *Netem) Attrs() *QdiscAttrs {
|
||||||
return &qdisc.QdiscAttrs
|
return &qdisc.QdiscAttrs
|
||||||
}
|
}
|
||||||
@ -231,6 +238,33 @@ func (qdisc *GenericQdisc) Type() string {
|
|||||||
return qdisc.QdiscType
|
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.
|
// Fq is a classless packet scheduler meant to be mostly used for locally generated traffic.
|
||||||
type Fq struct {
|
type Fq struct {
|
||||||
QdiscAttrs
|
QdiscAttrs
|
||||||
@ -249,6 +283,13 @@ type Fq struct {
|
|||||||
LowRateThreshold 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 {
|
func NewFq(attrs QdiscAttrs) *Fq {
|
||||||
return &Fq{
|
return &Fq{
|
||||||
QdiscAttrs: attrs,
|
QdiscAttrs: attrs,
|
||||||
@ -276,6 +317,13 @@ type FqCodel struct {
|
|||||||
// There are some more attributes here, but support for them seems not ubiquitous
|
// 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 {
|
func NewFqCodel(attrs QdiscAttrs) *FqCodel {
|
||||||
return &FqCodel{
|
return &FqCodel{
|
||||||
QdiscAttrs: attrs,
|
QdiscAttrs: attrs,
|
||||||
|
69
vendor/github.com/vishvananda/netlink/qdisc_linux.go
generated
vendored
69
vendor/github.com/vishvananda/netlink/qdisc_linux.go
generated
vendored
@ -175,15 +175,15 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
|
|||||||
opt.Peakrate.Rate = uint32(qdisc.Peakrate)
|
opt.Peakrate.Rate = uint32(qdisc.Peakrate)
|
||||||
opt.Limit = qdisc.Limit
|
opt.Limit = qdisc.Limit
|
||||||
opt.Buffer = qdisc.Buffer
|
opt.Buffer = qdisc.Buffer
|
||||||
nl.NewRtAttrChild(options, nl.TCA_TBF_PARMS, opt.Serialize())
|
options.AddRtAttr(nl.TCA_TBF_PARMS, opt.Serialize())
|
||||||
if qdisc.Rate >= uint64(1<<32) {
|
if qdisc.Rate >= uint64(1<<32) {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_TBF_RATE64, nl.Uint64Attr(qdisc.Rate))
|
options.AddRtAttr(nl.TCA_TBF_RATE64, nl.Uint64Attr(qdisc.Rate))
|
||||||
}
|
}
|
||||||
if qdisc.Peakrate >= uint64(1<<32) {
|
if qdisc.Peakrate >= uint64(1<<32) {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_TBF_PRATE64, nl.Uint64Attr(qdisc.Peakrate))
|
options.AddRtAttr(nl.TCA_TBF_PRATE64, nl.Uint64Attr(qdisc.Peakrate))
|
||||||
}
|
}
|
||||||
if qdisc.Peakrate > 0 {
|
if qdisc.Peakrate > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_TBF_PBURST, nl.Uint32Attr(qdisc.Minburst))
|
options.AddRtAttr(nl.TCA_TBF_PBURST, nl.Uint32Attr(qdisc.Minburst))
|
||||||
}
|
}
|
||||||
case *Htb:
|
case *Htb:
|
||||||
opt := nl.TcHtbGlob{}
|
opt := nl.TcHtbGlob{}
|
||||||
@ -193,8 +193,12 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
|
|||||||
// TODO: Handle Debug properly. For now default to 0
|
// TODO: Handle Debug properly. For now default to 0
|
||||||
opt.Debug = qdisc.Debug
|
opt.Debug = qdisc.Debug
|
||||||
opt.DirectPkts = qdisc.DirectPkts
|
opt.DirectPkts = qdisc.DirectPkts
|
||||||
nl.NewRtAttrChild(options, nl.TCA_HTB_INIT, opt.Serialize())
|
options.AddRtAttr(nl.TCA_HTB_INIT, opt.Serialize())
|
||||||
// nl.NewRtAttrChild(options, nl.TCA_HTB_DIRECT_QLEN, 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:
|
case *Netem:
|
||||||
opt := nl.TcNetemQopt{}
|
opt := nl.TcNetemQopt{}
|
||||||
opt.Latency = qdisc.Latency
|
opt.Latency = qdisc.Latency
|
||||||
@ -211,21 +215,21 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
|
|||||||
corr.DupCorr = qdisc.DuplicateCorr
|
corr.DupCorr = qdisc.DuplicateCorr
|
||||||
|
|
||||||
if corr.DelayCorr > 0 || corr.LossCorr > 0 || corr.DupCorr > 0 {
|
if corr.DelayCorr > 0 || corr.LossCorr > 0 || corr.DupCorr > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_NETEM_CORR, corr.Serialize())
|
options.AddRtAttr(nl.TCA_NETEM_CORR, corr.Serialize())
|
||||||
}
|
}
|
||||||
// Corruption
|
// Corruption
|
||||||
corruption := nl.TcNetemCorrupt{}
|
corruption := nl.TcNetemCorrupt{}
|
||||||
corruption.Probability = qdisc.CorruptProb
|
corruption.Probability = qdisc.CorruptProb
|
||||||
corruption.Correlation = qdisc.CorruptCorr
|
corruption.Correlation = qdisc.CorruptCorr
|
||||||
if corruption.Probability > 0 {
|
if corruption.Probability > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_NETEM_CORRUPT, corruption.Serialize())
|
options.AddRtAttr(nl.TCA_NETEM_CORRUPT, corruption.Serialize())
|
||||||
}
|
}
|
||||||
// Reorder
|
// Reorder
|
||||||
reorder := nl.TcNetemReorder{}
|
reorder := nl.TcNetemReorder{}
|
||||||
reorder.Probability = qdisc.ReorderProb
|
reorder.Probability = qdisc.ReorderProb
|
||||||
reorder.Correlation = qdisc.ReorderCorr
|
reorder.Correlation = qdisc.ReorderCorr
|
||||||
if reorder.Probability > 0 {
|
if reorder.Probability > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_NETEM_REORDER, reorder.Serialize())
|
options.AddRtAttr(nl.TCA_NETEM_REORDER, reorder.Serialize())
|
||||||
}
|
}
|
||||||
case *Ingress:
|
case *Ingress:
|
||||||
// ingress filters must use the proper handle
|
// ingress filters must use the proper handle
|
||||||
@ -233,50 +237,54 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
|
|||||||
return fmt.Errorf("Ingress filters must set Parent to HANDLE_INGRESS")
|
return fmt.Errorf("Ingress filters must set Parent to HANDLE_INGRESS")
|
||||||
}
|
}
|
||||||
case *FqCodel:
|
case *FqCodel:
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FQ_CODEL_ECN, nl.Uint32Attr((uint32(qdisc.ECN))))
|
options.AddRtAttr(nl.TCA_FQ_CODEL_ECN, nl.Uint32Attr((uint32(qdisc.ECN))))
|
||||||
if qdisc.Limit > 0 {
|
if qdisc.Limit > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FQ_CODEL_LIMIT, nl.Uint32Attr((uint32(qdisc.Limit))))
|
options.AddRtAttr(nl.TCA_FQ_CODEL_LIMIT, nl.Uint32Attr((uint32(qdisc.Limit))))
|
||||||
}
|
}
|
||||||
if qdisc.Interval > 0 {
|
if qdisc.Interval > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FQ_CODEL_INTERVAL, nl.Uint32Attr((uint32(qdisc.Interval))))
|
options.AddRtAttr(nl.TCA_FQ_CODEL_INTERVAL, nl.Uint32Attr((uint32(qdisc.Interval))))
|
||||||
}
|
}
|
||||||
if qdisc.Flows > 0 {
|
if qdisc.Flows > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FQ_CODEL_FLOWS, nl.Uint32Attr((uint32(qdisc.Flows))))
|
options.AddRtAttr(nl.TCA_FQ_CODEL_FLOWS, nl.Uint32Attr((uint32(qdisc.Flows))))
|
||||||
}
|
}
|
||||||
if qdisc.Quantum > 0 {
|
if qdisc.Quantum > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FQ_CODEL_QUANTUM, nl.Uint32Attr((uint32(qdisc.Quantum))))
|
options.AddRtAttr(nl.TCA_FQ_CODEL_QUANTUM, nl.Uint32Attr((uint32(qdisc.Quantum))))
|
||||||
}
|
}
|
||||||
|
|
||||||
case *Fq:
|
case *Fq:
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FQ_RATE_ENABLE, nl.Uint32Attr((uint32(qdisc.Pacing))))
|
options.AddRtAttr(nl.TCA_FQ_RATE_ENABLE, nl.Uint32Attr((uint32(qdisc.Pacing))))
|
||||||
|
|
||||||
if qdisc.Buckets > 0 {
|
if qdisc.Buckets > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FQ_BUCKETS_LOG, nl.Uint32Attr((uint32(qdisc.Buckets))))
|
options.AddRtAttr(nl.TCA_FQ_BUCKETS_LOG, nl.Uint32Attr((uint32(qdisc.Buckets))))
|
||||||
}
|
}
|
||||||
if qdisc.LowRateThreshold > 0 {
|
if qdisc.LowRateThreshold > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FQ_LOW_RATE_THRESHOLD, nl.Uint32Attr((uint32(qdisc.LowRateThreshold))))
|
options.AddRtAttr(nl.TCA_FQ_LOW_RATE_THRESHOLD, nl.Uint32Attr((uint32(qdisc.LowRateThreshold))))
|
||||||
}
|
}
|
||||||
if qdisc.Quantum > 0 {
|
if qdisc.Quantum > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FQ_QUANTUM, nl.Uint32Attr((uint32(qdisc.Quantum))))
|
options.AddRtAttr(nl.TCA_FQ_QUANTUM, nl.Uint32Attr((uint32(qdisc.Quantum))))
|
||||||
}
|
}
|
||||||
if qdisc.InitialQuantum > 0 {
|
if qdisc.InitialQuantum > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FQ_INITIAL_QUANTUM, nl.Uint32Attr((uint32(qdisc.InitialQuantum))))
|
options.AddRtAttr(nl.TCA_FQ_INITIAL_QUANTUM, nl.Uint32Attr((uint32(qdisc.InitialQuantum))))
|
||||||
}
|
}
|
||||||
if qdisc.FlowRefillDelay > 0 {
|
if qdisc.FlowRefillDelay > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FQ_FLOW_REFILL_DELAY, nl.Uint32Attr((uint32(qdisc.FlowRefillDelay))))
|
options.AddRtAttr(nl.TCA_FQ_FLOW_REFILL_DELAY, nl.Uint32Attr((uint32(qdisc.FlowRefillDelay))))
|
||||||
}
|
}
|
||||||
if qdisc.FlowPacketLimit > 0 {
|
if qdisc.FlowPacketLimit > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FQ_FLOW_PLIMIT, nl.Uint32Attr((uint32(qdisc.FlowPacketLimit))))
|
options.AddRtAttr(nl.TCA_FQ_FLOW_PLIMIT, nl.Uint32Attr((uint32(qdisc.FlowPacketLimit))))
|
||||||
}
|
}
|
||||||
if qdisc.FlowMaxRate > 0 {
|
if qdisc.FlowMaxRate > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FQ_FLOW_MAX_RATE, nl.Uint32Attr((uint32(qdisc.FlowMaxRate))))
|
options.AddRtAttr(nl.TCA_FQ_FLOW_MAX_RATE, nl.Uint32Attr((uint32(qdisc.FlowMaxRate))))
|
||||||
}
|
}
|
||||||
if qdisc.FlowDefaultRate > 0 {
|
if qdisc.FlowDefaultRate > 0 {
|
||||||
nl.NewRtAttrChild(options, nl.TCA_FQ_FLOW_DEFAULT_RATE, nl.Uint32Attr((uint32(qdisc.FlowDefaultRate))))
|
options.AddRtAttr(nl.TCA_FQ_FLOW_DEFAULT_RATE, nl.Uint32Attr((uint32(qdisc.FlowDefaultRate))))
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
options = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
req.AddData(options)
|
if options != nil {
|
||||||
|
req.AddData(options)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,6 +356,8 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
|
|||||||
qdisc = &Htb{}
|
qdisc = &Htb{}
|
||||||
case "fq":
|
case "fq":
|
||||||
qdisc = &Fq{}
|
qdisc = &Fq{}
|
||||||
|
case "hfsc":
|
||||||
|
qdisc = &Hfsc{}
|
||||||
case "fq_codel":
|
case "fq_codel":
|
||||||
qdisc = &FqCodel{}
|
qdisc = &FqCodel{}
|
||||||
case "netem":
|
case "netem":
|
||||||
@ -375,6 +385,10 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) {
|
|||||||
if err := parseTbfData(qdisc, data); err != nil {
|
if err := parseTbfData(qdisc, data); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
case "hfsc":
|
||||||
|
if err := parseHfscData(qdisc, attr.Value); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
case "htb":
|
case "htb":
|
||||||
data, err := nl.ParseRouteAttr(attr.Value)
|
data, err := nl.ParseRouteAttr(attr.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -474,6 +488,13 @@ func parseFqCodelData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
|
|||||||
return nil
|
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 {
|
func parseFqData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
|
||||||
native = nl.NativeEndian()
|
native = nl.NativeEndian()
|
||||||
fq := qdisc.(*Fq)
|
fq := qdisc.(*Fq)
|
||||||
|
264
vendor/github.com/vishvananda/netlink/rdma_link_linux.go
generated
vendored
Normal file
264
vendor/github.com/vishvananda/netlink/rdma_link_linux.go
generated
vendored
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
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)
|
||||||
|
}
|
2
vendor/github.com/vishvananda/netlink/route.go
generated
vendored
2
vendor/github.com/vishvananda/netlink/route.go
generated
vendored
@ -47,6 +47,7 @@ type Route struct {
|
|||||||
Encap Encap
|
Encap Encap
|
||||||
MTU int
|
MTU int
|
||||||
AdvMSS int
|
AdvMSS int
|
||||||
|
Hoplimit int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Route) String() string {
|
func (r Route) String() string {
|
||||||
@ -89,6 +90,7 @@ func (r Route) Equal(x Route) bool {
|
|||||||
r.Table == x.Table &&
|
r.Table == x.Table &&
|
||||||
r.Type == x.Type &&
|
r.Type == x.Type &&
|
||||||
r.Tos == x.Tos &&
|
r.Tos == x.Tos &&
|
||||||
|
r.Hoplimit == x.Hoplimit &&
|
||||||
r.Flags == x.Flags &&
|
r.Flags == x.Flags &&
|
||||||
(r.MPLSDst == x.MPLSDst || (r.MPLSDst != nil && x.MPLSDst != nil && *r.MPLSDst == *x.MPLSDst)) &&
|
(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.NewDst == x.NewDst || (r.NewDst != nil && r.NewDst.Equal(x.NewDst))) &&
|
||||||
|
229
vendor/github.com/vishvananda/netlink/route_linux.go
generated
vendored
229
vendor/github.com/vishvananda/netlink/route_linux.go
generated
vendored
@ -32,6 +32,7 @@ const (
|
|||||||
RT_FILTER_SRC
|
RT_FILTER_SRC
|
||||||
RT_FILTER_GW
|
RT_FILTER_GW
|
||||||
RT_FILTER_TABLE
|
RT_FILTER_TABLE
|
||||||
|
RT_FILTER_HOPLIMIT
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -207,6 +208,7 @@ func (e *SEG6Encap) Decode(buf []byte) error {
|
|||||||
}
|
}
|
||||||
buf = buf[:l] // make sure buf size upper limit is Length
|
buf = buf[:l] // make sure buf size upper limit is Length
|
||||||
typ := native.Uint16(buf[2:])
|
typ := native.Uint16(buf[2:])
|
||||||
|
// LWTUNNEL_ENCAP_SEG6 has only one attr type SEG6_IPTUNNEL_SRH
|
||||||
if typ != nl.SEG6_IPTUNNEL_SRH {
|
if typ != nl.SEG6_IPTUNNEL_SRH {
|
||||||
return fmt.Errorf("unknown SEG6 Type: %d", typ)
|
return fmt.Errorf("unknown SEG6 Type: %d", typ)
|
||||||
}
|
}
|
||||||
@ -259,6 +261,188 @@ func (e *SEG6Encap) Equal(x Encap) bool {
|
|||||||
return true
|
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.
|
// RouteAdd will add a route to the system.
|
||||||
// Equivalent to: `ip route add $route`
|
// Equivalent to: `ip route add $route`
|
||||||
func RouteAdd(route *Route) error {
|
func RouteAdd(route *Route) error {
|
||||||
@ -335,18 +519,18 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_NEWDST, buf))
|
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_NEWDST, buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
if route.Encap != nil {
|
if route.Encap != nil {
|
||||||
buf := make([]byte, 2)
|
buf := make([]byte, 2)
|
||||||
native.PutUint16(buf, uint16(route.Encap.Type()))
|
native.PutUint16(buf, uint16(route.Encap.Type()))
|
||||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_ENCAP_TYPE, buf))
|
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP_TYPE, buf))
|
||||||
buf, err := route.Encap.Encode()
|
buf, err := route.Encap.Encode()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_ENCAP, buf))
|
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP, buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
if route.Src != nil {
|
if route.Src != nil {
|
||||||
@ -410,17 +594,17 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
children = append(children, nl.NewRtAttr(nl.RTA_NEWDST, buf))
|
children = append(children, nl.NewRtAttr(unix.RTA_NEWDST, buf))
|
||||||
}
|
}
|
||||||
if nh.Encap != nil {
|
if nh.Encap != nil {
|
||||||
buf := make([]byte, 2)
|
buf := make([]byte, 2)
|
||||||
native.PutUint16(buf, uint16(nh.Encap.Type()))
|
native.PutUint16(buf, uint16(nh.Encap.Type()))
|
||||||
rtAttrs = append(rtAttrs, nl.NewRtAttr(nl.RTA_ENCAP_TYPE, buf))
|
children = append(children, nl.NewRtAttr(unix.RTA_ENCAP_TYPE, buf))
|
||||||
buf, err := nh.Encap.Encode()
|
buf, err := nh.Encap.Encode()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
children = append(children, nl.NewRtAttr(nl.RTA_ENCAP, buf))
|
children = append(children, nl.NewRtAttr(unix.RTA_ENCAP, buf))
|
||||||
}
|
}
|
||||||
rtnh.Children = children
|
rtnh.Children = children
|
||||||
buf = append(buf, rtnh.Serialize()...)
|
buf = append(buf, rtnh.Serialize()...)
|
||||||
@ -464,6 +648,10 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
|
|||||||
b := nl.Uint32Attr(uint32(route.AdvMSS))
|
b := nl.Uint32Attr(uint32(route.AdvMSS))
|
||||||
metrics = append(metrics, nl.NewRtAttr(unix.RTAX_ADVMSS, b))
|
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 {
|
if metrics != nil {
|
||||||
attr := nl.NewRtAttr(unix.RTA_METRICS, nil)
|
attr := nl.NewRtAttr(unix.RTA_METRICS, nil)
|
||||||
@ -574,6 +762,8 @@ func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64)
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case filterMask&RT_FILTER_HOPLIMIT != 0 && route.Hoplimit != filter.Hoplimit:
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res = append(res, route)
|
res = append(res, route)
|
||||||
@ -649,7 +839,7 @@ func deserializeRoute(m []byte) (Route, error) {
|
|||||||
switch attr.Attr.Type {
|
switch attr.Attr.Type {
|
||||||
case unix.RTA_GATEWAY:
|
case unix.RTA_GATEWAY:
|
||||||
info.Gw = net.IP(attr.Value)
|
info.Gw = net.IP(attr.Value)
|
||||||
case nl.RTA_NEWDST:
|
case unix.RTA_NEWDST:
|
||||||
var d Destination
|
var d Destination
|
||||||
switch msg.Family {
|
switch msg.Family {
|
||||||
case nl.FAMILY_MPLS:
|
case nl.FAMILY_MPLS:
|
||||||
@ -659,9 +849,9 @@ func deserializeRoute(m []byte) (Route, error) {
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
info.NewDst = d
|
info.NewDst = d
|
||||||
case nl.RTA_ENCAP_TYPE:
|
case unix.RTA_ENCAP_TYPE:
|
||||||
encapType = attr
|
encapType = attr
|
||||||
case nl.RTA_ENCAP:
|
case unix.RTA_ENCAP:
|
||||||
encap = attr
|
encap = attr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -690,7 +880,7 @@ func deserializeRoute(m []byte) (Route, error) {
|
|||||||
route.MultiPath = append(route.MultiPath, info)
|
route.MultiPath = append(route.MultiPath, info)
|
||||||
rest = buf
|
rest = buf
|
||||||
}
|
}
|
||||||
case nl.RTA_NEWDST:
|
case unix.RTA_NEWDST:
|
||||||
var d Destination
|
var d Destination
|
||||||
switch msg.Family {
|
switch msg.Family {
|
||||||
case nl.FAMILY_MPLS:
|
case nl.FAMILY_MPLS:
|
||||||
@ -700,9 +890,9 @@ func deserializeRoute(m []byte) (Route, error) {
|
|||||||
return route, err
|
return route, err
|
||||||
}
|
}
|
||||||
route.NewDst = d
|
route.NewDst = d
|
||||||
case nl.RTA_ENCAP_TYPE:
|
case unix.RTA_ENCAP_TYPE:
|
||||||
encapType = attr
|
encapType = attr
|
||||||
case nl.RTA_ENCAP:
|
case unix.RTA_ENCAP:
|
||||||
encap = attr
|
encap = attr
|
||||||
case unix.RTA_METRICS:
|
case unix.RTA_METRICS:
|
||||||
metrics, err := nl.ParseRouteAttr(attr.Value)
|
metrics, err := nl.ParseRouteAttr(attr.Value)
|
||||||
@ -715,6 +905,8 @@ func deserializeRoute(m []byte) (Route, error) {
|
|||||||
route.MTU = int(native.Uint32(metric.Value[0:4]))
|
route.MTU = int(native.Uint32(metric.Value[0:4]))
|
||||||
case unix.RTAX_ADVMSS:
|
case unix.RTAX_ADVMSS:
|
||||||
route.AdvMSS = int(native.Uint32(metric.Value[0:4]))
|
route.AdvMSS = int(native.Uint32(metric.Value[0:4]))
|
||||||
|
case unix.RTAX_HOPLIMIT:
|
||||||
|
route.Hoplimit = int(native.Uint32(metric.Value[0:4]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -734,6 +926,11 @@ func deserializeRoute(m []byte) (Route, error) {
|
|||||||
if err := e.Decode(encap.Value); err != nil {
|
if err := e.Decode(encap.Value); err != nil {
|
||||||
return route, err
|
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
|
route.Encap = e
|
||||||
}
|
}
|
||||||
@ -840,13 +1037,19 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <
|
|||||||
go func() {
|
go func() {
|
||||||
defer close(ch)
|
defer close(ch)
|
||||||
for {
|
for {
|
||||||
msgs, err := s.Receive()
|
msgs, from, err := s.Receive()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if cberr != nil {
|
if cberr != nil {
|
||||||
cberr(err)
|
cberr(err)
|
||||||
}
|
}
|
||||||
return
|
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 {
|
for _, m := range msgs {
|
||||||
if m.Header.Type == unix.NLMSG_DONE {
|
if m.Header.Type == unix.NLMSG_DONE {
|
||||||
continue
|
continue
|
||||||
|
2
vendor/github.com/vishvananda/netlink/rule_linux.go
generated
vendored
2
vendor/github.com/vishvananda/netlink/rule_linux.go
generated
vendored
@ -144,7 +144,7 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
|
|||||||
req.AddData(nl.NewRtAttr(nl.FRA_OIFNAME, []byte(rule.OifName)))
|
req.AddData(nl.NewRtAttr(nl.FRA_OIFNAME, []byte(rule.OifName)))
|
||||||
}
|
}
|
||||||
if rule.Goto >= 0 {
|
if rule.Goto >= 0 {
|
||||||
msg.Type = nl.FR_ACT_NOP
|
msg.Type = nl.FR_ACT_GOTO
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
native.PutUint32(b, uint32(rule.Goto))
|
native.PutUint32(b, uint32(rule.Goto))
|
||||||
req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b))
|
req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b))
|
||||||
|
5
vendor/github.com/vishvananda/netlink/socket_linux.go
generated
vendored
5
vendor/github.com/vishvananda/netlink/socket_linux.go
generated
vendored
@ -141,10 +141,13 @@ func SocketGet(local, remote net.Addr) (*Socket, error) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
s.Send(req)
|
s.Send(req)
|
||||||
msgs, err := s.Receive()
|
msgs, from, err := s.Receive()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
if len(msgs) == 0 {
|
||||||
return nil, errors.New("no message nor error from netlink")
|
return nil, errors.New("no message nor error from netlink")
|
||||||
}
|
}
|
||||||
|
6
vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go
generated
vendored
6
vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go
generated
vendored
@ -54,11 +54,15 @@ func XfrmMonitor(ch chan<- XfrmMsg, done <-chan struct{}, errorChan chan<- error
|
|||||||
go func() {
|
go func() {
|
||||||
defer close(ch)
|
defer close(ch)
|
||||||
for {
|
for {
|
||||||
msgs, err := s.Receive()
|
msgs, from, err := s.Receive()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorChan <- err
|
errorChan <- err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if from.Pid != nl.PidKernel {
|
||||||
|
errorChan <- fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
|
||||||
|
return
|
||||||
|
}
|
||||||
for _, m := range msgs {
|
for _, m := range msgs {
|
||||||
switch m.Header.Type {
|
switch m.Header.Type {
|
||||||
case nl.XFRM_MSG_EXPIRE:
|
case nl.XFRM_MSG_EXPIRE:
|
||||||
|
26
vendor/github.com/vishvananda/netlink/xfrm_policy.go
generated
vendored
26
vendor/github.com/vishvananda/netlink/xfrm_policy.go
generated
vendored
@ -35,6 +35,25 @@ func (d Dir) String() string {
|
|||||||
return fmt.Sprintf("socket %d", d-XFRM_SOCKET_IN)
|
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
|
// XfrmPolicyTmpl encapsulates a rule for the base addresses of an ipsec
|
||||||
// policy. These rules are matched with XfrmState to determine encryption
|
// policy. These rules are matched with XfrmState to determine encryption
|
||||||
// and authentication algorithms.
|
// and authentication algorithms.
|
||||||
@ -64,11 +83,14 @@ type XfrmPolicy struct {
|
|||||||
Dir Dir
|
Dir Dir
|
||||||
Priority int
|
Priority int
|
||||||
Index int
|
Index int
|
||||||
|
Action PolicyAction
|
||||||
|
Ifindex int
|
||||||
|
Ifid int
|
||||||
Mark *XfrmMark
|
Mark *XfrmMark
|
||||||
Tmpls []XfrmPolicyTmpl
|
Tmpls []XfrmPolicyTmpl
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p XfrmPolicy) String() string {
|
func (p XfrmPolicy) String() string {
|
||||||
return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, DstPort: %d, SrcPort: %d, Dir: %s, Priority: %d, Index: %d, Mark: %s, Tmpls: %s}",
|
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.Mark, p.Tmpls)
|
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)
|
||||||
}
|
}
|
||||||
|
19
vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
generated
vendored
19
vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
generated
vendored
@ -27,6 +27,7 @@ func selFromPolicy(sel *nl.XfrmSelector, policy *XfrmPolicy) {
|
|||||||
if sel.Sport != 0 {
|
if sel.Sport != 0 {
|
||||||
sel.SportMask = ^uint16(0)
|
sel.SportMask = ^uint16(0)
|
||||||
}
|
}
|
||||||
|
sel.Ifindex = int32(policy.Ifindex)
|
||||||
}
|
}
|
||||||
|
|
||||||
// XfrmPolicyAdd will add an xfrm policy to the system.
|
// XfrmPolicyAdd will add an xfrm policy to the system.
|
||||||
@ -61,6 +62,7 @@ func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
|
|||||||
msg.Priority = uint32(policy.Priority)
|
msg.Priority = uint32(policy.Priority)
|
||||||
msg.Index = uint32(policy.Index)
|
msg.Index = uint32(policy.Index)
|
||||||
msg.Dir = uint8(policy.Dir)
|
msg.Dir = uint8(policy.Dir)
|
||||||
|
msg.Action = uint8(policy.Action)
|
||||||
msg.Lft.SoftByteLimit = nl.XFRM_INF
|
msg.Lft.SoftByteLimit = nl.XFRM_INF
|
||||||
msg.Lft.HardByteLimit = nl.XFRM_INF
|
msg.Lft.HardByteLimit = nl.XFRM_INF
|
||||||
msg.Lft.SoftPacketLimit = nl.XFRM_INF
|
msg.Lft.SoftPacketLimit = nl.XFRM_INF
|
||||||
@ -90,6 +92,9 @@ func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
|
|||||||
req.AddData(out)
|
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)
|
_, err := req.Execute(unix.NETLINK_XFRM, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -183,6 +188,9 @@ func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPo
|
|||||||
req.AddData(out)
|
req.AddData(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(policy.Ifid)))
|
||||||
|
req.AddData(ifId)
|
||||||
|
|
||||||
resType := nl.XFRM_MSG_NEWPOLICY
|
resType := nl.XFRM_MSG_NEWPOLICY
|
||||||
if nlProto == nl.XFRM_MSG_DELPOLICY {
|
if nlProto == nl.XFRM_MSG_DELPOLICY {
|
||||||
resType = 0
|
resType = 0
|
||||||
@ -197,12 +205,7 @@ func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPo
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := parseXfrmPolicy(msgs[0], FAMILY_ALL)
|
return parseXfrmPolicy(msgs[0], FAMILY_ALL)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return p, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
|
func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
|
||||||
@ -220,9 +223,11 @@ func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
|
|||||||
policy.Proto = Proto(msg.Sel.Proto)
|
policy.Proto = Proto(msg.Sel.Proto)
|
||||||
policy.DstPort = int(nl.Swap16(msg.Sel.Dport))
|
policy.DstPort = int(nl.Swap16(msg.Sel.Dport))
|
||||||
policy.SrcPort = int(nl.Swap16(msg.Sel.Sport))
|
policy.SrcPort = int(nl.Swap16(msg.Sel.Sport))
|
||||||
|
policy.Ifindex = int(msg.Sel.Ifindex)
|
||||||
policy.Priority = int(msg.Priority)
|
policy.Priority = int(msg.Priority)
|
||||||
policy.Index = int(msg.Index)
|
policy.Index = int(msg.Index)
|
||||||
policy.Dir = Dir(msg.Dir)
|
policy.Dir = Dir(msg.Dir)
|
||||||
|
policy.Action = PolicyAction(msg.Action)
|
||||||
|
|
||||||
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
|
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -249,6 +254,8 @@ func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
|
|||||||
policy.Mark = new(XfrmMark)
|
policy.Mark = new(XfrmMark)
|
||||||
policy.Mark.Value = mark.Value
|
policy.Mark.Value = mark.Value
|
||||||
policy.Mark.Mask = mark.Mask
|
policy.Mark.Mask = mark.Mask
|
||||||
|
case nl.XFRMA_IF_ID:
|
||||||
|
policy.Ifid = int(native.Uint32(attr.Value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
6
vendor/github.com/vishvananda/netlink/xfrm_state.go
generated
vendored
6
vendor/github.com/vishvananda/netlink/xfrm_state.go
generated
vendored
@ -94,6 +94,8 @@ type XfrmState struct {
|
|||||||
Limits XfrmStateLimits
|
Limits XfrmStateLimits
|
||||||
Statistics XfrmStateStats
|
Statistics XfrmStateStats
|
||||||
Mark *XfrmMark
|
Mark *XfrmMark
|
||||||
|
OutputMark int
|
||||||
|
Ifid int
|
||||||
Auth *XfrmStateAlgo
|
Auth *XfrmStateAlgo
|
||||||
Crypt *XfrmStateAlgo
|
Crypt *XfrmStateAlgo
|
||||||
Aead *XfrmStateAlgo
|
Aead *XfrmStateAlgo
|
||||||
@ -102,8 +104,8 @@ type XfrmState struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sa XfrmState) String() string {
|
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, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t",
|
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.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN)
|
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 {
|
func (sa XfrmState) Print(stats bool) string {
|
||||||
if !stats {
|
if !stats {
|
||||||
|
27
vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
generated
vendored
27
vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
generated
vendored
@ -158,6 +158,13 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
|
|||||||
out := nl.NewRtAttr(nl.XFRMA_REPLAY_ESN_VAL, writeReplayEsn(state.ReplayWindow))
|
out := nl.NewRtAttr(nl.XFRMA_REPLAY_ESN_VAL, writeReplayEsn(state.ReplayWindow))
|
||||||
req.AddData(out)
|
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)
|
_, err := req.Execute(unix.NETLINK_XFRM, 0)
|
||||||
return err
|
return err
|
||||||
@ -184,12 +191,7 @@ func (h *Handle) xfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := parseXfrmState(msgs[0], FAMILY_ALL)
|
return parseXfrmState(msgs[0], FAMILY_ALL)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return s, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// XfrmStateDel will delete an xfrm state from the system. Note that
|
// XfrmStateDel will delete an xfrm state from the system. Note that
|
||||||
@ -275,6 +277,9 @@ func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState
|
|||||||
req.AddData(out)
|
req.AddData(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid)))
|
||||||
|
req.AddData(ifId)
|
||||||
|
|
||||||
resType := nl.XFRM_MSG_NEWSA
|
resType := nl.XFRM_MSG_NEWSA
|
||||||
if nlProto == nl.XFRM_MSG_DELSA {
|
if nlProto == nl.XFRM_MSG_DELSA {
|
||||||
resType = 0
|
resType = 0
|
||||||
@ -372,6 +377,10 @@ func parseXfrmState(m []byte, family int) (*XfrmState, error) {
|
|||||||
state.Mark = new(XfrmMark)
|
state.Mark = new(XfrmMark)
|
||||||
state.Mark.Value = mark.Value
|
state.Mark.Value = mark.Value
|
||||||
state.Mark.Mask = mark.Mask
|
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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,11 +403,7 @@ func (h *Handle) XfrmStateFlush(proto Proto) error {
|
|||||||
req.AddData(&nl.XfrmUsersaFlush{Proto: uint8(proto)})
|
req.AddData(&nl.XfrmUsersaFlush{Proto: uint8(proto)})
|
||||||
|
|
||||||
_, err := req.Execute(unix.NETLINK_XFRM, 0)
|
_, err := req.Execute(unix.NETLINK_XFRM, 0)
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func limitsToLft(lmts XfrmStateLimits, lft *nl.XfrmLifetimeCfg) {
|
func limitsToLft(lmts XfrmStateLimits, lft *nl.XfrmLifetimeCfg) {
|
||||||
|
Reference in New Issue
Block a user