1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #28562 from tomdee/bump-libnetwork

Update libnetwork version for IPv6 support
This commit is contained in:
Madhu Venugopal 2016-11-21 11:30:00 -08:00 committed by GitHub
commit 111a95fb50
31 changed files with 529 additions and 75 deletions

View file

@ -712,7 +712,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkInspectCustomUnspecified(c *check.
} }
func (s *DockerNetworkSuite) TestDockerNetworkInspectCustomSpecified(c *check.C) { func (s *DockerNetworkSuite) TestDockerNetworkInspectCustomSpecified(c *check.C) {
dockerCmd(c, "network", "create", "--driver=bridge", "--ipv6", "--subnet=172.28.0.0/16", "--ip-range=172.28.5.0/24", "--gateway=172.28.5.254", "br0") dockerCmd(c, "network", "create", "--driver=bridge", "--ipv6", "--subnet=fd80:24e2:f998:72d6::/64", "--subnet=172.28.0.0/16", "--ip-range=172.28.5.0/24", "--gateway=172.28.5.254", "br0")
assertNwIsAvailable(c, "br0") assertNwIsAvailable(c, "br0")
nr := getNetworkResource(c, "br0") nr := getNetworkResource(c, "br0")
@ -721,7 +721,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkInspectCustomSpecified(c *check.C)
c.Assert(nr.Internal, checker.Equals, false) c.Assert(nr.Internal, checker.Equals, false)
c.Assert(nr.EnableIPv6, checker.Equals, true) c.Assert(nr.EnableIPv6, checker.Equals, true)
c.Assert(nr.IPAM.Driver, checker.Equals, "default") c.Assert(nr.IPAM.Driver, checker.Equals, "default")
c.Assert(len(nr.IPAM.Config), checker.Equals, 1) c.Assert(len(nr.IPAM.Config), checker.Equals, 2)
c.Assert(nr.IPAM.Config[0].Subnet, checker.Equals, "172.28.0.0/16") c.Assert(nr.IPAM.Config[0].Subnet, checker.Equals, "172.28.0.0/16")
c.Assert(nr.IPAM.Config[0].IPRange, checker.Equals, "172.28.5.0/24") c.Assert(nr.IPAM.Config[0].IPRange, checker.Equals, "172.28.5.0/24")
c.Assert(nr.IPAM.Config[0].Gateway, checker.Equals, "172.28.5.254") c.Assert(nr.IPAM.Config[0].Gateway, checker.Equals, "172.28.5.254")

View file

@ -23,7 +23,7 @@ github.com/RackSec/srslog 365bf33cd9acc21ae1c355209865f17228ca534e
github.com/imdario/mergo 0.2.1 github.com/imdario/mergo 0.2.1
#get libnetwork packages #get libnetwork packages
github.com/docker/libnetwork 57be722e077059d1ee0539be31743a3642ccbeb3 github.com/docker/libnetwork f36e733a08cd8239a2db296994cb6613fef1cece
github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894 github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894
github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
@ -33,7 +33,7 @@ github.com/hashicorp/go-multierror fcdddc395df1ddf4247c69bd436e84cfa0733f7e
github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870 github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870
github.com/docker/libkv v0.2.1 github.com/docker/libkv v0.2.1
github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25 github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25
github.com/vishvananda/netlink e73bad418fd727ed3a02830b1af1ad0283a1de6c github.com/vishvananda/netlink 482f7a52b758233521878cb6c5904b6bd63f3457
github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060 github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060
github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374 github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374
github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d

View file

@ -381,7 +381,57 @@ func (n *network) leaveCluster() error {
return c.agent.networkDB.LeaveNetwork(n.ID()) return c.agent.networkDB.LeaveNetwork(n.ID())
} }
func (ep *endpoint) addToCluster() error { func (ep *endpoint) addDriverInfoToCluster() error {
n := ep.getNetwork()
if !n.isClusterEligible() {
return nil
}
if ep.joinInfo == nil {
return nil
}
ctrlr := n.ctrlr
ctrlr.Lock()
agent := ctrlr.agent
ctrlr.Unlock()
if agent == nil {
return nil
}
for _, te := range ep.joinInfo.driverTableEntries {
if err := agent.networkDB.CreateEntry(te.tableName, n.ID(), te.key, te.value); err != nil {
return err
}
}
return nil
}
func (ep *endpoint) deleteDriverInfoFromCluster() error {
n := ep.getNetwork()
if !n.isClusterEligible() {
return nil
}
if ep.joinInfo == nil {
return nil
}
ctrlr := n.ctrlr
ctrlr.Lock()
agent := ctrlr.agent
ctrlr.Unlock()
if agent == nil {
return nil
}
for _, te := range ep.joinInfo.driverTableEntries {
if err := agent.networkDB.DeleteEntry(te.tableName, n.ID(), te.key); err != nil {
return err
}
}
return nil
}
func (ep *endpoint) addServiceInfoToCluster() error {
n := ep.getNetwork() n := ep.getNetwork()
if !n.isClusterEligible() { if !n.isClusterEligible() {
return nil return nil
@ -421,16 +471,10 @@ func (ep *endpoint) addToCluster() error {
} }
} }
for _, te := range ep.joinInfo.driverTableEntries {
if err := c.agent.networkDB.CreateEntry(te.tableName, n.ID(), te.key, te.value); err != nil {
return err
}
}
return nil return nil
} }
func (ep *endpoint) deleteFromCluster() error { func (ep *endpoint) deleteServiceInfoFromCluster() error {
n := ep.getNetwork() n := ep.getNetwork()
if !n.isClusterEligible() { if !n.isClusterEligible() {
return nil return nil
@ -453,17 +497,6 @@ func (ep *endpoint) deleteFromCluster() error {
return err return err
} }
} }
if ep.joinInfo == nil {
return nil
}
for _, te := range ep.joinInfo.driverTableEntries {
if err := c.agent.networkDB.DeleteEntry(te.tableName, n.ID(), te.key); err != nil {
return err
}
}
return nil return nil
} }

View file

@ -17,11 +17,11 @@ import (
"github.com/docker/libnetwork/osl" "github.com/docker/libnetwork/osl"
) )
// RestrictedNameChars collects the characters allowed to represent a network or endpoint name. // restrictedNameRegex represents the regular expression which regulates the allowed network or endpoint names.
const restrictedNameChars = `[a-zA-Z0-9][a-zA-Z0-9_.-]` const restrictedNameRegex = `^[\w]+[\w-. ]*[\w]+$`
// RestrictedNamePattern is a regular expression to validate names against the collection of restricted characters. // RestrictedNamePattern is a regular expression to validate names against the collection of restricted characters.
var restrictedNamePattern = regexp.MustCompile(`^/?` + restrictedNameChars + `+$`) var restrictedNamePattern = regexp.MustCompile(restrictedNameRegex)
// Config encapsulates configurations of various Libnetwork components // Config encapsulates configurations of various Libnetwork components
type Config struct { type Config struct {
@ -234,7 +234,7 @@ func (c *Config) ProcessOptions(options ...Option) {
// ValidateName validates configuration objects supported by libnetwork // ValidateName validates configuration objects supported by libnetwork
func ValidateName(name string) error { func ValidateName(name string) error {
if !restrictedNamePattern.MatchString(name) { if !restrictedNamePattern.MatchString(name) {
return fmt.Errorf("%s includes invalid characters, only %q are allowed", name, restrictedNameChars) return fmt.Errorf("%q includes invalid characters, resource name has to conform to %q", name, restrictedNameRegex)
} }
return nil return nil
} }

View file

@ -77,7 +77,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
} }
if s := n.getSubnetforIP(ep.addr); s == nil { if s := n.getSubnetforIP(ep.addr); s == nil {
return fmt.Errorf("no matching subnet for IP %q in network %q\n", ep.addr, nid) return fmt.Errorf("no matching subnet for IP %q in network %q", ep.addr, nid)
} }
if ep.mac == nil { if ep.mac == nil {

View file

@ -320,6 +320,11 @@ func populateVNITbl() {
} }
defer nlh.Delete() defer nlh.Delete()
err = nlh.SetSocketTimeout(soTimeout)
if err != nil {
logrus.Warnf("Failed to set the timeout on the netlink handle sockets for vni table population: %v", err)
}
links, err := nlh.LinkList() links, err := nlh.LinkList()
if err != nil { if err != nil {
logrus.Errorf("Failed to list interfaces during vni population for ns %s: %v", path, err) logrus.Errorf("Failed to list interfaces during vni population for ns %s: %v", path, err)

View file

@ -13,6 +13,8 @@ import (
"github.com/vishvananda/netns" "github.com/vishvananda/netns"
) )
var soTimeout = ns.NetlinkSocketsTimeout
func validateID(nid, eid string) error { func validateID(nid, eid string) error {
if nid == "" { if nid == "" {
return fmt.Errorf("invalid network id") return fmt.Errorf("invalid network id")
@ -134,6 +136,10 @@ func deleteVxlanByVNI(path string, vni uint32) error {
return fmt.Errorf("failed to get netlink handle for ns %s: %v", path, err) return fmt.Errorf("failed to get netlink handle for ns %s: %v", path, err)
} }
defer nlh.Delete() defer nlh.Delete()
err = nlh.SetSocketTimeout(soTimeout)
if err != nil {
logrus.Warnf("Failed to set the timeout on the netlink handle sockets for vxlan deletion: %v", err)
}
} }
links, err := nlh.LinkList() links, err := nlh.LinkList()

View file

@ -277,7 +277,7 @@ func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
s := n.getSubnetforIP(IP) s := n.getSubnetforIP(IP)
if s == nil { if s == nil {
return fmt.Errorf("couldn't find the subnet %q in network %q\n", IP.String(), n.id) return fmt.Errorf("couldn't find the subnet %q in network %q", IP.String(), n.id)
} }
if err := n.obtainVxlanID(s); err != nil { if err := n.obtainVxlanID(s); err != nil {

View file

@ -76,7 +76,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
} }
if s := n.getSubnetforIP(ep.addr); s == nil { if s := n.getSubnetforIP(ep.addr); s == nil {
return fmt.Errorf("no matching subnet for IP %q in network %q\n", ep.addr, nid) return fmt.Errorf("no matching subnet for IP %q in network %q", ep.addr, nid)
} }
if ep.mac == nil { if ep.mac == nil {

View file

@ -263,7 +263,7 @@ func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
s := n.getSubnetforIP(IP) s := n.getSubnetforIP(IP)
if s == nil { if s == nil {
return fmt.Errorf("couldn't find the subnet %q in network %q\n", IP.String(), n.id) return fmt.Errorf("couldn't find the subnet %q in network %q", IP.String(), n.id)
} }
if err := n.obtainVxlanID(s); err != nil { if err := n.obtainVxlanID(s); err != nil {

View file

@ -515,6 +515,10 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error {
return err return err
} }
if err = ep.addDriverInfoToCluster(); err != nil {
return err
}
if sb.needDefaultGW() && sb.getEndpointInGWNetwork() == nil { if sb.needDefaultGW() && sb.getEndpointInGWNetwork() == nil {
return sb.setupDefaultGW() return sb.setupDefaultGW()
} }
@ -709,8 +713,12 @@ func (ep *endpoint) sbLeave(sb *sandbox, force bool, options ...EndpointOption)
return err return err
} }
if e := ep.deleteFromCluster(); e != nil { if e := ep.deleteServiceInfoFromCluster(); e != nil {
logrus.Errorf("Could not delete state for endpoint %s from cluster: %v", ep.Name(), e) logrus.Errorf("Could not delete service state for endpoint %s from cluster: %v", ep.Name(), e)
}
if e := ep.deleteDriverInfoFromCluster(); e != nil {
logrus.Errorf("Could not delete endpoint state for endpoint %s from cluster: %v", ep.Name(), e)
} }
sb.deleteHostsEntries(n.getSvcRecords(ep)) sb.deleteHostsEntries(n.getSvcRecords(ep))

View file

@ -413,7 +413,7 @@ func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error)
} }
} }
return nil, types.NotFoundErrorf("could not find an available non-overlapping address pool among the defaults to auto assign to the network") return nil, types.NotFoundErrorf("could not find an available, non-overlapping IPv%d address pool among the defaults to assign to the network", v)
} }
// RequestAddress returns an address from the specified pool ID // RequestAddress returns an address from the specified pool ID

View file

@ -130,7 +130,7 @@ func NewChain(name string, table Table, hairpinMode bool) (*ChainInfo, error) {
// ProgramChain is used to add rules to a chain // ProgramChain is used to add rules to a chain
func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode, enable bool) error { func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode, enable bool) error {
if c.Name == "" { if c.Name == "" {
return fmt.Errorf("Could not program chain, missing chain name.") return fmt.Errorf("Could not program chain, missing chain name")
} }
switch c.Table { switch c.Table {
@ -166,7 +166,7 @@ func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode, enable bool) err
} }
case Filter: case Filter:
if bridgeName == "" { if bridgeName == "" {
return fmt.Errorf("Could not program chain %s/%s, missing bridge name.", return fmt.Errorf("Could not program chain %s/%s, missing bridge name",
c.Table, c.Name) c.Table, c.Name)
} }
link := []string{ link := []string{

View file

@ -65,6 +65,7 @@ type NetworkInfo interface {
Scope() string Scope() string
IPv6Enabled() bool IPv6Enabled() bool
Internal() bool Internal() bool
Attachable() bool
Labels() map[string]string Labels() map[string]string
Dynamic() bool Dynamic() bool
Created() time.Time Created() time.Time
@ -196,6 +197,7 @@ type network struct {
resolverOnce sync.Once resolverOnce sync.Once
resolver []Resolver resolver []Resolver
internal bool internal bool
attachable bool
inDelete bool inDelete bool
ingress bool ingress bool
driverTables []string driverTables []string
@ -348,6 +350,7 @@ func (n *network) CopyTo(o datastore.KVObject) error {
dstN.dbExists = n.dbExists dstN.dbExists = n.dbExists
dstN.drvOnce = n.drvOnce dstN.drvOnce = n.drvOnce
dstN.internal = n.internal dstN.internal = n.internal
dstN.attachable = n.attachable
dstN.inDelete = n.inDelete dstN.inDelete = n.inDelete
dstN.ingress = n.ingress dstN.ingress = n.ingress
@ -456,6 +459,7 @@ func (n *network) MarshalJSON() ([]byte, error) {
netMap["ipamV6Info"] = string(iis) netMap["ipamV6Info"] = string(iis)
} }
netMap["internal"] = n.internal netMap["internal"] = n.internal
netMap["attachable"] = n.attachable
netMap["inDelete"] = n.inDelete netMap["inDelete"] = n.inDelete
netMap["ingress"] = n.ingress netMap["ingress"] = n.ingress
return json.Marshal(netMap) return json.Marshal(netMap)
@ -550,6 +554,9 @@ func (n *network) UnmarshalJSON(b []byte) (err error) {
if v, ok := netMap["internal"]; ok { if v, ok := netMap["internal"]; ok {
n.internal = v.(bool) n.internal = v.(bool)
} }
if v, ok := netMap["attachable"]; ok {
n.attachable = v.(bool)
}
if s, ok := netMap["scope"]; ok { if s, ok := netMap["scope"]; ok {
n.scope = s.(string) n.scope = s.(string)
} }
@ -628,6 +635,13 @@ func NetworkOptionInternalNetwork() NetworkOption {
} }
} }
// NetworkOptionAttachable returns an option setter to set attachable for a network
func NetworkOptionAttachable(attachable bool) NetworkOption {
return func(n *network) {
n.attachable = attachable
}
}
// NetworkOptionIpam function returns an option setter for the ipam configuration for this network // NetworkOptionIpam function returns an option setter for the ipam configuration for this network
func NetworkOptionIpam(ipamDriver string, addrSpace string, ipV4 []*IpamConf, ipV6 []*IpamConf, opts map[string]string) NetworkOption { func NetworkOptionIpam(ipamDriver string, addrSpace string, ipV4 []*IpamConf, ipV6 []*IpamConf, opts map[string]string) NetworkOption {
return func(n *network) { return func(n *network) {
@ -1289,9 +1303,6 @@ func (n *network) ipamAllocateVersion(ipVer int, ipam ipamapi.Ipam) error {
} }
if len(*cfgList) == 0 { if len(*cfgList) == 0 {
if ipVer == 6 {
return nil
}
*cfgList = []*IpamConf{{}} *cfgList = []*IpamConf{{}}
} }
@ -1555,6 +1566,13 @@ func (n *network) Internal() bool {
return n.internal return n.internal
} }
func (n *network) Attachable() bool {
n.Lock()
defer n.Unlock()
return n.attachable
}
func (n *network) Dynamic() bool { func (n *network) Dynamic() bool {
n.Lock() n.Lock()
defer n.Unlock() defer n.Unlock()

View file

@ -265,7 +265,7 @@ func (nDB *NetworkDB) CreateEntry(tname, nid, key string, value []byte) error {
} }
if err := nDB.sendTableEvent(TableEventTypeCreate, nid, tname, key, entry); err != nil { if err := nDB.sendTableEvent(TableEventTypeCreate, nid, tname, key, entry); err != nil {
return fmt.Errorf("cannot send table create event: %v", err) return fmt.Errorf("cannot send create event for table %s, %v", tname, err)
} }
nDB.Lock() nDB.Lock()

View file

@ -7,6 +7,7 @@ import (
"strings" "strings"
"sync" "sync"
"syscall" "syscall"
"time"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/vishvananda/netlink" "github.com/vishvananda/netlink"
@ -17,6 +18,8 @@ var (
initNs netns.NsHandle initNs netns.NsHandle
initNl *netlink.Handle initNl *netlink.Handle
initOnce sync.Once initOnce sync.Once
// NetlinkSocketsTimeout represents the default timeout duration for the sockets
NetlinkSocketsTimeout = 3 * time.Second
) )
// Init initializes a new network namespace // Init initializes a new network namespace
@ -30,6 +33,10 @@ func Init() {
if err != nil { if err != nil {
logrus.Errorf("could not create netlink handle on initial namespace: %v", err) logrus.Errorf("could not create netlink handle on initial namespace: %v", err)
} }
err = initNl.SetSocketTimeout(NetlinkSocketsTimeout)
if err != nil {
logrus.Warnf("Failed to set the timeout on the default netlink handle sockets: %v", err)
}
} }
// SetNamespace sets the initial namespace handler // SetNamespace sets the initial namespace handler

View file

@ -211,6 +211,11 @@ func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) {
return nil, fmt.Errorf("failed to create a netlink handle: %v", err) return nil, fmt.Errorf("failed to create a netlink handle: %v", err)
} }
err = n.nlHandle.SetSocketTimeout(ns.NetlinkSocketsTimeout)
if err != nil {
logrus.Warnf("Failed to set the timeout on the sandbox netlink handle sockets: %v", err)
}
if err = n.loopbackUp(); err != nil { if err = n.loopbackUp(); err != nil {
n.nlHandle.Delete() n.nlHandle.Delete()
return nil, err return nil, err
@ -253,6 +258,11 @@ func GetSandboxForExternalKey(basePath string, key string) (Sandbox, error) {
return nil, fmt.Errorf("failed to create a netlink handle: %v", err) return nil, fmt.Errorf("failed to create a netlink handle: %v", err)
} }
err = n.nlHandle.SetSocketTimeout(ns.NetlinkSocketsTimeout)
if err != nil {
logrus.Warnf("Failed to set the timeout on the sandbox netlink handle sockets: %v", err)
}
if err = n.loopbackUp(); err != nil { if err = n.loopbackUp(); err != nil {
n.nlHandle.Delete() n.nlHandle.Delete()
return nil, err return nil, err

View file

@ -80,6 +80,7 @@ func (n *networkNamespace) DeleteNeighbor(dstIP net.IP, dstMac net.HardwareAddr,
for i, nh := range n.neighbors { for i, nh := range n.neighbors {
if nh.dstIP.Equal(dstIP) && bytes.Equal(nh.dstMac, dstMac) { if nh.dstIP.Equal(dstIP) && bytes.Equal(nh.dstMac, dstMac) {
n.neighbors = append(n.neighbors[:i], n.neighbors[i+1:]...) n.neighbors = append(n.neighbors[:i], n.neighbors[i+1:]...)
break
} }
} }
n.Unlock() n.Unlock()

View file

@ -427,7 +427,13 @@ func (sb *sandbox) ResolveIP(ip string) string {
} }
func (sb *sandbox) ExecFunc(f func()) error { func (sb *sandbox) ExecFunc(f func()) error {
return sb.osSbox.InvokeFunc(f) sb.Lock()
osSbox := sb.osSbox
sb.Unlock()
if osSbox != nil {
return osSbox.InvokeFunc(f)
}
return fmt.Errorf("osl sandbox unavailable in ExecFunc for %v", sb.ContainerID())
} }
func (sb *sandbox) ResolveService(name string) ([]*net.SRV, []net.IP) { func (sb *sandbox) ResolveService(name string) ([]*net.SRV, []net.IP) {
@ -664,7 +670,7 @@ func (sb *sandbox) SetKey(basePath string) error {
func (sb *sandbox) EnableService() error { func (sb *sandbox) EnableService() error {
for _, ep := range sb.getConnectedEndpoints() { for _, ep := range sb.getConnectedEndpoints() {
if ep.enableService(true) { if ep.enableService(true) {
if err := ep.addToCluster(); err != nil { if err := ep.addServiceInfoToCluster(); err != nil {
ep.enableService(false) ep.enableService(false)
return fmt.Errorf("could not update state for endpoint %s into cluster: %v", ep.Name(), err) return fmt.Errorf("could not update state for endpoint %s into cluster: %v", ep.Name(), err)
} }
@ -676,7 +682,7 @@ func (sb *sandbox) EnableService() error {
func (sb *sandbox) DisableService() error { func (sb *sandbox) DisableService() error {
for _, ep := range sb.getConnectedEndpoints() { for _, ep := range sb.getConnectedEndpoints() {
if ep.enableService(false) { if ep.enableService(false) {
if err := ep.deleteFromCluster(); err != nil { if err := ep.deleteServiceInfoFromCluster(); err != nil {
ep.enableService(true) ep.enableService(true)
return fmt.Errorf("could not delete state for endpoint %s from cluster: %v", ep.Name(), err) return fmt.Errorf("could not delete state for endpoint %s from cluster: %v", ep.Name(), err)
} }

View file

@ -8,11 +8,11 @@ package netlink
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
static int load_simple_bpf(int prog_type) { static int load_simple_bpf(int prog_type, int ret) {
#ifdef __NR_bpf #ifdef __NR_bpf
// { return 1; } // { return ret; }
__u64 __attribute__((aligned(8))) insns[] = { __u64 __attribute__((aligned(8))) insns[] = {
0x00000001000000b7ull, 0x00000000000000b7ull | ((__u64)ret<<32),
0x0000000000000095ull, 0x0000000000000095ull,
}; };
__u8 __attribute__((aligned(8))) license[] = "ASL2"; __u8 __attribute__((aligned(8))) license[] = "ASL2";
@ -51,10 +51,12 @@ const (
BPF_PROG_TYPE_KPROBE BPF_PROG_TYPE_KPROBE
BPF_PROG_TYPE_SCHED_CLS BPF_PROG_TYPE_SCHED_CLS
BPF_PROG_TYPE_SCHED_ACT BPF_PROG_TYPE_SCHED_ACT
BPF_PROG_TYPE_TRACEPOINT
BPF_PROG_TYPE_XDP
) )
// loadSimpleBpf loads a trivial bpf program for testing purposes // loadSimpleBpf loads a trivial bpf program for testing purposes
func loadSimpleBpf(progType BpfProgType) (int, error) { func loadSimpleBpf(progType BpfProgType, ret int) (int, error) {
fd, err := C.load_simple_bpf(C.int(progType)) fd, err := C.load_simple_bpf(C.int(progType), C.int(ret))
return int(fd), err return int(fd), err
} }

View file

@ -60,7 +60,7 @@ func (a TcAct) String() string {
case TC_ACT_JUMP: case TC_ACT_JUMP:
return "jump" return "jump"
} }
return fmt.Sprintf("0x%x", a) return fmt.Sprintf("0x%x", int32(a))
} }
type TcPolAct int32 type TcPolAct int32
@ -86,7 +86,7 @@ func (a TcPolAct) String() string {
case TC_POLICE_PIPE: case TC_POLICE_PIPE:
return "pipe" return "pipe"
} }
return fmt.Sprintf("0x%x", a) return fmt.Sprintf("0x%x", int32(a))
} }
type ActionAttrs struct { type ActionAttrs struct {

View file

@ -1,7 +1,9 @@
package netlink package netlink
import ( import (
"fmt"
"syscall" "syscall"
"time"
"github.com/vishvananda/netlink/nl" "github.com/vishvananda/netlink/nl"
"github.com/vishvananda/netns" "github.com/vishvananda/netns"
@ -33,6 +35,29 @@ func NewHandle(nlFamilies ...int) (*Handle, error) {
return newHandle(netns.None(), netns.None(), nlFamilies...) return newHandle(netns.None(), netns.None(), nlFamilies...)
} }
// SetSocketTimeout sets the send and receive timeout for each socket in the
// netlink handle. Although the socket timeout has granularity of one
// microsecond, the effective granularity is floored by the kernel timer tick,
// which default value is four milliseconds.
func (h *Handle) SetSocketTimeout(to time.Duration) error {
if to < time.Microsecond {
return fmt.Errorf("invalid timeout, minimul value is %s", time.Microsecond)
}
tv := syscall.NsecToTimeval(to.Nanoseconds())
for _, sh := range h.sockets {
fd := sh.Socket.GetFd()
err := syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv)
if err != nil {
return err
}
err = syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, &tv)
if err != nil {
return err
}
}
return nil
}
// NewHandle returns a netlink handle on the network namespace // NewHandle returns a netlink handle on the network namespace
// specified by ns. If ns=netns.None(), current network namespace // specified by ns. If ns=netns.None(), current network namespace
// will be assumed // will be assumed

View file

@ -26,11 +26,15 @@ type LinkAttrs struct {
Name string Name string
HardwareAddr net.HardwareAddr HardwareAddr net.HardwareAddr
Flags net.Flags Flags net.Flags
RawFlags uint32
ParentIndex int // index of the parent link device ParentIndex int // index of the parent link device
MasterIndex int // must be the index of a bridge MasterIndex int // must be the index of a bridge
Namespace interface{} // nil | NsPid | NsFd Namespace interface{} // nil | NsPid | NsFd
Alias string Alias string
Statistics *LinkStatistics Statistics *LinkStatistics
Promisc int
Xdp *LinkXdp
EncapType string
} }
// NewLinkAttrs returns LinkAttrs structure filled with default values // NewLinkAttrs returns LinkAttrs structure filled with default values
@ -69,6 +73,11 @@ type LinkStatistics struct {
TxCompressed uint32 TxCompressed uint32
} }
type LinkXdp struct {
Fd int
Attached bool
}
// Device links cannot be created via netlink. These links // Device links cannot be created via netlink. These links
// are links created by udev like 'lo' and 'etho0' // are links created by udev like 'lo' and 'etho0'
type Device struct { type Device struct {
@ -171,11 +180,13 @@ func (macvtap Macvtap) Type() string {
} }
type TuntapMode uint16 type TuntapMode uint16
type TuntapFlag uint16
// Tuntap links created via /dev/tun/tap, but can be destroyed via netlink // Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
type Tuntap struct { type Tuntap struct {
LinkAttrs LinkAttrs
Mode TuntapMode Mode TuntapMode
Flags TuntapFlag
} }
func (tuntap *Tuntap) Attrs() *LinkAttrs { func (tuntap *Tuntap) Attrs() *LinkAttrs {
@ -251,6 +262,7 @@ type IPVlanMode uint16
const ( const (
IPVLAN_MODE_L2 IPVlanMode = iota IPVLAN_MODE_L2 IPVlanMode = iota
IPVLAN_MODE_L3 IPVLAN_MODE_L3
IPVLAN_MODE_L3S
IPVLAN_MODE_MAX IPVLAN_MODE_MAX
) )

View file

@ -16,8 +16,13 @@ import (
const SizeofLinkStats = 0x5c const SizeofLinkStats = 0x5c
const ( const (
TUNTAP_MODE_TUN TuntapMode = syscall.IFF_TUN TUNTAP_MODE_TUN TuntapMode = syscall.IFF_TUN
TUNTAP_MODE_TAP TuntapMode = syscall.IFF_TAP TUNTAP_MODE_TAP TuntapMode = syscall.IFF_TAP
TUNTAP_DEFAULTS TuntapFlag = syscall.IFF_TUN_EXCL | syscall.IFF_ONE_QUEUE
TUNTAP_VNET_HDR TuntapFlag = syscall.IFF_VNET_HDR
TUNTAP_TUN_EXCL TuntapFlag = syscall.IFF_TUN_EXCL
TUNTAP_NO_PI TuntapFlag = syscall.IFF_NO_PI
TUNTAP_ONE_QUEUE TuntapFlag = syscall.IFF_ONE_QUEUE
) )
var native = nl.NativeEndian() var native = nl.NativeEndian()
@ -50,6 +55,44 @@ func (h *Handle) ensureIndex(link *LinkAttrs) {
} }
} }
func (h *Handle) SetPromiscOn(link Link) error {
base := link.Attrs()
h.ensureIndex(base)
req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
msg.Change = syscall.IFF_PROMISC
msg.Flags = syscall.IFF_UP
msg.Index = int32(base.Index)
req.AddData(msg)
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
return err
}
func SetPromiscOn(link Link) error {
return pkgHandle.SetPromiscOn(link)
}
func (h *Handle) SetPromiscOff(link Link) error {
base := link.Attrs()
h.ensureIndex(base)
req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
msg.Change = syscall.IFF_PROMISC
msg.Flags = 0 & ^syscall.IFF_UP
msg.Index = int32(base.Index)
req.AddData(msg)
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
return err
}
func SetPromiscOff(link Link) error {
return pkgHandle.SetPromiscOff(link)
}
// LinkSetUp enables the link device. // LinkSetUp enables the link device.
// Equivalent to: `ip link set $link up` // Equivalent to: `ip link set $link up`
func LinkSetUp(link Link) error { func LinkSetUp(link Link) error {
@ -255,6 +298,36 @@ func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error {
return err return err
} }
// LinkSetVfTxRate sets the tx rate of a vf for the link.
// Equivalent to: `ip link set $link vf $vf rate $rate`
func LinkSetVfTxRate(link Link, vf, rate int) error {
return pkgHandle.LinkSetVfTxRate(link, vf, rate)
}
// LinkSetVfTxRate sets the tx rate of a vf for the link.
// Equivalent to: `ip link set $link vf $vf rate $rate`
func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error {
base := link.Attrs()
h.ensureIndex(base)
req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
msg.Index = int32(base.Index)
req.AddData(msg)
data := nl.NewRtAttr(nl.IFLA_VFINFO_LIST, nil)
info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil)
vfmsg := nl.VfTxRate{
Vf: uint32(vf),
Rate: uint32(rate),
}
nl.NewRtAttrChild(info, nl.IFLA_VF_TX_RATE, vfmsg.Serialize())
req.AddData(data)
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
return err
}
// LinkSetMaster sets the master of the link device. // LinkSetMaster sets the master of the link device.
// Equivalent to: `ip link set $link master $master` // Equivalent to: `ip link set $link master $master`
func LinkSetMaster(link Link, master *Bridge) error { func LinkSetMaster(link Link, master *Bridge) error {
@ -373,6 +446,23 @@ func (h *Handle) LinkSetNsFd(link Link, fd int) error {
return err return err
} }
// LinkSetXdpFd adds a bpf function to the driver. The fd must be a bpf
// program loaded with bpf(type=BPF_PROG_TYPE_XDP)
func LinkSetXdpFd(link Link, fd int) error {
base := link.Attrs()
ensureIndex(base)
req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
msg.Index = int32(base.Index)
req.AddData(msg)
addXdpAttrs(&LinkXdp{Fd: fd}, req)
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
return err
}
func boolAttr(val bool) []byte { func boolAttr(val bool) []byte {
var v uint8 var v uint8
if val { if val {
@ -552,9 +642,7 @@ func (h *Handle) LinkAdd(link Link) error {
if tuntap, ok := link.(*Tuntap); ok { if tuntap, ok := link.(*Tuntap); ok {
// TODO: support user // TODO: support user
// TODO: support group // TODO: support group
// TODO: support non- one_queue // TODO: multi_queue
// TODO: support pi | vnet_hdr | multi_queue
// TODO: support non- exclusive
// TODO: support non- persistent // TODO: support non- persistent
if tuntap.Mode < syscall.IFF_TUN || tuntap.Mode > syscall.IFF_TAP { if tuntap.Mode < syscall.IFF_TUN || tuntap.Mode > syscall.IFF_TAP {
return fmt.Errorf("Tuntap.Mode %v unknown!", tuntap.Mode) return fmt.Errorf("Tuntap.Mode %v unknown!", tuntap.Mode)
@ -565,10 +653,13 @@ func (h *Handle) LinkAdd(link Link) error {
} }
defer file.Close() defer file.Close()
var req ifReq var req ifReq
req.Flags |= syscall.IFF_ONE_QUEUE if tuntap.Flags == 0 {
req.Flags |= syscall.IFF_TUN_EXCL req.Flags = uint16(TUNTAP_DEFAULTS)
copy(req.Name[:15], base.Name) } else {
req.Flags = uint16(tuntap.Flags)
}
req.Flags |= uint16(tuntap.Mode) req.Flags |= uint16(tuntap.Mode)
copy(req.Name[:15], base.Name)
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), uintptr(syscall.TUNSETIFF), uintptr(unsafe.Pointer(&req))) _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), uintptr(syscall.TUNSETIFF), uintptr(unsafe.Pointer(&req)))
if errno != 0 { if errno != 0 {
return fmt.Errorf("Tuntap IOCTL TUNSETIFF failed, errno %v", errno) return fmt.Errorf("Tuntap IOCTL TUNSETIFF failed, errno %v", errno)
@ -649,6 +740,10 @@ func (h *Handle) LinkAdd(link Link) error {
req.AddData(attr) req.AddData(attr)
} }
if base.Xdp != nil {
addXdpAttrs(base.Xdp, req)
}
linkInfo := nl.NewRtAttr(syscall.IFLA_LINKINFO, nil) linkInfo := nl.NewRtAttr(syscall.IFLA_LINKINFO, nil)
nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type())) nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type()))
@ -871,7 +966,10 @@ func linkDeserialize(m []byte) (Link, error) {
return nil, err return nil, err
} }
base := LinkAttrs{Index: int(msg.Index), Flags: linkFlags(msg.Flags)} base := LinkAttrs{Index: int(msg.Index), RawFlags: msg.Flags, Flags: linkFlags(msg.Flags), EncapType: msg.EncapType()}
if msg.Flags&syscall.IFF_PROMISC != 0 {
base.Promisc = 1
}
var link Link var link Link
linkType := "" linkType := ""
for _, attr := range attrs { for _, attr := range attrs {
@ -958,6 +1056,12 @@ func linkDeserialize(m []byte) (Link, error) {
base.Alias = string(attr.Value[:len(attr.Value)-1]) base.Alias = string(attr.Value[:len(attr.Value)-1])
case syscall.IFLA_STATS: case syscall.IFLA_STATS:
base.Statistics = parseLinkStats(attr.Value[:]) base.Statistics = parseLinkStats(attr.Value[:])
case nl.IFLA_XDP:
xdp, err := parseLinkXdp(attr.Value[:])
if err != nil {
return nil, err
}
base.Xdp = xdp
} }
} }
// Links that don't have IFLA_INFO_KIND are hardware devices // Links that don't have IFLA_INFO_KIND are hardware devices
@ -1389,3 +1493,28 @@ func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) {
func parseLinkStats(data []byte) *LinkStatistics { func parseLinkStats(data []byte) *LinkStatistics {
return (*LinkStatistics)(unsafe.Pointer(&data[0:SizeofLinkStats][0])) return (*LinkStatistics)(unsafe.Pointer(&data[0:SizeofLinkStats][0]))
} }
func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) {
attrs := nl.NewRtAttr(nl.IFLA_XDP|syscall.NLA_F_NESTED, nil)
b := make([]byte, 4)
native.PutUint32(b, uint32(xdp.Fd))
nl.NewRtAttrChild(attrs, nl.IFLA_XDP_FD, b)
req.AddData(attrs)
}
func parseLinkXdp(data []byte) (*LinkXdp, error) {
attrs, err := nl.ParseRouteAttr(data)
if err != nil {
return nil, err
}
xdp := &LinkXdp{}
for _, attr := range attrs {
switch attr.Attr.Type {
case nl.IFLA_XDP_FD:
xdp.Fd = int(native.Uint32(attr.Value[0:4]))
case nl.IFLA_XDP_ATTACHED:
xdp.Attached = attr.Value[0] != 0
}
}
return xdp, nil
}

View file

@ -151,8 +151,10 @@ func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
dstData := nl.NewRtAttr(NDA_DST, ipData) dstData := nl.NewRtAttr(NDA_DST, ipData)
req.AddData(dstData) req.AddData(dstData)
hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr)) if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil {
req.AddData(hwData) hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
req.AddData(hwData)
}
_, err := req.Execute(syscall.NETLINK_ROUTE, 0) _, err := req.Execute(syscall.NETLINK_ROUTE, 0)
return err return err
@ -165,14 +167,33 @@ func NeighList(linkIndex, family int) ([]Neigh, error) {
return pkgHandle.NeighList(linkIndex, family) return pkgHandle.NeighList(linkIndex, family)
} }
// NeighProxyList gets a list of neighbor proxies in the system.
// Equivalent to: `ip neighbor show proxy`.
// The list can be filtered by link and ip family.
func NeighProxyList(linkIndex, family int) ([]Neigh, error) {
return pkgHandle.NeighProxyList(linkIndex, family)
}
// NeighList gets a list of IP-MAC mappings in the system (ARP table). // NeighList gets a list of IP-MAC mappings in the system (ARP table).
// Equivalent to: `ip neighbor show`. // Equivalent to: `ip neighbor show`.
// The list can be filtered by link and ip family. // The list can be filtered by link and ip family.
func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) { func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) {
return h.neighList(linkIndex, family, 0)
}
// NeighProxyList gets a list of neighbor proxies in the system.
// Equivalent to: `ip neighbor show proxy`.
// The list can be filtered by link, ip family.
func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) {
return h.neighList(linkIndex, family, NTF_PROXY)
}
func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) {
req := h.newNetlinkRequest(syscall.RTM_GETNEIGH, syscall.NLM_F_DUMP) req := h.newNetlinkRequest(syscall.RTM_GETNEIGH, syscall.NLM_F_DUMP)
msg := Ndmsg{ msg := Ndmsg{
Family: uint8(family), Family: uint8(family),
Index: uint32(linkIndex), Index: uint32(linkIndex),
Flags: uint8(flags),
} }
req.AddData(&msg) req.AddData(&msg)

View file

@ -78,7 +78,7 @@ func AddrDel(link *Link, addr *Addr) error {
return ErrNotImplemented return ErrNotImplemented
} }
func AddrList(link *Link, family int) ([]Addr, error) { func AddrList(link Link, family int) ([]Addr, error) {
return nil, ErrNotImplemented return nil, ErrNotImplemented
} }

View file

@ -1,13 +1,35 @@
package nl package nl
import ( import (
"syscall"
"unsafe" "unsafe"
) )
const ( const (
DEFAULT_CHANGE = 0xFFFFFFFF DEFAULT_CHANGE = 0xFFFFFFFF
// doesn't exist in syscall // doesn't exist in syscall
IFLA_VFINFO_LIST = 0x16 IFLA_VFINFO_LIST = syscall.IFLA_IFALIAS + 1 + iota
IFLA_STATS64
IFLA_VF_PORTS
IFLA_PORT_SELF
IFLA_AF_SPEC
IFLA_GROUP
IFLA_NET_NS_FD
IFLA_EXT_MASK
IFLA_PROMISCUITY
IFLA_NUM_TX_QUEUES
IFLA_NUM_RX_QUEUES
IFLA_CARRIER
IFLA_PHYS_PORT_ID
IFLA_CARRIER_CHANGES
IFLA_PHYS_SWITCH_ID
IFLA_LINK_NETNSID
IFLA_PHYS_PORT_NAME
IFLA_PROTO_DOWN
IFLA_GSO_MAX_SEGS
IFLA_GSO_MAX_SIZE
IFLA_PAD
IFLA_XDP
) )
const ( const (
@ -89,11 +111,6 @@ const (
IFLA_IPVLAN_MAX = IFLA_IPVLAN_MODE IFLA_IPVLAN_MAX = IFLA_IPVLAN_MODE
) )
const (
// not defined in syscall
IFLA_NET_NS_FD = 28
)
const ( const (
IFLA_MACVLAN_UNSPEC = iota IFLA_MACVLAN_UNSPEC = iota
IFLA_MACVLAN_MODE IFLA_MACVLAN_MODE
@ -394,3 +411,10 @@ func DeserializeVfRssQueryEn(b []byte) *VfRssQueryEn {
func (msg *VfRssQueryEn) Serialize() []byte { func (msg *VfRssQueryEn) Serialize() []byte {
return (*(*[SizeofVfRssQueryEn]byte)(unsafe.Pointer(msg)))[:] return (*(*[SizeofVfRssQueryEn]byte)(unsafe.Pointer(msg)))[:]
} }
const (
IFLA_XDP_UNSPEC = iota
IFLA_XDP_FD /* fd of xdp program to attach, or -1 to remove */
IFLA_XDP_ATTACHED /* read-only bool indicating if prog is attached */
IFLA_XDP_MAX = IFLA_XDP_ATTACHED
)

View file

@ -100,6 +100,147 @@ func (msg *IfInfomsg) Len() int {
return syscall.SizeofIfInfomsg return syscall.SizeofIfInfomsg
} }
func (msg *IfInfomsg) EncapType() string {
switch msg.Type {
case 0:
return "generic"
case syscall.ARPHRD_ETHER:
return "ether"
case syscall.ARPHRD_EETHER:
return "eether"
case syscall.ARPHRD_AX25:
return "ax25"
case syscall.ARPHRD_PRONET:
return "pronet"
case syscall.ARPHRD_CHAOS:
return "chaos"
case syscall.ARPHRD_IEEE802:
return "ieee802"
case syscall.ARPHRD_ARCNET:
return "arcnet"
case syscall.ARPHRD_APPLETLK:
return "atalk"
case syscall.ARPHRD_DLCI:
return "dlci"
case syscall.ARPHRD_ATM:
return "atm"
case syscall.ARPHRD_METRICOM:
return "metricom"
case syscall.ARPHRD_IEEE1394:
return "ieee1394"
case syscall.ARPHRD_INFINIBAND:
return "infiniband"
case syscall.ARPHRD_SLIP:
return "slip"
case syscall.ARPHRD_CSLIP:
return "cslip"
case syscall.ARPHRD_SLIP6:
return "slip6"
case syscall.ARPHRD_CSLIP6:
return "cslip6"
case syscall.ARPHRD_RSRVD:
return "rsrvd"
case syscall.ARPHRD_ADAPT:
return "adapt"
case syscall.ARPHRD_ROSE:
return "rose"
case syscall.ARPHRD_X25:
return "x25"
case syscall.ARPHRD_HWX25:
return "hwx25"
case syscall.ARPHRD_PPP:
return "ppp"
case syscall.ARPHRD_HDLC:
return "hdlc"
case syscall.ARPHRD_LAPB:
return "lapb"
case syscall.ARPHRD_DDCMP:
return "ddcmp"
case syscall.ARPHRD_RAWHDLC:
return "rawhdlc"
case syscall.ARPHRD_TUNNEL:
return "ipip"
case syscall.ARPHRD_TUNNEL6:
return "tunnel6"
case syscall.ARPHRD_FRAD:
return "frad"
case syscall.ARPHRD_SKIP:
return "skip"
case syscall.ARPHRD_LOOPBACK:
return "loopback"
case syscall.ARPHRD_LOCALTLK:
return "ltalk"
case syscall.ARPHRD_FDDI:
return "fddi"
case syscall.ARPHRD_BIF:
return "bif"
case syscall.ARPHRD_SIT:
return "sit"
case syscall.ARPHRD_IPDDP:
return "ip/ddp"
case syscall.ARPHRD_IPGRE:
return "gre"
case syscall.ARPHRD_PIMREG:
return "pimreg"
case syscall.ARPHRD_HIPPI:
return "hippi"
case syscall.ARPHRD_ASH:
return "ash"
case syscall.ARPHRD_ECONET:
return "econet"
case syscall.ARPHRD_IRDA:
return "irda"
case syscall.ARPHRD_FCPP:
return "fcpp"
case syscall.ARPHRD_FCAL:
return "fcal"
case syscall.ARPHRD_FCPL:
return "fcpl"
case syscall.ARPHRD_FCFABRIC:
return "fcfb0"
case syscall.ARPHRD_FCFABRIC + 1:
return "fcfb1"
case syscall.ARPHRD_FCFABRIC + 2:
return "fcfb2"
case syscall.ARPHRD_FCFABRIC + 3:
return "fcfb3"
case syscall.ARPHRD_FCFABRIC + 4:
return "fcfb4"
case syscall.ARPHRD_FCFABRIC + 5:
return "fcfb5"
case syscall.ARPHRD_FCFABRIC + 6:
return "fcfb6"
case syscall.ARPHRD_FCFABRIC + 7:
return "fcfb7"
case syscall.ARPHRD_FCFABRIC + 8:
return "fcfb8"
case syscall.ARPHRD_FCFABRIC + 9:
return "fcfb9"
case syscall.ARPHRD_FCFABRIC + 10:
return "fcfb10"
case syscall.ARPHRD_FCFABRIC + 11:
return "fcfb11"
case syscall.ARPHRD_FCFABRIC + 12:
return "fcfb12"
case syscall.ARPHRD_IEEE802_TR:
return "tr"
case syscall.ARPHRD_IEEE80211:
return "ieee802.11"
case syscall.ARPHRD_IEEE80211_PRISM:
return "ieee802.11/prism"
case syscall.ARPHRD_IEEE80211_RADIOTAP:
return "ieee802.11/radiotap"
case syscall.ARPHRD_IEEE802154:
return "ieee802.15.4"
case 65534:
return "none"
case 65535:
return "void"
}
return fmt.Sprintf("unknown%d", msg.Type)
}
func rtaAlignOf(attrlen int) int { func rtaAlignOf(attrlen int) int {
return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1) return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1)
} }

View file

@ -153,7 +153,7 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
} else { } else {
gw = nl.NewRtAttr(syscall.RTA_GATEWAY, []byte(nh.Gw.To16())) gw = nl.NewRtAttr(syscall.RTA_GATEWAY, []byte(nh.Gw.To16()))
} }
gwData := gw.Serialize() gwData = gw.Serialize()
rtnh.Len += uint16(len(gwData)) rtnh.Len += uint16(len(gwData))
} }
buf = append(buf, rtnh.Serialize()...) buf = append(buf, rtnh.Serialize()...)

View file

@ -82,41 +82,46 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
req.AddData(rtAttrs[i]) req.AddData(rtAttrs[i])
} }
var ( native := nl.NativeEndian()
b = make([]byte, 4)
native = nl.NativeEndian()
)
if rule.Priority >= 0 { if rule.Priority >= 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.Priority)) native.PutUint32(b, uint32(rule.Priority))
req.AddData(nl.NewRtAttr(nl.FRA_PRIORITY, b)) req.AddData(nl.NewRtAttr(nl.FRA_PRIORITY, b))
} }
if rule.Mark >= 0 { if rule.Mark >= 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.Mark)) native.PutUint32(b, uint32(rule.Mark))
req.AddData(nl.NewRtAttr(nl.FRA_FWMARK, b)) req.AddData(nl.NewRtAttr(nl.FRA_FWMARK, b))
} }
if rule.Mask >= 0 { if rule.Mask >= 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.Mask)) native.PutUint32(b, uint32(rule.Mask))
req.AddData(nl.NewRtAttr(nl.FRA_FWMASK, b)) req.AddData(nl.NewRtAttr(nl.FRA_FWMASK, b))
} }
if rule.Flow >= 0 { if rule.Flow >= 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.Flow)) native.PutUint32(b, uint32(rule.Flow))
req.AddData(nl.NewRtAttr(nl.FRA_FLOW, b)) req.AddData(nl.NewRtAttr(nl.FRA_FLOW, b))
} }
if rule.TunID > 0 { if rule.TunID > 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.TunID)) native.PutUint32(b, uint32(rule.TunID))
req.AddData(nl.NewRtAttr(nl.FRA_TUN_ID, b)) req.AddData(nl.NewRtAttr(nl.FRA_TUN_ID, b))
} }
if rule.Table >= 256 { if rule.Table >= 256 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.Table)) native.PutUint32(b, uint32(rule.Table))
req.AddData(nl.NewRtAttr(nl.FRA_TABLE, b)) req.AddData(nl.NewRtAttr(nl.FRA_TABLE, b))
} }
if msg.Table > 0 { if msg.Table > 0 {
if rule.SuppressPrefixlen >= 0 { if rule.SuppressPrefixlen >= 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.SuppressPrefixlen)) native.PutUint32(b, uint32(rule.SuppressPrefixlen))
req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_PREFIXLEN, b)) req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_PREFIXLEN, b))
} }
if rule.SuppressIfgroup >= 0 { if rule.SuppressIfgroup >= 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.SuppressIfgroup)) native.PutUint32(b, uint32(rule.SuppressIfgroup))
req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_IFGROUP, b)) req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_IFGROUP, b))
} }
@ -129,6 +134,7 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
} }
if rule.Goto >= 0 { if rule.Goto >= 0 {
msg.Type = nl.FR_ACT_NOP msg.Type = nl.FR_ACT_NOP
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.Goto)) native.PutUint32(b, uint32(rule.Goto))
req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b)) req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b))
} }

View file

@ -213,7 +213,7 @@ func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState
req.AddData(out) req.AddData(out)
} }
if state.Src != nil { if state.Src != nil {
out := nl.NewRtAttr(nl.XFRMA_SRCADDR, state.Src) out := nl.NewRtAttr(nl.XFRMA_SRCADDR, state.Src.To16())
req.AddData(out) req.AddData(out)
} }