Skip to content

Commit 99729e4

Browse files
brad-definednbrownus
authored andcommitted
Quietly log error on UDP_NETRESET ioctl on Windows. (#1453)
* Quietly log error on UDP_NETRESET ioctl on Windows. * dampen unexpected error warnings
1 parent 2f71d6b commit 99729e4

2 files changed

Lines changed: 37 additions & 12 deletions

File tree

udp/udp_generic.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ package udp
1010

1111
import (
1212
"context"
13+
"errors"
1314
"fmt"
1415
"net"
1516
"net/netip"
17+
"time"
1618

1719
"github.com/sirupsen/logrus"
1820
"github.com/slackhq/nebula/config"
@@ -74,12 +76,22 @@ type rawMessage struct {
7476
func (u *GenericConn) ListenOut(r EncReader) {
7577
buffer := make([]byte, MTU)
7678

79+
var lastRecvErr time.Time
80+
7781
for {
7882
// Just read one packet at a time
7983
n, rua, err := u.ReadFromUDPAddrPort(buffer)
8084
if err != nil {
81-
u.l.WithError(err).Debug("udp socket is closed, exiting read loop")
82-
return
85+
if errors.Is(err, net.ErrClosed) {
86+
u.l.WithError(err).Debug("udp socket is closed, exiting read loop")
87+
return
88+
}
89+
// Dampen unexpected message warns to once per minute
90+
if lastRecvErr.IsZero() || time.Since(lastRecvErr) > time.Minute {
91+
lastRecvErr = time.Now()
92+
u.l.WithError(err).Warn("unexpected udp socket receive error")
93+
}
94+
continue
8395
}
8496

8597
r(netip.AddrPortFrom(rua.Addr().Unmap(), rua.Port()), buffer[:n])

udp/udp_rio_windows.go

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"sync"
1515
"sync/atomic"
1616
"syscall"
17+
"time"
1718
"unsafe"
1819

1920
"github.com/sirupsen/logrus"
@@ -66,7 +67,7 @@ func NewRIOListener(l *logrus.Logger, addr netip.Addr, port int) (*RIOConn, erro
6667

6768
u := &RIOConn{l: l}
6869

69-
err := u.bind(&windows.SockaddrInet6{Addr: addr.As16(), Port: port})
70+
err := u.bind(l, &windows.SockaddrInet6{Addr: addr.As16(), Port: port})
7071
if err != nil {
7172
return nil, fmt.Errorf("bind: %w", err)
7273
}
@@ -82,11 +83,11 @@ func NewRIOListener(l *logrus.Logger, addr netip.Addr, port int) (*RIOConn, erro
8283
return u, nil
8384
}
8485

85-
func (u *RIOConn) bind(sa windows.Sockaddr) error {
86+
func (u *RIOConn) bind(l *logrus.Logger, sa windows.Sockaddr) error {
8687
var err error
8788
u.sock, err = winrio.Socket(windows.AF_INET6, windows.SOCK_DGRAM, windows.IPPROTO_UDP)
8889
if err != nil {
89-
return err
90+
return fmt.Errorf("winrio.Socket error: %w", err)
9091
}
9192

9293
// Enable v4 for this socket
@@ -100,35 +101,40 @@ func (u *RIOConn) bind(sa windows.Sockaddr) error {
100101
size := uint32(unsafe.Sizeof(flag))
101102
err = syscall.WSAIoctl(syscall.Handle(u.sock), syscall.SIO_UDP_CONNRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0)
102103
if err != nil {
103-
return err
104+
// This is a best-effort to prevent errors from being returned by the udp recv operation.
105+
// Quietly log a failure and continue.
106+
l.WithError(err).Debug("failed to set UDP_CONNRESET ioctl")
104107
}
108+
105109
ret = 0
106110
flag = 0
107111
size = uint32(unsafe.Sizeof(flag))
108112
SIO_UDP_NETRESET := uint32(syscall.IOC_IN | syscall.IOC_VENDOR | 15)
109113
err = syscall.WSAIoctl(syscall.Handle(u.sock), SIO_UDP_NETRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0)
110114
if err != nil {
111-
return err
115+
// This is a best-effort to prevent errors from being returned by the udp recv operation.
116+
// Quietly log a failure and continue.
117+
l.WithError(err).Debug("failed to set UDP_NETRESET ioctl")
112118
}
113119

114120
err = u.rx.Open()
115121
if err != nil {
116-
return err
122+
return fmt.Errorf("error rx.Open(): %w", err)
117123
}
118124

119125
err = u.tx.Open()
120126
if err != nil {
121-
return err
127+
return fmt.Errorf("error tx.Open(): %w", err)
122128
}
123129

124130
u.rq, err = winrio.CreateRequestQueue(u.sock, packetsPerRing, 1, packetsPerRing, 1, u.rx.cq, u.tx.cq, 0)
125131
if err != nil {
126-
return err
132+
return fmt.Errorf("error CreateRequestQueue: %w", err)
127133
}
128134

129135
err = windows.Bind(u.sock, sa)
130136
if err != nil {
131-
return err
137+
return fmt.Errorf("error windows.Bind(): %w", err)
132138
}
133139

134140
return nil
@@ -137,15 +143,22 @@ func (u *RIOConn) bind(sa windows.Sockaddr) error {
137143
func (u *RIOConn) ListenOut(r EncReader) {
138144
buffer := make([]byte, MTU)
139145

146+
var lastRecvErr time.Time
147+
140148
for {
141149
// Just read one packet at a time
142150
n, rua, err := u.receive(buffer)
151+
143152
if err != nil {
144153
if errors.Is(err, net.ErrClosed) {
145154
u.l.WithError(err).Debug("udp socket is closed, exiting read loop")
146155
return
147156
}
148-
u.l.WithError(err).Error("unexpected udp socket receive error")
157+
// Dampen unexpected message warns to once per minute
158+
if lastRecvErr.IsZero() || time.Since(lastRecvErr) > time.Minute {
159+
lastRecvErr = time.Now()
160+
u.l.WithError(err).Warn("unexpected udp socket receive error")
161+
}
149162
continue
150163
}
151164

0 commit comments

Comments
 (0)