Corrected bugs in the TCP logic. There might be a few more which need to be taken care of.
This commit is contained in:
parent
72cd29f13c
commit
8bf38fb400
|
@ -326,8 +326,6 @@ void tcp_trans ( struct tcp_connection *conn, int nxt_state ) {
|
||||||
conn->tcp_lstate = conn->tcp_state;
|
conn->tcp_lstate = conn->tcp_state;
|
||||||
conn->tcp_state = nxt_state;
|
conn->tcp_state = nxt_state;
|
||||||
|
|
||||||
printf ( "Transition from %s to %s\n", tcp_states[conn->tcp_lstate], tcp_states[conn->tcp_state] );
|
|
||||||
|
|
||||||
/* TODO: Check if this check is required */
|
/* TODO: Check if this check is required */
|
||||||
if ( conn->tcp_lstate == conn->tcp_state ||
|
if ( conn->tcp_lstate == conn->tcp_state ||
|
||||||
conn->tcp_state == TCP_INVALID ) {
|
conn->tcp_state == TCP_INVALID ) {
|
||||||
|
@ -343,20 +341,8 @@ void tcp_trans ( struct tcp_connection *conn, int nxt_state ) {
|
||||||
* @v tcphdr TCP header
|
* @v tcphdr TCP header
|
||||||
*/
|
*/
|
||||||
void tcp_dump ( struct tcp_header *tcphdr ) {
|
void tcp_dump ( struct tcp_header *tcphdr ) {
|
||||||
/*
|
DBG ( "TCP %p src:%d dest:%d seq:%lld ack:%lld hlen:%hd flags:%#hx\n",
|
||||||
DBG ( "TCP header at %p+%d\n", tcphdr, sizeof ( *tcphdr ) );
|
tcphdr, ntohs ( tcphdr->src ), ntohs ( tcphdr->dest ), ntohl ( tcphdr->seq ),
|
||||||
DBG ( "\tSource port = %d, Destination port = %d\n",
|
|
||||||
ntohs ( tcphdr->src ), ntohs ( tcphdr->dest ) );
|
|
||||||
DBG ( "\tSequence Number = %ld, Acknowledgement Number = %ld\n",
|
|
||||||
ntohl ( tcphdr->seq ), ntohl ( tcphdr->ack ) );
|
|
||||||
DBG ( "\tHeader length (/4) = %hd, Flags [..RAPUSF]= %#x\n",
|
|
||||||
( ( tcphdr->hlen & TCP_MASK_HLEN ) / 16 ),
|
|
||||||
( tcphdr->flags & TCP_MASK_FLAGS ) );
|
|
||||||
DBG ( "\tAdvertised window = %ld, Checksum = %x, Urgent Pointer = %d\n",
|
|
||||||
ntohs ( tcphdr->win ), tcphdr->csum, ntohs ( tcphdr->urg ) );
|
|
||||||
*/
|
|
||||||
DBG ( "TCP %p at %p src:%d dest:%d seq:%lld ack:%lld hlen:%hd flags:%#hx\n",
|
|
||||||
&tcp_protocol, tcphdr, ntohs ( tcphdr->src ), ntohs ( tcphdr->dest ), ntohl ( tcphdr->seq ),
|
|
||||||
ntohl ( tcphdr->ack ), ( ( tcphdr->hlen & TCP_MASK_HLEN ) / 16 ), ( tcphdr->flags & TCP_MASK_FLAGS ) );
|
ntohl ( tcphdr->ack ), ( ( tcphdr->hlen & TCP_MASK_HLEN ) / 16 ), ( tcphdr->flags & TCP_MASK_FLAGS ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,7 +423,7 @@ void tcp_expired ( struct retry_timer *timer, int over ) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
send_tcp_nomsg:
|
send_tcp_nomsg:
|
||||||
// free_pkb ( conn->tx_pkb );
|
free_pkb ( conn->tx_pkb );
|
||||||
conn->tx_pkb = alloc_pkb ( MIN_PKB_LEN );
|
conn->tx_pkb = alloc_pkb ( MIN_PKB_LEN );
|
||||||
pkb_reserve ( conn->tx_pkb, MAX_HDR_LEN );
|
pkb_reserve ( conn->tx_pkb, MAX_HDR_LEN );
|
||||||
tcp_set_flags ( conn );
|
tcp_set_flags ( conn );
|
||||||
|
@ -657,7 +643,6 @@ int tcp_send ( struct tcp_connection *conn, const void *data, size_t len ) {
|
||||||
tcphdr->csum = tcpip_chksum ( pkb->data, pkb_len ( pkb ) );
|
tcphdr->csum = tcpip_chksum ( pkb->data, pkb_len ( pkb ) );
|
||||||
|
|
||||||
/* Dump the TCP header */
|
/* Dump the TCP header */
|
||||||
tcp_dump ( tcphdr );
|
|
||||||
|
|
||||||
/* Start the timer */
|
/* Start the timer */
|
||||||
if ( ( conn->tcp_state == TCP_ESTABLISHED && conn->tcp_lstate == TCP_SYN_SENT ) ||
|
if ( ( conn->tcp_state == TCP_ESTABLISHED && conn->tcp_lstate == TCP_SYN_SENT ) ||
|
||||||
|
@ -685,7 +670,7 @@ static int tcp_rx ( struct pk_buff *pkb,
|
||||||
struct tcp_header *tcphdr;
|
struct tcp_header *tcphdr;
|
||||||
uint32_t acked, toack;
|
uint32_t acked, toack;
|
||||||
int hlen;
|
int hlen;
|
||||||
int add = 0;
|
int add = 4;
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
if ( pkb_len ( pkb ) < sizeof ( *tcphdr ) ) {
|
if ( pkb_len ( pkb ) < sizeof ( *tcphdr ) ) {
|
||||||
|
@ -710,6 +695,7 @@ static int tcp_rx ( struct pk_buff *pkb,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TODO: Verify checksum */
|
/* TODO: Verify checksum */
|
||||||
|
|
||||||
/* Demux TCP connection */
|
/* Demux TCP connection */
|
||||||
|
@ -768,14 +754,15 @@ static int tcp_rx ( struct pk_buff *pkb,
|
||||||
*/
|
*/
|
||||||
conn->snd_una = ntohl ( tcphdr->ack );
|
conn->snd_una = ntohl ( tcphdr->ack );
|
||||||
conn->tcp_op->connected ( conn );
|
conn->tcp_op->connected ( conn );
|
||||||
|
out_flags |= TCP_ACK;
|
||||||
tcp_senddata ( conn );
|
tcp_senddata ( conn );
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
tcp_trans ( conn, TCP_SYN_RCVD );
|
tcp_trans ( conn, TCP_SYN_RCVD );
|
||||||
out_flags |= TCP_SYN;
|
out_flags |= TCP_SYN;
|
||||||
}
|
|
||||||
/* Send SYN,ACK or ACK packet */
|
|
||||||
goto send_tcp_nomsg;
|
goto send_tcp_nomsg;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* Unexpected packet */
|
/* Unexpected packet */
|
||||||
goto unexpected;
|
goto unexpected;
|
||||||
case TCP_SYN_RCVD:
|
case TCP_SYN_RCVD:
|
||||||
|
@ -792,12 +779,12 @@ static int tcp_rx ( struct pk_buff *pkb,
|
||||||
*/
|
*/
|
||||||
conn->snd_una = tcphdr->ack - 1;
|
conn->snd_una = tcphdr->ack - 1;
|
||||||
conn->tcp_op->connected ( conn );
|
conn->tcp_op->connected ( conn );
|
||||||
tcp_senddata ( conn );
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Unexpected packet */
|
/* Unexpected packet */
|
||||||
goto unexpected;
|
goto unexpected;
|
||||||
case TCP_ESTABLISHED:
|
case TCP_ESTABLISHED:
|
||||||
|
#if 0
|
||||||
if ( tcphdr->flags & TCP_FIN ) {
|
if ( tcphdr->flags & TCP_FIN ) {
|
||||||
tcp_trans ( conn, TCP_CLOSE_WAIT );
|
tcp_trans ( conn, TCP_CLOSE_WAIT );
|
||||||
/* FIN consumes one byte */
|
/* FIN consumes one byte */
|
||||||
|
@ -806,6 +793,7 @@ static int tcp_rx ( struct pk_buff *pkb,
|
||||||
/* Send an acknowledgement */
|
/* Send an acknowledgement */
|
||||||
goto send_tcp_nomsg;
|
goto send_tcp_nomsg;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/* Packet might contain data */
|
/* Packet might contain data */
|
||||||
break;
|
break;
|
||||||
case TCP_FIN_WAIT_1:
|
case TCP_FIN_WAIT_1:
|
||||||
|
@ -874,6 +862,9 @@ static int tcp_rx ( struct pk_buff *pkb,
|
||||||
if ( conn->rcv_nxt == ntohl ( tcphdr->seq ) ) {
|
if ( conn->rcv_nxt == ntohl ( tcphdr->seq ) ) {
|
||||||
conn->rcv_nxt += toack;
|
conn->rcv_nxt += toack;
|
||||||
conn->tcp_op->newdata ( conn, pkb->data + sizeof ( *tcphdr ) + add, toack );
|
conn->tcp_op->newdata ( conn, pkb->data + sizeof ( *tcphdr ) + add, toack );
|
||||||
|
} else {
|
||||||
|
printf ( "Unexpected sequence number %ld\n",
|
||||||
|
ntohl ( tcphdr->seq ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Acknowledge new data */
|
/* Acknowledge new data */
|
||||||
|
@ -892,13 +883,24 @@ static int tcp_rx ( struct pk_buff *pkb,
|
||||||
}
|
}
|
||||||
/* Advance snd stream */
|
/* Advance snd stream */
|
||||||
conn->snd_una += acked;
|
conn->snd_una += acked;
|
||||||
/* Set the ACK flag */
|
|
||||||
conn->tcp_flags |= TCP_ACK;
|
|
||||||
/* Invoke the acked() callback function */
|
/* Invoke the acked() callback function */
|
||||||
conn->tcp_op->acked ( conn, acked );
|
conn->tcp_op->acked ( conn, acked );
|
||||||
/* Invoke the senddata() callback function */
|
/* Invoke the senddata() callback function */
|
||||||
tcp_senddata ( conn );
|
tcp_senddata ( conn );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the connection is in ESTABLISHED and it receives a FIN */
|
||||||
|
if ( conn->tcp_state == ESTABLISHED && ( tcphdr->flags & TCP_FIN ) ) {
|
||||||
|
tcp_trans ( conn, TCP_CLOSE_WAIT );
|
||||||
|
conn->tcp_op->closed ( conn, CONN_SNDCLOSE );
|
||||||
|
conn->rcv_nxt++;
|
||||||
|
if ( ! ( tcphdr->flags & TCP_ACK ) ) {
|
||||||
|
out_flags |= TCP_ACK;
|
||||||
|
/* Send an acknowledgement */
|
||||||
|
goto send_tcp_nomsg;
|
||||||
|
}
|
||||||
|
/* Otherwise, the packet has been ACKed already */
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
send_tcp_nomsg:
|
send_tcp_nomsg:
|
||||||
|
|
Reference in New Issue