diff --git a/pkg/kubelet/network/kubenet/kubenet_linux.go b/pkg/kubelet/network/kubenet/kubenet_linux.go index 34165d83218..8a59479aee5 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 } @@ -243,6 +275,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() }