Skip to content
28 changes: 20 additions & 8 deletions plugins/meta/sbr/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
23 changes: 17 additions & 6 deletions plugins/meta/sbr/sbr_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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())
Expand Down Expand Up @@ -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 {
Expand All @@ -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())
Expand Down Expand Up @@ -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]

Expand Down Expand Up @@ -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"))

Expand Down