PERFORCE change 122529 for review

Alexey Tarasov taleks at FreeBSD.org
Fri Jun 29 15:15:08 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=122529

Change 122529 by taleks at taleks_th on 2007/06/29 15:14:52

	Updated segment resending code, added tcp_resend_update() to recalc checksum with latest ack value. Updated pxe_tcp_send() to use segments functions. Changed await function  to be able perform resending during waiting.

Affected files ...

.. //depot/projects/soc2007/taleks-pxe_http/pxe_connection.c#2 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_segment.c#2 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_segment.h#2 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_tcp.c#4 edit

Differences ...

==== //depot/projects/soc2007/taleks-pxe_http/pxe_connection.c#2 (text+ko) ====

@@ -104,6 +104,8 @@
 		
 	        case PXE_AWAIT_STARTTRY: /* nothing to do */
 	        case PXE_AWAIT_FINISHTRY:
+			pxe_resend_check(wait_data->connection);
+			break;
 		case PXE_AWAIT_END:
 		default:
 			break;
@@ -143,12 +145,14 @@
 	connection->next_recv = 0;
 	
 	/* NOTE: need to make more correct initial number */
-	connection->iss = (filter->src_ip ^ filter->dst_ip) + (uint32_t)pxe_get_secs();
+	connection->iss = (filter->src_ip + filter->dst_ip) + (uint32_t)pxe_get_secs();
 	connection->next_send = connection->iss;
 	
 	connection->filter = filter;
 	connection->recv = &sock->recv_buffer;
 	connection->send = &sock->send_buffer;
+	
+	pxe_resend_init(connection);
 
 	if (!pxe_tcp_send(connection, 0, PXE_TCP_SYN)) {
 		printf("pxe_tcp_connect(): failed to send SYN.\n");
@@ -170,7 +174,7 @@
 	 * connection will fell in this state in pxe_tcp_callback(),
 	 * after receiving SYN ACK and sending ACK to remote host
 	 */
-	if (!pxe_await(tcp_await, 1, PXE_TCP_MSL, &wait_data)) { /* failed to get SYN/ACK */
+	if (!pxe_await(tcp_await, 5, PXE_TCP_MSL / 5, &wait_data)) { /* failed to get SYN/ACK */
 	    	free_connection(connection);
 		return (0);
 	}
@@ -233,13 +237,15 @@
 	
 	/* await TIME_WITE state.
 	 * connection will fell in this state in pxe_tcp_callback(),
-	 * after receiving SYN ACK and sending ACK to remote host
+	 * TODO: add waiting of TCP_CLOSED also
 	 */
-	if (!pxe_await(tcp_await, 1, PXE_TCP_MSL, &wait_data)) { /* failed to get SYN/ACK */
+	if (!pxe_await(tcp_await, 5, PXE_TCP_MSL / 5, &wait_data)) { /* failed to get to TIME_WAIT state */
 	    	free_connection(connection);
 		return (0);
 	}
 
+	pxe_resend_free(connection);
+	
 #ifdef PXE_DEBUG
 	printf("pxe_tcp_disconnect(): connection closed.\n");
 #endif	

==== //depot/projects/soc2007/taleks-pxe_http/pxe_segment.c#2 (text+ko) ====

@@ -23,6 +23,10 @@
 	 * But in case it'll be redone to be more effective or just using other segment allocation
 	 * algorithm - this function may be needed.
 	 */
+	 
+#ifdef PXE_DEBUG
+	tcp_resend_stats(connection);
+#endif
 }
 
 /* pxe_resend_init() - initialize buffer map for connection
@@ -62,7 +66,7 @@
 /* tcp_segment_alloc() - allocates from send buffer memory for packet,
  *			including segment data, IP & TCP headers
  * in:
- *	connection	- connection, from which send byffer segment is allocated
+ *	connection	- connection, from which send buffer segment is allocated
  *	allocBig	- 1 if need big segment, 0 otherwise
  * out:
  *	NULL		- failed to allocate memory chunk(s) for segment
@@ -177,8 +181,18 @@
 		
                 /* block is used exclusevely by one "big" packet */
                 if (buf_blocks[block_index] == PXE_TCP_BLOCK_EXCLUSIVE) {
+		
+			if (segment->status != PXE_SEGMENT_SENT)
+				continue;	/* it was not ever sent yet */
+				
                         if (cur_time >= segment->resend_at) { /* time to resend */
+#ifdef PXE_DEBUG
+				printf("pxe_resend_check(): %d:%d resending...\n", segment->resend_at, cur_time);
+#endif				
+				tcp_update_segment(connection, segment);
                                 pxe_tcp_send_segment(connection, segment);
+				segment->trys += 1;				
+				segment->resend_at += PXE_RESEND_TIME * segment->trys;
             		}
                         continue;
                 }
@@ -188,15 +202,17 @@
 
                 for ( ; chunk_index < PXE_TCP_CHUNK_COUNT; ++chunk_index) {
 
-                        if (segment->status != PXE_SEGMENT_FREE) {
+                        if (segment->status == PXE_SEGMENT_SENT) {
 
                                 if (cur_time >= segment->resend_at) { /* time to resend */
-
+#ifdef PXE_DEBUG
+					printf("pxe_resend_check(): %d:%d resending...\n", segment->resend_at, cur_time);
+#endif
+					tcp_update_segment(connection, segment);
 	                                pxe_tcp_send_segment(connection, segment);
-
-					/* resend a minute later, if failed  */
-					segment->resend_at += 60;
-					segment->trys += 1;
+					/* resend later, with more delay with every try */
+					segment->trys += 1;				
+					segment->resend_at += PXE_RESEND_TIME * segment->trys;
 	                        }
 	                }
 
@@ -233,7 +249,14 @@
 
                 /* block is used exclusevely by one "big" packet */
                 if (connection->buf_blocks[block_index] == PXE_TCP_BLOCK_EXCLUSIVE) {
-                        if (connection->una > segment->seq) { /* segment was acked, release it */
+		
+			if (segment->status != PXE_SEGMENT_SENT)
+				continue;	/* it was not ever sent yet */
+
+                        if (connection->una >= segment->seq) { /* segment was acked, release it */
+#ifdef PXE_DEBUG
+				printf("pxe_resend_update(): block %d acked.\n", block_index);
+#endif
 				tcp_segment_free(connection, block_index, segment);
             		}
                         continue;
@@ -244,8 +267,12 @@
 
                 for ( ; chunk_index < PXE_TCP_CHUNK_COUNT; ++chunk_index) {
 
-                        if (segment->status != PXE_SEGMENT_FREE) {
-                                if (connection->una > segment->seq) { /* segment was acked */
+                        if (segment->status == PXE_SEGMENT_SENT) {
+
+                                if (connection->una >= segment->seq) { /* segment was acked */
+#ifdef PXE_DEBUG
+				    printf("pxe_resend_update(): chunk %d@%d acked.\n", chunk_index, block_index);
+#endif
 	                                tcp_segment_free(connection, block_index, segment);
 	                        }
 	                }
@@ -269,13 +296,12 @@
 	tcp_packet->tcphdr.dst_port = le2be16(connection->dst_port);
 	tcp_packet->tcphdr.checksum = 0;
 	tcp_packet->tcphdr.sequence = le2be32(connection->next_send);
-	
-	tcp_packet->tcphdr.data_off = (uint8_t)((sizeof(PXE_TCP_HDR)/4) << 4);
+	tcp_packet->tcphdr.data_off = sizeof(PXE_TCP_HDR);
 	
 	if (add_options == 1) {
 		/* reserving 8 bytes for options */
 		length += 8;
-		tcp_packet->tcphdr.data_off += 2;
+		tcp_packet->tcphdr.data_off += 8;
 		
 		/* pointing to options, leading tcp_header */
 		PXE_TCP_DEFAULT_OPTIONS *options = (PXE_TCP_DEFAULT_OPTIONS *)(tcp_packet + 1);
@@ -286,7 +312,13 @@
 		options->mss = le2be16(PXE_TCP_MSS);
 	}
 	
+	tcp_packet->tcphdr.data_off = (tcp_packet->tcphdr.data_off / 4) << 4;
 	tcp_packet->tcphdr.urgent = 0;
+	
+	segment->trys = 0;
+	segment->resend_at = 0;
+	segment->size = length;
+	segment->seq = connection->next_send;
 }
 
 void
@@ -331,39 +363,95 @@
 	if (tcp_packet->tcphdr.checksum == 0)
 		tcp_packet->tcphdr.checksum = 0xffff;
 
+	/* setting sequence number next to the segment last byte
+	 * when connection->una become this value we must remove packet
+	 * from resend queue.
+	 */
+	segment->seq += (length - 4 * (tcp_packet->tcphdr.data_off >> 4) + 1);
+	
 #ifdef PXE_DEBUG_HELL
 	printf("tcp_finish_segment(): checksum 0x%4x for %d bytes\n", tcp_packet->tcphdr.checksum, length);
 #endif
 }
 
+void
+tcp_update_segment(PXE_TCP_CONNECTION *connection, PXE_TCP_QUEUED_SEGMENT *segment)
+{
+	PXE_TCP_PACKET  *tcp_packet = (PXE_TCP_PACKET  *)(segment + 1);
+		
+	uint16_t length = segment->size - sizeof(PXE_IP_HDR);
+	
+	tcp_packet->tcphdr.ack_next = le2be32(connection->next_recv);
+												
+	PXE_BUFFER *recv_buffer = connection->recv;
+	
+	/* set window size to free buffer space size, or to zero if recv_buffer == NULL */
+	tcp_packet->tcphdr.window_size = (recv_buffer != NULL) ? le2be16(recv_buffer->bufleft) : 0;
+	tcp_packet->tcphdr.checksum = 0;
+	
+	PXE_IP4_PSEUDO_HDR      pseudo_hdr;
+
+        pseudo_hdr.src_ip = pxe_get_ip32(PXE_IP_MY);
+        pseudo_hdr.dst_ip = connection->dst_ip;
+        pseudo_hdr.zero = 0;
+        pseudo_hdr.proto = PXE_TCP_PROTOCOL;
+        pseudo_hdr.length = le2be16(length);
+					
+       /* adding pseudo header checksum to checksum of tcp header with data
+        * and make it complimentary
+        */
+	uint16_t part1 = pxe_ip_checksum(&pseudo_hdr, sizeof(PXE_IP4_PSEUDO_HDR));
+	uint16_t part2 = pxe_ip_checksum(&tcp_packet->tcphdr, length);
+									       
+	uint32_t tmp_sum = ((uint32_t)part1) + ((uint32_t)part2);
+										       
+	if (tmp_sum & 0xf0000) { /* need carry out */
+		tmp_sum -= 0xffff;
+	}
+	
+	tcp_packet->tcphdr.checksum = ~((uint16_t)(tmp_sum & 0xffff));
+	
+	/* special case */
+	if (tcp_packet->tcphdr.checksum == 0)
+		tcp_packet->tcphdr.checksum = 0xffff;
+
+#ifdef PXE_DEBUG_HELL
+	printf("tcp_update_segment(): checksum 0x%4x for %d bytes\n", tcp_packet->tcphdr.checksum, length);
+#endif
+}
+
 /* pxe_tcp_send_segment() - send data segment via TCP protocol
  * in:
+ *	connection	- connection to which segment belongs
  *      segment         - segment to send
  * out:
  *      0       - failed
  *      1       - success
  */
 int
-pxe_tcp_send_segment(PXE_TCP_QUEUED_SEGMENT *segment)
+pxe_tcp_send_segment(PXE_TCP_CONNECTION *connection, PXE_TCP_QUEUED_SEGMENT *segment)
 {
 	PXE_TCP_PACKET *tcp_packet = (PXE_TCP_PACKET *)(segment + 1);
 	
-	if (!pxe_ip_send(tcp_packet, tcp_packet->iphdr.dst_ip, PXE_TCP_PROTOCOL, segment->size, 1)) {
-		printf("pxe_tcp_send_send(): failed to send tcp packet to 0x%x\n", tcp_packet->iphdr.dst_ip);
+	if (!pxe_ip_send(tcp_packet, connection->dst_ip, PXE_TCP_PROTOCOL, segment->size, 1)) {
+		printf("pxe_tcp_send_send(): failed to send tcp packet to 0x%x\n", connection->dst_ip);
 		return (0);
 	}
 
+	/* mark segment to be checked in resend and update calls*/
+	segment->status = PXE_SEGMENT_SENT;
+	
 #ifdef PXE_DEBUG
 	PXE_IPADDR      from;
 	PXE_IPADDR      to;
 
-	from.ip = tcp_packet->iphdr.src_ip;
-	to.ip = tcp_packet->iphdr.dst_ip;
+	from.ip = pxe_get_ip32(PXE_IP_MY);
+	to.ip = connection->dst_ip;
 
-	printf("pxe_tcp_send_segment(): tcp packet from %d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n seq %d",
-	    from.octet[0], from.octet[1], from.octet[2], from.octet[3], tcp_packet->tcphdr.src_port,
-            to.octet[0], to.octet[1], to.octet[2], to.octet[3], tcp_packet->tcphdr.dst_port,
-	    segment->seq
+	printf("pxe_tcp_send_segment(): tcp packet from %d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n next seq %d",
+	    from.octet[0], from.octet[1], from.octet[2], from.octet[3], connection->src_port,
+            to.octet[0], to.octet[1], to.octet[2], to.octet[3], connection->dst_port,
+	    segment->seq - connection->iss
         );
 
 	uint8_t flags = tcp_packet->tcphdr.flags;
@@ -378,16 +466,65 @@
 	        printf(" rst,");
 
 	if (flags & PXE_TCP_ACK)
-	        printf(" ack %d,", be2le32(tcp_packet->tcphdr.ack_next));
+	        printf(" ack %d,", connection->next_recv - connection->irs);
 
 	if (flags & PXE_TCP_URG)
 	        printf(" urg,");
 
 	if (flags & PXE_TCP_URG)
 	        printf(" psh,");
-		
-	printf(" %d bytes.\n", segment->size);
+	
+	uint16_t length = segment->size - sizeof(PXE_IP_HDR) - 4 * (tcp_packet->tcphdr.data_off >> 4);
+	
+	printf(" %d bytes.\n", length);
 #endif
 
         return (1);
 }
+
+void
+tcp_resend_stats(PXE_TCP_CONNECTION *connection)
+{
+	int	block_index = 0;
+	PXE_BUFFER		*buffer = connection->send;
+	uint8_t			*buf_blocks = connection->buf_blocks;
+	void			*data = NULL;
+	PXE_TCP_QUEUED_SEGMENT	*segment = NULL;
+	
+		printf("pxe_resend_stats(): stats for connection 0x%x\n", connection);
+		
+	for ( ; block_index < PXE_TCP_BLOCK_COUNT; ++block_index) {
+
+		/* start of block */
+		data = buffer->data + PXE_TCP_CHUNK_COUNT * block_index * connection->chunk_size;
+		segment = (PXE_TCP_QUEUED_SEGMENT *)data;
+		    
+		if (buf_blocks[block_index] != PXE_TCP_BLOCK_FREE) {
+
+			if (buf_blocks[block_index] != PXE_TCP_BLOCK_EXCLUSIVE) {
+				/* search free chunk in block */
+				int chunk_index = 0;
+				
+				for ( ; chunk_index < PXE_TCP_CHUNK_COUNT; ++chunk_index) {
+					
+					if (segment->status != PXE_SEGMENT_FREE) {
+
+						printf("\tchunk %d@%d awaiting %d ack.\n",
+						    chunk_index, block_index, segment->seq - connection->iss
+						);
+					}
+					
+					/* next chunk in block */
+					data += connection->chunk_size;
+					segment = (PXE_TCP_QUEUED_SEGMENT *)data;
+				}
+			
+			} else {
+
+				printf("pxe_resend_stats(): block %d awaiting %d ack.\n",
+				    block_index, segment->seq - connection->iss
+				);
+			}
+		}
+	}
+}
==== //depot/projects/soc2007/taleks-pxe_http/pxe_segment.h#2 (text+ko) ====

@@ -11,6 +11,8 @@
 #define PXE_SEGMENT_USED	0x01
 /* segment is filled with data, sent but not ACKed yet */
 #define PXE_SEGMENT_SENT	0x02
+/* default resend time if not acked in seconds */
+#define PXE_RESEND_TIME		5
 
 /* how much blocks in buffer */
 #define PXE_TCP_BLOCK_COUNT     8
@@ -58,4 +60,25 @@
 /* inits buffer map of connection  */
 void pxe_resend_init(PXE_TCP_CONNECTION *connection);
 
+/* sends chhosed segment to adrressee */
+int pxe_tcp_send_segment(PXE_TCP_CONNECTION *connection, PXE_TCP_QUEUED_SEGMENT *segment);
+
+/* allocates in buffer space segment */
+PXE_TCP_QUEUED_SEGMENT * tcp_segment_alloc(PXE_TCP_CONNECTION *connection, int allocBig);
+
+/* releases memory used by segment */
+void tcp_segment_free(PXE_TCP_CONNECTION *connection, int block_index, PXE_TCP_QUEUED_SEGMENT *segment);
+
+/* fills most of fields of tcp header of segment */
+void tcp_start_segment(PXE_TCP_CONNECTION *connection, PXE_TCP_QUEUED_SEGMENT *segment, int add_options);
+
+/* finishes filling of tcp header, adds checksum */
+void tcp_finish_segment(PXE_TCP_CONNECTION *connection, PXE_TCP_QUEUED_SEGMENT *segment, uint8_t tcp_flags);
+
+/* when resending updates ack and checksum */
+void tcp_update_segment(PXE_TCP_CONNECTION *connection, PXE_TCP_QUEUED_SEGMENT *segment);
+
+/* when resending updates ack and checksum */
+void tcp_resend_stats(PXE_TCP_CONNECTION *connection);
+
 #endif

==== //depot/projects/soc2007/taleks-pxe_http/pxe_tcp.c#4 (text+ko) ====

@@ -6,6 +6,7 @@
 #include "pxe_core.h"
 #include "pxe_filter.h"
 #include "pxe_ip.h"
+#include "pxe_segment.h"
 #include "pxe_tcp.h"
 
 /* state handle functions */
@@ -244,17 +245,16 @@
 		return (0);
 	}
 	
-/*	printf("tcp_check_5(): una = %d, ack = %d\n", connection->una, ack);
-	if ( connection->una < ack) { */
+/*	printf("tcp_check_5(): una = %d, ack = %d\n", connection->una, ack); */
+	if ( connection->una <= ack) {
 	        connection->una = ack;
 		pxe_resend_update(connection);
-/*	} else  { /* ignore dublicate packet */
-/* #ifdef PXE_DEBUG
+	} else  { /* ignore dublicate packet */
+#ifdef PXE_DEBUG
 		printf("tcp_check_5(): failed\n");
 #endif
 		return (0);
 	}
-*/
 	
 	connection->remote_window = tcp_packet->tcphdr.window_size;
 	
@@ -274,7 +274,7 @@
 	if (tcp_packet->tcphdr.flags & PXE_TCP_URG)
 		return (1);
 
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 	printf("tcp_check_6(): failed\n");
 #endif	
 	return (0);
@@ -296,10 +296,13 @@
 	
 	if (seglen == 0 )
 		connection->next_recv += 1;
-	    
+/*	    
 #ifdef PXE_DEBUG
-	printf("tcp_process_7(): ack = %d, seq = %d, seglen = %d\n", connection->next_recv, connection->next_send, seglen);
+	printf("tcp_process_7(): ack = %d, seq = %d, seglen = %d\n",
+	    connection->next_recv - connection->irs, connection->next_send - connection->iss, seglen
+	);
 #endif				
+*/
 	if (seglen > 0) {
 		/* write data to buffer */
 		void *data = ((void *)tcp_packet) + sizeof(PXE_IP_HDR) + 4 * (tcp_packet->tcphdr.data_off >> 4);
@@ -322,7 +325,7 @@
 {
 	if (tcp_packet->tcphdr.flags & PXE_TCP_FIN)
 		return (1);
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 	printf("tcp_check_8(): failed\n");
 #endif	
 	return (0);
@@ -505,8 +508,7 @@
 		connection->next_send = tcp_packet->tcphdr.ack_next;
 	}
 	
-	/* if acked  FIN */
-/*	if (tcp_check_8(tcp_packet)) { */
+	/* if acked our FIN */
 	if (connection->state_out == PXE_TCP_FIN) { 
 		connection->state = PXE_TCP_FIN_WAIT2;
 #ifdef PXE_DEBUG
@@ -809,8 +811,6 @@
 	uint16_t	src_port = tcp_packet->tcphdr.src_port;
 	uint16_t	dst_port = tcp_packet->tcphdr.dst_port;
 	
-/*	uint16_t	data_size = pack->data_size - sizeof(PXE_IP_HDR) - 4 * (tcp_packet->tcphdr.data_off >> 4);*/
-
 	PXE_IP_HDR	*iphdr = pack->data;
 
 	/* calculating data size from ip length minus headers length */
@@ -835,16 +835,13 @@
 #ifdef PXE_DEBUG
 		printf("pxe_tcp_callback(): packet filtered out, sending RST.\n");
 #endif
-/*		if (flags & PXE_TCP_SYN) {	/* this was hopeless attempt to connect */
+		if (flags & PXE_TCP_ACK) {
+			tcp_send_rst_for(tcp_packet, 0, tcp_packet->tcphdr.ack_next, PXE_TCP_RST, data_size);
+		} else {
+			tcp_send_rst_for(tcp_packet, tcp_packet->tcphdr.ack_next + data_size,
+						     0, PXE_TCP_RST | PXE_TCP_ACK, data_size);
+		}
 		
-			if (flags & PXE_TCP_ACK) {
-				tcp_send_rst_for(tcp_packet, 0, tcp_packet->tcphdr.ack_next, PXE_TCP_RST, data_size);
-			} else {
-				tcp_send_rst_for(tcp_packet, tcp_packet->tcphdr.ack_next + data_size,
-							     0, PXE_TCP_RST | PXE_TCP_ACK, data_size);
-			}
-/*		} /* otherwise just ignore this packet */
-		
 		return (0);	
 	}
 	
@@ -902,10 +899,10 @@
 	if (connection->state > PXE_TCP_SYN_SENT) { /* if we know sequence number, then check it */
 
 		if (seq != connection->next_recv) {			/* not next in order, drop it, send ACK */
-/*		tcp_send_ack_for(tcp_packet, connection->next_recv,	/* with next needed sequence number */
-/*			connection->next_send, sock); */
 #ifdef PXE_DEBUG
-			printf("pxe_tcp_callback(): got %d != awaited %d\n", seq, connection->next_recv);
+			printf("pxe_tcp_callback(): got %d != awaited %d\n",
+			    seq - connection->irs, connection->next_recv - connection->irs
+			);
 #endif
 			return (0);
 		}
@@ -913,10 +910,12 @@
 	    /* in case of SYN_SENT state we don't know sequence number yet */
 	}
 	
+	int result = 0;
+	
 	/* calling appropriate state handler, if it's not NULL */
 	if (connection->state < PXE_TCP_ALL_STATES) {
 	
-		int result = 0;
+
 		while (1) {
 #ifdef PXE_DEBUG
 			printf("pxe_tcp_callback(): connection state = 0x%x\n", connection->state);
@@ -927,14 +926,20 @@
 				if (result == 2)
 					continue;
 			
-				return (result);
+				break;
 			} else {	/* state handler not registered */
-				return (0);    
+				break;    
 			}
 		}
 	}
 	
-	return (0);
+	/* check ACKed packets*/
+	pxe_resend_update(connection);
+	
+	/* check if need to resend some segments */
+	pxe_resend_check(connection);
+	
+	return (result);
 }                                                            
 
 /* pxe_tcp_init() - initialization of TCP module
@@ -952,7 +957,7 @@
 	pxe_core_register(PXE_TCP_PROTOCOL, pxe_tcp_callback);
 }
 
-/* pxe_tcp_send() - send data via TCP protocol
+/* pxe_tcp_send() - send system packets via TCP protocol
  * in:
  *	connection	- connection to send to
  *	size		- data size
@@ -964,5 +969,31 @@
 int
 pxe_tcp_send(PXE_TCP_CONNECTION *connection, uint16_t size, uint8_t tcp_flags)
 {
-	return (0);
+	/* allocating smmall segment */
+	PXE_TCP_QUEUED_SEGMENT *segment = tcp_segment_alloc(connection, 0);	
+	
+	if (segment == NULL) {
+		printf("pxe_tcp_send(): failed to allocate segment.\n");
+		return (0);
+	}
+
+/*	segment->seq = connection->next_send; */
+	/* here is simpliest ever in the world way to calculate resend time
+	 * for more reliable resend time calculation need to implement RTT calculating.
+	 */
+
+	
+	/* add to every system segment default options */
+	tcp_start_segment(connection, segment, 1);
+	
+	/* finish segment */
+	tcp_finish_segment(connection, segment, tcp_flags);
+	segment->resend_at = pxe_get_secs() + PXE_RESEND_TIME;
+	
+	if (!pxe_tcp_send_segment(connection, segment)) {
+		printf("pxe_tcp_send(): failed to send segment.\n");
+		return (0);
+	}
+	
+	return (1);
 }


More information about the p4-projects mailing list