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