diff --git a/plugins/meta/sbr/main.go b/plugins/meta/sbr/main.go index acfa24640..25f02ef66 100644 --- a/plugins/meta/sbr/main.go +++ b/plugins/meta/sbr/main.go @@ -231,6 +231,18 @@ func doRoutes(ipCfgs []*current.IPConfig, iface string) error { linkIndex := link.Attrs().Index + // Add an interface rule, only if there is a single IP address configured on the interface + if len(ipCfgs) == 1 { + interfaceRule := netlink.NewRule() + interfaceRule.Table = table + log.Printf("Interface to use %s", iface) + interfaceRule.OifName = iface + + if err = netlink.RuleAdd(interfaceRule); err != nil { + return fmt.Errorf("Failed to add interface rule: %v", err) + } + } + // Get all routes for the interface in the default routing table routes, err = netlink.RouteList(link, netlink.FAMILY_ALL) if err != nil { @@ -239,9 +251,9 @@ func doRoutes(ipCfgs []*current.IPConfig, iface string) error { // Loop through setting up source based rules and default routes. for _, ipCfg := range ipCfgs { - log.Printf("Set rule for source %s", ipCfg.String()) - rule := netlink.NewRule() - rule.Table = table + log.Printf("Set src and interface rules for source %s", ipCfg.String()) + srcRule := netlink.NewRule() + srcRule.Table = table // Source must be restricted to a single IP, not a full subnet var src net.IPNet @@ -253,10 +265,10 @@ func doRoutes(ipCfgs []*current.IPConfig, iface string) error { } log.Printf("Source to use %s", src.String()) - rule.Src = &src + srcRule.Src = &src - if err = netlink.RuleAdd(rule); err != nil { - return fmt.Errorf("Failed to add rule: %v", err) + if err = netlink.RuleAdd(srcRule); err != nil { + return fmt.Errorf("Failed to add src rule: %v", err) } // Add a default route, since this may have been removed by previous @@ -425,12 +437,12 @@ func tidyRules(iface string, table *int) error { RULE_LOOP: for _, rule := range rules { log.Printf("Check rule: %v", rule) - if rule.Src == nil { + if rule.Src == nil && rule.OifName == "" { continue } for _, addr := range addrs { - if rule.Src.IP.Equal(addr.IP) { + if rule.OifName == iface || rule.Src.IP.Equal(addr.IP) { log.Printf("Delete rule %v", rule) err := netlink.RuleDel(&rule) if err != nil { diff --git a/plugins/meta/sbr/sbr_linux_test.go b/plugins/meta/sbr/sbr_linux_test.go index 731f71d81..5546dafbe 100644 --- a/plugins/meta/sbr/sbr_linux_test.go +++ b/plugins/meta/sbr/sbr_linux_test.go @@ -287,7 +287,7 @@ var _ = Describe("sbr test", func() { // Check results. We expect all the routes on net1 to have moved to // table 100 except for local routes (table 255); a new default gateway - // route to have been created; and a single rule to exist. + // route to have been created; and two rules to exist. expNet1 := oldStatus.Devices[0] expEth0 := oldStatus.Devices[1] for i := range expNet1.Routes { @@ -303,9 +303,14 @@ var _ = Describe("sbr test", func() { LinkIndex: expNet1.Routes[0].LinkIndex, }) - Expect(newStatus.Rules).To(HaveLen(1)) + Expect(newStatus.Rules).To(HaveLen(2)) + Expect(newStatus.Rules[0].Table).To(Equal(100)) Expect(newStatus.Rules[0].Src.String()).To(Equal("192.168.1.209/32")) + + Expect(newStatus.Rules[1].Table).To(Equal(100)) + Expect(newStatus.Rules[1].OifName).To(Equal("net1")) + devNet1 := newStatus.Devices[0] devEth0 := newStatus.Devices[1] Expect(equalRoutes(expNet1.Routes, devNet1.Routes)).To(BeTrue()) @@ -392,7 +397,7 @@ var _ = Describe("sbr test", func() { // Check results. We expect all the routes on net1 to have moved to // table 100 except for local routes (table 255); a new default gateway - // route to have been created; and a single rule to exist. + // route to have been created; and two rules to exist. expNet1 := oldStatus.Devices[0] expEth0 := oldStatus.Devices[1] for i := range expNet1.Routes { @@ -401,9 +406,14 @@ var _ = Describe("sbr test", func() { } } - Expect(newStatus.Rules).To(HaveLen(1)) + Expect(newStatus.Rules).To(HaveLen(2)) + Expect(newStatus.Rules[0].Table).To(Equal(100)) Expect(newStatus.Rules[0].Src.String()).To(Equal("192.168.1.209/32")) + + Expect(newStatus.Rules[1].Table).To(Equal(100)) + Expect(newStatus.Rules[1].OifName).To(Equal("net1")) + devNet1 := newStatus.Devices[0] devEth0 := newStatus.Devices[1] Expect(equalRoutes(expEth0.Routes, devEth0.Routes)).To(BeTrue()) @@ -472,7 +482,9 @@ var _ = Describe("sbr test", func() { // Check results. We expect all the routes on net1 to have moved to // table 100 except for local routes (table 255); a new default gateway - // route to have been created; and 2 rules to exist. + // route to have been created; and 2 rules to exist. There will be no + // interface rules, because they don't make sense when there are multiple + // IPs for a single interface expNet1 := oldStatus.Devices[0] expEth0 := oldStatus.Devices[1] @@ -520,7 +532,6 @@ var _ = Describe("sbr test", func() { Expect(newStatus.Rules[0].Table).To(Equal(101)) Expect(newStatus.Rules[0].Src.String()).To(Equal("192.168.101.209/32")) - // Second entry corresponds to first table (100) Expect(newStatus.Rules[1].Table).To(Equal(100)) Expect(newStatus.Rules[1].Src.String()).To(Equal("192.168.1.209/32"))