Commit 686ccb6e authored by David S. Miller's avatar David S. Miller

[TCP]: Kill tso_{factor,mss}.

We can just use skb_shinfo(skb)->tso_{segs,size}
directly.  This also allows us to kill the
hack zone code in ip_output.c

The original impetus for thus change was a problem
noted by John Heffner.  We do not abide by the MSS
of the connection for TCP segmentation, we were using
the path MTU instead.  This broke various local
network setups with TSO enabled and is fixed as a side
effect of these changes.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 008f4d3c
......@@ -1152,8 +1152,6 @@ struct tcp_skb_cb {
__u16 urg_ptr; /* Valid w/URG flags is set. */
__u32 ack_seq; /* Sequence number ACK'd */
__u16 tso_factor; /* If > 1, TSO frame */
__u16 tso_mss; /* MSS that FACTOR's in terms of*/
};
#define TCP_SKB_CB(__skb) ((struct tcp_skb_cb *)&((__skb)->cb[0]))
......@@ -1165,7 +1163,13 @@ struct tcp_skb_cb {
*/
static inline int tcp_skb_pcount(struct sk_buff *skb)
{
return TCP_SKB_CB(skb)->tso_factor;
return skb_shinfo(skb)->tso_segs;
}
/* This is valid iff tcp_skb_pcount() > 1. */
static inline int tcp_skb_psize(struct sk_buff *skb)
{
return skb_shinfo(skb)->tso_size;
}
static inline void tcp_inc_pcount(tcp_pcount_t *count, struct sk_buff *skb)
......@@ -1440,7 +1444,7 @@ tcp_nagle_check(struct tcp_opt *tp, struct sk_buff *skb, unsigned mss_now, int n
tcp_minshall_check(tp))));
}
extern void tcp_set_skb_tso_factor(struct sk_buff *, unsigned int);
extern void tcp_set_skb_tso_segs(struct sk_buff *, unsigned int);
/* This checks if the data bearing packet SKB (usually sk->sk_send_head)
* should be put on the wire right now.
......@@ -1448,11 +1452,11 @@ extern void tcp_set_skb_tso_factor(struct sk_buff *, unsigned int);
static __inline__ int tcp_snd_test(struct tcp_opt *tp, struct sk_buff *skb,
unsigned cur_mss, int nonagle)
{
int pkts = TCP_SKB_CB(skb)->tso_factor;
int pkts = tcp_skb_pcount(skb);
if (!pkts) {
tcp_set_skb_tso_factor(skb, tp->mss_cache_std);
pkts = TCP_SKB_CB(skb)->tso_factor;
tcp_set_skb_tso_segs(skb, tp->mss_cache_std);
pkts = tcp_skb_pcount(skb);
}
/* RFC 1122 - section 4.2.3.4
......
......@@ -305,7 +305,6 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
struct ip_options *opt = inet->opt;
struct rtable *rt;
struct iphdr *iph;
u32 mtu;
/* Skip all of this if the packet is already routed,
* f.e. by something like SCTP.
......@@ -366,23 +365,11 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
skb->nh.iph = iph;
/* Transport layer set skb->h.foo itself. */
if(opt && opt->optlen) {
if (opt && opt->optlen) {
iph->ihl += opt->optlen >> 2;
ip_options_build(skb, opt, inet->daddr, rt, 0);
}
mtu = dst_pmtu(&rt->u.dst);
if (skb->len > mtu && (sk->sk_route_caps & NETIF_F_TSO)) {
unsigned int hlen;
/* Hack zone: all this must be done by TCP. */
hlen = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
skb_shinfo(skb)->tso_size = mtu - hlen;
skb_shinfo(skb)->tso_segs =
(skb->len - hlen + skb_shinfo(skb)->tso_size - 1)/
skb_shinfo(skb)->tso_size - 1;
}
ip_select_ident_more(iph, &rt->u.dst, sk, skb_shinfo(skb)->tso_segs);
/* Add an IP checksum. */
......
......@@ -691,7 +691,7 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffse
skb->ip_summed = CHECKSUM_HW;
tp->write_seq += copy;
TCP_SKB_CB(skb)->end_seq += copy;
TCP_SKB_CB(skb)->tso_factor = 0;
skb_shinfo(skb)->tso_segs = 0;
if (!copied)
TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_PSH;
......@@ -938,7 +938,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
tp->write_seq += copy;
TCP_SKB_CB(skb)->end_seq += copy;
TCP_SKB_CB(skb)->tso_factor = 0;
skb_shinfo(skb)->tso_segs = 0;
from += copy;
copied += copy;
......
......@@ -1035,7 +1035,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
if(!before(TCP_SKB_CB(skb)->seq, end_seq))
break;
fack_count += TCP_SKB_CB(skb)->tso_factor;
fack_count += tcp_skb_pcount(skb);
in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) &&
!before(end_seq, TCP_SKB_CB(skb)->end_seq);
......@@ -1224,7 +1224,7 @@ static void tcp_enter_frto_loss(struct sock *sk)
tcp_set_pcount(&tp->fackets_out, 0);
sk_stream_for_retrans_queue(skb, sk) {
cnt += TCP_SKB_CB(skb)->tso_factor;;
cnt += tcp_skb_pcount(skb);
TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED)) {
......@@ -1299,7 +1299,7 @@ void tcp_enter_loss(struct sock *sk, int how)
tp->undo_marker = tp->snd_una;
sk_stream_for_retrans_queue(skb, sk) {
cnt += TCP_SKB_CB(skb)->tso_factor;
cnt += tcp_skb_pcount(skb);
if (TCP_SKB_CB(skb)->sacked&TCPCB_RETRANS)
tp->undo_marker = 0;
TCP_SKB_CB(skb)->sacked &= (~TCPCB_TAGBITS)|TCPCB_SACKED_ACKED;
......@@ -1550,7 +1550,7 @@ tcp_mark_head_lost(struct sock *sk, struct tcp_opt *tp, int packets, u32 high_se
BUG_TRAP(cnt <= tcp_get_pcount(&tp->packets_out));
sk_stream_for_retrans_queue(skb, sk) {
cnt -= TCP_SKB_CB(skb)->tso_factor;
cnt -= tcp_skb_pcount(skb);
if (cnt < 0 || after(TCP_SKB_CB(skb)->end_seq, high_seq))
break;
if (!(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) {
......@@ -2369,7 +2369,7 @@ static int tcp_tso_acked(struct sock *sk, struct sk_buff *skb,
{
struct tcp_opt *tp = tcp_sk(sk);
struct tcp_skb_cb *scb = TCP_SKB_CB(skb);
__u32 mss = scb->tso_mss;
__u32 mss = tcp_skb_psize(skb);
__u32 snd_una = tp->snd_una;
__u32 orig_seq, seq;
__u32 packets_acked = 0;
......@@ -2423,7 +2423,7 @@ static int tcp_tso_acked(struct sock *sk, struct sk_buff *skb,
}
tcp_dec_pcount_explicit(&tp->packets_out, packets_acked);
BUG_ON(scb->tso_factor == 0);
BUG_ON(tcp_skb_pcount(skb) == 0);
BUG_ON(!before(scb->seq, scb->end_seq));
}
......@@ -2450,7 +2450,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
* the other end.
*/
if (after(scb->end_seq, tp->snd_una)) {
if (scb->tso_factor > 1)
if (tcp_skb_pcount(skb) > 1)
acked |= tcp_tso_acked(sk, skb,
now, &seq_rtt);
break;
......
......@@ -274,7 +274,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
int sysctl_flags;
int err;
BUG_ON(!TCP_SKB_CB(skb)->tso_factor);
BUG_ON(!tcp_skb_pcount(skb));
#define SYSCTL_FLAG_TSTAMPS 0x1
#define SYSCTL_FLAG_WSCALE 0x2
......@@ -428,21 +428,22 @@ void tcp_push_one(struct sock *sk, unsigned cur_mss)
}
}
void tcp_set_skb_tso_factor(struct sk_buff *skb, unsigned int mss_std)
void tcp_set_skb_tso_segs(struct sk_buff *skb, unsigned int mss_std)
{
if (skb->len <= mss_std) {
/* Avoid the costly divide in the normal
* non-TSO case.
*/
TCP_SKB_CB(skb)->tso_factor = 1;
skb_shinfo(skb)->tso_segs = 1;
skb_shinfo(skb)->tso_size = 0;
} else {
unsigned int factor;
factor = skb->len + (mss_std - 1);
factor /= mss_std;
TCP_SKB_CB(skb)->tso_factor = factor;
skb_shinfo(skb)->tso_segs = factor;
skb_shinfo(skb)->tso_size = mss_std;
}
TCP_SKB_CB(skb)->tso_mss = mss_std;
}
/* Function to create two new TCP segments. Shrinks the given segment
......@@ -508,8 +509,8 @@ static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len)
}
/* Fix up tso_factor for both original and new SKB. */
tcp_set_skb_tso_factor(skb, tp->mss_cache_std);
tcp_set_skb_tso_factor(buff, tp->mss_cache_std);
tcp_set_skb_tso_segs(skb, tp->mss_cache_std);
tcp_set_skb_tso_segs(buff, tp->mss_cache_std);
if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
tcp_inc_pcount(&tp->lost_out, skb);
......@@ -585,7 +586,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
/* Any change of skb->len requires recalculation of tso
* factor and mss.
*/
tcp_set_skb_tso_factor(skb, tp->mss_cache_std);
tcp_set_skb_tso_segs(skb, tp->mss_cache_std);
return 0;
}
......@@ -914,8 +915,8 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m
((skb_size + next_skb_size) > mss_now))
return;
BUG_ON(TCP_SKB_CB(skb)->tso_factor != 1 ||
TCP_SKB_CB(next_skb)->tso_factor != 1);
BUG_ON(tcp_skb_pcount(skb) != 1 ||
tcp_skb_pcount(next_skb) != 1);
/* Ok. We will be able to collapse the packet. */
__skb_unlink(next_skb, next_skb->list);
......@@ -1047,14 +1048,14 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
return -EAGAIN;
if (skb->len > cur_mss) {
int old_factor = TCP_SKB_CB(skb)->tso_factor;
int old_factor = tcp_skb_pcount(skb);
int new_factor;
if (tcp_fragment(sk, skb, cur_mss))
return -ENOMEM; /* We'll try again later. */
/* New SKB created, account for it. */
new_factor = TCP_SKB_CB(skb)->tso_factor;
new_factor = tcp_skb_pcount(skb);
tcp_dec_pcount_explicit(&tp->packets_out,
old_factor - new_factor);
tcp_inc_pcount(&tp->packets_out, skb->next);
......@@ -1081,7 +1082,8 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) {
if (!pskb_trim(skb, 0)) {
TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1;
TCP_SKB_CB(skb)->tso_factor = 1;
skb_shinfo(skb)->tso_segs = 1;
skb_shinfo(skb)->tso_size = 0;
skb->ip_summed = CHECKSUM_NONE;
skb->csum = 0;
}
......@@ -1166,7 +1168,7 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
}
packet_cnt -= TCP_SKB_CB(skb)->tso_factor;
packet_cnt -= tcp_skb_pcount(skb);
if (packet_cnt <= 0)
break;
}
......@@ -1256,8 +1258,8 @@ void tcp_send_fin(struct sock *sk)
skb->csum = 0;
TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_FIN);
TCP_SKB_CB(skb)->sacked = 0;
TCP_SKB_CB(skb)->tso_factor = 1;
TCP_SKB_CB(skb)->tso_mss = tp->mss_cache_std;
skb_shinfo(skb)->tso_segs = 1;
skb_shinfo(skb)->tso_size = 0;
/* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */
TCP_SKB_CB(skb)->seq = tp->write_seq;
......@@ -1289,8 +1291,8 @@ void tcp_send_active_reset(struct sock *sk, int priority)
skb->csum = 0;
TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_RST);
TCP_SKB_CB(skb)->sacked = 0;
TCP_SKB_CB(skb)->tso_factor = 1;
TCP_SKB_CB(skb)->tso_mss = tp->mss_cache_std;
skb_shinfo(skb)->tso_segs = 1;
skb_shinfo(skb)->tso_size = 0;
/* Send it off. */
TCP_SKB_CB(skb)->seq = tcp_acceptable_seq(sk, tp);
......@@ -1371,8 +1373,8 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
TCP_SKB_CB(skb)->seq = req->snt_isn;
TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
TCP_SKB_CB(skb)->sacked = 0;
TCP_SKB_CB(skb)->tso_factor = 1;
TCP_SKB_CB(skb)->tso_mss = tp->mss_cache_std;
skb_shinfo(skb)->tso_segs = 1;
skb_shinfo(skb)->tso_size = 0;
th->seq = htonl(TCP_SKB_CB(skb)->seq);
th->ack_seq = htonl(req->rcv_isn + 1);
if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */
......@@ -1474,8 +1476,8 @@ int tcp_connect(struct sock *sk)
TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN;
TCP_ECN_send_syn(sk, tp, buff);
TCP_SKB_CB(buff)->sacked = 0;
TCP_SKB_CB(buff)->tso_factor = 1;
TCP_SKB_CB(buff)->tso_mss = tp->mss_cache_std;
skb_shinfo(buff)->tso_segs = 1;
skb_shinfo(buff)->tso_size = 0;
buff->csum = 0;
TCP_SKB_CB(buff)->seq = tp->write_seq++;
TCP_SKB_CB(buff)->end_seq = tp->write_seq;
......@@ -1575,8 +1577,8 @@ void tcp_send_ack(struct sock *sk)
buff->csum = 0;
TCP_SKB_CB(buff)->flags = TCPCB_FLAG_ACK;
TCP_SKB_CB(buff)->sacked = 0;
TCP_SKB_CB(buff)->tso_factor = 1;
TCP_SKB_CB(buff)->tso_mss = tp->mss_cache_std;
skb_shinfo(buff)->tso_segs = 1;
skb_shinfo(buff)->tso_size = 0;
/* Send it off, this clears delayed acks for us. */
TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tcp_acceptable_seq(sk, tp);
......@@ -1611,8 +1613,8 @@ static int tcp_xmit_probe_skb(struct sock *sk, int urgent)
skb->csum = 0;
TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
TCP_SKB_CB(skb)->sacked = urgent;
TCP_SKB_CB(skb)->tso_factor = 1;
TCP_SKB_CB(skb)->tso_mss = tp->mss_cache_std;
skb_shinfo(skb)->tso_segs = 1;
skb_shinfo(skb)->tso_size = 0;
/* Use a previous sequence. This should cause the other
* end to send an ack. Don't queue or clone SKB, just
......@@ -1656,8 +1658,8 @@ int tcp_write_wakeup(struct sock *sk)
sk->sk_route_caps &= ~NETIF_F_TSO;
tp->mss_cache = tp->mss_cache_std;
}
} else if (!TCP_SKB_CB(skb)->tso_factor)
tcp_set_skb_tso_factor(skb, tp->mss_cache_std);
} else if (!tcp_skb_pcount(skb))
tcp_set_skb_tso_segs(skb, tp->mss_cache_std);
TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
TCP_SKB_CB(skb)->when = tcp_time_stamp;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment