ipvlan_joinleave.go 5.8 KB

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