interface_linux.go 11 KB

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