interface_linux.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. package osl
  2. import (
  3. "context"
  4. "fmt"
  5. "net"
  6. "syscall"
  7. "time"
  8. "github.com/containerd/log"
  9. "github.com/docker/docker/libnetwork/ns"
  10. "github.com/docker/docker/libnetwork/types"
  11. "github.com/vishvananda/netlink"
  12. "github.com/vishvananda/netns"
  13. )
  14. // newInterface creates a new interface in the given namespace using the
  15. // provided options.
  16. func newInterface(ns *Namespace, srcName, dstPrefix string, options ...IfaceOption) (*Interface, error) {
  17. i := &Interface{
  18. srcName: srcName,
  19. dstName: dstPrefix,
  20. ns: ns,
  21. }
  22. for _, opt := range options {
  23. if opt != nil {
  24. // TODO(thaJeztah): use multi-error instead of returning early.
  25. if err := opt(i); err != nil {
  26. return nil, err
  27. }
  28. }
  29. }
  30. if i.master != "" {
  31. i.dstMaster = ns.findDst(i.master, true)
  32. if i.dstMaster == "" {
  33. return nil, fmt.Errorf("could not find an appropriate master %q for %q", i.master, i.srcName)
  34. }
  35. }
  36. return i, nil
  37. }
  38. // Interface represents the settings and identity of a network device.
  39. // It is used as a return type for Network.Link, and it is common practice
  40. // for the caller to use this information when moving interface SrcName from
  41. // host namespace to DstName in a different net namespace with the appropriate
  42. // network settings.
  43. type Interface struct {
  44. srcName string
  45. dstName string
  46. master string
  47. dstMaster string
  48. mac net.HardwareAddr
  49. address *net.IPNet
  50. addressIPv6 *net.IPNet
  51. llAddrs []*net.IPNet
  52. routes []*net.IPNet
  53. bridge bool
  54. ns *Namespace
  55. }
  56. // SrcName returns the name of the interface in the origin network namespace.
  57. func (i *Interface) SrcName() string {
  58. return i.srcName
  59. }
  60. // DstName returns the name that will be assigned to the interface once
  61. // moved inside a network namespace. When the caller passes in a DstName,
  62. // it is only expected to pass a prefix. The name will be modified with an
  63. // auto-generated suffix.
  64. func (i *Interface) DstName() string {
  65. return i.dstName
  66. }
  67. func (i *Interface) DstMaster() string {
  68. return i.dstMaster
  69. }
  70. // Bridge returns true if the interface is a bridge.
  71. func (i *Interface) Bridge() bool {
  72. return i.bridge
  73. }
  74. func (i *Interface) MacAddress() net.HardwareAddr {
  75. return types.GetMacCopy(i.mac)
  76. }
  77. // Address returns the IPv4 address for the interface.
  78. func (i *Interface) Address() *net.IPNet {
  79. return types.GetIPNetCopy(i.address)
  80. }
  81. // AddressIPv6 returns the IPv6 address for the interface.
  82. func (i *Interface) AddressIPv6() *net.IPNet {
  83. return types.GetIPNetCopy(i.addressIPv6)
  84. }
  85. // LinkLocalAddresses returns the link-local IP addresses assigned to the
  86. // interface.
  87. func (i *Interface) LinkLocalAddresses() []*net.IPNet {
  88. return i.llAddrs
  89. }
  90. // Routes returns IP routes for the interface.
  91. func (i *Interface) Routes() []*net.IPNet {
  92. routes := make([]*net.IPNet, len(i.routes))
  93. for index, route := range i.routes {
  94. routes[index] = types.GetIPNetCopy(route)
  95. }
  96. return routes
  97. }
  98. // Remove an interface from the sandbox by renaming to original name
  99. // and moving it out of the sandbox.
  100. func (i *Interface) Remove() error {
  101. nameSpace := i.ns
  102. return nameSpace.RemoveInterface(i)
  103. }
  104. // Statistics returns the sandbox's side veth interface statistics.
  105. func (i *Interface) Statistics() (*types.InterfaceStatistics, error) {
  106. l, err := i.ns.nlHandle.LinkByName(i.DstName())
  107. if err != nil {
  108. return nil, fmt.Errorf("failed to retrieve the statistics for %s in netns %s: %v", i.DstName(), i.ns.path, err)
  109. }
  110. stats := l.Attrs().Statistics
  111. if stats == nil {
  112. return nil, fmt.Errorf("no statistics were returned")
  113. }
  114. return &types.InterfaceStatistics{
  115. RxBytes: stats.RxBytes,
  116. TxBytes: stats.TxBytes,
  117. RxPackets: stats.RxPackets,
  118. TxPackets: stats.TxPackets,
  119. RxDropped: stats.RxDropped,
  120. TxDropped: stats.TxDropped,
  121. }, nil
  122. }
  123. func (n *Namespace) findDst(srcName string, isBridge bool) string {
  124. n.mu.Lock()
  125. defer n.mu.Unlock()
  126. for _, i := range n.iFaces {
  127. // The master should match the srcname of the interface and the
  128. // master interface should be of type bridge, if searching for a bridge type
  129. if i.SrcName() == srcName && (!isBridge || i.Bridge()) {
  130. return i.DstName()
  131. }
  132. }
  133. return ""
  134. }
  135. // AddInterface adds an existing Interface to the sandbox. The operation will rename
  136. // from the Interface SrcName to DstName as it moves, and reconfigure the
  137. // interface according to the specified settings. The caller is expected
  138. // to only provide a prefix for DstName. The AddInterface api will auto-generate
  139. // an appropriate suffix for the DstName to disambiguate.
  140. func (n *Namespace) AddInterface(srcName, dstPrefix string, options ...IfaceOption) error {
  141. i, err := newInterface(n, srcName, dstPrefix, options...)
  142. if err != nil {
  143. return err
  144. }
  145. n.mu.Lock()
  146. if n.isDefault {
  147. i.dstName = i.srcName
  148. } else {
  149. i.dstName = fmt.Sprintf("%s%d", dstPrefix, n.nextIfIndex[dstPrefix])
  150. n.nextIfIndex[dstPrefix]++
  151. }
  152. path := n.path
  153. isDefault := n.isDefault
  154. nlh := n.nlHandle
  155. nlhHost := ns.NlHandle()
  156. n.mu.Unlock()
  157. // If it is a bridge interface we have to create the bridge inside
  158. // the namespace so don't try to lookup the interface using srcName
  159. if i.bridge {
  160. if err := nlh.LinkAdd(&netlink.Bridge{
  161. LinkAttrs: netlink.LinkAttrs{
  162. Name: i.srcName,
  163. },
  164. }); err != nil {
  165. return fmt.Errorf("failed to create bridge %q: %v", i.srcName, err)
  166. }
  167. } else {
  168. // Find the network interface identified by the SrcName attribute.
  169. iface, err := nlhHost.LinkByName(i.srcName)
  170. if err != nil {
  171. return fmt.Errorf("failed to get link by name %q: %v", i.srcName, err)
  172. }
  173. // Move the network interface to the destination
  174. // namespace only if the namespace is not a default
  175. // type
  176. if !isDefault {
  177. newNs, err := netns.GetFromPath(path)
  178. if err != nil {
  179. return fmt.Errorf("failed get network namespace %q: %v", path, err)
  180. }
  181. defer newNs.Close()
  182. if err := nlhHost.LinkSetNsFd(iface, int(newNs)); err != nil {
  183. return fmt.Errorf("failed to set namespace on link %q: %v", i.srcName, err)
  184. }
  185. }
  186. }
  187. // Find the network interface identified by the SrcName attribute.
  188. iface, err := nlh.LinkByName(i.srcName)
  189. if err != nil {
  190. return fmt.Errorf("failed to get link by name %q: %v", i.srcName, err)
  191. }
  192. // Down the interface before configuring
  193. if err := nlh.LinkSetDown(iface); err != nil {
  194. return fmt.Errorf("failed to set link down: %v", err)
  195. }
  196. // Configure the interface now this is moved in the proper namespace.
  197. if err := configureInterface(nlh, iface, i); err != nil {
  198. // If configuring the device fails move it back to the host namespace
  199. // and change the name back to the source name. This allows the caller
  200. // to properly cleanup the interface. Its important especially for
  201. // interfaces with global attributes, ex: vni id for vxlan interfaces.
  202. if nerr := nlh.LinkSetName(iface, i.SrcName()); nerr != nil {
  203. log.G(context.TODO()).Errorf("renaming interface (%s->%s) failed, %v after config error %v", i.DstName(), i.SrcName(), nerr, err)
  204. }
  205. if nerr := nlh.LinkSetNsFd(iface, ns.ParseHandlerInt()); nerr != nil {
  206. log.G(context.TODO()).Errorf("moving interface %s to host ns failed, %v, after config error %v", i.SrcName(), nerr, err)
  207. }
  208. return err
  209. }
  210. // Up the interface.
  211. cnt := 0
  212. for err = nlh.LinkSetUp(iface); err != nil && cnt < 3; cnt++ {
  213. log.G(context.TODO()).Debugf("retrying link setup because of: %v", err)
  214. time.Sleep(10 * time.Millisecond)
  215. err = nlh.LinkSetUp(iface)
  216. }
  217. if err != nil {
  218. return fmt.Errorf("failed to set link up: %v", err)
  219. }
  220. // Set the routes on the interface. This can only be done when the interface is up.
  221. if err := setInterfaceRoutes(nlh, iface, i); err != nil {
  222. return fmt.Errorf("error setting interface %q routes to %q: %v", iface.Attrs().Name, i.Routes(), err)
  223. }
  224. n.mu.Lock()
  225. n.iFaces = append(n.iFaces, i)
  226. n.mu.Unlock()
  227. n.checkLoV6()
  228. return nil
  229. }
  230. // RemoveInterface removes an interface from the namespace by renaming to
  231. // original name and moving it out of the sandbox.
  232. func (n *Namespace) RemoveInterface(i *Interface) error {
  233. n.mu.Lock()
  234. isDefault := n.isDefault
  235. nlh := n.nlHandle
  236. n.mu.Unlock()
  237. // Find the network interface identified by the DstName attribute.
  238. iface, err := nlh.LinkByName(i.DstName())
  239. if err != nil {
  240. return err
  241. }
  242. // Down the interface before configuring
  243. if err := nlh.LinkSetDown(iface); err != nil {
  244. return err
  245. }
  246. // TODO(aker): Why are we doing this? This would fail if the initial interface set up failed before the "dest interface" was moved into its own namespace; see https://github.com/moby/moby/pull/46315/commits/108595c2fe852a5264b78e96f9e63cda284990a6#r1331253578
  247. err = nlh.LinkSetName(iface, i.SrcName())
  248. if err != nil {
  249. log.G(context.TODO()).Debugf("LinkSetName failed for interface %s: %v", i.SrcName(), err)
  250. return err
  251. }
  252. // if it is a bridge just delete it.
  253. if i.Bridge() {
  254. if err := nlh.LinkDel(iface); err != nil {
  255. return fmt.Errorf("failed deleting bridge %q: %v", i.SrcName(), err)
  256. }
  257. } else if !isDefault {
  258. // Move the network interface to caller namespace.
  259. // TODO(aker): What's this really doing? There are no calls to LinkDel in this package: is this code really used? (Interface.Remove() has 3 callers); see https://github.com/moby/moby/pull/46315/commits/108595c2fe852a5264b78e96f9e63cda284990a6#r1331265335
  260. if err := nlh.LinkSetNsFd(iface, ns.ParseHandlerInt()); err != nil {
  261. log.G(context.TODO()).Debugf("LinkSetNsFd failed for interface %s: %v", i.SrcName(), err)
  262. return err
  263. }
  264. }
  265. n.mu.Lock()
  266. for index, intf := range i.ns.iFaces {
  267. if intf == i {
  268. i.ns.iFaces = append(i.ns.iFaces[:index], i.ns.iFaces[index+1:]...)
  269. break
  270. }
  271. }
  272. n.mu.Unlock()
  273. // TODO(aker): This function will disable IPv6 on lo interface if the removed interface was the last one offering IPv6 connectivity. That's a weird behavior, and shouldn't be hiding this deep down in this function.
  274. n.checkLoV6()
  275. return nil
  276. }
  277. func configureInterface(nlh *netlink.Handle, iface netlink.Link, i *Interface) error {
  278. ifaceName := iface.Attrs().Name
  279. ifaceConfigurators := []struct {
  280. Fn func(*netlink.Handle, netlink.Link, *Interface) error
  281. ErrMessage string
  282. }{
  283. {setInterfaceName, fmt.Sprintf("error renaming interface %q to %q", ifaceName, i.DstName())},
  284. {setInterfaceMAC, fmt.Sprintf("error setting interface %q MAC to %q", ifaceName, i.MacAddress())},
  285. {setInterfaceIP, fmt.Sprintf("error setting interface %q IP to %v", ifaceName, i.Address())},
  286. {setInterfaceIPv6, fmt.Sprintf("error setting interface %q IPv6 to %v", ifaceName, i.AddressIPv6())},
  287. {setInterfaceMaster, fmt.Sprintf("error setting interface %q master to %q", ifaceName, i.DstMaster())},
  288. {setInterfaceLinkLocalIPs, fmt.Sprintf("error setting interface %q link local IPs to %v", ifaceName, i.LinkLocalAddresses())},
  289. }
  290. for _, config := range ifaceConfigurators {
  291. if err := config.Fn(nlh, iface, i); err != nil {
  292. return fmt.Errorf("%s: %v", config.ErrMessage, err)
  293. }
  294. }
  295. return nil
  296. }
  297. func setInterfaceMaster(nlh *netlink.Handle, iface netlink.Link, i *Interface) error {
  298. if i.DstMaster() == "" {
  299. return nil
  300. }
  301. return nlh.LinkSetMaster(iface, &netlink.Bridge{
  302. LinkAttrs: netlink.LinkAttrs{Name: i.DstMaster()},
  303. })
  304. }
  305. func setInterfaceMAC(nlh *netlink.Handle, iface netlink.Link, i *Interface) error {
  306. if i.MacAddress() == nil {
  307. return nil
  308. }
  309. return nlh.LinkSetHardwareAddr(iface, i.MacAddress())
  310. }
  311. func setInterfaceIP(nlh *netlink.Handle, iface netlink.Link, i *Interface) error {
  312. if i.Address() == nil {
  313. return nil
  314. }
  315. if err := checkRouteConflict(nlh, i.Address(), netlink.FAMILY_V4); err != nil {
  316. return err
  317. }
  318. ipAddr := &netlink.Addr{IPNet: i.Address(), Label: ""}
  319. return nlh.AddrAdd(iface, ipAddr)
  320. }
  321. func setInterfaceIPv6(nlh *netlink.Handle, iface netlink.Link, i *Interface) error {
  322. if i.AddressIPv6() == nil {
  323. return nil
  324. }
  325. if err := checkRouteConflict(nlh, i.AddressIPv6(), netlink.FAMILY_V6); err != nil {
  326. return err
  327. }
  328. if err := setIPv6(i.ns.path, i.DstName(), true); err != nil {
  329. return fmt.Errorf("failed to enable ipv6: %v", err)
  330. }
  331. ipAddr := &netlink.Addr{IPNet: i.AddressIPv6(), Label: "", Flags: syscall.IFA_F_NODAD}
  332. return nlh.AddrAdd(iface, ipAddr)
  333. }
  334. func setInterfaceLinkLocalIPs(nlh *netlink.Handle, iface netlink.Link, i *Interface) error {
  335. for _, llIP := range i.LinkLocalAddresses() {
  336. ipAddr := &netlink.Addr{IPNet: llIP}
  337. if err := nlh.AddrAdd(iface, ipAddr); err != nil {
  338. return err
  339. }
  340. }
  341. return nil
  342. }
  343. func setInterfaceName(nlh *netlink.Handle, iface netlink.Link, i *Interface) error {
  344. return nlh.LinkSetName(iface, i.DstName())
  345. }
  346. func setInterfaceRoutes(nlh *netlink.Handle, iface netlink.Link, i *Interface) error {
  347. for _, route := range i.Routes() {
  348. err := nlh.RouteAdd(&netlink.Route{
  349. Scope: netlink.SCOPE_LINK,
  350. LinkIndex: iface.Attrs().Index,
  351. Dst: route,
  352. })
  353. if err != nil {
  354. return err
  355. }
  356. }
  357. return nil
  358. }
  359. func checkRouteConflict(nlh *netlink.Handle, address *net.IPNet, family int) error {
  360. routes, err := nlh.RouteList(nil, family)
  361. if err != nil {
  362. return err
  363. }
  364. for _, route := range routes {
  365. if route.Dst != nil {
  366. if route.Dst.Contains(address.IP) || address.Contains(route.Dst.IP) {
  367. return fmt.Errorf("cannot program address %v in sandbox interface because it conflicts with existing route %s",
  368. address, route)
  369. }
  370. }
  371. }
  372. return nil
  373. }