diff --git a/netlink/netlink_linux.go b/netlink/netlink_linux.go index 3083cf90..c858b112 100644 --- a/netlink/netlink_linux.go +++ b/netlink/netlink_linux.go @@ -681,7 +681,7 @@ func NetworkChangeName(iface *net.Interface, newName string) error { // Add a new VETH pair link on the host // This is identical to running: ip link add name $name type veth peer name $peername -func NetworkCreateVethPair(name1, name2 string) error { +func NetworkCreateVethPair(name1, name2 string, txQueueLen int) error { s, err := getNetlinkSocket() if err != nil { return err @@ -696,6 +696,11 @@ func NetworkCreateVethPair(name1, name2 string) error { nameData := newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(name1)) wb.AddData(nameData) + txqLen := make([]byte, 4) + native.PutUint32(txqLen, uint32(txQueueLen)) + txqData := newRtAttr(syscall.IFLA_TXQLEN, txqLen) + wb.AddData(txqData) + nest1 := newRtAttr(syscall.IFLA_LINKINFO, nil) newRtAttrChild(nest1, IFLA_INFO_KIND, zeroTerminated("veth")) nest2 := newRtAttrChild(nest1, IFLA_INFO_DATA, nil) @@ -704,6 +709,10 @@ func NetworkCreateVethPair(name1, name2 string) error { newIfInfomsgChild(nest3, syscall.AF_UNSPEC) newRtAttrChild(nest3, syscall.IFLA_IFNAME, zeroTerminated(name2)) + txqLen2 := make([]byte, 4) + native.PutUint32(txqLen2, uint32(txQueueLen)) + newRtAttrChild(nest3, syscall.IFLA_TXQLEN, txqLen2) + wb.AddData(nest1) if err := s.Send(wb); err != nil { diff --git a/netlink/netlink_linux_test.go b/netlink/netlink_linux_test.go index 88c2e04a..0320c472 100644 --- a/netlink/netlink_linux_test.go +++ b/netlink/netlink_linux_test.go @@ -290,7 +290,7 @@ func TestCreateVethPair(t *testing.T) { name2 = "veth2" ) - if err := NetworkCreateVethPair(name1, name2); err != nil { + if err := NetworkCreateVethPair(name1, name2, 0); err != nil { t.Fatalf("Could not create veth pair %s %s: %s", name1, name2, err) } defer NetworkLinkDel(name1) diff --git a/netlink/netlink_unsupported.go b/netlink/netlink_unsupported.go index f6e84adf..747cd1d8 100644 --- a/netlink/netlink_unsupported.go +++ b/netlink/netlink_unsupported.go @@ -47,7 +47,7 @@ func NetworkSetMTU(iface *net.Interface, mtu int) error { return ErrNotImplemented } -func NetworkCreateVethPair(name1, name2 string) error { +func NetworkCreateVethPair(name1, name2 string, txQueueLen int) error { return ErrNotImplemented } diff --git a/network/network.go b/network/network.go index 014ba743..2c3499b6 100644 --- a/network/network.go +++ b/network/network.go @@ -32,8 +32,8 @@ func ChangeInterfaceName(old, newName string) error { return netlink.NetworkChangeName(iface, newName) } -func CreateVethPair(name1, name2 string) error { - return netlink.NetworkCreateVethPair(name1, name2) +func CreateVethPair(name1, name2 string, txQueueLen int) error { + return netlink.NetworkCreateVethPair(name1, name2, txQueueLen) } func SetInterfaceInNamespacePid(name string, nsPid int) error { diff --git a/network/types.go b/network/types.go index 383e27c8..ea0741be 100644 --- a/network/types.go +++ b/network/types.go @@ -36,6 +36,11 @@ type Network struct { // container's interfaces if a pair is created, specifically in the case of type veth // Note: This does not apply to loopback interfaces. Mtu int `json:"mtu,omitempty"` + + // TxQueueLen sets the tx_queuelen value for the interface and will be mirrored on both the host and + // container's interfaces if a pair is created, specifically in the case of type veth + // Note: This does not apply to loopback interfaces. + TxQueueLen int `json:"txqueuelen,omitempty"` } // Struct describing the network specific runtime state that will be maintained by libcontainer for all running containers diff --git a/network/veth.go b/network/veth.go index e5185de7..3d7dc872 100644 --- a/network/veth.go +++ b/network/veth.go @@ -19,8 +19,9 @@ const defaultDevice = "eth0" func (v *Veth) Create(n *Network, nspid int, networkState *NetworkState) error { var ( - bridge = n.Bridge - prefix = n.VethPrefix + bridge = n.Bridge + prefix = n.VethPrefix + txQueueLen = n.TxQueueLen ) if bridge == "" { return fmt.Errorf("bridge is not specified") @@ -28,7 +29,7 @@ func (v *Veth) Create(n *Network, nspid int, networkState *NetworkState) error { if prefix == "" { return fmt.Errorf("veth prefix is not specified") } - name1, name2, err := createVethPair(prefix) + name1, name2, err := createVethPair(prefix, txQueueLen) if err != nil { return err } @@ -96,7 +97,7 @@ func (v *Veth) Initialize(config *Network, networkState *NetworkState) error { // createVethPair will automatically generage two random names for // the veth pair and ensure that they have been created -func createVethPair(prefix string) (name1 string, name2 string, err error) { +func createVethPair(prefix string, txQueueLen int) (name1 string, name2 string, err error) { for i := 0; i < 10; i++ { if name1, err = utils.GenerateRandomName(prefix, 7); err != nil { return @@ -106,7 +107,7 @@ func createVethPair(prefix string) (name1 string, name2 string, err error) { return } - if err = CreateVethPair(name1, name2); err != nil { + if err = CreateVethPair(name1, name2, txQueueLen); err != nil { if err == netlink.ErrInterfaceExists { continue } diff --git a/network/veth_test.go b/network/veth_test.go index e09a6042..b92b284e 100644 --- a/network/veth_test.go +++ b/network/veth_test.go @@ -15,7 +15,7 @@ func TestGenerateVethNames(t *testing.T) { prefix := "veth" - name1, name2, err := createVethPair(prefix) + name1, name2, err := createVethPair(prefix, 0) if err != nil { t.Fatal(err) } @@ -36,13 +36,13 @@ func TestCreateDuplicateVethPair(t *testing.T) { prefix := "veth" - name1, name2, err := createVethPair(prefix) + name1, name2, err := createVethPair(prefix, 0) if err != nil { t.Fatal(err) } // retry to create the name interfaces and make sure that we get the correct error - err = CreateVethPair(name1, name2) + err = CreateVethPair(name1, name2, 0) if err == nil { t.Fatal("expected error to not be nil with duplicate interface") }