Add LinkAttrs constructor NewLinkAttrs

It looks little awkward, but should be enough for people who care about
defaults from kernel.

Fix #26

Also fixed bug with setting TxQLen for main device. It was never set
before.

Signed-off-by: Alexander Morozov <lk4d4@docker.com>
This commit is contained in:
Alexander Morozov 2015-06-12 11:09:57 -07:00
parent 991a7a2fa7
commit 72a1f403a3
3 changed files with 118 additions and 9 deletions

View File

@ -19,7 +19,7 @@ type (
type LinkAttrs struct { type LinkAttrs struct {
Index int Index int
MTU int MTU int
TxQLen uint32 // Transmit Queue Length TxQLen int // Transmit Queue Length
Name string Name string
HardwareAddr net.HardwareAddr HardwareAddr net.HardwareAddr
Flags net.Flags Flags net.Flags
@ -28,6 +28,13 @@ type LinkAttrs struct {
Namespace interface{} // nil | NsPid | NsFd Namespace interface{} // nil | NsPid | NsFd
} }
// NewLinkAttrs returns LinkAttrs structure filled with default values
func NewLinkAttrs() LinkAttrs {
return LinkAttrs{
TxQLen: -1,
}
}
// 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 {

View File

@ -321,6 +321,11 @@ func LinkAdd(link Link) error {
req.AddData(mtu) req.AddData(mtu)
} }
if base.TxQLen >= 0 {
qlen := nl.NewRtAttr(syscall.IFLA_TXQLEN, nl.Uint32Attr(uint32(base.TxQLen)))
req.AddData(qlen)
}
if base.Namespace != nil { if base.Namespace != nil {
var attr *nl.RtAttr var attr *nl.RtAttr
switch base.Namespace.(type) { switch base.Namespace.(type) {
@ -338,8 +343,6 @@ func LinkAdd(link Link) error {
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()))
nl.NewRtAttrChild(linkInfo, syscall.IFLA_TXQLEN, nl.Uint32Attr(base.TxQLen))
if vlan, ok := link.(*Vlan); ok { if vlan, ok := link.(*Vlan); ok {
b := make([]byte, 2) b := make([]byte, 2)
native.PutUint16(b, uint16(vlan.VlanId)) native.PutUint16(b, uint16(vlan.VlanId))
@ -350,10 +353,13 @@ func LinkAdd(link Link) error {
peer := nl.NewRtAttrChild(data, nl.VETH_INFO_PEER, nil) peer := nl.NewRtAttrChild(data, nl.VETH_INFO_PEER, nil)
nl.NewIfInfomsgChild(peer, syscall.AF_UNSPEC) nl.NewIfInfomsgChild(peer, syscall.AF_UNSPEC)
nl.NewRtAttrChild(peer, syscall.IFLA_IFNAME, nl.ZeroTerminated(veth.PeerName)) nl.NewRtAttrChild(peer, syscall.IFLA_IFNAME, nl.ZeroTerminated(veth.PeerName))
nl.NewRtAttrChild(peer, syscall.IFLA_TXQLEN, nl.Uint32Attr(base.TxQLen)) if base.TxQLen >= 0 {
nl.NewRtAttrChild(peer, syscall.IFLA_TXQLEN, nl.Uint32Attr(uint32(base.TxQLen)))
}
if base.MTU > 0 { if base.MTU > 0 {
nl.NewRtAttrChild(peer, syscall.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU))) nl.NewRtAttrChild(peer, syscall.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU)))
} }
} else if vxlan, ok := link.(*Vxlan); ok { } else if vxlan, ok := link.(*Vxlan); ok {
addVxlanAttrs(vxlan, linkInfo) addVxlanAttrs(vxlan, linkInfo)
} else if ipv, ok := link.(*IPVlan); ok { } else if ipv, ok := link.(*IPVlan); ok {
@ -552,7 +558,7 @@ func linkDeserialize(m []byte) (Link, error) {
case syscall.IFLA_MASTER: case syscall.IFLA_MASTER:
base.MasterIndex = int(native.Uint32(attr.Value[0:4])) base.MasterIndex = int(native.Uint32(attr.Value[0:4]))
case syscall.IFLA_TXQLEN: case syscall.IFLA_TXQLEN:
base.TxQLen = native.Uint32(attr.Value[0:4]) base.TxQLen = int(native.Uint32(attr.Value[0:4]))
} }
} }
// Links that don't have IFLA_INFO_KIND are hardware devices // Links that don't have IFLA_INFO_KIND are hardware devices

View File

@ -8,7 +8,10 @@ import (
"github.com/vishvananda/netns" "github.com/vishvananda/netns"
) )
const testTxQLen uint32 = 100 const (
testTxQLen int = 100
defaultTxQLen int = 1000
)
func testLinkAddDel(t *testing.T, link Link) { func testLinkAddDel(t *testing.T, link Link) {
links, err := LinkList() links, err := LinkList()
@ -50,9 +53,9 @@ func testLinkAddDel(t *testing.T, link Link) {
} }
} }
if veth, ok := link.(*Veth); ok { if veth, ok := result.(*Veth); ok {
if veth.TxQLen != testTxQLen { if rBase.TxQLen != base.TxQLen {
t.Fatalf("TxQLen is %d, should be %d", veth.TxQLen, testTxQLen) t.Fatalf("qlen is %d, should be %d", rBase.TxQLen, base.TxQLen)
} }
if rBase.MTU != base.MTU { if rBase.MTU != base.MTU {
t.Fatalf("MTU is %d, should be %d", rBase.MTU, base.MTU) t.Fatalf("MTU is %d, should be %d", rBase.MTU, base.MTU)
@ -226,6 +229,99 @@ func TestLinkAddDelVeth(t *testing.T) {
testLinkAddDel(t, &Veth{LinkAttrs{Name: "foo", TxQLen: testTxQLen, MTU: 1400}, "bar"}) testLinkAddDel(t, &Veth{LinkAttrs{Name: "foo", TxQLen: testTxQLen, MTU: 1400}, "bar"})
} }
func TestLinkAddVethWithDefaultTxQLen(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()
la := NewLinkAttrs()
la.Name = "foo"
veth := &Veth{LinkAttrs: la, PeerName: "bar"}
if err := LinkAdd(veth); err != nil {
t.Fatal(err)
}
link, err := LinkByName("foo")
if err != nil {
t.Fatal(err)
}
if veth, ok := link.(*Veth); !ok {
t.Fatalf("unexpected link type: %T", link)
} else {
if veth.TxQLen != defaultTxQLen {
t.Fatalf("TxQLen is %d, should be %d", veth.TxQLen, defaultTxQLen)
}
}
peer, err := LinkByName("bar")
if err != nil {
t.Fatal(err)
}
if veth, ok := peer.(*Veth); !ok {
t.Fatalf("unexpected link type: %T", link)
} else {
if veth.TxQLen != defaultTxQLen {
t.Fatalf("TxQLen is %d, should be %d", veth.TxQLen, defaultTxQLen)
}
}
}
func TestLinkAddVethWithZeroTxQLen(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()
la := NewLinkAttrs()
la.Name = "foo"
la.TxQLen = 0
veth := &Veth{LinkAttrs: la, PeerName: "bar"}
if err := LinkAdd(veth); err != nil {
t.Fatal(err)
}
link, err := LinkByName("foo")
if err != nil {
t.Fatal(err)
}
if veth, ok := link.(*Veth); !ok {
t.Fatalf("unexpected link type: %T", link)
} else {
if veth.TxQLen != 0 {
t.Fatalf("TxQLen is %d, should be %d", veth.TxQLen, 0)
}
}
peer, err := LinkByName("bar")
if err != nil {
t.Fatal(err)
}
if veth, ok := peer.(*Veth); !ok {
t.Fatalf("unexpected link type: %T", link)
} else {
if veth.TxQLen != 0 {
t.Fatalf("TxQLen is %d, should be %d", veth.TxQLen, 0)
}
}
}
func TestLinkAddDummyWithTxQLen(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()
la := NewLinkAttrs()
la.Name = "foo"
la.TxQLen = 1500
dummy := &Dummy{LinkAttrs: la}
if err := LinkAdd(dummy); err != nil {
t.Fatal(err)
}
link, err := LinkByName("foo")
if err != nil {
t.Fatal(err)
}
if dummy, ok := link.(*Dummy); !ok {
t.Fatalf("unexpected link type: %T", link)
} else {
if dummy.TxQLen != 1500 {
t.Fatalf("TxQLen is %d, should be %d", dummy.TxQLen, 1500)
}
}
}
func TestLinkAddDelBridgeMaster(t *testing.T) { func TestLinkAddDelBridgeMaster(t *testing.T) {
tearDown := setUpNetlinkTest(t) tearDown := setUpNetlinkTest(t)
defer tearDown() defer tearDown()