github.com/jfrazelle/docker@v1.1.2-0.20210712172922-bf78e25fe508/libnetwork/drivers/overlay/ov_serf.go (about) 1 // +build linux 2 3 package overlay 4 5 import ( 6 "fmt" 7 "net" 8 "strings" 9 "time" 10 11 "github.com/hashicorp/serf/serf" 12 "github.com/sirupsen/logrus" 13 ) 14 15 type ovNotify struct { 16 action string 17 ep *endpoint 18 nw *network 19 } 20 21 type logWriter struct{} 22 23 func (l *logWriter) Write(p []byte) (int, error) { 24 str := string(p) 25 26 switch { 27 case strings.Contains(str, "[WARN]"): 28 logrus.Warn(str) 29 case strings.Contains(str, "[DEBUG]"): 30 logrus.Debug(str) 31 case strings.Contains(str, "[INFO]"): 32 logrus.Info(str) 33 case strings.Contains(str, "[ERR]"): 34 logrus.Error(str) 35 } 36 37 return len(p), nil 38 } 39 40 func (d *driver) serfInit() error { 41 var err error 42 43 config := serf.DefaultConfig() 44 config.Init() 45 config.MemberlistConfig.BindAddr = d.advertiseAddress 46 47 d.eventCh = make(chan serf.Event, 4) 48 config.EventCh = d.eventCh 49 config.UserCoalescePeriod = 1 * time.Second 50 config.UserQuiescentPeriod = 50 * time.Millisecond 51 52 config.LogOutput = &logWriter{} 53 config.MemberlistConfig.LogOutput = config.LogOutput 54 55 s, err := serf.Create(config) 56 if err != nil { 57 return fmt.Errorf("failed to create cluster node: %v", err) 58 } 59 defer func() { 60 if err != nil { 61 s.Shutdown() 62 } 63 }() 64 65 d.serfInstance = s 66 67 d.notifyCh = make(chan ovNotify) 68 d.exitCh = make(chan chan struct{}) 69 70 go d.startSerfLoop(d.eventCh, d.notifyCh, d.exitCh) 71 return nil 72 } 73 74 func (d *driver) serfJoin(neighIP string) error { 75 if neighIP == "" { 76 return fmt.Errorf("no neighbor to join") 77 } 78 if _, err := d.serfInstance.Join([]string{neighIP}, true); err != nil { 79 return fmt.Errorf("Failed to join the cluster at neigh IP %s: %v", 80 neighIP, err) 81 } 82 return nil 83 } 84 85 func (d *driver) notifyEvent(event ovNotify) { 86 ep := event.ep 87 88 ePayload := fmt.Sprintf("%s %s %s %s", event.action, ep.addr.IP.String(), 89 net.IP(ep.addr.Mask).String(), ep.mac.String()) 90 eName := fmt.Sprintf("jl %s %s %s", d.serfInstance.LocalMember().Addr.String(), 91 event.nw.id, ep.id) 92 93 if err := d.serfInstance.UserEvent(eName, []byte(ePayload), true); err != nil { 94 logrus.Errorf("Sending user event failed: %v\n", err) 95 } 96 } 97 98 func (d *driver) processEvent(u serf.UserEvent) { 99 logrus.Debugf("Received user event name:%s, payload:%s LTime:%d \n", u.Name, 100 string(u.Payload), uint64(u.LTime)) 101 102 var dummy, action, vtepStr, nid, eid, ipStr, maskStr, macStr string 103 if _, err := fmt.Sscan(u.Name, &dummy, &vtepStr, &nid, &eid); err != nil { 104 fmt.Printf("Failed to scan name string: %v\n", err) 105 } 106 107 if _, err := fmt.Sscan(string(u.Payload), &action, 108 &ipStr, &maskStr, &macStr); err != nil { 109 fmt.Printf("Failed to scan value string: %v\n", err) 110 } 111 112 logrus.Debugf("Parsed data = %s/%s/%s/%s/%s/%s\n", nid, eid, vtepStr, ipStr, maskStr, macStr) 113 114 mac, err := net.ParseMAC(macStr) 115 if err != nil { 116 logrus.Errorf("Failed to parse mac: %v\n", err) 117 } 118 119 if d.serfInstance.LocalMember().Addr.String() == vtepStr { 120 return 121 } 122 123 switch action { 124 case "join": 125 d.peerAdd(nid, eid, net.ParseIP(ipStr), net.IPMask(net.ParseIP(maskStr).To4()), mac, net.ParseIP(vtepStr), false, false, false) 126 case "leave": 127 d.peerDelete(nid, eid, net.ParseIP(ipStr), net.IPMask(net.ParseIP(maskStr).To4()), mac, net.ParseIP(vtepStr), false) 128 } 129 } 130 131 func (d *driver) processQuery(q *serf.Query) { 132 logrus.Debugf("Received query name:%s, payload:%s\n", q.Name, 133 string(q.Payload)) 134 135 var nid, ipStr string 136 if _, err := fmt.Sscan(string(q.Payload), &nid, &ipStr); err != nil { 137 fmt.Printf("Failed to scan query payload string: %v\n", err) 138 } 139 140 pKey, pEntry, err := d.peerDbSearch(nid, net.ParseIP(ipStr)) 141 if err != nil { 142 return 143 } 144 145 logrus.Debugf("Sending peer query resp mac %v, mask %s, vtep %s", pKey.peerMac, net.IP(pEntry.peerIPMask).String(), pEntry.vtep) 146 q.Respond([]byte(fmt.Sprintf("%s %s %s", pKey.peerMac.String(), net.IP(pEntry.peerIPMask).String(), pEntry.vtep.String()))) 147 } 148 149 func (d *driver) resolvePeer(nid string, peerIP net.IP) (net.HardwareAddr, net.IPMask, net.IP, error) { 150 if d.serfInstance == nil { 151 return nil, nil, nil, fmt.Errorf("could not resolve peer: serf instance not initialized") 152 } 153 154 qPayload := fmt.Sprintf("%s %s", nid, peerIP.String()) 155 resp, err := d.serfInstance.Query("peerlookup", []byte(qPayload), nil) 156 if err != nil { 157 return nil, nil, nil, fmt.Errorf("resolving peer by querying the cluster failed: %v", err) 158 } 159 160 respCh := resp.ResponseCh() 161 select { 162 case r := <-respCh: 163 var macStr, maskStr, vtepStr string 164 if _, err := fmt.Sscan(string(r.Payload), &macStr, &maskStr, &vtepStr); err != nil { 165 return nil, nil, nil, fmt.Errorf("bad response %q for the resolve query: %v", string(r.Payload), err) 166 } 167 168 mac, err := net.ParseMAC(macStr) 169 if err != nil { 170 return nil, nil, nil, fmt.Errorf("failed to parse mac: %v", err) 171 } 172 173 logrus.Debugf("Received peer query response, mac %s, vtep %s, mask %s", macStr, vtepStr, maskStr) 174 return mac, net.IPMask(net.ParseIP(maskStr).To4()), net.ParseIP(vtepStr), nil 175 176 case <-time.After(time.Second): 177 return nil, nil, nil, fmt.Errorf("timed out resolving peer by querying the cluster") 178 } 179 } 180 181 func (d *driver) startSerfLoop(eventCh chan serf.Event, notifyCh chan ovNotify, 182 exitCh chan chan struct{}) { 183 184 for { 185 select { 186 case notify, ok := <-notifyCh: 187 if !ok { 188 break 189 } 190 191 d.notifyEvent(notify) 192 case ch, ok := <-exitCh: 193 if !ok { 194 break 195 } 196 197 if err := d.serfInstance.Leave(); err != nil { 198 logrus.Errorf("failed leaving the cluster: %v\n", err) 199 } 200 201 d.serfInstance.Shutdown() 202 close(ch) 203 return 204 case e, ok := <-eventCh: 205 if !ok { 206 break 207 } 208 209 if e.EventType() == serf.EventQuery { 210 d.processQuery(e.(*serf.Query)) 211 break 212 } 213 214 u, ok := e.(serf.UserEvent) 215 if !ok { 216 break 217 } 218 d.processEvent(u) 219 } 220 } 221 } 222 223 func (d *driver) isSerfAlive() bool { 224 d.Lock() 225 serfInstance := d.serfInstance 226 d.Unlock() 227 if serfInstance == nil || serfInstance.State() != serf.SerfAlive { 228 return false 229 } 230 return true 231 }