aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2005-07-05 18:18:03 -0400
committerDavid S. Miller <davem@davemloft.net>2005-07-05 18:18:03 -0400
commitf6302d1d78f77c2d4c8bd32b0afc2df7fdf5f281 (patch)
tree204ae65914f845312059af3fbd633460bda820e9
parentfc6415bcb0f58f03adb910e56d7e1df6368794e0 (diff)
[TCP]: Move send test logic out of net/tcp.h
This just moves the code into tcp_output.c, no code logic changes are made by this patch. Using this as a baseline, we can begin to untangle the mess of comparisons for the Nagle test et al. We will also be able to reduce all of the redundant computation that occurs when outputting data packets. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/tcp.h113
-rw-r--r--net/ipv4/tcp_output.c150
2 files changed, 132 insertions, 131 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h
index afe41c5de2f2..f2b104532de1 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -849,6 +849,9 @@ extern __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb,
849/* tcp_output.c */ 849/* tcp_output.c */
850 850
851extern int tcp_write_xmit(struct sock *, int nonagle); 851extern int tcp_write_xmit(struct sock *, int nonagle);
852extern void __tcp_push_pending_frames(struct sock *sk, struct tcp_sock *tp,
853 unsigned cur_mss, int nonagle);
854extern int tcp_may_send_now(struct sock *sk, struct tcp_sock *tp);
852extern int tcp_retransmit_skb(struct sock *, struct sk_buff *); 855extern int tcp_retransmit_skb(struct sock *, struct sk_buff *);
853extern void tcp_xmit_retransmit_queue(struct sock *); 856extern void tcp_xmit_retransmit_queue(struct sock *);
854extern void tcp_simple_retransmit(struct sock *); 857extern void tcp_simple_retransmit(struct sock *);
@@ -1284,12 +1287,6 @@ static __inline__ __u32 tcp_max_burst(const struct tcp_sock *tp)
1284 return 3; 1287 return 3;
1285} 1288}
1286 1289
1287static __inline__ int tcp_minshall_check(const struct tcp_sock *tp)
1288{
1289 return after(tp->snd_sml,tp->snd_una) &&
1290 !after(tp->snd_sml, tp->snd_nxt);
1291}
1292
1293static __inline__ void tcp_minshall_update(struct tcp_sock *tp, int mss, 1290static __inline__ void tcp_minshall_update(struct tcp_sock *tp, int mss,
1294 const struct sk_buff *skb) 1291 const struct sk_buff *skb)
1295{ 1292{
@@ -1297,122 +1294,18 @@ static __inline__ void tcp_minshall_update(struct tcp_sock *tp, int mss,
1297 tp->snd_sml = TCP_SKB_CB(skb)->end_seq; 1294 tp->snd_sml = TCP_SKB_CB(skb)->end_seq;
1298} 1295}
1299 1296
1300/* Return 0, if packet can be sent now without violation Nagle's rules:
1301 1. It is full sized.
1302 2. Or it contains FIN.
1303 3. Or TCP_NODELAY was set.
1304 4. Or TCP_CORK is not set, and all sent packets are ACKed.
1305 With Minshall's modification: all sent small packets are ACKed.
1306 */
1307
1308static __inline__ int
1309tcp_nagle_check(const struct tcp_sock *tp, const struct sk_buff *skb,
1310 unsigned mss_now, int nonagle)
1311{
1312 return (skb->len < mss_now &&
1313 !(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
1314 ((nonagle&TCP_NAGLE_CORK) ||
1315 (!nonagle &&
1316 tp->packets_out &&
1317 tcp_minshall_check(tp))));
1318}
1319
1320extern void tcp_set_skb_tso_segs(struct sock *, struct sk_buff *);
1321
1322/* This checks if the data bearing packet SKB (usually sk->sk_send_head)
1323 * should be put on the wire right now.
1324 */
1325static __inline__ int tcp_snd_test(struct sock *sk,
1326 struct sk_buff *skb,
1327 unsigned cur_mss, int nonagle)
1328{
1329 struct tcp_sock *tp = tcp_sk(sk);
1330 int pkts = tcp_skb_pcount(skb);
1331
1332 if (!pkts) {
1333 tcp_set_skb_tso_segs(sk, skb);
1334 pkts = tcp_skb_pcount(skb);
1335 }
1336
1337 /* RFC 1122 - section 4.2.3.4
1338 *
1339 * We must queue if
1340 *
1341 * a) The right edge of this frame exceeds the window
1342 * b) There are packets in flight and we have a small segment
1343 * [SWS avoidance and Nagle algorithm]
1344 * (part of SWS is done on packetization)
1345 * Minshall version sounds: there are no _small_
1346 * segments in flight. (tcp_nagle_check)
1347 * c) We have too many packets 'in flight'
1348 *
1349 * Don't use the nagle rule for urgent data (or
1350 * for the final FIN -DaveM).
1351 *
1352 * Also, Nagle rule does not apply to frames, which
1353 * sit in the middle of queue (they have no chances
1354 * to get new data) and if room at tail of skb is
1355 * not enough to save something seriously (<32 for now).
1356 */
1357
1358 /* Don't be strict about the congestion window for the
1359 * final FIN frame. -DaveM
1360 */
1361 return (((nonagle&TCP_NAGLE_PUSH) || tp->urg_mode
1362 || !tcp_nagle_check(tp, skb, cur_mss, nonagle)) &&
1363 (((tcp_packets_in_flight(tp) + (pkts-1)) < tp->snd_cwnd) ||
1364 (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)) &&
1365 !after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd));
1366}
1367
1368static __inline__ void tcp_check_probe_timer(struct sock *sk, struct tcp_sock *tp) 1297static __inline__ void tcp_check_probe_timer(struct sock *sk, struct tcp_sock *tp)
1369{ 1298{
1370 if (!tp->packets_out && !tp->pending) 1299 if (!tp->packets_out && !tp->pending)
1371 tcp_reset_xmit_timer(sk, TCP_TIME_PROBE0, tp->rto); 1300 tcp_reset_xmit_timer(sk, TCP_TIME_PROBE0, tp->rto);
1372} 1301}
1373 1302
1374static __inline__ int tcp_skb_is_last(const struct sock *sk,
1375 const struct sk_buff *skb)
1376{
1377 return skb->next == (struct sk_buff *)&sk->sk_write_queue;
1378}
1379
1380/* Push out any pending frames which were held back due to
1381 * TCP_CORK or attempt at coalescing tiny packets.
1382 * The socket must be locked by the caller.
1383 */
1384static __inline__ void __tcp_push_pending_frames(struct sock *sk,
1385 struct tcp_sock *tp,
1386 unsigned cur_mss,
1387 int nonagle)
1388{
1389 struct sk_buff *skb = sk->sk_send_head;
1390
1391 if (skb) {
1392 if (!tcp_skb_is_last(sk, skb))
1393 nonagle = TCP_NAGLE_PUSH;
1394 if (!tcp_snd_test(sk, skb, cur_mss, nonagle) ||
1395 tcp_write_xmit(sk, nonagle))
1396 tcp_check_probe_timer(sk, tp);
1397 }
1398 tcp_cwnd_validate(sk, tp);
1399}
1400
1401static __inline__ void tcp_push_pending_frames(struct sock *sk, 1303static __inline__ void tcp_push_pending_frames(struct sock *sk,
1402 struct tcp_sock *tp) 1304 struct tcp_sock *tp)
1403{ 1305{
1404 __tcp_push_pending_frames(sk, tp, tcp_current_mss(sk, 1), tp->nonagle); 1306 __tcp_push_pending_frames(sk, tp, tcp_current_mss(sk, 1), tp->nonagle);
1405} 1307}
1406 1308
1407static __inline__ int tcp_may_send_now(struct sock *sk, struct tcp_sock *tp)
1408{
1409 struct sk_buff *skb = sk->sk_send_head;
1410
1411 return (skb &&
1412 tcp_snd_test(sk, skb, tcp_current_mss(sk, 1),
1413 tcp_skb_is_last(sk, skb) ? TCP_NAGLE_PUSH : tp->nonagle));
1414}
1415
1416static __inline__ void tcp_init_wl(struct tcp_sock *tp, u32 ack, u32 seq) 1309static __inline__ void tcp_init_wl(struct tcp_sock *tp, u32 ack, u32 seq)
1417{ 1310{
1418 tp->snd_wl1 = seq; 1311 tp->snd_wl1 = seq;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 389deeb2a457..2cbe879ee16a 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -413,6 +413,135 @@ static inline void tcp_tso_set_push(struct sk_buff *skb)
413 TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH; 413 TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
414} 414}
415 415
416static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb)
417{
418 struct tcp_sock *tp = tcp_sk(sk);
419
420 if (skb->len <= tp->mss_cache_std ||
421 !(sk->sk_route_caps & NETIF_F_TSO)) {
422 /* Avoid the costly divide in the normal
423 * non-TSO case.
424 */
425 skb_shinfo(skb)->tso_segs = 1;
426 skb_shinfo(skb)->tso_size = 0;
427 } else {
428 unsigned int factor;
429
430 factor = skb->len + (tp->mss_cache_std - 1);
431 factor /= tp->mss_cache_std;
432 skb_shinfo(skb)->tso_segs = factor;
433 skb_shinfo(skb)->tso_size = tp->mss_cache_std;
434 }
435}
436
437static inline int tcp_minshall_check(const struct tcp_sock *tp)
438{
439 return after(tp->snd_sml,tp->snd_una) &&
440 !after(tp->snd_sml, tp->snd_nxt);
441}
442
443/* Return 0, if packet can be sent now without violation Nagle's rules:
444 * 1. It is full sized.
445 * 2. Or it contains FIN.
446 * 3. Or TCP_NODELAY was set.
447 * 4. Or TCP_CORK is not set, and all sent packets are ACKed.
448 * With Minshall's modification: all sent small packets are ACKed.
449 */
450
451static inline int tcp_nagle_check(const struct tcp_sock *tp,
452 const struct sk_buff *skb,
453 unsigned mss_now, int nonagle)
454{
455 return (skb->len < mss_now &&
456 !(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
457 ((nonagle&TCP_NAGLE_CORK) ||
458 (!nonagle &&
459 tp->packets_out &&
460 tcp_minshall_check(tp))));
461}
462
463/* This checks if the data bearing packet SKB (usually sk->sk_send_head)
464 * should be put on the wire right now.
465 */
466static int tcp_snd_test(struct sock *sk, struct sk_buff *skb,
467 unsigned cur_mss, int nonagle)
468{
469 struct tcp_sock *tp = tcp_sk(sk);
470 int pkts = tcp_skb_pcount(skb);
471
472 if (!pkts) {
473 tcp_set_skb_tso_segs(sk, skb);
474 pkts = tcp_skb_pcount(skb);
475 }
476
477 /* RFC 1122 - section 4.2.3.4
478 *
479 * We must queue if
480 *
481 * a) The right edge of this frame exceeds the window
482 * b) There are packets in flight and we have a small segment
483 * [SWS avoidance and Nagle algorithm]
484 * (part of SWS is done on packetization)
485 * Minshall version sounds: there are no _small_
486 * segments in flight. (tcp_nagle_check)
487 * c) We have too many packets 'in flight'
488 *
489 * Don't use the nagle rule for urgent data (or
490 * for the final FIN -DaveM).
491 *
492 * Also, Nagle rule does not apply to frames, which
493 * sit in the middle of queue (they have no chances
494 * to get new data) and if room at tail of skb is
495 * not enough to save something seriously (<32 for now).
496 */
497
498 /* Don't be strict about the congestion window for the
499 * final FIN frame. -DaveM
500 */
501 return (((nonagle&TCP_NAGLE_PUSH) || tp->urg_mode
502 || !tcp_nagle_check(tp, skb, cur_mss, nonagle)) &&
503 (((tcp_packets_in_flight(tp) + (pkts-1)) < tp->snd_cwnd) ||
504 (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)) &&
505 !after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd));
506}
507
508static inline int tcp_skb_is_last(const struct sock *sk,
509 const struct sk_buff *skb)
510{
511 return skb->next == (struct sk_buff *)&sk->sk_write_queue;
512}
513
514/* Push out any pending frames which were held back due to
515 * TCP_CORK or attempt at coalescing tiny packets.
516 * The socket must be locked by the caller.
517 */
518void __tcp_push_pending_frames(struct sock *sk, struct tcp_sock *tp,
519 unsigned cur_mss, int nonagle)
520{
521 struct sk_buff *skb = sk->sk_send_head;
522
523 if (skb) {
524 if (!tcp_skb_is_last(sk, skb))
525 nonagle = TCP_NAGLE_PUSH;
526 if (!tcp_snd_test(sk, skb, cur_mss, nonagle) ||
527 tcp_write_xmit(sk, nonagle))
528 tcp_check_probe_timer(sk, tp);
529 }
530 tcp_cwnd_validate(sk, tp);
531}
532
533int tcp_may_send_now(struct sock *sk, struct tcp_sock *tp)
534{
535 struct sk_buff *skb = sk->sk_send_head;
536
537 return (skb &&
538 tcp_snd_test(sk, skb, tcp_current_mss(sk, 1),
539 (tcp_skb_is_last(sk, skb) ?
540 TCP_NAGLE_PUSH :
541 tp->nonagle)));
542}
543
544
416/* Send _single_ skb sitting at the send head. This function requires 545/* Send _single_ skb sitting at the send head. This function requires
417 * true push pending frames to setup probe timer etc. 546 * true push pending frames to setup probe timer etc.
418 */ 547 */
@@ -434,27 +563,6 @@ void tcp_push_one(struct sock *sk, unsigned cur_mss)
434 } 563 }
435} 564}
436 565
437void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb)
438{
439 struct tcp_sock *tp = tcp_sk(sk);
440
441 if (skb->len <= tp->mss_cache_std ||
442 !(sk->sk_route_caps & NETIF_F_TSO)) {
443 /* Avoid the costly divide in the normal
444 * non-TSO case.
445 */
446 skb_shinfo(skb)->tso_segs = 1;
447 skb_shinfo(skb)->tso_size = 0;
448 } else {
449 unsigned int factor;
450
451 factor = skb->len + (tp->mss_cache_std - 1);
452 factor /= tp->mss_cache_std;
453 skb_shinfo(skb)->tso_segs = factor;
454 skb_shinfo(skb)->tso_size = tp->mss_cache_std;
455 }
456}
457
458/* Function to create two new TCP segments. Shrinks the given segment 566/* Function to create two new TCP segments. Shrinks the given segment
459 * to the specified size and appends a new segment with the rest of the 567 * to the specified size and appends a new segment with the rest of the
460 * packet to the list. This won't be called frequently, I hope. 568 * packet to the list. This won't be called frequently, I hope.