interface_linux.go 9.6 KB

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