handle_linux.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package netlink
  2. import (
  3. "fmt"
  4. "syscall"
  5. "time"
  6. "github.com/vishvananda/netlink/nl"
  7. "github.com/vishvananda/netns"
  8. )
  9. // Empty handle used by the netlink package methods
  10. var pkgHandle = &Handle{}
  11. // Handle is an handle for the netlink requests on a
  12. // specific network namespace. All the requests on the
  13. // same netlink family share the same netlink socket,
  14. // which gets released when the handle is deleted.
  15. type Handle struct {
  16. sockets map[int]*nl.SocketHandle
  17. lookupByDump bool
  18. }
  19. // SupportsNetlinkFamily reports whether the passed netlink family is supported by this Handle
  20. func (h *Handle) SupportsNetlinkFamily(nlFamily int) bool {
  21. _, ok := h.sockets[nlFamily]
  22. return ok
  23. }
  24. // NewHandle returns a netlink handle on the current network namespace.
  25. // Caller may specify the netlink families the handle should support.
  26. // If no families are specified, all the families the netlink package
  27. // supports will be automatically added.
  28. func NewHandle(nlFamilies ...int) (*Handle, error) {
  29. return newHandle(netns.None(), netns.None(), nlFamilies...)
  30. }
  31. // SetSocketTimeout sets the send and receive timeout for each socket in the
  32. // netlink handle. Although the socket timeout has granularity of one
  33. // microsecond, the effective granularity is floored by the kernel timer tick,
  34. // which default value is four milliseconds.
  35. func (h *Handle) SetSocketTimeout(to time.Duration) error {
  36. if to < time.Microsecond {
  37. return fmt.Errorf("invalid timeout, minimul value is %s", time.Microsecond)
  38. }
  39. tv := syscall.NsecToTimeval(to.Nanoseconds())
  40. for _, sh := range h.sockets {
  41. fd := sh.Socket.GetFd()
  42. err := syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv)
  43. if err != nil {
  44. return err
  45. }
  46. err = syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, &tv)
  47. if err != nil {
  48. return err
  49. }
  50. }
  51. return nil
  52. }
  53. // NewHandle returns a netlink handle on the network namespace
  54. // specified by ns. If ns=netns.None(), current network namespace
  55. // will be assumed
  56. func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) {
  57. return newHandle(ns, netns.None(), nlFamilies...)
  58. }
  59. // NewHandleAtFrom works as NewHandle but allows client to specify the
  60. // new and the origin netns Handle.
  61. func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) {
  62. return newHandle(newNs, curNs)
  63. }
  64. func newHandle(newNs, curNs netns.NsHandle, nlFamilies ...int) (*Handle, error) {
  65. h := &Handle{sockets: map[int]*nl.SocketHandle{}}
  66. fams := nl.SupportedNlFamilies
  67. if len(nlFamilies) != 0 {
  68. fams = nlFamilies
  69. }
  70. for _, f := range fams {
  71. s, err := nl.GetNetlinkSocketAt(newNs, curNs, f)
  72. if err != nil {
  73. return nil, err
  74. }
  75. h.sockets[f] = &nl.SocketHandle{Socket: s}
  76. }
  77. return h, nil
  78. }
  79. // Delete releases the resources allocated to this handle
  80. func (h *Handle) Delete() {
  81. for _, sh := range h.sockets {
  82. sh.Close()
  83. }
  84. h.sockets = nil
  85. }
  86. func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest {
  87. // Do this so that package API still use nl package variable nextSeqNr
  88. if h.sockets == nil {
  89. return nl.NewNetlinkRequest(proto, flags)
  90. }
  91. return &nl.NetlinkRequest{
  92. NlMsghdr: syscall.NlMsghdr{
  93. Len: uint32(syscall.SizeofNlMsghdr),
  94. Type: uint16(proto),
  95. Flags: syscall.NLM_F_REQUEST | uint16(flags),
  96. },
  97. Sockets: h.sockets,
  98. }
  99. }