Skip to content

Commit ec5d56d

Browse files
committed
netstack/icmp: short-circuit to icmpForwarder
1 parent a4dfec5 commit ec5d56d

File tree

2 files changed

+33
-16
lines changed

2 files changed

+33
-16
lines changed

intra/netstack/icmp.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func (f *icmpForwarder) reply4(id stack.TransportEndpointID, pkt *stack.PacketBu
7373
l4hdr := pkt.TransportHeader().Slice()
7474
l3hdr := pkt.NetworkHeader().Slice()
7575
if len(l4hdr) < header.ICMPv4MinimumSize || len(l3hdr) < header.IPv4MinimumSize {
76-
log.E("icmp: v4: %s: invalid packet size; l4hdr: %d / l3hdr: %d", f.o, len(l4hdr), len(l3hdr))
76+
log.E("icmp: v4: %s: invalid packet size %d; l4hdr: %d / l3hdr: %d", f.o, pkt.Size(), len(l4hdr), len(l3hdr))
7777
return // not handled
7878
}
7979

@@ -167,14 +167,14 @@ func (f *icmpForwarder) reply6(id stack.TransportEndpointID, pkt *stack.PacketBu
167167
log.VV("icmp: v6: %s: packet? %v", f.o, pkt)
168168
}
169169

170-
if pkt == nil {
171-
log.E("icmp: v6: %s: nil packet", f.o)
170+
if pkt == nil || pkt.Size() <= 0 {
171+
log.E("icmp: v6: %s: nil packet (%t) or sz <= 0", f.o, pkt == nil)
172172
return // not handled
173173
}
174174

175175
l4hdr := pkt.TransportHeader().Slice()
176176
if len(l4hdr) < header.ICMPv6MinimumSize {
177-
log.E("icmp: v6: %s: invalid packet size; l4hdr: %d", f.o, len(l4hdr))
177+
log.E("icmp: v6: %s: invalid packet size %d; l4hdr: %d", f.o, pkt.Size(), len(l4hdr))
178178
return // not handled
179179
}
180180

intra/netstack/icmpecho.go

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,27 @@ func (r *icmpResponder) respond(pkt *stack.PacketBuffer) (handled bool) {
6363
if !r.ok() {
6464
return
6565
}
66-
return r.handle(pkt.NICID, pkt)
66+
h := hdlEcho.Load()
67+
if h == nil {
68+
log.E("icmp: responder: no handler")
69+
return
70+
}
71+
if useIcmpForwarder {
72+
var id stack.TransportEndpointID
73+
id.LocalAddress = pkt.Network().SourceAddress()
74+
id.RemoteAddress = pkt.Network().DestinationAddress()
75+
if settings.Debug {
76+
log.VV("icmp: responder: forward (sz: %d); src %s => dst %s",
77+
pkt.Size(), id.RemoteAddress, id.LocalAddress)
78+
}
79+
return icmpForward2(h, pkt, id)
80+
}
81+
return r.handle(h, pkt.NICID, pkt)
6782
}
6883

6984
// handle returns true if the packet is ICMP and is handled (or dropped) by the
7085
// bypass path.
71-
func (r *icmpResponder) handle(nic tcpip.NICID, pkt *stack.PacketBuffer) (handled bool) {
86+
func (r *icmpResponder) handle(h *icmpForwarder, nic tcpip.NICID, pkt *stack.PacketBuffer) (handled bool) {
7287
if !r.ok() {
7388
return
7489
}
@@ -85,7 +100,6 @@ func (r *icmpResponder) handle(nic tcpip.NICID, pkt *stack.PacketBuffer) (handle
85100

86101
v := c.ToView()
87102
b := v.ToSlice()
88-
h := hdlEcho.Load()
89103
n := len(b)
90104

91105
notok := n <= 0 || h == nil
@@ -111,7 +125,6 @@ func (r *icmpResponder) handle(nic tcpip.NICID, pkt *stack.PacketBuffer) (handle
111125
return
112126
}
113127

114-
// Capture fields before spawning the goroutine.
115128
src := parsed.Src
116129
dst := parsed.Dst
117130
has := parsed.HasTransportData()
@@ -135,7 +148,7 @@ func (r *icmpResponder) handle(nic tcpip.NICID, pkt *stack.PacketBuffer) (handle
135148

136149
if useIcmpForwarder {
137150
wire.Pool.Put(parsed)
138-
return r.forward(h, pkt, src, dst)
151+
return icmpForward(h, pkt, src, dst)
139152
} else {
140153
// Process asynchronously to avoid blocking the dispatcher loop.
141154
core.Gx("icmp.responder", func() {
@@ -146,10 +159,7 @@ func (r *icmpResponder) handle(nic tcpip.NICID, pkt *stack.PacketBuffer) (handle
146159
return true
147160
}
148161

149-
func (r *icmpResponder) forward(h *icmpForwarder, pkt *stack.PacketBuffer, src, dst netip.AddrPort) bool {
150-
pkt = pkt.Clone()
151-
defer pkt.DecRef()
152-
162+
func icmpForward(h *icmpForwarder, pkt *stack.PacketBuffer, src, dst netip.AddrPort) bool {
153163
// local is dst / remote is src; see: netstack/icmp/icmp.go:func (h *icmpForwarder) reply4
154164
// and netstack/icmp/icmp.go:func (h *icmpForwarder) reply6
155165
local := dst.Addr().AsSlice()
@@ -166,17 +176,24 @@ func (r *icmpResponder) forward(h *icmpForwarder, pkt *stack.PacketBuffer, src,
166176
id.RemoteAddress = tcpip.AddrFromSlice(remote)
167177
// ICMP does not use ports, so they remain zero.
168178

179+
return icmpForward2(h, pkt, id)
180+
}
181+
182+
func icmpForward2(h *icmpForwarder, pkt *stack.PacketBuffer, id stack.TransportEndpointID) bool {
183+
pkt = pkt.Clone()
184+
defer pkt.DecRef()
185+
169186
switch pkt.NetworkProtocolNumber {
170187
case header.IPv4ProtocolNumber:
171-
v, got := core.Await1(func() bool { defer pkt.DecRef(); return h.reply4(id, pkt.IncRef()) }, 3*time.Second)
188+
v, got := core.Await1(func() bool { defer pkt.DecRef(); return h.reply4(id, pkt.IncRef()) }, 5*time.Second)
172189
return got && v
173190
case header.IPv6ProtocolNumber:
174-
v, got := core.Await1(func() bool { defer pkt.DecRef(); return h.reply6(id, pkt.IncRef()) }, 3*time.Second)
191+
v, got := core.Await1(func() bool { defer pkt.DecRef(); return h.reply6(id, pkt.IncRef()) }, 5*time.Second)
175192
return got && v
176193
}
177194

178195
log.W("icmp: responder: unsupported proto: %d; %s => %s",
179-
pkt.NetworkProtocolNumber, src, dst)
196+
pkt.NetworkProtocolNumber, id.RemoteAddress, id.LocalAddress)
180197
return false
181198
}
182199

0 commit comments

Comments
 (0)