All of lore.kernel.org
 help / color / mirror / Atom feed
* [Xenomai] A fix to few generic issues in rttcp stack
@ 2016-03-31 10:33 Matti Suominen
  2016-03-31 10:44 ` Gilles Chanteperdrix
  2016-04-03 19:09 ` Gilles Chanteperdrix
  0 siblings, 2 replies; 15+ messages in thread
From: Matti Suominen @ 2016-03-31 10:33 UTC (permalink / raw)
  To: xenomai@xenomai.org, Lassi Niemistö, rpm@xenomai.org

Hi,

I have case where we use rtnet's tcp socket in server application to 
communicate with real time and non-real time tcp clients. To get 
communication work between client and server I had to do some changes to 
stack/ipv4/tcp/tcp.c file.

First. Original tcp flag enumeration didn't work at all in this case. This 
was verified by using Wireshark to track communication which didn't show 
me any flags in tcp packets. This was solved by replacing flags assigning 
TCP_FLAG_ prefixed enums with TCPHDR_ prefixed defines from <net/tcp.h> in 
stack/ipv4/tcp/tcp.c file. The original code only works in case of little 
endian machine, as rt_tcp_set_flags function places assumption that flags 
are located in the least-significant 8bits of the 32bit flag variable. 
This approach is similar to what regular TCP is using: 
https://github.com/torvalds/linux/blob/master/net/ipv4/tcp.c

Second. Server was able to receive messages from client but was unable to 
reply messages. I was able to trace function calls by adding debug prints 
to tcp.c functions and noticed that accepted socket wasn't signaled for 
"ready to send" at all and server was unable to reply messages. This seems 
to work properly if the send signal is posted in the end of the accept 
function, which also would seem the logical way to initialize it once 
connection has been established.

Third. In our case we have regular Linux tcp sockets and rtnet tcp sockets 
working parallel, serving different services. Referred to this I noticed 
that *rt_tcp_dest_socket() may cause problem when real time stack 
processes a message targeted to a regular Linux socket and does not find a 
rttcp socket for it. The rttcp stack then  tries to send RST|ACK to client 
to terminate the connection. This is temporarily disabled by setting 
"if (!th->rst)" clause into #ifdef YET_UNUSED. This should be corrected 
for example by implementing layer which is able to loop also non real time 
sockets. Or is it really a desired rttcp design principle to unsupport the 
usage of regular Linux tcp sockets in parallel?

---------------------------------------------------------------------------

We noticed also that Windows client causes assertion in pool balance at 
end of transmission.

Assertion failed! /src/stack/socket.c:rt_socket_cleanup:199 
(&sock->skb_pool)->pool_balance == 0

Call Trace:
[cbe97db0] [c00087e0] show_stack+0x48/0x150 (unreliable)
[cbe97df0] [d3830414] rt_socket_cleanup+0x13c/0x140 [rtnet]
[cbe97e10] [d38a1f00] rt_tcp_close+0x2b0/0x3a8 [rttcp]
[cbe97e50] [c009d3c0] __rt_dev_close+0x174/0x368
[cbe97e80] [c0071588] hisyscall_event+0x18c/0x35c
[cbe97ec0] [c00615c0] __ipipe_dispatch_event+0xac/0x1ec
[cbe97f20] [c000ea5c] __ipipe_syscall_root+0x5c/0x140
[cbe97f40] [c000fe60] DoSyscall+0x20/0x5c
--- Exception: c01 at 0x4899ba08

This is still unsolved but it seems not to cause harms.

---------------------------------------------------------------------------

Difference between Xenomai 3 tcp.c and our tcp.c additions at end of 
message. Our fixes is based to rtnet 0.9.13, but this is how we could do 
fix if we use Xenomai 3's rtnet.

Best regards,
Matti Suominen
Wapice Oy
Vaasa, Finland

---------------------------------------------------------------------------

PowerPC, CPU: MPC8309E
RTNet version 0.9.13
Xenomai 2.6.1
Linux version 3.1.10-ipipe

---------------------------------------------------------------------------
--- xeno3-tcp.c	2016-03-30 09:49:36.020400900 +0300
+++ xeno3-tcp-diff.c	2016-03-31 10:04:44.744351290 +0300
@@ -704,7 +704,7 @@
 
     /* add rtskb entry to the socket retransmission queue */
     if (ts->tcp_state != TCP_CLOSE &&
-	((flags & (TCP_FLAG_SYN|TCP_FLAG_FIN)) || data_len)) {
+	((flags & (TCPHDR_SYN|TCPHDR_FIN)) || data_len)) {
 	/* rtskb_clone below is called under lock, this is an admission,
 	   because for now there is no rtskb copy by reference */
 	cloned_skb = rtskb_clone(skb, &ts->sock.skb_pool);
@@ -720,7 +720,7 @@
 
     /* need to update sync here, because it is safe way in
        comparison with races on fast ACK response */
-    if (flags & (TCP_FLAG_FIN|TCP_FLAG_SYN))
+    if (flags & (TCPHDR_FIN|TCPHDR_SYN))
 	ts->sync.seq++;
 
     ts->sync.seq += data_len;
@@ -832,6 +832,11 @@
 	/*
 	  rtdm_printk("Not found addr:0x%08x, port: 0x%04x\n", daddr, dport);
 	*/
+#ifdef YET_UNUSED
+/* This ifdef is added because parallel use of linux and rt_dev sockets may
+ * produce unwanted connection close when application uses linux socket instead
+ * of rt_dev sockets and cannot find destination socket for package.
+ */
 	if (!th->rst) {
 	    /* No listening socket found, send RST|ACK */
 	    rst_socket.saddr = daddr;
@@ -846,10 +851,11 @@
 
 	    if (rt_ip_route_output(&rst_socket.rt, daddr, saddr) == 0) {
 		rt_socket_reference(&rst_socket.sock);
-		rt_tcp_send(&rst_socket, TCP_FLAG_ACK|TCP_FLAG_RST);
+		rt_tcp_send(&rst_socket, TCPHDR_ACK|TCPHDR_RST);
 		rtdev_dereference(rst_socket.rt.rtdev);
 	    }
 	}
+#endif
     }
 
     return skb->sk;
@@ -918,7 +924,7 @@
     if (ts->sync.ack_seq == (seq + 1) &&
 	ts->tcp_state == TCP_ESTABLISHED) {
 	rtdm_lock_put_irqrestore(&ts->socket_lock, context);
-	rt_tcp_send(ts, TCP_FLAG_ACK);
+	rt_tcp_send(ts, TCPHDR_ACK);
 	goto feed;
     }
 
@@ -930,7 +936,7 @@
 	    rtdm_lock_put_irqrestore(&ts->socket_lock, context);
 	    rtdm_event_signal(&ts->conn_evt);
 	    /* Send ACK */
-	    rt_tcp_send(ts, TCP_FLAG_ACK);
+	    rt_tcp_send(ts, TCPHDR_ACK);
 	    goto feed;
 	}
 
@@ -940,7 +946,7 @@
 
 	/* Send RST|ACK */
 	rtdm_event_signal(&ts->conn_evt);
-	rt_tcp_send(ts, TCP_FLAG_RST|TCP_FLAG_ACK);
+	rt_tcp_send(ts, TCPHDR_RST|TCPHDR_ACK);
 	goto drop;
     }
 
@@ -965,7 +971,7 @@
     } else if (rt_tcp_after(seq, ts->sync.ack_seq - data_len)) {
 	/* retransmission of data we already acked */
 	rtdm_lock_put_irqrestore(&ts->socket_lock, context);
-	rt_tcp_send(ts, TCP_FLAG_ACK);
+	rt_tcp_send(ts, TCPHDR_ACK);
 	goto drop;
     } else {
 	/* drop forward ack */
@@ -995,7 +1001,7 @@
 	if (rt_ip_route_output(&rst_socket.rt, rst_socket.daddr,
 			       rst_socket.saddr) == 0) {
 	    rt_socket_reference(&rst_socket.sock);
-	    rt_tcp_send(&rst_socket, TCP_FLAG_RST|TCP_FLAG_ACK);
+	    rt_tcp_send(&rst_socket, TCPHDR_RST|TCPHDR_ACK);
 	    rtdev_dereference(rst_socket.rt.rtdev);
 	}
 	goto drop;
@@ -1029,14 +1035,14 @@
 	    if (signal)
 		rt_tcp_socket_invalidate_signal(ts);
 
-	    rt_tcp_send(ts, TCP_FLAG_ACK);
+	    rt_tcp_send(ts, TCPHDR_ACK);
 	    goto feed;
 	} else if ((ts->tcp_state == TCP_FIN_WAIT1 && th->ack) ||
 		   ts->tcp_state == TCP_FIN_WAIT2) {
 	    /* Send ACK */
 	    ts->tcp_state = TCP_TIME_WAIT;
 	    rtdm_lock_put_irqrestore(&ts->socket_lock, context);
-	    rt_tcp_send(ts, TCP_FLAG_ACK);
+	    rt_tcp_send(ts, TCPHDR_ACK);
 	    /* data receiving is not possible anymore */
 	    rtdm_sem_destroy(&ts->sock.pending_sem);
 	    goto feed;
@@ -1044,7 +1050,7 @@
 	    /* Send ACK */
 	    ts->tcp_state = TCP_CLOSING;
 	    rtdm_lock_put_irqrestore(&ts->socket_lock, context);
-	    rt_tcp_send(ts, TCP_FLAG_ACK);
+	    rt_tcp_send(ts, TCPHDR_ACK);
 	    /* data receiving is not possible anymore */
 	    rtdm_sem_destroy(&ts->sock.pending_sem);
 	    goto feed;
@@ -1076,13 +1082,13 @@
 	    rtdm_lock_put_irqrestore(&ts->socket_lock, context);
 
 	    /* Send SYN|ACK */
-	    rt_tcp_send(ts, TCP_FLAG_SYN|TCP_FLAG_ACK);
+	    rt_tcp_send(ts, TCPHDR_SYN|TCPHDR_ACK);
 	    goto drop;
 	}
 
 	/* Send RST|ACK */
 	rtdm_lock_put_irqrestore(&ts->socket_lock, context);
-	rt_tcp_send(ts, TCP_FLAG_RST|TCP_FLAG_ACK);
+	rt_tcp_send(ts, TCPHDR_RST|TCPHDR_ACK);
 	goto drop;
     }
 
@@ -1134,7 +1140,7 @@
     /* Send ACK */
     ts->sync.window -= data_len;
     rtdm_lock_put_irqrestore(&ts->socket_lock, context);
-    rt_tcp_send(ts, TCP_FLAG_ACK);
+    rt_tcp_send(ts, TCPHDR_ACK);
 
     rtskb_queue_tail(&skb->sk->incoming, skb);
     rtdm_sem_up(&ts->sock.pending_sem);
@@ -1181,7 +1187,7 @@
     if (data_len > dst_window)
 	data_len = dst_window;
 
-    if ((ret = rt_tcp_segment(&ts->rt, ts, TCP_FLAG_ACK,
+    if ((ret = rt_tcp_segment(&ts->rt, ts, TCPHDR_ACK,
 			      data_len, data_ptr, 0)) < 0) {
 	rtdm_printk("rttcp: cann't send a packet: err %d\n", -ret);
 	return ret;
@@ -1372,7 +1378,7 @@
 	ts->tcp_state == TCP_SYN_RECV) {
 	/* close() from ESTABLISHED */
 	send_cmd.ts = ts;
-	send_cmd.flags = TCP_FLAG_FIN|TCP_FLAG_ACK;
+	send_cmd.flags = TCPHDR_FIN|TCPHDR_ACK;
 	signal = rt_tcp_socket_invalidate(ts, TCP_FIN_WAIT1);
 
 	rtdm_lock_put_irqrestore(&ts->socket_lock, context);
@@ -1386,7 +1392,7 @@
     } else if (ts->tcp_state == TCP_CLOSE_WAIT) {
 	/* Send FIN in CLOSE_WAIT */
 	send_cmd.ts = ts;
-	send_cmd.flags = TCP_FLAG_FIN|TCP_FLAG_ACK;
+	send_cmd.flags = TCPHDR_FIN|TCPHDR_ACK;
 	signal = rt_tcp_socket_invalidate(ts, TCP_LAST_ACK);
 
 	rtdm_lock_put_irqrestore(&ts->socket_lock, context);
@@ -1532,7 +1538,7 @@
     rtdm_lock_put_irqrestore(&ts->socket_lock, context);
 
     /* Complete three-way handshake */
-    ret = rt_tcp_send(ts, TCP_FLAG_SYN);
+    ret = rt_tcp_send(ts, TCPHDR_SYN);
     if (ret < 0) {
 	rtdm_printk("rttcp: cann't send SYN\n");
 	return ret;
@@ -1668,6 +1674,10 @@
     rtdm_lock_put_irqrestore(&ts->socket_lock, context);
 
     ret = rt_socket_fd(&ts->sock)->fd;
+/*
+ * Socket should be signaled ready to send
+ */
+    rtdm_event_signal(&ts->send_evt);
 
  err:
     /* it is not critical to leave this unlocked
@@ -1931,7 +1941,7 @@
 	    } else {
 		ts->sync.window = block_size;
 		rtdm_lock_put_irqrestore(&ts->socket_lock, context);
-		rt_tcp_send(ts, TCP_FLAG_ACK); /* window update */
+		rt_tcp_send(ts, TCPHDR_ACK); /* window update */
 	    }
 
 	    __rtskb_pull(skb, block_size);
@@ -1954,7 +1964,7 @@
 	} else {
 	    ts->sync.window = block_size;
 	    rtdm_lock_put_irqrestore(&ts->socket_lock, context);
-	    rt_tcp_send(ts, TCP_FLAG_ACK); /* window update */
+	    rt_tcp_send(ts, TCPHDR_ACK); /* window update */
 	}
 
 	if ((skb = skb->next) != NULL) {


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2016-06-13 15:20 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-03-31 10:33 [Xenomai] A fix to few generic issues in rttcp stack Matti Suominen
2016-03-31 10:44 ` Gilles Chanteperdrix
2016-03-31 16:22   ` Gilles Chanteperdrix
2016-04-01  9:36     ` Matti Suominen
2016-04-01 10:40       ` Gilles Chanteperdrix
2016-04-03 19:09 ` Gilles Chanteperdrix
2016-04-30  6:49   ` Gilles Chanteperdrix
2016-05-02  6:32     ` Matti Suominen
2016-05-02  7:10       ` Gilles Chanteperdrix
2016-05-03  4:54         ` Matti Suominen
2016-05-03  5:55           ` Gilles Chanteperdrix
2016-06-13 14:01     ` [Xenomai] PowerPC hardware watchpoints unstable with GDB and Xenomai Lassi Niemistö
2016-06-13 14:30       ` Gilles Chanteperdrix
2016-06-13 15:14         ` Lassi Niemistö
2016-06-13 15:20           ` Gilles Chanteperdrix

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.