Signed-off-by: Jess Frazelle <jess@mesosphere.com>
This commit is contained in:
Jess Frazelle 2016-04-15 01:54:02 -07:00
parent 7643294230
commit d4da2f0fe2
No known key found for this signature in database
GPG key ID: 18F3685C0022BFF3
380 changed files with 53507 additions and 67 deletions

192
vendor/github.com/vishvananda/netlink/LICENSE generated vendored Normal file
View file

@ -0,0 +1,192 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Copyright 2014 Vishvananda Ishaya.
Copyright 2014 Docker, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

45
vendor/github.com/vishvananda/netlink/addr.go generated vendored Normal file
View file

@ -0,0 +1,45 @@
package netlink
import (
"fmt"
"net"
"strings"
)
// Addr represents an IP address from netlink. Netlink ip addresses
// include a mask, so it stores the address as a net.IPNet.
type Addr struct {
*net.IPNet
Label string
Flags int
Scope int
}
// String returns $ip/$netmask $label
func (a Addr) String() string {
return strings.TrimSpace(fmt.Sprintf("%s %s", a.IPNet, a.Label))
}
// ParseAddr parses the string representation of an address in the
// form $ip/$netmask $label. The label portion is optional
func ParseAddr(s string) (*Addr, error) {
label := ""
parts := strings.Split(s, " ")
if len(parts) > 1 {
s = parts[0]
label = parts[1]
}
m, err := ParseIPNet(s)
if err != nil {
return nil, err
}
return &Addr{IPNet: m, Label: label}, nil
}
// Equal returns true if both Addrs have the same net.IPNet value.
func (a Addr) Equal(x Addr) bool {
sizea, _ := a.Mask.Size()
sizeb, _ := x.Mask.Size()
// ignore label for comparison
return a.IP.Equal(x.IP) && sizea == sizeb
}

210
vendor/github.com/vishvananda/netlink/addr_linux.go generated vendored Normal file
View file

@ -0,0 +1,210 @@
package netlink
import (
"fmt"
"log"
"net"
"strings"
"syscall"
"github.com/vishvananda/netlink/nl"
)
// IFA_FLAGS is a u32 attribute.
const IFA_FLAGS = 0x8
// AddrAdd will add an IP address to a link device.
// Equivalent to: `ip addr add $addr dev $link`
func AddrAdd(link Link, addr *Addr) error {
req := nl.NewNetlinkRequest(syscall.RTM_NEWADDR, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
return addrHandle(link, addr, req)
}
// AddrDel will delete an IP address from a link device.
// Equivalent to: `ip addr del $addr dev $link`
func AddrDel(link Link, addr *Addr) error {
req := nl.NewNetlinkRequest(syscall.RTM_DELADDR, syscall.NLM_F_ACK)
return addrHandle(link, addr, req)
}
func addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error {
base := link.Attrs()
if addr.Label != "" && !strings.HasPrefix(addr.Label, base.Name) {
return fmt.Errorf("label must begin with interface name")
}
ensureIndex(base)
family := nl.GetIPFamily(addr.IP)
msg := nl.NewIfAddrmsg(family)
msg.Index = uint32(base.Index)
msg.Scope = uint8(addr.Scope)
prefixlen, _ := addr.Mask.Size()
msg.Prefixlen = uint8(prefixlen)
req.AddData(msg)
var addrData []byte
if family == FAMILY_V4 {
addrData = addr.IP.To4()
} else {
addrData = addr.IP.To16()
}
localData := nl.NewRtAttr(syscall.IFA_LOCAL, addrData)
req.AddData(localData)
addressData := nl.NewRtAttr(syscall.IFA_ADDRESS, addrData)
req.AddData(addressData)
if addr.Flags != 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(addr.Flags))
flagsData := nl.NewRtAttr(IFA_FLAGS, b)
req.AddData(flagsData)
}
if addr.Label != "" {
labelData := nl.NewRtAttr(syscall.IFA_LABEL, nl.ZeroTerminated(addr.Label))
req.AddData(labelData)
}
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
return err
}
// AddrList gets a list of IP addresses in the system.
// Equivalent to: `ip addr show`.
// The list can be filtered by link and ip family.
func AddrList(link Link, family int) ([]Addr, error) {
req := nl.NewNetlinkRequest(syscall.RTM_GETADDR, syscall.NLM_F_DUMP)
msg := nl.NewIfInfomsg(family)
req.AddData(msg)
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWADDR)
if err != nil {
return nil, err
}
indexFilter := 0
if link != nil {
base := link.Attrs()
ensureIndex(base)
indexFilter = base.Index
}
var res []Addr
for _, m := range msgs {
addr, msgFamily, ifindex, err := parseAddr(m)
if err != nil {
return res, err
}
if link != nil && ifindex != indexFilter {
// Ignore messages from other interfaces
continue
}
if family != FAMILY_ALL && msgFamily != family {
continue
}
res = append(res, addr)
}
return res, nil
}
func parseAddr(m []byte) (addr Addr, family, index int, err error) {
msg := nl.DeserializeIfAddrmsg(m)
family = -1
index = -1
attrs, err1 := nl.ParseRouteAttr(m[msg.Len():])
if err1 != nil {
err = err1
return
}
family = int(msg.Family)
index = int(msg.Index)
var local, dst *net.IPNet
for _, attr := range attrs {
switch attr.Attr.Type {
case syscall.IFA_ADDRESS:
dst = &net.IPNet{
IP: attr.Value,
Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
}
case syscall.IFA_LOCAL:
local = &net.IPNet{
IP: attr.Value,
Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
}
case syscall.IFA_LABEL:
addr.Label = string(attr.Value[:len(attr.Value)-1])
case IFA_FLAGS:
addr.Flags = int(native.Uint32(attr.Value[0:4]))
}
}
// IFA_LOCAL should be there but if not, fall back to IFA_ADDRESS
if local != nil {
addr.IPNet = local
} else {
addr.IPNet = dst
}
addr.Scope = int(msg.Scope)
return
}
type AddrUpdate struct {
LinkAddress net.IPNet
LinkIndex int
NewAddr bool // true=added false=deleted
}
// AddrSubscribe takes a chan down which notifications will be sent
// when addresses change. Close the 'done' chan to stop subscription.
func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error {
s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_IFADDR, syscall.RTNLGRP_IPV6_IFADDR)
if err != nil {
return err
}
if done != nil {
go func() {
<-done
s.Close()
}()
}
go func() {
defer close(ch)
for {
msgs, err := s.Receive()
if err != nil {
log.Printf("netlink.AddrSubscribe: Receive() error: %v", err)
return
}
for _, m := range msgs {
msgType := m.Header.Type
if msgType != syscall.RTM_NEWADDR && msgType != syscall.RTM_DELADDR {
log.Printf("netlink.AddrSubscribe: bad message type: %d", msgType)
continue
}
addr, _, ifindex, err := parseAddr(m.Data)
if err != nil {
log.Printf("netlink.AddrSubscribe: could not parse address: %v", err)
continue
}
ch <- AddrUpdate{LinkAddress: *addr.IPNet, LinkIndex: ifindex, NewAddr: msgType == syscall.RTM_NEWADDR}
}
}
}()
return nil
}

60
vendor/github.com/vishvananda/netlink/bpf_linux.go generated vendored Normal file
View file

@ -0,0 +1,60 @@
package netlink
/*
#include <asm/types.h>
#include <asm/unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
static int load_simple_bpf(int prog_type) {
#ifdef __NR_bpf
// { return 1; }
__u64 __attribute__((aligned(8))) insns[] = {
0x00000001000000b7ull,
0x0000000000000095ull,
};
__u8 __attribute__((aligned(8))) license[] = "ASL2";
// Copied from a header file since libc is notoriously slow to update.
// The call will succeed or fail and that will be our indication on
// whether or not it is supported.
struct {
__u32 prog_type;
__u32 insn_cnt;
__u64 insns;
__u64 license;
__u32 log_level;
__u32 log_size;
__u64 log_buf;
__u32 kern_version;
} __attribute__((aligned(8))) attr = {
.prog_type = prog_type,
.insn_cnt = 2,
.insns = (uintptr_t)&insns,
.license = (uintptr_t)&license,
};
return syscall(__NR_bpf, 5, &attr, sizeof(attr));
#else
errno = EINVAL;
return -1;
#endif
}
*/
import "C"
type BpfProgType C.int
const (
BPF_PROG_TYPE_UNSPEC BpfProgType = iota
BPF_PROG_TYPE_SOCKET_FILTER
BPF_PROG_TYPE_KPROBE
BPF_PROG_TYPE_SCHED_CLS
BPF_PROG_TYPE_SCHED_ACT
)
// loadSimpleBpf loads a trivial bpf program for testing purposes
func loadSimpleBpf(progType BpfProgType) (int, error) {
fd, err := C.load_simple_bpf(C.int(progType))
return int(fd), err
}

111
vendor/github.com/vishvananda/netlink/class.go generated vendored Normal file
View file

@ -0,0 +1,111 @@
package netlink
import (
"fmt"
)
type Class interface {
Attrs() *ClassAttrs
Type() string
}
// ClassAttrs represents a netlink class. A filter is associated with a link,
// has a handle and a parent. The root filter of a device should have a
// parent == HANDLE_ROOT.
type ClassAttrs struct {
LinkIndex int
Handle uint32
Parent uint32
Leaf uint32
}
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)
}
type HtbClassAttrs struct {
// TODO handle all attributes
Rate uint64
Ceil uint64
Buffer uint32
Cbuffer uint32
Quantum uint32
Level uint32
Prio uint32
}
func (q HtbClassAttrs) String() string {
return fmt.Sprintf("{Rate: %d, Ceil: %d, Buffer: %d, Cbuffer: %d}", q.Rate, q.Ceil, q.Buffer, q.Cbuffer)
}
// HtbClass represents an Htb class
type HtbClass struct {
ClassAttrs
Rate uint64
Ceil uint64
Buffer uint32
Cbuffer uint32
Quantum uint32
Level uint32
Prio uint32
}
func NewHtbClass(attrs ClassAttrs, cattrs HtbClassAttrs) *HtbClass {
mtu := 1600
rate := cattrs.Rate / 8
ceil := cattrs.Ceil / 8
buffer := cattrs.Buffer
cbuffer := cattrs.Cbuffer
if ceil == 0 {
ceil = rate
}
if buffer == 0 {
buffer = uint32(float64(rate)/Hz() + float64(mtu))
}
buffer = uint32(Xmittime(rate, buffer))
if cbuffer == 0 {
cbuffer = uint32(float64(ceil)/Hz() + float64(mtu))
}
cbuffer = uint32(Xmittime(ceil, cbuffer))
return &HtbClass{
ClassAttrs: attrs,
Rate: rate,
Ceil: ceil,
Buffer: buffer,
Cbuffer: cbuffer,
Quantum: 10,
Level: 0,
Prio: 0,
}
}
func (q HtbClass) String() string {
return fmt.Sprintf("{Rate: %d, Ceil: %d, Buffer: %d, Cbuffer: %d}", q.Rate, q.Ceil, q.Buffer, q.Cbuffer)
}
func (q *HtbClass) Attrs() *ClassAttrs {
return &q.ClassAttrs
}
func (q *HtbClass) Type() string {
return "htb"
}
// GenericClass classes represent types that are not currently understood
// by this netlink library.
type GenericClass struct {
ClassAttrs
ClassType string
}
func (class *GenericClass) Attrs() *ClassAttrs {
return &class.ClassAttrs
}
func (class *GenericClass) Type() string {
return class.ClassType
}

186
vendor/github.com/vishvananda/netlink/class_linux.go generated vendored Normal file
View file

@ -0,0 +1,186 @@
package netlink
import (
"errors"
"syscall"
"github.com/vishvananda/netlink/nl"
)
// ClassDel will delete a class from the system.
// Equivalent to: `tc class del $class`
func ClassDel(class Class) error {
return classModify(syscall.RTM_DELTCLASS, 0, class)
}
// ClassChange will change a class in place
// Equivalent to: `tc class change $class`
// The parent and handle MUST NOT be changed.
func ClassChange(class Class) error {
return classModify(syscall.RTM_NEWTCLASS, 0, class)
}
// ClassReplace will replace a class to the system.
// quivalent to: `tc class replace $class`
// The handle MAY be changed.
// If a class already exist with this parent/handle pair, the class is changed.
// If a class does not already exist with this parent/handle, a new class is created.
func ClassReplace(class Class) error {
return classModify(syscall.RTM_NEWTCLASS, syscall.NLM_F_CREATE, class)
}
// ClassAdd will add a class to the system.
// Equivalent to: `tc class add $class`
func ClassAdd(class Class) error {
return classModify(
syscall.RTM_NEWTCLASS,
syscall.NLM_F_CREATE|syscall.NLM_F_EXCL,
class,
)
}
func classModify(cmd, flags int, class Class) error {
req := nl.NewNetlinkRequest(cmd, flags|syscall.NLM_F_ACK)
base := class.Attrs()
msg := &nl.TcMsg{
Family: nl.FAMILY_ALL,
Ifindex: int32(base.LinkIndex),
Handle: base.Handle,
Parent: base.Parent,
}
req.AddData(msg)
if cmd != syscall.RTM_DELTCLASS {
if err := classPayload(req, class); err != nil {
return err
}
}
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
return err
}
func classPayload(req *nl.NetlinkRequest, class Class) error {
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(class.Type())))
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
if htb, ok := class.(*HtbClass); ok {
opt := nl.TcHtbCopt{}
opt.Buffer = htb.Buffer
opt.Cbuffer = htb.Cbuffer
opt.Quantum = htb.Quantum
opt.Level = htb.Level
opt.Prio = htb.Prio
// TODO: Handle Debug properly. For now default to 0
/* Calculate {R,C}Tab and set Rate and Ceil */
cellLog := -1
ccellLog := -1
linklayer := nl.LINKLAYER_ETHERNET
mtu := 1600
var rtab [256]uint32
var ctab [256]uint32
tcrate := nl.TcRateSpec{Rate: uint32(htb.Rate)}
if CalcRtable(&tcrate, rtab, cellLog, uint32(mtu), linklayer) < 0 {
return errors.New("HTB: failed to calculate rate table")
}
opt.Rate = tcrate
tcceil := nl.TcRateSpec{Rate: uint32(htb.Ceil)}
if CalcRtable(&tcceil, ctab, ccellLog, uint32(mtu), linklayer) < 0 {
return errors.New("HTB: failed to calculate ceil rate table")
}
opt.Ceil = tcceil
nl.NewRtAttrChild(options, nl.TCA_HTB_PARMS, opt.Serialize())
nl.NewRtAttrChild(options, nl.TCA_HTB_RTAB, SerializeRtab(rtab))
nl.NewRtAttrChild(options, nl.TCA_HTB_CTAB, SerializeRtab(ctab))
}
req.AddData(options)
return nil
}
// ClassList gets a list of classes in the system.
// Equivalent to: `tc class show`.
// Generally returns nothing if link and parent are not specified.
func ClassList(link Link, parent uint32) ([]Class, error) {
req := nl.NewNetlinkRequest(syscall.RTM_GETTCLASS, syscall.NLM_F_DUMP)
msg := &nl.TcMsg{
Family: nl.FAMILY_ALL,
Parent: parent,
}
if link != nil {
base := link.Attrs()
ensureIndex(base)
msg.Ifindex = int32(base.Index)
}
req.AddData(msg)
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWTCLASS)
if err != nil {
return nil, err
}
var res []Class
for _, m := range msgs {
msg := nl.DeserializeTcMsg(m)
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
if err != nil {
return nil, err
}
base := ClassAttrs{
LinkIndex: int(msg.Ifindex),
Handle: msg.Handle,
Parent: msg.Parent,
}
var class Class
classType := ""
for _, attr := range attrs {
switch attr.Attr.Type {
case nl.TCA_KIND:
classType = string(attr.Value[:len(attr.Value)-1])
switch classType {
case "htb":
class = &HtbClass{}
default:
class = &GenericClass{ClassType: classType}
}
case nl.TCA_OPTIONS:
switch classType {
case "htb":
data, err := nl.ParseRouteAttr(attr.Value)
if err != nil {
return nil, err
}
_, err = parseHtbClassData(class, data)
if err != nil {
return nil, err
}
}
}
}
*class.Attrs() = base
res = append(res, class)
}
return res, nil
}
func parseHtbClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, error) {
htb := class.(*HtbClass)
detailed := false
for _, datum := range data {
switch datum.Attr.Type {
case nl.TCA_HTB_PARMS:
opt := nl.DeserializeTcHtbCopt(datum.Value)
htb.Rate = uint64(opt.Rate.Rate)
htb.Ceil = uint64(opt.Ceil.Rate)
htb.Buffer = opt.Buffer
htb.Cbuffer = opt.Cbuffer
htb.Quantum = opt.Quantum
htb.Level = opt.Level
htb.Prio = opt.Prio
}
}
return detailed, nil
}

190
vendor/github.com/vishvananda/netlink/filter.go generated vendored Normal file
View file

@ -0,0 +1,190 @@
package netlink
import (
"errors"
"fmt"
"github.com/vishvananda/netlink/nl"
)
type Filter interface {
Attrs() *FilterAttrs
Type() string
}
// FilterAttrs represents a netlink filter. A filter is associated with a link,
// has a handle and a parent. The root filter of a device should have a
// parent == HANDLE_ROOT.
type FilterAttrs struct {
LinkIndex int
Handle uint32
Parent uint32
Priority uint16 // lower is higher priority
Protocol uint16 // syscall.ETH_P_*
}
func (q FilterAttrs) String() string {
return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Priority: %d, Protocol: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Priority, q.Protocol)
}
// Action represents an action in any supported filter.
type Action interface {
Type() string
}
type BpfAction struct {
nl.TcActBpf
Fd int
Name string
}
func (action *BpfAction) Type() string {
return "bpf"
}
type MirredAction struct {
nl.TcMirred
}
func (action *MirredAction) Type() string {
return "mirred"
}
func NewMirredAction(redirIndex int) *MirredAction {
return &MirredAction{
TcMirred: nl.TcMirred{
TcGen: nl.TcGen{Action: nl.TC_ACT_STOLEN},
Eaction: nl.TCA_EGRESS_REDIR,
Ifindex: uint32(redirIndex),
},
}
}
// U32 filters on many packet related properties
type U32 struct {
FilterAttrs
ClassId uint32
RedirIndex int
Actions []Action
}
func (filter *U32) Attrs() *FilterAttrs {
return &filter.FilterAttrs
}
func (filter *U32) Type() string {
return "u32"
}
type FilterFwAttrs struct {
ClassId uint32
InDev string
Mask uint32
Index uint32
Buffer uint32
Mtu uint32
Mpu uint16
Rate uint32
AvRate uint32
PeakRate uint32
Action int
Overhead uint16
LinkLayer int
}
// Fw filter filters on firewall marks
type Fw struct {
FilterAttrs
ClassId uint32
Police nl.TcPolice
InDev string
// TODO Action
Mask uint32
AvRate uint32
Rtab [256]uint32
Ptab [256]uint32
}
func NewFw(attrs FilterAttrs, fattrs FilterFwAttrs) (*Fw, error) {
var rtab [256]uint32
var ptab [256]uint32
rcellLog := -1
pcellLog := -1
avrate := fattrs.AvRate / 8
police := nl.TcPolice{}
police.Rate.Rate = fattrs.Rate / 8
police.PeakRate.Rate = fattrs.PeakRate / 8
buffer := fattrs.Buffer
linklayer := nl.LINKLAYER_ETHERNET
if fattrs.LinkLayer != nl.LINKLAYER_UNSPEC {
linklayer = fattrs.LinkLayer
}
police.Action = int32(fattrs.Action)
if police.Rate.Rate != 0 {
police.Rate.Mpu = fattrs.Mpu
police.Rate.Overhead = fattrs.Overhead
if CalcRtable(&police.Rate, rtab, rcellLog, fattrs.Mtu, linklayer) < 0 {
return nil, errors.New("TBF: failed to calculate rate table")
}
police.Burst = uint32(Xmittime(uint64(police.Rate.Rate), uint32(buffer)))
}
police.Mtu = fattrs.Mtu
if police.PeakRate.Rate != 0 {
police.PeakRate.Mpu = fattrs.Mpu
police.PeakRate.Overhead = fattrs.Overhead
if CalcRtable(&police.PeakRate, ptab, pcellLog, fattrs.Mtu, linklayer) < 0 {
return nil, errors.New("POLICE: failed to calculate peak rate table")
}
}
return &Fw{
FilterAttrs: attrs,
ClassId: fattrs.ClassId,
InDev: fattrs.InDev,
Mask: fattrs.Mask,
Police: police,
AvRate: avrate,
Rtab: rtab,
Ptab: ptab,
}, nil
}
func (filter *Fw) Attrs() *FilterAttrs {
return &filter.FilterAttrs
}
func (filter *Fw) Type() string {
return "fw"
}
type BpfFilter struct {
FilterAttrs
ClassId uint32
Fd int
Name string
DirectAction bool
}
func (filter *BpfFilter) Type() string {
return "bpf"
}
func (filter *BpfFilter) Attrs() *FilterAttrs {
return &filter.FilterAttrs
}
// GenericFilter filters represent types that are not currently understood
// by this netlink library.
type GenericFilter struct {
FilterAttrs
FilterType string
}
func (filter *GenericFilter) Attrs() *FilterAttrs {
return &filter.FilterAttrs
}
func (filter *GenericFilter) Type() string {
return filter.FilterType
}

424
vendor/github.com/vishvananda/netlink/filter_linux.go generated vendored Normal file
View file

@ -0,0 +1,424 @@
package netlink
import (
"bytes"
"encoding/binary"
"fmt"
"syscall"
"github.com/vishvananda/netlink/nl"
)
// FilterDel will delete a filter from the system.
// Equivalent to: `tc filter del $filter`
func FilterDel(filter Filter) error {
req := nl.NewNetlinkRequest(syscall.RTM_DELTFILTER, syscall.NLM_F_ACK)
base := filter.Attrs()
msg := &nl.TcMsg{
Family: nl.FAMILY_ALL,
Ifindex: int32(base.LinkIndex),
Handle: base.Handle,
Parent: base.Parent,
Info: MakeHandle(base.Priority, nl.Swap16(base.Protocol)),
}
req.AddData(msg)
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
return err
}
// FilterAdd will add a filter to the system.
// Equivalent to: `tc filter add $filter`
func FilterAdd(filter Filter) error {
native = nl.NativeEndian()
req := nl.NewNetlinkRequest(syscall.RTM_NEWTFILTER, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
base := filter.Attrs()
msg := &nl.TcMsg{
Family: nl.FAMILY_ALL,
Ifindex: int32(base.LinkIndex),
Handle: base.Handle,
Parent: base.Parent,
Info: MakeHandle(base.Priority, nl.Swap16(base.Protocol)),
}
req.AddData(msg)
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(filter.Type())))
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
if u32, ok := filter.(*U32); ok {
// match all
sel := nl.TcU32Sel{
Nkeys: 1,
Flags: nl.TC_U32_TERMINAL,
}
sel.Keys = append(sel.Keys, nl.TcU32Key{})
nl.NewRtAttrChild(options, nl.TCA_U32_SEL, sel.Serialize())
if u32.ClassId != 0 {
nl.NewRtAttrChild(options, nl.TCA_U32_CLASSID, nl.Uint32Attr(u32.ClassId))
}
actionsAttr := nl.NewRtAttrChild(options, nl.TCA_U32_ACT, nil)
// backwards compatibility
if u32.RedirIndex != 0 {
u32.Actions = append([]Action{NewMirredAction(u32.RedirIndex)}, u32.Actions...)
}
if err := encodeActions(actionsAttr, u32.Actions); err != nil {
return err
}
} else if fw, ok := filter.(*Fw); ok {
if fw.Mask != 0 {
b := make([]byte, 4)
native.PutUint32(b, fw.Mask)
nl.NewRtAttrChild(options, nl.TCA_FW_MASK, b)
}
if fw.InDev != "" {
nl.NewRtAttrChild(options, nl.TCA_FW_INDEV, nl.ZeroTerminated(fw.InDev))
}
if (fw.Police != nl.TcPolice{}) {
police := nl.NewRtAttrChild(options, nl.TCA_FW_POLICE, nil)
nl.NewRtAttrChild(police, nl.TCA_POLICE_TBF, fw.Police.Serialize())
if (fw.Police.Rate != nl.TcRateSpec{}) {
payload := SerializeRtab(fw.Rtab)
nl.NewRtAttrChild(police, nl.TCA_POLICE_RATE, payload)
}
if (fw.Police.PeakRate != nl.TcRateSpec{}) {
payload := SerializeRtab(fw.Ptab)
nl.NewRtAttrChild(police, nl.TCA_POLICE_PEAKRATE, payload)
}
}
if fw.ClassId != 0 {
b := make([]byte, 4)
native.PutUint32(b, fw.ClassId)
nl.NewRtAttrChild(options, nl.TCA_FW_CLASSID, b)
}
} else if bpf, ok := filter.(*BpfFilter); ok {
var bpfFlags uint32
if bpf.ClassId != 0 {
nl.NewRtAttrChild(options, nl.TCA_BPF_CLASSID, nl.Uint32Attr(bpf.ClassId))
}
if bpf.Fd >= 0 {
nl.NewRtAttrChild(options, nl.TCA_BPF_FD, nl.Uint32Attr((uint32(bpf.Fd))))
}
if bpf.Name != "" {
nl.NewRtAttrChild(options, nl.TCA_BPF_NAME, nl.ZeroTerminated(bpf.Name))
}
if bpf.DirectAction {
bpfFlags |= nl.TCA_BPF_FLAG_ACT_DIRECT
}
nl.NewRtAttrChild(options, nl.TCA_BPF_FLAGS, nl.Uint32Attr(bpfFlags))
}
req.AddData(options)
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
return err
}
// FilterList gets a list of filters in the system.
// Equivalent to: `tc filter show`.
// Generally retunrs nothing if link and parent are not specified.
func FilterList(link Link, parent uint32) ([]Filter, error) {
req := nl.NewNetlinkRequest(syscall.RTM_GETTFILTER, syscall.NLM_F_DUMP)
msg := &nl.TcMsg{
Family: nl.FAMILY_ALL,
Parent: parent,
}
if link != nil {
base := link.Attrs()
ensureIndex(base)
msg.Ifindex = int32(base.Index)
}
req.AddData(msg)
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWTFILTER)
if err != nil {
return nil, err
}
var res []Filter
for _, m := range msgs {
msg := nl.DeserializeTcMsg(m)
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
if err != nil {
return nil, err
}
base := FilterAttrs{
LinkIndex: int(msg.Ifindex),
Handle: msg.Handle,
Parent: msg.Parent,
}
base.Priority, base.Protocol = MajorMinor(msg.Info)
base.Protocol = nl.Swap16(base.Protocol)
var filter Filter
filterType := ""
detailed := false
for _, attr := range attrs {
switch attr.Attr.Type {
case nl.TCA_KIND:
filterType = string(attr.Value[:len(attr.Value)-1])
switch filterType {
case "u32":
filter = &U32{}
case "fw":
filter = &Fw{}
case "bpf":
filter = &BpfFilter{}
default:
filter = &GenericFilter{FilterType: filterType}
}
case nl.TCA_OPTIONS:
data, err := nl.ParseRouteAttr(attr.Value)
if err != nil {
return nil, err
}
switch filterType {
case "u32":
detailed, err = parseU32Data(filter, data)
if err != nil {
return nil, err
}
case "fw":
detailed, err = parseFwData(filter, data)
if err != nil {
return nil, err
}
case "bpf":
detailed, err = parseBpfData(filter, data)
if err != nil {
return nil, err
}
}
}
}
// only return the detailed version of the filter
if detailed {
*filter.Attrs() = base
res = append(res, filter)
}
}
return res, nil
}
func encodeActions(attr *nl.RtAttr, actions []Action) error {
tabIndex := int(nl.TCA_ACT_TAB)
for _, action := range actions {
switch action := action.(type) {
default:
return fmt.Errorf("unknown action type %s", action.Type())
case *MirredAction:
table := nl.NewRtAttrChild(attr, tabIndex, nil)
tabIndex++
nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("mirred"))
aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil)
nl.NewRtAttrChild(aopts, nl.TCA_MIRRED_PARMS, action.Serialize())
case *BpfAction:
table := nl.NewRtAttrChild(attr, tabIndex, nil)
tabIndex++
nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("bpf"))
aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil)
nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_PARMS, action.Serialize())
nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd)))
nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_NAME, nl.ZeroTerminated(action.Name))
}
}
return nil
}
func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
var actions []Action
for _, table := range tables {
var action Action
var actionType string
aattrs, err := nl.ParseRouteAttr(table.Value)
if err != nil {
return nil, err
}
nextattr:
for _, aattr := range aattrs {
switch aattr.Attr.Type {
case nl.TCA_KIND:
actionType = string(aattr.Value[:len(aattr.Value)-1])
// only parse if the action is mirred or bpf
switch actionType {
case "mirred":
action = &MirredAction{}
case "bpf":
action = &BpfAction{}
default:
break nextattr
}
case nl.TCA_OPTIONS:
adata, err := nl.ParseRouteAttr(aattr.Value)
if err != nil {
return nil, err
}
for _, adatum := range adata {
switch actionType {
case "mirred":
switch adatum.Attr.Type {
case nl.TCA_MIRRED_PARMS:
action.(*MirredAction).TcMirred = *nl.DeserializeTcMirred(adatum.Value)
}
case "bpf":
switch adatum.Attr.Type {
case nl.TCA_ACT_BPF_PARMS:
action.(*BpfAction).TcActBpf = *nl.DeserializeTcActBpf(adatum.Value)
case nl.TCA_ACT_BPF_FD:
action.(*BpfAction).Fd = int(native.Uint32(adatum.Value[0:4]))
case nl.TCA_ACT_BPF_NAME:
action.(*BpfAction).Name = string(adatum.Value[:len(adatum.Value)-1])
}
}
}
}
}
actions = append(actions, action)
}
return actions, nil
}
func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
native = nl.NativeEndian()
u32 := filter.(*U32)
detailed := false
for _, datum := range data {
switch datum.Attr.Type {
case nl.TCA_U32_SEL:
detailed = true
sel := nl.DeserializeTcU32Sel(datum.Value)
// only parse if we have a very basic redirect
if sel.Flags&nl.TC_U32_TERMINAL == 0 || sel.Nkeys != 1 {
return detailed, nil
}
case nl.TCA_U32_ACT:
tables, err := nl.ParseRouteAttr(datum.Value)
if err != nil {
return detailed, err
}
u32.Actions, err = parseActions(tables)
if err != nil {
return detailed, err
}
for _, action := range u32.Actions {
if action, ok := action.(*MirredAction); ok {
u32.RedirIndex = int(action.Ifindex)
}
}
}
}
return detailed, nil
}
func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
native = nl.NativeEndian()
fw := filter.(*Fw)
detailed := true
for _, datum := range data {
switch datum.Attr.Type {
case nl.TCA_FW_MASK:
fw.Mask = native.Uint32(datum.Value[0:4])
case nl.TCA_FW_CLASSID:
fw.ClassId = native.Uint32(datum.Value[0:4])
case nl.TCA_FW_INDEV:
fw.InDev = string(datum.Value[:len(datum.Value)-1])
case nl.TCA_FW_POLICE:
adata, _ := nl.ParseRouteAttr(datum.Value)
for _, aattr := range adata {
switch aattr.Attr.Type {
case nl.TCA_POLICE_TBF:
fw.Police = *nl.DeserializeTcPolice(aattr.Value)
case nl.TCA_POLICE_RATE:
fw.Rtab = DeserializeRtab(aattr.Value)
case nl.TCA_POLICE_PEAKRATE:
fw.Ptab = DeserializeRtab(aattr.Value)
}
}
}
}
return detailed, nil
}
func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
native = nl.NativeEndian()
bpf := filter.(*BpfFilter)
detailed := true
for _, datum := range data {
switch datum.Attr.Type {
case nl.TCA_BPF_FD:
bpf.Fd = int(native.Uint32(datum.Value[0:4]))
case nl.TCA_BPF_NAME:
bpf.Name = string(datum.Value[:len(datum.Value)-1])
case nl.TCA_BPF_CLASSID:
bpf.ClassId = native.Uint32(datum.Value[0:4])
case nl.TCA_BPF_FLAGS:
flags := native.Uint32(datum.Value[0:4])
if (flags & nl.TCA_BPF_FLAG_ACT_DIRECT) != 0 {
bpf.DirectAction = true
}
}
}
return detailed, nil
}
func AlignToAtm(size uint) uint {
var linksize, cells int
cells = int(size / nl.ATM_CELL_PAYLOAD)
if (size % nl.ATM_CELL_PAYLOAD) > 0 {
cells++
}
linksize = cells * nl.ATM_CELL_SIZE
return uint(linksize)
}
func AdjustSize(sz uint, mpu uint, linklayer int) uint {
if sz < mpu {
sz = mpu
}
switch linklayer {
case nl.LINKLAYER_ATM:
return AlignToAtm(sz)
default:
return sz
}
}
func CalcRtable(rate *nl.TcRateSpec, rtab [256]uint32, cellLog int, mtu uint32, linklayer int) int {
bps := rate.Rate
mpu := rate.Mpu
var sz uint
if mtu == 0 {
mtu = 2047
}
if cellLog < 0 {
cellLog = 0
for (mtu >> uint(cellLog)) > 255 {
cellLog++
}
}
for i := 0; i < 256; i++ {
sz = AdjustSize(uint((i+1)<<uint32(cellLog)), uint(mpu), linklayer)
rtab[i] = uint32(Xmittime(uint64(bps), uint32(sz)))
}
rate.CellAlign = -1
rate.CellLog = uint8(cellLog)
rate.Linklayer = uint8(linklayer & nl.TC_LINKLAYER_MASK)
return cellLog
}
func DeserializeRtab(b []byte) [256]uint32 {
var rtab [256]uint32
native := nl.NativeEndian()
r := bytes.NewReader(b)
_ = binary.Read(r, native, &rtab)
return rtab
}
func SerializeRtab(rtab [256]uint32) []byte {
native := nl.NativeEndian()
var w bytes.Buffer
_ = binary.Write(&w, native, rtab)
return w.Bytes()
}

560
vendor/github.com/vishvananda/netlink/link.go generated vendored Normal file
View file

@ -0,0 +1,560 @@
package netlink
import (
"fmt"
"net"
"syscall"
)
// Link represents a link device from netlink. Shared link attributes
// like name may be retrieved using the Attrs() method. Unique data
// can be retrieved by casting the object to the proper type.
type Link interface {
Attrs() *LinkAttrs
Type() string
}
type (
NsPid int
NsFd int
)
// LinkAttrs represents data shared by most link types
type LinkAttrs struct {
Index int
MTU int
TxQLen int // Transmit Queue Length
Name string
HardwareAddr net.HardwareAddr
Flags net.Flags
ParentIndex int // index of the parent link device
MasterIndex int // must be the index of a bridge
Namespace interface{} // nil | NsPid | NsFd
Alias string
}
// NewLinkAttrs returns LinkAttrs structure filled with default values
func NewLinkAttrs() LinkAttrs {
return LinkAttrs{
TxQLen: -1,
}
}
// Device links cannot be created via netlink. These links
// are links created by udev like 'lo' and 'etho0'
type Device struct {
LinkAttrs
}
func (device *Device) Attrs() *LinkAttrs {
return &device.LinkAttrs
}
func (device *Device) Type() string {
return "device"
}
// Dummy links are dummy ethernet devices
type Dummy struct {
LinkAttrs
}
func (dummy *Dummy) Attrs() *LinkAttrs {
return &dummy.LinkAttrs
}
func (dummy *Dummy) Type() string {
return "dummy"
}
// Ifb links are advanced dummy devices for packet filtering
type Ifb struct {
LinkAttrs
}
func (ifb *Ifb) Attrs() *LinkAttrs {
return &ifb.LinkAttrs
}
func (ifb *Ifb) Type() string {
return "ifb"
}
// Bridge links are simple linux bridges
type Bridge struct {
LinkAttrs
}
func (bridge *Bridge) Attrs() *LinkAttrs {
return &bridge.LinkAttrs
}
func (bridge *Bridge) Type() string {
return "bridge"
}
// Vlan links have ParentIndex set in their Attrs()
type Vlan struct {
LinkAttrs
VlanId int
}
func (vlan *Vlan) Attrs() *LinkAttrs {
return &vlan.LinkAttrs
}
func (vlan *Vlan) Type() string {
return "vlan"
}
type MacvlanMode uint16
const (
MACVLAN_MODE_DEFAULT MacvlanMode = iota
MACVLAN_MODE_PRIVATE
MACVLAN_MODE_VEPA
MACVLAN_MODE_BRIDGE
MACVLAN_MODE_PASSTHRU
MACVLAN_MODE_SOURCE
)
// Macvlan links have ParentIndex set in their Attrs()
type Macvlan struct {
LinkAttrs
Mode MacvlanMode
}
func (macvlan *Macvlan) Attrs() *LinkAttrs {
return &macvlan.LinkAttrs
}
func (macvlan *Macvlan) Type() string {
return "macvlan"
}
// Macvtap - macvtap is a virtual interfaces based on macvlan
type Macvtap struct {
Macvlan
}
func (macvtap Macvtap) Type() string {
return "macvtap"
}
type TuntapMode uint16
const (
TUNTAP_MODE_TUN TuntapMode = syscall.IFF_TUN
TUNTAP_MODE_TAP TuntapMode = syscall.IFF_TAP
)
// Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
type Tuntap struct {
LinkAttrs
Mode TuntapMode
}
func (tuntap *Tuntap) Attrs() *LinkAttrs {
return &tuntap.LinkAttrs
}
func (tuntap *Tuntap) Type() string {
return "tuntap"
}
// Veth devices must specify PeerName on create
type Veth struct {
LinkAttrs
PeerName string // veth on create only
}
func (veth *Veth) Attrs() *LinkAttrs {
return &veth.LinkAttrs
}
func (veth *Veth) Type() string {
return "veth"
}
// GenericLink links represent types that are not currently understood
// by this netlink library.
type GenericLink struct {
LinkAttrs
LinkType string
}
func (generic *GenericLink) Attrs() *LinkAttrs {
return &generic.LinkAttrs
}
func (generic *GenericLink) Type() string {
return generic.LinkType
}
type Vxlan struct {
LinkAttrs
VxlanId int
VtepDevIndex int
SrcAddr net.IP
Group net.IP
TTL int
TOS int
Learning bool
Proxy bool
RSC bool
L2miss bool
L3miss bool
UDPCSum bool
NoAge bool
GBP bool
Age int
Limit int
Port int
PortLow int
PortHigh int
}
func (vxlan *Vxlan) Attrs() *LinkAttrs {
return &vxlan.LinkAttrs
}
func (vxlan *Vxlan) Type() string {
return "vxlan"
}
type IPVlanMode uint16
const (
IPVLAN_MODE_L2 IPVlanMode = iota
IPVLAN_MODE_L3
IPVLAN_MODE_MAX
)
type IPVlan struct {
LinkAttrs
Mode IPVlanMode
}
func (ipvlan *IPVlan) Attrs() *LinkAttrs {
return &ipvlan.LinkAttrs
}
func (ipvlan *IPVlan) Type() string {
return "ipvlan"
}
// BondMode type
type BondMode int
func (b BondMode) String() string {
s, ok := bondModeToString[b]
if !ok {
return fmt.Sprintf("BondMode(%d)", b)
}
return s
}
// StringToBondMode returns bond mode, or uknonw is the s is invalid.
func StringToBondMode(s string) BondMode {
mode, ok := StringToBondModeMap[s]
if !ok {
return BOND_MODE_UNKNOWN
}
return mode
}
// Possible BondMode
const (
BOND_MODE_802_3AD BondMode = iota
BOND_MODE_BALANCE_RR
BOND_MODE_ACTIVE_BACKUP
BOND_MODE_BALANCE_XOR
BOND_MODE_BROADCAST
BOND_MODE_BALANCE_TLB
BOND_MODE_BALANCE_ALB
BOND_MODE_UNKNOWN
)
var bondModeToString = map[BondMode]string{
BOND_MODE_802_3AD: "802.3ad",
BOND_MODE_BALANCE_RR: "balance-rr",
BOND_MODE_ACTIVE_BACKUP: "active-backup",
BOND_MODE_BALANCE_XOR: "balance-xor",
BOND_MODE_BROADCAST: "broadcast",
BOND_MODE_BALANCE_TLB: "balance-tlb",
BOND_MODE_BALANCE_ALB: "balance-alb",
}
var StringToBondModeMap = map[string]BondMode{
"802.3ad": BOND_MODE_802_3AD,
"balance-rr": BOND_MODE_BALANCE_RR,
"active-backup": BOND_MODE_ACTIVE_BACKUP,
"balance-xor": BOND_MODE_BALANCE_XOR,
"broadcast": BOND_MODE_BROADCAST,
"balance-tlb": BOND_MODE_BALANCE_TLB,
"balance-alb": BOND_MODE_BALANCE_ALB,
}
// BondArpValidate type
type BondArpValidate int
// Possible BondArpValidate value
const (
BOND_ARP_VALIDATE_NONE BondArpValidate = iota
BOND_ARP_VALIDATE_ACTIVE
BOND_ARP_VALIDATE_BACKUP
BOND_ARP_VALIDATE_ALL
)
// BondPrimaryReselect type
type BondPrimaryReselect int
// Possible BondPrimaryReselect value
const (
BOND_PRIMARY_RESELECT_ALWAYS BondPrimaryReselect = iota
BOND_PRIMARY_RESELECT_BETTER
BOND_PRIMARY_RESELECT_FAILURE
)
// BondArpAllTargets type
type BondArpAllTargets int
// Possible BondArpAllTargets value
const (
BOND_ARP_ALL_TARGETS_ANY BondArpAllTargets = iota
BOND_ARP_ALL_TARGETS_ALL
)
// BondFailOverMac type
type BondFailOverMac int
// Possible BondFailOverMac value
const (
BOND_FAIL_OVER_MAC_NONE BondFailOverMac = iota
BOND_FAIL_OVER_MAC_ACTIVE
BOND_FAIL_OVER_MAC_FOLLOW
)
// BondXmitHashPolicy type
type BondXmitHashPolicy int
func (b BondXmitHashPolicy) String() string {
s, ok := bondXmitHashPolicyToString[b]
if !ok {
return fmt.Sprintf("XmitHashPolicy(%d)", b)
}
return s
}
// StringToBondXmitHashPolicy returns bond lacp arte, or uknonw is the s is invalid.
func StringToBondXmitHashPolicy(s string) BondXmitHashPolicy {
lacp, ok := StringToBondXmitHashPolicyMap[s]
if !ok {
return BOND_XMIT_HASH_POLICY_UNKNOWN
}
return lacp
}
// Possible BondXmitHashPolicy value
const (
BOND_XMIT_HASH_POLICY_LAYER2 BondXmitHashPolicy = iota
BOND_XMIT_HASH_POLICY_LAYER3_4
BOND_XMIT_HASH_POLICY_LAYER2_3
BOND_XMIT_HASH_POLICY_ENCAP2_3
BOND_XMIT_HASH_POLICY_ENCAP3_4
BOND_XMIT_HASH_POLICY_UNKNOWN
)
var bondXmitHashPolicyToString = map[BondXmitHashPolicy]string{
BOND_XMIT_HASH_POLICY_LAYER2: "layer2",
BOND_XMIT_HASH_POLICY_LAYER3_4: "layer3+4",
BOND_XMIT_HASH_POLICY_LAYER2_3: "layer2+3",
BOND_XMIT_HASH_POLICY_ENCAP2_3: "encap2+3",
BOND_XMIT_HASH_POLICY_ENCAP3_4: "encap3+4",
}
var StringToBondXmitHashPolicyMap = map[string]BondXmitHashPolicy{
"layer2": BOND_XMIT_HASH_POLICY_LAYER2,
"layer3+4": BOND_XMIT_HASH_POLICY_LAYER3_4,
"layer2+3": BOND_XMIT_HASH_POLICY_LAYER2_3,
"encap2+3": BOND_XMIT_HASH_POLICY_ENCAP2_3,
"encap3+4": BOND_XMIT_HASH_POLICY_ENCAP3_4,
}
// BondLacpRate type
type BondLacpRate int
func (b BondLacpRate) String() string {
s, ok := bondLacpRateToString[b]
if !ok {
return fmt.Sprintf("LacpRate(%d)", b)
}
return s
}
// StringToBondLacpRate returns bond lacp arte, or uknonw is the s is invalid.
func StringToBondLacpRate(s string) BondLacpRate {
lacp, ok := StringToBondLacpRateMap[s]
if !ok {
return BOND_LACP_RATE_UNKNOWN
}
return lacp
}
// Possible BondLacpRate value
const (
BOND_LACP_RATE_SLOW BondLacpRate = iota
BOND_LACP_RATE_FAST
BOND_LACP_RATE_UNKNOWN
)
var bondLacpRateToString = map[BondLacpRate]string{
BOND_LACP_RATE_SLOW: "slow",
BOND_LACP_RATE_FAST: "fast",
}
var StringToBondLacpRateMap = map[string]BondLacpRate{
"slow": BOND_LACP_RATE_SLOW,
"fast": BOND_LACP_RATE_FAST,
}
// BondAdSelect type
type BondAdSelect int
// Possible BondAdSelect value
const (
BOND_AD_SELECT_STABLE BondAdSelect = iota
BOND_AD_SELECT_BANDWIDTH
BOND_AD_SELECT_COUNT
)
// BondAdInfo represents ad info for bond
type BondAdInfo struct {
AggregatorId int
NumPorts int
ActorKey int
PartnerKey int
PartnerMac net.HardwareAddr
}
// Bond representation
type Bond struct {
LinkAttrs
Mode BondMode
ActiveSlave int
Miimon int
UpDelay int
DownDelay int
UseCarrier int
ArpInterval int
ArpIpTargets []net.IP
ArpValidate BondArpValidate
ArpAllTargets BondArpAllTargets
Primary int
PrimaryReselect BondPrimaryReselect
FailOverMac BondFailOverMac
XmitHashPolicy BondXmitHashPolicy
ResendIgmp int
NumPeerNotif int
AllSlavesActive int
MinLinks int
LpInterval int
PackersPerSlave int
LacpRate BondLacpRate
AdSelect BondAdSelect
// looking at iproute tool AdInfo can only be retrived. It can't be set.
AdInfo *BondAdInfo
}
func NewLinkBond(atr LinkAttrs) *Bond {
return &Bond{
LinkAttrs: atr,
Mode: -1,
ActiveSlave: -1,
Miimon: -1,
UpDelay: -1,
DownDelay: -1,
UseCarrier: -1,
ArpInterval: -1,
ArpIpTargets: nil,
ArpValidate: -1,
ArpAllTargets: -1,
Primary: -1,
PrimaryReselect: -1,
FailOverMac: -1,
XmitHashPolicy: -1,
ResendIgmp: -1,
NumPeerNotif: -1,
AllSlavesActive: -1,
MinLinks: -1,
LpInterval: -1,
PackersPerSlave: -1,
LacpRate: -1,
AdSelect: -1,
}
}
// Flag mask for bond options. Bond.Flagmask must be set to on for option to work.
const (
BOND_MODE_MASK uint64 = 1 << (1 + iota)
BOND_ACTIVE_SLAVE_MASK
BOND_MIIMON_MASK
BOND_UPDELAY_MASK
BOND_DOWNDELAY_MASK
BOND_USE_CARRIER_MASK
BOND_ARP_INTERVAL_MASK
BOND_ARP_VALIDATE_MASK
BOND_ARP_ALL_TARGETS_MASK
BOND_PRIMARY_MASK
BOND_PRIMARY_RESELECT_MASK
BOND_FAIL_OVER_MAC_MASK
BOND_XMIT_HASH_POLICY_MASK
BOND_RESEND_IGMP_MASK
BOND_NUM_PEER_NOTIF_MASK
BOND_ALL_SLAVES_ACTIVE_MASK
BOND_MIN_LINKS_MASK
BOND_LP_INTERVAL_MASK
BOND_PACKETS_PER_SLAVE_MASK
BOND_LACP_RATE_MASK
BOND_AD_SELECT_MASK
)
// Attrs implementation.
func (bond *Bond) Attrs() *LinkAttrs {
return &bond.LinkAttrs
}
// Type implementation fro Vxlan.
func (bond *Bond) Type() string {
return "bond"
}
// Gretap devices must specify LocalIP and RemoteIP on create
type Gretap struct {
LinkAttrs
IKey uint32
OKey uint32
EncapSport uint16
EncapDport uint16
Local net.IP
Remote net.IP
IFlags uint16
OFlags uint16
PMtuDisc uint8
Ttl uint8
Tos uint8
EncapType uint16
EncapFlags uint16
Link uint32
}
func (gretap *Gretap) Attrs() *LinkAttrs {
return &gretap.LinkAttrs
}
func (gretap *Gretap) Type() string {
return "gretap"
}
// iproute2 supported devices;
// vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
// bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |
// gre | gretap | ip6gre | ip6gretap | vti | nlmon |
// bond_slave | ipvlan

1213
vendor/github.com/vishvananda/netlink/link_linux.go generated vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,14 @@
package netlink
// ideally golang.org/x/sys/unix would define IfReq but it only has
// IFNAMSIZ, hence this minimalistic implementation
const (
SizeOfIfReq = 40
IFNAMSIZ = 16
)
type ifReq struct {
Name [IFNAMSIZ]byte
Flags uint16
pad [SizeOfIfReq - IFNAMSIZ - 2]byte
}

22
vendor/github.com/vishvananda/netlink/neigh.go generated vendored Normal file
View file

@ -0,0 +1,22 @@
package netlink
import (
"fmt"
"net"
)
// Neigh represents a link layer neighbor from netlink.
type Neigh struct {
LinkIndex int
Family int
State int
Type int
Flags int
IP net.IP
HardwareAddr net.HardwareAddr
}
// String returns $ip/$hwaddr $label
func (neigh *Neigh) String() string {
return fmt.Sprintf("%s %s", neigh.IP, neigh.HardwareAddr)
}

190
vendor/github.com/vishvananda/netlink/neigh_linux.go generated vendored Normal file
View file

@ -0,0 +1,190 @@
package netlink
import (
"net"
"syscall"
"unsafe"
"github.com/vishvananda/netlink/nl"
)
const (
NDA_UNSPEC = iota
NDA_DST
NDA_LLADDR
NDA_CACHEINFO
NDA_PROBES
NDA_VLAN
NDA_PORT
NDA_VNI
NDA_IFINDEX
NDA_MAX = NDA_IFINDEX
)
// Neighbor Cache Entry States.
const (
NUD_NONE = 0x00
NUD_INCOMPLETE = 0x01
NUD_REACHABLE = 0x02
NUD_STALE = 0x04
NUD_DELAY = 0x08
NUD_PROBE = 0x10
NUD_FAILED = 0x20
NUD_NOARP = 0x40
NUD_PERMANENT = 0x80
)
// Neighbor Flags
const (
NTF_USE = 0x01
NTF_SELF = 0x02
NTF_MASTER = 0x04
NTF_PROXY = 0x08
NTF_ROUTER = 0x80
)
type Ndmsg struct {
Family uint8
Index uint32
State uint16
Flags uint8
Type uint8
}
func deserializeNdmsg(b []byte) *Ndmsg {
var dummy Ndmsg
return (*Ndmsg)(unsafe.Pointer(&b[0:unsafe.Sizeof(dummy)][0]))
}
func (msg *Ndmsg) Serialize() []byte {
return (*(*[unsafe.Sizeof(*msg)]byte)(unsafe.Pointer(msg)))[:]
}
func (msg *Ndmsg) Len() int {
return int(unsafe.Sizeof(*msg))
}
// NeighAdd will add an IP to MAC mapping to the ARP table
// Equivalent to: `ip neigh add ....`
func NeighAdd(neigh *Neigh) error {
return neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL)
}
// NeighSet will add or replace an IP to MAC mapping to the ARP table
// Equivalent to: `ip neigh replace....`
func NeighSet(neigh *Neigh) error {
return neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_REPLACE)
}
// NeighAppend will append an entry to FDB
// Equivalent to: `bridge fdb append...`
func NeighAppend(neigh *Neigh) error {
return neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_APPEND)
}
func neighAdd(neigh *Neigh, mode int) error {
req := nl.NewNetlinkRequest(syscall.RTM_NEWNEIGH, mode|syscall.NLM_F_ACK)
return neighHandle(neigh, req)
}
// NeighDel will delete an IP address from a link device.
// Equivalent to: `ip addr del $addr dev $link`
func NeighDel(neigh *Neigh) error {
req := nl.NewNetlinkRequest(syscall.RTM_DELNEIGH, syscall.NLM_F_ACK)
return neighHandle(neigh, req)
}
func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
var family int
if neigh.Family > 0 {
family = neigh.Family
} else {
family = nl.GetIPFamily(neigh.IP)
}
msg := Ndmsg{
Family: uint8(family),
Index: uint32(neigh.LinkIndex),
State: uint16(neigh.State),
Type: uint8(neigh.Type),
Flags: uint8(neigh.Flags),
}
req.AddData(&msg)
ipData := neigh.IP.To4()
if ipData == nil {
ipData = neigh.IP.To16()
}
dstData := nl.NewRtAttr(NDA_DST, ipData)
req.AddData(dstData)
hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
req.AddData(hwData)
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
return err
}
// NeighList gets a list of IP-MAC mappings in the system (ARP table).
// Equivalent to: `ip neighbor show`.
// The list can be filtered by link and ip family.
func NeighList(linkIndex, family int) ([]Neigh, error) {
req := nl.NewNetlinkRequest(syscall.RTM_GETNEIGH, syscall.NLM_F_DUMP)
msg := Ndmsg{
Family: uint8(family),
Index: uint32(linkIndex),
}
req.AddData(&msg)
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWNEIGH)
if err != nil {
return nil, err
}
var res []Neigh
for _, m := range msgs {
ndm := deserializeNdmsg(m)
if linkIndex != 0 && int(ndm.Index) != linkIndex {
// Ignore messages from other interfaces
continue
}
neigh, err := NeighDeserialize(m)
if err != nil {
continue
}
res = append(res, *neigh)
}
return res, nil
}
func NeighDeserialize(m []byte) (*Neigh, error) {
msg := deserializeNdmsg(m)
neigh := Neigh{
LinkIndex: int(msg.Index),
Family: int(msg.Family),
State: int(msg.State),
Type: int(msg.Type),
Flags: int(msg.Flags),
}
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
if err != nil {
return nil, err
}
for _, attr := range attrs {
switch attr.Attr.Type {
case NDA_DST:
neigh.IP = net.IP(attr.Value)
case NDA_LLADDR:
neigh.HardwareAddr = net.HardwareAddr(attr.Value)
}
}
return &neigh, nil
}

42
vendor/github.com/vishvananda/netlink/netlink.go generated vendored Normal file
View file

@ -0,0 +1,42 @@
// Package netlink provides a simple library for netlink. Netlink is
// the interface a user-space program in linux uses to communicate with
// the kernel. It can be used to add and remove interfaces, set up ip
// addresses and routes, and confiugre ipsec. Netlink communication
// requires elevated privileges, so in most cases this code needs to
// be run as root. The low level primitives for netlink are contained
// in the nl subpackage. This package attempts to provide a high-level
// interface that is loosly modeled on the iproute2 cli.
package netlink
import (
"net"
"github.com/vishvananda/netlink/nl"
)
// Family type definitions
const (
FAMILY_ALL = nl.FAMILY_ALL
FAMILY_V4 = nl.FAMILY_V4
FAMILY_V6 = nl.FAMILY_V6
)
// ParseIPNet parses a string in ip/net format and returns a net.IPNet.
// This is valuable because addresses in netlink are often IPNets and
// ParseCIDR returns an IPNet with the IP part set to the base IP of the
// range.
func ParseIPNet(s string) (*net.IPNet, error) {
ip, ipNet, err := net.ParseCIDR(s)
if err != nil {
return nil, err
}
return &net.IPNet{IP: ip, Mask: ipNet.Mask}, nil
}
// NewIPNet generates an IPNet from an ip address using a netmask of 32 or 128.
func NewIPNet(ip net.IP) *net.IPNet {
if ip.To4() != nil {
return &net.IPNet{IP: ip, Mask: net.CIDRMask(32, 32)}
}
return &net.IPNet{IP: ip, Mask: net.CIDRMask(128, 128)}
}

View file

@ -0,0 +1,143 @@
// +build !linux
package netlink
import (
"errors"
)
var (
ErrNotImplemented = errors.New("not implemented")
)
func LinkSetUp(link *Link) error {
return ErrNotImplemented
}
func LinkSetDown(link *Link) error {
return ErrNotImplemented
}
func LinkSetMTU(link *Link, mtu int) error {
return ErrNotImplemented
}
func LinkSetMaster(link *Link, master *Link) error {
return ErrNotImplemented
}
func LinkSetNsPid(link *Link, nspid int) error {
return ErrNotImplemented
}
func LinkSetNsFd(link *Link, fd int) error {
return ErrNotImplemented
}
func LinkAdd(link *Link) error {
return ErrNotImplemented
}
func LinkDel(link *Link) error {
return ErrNotImplemented
}
func SetHairpin(link Link, mode bool) error {
return ErrNotImplemented
}
func SetGuard(link Link, mode bool) error {
return ErrNotImplemented
}
func SetFastLeave(link Link, mode bool) error {
return ErrNotImplemented
}
func SetLearning(link Link, mode bool) error {
return ErrNotImplemented
}
func SetRootBlock(link Link, mode bool) error {
return ErrNotImplemented
}
func SetFlood(link Link, mode bool) error {
return ErrNotImplemented
}
func LinkList() ([]Link, error) {
return nil, ErrNotImplemented
}
func AddrAdd(link *Link, addr *Addr) error {
return ErrNotImplemented
}
func AddrDel(link *Link, addr *Addr) error {
return ErrNotImplemented
}
func AddrList(link *Link, family int) ([]Addr, error) {
return nil, ErrNotImplemented
}
func RouteAdd(route *Route) error {
return ErrNotImplemented
}
func RouteDel(route *Route) error {
return ErrNotImplemented
}
func RouteList(link *Link, family int) ([]Route, error) {
return nil, ErrNotImplemented
}
func XfrmPolicyAdd(policy *XfrmPolicy) error {
return ErrNotImplemented
}
func XfrmPolicyDel(policy *XfrmPolicy) error {
return ErrNotImplemented
}
func XfrmPolicyList(family int) ([]XfrmPolicy, error) {
return nil, ErrNotImplemented
}
func XfrmStateAdd(policy *XfrmState) error {
return ErrNotImplemented
}
func XfrmStateDel(policy *XfrmState) error {
return ErrNotImplemented
}
func XfrmStateList(family int) ([]XfrmState, error) {
return nil, ErrNotImplemented
}
func NeighAdd(neigh *Neigh) error {
return ErrNotImplemented
}
func NeighSet(neigh *Neigh) error {
return ErrNotImplemented
}
func NeighAppend(neigh *Neigh) error {
return ErrNotImplemented
}
func NeighDel(neigh *Neigh) error {
return ErrNotImplemented
}
func NeighList(linkIndex, family int) ([]Neigh, error) {
return nil, ErrNotImplemented
}
func NeighDeserialize(m []byte) (*Ndmsg, *Neigh, error) {
return nil, nil, ErrNotImplemented
}

47
vendor/github.com/vishvananda/netlink/nl/addr_linux.go generated vendored Normal file
View file

@ -0,0 +1,47 @@
package nl
import (
"syscall"
"unsafe"
)
type IfAddrmsg struct {
syscall.IfAddrmsg
}
func NewIfAddrmsg(family int) *IfAddrmsg {
return &IfAddrmsg{
IfAddrmsg: syscall.IfAddrmsg{
Family: uint8(family),
},
}
}
// struct ifaddrmsg {
// __u8 ifa_family;
// __u8 ifa_prefixlen; /* The prefix length */
// __u8 ifa_flags; /* Flags */
// __u8 ifa_scope; /* Address scope */
// __u32 ifa_index; /* Link index */
// };
// type IfAddrmsg struct {
// Family uint8
// Prefixlen uint8
// Flags uint8
// Scope uint8
// Index uint32
// }
// SizeofIfAddrmsg = 0x8
func DeserializeIfAddrmsg(b []byte) *IfAddrmsg {
return (*IfAddrmsg)(unsafe.Pointer(&b[0:syscall.SizeofIfAddrmsg][0]))
}
func (msg *IfAddrmsg) Serialize() []byte {
return (*(*[syscall.SizeofIfAddrmsg]byte)(unsafe.Pointer(msg)))[:]
}
func (msg *IfAddrmsg) Len() int {
return syscall.SizeofIfAddrmsg
}

396
vendor/github.com/vishvananda/netlink/nl/link_linux.go generated vendored Normal file
View file

@ -0,0 +1,396 @@
package nl
import (
"unsafe"
)
const (
DEFAULT_CHANGE = 0xFFFFFFFF
// doesn't exist in syscall
IFLA_VFINFO_LIST = 0x16
)
const (
IFLA_INFO_UNSPEC = iota
IFLA_INFO_KIND
IFLA_INFO_DATA
IFLA_INFO_XSTATS
IFLA_INFO_MAX = IFLA_INFO_XSTATS
)
const (
IFLA_VLAN_UNSPEC = iota
IFLA_VLAN_ID
IFLA_VLAN_FLAGS
IFLA_VLAN_EGRESS_QOS
IFLA_VLAN_INGRESS_QOS
IFLA_VLAN_PROTOCOL
IFLA_VLAN_MAX = IFLA_VLAN_PROTOCOL
)
const (
VETH_INFO_UNSPEC = iota
VETH_INFO_PEER
VETH_INFO_MAX = VETH_INFO_PEER
)
const (
IFLA_VXLAN_UNSPEC = iota
IFLA_VXLAN_ID
IFLA_VXLAN_GROUP
IFLA_VXLAN_LINK
IFLA_VXLAN_LOCAL
IFLA_VXLAN_TTL
IFLA_VXLAN_TOS
IFLA_VXLAN_LEARNING
IFLA_VXLAN_AGEING
IFLA_VXLAN_LIMIT
IFLA_VXLAN_PORT_RANGE
IFLA_VXLAN_PROXY
IFLA_VXLAN_RSC
IFLA_VXLAN_L2MISS
IFLA_VXLAN_L3MISS
IFLA_VXLAN_PORT
IFLA_VXLAN_GROUP6
IFLA_VXLAN_LOCAL6
IFLA_VXLAN_UDP_CSUM
IFLA_VXLAN_UDP_ZERO_CSUM6_TX
IFLA_VXLAN_UDP_ZERO_CSUM6_RX
IFLA_VXLAN_REMCSUM_TX
IFLA_VXLAN_REMCSUM_RX
IFLA_VXLAN_GBP
IFLA_VXLAN_REMCSUM_NOPARTIAL
IFLA_VXLAN_FLOWBASED
IFLA_VXLAN_MAX = IFLA_VXLAN_FLOWBASED
)
const (
BRIDGE_MODE_UNSPEC = iota
BRIDGE_MODE_HAIRPIN
)
const (
IFLA_BRPORT_UNSPEC = iota
IFLA_BRPORT_STATE
IFLA_BRPORT_PRIORITY
IFLA_BRPORT_COST
IFLA_BRPORT_MODE
IFLA_BRPORT_GUARD
IFLA_BRPORT_PROTECT
IFLA_BRPORT_FAST_LEAVE
IFLA_BRPORT_LEARNING
IFLA_BRPORT_UNICAST_FLOOD
IFLA_BRPORT_MAX = IFLA_BRPORT_UNICAST_FLOOD
)
const (
IFLA_IPVLAN_UNSPEC = iota
IFLA_IPVLAN_MODE
IFLA_IPVLAN_MAX = IFLA_IPVLAN_MODE
)
const (
// not defined in syscall
IFLA_NET_NS_FD = 28
)
const (
IFLA_MACVLAN_UNSPEC = iota
IFLA_MACVLAN_MODE
IFLA_MACVLAN_FLAGS
IFLA_MACVLAN_MAX = IFLA_MACVLAN_FLAGS
)
const (
MACVLAN_MODE_PRIVATE = 1
MACVLAN_MODE_VEPA = 2
MACVLAN_MODE_BRIDGE = 4
MACVLAN_MODE_PASSTHRU = 8
MACVLAN_MODE_SOURCE = 16
)
const (
IFLA_BOND_UNSPEC = iota
IFLA_BOND_MODE
IFLA_BOND_ACTIVE_SLAVE
IFLA_BOND_MIIMON
IFLA_BOND_UPDELAY
IFLA_BOND_DOWNDELAY
IFLA_BOND_USE_CARRIER
IFLA_BOND_ARP_INTERVAL
IFLA_BOND_ARP_IP_TARGET
IFLA_BOND_ARP_VALIDATE
IFLA_BOND_ARP_ALL_TARGETS
IFLA_BOND_PRIMARY
IFLA_BOND_PRIMARY_RESELECT
IFLA_BOND_FAIL_OVER_MAC
IFLA_BOND_XMIT_HASH_POLICY
IFLA_BOND_RESEND_IGMP
IFLA_BOND_NUM_PEER_NOTIF
IFLA_BOND_ALL_SLAVES_ACTIVE
IFLA_BOND_MIN_LINKS
IFLA_BOND_LP_INTERVAL
IFLA_BOND_PACKETS_PER_SLAVE
IFLA_BOND_AD_LACP_RATE
IFLA_BOND_AD_SELECT
IFLA_BOND_AD_INFO
)
const (
IFLA_BOND_AD_INFO_UNSPEC = iota
IFLA_BOND_AD_INFO_AGGREGATOR
IFLA_BOND_AD_INFO_NUM_PORTS
IFLA_BOND_AD_INFO_ACTOR_KEY
IFLA_BOND_AD_INFO_PARTNER_KEY
IFLA_BOND_AD_INFO_PARTNER_MAC
)
const (
IFLA_BOND_SLAVE_UNSPEC = iota
IFLA_BOND_SLAVE_STATE
IFLA_BOND_SLAVE_MII_STATUS
IFLA_BOND_SLAVE_LINK_FAILURE_COUNT
IFLA_BOND_SLAVE_PERM_HWADDR
IFLA_BOND_SLAVE_QUEUE_ID
IFLA_BOND_SLAVE_AD_AGGREGATOR_ID
)
const (
IFLA_GRE_UNSPEC = iota
IFLA_GRE_LINK
IFLA_GRE_IFLAGS
IFLA_GRE_OFLAGS
IFLA_GRE_IKEY
IFLA_GRE_OKEY
IFLA_GRE_LOCAL
IFLA_GRE_REMOTE
IFLA_GRE_TTL
IFLA_GRE_TOS
IFLA_GRE_PMTUDISC
IFLA_GRE_ENCAP_LIMIT
IFLA_GRE_FLOWINFO
IFLA_GRE_FLAGS
IFLA_GRE_ENCAP_TYPE
IFLA_GRE_ENCAP_FLAGS
IFLA_GRE_ENCAP_SPORT
IFLA_GRE_ENCAP_DPORT
IFLA_GRE_COLLECT_METADATA
IFLA_GRE_MAX = IFLA_GRE_COLLECT_METADATA
)
const (
GRE_CSUM = 0x8000
GRE_ROUTING = 0x4000
GRE_KEY = 0x2000
GRE_SEQ = 0x1000
GRE_STRICT = 0x0800
GRE_REC = 0x0700
GRE_FLAGS = 0x00F8
GRE_VERSION = 0x0007
)
const (
IFLA_VF_INFO_UNSPEC = iota
IFLA_VF_INFO
IFLA_VF_INFO_MAX = IFLA_VF_INFO
)
const (
IFLA_VF_UNSPEC = iota
IFLA_VF_MAC /* Hardware queue specific attributes */
IFLA_VF_VLAN
IFLA_VF_TX_RATE /* Max TX Bandwidth Allocation */
IFLA_VF_SPOOFCHK /* Spoof Checking on/off switch */
IFLA_VF_LINK_STATE /* link state enable/disable/auto switch */
IFLA_VF_RATE /* Min and Max TX Bandwidth Allocation */
IFLA_VF_RSS_QUERY_EN /* RSS Redirection Table and Hash Key query
* on/off switch
*/
IFLA_VF_STATS /* network device statistics */
IFLA_VF_MAX = IFLA_VF_STATS
)
const (
IFLA_VF_LINK_STATE_AUTO = iota /* link state of the uplink */
IFLA_VF_LINK_STATE_ENABLE /* link always up */
IFLA_VF_LINK_STATE_DISABLE /* link always down */
IFLA_VF_LINK_STATE_MAX = IFLA_VF_LINK_STATE_DISABLE
)
const (
IFLA_VF_STATS_RX_PACKETS = iota
IFLA_VF_STATS_TX_PACKETS
IFLA_VF_STATS_RX_BYTES
IFLA_VF_STATS_TX_BYTES
IFLA_VF_STATS_BROADCAST
IFLA_VF_STATS_MULTICAST
IFLA_VF_STATS_MAX = IFLA_VF_STATS_MULTICAST
)
const (
SizeofVfMac = 0x24
SizeofVfVlan = 0x0c
SizeofVfTxRate = 0x08
SizeofVfRate = 0x0c
SizeofVfSpoofchk = 0x08
SizeofVfLinkState = 0x08
SizeofVfRssQueryEn = 0x08
)
// struct ifla_vf_mac {
// __u32 vf;
// __u8 mac[32]; /* MAX_ADDR_LEN */
// };
type VfMac struct {
Vf uint32
Mac [32]byte
}
func (msg *VfMac) Len() int {
return SizeofVfMac
}
func DeserializeVfMac(b []byte) *VfMac {
return (*VfMac)(unsafe.Pointer(&b[0:SizeofVfMac][0]))
}
func (msg *VfMac) Serialize() []byte {
return (*(*[SizeofVfMac]byte)(unsafe.Pointer(msg)))[:]
}
// struct ifla_vf_vlan {
// __u32 vf;
// __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */
// __u32 qos;
// };
type VfVlan struct {
Vf uint32
Vlan uint32
Qos uint32
}
func (msg *VfVlan) Len() int {
return SizeofVfVlan
}
func DeserializeVfVlan(b []byte) *VfVlan {
return (*VfVlan)(unsafe.Pointer(&b[0:SizeofVfVlan][0]))
}
func (msg *VfVlan) Serialize() []byte {
return (*(*[SizeofVfVlan]byte)(unsafe.Pointer(msg)))[:]
}
// struct ifla_vf_tx_rate {
// __u32 vf;
// __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */
// };
type VfTxRate struct {
Vf uint32
Rate uint32
}
func (msg *VfTxRate) Len() int {
return SizeofVfTxRate
}
func DeserializeVfTxRate(b []byte) *VfTxRate {
return (*VfTxRate)(unsafe.Pointer(&b[0:SizeofVfTxRate][0]))
}
func (msg *VfTxRate) Serialize() []byte {
return (*(*[SizeofVfTxRate]byte)(unsafe.Pointer(msg)))[:]
}
// struct ifla_vf_rate {
// __u32 vf;
// __u32 min_tx_rate; /* Min Bandwidth in Mbps */
// __u32 max_tx_rate; /* Max Bandwidth in Mbps */
// };
type VfRate struct {
Vf uint32
MinTxRate uint32
MaxTxRate uint32
}
func (msg *VfRate) Len() int {
return SizeofVfRate
}
func DeserializeVfRate(b []byte) *VfRate {
return (*VfRate)(unsafe.Pointer(&b[0:SizeofVfRate][0]))
}
func (msg *VfRate) Serialize() []byte {
return (*(*[SizeofVfRate]byte)(unsafe.Pointer(msg)))[:]
}
// struct ifla_vf_spoofchk {
// __u32 vf;
// __u32 setting;
// };
type VfSpoofchk struct {
Vf uint32
Setting uint32
}
func (msg *VfSpoofchk) Len() int {
return SizeofVfSpoofchk
}
func DeserializeVfSpoofchk(b []byte) *VfSpoofchk {
return (*VfSpoofchk)(unsafe.Pointer(&b[0:SizeofVfSpoofchk][0]))
}
func (msg *VfSpoofchk) Serialize() []byte {
return (*(*[SizeofVfSpoofchk]byte)(unsafe.Pointer(msg)))[:]
}
// struct ifla_vf_link_state {
// __u32 vf;
// __u32 link_state;
// };
type VfLinkState struct {
Vf uint32
LinkState uint32
}
func (msg *VfLinkState) Len() int {
return SizeofVfLinkState
}
func DeserializeVfLinkState(b []byte) *VfLinkState {
return (*VfLinkState)(unsafe.Pointer(&b[0:SizeofVfLinkState][0]))
}
func (msg *VfLinkState) Serialize() []byte {
return (*(*[SizeofVfLinkState]byte)(unsafe.Pointer(msg)))[:]
}
// struct ifla_vf_rss_query_en {
// __u32 vf;
// __u32 setting;
// };
type VfRssQueryEn struct {
Vf uint32
Setting uint32
}
func (msg *VfRssQueryEn) Len() int {
return SizeofVfRssQueryEn
}
func DeserializeVfRssQueryEn(b []byte) *VfRssQueryEn {
return (*VfRssQueryEn)(unsafe.Pointer(&b[0:SizeofVfRssQueryEn][0]))
}
func (msg *VfRssQueryEn) Serialize() []byte {
return (*(*[SizeofVfRssQueryEn]byte)(unsafe.Pointer(msg)))[:]
}

424
vendor/github.com/vishvananda/netlink/nl/nl_linux.go generated vendored Normal file
View file

@ -0,0 +1,424 @@
// Package nl has low level primitives for making Netlink calls.
package nl
import (
"bytes"
"encoding/binary"
"fmt"
"net"
"sync/atomic"
"syscall"
"unsafe"
)
const (
// Family type definitions
FAMILY_ALL = syscall.AF_UNSPEC
FAMILY_V4 = syscall.AF_INET
FAMILY_V6 = syscall.AF_INET6
)
var nextSeqNr uint32
// GetIPFamily returns the family type of a net.IP.
func GetIPFamily(ip net.IP) int {
if len(ip) <= net.IPv4len {
return FAMILY_V4
}
if ip.To4() != nil {
return FAMILY_V4
}
return FAMILY_V6
}
var nativeEndian binary.ByteOrder
// Get native endianness for the system
func NativeEndian() binary.ByteOrder {
if nativeEndian == nil {
var x uint32 = 0x01020304
if *(*byte)(unsafe.Pointer(&x)) == 0x01 {
nativeEndian = binary.BigEndian
} else {
nativeEndian = binary.LittleEndian
}
}
return nativeEndian
}
// Byte swap a 16 bit value if we aren't big endian
func Swap16(i uint16) uint16 {
if NativeEndian() == binary.BigEndian {
return i
}
return (i&0xff00)>>8 | (i&0xff)<<8
}
// Byte swap a 32 bit value if aren't big endian
func Swap32(i uint32) uint32 {
if NativeEndian() == binary.BigEndian {
return i
}
return (i&0xff000000)>>24 | (i&0xff0000)>>8 | (i&0xff00)<<8 | (i&0xff)<<24
}
type NetlinkRequestData interface {
Len() int
Serialize() []byte
}
// IfInfomsg is related to links, but it is used for list requests as well
type IfInfomsg struct {
syscall.IfInfomsg
}
// Create an IfInfomsg with family specified
func NewIfInfomsg(family int) *IfInfomsg {
return &IfInfomsg{
IfInfomsg: syscall.IfInfomsg{
Family: uint8(family),
},
}
}
func DeserializeIfInfomsg(b []byte) *IfInfomsg {
return (*IfInfomsg)(unsafe.Pointer(&b[0:syscall.SizeofIfInfomsg][0]))
}
func (msg *IfInfomsg) Serialize() []byte {
return (*(*[syscall.SizeofIfInfomsg]byte)(unsafe.Pointer(msg)))[:]
}
func (msg *IfInfomsg) Len() int {
return syscall.SizeofIfInfomsg
}
func rtaAlignOf(attrlen int) int {
return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1)
}
func NewIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg {
msg := NewIfInfomsg(family)
parent.children = append(parent.children, msg)
return msg
}
// Extend RtAttr to handle data and children
type RtAttr struct {
syscall.RtAttr
Data []byte
children []NetlinkRequestData
}
// Create a new Extended RtAttr object
func NewRtAttr(attrType int, data []byte) *RtAttr {
return &RtAttr{
RtAttr: syscall.RtAttr{
Type: uint16(attrType),
},
children: []NetlinkRequestData{},
Data: data,
}
}
// Create a new RtAttr obj anc add it as a child of an existing object
func NewRtAttrChild(parent *RtAttr, attrType int, data []byte) *RtAttr {
attr := NewRtAttr(attrType, data)
parent.children = append(parent.children, attr)
return attr
}
func (a *RtAttr) Len() int {
if len(a.children) == 0 {
return (syscall.SizeofRtAttr + len(a.Data))
}
l := 0
for _, child := range a.children {
l += rtaAlignOf(child.Len())
}
l += syscall.SizeofRtAttr
return rtaAlignOf(l + len(a.Data))
}
// Serialize the RtAttr into a byte array
// This can't just unsafe.cast because it must iterate through children.
func (a *RtAttr) Serialize() []byte {
native := NativeEndian()
length := a.Len()
buf := make([]byte, rtaAlignOf(length))
next := 4
if a.Data != nil {
copy(buf[next:], a.Data)
next += rtaAlignOf(len(a.Data))
}
if len(a.children) > 0 {
for _, child := range a.children {
childBuf := child.Serialize()
copy(buf[next:], childBuf)
next += rtaAlignOf(len(childBuf))
}
}
if l := uint16(length); l != 0 {
native.PutUint16(buf[0:2], l)
}
native.PutUint16(buf[2:4], a.Type)
return buf
}
type NetlinkRequest struct {
syscall.NlMsghdr
Data []NetlinkRequestData
}
// Serialize the Netlink Request into a byte array
func (req *NetlinkRequest) Serialize() []byte {
length := syscall.SizeofNlMsghdr
dataBytes := make([][]byte, len(req.Data))
for i, data := range req.Data {
dataBytes[i] = data.Serialize()
length = length + len(dataBytes[i])
}
req.Len = uint32(length)
b := make([]byte, length)
hdr := (*(*[syscall.SizeofNlMsghdr]byte)(unsafe.Pointer(req)))[:]
next := syscall.SizeofNlMsghdr
copy(b[0:next], hdr)
for _, data := range dataBytes {
for _, dataByte := range data {
b[next] = dataByte
next = next + 1
}
}
return b
}
func (req *NetlinkRequest) AddData(data NetlinkRequestData) {
if data != nil {
req.Data = append(req.Data, data)
}
}
// Execute the request against a the given sockType.
// Returns a list of netlink messages in seriaized format, optionally filtered
// by resType.
func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, error) {
s, err := getNetlinkSocket(sockType)
if err != nil {
return nil, err
}
defer s.Close()
if err := s.Send(req); err != nil {
return nil, err
}
pid, err := s.GetPid()
if err != nil {
return nil, err
}
var res [][]byte
done:
for {
msgs, err := s.Receive()
if err != nil {
return nil, err
}
for _, m := range msgs {
if m.Header.Seq != req.Seq {
return nil, fmt.Errorf("Wrong Seq nr %d, expected 1", m.Header.Seq)
}
if m.Header.Pid != pid {
return nil, fmt.Errorf("Wrong pid %d, expected %d", m.Header.Pid, pid)
}
if m.Header.Type == syscall.NLMSG_DONE {
break done
}
if m.Header.Type == syscall.NLMSG_ERROR {
native := NativeEndian()
error := int32(native.Uint32(m.Data[0:4]))
if error == 0 {
break done
}
return nil, syscall.Errno(-error)
}
if resType != 0 && m.Header.Type != resType {
continue
}
res = append(res, m.Data)
if m.Header.Flags&syscall.NLM_F_MULTI == 0 {
break done
}
}
}
return res, nil
}
// Create a new netlink request from proto and flags
// Note the Len value will be inaccurate once data is added until
// the message is serialized
func NewNetlinkRequest(proto, flags int) *NetlinkRequest {
return &NetlinkRequest{
NlMsghdr: syscall.NlMsghdr{
Len: uint32(syscall.SizeofNlMsghdr),
Type: uint16(proto),
Flags: syscall.NLM_F_REQUEST | uint16(flags),
Seq: atomic.AddUint32(&nextSeqNr, 1),
},
}
}
type NetlinkSocket struct {
fd int
lsa syscall.SockaddrNetlink
}
func getNetlinkSocket(protocol int) (*NetlinkSocket, error) {
fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, protocol)
if err != nil {
return nil, err
}
s := &NetlinkSocket{
fd: fd,
}
s.lsa.Family = syscall.AF_NETLINK
if err := syscall.Bind(fd, &s.lsa); err != nil {
syscall.Close(fd)
return nil, err
}
return s, nil
}
// Create a netlink socket with a given protocol (e.g. NETLINK_ROUTE)
// and subscribe it to multicast groups passed in variable argument list.
// Returns the netlink socket on which Receive() method can be called
// to retrieve the messages from the kernel.
func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, protocol)
if err != nil {
return nil, err
}
s := &NetlinkSocket{
fd: fd,
}
s.lsa.Family = syscall.AF_NETLINK
for _, g := range groups {
s.lsa.Groups |= (1 << (g - 1))
}
if err := syscall.Bind(fd, &s.lsa); err != nil {
syscall.Close(fd)
return nil, err
}
return s, nil
}
func (s *NetlinkSocket) Close() {
syscall.Close(s.fd)
}
func (s *NetlinkSocket) GetFd() int {
return s.fd
}
func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
if err := syscall.Sendto(s.fd, request.Serialize(), 0, &s.lsa); err != nil {
return err
}
return nil
}
func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) {
rb := make([]byte, syscall.Getpagesize())
nr, _, err := syscall.Recvfrom(s.fd, rb, 0)
if err != nil {
return nil, err
}
if nr < syscall.NLMSG_HDRLEN {
return nil, fmt.Errorf("Got short response from netlink")
}
rb = rb[:nr]
return syscall.ParseNetlinkMessage(rb)
}
func (s *NetlinkSocket) GetPid() (uint32, error) {
lsa, err := syscall.Getsockname(s.fd)
if err != nil {
return 0, err
}
switch v := lsa.(type) {
case *syscall.SockaddrNetlink:
return v.Pid, nil
}
return 0, fmt.Errorf("Wrong socket type")
}
func ZeroTerminated(s string) []byte {
bytes := make([]byte, len(s)+1)
for i := 0; i < len(s); i++ {
bytes[i] = s[i]
}
bytes[len(s)] = 0
return bytes
}
func NonZeroTerminated(s string) []byte {
bytes := make([]byte, len(s))
for i := 0; i < len(s); i++ {
bytes[i] = s[i]
}
return bytes
}
func BytesToString(b []byte) string {
n := bytes.Index(b, []byte{0})
return string(b[:n])
}
func Uint8Attr(v uint8) []byte {
return []byte{byte(v)}
}
func Uint16Attr(v uint16) []byte {
native := NativeEndian()
bytes := make([]byte, 2)
native.PutUint16(bytes, v)
return bytes
}
func Uint32Attr(v uint32) []byte {
native := NativeEndian()
bytes := make([]byte, 4)
native.PutUint32(bytes, v)
return bytes
}
func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) {
var attrs []syscall.NetlinkRouteAttr
for len(b) >= syscall.SizeofRtAttr {
a, vbuf, alen, err := netlinkRouteAttrAndValue(b)
if err != nil {
return nil, err
}
ra := syscall.NetlinkRouteAttr{Attr: *a, Value: vbuf[:int(a.Len)-syscall.SizeofRtAttr]}
attrs = append(attrs, ra)
b = b[alen:]
}
return attrs, nil
}
func netlinkRouteAttrAndValue(b []byte) (*syscall.RtAttr, []byte, int, error) {
a := (*syscall.RtAttr)(unsafe.Pointer(&b[0]))
if int(a.Len) < syscall.SizeofRtAttr || int(a.Len) > len(b) {
return nil, nil, 0, syscall.EINVAL
}
return a, b[syscall.SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil
}

View file

@ -0,0 +1,42 @@
package nl
import (
"syscall"
"unsafe"
)
type RtMsg struct {
syscall.RtMsg
}
func NewRtMsg() *RtMsg {
return &RtMsg{
RtMsg: syscall.RtMsg{
Table: syscall.RT_TABLE_MAIN,
Scope: syscall.RT_SCOPE_UNIVERSE,
Protocol: syscall.RTPROT_BOOT,
Type: syscall.RTN_UNICAST,
},
}
}
func NewRtDelMsg() *RtMsg {
return &RtMsg{
RtMsg: syscall.RtMsg{
Table: syscall.RT_TABLE_MAIN,
Scope: syscall.RT_SCOPE_NOWHERE,
},
}
}
func (msg *RtMsg) Len() int {
return syscall.SizeofRtMsg
}
func DeserializeRtMsg(b []byte) *RtMsg {
return (*RtMsg)(unsafe.Pointer(&b[0:syscall.SizeofRtMsg][0]))
}
func (msg *RtMsg) Serialize() []byte {
return (*(*[syscall.SizeofRtMsg]byte)(unsafe.Pointer(msg)))[:]
}

37
vendor/github.com/vishvananda/netlink/nl/syscall.go generated vendored Normal file
View file

@ -0,0 +1,37 @@
package nl
// syscall package lack of rule atributes type.
// Thus there are defined below
const (
FRA_UNSPEC = iota
FRA_DST /* destination address */
FRA_SRC /* source address */
FRA_IIFNAME /* interface name */
FRA_GOTO /* target to jump to (FR_ACT_GOTO) */
FRA_UNUSED2
FRA_PRIORITY /* priority/preference */
FRA_UNUSED3
FRA_UNUSED4
FRA_UNUSED5
FRA_FWMARK /* mark */
FRA_FLOW /* flow/class id */
FRA_TUN_ID
FRA_SUPPRESS_IFGROUP
FRA_SUPPRESS_PREFIXLEN
FRA_TABLE /* Extended table id */
FRA_FWMASK /* mask for netfilter mark */
FRA_OIFNAME
)
// ip rule netlink request types
const (
FR_ACT_UNSPEC = iota
FR_ACT_TO_TBL /* Pass to fixed table */
FR_ACT_GOTO /* Jump to another rule */
FR_ACT_NOP /* No operation */
FR_ACT_RES3
FR_ACT_RES4
FR_ACT_BLACKHOLE /* Drop without notification */
FR_ACT_UNREACHABLE /* Drop with ENETUNREACH */
FR_ACT_PROHIBIT /* Drop with EACCES */
)

686
vendor/github.com/vishvananda/netlink/nl/tc_linux.go generated vendored Normal file
View file

@ -0,0 +1,686 @@
package nl
import (
"unsafe"
)
// LinkLayer
const (
LINKLAYER_UNSPEC = iota
LINKLAYER_ETHERNET
LINKLAYER_ATM
)
// ATM
const (
ATM_CELL_PAYLOAD = 48
ATM_CELL_SIZE = 53
)
const TC_LINKLAYER_MASK = 0x0F
// Police
const (
TCA_POLICE_UNSPEC = iota
TCA_POLICE_TBF
TCA_POLICE_RATE
TCA_POLICE_PEAKRATE
TCA_POLICE_AVRATE
TCA_POLICE_RESULT
TCA_POLICE_MAX = TCA_POLICE_RESULT
)
// Message types
const (
TCA_UNSPEC = iota
TCA_KIND
TCA_OPTIONS
TCA_STATS
TCA_XSTATS
TCA_RATE
TCA_FCNT
TCA_STATS2
TCA_STAB
TCA_MAX = TCA_STAB
)
const (
TCA_ACT_TAB = 1
TCAA_MAX = 1
)
const (
TCA_ACT_UNSPEC = iota
TCA_ACT_KIND
TCA_ACT_OPTIONS
TCA_ACT_INDEX
TCA_ACT_STATS
TCA_ACT_MAX
)
const (
TCA_PRIO_UNSPEC = iota
TCA_PRIO_MQ
TCA_PRIO_MAX = TCA_PRIO_MQ
)
const (
SizeofTcMsg = 0x14
SizeofTcActionMsg = 0x04
SizeofTcPrioMap = 0x14
SizeofTcRateSpec = 0x0c
SizeofTcNetemQopt = 0x18
SizeofTcNetemCorr = 0x0c
SizeofTcNetemReorder = 0x08
SizeofTcNetemCorrupt = 0x08
SizeofTcTbfQopt = 2*SizeofTcRateSpec + 0x0c
SizeofTcHtbCopt = 2*SizeofTcRateSpec + 0x14
SizeofTcHtbGlob = 0x14
SizeofTcU32Key = 0x10
SizeofTcU32Sel = 0x10 // without keys
SizeofTcActBpf = 0x14
SizeofTcMirred = 0x1c
SizeofTcPolice = 2*SizeofTcRateSpec + 0x20
)
// struct tcmsg {
// unsigned char tcm_family;
// unsigned char tcm__pad1;
// unsigned short tcm__pad2;
// int tcm_ifindex;
// __u32 tcm_handle;
// __u32 tcm_parent;
// __u32 tcm_info;
// };
type TcMsg struct {
Family uint8
Pad [3]byte
Ifindex int32
Handle uint32
Parent uint32
Info uint32
}
func (msg *TcMsg) Len() int {
return SizeofTcMsg
}
func DeserializeTcMsg(b []byte) *TcMsg {
return (*TcMsg)(unsafe.Pointer(&b[0:SizeofTcMsg][0]))
}
func (x *TcMsg) Serialize() []byte {
return (*(*[SizeofTcMsg]byte)(unsafe.Pointer(x)))[:]
}
// struct tcamsg {
// unsigned char tca_family;
// unsigned char tca__pad1;
// unsigned short tca__pad2;
// };
type TcActionMsg struct {
Family uint8
Pad [3]byte
}
func (msg *TcActionMsg) Len() int {
return SizeofTcActionMsg
}
func DeserializeTcActionMsg(b []byte) *TcActionMsg {
return (*TcActionMsg)(unsafe.Pointer(&b[0:SizeofTcActionMsg][0]))
}
func (x *TcActionMsg) Serialize() []byte {
return (*(*[SizeofTcActionMsg]byte)(unsafe.Pointer(x)))[:]
}
const (
TC_PRIO_MAX = 15
)
// struct tc_prio_qopt {
// int bands; /* Number of bands */
// __u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */
// };
type TcPrioMap struct {
Bands int32
Priomap [TC_PRIO_MAX + 1]uint8
}
func (msg *TcPrioMap) Len() int {
return SizeofTcPrioMap
}
func DeserializeTcPrioMap(b []byte) *TcPrioMap {
return (*TcPrioMap)(unsafe.Pointer(&b[0:SizeofTcPrioMap][0]))
}
func (x *TcPrioMap) Serialize() []byte {
return (*(*[SizeofTcPrioMap]byte)(unsafe.Pointer(x)))[:]
}
const (
TCA_TBF_UNSPEC = iota
TCA_TBF_PARMS
TCA_TBF_RTAB
TCA_TBF_PTAB
TCA_TBF_RATE64
TCA_TBF_PRATE64
TCA_TBF_BURST
TCA_TBF_PBURST
TCA_TBF_MAX = TCA_TBF_PBURST
)
// struct tc_ratespec {
// unsigned char cell_log;
// __u8 linklayer; /* lower 4 bits */
// unsigned short overhead;
// short cell_align;
// unsigned short mpu;
// __u32 rate;
// };
type TcRateSpec struct {
CellLog uint8
Linklayer uint8
Overhead uint16
CellAlign int16
Mpu uint16
Rate uint32
}
func (msg *TcRateSpec) Len() int {
return SizeofTcRateSpec
}
func DeserializeTcRateSpec(b []byte) *TcRateSpec {
return (*TcRateSpec)(unsafe.Pointer(&b[0:SizeofTcRateSpec][0]))
}
func (x *TcRateSpec) Serialize() []byte {
return (*(*[SizeofTcRateSpec]byte)(unsafe.Pointer(x)))[:]
}
/**
* NETEM
*/
const (
TCA_NETEM_UNSPEC = iota
TCA_NETEM_CORR
TCA_NETEM_DELAY_DIST
TCA_NETEM_REORDER
TCA_NETEM_CORRUPT
TCA_NETEM_LOSS
TCA_NETEM_RATE
TCA_NETEM_ECN
TCA_NETEM_RATE64
TCA_NETEM_MAX = TCA_NETEM_RATE64
)
// struct tc_netem_qopt {
// __u32 latency; /* added delay (us) */
// __u32 limit; /* fifo limit (packets) */
// __u32 loss; /* random packet loss (0=none ~0=100%) */
// __u32 gap; /* re-ordering gap (0 for none) */
// __u32 duplicate; /* random packet dup (0=none ~0=100%) */
// __u32 jitter; /* random jitter in latency (us) */
// };
type TcNetemQopt struct {
Latency uint32
Limit uint32
Loss uint32
Gap uint32
Duplicate uint32
Jitter uint32
}
func (msg *TcNetemQopt) Len() int {
return SizeofTcNetemQopt
}
func DeserializeTcNetemQopt(b []byte) *TcNetemQopt {
return (*TcNetemQopt)(unsafe.Pointer(&b[0:SizeofTcNetemQopt][0]))
}
func (x *TcNetemQopt) Serialize() []byte {
return (*(*[SizeofTcNetemQopt]byte)(unsafe.Pointer(x)))[:]
}
// struct tc_netem_corr {
// __u32 delay_corr; /* delay correlation */
// __u32 loss_corr; /* packet loss correlation */
// __u32 dup_corr; /* duplicate correlation */
// };
type TcNetemCorr struct {
DelayCorr uint32
LossCorr uint32
DupCorr uint32
}
func (msg *TcNetemCorr) Len() int {
return SizeofTcNetemCorr
}
func DeserializeTcNetemCorr(b []byte) *TcNetemCorr {
return (*TcNetemCorr)(unsafe.Pointer(&b[0:SizeofTcNetemCorr][0]))
}
func (x *TcNetemCorr) Serialize() []byte {
return (*(*[SizeofTcNetemCorr]byte)(unsafe.Pointer(x)))[:]
}
// struct tc_netem_reorder {
// __u32 probability;
// __u32 correlation;
// };
type TcNetemReorder struct {
Probability uint32
Correlation uint32
}
func (msg *TcNetemReorder) Len() int {
return SizeofTcNetemReorder
}
func DeserializeTcNetemReorder(b []byte) *TcNetemReorder {
return (*TcNetemReorder)(unsafe.Pointer(&b[0:SizeofTcNetemReorder][0]))
}
func (x *TcNetemReorder) Serialize() []byte {
return (*(*[SizeofTcNetemReorder]byte)(unsafe.Pointer(x)))[:]
}
// struct tc_netem_corrupt {
// __u32 probability;
// __u32 correlation;
// };
type TcNetemCorrupt struct {
Probability uint32
Correlation uint32
}
func (msg *TcNetemCorrupt) Len() int {
return SizeofTcNetemCorrupt
}
func DeserializeTcNetemCorrupt(b []byte) *TcNetemCorrupt {
return (*TcNetemCorrupt)(unsafe.Pointer(&b[0:SizeofTcNetemCorrupt][0]))
}
func (x *TcNetemCorrupt) Serialize() []byte {
return (*(*[SizeofTcNetemCorrupt]byte)(unsafe.Pointer(x)))[:]
}
// struct tc_tbf_qopt {
// struct tc_ratespec rate;
// struct tc_ratespec peakrate;
// __u32 limit;
// __u32 buffer;
// __u32 mtu;
// };
type TcTbfQopt struct {
Rate TcRateSpec
Peakrate TcRateSpec
Limit uint32
Buffer uint32
Mtu uint32
}
func (msg *TcTbfQopt) Len() int {
return SizeofTcTbfQopt
}
func DeserializeTcTbfQopt(b []byte) *TcTbfQopt {
return (*TcTbfQopt)(unsafe.Pointer(&b[0:SizeofTcTbfQopt][0]))
}
func (x *TcTbfQopt) Serialize() []byte {
return (*(*[SizeofTcTbfQopt]byte)(unsafe.Pointer(x)))[:]
}
const (
TCA_HTB_UNSPEC = iota
TCA_HTB_PARMS
TCA_HTB_INIT
TCA_HTB_CTAB
TCA_HTB_RTAB
TCA_HTB_DIRECT_QLEN
TCA_HTB_RATE64
TCA_HTB_CEIL64
TCA_HTB_MAX = TCA_HTB_CEIL64
)
//struct tc_htb_opt {
// struct tc_ratespec rate;
// struct tc_ratespec ceil;
// __u32 buffer;
// __u32 cbuffer;
// __u32 quantum;
// __u32 level; /* out only */
// __u32 prio;
//};
type TcHtbCopt struct {
Rate TcRateSpec
Ceil TcRateSpec
Buffer uint32
Cbuffer uint32
Quantum uint32
Level uint32
Prio uint32
}
func (msg *TcHtbCopt) Len() int {
return SizeofTcHtbCopt
}
func DeserializeTcHtbCopt(b []byte) *TcHtbCopt {
return (*TcHtbCopt)(unsafe.Pointer(&b[0:SizeofTcHtbCopt][0]))
}
func (x *TcHtbCopt) Serialize() []byte {
return (*(*[SizeofTcHtbCopt]byte)(unsafe.Pointer(x)))[:]
}
type TcHtbGlob struct {
Version uint32
Rate2Quantum uint32
Defcls uint32
Debug uint32
DirectPkts uint32
}
func (msg *TcHtbGlob) Len() int {
return SizeofTcHtbGlob
}
func DeserializeTcHtbGlob(b []byte) *TcHtbGlob {
return (*TcHtbGlob)(unsafe.Pointer(&b[0:SizeofTcHtbGlob][0]))
}
func (x *TcHtbGlob) Serialize() []byte {
return (*(*[SizeofTcHtbGlob]byte)(unsafe.Pointer(x)))[:]
}
const (
TCA_U32_UNSPEC = iota
TCA_U32_CLASSID
TCA_U32_HASH
TCA_U32_LINK
TCA_U32_DIVISOR
TCA_U32_SEL
TCA_U32_POLICE
TCA_U32_ACT
TCA_U32_INDEV
TCA_U32_PCNT
TCA_U32_MARK
TCA_U32_MAX = TCA_U32_MARK
)
// struct tc_u32_key {
// __be32 mask;
// __be32 val;
// int off;
// int offmask;
// };
type TcU32Key struct {
Mask uint32 // big endian
Val uint32 // big endian
Off int32
OffMask int32
}
func (msg *TcU32Key) Len() int {
return SizeofTcU32Key
}
func DeserializeTcU32Key(b []byte) *TcU32Key {
return (*TcU32Key)(unsafe.Pointer(&b[0:SizeofTcU32Key][0]))
}
func (x *TcU32Key) Serialize() []byte {
return (*(*[SizeofTcU32Key]byte)(unsafe.Pointer(x)))[:]
}
// struct tc_u32_sel {
// unsigned char flags;
// unsigned char offshift;
// unsigned char nkeys;
//
// __be16 offmask;
// __u16 off;
// short offoff;
//
// short hoff;
// __be32 hmask;
// struct tc_u32_key keys[0];
// };
const (
TC_U32_TERMINAL = 1 << iota
TC_U32_OFFSET = 1 << iota
TC_U32_VAROFFSET = 1 << iota
TC_U32_EAT = 1 << iota
)
type TcU32Sel struct {
Flags uint8
Offshift uint8
Nkeys uint8
Pad uint8
Offmask uint16 // big endian
Off uint16
Offoff int16
Hoff int16
Hmask uint32 // big endian
Keys []TcU32Key
}
func (msg *TcU32Sel) Len() int {
return SizeofTcU32Sel + int(msg.Nkeys)*SizeofTcU32Key
}
func DeserializeTcU32Sel(b []byte) *TcU32Sel {
x := &TcU32Sel{}
copy((*(*[SizeofTcU32Sel]byte)(unsafe.Pointer(x)))[:], b)
next := SizeofTcU32Sel
var i uint8
for i = 0; i < x.Nkeys; i++ {
x.Keys = append(x.Keys, *DeserializeTcU32Key(b[next:]))
next += SizeofTcU32Key
}
return x
}
func (x *TcU32Sel) Serialize() []byte {
// This can't just unsafe.cast because it must iterate through keys.
buf := make([]byte, x.Len())
copy(buf, (*(*[SizeofTcU32Sel]byte)(unsafe.Pointer(x)))[:])
next := SizeofTcU32Sel
for _, key := range x.Keys {
keyBuf := key.Serialize()
copy(buf[next:], keyBuf)
next += SizeofTcU32Key
}
return buf
}
const (
TCA_ACT_MIRRED = 8
)
const (
TCA_MIRRED_UNSPEC = iota
TCA_MIRRED_TM
TCA_MIRRED_PARMS
TCA_MIRRED_MAX = TCA_MIRRED_PARMS
)
const (
TCA_EGRESS_REDIR = 1 /* packet redirect to EGRESS*/
TCA_EGRESS_MIRROR = 2 /* mirror packet to EGRESS */
TCA_INGRESS_REDIR = 3 /* packet redirect to INGRESS*/
TCA_INGRESS_MIRROR = 4 /* mirror packet to INGRESS */
)
const (
TC_ACT_UNSPEC = int32(-1)
TC_ACT_OK = 0
TC_ACT_RECLASSIFY = 1
TC_ACT_SHOT = 2
TC_ACT_PIPE = 3
TC_ACT_STOLEN = 4
TC_ACT_QUEUED = 5
TC_ACT_REPEAT = 6
TC_ACT_REDIRECT = 7
TC_ACT_JUMP = 0x10000000
)
type TcGen struct {
Index uint32
Capab uint32
Action int32
Refcnt int32
Bindcnt int32
}
type TcActBpf struct {
TcGen
}
func (msg *TcActBpf) Len() int {
return SizeofTcActBpf
}
func DeserializeTcActBpf(b []byte) *TcActBpf {
return (*TcActBpf)(unsafe.Pointer(&b[0:SizeofTcActBpf][0]))
}
func (x *TcActBpf) Serialize() []byte {
return (*(*[SizeofTcActBpf]byte)(unsafe.Pointer(x)))[:]
}
// #define tc_gen \
// __u32 index; \
// __u32 capab; \
// int action; \
// int refcnt; \
// int bindcnt
// struct tc_mirred {
// tc_gen;
// int eaction; /* one of IN/EGRESS_MIRROR/REDIR */
// __u32 ifindex; /* ifindex of egress port */
// };
type TcMirred struct {
TcGen
Eaction int32
Ifindex uint32
}
func (msg *TcMirred) Len() int {
return SizeofTcMirred
}
func DeserializeTcMirred(b []byte) *TcMirred {
return (*TcMirred)(unsafe.Pointer(&b[0:SizeofTcMirred][0]))
}
func (x *TcMirred) Serialize() []byte {
return (*(*[SizeofTcMirred]byte)(unsafe.Pointer(x)))[:]
}
const (
TC_POLICE_UNSPEC = TC_ACT_UNSPEC
TC_POLICE_OK = TC_ACT_OK
TC_POLICE_RECLASSIFY = TC_ACT_RECLASSIFY
TC_POLICE_SHOT = TC_ACT_SHOT
TC_POLICE_PIPE = TC_ACT_PIPE
)
// struct tc_police {
// __u32 index;
// int action;
// __u32 limit;
// __u32 burst;
// __u32 mtu;
// struct tc_ratespec rate;
// struct tc_ratespec peakrate;
// int refcnt;
// int bindcnt;
// __u32 capab;
// };
type TcPolice struct {
Index uint32
Action int32
Limit uint32
Burst uint32
Mtu uint32
Rate TcRateSpec
PeakRate TcRateSpec
Refcnt int32
Bindcnt int32
Capab uint32
}
func (msg *TcPolice) Len() int {
return SizeofTcPolice
}
func DeserializeTcPolice(b []byte) *TcPolice {
return (*TcPolice)(unsafe.Pointer(&b[0:SizeofTcPolice][0]))
}
func (x *TcPolice) Serialize() []byte {
return (*(*[SizeofTcPolice]byte)(unsafe.Pointer(x)))[:]
}
const (
TCA_FW_UNSPEC = iota
TCA_FW_CLASSID
TCA_FW_POLICE
TCA_FW_INDEV
TCA_FW_ACT
TCA_FW_MASK
TCA_FW_MAX = TCA_FW_MASK
)
const (
TCA_BPF_FLAG_ACT_DIRECT uint32 = 1 << iota
)
const (
TCA_BPF_UNSPEC = iota
TCA_BPF_ACT
TCA_BPF_POLICE
TCA_BPF_CLASSID
TCA_BPF_OPS_LEN
TCA_BPF_OPS
TCA_BPF_FD
TCA_BPF_NAME
TCA_BPF_FLAGS
TCA_BPF_MAX = TCA_BPF_FLAGS
)
const (
TCA_ACT_BPF_UNSPEC = iota
TCA_ACT_BPF_TM
TCA_ACT_BPF_PARMS
TCA_ACT_BPF_OPS_LEN
TCA_ACT_BPF_OPS
TCA_ACT_BPF_FD
TCA_ACT_BPF_NAME
TCA_ACT_BPF_MAX = TCA_ACT_BPF_NAME
)

258
vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go generated vendored Normal file
View file

@ -0,0 +1,258 @@
package nl
import (
"bytes"
"net"
"unsafe"
)
// Infinity for packet and byte counts
const (
XFRM_INF = ^uint64(0)
)
// Message Types
const (
XFRM_MSG_BASE = 0x10
XFRM_MSG_NEWSA = 0x10
XFRM_MSG_DELSA = 0x11
XFRM_MSG_GETSA = 0x12
XFRM_MSG_NEWPOLICY = 0x13
XFRM_MSG_DELPOLICY = 0x14
XFRM_MSG_GETPOLICY = 0x15
XFRM_MSG_ALLOCSPI = 0x16
XFRM_MSG_ACQUIRE = 0x17
XFRM_MSG_EXPIRE = 0x18
XFRM_MSG_UPDPOLICY = 0x19
XFRM_MSG_UPDSA = 0x1a
XFRM_MSG_POLEXPIRE = 0x1b
XFRM_MSG_FLUSHSA = 0x1c
XFRM_MSG_FLUSHPOLICY = 0x1d
XFRM_MSG_NEWAE = 0x1e
XFRM_MSG_GETAE = 0x1f
XFRM_MSG_REPORT = 0x20
XFRM_MSG_MIGRATE = 0x21
XFRM_MSG_NEWSADINFO = 0x22
XFRM_MSG_GETSADINFO = 0x23
XFRM_MSG_NEWSPDINFO = 0x24
XFRM_MSG_GETSPDINFO = 0x25
XFRM_MSG_MAPPING = 0x26
XFRM_MSG_MAX = 0x26
XFRM_NR_MSGTYPES = 0x17
)
// Attribute types
const (
/* Netlink message attributes. */
XFRMA_UNSPEC = 0x00
XFRMA_ALG_AUTH = 0x01 /* struct xfrm_algo */
XFRMA_ALG_CRYPT = 0x02 /* struct xfrm_algo */
XFRMA_ALG_COMP = 0x03 /* struct xfrm_algo */
XFRMA_ENCAP = 0x04 /* struct xfrm_algo + struct xfrm_encap_tmpl */
XFRMA_TMPL = 0x05 /* 1 or more struct xfrm_user_tmpl */
XFRMA_SA = 0x06 /* struct xfrm_usersa_info */
XFRMA_POLICY = 0x07 /* struct xfrm_userpolicy_info */
XFRMA_SEC_CTX = 0x08 /* struct xfrm_sec_ctx */
XFRMA_LTIME_VAL = 0x09
XFRMA_REPLAY_VAL = 0x0a
XFRMA_REPLAY_THRESH = 0x0b
XFRMA_ETIMER_THRESH = 0x0c
XFRMA_SRCADDR = 0x0d /* xfrm_address_t */
XFRMA_COADDR = 0x0e /* xfrm_address_t */
XFRMA_LASTUSED = 0x0f /* unsigned long */
XFRMA_POLICY_TYPE = 0x10 /* struct xfrm_userpolicy_type */
XFRMA_MIGRATE = 0x11
XFRMA_ALG_AEAD = 0x12 /* struct xfrm_algo_aead */
XFRMA_KMADDRESS = 0x13 /* struct xfrm_user_kmaddress */
XFRMA_ALG_AUTH_TRUNC = 0x14 /* struct xfrm_algo_auth */
XFRMA_MARK = 0x15 /* struct xfrm_mark */
XFRMA_TFCPAD = 0x16 /* __u32 */
XFRMA_REPLAY_ESN_VAL = 0x17 /* struct xfrm_replay_esn */
XFRMA_SA_EXTRA_FLAGS = 0x18 /* __u32 */
XFRMA_MAX = 0x18
)
const (
SizeofXfrmAddress = 0x10
SizeofXfrmSelector = 0x38
SizeofXfrmLifetimeCfg = 0x40
SizeofXfrmLifetimeCur = 0x20
SizeofXfrmId = 0x18
)
// typedef union {
// __be32 a4;
// __be32 a6[4];
// } xfrm_address_t;
type XfrmAddress [SizeofXfrmAddress]byte
func (x *XfrmAddress) ToIP() net.IP {
var empty = [12]byte{}
ip := make(net.IP, net.IPv6len)
if bytes.Equal(x[4:16], empty[:]) {
ip[10] = 0xff
ip[11] = 0xff
copy(ip[12:16], x[0:4])
} else {
copy(ip[:], x[:])
}
return ip
}
func (x *XfrmAddress) ToIPNet(prefixlen uint8) *net.IPNet {
ip := x.ToIP()
if GetIPFamily(ip) == FAMILY_V4 {
return &net.IPNet{IP: ip, Mask: net.CIDRMask(int(prefixlen), 32)}
}
return &net.IPNet{IP: ip, Mask: net.CIDRMask(int(prefixlen), 128)}
}
func (x *XfrmAddress) FromIP(ip net.IP) {
var empty = [16]byte{}
if len(ip) < net.IPv4len {
copy(x[4:16], empty[:])
} else if GetIPFamily(ip) == FAMILY_V4 {
copy(x[0:4], ip.To4()[0:4])
copy(x[4:16], empty[:12])
} else {
copy(x[0:16], ip.To16()[0:16])
}
}
func DeserializeXfrmAddress(b []byte) *XfrmAddress {
return (*XfrmAddress)(unsafe.Pointer(&b[0:SizeofXfrmAddress][0]))
}
func (x *XfrmAddress) Serialize() []byte {
return (*(*[SizeofXfrmAddress]byte)(unsafe.Pointer(x)))[:]
}
// struct xfrm_selector {
// xfrm_address_t daddr;
// xfrm_address_t saddr;
// __be16 dport;
// __be16 dport_mask;
// __be16 sport;
// __be16 sport_mask;
// __u16 family;
// __u8 prefixlen_d;
// __u8 prefixlen_s;
// __u8 proto;
// int ifindex;
// __kernel_uid32_t user;
// };
type XfrmSelector struct {
Daddr XfrmAddress
Saddr XfrmAddress
Dport uint16 // big endian
DportMask uint16 // big endian
Sport uint16 // big endian
SportMask uint16 // big endian
Family uint16
PrefixlenD uint8
PrefixlenS uint8
Proto uint8
Pad [3]byte
Ifindex int32
User uint32
}
func (msg *XfrmSelector) Len() int {
return SizeofXfrmSelector
}
func DeserializeXfrmSelector(b []byte) *XfrmSelector {
return (*XfrmSelector)(unsafe.Pointer(&b[0:SizeofXfrmSelector][0]))
}
func (msg *XfrmSelector) Serialize() []byte {
return (*(*[SizeofXfrmSelector]byte)(unsafe.Pointer(msg)))[:]
}
// struct xfrm_lifetime_cfg {
// __u64 soft_byte_limit;
// __u64 hard_byte_limit;
// __u64 soft_packet_limit;
// __u64 hard_packet_limit;
// __u64 soft_add_expires_seconds;
// __u64 hard_add_expires_seconds;
// __u64 soft_use_expires_seconds;
// __u64 hard_use_expires_seconds;
// };
//
type XfrmLifetimeCfg struct {
SoftByteLimit uint64
HardByteLimit uint64
SoftPacketLimit uint64
HardPacketLimit uint64
SoftAddExpiresSeconds uint64
HardAddExpiresSeconds uint64
SoftUseExpiresSeconds uint64
HardUseExpiresSeconds uint64
}
func (msg *XfrmLifetimeCfg) Len() int {
return SizeofXfrmLifetimeCfg
}
func DeserializeXfrmLifetimeCfg(b []byte) *XfrmLifetimeCfg {
return (*XfrmLifetimeCfg)(unsafe.Pointer(&b[0:SizeofXfrmLifetimeCfg][0]))
}
func (msg *XfrmLifetimeCfg) Serialize() []byte {
return (*(*[SizeofXfrmLifetimeCfg]byte)(unsafe.Pointer(msg)))[:]
}
// struct xfrm_lifetime_cur {
// __u64 bytes;
// __u64 packets;
// __u64 add_time;
// __u64 use_time;
// };
type XfrmLifetimeCur struct {
Bytes uint64
Packets uint64
AddTime uint64
UseTime uint64
}
func (msg *XfrmLifetimeCur) Len() int {
return SizeofXfrmLifetimeCur
}
func DeserializeXfrmLifetimeCur(b []byte) *XfrmLifetimeCur {
return (*XfrmLifetimeCur)(unsafe.Pointer(&b[0:SizeofXfrmLifetimeCur][0]))
}
func (msg *XfrmLifetimeCur) Serialize() []byte {
return (*(*[SizeofXfrmLifetimeCur]byte)(unsafe.Pointer(msg)))[:]
}
// struct xfrm_id {
// xfrm_address_t daddr;
// __be32 spi;
// __u8 proto;
// };
type XfrmId struct {
Daddr XfrmAddress
Spi uint32 // big endian
Proto uint8
Pad [3]byte
}
func (msg *XfrmId) Len() int {
return SizeofXfrmId
}
func DeserializeXfrmId(b []byte) *XfrmId {
return (*XfrmId)(unsafe.Pointer(&b[0:SizeofXfrmId][0]))
}
func (msg *XfrmId) Serialize() []byte {
return (*(*[SizeofXfrmId]byte)(unsafe.Pointer(msg)))[:]
}

View file

@ -0,0 +1,119 @@
package nl
import (
"unsafe"
)
const (
SizeofXfrmUserpolicyId = 0x40
SizeofXfrmUserpolicyInfo = 0xa8
SizeofXfrmUserTmpl = 0x40
)
// struct xfrm_userpolicy_id {
// struct xfrm_selector sel;
// __u32 index;
// __u8 dir;
// };
//
type XfrmUserpolicyId struct {
Sel XfrmSelector
Index uint32
Dir uint8
Pad [3]byte
}
func (msg *XfrmUserpolicyId) Len() int {
return SizeofXfrmUserpolicyId
}
func DeserializeXfrmUserpolicyId(b []byte) *XfrmUserpolicyId {
return (*XfrmUserpolicyId)(unsafe.Pointer(&b[0:SizeofXfrmUserpolicyId][0]))
}
func (msg *XfrmUserpolicyId) Serialize() []byte {
return (*(*[SizeofXfrmUserpolicyId]byte)(unsafe.Pointer(msg)))[:]
}
// struct xfrm_userpolicy_info {
// struct xfrm_selector sel;
// struct xfrm_lifetime_cfg lft;
// struct xfrm_lifetime_cur curlft;
// __u32 priority;
// __u32 index;
// __u8 dir;
// __u8 action;
// #define XFRM_POLICY_ALLOW 0
// #define XFRM_POLICY_BLOCK 1
// __u8 flags;
// #define XFRM_POLICY_LOCALOK 1 /* Allow user to override global policy */
// /* Automatically expand selector to include matching ICMP payloads. */
// #define XFRM_POLICY_ICMP 2
// __u8 share;
// };
type XfrmUserpolicyInfo struct {
Sel XfrmSelector
Lft XfrmLifetimeCfg
Curlft XfrmLifetimeCur
Priority uint32
Index uint32
Dir uint8
Action uint8
Flags uint8
Share uint8
Pad [4]byte
}
func (msg *XfrmUserpolicyInfo) Len() int {
return SizeofXfrmUserpolicyInfo
}
func DeserializeXfrmUserpolicyInfo(b []byte) *XfrmUserpolicyInfo {
return (*XfrmUserpolicyInfo)(unsafe.Pointer(&b[0:SizeofXfrmUserpolicyInfo][0]))
}
func (msg *XfrmUserpolicyInfo) Serialize() []byte {
return (*(*[SizeofXfrmUserpolicyInfo]byte)(unsafe.Pointer(msg)))[:]
}
// struct xfrm_user_tmpl {
// struct xfrm_id id;
// __u16 family;
// xfrm_address_t saddr;
// __u32 reqid;
// __u8 mode;
// __u8 share;
// __u8 optional;
// __u32 aalgos;
// __u32 ealgos;
// __u32 calgos;
// }
type XfrmUserTmpl struct {
XfrmId XfrmId
Family uint16
Pad1 [2]byte
Saddr XfrmAddress
Reqid uint32
Mode uint8
Share uint8
Optional uint8
Pad2 byte
Aalgos uint32
Ealgos uint32
Calgos uint32
}
func (msg *XfrmUserTmpl) Len() int {
return SizeofXfrmUserTmpl
}
func DeserializeXfrmUserTmpl(b []byte) *XfrmUserTmpl {
return (*XfrmUserTmpl)(unsafe.Pointer(&b[0:SizeofXfrmUserTmpl][0]))
}
func (msg *XfrmUserTmpl) Serialize() []byte {
return (*(*[SizeofXfrmUserTmpl]byte)(unsafe.Pointer(msg)))[:]
}

View file

@ -0,0 +1,221 @@
package nl
import (
"unsafe"
)
const (
SizeofXfrmUsersaId = 0x18
SizeofXfrmStats = 0x0c
SizeofXfrmUsersaInfo = 0xe0
SizeofXfrmAlgo = 0x44
SizeofXfrmAlgoAuth = 0x48
SizeofXfrmEncapTmpl = 0x18
)
// struct xfrm_usersa_id {
// xfrm_address_t daddr;
// __be32 spi;
// __u16 family;
// __u8 proto;
// };
type XfrmUsersaId struct {
Daddr XfrmAddress
Spi uint32 // big endian
Family uint16
Proto uint8
Pad byte
}
func (msg *XfrmUsersaId) Len() int {
return SizeofXfrmUsersaId
}
func DeserializeXfrmUsersaId(b []byte) *XfrmUsersaId {
return (*XfrmUsersaId)(unsafe.Pointer(&b[0:SizeofXfrmUsersaId][0]))
}
func (msg *XfrmUsersaId) Serialize() []byte {
return (*(*[SizeofXfrmUsersaId]byte)(unsafe.Pointer(msg)))[:]
}
// struct xfrm_stats {
// __u32 replay_window;
// __u32 replay;
// __u32 integrity_failed;
// };
type XfrmStats struct {
ReplayWindow uint32
Replay uint32
IntegrityFailed uint32
}
func (msg *XfrmStats) Len() int {
return SizeofXfrmStats
}
func DeserializeXfrmStats(b []byte) *XfrmStats {
return (*XfrmStats)(unsafe.Pointer(&b[0:SizeofXfrmStats][0]))
}
func (msg *XfrmStats) Serialize() []byte {
return (*(*[SizeofXfrmStats]byte)(unsafe.Pointer(msg)))[:]
}
// struct xfrm_usersa_info {
// struct xfrm_selector sel;
// struct xfrm_id id;
// xfrm_address_t saddr;
// struct xfrm_lifetime_cfg lft;
// struct xfrm_lifetime_cur curlft;
// struct xfrm_stats stats;
// __u32 seq;
// __u32 reqid;
// __u16 family;
// __u8 mode; /* XFRM_MODE_xxx */
// __u8 replay_window;
// __u8 flags;
// #define XFRM_STATE_NOECN 1
// #define XFRM_STATE_DECAP_DSCP 2
// #define XFRM_STATE_NOPMTUDISC 4
// #define XFRM_STATE_WILDRECV 8
// #define XFRM_STATE_ICMP 16
// #define XFRM_STATE_AF_UNSPEC 32
// #define XFRM_STATE_ALIGN4 64
// #define XFRM_STATE_ESN 128
// };
//
// #define XFRM_SA_XFLAG_DONT_ENCAP_DSCP 1
//
type XfrmUsersaInfo struct {
Sel XfrmSelector
Id XfrmId
Saddr XfrmAddress
Lft XfrmLifetimeCfg
Curlft XfrmLifetimeCur
Stats XfrmStats
Seq uint32
Reqid uint32
Family uint16
Mode uint8
ReplayWindow uint8
Flags uint8
Pad [7]byte
}
func (msg *XfrmUsersaInfo) Len() int {
return SizeofXfrmUsersaInfo
}
func DeserializeXfrmUsersaInfo(b []byte) *XfrmUsersaInfo {
return (*XfrmUsersaInfo)(unsafe.Pointer(&b[0:SizeofXfrmUsersaInfo][0]))
}
func (msg *XfrmUsersaInfo) Serialize() []byte {
return (*(*[SizeofXfrmUsersaInfo]byte)(unsafe.Pointer(msg)))[:]
}
// struct xfrm_algo {
// char alg_name[64];
// unsigned int alg_key_len; /* in bits */
// char alg_key[0];
// };
type XfrmAlgo struct {
AlgName [64]byte
AlgKeyLen uint32
AlgKey []byte
}
func (msg *XfrmAlgo) Len() int {
return SizeofXfrmAlgo + int(msg.AlgKeyLen/8)
}
func DeserializeXfrmAlgo(b []byte) *XfrmAlgo {
ret := XfrmAlgo{}
copy(ret.AlgName[:], b[0:64])
ret.AlgKeyLen = *(*uint32)(unsafe.Pointer(&b[64]))
ret.AlgKey = b[68:ret.Len()]
return &ret
}
func (msg *XfrmAlgo) Serialize() []byte {
b := make([]byte, msg.Len())
copy(b[0:64], msg.AlgName[:])
copy(b[64:68], (*(*[4]byte)(unsafe.Pointer(&msg.AlgKeyLen)))[:])
copy(b[68:msg.Len()], msg.AlgKey[:])
return b
}
// struct xfrm_algo_auth {
// char alg_name[64];
// unsigned int alg_key_len; /* in bits */
// unsigned int alg_trunc_len; /* in bits */
// char alg_key[0];
// };
type XfrmAlgoAuth struct {
AlgName [64]byte
AlgKeyLen uint32
AlgTruncLen uint32
AlgKey []byte
}
func (msg *XfrmAlgoAuth) Len() int {
return SizeofXfrmAlgoAuth + int(msg.AlgKeyLen/8)
}
func DeserializeXfrmAlgoAuth(b []byte) *XfrmAlgoAuth {
ret := XfrmAlgoAuth{}
copy(ret.AlgName[:], b[0:64])
ret.AlgKeyLen = *(*uint32)(unsafe.Pointer(&b[64]))
ret.AlgTruncLen = *(*uint32)(unsafe.Pointer(&b[68]))
ret.AlgKey = b[72:ret.Len()]
return &ret
}
func (msg *XfrmAlgoAuth) Serialize() []byte {
b := make([]byte, msg.Len())
copy(b[0:64], msg.AlgName[:])
copy(b[64:68], (*(*[4]byte)(unsafe.Pointer(&msg.AlgKeyLen)))[:])
copy(b[68:72], (*(*[4]byte)(unsafe.Pointer(&msg.AlgTruncLen)))[:])
copy(b[72:msg.Len()], msg.AlgKey[:])
return b
}
// struct xfrm_algo_aead {
// char alg_name[64];
// unsigned int alg_key_len; /* in bits */
// unsigned int alg_icv_len; /* in bits */
// char alg_key[0];
// }
// struct xfrm_encap_tmpl {
// __u16 encap_type;
// __be16 encap_sport;
// __be16 encap_dport;
// xfrm_address_t encap_oa;
// };
type XfrmEncapTmpl struct {
EncapType uint16
EncapSport uint16 // big endian
EncapDport uint16 // big endian
Pad [2]byte
EncapOa XfrmAddress
}
func (msg *XfrmEncapTmpl) Len() int {
return SizeofXfrmEncapTmpl
}
func DeserializeXfrmEncapTmpl(b []byte) *XfrmEncapTmpl {
return (*XfrmEncapTmpl)(unsafe.Pointer(&b[0:SizeofXfrmEncapTmpl][0]))
}
func (msg *XfrmEncapTmpl) Serialize() []byte {
return (*(*[SizeofXfrmEncapTmpl]byte)(unsafe.Pointer(msg)))[:]
}

53
vendor/github.com/vishvananda/netlink/protinfo.go generated vendored Normal file
View file

@ -0,0 +1,53 @@
package netlink
import (
"strings"
)
// Protinfo represents bridge flags from netlink.
type Protinfo struct {
Hairpin bool
Guard bool
FastLeave bool
RootBlock bool
Learning bool
Flood bool
}
// String returns a list of enabled flags
func (prot *Protinfo) String() string {
var boolStrings []string
if prot.Hairpin {
boolStrings = append(boolStrings, "Hairpin")
}
if prot.Guard {
boolStrings = append(boolStrings, "Guard")
}
if prot.FastLeave {
boolStrings = append(boolStrings, "FastLeave")
}
if prot.RootBlock {
boolStrings = append(boolStrings, "RootBlock")
}
if prot.Learning {
boolStrings = append(boolStrings, "Learning")
}
if prot.Flood {
boolStrings = append(boolStrings, "Flood")
}
return strings.Join(boolStrings, " ")
}
func boolToByte(x bool) []byte {
if x {
return []byte{1}
}
return []byte{0}
}
func byteToBool(x byte) bool {
if uint8(x) != 0 {
return true
}
return false
}

View file

@ -0,0 +1,60 @@
package netlink
import (
"fmt"
"syscall"
"github.com/vishvananda/netlink/nl"
)
func LinkGetProtinfo(link Link) (Protinfo, error) {
base := link.Attrs()
ensureIndex(base)
var pi Protinfo
req := nl.NewNetlinkRequest(syscall.RTM_GETLINK, syscall.NLM_F_DUMP)
msg := nl.NewIfInfomsg(syscall.AF_BRIDGE)
req.AddData(msg)
msgs, err := req.Execute(syscall.NETLINK_ROUTE, 0)
if err != nil {
return pi, err
}
for _, m := range msgs {
ans := nl.DeserializeIfInfomsg(m)
if int(ans.Index) != base.Index {
continue
}
attrs, err := nl.ParseRouteAttr(m[ans.Len():])
if err != nil {
return pi, err
}
for _, attr := range attrs {
if attr.Attr.Type != syscall.IFLA_PROTINFO|syscall.NLA_F_NESTED {
continue
}
infos, err := nl.ParseRouteAttr(attr.Value)
if err != nil {
return pi, err
}
var pi Protinfo
for _, info := range infos {
switch info.Attr.Type {
case nl.IFLA_BRPORT_MODE:
pi.Hairpin = byteToBool(info.Value[0])
case nl.IFLA_BRPORT_GUARD:
pi.Guard = byteToBool(info.Value[0])
case nl.IFLA_BRPORT_FAST_LEAVE:
pi.FastLeave = byteToBool(info.Value[0])
case nl.IFLA_BRPORT_PROTECT:
pi.RootBlock = byteToBool(info.Value[0])
case nl.IFLA_BRPORT_LEARNING:
pi.Learning = byteToBool(info.Value[0])
case nl.IFLA_BRPORT_UNICAST_FLOOD:
pi.Flood = byteToBool(info.Value[0])
}
}
return pi, nil
}
}
return pi, fmt.Errorf("Device with index %d not found", base.Index)
}

295
vendor/github.com/vishvananda/netlink/qdisc.go generated vendored Normal file
View file

@ -0,0 +1,295 @@
package netlink
import (
"fmt"
"math"
)
const (
HANDLE_NONE = 0
HANDLE_INGRESS = 0xFFFFFFF1
HANDLE_CLSACT = HANDLE_INGRESS
HANDLE_ROOT = 0xFFFFFFFF
PRIORITY_MAP_LEN = 16
)
const (
HANDLE_MIN_INGRESS = 0xFFFFFFF2
HANDLE_MIN_EGRESS = 0xFFFFFFF3
)
type Qdisc interface {
Attrs() *QdiscAttrs
Type() string
}
// QdiscAttrs represents a netlink qdisc. A qdisc is associated with a link,
// has a handle, a parent and a refcnt. The root qdisc of a device should
// have parent == HANDLE_ROOT.
type QdiscAttrs struct {
LinkIndex int
Handle uint32
Parent uint32
Refcnt uint32 // read only
}
func (q QdiscAttrs) String() string {
return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Refcnt: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Refcnt)
}
func MakeHandle(major, minor uint16) uint32 {
return (uint32(major) << 16) | uint32(minor)
}
func MajorMinor(handle uint32) (uint16, uint16) {
return uint16((handle & 0xFFFF0000) >> 16), uint16(handle & 0x0000FFFFF)
}
func HandleStr(handle uint32) string {
switch handle {
case HANDLE_NONE:
return "none"
case HANDLE_INGRESS:
return "ingress"
case HANDLE_ROOT:
return "root"
default:
major, minor := MajorMinor(handle)
return fmt.Sprintf("%x:%x", major, minor)
}
}
func Percentage2u32(percentage float32) uint32 {
// FIXME this is most likely not the best way to convert from % to uint32
if percentage == 100 {
return math.MaxUint32
}
return uint32(math.MaxUint32 * (percentage / 100))
}
// PfifoFast is the default qdisc created by the kernel if one has not
// been defined for the interface
type PfifoFast struct {
QdiscAttrs
Bands uint8
PriorityMap [PRIORITY_MAP_LEN]uint8
}
func (qdisc *PfifoFast) Attrs() *QdiscAttrs {
return &qdisc.QdiscAttrs
}
func (qdisc *PfifoFast) Type() string {
return "pfifo_fast"
}
// Prio is a basic qdisc that works just like PfifoFast
type Prio struct {
QdiscAttrs
Bands uint8
PriorityMap [PRIORITY_MAP_LEN]uint8
}
func NewPrio(attrs QdiscAttrs) *Prio {
return &Prio{
QdiscAttrs: attrs,
Bands: 3,
PriorityMap: [PRIORITY_MAP_LEN]uint8{1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1},
}
}
func (qdisc *Prio) Attrs() *QdiscAttrs {
return &qdisc.QdiscAttrs
}
func (qdisc *Prio) Type() string {
return "prio"
}
// Htb is a classful qdisc that rate limits based on tokens
type Htb struct {
QdiscAttrs
Version uint32
Rate2Quantum uint32
Defcls uint32
Debug uint32
DirectPkts uint32
}
func NewHtb(attrs QdiscAttrs) *Htb {
return &Htb{
QdiscAttrs: attrs,
Version: 3,
Defcls: 0,
Rate2Quantum: 10,
Debug: 0,
DirectPkts: 0,
}
}
func (qdisc *Htb) Attrs() *QdiscAttrs {
return &qdisc.QdiscAttrs
}
func (qdisc *Htb) Type() string {
return "htb"
}
// Netem is a classless qdisc that rate limits based on tokens
type NetemQdiscAttrs struct {
Latency uint32 // in us
DelayCorr float32 // in %
Limit uint32
Loss float32 // in %
LossCorr float32 // in %
Gap uint32
Duplicate float32 // in %
DuplicateCorr float32 // in %
Jitter uint32 // in us
ReorderProb float32 // in %
ReorderCorr float32 // in %
CorruptProb float32 // in %
CorruptCorr float32 // in %
}
func (q NetemQdiscAttrs) String() string {
return fmt.Sprintf(
"{Latency: %d, Limit: %d, Loss: %f, Gap: %d, Duplicate: %f, Jitter: %d}",
q.Latency, q.Limit, q.Loss, q.Gap, q.Duplicate, q.Jitter,
)
}
type Netem struct {
QdiscAttrs
Latency uint32
DelayCorr uint32
Limit uint32
Loss uint32
LossCorr uint32
Gap uint32
Duplicate uint32
DuplicateCorr uint32
Jitter uint32
ReorderProb uint32
ReorderCorr uint32
CorruptProb uint32
CorruptCorr uint32
}
func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem {
var limit uint32 = 1000
var lossCorr, delayCorr, duplicateCorr uint32
var reorderProb, reorderCorr uint32
var corruptProb, corruptCorr uint32
latency := nattrs.Latency
loss := Percentage2u32(nattrs.Loss)
gap := nattrs.Gap
duplicate := Percentage2u32(nattrs.Duplicate)
jitter := nattrs.Jitter
// Correlation
if latency > 0 && jitter > 0 {
delayCorr = Percentage2u32(nattrs.DelayCorr)
}
if loss > 0 {
lossCorr = Percentage2u32(nattrs.LossCorr)
}
if duplicate > 0 {
duplicateCorr = Percentage2u32(nattrs.DuplicateCorr)
}
// FIXME should validate values(like loss/duplicate are percentages...)
latency = time2Tick(latency)
if nattrs.Limit != 0 {
limit = nattrs.Limit
}
// Jitter is only value if latency is > 0
if latency > 0 {
jitter = time2Tick(jitter)
}
reorderProb = Percentage2u32(nattrs.ReorderProb)
reorderCorr = Percentage2u32(nattrs.ReorderCorr)
if reorderProb > 0 {
// ERROR if lantency == 0
if gap == 0 {
gap = 1
}
}
corruptProb = Percentage2u32(nattrs.CorruptProb)
corruptCorr = Percentage2u32(nattrs.CorruptCorr)
return &Netem{
QdiscAttrs: attrs,
Latency: latency,
DelayCorr: delayCorr,
Limit: limit,
Loss: loss,
LossCorr: lossCorr,
Gap: gap,
Duplicate: duplicate,
DuplicateCorr: duplicateCorr,
Jitter: jitter,
ReorderProb: reorderProb,
ReorderCorr: reorderCorr,
CorruptProb: corruptProb,
CorruptCorr: corruptCorr,
}
}
func (qdisc *Netem) Attrs() *QdiscAttrs {
return &qdisc.QdiscAttrs
}
func (qdisc *Netem) Type() string {
return "netem"
}
// Tbf is a classless qdisc that rate limits based on tokens
type Tbf struct {
QdiscAttrs
// TODO: handle 64bit rate properly
Rate uint64
Limit uint32
Buffer uint32
// TODO: handle other settings
}
func (qdisc *Tbf) Attrs() *QdiscAttrs {
return &qdisc.QdiscAttrs
}
func (qdisc *Tbf) Type() string {
return "tbf"
}
// Ingress is a qdisc for adding ingress filters
type Ingress struct {
QdiscAttrs
}
func (qdisc *Ingress) Attrs() *QdiscAttrs {
return &qdisc.QdiscAttrs
}
func (qdisc *Ingress) Type() string {
return "ingress"
}
// GenericQdisc qdiscs represent types that are not currently understood
// by this netlink library.
type GenericQdisc struct {
QdiscAttrs
QdiscType string
}
func (qdisc *GenericQdisc) Attrs() *QdiscAttrs {
return &qdisc.QdiscAttrs
}
func (qdisc *GenericQdisc) Type() string {
return qdisc.QdiscType
}

415
vendor/github.com/vishvananda/netlink/qdisc_linux.go generated vendored Normal file
View file

@ -0,0 +1,415 @@
package netlink
import (
"fmt"
"io/ioutil"
"strconv"
"strings"
"syscall"
"github.com/vishvananda/netlink/nl"
)
// QdiscDel will delete a qdisc from the system.
// Equivalent to: `tc qdisc del $qdisc`
func QdiscDel(qdisc Qdisc) error {
return qdiscModify(syscall.RTM_DELQDISC, 0, qdisc)
}
// QdiscChange will change a qdisc in place
// Equivalent to: `tc qdisc change $qdisc`
// The parent and handle MUST NOT be changed.
func QdiscChange(qdisc Qdisc) error {
return qdiscModify(syscall.RTM_NEWQDISC, 0, qdisc)
}
// QdiscReplace will replace a qdisc to the system.
// Equivalent to: `tc qdisc replace $qdisc`
// The handle MUST change.
func QdiscReplace(qdisc Qdisc) error {
return qdiscModify(
syscall.RTM_NEWQDISC,
syscall.NLM_F_CREATE|syscall.NLM_F_REPLACE,
qdisc)
}
// QdiscAdd will add a qdisc to the system.
// Equivalent to: `tc qdisc add $qdisc`
func QdiscAdd(qdisc Qdisc) error {
return qdiscModify(
syscall.RTM_NEWQDISC,
syscall.NLM_F_CREATE|syscall.NLM_F_EXCL,
qdisc)
}
func qdiscModify(cmd, flags int, qdisc Qdisc) error {
req := nl.NewNetlinkRequest(cmd, flags|syscall.NLM_F_ACK)
base := qdisc.Attrs()
msg := &nl.TcMsg{
Family: nl.FAMILY_ALL,
Ifindex: int32(base.LinkIndex),
Handle: base.Handle,
Parent: base.Parent,
}
req.AddData(msg)
// When deleting don't bother building the rest of the netlink payload
if cmd != syscall.RTM_DELQDISC {
if err := qdiscPayload(req, qdisc); err != nil {
return err
}
}
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
return err
}
func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(qdisc.Type())))
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
if prio, ok := qdisc.(*Prio); ok {
tcmap := nl.TcPrioMap{
Bands: int32(prio.Bands),
Priomap: prio.PriorityMap,
}
options = nl.NewRtAttr(nl.TCA_OPTIONS, tcmap.Serialize())
} else if tbf, ok := qdisc.(*Tbf); ok {
opt := nl.TcTbfQopt{}
// TODO: handle rate > uint32
opt.Rate.Rate = uint32(tbf.Rate)
opt.Limit = tbf.Limit
opt.Buffer = tbf.Buffer
nl.NewRtAttrChild(options, nl.TCA_TBF_PARMS, opt.Serialize())
} else if htb, ok := qdisc.(*Htb); ok {
opt := nl.TcHtbGlob{}
opt.Version = htb.Version
opt.Rate2Quantum = htb.Rate2Quantum
opt.Defcls = htb.Defcls
// TODO: Handle Debug properly. For now default to 0
opt.Debug = htb.Debug
opt.DirectPkts = htb.DirectPkts
nl.NewRtAttrChild(options, nl.TCA_HTB_INIT, opt.Serialize())
// nl.NewRtAttrChild(options, nl.TCA_HTB_DIRECT_QLEN, opt.Serialize())
} else if netem, ok := qdisc.(*Netem); ok {
opt := nl.TcNetemQopt{}
opt.Latency = netem.Latency
opt.Limit = netem.Limit
opt.Loss = netem.Loss
opt.Gap = netem.Gap
opt.Duplicate = netem.Duplicate
opt.Jitter = netem.Jitter
options = nl.NewRtAttr(nl.TCA_OPTIONS, opt.Serialize())
// Correlation
corr := nl.TcNetemCorr{}
corr.DelayCorr = netem.DelayCorr
corr.LossCorr = netem.LossCorr
corr.DupCorr = netem.DuplicateCorr
if corr.DelayCorr > 0 || corr.LossCorr > 0 || corr.DupCorr > 0 {
nl.NewRtAttrChild(options, nl.TCA_NETEM_CORR, corr.Serialize())
}
// Corruption
corruption := nl.TcNetemCorrupt{}
corruption.Probability = netem.CorruptProb
corruption.Correlation = netem.CorruptCorr
if corruption.Probability > 0 {
nl.NewRtAttrChild(options, nl.TCA_NETEM_CORRUPT, corruption.Serialize())
}
// Reorder
reorder := nl.TcNetemReorder{}
reorder.Probability = netem.ReorderProb
reorder.Correlation = netem.ReorderCorr
if reorder.Probability > 0 {
nl.NewRtAttrChild(options, nl.TCA_NETEM_REORDER, reorder.Serialize())
}
} else if _, ok := qdisc.(*Ingress); ok {
// ingress filters must use the proper handle
if qdisc.Attrs().Parent != HANDLE_INGRESS {
return fmt.Errorf("Ingress filters must set Parent to HANDLE_INGRESS")
}
}
req.AddData(options)
return nil
}
// QdiscList gets a list of qdiscs in the system.
// Equivalent to: `tc qdisc show`.
// The list can be filtered by link.
func QdiscList(link Link) ([]Qdisc, error) {
req := nl.NewNetlinkRequest(syscall.RTM_GETQDISC, syscall.NLM_F_DUMP)
index := int32(0)
if link != nil {
base := link.Attrs()
ensureIndex(base)
index = int32(base.Index)
}
msg := &nl.TcMsg{
Family: nl.FAMILY_ALL,
Ifindex: index,
}
req.AddData(msg)
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWQDISC)
if err != nil {
return nil, err
}
var res []Qdisc
for _, m := range msgs {
msg := nl.DeserializeTcMsg(m)
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
if err != nil {
return nil, err
}
// skip qdiscs from other interfaces
if link != nil && msg.Ifindex != index {
continue
}
base := QdiscAttrs{
LinkIndex: int(msg.Ifindex),
Handle: msg.Handle,
Parent: msg.Parent,
Refcnt: msg.Info,
}
var qdisc Qdisc
qdiscType := ""
for _, attr := range attrs {
switch attr.Attr.Type {
case nl.TCA_KIND:
qdiscType = string(attr.Value[:len(attr.Value)-1])
switch qdiscType {
case "pfifo_fast":
qdisc = &PfifoFast{}
case "prio":
qdisc = &Prio{}
case "tbf":
qdisc = &Tbf{}
case "ingress":
qdisc = &Ingress{}
case "htb":
qdisc = &Htb{}
case "netem":
qdisc = &Netem{}
default:
qdisc = &GenericQdisc{QdiscType: qdiscType}
}
case nl.TCA_OPTIONS:
switch qdiscType {
case "pfifo_fast":
// pfifo returns TcPrioMap directly without wrapping it in rtattr
if err := parsePfifoFastData(qdisc, attr.Value); err != nil {
return nil, err
}
case "prio":
// prio returns TcPrioMap directly without wrapping it in rtattr
if err := parsePrioData(qdisc, attr.Value); err != nil {
return nil, err
}
case "tbf":
data, err := nl.ParseRouteAttr(attr.Value)
if err != nil {
return nil, err
}
if err := parseTbfData(qdisc, data); err != nil {
return nil, err
}
case "htb":
data, err := nl.ParseRouteAttr(attr.Value)
if err != nil {
return nil, err
}
if err := parseHtbData(qdisc, data); err != nil {
return nil, err
}
case "netem":
if err := parseNetemData(qdisc, attr.Value); err != nil {
return nil, err
}
// no options for ingress
}
}
}
*qdisc.Attrs() = base
res = append(res, qdisc)
}
return res, nil
}
func parsePfifoFastData(qdisc Qdisc, value []byte) error {
pfifo := qdisc.(*PfifoFast)
tcmap := nl.DeserializeTcPrioMap(value)
pfifo.PriorityMap = tcmap.Priomap
pfifo.Bands = uint8(tcmap.Bands)
return nil
}
func parsePrioData(qdisc Qdisc, value []byte) error {
prio := qdisc.(*Prio)
tcmap := nl.DeserializeTcPrioMap(value)
prio.PriorityMap = tcmap.Priomap
prio.Bands = uint8(tcmap.Bands)
return nil
}
func parseHtbData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
native = nl.NativeEndian()
htb := qdisc.(*Htb)
for _, datum := range data {
switch datum.Attr.Type {
case nl.TCA_HTB_INIT:
opt := nl.DeserializeTcHtbGlob(datum.Value)
htb.Version = opt.Version
htb.Rate2Quantum = opt.Rate2Quantum
htb.Defcls = opt.Defcls
htb.Debug = opt.Debug
htb.DirectPkts = opt.DirectPkts
case nl.TCA_HTB_DIRECT_QLEN:
// TODO
//htb.DirectQlen = native.uint32(datum.Value)
}
}
return nil
}
func parseNetemData(qdisc Qdisc, value []byte) error {
netem := qdisc.(*Netem)
opt := nl.DeserializeTcNetemQopt(value)
netem.Latency = opt.Latency
netem.Limit = opt.Limit
netem.Loss = opt.Loss
netem.Gap = opt.Gap
netem.Duplicate = opt.Duplicate
netem.Jitter = opt.Jitter
data, err := nl.ParseRouteAttr(value[nl.SizeofTcNetemQopt:])
if err != nil {
return err
}
for _, datum := range data {
switch datum.Attr.Type {
case nl.TCA_NETEM_CORR:
opt := nl.DeserializeTcNetemCorr(datum.Value)
netem.DelayCorr = opt.DelayCorr
netem.LossCorr = opt.LossCorr
netem.DuplicateCorr = opt.DupCorr
case nl.TCA_NETEM_CORRUPT:
opt := nl.DeserializeTcNetemCorrupt(datum.Value)
netem.CorruptProb = opt.Probability
netem.CorruptCorr = opt.Correlation
case nl.TCA_NETEM_REORDER:
opt := nl.DeserializeTcNetemReorder(datum.Value)
netem.ReorderProb = opt.Probability
netem.ReorderCorr = opt.Correlation
}
}
return nil
}
func parseTbfData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
native = nl.NativeEndian()
tbf := qdisc.(*Tbf)
for _, datum := range data {
switch datum.Attr.Type {
case nl.TCA_TBF_PARMS:
opt := nl.DeserializeTcTbfQopt(datum.Value)
tbf.Rate = uint64(opt.Rate.Rate)
tbf.Limit = opt.Limit
tbf.Buffer = opt.Buffer
case nl.TCA_TBF_RATE64:
tbf.Rate = native.Uint64(datum.Value[0:4])
}
}
return nil
}
const (
TIME_UNITS_PER_SEC = 1000000
)
var (
tickInUsec float64
clockFactor float64
hz float64
)
func initClock() {
data, err := ioutil.ReadFile("/proc/net/psched")
if err != nil {
return
}
parts := strings.Split(strings.TrimSpace(string(data)), " ")
if len(parts) < 3 {
return
}
var vals [3]uint64
for i := range vals {
val, err := strconv.ParseUint(parts[i], 16, 32)
if err != nil {
return
}
vals[i] = val
}
// compatibility
if vals[2] == 1000000000 {
vals[0] = vals[1]
}
clockFactor = float64(vals[2]) / TIME_UNITS_PER_SEC
tickInUsec = float64(vals[0]) / float64(vals[1]) * clockFactor
hz = float64(vals[0])
}
func TickInUsec() float64 {
if tickInUsec == 0.0 {
initClock()
}
return tickInUsec
}
func ClockFactor() float64 {
if clockFactor == 0.0 {
initClock()
}
return clockFactor
}
func Hz() float64 {
if hz == 0.0 {
initClock()
}
return hz
}
func time2Tick(time uint32) uint32 {
return uint32(float64(time) * TickInUsec())
}
func tick2Time(tick uint32) uint32 {
return uint32(float64(tick) / TickInUsec())
}
func time2Ktime(time uint32) uint32 {
return uint32(float64(time) * ClockFactor())
}
func ktime2Time(ktime uint32) uint32 {
return uint32(float64(ktime) / ClockFactor())
}
func burst(rate uint64, buffer uint32) uint32 {
return uint32(float64(rate) * float64(tick2Time(buffer)) / TIME_UNITS_PER_SEC)
}
func latency(rate uint64, limit, buffer uint32) float64 {
return TIME_UNITS_PER_SEC*(float64(limit)/float64(rate)) - float64(tick2Time(buffer))
}
func Xmittime(rate uint64, size uint32) float64 {
return TickInUsec() * TIME_UNITS_PER_SEC * (float64(size) / float64(rate))
}

80
vendor/github.com/vishvananda/netlink/route.go generated vendored Normal file
View file

@ -0,0 +1,80 @@
package netlink
import (
"fmt"
"net"
"syscall"
)
// Scope is an enum representing a route scope.
type Scope uint8
const (
SCOPE_UNIVERSE Scope = syscall.RT_SCOPE_UNIVERSE
SCOPE_SITE Scope = syscall.RT_SCOPE_SITE
SCOPE_LINK Scope = syscall.RT_SCOPE_LINK
SCOPE_HOST Scope = syscall.RT_SCOPE_HOST
SCOPE_NOWHERE Scope = syscall.RT_SCOPE_NOWHERE
)
type NextHopFlag int
const (
FLAG_ONLINK NextHopFlag = syscall.RTNH_F_ONLINK
FLAG_PERVASIVE NextHopFlag = syscall.RTNH_F_PERVASIVE
)
// Route represents a netlink route.
type Route struct {
LinkIndex int
ILinkIndex int
Scope Scope
Dst *net.IPNet
Src net.IP
Gw net.IP
Protocol int
Priority int
Table int
Type int
Tos int
Flags int
}
func (r Route) String() string {
return fmt.Sprintf("{Ifindex: %d Dst: %s Src: %s Gw: %s Flags: %s}", r.LinkIndex, r.Dst,
r.Src, r.Gw, r.ListFlags())
}
func (r *Route) SetFlag(flag NextHopFlag) {
r.Flags |= int(flag)
}
func (r *Route) ClearFlag(flag NextHopFlag) {
r.Flags &^= int(flag)
}
type flagString struct {
f NextHopFlag
s string
}
var testFlags = []flagString{
{f: FLAG_ONLINK, s: "onlink"},
{f: FLAG_PERVASIVE, s: "pervasive"},
}
func (r *Route) ListFlags() []string {
var flags []string
for _, tf := range testFlags {
if r.Flags&int(tf.f) != 0 {
flags = append(flags, tf.s)
}
}
return flags
}
// RouteUpdate is sent when a route changes - type is RTM_NEWROUTE or RTM_DELROUTE
type RouteUpdate struct {
Type uint16
Route
}

328
vendor/github.com/vishvananda/netlink/route_linux.go generated vendored Normal file
View file

@ -0,0 +1,328 @@
package netlink
import (
"fmt"
"net"
"syscall"
"github.com/vishvananda/netlink/nl"
)
// RtAttr is shared so it is in netlink_linux.go
const (
RT_FILTER_PROTOCOL uint64 = 1 << (1 + iota)
RT_FILTER_SCOPE
RT_FILTER_TYPE
RT_FILTER_TOS
RT_FILTER_IIF
RT_FILTER_OIF
RT_FILTER_DST
RT_FILTER_SRC
RT_FILTER_GW
RT_FILTER_TABLE
)
// RouteAdd will add a route to the system.
// Equivalent to: `ip route add $route`
func RouteAdd(route *Route) error {
req := nl.NewNetlinkRequest(syscall.RTM_NEWROUTE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
return routeHandle(route, req, nl.NewRtMsg())
}
// RouteDel will delete a route from the system.
// Equivalent to: `ip route del $route`
func RouteDel(route *Route) error {
req := nl.NewNetlinkRequest(syscall.RTM_DELROUTE, syscall.NLM_F_ACK)
return routeHandle(route, req, nl.NewRtDelMsg())
}
func routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error {
if (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil {
return fmt.Errorf("one of Dst.IP, Src, or Gw must not be nil")
}
family := -1
var rtAttrs []*nl.RtAttr
if route.Dst != nil && route.Dst.IP != nil {
dstLen, _ := route.Dst.Mask.Size()
msg.Dst_len = uint8(dstLen)
dstFamily := nl.GetIPFamily(route.Dst.IP)
family = dstFamily
var dstData []byte
if dstFamily == FAMILY_V4 {
dstData = route.Dst.IP.To4()
} else {
dstData = route.Dst.IP.To16()
}
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_DST, dstData))
}
if route.Src != nil {
srcFamily := nl.GetIPFamily(route.Src)
if family != -1 && family != srcFamily {
return fmt.Errorf("source and destination ip are not the same IP family")
}
family = srcFamily
var srcData []byte
if srcFamily == FAMILY_V4 {
srcData = route.Src.To4()
} else {
srcData = route.Src.To16()
}
// The commonly used src ip for routes is actually PREFSRC
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_PREFSRC, srcData))
}
if route.Gw != nil {
gwFamily := nl.GetIPFamily(route.Gw)
if family != -1 && family != gwFamily {
return fmt.Errorf("gateway, source, and destination ip are not the same IP family")
}
family = gwFamily
var gwData []byte
if gwFamily == FAMILY_V4 {
gwData = route.Gw.To4()
} else {
gwData = route.Gw.To16()
}
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_GATEWAY, gwData))
}
if route.Table > 0 {
if route.Table >= 256 {
msg.Table = syscall.RT_TABLE_UNSPEC
b := make([]byte, 4)
native.PutUint32(b, uint32(route.Table))
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_TABLE, b))
} else {
msg.Table = uint8(route.Table)
}
}
if route.Priority > 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(route.Priority))
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_PRIORITY, b))
}
if route.Tos > 0 {
msg.Tos = uint8(route.Tos)
}
if route.Protocol > 0 {
msg.Protocol = uint8(route.Protocol)
}
if route.Type > 0 {
msg.Type = uint8(route.Type)
}
msg.Flags = uint32(route.Flags)
msg.Scope = uint8(route.Scope)
msg.Family = uint8(family)
req.AddData(msg)
for _, attr := range rtAttrs {
req.AddData(attr)
}
var (
b = make([]byte, 4)
native = nl.NativeEndian()
)
native.PutUint32(b, uint32(route.LinkIndex))
req.AddData(nl.NewRtAttr(syscall.RTA_OIF, b))
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
return err
}
// RouteList gets a list of routes in the system.
// Equivalent to: `ip route show`.
// The list can be filtered by link and ip family.
func RouteList(link Link, family int) ([]Route, error) {
var routeFilter *Route
if link != nil {
routeFilter = &Route{
LinkIndex: link.Attrs().Index,
}
}
return RouteListFiltered(family, routeFilter, RT_FILTER_OIF)
}
// RouteListFiltered gets a list of routes in the system filtered with specified rules.
// All rules must be defined in RouteFilter struct
func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) {
req := nl.NewNetlinkRequest(syscall.RTM_GETROUTE, syscall.NLM_F_DUMP)
infmsg := nl.NewIfInfomsg(family)
req.AddData(infmsg)
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWROUTE)
if err != nil {
return nil, err
}
var res []Route
for _, m := range msgs {
msg := nl.DeserializeRtMsg(m)
if msg.Flags&syscall.RTM_F_CLONED != 0 {
// Ignore cloned routes
continue
}
if msg.Table != syscall.RT_TABLE_MAIN {
if filter == nil || filter != nil && filterMask&RT_FILTER_TABLE == 0 {
// Ignore non-main tables
continue
}
}
route, err := deserializeRoute(m)
if err != nil {
return nil, err
}
if filter != nil {
switch {
case filterMask&RT_FILTER_TABLE != 0 && route.Table != filter.Table:
continue
case filterMask&RT_FILTER_PROTOCOL != 0 && route.Protocol != filter.Protocol:
continue
case filterMask&RT_FILTER_SCOPE != 0 && route.Scope != filter.Scope:
continue
case filterMask&RT_FILTER_TYPE != 0 && route.Type != filter.Type:
continue
case filterMask&RT_FILTER_TOS != 0 && route.Tos != filter.Tos:
continue
case filterMask&RT_FILTER_OIF != 0 && route.LinkIndex != filter.LinkIndex:
continue
case filterMask&RT_FILTER_IIF != 0 && route.ILinkIndex != filter.ILinkIndex:
continue
case filterMask&RT_FILTER_GW != 0 && !route.Gw.Equal(filter.Gw):
continue
case filterMask&RT_FILTER_SRC != 0 && !route.Src.Equal(filter.Src):
continue
case filterMask&RT_FILTER_DST != 0 && filter.Dst != nil:
if route.Dst == nil {
continue
}
aMaskLen, aMaskBits := route.Dst.Mask.Size()
bMaskLen, bMaskBits := filter.Dst.Mask.Size()
if !(route.Dst.IP.Equal(filter.Dst.IP) && aMaskLen == bMaskLen && aMaskBits == bMaskBits) {
continue
}
}
}
res = append(res, route)
}
return res, nil
}
// deserializeRoute decodes a binary netlink message into a Route struct
func deserializeRoute(m []byte) (Route, error) {
msg := nl.DeserializeRtMsg(m)
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
if err != nil {
return Route{}, err
}
route := Route{
Scope: Scope(msg.Scope),
Protocol: int(msg.Protocol),
Table: int(msg.Table),
Type: int(msg.Type),
Tos: int(msg.Tos),
Flags: int(msg.Flags),
}
native := nl.NativeEndian()
for _, attr := range attrs {
switch attr.Attr.Type {
case syscall.RTA_GATEWAY:
route.Gw = net.IP(attr.Value)
case syscall.RTA_PREFSRC:
route.Src = net.IP(attr.Value)
case syscall.RTA_DST:
route.Dst = &net.IPNet{
IP: attr.Value,
Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)),
}
case syscall.RTA_OIF:
route.LinkIndex = int(native.Uint32(attr.Value[0:4]))
case syscall.RTA_IIF:
route.ILinkIndex = int(native.Uint32(attr.Value[0:4]))
case syscall.RTA_PRIORITY:
route.Priority = int(native.Uint32(attr.Value[0:4]))
case syscall.RTA_TABLE:
route.Table = int(native.Uint32(attr.Value[0:4]))
}
}
return route, nil
}
// RouteGet gets a route to a specific destination from the host system.
// Equivalent to: 'ip route get'.
func RouteGet(destination net.IP) ([]Route, error) {
req := nl.NewNetlinkRequest(syscall.RTM_GETROUTE, syscall.NLM_F_REQUEST)
family := nl.GetIPFamily(destination)
var destinationData []byte
var bitlen uint8
if family == FAMILY_V4 {
destinationData = destination.To4()
bitlen = 32
} else {
destinationData = destination.To16()
bitlen = 128
}
msg := &nl.RtMsg{}
msg.Family = uint8(family)
msg.Dst_len = bitlen
req.AddData(msg)
rtaDst := nl.NewRtAttr(syscall.RTA_DST, destinationData)
req.AddData(rtaDst)
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWROUTE)
if err != nil {
return nil, err
}
var res []Route
for _, m := range msgs {
route, err := deserializeRoute(m)
if err != nil {
return nil, err
}
res = append(res, route)
}
return res, nil
}
// RouteSubscribe takes a chan down which notifications will be sent
// when routes are added or deleted. Close the 'done' chan to stop subscription.
func RouteSubscribe(ch chan<- RouteUpdate, done <-chan struct{}) error {
s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_ROUTE, syscall.RTNLGRP_IPV6_ROUTE)
if err != nil {
return err
}
if done != nil {
go func() {
<-done
s.Close()
}()
}
go func() {
defer close(ch)
for {
msgs, err := s.Receive()
if err != nil {
return
}
for _, m := range msgs {
route, err := deserializeRoute(m.Data)
if err != nil {
return
}
ch <- RouteUpdate{Type: m.Header.Type, Route: route}
}
}
}()
return nil
}

43
vendor/github.com/vishvananda/netlink/rule.go generated vendored Normal file
View file

@ -0,0 +1,43 @@
package netlink
import (
"fmt"
"net"
"github.com/vishvananda/netlink/nl"
)
// Rule represents a netlink rule.
type Rule struct {
*nl.RtMsg
Priority int
Table int
Mark int
Mask int
TunID uint
Goto int
Src *net.IPNet
Dst *net.IPNet
Flow int
IifName string
OifName string
SuppressIfgroup int
SuppressPrefixlen int
}
func (r Rule) String() string {
return fmt.Sprintf("ip rule %d: from %s table %d", r.Priority, r.Src, r.Table)
}
// NewRule return empty rules.
func NewRule() *Rule {
return &Rule{
SuppressIfgroup: -1,
SuppressPrefixlen: -1,
Priority: -1,
Mark: -1,
Mask: -1,
Goto: -1,
Flow: -1,
}
}

198
vendor/github.com/vishvananda/netlink/rule_linux.go generated vendored Normal file
View file

@ -0,0 +1,198 @@
package netlink
import (
"fmt"
"net"
"syscall"
"github.com/vishvananda/netlink/nl"
)
// RuleAdd adds a rule to the system.
// Equivalent to: ip rule add
func RuleAdd(rule *Rule) error {
req := nl.NewNetlinkRequest(syscall.RTM_NEWRULE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
return ruleHandle(rule, req)
}
// RuleDel deletes a rule from the system.
// Equivalent to: ip rule del
func RuleDel(rule *Rule) error {
req := nl.NewNetlinkRequest(syscall.RTM_DELRULE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
return ruleHandle(rule, req)
}
func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
msg := nl.NewRtMsg()
msg.Family = syscall.AF_INET
var dstFamily uint8
var rtAttrs []*nl.RtAttr
if rule.Dst != nil && rule.Dst.IP != nil {
dstLen, _ := rule.Dst.Mask.Size()
msg.Dst_len = uint8(dstLen)
msg.Family = uint8(nl.GetIPFamily(rule.Dst.IP))
dstFamily = msg.Family
var dstData []byte
if msg.Family == syscall.AF_INET {
dstData = rule.Dst.IP.To4()
} else {
dstData = rule.Dst.IP.To16()
}
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_DST, dstData))
}
if rule.Src != nil && rule.Src.IP != nil {
msg.Family = uint8(nl.GetIPFamily(rule.Src.IP))
if dstFamily != 0 && dstFamily != msg.Family {
return fmt.Errorf("source and destination ip are not the same IP family")
}
srcLen, _ := rule.Src.Mask.Size()
msg.Src_len = uint8(srcLen)
var srcData []byte
if msg.Family == syscall.AF_INET {
srcData = rule.Src.IP.To4()
} else {
srcData = rule.Src.IP.To16()
}
rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_SRC, srcData))
}
if rule.Table >= 0 {
msg.Table = uint8(rule.Table)
if rule.Table >= 256 {
msg.Table = syscall.RT_TABLE_UNSPEC
}
}
req.AddData(msg)
for i := range rtAttrs {
req.AddData(rtAttrs[i])
}
var (
b = make([]byte, 4)
native = nl.NativeEndian()
)
if rule.Priority >= 0 {
native.PutUint32(b, uint32(rule.Priority))
req.AddData(nl.NewRtAttr(nl.FRA_PRIORITY, b))
}
if rule.Mark >= 0 {
native.PutUint32(b, uint32(rule.Mark))
req.AddData(nl.NewRtAttr(nl.FRA_FWMARK, b))
}
if rule.Mask >= 0 {
native.PutUint32(b, uint32(rule.Mask))
req.AddData(nl.NewRtAttr(nl.FRA_FWMASK, b))
}
if rule.Flow >= 0 {
native.PutUint32(b, uint32(rule.Flow))
req.AddData(nl.NewRtAttr(nl.FRA_FLOW, b))
}
if rule.TunID > 0 {
native.PutUint32(b, uint32(rule.TunID))
req.AddData(nl.NewRtAttr(nl.FRA_TUN_ID, b))
}
if rule.Table >= 256 {
native.PutUint32(b, uint32(rule.Table))
req.AddData(nl.NewRtAttr(nl.FRA_TABLE, b))
}
if msg.Table > 0 {
if rule.SuppressPrefixlen >= 0 {
native.PutUint32(b, uint32(rule.SuppressPrefixlen))
req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_PREFIXLEN, b))
}
if rule.SuppressIfgroup >= 0 {
native.PutUint32(b, uint32(rule.SuppressIfgroup))
req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_IFGROUP, b))
}
}
if rule.IifName != "" {
req.AddData(nl.NewRtAttr(nl.FRA_IIFNAME, []byte(rule.IifName)))
}
if rule.OifName != "" {
req.AddData(nl.NewRtAttr(nl.FRA_OIFNAME, []byte(rule.OifName)))
}
if rule.Goto >= 0 {
msg.Type = nl.FR_ACT_NOP
native.PutUint32(b, uint32(rule.Goto))
req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b))
}
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
return err
}
// RuleList lists rules in the system.
// Equivalent to: ip rule list
func RuleList(family int) ([]Rule, error) {
req := nl.NewNetlinkRequest(syscall.RTM_GETRULE, syscall.NLM_F_DUMP|syscall.NLM_F_REQUEST)
msg := nl.NewIfInfomsg(family)
req.AddData(msg)
msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWRULE)
if err != nil {
return nil, err
}
native := nl.NativeEndian()
var res = make([]Rule, 0)
for i := range msgs {
msg := nl.DeserializeRtMsg(msgs[i])
attrs, err := nl.ParseRouteAttr(msgs[i][msg.Len():])
if err != nil {
return nil, err
}
rule := NewRule()
rule.RtMsg = msg
for j := range attrs {
switch attrs[j].Attr.Type {
case syscall.RTA_TABLE:
rule.Table = int(native.Uint32(attrs[j].Value[0:4]))
case nl.FRA_SRC:
rule.Src = &net.IPNet{
IP: attrs[j].Value,
Mask: net.CIDRMask(int(msg.Src_len), 8*len(attrs[j].Value)),
}
case nl.FRA_DST:
rule.Dst = &net.IPNet{
IP: attrs[j].Value,
Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attrs[j].Value)),
}
case nl.FRA_FWMARK:
rule.Mark = int(native.Uint32(attrs[j].Value[0:4]))
case nl.FRA_FWMASK:
rule.Mask = int(native.Uint32(attrs[j].Value[0:4]))
case nl.FRA_TUN_ID:
rule.TunID = uint(native.Uint64(attrs[j].Value[0:4]))
case nl.FRA_IIFNAME:
rule.IifName = string(attrs[j].Value[:len(attrs[j].Value)-1])
case nl.FRA_OIFNAME:
rule.OifName = string(attrs[j].Value[:len(attrs[j].Value)-1])
case nl.FRA_SUPPRESS_PREFIXLEN:
i := native.Uint32(attrs[j].Value[0:4])
if i != 0xffffffff {
rule.SuppressPrefixlen = int(i)
}
case nl.FRA_SUPPRESS_IFGROUP:
i := native.Uint32(attrs[j].Value[0:4])
if i != 0xffffffff {
rule.SuppressIfgroup = int(i)
}
case nl.FRA_FLOW:
rule.Flow = int(native.Uint32(attrs[j].Value[0:4]))
case nl.FRA_GOTO:
rule.Goto = int(native.Uint32(attrs[j].Value[0:4]))
case nl.FRA_PRIORITY:
rule.Priority = int(native.Uint32(attrs[j].Value[0:4]))
}
}
res = append(res, *rule)
}
return res, nil
}

64
vendor/github.com/vishvananda/netlink/xfrm.go generated vendored Normal file
View file

@ -0,0 +1,64 @@
package netlink
import (
"fmt"
"syscall"
)
// Proto is an enum representing an ipsec protocol.
type Proto uint8
const (
XFRM_PROTO_ROUTE2 Proto = syscall.IPPROTO_ROUTING
XFRM_PROTO_ESP Proto = syscall.IPPROTO_ESP
XFRM_PROTO_AH Proto = syscall.IPPROTO_AH
XFRM_PROTO_HAO Proto = syscall.IPPROTO_DSTOPTS
XFRM_PROTO_COMP Proto = syscall.IPPROTO_COMP
XFRM_PROTO_IPSEC_ANY Proto = syscall.IPPROTO_RAW
)
func (p Proto) String() string {
switch p {
case XFRM_PROTO_ROUTE2:
return "route2"
case XFRM_PROTO_ESP:
return "esp"
case XFRM_PROTO_AH:
return "ah"
case XFRM_PROTO_HAO:
return "hao"
case XFRM_PROTO_COMP:
return "comp"
case XFRM_PROTO_IPSEC_ANY:
return "ipsec-any"
}
return fmt.Sprintf("%d", p)
}
// Mode is an enum representing an ipsec transport.
type Mode uint8
const (
XFRM_MODE_TRANSPORT Mode = iota
XFRM_MODE_TUNNEL
XFRM_MODE_ROUTEOPTIMIZATION
XFRM_MODE_IN_TRIGGER
XFRM_MODE_BEET
XFRM_MODE_MAX
)
func (m Mode) String() string {
switch m {
case XFRM_MODE_TRANSPORT:
return "transport"
case XFRM_MODE_TUNNEL:
return "tunnel"
case XFRM_MODE_ROUTEOPTIMIZATION:
return "ro"
case XFRM_MODE_IN_TRIGGER:
return "in_trigger"
case XFRM_MODE_BEET:
return "beet"
}
return fmt.Sprintf("%d", m)
}

59
vendor/github.com/vishvananda/netlink/xfrm_policy.go generated vendored Normal file
View file

@ -0,0 +1,59 @@
package netlink
import (
"fmt"
"net"
)
// Dir is an enum representing an ipsec template direction.
type Dir uint8
const (
XFRM_DIR_IN Dir = iota
XFRM_DIR_OUT
XFRM_DIR_FWD
XFRM_SOCKET_IN
XFRM_SOCKET_OUT
XFRM_SOCKET_FWD
)
func (d Dir) String() string {
switch d {
case XFRM_DIR_IN:
return "dir in"
case XFRM_DIR_OUT:
return "dir out"
case XFRM_DIR_FWD:
return "dir fwd"
case XFRM_SOCKET_IN:
return "socket in"
case XFRM_SOCKET_OUT:
return "socket out"
case XFRM_SOCKET_FWD:
return "socket fwd"
}
return fmt.Sprintf("socket %d", d-XFRM_SOCKET_IN)
}
// XfrmPolicyTmpl encapsulates a rule for the base addresses of an ipsec
// policy. These rules are matched with XfrmState to determine encryption
// and authentication algorithms.
type XfrmPolicyTmpl struct {
Dst net.IP
Src net.IP
Proto Proto
Mode Mode
Reqid int
}
// XfrmPolicy represents an ipsec policy. It represents the overlay network
// and has a list of XfrmPolicyTmpls representing the base addresses of
// the policy.
type XfrmPolicy struct {
Dst *net.IPNet
Src *net.IPNet
Dir Dir
Priority int
Index int
Tmpls []XfrmPolicyTmpl
}

View file

@ -0,0 +1,127 @@
package netlink
import (
"syscall"
"github.com/vishvananda/netlink/nl"
)
func selFromPolicy(sel *nl.XfrmSelector, policy *XfrmPolicy) {
sel.Family = uint16(nl.GetIPFamily(policy.Dst.IP))
sel.Daddr.FromIP(policy.Dst.IP)
sel.Saddr.FromIP(policy.Src.IP)
prefixlenD, _ := policy.Dst.Mask.Size()
sel.PrefixlenD = uint8(prefixlenD)
prefixlenS, _ := policy.Src.Mask.Size()
sel.PrefixlenS = uint8(prefixlenS)
}
// XfrmPolicyAdd will add an xfrm policy to the system.
// Equivalent to: `ip xfrm policy add $policy`
func XfrmPolicyAdd(policy *XfrmPolicy) error {
req := nl.NewNetlinkRequest(nl.XFRM_MSG_NEWPOLICY, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
msg := &nl.XfrmUserpolicyInfo{}
selFromPolicy(&msg.Sel, policy)
msg.Priority = uint32(policy.Priority)
msg.Index = uint32(policy.Index)
msg.Dir = uint8(policy.Dir)
msg.Lft.SoftByteLimit = nl.XFRM_INF
msg.Lft.HardByteLimit = nl.XFRM_INF
msg.Lft.SoftPacketLimit = nl.XFRM_INF
msg.Lft.HardPacketLimit = nl.XFRM_INF
req.AddData(msg)
tmplData := make([]byte, nl.SizeofXfrmUserTmpl*len(policy.Tmpls))
for i, tmpl := range policy.Tmpls {
start := i * nl.SizeofXfrmUserTmpl
userTmpl := nl.DeserializeXfrmUserTmpl(tmplData[start : start+nl.SizeofXfrmUserTmpl])
userTmpl.XfrmId.Daddr.FromIP(tmpl.Dst)
userTmpl.Saddr.FromIP(tmpl.Src)
userTmpl.XfrmId.Proto = uint8(tmpl.Proto)
userTmpl.Mode = uint8(tmpl.Mode)
userTmpl.Reqid = uint32(tmpl.Reqid)
userTmpl.Aalgos = ^uint32(0)
userTmpl.Ealgos = ^uint32(0)
userTmpl.Calgos = ^uint32(0)
}
if len(tmplData) > 0 {
tmpls := nl.NewRtAttr(nl.XFRMA_TMPL, tmplData)
req.AddData(tmpls)
}
_, err := req.Execute(syscall.NETLINK_XFRM, 0)
return err
}
// XfrmPolicyDel will delete an xfrm policy from the system. Note that
// the Tmpls are ignored when matching the policy to delete.
// Equivalent to: `ip xfrm policy del $policy`
func XfrmPolicyDel(policy *XfrmPolicy) error {
req := nl.NewNetlinkRequest(nl.XFRM_MSG_DELPOLICY, syscall.NLM_F_ACK)
msg := &nl.XfrmUserpolicyId{}
selFromPolicy(&msg.Sel, policy)
msg.Index = uint32(policy.Index)
msg.Dir = uint8(policy.Dir)
req.AddData(msg)
_, err := req.Execute(syscall.NETLINK_XFRM, 0)
return err
}
// XfrmPolicyList gets a list of xfrm policies in the system.
// Equivalent to: `ip xfrm policy show`.
// The list can be filtered by ip family.
func XfrmPolicyList(family int) ([]XfrmPolicy, error) {
req := nl.NewNetlinkRequest(nl.XFRM_MSG_GETPOLICY, syscall.NLM_F_DUMP)
msg := nl.NewIfInfomsg(family)
req.AddData(msg)
msgs, err := req.Execute(syscall.NETLINK_XFRM, nl.XFRM_MSG_NEWPOLICY)
if err != nil {
return nil, err
}
var res []XfrmPolicy
for _, m := range msgs {
msg := nl.DeserializeXfrmUserpolicyInfo(m)
if family != FAMILY_ALL && family != int(msg.Sel.Family) {
continue
}
var policy XfrmPolicy
policy.Dst = msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD)
policy.Src = msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS)
policy.Priority = int(msg.Priority)
policy.Index = int(msg.Index)
policy.Dir = Dir(msg.Dir)
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
if err != nil {
return nil, err
}
for _, attr := range attrs {
switch attr.Attr.Type {
case nl.XFRMA_TMPL:
max := len(attr.Value)
for i := 0; i < max; i += nl.SizeofXfrmUserTmpl {
var resTmpl XfrmPolicyTmpl
tmpl := nl.DeserializeXfrmUserTmpl(attr.Value[i : i+nl.SizeofXfrmUserTmpl])
resTmpl.Dst = tmpl.XfrmId.Daddr.ToIP()
resTmpl.Src = tmpl.Saddr.ToIP()
resTmpl.Proto = Proto(tmpl.XfrmId.Proto)
resTmpl.Mode = Mode(tmpl.Mode)
resTmpl.Reqid = int(tmpl.Reqid)
policy.Tmpls = append(policy.Tmpls, resTmpl)
}
}
}
res = append(res, policy)
}
return res, nil
}

53
vendor/github.com/vishvananda/netlink/xfrm_state.go generated vendored Normal file
View file

@ -0,0 +1,53 @@
package netlink
import (
"net"
)
// XfrmStateAlgo represents the algorithm to use for the ipsec encryption.
type XfrmStateAlgo struct {
Name string
Key []byte
TruncateLen int // Auth only
}
// EncapType is an enum representing an ipsec template direction.
type EncapType uint8
const (
XFRM_ENCAP_ESPINUDP_NONIKE EncapType = iota + 1
XFRM_ENCAP_ESPINUDP
)
func (e EncapType) String() string {
switch e {
case XFRM_ENCAP_ESPINUDP_NONIKE:
return "espinudp-nonike"
case XFRM_ENCAP_ESPINUDP:
return "espinudp"
}
return "unknown"
}
// XfrmStateEncap represents the encapsulation to use for the ipsec encryption.
type XfrmStateEncap struct {
Type EncapType
SrcPort int
DstPort int
OriginalAddress net.IP
}
// XfrmState represents the state of an ipsec policy. It optionally
// contains an XfrmStateAlgo for encryption and one for authentication.
type XfrmState struct {
Dst net.IP
Src net.IP
Proto Proto
Mode Mode
Spi int
Reqid int
ReplayWindow int
Auth *XfrmStateAlgo
Crypt *XfrmStateAlgo
Encap *XfrmStateEncap
}

View file

@ -0,0 +1,178 @@
package netlink
import (
"fmt"
"syscall"
"github.com/vishvananda/netlink/nl"
)
func writeStateAlgo(a *XfrmStateAlgo) []byte {
algo := nl.XfrmAlgo{
AlgKeyLen: uint32(len(a.Key) * 8),
AlgKey: a.Key,
}
end := len(a.Name)
if end > 64 {
end = 64
}
copy(algo.AlgName[:end], a.Name)
return algo.Serialize()
}
func writeStateAlgoAuth(a *XfrmStateAlgo) []byte {
algo := nl.XfrmAlgoAuth{
AlgKeyLen: uint32(len(a.Key) * 8),
AlgTruncLen: uint32(a.TruncateLen),
AlgKey: a.Key,
}
end := len(a.Name)
if end > 64 {
end = 64
}
copy(algo.AlgName[:end], a.Name)
return algo.Serialize()
}
// XfrmStateAdd will add an xfrm state to the system.
// Equivalent to: `ip xfrm state add $state`
func XfrmStateAdd(state *XfrmState) error {
// A state with spi 0 can't be deleted so don't allow it to be set
if state.Spi == 0 {
return fmt.Errorf("Spi must be set when adding xfrm state.")
}
req := nl.NewNetlinkRequest(nl.XFRM_MSG_NEWSA, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
msg := &nl.XfrmUsersaInfo{}
msg.Family = uint16(nl.GetIPFamily(state.Dst))
msg.Id.Daddr.FromIP(state.Dst)
msg.Saddr.FromIP(state.Src)
msg.Id.Proto = uint8(state.Proto)
msg.Mode = uint8(state.Mode)
msg.Id.Spi = nl.Swap32(uint32(state.Spi))
msg.Reqid = uint32(state.Reqid)
msg.ReplayWindow = uint8(state.ReplayWindow)
msg.Lft.SoftByteLimit = nl.XFRM_INF
msg.Lft.HardByteLimit = nl.XFRM_INF
msg.Lft.SoftPacketLimit = nl.XFRM_INF
msg.Lft.HardPacketLimit = nl.XFRM_INF
req.AddData(msg)
if state.Auth != nil {
out := nl.NewRtAttr(nl.XFRMA_ALG_AUTH_TRUNC, writeStateAlgoAuth(state.Auth))
req.AddData(out)
}
if state.Crypt != nil {
out := nl.NewRtAttr(nl.XFRMA_ALG_CRYPT, writeStateAlgo(state.Crypt))
req.AddData(out)
}
if state.Encap != nil {
encapData := make([]byte, nl.SizeofXfrmEncapTmpl)
encap := nl.DeserializeXfrmEncapTmpl(encapData)
encap.EncapType = uint16(state.Encap.Type)
encap.EncapSport = nl.Swap16(uint16(state.Encap.SrcPort))
encap.EncapDport = nl.Swap16(uint16(state.Encap.DstPort))
encap.EncapOa.FromIP(state.Encap.OriginalAddress)
out := nl.NewRtAttr(nl.XFRMA_ENCAP, encapData)
req.AddData(out)
}
_, err := req.Execute(syscall.NETLINK_XFRM, 0)
return err
}
// XfrmStateDel will delete an xfrm state from the system. Note that
// the Algos are ignored when matching the state to delete.
// Equivalent to: `ip xfrm state del $state`
func XfrmStateDel(state *XfrmState) error {
req := nl.NewNetlinkRequest(nl.XFRM_MSG_DELSA, syscall.NLM_F_ACK)
msg := &nl.XfrmUsersaId{}
msg.Daddr.FromIP(state.Dst)
msg.Family = uint16(nl.GetIPFamily(state.Dst))
msg.Proto = uint8(state.Proto)
msg.Spi = nl.Swap32(uint32(state.Spi))
req.AddData(msg)
saddr := nl.XfrmAddress{}
saddr.FromIP(state.Src)
srcdata := nl.NewRtAttr(nl.XFRMA_SRCADDR, saddr.Serialize())
req.AddData(srcdata)
_, err := req.Execute(syscall.NETLINK_XFRM, 0)
return err
}
// XfrmStateList gets a list of xfrm states in the system.
// Equivalent to: `ip xfrm state show`.
// The list can be filtered by ip family.
func XfrmStateList(family int) ([]XfrmState, error) {
req := nl.NewNetlinkRequest(nl.XFRM_MSG_GETSA, syscall.NLM_F_DUMP)
msgs, err := req.Execute(syscall.NETLINK_XFRM, nl.XFRM_MSG_NEWSA)
if err != nil {
return nil, err
}
var res []XfrmState
for _, m := range msgs {
msg := nl.DeserializeXfrmUsersaInfo(m)
if family != FAMILY_ALL && family != int(msg.Family) {
continue
}
var state XfrmState
state.Dst = msg.Id.Daddr.ToIP()
state.Src = msg.Saddr.ToIP()
state.Proto = Proto(msg.Id.Proto)
state.Mode = Mode(msg.Mode)
state.Spi = int(nl.Swap32(msg.Id.Spi))
state.Reqid = int(msg.Reqid)
state.ReplayWindow = int(msg.ReplayWindow)
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
if err != nil {
return nil, err
}
for _, attr := range attrs {
switch attr.Attr.Type {
case nl.XFRMA_ALG_AUTH, nl.XFRMA_ALG_CRYPT:
var resAlgo *XfrmStateAlgo
if attr.Attr.Type == nl.XFRMA_ALG_AUTH {
if state.Auth == nil {
state.Auth = new(XfrmStateAlgo)
}
resAlgo = state.Auth
} else {
state.Crypt = new(XfrmStateAlgo)
resAlgo = state.Crypt
}
algo := nl.DeserializeXfrmAlgo(attr.Value[:])
(*resAlgo).Name = nl.BytesToString(algo.AlgName[:])
(*resAlgo).Key = algo.AlgKey
case nl.XFRMA_ALG_AUTH_TRUNC:
if state.Auth == nil {
state.Auth = new(XfrmStateAlgo)
}
algo := nl.DeserializeXfrmAlgoAuth(attr.Value[:])
state.Auth.Name = nl.BytesToString(algo.AlgName[:])
state.Auth.Key = algo.AlgKey
state.Auth.TruncateLen = int(algo.AlgTruncLen)
case nl.XFRMA_ENCAP:
encap := nl.DeserializeXfrmEncapTmpl(attr.Value[:])
state.Encap = new(XfrmStateEncap)
state.Encap.Type = EncapType(encap.EncapType)
state.Encap.SrcPort = int(nl.Swap16(encap.EncapSport))
state.Encap.DstPort = int(nl.Swap16(encap.EncapDport))
state.Encap.OriginalAddress = encap.EncapOa.ToIP()
}
}
res = append(res, state)
}
return res, nil
}