interface_linux.go 9.2 KB

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