Module: xenomai-gch Branch: stable-3.0.x Commit: d9c2d6cfb0b13687d6125973f42792d99224d576 URL: http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=d9c2d6cfb0b13687d6125973f42792d99224d576
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. 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? 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