Bladeren bron

Merge pull request #163 from windwizard/master

fix the bug of lost route information when restart network
Eugene Yakubovich 10 jaren geleden
bovenliggende
commit
ebabf76eb4
1 gewijzigde bestanden met toevoegingen van 75 en 0 verwijderingen
  1. 75 0
      backend/hostgw/hostgw.go

+ 75 - 0
backend/hostgw/hostgw.go

@@ -15,9 +15,11 @@
 package hostgw
 
 import (
+	"bytes"
 	"fmt"
 	"net"
 	"sync"
+	"time"
 
 	log "github.com/coreos/flannel/Godeps/_workspace/src/github.com/golang/glog"
 	"github.com/coreos/flannel/Godeps/_workspace/src/github.com/vishvananda/netlink"
@@ -28,12 +30,17 @@ import (
 	"github.com/coreos/flannel/subnet"
 )
 
+const (
+	routeCheckRetries = 10
+)
+
 type HostgwBackend struct {
 	sm       *subnet.SubnetManager
 	extIface *net.Interface
 	extIP    net.IP
 	stop     chan bool
 	wg       sync.WaitGroup
+	rl       []netlink.Route
 }
 
 func New(sm *subnet.SubnetManager) backend.Backend {
@@ -85,6 +92,13 @@ func (rb *HostgwBackend) Run() {
 		rb.wg.Done()
 	}()
 
+	rb.rl = make([]netlink.Route, 0, 10)
+	rb.wg.Add(1)
+	go func() {
+		rb.routeCheck(rb.stop)
+		rb.wg.Done()
+	}()
+
 	defer rb.wg.Wait()
 
 	for {
@@ -126,6 +140,7 @@ func (rb *HostgwBackend) handleSubnetEvents(batch subnet.EventBatch) {
 				log.Errorf("Error adding route to %v via %v: %v", evt.Lease.Network, evt.Lease.Attrs.PublicIP, err)
 				continue
 			}
+			rb.addToRouteList(route)
 
 		case subnet.SubnetRemoved:
 			log.Info("Subnet removed: ", evt.Lease.Network)
@@ -144,9 +159,69 @@ func (rb *HostgwBackend) handleSubnetEvents(batch subnet.EventBatch) {
 				log.Errorf("Error deleting route to %v: %v", evt.Lease.Network, err)
 				continue
 			}
+			rb.removeFromRouteList(route)
 
 		default:
 			log.Error("Internal error: unknown event type: ", int(evt.Type))
 		}
 	}
 }
+
+func (rb *HostgwBackend) addToRouteList(route netlink.Route) {
+	rb.rl = append(rb.rl, route)
+}
+
+func (rb *HostgwBackend) removeFromRouteList(route netlink.Route) {
+	for index, r := range rb.rl {
+		if routeEqual(r, route) {
+			rb.rl = append(rb.rl[:index], rb.rl[index+1:]...)
+			return
+		}
+	}
+}
+
+func (rb *HostgwBackend) routeCheck(cancel chan bool) {
+	for {
+		select {
+		case <-cancel:
+			return
+		case <-time.After(routeCheckRetries * time.Second):
+			rb.checkSubnetExistInRoutes()
+		}
+	}
+}
+
+func (rb *HostgwBackend) checkSubnetExistInRoutes() {
+	routeList, err := netlink.RouteList(nil, netlink.FAMILY_V4)
+	if err == nil {
+		for _, route := range rb.rl {
+			exist := false
+			for _, r := range routeList {
+				if r.Dst == nil {
+					continue
+				}
+				if routeEqual(r, route) {
+					exist = true
+					break
+				}
+			}
+			if !exist {
+				if err := netlink.RouteAdd(&route); err != nil {
+					if nerr, ok := err.(net.Error); !ok {
+						log.Errorf("Error recovering route to %v: %v, %v", route.Dst, route.Gw, nerr)
+					}
+					continue
+				} else {
+					log.Infof("Route recovered %v : %v", route.Dst, route.Gw)
+				}
+			}
+		}
+	}
+}
+
+func routeEqual(x, y netlink.Route) bool {
+	if x.Dst.IP.Equal(y.Dst.IP) && x.Gw.Equal(y.Gw) && bytes.Equal(x.Dst.Mask, y.Dst.Mask) {
+		return true
+	}
+	return false
+}