Module: xenomai-gch
Branch: stable-3.0.x
Commit: 1175724929fd620ac3611d4169df4d60ec4b9851
URL:    
http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=1175724929fd620ac3611d4169df4d60ec4b9851

Author: Matti Suominen <matti.suomi...@wapice.com>
Date:   Wed Jun 15 10:49:17 2016 +0200

rtnet: various fixes

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. We avoid
this by forwarding such packets to the rtnetproxy when it is enabled.

Note that RTnet TCP is still disabled as we need to fix the "accept"
syscall to be able to create sockets without switching to primary
mode.

---

 kernel/drivers/net/stack/ipv4/tcp/tcp.c |   52 ++++++++++++++++++-------------
 1 file changed, 31 insertions(+), 21 deletions(-)

diff --git a/kernel/drivers/net/stack/ipv4/tcp/tcp.c 
b/kernel/drivers/net/stack/ipv4/tcp/tcp.c
index 8bbb740..61a01cb 100644
--- a/kernel/drivers/net/stack/ipv4/tcp/tcp.c
+++ b/kernel/drivers/net/stack/ipv4/tcp/tcp.c
@@ -704,7 +704,7 @@ rt_tcp_segment(struct dest_route *rt, struct tcp_socket 
*ts, __be32 flags,
 
     /* 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 @@ rt_tcp_segment(struct dest_route *rt, struct tcp_socket 
*ts, __be32 flags,
 
     /* 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,7 +832,13 @@ static struct rtsocket *rt_tcp_dest_socket(struct rtskb 
*skb)
        /*
          rtdm_printk("Not found addr:0x%08x, port: 0x%04x\n", daddr, dport);
        */
-       if (!th->rst) {
+#ifdef CONFIG_RTNET_ADDON_PROXY
+           if (rt_ip_fallback_handler) {
+                   /* If a fallback handler for IP protocol has been installed,
+                    * call it. */
+                   return NULL;
+           }
+#endif if (!th->rst) {
            /* No listening socket found, send RST|ACK */
            rst_socket.saddr = daddr;
            rst_socket.daddr = saddr;
@@ -846,7 +852,7 @@ static struct rtsocket *rt_tcp_dest_socket(struct rtskb 
*skb)
 
            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);
            }
        }
@@ -918,7 +924,7 @@ static void rt_tcp_rcv(struct rtskb *skb)
     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 @@ static void rt_tcp_rcv(struct rtskb *skb)
            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 @@ static void rt_tcp_rcv(struct rtskb *skb)
 
        /* 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 @@ static void rt_tcp_rcv(struct rtskb *skb)
     } 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 @@ static void rt_tcp_rcv(struct rtskb *skb)
        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 @@ static void rt_tcp_rcv(struct rtskb *skb)
            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 @@ static void rt_tcp_rcv(struct rtskb *skb)
            /* 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 @@ static void rt_tcp_rcv(struct rtskb *skb)
            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 @@ static void rt_tcp_rcv(struct rtskb *skb)
     /* 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 @@ static int rt_tcp_window_send(struct tcp_socket *ts, u32 
data_len,
     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 @@ static void rt_tcp_close(struct rtdm_fd *fd)
        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 @@ static void rt_tcp_close(struct rtdm_fd *fd)
     } 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 @@ static int rt_tcp_connect(struct tcp_socket *ts, const 
struct sockaddr *serv_add
     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 @@ static int rt_tcp_accept(struct tcp_socket *ts, struct 
sockaddr *addr,
     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 @@ static ssize_t rt_tcp_read(struct rtdm_fd *fd, void *buf, 
size_t nbyte)
            } 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 @@ static ssize_t rt_tcp_read(struct rtdm_fd *fd, void *buf, 
size_t nbyte)
        } 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) {


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
https://xenomai.org/mailman/listinfo/xenomai-git

Reply via email to