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