6LoWPAN: Handle case where the local address is zero (listen socket)
This commit is contained in:
parent
2fb938202c
commit
96af668ab8
@ -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:
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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]);
|
||||
|
@ -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 */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user