interface_linux.go 12 KB

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