udp_linux.go 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434
  1. //go:build !android && !e2e_testing
  2. // +build !android,!e2e_testing
  3. package udp
  4. import (
  5. "encoding/binary"
  6. "errors"
  7. "fmt"
  8. "net"
  9. "net/netip"
  10. "runtime"
  11. "sync"
  12. "sync/atomic"
  13. "syscall"
  14. "time"
  15. "unsafe"
  16. "github.com/rcrowley/go-metrics"
  17. "github.com/sirupsen/logrus"
  18. "github.com/slackhq/nebula/config"
  19. "github.com/slackhq/nebula/header"
  20. "golang.org/x/sys/unix"
  21. )
  22. const (
  23. defaultGSOMaxSegments = 8
  24. defaultGSOMaxBytes = MTU * defaultGSOMaxSegments
  25. defaultGROReadBufferSize = MTU * defaultGSOMaxSegments
  26. defaultGSOFlushTimeout = 50 * time.Microsecond
  27. linuxMaxGSOBatchBytes = 0xFFFF // Linux UDP GSO still limits the datagram payload to 64 KiB
  28. maxSendmmsgBatch = 32
  29. )
  30. type StdConn struct {
  31. sysFd int
  32. isV4 bool
  33. l *logrus.Logger
  34. batch int
  35. enableGRO bool
  36. enableGSO bool
  37. controlLen atomic.Int32
  38. gsoMaxSegments int
  39. gsoMaxBytes int
  40. gsoFlushTimeout time.Duration
  41. groSegmentPool sync.Pool
  42. groBufSize atomic.Int64
  43. rxBufferPool chan []byte
  44. gsoBufferPool sync.Pool
  45. gsoBatches metrics.Counter
  46. gsoSegments metrics.Counter
  47. groSegments metrics.Counter
  48. sendShards []*sendShard
  49. shardCounter atomic.Uint32
  50. }
  51. type sendTask struct {
  52. buf []byte
  53. addr netip.AddrPort
  54. segSize int
  55. segments int
  56. owned bool
  57. }
  58. const sendShardQueueDepth = 128
  59. type sendShard struct {
  60. parent *StdConn
  61. mu sync.Mutex
  62. pendingBuf []byte
  63. pendingSegments int
  64. pendingAddr netip.AddrPort
  65. pendingSegSize int
  66. flushTimer *time.Timer
  67. controlBuf []byte
  68. mmsgHeaders []linuxMmsgHdr
  69. mmsgIovecs []unix.Iovec
  70. mmsgLengths []int
  71. outQueue chan *sendTask
  72. workerDone sync.WaitGroup
  73. }
  74. func (u *StdConn) initSendShards() {
  75. shardCount := runtime.GOMAXPROCS(0)
  76. if shardCount < 1 {
  77. shardCount = 1
  78. }
  79. u.resizeSendShards(shardCount)
  80. }
  81. func (u *StdConn) selectSendShard(addr netip.AddrPort) *sendShard {
  82. if len(u.sendShards) == 0 {
  83. return nil
  84. }
  85. if len(u.sendShards) == 1 {
  86. return u.sendShards[0]
  87. }
  88. idx := int(u.shardCounter.Add(1)-1) % len(u.sendShards)
  89. if idx < 0 {
  90. idx = -idx
  91. }
  92. return u.sendShards[idx]
  93. }
  94. func (u *StdConn) resizeSendShards(count int) {
  95. if count <= 0 {
  96. count = runtime.GOMAXPROCS(0)
  97. if count < 1 {
  98. count = 1
  99. }
  100. }
  101. if len(u.sendShards) == count {
  102. return
  103. }
  104. for _, shard := range u.sendShards {
  105. if shard == nil {
  106. continue
  107. }
  108. shard.mu.Lock()
  109. if shard.pendingSegments > 0 {
  110. if err := shard.flushPendingLocked(); err != nil {
  111. u.l.WithError(err).Warn("Failed to flush send shard while resizing")
  112. }
  113. } else {
  114. shard.stopFlushTimerLocked()
  115. }
  116. buf := shard.pendingBuf
  117. shard.pendingBuf = nil
  118. shard.mu.Unlock()
  119. if buf != nil {
  120. u.releaseGSOBuf(buf)
  121. }
  122. shard.stopSender()
  123. }
  124. newShards := make([]*sendShard, count)
  125. for i := range newShards {
  126. shard := &sendShard{parent: u}
  127. shard.startSender()
  128. newShards[i] = shard
  129. }
  130. u.sendShards = newShards
  131. u.shardCounter.Store(0)
  132. u.l.WithField("send_shards", count).Debug("Configured UDP send shards")
  133. }
  134. func (u *StdConn) setGroBufferSize(size int) {
  135. if size < defaultGROReadBufferSize {
  136. size = defaultGROReadBufferSize
  137. }
  138. u.groBufSize.Store(int64(size))
  139. u.groSegmentPool = sync.Pool{New: func() any {
  140. return make([]byte, size)
  141. }}
  142. if u.rxBufferPool == nil {
  143. poolSize := u.batch * 4
  144. if poolSize < u.batch {
  145. poolSize = u.batch
  146. }
  147. u.rxBufferPool = make(chan []byte, poolSize)
  148. for i := 0; i < poolSize; i++ {
  149. u.rxBufferPool <- make([]byte, size)
  150. }
  151. }
  152. }
  153. func (u *StdConn) borrowRxBuffer(desired int) []byte {
  154. if desired < MTU {
  155. desired = MTU
  156. }
  157. if u.rxBufferPool == nil {
  158. return make([]byte, desired)
  159. }
  160. buf := <-u.rxBufferPool
  161. if cap(buf) < desired {
  162. buf = make([]byte, desired)
  163. }
  164. return buf[:desired]
  165. }
  166. func (u *StdConn) recycleBuffer(buf []byte) {
  167. if buf == nil {
  168. return
  169. }
  170. if u.rxBufferPool == nil {
  171. return
  172. }
  173. buf = buf[:cap(buf)]
  174. desired := int(u.groBufSize.Load())
  175. if desired < MTU {
  176. desired = MTU
  177. }
  178. if cap(buf) < desired {
  179. return
  180. }
  181. select {
  182. case u.rxBufferPool <- buf[:desired]:
  183. default:
  184. }
  185. }
  186. func (u *StdConn) recycleBufferSet(bufs [][]byte) {
  187. for i := range bufs {
  188. u.recycleBuffer(bufs[i])
  189. }
  190. }
  191. func (u *StdConn) borrowGSOBuf() []byte {
  192. size := u.gsoMaxBytes
  193. if size <= 0 {
  194. size = MTU
  195. }
  196. if v := u.gsoBufferPool.Get(); v != nil {
  197. buf := v.([]byte)
  198. if cap(buf) < size {
  199. return make([]byte, 0, size)
  200. }
  201. return buf[:0]
  202. }
  203. return make([]byte, 0, size)
  204. }
  205. func (u *StdConn) releaseGSOBuf(buf []byte) {
  206. if buf == nil {
  207. return
  208. }
  209. size := u.gsoMaxBytes
  210. if size <= 0 {
  211. size = MTU
  212. }
  213. buf = buf[:0]
  214. if cap(buf) > size*4 {
  215. return
  216. }
  217. u.gsoBufferPool.Put(buf)
  218. }
  219. func (s *sendShard) ensureMmsgCapacity(n int) {
  220. if cap(s.mmsgHeaders) < n {
  221. s.mmsgHeaders = make([]linuxMmsgHdr, n)
  222. }
  223. s.mmsgHeaders = s.mmsgHeaders[:n]
  224. if cap(s.mmsgIovecs) < n {
  225. s.mmsgIovecs = make([]unix.Iovec, n)
  226. }
  227. s.mmsgIovecs = s.mmsgIovecs[:n]
  228. if cap(s.mmsgLengths) < n {
  229. s.mmsgLengths = make([]int, n)
  230. }
  231. s.mmsgLengths = s.mmsgLengths[:n]
  232. }
  233. func (s *sendShard) ensurePendingBuf(p *StdConn) {
  234. if s.pendingBuf == nil {
  235. s.pendingBuf = p.borrowGSOBuf()
  236. }
  237. }
  238. func (s *sendShard) startSender() {
  239. if s.outQueue != nil {
  240. return
  241. }
  242. s.outQueue = make(chan *sendTask, sendShardQueueDepth)
  243. s.workerDone.Add(1)
  244. go s.senderLoop()
  245. }
  246. func (s *sendShard) stopSender() {
  247. s.closeSender()
  248. s.workerDone.Wait()
  249. }
  250. func (s *sendShard) closeSender() {
  251. s.mu.Lock()
  252. queue := s.outQueue
  253. s.outQueue = nil
  254. s.mu.Unlock()
  255. if queue != nil {
  256. close(queue)
  257. }
  258. }
  259. func (s *sendShard) senderLoop() {
  260. defer s.workerDone.Done()
  261. for task := range s.outQueue {
  262. if task == nil {
  263. continue
  264. }
  265. _ = s.processTask(task)
  266. }
  267. }
  268. func (s *sendShard) processTask(task *sendTask) error {
  269. if task == nil {
  270. return nil
  271. }
  272. p := s.parent
  273. defer func() {
  274. if task.owned && task.buf != nil {
  275. p.releaseGSOBuf(task.buf)
  276. }
  277. task.buf = nil
  278. }()
  279. if len(task.buf) == 0 {
  280. return nil
  281. }
  282. useGSO := p.enableGSO && task.segments > 1
  283. if useGSO {
  284. if err := s.sendSegmentedLocked(task.buf, task.addr, task.segSize); err != nil {
  285. if errors.Is(err, unix.EOPNOTSUPP) || errors.Is(err, unix.ENOTSUP) {
  286. p.enableGSO = false
  287. p.l.WithError(err).Warn("UDP GSO not supported, disabling")
  288. } else {
  289. p.l.WithError(err).Warn("Failed to flush GSO batch")
  290. return err
  291. }
  292. } else {
  293. s.recordGSOMetrics(task)
  294. return nil
  295. }
  296. }
  297. if err := s.sendSequentialLocked(task.buf, task.addr, task.segSize); err != nil {
  298. p.l.WithError(err).Warn("Failed to flush batch")
  299. return err
  300. }
  301. return nil
  302. }
  303. func (s *sendShard) recordGSOMetrics(task *sendTask) {
  304. p := s.parent
  305. if p.gsoBatches != nil {
  306. p.gsoBatches.Inc(1)
  307. }
  308. if p.gsoSegments != nil {
  309. p.gsoSegments.Inc(int64(task.segments))
  310. }
  311. if p.l.IsLevelEnabled(logrus.DebugLevel) {
  312. p.l.WithFields(logrus.Fields{
  313. "tag": "gso-debug",
  314. "stage": "flush",
  315. "segments": task.segments,
  316. "segment_size": task.segSize,
  317. "batch_bytes": len(task.buf),
  318. "remote_addr": task.addr.String(),
  319. }).Debug("gso batch sent")
  320. }
  321. }
  322. func (s *sendShard) write(b []byte, addr netip.AddrPort) error {
  323. if len(b) == 0 {
  324. return nil
  325. }
  326. s.mu.Lock()
  327. defer s.mu.Unlock()
  328. p := s.parent
  329. if !p.enableGSO || !addr.IsValid() {
  330. return p.directWrite(b, addr)
  331. }
  332. s.ensurePendingBuf(p)
  333. if s.pendingSegments > 0 && s.pendingAddr != addr {
  334. if err := s.flushPendingLocked(); err != nil {
  335. return err
  336. }
  337. s.ensurePendingBuf(p)
  338. }
  339. if len(b) > p.gsoMaxBytes || p.gsoMaxSegments <= 1 {
  340. if err := s.flushPendingLocked(); err != nil {
  341. return err
  342. }
  343. return p.directWrite(b, addr)
  344. }
  345. if s.pendingSegments == 0 {
  346. s.pendingAddr = addr
  347. s.pendingSegSize = len(b)
  348. } else if len(b) != s.pendingSegSize {
  349. if err := s.flushPendingLocked(); err != nil {
  350. return err
  351. }
  352. s.pendingAddr = addr
  353. s.pendingSegSize = len(b)
  354. s.ensurePendingBuf(p)
  355. }
  356. if len(s.pendingBuf)+len(b) > p.gsoMaxBytes {
  357. if err := s.flushPendingLocked(); err != nil {
  358. return err
  359. }
  360. s.pendingAddr = addr
  361. s.pendingSegSize = len(b)
  362. s.ensurePendingBuf(p)
  363. }
  364. s.pendingBuf = append(s.pendingBuf, b...)
  365. s.pendingSegments++
  366. if s.pendingSegments >= p.gsoMaxSegments {
  367. return s.flushPendingLocked()
  368. }
  369. if p.gsoFlushTimeout <= 0 {
  370. return s.flushPendingLocked()
  371. }
  372. s.scheduleFlushLocked()
  373. return nil
  374. }
  375. func (s *sendShard) flushPendingLocked() error {
  376. if s.pendingSegments == 0 {
  377. s.stopFlushTimerLocked()
  378. return nil
  379. }
  380. buf := s.pendingBuf
  381. task := &sendTask{
  382. buf: buf,
  383. addr: s.pendingAddr,
  384. segSize: s.pendingSegSize,
  385. segments: s.pendingSegments,
  386. owned: true,
  387. }
  388. s.pendingBuf = nil
  389. s.pendingSegments = 0
  390. s.pendingSegSize = 0
  391. s.pendingAddr = netip.AddrPort{}
  392. s.stopFlushTimerLocked()
  393. queue := s.outQueue
  394. s.mu.Unlock()
  395. var err error
  396. if queue == nil {
  397. err = s.processTask(task)
  398. } else {
  399. sent := false
  400. func() {
  401. defer func() {
  402. if r := recover(); r != nil {
  403. err = s.processTask(task)
  404. sent = true
  405. }
  406. }()
  407. select {
  408. case queue <- task:
  409. sent = true
  410. default:
  411. }
  412. }()
  413. if !sent {
  414. err = s.processTask(task)
  415. }
  416. }
  417. s.mu.Lock()
  418. return err
  419. }
  420. func (s *sendShard) sendSegmentedLocked(buf []byte, addr netip.AddrPort, segSize int) error {
  421. if len(buf) == 0 {
  422. return nil
  423. }
  424. if segSize <= 0 {
  425. segSize = len(buf)
  426. }
  427. if len(s.controlBuf) < unix.CmsgSpace(2) {
  428. s.controlBuf = make([]byte, unix.CmsgSpace(2))
  429. }
  430. control := s.controlBuf[:unix.CmsgSpace(2)]
  431. for i := range control {
  432. control[i] = 0
  433. }
  434. hdr := (*unix.Cmsghdr)(unsafe.Pointer(&control[0]))
  435. setCmsgLen(hdr, 2)
  436. hdr.Level = unix.SOL_UDP
  437. hdr.Type = unix.UDP_SEGMENT
  438. dataOff := unix.CmsgLen(0)
  439. binary.NativeEndian.PutUint16(control[dataOff:dataOff+2], uint16(segSize))
  440. var sa unix.Sockaddr
  441. if s.parent.isV4 {
  442. sa4 := &unix.SockaddrInet4{Port: int(addr.Port())}
  443. sa4.Addr = addr.Addr().As4()
  444. sa = sa4
  445. } else {
  446. sa6 := &unix.SockaddrInet6{Port: int(addr.Port())}
  447. sa6.Addr = addr.Addr().As16()
  448. sa = sa6
  449. }
  450. for {
  451. n, err := unix.SendmsgN(s.parent.sysFd, buf, control[:unix.CmsgSpace(2)], sa, 0)
  452. if err != nil {
  453. if err == unix.EINTR {
  454. continue
  455. }
  456. return &net.OpError{Op: "sendmsg", Err: err}
  457. }
  458. if n != len(buf) {
  459. return &net.OpError{Op: "sendmsg", Err: unix.EIO}
  460. }
  461. return nil
  462. }
  463. }
  464. func (s *sendShard) sendSequentialLocked(buf []byte, addr netip.AddrPort, segSize int) error {
  465. if len(buf) == 0 {
  466. return nil
  467. }
  468. if segSize <= 0 {
  469. segSize = len(buf)
  470. }
  471. if segSize >= len(buf) {
  472. return s.parent.directWrite(buf, addr)
  473. }
  474. var (
  475. namePtr *byte
  476. nameLen uint32
  477. )
  478. if s.parent.isV4 {
  479. var sa4 unix.RawSockaddrInet4
  480. sa4.Family = unix.AF_INET
  481. sa4.Addr = addr.Addr().As4()
  482. binary.BigEndian.PutUint16((*[2]byte)(unsafe.Pointer(&sa4.Port))[:], addr.Port())
  483. namePtr = (*byte)(unsafe.Pointer(&sa4))
  484. nameLen = uint32(unsafe.Sizeof(sa4))
  485. } else {
  486. var sa6 unix.RawSockaddrInet6
  487. sa6.Family = unix.AF_INET6
  488. sa6.Addr = addr.Addr().As16()
  489. binary.BigEndian.PutUint16((*[2]byte)(unsafe.Pointer(&sa6.Port))[:], addr.Port())
  490. namePtr = (*byte)(unsafe.Pointer(&sa6))
  491. nameLen = uint32(unsafe.Sizeof(sa6))
  492. }
  493. total := len(buf)
  494. if total == 0 {
  495. return nil
  496. }
  497. basePtr := uintptr(unsafe.Pointer(&buf[0]))
  498. offset := 0
  499. for offset < total {
  500. remaining := total - offset
  501. segments := (remaining + segSize - 1) / segSize
  502. if segments > maxSendmmsgBatch {
  503. segments = maxSendmmsgBatch
  504. }
  505. s.ensureMmsgCapacity(segments)
  506. msgs := s.mmsgHeaders[:segments]
  507. iovecs := s.mmsgIovecs[:segments]
  508. lens := s.mmsgLengths[:segments]
  509. batchStart := offset
  510. segOffset := offset
  511. actual := 0
  512. for actual < segments && segOffset < total {
  513. segLen := segSize
  514. if segLen > total-segOffset {
  515. segLen = total - segOffset
  516. }
  517. msgs[actual] = linuxMmsgHdr{}
  518. lens[actual] = segLen
  519. iovecs[actual].Base = &buf[segOffset]
  520. setIovecLen(&iovecs[actual], segLen)
  521. msgs[actual].Hdr.Iov = &iovecs[actual]
  522. setMsghdrIovlen(&msgs[actual].Hdr, 1)
  523. msgs[actual].Hdr.Name = namePtr
  524. msgs[actual].Hdr.Namelen = nameLen
  525. msgs[actual].Hdr.Control = nil
  526. msgs[actual].Hdr.Controllen = 0
  527. msgs[actual].Hdr.Flags = 0
  528. msgs[actual].Len = 0
  529. actual++
  530. segOffset += segLen
  531. }
  532. if actual == 0 {
  533. break
  534. }
  535. msgs = msgs[:actual]
  536. lens = lens[:actual]
  537. retry:
  538. sent, err := sendmmsg(s.parent.sysFd, msgs, 0)
  539. if err != nil {
  540. if err == unix.EINTR {
  541. goto retry
  542. }
  543. return &net.OpError{Op: "sendmmsg", Err: err}
  544. }
  545. if sent == 0 {
  546. goto retry
  547. }
  548. bytesSent := 0
  549. for i := 0; i < sent; i++ {
  550. bytesSent += lens[i]
  551. }
  552. offset = batchStart + bytesSent
  553. if sent < len(msgs) {
  554. for j := sent; j < len(msgs); j++ {
  555. start := int(uintptr(unsafe.Pointer(iovecs[j].Base)) - basePtr)
  556. if start < 0 || start >= total {
  557. continue
  558. }
  559. end := start + lens[j]
  560. if end > total {
  561. end = total
  562. }
  563. if err := s.parent.directWrite(buf[start:end], addr); err != nil {
  564. return err
  565. }
  566. if end > offset {
  567. offset = end
  568. }
  569. }
  570. }
  571. }
  572. return nil
  573. }
  574. func (s *sendShard) scheduleFlushLocked() {
  575. timeout := s.parent.gsoFlushTimeout
  576. if timeout <= 0 {
  577. _ = s.flushPendingLocked()
  578. return
  579. }
  580. if s.flushTimer == nil {
  581. s.flushTimer = time.AfterFunc(timeout, s.flushTimerHandler)
  582. return
  583. }
  584. if !s.flushTimer.Stop() {
  585. // allow existing timer to drain
  586. }
  587. if !s.flushTimer.Reset(timeout) {
  588. s.flushTimer = time.AfterFunc(timeout, s.flushTimerHandler)
  589. }
  590. }
  591. func (s *sendShard) stopFlushTimerLocked() {
  592. if s.flushTimer != nil {
  593. s.flushTimer.Stop()
  594. }
  595. }
  596. func (s *sendShard) flushTimerHandler() {
  597. s.mu.Lock()
  598. defer s.mu.Unlock()
  599. if s.pendingSegments == 0 {
  600. return
  601. }
  602. if err := s.flushPendingLocked(); err != nil {
  603. s.parent.l.WithError(err).Warn("Failed to flush GSO batch")
  604. }
  605. }
  606. func maybeIPV4(ip net.IP) (net.IP, bool) {
  607. ip4 := ip.To4()
  608. if ip4 != nil {
  609. return ip4, true
  610. }
  611. return ip, false
  612. }
  613. func NewListener(l *logrus.Logger, ip netip.Addr, port int, multi bool, batch int) (Conn, error) {
  614. af := unix.AF_INET6
  615. if ip.Is4() {
  616. af = unix.AF_INET
  617. }
  618. syscall.ForkLock.RLock()
  619. fd, err := unix.Socket(af, unix.SOCK_DGRAM, unix.IPPROTO_UDP)
  620. if err == nil {
  621. unix.CloseOnExec(fd)
  622. }
  623. syscall.ForkLock.RUnlock()
  624. if err != nil {
  625. unix.Close(fd)
  626. return nil, fmt.Errorf("unable to open socket: %s", err)
  627. }
  628. if multi {
  629. if err = unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil {
  630. return nil, fmt.Errorf("unable to set SO_REUSEPORT: %s", err)
  631. }
  632. }
  633. var sa unix.Sockaddr
  634. if ip.Is4() {
  635. sa4 := &unix.SockaddrInet4{Port: port}
  636. sa4.Addr = ip.As4()
  637. sa = sa4
  638. } else {
  639. sa6 := &unix.SockaddrInet6{Port: port}
  640. sa6.Addr = ip.As16()
  641. sa = sa6
  642. }
  643. if err = unix.Bind(fd, sa); err != nil {
  644. return nil, fmt.Errorf("unable to bind to socket: %s", err)
  645. }
  646. if ip.Is4() && udpChecksumDisabled() {
  647. if err := unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_NO_CHECK, 1); err != nil {
  648. l.WithError(err).Warn("Failed to disable IPv4 UDP checksum via SO_NO_CHECK")
  649. } else {
  650. l.Debug("Disabled IPv4 UDP checksum using SO_NO_CHECK")
  651. }
  652. }
  653. conn := &StdConn{
  654. sysFd: fd,
  655. isV4: ip.Is4(),
  656. l: l,
  657. batch: batch,
  658. gsoMaxSegments: defaultGSOMaxSegments,
  659. gsoMaxBytes: defaultGSOMaxBytes,
  660. gsoFlushTimeout: defaultGSOFlushTimeout,
  661. gsoBatches: metrics.GetOrRegisterCounter("udp.gso.batches", nil),
  662. gsoSegments: metrics.GetOrRegisterCounter("udp.gso.segments", nil),
  663. groSegments: metrics.GetOrRegisterCounter("udp.gro.segments", nil),
  664. }
  665. conn.setGroBufferSize(defaultGROReadBufferSize)
  666. conn.initSendShards()
  667. return conn, err
  668. }
  669. func (u *StdConn) Rebind() error {
  670. return nil
  671. }
  672. func (u *StdConn) SetRecvBuffer(n int) error {
  673. return unix.SetsockoptInt(u.sysFd, unix.SOL_SOCKET, unix.SO_RCVBUFFORCE, n)
  674. }
  675. func (u *StdConn) SetSendBuffer(n int) error {
  676. return unix.SetsockoptInt(u.sysFd, unix.SOL_SOCKET, unix.SO_SNDBUFFORCE, n)
  677. }
  678. func (u *StdConn) SetSoMark(mark int) error {
  679. return unix.SetsockoptInt(u.sysFd, unix.SOL_SOCKET, unix.SO_MARK, mark)
  680. }
  681. func (u *StdConn) GetRecvBuffer() (int, error) {
  682. return unix.GetsockoptInt(int(u.sysFd), unix.SOL_SOCKET, unix.SO_RCVBUF)
  683. }
  684. func (u *StdConn) GetSendBuffer() (int, error) {
  685. return unix.GetsockoptInt(int(u.sysFd), unix.SOL_SOCKET, unix.SO_SNDBUF)
  686. }
  687. func (u *StdConn) GetSoMark() (int, error) {
  688. return unix.GetsockoptInt(int(u.sysFd), unix.SOL_SOCKET, unix.SO_MARK)
  689. }
  690. func (u *StdConn) LocalAddr() (netip.AddrPort, error) {
  691. sa, err := unix.Getsockname(u.sysFd)
  692. if err != nil {
  693. return netip.AddrPort{}, err
  694. }
  695. switch sa := sa.(type) {
  696. case *unix.SockaddrInet4:
  697. return netip.AddrPortFrom(netip.AddrFrom4(sa.Addr), uint16(sa.Port)), nil
  698. case *unix.SockaddrInet6:
  699. return netip.AddrPortFrom(netip.AddrFrom16(sa.Addr), uint16(sa.Port)), nil
  700. default:
  701. return netip.AddrPort{}, fmt.Errorf("unsupported sock type: %T", sa)
  702. }
  703. }
  704. func (u *StdConn) ListenOut(r EncReader) {
  705. var ip netip.Addr
  706. msgs, buffers, names, controls := u.PrepareRawMessages(u.batch)
  707. read := u.ReadMulti
  708. if u.batch == 1 {
  709. read = u.ReadSingle
  710. }
  711. for {
  712. desiredGroSize := int(u.groBufSize.Load())
  713. if desiredGroSize < MTU {
  714. desiredGroSize = MTU
  715. }
  716. if len(buffers) == 0 || cap(buffers[0]) < desiredGroSize {
  717. u.recycleBufferSet(buffers)
  718. msgs, buffers, names, controls = u.PrepareRawMessages(u.batch)
  719. }
  720. desiredControl := int(u.controlLen.Load())
  721. hasControl := len(controls) > 0
  722. if (desiredControl > 0) != hasControl || (desiredControl > 0 && hasControl && len(controls[0]) != desiredControl) {
  723. u.recycleBufferSet(buffers)
  724. msgs, buffers, names, controls = u.PrepareRawMessages(u.batch)
  725. hasControl = len(controls) > 0
  726. }
  727. if hasControl {
  728. for i := range msgs {
  729. if len(controls) <= i || len(controls[i]) == 0 {
  730. continue
  731. }
  732. msgs[i].Hdr.Controllen = controllen(len(controls[i]))
  733. }
  734. }
  735. n, err := read(msgs)
  736. if err != nil {
  737. u.l.WithError(err).Debug("udp socket is closed, exiting read loop")
  738. u.recycleBufferSet(buffers)
  739. return
  740. }
  741. for i := 0; i < n; i++ {
  742. payloadLen := int(msgs[i].Len)
  743. if payloadLen == 0 {
  744. continue
  745. }
  746. // Its ok to skip the ok check here, the slicing is the only error that can occur and it will panic
  747. if u.isV4 {
  748. ip, _ = netip.AddrFromSlice(names[i][4:8])
  749. } else {
  750. ip, _ = netip.AddrFromSlice(names[i][8:24])
  751. }
  752. addr := netip.AddrPortFrom(ip.Unmap(), binary.BigEndian.Uint16(names[i][2:4]))
  753. buf := buffers[i]
  754. payload := buf[:payloadLen]
  755. released := false
  756. release := func() {
  757. if !released {
  758. released = true
  759. u.recycleBuffer(buf)
  760. }
  761. }
  762. handled := false
  763. if len(controls) > i && len(controls[i]) > 0 {
  764. if segSize, segCount := u.parseGROSegment(&msgs[i], controls[i]); segSize > 0 && segSize < payloadLen {
  765. if u.emitSegments(r, addr, payload, segSize, segCount, release) {
  766. handled = true
  767. } else if segCount > 1 {
  768. u.l.WithFields(logrus.Fields{
  769. "tag": "gro-debug",
  770. "stage": "listen_out",
  771. "reason": "emit_failed",
  772. "payload_len": payloadLen,
  773. "seg_size": segSize,
  774. "seg_count": segCount,
  775. }).Debug("gro-debug fallback to single packet")
  776. }
  777. }
  778. }
  779. if !handled {
  780. r(addr, payload, release)
  781. }
  782. buffers[i] = u.borrowRxBuffer(desiredGroSize)
  783. setIovecBase(&msgs[i], buffers[i])
  784. }
  785. }
  786. }
  787. func (u *StdConn) ReadSingle(msgs []rawMessage) (int, error) {
  788. for {
  789. n, _, err := unix.Syscall6(
  790. unix.SYS_RECVMSG,
  791. uintptr(u.sysFd),
  792. uintptr(unsafe.Pointer(&(msgs[0].Hdr))),
  793. 0,
  794. 0,
  795. 0,
  796. 0,
  797. )
  798. if err != 0 {
  799. return 0, &net.OpError{Op: "recvmsg", Err: err}
  800. }
  801. msgs[0].Len = uint32(n)
  802. return 1, nil
  803. }
  804. }
  805. func (u *StdConn) ReadMulti(msgs []rawMessage) (int, error) {
  806. for {
  807. n, _, err := unix.Syscall6(
  808. unix.SYS_RECVMMSG,
  809. uintptr(u.sysFd),
  810. uintptr(unsafe.Pointer(&msgs[0])),
  811. uintptr(len(msgs)),
  812. unix.MSG_WAITFORONE,
  813. 0,
  814. 0,
  815. )
  816. if err != 0 {
  817. return 0, &net.OpError{Op: "recvmmsg", Err: err}
  818. }
  819. return int(n), nil
  820. }
  821. }
  822. func (u *StdConn) WriteTo(b []byte, ip netip.AddrPort) error {
  823. if u.enableGSO {
  824. if err := u.writeToGSO(b, ip); err != nil {
  825. return err
  826. }
  827. return nil
  828. }
  829. if u.isV4 {
  830. return u.writeTo4(b, ip)
  831. }
  832. return u.writeTo6(b, ip)
  833. }
  834. func (u *StdConn) writeTo6(b []byte, ip netip.AddrPort) error {
  835. var rsa unix.RawSockaddrInet6
  836. rsa.Family = unix.AF_INET6
  837. rsa.Addr = ip.Addr().As16()
  838. binary.BigEndian.PutUint16((*[2]byte)(unsafe.Pointer(&rsa.Port))[:], ip.Port())
  839. for {
  840. _, _, err := unix.Syscall6(
  841. unix.SYS_SENDTO,
  842. uintptr(u.sysFd),
  843. uintptr(unsafe.Pointer(&b[0])),
  844. uintptr(len(b)),
  845. uintptr(0),
  846. uintptr(unsafe.Pointer(&rsa)),
  847. uintptr(unix.SizeofSockaddrInet6),
  848. )
  849. if err != 0 {
  850. return &net.OpError{Op: "sendto", Err: err}
  851. }
  852. return nil
  853. }
  854. }
  855. func (u *StdConn) writeTo4(b []byte, ip netip.AddrPort) error {
  856. if !ip.Addr().Is4() {
  857. return ErrInvalidIPv6RemoteForSocket
  858. }
  859. var rsa unix.RawSockaddrInet4
  860. rsa.Family = unix.AF_INET
  861. rsa.Addr = ip.Addr().As4()
  862. binary.BigEndian.PutUint16((*[2]byte)(unsafe.Pointer(&rsa.Port))[:], ip.Port())
  863. for {
  864. _, _, err := unix.Syscall6(
  865. unix.SYS_SENDTO,
  866. uintptr(u.sysFd),
  867. uintptr(unsafe.Pointer(&b[0])),
  868. uintptr(len(b)),
  869. uintptr(0),
  870. uintptr(unsafe.Pointer(&rsa)),
  871. uintptr(unix.SizeofSockaddrInet4),
  872. )
  873. if err != 0 {
  874. return &net.OpError{Op: "sendto", Err: err}
  875. }
  876. return nil
  877. }
  878. }
  879. func (u *StdConn) writeToGSO(b []byte, addr netip.AddrPort) error {
  880. if len(b) == 0 {
  881. return nil
  882. }
  883. shard := u.selectSendShard(addr)
  884. if shard == nil {
  885. return u.directWrite(b, addr)
  886. }
  887. return shard.write(b, addr)
  888. }
  889. func (u *StdConn) directWrite(b []byte, addr netip.AddrPort) error {
  890. if u.isV4 {
  891. return u.writeTo4(b, addr)
  892. }
  893. return u.writeTo6(b, addr)
  894. }
  895. func (u *StdConn) emitSegments(r EncReader, addr netip.AddrPort, payload []byte, segSize, segCount int, release func()) bool {
  896. if segSize <= 0 || segSize >= len(payload) {
  897. u.l.WithFields(logrus.Fields{
  898. "tag": "gro-debug",
  899. "stage": "emit",
  900. "reason": "invalid_seg_size",
  901. "payload_len": len(payload),
  902. "seg_size": segSize,
  903. "seg_count": segCount,
  904. }).Debug("gro-debug skip emit")
  905. return false
  906. }
  907. totalLen := len(payload)
  908. if segCount <= 0 {
  909. segCount = (totalLen + segSize - 1) / segSize
  910. }
  911. if segCount <= 1 {
  912. u.l.WithFields(logrus.Fields{
  913. "tag": "gro-debug",
  914. "stage": "emit",
  915. "reason": "single_segment",
  916. "payload_len": totalLen,
  917. "seg_size": segSize,
  918. "seg_count": segCount,
  919. }).Debug("gro-debug skip emit")
  920. return false
  921. }
  922. defer func() {
  923. if release != nil {
  924. release()
  925. }
  926. }()
  927. actualSegments := 0
  928. start := 0
  929. debugEnabled := u.l.IsLevelEnabled(logrus.DebugLevel)
  930. var firstHeader header.H
  931. var firstParsed bool
  932. var firstCounter uint64
  933. var firstRemote uint32
  934. for start < totalLen && actualSegments < segCount {
  935. end := start + segSize
  936. if end > totalLen {
  937. end = totalLen
  938. }
  939. segLen := end - start
  940. bufAny := u.groSegmentPool.Get()
  941. var segBuf []byte
  942. if bufAny == nil {
  943. segBuf = make([]byte, segLen)
  944. } else {
  945. segBuf = bufAny.([]byte)
  946. if cap(segBuf) < segLen {
  947. segBuf = make([]byte, segLen)
  948. }
  949. }
  950. segment := segBuf[:segLen]
  951. copy(segment, payload[start:end])
  952. if debugEnabled && !firstParsed {
  953. if err := firstHeader.Parse(segment); err == nil {
  954. firstParsed = true
  955. firstCounter = firstHeader.MessageCounter
  956. firstRemote = firstHeader.RemoteIndex
  957. } else {
  958. u.l.WithFields(logrus.Fields{
  959. "tag": "gro-debug",
  960. "stage": "emit",
  961. "event": "parse_fail",
  962. "seg_index": actualSegments,
  963. "seg_size": segSize,
  964. "seg_count": segCount,
  965. "payload_len": totalLen,
  966. "err": err,
  967. }).Debug("gro-debug segment parse failed")
  968. }
  969. }
  970. start = end
  971. actualSegments++
  972. r(addr, segment, func() {
  973. u.groSegmentPool.Put(segBuf[:cap(segBuf)])
  974. })
  975. if debugEnabled && actualSegments == segCount && segLen < segSize {
  976. var tail header.H
  977. if err := tail.Parse(segment); err == nil {
  978. u.l.WithFields(logrus.Fields{
  979. "tag": "gro-debug",
  980. "stage": "emit",
  981. "event": "tail_segment",
  982. "segment_len": segLen,
  983. "remote_index": tail.RemoteIndex,
  984. "message_counter": tail.MessageCounter,
  985. }).Debug("gro-debug tail segment metadata")
  986. }
  987. }
  988. }
  989. if u.groSegments != nil {
  990. u.groSegments.Inc(int64(actualSegments))
  991. }
  992. if debugEnabled && actualSegments > 0 {
  993. lastLen := segSize
  994. if tail := totalLen % segSize; tail != 0 {
  995. lastLen = tail
  996. }
  997. u.l.WithFields(logrus.Fields{
  998. "tag": "gro-debug",
  999. "stage": "emit",
  1000. "event": "success",
  1001. "payload_len": totalLen,
  1002. "seg_size": segSize,
  1003. "seg_count": segCount,
  1004. "actual_segs": actualSegments,
  1005. "last_seg_len": lastLen,
  1006. "addr": addr.String(),
  1007. "first_remote": firstRemote,
  1008. "first_counter": firstCounter,
  1009. }).Debug("gro-debug emit")
  1010. }
  1011. return true
  1012. }
  1013. func (u *StdConn) parseGROSegment(msg *rawMessage, control []byte) (int, int) {
  1014. ctrlLen := int(msg.Hdr.Controllen)
  1015. if ctrlLen <= 0 {
  1016. return 0, 0
  1017. }
  1018. if ctrlLen > len(control) {
  1019. ctrlLen = len(control)
  1020. }
  1021. cmsgs, err := unix.ParseSocketControlMessage(control[:ctrlLen])
  1022. if err != nil {
  1023. u.l.WithError(err).Debug("failed to parse UDP GRO control message")
  1024. return 0, 0
  1025. }
  1026. for _, c := range cmsgs {
  1027. if c.Header.Level == unix.SOL_UDP && c.Header.Type == unix.UDP_GRO && len(c.Data) >= 2 {
  1028. segSize := int(binary.NativeEndian.Uint16(c.Data[:2]))
  1029. segCount := 0
  1030. if len(c.Data) >= 4 {
  1031. segCount = int(binary.NativeEndian.Uint16(c.Data[2:4]))
  1032. }
  1033. u.l.WithFields(logrus.Fields{
  1034. "tag": "gro-debug",
  1035. "stage": "parse",
  1036. "seg_size": segSize,
  1037. "seg_count": segCount,
  1038. }).Debug("gro-debug control parsed")
  1039. return segSize, segCount
  1040. }
  1041. }
  1042. return 0, 0
  1043. }
  1044. func (u *StdConn) configureGRO(enable bool) {
  1045. if enable == u.enableGRO {
  1046. if enable {
  1047. u.controlLen.Store(int32(unix.CmsgSpace(2)))
  1048. } else {
  1049. u.controlLen.Store(0)
  1050. }
  1051. return
  1052. }
  1053. if enable {
  1054. if err := unix.SetsockoptInt(u.sysFd, unix.SOL_UDP, unix.UDP_GRO, 1); err != nil {
  1055. u.l.WithError(err).Warn("Failed to enable UDP GRO")
  1056. u.enableGRO = false
  1057. u.controlLen.Store(0)
  1058. return
  1059. }
  1060. u.enableGRO = true
  1061. u.controlLen.Store(int32(unix.CmsgSpace(2)))
  1062. u.l.Info("UDP GRO enabled")
  1063. } else {
  1064. if u.enableGRO {
  1065. if err := unix.SetsockoptInt(u.sysFd, unix.SOL_UDP, unix.UDP_GRO, 0); err != nil {
  1066. u.l.WithError(err).Warn("Failed to disable UDP GRO")
  1067. }
  1068. }
  1069. u.enableGRO = false
  1070. u.controlLen.Store(0)
  1071. }
  1072. }
  1073. func (u *StdConn) configureGSO(enable bool, c *config.C) {
  1074. if len(u.sendShards) == 0 {
  1075. u.initSendShards()
  1076. }
  1077. shardCount := c.GetInt("listen.send_shards", 0)
  1078. u.resizeSendShards(shardCount)
  1079. if !enable {
  1080. if u.enableGSO {
  1081. for _, shard := range u.sendShards {
  1082. shard.mu.Lock()
  1083. if shard.pendingSegments > 0 {
  1084. if err := shard.flushPendingLocked(); err != nil {
  1085. u.l.WithError(err).Warn("Failed to flush GSO buffers while disabling")
  1086. }
  1087. } else {
  1088. shard.stopFlushTimerLocked()
  1089. }
  1090. buf := shard.pendingBuf
  1091. shard.pendingBuf = nil
  1092. shard.mu.Unlock()
  1093. if buf != nil {
  1094. u.releaseGSOBuf(buf)
  1095. }
  1096. }
  1097. u.enableGSO = false
  1098. u.l.Info("UDP GSO disabled")
  1099. }
  1100. u.setGroBufferSize(defaultGROReadBufferSize)
  1101. return
  1102. }
  1103. maxSegments := c.GetInt("listen.gso_max_segments", defaultGSOMaxSegments)
  1104. if maxSegments < 2 {
  1105. maxSegments = 2
  1106. }
  1107. maxBytes := c.GetInt("listen.gso_max_bytes", 0)
  1108. if maxBytes <= 0 {
  1109. maxBytes = defaultGSOMaxBytes
  1110. }
  1111. if maxBytes < MTU {
  1112. maxBytes = MTU
  1113. }
  1114. if maxBytes > linuxMaxGSOBatchBytes {
  1115. u.l.WithFields(logrus.Fields{
  1116. "configured_bytes": maxBytes,
  1117. "clamped_bytes": linuxMaxGSOBatchBytes,
  1118. }).Warn("listen.gso_max_bytes exceeds Linux UDP limit; clamping")
  1119. maxBytes = linuxMaxGSOBatchBytes
  1120. }
  1121. flushTimeout := c.GetDuration("listen.gso_flush_timeout", defaultGSOFlushTimeout)
  1122. if flushTimeout < 0 {
  1123. flushTimeout = 0
  1124. }
  1125. u.enableGSO = true
  1126. u.gsoMaxSegments = maxSegments
  1127. u.gsoMaxBytes = maxBytes
  1128. u.gsoFlushTimeout = flushTimeout
  1129. bufSize := defaultGROReadBufferSize
  1130. if u.gsoMaxBytes > bufSize {
  1131. bufSize = u.gsoMaxBytes
  1132. }
  1133. u.setGroBufferSize(bufSize)
  1134. for _, shard := range u.sendShards {
  1135. shard.mu.Lock()
  1136. if shard.pendingBuf != nil {
  1137. u.releaseGSOBuf(shard.pendingBuf)
  1138. shard.pendingBuf = nil
  1139. }
  1140. shard.pendingSegments = 0
  1141. shard.pendingSegSize = 0
  1142. shard.pendingAddr = netip.AddrPort{}
  1143. shard.stopFlushTimerLocked()
  1144. if len(shard.controlBuf) < unix.CmsgSpace(2) {
  1145. shard.controlBuf = make([]byte, unix.CmsgSpace(2))
  1146. }
  1147. shard.mu.Unlock()
  1148. }
  1149. u.l.WithFields(logrus.Fields{
  1150. "segments": u.gsoMaxSegments,
  1151. "bytes": u.gsoMaxBytes,
  1152. "flush_timeout": u.gsoFlushTimeout,
  1153. }).Info("UDP GSO configured")
  1154. }
  1155. func (u *StdConn) ReloadConfig(c *config.C) {
  1156. b := c.GetInt("listen.read_buffer", 0)
  1157. if b > 0 {
  1158. err := u.SetRecvBuffer(b)
  1159. if err == nil {
  1160. s, err := u.GetRecvBuffer()
  1161. if err == nil {
  1162. u.l.WithField("size", s).Info("listen.read_buffer was set")
  1163. } else {
  1164. u.l.WithError(err).Warn("Failed to get listen.read_buffer")
  1165. }
  1166. } else {
  1167. u.l.WithError(err).Error("Failed to set listen.read_buffer")
  1168. }
  1169. }
  1170. b = c.GetInt("listen.write_buffer", 0)
  1171. if b > 0 {
  1172. err := u.SetSendBuffer(b)
  1173. if err == nil {
  1174. s, err := u.GetSendBuffer()
  1175. if err == nil {
  1176. u.l.WithField("size", s).Info("listen.write_buffer was set")
  1177. } else {
  1178. u.l.WithError(err).Warn("Failed to get listen.write_buffer")
  1179. }
  1180. } else {
  1181. u.l.WithError(err).Error("Failed to set listen.write_buffer")
  1182. }
  1183. }
  1184. b = c.GetInt("listen.so_mark", 0)
  1185. s, err := u.GetSoMark()
  1186. if b > 0 || (err == nil && s != 0) {
  1187. err := u.SetSoMark(b)
  1188. if err == nil {
  1189. s, err := u.GetSoMark()
  1190. if err == nil {
  1191. u.l.WithField("mark", s).Info("listen.so_mark was set")
  1192. } else {
  1193. u.l.WithError(err).Warn("Failed to get listen.so_mark")
  1194. }
  1195. } else {
  1196. u.l.WithError(err).Error("Failed to set listen.so_mark")
  1197. }
  1198. }
  1199. u.configureGRO(c.GetBool("listen.enable_gro", false))
  1200. u.configureGSO(c.GetBool("listen.enable_gso", false), c)
  1201. }
  1202. func (u *StdConn) getMemInfo(meminfo *[unix.SK_MEMINFO_VARS]uint32) error {
  1203. var vallen uint32 = 4 * unix.SK_MEMINFO_VARS
  1204. _, _, err := unix.Syscall6(unix.SYS_GETSOCKOPT, uintptr(u.sysFd), uintptr(unix.SOL_SOCKET), uintptr(unix.SO_MEMINFO), uintptr(unsafe.Pointer(meminfo)), uintptr(unsafe.Pointer(&vallen)), 0)
  1205. if err != 0 {
  1206. return err
  1207. }
  1208. return nil
  1209. }
  1210. func (u *StdConn) Close() error {
  1211. // Attempt to unblock any outstanding sendmsg/sendmmsg calls so the shard
  1212. // workers can drain promptly during shutdown. Ignoring errors here is fine
  1213. // because some platforms/kernels may not support shutdown on UDP sockets.
  1214. if err := unix.Shutdown(u.sysFd, unix.SHUT_WR); err != nil && err != unix.ENOTCONN && err != unix.EINVAL && err != unix.EBADF {
  1215. u.l.WithError(err).Debug("Failed to shutdown UDP socket for close")
  1216. }
  1217. var flushErr error
  1218. for _, shard := range u.sendShards {
  1219. if shard == nil {
  1220. continue
  1221. }
  1222. shard.mu.Lock()
  1223. if shard.pendingSegments > 0 {
  1224. if err := shard.flushPendingLocked(); err != nil && flushErr == nil {
  1225. flushErr = err
  1226. }
  1227. } else {
  1228. shard.stopFlushTimerLocked()
  1229. }
  1230. buf := shard.pendingBuf
  1231. shard.pendingBuf = nil
  1232. shard.mu.Unlock()
  1233. if buf != nil {
  1234. u.releaseGSOBuf(buf)
  1235. }
  1236. shard.stopSender()
  1237. }
  1238. closeErr := syscall.Close(u.sysFd)
  1239. if flushErr != nil {
  1240. return flushErr
  1241. }
  1242. return closeErr
  1243. }
  1244. func NewUDPStatsEmitter(udpConns []Conn) func() {
  1245. // Check if our kernel supports SO_MEMINFO before registering the gauges
  1246. var udpGauges [][unix.SK_MEMINFO_VARS]metrics.Gauge
  1247. var meminfo [unix.SK_MEMINFO_VARS]uint32
  1248. if err := udpConns[0].(*StdConn).getMemInfo(&meminfo); err == nil {
  1249. udpGauges = make([][unix.SK_MEMINFO_VARS]metrics.Gauge, len(udpConns))
  1250. for i := range udpConns {
  1251. udpGauges[i] = [unix.SK_MEMINFO_VARS]metrics.Gauge{
  1252. metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.rmem_alloc", i), nil),
  1253. metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.rcvbuf", i), nil),
  1254. metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.wmem_alloc", i), nil),
  1255. metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.sndbuf", i), nil),
  1256. metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.fwd_alloc", i), nil),
  1257. metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.wmem_queued", i), nil),
  1258. metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.optmem", i), nil),
  1259. metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.backlog", i), nil),
  1260. metrics.GetOrRegisterGauge(fmt.Sprintf("udp.%d.drops", i), nil),
  1261. }
  1262. }
  1263. }
  1264. return func() {
  1265. for i, gauges := range udpGauges {
  1266. if err := udpConns[i].(*StdConn).getMemInfo(&meminfo); err == nil {
  1267. for j := 0; j < unix.SK_MEMINFO_VARS; j++ {
  1268. gauges[j].Update(int64(meminfo[j]))
  1269. }
  1270. }
  1271. }
  1272. }
  1273. }