forked from mirrors/linux
		
	tcp: Make SACK code to split only at mss boundaries
Sadly enough, this adds possible divide though we try to avoid it by checking one mss as common case. Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									e8bae275d9
								
							
						
					
					
						commit
						adb92db857
					
				
					 1 changed files with 23 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -1248,20 +1248,39 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb,
 | 
			
		|||
{
 | 
			
		||||
	int in_sack, err;
 | 
			
		||||
	unsigned int pkt_len;
 | 
			
		||||
	unsigned int mss;
 | 
			
		||||
 | 
			
		||||
	in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) &&
 | 
			
		||||
		  !before(end_seq, TCP_SKB_CB(skb)->end_seq);
 | 
			
		||||
 | 
			
		||||
	if (tcp_skb_pcount(skb) > 1 && !in_sack &&
 | 
			
		||||
	    after(TCP_SKB_CB(skb)->end_seq, start_seq)) {
 | 
			
		||||
 | 
			
		||||
		mss = tcp_skb_mss(skb);
 | 
			
		||||
		in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq);
 | 
			
		||||
 | 
			
		||||
		if (!in_sack)
 | 
			
		||||
		if (!in_sack) {
 | 
			
		||||
			pkt_len = start_seq - TCP_SKB_CB(skb)->seq;
 | 
			
		||||
		else
 | 
			
		||||
			if (pkt_len < mss)
 | 
			
		||||
				pkt_len = mss;
 | 
			
		||||
		} else {
 | 
			
		||||
			pkt_len = end_seq - TCP_SKB_CB(skb)->seq;
 | 
			
		||||
		err = tcp_fragment(sk, skb, pkt_len, skb_shinfo(skb)->gso_size);
 | 
			
		||||
			if (pkt_len < mss)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Round if necessary so that SACKs cover only full MSSes
 | 
			
		||||
		 * and/or the remaining small portion (if present)
 | 
			
		||||
		 */
 | 
			
		||||
		if (pkt_len > mss) {
 | 
			
		||||
			unsigned int new_len = (pkt_len / mss) * mss;
 | 
			
		||||
			if (!in_sack && new_len < pkt_len) {
 | 
			
		||||
				new_len += mss;
 | 
			
		||||
				if (new_len > skb->len)
 | 
			
		||||
					return 0;
 | 
			
		||||
			}
 | 
			
		||||
			pkt_len = new_len;
 | 
			
		||||
		}
 | 
			
		||||
		err = tcp_fragment(sk, skb, pkt_len, mss);
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
			return err;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue