Merge pull request #29004 from aboch/c1.12.x
[1.12.x] Porting libnetwork fixes
This commit is contained in:
commit
f25e197379
35 changed files with 603 additions and 117 deletions
|
@ -65,7 +65,7 @@ clone git github.com/RackSec/srslog 365bf33cd9acc21ae1c355209865f17228ca534e
|
|||
clone git github.com/imdario/mergo 0.2.1
|
||||
|
||||
#get libnetwork packages
|
||||
clone git github.com/docker/libnetwork 66c844678f7d7df33e4f46184e5b4749f0204b5a
|
||||
clone git github.com/docker/libnetwork 73363066ecb4df200da5a056d79ca4026376a5ad
|
||||
clone git github.com/docker/go-events afb2b9f2c23f33ada1a22b03651775fdc65a5089
|
||||
clone git github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
|
||||
clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
|
||||
|
@ -73,9 +73,9 @@ clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece581016509
|
|||
clone git github.com/hashicorp/memberlist 88ac4de0d1a0ca6def284b571342db3b777a4c37
|
||||
clone git github.com/hashicorp/go-multierror fcdddc395df1ddf4247c69bd436e84cfa0733f7e
|
||||
clone git github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870
|
||||
clone git github.com/docker/libkv v0.2.1
|
||||
clone git github.com/docker/libkv 1d8431073ae03cdaedb198a89722f3aab6d418ef
|
||||
clone git github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25
|
||||
clone git github.com/vishvananda/netlink e73bad418fd727ed3a02830b1af1ad0283a1de6c
|
||||
clone git github.com/vishvananda/netlink 17ea11b5a11c5614597c65a671105e8ee58c4d04
|
||||
clone git github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060
|
||||
clone git github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374
|
||||
clone git github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d
|
||||
|
|
|
@ -671,7 +671,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkInspectCustomUnspecified(c *check.
|
|||
}
|
||||
|
||||
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")
|
||||
|
||||
nr := getNetworkResource(c, "br0")
|
||||
|
@ -680,7 +680,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkInspectCustomSpecified(c *check.C)
|
|||
c.Assert(nr.Internal, checker.Equals, false)
|
||||
c.Assert(nr.EnableIPv6, checker.Equals, true)
|
||||
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].IPRange, checker.Equals, "172.28.5.0/24")
|
||||
c.Assert(nr.IPAM.Config[0].Gateway, checker.Equals, "172.28.5.254")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.5.3
|
||||
- 1.7.1
|
||||
|
||||
# let us have speedy Docker-based Travis workers
|
||||
sudo: false
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
[Org]
|
||||
[Org."Core maintainers"]
|
||||
people = [
|
||||
"abronan",
|
||||
"aluzzardi",
|
||||
"sanimej",
|
||||
"vieux",
|
||||
|
@ -25,11 +24,6 @@
|
|||
|
||||
# ADD YOURSELF HERE IN ALPHABETICAL ORDER
|
||||
|
||||
[people.abronan]
|
||||
Name = "Alexandre Beslic"
|
||||
Email = "abronan@docker.com"
|
||||
GitHub = "abronan"
|
||||
|
||||
[people.aluzzardi]
|
||||
Name = "Andrea Luzzardi"
|
||||
Email = "al@docker.com"
|
||||
|
|
|
@ -59,6 +59,7 @@ func New(endpoints []string, options *store.Config) (store.Store, error) {
|
|||
db *bolt.DB
|
||||
err error
|
||||
boltOptions *bolt.Options
|
||||
timeout = transientTimeout
|
||||
)
|
||||
|
||||
if len(endpoints) > 1 {
|
||||
|
@ -82,11 +83,15 @@ func New(endpoints []string, options *store.Config) (store.Store, error) {
|
|||
}
|
||||
}
|
||||
|
||||
if options.ConnectionTimeout != 0 {
|
||||
timeout = options.ConnectionTimeout
|
||||
}
|
||||
|
||||
b := &BoltDB{
|
||||
client: db,
|
||||
path: endpoints[0],
|
||||
boltBucket: []byte(options.Bucket),
|
||||
timeout: transientTimeout,
|
||||
timeout: timeout,
|
||||
PersistConnection: options.PersistConnection,
|
||||
}
|
||||
|
||||
|
|
156
vendor/src/github.com/docker/libnetwork/agent.go
vendored
156
vendor/src/github.com/docker/libnetwork/agent.go
vendored
|
@ -7,6 +7,7 @@ import (
|
|||
"net"
|
||||
"os"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
|
@ -39,6 +40,7 @@ type agent struct {
|
|||
advertiseAddr string
|
||||
epTblCancel func()
|
||||
driverCancelFuncs map[string][]func()
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func getBindAddr(ifaceName string) (string, error) {
|
||||
|
@ -86,9 +88,16 @@ func resolveAddr(addrOrInterface string) (string, error) {
|
|||
func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error {
|
||||
drvEnc := discoverapi.DriverEncryptionUpdate{}
|
||||
|
||||
a := c.agent
|
||||
a := c.getAgent()
|
||||
if a == nil {
|
||||
logrus.Debug("Skipping key change as agent is nil")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Find the deleted key. If the deleted key was the primary key,
|
||||
// a new primary key should be set before removing if from keyring.
|
||||
c.Lock()
|
||||
added := []byte{}
|
||||
deleted := []byte{}
|
||||
j := len(c.keys)
|
||||
for i := 0; i < j; {
|
||||
|
@ -127,7 +136,7 @@ func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error {
|
|||
if !same {
|
||||
c.keys = append(c.keys, key)
|
||||
if key.Subsystem == subsysGossip {
|
||||
a.networkDB.SetKey(key.Key)
|
||||
added = key.Key
|
||||
}
|
||||
|
||||
if key.Subsystem == subsysIPSec {
|
||||
|
@ -136,6 +145,11 @@ func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
c.Unlock()
|
||||
|
||||
if len(added) > 0 {
|
||||
a.networkDB.SetKey(added)
|
||||
}
|
||||
|
||||
key, tag, err := c.getPrimaryKeyTag(subsysGossip)
|
||||
if err != nil {
|
||||
|
@ -166,8 +180,10 @@ func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error {
|
|||
}
|
||||
|
||||
func (c *controller) agentSetup() error {
|
||||
c.Lock()
|
||||
clusterProvider := c.cfg.Daemon.ClusterProvider
|
||||
|
||||
agent := c.agent
|
||||
c.Unlock()
|
||||
bindAddr := clusterProvider.GetLocalAddress()
|
||||
advAddr := clusterProvider.GetAdvertiseAddress()
|
||||
remote := clusterProvider.GetRemoteAddress()
|
||||
|
@ -176,7 +192,7 @@ func (c *controller) agentSetup() error {
|
|||
listenAddr, _, _ := net.SplitHostPort(listen)
|
||||
|
||||
logrus.Infof("Initializing Libnetwork Agent Listen-Addr=%s Local-addr=%s Adv-addr=%s Remote-addr =%s", listenAddr, bindAddr, advAddr, remoteAddr)
|
||||
if advAddr != "" && c.agent == nil {
|
||||
if advAddr != "" && agent == nil {
|
||||
if err := c.agentInit(listenAddr, bindAddr, advAddr); err != nil {
|
||||
logrus.Errorf("Error in agentInit : %v", err)
|
||||
} else {
|
||||
|
@ -208,6 +224,9 @@ func (c *controller) agentSetup() error {
|
|||
// For a given subsystem getKeys sorts the keys by lamport time and returns
|
||||
// slice of keys and lamport time which can used as a unique tag for the keys
|
||||
func (c *controller) getKeys(subsys string) ([][]byte, []uint64) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
sort.Sort(ByTime(c.keys))
|
||||
|
||||
keys := [][]byte{}
|
||||
|
@ -227,6 +246,8 @@ func (c *controller) getKeys(subsys string) ([][]byte, []uint64) {
|
|||
// getPrimaryKeyTag returns the primary key for a given subsystem from the
|
||||
// list of sorted key and the associated tag
|
||||
func (c *controller) getPrimaryKeyTag(subsys string) ([]byte, uint64, error) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
sort.Sort(ByTime(c.keys))
|
||||
keys := []*types.EncryptionKey{}
|
||||
for _, key := range c.keys {
|
||||
|
@ -265,6 +286,7 @@ func (c *controller) agentInit(listenAddr, bindAddrOrInterface, advertiseAddr st
|
|||
|
||||
ch, cancel := nDB.Watch("endpoint_table", "", "")
|
||||
|
||||
c.Lock()
|
||||
c.agent = &agent{
|
||||
networkDB: nDB,
|
||||
bindAddr: bindAddr,
|
||||
|
@ -272,6 +294,7 @@ func (c *controller) agentInit(listenAddr, bindAddrOrInterface, advertiseAddr st
|
|||
epTblCancel: cancel,
|
||||
driverCancelFuncs: make(map[string][]func()),
|
||||
}
|
||||
c.Unlock()
|
||||
|
||||
go c.handleTableEvents(ch, c.handleEpTableEvent)
|
||||
|
||||
|
@ -294,21 +317,22 @@ func (c *controller) agentInit(listenAddr, bindAddrOrInterface, advertiseAddr st
|
|||
}
|
||||
|
||||
func (c *controller) agentJoin(remote string) error {
|
||||
if c.agent == nil {
|
||||
agent := c.getAgent()
|
||||
if agent == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return c.agent.networkDB.Join([]string{remote})
|
||||
return agent.networkDB.Join([]string{remote})
|
||||
}
|
||||
|
||||
func (c *controller) agentDriverNotify(d driverapi.Driver) {
|
||||
if c.agent == nil {
|
||||
agent := c.getAgent()
|
||||
if agent == nil {
|
||||
return
|
||||
}
|
||||
|
||||
d.DiscoverNew(discoverapi.NodeDiscovery, discoverapi.NodeDiscoveryData{
|
||||
Address: c.agent.advertiseAddr,
|
||||
BindAddress: c.agent.bindAddr,
|
||||
Address: agent.advertiseAddr,
|
||||
BindAddress: agent.bindAddr,
|
||||
Self: true,
|
||||
})
|
||||
|
||||
|
@ -328,35 +352,41 @@ func (c *controller) agentDriverNotify(d driverapi.Driver) {
|
|||
}
|
||||
|
||||
func (c *controller) agentClose() {
|
||||
if c.agent == nil {
|
||||
// Acquire current agent instance and reset its pointer
|
||||
// then run closing functions
|
||||
c.Lock()
|
||||
agent := c.agent
|
||||
c.agent = nil
|
||||
c.Unlock()
|
||||
|
||||
if agent == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, cancelFuncs := range c.agent.driverCancelFuncs {
|
||||
var cancelList []func()
|
||||
|
||||
agent.Lock()
|
||||
for _, cancelFuncs := range agent.driverCancelFuncs {
|
||||
for _, cancel := range cancelFuncs {
|
||||
cancel()
|
||||
cancelList = append(cancelList, cancel)
|
||||
}
|
||||
}
|
||||
c.agent.epTblCancel()
|
||||
agent.Unlock()
|
||||
|
||||
c.agent.networkDB.Close()
|
||||
for _, cancel := range cancelList {
|
||||
cancel()
|
||||
}
|
||||
|
||||
c.Lock()
|
||||
c.agent = nil
|
||||
c.Unlock()
|
||||
agent.epTblCancel()
|
||||
|
||||
agent.networkDB.Close()
|
||||
}
|
||||
|
||||
func (n *network) isClusterEligible() bool {
|
||||
if n.driverScope() != datastore.GlobalScope {
|
||||
return false
|
||||
}
|
||||
|
||||
c := n.getController()
|
||||
if c.agent == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
return n.getController().getAgent() != nil
|
||||
}
|
||||
|
||||
func (n *network) joinCluster() error {
|
||||
|
@ -364,8 +394,12 @@ func (n *network) joinCluster() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
c := n.getController()
|
||||
return c.agent.networkDB.JoinNetwork(n.ID())
|
||||
agent := n.getController().getAgent()
|
||||
if agent == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return agent.networkDB.JoinNetwork(n.ID())
|
||||
}
|
||||
|
||||
func (n *network) leaveCluster() error {
|
||||
|
@ -373,8 +407,12 @@ func (n *network) leaveCluster() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
c := n.getController()
|
||||
return c.agent.networkDB.LeaveNetwork(n.ID())
|
||||
agent := n.getController().getAgent()
|
||||
if agent == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return agent.networkDB.LeaveNetwork(n.ID())
|
||||
}
|
||||
|
||||
func (ep *endpoint) addToCluster() error {
|
||||
|
@ -384,6 +422,7 @@ func (ep *endpoint) addToCluster() error {
|
|||
}
|
||||
|
||||
c := n.getController()
|
||||
agent := c.getAgent()
|
||||
if !ep.isAnonymous() && ep.Iface().Address() != nil {
|
||||
var ingressPorts []*PortConfig
|
||||
if ep.svcID != "" {
|
||||
|
@ -412,13 +451,19 @@ func (ep *endpoint) addToCluster() error {
|
|||
return err
|
||||
}
|
||||
|
||||
if err := c.agent.networkDB.CreateEntry("endpoint_table", n.ID(), ep.ID(), buf); err != nil {
|
||||
return err
|
||||
if agent != nil {
|
||||
if err := agent.networkDB.CreateEntry("endpoint_table", n.ID(), ep.ID(), buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if agent == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, te := range ep.joinInfo.driverTableEntries {
|
||||
if err := c.agent.networkDB.CreateEntry(te.tableName, n.ID(), te.key, te.value); err != nil {
|
||||
if err := agent.networkDB.CreateEntry(te.tableName, n.ID(), te.key, te.value); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -433,6 +478,8 @@ func (ep *endpoint) deleteFromCluster() error {
|
|||
}
|
||||
|
||||
c := n.getController()
|
||||
agent := c.getAgent()
|
||||
|
||||
if !ep.isAnonymous() {
|
||||
if ep.svcID != "" && ep.Iface().Address() != nil {
|
||||
var ingressPorts []*PortConfig
|
||||
|
@ -445,8 +492,10 @@ func (ep *endpoint) deleteFromCluster() error {
|
|||
}
|
||||
}
|
||||
|
||||
if err := c.agent.networkDB.DeleteEntry("endpoint_table", n.ID(), ep.ID()); err != nil {
|
||||
return err
|
||||
if agent != nil {
|
||||
if err := agent.networkDB.DeleteEntry("endpoint_table", n.ID(), ep.ID()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -454,8 +503,12 @@ func (ep *endpoint) deleteFromCluster() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
if agent == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, te := range ep.joinInfo.driverTableEntries {
|
||||
if err := c.agent.networkDB.DeleteEntry(te.tableName, n.ID(), te.key); err != nil {
|
||||
if err := agent.networkDB.DeleteEntry(te.tableName, n.ID(), te.key); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -469,16 +522,15 @@ func (n *network) addDriverWatches() {
|
|||
}
|
||||
|
||||
c := n.getController()
|
||||
agent := c.getAgent()
|
||||
if agent == nil {
|
||||
return
|
||||
}
|
||||
for _, tableName := range n.driverTables {
|
||||
c.Lock()
|
||||
if c.agent == nil {
|
||||
c.Unlock()
|
||||
return
|
||||
}
|
||||
ch, cancel := c.agent.networkDB.Watch(tableName, n.ID(), "")
|
||||
c.agent.driverCancelFuncs[n.ID()] = append(c.agent.driverCancelFuncs[n.ID()], cancel)
|
||||
c.Unlock()
|
||||
|
||||
ch, cancel := agent.networkDB.Watch(tableName, n.ID(), "")
|
||||
agent.Lock()
|
||||
agent.driverCancelFuncs[n.ID()] = append(agent.driverCancelFuncs[n.ID()], cancel)
|
||||
agent.Unlock()
|
||||
go c.handleTableEvents(ch, n.handleDriverTableEvent)
|
||||
d, err := n.driver(false)
|
||||
if err != nil {
|
||||
|
@ -486,7 +538,7 @@ func (n *network) addDriverWatches() {
|
|||
return
|
||||
}
|
||||
|
||||
c.agent.networkDB.WalkTable(tableName, func(nid, key string, value []byte) bool {
|
||||
agent.networkDB.WalkTable(tableName, func(nid, key string, value []byte) bool {
|
||||
if nid == n.ID() {
|
||||
d.EventNotify(driverapi.Create, nid, tableName, key, value)
|
||||
}
|
||||
|
@ -501,11 +553,15 @@ func (n *network) cancelDriverWatches() {
|
|||
return
|
||||
}
|
||||
|
||||
c := n.getController()
|
||||
c.Lock()
|
||||
cancelFuncs := c.agent.driverCancelFuncs[n.ID()]
|
||||
delete(c.agent.driverCancelFuncs, n.ID())
|
||||
c.Unlock()
|
||||
agent := n.getController().getAgent()
|
||||
if agent == nil {
|
||||
return
|
||||
}
|
||||
|
||||
agent.Lock()
|
||||
cancelFuncs := agent.driverCancelFuncs[n.ID()]
|
||||
delete(agent.driverCancelFuncs, n.ID())
|
||||
agent.Unlock()
|
||||
|
||||
for _, cancel := range cancelFuncs {
|
||||
cancel()
|
||||
|
|
|
@ -232,12 +232,13 @@ func New(cfgOptions ...config.Option) (NetworkController, error) {
|
|||
|
||||
func (c *controller) SetClusterProvider(provider cluster.Provider) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
c.cfg.Daemon.ClusterProvider = provider
|
||||
disableProviderCh := c.cfg.Daemon.DisableProvider
|
||||
c.Unlock()
|
||||
if provider != nil {
|
||||
go c.clusterAgentInit()
|
||||
} else {
|
||||
c.cfg.Daemon.DisableProvider <- struct{}{}
|
||||
disableProviderCh <- struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -290,6 +291,12 @@ func (c *controller) SetKeys(keys []*types.EncryptionKey) error {
|
|||
return c.handleKeyChange(keys)
|
||||
}
|
||||
|
||||
func (c *controller) getAgent() *agent {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
return c.agent
|
||||
}
|
||||
|
||||
func (c *controller) clusterAgentInit() {
|
||||
clusterProvider := c.cfg.Daemon.ClusterProvider
|
||||
for {
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/docker/libkv"
|
||||
"github.com/docker/libkv/store"
|
||||
|
@ -134,7 +135,8 @@ func makeDefaultScopes() map[string]*ScopeCfg {
|
|||
Provider: string(store.BOLTDB),
|
||||
Address: defaultPrefix + "/local-kv.db",
|
||||
Config: &store.Config{
|
||||
Bucket: "libnetwork",
|
||||
Bucket: "libnetwork",
|
||||
ConnectionTimeout: time.Minute,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ func (sb *sandbox) needDefaultGW() bool {
|
|||
return false
|
||||
}
|
||||
for _, r := range ep.StaticRoutes() {
|
||||
if r.Destination.String() == "0.0.0.0/0" {
|
||||
if r.Destination != nil && r.Destination.String() == "0.0.0.0/0" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
|||
}
|
||||
|
||||
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 {
|
||||
|
|
|
@ -308,6 +308,11 @@ func populateVNITbl() {
|
|||
}
|
||||
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()
|
||||
if err != nil {
|
||||
logrus.Errorf("Failed to list interfaces during vni population for ns %s: %v", path, err)
|
||||
|
|
|
@ -13,6 +13,8 @@ import (
|
|||
"github.com/vishvananda/netns"
|
||||
)
|
||||
|
||||
var soTimeout = ns.NetlinkSocketsTimeout
|
||||
|
||||
func validateID(nid, eid string) error {
|
||||
if nid == "" {
|
||||
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)
|
||||
}
|
||||
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()
|
||||
|
|
|
@ -277,7 +277,7 @@ func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
|
|||
|
||||
s := n.getSubnetforIP(IP)
|
||||
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 {
|
||||
|
|
|
@ -114,12 +114,12 @@ func (epi *endpointInterface) UnmarshalJSON(b []byte) error {
|
|||
}
|
||||
}
|
||||
if v, ok := epMap["llAddrs"]; ok {
|
||||
list := v.([]string)
|
||||
list := v.([]interface{})
|
||||
epi.llAddrs = make([]*net.IPNet, 0, len(list))
|
||||
for _, llS := range list {
|
||||
ll, err := types.ParseCIDR(llS)
|
||||
ll, err := types.ParseCIDR(llS.(string))
|
||||
if err != nil {
|
||||
return types.InternalErrorf("failed to decode endpoint interface link-local address (%s) after json unmarshal: %v", llS, err)
|
||||
return types.InternalErrorf("failed to decode endpoint interface link-local address (%v) after json unmarshal: %v", llS, err)
|
||||
}
|
||||
epi.llAddrs = append(epi.llAddrs, ll)
|
||||
}
|
||||
|
|
|
@ -406,7 +406,7 @@ func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error)
|
|||
}
|
||||
}
|
||||
|
||||
return nil, types.NotFoundErrorf("could not find an available predefined 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
|
||||
|
|
|
@ -123,7 +123,7 @@ func NewChain(name string, table Table, hairpinMode bool) (*ChainInfo, error) {
|
|||
// ProgramChain is used to add rules to a chain
|
||||
func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode, enable bool) error {
|
||||
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 {
|
||||
|
@ -159,7 +159,7 @@ func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode, enable bool) err
|
|||
}
|
||||
case Filter:
|
||||
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)
|
||||
}
|
||||
link := []string{
|
||||
|
|
|
@ -1254,9 +1254,6 @@ func (n *network) ipamAllocateVersion(ipVer int, ipam ipamapi.Ipam) error {
|
|||
}
|
||||
|
||||
if len(*cfgList) == 0 {
|
||||
if ipVer == 6 {
|
||||
return nil
|
||||
}
|
||||
*cfgList = []*IpamConf{{}}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,8 @@ func (l *logWriter) Write(p []byte) (int, error) {
|
|||
// SetKey adds a new key to the key ring
|
||||
func (nDB *NetworkDB) SetKey(key []byte) {
|
||||
logrus.Debugf("Adding key %s", hex.EncodeToString(key)[0:5])
|
||||
nDB.Lock()
|
||||
defer nDB.Unlock()
|
||||
for _, dbKey := range nDB.config.Keys {
|
||||
if bytes.Equal(key, dbKey) {
|
||||
return
|
||||
|
@ -58,6 +60,8 @@ func (nDB *NetworkDB) SetKey(key []byte) {
|
|||
// been added apriori through SetKey
|
||||
func (nDB *NetworkDB) SetPrimaryKey(key []byte) {
|
||||
logrus.Debugf("Primary Key %s", hex.EncodeToString(key)[0:5])
|
||||
nDB.RLock()
|
||||
defer nDB.RUnlock()
|
||||
for _, dbKey := range nDB.config.Keys {
|
||||
if bytes.Equal(key, dbKey) {
|
||||
if nDB.keyring != nil {
|
||||
|
@ -72,6 +76,8 @@ func (nDB *NetworkDB) SetPrimaryKey(key []byte) {
|
|||
// can't be the primary key
|
||||
func (nDB *NetworkDB) RemoveKey(key []byte) {
|
||||
logrus.Debugf("Remove Key %s", hex.EncodeToString(key)[0:5])
|
||||
nDB.Lock()
|
||||
defer nDB.Unlock()
|
||||
for i, dbKey := range nDB.config.Keys {
|
||||
if bytes.Equal(key, dbKey) {
|
||||
nDB.config.Keys = append(nDB.config.Keys[:i], nDB.config.Keys[i+1:]...)
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
|
@ -17,6 +18,8 @@ var (
|
|||
initNs netns.NsHandle
|
||||
initNl *netlink.Handle
|
||||
initOnce sync.Once
|
||||
// NetlinkSocketsTimeout represents the default timeout duration for the sockets
|
||||
NetlinkSocketsTimeout = 3 * time.Second
|
||||
)
|
||||
|
||||
// Init initializes a new network namespace
|
||||
|
@ -30,6 +33,10 @@ func Init() {
|
|||
if err != nil {
|
||||
log.Errorf("could not create netlink handle on initial namespace: %v", err)
|
||||
}
|
||||
err = initNl.SetSocketTimeout(NetlinkSocketsTimeout)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to set the timeout on the default netlink handle sockets: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// SetNamespace sets the initial namespace handler
|
||||
|
@ -69,8 +76,10 @@ func NlHandle() *netlink.Handle {
|
|||
func getSupportedNlFamilies() []int {
|
||||
fams := []int{syscall.NETLINK_ROUTE}
|
||||
if err := loadXfrmModules(); err != nil {
|
||||
log.Warnf("Could not load necessary modules for IPSEC rules: %v", err)
|
||||
return fams
|
||||
if checkXfrmSocket() != nil {
|
||||
log.Warnf("Could not load necessary modules for IPSEC rules: %v", err)
|
||||
return fams
|
||||
}
|
||||
}
|
||||
return append(fams, syscall.NETLINK_XFRM)
|
||||
}
|
||||
|
@ -84,3 +93,13 @@ func loadXfrmModules() error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// API check on required xfrm modules (xfrm_user, xfrm_algo)
|
||||
func checkXfrmSocket() error {
|
||||
fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_XFRM)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
syscall.Close(fd)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
err = n.nlHandle.SetSocketTimeout(ns.NetlinkSocketsTimeout)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to set the timeout on the sandbox netlink handle sockets: %v", err)
|
||||
}
|
||||
|
||||
if err = n.loopbackUp(); err != nil {
|
||||
n.nlHandle.Delete()
|
||||
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)
|
||||
}
|
||||
|
||||
err = n.nlHandle.SetSocketTimeout(ns.NetlinkSocketsTimeout)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to set the timeout on the sandbox netlink handle sockets: %v", err)
|
||||
}
|
||||
|
||||
if err = n.loopbackUp(); err != nil {
|
||||
n.nlHandle.Delete()
|
||||
return nil, err
|
||||
|
|
|
@ -80,6 +80,7 @@ func (n *networkNamespace) DeleteNeighbor(dstIP net.IP, dstMac net.HardwareAddr,
|
|||
for i, nh := range n.neighbors {
|
||||
if nh.dstIP.Equal(dstIP) && bytes.Equal(nh.dstMac, dstMac) {
|
||||
n.neighbors = append(n.neighbors[:i], n.neighbors[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
n.Unlock()
|
||||
|
|
|
@ -63,6 +63,7 @@ type resolver struct {
|
|||
count int32
|
||||
tStamp time.Time
|
||||
queryLock sync.Mutex
|
||||
startCh chan struct{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -72,8 +73,9 @@ func init() {
|
|||
// NewResolver creates a new instance of the Resolver
|
||||
func NewResolver(sb *sandbox) Resolver {
|
||||
return &resolver{
|
||||
sb: sb,
|
||||
err: fmt.Errorf("setup not done yet"),
|
||||
sb: sb,
|
||||
err: fmt.Errorf("setup not done yet"),
|
||||
startCh: make(chan struct{}, 1),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,6 +109,9 @@ func (r *resolver) SetupFunc() func() {
|
|||
}
|
||||
|
||||
func (r *resolver) Start() error {
|
||||
r.startCh <- struct{}{}
|
||||
defer func() { <-r.startCh }()
|
||||
|
||||
// make sure the resolver has been setup before starting
|
||||
if r.err != nil {
|
||||
return r.err
|
||||
|
@ -131,6 +136,9 @@ func (r *resolver) Start() error {
|
|||
}
|
||||
|
||||
func (r *resolver) Stop() {
|
||||
r.startCh <- struct{}{}
|
||||
defer func() { <-r.startCh }()
|
||||
|
||||
if r.server != nil {
|
||||
r.server.Shutdown()
|
||||
}
|
||||
|
@ -355,8 +363,12 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
|
|||
}
|
||||
|
||||
execErr := r.sb.execFunc(extConnect)
|
||||
if execErr != nil || err != nil {
|
||||
log.Debugf("Connect failed, %s", err)
|
||||
if execErr != nil {
|
||||
log.Warn(execErr)
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
log.Warnf("Connect failed: %s", err)
|
||||
continue
|
||||
}
|
||||
log.Debugf("Query %s[%d] from %s, forwarding to %s:%s", name, query.Question[0].Qtype,
|
||||
|
|
|
@ -437,7 +437,13 @@ func (sb *sandbox) ResolveIP(ip string) string {
|
|||
}
|
||||
|
||||
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, error) {
|
||||
|
|
|
@ -250,8 +250,8 @@ func (c *controller) rmServiceBinding(name, sid, nid, eid string, vip net.IP, in
|
|||
func (n *network) connectedLoadbalancers() []*loadBalancer {
|
||||
c := n.getController()
|
||||
|
||||
serviceBindings := make([]*service, 0, len(c.serviceBindings))
|
||||
c.Lock()
|
||||
serviceBindings := make([]*service, 0, len(c.serviceBindings))
|
||||
for _, s := range c.serviceBindings {
|
||||
serviceBindings = append(serviceBindings, s)
|
||||
}
|
||||
|
|
|
@ -8,11 +8,11 @@ package netlink
|
|||
#include <stdint.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
|
||||
// { return 1; }
|
||||
// { return ret; }
|
||||
__u64 __attribute__((aligned(8))) insns[] = {
|
||||
0x00000001000000b7ull,
|
||||
0x00000000000000b7ull | ((__u64)ret<<32),
|
||||
0x0000000000000095ull,
|
||||
};
|
||||
__u8 __attribute__((aligned(8))) license[] = "ASL2";
|
||||
|
@ -51,10 +51,12 @@ const (
|
|||
BPF_PROG_TYPE_KPROBE
|
||||
BPF_PROG_TYPE_SCHED_CLS
|
||||
BPF_PROG_TYPE_SCHED_ACT
|
||||
BPF_PROG_TYPE_TRACEPOINT
|
||||
BPF_PROG_TYPE_XDP
|
||||
)
|
||||
|
||||
// loadSimpleBpf loads a trivial bpf program for testing purposes
|
||||
func loadSimpleBpf(progType BpfProgType) (int, error) {
|
||||
fd, err := C.load_simple_bpf(C.int(progType))
|
||||
func loadSimpleBpf(progType BpfProgType, ret int) (int, error) {
|
||||
fd, err := C.load_simple_bpf(C.int(progType), C.int(ret))
|
||||
return int(fd), err
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ func (a TcAct) String() string {
|
|||
case TC_ACT_JUMP:
|
||||
return "jump"
|
||||
}
|
||||
return fmt.Sprintf("0x%x", a)
|
||||
return fmt.Sprintf("0x%x", int32(a))
|
||||
}
|
||||
|
||||
type TcPolAct int32
|
||||
|
@ -86,7 +86,7 @@ func (a TcPolAct) String() string {
|
|||
case TC_POLICE_PIPE:
|
||||
return "pipe"
|
||||
}
|
||||
return fmt.Sprintf("0x%x", a)
|
||||
return fmt.Sprintf("0x%x", int32(a))
|
||||
}
|
||||
|
||||
type ActionAttrs struct {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package netlink
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
"github.com/vishvananda/netns"
|
||||
|
@ -33,6 +35,29 @@ func NewHandle(nlFamilies ...int) (*Handle, error) {
|
|||
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
|
||||
// specified by ns. If ns=netns.None(), current network namespace
|
||||
// will be assumed
|
||||
|
|
|
@ -26,11 +26,15 @@ type LinkAttrs struct {
|
|||
Name string
|
||||
HardwareAddr net.HardwareAddr
|
||||
Flags net.Flags
|
||||
RawFlags uint32
|
||||
ParentIndex int // index of the parent link device
|
||||
MasterIndex int // must be the index of a bridge
|
||||
Namespace interface{} // nil | NsPid | NsFd
|
||||
Alias string
|
||||
Statistics *LinkStatistics
|
||||
Promisc int
|
||||
Xdp *LinkXdp
|
||||
EncapType string
|
||||
}
|
||||
|
||||
// NewLinkAttrs returns LinkAttrs structure filled with default values
|
||||
|
@ -69,6 +73,11 @@ type LinkStatistics struct {
|
|||
TxCompressed uint32
|
||||
}
|
||||
|
||||
type LinkXdp struct {
|
||||
Fd int
|
||||
Attached bool
|
||||
}
|
||||
|
||||
// Device links cannot be created via netlink. These links
|
||||
// are links created by udev like 'lo' and 'etho0'
|
||||
type Device struct {
|
||||
|
@ -171,11 +180,13 @@ func (macvtap Macvtap) Type() string {
|
|||
}
|
||||
|
||||
type TuntapMode uint16
|
||||
type TuntapFlag uint16
|
||||
|
||||
// Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
|
||||
type Tuntap struct {
|
||||
LinkAttrs
|
||||
Mode TuntapMode
|
||||
Mode TuntapMode
|
||||
Flags TuntapFlag
|
||||
}
|
||||
|
||||
func (tuntap *Tuntap) Attrs() *LinkAttrs {
|
||||
|
@ -251,6 +262,7 @@ type IPVlanMode uint16
|
|||
const (
|
||||
IPVLAN_MODE_L2 IPVlanMode = iota
|
||||
IPVLAN_MODE_L3
|
||||
IPVLAN_MODE_L3S
|
||||
IPVLAN_MODE_MAX
|
||||
)
|
||||
|
||||
|
|
|
@ -16,8 +16,13 @@ import (
|
|||
const SizeofLinkStats = 0x5c
|
||||
|
||||
const (
|
||||
TUNTAP_MODE_TUN TuntapMode = syscall.IFF_TUN
|
||||
TUNTAP_MODE_TAP TuntapMode = syscall.IFF_TAP
|
||||
TUNTAP_MODE_TUN TuntapMode = syscall.IFF_TUN
|
||||
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()
|
||||
|
@ -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.
|
||||
// Equivalent to: `ip link set $link up`
|
||||
func LinkSetUp(link Link) error {
|
||||
|
@ -255,6 +298,36 @@ func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error {
|
|||
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.
|
||||
// Equivalent to: `ip link set $link master $master`
|
||||
func LinkSetMaster(link Link, master *Bridge) error {
|
||||
|
@ -373,6 +446,23 @@ func (h *Handle) LinkSetNsFd(link Link, fd int) error {
|
|||
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 {
|
||||
var v uint8
|
||||
if val {
|
||||
|
@ -552,9 +642,7 @@ func (h *Handle) LinkAdd(link Link) error {
|
|||
if tuntap, ok := link.(*Tuntap); ok {
|
||||
// TODO: support user
|
||||
// TODO: support group
|
||||
// TODO: support non- one_queue
|
||||
// TODO: support pi | vnet_hdr | multi_queue
|
||||
// TODO: support non- exclusive
|
||||
// TODO: multi_queue
|
||||
// TODO: support non- persistent
|
||||
if tuntap.Mode < syscall.IFF_TUN || tuntap.Mode > syscall.IFF_TAP {
|
||||
return fmt.Errorf("Tuntap.Mode %v unknown!", tuntap.Mode)
|
||||
|
@ -565,10 +653,13 @@ func (h *Handle) LinkAdd(link Link) error {
|
|||
}
|
||||
defer file.Close()
|
||||
var req ifReq
|
||||
req.Flags |= syscall.IFF_ONE_QUEUE
|
||||
req.Flags |= syscall.IFF_TUN_EXCL
|
||||
copy(req.Name[:15], base.Name)
|
||||
if tuntap.Flags == 0 {
|
||||
req.Flags = uint16(TUNTAP_DEFAULTS)
|
||||
} else {
|
||||
req.Flags = uint16(tuntap.Flags)
|
||||
}
|
||||
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)))
|
||||
if errno != 0 {
|
||||
return fmt.Errorf("Tuntap IOCTL TUNSETIFF failed, errno %v", errno)
|
||||
|
@ -649,6 +740,10 @@ func (h *Handle) LinkAdd(link Link) error {
|
|||
req.AddData(attr)
|
||||
}
|
||||
|
||||
if base.Xdp != nil {
|
||||
addXdpAttrs(base.Xdp, req)
|
||||
}
|
||||
|
||||
linkInfo := nl.NewRtAttr(syscall.IFLA_LINKINFO, nil)
|
||||
nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type()))
|
||||
|
||||
|
@ -871,7 +966,10 @@ func linkDeserialize(m []byte) (Link, error) {
|
|||
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
|
||||
linkType := ""
|
||||
for _, attr := range attrs {
|
||||
|
@ -958,6 +1056,12 @@ func linkDeserialize(m []byte) (Link, error) {
|
|||
base.Alias = string(attr.Value[:len(attr.Value)-1])
|
||||
case syscall.IFLA_STATS:
|
||||
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
|
||||
|
@ -1389,3 +1493,28 @@ func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) {
|
|||
func parseLinkStats(data []byte) *LinkStatistics {
|
||||
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
|
||||
}
|
||||
|
|
|
@ -151,8 +151,10 @@ func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
|
|||
dstData := nl.NewRtAttr(NDA_DST, ipData)
|
||||
req.AddData(dstData)
|
||||
|
||||
hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
|
||||
req.AddData(hwData)
|
||||
if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil {
|
||||
hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
|
||||
req.AddData(hwData)
|
||||
}
|
||||
|
||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
|
@ -165,14 +167,33 @@ func NeighList(linkIndex, family int) ([]Neigh, error) {
|
|||
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).
|
||||
// Equivalent to: `ip neighbor show`.
|
||||
// The list can be filtered by link and ip family.
|
||||
func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) {
|
||||
return h.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)
|
||||
msg := Ndmsg{
|
||||
Family: uint8(family),
|
||||
Index: uint32(linkIndex),
|
||||
Flags: uint8(flags),
|
||||
}
|
||||
req.AddData(&msg)
|
||||
|
||||
|
|
|
@ -1,13 +1,35 @@
|
|||
package nl
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
DEFAULT_CHANGE = 0xFFFFFFFF
|
||||
// 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 (
|
||||
|
@ -89,11 +111,6 @@ const (
|
|||
IFLA_IPVLAN_MAX = IFLA_IPVLAN_MODE
|
||||
)
|
||||
|
||||
const (
|
||||
// not defined in syscall
|
||||
IFLA_NET_NS_FD = 28
|
||||
)
|
||||
|
||||
const (
|
||||
IFLA_MACVLAN_UNSPEC = iota
|
||||
IFLA_MACVLAN_MODE
|
||||
|
@ -394,3 +411,10 @@ func DeserializeVfRssQueryEn(b []byte) *VfRssQueryEn {
|
|||
func (msg *VfRssQueryEn) Serialize() []byte {
|
||||
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
|
||||
)
|
||||
|
|
|
@ -100,6 +100,147 @@ func (msg *IfInfomsg) Len() int {
|
|||
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 {
|
||||
return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1)
|
||||
}
|
||||
|
|
|
@ -153,7 +153,7 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
|
|||
} else {
|
||||
gw = nl.NewRtAttr(syscall.RTA_GATEWAY, []byte(nh.Gw.To16()))
|
||||
}
|
||||
gwData := gw.Serialize()
|
||||
gwData = gw.Serialize()
|
||||
rtnh.Len += uint16(len(gwData))
|
||||
}
|
||||
buf = append(buf, rtnh.Serialize()...)
|
||||
|
|
|
@ -82,41 +82,46 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
|
|||
req.AddData(rtAttrs[i])
|
||||
}
|
||||
|
||||
var (
|
||||
b = make([]byte, 4)
|
||||
native = nl.NativeEndian()
|
||||
)
|
||||
native := nl.NativeEndian()
|
||||
|
||||
if rule.Priority >= 0 {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(rule.Priority))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_PRIORITY, b))
|
||||
}
|
||||
if rule.Mark >= 0 {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(rule.Mark))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_FWMARK, b))
|
||||
}
|
||||
if rule.Mask >= 0 {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(rule.Mask))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_FWMASK, b))
|
||||
}
|
||||
if rule.Flow >= 0 {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(rule.Flow))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_FLOW, b))
|
||||
}
|
||||
if rule.TunID > 0 {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(rule.TunID))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_TUN_ID, b))
|
||||
}
|
||||
if rule.Table >= 256 {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(rule.Table))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_TABLE, b))
|
||||
}
|
||||
if msg.Table > 0 {
|
||||
if rule.SuppressPrefixlen >= 0 {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(rule.SuppressPrefixlen))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_PREFIXLEN, b))
|
||||
}
|
||||
if rule.SuppressIfgroup >= 0 {
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(rule.SuppressIfgroup))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_IFGROUP, b))
|
||||
}
|
||||
|
@ -129,6 +134,7 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
|
|||
}
|
||||
if rule.Goto >= 0 {
|
||||
msg.Type = nl.FR_ACT_NOP
|
||||
b := make([]byte, 4)
|
||||
native.PutUint32(b, uint32(rule.Goto))
|
||||
req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b))
|
||||
}
|
||||
|
|
|
@ -213,7 +213,7 @@ func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState
|
|||
req.AddData(out)
|
||||
}
|
||||
if state.Src != nil {
|
||||
out := nl.NewRtAttr(nl.XFRMA_SRCADDR, state.Src)
|
||||
out := nl.NewRtAttr(nl.XFRMA_SRCADDR, state.Src.To16())
|
||||
req.AddData(out)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue