aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>2016-08-18 13:58:35 -0400
committerDavid S. Miller <davem@davemloft.net>2016-08-19 20:09:42 -0400
commit4c2f2454964477c66ef57745daab203b71783f66 (patch)
tree51f1daf90f01ee0775b82eab4727edbe36a80457
parent187335cdfec32475677b8ea2e7a165843fc38675 (diff)
sctp: linearize early if it's not GSO
Because otherwise when crc computation is still needed it's way more expensive than on a linear buffer to the point that it affects performance. It's so expensive that netperf test gives a perf output as below: Overhead Command Shared Object Symbol 18,62% netserver [kernel.vmlinux] [k] crc32_generic_shift 2,57% netserver [kernel.vmlinux] [k] __pskb_pull_tail 1,94% netserver [kernel.vmlinux] [k] fib_table_lookup 1,90% netserver [kernel.vmlinux] [k] copy_user_enhanced_fast_string 1,66% swapper [kernel.vmlinux] [k] intel_idle 1,63% netserver [kernel.vmlinux] [k] _raw_spin_lock 1,59% netserver [sctp] [k] sctp_packet_transmit 1,55% netserver [kernel.vmlinux] [k] memcpy_erms 1,42% netserver [sctp] [k] sctp_rcv # netperf -H 192.168.10.1 -l 10 -t SCTP_STREAM -cC -- -m 12000 SCTP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.10.1 () port 0 AF_INET Recv Send Send Utilization Service Demand Socket Socket Message Elapsed Send Recv Send Recv Size Size Size Time Throughput local remote local remote bytes bytes bytes secs. 10^6bits/s % S % S us/KB us/KB 212992 212992 12000 10.00 3016.42 2.88 3.78 1.874 2.462 After patch: Overhead Command Shared Object Symbol 2,75% netserver [kernel.vmlinux] [k] memcpy_erms 2,63% netserver [kernel.vmlinux] [k] copy_user_enhanced_fast_string 2,39% netserver [kernel.vmlinux] [k] fib_table_lookup 2,04% netserver [kernel.vmlinux] [k] __pskb_pull_tail 1,91% netserver [kernel.vmlinux] [k] _raw_spin_lock 1,91% netserver [sctp] [k] sctp_packet_transmit 1,72% netserver [mlx4_en] [k] mlx4_en_process_rx_cq 1,68% netserver [sctp] [k] sctp_rcv # netperf -H 192.168.10.1 -l 10 -t SCTP_STREAM -cC -- -m 12000 SCTP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.10.1 () port 0 AF_INET Recv Send Send Utilization Service Demand Socket Socket Message Elapsed Send Recv Send Recv Size Size Size Time Throughput local remote local remote bytes bytes bytes secs. 10^6bits/s % S % S us/KB us/KB 212992 212992 12000 10.00 3681.77 3.83 3.46 2.045 1.849 Fixes: 3acb50c18d8d ("sctp: delay as much as possible skb_linearize") Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/sctp/input.c11
-rw-r--r--net/sctp/inqueue.c13
2 files changed, 7 insertions, 17 deletions
diff --git a/net/sctp/input.c b/net/sctp/input.c
index c182db7d691f..69444d32ecda 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -119,7 +119,13 @@ int sctp_rcv(struct sk_buff *skb)
119 skb_transport_offset(skb)) 119 skb_transport_offset(skb))
120 goto discard_it; 120 goto discard_it;
121 121
122 if (!pskb_may_pull(skb, sizeof(struct sctphdr))) 122 /* If the packet is fragmented and we need to do crc checking,
123 * it's better to just linearize it otherwise crc computing
124 * takes longer.
125 */
126 if ((!(skb_shinfo(skb)->gso_type & SKB_GSO_SCTP) &&
127 skb_linearize(skb)) ||
128 !pskb_may_pull(skb, sizeof(struct sctphdr)))
123 goto discard_it; 129 goto discard_it;
124 130
125 /* Pull up the IP header. */ 131 /* Pull up the IP header. */
@@ -1177,9 +1183,6 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct net *net,
1177 if ((skb_shinfo(skb)->gso_type & SKB_GSO_SCTP) == SKB_GSO_SCTP) 1183 if ((skb_shinfo(skb)->gso_type & SKB_GSO_SCTP) == SKB_GSO_SCTP)
1178 return NULL; 1184 return NULL;
1179 1185
1180 if (skb_linearize(skb))
1181 return NULL;
1182
1183 ch = (sctp_chunkhdr_t *) skb->data; 1186 ch = (sctp_chunkhdr_t *) skb->data;
1184 1187
1185 /* The code below will attempt to walk the chunk and extract 1188 /* The code below will attempt to walk the chunk and extract
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
index c30ddb0f3190..6437aa97cfd7 100644
--- a/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -170,19 +170,6 @@ next_chunk:
170 170
171 chunk = list_entry(entry, struct sctp_chunk, list); 171 chunk = list_entry(entry, struct sctp_chunk, list);
172 172
173 /* Linearize if it's not GSO */
174 if ((skb_shinfo(chunk->skb)->gso_type & SKB_GSO_SCTP) != SKB_GSO_SCTP &&
175 skb_is_nonlinear(chunk->skb)) {
176 if (skb_linearize(chunk->skb)) {
177 __SCTP_INC_STATS(dev_net(chunk->skb->dev), SCTP_MIB_IN_PKT_DISCARDS);
178 sctp_chunk_free(chunk);
179 goto next_chunk;
180 }
181
182 /* Update sctp_hdr as it probably changed */
183 chunk->sctp_hdr = sctp_hdr(chunk->skb);
184 }
185
186 if ((skb_shinfo(chunk->skb)->gso_type & SKB_GSO_SCTP) == SKB_GSO_SCTP) { 173 if ((skb_shinfo(chunk->skb)->gso_type & SKB_GSO_SCTP) == SKB_GSO_SCTP) {
187 /* GSO-marked skbs but without frags, handle 174 /* GSO-marked skbs but without frags, handle
188 * them normally 175 * them normally