Skip to content

Commit 19b0969

Browse files
committed
Merge remote-tracking branch 'upstream/unsafe-route-reload'
2 parents 338383e + e3be26e commit 19b0969

File tree

1 file changed

+67
-34
lines changed

1 file changed

+67
-34
lines changed

overlay/tun_linux.go

Lines changed: 67 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type tun struct {
3131
DefaultMTU int
3232
TXQueueLen int
3333
deviceIndex int
34+
ioctlFd uintptr
3435

3536
Routes atomic.Pointer[[]Route]
3637
routeTree atomic.Pointer[cidr.Tree4[iputil.VpnIp]]
@@ -110,7 +111,6 @@ func newTunGeneric(c *config.C, l *logrus.Logger, file *os.File, cidr *net.IPNet
110111
ReadWriteCloser: file,
111112
fd: int(file.Fd()),
112113
cidr: cidr,
113-
DefaultMTU: c.GetInt("tun.mtu", DefaultMTU),
114114
TXQueueLen: c.GetInt("tun.tx_queue", 500),
115115
useSystemRoutes: c.GetBool("tun.use_system_route_table", false),
116116
l: l,
@@ -132,12 +132,12 @@ func newTunGeneric(c *config.C, l *logrus.Logger, file *os.File, cidr *net.IPNet
132132
}
133133

134134
func (t *tun) reload(c *config.C, initial bool) error {
135-
change, routes, err := getAllRoutesFromConfig(c, t.cidr, initial)
135+
routeChange, routes, err := getAllRoutesFromConfig(c, t.cidr, initial)
136136
if err != nil {
137137
return err
138138
}
139139

140-
if !initial && !change {
140+
if !initial && !routeChange && !c.HasChanged("tun.mtu") {
141141
return nil
142142
}
143143

@@ -146,24 +146,42 @@ func (t *tun) reload(c *config.C, initial bool) error {
146146
return err
147147
}
148148

149+
oldDefaultMTU := t.DefaultMTU
150+
oldMaxMTU := t.MaxMTU
151+
newDefaultMTU := c.GetInt("tun.mtu", DefaultMTU)
152+
newMaxMTU := newDefaultMTU
149153
for i, r := range routes {
150154
if r.MTU == 0 {
151-
//TODO: This was horribly broken before, I have doubts anyone is using it
152-
routes[i].MTU = t.DefaultMTU
155+
routes[i].MTU = newDefaultMTU
153156
}
154157

155158
if r.MTU > t.MaxMTU {
156-
//TODO: This needs to be atomic but it is not used so maybe its fine?
157-
//TODO: this is also not handled since it would adjust the main route and device mtu
158-
t.MaxMTU = r.MTU
159+
newMaxMTU = r.MTU
159160
}
160161
}
161162

163+
t.MaxMTU = newMaxMTU
164+
t.DefaultMTU = newDefaultMTU
165+
162166
// Teach nebula how to handle the routes before establishing them in the system table
163167
oldRoutes := t.Routes.Swap(&routes)
164168
t.routeTree.Store(routeTree)
165169

166170
if !initial {
171+
if oldMaxMTU != newMaxMTU {
172+
t.setMTU()
173+
t.l.Infof("Set max MTU to %v was %v", t.MaxMTU, oldMaxMTU)
174+
}
175+
176+
if oldDefaultMTU != newDefaultMTU {
177+
err := t.setDefaultRoute()
178+
if err != nil {
179+
t.l.Warn(err)
180+
} else {
181+
t.l.Infof("Set default MTU to %v was %v", t.DefaultMTU, oldDefaultMTU)
182+
}
183+
}
184+
167185
// Remove first, if the system removes a wanted route hopefully it will be re-added next
168186
t.removeRoutes(findRemovedRoutes(routes, *oldRoutes))
169187

@@ -251,7 +269,7 @@ func (t *tun) Activate() error {
251269
if err != nil {
252270
return err
253271
}
254-
fd := uintptr(s)
272+
t.ioctlFd = uintptr(s)
255273

256274
ifra := ifreqAddr{
257275
Name: devName,
@@ -262,50 +280,72 @@ func (t *tun) Activate() error {
262280
}
263281

264282
// Set the device ip address
265-
if err = ioctl(fd, unix.SIOCSIFADDR, uintptr(unsafe.Pointer(&ifra))); err != nil {
283+
if err = ioctl(t.ioctlFd, unix.SIOCSIFADDR, uintptr(unsafe.Pointer(&ifra))); err != nil {
266284
return fmt.Errorf("failed to set tun address: %s", err)
267285
}
268286

269287
// Set the device network
270288
ifra.Addr.Addr = mask
271-
if err = ioctl(fd, unix.SIOCSIFNETMASK, uintptr(unsafe.Pointer(&ifra))); err != nil {
289+
if err = ioctl(t.ioctlFd, unix.SIOCSIFNETMASK, uintptr(unsafe.Pointer(&ifra))); err != nil {
272290
return fmt.Errorf("failed to set tun netmask: %s", err)
273291
}
274292

275293
// Set the device name
276294
ifrf := ifReq{Name: devName}
277-
if err = ioctl(fd, unix.SIOCGIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil {
295+
if err = ioctl(t.ioctlFd, unix.SIOCGIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil {
278296
return fmt.Errorf("failed to set tun device name: %s", err)
279297
}
280298

281-
// Set the MTU on the device
282-
ifm := ifreqMTU{Name: devName, MTU: int32(t.MaxMTU)}
283-
if err = ioctl(fd, unix.SIOCSIFMTU, uintptr(unsafe.Pointer(&ifm))); err != nil {
284-
// This is currently a non fatal condition because the route table must have the MTU set appropriately as well
285-
t.l.WithError(err).Error("Failed to set tun mtu")
286-
}
299+
// Setup our default MTU
300+
t.setMTU()
287301

288302
// Set the transmit queue length
289303
ifrq := ifreqQLEN{Name: devName, Value: int32(t.TXQueueLen)}
290-
if err = ioctl(fd, unix.SIOCSIFTXQLEN, uintptr(unsafe.Pointer(&ifrq))); err != nil {
304+
if err = ioctl(t.ioctlFd, unix.SIOCSIFTXQLEN, uintptr(unsafe.Pointer(&ifrq))); err != nil {
291305
// If we can't set the queue length nebula will still work but it may lead to packet loss
292306
t.l.WithError(err).Error("Failed to set tun tx queue length")
293307
}
294308

295309
// Bring up the interface
296310
ifrf.Flags = ifrf.Flags | unix.IFF_UP
297-
if err = ioctl(fd, unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil {
311+
if err = ioctl(t.ioctlFd, unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil {
298312
return fmt.Errorf("failed to bring the tun device up: %s", err)
299313
}
300314

301-
// Set the routes
302315
link, err := netlink.LinkByName(t.Device)
303316
if err != nil {
304317
return fmt.Errorf("failed to get tun device link: %s", err)
305318
}
306-
307319
t.deviceIndex = link.Attrs().Index
308320

321+
if err = t.setDefaultRoute(); err != nil {
322+
return err
323+
}
324+
325+
// Set the routes
326+
if err = t.addRoutes(false); err != nil {
327+
return err
328+
}
329+
330+
// Run the interface
331+
ifrf.Flags = ifrf.Flags | unix.IFF_UP | unix.IFF_RUNNING
332+
if err = ioctl(t.ioctlFd, unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil {
333+
return fmt.Errorf("failed to run tun device: %s", err)
334+
}
335+
336+
return nil
337+
}
338+
339+
func (t *tun) setMTU() {
340+
// Set the MTU on the device
341+
ifm := ifreqMTU{Name: t.deviceBytes(), MTU: int32(t.MaxMTU)}
342+
if err := ioctl(t.ioctlFd, unix.SIOCSIFMTU, uintptr(unsafe.Pointer(&ifm))); err != nil {
343+
// This is currently a non fatal condition because the route table must have the MTU set appropriately as well
344+
t.l.WithError(err).Error("Failed to set tun mtu")
345+
}
346+
}
347+
348+
func (t *tun) setDefaultRoute() error {
309349
// Default route
310350
dr := &net.IPNet{IP: t.cidr.IP.Mask(t.cidr.Mask), Mask: t.cidr.Mask}
311351
nr := netlink.Route{
@@ -319,22 +359,11 @@ func (t *tun) Activate() error {
319359
Table: unix.RT_TABLE_MAIN,
320360
Type: unix.RTN_UNICAST,
321361
}
322-
err = netlink.RouteReplace(&nr)
362+
err := netlink.RouteReplace(&nr)
323363
if err != nil {
324364
return fmt.Errorf("failed to set mtu %v on the default route %v; %v", t.DefaultMTU, dr, err)
325365
}
326366

327-
err = t.addRoutes(false)
328-
if err != nil {
329-
return err
330-
}
331-
332-
// Run the interface
333-
ifrf.Flags = ifrf.Flags | unix.IFF_UP | unix.IFF_RUNNING
334-
if err = ioctl(fd, unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil {
335-
return fmt.Errorf("failed to run tun device: %s", err)
336-
}
337-
338367
return nil
339368
}
340369

@@ -499,5 +528,9 @@ func (t *tun) Close() error {
499528
t.ReadWriteCloser.Close()
500529
}
501530

531+
if t.ioctlFd > 0 {
532+
os.NewFile(t.ioctlFd, "ioctlFd").Close()
533+
}
534+
502535
return nil
503536
}

0 commit comments

Comments
 (0)