interface_linux.go 12 KB

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