|
@@ -12,6 +12,7 @@ import (
|
|
"strings"
|
|
"strings"
|
|
"sync"
|
|
"sync"
|
|
"syscall"
|
|
"syscall"
|
|
|
|
+ "time"
|
|
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
"github.com/Sirupsen/logrus"
|
|
"github.com/docker/docker/pkg/reexec"
|
|
"github.com/docker/docker/pkg/reexec"
|
|
@@ -705,6 +706,7 @@ func (n *network) initSandbox(restore bool) error {
|
|
}
|
|
}
|
|
|
|
|
|
func (n *network) watchMiss(nlSock *nl.NetlinkSocket) {
|
|
func (n *network) watchMiss(nlSock *nl.NetlinkSocket) {
|
|
|
|
+ t := time.Now()
|
|
for {
|
|
for {
|
|
msgs, err := nlSock.Receive()
|
|
msgs, err := nlSock.Receive()
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -757,23 +759,55 @@ func (n *network) watchMiss(nlSock *nl.NetlinkSocket) {
|
|
continue
|
|
continue
|
|
}
|
|
}
|
|
|
|
|
|
- if !n.driver.isSerfAlive() {
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- mac, IPmask, vtep, err := n.driver.resolvePeer(n.id, ip)
|
|
|
|
- if err != nil {
|
|
|
|
- logrus.Errorf("could not resolve peer %q: %v", ip, err)
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
|
|
+ if n.driver.isSerfAlive() {
|
|
|
|
+ mac, IPmask, vtep, err := n.driver.resolvePeer(n.id, ip)
|
|
|
|
+ if err != nil {
|
|
|
|
+ logrus.Errorf("could not resolve peer %q: %v", ip, err)
|
|
|
|
+ continue
|
|
|
|
+ }
|
|
|
|
|
|
- if err := n.driver.peerAdd(n.id, "dummy", ip, IPmask, mac, vtep, true, l2Miss, l3Miss); err != nil {
|
|
|
|
- logrus.Errorf("could not add neighbor entry for missed peer %q: %v", ip, err)
|
|
|
|
|
|
+ if err := n.driver.peerAdd(n.id, "dummy", ip, IPmask, mac, vtep, true, l2Miss, l3Miss); err != nil {
|
|
|
|
+ logrus.Errorf("could not add neighbor entry for missed peer %q: %v", ip, err)
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ // If the gc_thresh values are lower kernel might knock off the neighor entries.
|
|
|
|
+ // When we get a L3 miss check if its a valid peer and reprogram the neighbor
|
|
|
|
+ // entry again. Rate limit it to once attempt every 500ms, just in case a faulty
|
|
|
|
+ // container sends a flood of packets to invalid peers
|
|
|
|
+ if !l3Miss {
|
|
|
|
+ continue
|
|
|
|
+ }
|
|
|
|
+ if time.Since(t) > 500*time.Millisecond {
|
|
|
|
+ t = time.Now()
|
|
|
|
+ n.programNeighbor(ip)
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+func (n *network) programNeighbor(ip net.IP) {
|
|
|
|
+ peerMac, _, _, err := n.driver.peerDbSearch(n.id, ip)
|
|
|
|
+ if err != nil {
|
|
|
|
+ logrus.Errorf("Reprogramming on L3 miss failed for %s, no peer entry", ip)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ s := n.getSubnetforIPAddr(ip)
|
|
|
|
+ if s == nil {
|
|
|
|
+ logrus.Errorf("Reprogramming on L3 miss failed for %s, not a valid subnet", ip)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ sbox := n.sandbox()
|
|
|
|
+ if sbox == nil {
|
|
|
|
+ logrus.Errorf("Reprogramming on L3 miss failed for %s, overlay sandbox missing", ip)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if err := sbox.AddNeighbor(ip, peerMac, true, sbox.NeighborOptions().LinkName(s.vxlanName)); err != nil {
|
|
|
|
+ logrus.Errorf("Reprogramming on L3 miss failed for %s: %v", ip, err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
func (d *driver) addNetwork(n *network) {
|
|
func (d *driver) addNetwork(n *network) {
|
|
d.Lock()
|
|
d.Lock()
|
|
d.networks[n.id] = n
|
|
d.networks[n.id] = n
|
|
@@ -1052,6 +1086,15 @@ func (n *network) contains(ip net.IP) bool {
|
|
return false
|
|
return false
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+func (n *network) getSubnetforIPAddr(ip net.IP) *subnet {
|
|
|
|
+ for _, s := range n.subnets {
|
|
|
|
+ if s.subnetIP.Contains(ip) {
|
|
|
|
+ return s
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
// getSubnetforIP returns the subnet to which the given IP belongs
|
|
// getSubnetforIP returns the subnet to which the given IP belongs
|
|
func (n *network) getSubnetforIP(ip *net.IPNet) *subnet {
|
|
func (n *network) getSubnetforIP(ip *net.IPNet) *subnet {
|
|
for _, s := range n.subnets {
|
|
for _, s := range n.subnets {
|