handle_linux.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. package netlink
  2. import (
  3. "fmt"
  4. "time"
  5. "github.com/vishvananda/netlink/nl"
  6. "github.com/vishvananda/netns"
  7. "golang.org/x/sys/unix"
  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 := unix.NsecToTimeval(to.Nanoseconds())
  40. for _, sh := range h.sockets {
  41. if err := sh.Socket.SetSendTimeout(&tv); err != nil {
  42. return err
  43. }
  44. if err := sh.Socket.SetReceiveTimeout(&tv); err != nil {
  45. return err
  46. }
  47. }
  48. return nil
  49. }
  50. // SetSocketReceiveBufferSize sets the receive buffer size for each
  51. // socket in the netlink handle. The maximum value is capped by
  52. // /proc/sys/net/core/rmem_max.
  53. func (h *Handle) SetSocketReceiveBufferSize(size int, force bool) error {
  54. opt := unix.SO_RCVBUF
  55. if force {
  56. opt = unix.SO_RCVBUFFORCE
  57. }
  58. for _, sh := range h.sockets {
  59. fd := sh.Socket.GetFd()
  60. err := unix.SetsockoptInt(fd, unix.SOL_SOCKET, opt, size)
  61. if err != nil {
  62. return err
  63. }
  64. }
  65. return nil
  66. }
  67. // GetSocketReceiveBufferSize gets the receiver buffer size for each
  68. // socket in the netlink handle. The retrieved value should be the
  69. // double to the one set for SetSocketReceiveBufferSize.
  70. func (h *Handle) GetSocketReceiveBufferSize() ([]int, error) {
  71. results := make([]int, len(h.sockets))
  72. i := 0
  73. for _, sh := range h.sockets {
  74. fd := sh.Socket.GetFd()
  75. size, err := unix.GetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_RCVBUF)
  76. if err != nil {
  77. return nil, err
  78. }
  79. results[i] = size
  80. i++
  81. }
  82. return results, nil
  83. }
  84. // NewHandle returns a netlink handle on the network namespace
  85. // specified by ns. If ns=netns.None(), current network namespace
  86. // will be assumed
  87. func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) {
  88. return newHandle(ns, netns.None(), nlFamilies...)
  89. }
  90. // NewHandleAtFrom works as NewHandle but allows client to specify the
  91. // new and the origin netns Handle.
  92. func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) {
  93. return newHandle(newNs, curNs)
  94. }
  95. func newHandle(newNs, curNs netns.NsHandle, nlFamilies ...int) (*Handle, error) {
  96. h := &Handle{sockets: map[int]*nl.SocketHandle{}}
  97. fams := nl.SupportedNlFamilies
  98. if len(nlFamilies) != 0 {
  99. fams = nlFamilies
  100. }
  101. for _, f := range fams {
  102. s, err := nl.GetNetlinkSocketAt(newNs, curNs, f)
  103. if err != nil {
  104. return nil, err
  105. }
  106. h.sockets[f] = &nl.SocketHandle{Socket: s}
  107. }
  108. return h, nil
  109. }
  110. // Delete releases the resources allocated to this handle
  111. func (h *Handle) Delete() {
  112. for _, sh := range h.sockets {
  113. sh.Close()
  114. }
  115. h.sockets = nil
  116. }
  117. func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest {
  118. // Do this so that package API still use nl package variable nextSeqNr
  119. if h.sockets == nil {
  120. return nl.NewNetlinkRequest(proto, flags)
  121. }
  122. return &nl.NetlinkRequest{
  123. NlMsghdr: unix.NlMsghdr{
  124. Len: uint32(unix.SizeofNlMsghdr),
  125. Type: uint16(proto),
  126. Flags: unix.NLM_F_REQUEST | uint16(flags),
  127. },
  128. Sockets: h.sockets,
  129. }
  130. }