summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/network/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/tcpip/network/ipv4')
-rw-r--r--pkg/tcpip/network/ipv4/ipv4.go60
1 files changed, 25 insertions, 35 deletions
diff --git a/pkg/tcpip/network/ipv4/ipv4.go b/pkg/tcpip/network/ipv4/ipv4.go
index e1e05e39c..14cf786d2 100644
--- a/pkg/tcpip/network/ipv4/ipv4.go
+++ b/pkg/tcpip/network/ipv4/ipv4.go
@@ -441,47 +441,37 @@ func (e *endpoint) WritePackets(r *stack.Route, gso *stack.GSO, pkts stack.Packe
// iptables filtering. All packets that reach here are locally
// generated.
dropped, natPkts := e.protocol.stack.IPTables().CheckPackets(stack.Output, pkts, gso, r, "", outNicName)
- if len(dropped) == 0 && len(natPkts) == 0 {
- // Fast path: If no packets are to be dropped then we can just invoke the
- // faster WritePackets API directly.
- n, err := e.nic.WritePackets(r, gso, pkts, ProtocolNumber)
- stats.PacketsSent.IncrementBy(uint64(n))
- if err != nil {
- stats.OutgoingPacketErrors.IncrementBy(uint64(pkts.Len() - n))
- }
- return n, err
- }
stats.IPTablesOutputDropped.IncrementBy(uint64(len(dropped)))
+ for pkt := range dropped {
+ pkts.Remove(pkt)
+ }
- // Slow path as we are dropping some packets in the batch degrade to
- // emitting one packet at a time.
- n := 0
- for pkt := pkts.Front(); pkt != nil; pkt = pkt.Next() {
- if _, ok := dropped[pkt]; ok {
+ // The NAT-ed packets may now be destined for us.
+ locallyDelivered := 0
+ for pkt := range natPkts {
+ ep := e.protocol.stack.FindNetworkEndpoint(ProtocolNumber, header.IPv4(pkt.NetworkHeader().View()).DestinationAddress())
+ if ep == nil {
+ // The NAT-ed packet is still destined for some remote node.
continue
}
- if _, ok := natPkts[pkt]; ok {
- netHeader := header.IPv4(pkt.NetworkHeader().View())
- if ep := e.protocol.stack.FindNetworkEndpoint(ProtocolNumber, netHeader.DestinationAddress()); ep != nil {
- // Since we rewrote the packet but it is being routed back to us, we
- // can safely assume the checksum is valid.
- ep.(*endpoint).handleLocalPacket(pkt, true /* canSkipRXChecksum */)
- n++
- continue
- }
- }
- if err := e.nic.WritePacket(r, gso, ProtocolNumber, pkt); err != nil {
- stats.PacketsSent.IncrementBy(uint64(n))
- stats.OutgoingPacketErrors.IncrementBy(uint64(pkts.Len() - n - len(dropped)))
- // Dropped packets aren't errors, so include them in
- // the return value.
- return n + len(dropped), err
- }
- n++
+
+ // Do not send the locally destined packet out the NIC.
+ pkts.Remove(pkt)
+
+ // Deliver the packet locally.
+ ep.(*endpoint).handleLocalPacket(pkt, true)
+ locallyDelivered++
+
}
- stats.PacketsSent.IncrementBy(uint64(n))
+
+ // The rest of the packets can be delivered to the NIC as a batch.
+ pktsLen := pkts.Len()
+ written, err := e.nic.WritePackets(r, gso, pkts, ProtocolNumber)
+ stats.PacketsSent.IncrementBy(uint64(written))
+ stats.OutgoingPacketErrors.IncrementBy(uint64(pktsLen - written))
+
// Dropped packets aren't errors, so include them in the return value.
- return n + len(dropped), nil
+ return locallyDelivered + written + len(dropped), err
}
// WriteHeaderIncludedPacket implements stack.NetworkEndpoint.