PERFORCE change 123127 for review

Alexey Tarasov taleks at FreeBSD.org
Sun Jul 8 14:26:27 UTC 2007


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

Change 123127 by taleks at taleks_th on 2007/07/08 14:26:13

	Overall: removed flags parameter from pxe_ip_send() and related functions, so now every sending function expects that ip/tcp/udp header is allocated by higher level code. pxe_corre_alloc_packet() is unused, will be removed.
	pxe_buffer: write/read code updated, pxe_buffer_alloc() function now also inits members of PXE_BUFFER structure. Default receive buffer size set to 32768, more optimal for  fast connections. There is still problem in tests with data receiving exceeding buffer sizes after closing connection. Most probably corruption of stack during buffer read/write.
	pxe_connection: add pxe_tcp_check_connection() which sends ACK if have big space in recv buffer and have not receivig packets (situation after small receiving window). pxe_tcp_read() also starts pxe_core_recv_packets() if have big unused space in buffer.
	pxe_core: added for experimental purposes "exclusive" protocol handling. Which blocks receiving by PXE core other protocols. Usefull when remote host is agreessively sends packets and it's MAC address is unknown, in some cases this lead to infinite cyce of ARP packets sending.
	pxe_segment: adde pxe_resend_drop_same() function to remove from resending queue packets with same sequence number, in most cases with same flags but different ack number. Some updates in checks of parameters of functions to be more accurate with NULL pointer.
	pxe_sock: made pxe_recv()  behaviour more similar to blocking function.
	pxe_tcp: mainly tcp_process_7() changed to update correctly FIN & SYN segments sequence numbers. Also pxe_tcp_syssend() modified to drop same packets.

Affected files ...

.. //depot/projects/soc2007/taleks-pxe_http/pxe_arp.c#9 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_await.h#2 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_buffer.c#4 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_buffer.h#4 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_connection.c#5 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_connection.h#4 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_core.c#18 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_core.h#14 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_icmp.c#9 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_ip.c#9 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_ip.h#7 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_segment.c#5 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_segment.h#4 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_sock.c#12 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_sock.h#10 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_tcp.c#7 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_udp.c#6 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_udp.h#4 edit

Differences ...

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

@@ -63,12 +63,23 @@
 const MAC_ADDR *
 pxe_arp_table_search(uint32_t ip)
 {
+#ifdef PXE_DEBUG_HELL
+	printf("pxe_arp_table_search(): started\n");
+#endif		
 	int entry = 0;
 	
 	for (; entry < MAX_ARP_ENTRIES + 1; ++entry) {
 
-		if (arp_table[entry].ip4.ip == ip)
-			return (const MAC_ADDR *)&(arp_table[entry].mac);
+		if (arp_table[entry].ip4.ip == ip) {
+		
+			uint8_t *mac = &arp_table[entry].mac[0];
+#ifdef PXE_DEBUG_HELL
+			printf("pxe_arp_table_search(): %2x:%2x:%2x:%2x:%2x:%2x\n",
+			    mac[0],  mac[1], mac[2], mac[3], mac[4], mac[5]
+			);
+#endif			
+			return (const MAC_ADDR *)mac;
+		}
 	}
 
 	return (NULL);
@@ -319,6 +330,8 @@
 	if (res != NULL)
 		return (res);
 
+	pxe_core_exclusive(PXE_PROTOCOL_ARP);
+	
 	PXE_ARP_WAIT_DATA	wait_data;
 	
 	wait_data.ip = ip;
@@ -327,5 +340,7 @@
 	if (!pxe_await(pxe_arp_await, PXE_MAX_ARP_TRY, PXE_TIME_TO_DIE, &wait_data)) {
 	}
 
+	pxe_core_exclusive(0);
+	
 	return (wait_data.mac);
 }

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

@@ -18,8 +18,8 @@
 #define PXE_AWAIT_NEXTTRY	0x03		/* continue with next try */
 #define PXE_AWAIT_BREAK		0x04		/* wait ended with failure */
 
-#define TIME_DELTA_MS		100
-#define TIME_DELTA		100000
+#define TIME_DELTA_MS		10
+#define TIME_DELTA		10000
 
 /* universal waiting function */
 int pxe_await(pxe_await_func func, uint16_t try_counter, uint32_t timeout, void *data);

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

@@ -13,7 +13,12 @@
 pxe_buffer_write(PXE_BUFFER *buf, const void *from, uint16_t size)
 {
 	uint16_t	to_write = (size < buf->bufleft) ? size : buf->bufleft;
-	
+
+#ifdef PXE_DEBUG_HELL
+	printf("pxe_buffer_write(): fstart %d, fend %d, bufleft %d (of %d), to_write %d (%d)\n",
+	    buf->fstart, buf->fend, buf->bufleft, buf->bufsize, to_write, size);
+#endif			
+
 	if (to_write == 0)	/* no space left*/
 		return (0);
 		
@@ -26,31 +31,35 @@
 			
 	} else {/* may be need to place, using two memcpy operations */
 		
-		/* right part of space */
+		/* right part of buffer */
 		uint16_t part1 = buf->bufsize - buf->fstart;
-		uint16_t part2 = 0;
-		
+		/* left part of buffer */
+		uint16_t part2 = to_write - part1;
+
+		if (part1)
+			pxe_memcpy(from, buf->data + buf->fstart, part1);
+
 		if (part1 >= to_write) {
-			pxe_memcpy(from, buf->data + buf->fstart, to_write);
 			buf->fstart += to_write;
+
+			if (buf->fstart > buf->bufsize) {
+				printf("pxe_buffer_write(): internal error! fstart = %d", buf->fstart);
+			}
 		} else {
-			pxe_memcpy(from, buf->data + buf->fstart, part1);
-			/* left part of space */
-			part2 = to_write - part1;
 			pxe_memcpy(from + part1, buf->data, part2);
-			buf->fstart = part2;			
+			buf->fstart = part2;
 		}
+		
 #ifdef PXE_DEBUG_HELL
-		printf("pxe_buffer_write(): fstart %d, fend %d, bufleft %d (of %d)\n\tpart1 %d, part2 %d, to_write %d (%d)\n",
-		    buf->fstart, buf->fend, buf->bufleft, buf->bufsize, part1, part2, to_write, size);
-#endif		
+		printf("pxe_buffer_write(): fstart %d, fend %d, bufsize %d\n\tpart1 %d, part2 %d, to_write %d (%d)\n",
+		    buf->fstart, buf->fend, buf->bufsize, part1, part2, to_write, size);
+#endif
 	}
 
-
 	buf->bufleft -= to_write;
 
-#ifdef PXE_DEBUG_HELL			
-	printf("bufleft %d (-%d)\n", buf->bufleft, to_write);
+#ifdef PXE_DEBUG
+	printf("pxe_buffer_write(): bufleft %d (-%d)\n", buf->bufleft, to_write);
 #endif	
 	return (to_write);
 }
@@ -58,7 +67,7 @@
 /* pxe_buffer_read() - reades data from buffer, if possible
  * in:
  *	buf	- pointer to buffer structure
- *	to	- pointer to data to read to
+ *	to	- pointer to data to read to, if NULL data is read but not placed anywhere
  *	size	- size of data buffer
  * out:
  *	actual count of read bytes
@@ -77,36 +86,31 @@
 	uint16_t fend = buf->fend;
 	uint16_t bufsize = buf->bufsize;
 	
-	if (fstart < fend) { /* two cases */
-	
-		if (fend != bufsize) { /* case one: |**s...e***| */
-			/* right part of buffer */
-			uint16_t part1 = bufsize - fend;
-			/* left part of buffer */
-			uint16_t part2 = to_read - part1;
+	if (fstart <= fend) { /* two cases handling: |*s...e**|, |***se***| */
+		/* right part of buffer */
+		uint16_t part1 = bufsize - fend;
+		/* left part of buffer */
+		uint16_t part2 = to_read - part1;
 
-			if (to != NULL) {
-				pxe_memcpy(buf->data + fend, to, part1);
+		if (part1 && (to != NULL) )
+			pxe_memcpy(buf->data + fend, to, part1);
+		
+		if (part1 >= to_read) {
+			buf->fend += to_read;
+		} else {
+			if (to != NULL)
 				pxe_memcpy(buf->data, to + part1, part2);
-			}
-					
-			buf->fend = part2;	
+			
+			buf->fend = part2;			
+		}
 		
-		} else  { /* case two: |***s.....e| */
-		
-			if (to != NULL)
-				pxe_memcpy(buf->data, to, to_read);
+	} else  { /* third case: |..e**s...| */
 
-			buf->fend = to_read;	
-		}
-	
-	} else { /* third case: |..e**s...|*/
 		if (to != NULL)	
 			pxe_memcpy(buf->data + buf->fend, to, to_read);
 		
 		buf->fend += to_read;	
-	}
-	
+	} 
 
 	buf->bufleft += to_read;
 
@@ -143,14 +147,18 @@
 pxe_buffer_memalloc(PXE_BUFFER *buffer, uint16_t size)
 {
 
-	if (buffer->data != NULL) { /* don't alloc nothing, if mem already allocated */
-		return (0);
+	if (buffer->data == NULL) { /* alloc if not already allocated */
+		buffer->data = pxe_alloc(size);
+	
+		if (buffer->data == NULL)
+			return (0);
 	}
 	
-	buffer->data = pxe_alloc(size);
-	
-	if (buffer->data == NULL)
-		return (0);
+
+	buffer->bufsize = size;
+	buffer->bufleft = size;
+        buffer->fstart = 0;
+        buffer->fend = size;
 		
 	return (1);
 }

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

@@ -4,7 +4,7 @@
 #include <stdint.h>
 
 /* buffer size choosed by default for sending/recieving*/
-#define PXE_DEFAULT_RECV_BUFSIZE        8192
+#define PXE_DEFAULT_RECV_BUFSIZE	32768
 #define PXE_DEFAULT_SEND_BUFSIZE        4096
 
 /* pxe_buffer - buffer related information */

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

@@ -221,26 +221,26 @@
 	if (connection->state == PXE_TCP_CLOSED) { /* already  closed */
 #ifdef PXE_DEBUG
 		printf("pxe_tcp_disconnect(): connection already is closing.\n");
-#endif		
+#endif
 		return (1);
 	}
 	
 	/* if connection in established state - initiate active close */
-	if (connection->state == PXE_TCP_ESTABLISHED) {
-		if (!pxe_tcp_syssend(connection, PXE_TCP_FIN | PXE_TCP_ACK)) {
-			printf("pxe_tcp_disconnect(): failed to send FIN.\n");
-			free_connection(connection);
-			return (0);
-		}
+	if (!pxe_tcp_syssend(connection, PXE_TCP_FIN | PXE_TCP_ACK)) {
+		printf("pxe_tcp_disconnect(): failed to send FIN.\n");
+		free_connection(connection);
+		return (0);
 	}
-
 	/* update sequence number */	
 	connection->next_send += 1;
-	connection->state = PXE_TCP_FIN_WAIT1;
+
+	if (connection->state == PXE_TCP_ESTABLISHED)
+		connection->state = PXE_TCP_FIN_WAIT1;
+
 	connection->state_out = PXE_TCP_FIN;
 #ifdef PXE_DEBUG
 	printf("pxe_tcp_disconnect(): new state - FIN_WAIT_1\n");
-#endif	
+#endif
 	PXE_TCP_WAIT_DATA wait_data;
 	wait_data.connection = connection;
 	
@@ -248,7 +248,7 @@
 	
 	/* await TIME_WITE state.
 	 * connection will fell in this state in pxe_tcp_callback(),
-	 * TODO: add waiting of TCP_CLOSED also
+	 * TODO: add waiting of LAST_ACK also
 	 */
 	if (!pxe_await(tcp_await, 5, PXE_TCP_MSL / 5, &wait_data)) { /* failed to get to TIME_WAIT state */
 	    	free_connection(connection);
@@ -265,7 +265,7 @@
 	
 #ifdef PXE_DEBUG
 	printf("pxe_tcp_disconnect(): connection closed.\n");
-#endif	
+#endif
 	return (1);
 }
 
@@ -404,8 +404,8 @@
 	if (result != 0) { 
 
 		/* if receive window was zero and now is big enough, notify remote host */
-		if ( (recv_buffer->bufleft > PXE_DEFAULT_RECV_BUFSIZE / 4) &&
-		     (connection->winlock == 1) )
+		if ( (connection->winlock == 1) &&
+		     (recv_buffer->bufleft > PXE_DEFAULT_RECV_BUFSIZE / 4))
 		{
 			if (!pxe_tcp_syssend(connection, PXE_TCP_ACK)) {
 				printf("pxe_tcp_read(): failed to notify remote host about window.\n");
@@ -415,8 +415,9 @@
 		}
 	}
 	
-	/* process new packets if there are any */
-	pxe_core_recv_packets();
+	/* process new packets if too low data in buffer */
+	if (recv_buffer->bufleft > recv_buffer->bufsize / 2)
+		pxe_core_recv_packets();
 	
 	return (result);
 }
@@ -468,6 +469,51 @@
 	return (1);
 }
 
+/* pxe_tcp_check_connection() - checks connections state by sending ACK,
+ *				used e,g, to notify remote host about enough window to recv
+ * in:
+ *      sock		- TCP socket to check connection for
+ * out:
+ *      0	- failed
+ *      1	- success
+ */
+int
+pxe_tcp_check_connection(PXE_SOCKET *sock)
+{
+#ifdef PXE_DEBUG
+	printf("pxe_tcp_check_connection(): started.\n");
+#endif
+	PXE_TCP_CONNECTION	*connection = filter_to_connection(sock->filter);
+
+	if (connection == NULL) {
+		printf("pxe_tcp_check_connection(): no connection for filter 0x%x (socket: 0x%x).\n",
+		    sock->filter, sock
+		);
+		return (0);
+	}
+
+	if (connection->state != PXE_TCP_ESTABLISHED) {
+		printf("pxe_tcp_check_connection(): connection 0x%x is not in established state(%d).\n",
+		    connection, connection->state
+		);
+		return (0);	/* connection not in established state, ignore available data */
+	}
+	
+	PXE_BUFFER *buffer = connection->recv;
+	
+	/* send ACK ony if we place for one segment at least */
+	if (buffer->bufleft < buffer->bufsize / 2) {
+		return (0);
+	}
+	
+	if (!pxe_tcp_syssend(connection, PXE_TCP_ACK)) {
+		printf("pxe_tcp_check_connection(): failed to send ACK.\n");
+		return (0);
+	}
+	
+	return (1);
+}
+
 void
 pxe_connection_stats()
 {

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

@@ -89,4 +89,7 @@
 /* pushes current segment data */
 int pxe_tcp_push(PXE_SOCKET *sock);
 
+/* checks connection, by sending ACK */
+int pxe_tcp_check_connection(PXE_SOCKET *sock);
+
 #endif

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

@@ -22,6 +22,7 @@
 #define	PXE_BUFFER_SIZE		0x1000
 static uint8_t      scratch_buffer[PXE_BUFFER_SIZE];
 static uint8_t      data_buffer[PXE_BUFFER_SIZE];
+static uint8_t	    exclusive_protocol = 0;
 static pxenv_t	    *pxenv = NULL;    /* PXENV+ */
 static pxe_t	    *pxe   = NULL;    /* !PXE */
 static BOOTPLAYER   bootplayer;         /* PXE Cached information. */
@@ -425,7 +426,7 @@
  *	1 - success
  *	0 - failed
  */
-int
+static int
 pxe_core_call(int func)
 {
 #ifdef PXE_DEBUG_HELL
@@ -520,6 +521,7 @@
 
 		if (undi_send->Status != 0) {
 			printf("%d: pxe_core_transmit(): failed with status 0x%x\n", tryCount, undi_send->Status);
+			delay(100);
 	    		continue;
 		}
 		
@@ -541,7 +543,7 @@
  *	0 - failed
  *	1 - success
  */
-int
+static int
 pxe_core_get_packet(int func, t_PXENV_UNDI_ISR *undi_isr )
 {
 #ifdef PXE_DEBUG_HELL
@@ -586,7 +588,7 @@
 			if (count == 10)
 			    return (0);
 			    
-			delay(1000);	/* wait, may be it will be not busy later */
+			delay(10);	/* wait, may be it will be not busy later */
 
 			continue;
 		}
@@ -682,11 +684,23 @@
 		++packets_dropped;
 		drop_flag = 1;		/* clear queue, receiving all frames of packet */
 	}
+	
+	/* experimental: to avoid resendings of ip packets for unknown MAC*/
+	if (exclusive_protocol && (protocol != exclusive_protocol)) {
+#ifdef PXE_DEBUG
+		printf("recv_packets(): dropping packet, not exclusive protocol (%d != %d).\n",
+			protocol, exclusive_protocol
+		);
+#endif		
+		++packets_dropped;
+		drop_flag = 1;		/* clear queue, receiving all frames of packet */	
+	}
 
 	/* sanity check */
 	if (frame_size < PXE_BUFFER_SIZE) {
 		pxe_core_copy(	undi_isr->Frame.segment, undi_isr->Frame.offset,
 			VTOPSEG(data_buffer), VTOPOFF(data_buffer), frame_size);
+/*		pxe_memcpy(PTOV(undi_isr->Frame.segment * 16 + undi_isr->Frame.offset), data_buffer, frame_size); */
 	} else {
 		printf("pxe_core_recv_packets(): not enough buffer size (%d bytes) for frame size %d bytes.\n",
 		    PXE_BUFFER_SIZE, frame_size);
@@ -916,6 +930,22 @@
     core_protocol[proto]=proc;
 }
 
+/* pxe_core_exclusive() -  sets protocol exclusive when receiving packets
+ * in:
+ * 	proto	- IP protocol number
+ * out:
+ *	none
+ */
+void
+pxe_core_exclusive(uint8_t proto)
+{
+#ifdef PXE_DEBUG_HELL
+	printf("pxe_core_exlusive(): %d protocol.\n", proto);
+#endif
+	exclusive_protocol = proto;
+}
+
+
 /* pxe_get_mymac() - returns NIC MAC
  * in:
  *	none

==== //depot/projects/soc2007/taleks-pxe_http/pxe_core.h#14 (text+ko) ====

@@ -106,6 +106,9 @@
 /* registers protocol */
 void pxe_core_register(uint8_t ip_proto, pxe_protocol_call proc);
 
+/* set this protocol exclusive, other packets are ignored */
+void pxe_core_exclusive(uint8_t proto);
+
 /* returns NIC MAC */
 const MAC_ADDR *pxe_get_mymac();
 

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

@@ -118,7 +118,7 @@
 	reply_icmphdr->checksum =
 	        ~pxe_ip_checksum(reply_icmphdr, sizeof(PXE_ICMP_HDR) + data_size);
 		
-	if (!pxe_ip_send(pack->data, iphdr->src_ip, PXE_ICMP_PROTOCOL, pack->data_size, 1) && echo_flags) {
+	if (!pxe_ip_send(pack->data, iphdr->src_ip, PXE_ICMP_PROTOCOL, pack->data_size) && echo_flags) {
 		printf("pxe_ping(): failed to send echo reply.\n");
 	}
 
@@ -193,7 +193,7 @@
 		icmphdr->checksum =
 		    ~(pxe_ip_checksum(icmphdr, sizeof(PXE_ICMP_HDR) + 32));
 
-	    	if (!pxe_ip_send(data, ip->ip, PXE_ICMP_PROTOCOL, pack_size, 1) && echo_flags) {
+	    	if (!pxe_ip_send(data, ip->ip, PXE_ICMP_PROTOCOL, pack_size) && echo_flags) {
 			printf("pxe_ping(): failed to send echo reply.\n");
 		}	
 

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

@@ -350,54 +350,39 @@
  *	dst_ip	- destination IP address
  *	protocol- IP stack protocol (e.g. UDP)
  *	size	- size of data buffer
- *	flags	- 1 if space reserved in buffer for IP header, 0 - otherwise
  * out:
  *	0	- failed
  *	1	- success
  */
 int
-pxe_ip_send(void *data, uint32_t dst_ip, uint8_t protocol, uint16_t size, int flags)
+pxe_ip_send(void *data, uint32_t dst_ip, uint8_t protocol, uint16_t size)
 {
-	uint16_t	pack_size = (flags == 0) ? size + sizeof(PXE_IP_HDR) : size;
-	PXE_PACKET	pack;
-	PXE_PACKET*	pack_out = &pack;
+	PXE_PACKET	pack_out;
 	int		status = 0;
 	
-	/* flags == 0: there is no space for ip header in user buffer
-	 * flags == 1: user manually allocated space for ip header
-	 */ 
-	if (flags == 0) {
-		pack_out = pxe_core_alloc_packet(pack_size);
-
-		if (pack_out == NULL) {	/* failed to allocate packet*/
-			return (0);
-		}
-		
-		/* copying user data */
-		pxe_memcpy(data, pack_out->data + sizeof(PXE_IP_HDR), size);
-	} else {
+	pack_out.data = data;
+	pack_out.data_size = size;
 	
-		pack_out->data = data;
-		pack_out->data_size = size;
-	}
-      
-	
 	/* creating ip header */
-	pxe_create_ip_hdr(pack_out->data, dst_ip, protocol, pack_size, 0);
+	pxe_create_ip_hdr(pack_out.data, dst_ip, protocol, size, 0);
 	 
-	/* setting pxe_core packet parameters*/
-        pack_out->flags = (dst_ip != PXE_IP_BCAST) ? PXE_SINGLE : PXE_BCAST;
-        pack_out->protocol = PXE_PROTOCOL_IP;	
+	/* setting pxe_core packet parameters */
+        pack_out.flags = (dst_ip != PXE_IP_BCAST) ? PXE_SINGLE : PXE_BCAST;
+        pack_out.protocol = PXE_PROTOCOL_IP;	
 	
-	/* find gateway or direct MAC*/
+	/* find gateway or direct MAC */
 	uint32_t	ip_to_send = dst_ip;
 	
-	if (pack_out->flags != PXE_BCAST) {
+	if (pack_out.flags != PXE_BCAST) {
 		ip_to_send = pxe_ip_route_find(dst_ip);
-	        pack_out->dest_mac = pxe_arp_ip4mac(ip_to_send);
-	}
+	        pack_out.dest_mac = pxe_arp_ip4mac(ip_to_send);
+	} 
+#ifdef PXE_DEBUG_HELL
+	printf("pxe_ip_send(): %d proto, 0x%x, %s.\n", protocol, pack_out.dest_mac,
+		pack_out.flags == PXE_SINGLE ? "single" : "bcast");
+#endif	
 
-        if ( (pack_out->flags != PXE_BCAST) && (pack_out->dest_mac == NULL) ) {	
+        if ( (pack_out.flags != PXE_BCAST) && (pack_out.dest_mac == NULL) ) {	
 		/* MAC is not found for destination ip or gateway */
 #ifdef PXE_DEBUG
 		PXE_IPADDR dst;
@@ -411,7 +396,7 @@
 		);
 #endif
         } else  {
-                if (!pxe_core_transmit(pack_out)) {
+                if (!pxe_core_transmit(&pack_out)) {
 #ifdef PXE_DEBUG
                         printf("pxe_ip_send(): failed to send packet.\n");
 #endif			
@@ -420,9 +405,5 @@
 		}
         }
 
-	if (flags == 0) {
-		pxe_core_commit(pack_out);
-	}
-																																	    
 	return (status);
 }

==== //depot/projects/soc2007/taleks-pxe_http/pxe_ip.h#7 (text+ko) ====

@@ -79,7 +79,7 @@
 int pxe_ip_route_default(uint32_t gw);
 
 /* sends ip packet */
-int pxe_ip_send(void *data, uint32_t dst_ip, uint8_t protocol, uint16_t size, int flags);
+int pxe_ip_send(void *data, uint32_t dst_ip, uint8_t protocol, uint16_t size);
 
 /* show route table */
 void pxe_ip_route_stat();

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

@@ -84,6 +84,9 @@
 	void			*data = NULL;
 	PXE_TCP_QUEUED_SEGMENT	*segment = NULL;
 	
+	if (connection->send == NULL)
+		return (NULL);
+	
 	for ( ; block_index < PXE_TCP_BLOCK_COUNT; ++block_index) {
 
 		/* start of block */
@@ -168,7 +171,7 @@
 pxe_resend_check(PXE_TCP_CONNECTION *connection)
 {
 #ifdef PXE_DEBUG
-	printf("pxe_resend_check(): started.\n");
+	printf("pxe_resend_check(): started, state %d.\n", connection->state);
 #endif
         PXE_BUFFER              *buffer = connection->send;
         void                    *data = buffer->data;
@@ -203,6 +206,10 @@
 				segment->trys += 1;				
 				segment->resend_at += PXE_RESEND_TIME * segment->trys;
 				
+				if (segment->trys == PXE_RESEND_TRYS) {
+					/* TODO: need to break connection */
+				}
+				
 				tcp_update_segment(connection, segment);
                                 pxe_tcp_send_segment(connection, segment);
 
@@ -226,6 +233,10 @@
 					/* resend later, with more delay with every try */
 					segment->trys += 1;				
 					segment->resend_at += PXE_RESEND_TIME * segment->trys;
+
+					if (segment->trys == PXE_RESEND_TRYS) {
+						/* TODO: need to break connection */
+					}
 					
 					tcp_update_segment(connection, segment);
 	                                pxe_tcp_send_segment(connection, segment);
@@ -239,6 +250,72 @@
         }
 }
 
+/* pxe_resend_drop_same() - removes from resend queue older segments with same 
+ *			sequence number to avoid duplicate resending of same ACKs and etc.
+ * in:
+ *	connection	- connection to update segments for
+ *	segment		- segment to check with
+ * out:
+ *	none
+ */
+void
+pxe_resend_drop_same(PXE_TCP_CONNECTION *connection, PXE_TCP_QUEUED_SEGMENT *new_segment)
+{
+#ifdef PXE_DEBUG
+	printf("pxe_resend_drop_same(): started.\n");
+#endif
+	uint32_t		drop_seq = new_segment->seq;
+        PXE_BUFFER              *buffer = connection->send;
+        void                    *data = buffer->data;
+        int                     block_index = 0;
+        PXE_TCP_QUEUED_SEGMENT  *segment = NULL;
+	uint8_t			*buf_blocks = connection->buf_blocks;
+				
+        for ( ; block_index < PXE_TCP_BLOCK_COUNT; ++block_index) {
+		
+	        /* block is used exclusevely by one "big" packet, skip this */
+                if (buf_blocks[block_index] == PXE_TCP_BLOCK_EXCLUSIVE) {
+			
+			continue;
+                }				
+		
+                if (buf_blocks[block_index] == PXE_TCP_BLOCK_FREE)
+                        continue;       /* block is unused */
+
+		/* pointer to head chunk of block */
+		data = buffer->data + block_index * PXE_TCP_CHUNK_COUNT * connection->chunk_size;
+
+                segment = (PXE_TCP_QUEUED_SEGMENT *)data;
+		
+		if (segment == new_segment)
+			continue;
+		
+                /* block is dirty, need to check chunks manually  */
+                int chunk_index = 0;
+
+                for ( ; chunk_index < PXE_TCP_CHUNK_COUNT; ++chunk_index) {
+
+			if (segment == new_segment) /* skip segment if it's new_segment */
+				continue;
+				
+                        if ( (segment->status != PXE_SEGMENT_FREE) &&
+			     (segment->seq == drop_seq) )
+			{ /* this segment is renewed by new segment */
+#ifdef PXE_DEBUG_HELL
+				printf("pxe_resend_drop_same(): dropping chunk %d#%d.\n",
+				    chunk_index, block_index
+				);
+#endif			
+				tcp_segment_free(connection, block_index, segment);
+	                }
+
+                        /* point segment to next chunk */
+			data += connection->chunk_size;
+                        segment = (PXE_TCP_QUEUED_SEGMENT *)data;
+                }
+        }	
+}
+
 /* pxe_resend_update() - update segments that were acked
  * in:
  *	connection	- connection to update segments for
@@ -273,7 +350,7 @@
 				continue;	/* it was not ever sent yet */
 
                         if (connection->una >= segment->seq) { /* segment was acked, release it */
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 				printf("pxe_resend_update(): block %d acked.\n", block_index);
 #endif
 				tcp_segment_free(connection, block_index, segment);
@@ -303,9 +380,22 @@
         }
 }
 
+/* pxe_start_segment() - fills initial data in headers for provided segment
+ * in:
+ *	connection	- connection to update segments for
+ *	segment		- segment to start
+ *	add_options	- 1 if add default options (mss), 0 - do not add anything
+ * out:
+ *	none
+ */
 void
 tcp_start_segment(PXE_TCP_CONNECTION *connection, PXE_TCP_QUEUED_SEGMENT *segment, int add_options)
 {
+	if (segment == NULL) {
+		printf("tcp_start_segment(): segment = NULL.\n");
+		return;
+	}
+	
 	PXE_TCP_PACKET  *tcp_packet = (PXE_TCP_PACKET  *)(segment + 1);
 		
 	/* reserving 8 bytes for options */
@@ -340,9 +430,22 @@
 	segment->seq = connection->next_send;
 }
 
+/* pxe_finish_segment() - finishes segmentm calculates checksums and fills sequence numbers
+ * in:
+ *	connection	- connection to update segments for
+ *	segment		- segment to start
+ *	tcp_flags	- flags of header (PXE_TCP_...)
+ * out:
+ *	none
+ */
 void
 tcp_finish_segment(PXE_TCP_CONNECTION *connection, PXE_TCP_QUEUED_SEGMENT *segment, uint8_t tcp_flags)
 {
+	if (segment == NULL) {
+		printf("tcp_finish_segment(): segment = NULL.\n");
+		return;
+	}
+	
 	PXE_TCP_PACKET  *tcp_packet = (PXE_TCP_PACKET  *)(segment + 1);
 		
 	uint16_t length = segment->size - sizeof(PXE_IP_HDR);
@@ -393,9 +496,21 @@
 #endif
 }
 
+/* pxe_update_segment() - updates segment at resending, recalcs checksum for updated header
+ * in:
+ *	connection	- connection to update segments for
+ *	segment		- segment to start
+ * out:
+ *	none
+ */
 void
 tcp_update_segment(PXE_TCP_CONNECTION *connection, PXE_TCP_QUEUED_SEGMENT *segment)
 {
+	if (segment == NULL) {
+		printf("tcp_update_segment(): segment = NULL.\n");
+		return;
+	}
+	
 	PXE_TCP_PACKET  *tcp_packet = (PXE_TCP_PACKET  *)(segment + 1);
 		
 	uint16_t length = segment->size - sizeof(PXE_IP_HDR);
@@ -450,9 +565,14 @@
 int
 pxe_tcp_send_segment(PXE_TCP_CONNECTION *connection, PXE_TCP_QUEUED_SEGMENT *segment)
 {
+	if (segment == NULL) {
+		printf("pxe_tcp_send_segment(): segment = NULL.\n");
+		return (0);
+	}
+	
 	PXE_TCP_PACKET *tcp_packet = (PXE_TCP_PACKET *)(segment + 1);
 	
-	if (!pxe_ip_send(tcp_packet, connection->dst_ip, PXE_TCP_PROTOCOL, segment->size, 1)) {
+	if (!pxe_ip_send(tcp_packet, connection->dst_ip, PXE_TCP_PROTOCOL, segment->size)) {
 		printf("pxe_tcp_send_segment(): failed to send tcp packet to 0x%x\n", connection->dst_ip);
 		return (0);
 	}
@@ -497,7 +617,6 @@
 	
 	printf(" %d bytes.\n", length);
 #endif
-	/* check received packets */
         return (1);
 }
 

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

@@ -11,8 +11,10 @@
 #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
+/* default resend time if not acked, in seconds */
+#define PXE_RESEND_TIME		1
+/* default resend trys */
+#define PXE_RESEND_TRYS		5
 
 /* how much blocks in buffer */
 #define PXE_TCP_BLOCK_COUNT     8
@@ -56,6 +58,9 @@
 /* updates resend queue, removes ACKed segments */
 void pxe_resend_update(PXE_TCP_CONNECTION *connection);
 
+/* removes segments that are dublicates or old versions of new segment */
+void pxe_resend_drop_same(PXE_TCP_CONNECTION *connection, PXE_TCP_QUEUED_SEGMENT *segment);
+
 /* destroys resend queue */
 void pxe_resend_free(PXE_TCP_CONNECTION *connection);
 

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

@@ -94,11 +94,6 @@
 		return (-1);
 	}
 	
-	sbuf->bufsize = PXE_DEFAULT_SEND_BUFSIZE;
-	sbuf->bufleft = PXE_DEFAULT_SEND_BUFSIZE;
-	sbuf->fstart = 0;
-	sbuf->fend = sbuf->bufsize;
-
 	if (!pxe_buffer_memalloc(rbuf, PXE_DEFAULT_RECV_BUFSIZE)) {
 	
 		pxe_buffer_memfree(sbuf);
@@ -106,11 +101,6 @@
 		return (-1);
 	}
 	
-	rbuf->bufsize = PXE_DEFAULT_RECV_BUFSIZE;
-	rbuf->bufleft = PXE_DEFAULT_RECV_BUFSIZE;	
-	rbuf->fstart = 0;
-	rbuf->fend = rbuf->bufsize;
-	
 	return (socket);		
 }
 
@@ -365,7 +355,7 @@
 	printf("pxe_sendto(): %8x:%d -> %8x:%d, size = %d bytes.\n", pxe_get_ip32(PXE_IP_MY), lport, ip, port, size);
 #endif	
 
-	if (!pxe_udp_send(udp_pack, ip, port, lport, size + sizeof(PXE_UDP_PACKET), 1)) {
+	if (!pxe_udp_send(udp_pack, ip, port, lport, size + sizeof(PXE_UDP_PACKET))) {
 		printf("pxe_sendto(): failed to send data.\n");
 		return (-1);
 	}
@@ -498,19 +488,52 @@
 	
 	PXE_SOCKET	*sock = &pxe_sockets[socket];
 	PXE_FILTER_ENTRY *filter = sock->filter;
+
+	if ( (filter->protocol != PXE_UDP_PROTOCOL) &&
+	     (filter->protocol != PXE_TCP_PROTOCOL) )
+	{
+		printf("pxe_recv(): only TCP and UDP sockets are implemented.\n");
+		return (-1);
+	}
 	
-	if (filter->protocol == PXE_UDP_PROTOCOL) {
+	uint32_t timer = 0;
+	uint32_t check_timer = 0;
+
+	int	 result = 0;	
 	
-		return pxe_udp_read(sock, tobuf, buflen);
+	while (1) {
 		
-	} else if (filter->protocol == PXE_TCP_PROTOCOL) {
+		if (filter->protocol == PXE_UDP_PROTOCOL) {
 	
-		return pxe_tcp_read(sock, tobuf, buflen);
-	}	
+		    result =  pxe_udp_read(sock, tobuf, buflen);
+		
+		} else {
 	
-	printf("pxe_recv(): only TCP and UDP sockets are implemented.\n");
+		    result =  pxe_tcp_read(sock, tobuf, buflen);
+
+		} 
+		
+		if (result != 0)
+			break;
+		
+		if (timer > PXE_SOCKET_TIMEOUT * 1000)
+			break;
+		
+		if (filter->protocol == PXE_TCP_PROTOCOL) {
 
-	return (-1);
+			if (check_timer > PXE_SOCKET_CHECK_TIMEOUT) {
+				check_timer = 0;
+				pxe_tcp_check_connection(sock);
+			}
+		}
+		
+		check_timer += 10;
+		timer += 10;
+		/* idle 10 ms */
+		delay(10000);
+	}
+	
+	return (result);
 }
 
 /* pxe_recvfrom() - receive data to socket with information about sender

==== //depot/projects/soc2007/taleks-pxe_http/pxe_sock.h#10 (text+ko) ====

@@ -12,6 +12,10 @@
 #define PXE_DEFAULT_SOCKETS             8
 /* default count of waiting queue */
 #define PXE_DEFAULT_WAITCOUNT           3
+/* socket timeout when receiving data, in seconds */
+#define PXE_SOCKET_TIMEOUT		30
+/* timeout, after that force connection checking, in milliseconds */
+#define PXE_SOCKET_CHECK_TIMEOUT	200
 /* socket states */
 #define PXE_SOCKET_FREE                 0x0	/* socket unused and free for allocating  */
 #define PXE_SOCKET_USED                 0x1	/* socket structure used */

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

@@ -109,6 +109,12 @@
 int
 tcp_is_acceptable(PXE_TCP_CONNECTION *connection, PXE_TCP_PACKET *tcp_packet, uint16_t seglen)
 {
+	if (connection == NULL)
+		return (0);
+

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list