github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/libnetwork/drivers/overlay/joinleave.go (about) 1 //go:build linux 2 // +build linux 3 4 package overlay 5 6 import ( 7 "fmt" 8 "net" 9 "syscall" 10 11 "github.com/docker/docker/libnetwork/driverapi" 12 "github.com/docker/docker/libnetwork/ns" 13 "github.com/docker/docker/libnetwork/types" 14 "github.com/gogo/protobuf/proto" 15 "github.com/sirupsen/logrus" 16 ) 17 18 // Join method is invoked when a Sandbox is attached to an endpoint. 19 func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error { 20 if err := validateID(nid, eid); err != nil { 21 return err 22 } 23 24 n := d.network(nid) 25 if n == nil { 26 return fmt.Errorf("could not find network with id %s", nid) 27 } 28 29 ep := n.endpoint(eid) 30 if ep == nil { 31 return fmt.Errorf("could not find endpoint with id %s", eid) 32 } 33 34 if n.secure && len(d.keys) == 0 { 35 return fmt.Errorf("cannot join secure network: encryption keys not present") 36 } 37 38 nlh := ns.NlHandle() 39 40 if n.secure && !nlh.SupportsNetlinkFamily(syscall.NETLINK_XFRM) { 41 return fmt.Errorf("cannot join secure network: required modules to install IPSEC rules are missing on host") 42 } 43 44 s := n.getSubnetforIP(ep.addr) 45 if s == nil { 46 return fmt.Errorf("could not find subnet for endpoint %s", eid) 47 } 48 49 if err := n.obtainVxlanID(s); err != nil { 50 return fmt.Errorf("couldn't get vxlan id for %q: %v", s.subnetIP.String(), err) 51 } 52 53 if err := n.joinSandbox(s, false, true); err != nil { 54 return fmt.Errorf("network sandbox join failed: %v", err) 55 } 56 57 sbox := n.sandbox() 58 59 overlayIfName, containerIfName, err := createVethPair() 60 if err != nil { 61 return err 62 } 63 64 ep.ifName = containerIfName 65 66 if err = d.writeEndpointToStore(ep); err != nil { 67 return fmt.Errorf("failed to update overlay endpoint %.7s to local data store: %v", ep.id, err) 68 } 69 70 // Set the container interface and its peer MTU to 1450 to allow 71 // for 50 bytes vxlan encap (inner eth header(14) + outer IP(20) + 72 // outer UDP(8) + vxlan header(8)) 73 mtu := n.maxMTU() 74 75 veth, err := nlh.LinkByName(overlayIfName) 76 if err != nil { 77 return fmt.Errorf("cound not find link by name %s: %v", overlayIfName, err) 78 } 79 err = nlh.LinkSetMTU(veth, mtu) 80 if err != nil { 81 return err 82 } 83 84 if err = sbox.AddInterface(overlayIfName, "veth", 85 sbox.InterfaceOptions().Master(s.brName)); err != nil { 86 return fmt.Errorf("could not add veth pair inside the network sandbox: %v", err) 87 } 88 89 veth, err = nlh.LinkByName(containerIfName) 90 if err != nil { 91 return fmt.Errorf("could not find link by name %s: %v", containerIfName, err) 92 } 93 err = nlh.LinkSetMTU(veth, mtu) 94 if err != nil { 95 return err 96 } 97 98 if err = nlh.LinkSetHardwareAddr(veth, ep.mac); err != nil { 99 return fmt.Errorf("could not set mac address (%v) to the container interface: %v", ep.mac, err) 100 } 101 102 for _, sub := range n.subnets { 103 if sub == s { 104 continue 105 } 106 if err = jinfo.AddStaticRoute(sub.subnetIP, types.NEXTHOP, s.gwIP.IP); err != nil { 107 logrus.Errorf("Adding subnet %s static route in network %q failed\n", s.subnetIP, n.id) 108 } 109 } 110 111 if iNames := jinfo.InterfaceName(); iNames != nil { 112 err = iNames.SetNames(containerIfName, "eth") 113 if err != nil { 114 return err 115 } 116 } 117 118 d.peerAdd(nid, eid, ep.addr.IP, ep.addr.Mask, ep.mac, net.ParseIP(d.advertiseAddress), false, false, true) 119 120 if err = d.checkEncryption(nid, nil, n.vxlanID(s), true, true); err != nil { 121 logrus.Warn(err) 122 } 123 124 buf, err := proto.Marshal(&PeerRecord{ 125 EndpointIP: ep.addr.String(), 126 EndpointMAC: ep.mac.String(), 127 TunnelEndpointIP: d.advertiseAddress, 128 }) 129 if err != nil { 130 return err 131 } 132 133 if err := jinfo.AddTableEntry(ovPeerTable, eid, buf); err != nil { 134 logrus.Errorf("overlay: Failed adding table entry to joininfo: %v", err) 135 } 136 137 d.pushLocalEndpointEvent("join", nid, eid) 138 139 return nil 140 } 141 142 func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) { 143 if tablename != ovPeerTable { 144 logrus.Errorf("DecodeTableEntry: unexpected table name %s", tablename) 145 return "", nil 146 } 147 148 var peer PeerRecord 149 if err := proto.Unmarshal(value, &peer); err != nil { 150 logrus.Errorf("DecodeTableEntry: failed to unmarshal peer record for key %s: %v", key, err) 151 return "", nil 152 } 153 154 return key, map[string]string{ 155 "Host IP": peer.TunnelEndpointIP, 156 } 157 } 158 159 func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) { 160 if tableName != ovPeerTable { 161 logrus.Errorf("Unexpected table notification for table %s received", tableName) 162 return 163 } 164 165 eid := key 166 167 var peer PeerRecord 168 if err := proto.Unmarshal(value, &peer); err != nil { 169 logrus.Errorf("Failed to unmarshal peer record: %v", err) 170 return 171 } 172 173 // Ignore local peers. We already know about them and they 174 // should not be added to vxlan fdb. 175 if peer.TunnelEndpointIP == d.advertiseAddress { 176 return 177 } 178 179 addr, err := types.ParseCIDR(peer.EndpointIP) 180 if err != nil { 181 logrus.Errorf("Invalid peer IP %s received in event notify", peer.EndpointIP) 182 return 183 } 184 185 mac, err := net.ParseMAC(peer.EndpointMAC) 186 if err != nil { 187 logrus.Errorf("Invalid mac %s received in event notify", peer.EndpointMAC) 188 return 189 } 190 191 vtep := net.ParseIP(peer.TunnelEndpointIP) 192 if vtep == nil { 193 logrus.Errorf("Invalid VTEP %s received in event notify", peer.TunnelEndpointIP) 194 return 195 } 196 197 if etype == driverapi.Delete { 198 d.peerDelete(nid, eid, addr.IP, addr.Mask, mac, vtep, false) 199 return 200 } 201 202 d.peerAdd(nid, eid, addr.IP, addr.Mask, mac, vtep, false, false, false) 203 } 204 205 // Leave method is invoked when a Sandbox detaches from an endpoint. 206 func (d *driver) Leave(nid, eid string) error { 207 if err := validateID(nid, eid); err != nil { 208 return err 209 } 210 211 n := d.network(nid) 212 if n == nil { 213 return fmt.Errorf("could not find network with id %s", nid) 214 } 215 216 ep := n.endpoint(eid) 217 218 if ep == nil { 219 return types.InternalMaskableErrorf("could not find endpoint with id %s", eid) 220 } 221 222 if d.notifyCh != nil { 223 d.notifyCh <- ovNotify{ 224 action: "leave", 225 nw: n, 226 ep: ep, 227 } 228 } 229 230 d.peerDelete(nid, eid, ep.addr.IP, ep.addr.Mask, ep.mac, net.ParseIP(d.advertiseAddress), true) 231 232 n.leaveSandbox() 233 234 return nil 235 }