Skip to content

Commit c194ce7

Browse files
pkitgvisor-bot
authored andcommitted
tcpip: fix IP_MTU_DISCOVER flag for tcp and udp
Fixes #12319 This patch only supports various IP_MTU_DISCOVER flags. To fully support `tracepath` actually tracing the path the correct propagation of TTL exceeded is needed. FUTURE_COPYBARA_INTEGRATE_REVIEW=#12366 from pkit:pmtu_probe_support 5ca5162 PiperOrigin-RevId: 844591169
1 parent e79ac37 commit c194ce7

File tree

5 files changed

+48
-22
lines changed

5 files changed

+48
-22
lines changed

pkg/tcpip/network/ipv4/ipv4.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -609,9 +609,7 @@ func (e *endpoint) writePacketPostRouting(r *stack.Route, pkt *stack.PacketBuffe
609609

610610
if packetMustBeFragmented(pkt, networkMTU) {
611611
h := header.IPv4(pkt.NetworkHeader().Slice())
612-
if h.Flags()&header.IPv4FlagDontFragment != 0 && pkt.NetworkPacketInfo.IsForwardedPacket {
613-
// TODO(gvisor.dev/issue/5919): Handle error condition in which DontFragment
614-
// is set but the packet must be fragmented for the non-forwarding case.
612+
if h.Flags()&header.IPv4FlagDontFragment != 0 {
615613
return &tcpip.ErrMessageTooLong{}
616614
}
617615
sent, remain, err := e.handleFragments(r, networkMTU, pkt, func(fragPkt *stack.PacketBuffer) tcpip.Error {

pkg/tcpip/transport/internal/network/endpoint.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ type Endpoint struct {
7474
ipv4TOS uint8
7575
// +checklocks:mu
7676
ipv6TClass uint8
77+
// +checklocks:mu
78+
pmtudStrategy tcpip.PMTUDStrategy
7779

7880
// Lock ordering: mu > infoMu.
7981
infoMu sync.RWMutex `state:"nosave"`
@@ -358,10 +360,15 @@ func (c *WriteContext) WritePacket(pkt *stack.PacketBuffer, headerIncluded bool)
358360
expOptVal = c.e.ops.GetExperimentOptionValue()
359361
}
360362

363+
c.e.mu.RLock()
364+
pmtud := c.e.pmtudStrategy
365+
c.e.mu.RUnlock()
366+
361367
err := c.route.WritePacket(stack.NetworkHeaderParams{
362368
Protocol: c.e.transProto,
363369
TTL: c.ttl,
364370
TOS: c.tos,
371+
DF: pmtud == tcpip.PMTUDiscoveryWant || pmtud == tcpip.PMTUDiscoveryDo || pmtud == tcpip.PMTUDiscoveryProbe,
365372
ExperimentOptionValue: expOptVal,
366373
}, pkt)
367374

@@ -840,9 +847,13 @@ func (e *Endpoint) GetRemoteAddress() (tcpip.FullAddress, bool) {
840847
func (e *Endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) tcpip.Error {
841848
switch opt {
842849
case tcpip.MTUDiscoverOption:
843-
// Return not supported if the value is not disabling path
844-
// MTU discovery.
845-
if tcpip.PMTUDStrategy(v) != tcpip.PMTUDiscoveryDont {
850+
strategy := tcpip.PMTUDStrategy(v)
851+
switch strategy {
852+
case tcpip.PMTUDiscoveryWant, tcpip.PMTUDiscoveryDont, tcpip.PMTUDiscoveryDo, tcpip.PMTUDiscoveryProbe:
853+
e.mu.Lock()
854+
e.pmtudStrategy = strategy
855+
e.mu.Unlock()
856+
default:
846857
return &tcpip.ErrNotSupported{}
847858
}
848859

@@ -891,8 +902,10 @@ func (e *Endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) tcpip.Error {
891902
func (e *Endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, tcpip.Error) {
892903
switch opt {
893904
case tcpip.MTUDiscoverOption:
894-
// The only supported setting is path MTU discovery disabled.
895-
return int(tcpip.PMTUDiscoveryDont), nil
905+
e.mu.Lock()
906+
v := int(e.pmtudStrategy)
907+
e.mu.Unlock()
908+
return v, nil
896909

897910
case tcpip.MulticastTTLOption:
898911
e.mu.Lock()

pkg/tcpip/transport/tcp/connect.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1042,7 +1042,7 @@ func (e *Endpoint) sendRaw(pkt *stack.PacketBuffer, flags header.TCPFlags, seq,
10421042
ack: ack,
10431043
rcvWnd: rcvWnd,
10441044
opts: options,
1045-
df: e.pmtud == tcpip.PMTUDiscoveryWant || e.pmtud == tcpip.PMTUDiscoveryDo,
1045+
df: e.pmtud == tcpip.PMTUDiscoveryWant || e.pmtud == tcpip.PMTUDiscoveryDo || e.pmtud == tcpip.PMTUDiscoveryProbe,
10461046
expOptVal: expOptVal,
10471047
}, pkt, e.gso)
10481048
}

pkg/tcpip/transport/tcp/endpoint.go

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1895,18 +1895,9 @@ func (e *Endpoint) SetSockOptInt(opt tcpip.SockOptInt, v int) tcpip.Error {
18951895
e.UnlockUser()
18961896

18971897
case tcpip.MTUDiscoverOption:
1898-
switch v := tcpip.PMTUDStrategy(v); v {
1899-
case tcpip.PMTUDiscoveryWant, tcpip.PMTUDiscoveryDont, tcpip.PMTUDiscoveryDo:
1900-
e.LockUser()
1901-
e.pmtud = v
1902-
e.UnlockUser()
1903-
case tcpip.PMTUDiscoveryProbe:
1904-
// We don't support a way to ignore MTU updates; it's
1905-
// either on or it's off.
1906-
return &tcpip.ErrNotSupported{}
1907-
default:
1908-
return &tcpip.ErrNotSupported{}
1909-
}
1898+
e.LockUser()
1899+
e.pmtud = tcpip.PMTUDStrategy(v)
1900+
e.UnlockUser()
19101901

19111902
case tcpip.IPv4TTLOption:
19121903
e.LockUser()
@@ -2965,7 +2956,14 @@ func (e *Endpoint) HandleError(transErr stack.TransportError, pkt *stack.PacketB
29652956
// TODO(gvisor.dev/issues/5270): Handle all transport errors.
29662957
switch transErr.Kind() {
29672958
case stack.PacketTooBigTransportError:
2968-
handlePacketTooBig(transErr.Info())
2959+
e.mu.Lock()
2960+
pmtud := e.pmtud
2961+
e.mu.Unlock()
2962+
if pmtud == tcpip.PMTUDiscoveryProbe {
2963+
e.onICMPError(&tcpip.ErrMessageTooLong{}, transErr, pkt)
2964+
} else {
2965+
handlePacketTooBig(transErr.Info())
2966+
}
29692967
case stack.DestinationHostUnreachableTransportError:
29702968
e.onICMPError(&tcpip.ErrHostUnreachable{}, transErr, pkt)
29712969
case stack.DestinationNetworkUnreachableTransportError:

pkg/tcpip/transport/udp/endpoint.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,21 @@ func (e *endpoint) write(p tcpip.Payloader, opts tcpip.WriteOptions) (int64, tcp
520520
}
521521
if err := udpInfo.ctx.WritePacket(pkt, false /* headerIncluded */); err != nil {
522522
e.stack.Stats().UDP.PacketSendErrors.Increment()
523+
if _, ok := err.(*tcpip.ErrMessageTooLong); ok {
524+
so := e.SocketOptions()
525+
if so.GetIPv4RecvError() || so.GetIPv6RecvError() {
526+
so.QueueLocalErr(
527+
err,
528+
udpInfo.ctx.PacketInfo().NetProto,
529+
udpInfo.ctx.MTU(),
530+
tcpip.FullAddress{
531+
Addr: udpInfo.ctx.PacketInfo().RemoteAddress,
532+
Port: udpInfo.remotePort,
533+
},
534+
nil,
535+
)
536+
}
537+
}
523538
return 0, err
524539
}
525540

@@ -1050,6 +1065,8 @@ func (e *endpoint) HandleError(transErr stack.TransportError, pkt *stack.PacketB
10501065
if e.net.State() == transport.DatagramEndpointStateConnected {
10511066
e.onICMPError(&tcpip.ErrConnectionRefused{}, transErr, pkt)
10521067
}
1068+
case stack.PacketTooBigTransportError:
1069+
e.onICMPError(&tcpip.ErrMessageTooLong{}, transErr, pkt)
10531070
}
10541071
}
10551072

0 commit comments

Comments
 (0)