interface_linux.go 11 KB

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