Commit aad6535a authored by Dan Williams's avatar Dan Williams

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.
parent 1642083e
...@@ -26,6 +26,7 @@ import ( ...@@ -26,6 +26,7 @@ import (
"syscall" "syscall"
"github.com/vishvananda/netlink" "github.com/vishvananda/netlink"
"github.com/vishvananda/netlink/nl"
"github.com/appc/cni/libcni" "github.com/appc/cni/libcni"
"github.com/golang/glog" "github.com/golang/glog"
...@@ -197,6 +198,37 @@ func (plugin *kubenetNetworkPlugin) clearBridgeAddressesExcept(keep string) { ...@@ -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 { func (plugin *kubenetNetworkPlugin) Name() string {
return KubenetPluginName return KubenetPluginName
} }
...@@ -244,6 +276,7 @@ func (plugin *kubenetNetworkPlugin) SetUpPod(namespace string, name string, id k ...@@ -244,6 +276,7 @@ func (plugin *kubenetNetworkPlugin) SetUpPod(namespace string, name string, id k
if plugin.shaper == nil { if plugin.shaper == nil {
return fmt.Errorf("Failed to create bandwidth shaper!") return fmt.Errorf("Failed to create bandwidth shaper!")
} }
plugin.ensureBridgeTxQueueLen()
plugin.shaper.ReconcileInterface() plugin.shaper.ReconcileInterface()
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment