patch-1.3.6 linux/net/ipv4/tcp.c
Next file: linux/net/ipv4/udp.c
Previous file: linux/net/ipv4/route.c
Back to the patch index
Back to the overall index
- Lines: 593
- Date:
Thu Jun 29 19:18:53 1995
- Orig file:
v1.3.5/linux/net/ipv4/tcp.c
- Orig date:
Tue Jun 27 14:11:48 1995
diff -u --recursive --new-file v1.3.5/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
@@ -140,6 +140,11 @@
* Alan Cox : Cache last socket.
* Alan Cox : Per route irtt.
* Matt Day : Select() match BSD precisely on error
+ * Alan Cox : New buffers
+ * Mark Tamsky : Various sk->prot->retransmits and
+ * sk->retransmits misupdating fixed.
+ * Fixed tcp_write_timeout: stuck close,
+ * and TCP syn retries gets used now.
*
*
* To Fix:
@@ -517,6 +522,8 @@
ct++;
sk->prot->retransmits ++;
+ tcp_statistics.TcpRetransSegs++;
+
/*
* Only one retransmit requested.
@@ -582,6 +589,7 @@
*/
sk->retransmits++;
+ sk->prot->retransmits++;
sk->backoff++;
sk->rto = min(sk->rto << 1, 120*HZ);
reset_xmit_timer(sk, TIME_WRITE, sk->rto);
@@ -632,6 +640,22 @@
arp_destroy (sk->daddr, 0);
/*ip_route_check (sk->daddr);*/
}
+
+ /*
+ * Have we tried to SYN too many times (repent repent 8))
+ */
+
+ if(sk->retransmits > TCP_SYN_RETRIES && sk->state==TCP_SYN_SENT)
+ {
+ sk->err=ETIMEDOUT;
+ sk->error_report(sk);
+ del_timer(&sk->retransmit_timer);
+ tcp_statistics.TcpAttemptFails++; /* Is this right ??? - FIXME - */
+ tcp_set_state(sk,TCP_CLOSE);
+ /* Don't FIN, we got nothing back */
+ release_sock(sk);
+ return 0;
+ }
/*
* Has it gone just too far ?
*/
@@ -654,6 +678,7 @@
* Clean up time.
*/
tcp_set_state(sk, TCP_CLOSE);
+ release_sock(sk);
return 0;
}
}
@@ -759,6 +784,7 @@
if (sk->prot->write_wakeup)
sk->prot->write_wakeup (sk);
sk->retransmits++;
+ sk->prot->retransmits++;
tcp_write_timeout(sk);
break;
default:
@@ -1291,10 +1317,8 @@
* Assemble a suitable TCP frame
*/
- buff->len = sizeof(struct tcphdr);
buff->sk = sk;
buff->localroute = sk->localroute;
- t1 =(struct tcphdr *) buff->data;
/*
* Put in the IP header and routing stuff.
@@ -1305,11 +1329,10 @@
if (tmp < 0)
{
buff->free = 1;
- sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
+ sk->prot->wfree(sk, buff);
return;
}
- buff->len += tmp;
- t1 =(struct tcphdr *)((char *)t1 +tmp);
+ t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
memcpy(t1, th, sizeof(*t1));
@@ -1403,7 +1426,6 @@
int tmp;
struct sk_buff *skb;
struct sk_buff *send_tmp;
- unsigned char *buff;
struct proto *prot;
struct device *dev = NULL;
@@ -1533,8 +1555,7 @@
copy = 0;
}
- memcpy_fromfs(skb->data + skb->len, from, copy);
- skb->len += copy;
+ memcpy_fromfs(skb_put(skb,copy), from, copy);
from += copy;
copied += copy;
len -= copy;
@@ -1639,36 +1660,31 @@
continue;
}
- skb->len = 0;
skb->sk = sk;
skb->free = 0;
skb->localroute = sk->localroute|(flags&MSG_DONTROUTE);
- buff = skb->data;
-
/*
* FIXME: we need to optimize this.
* Perhaps some hints here would be good.
*/
tmp = prot->build_header(skb, sk->saddr, sk->daddr, &dev,
- IPPROTO_TCP, sk->opt, skb->mem_len,sk->ip_tos,sk->ip_ttl);
+ IPPROTO_TCP, sk->opt, skb->truesize,sk->ip_tos,sk->ip_ttl);
if (tmp < 0 )
{
- prot->wfree(sk, skb->mem_addr, skb->mem_len);
+ prot->wfree(sk, skb);
release_sock(sk);
if (copied)
return(copied);
return(tmp);
}
- skb->len += tmp;
skb->dev = dev;
- buff += tmp;
- skb->h.th =(struct tcphdr *) buff;
- tmp = tcp_build_header((struct tcphdr *)buff, sk, len-copy);
+ skb->h.th =(struct tcphdr *)skb_put(skb,sizeof(struct tcphdr));
+ tmp = tcp_build_header(skb->h.th, sk, len-copy);
if (tmp < 0)
{
- prot->wfree(sk, skb->mem_addr, skb->mem_len);
+ prot->wfree(sk, skb);
release_sock(sk);
if (copied)
return(copied);
@@ -1677,16 +1693,15 @@
if (flags & MSG_OOB)
{
- ((struct tcphdr *)buff)->urg = 1;
- ((struct tcphdr *)buff)->urg_ptr = ntohs(copy);
+ skb->h.th->urg = 1;
+ skb->h.th->urg_ptr = ntohs(copy);
}
- skb->len += tmp;
- memcpy_fromfs(buff+tmp, from, copy);
+ memcpy_fromfs(skb_put(skb,copy), from, copy);
+
from += copy;
copied += copy;
len -= copy;
- skb->len += copy;
skb->free = 0;
sk->write_seq += copy;
@@ -1778,7 +1793,6 @@
return;
}
- buff->len = sizeof(struct tcphdr);
buff->sk = sk;
buff->localroute = sk->localroute;
@@ -1791,12 +1805,11 @@
if (tmp < 0)
{
buff->free = 1;
- sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
+ sk->prot->wfree(sk, buff);
return;
}
- buff->len += tmp;
- t1 =(struct tcphdr *)(buff->data +tmp);
+ t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
memcpy(t1,(void *) &sk->dummy_th, sizeof(*t1));
t1->seq = htonl(sk->sent_seq);
@@ -2285,9 +2298,7 @@
*/
buff->sk = sk;
- buff->len = sizeof(*t1);
buff->localroute = sk->localroute;
- t1 =(struct tcphdr *) buff->data;
/*
* Put in the IP header and routing stuff.
@@ -2305,7 +2316,7 @@
*/
buff->free = 1;
- prot->wfree(sk,buff->mem_addr, buff->mem_len);
+ prot->wfree(sk,buff);
sk->write_seq++;
t=del_timer(&sk->timer);
if(t)
@@ -2320,8 +2331,7 @@
* if so simply add the fin to that buffer, not send it ahead.
*/
- t1 =(struct tcphdr *)((char *)t1 +tmp);
- buff->len += tmp;
+ t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
buff->dev = dev;
memcpy(t1, th, sizeof(*t1));
t1->seq = ntohl(sk->write_seq);
@@ -2473,13 +2483,10 @@
if (buff == NULL)
return;
- buff->len = sizeof(*t1);
buff->sk = NULL;
buff->dev = dev;
buff->localroute = 0;
- t1 =(struct tcphdr *) buff->data;
-
/*
* Put in the IP header and routing stuff.
*/
@@ -2489,12 +2496,11 @@
if (tmp < 0)
{
buff->free = 1;
- prot->wfree(NULL, buff->mem_addr, buff->mem_len);
+ prot->wfree(NULL, buff);
return;
}
- t1 =(struct tcphdr *)((char *)t1 +tmp);
- buff->len += tmp;
+ t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
memcpy(t1, th, sizeof(*t1));
/*
@@ -2825,12 +2831,9 @@
return;
}
- buff->len = sizeof(struct tcphdr)+4;
buff->sk = newsk;
buff->localroute = newsk->localroute;
- t1 =(struct tcphdr *) buff->data;
-
/*
* Put in the IP header and routing stuff.
*/
@@ -2856,8 +2859,7 @@
return;
}
- buff->len += tmp;
- t1 =(struct tcphdr *)((char *)t1 +tmp);
+ t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
memcpy(t1, skb->h.th, sizeof(*t1));
buff->h.seq = newsk->write_seq;
@@ -2879,7 +2881,7 @@
t1->syn = 1;
t1->ack_seq = ntohl(skb->h.th->seq+1);
t1->doff = sizeof(*t1)/4+1;
- ptr =(unsigned char *)(t1+1);
+ ptr = skb_put(buff,4);
ptr[0] = 2;
ptr[1] = 4;
ptr[2] = ((newsk->mtu) >> 8) & 0xff;
@@ -2894,8 +2896,8 @@
* Charge the sock_buff to newsk.
*/
- sk->rmem_alloc -= skb->mem_len;
- newsk->rmem_alloc += skb->mem_len;
+ sk->rmem_alloc -= skb->truesize;
+ newsk->rmem_alloc += skb->truesize;
skb_queue_tail(&sk->receive_queue,skb);
sk->ack_backlog++;
@@ -3766,7 +3768,8 @@
u32 new_seq, shut_seq;
th = skb->h.th;
- skb->len = len -(th->doff*4);
+ skb_pull(skb,th->doff*4);
+ skb_trim(skb,len-(th->doff*4));
/*
* The bytes in the receive read/assembly queue has increased. Needed for the
@@ -4265,12 +4268,10 @@
return(-ENOMEM);
}
sk->inuse = 1;
- buff->len = 24;
buff->sk = sk;
buff->free = 0;
buff->localroute = sk->localroute;
- t1 = (struct tcphdr *) buff->data;
/*
* Put in the IP header and routing stuff.
@@ -4287,13 +4288,12 @@
IPPROTO_TCP, NULL, MAX_SYN_SIZE,sk->ip_tos,sk->ip_ttl);
if (tmp < 0)
{
- sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
+ sk->prot->wfree(sk, buff);
release_sock(sk);
return(-ENETUNREACH);
}
- buff->len += tmp;
- t1 = (struct tcphdr *)((char *)t1 +tmp);
+ t1 = (struct tcphdr *) skb_put(buff,sizeof(struct tcphdr));
memcpy(t1,(void *)&(sk->dummy_th), sizeof(*t1));
t1->seq = ntohl(sk->write_seq++);
@@ -4344,7 +4344,7 @@
* Put in the TCP options to say MTU.
*/
- ptr = (unsigned char *)(t1+1);
+ ptr = skb_put(buff,4);
ptr[0] = 2;
ptr[1] = 4;
ptr[2] = (sk->mtu) >> 8;
@@ -4365,7 +4365,7 @@
sk->retransmit_timer.function=&retransmit_timer;
sk->retransmit_timer.data = (unsigned long)sk;
reset_xmit_timer(sk, TIME_WRITE, sk->rto); /* Timer for repeating the SYN until an answer */
- sk->retransmits = TCP_SYN_RETRIES;
+ sk->retransmits = 0; /* Now works the right way instead of a hacked initial setting */
sk->prot->queue_xmit(sk, dev, buff, 0);
reset_xmit_timer(sk, TIME_WRITE, sk->rto);
@@ -4464,6 +4464,7 @@
/*
* A TCP packet has arrived.
+ * skb->h.raw is the TCP header.
*/
int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
@@ -4514,6 +4515,10 @@
if (!redo)
{
+ /*
+ * Pull up the IP header.
+ */
+ skb_pull(skb, skb->h.raw-skb->data);
if (tcp_check(th, len, saddr, daddr ))
{
skb->sk = NULL;
@@ -4541,7 +4546,7 @@
return(0);
}
- skb->len = len;
+/* skb->len = len;*/
skb->acked = 0;
skb->used = 0;
skb->free = 0;
@@ -4582,7 +4587,7 @@
* Charge the memory to the socket.
*/
- if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf)
+ if (sk->rmem_alloc + skb->truesize >= sk->rcvbuf)
{
kfree_skb(skb, FREE_READ);
release_sock(sk);
@@ -4590,7 +4595,7 @@
}
skb->sk=sk;
- sk->rmem_alloc += skb->mem_len;
+ sk->rmem_alloc += skb->truesize;
/*
* This basically follows the flow suggested by RFC793, with the corrections in RFC1122. We
@@ -4754,7 +4759,7 @@
if(sk->debug)
printk("Doing a BSD time wait\n");
tcp_statistics.TcpEstabResets++;
- sk->rmem_alloc -= skb->mem_len;
+ sk->rmem_alloc -= skb->truesize;
skb->sk = NULL;
sk->err=ECONNRESET;
tcp_set_state(sk, TCP_CLOSE);
@@ -4765,7 +4770,7 @@
{
sk->inuse=1;
skb->sk = sk;
- sk->rmem_alloc += skb->mem_len;
+ sk->rmem_alloc += skb->truesize;
tcp_conn_request(sk, skb, daddr, saddr,opt, dev,seq+128000);
release_sock(sk);
return 0;
@@ -4885,8 +4890,7 @@
{
return;
}
-
- if (before(sk->sent_seq, sk->window_seq) &&
+ if ( before(sk->sent_seq, sk->window_seq) &&
(skb=skb_peek(&sk->write_queue)))
{
/*
@@ -4901,11 +4905,23 @@
unsigned long win_size, ow_size;
void * tcp_data_start;
+ /*
+ * How many bytes can we send ?
+ */
+
win_size = sk->window_seq - sk->sent_seq;
+ /*
+ * Recover the buffer pointers
+ */
+
iph = (struct iphdr *)(skb->data + skb->dev->hard_header_len);
th = (struct tcphdr *)(((char *)iph) +(iph->ihl << 2));
+ /*
+ * Grab the data for a temporary frame
+ */
+
buff = sk->prot->wmalloc(sk, win_size + th->doff * 4 +
(iph->ihl << 2) +
skb->dev->hard_header_len,
@@ -4913,46 +4929,67 @@
if ( buff == NULL )
return;
- buff->len = 0;
-
/*
* If we strip the packet on the write queue we must
* be ready to retransmit this one
*/
- buff->free = 0;
+ buff->free = /*0*/1;
buff->sk = sk;
buff->localroute = sk->localroute;
+
+ /*
+ * Put headers on the new packet
+ */
tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev,
- IPPROTO_TCP, sk->opt, buff->mem_len,
+ IPPROTO_TCP, sk->opt, buff->truesize,
sk->ip_tos,sk->ip_ttl);
if (tmp < 0)
{
- sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
+ sk->prot->wfree(sk, buff);
return;
}
+
+ /*
+ * Move the TCP header over
+ */
- buff->len += tmp;
buff->dev = dev;
- nth = (struct tcphdr *) (buff->data + buff->len);
- buff->len += th->doff * 4;
+ nth = (struct tcphdr *) skb_put(buff,th->doff*4);
memcpy(nth, th, th->doff * 4);
-
+
+ /*
+ * Correct the new header
+ */
+
nth->ack = 1;
nth->ack_seq = ntohl(sk->acked_seq);
nth->window = ntohs(tcp_select_window(sk));
nth->check = 0;
+ /*
+ * Find the first data byte.
+ */
+
tcp_data_start = skb->data + skb->dev->hard_header_len +
(iph->ihl << 2) + th->doff * 4;
- memcpy(buff->data + buff->len, tcp_data_start, win_size);
- buff->len += win_size;
+ /*
+ * Add it to our new buffer
+ */
+ memcpy(skb_put(buff,win_size), tcp_data_start, win_size);
+
+ /*
+ * Remember our right edge sequence number.
+ */
+
buff->h.seq = sk->sent_seq + win_size;
+ sk->sent_seq = buff->h.seq; /* Hack */
+#if 0
/*
* now: shrink the queue head segment
@@ -4963,10 +5000,9 @@
((unsigned long) (tcp_data_start - (void *) skb->data));
memmove(tcp_data_start, tcp_data_start + win_size, ow_size);
- skb->len -= win_size;
+ skb_trim(skb,skb->len-win_size);
sk->sent_seq += win_size;
th->seq = htonl(sk->sent_seq);
-
if (th->urg)
{
unsigned short urg_ptr;
@@ -4981,23 +5017,28 @@
nth->urg_ptr = htons(win_size);
}
}
+#else
+ if(th->urg && ntohs(th->urg_ptr) < win_size)
+ nth->urg = 0;
+#endif
+ /*
+ * Checksum the split buffer
+ */
+
tcp_send_check(nth, sk->saddr, sk->daddr,
nth->doff * 4 + win_size , sk);
}
else
- {
+ {
buff = sk->prot->wmalloc(sk,MAX_ACK_SIZE,1, GFP_ATOMIC);
if (buff == NULL)
return;
- buff->len = sizeof(struct tcphdr);
buff->free = 1;
buff->sk = sk;
buff->localroute = sk->localroute;
- t1 = (struct tcphdr *) buff->data;
-
/*
* Put in the IP header and routing stuff.
*/
@@ -5006,13 +5047,11 @@
IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,sk->ip_tos,sk->ip_ttl);
if (tmp < 0)
{
- sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
+ sk->prot->wfree(sk, buff);
return;
}
- buff->len += tmp;
- t1 = (struct tcphdr *)((char *)t1 +tmp);
-
+ t1 = (struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
memcpy(t1,(void *) &sk->dummy_th, sizeof(*t1));
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this