From 7cf02869ecbc184598112494dd18dd52535559e4 Mon Sep 17 00:00:00 2001 From: m1093782566 Date: Tue, 3 Apr 2018 14:46:09 +0800 Subject: [PATCH 1/2] traffic shaping: take configuration via a runtimeConfig --- .../meta/bandwidth/bandwidth_linux_test.go | 63 ++++++++++++------- plugins/meta/bandwidth/main.go | 54 +++++++++------- 2 files changed, 75 insertions(+), 42 deletions(-) diff --git a/plugins/meta/bandwidth/bandwidth_linux_test.go b/plugins/meta/bandwidth/bandwidth_linux_test.go index befc6f67..395ef849 100644 --- a/plugins/meta/bandwidth/bandwidth_linux_test.go +++ b/plugins/meta/bandwidth/bandwidth_linux_test.go @@ -77,10 +77,14 @@ var _ = Describe("bandwidth test", func() { "cniVersion": "0.3.0", "name": "cni-plugin-bandwidth-test", "type": "bandwidth", - "ingressRate": 8, - "ingressBurst": 8, - "egressRate": 16, - "egressBurst": 9, + "runtimeConfig": { + "bandWidth": { + "ingressRate": 8, + "ingressBurst": 8, + "egressRate": 16, + "egressBurst": 9 + } + }, "prevResult": { "interfaces": [ { @@ -174,10 +178,14 @@ var _ = Describe("bandwidth test", func() { "cniVersion": "0.3.0", "name": "cni-plugin-bandwidth-test", "type": "bandwidth", - "ingressRate": 0, - "ingressBurst": 0, - "egressRate": 8, - "egressBurst": 1, + "runtimeConfig": { + "bandWidth": { + "ingressRate": 0, + "ingressBurst": 0, + "egressRate": 8, + "egressBurst": 1 + } + }, "prevResult": { "interfaces": [ { @@ -243,10 +251,14 @@ var _ = Describe("bandwidth test", func() { "cniVersion": "0.3.0", "name": "cni-plugin-bandwidth-test", "type": "bandwidth", - "egressRate": 0, - "egressBurst": 0, - "ingressRate": 8, - "ingressBurst": 1, + "runtimeConfig": { + "bandWidth": { + "egressRate": 0, + "egressBurst": 0, + "ingressRate": 8, + "ingressBurst": 1 + } + }, "prevResult": { "interfaces": [ { @@ -314,10 +326,14 @@ var _ = Describe("bandwidth test", func() { "cniVersion": "0.3.0", "name": "cni-plugin-bandwidth-test", "type": "bandwidth", - "ingressRate": 0, - "ingressBurst": 123, - "egressRate": 123, - "egressBurst": 123, + "runtimeConfig": { + "bandWidth": { + "ingressRate": 0, + "ingressBurst": 123, + "egressRate": 123, + "egressBurst": 123 + } + }, "prevResult": { "interfaces": [ { @@ -366,10 +382,14 @@ var _ = Describe("bandwidth test", func() { "cniVersion": "0.3.0", "name": "cni-plugin-bandwidth-test", "type": "bandwidth", - "ingressRate": 8, - "ingressBurst": 8, - "egressRate": 9, - "egressBurst": 9, + "runtimeConfig": { + "bandWidth": { + "ingressRate": 8, + "ingressBurst": 8, + "egressRate": 9, + "egressBurst": 9 + } + }, "prevResult": { "interfaces": [ { @@ -484,7 +504,8 @@ var _ = Describe("bandwidth test", func() { containerWithTbfResult, err := current.GetResult(containerWithTbfRes) Expect(err).NotTo(HaveOccurred()) - tbfPluginConf := PluginConf{ + tbfPluginConf := PluginConf{} + tbfPluginConf.RuntimeConfig.BandWidth = &BandWidthEntry{ IngressBurst: burstInBits, IngressRate: rateInBits, EgressBurst: burstInBits, diff --git a/plugins/meta/bandwidth/main.go b/plugins/meta/bandwidth/main.go index 7aa7c39d..fa9f6ed0 100644 --- a/plugins/meta/bandwidth/main.go +++ b/plugins/meta/bandwidth/main.go @@ -17,25 +17,21 @@ package main import ( "crypto/sha1" "encoding/json" + "errors" "fmt" "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" "github.com/containernetworking/cni/pkg/types/current" "github.com/containernetworking/cni/pkg/version" - - "errors" "github.com/containernetworking/plugins/pkg/ip" + "github.com/vishvananda/netlink" ) -type PluginConf struct { - types.NetConf - RuntimeConfig *struct{} `json:"runtimeConfig"` - - RawPrevResult *map[string]interface{} `json:"prevResult"` - PrevResult *current.Result `json:"-"` - +// BandWidthEntry corresponds to a single entry in the bandwidth argument, +// see CONVENTIONS.md +type BandWidthEntry struct { IngressRate int `json:"ingressRate"` //Bandwidth rate in Kbps for traffic through container. 0 for no limit. If ingressRate is set, ingressBurst must also be set IngressBurst int `json:"ingressBurst"` //Bandwidth burst in Kb for traffic through container. 0 for no limit. If ingressBurst is set, ingressRate must also be set @@ -43,6 +39,19 @@ type PluginConf struct { EgressBurst int `json:"egressBurst"` //Bandwidth burst in Kb for traffic through container. 0 for no limit. If egressBurst is set, egressRate must also be set } +type PluginConf struct { + types.NetConf + + RuntimeConfig struct { + BandWidth *BandWidthEntry `json:"bandWidth,omitempty"` + } `json:"runtimeConfig,omitempty"` + + // RuntimeConfig *struct{} `json:"runtimeConfig"` + + RawPrevResult *map[string]interface{} `json:"prevResult"` + PrevResult *current.Result `json:"-"` +} + // parseConfig parses the supplied configuration (and prevResult) from stdin. func parseConfig(stdin []byte) (*PluginConf, error) { conf := PluginConf{} @@ -67,13 +76,15 @@ func parseConfig(stdin []byte) (*PluginConf, error) { } } - err := validateRateAndBurst(conf.IngressRate, conf.IngressBurst) - if err != nil { - return nil, err - } - err = validateRateAndBurst(conf.EgressRate, conf.EgressBurst) - if err != nil { - return nil, err + if conf.RuntimeConfig.BandWidth != nil { + err := validateRateAndBurst(conf.RuntimeConfig.BandWidth.IngressRate, conf.RuntimeConfig.BandWidth.IngressBurst) + if err != nil { + return nil, err + } + err = validateRateAndBurst(conf.RuntimeConfig.BandWidth.EgressRate, conf.RuntimeConfig.BandWidth.EgressBurst) + if err != nil { + return nil, err + } } return &conf, nil @@ -135,8 +146,9 @@ func cmdAdd(args *skel.CmdArgs) error { return err } + bandwidth := conf.RuntimeConfig.BandWidth //no traffic shaping was requested, so just no-op and quit - if conf.IngressRate == 0 && conf.IngressBurst == 0 && conf.EgressRate == 0 && conf.EgressBurst == 0 { + if bandwidth == nil || (bandwidth.IngressRate == 0 && bandwidth.IngressBurst == 0 && bandwidth.EgressRate == 0 && bandwidth.EgressBurst == 0) { return types.PrintResult(conf.PrevResult, conf.CNIVersion) } @@ -149,14 +161,14 @@ func cmdAdd(args *skel.CmdArgs) error { return err } - if conf.IngressRate > 0 && conf.IngressBurst > 0 { - err = CreateIngressQdisc(conf.IngressRate, conf.IngressBurst, hostInterface.Name) + if bandwidth.IngressRate > 0 && bandwidth.IngressBurst > 0 { + err = CreateIngressQdisc(bandwidth.IngressRate, bandwidth.IngressBurst, hostInterface.Name) if err != nil { return err } } - if conf.EgressRate > 0 && conf.EgressBurst > 0 { + if bandwidth.EgressRate > 0 && bandwidth.EgressBurst > 0 { mtu, err := getMTU(hostInterface.Name) if err != nil { return err @@ -181,7 +193,7 @@ func cmdAdd(args *skel.CmdArgs) error { Name: ifbDeviceName, Mac: ifbDevice.Attrs().HardwareAddr.String(), }) - err = CreateEgressQdisc(conf.EgressRate, conf.EgressBurst, hostInterface.Name, ifbDeviceName) + err = CreateEgressQdisc(bandwidth.EgressRate, bandwidth.EgressBurst, hostInterface.Name, ifbDeviceName) if err != nil { return err } From 4a0971bcd86f6ff416039f4e22c58cdaeab47674 Mon Sep 17 00:00:00 2001 From: Lion-Wei Date: Tue, 10 Apr 2018 10:54:59 +0800 Subject: [PATCH 2/2] update integration test configlist --- .../network-chain-test.conflist | 12 +- .../testdata/chained-ptp-bandwidth.conflist | 12 +- .../meta/bandwidth/bandwidth_linux_test.go | 461 ++++++++++++------ plugins/meta/bandwidth/main.go | 31 +- 4 files changed, 337 insertions(+), 179 deletions(-) diff --git a/integration/testdata/chained-bridge-bandwidth/network-chain-test.conflist b/integration/testdata/chained-bridge-bandwidth/network-chain-test.conflist index 81a99b4d..82fe6c5a 100644 --- a/integration/testdata/chained-bridge-bandwidth/network-chain-test.conflist +++ b/integration/testdata/chained-bridge-bandwidth/network-chain-test.conflist @@ -14,10 +14,14 @@ }, { "type": "bandwidth", - "ingressRate": 8000, - "ingressBurst": 16000, - "egressRate": 8000, - "egressBurst": 16000 + "runtimeConfig": { + "bandWidth": { + "ingressRate": 8000, + "ingressBurst": 16000, + "egressRate": 8000, + "egressBurst": 16000 + } + } } ] } diff --git a/integration/testdata/chained-ptp-bandwidth.conflist b/integration/testdata/chained-ptp-bandwidth.conflist index 3919da0f..2510ba88 100644 --- a/integration/testdata/chained-ptp-bandwidth.conflist +++ b/integration/testdata/chained-ptp-bandwidth.conflist @@ -13,10 +13,14 @@ }, { "type": "bandwidth", - "ingressRate": 800, - "ingressBurst": 200, - "egressRate": 800, - "egressBurst": 200 + "runtimeConfig": { + "bandWidth": { + "ingressRate": 800, + "ingressBurst": 200, + "egressRate": 800, + "egressBurst": 200 + } + } } ] } diff --git a/plugins/meta/bandwidth/bandwidth_linux_test.go b/plugins/meta/bandwidth/bandwidth_linux_test.go index 395ef849..92028479 100644 --- a/plugins/meta/bandwidth/bandwidth_linux_test.go +++ b/plugins/meta/bandwidth/bandwidth_linux_test.go @@ -77,6 +77,293 @@ var _ = Describe("bandwidth test", func() { "cniVersion": "0.3.0", "name": "cni-plugin-bandwidth-test", "type": "bandwidth", + "ingressRate": 8, + "ingressBurst": 8, + "egressRate": 16, + "egressBurst": 9, + "prevResult": { + "interfaces": [ + { + "name": "%s", + "sandbox": "" + }, + { + "name": "%s", + "sandbox": "%s" + } + ], + "ips": [ + { + "version": "4", + "address": "%s/24", + "gateway": "10.0.0.1", + "interface": 1 + } + ], + "routes": [] + } +}` + + conf = fmt.Sprintf(conf, hostIfname, containerIfname, containerNs.Path(), containerIP.String()) + args := &skel.CmdArgs{ + ContainerID: "dummy", + Netns: containerNs.Path(), + IfName: containerIfname, + StdinData: []byte(conf), + } + + Expect(hostNs.Do(func(netNS ns.NetNS) error { + defer GinkgoRecover() + r, out, err := testutils.CmdAddWithResult(containerNs.Path(), "", []byte(conf), func() error { return cmdAdd(args) }) + Expect(err).NotTo(HaveOccurred(), string(out)) + result, err := current.GetResult(r) + Expect(err).NotTo(HaveOccurred()) + + Expect(result.Interfaces).To(HaveLen(3)) + Expect(result.Interfaces[2].Name).To(Equal(ifbDeviceName)) + Expect(result.Interfaces[2].Sandbox).To(Equal("")) + + ifbLink, err := netlink.LinkByName(ifbDeviceName) + Expect(err).NotTo(HaveOccurred()) + Expect(ifbLink.Attrs().MTU).To(Equal(hostIfaceMTU)) + + qdiscs, err := netlink.QdiscList(ifbLink) + Expect(err).NotTo(HaveOccurred()) + + Expect(qdiscs).To(HaveLen(1)) + Expect(qdiscs[0].Attrs().LinkIndex).To(Equal(ifbLink.Attrs().Index)) + + Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{})) + Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(2))) + Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(9))) + + hostVethLink, err := netlink.LinkByName(hostIfname) + Expect(err).NotTo(HaveOccurred()) + + qdiscFilters, err := netlink.FilterList(hostVethLink, netlink.MakeHandle(0xffff, 0)) + Expect(err).NotTo(HaveOccurred()) + + Expect(qdiscFilters).To(HaveLen(1)) + Expect(qdiscFilters[0].(*netlink.U32).Actions[0].(*netlink.MirredAction).Ifindex).To(Equal(ifbLink.Attrs().Index)) + + return nil + })).To(Succeed()) + + Expect(hostNs.Do(func(n ns.NetNS) error { + defer GinkgoRecover() + + ifbLink, err := netlink.LinkByName(hostIfname) + Expect(err).NotTo(HaveOccurred()) + + qdiscs, err := netlink.QdiscList(ifbLink) + Expect(err).NotTo(HaveOccurred()) + + Expect(qdiscs).To(HaveLen(2)) + Expect(qdiscs[0].Attrs().LinkIndex).To(Equal(ifbLink.Attrs().Index)) + + Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{})) + Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(1))) + Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(8))) + return nil + })).To(Succeed()) + + }) + + It("Does not apply ingress when disabled", func() { + conf := `{ + "cniVersion": "0.3.0", + "name": "cni-plugin-bandwidth-test", + "type": "bandwidth", + "ingressRate": 0, + "ingressBurst": 0, + "egressRate": 8, + "egressBurst": 1, + "prevResult": { + "interfaces": [ + { + "name": "%s", + "sandbox": "" + }, + { + "name": "%s", + "sandbox": "%s" + } + ], + "ips": [ + { + "version": "4", + "address": "%s/24", + "gateway": "10.0.0.1", + "interface": 1 + } + ], + "routes": [] + } +}` + + conf = fmt.Sprintf(conf, hostIfname, containerIfname, containerNs.Path(), containerIP.String()) + args := &skel.CmdArgs{ + ContainerID: "dummy", + Netns: containerNs.Path(), + IfName: containerIfname, + StdinData: []byte(conf), + } + + Expect(hostNs.Do(func(netNS ns.NetNS) error { + defer GinkgoRecover() + + _, out, err := testutils.CmdAddWithResult(containerNs.Path(), ifbDeviceName, []byte(conf), func() error { return cmdAdd(args) }) + Expect(err).NotTo(HaveOccurred(), string(out)) + + _, err = netlink.LinkByName(ifbDeviceName) + Expect(err).NotTo(HaveOccurred()) + return nil + })).To(Succeed()) + + Expect(hostNs.Do(func(n ns.NetNS) error { + defer GinkgoRecover() + + containerIfLink, err := netlink.LinkByName(hostIfname) + Expect(err).NotTo(HaveOccurred()) + + qdiscs, err := netlink.QdiscList(containerIfLink) + Expect(err).NotTo(HaveOccurred()) + + Expect(qdiscs).To(HaveLen(2)) + Expect(qdiscs[0]).NotTo(BeAssignableToTypeOf(&netlink.Tbf{})) + Expect(qdiscs[1]).NotTo(BeAssignableToTypeOf(&netlink.Tbf{})) + + return nil + })).To(Succeed()) + + }) + + It("Does not apply egress when disabled", func() { + conf := `{ + "cniVersion": "0.3.0", + "name": "cni-plugin-bandwidth-test", + "type": "bandwidth", + "egressRate": 0, + "egressBurst": 0, + "ingressRate": 8, + "ingressBurst": 1, + "prevResult": { + "interfaces": [ + { + "name": "%s", + "sandbox": "" + }, + { + "name": "%s", + "sandbox": "%s" + } + ], + "ips": [ + { + "version": "4", + "address": "%s/24", + "gateway": "10.0.0.1", + "interface": 1 + } + ], + "routes": [] + } +}` + + conf = fmt.Sprintf(conf, hostIfname, containerIfname, containerNs.Path(), containerIP.String()) + args := &skel.CmdArgs{ + ContainerID: "dummy", + Netns: containerNs.Path(), + IfName: containerIfname, + StdinData: []byte(conf), + } + + Expect(hostNs.Do(func(netNS ns.NetNS) error { + defer GinkgoRecover() + + _, out, err := testutils.CmdAddWithResult(containerNs.Path(), ifbDeviceName, []byte(conf), func() error { return cmdAdd(args) }) + Expect(err).NotTo(HaveOccurred(), string(out)) + + _, err = netlink.LinkByName(ifbDeviceName) + Expect(err).To(HaveOccurred()) + return nil + })).To(Succeed()) + + Expect(hostNs.Do(func(n ns.NetNS) error { + defer GinkgoRecover() + + containerIfLink, err := netlink.LinkByName(hostIfname) + Expect(err).NotTo(HaveOccurred()) + + qdiscs, err := netlink.QdiscList(containerIfLink) + Expect(err).NotTo(HaveOccurred()) + + Expect(qdiscs).To(HaveLen(1)) + Expect(qdiscs[0].Attrs().LinkIndex).To(Equal(containerIfLink.Attrs().Index)) + + Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{})) + Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(1))) + Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(1))) + return nil + })).To(Succeed()) + + }) + + It("fails an invalid ingress config", func() { + conf := `{ + "cniVersion": "0.3.0", + "name": "cni-plugin-bandwidth-test", + "type": "bandwidth", + "ingressRate": 0, + "ingressBurst": 123, + "egressRate": 123, + "egressBurst": 123, + "prevResult": { + "interfaces": [ + { + "name": "%s", + "sandbox": "" + }, + { + "name": "%s", + "sandbox": "%s" + } + ], + "ips": [ + { + "version": "4", + "address": "%s/24", + "gateway": "10.0.0.1", + "interface": 1 + } + ], + "routes": [] + } +}` + + conf = fmt.Sprintf(conf, hostIfname, containerIfname, containerNs.Path(), containerIP.String()) + + args := &skel.CmdArgs{ + ContainerID: "dummy", + Netns: containerNs.Path(), + IfName: "eth0", + StdinData: []byte(conf), + } + + Expect(hostNs.Do(func(netNS ns.NetNS) error { + defer GinkgoRecover() + + _, _, err := testutils.CmdAddWithResult(containerNs.Path(), "", []byte(conf), func() error { return cmdAdd(args) }) + Expect(err).To(MatchError("if burst is set, rate must also be set")) + return nil + })).To(Succeed()) + }) + + It("Works with a Veth pair using runtime config", func() { + conf := `{ + "cniVersion": "0.3.0", + "name": "cni-plugin-bandwidth-test", + "type": "bandwidth", "runtimeConfig": { "bandWidth": { "ingressRate": 8, @@ -173,165 +460,21 @@ var _ = Describe("bandwidth test", func() { }) - It("Does not apply ingress when disabled", func() { + It("Should apply static config when both static config and runtime config exist", func() { conf := `{ "cniVersion": "0.3.0", "name": "cni-plugin-bandwidth-test", "type": "bandwidth", + "ingressRate": 0, + "ingressBurst": 123, + "egressRate": 123, + "egressBurst": 123, "runtimeConfig": { "bandWidth": { - "ingressRate": 0, - "ingressBurst": 0, - "egressRate": 8, - "egressBurst": 1 - } - }, - "prevResult": { - "interfaces": [ - { - "name": "%s", - "sandbox": "" - }, - { - "name": "%s", - "sandbox": "%s" - } - ], - "ips": [ - { - "version": "4", - "address": "%s/24", - "gateway": "10.0.0.1", - "interface": 1 - } - ], - "routes": [] - } -}` - - conf = fmt.Sprintf(conf, hostIfname, containerIfname, containerNs.Path(), containerIP.String()) - args := &skel.CmdArgs{ - ContainerID: "dummy", - Netns: containerNs.Path(), - IfName: containerIfname, - StdinData: []byte(conf), - } - - Expect(hostNs.Do(func(netNS ns.NetNS) error { - defer GinkgoRecover() - - _, out, err := testutils.CmdAddWithResult(containerNs.Path(), ifbDeviceName, []byte(conf), func() error { return cmdAdd(args) }) - Expect(err).NotTo(HaveOccurred(), string(out)) - - _, err = netlink.LinkByName(ifbDeviceName) - Expect(err).NotTo(HaveOccurred()) - return nil - })).To(Succeed()) - - Expect(hostNs.Do(func(n ns.NetNS) error { - defer GinkgoRecover() - - containerIfLink, err := netlink.LinkByName(hostIfname) - Expect(err).NotTo(HaveOccurred()) - - qdiscs, err := netlink.QdiscList(containerIfLink) - Expect(err).NotTo(HaveOccurred()) - - Expect(qdiscs).To(HaveLen(2)) - Expect(qdiscs[0]).NotTo(BeAssignableToTypeOf(&netlink.Tbf{})) - Expect(qdiscs[1]).NotTo(BeAssignableToTypeOf(&netlink.Tbf{})) - - return nil - })).To(Succeed()) - - }) - - It("Does not apply egress when disabled", func() { - conf := `{ - "cniVersion": "0.3.0", - "name": "cni-plugin-bandwidth-test", - "type": "bandwidth", - "runtimeConfig": { - "bandWidth": { - "egressRate": 0, - "egressBurst": 0, "ingressRate": 8, - "ingressBurst": 1 - } - }, - "prevResult": { - "interfaces": [ - { - "name": "%s", - "sandbox": "" - }, - { - "name": "%s", - "sandbox": "%s" - } - ], - "ips": [ - { - "version": "4", - "address": "%s/24", - "gateway": "10.0.0.1", - "interface": 1 - } - ], - "routes": [] - } -}` - - conf = fmt.Sprintf(conf, hostIfname, containerIfname, containerNs.Path(), containerIP.String()) - args := &skel.CmdArgs{ - ContainerID: "dummy", - Netns: containerNs.Path(), - IfName: containerIfname, - StdinData: []byte(conf), - } - - Expect(hostNs.Do(func(netNS ns.NetNS) error { - defer GinkgoRecover() - - _, out, err := testutils.CmdAddWithResult(containerNs.Path(), ifbDeviceName, []byte(conf), func() error { return cmdAdd(args) }) - Expect(err).NotTo(HaveOccurred(), string(out)) - - _, err = netlink.LinkByName(ifbDeviceName) - Expect(err).To(HaveOccurred()) - return nil - })).To(Succeed()) - - Expect(hostNs.Do(func(n ns.NetNS) error { - defer GinkgoRecover() - - containerIfLink, err := netlink.LinkByName(hostIfname) - Expect(err).NotTo(HaveOccurred()) - - qdiscs, err := netlink.QdiscList(containerIfLink) - Expect(err).NotTo(HaveOccurred()) - - Expect(qdiscs).To(HaveLen(1)) - Expect(qdiscs[0].Attrs().LinkIndex).To(Equal(containerIfLink.Attrs().Index)) - - Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{})) - Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(1))) - Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(1))) - return nil - })).To(Succeed()) - - }) - - It("fails an invalid ingress config", func() { - conf := `{ - "cniVersion": "0.3.0", - "name": "cni-plugin-bandwidth-test", - "type": "bandwidth", - "runtimeConfig": { - "bandWidth": { - "ingressRate": 0, - "ingressBurst": 123, - "egressRate": 123, - "egressBurst": 123 + "ingressBurst": 8, + "egressRate": 16, + "egressBurst": 9 } }, "prevResult": { @@ -382,14 +525,10 @@ var _ = Describe("bandwidth test", func() { "cniVersion": "0.3.0", "name": "cni-plugin-bandwidth-test", "type": "bandwidth", - "runtimeConfig": { - "bandWidth": { - "ingressRate": 8, - "ingressBurst": 8, - "egressRate": 9, - "egressBurst": 9 - } - }, + "ingressRate": 8, + "ingressBurst": 8, + "egressRate": 9, + "egressBurst": 9, "prevResult": { "interfaces": [ { @@ -505,7 +644,7 @@ var _ = Describe("bandwidth test", func() { Expect(err).NotTo(HaveOccurred()) tbfPluginConf := PluginConf{} - tbfPluginConf.RuntimeConfig.BandWidth = &BandWidthEntry{ + tbfPluginConf.RuntimeConfig.Bandwidth = &BandwidthEntry{ IngressBurst: burstInBits, IngressRate: rateInBits, EgressBurst: burstInBits, diff --git a/plugins/meta/bandwidth/main.go b/plugins/meta/bandwidth/main.go index fa9f6ed0..da580ae0 100644 --- a/plugins/meta/bandwidth/main.go +++ b/plugins/meta/bandwidth/main.go @@ -29,9 +29,9 @@ import ( "github.com/vishvananda/netlink" ) -// BandWidthEntry corresponds to a single entry in the bandwidth argument, +// BandwidthEntry corresponds to a single entry in the bandwidth argument, // see CONVENTIONS.md -type BandWidthEntry struct { +type BandwidthEntry struct { IngressRate int `json:"ingressRate"` //Bandwidth rate in Kbps for traffic through container. 0 for no limit. If ingressRate is set, ingressBurst must also be set IngressBurst int `json:"ingressBurst"` //Bandwidth burst in Kb for traffic through container. 0 for no limit. If ingressBurst is set, ingressRate must also be set @@ -39,17 +39,22 @@ type BandWidthEntry struct { EgressBurst int `json:"egressBurst"` //Bandwidth burst in Kb for traffic through container. 0 for no limit. If egressBurst is set, egressRate must also be set } +func (bw *BandwidthEntry) isZero() bool { + return bw.IngressBurst == 0 && bw.IngressRate == 0 && bw.EgressBurst == 0 && bw.EgressRate == 0 +} + type PluginConf struct { types.NetConf RuntimeConfig struct { - BandWidth *BandWidthEntry `json:"bandWidth,omitempty"` + Bandwidth *BandwidthEntry `json:"bandwidth,omitempty"` } `json:"runtimeConfig,omitempty"` // RuntimeConfig *struct{} `json:"runtimeConfig"` RawPrevResult *map[string]interface{} `json:"prevResult"` PrevResult *current.Result `json:"-"` + *BandwidthEntry } // parseConfig parses the supplied configuration (and prevResult) from stdin. @@ -75,13 +80,13 @@ func parseConfig(stdin []byte) (*PluginConf, error) { return nil, fmt.Errorf("could not convert result to current version: %v", err) } } - - if conf.RuntimeConfig.BandWidth != nil { - err := validateRateAndBurst(conf.RuntimeConfig.BandWidth.IngressRate, conf.RuntimeConfig.BandWidth.IngressBurst) + bandwidth := getBandwidth(&conf) + if bandwidth != nil { + err := validateRateAndBurst(bandwidth.IngressRate, bandwidth.IngressBurst) if err != nil { return nil, err } - err = validateRateAndBurst(conf.RuntimeConfig.BandWidth.EgressRate, conf.RuntimeConfig.BandWidth.EgressBurst) + err = validateRateAndBurst(bandwidth.EgressRate, bandwidth.EgressBurst) if err != nil { return nil, err } @@ -91,6 +96,13 @@ func parseConfig(stdin []byte) (*PluginConf, error) { } +func getBandwidth(conf *PluginConf) *BandwidthEntry { + if conf.BandwidthEntry == nil && conf.RuntimeConfig.Bandwidth != nil { + return conf.RuntimeConfig.Bandwidth + } + return conf.BandwidthEntry +} + func validateRateAndBurst(rate int, burst int) error { switch { case burst < 0 || rate < 0: @@ -146,9 +158,8 @@ func cmdAdd(args *skel.CmdArgs) error { return err } - bandwidth := conf.RuntimeConfig.BandWidth - //no traffic shaping was requested, so just no-op and quit - if bandwidth == nil || (bandwidth.IngressRate == 0 && bandwidth.IngressBurst == 0 && bandwidth.EgressRate == 0 && bandwidth.EgressBurst == 0) { + bandwidth := getBandwidth(conf) + if bandwidth == nil || bandwidth.isZero() { return types.PrintResult(conf.PrevResult, conf.CNIVersion) }