From aad6535a00d2caaf239083433bb126f8613b09d9 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 4 May 2016 09:48:12 -0500 Subject: [PATCH] kubenet: fix up CNI bridge TX queue length if needed CNI's bridge plugin mis-handles the TxQLen when creating the bridge, leading to a zero-length TX queue. This doesn't typically cause problems (since virtual interfaces don't have hard queue limits) but when adding traffic shaping, some qdiscs pull their packet limits from the TX queue length, leading to a packet limit of 0 in some cases. Until we can depend on a new enough version of CNI, fix up the TX queue length internally. --- pkg/kubelet/network/kubenet/kubenet_linux.go | 33 ++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/pkg/kubelet/network/kubenet/kubenet_linux.go b/pkg/kubelet/network/kubenet/kubenet_linux.go index 63b12a24e65..763ad6525bb 100644 --- a/pkg/kubelet/network/kubenet/kubenet_linux.go +++ b/pkg/kubelet/network/kubenet/kubenet_linux.go @@ -26,6 +26,7 @@ import ( "syscall" "github.com/vishvananda/netlink" + "github.com/vishvananda/netlink/nl" "github.com/appc/cni/libcni" "github.com/golang/glog" @@ -197,6 +198,37 @@ func (plugin *kubenetNetworkPlugin) clearBridgeAddressesExcept(keep string) { } } +// ensureBridgeTxQueueLen() ensures that the bridge interface's TX queue +// length is greater than zero. Due to a CNI <= 0.3.0 'bridge' plugin bug, +// the bridge is initially created with a TX queue length of 0, which gets +// used as the packet limit for FIFO traffic shapers, which drops packets. +// TODO: remove when we can depend on a fixed CNI +func (plugin *kubenetNetworkPlugin) ensureBridgeTxQueueLen() { + bridge, err := netlink.LinkByName(BridgeName) + if err != nil { + return + } + + if bridge.Attrs().TxQLen > 0 { + return + } + + req := nl.NewNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_ACK) + msg := nl.NewIfInfomsg(syscall.AF_UNSPEC) + req.AddData(msg) + + nameData := nl.NewRtAttr(syscall.IFLA_IFNAME, nl.ZeroTerminated(BridgeName)) + req.AddData(nameData) + + qlen := nl.NewRtAttr(syscall.IFLA_TXQLEN, nl.Uint32Attr(1000)) + req.AddData(qlen) + + _, err = req.Execute(syscall.NETLINK_ROUTE, 0) + if err != nil { + glog.V(5).Infof("Failed to set bridge tx queue length: %v", err) + } +} + func (plugin *kubenetNetworkPlugin) Name() string { return KubenetPluginName } @@ -244,6 +276,7 @@ func (plugin *kubenetNetworkPlugin) SetUpPod(namespace string, name string, id k if plugin.shaper == nil { return fmt.Errorf("Failed to create bandwidth shaper!") } + plugin.ensureBridgeTxQueueLen() plugin.shaper.ReconcileInterface() }