github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/libnetwork/drivers/ipvlan/ipvlan_joinleave.go (about) 1 //go:build linux 2 // +build linux 3 4 package ipvlan 5 6 import ( 7 "fmt" 8 "net" 9 10 "github.com/docker/docker/libnetwork/driverapi" 11 "github.com/docker/docker/libnetwork/netutils" 12 "github.com/docker/docker/libnetwork/ns" 13 "github.com/docker/docker/libnetwork/osl" 14 "github.com/docker/docker/libnetwork/types" 15 "github.com/sirupsen/logrus" 16 ) 17 18 type staticRoute struct { 19 Destination *net.IPNet 20 RouteType int 21 NextHop net.IP 22 } 23 24 const ( 25 defaultV4RouteCidr = "0.0.0.0/0" 26 defaultV6RouteCidr = "::/0" 27 ) 28 29 // Join method is invoked when a Sandbox is attached to an endpoint. 30 func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error { 31 defer osl.InitOSContext()() 32 n, err := d.getNetwork(nid) 33 if err != nil { 34 return err 35 } 36 endpoint := n.endpoint(eid) 37 if endpoint == nil { 38 return fmt.Errorf("could not find endpoint with id %s", eid) 39 } 40 // generate a name for the iface that will be renamed to eth0 in the sbox 41 containerIfName, err := netutils.GenerateIfaceName(ns.NlHandle(), vethPrefix, vethLen) 42 if err != nil { 43 return fmt.Errorf("error generating an interface name: %v", err) 44 } 45 // create the netlink ipvlan interface 46 vethName, err := createIPVlan(containerIfName, n.config.Parent, n.config.IpvlanMode, n.config.IpvlanFlag) 47 if err != nil { 48 return err 49 } 50 // bind the generated iface name to the endpoint 51 endpoint.srcName = vethName 52 ep := n.endpoint(eid) 53 if ep == nil { 54 return fmt.Errorf("could not find endpoint with id %s", eid) 55 } 56 if !n.config.Internal { 57 switch n.config.IpvlanMode { 58 case modeL3, modeL3S: 59 // disable gateway services to add a default gw using dev eth0 only 60 jinfo.DisableGatewayService() 61 defaultRoute, err := ifaceGateway(defaultV4RouteCidr) 62 if err != nil { 63 return err 64 } 65 if err := jinfo.AddStaticRoute(defaultRoute.Destination, defaultRoute.RouteType, defaultRoute.NextHop); err != nil { 66 return fmt.Errorf("failed to set an ipvlan l3/l3s mode ipv4 default gateway: %v", err) 67 } 68 logrus.Debugf("Ipvlan Endpoint Joined with IPv4_Addr: %s, Ipvlan_Mode: %s, Parent: %s", 69 ep.addr.IP.String(), n.config.IpvlanMode, n.config.Parent) 70 // If the endpoint has a v6 address, set a v6 default route 71 if ep.addrv6 != nil { 72 default6Route, err := ifaceGateway(defaultV6RouteCidr) 73 if err != nil { 74 return err 75 } 76 if err = jinfo.AddStaticRoute(default6Route.Destination, default6Route.RouteType, default6Route.NextHop); err != nil { 77 return fmt.Errorf("failed to set an ipvlan l3/l3s mode ipv6 default gateway: %v", err) 78 } 79 logrus.Debugf("Ipvlan Endpoint Joined with IPv6_Addr: %s, Ipvlan_Mode: %s, Parent: %s", 80 ep.addrv6.IP.String(), n.config.IpvlanMode, n.config.Parent) 81 } 82 case modeL2: 83 // parse and correlate the endpoint v4 address with the available v4 subnets 84 if len(n.config.Ipv4Subnets) > 0 { 85 s := n.getSubnetforIPv4(ep.addr) 86 if s == nil { 87 return fmt.Errorf("could not find a valid ipv4 subnet for endpoint %s", eid) 88 } 89 v4gw, _, err := net.ParseCIDR(s.GwIP) 90 if err != nil { 91 return fmt.Errorf("gateway %s is not a valid ipv4 address: %v", s.GwIP, err) 92 } 93 err = jinfo.SetGateway(v4gw) 94 if err != nil { 95 return err 96 } 97 logrus.Debugf("Ipvlan Endpoint Joined with IPv4_Addr: %s, Gateway: %s, Ipvlan_Mode: %s, Parent: %s", 98 ep.addr.IP.String(), v4gw.String(), n.config.IpvlanMode, n.config.Parent) 99 } 100 // parse and correlate the endpoint v6 address with the available v6 subnets 101 if len(n.config.Ipv6Subnets) > 0 { 102 s := n.getSubnetforIPv6(ep.addrv6) 103 if s == nil { 104 return fmt.Errorf("could not find a valid ipv6 subnet for endpoint %s", eid) 105 } 106 v6gw, _, err := net.ParseCIDR(s.GwIP) 107 if err != nil { 108 return fmt.Errorf("gateway %s is not a valid ipv6 address: %v", s.GwIP, err) 109 } 110 err = jinfo.SetGatewayIPv6(v6gw) 111 if err != nil { 112 return err 113 } 114 logrus.Debugf("Ipvlan Endpoint Joined with IPv6_Addr: %s, Gateway: %s, Ipvlan_Mode: %s, Parent: %s", 115 ep.addrv6.IP.String(), v6gw.String(), n.config.IpvlanMode, n.config.Parent) 116 } 117 } 118 } else { 119 if len(n.config.Ipv4Subnets) > 0 { 120 logrus.Debugf("Ipvlan Endpoint Joined with IPv4_Addr: %s, IpVlan_Mode: %s, Parent: %s", 121 ep.addr.IP.String(), n.config.IpvlanMode, n.config.Parent) 122 } 123 if len(n.config.Ipv6Subnets) > 0 { 124 logrus.Debugf("Ipvlan Endpoint Joined with IPv6_Addr: %s IpVlan_Mode: %s, Parent: %s", 125 ep.addrv6.IP.String(), n.config.IpvlanMode, n.config.Parent) 126 } 127 } 128 iNames := jinfo.InterfaceName() 129 err = iNames.SetNames(vethName, containerVethPrefix) 130 if err != nil { 131 return err 132 } 133 if err = d.storeUpdate(ep); err != nil { 134 return fmt.Errorf("failed to save ipvlan endpoint %.7s to store: %v", ep.id, err) 135 } 136 137 return nil 138 } 139 140 // Leave method is invoked when a Sandbox detaches from an endpoint. 141 func (d *driver) Leave(nid, eid string) error { 142 defer osl.InitOSContext()() 143 network, err := d.getNetwork(nid) 144 if err != nil { 145 return err 146 } 147 endpoint, err := network.getEndpoint(eid) 148 if err != nil { 149 return err 150 } 151 if endpoint == nil { 152 return fmt.Errorf("could not find endpoint with id %s", eid) 153 } 154 155 return nil 156 } 157 158 // ifaceGateway returns a static route for either v4/v6 to be set to the container eth0 159 func ifaceGateway(dfNet string) (*staticRoute, error) { 160 nh, dst, err := net.ParseCIDR(dfNet) 161 if err != nil { 162 return nil, fmt.Errorf("unable to parse default route %v", err) 163 } 164 defaultRoute := &staticRoute{ 165 Destination: dst, 166 RouteType: types.CONNECTED, 167 NextHop: nh, 168 } 169 170 return defaultRoute, nil 171 } 172 173 // getSubnetforIPv4 returns the ipv4 subnet to which the given IP belongs 174 func (n *network) getSubnetforIPv4(ip *net.IPNet) *ipv4Subnet { 175 for _, s := range n.config.Ipv4Subnets { 176 _, snet, err := net.ParseCIDR(s.SubnetIP) 177 if err != nil { 178 return nil 179 } 180 // first check if the mask lengths are the same 181 i, _ := snet.Mask.Size() 182 j, _ := ip.Mask.Size() 183 if i != j { 184 continue 185 } 186 if snet.Contains(ip.IP) { 187 return s 188 } 189 } 190 191 return nil 192 } 193 194 // getSubnetforIPv6 returns the ipv6 subnet to which the given IP belongs 195 func (n *network) getSubnetforIPv6(ip *net.IPNet) *ipv6Subnet { 196 for _, s := range n.config.Ipv6Subnets { 197 _, snet, err := net.ParseCIDR(s.SubnetIP) 198 if err != nil { 199 return nil 200 } 201 // first check if the mask lengths are the same 202 i, _ := snet.Mask.Size() 203 j, _ := ip.Mask.Size() 204 if i != j { 205 continue 206 } 207 if snet.Contains(ip.IP) { 208 return s 209 } 210 } 211 212 return nil 213 }