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