udp_linux.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. //go:build !android && !e2e_testing
  2. // +build !android,!e2e_testing
  3. package udp
  4. import (
  5. "context"
  6. "encoding/binary"
  7. "fmt"
  8. "net"
  9. "net/netip"
  10. "syscall"
  11. "unsafe"
  12. "github.com/rcrowley/go-metrics"
  13. "github.com/sirupsen/logrus"
  14. "github.com/slackhq/nebula/config"
  15. "golang.org/x/sys/unix"
  16. )
  17. type StdConn struct {
  18. udpConn *net.UDPConn
  19. rawConn syscall.RawConn
  20. isV4 bool
  21. l *logrus.Logger
  22. batch int
  23. // sendmmsg scratch. Each queue has its own StdConn, so no locking is
  24. // needed. Sized to MaxWriteBatch at construction; WriteBatch chunks
  25. // larger inputs.
  26. writeMsgs []rawMessage
  27. writeIovs []iovec
  28. writeNames [][]byte
  29. }
  30. func setReusePort(network, address string, c syscall.RawConn) error {
  31. var opErr error
  32. err := c.Control(func(fd uintptr) {
  33. opErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1)
  34. //CloseOnExec already set by the runtime
  35. })
  36. if err != nil {
  37. return err
  38. }
  39. return opErr
  40. }
  41. func NewListener(l *logrus.Logger, ip netip.Addr, port int, multi bool, batch int) (Conn, error) {
  42. listen := netip.AddrPortFrom(ip, uint16(port))
  43. lc := net.ListenConfig{}
  44. if multi {
  45. lc.Control = setReusePort
  46. }
  47. //this context is only used during the bind operation, you can't cancel it to kill the socket
  48. pc, err := lc.ListenPacket(context.Background(), "udp", listen.String())
  49. if err != nil {
  50. return nil, fmt.Errorf("unable to open socket: %s", err)
  51. }
  52. udpConn := pc.(*net.UDPConn)
  53. rawConn, err := udpConn.SyscallConn()
  54. if err != nil {
  55. _ = udpConn.Close()
  56. return nil, err
  57. }
  58. //gotta find out if we got an AF_INET6 socket or not:
  59. out := &StdConn{
  60. udpConn: udpConn,
  61. rawConn: rawConn,
  62. l: l,
  63. batch: batch,
  64. }
  65. af, err := out.getSockOptInt(unix.SO_DOMAIN)
  66. if err != nil {
  67. _ = out.Close()
  68. return nil, err
  69. }
  70. out.isV4 = af == unix.AF_INET
  71. out.prepareWriteMessages(MaxWriteBatch)
  72. return out, nil
  73. }
  74. func (u *StdConn) SupportsMultipleReaders() bool {
  75. return true
  76. }
  77. func (u *StdConn) Rebind() error {
  78. return nil
  79. }
  80. func (u *StdConn) getSockOptInt(opt int) (int, error) {
  81. if u.rawConn == nil {
  82. return 0, fmt.Errorf("no UDP connection")
  83. }
  84. var out int
  85. var opErr error
  86. err := u.rawConn.Control(func(fd uintptr) {
  87. out, opErr = unix.GetsockoptInt(int(fd), unix.SOL_SOCKET, opt)
  88. })
  89. if err != nil {
  90. return 0, err
  91. }
  92. return out, opErr
  93. }
  94. func (u *StdConn) setSockOptInt(opt int, n int) error {
  95. if u.rawConn == nil {
  96. return fmt.Errorf("no UDP connection")
  97. }
  98. var opErr error
  99. err := u.rawConn.Control(func(fd uintptr) {
  100. opErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, opt, n)
  101. })
  102. if err != nil {
  103. return err
  104. }
  105. return opErr
  106. }
  107. func (u *StdConn) SetRecvBuffer(n int) error {
  108. return u.setSockOptInt(unix.SO_RCVBUFFORCE, n)
  109. }
  110. func (u *StdConn) SetSendBuffer(n int) error {
  111. return u.setSockOptInt(unix.SO_SNDBUFFORCE, n)
  112. }
  113. func (u *StdConn) SetSoMark(mark int) error {
  114. return u.setSockOptInt(unix.SO_MARK, mark)
  115. }
  116. func (u *StdConn) GetRecvBuffer() (int, error) {
  117. return u.getSockOptInt(unix.SO_RCVBUF)
  118. }
  119. func (u *StdConn) GetSendBuffer() (int, error) {
  120. return u.getSockOptInt(unix.SO_SNDBUF)
  121. }
  122. func (u *StdConn) GetSoMark() (int, error) {
  123. return u.getSockOptInt(unix.SO_MARK)
  124. }
  125. func (u *StdConn) LocalAddr() (netip.AddrPort, error) {
  126. a := u.udpConn.LocalAddr()
  127. switch v := a.(type) {
  128. case *net.UDPAddr:
  129. addr, ok := netip.AddrFromSlice(v.IP)
  130. if !ok {
  131. return netip.AddrPort{}, fmt.Errorf("LocalAddr returned invalid IP address: %s", v.IP)
  132. }
  133. return netip.AddrPortFrom(addr, uint16(v.Port)), nil
  134. default:
  135. return netip.AddrPort{}, fmt.Errorf("LocalAddr returned: %#v", a)
  136. }
  137. }
  138. func recvmmsg(fd uintptr, msgs []rawMessage) (int, bool, error) {
  139. var errno syscall.Errno
  140. n, _, errno := unix.Syscall6(
  141. unix.SYS_RECVMMSG,
  142. fd,
  143. uintptr(unsafe.Pointer(&msgs[0])),
  144. uintptr(len(msgs)),
  145. unix.MSG_WAITFORONE,
  146. 0,
  147. 0,
  148. )
  149. if errno == syscall.EAGAIN || errno == syscall.EWOULDBLOCK {
  150. // No data available, block for I/O and try again.
  151. return int(n), false, nil
  152. }
  153. if errno != 0 {
  154. return int(n), true, &net.OpError{Op: "recvmmsg", Err: errno}
  155. }
  156. return int(n), true, nil
  157. }
  158. func (u *StdConn) listenOutSingle(r EncReader) error {
  159. var err error
  160. var n int
  161. var from netip.AddrPort
  162. buffer := make([]byte, MTU)
  163. for {
  164. n, from, err = u.udpConn.ReadFromUDPAddrPort(buffer)
  165. if err != nil {
  166. return err
  167. }
  168. from = netip.AddrPortFrom(from.Addr().Unmap(), from.Port())
  169. r(from, buffer[:n])
  170. }
  171. }
  172. func (u *StdConn) listenOutBatch(r EncReader) error {
  173. var ip netip.Addr
  174. var n int
  175. var operr error
  176. msgs, buffers, names := u.PrepareRawMessages(u.batch)
  177. //reader needs to capture variables from this function, since it's used as a lambda with rawConn.Read
  178. //defining it outside the loop so it gets re-used
  179. reader := func(fd uintptr) (done bool) {
  180. n, done, operr = recvmmsg(fd, msgs)
  181. return done
  182. }
  183. for {
  184. err := u.rawConn.Read(reader)
  185. if err != nil {
  186. return err
  187. }
  188. if operr != nil {
  189. return operr
  190. }
  191. for i := 0; i < n; i++ {
  192. // Its ok to skip the ok check here, the slicing is the only error that can occur and it will panic
  193. if u.isV4 {
  194. ip, _ = netip.AddrFromSlice(names[i][4:8])
  195. } else {
  196. ip, _ = netip.AddrFromSlice(names[i][8:24])
  197. }
  198. r(netip.AddrPortFrom(ip.Unmap(), binary.BigEndian.Uint16(names[i][2:4])), buffers[i][:msgs[i].Len])
  199. }
  200. }
  201. }
  202. func (u *StdConn) ListenOut(r EncReader) error {
  203. if u.batch == 1 {
  204. return u.listenOutSingle(r)
  205. } else {
  206. return u.listenOutBatch(r)
  207. }
  208. }
  209. func (u *StdConn) WriteTo(b []byte, ip netip.AddrPort) error {
  210. _, err := u.udpConn.WriteToUDPAddrPort(b, ip)
  211. return err
  212. }
  213. // WriteBatch sends bufs via sendmmsg(2) using the preallocated scratch on
  214. // StdConn. Chunks larger than the scratch are processed in multiple syscalls.
  215. // If sendmmsg returns a fatal error mid-chunk we fall back to single WriteTo
  216. // calls for the remainder so the caller still gets best-effort delivery.
  217. func (u *StdConn) WriteBatch(bufs [][]byte, addrs []netip.AddrPort) error {
  218. if len(bufs) != len(addrs) {
  219. return fmt.Errorf("WriteBatch: len(bufs)=%d != len(addrs)=%d", len(bufs), len(addrs))
  220. }
  221. i := 0
  222. for i < len(bufs) {
  223. chunk := len(bufs) - i
  224. if chunk > len(u.writeMsgs) {
  225. chunk = len(u.writeMsgs)
  226. }
  227. for k := 0; k < chunk; k++ {
  228. b := bufs[i+k]
  229. if len(b) == 0 {
  230. // sendmmsg with an empty iovec is legal but pointless; fall
  231. // through after filling the slot so Base is still valid.
  232. u.writeIovs[k].Base = nil
  233. setIovLen(&u.writeIovs[k], 0)
  234. } else {
  235. u.writeIovs[k].Base = &b[0]
  236. setIovLen(&u.writeIovs[k], len(b))
  237. }
  238. nlen, err := writeSockaddr(u.writeNames[k], addrs[i+k], u.isV4)
  239. if err != nil {
  240. return err
  241. }
  242. u.writeMsgs[k].Hdr.Namelen = uint32(nlen)
  243. }
  244. sent, serr := u.sendmmsg(chunk)
  245. if serr != nil {
  246. if sent <= 0 {
  247. // nothing went out; fall back to WriteTo for this chunk.
  248. for k := 0; k < chunk; k++ {
  249. if err := u.WriteTo(bufs[i+k], addrs[i+k]); err != nil {
  250. return err
  251. }
  252. }
  253. i += chunk
  254. continue
  255. }
  256. // partial: treat as success for the sent packets and retry the
  257. // remainder on the next outer-loop iteration.
  258. }
  259. if sent == 0 {
  260. return fmt.Errorf("sendmmsg made no progress")
  261. }
  262. i += sent
  263. }
  264. return nil
  265. }
  266. func (u *StdConn) sendmmsg(n int) (int, error) {
  267. var sent int
  268. var sysErr error
  269. err := u.rawConn.Write(func(fd uintptr) (done bool) {
  270. r1, _, errno := unix.Syscall6(
  271. unix.SYS_SENDMMSG,
  272. fd,
  273. uintptr(unsafe.Pointer(&u.writeMsgs[0])),
  274. uintptr(n),
  275. 0,
  276. 0,
  277. 0,
  278. )
  279. if errno == syscall.EAGAIN || errno == syscall.EWOULDBLOCK {
  280. return false
  281. }
  282. sent = int(r1)
  283. if errno != 0 {
  284. sysErr = &net.OpError{Op: "sendmmsg", Err: errno}
  285. }
  286. return true
  287. })
  288. if err != nil {
  289. return sent, err
  290. }
  291. return sent, sysErr
  292. }
  293. // writeSockaddr encodes addr into buf (which must be at least
  294. // SizeofSockaddrInet6 bytes). Returns the number of bytes used. If isV4 is
  295. // true and addr is not a v4 (or v4-in-v6) address, returns an error.
  296. func writeSockaddr(buf []byte, addr netip.AddrPort, isV4 bool) (int, error) {
  297. ap := addr.Addr().Unmap()
  298. if isV4 {
  299. if !ap.Is4() {
  300. return 0, ErrInvalidIPv6RemoteForSocket
  301. }
  302. // struct sockaddr_in: { sa_family_t(2), in_port_t(2, BE), in_addr(4), zero(8) }
  303. // sa_family is host endian.
  304. binary.NativeEndian.PutUint16(buf[0:2], unix.AF_INET)
  305. binary.BigEndian.PutUint16(buf[2:4], addr.Port())
  306. ip4 := ap.As4()
  307. copy(buf[4:8], ip4[:])
  308. for j := 8; j < 16; j++ {
  309. buf[j] = 0
  310. }
  311. return unix.SizeofSockaddrInet4, nil
  312. }
  313. // struct sockaddr_in6: { sa_family_t(2), in_port_t(2, BE), flowinfo(4), in6_addr(16), scope_id(4) }
  314. binary.NativeEndian.PutUint16(buf[0:2], unix.AF_INET6)
  315. binary.BigEndian.PutUint16(buf[2:4], addr.Port())
  316. binary.NativeEndian.PutUint32(buf[4:8], 0)
  317. ip6 := addr.Addr().As16()
  318. copy(buf[8:24], ip6[:])
  319. binary.NativeEndian.PutUint32(buf[24:28], 0)
  320. return unix.SizeofSockaddrInet6, nil
  321. }
  322. func (u *StdConn) ReloadConfig(c *config.C) {
  323. b := c.GetInt("listen.read_buffer", 0)
  324. if b > 0 {
  325. err := u.SetRecvBuffer(b)
  326. if err == nil {
  327. s, err := u.GetRecvBuffer()
  328. if err == nil {
  329. u.l.WithField("size", s).Info("listen.read_buffer was set")
  330. } else {
  331. u.l.WithError(err).Warn("Failed to get listen.read_buffer")
  332. }
  333. } else {
  334. u.l.WithError(err).Error("Failed to set listen.read_buffer")
  335. }
  336. }
  337. b = c.GetInt("listen.write_buffer", 0)
  338. if b > 0 {
  339. err := u.SetSendBuffer(b)
  340. if err == nil {
  341. s, err := u.GetSendBuffer()
  342. if err == nil {
  343. u.l.WithField("size", s).Info("listen.write_buffer was set")
  344. } else {
  345. u.l.WithError(err).Warn("Failed to get listen.write_buffer")
  346. }
  347. } else {
  348. u.l.WithError(err).Error("Failed to set listen.write_buffer")
  349. }
  350. }
  351. b = c.GetInt("listen.so_mark", 0)
  352. s, err := u.GetSoMark()
  353. if b > 0 || (err == nil && s != 0) {
  354. err := u.SetSoMark(b)
  355. if err == nil {
  356. s, err := u.GetSoMark()
  357. if err == nil {
  358. u.l.WithField("mark", s).Info("listen.so_mark was set")
  359. } else {
  360. u.l.WithError(err).Warn("Failed to get listen.so_mark")
  361. }
  362. } else {
  363. u.l.WithError(err).Error("Failed to set listen.so_mark")
  364. }
  365. }
  366. }
  367. func (u *StdConn) getMemInfo(meminfo *[unix.SK_MEMINFO_VARS]uint32) error {
  368. var vallen uint32 = 4 * unix.SK_MEMINFO_VARS
  369. if u.rawConn == nil {
  370. return fmt.Errorf("no UDP connection")
  371. }
  372. var opErr error
  373. err := u.rawConn.Control(func(fd uintptr) {
  374. _, _, syserr := unix.Syscall6(unix.SYS_GETSOCKOPT, fd, uintptr(unix.SOL_SOCKET), uintptr(unix.SO_MEMINFO), uintptr(unsafe.Pointer(meminfo)), uintptr(unsafe.Pointer(&vallen)), 0)
  375. if syserr != 0 {
  376. opErr = syserr
  377. }
  378. })
  379. if err != nil {
  380. return err
  381. }
  382. return opErr
  383. }
  384. func (u *StdConn) Close() error {
  385. if u.udpConn != nil {
  386. return u.udpConn.Close()
  387. }
  388. return nil
  389. }
  390. func NewUDPStatsEmitter(udpConns []Conn) func() {
  391. // Check if our kernel supports SO_MEMINFO before registering the gauges
  392. var udpGauges [][unix.SK_MEMINFO_VARS]metrics.Gauge
  393. var meminfo [unix.SK_MEMINFO_VARS]uint32
  394. if err := udpConns[0].(*StdConn).getMemInfo(&meminfo); err == nil {
  395. udpGauges = make([][unix.SK_MEMINFO_VARS]metrics.Gauge, len(udpConns))
  396. for i := range udpConns {
  397. udpGauges[i] = [unix.SK_MEMINFO_VARS]metrics.Gauge{
  398. metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.rmem_alloc", i), nil),
  399. metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.rcvbuf", i), nil),
  400. metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.wmem_alloc", i), nil),
  401. metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.sndbuf", i), nil),
  402. metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.fwd_alloc", i), nil),
  403. metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.wmem_queued", i), nil),
  404. metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.optmem", i), nil),
  405. metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.backlog", i), nil),
  406. metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.drops", i), nil),
  407. }
  408. }
  409. }
  410. return func() {
  411. for i, gauges := range udpGauges {
  412. if err := udpConns[i].(*StdConn).getMemInfo(&meminfo); err == nil {
  413. for j := 0; j < unix.SK_MEMINFO_VARS; j++ {
  414. gauges[j].Update(int64(meminfo[j]))
  415. }
  416. }
  417. }
  418. }
  419. }