6LoWPAN: Handle case where the local address is zero (listen socket)

This commit is contained in:
Gregory Nutt 2017-06-24 11:57:59 -06:00
parent 2fb938202c
commit 96af668ab8
5 changed files with 57 additions and 16 deletions

View File

@ -508,6 +508,10 @@ Configurations
other configurations (see text matrix below).
2017-06-23: Added test for TCP functionality. As of yet unverified.
2017-06-24: There are significant problems with the 6LoWPAN TCP send
logic. The problems are due to the fact that the current design
bypasses the normal TCP sending logic and does not correctly support
ACKs and retransmisions.
Test Matrix:
The following configurations have been tested:

View File

@ -227,7 +227,8 @@ static void sixlowpan_uncompress_ipv6hdr(FAR uint8_t *fptr, FAR uint8_t *bptr)
#ifdef CONFIG_NET_TCP
case IP_PROTO_TCP:
{
FAR struct tcp_hdr_s *tcp = &((FAR struct ipv6tcp_hdr_s *)ipv6)->tcp;
FAR struct tcp_hdr_s *tcp =
(FAR struct tcp_hdr_s *)(fptr + g_frame_hdrlen);
/* The TCP header length is encoded in the top 4 bits of the
* tcpoffset field (in units of 32-bit words).
@ -798,7 +799,7 @@ int sixlowpan_input(FAR struct ieee802154_driver_s *ieee,
* reassembled?
*/
if (ret >= 0 && ret == INPUT_COMPLETE)
if (ret == INPUT_COMPLETE)
{
/* Inject the uncompressed, reassembled packet into the network */

View File

@ -163,6 +163,7 @@ static ssize_t sixlowpan_send_packet(FAR struct tcp_conn_s *conn,
struct sixlowpan_tagaddr_s destmac;
struct ipv6tcp_hdr_s ipv6tcp;
ssize_t pktlen;
uint32_t sndseq;
uint16_t iplen;
int ret;
@ -178,6 +179,18 @@ static ssize_t sixlowpan_send_packet(FAR struct tcp_conn_s *conn,
pktlen = buflen;
}
/* Check if we have "space" in the window */
if (pktlen > conn->winsize)
{
pktlen = conn->winsize;
}
if (pktlen <= 0)
{
return 0;
}
/* Initialize the IPv6/TCP headers */
ipv6tcp.ipv6.vtc = 0x60;
@ -196,10 +209,17 @@ static ssize_t sixlowpan_send_packet(FAR struct tcp_conn_s *conn,
/* Copy the source and destination addresses */
#ifdef CONFIG_NETDEV_MULTINIC
net_ipv6addr_hdrcopy(ipv6tcp.ipv6.srcipaddr, conn->u.ipv6.laddr);
#endif
net_ipv6addr_hdrcopy(ipv6tcp.ipv6.destipaddr, conn->u.ipv6.raddr);
#ifdef CONFIG_NETDEV_MULTINIC
if (!net_ipv6addr_cmp(conn->u.ipv6.laddr, g_ipv6_allzeroaddr))
{
net_ipv6addr_hdrcopy(ipv6tcp.ipv6.srcipaddr, conn->u.ipv6.laddr);
}
else
#endif
{
net_ipv6addr_hdrcopy(ipv6tcp.ipv6.srcipaddr, dev->d_ipv6addr);
}
ninfo("IPv6 length: %d\n",
((int)ipv6tcp.ipv6.len[0] << 8) + ipv6tcp.ipv6.len[1]);
@ -213,15 +233,23 @@ static ssize_t sixlowpan_send_packet(FAR struct tcp_conn_s *conn,
ipv6tcp.tcp.srcport = conn->lport; /* Local port */
ipv6tcp.tcp.destport = conn->rport; /* Connected remote port */
memcpy(ipv6tcp.tcp.ackno, conn->rcvseq, 4); /* ACK number */
memcpy(ipv6tcp.tcp.seqno, conn->sndseq, 4); /* Sequence number */
ipv6tcp.tcp.tcpoffset = (TCP_HDRLEN / 4) << 4; /* No optdata */
ipv6tcp.tcp.flags = 0; /* No urgent data */
ipv6tcp.tcp.urgp[0] = 0; /* No urgent data */
ipv6tcp.tcp.urgp[1] = 0;
/* Set the TCP window */
/* Set the sequency number information */
/* REVISIT: There is currently no wait for the data to be ACKed and,
* hence, no mechanism to retransmit the packet.
*/
memcpy(ipv6tcp.tcp.ackno, conn->rcvseq, 4); /* ACK number */
memcpy(ipv6tcp.tcp.seqno, conn->sndseq, 4); /* Sequence number */
sndseq = tcp_getsequence(conn->sndseq);
tcp_setsequence(conn->sndseq, sndseq + pktlen);
/* Set the TCP window */
if (conn->tcpstateflags & TCP_STOPPED)
{
@ -408,7 +436,7 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
ssize_t pktlen = sixlowpan_send_packet(conn, dev, buf, remaining,
timeout);
if (pktlen < 0)
if (pktlen <= 0)
{
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
return (ssize_t)pktlen;

View File

@ -259,10 +259,15 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock,
net_ipv6addr_hdrcopy(ipv6udp.ipv6.destipaddr, to6->sin6_addr.in6_u.u6_addr16);
#ifdef CONFIG_NETDEV_MULTINIC
net_ipv6addr_hdrcopy(ipv6udp.ipv6.srcipaddr, conn->u.ipv6.laddr);
#else
net_ipv6addr_hdrcopy(ipv6udp.ipv6.srcipaddr, dev->d_ipv6addr);
if (!net_ipv6addr_cmp(conn->u.ipv6.laddr, g_ipv6_allzeroaddr))
{
net_ipv6addr_hdrcopy(ipv6udp.ipv6.srcipaddr, conn->u.ipv6.laddr);
}
else
#endif
{
net_ipv6addr_hdrcopy(ipv6udp.ipv6.srcipaddr, dev->d_ipv6addr);
}
ninfo("IPv6 length: %d\n",
((int)ipv6udp.ipv6.len[0] << 8) + ipv6udp.ipv6.len[1]);

View File

@ -145,6 +145,7 @@ static void tcp_input(FAR struct net_driver_s *dev, uint8_t domain,
if ((conn->tcpstateflags & TCP_STATE_MASK) != TCP_SYN_RCVD &&
(tcp->flags & TCP_CTL) == TCP_SYN)
{
nwarn("WARNING: SYN in TCP_SYN_RCVD\n");
goto reset;
}
else
@ -155,7 +156,7 @@ static void tcp_input(FAR struct net_driver_s *dev, uint8_t domain,
/* If we didn't find an active connection that expected the packet,
* either (1) this packet is an old duplicate, or (2) this is a SYN packet
* destined for a connection in LISTEN. If the SYN flag isn't set,
* destined for a connection in LISTEN. If the SYN flag isn't set,
* it is an old packet and we send a RST.
*/
@ -284,6 +285,8 @@ static void tcp_input(FAR struct net_driver_s *dev, uint8_t domain,
}
}
nwarn("WARNING: Old packet .. reset\n");
/* This is (1) an old duplicate packet or (2) a SYN packet but with
* no matching listener found. Send RST packet in either case.
*/
@ -527,8 +530,8 @@ found:
* handshake is not complete
*/
nerr("Listen canceled while waiting for ACK on port %d\n",
tcp->destport);
nwarn("WARNING: Listen canceled while waiting for ACK on port %d\n",
tcp->destport);
/* Free the connection structure */