interface_linux.go 9.1 KB

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