diff --git a/net/sixlowpan/sixlowpan_internal.h b/net/sixlowpan/sixlowpan_internal.h index dff37cf6f8..c6a83480d9 100644 --- a/net/sixlowpan/sixlowpan_internal.h +++ b/net/sixlowpan/sixlowpan_internal.h @@ -465,7 +465,7 @@ struct iob_s; /* Forward reference */ * it to be sent on an 802.15.4 network using 6lowpan. Called from common * UDP/TCP send logic. * - * The payload data is in the caller 'buf' and is of length 'len'. + * The payload data is in the caller 'buf' and is of length 'buflen'. * Compressed headers will be added and if necessary the packet is * fragmented. The resulting packet/fragments are put in ieee->i_framelist * and the entire list of frames will be delivered to the 802.15.4 MAC via @@ -473,9 +473,9 @@ struct iob_s; /* Forward reference */ * * Input Parameters: * dev - The IEEE802.15.4 MAC network driver interface. - * destip - IPv6 plus TCP or UDP headers. + * destip - IPv6 plus TCP or UDP headers. * buf - Data to send - * len - Length of data to send + * buflen - Length of data to send * raddr - The MAC address of the destination * timeout - Send timeout in deciseconds * @@ -492,7 +492,7 @@ struct iob_s; /* Forward reference */ int sixlowpan_send(FAR struct net_driver_s *dev, FAR const struct ipv6_hdr_s *destip, FAR const void *buf, - size_t len, FAR const struct rimeaddr_s *raddr, + size_t buflen, FAR const struct rimeaddr_s *raddr, uint16_t timeout); /**************************************************************************** @@ -557,7 +557,7 @@ int sixlowpan_framecreate(FAR struct ieee802154_driver_s *ieee, * ieee - The IEEE802.15.4 MAC driver instance * ipv6hdr - IPv6 header followed by TCP or UDP header. * buf - Data to send - * len - Length of data to send + * buflen - Length of data to send * destmac - The IEEE802.15.4 MAC address of the destination * * Returned Value: @@ -573,7 +573,7 @@ int sixlowpan_framecreate(FAR struct ieee802154_driver_s *ieee, int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, FAR const struct ipv6_hdr_s *ipv6hdr, - FAR const void *buf, size_t len, + FAR const void *buf, size_t buflen, FAR const struct rimeaddr_s *destmac); /**************************************************************************** diff --git a/net/sixlowpan/sixlowpan_tcpsend.c b/net/sixlowpan/sixlowpan_tcpsend.c index bc3e84f934..a7a1a90f3b 100644 --- a/net/sixlowpan/sixlowpan_tcpsend.c +++ b/net/sixlowpan/sixlowpan_tcpsend.c @@ -39,11 +39,13 @@ #include +#include #include #include #include #include "nuttx/net/netdev.h" +#include "nuttx/net/netstats.h" #include "netdev/netdev.h" #include "socket/socket.h" @@ -66,7 +68,7 @@ * Parameters: * psock - An instance of the internal socket structure. * buf - Data to send - * len - Length of data to send + * bulen - Length of data to send * * Returned Value: * On success, returns the number of characters sent. On error, @@ -80,13 +82,14 @@ ****************************************************************************/ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf, - size_t len) + size_t buflen) { FAR struct tcp_conn_s *conn; FAR struct net_driver_s *dev; struct ipv6tcp_hdr_s ipv6tcp; struct rimeaddr_s destmac; uint16_t timeout; + uint16_t iplen; int ret; DEBUGASSERT(psock != NULL && psock->s_crefs > 0); @@ -161,8 +164,79 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf, #endif /* Initialize the IPv6/TCP headers */ -#warning Missing logic + /* Initialize the IPv6/UDP headers */ + + ipv6tcp.ipv6.vtc = 0x60; + ipv6tcp.ipv6.tcf = 0x00; + ipv6tcp.ipv6.flow = 0x00; + ipv6tcp.ipv6.proto = IP_PROTO_TCP; + ipv6tcp.ipv6.ttl = IP_TTL; + + /* The IPv6 header length field does not include the size of IPv6 IP + * header. + */ + + iplen = buflen + TCP_HDRLEN; + ipv6tcp.ipv6.len[0] = (iplen >> 8); + ipv6tcp.ipv6.len[1] = (iplen & 0xff); + + /* Copy the source and destination addresses */ + + net_ipv6addr_hdrcopy(ipv6tcp.ipv6.srcipaddr, conn->u.ipv6.laddr); + net_ipv6addr_hdrcopy(ipv6tcp.ipv6.destipaddr, conn->u.ipv6.raddr); + + ninfo("IPv6 length: %d\n", ((int)ipv6->len[0] << 8) + ipv6->len[1]); + +#ifdef CONFIG_NET_STATISTICS + g_netstats.ipv6.sent++; +#endif + + /* Initialize the TCP header */ + + 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.urgp[0] = 0; /* No urgent data */ + ipv6tcp.tcp.urgp[1] = 0; + + /* Set the TCP window */ + + if (conn->tcpstateflags & TCP_STOPPED) + { + /* If the connection has issued TCP_STOPPED, we advertise a zero + * window so that the remote host will stop sending data. + */ + + ipv6tcp.tcp.wnd[0] = 0; + ipv6tcp.tcp.wnd[1] = 0; + } + else + { + ipv6tcp.tcp.wnd[0] = ((NET_DEV_RCVWNDO(dev)) >> 8); + ipv6tcp.tcp.wnd[1] = ((NET_DEV_RCVWNDO(dev)) & 0xff); + } + + /* Calculate TCP checksum. */ + + ipv6tcp.tcp.tcpchksum = 0; +#if 0 + /* REVISIT: Current checksum logic expects the IPv6 header, the UDP header, and + * the payload data to be in contiguous memory. + */ + + ipv6tcp.tcp.tcpchksum = ~tcp_ipv6_chksum(dev); +#endif + + ninfo("Outgoing TCP packet length: %d bytes\n", iplen + IOPv6_HDRLEN); + +#ifdef CONFIG_NET_STATISTICS + g_netstats.tcp.sent++; +#endif /* Set the socket state to sending */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND); @@ -184,7 +258,7 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf, #endif ret = sixlowpan_send(dev, (FAR const struct ipv6_hdr_s *)&ipv6tcp, - buf, len, &destmac, timeout); + buf, buflen, &destmac, timeout); if (ret < 0) { nerr("ERROR: sixlowpan_send() failed: %d\n", ret); diff --git a/net/sixlowpan/sixlowpan_udpsend.c b/net/sixlowpan/sixlowpan_udpsend.c index ae16a23355..49932514c8 100644 --- a/net/sixlowpan/sixlowpan_udpsend.c +++ b/net/sixlowpan/sixlowpan_udpsend.c @@ -46,6 +46,7 @@ #include #include "nuttx/net/netdev.h" +#include "nuttx/net/netstats.h" #include "netdev/netdev.h" #include "socket/socket.h" @@ -70,7 +71,7 @@ * Parameters: * psock A pointer to a NuttX-specific, internal socket structure * buf Data to send - * len Length of data to send + * buflen Length of data to send * flags Send flags * to Address of recipient * tolen The length of the address structure @@ -88,7 +89,7 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock, FAR const void *buf, - size_t len, int flags, + size_t buflen, int flags, FAR const struct sockaddr *to, socklen_t tolen) { @@ -97,6 +98,7 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock, FAR struct net_driver_s *dev; struct ipv6udp_hdr_s ipv6udp; struct rimeaddr_s destmac; + uint16_t iplen; uint16_t timeout; int ret; @@ -176,7 +178,62 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock, #endif /* Initialize the IPv6/UDP headers */ + + ipv6udp.ipv6.vtc = 0x60; + ipv6udp.ipv6.tcf = 0x00; + ipv6udp.ipv6.flow = 0x00; + ipv6udp.ipv6.proto = IP_PROTO_UDP; + ipv6udp.ipv6.ttl = conn->ttl; + + /* The IPv6 header length field does not include the size of IPv6 IP + * header. + */ + + iplen = buflen + UDP_HDRLEN; + ipv6udp.ipv6.len[0] = (iplen >> 8); + ipv6udp.ipv6.len[1] = (iplen & 0xff); + + /* Copy the source and destination addresses */ + + net_ipv6addr_hdrcopy(ipv6udp.ipv6.srcipaddr, to6->sin6_addr.in6_u.u6_addr16); + net_ipv6addr_hdrcopy(ipv6udp.ipv6.destipaddr, conn->u.ipv6.raddr); + + ninfo("IPv6 length: %d\n", ((int)ipv6->len[0] << 8) + ipv6->len[1]); + +#ifdef CONFIG_NET_STATISTICS + g_netstats.ipv6.sent++; +#endif + + /* Initialize the UDP header */ + + ipv6udp.udp.srcport = conn->lport; + ipv6udp.udp.destport = to6->sin6_port; + ipv6udp.udp.udplen = htons(iplen); + ipv6udp.udp.udpchksum = 0; + + ipv6udp.udp.udpchksum = 0; + #warning Missing logic +#if 0 /* REVISIT */ +#ifdef CONFIG_NET_UDP_CHECKSUMS + /* Calculate UDP checksum. */ + /* REVISIT: Current checksum logic expects the IPv6 header, the UDP header, and + * the payload data to be in contiguous memory. + */ + + ipv6udp.udp.udpchksum = ~udp_ipv6_chksum(dev); + if (ipv6udp.udp.udpchksum == 0) + { + ipv6udp.udp.udpchksum = 0xffff; + } +#endif /* CONFIG_NET_UDP_CHECKSUMS */ +#endif /* REVISIT */ + + ninfo("Outgoing UDP packet length: %d\n", iplen + IPv6_HDRLEN); + +#ifdef CONFIG_NET_STATISTICS + g_netstats.udp.sent++; +#endif /* Set the socket state to sending */ @@ -199,7 +256,7 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock, #endif ret = sixlowpan_send(dev, (FAR const struct ipv6_hdr_s *)&ipv6udp, - buf, len, &destmac, timeout); + buf, buflen, &destmac, timeout); if (ret < 0) { nerr("ERROR: sixlowpan_send() failed: %d\n", ret); @@ -219,9 +276,9 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock, * sockets. * * Parameters: - * psock - An instance of the internal socket structure. - * buf - Data to send - * len - Length of data to send + * psock - An instance of the internal socket structure. + * buf - Data to send + * buflen - Length of data to send * * Returned Value: * On success, returns the number of characters sent. On error, @@ -234,7 +291,7 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock, ****************************************************************************/ ssize_t psock_6lowpan_udp_send(FAR struct socket *psock, FAR const void *buf, - size_t len) + size_t buflen) { FAR struct udp_conn_s *conn; struct sockaddr_in6 to; @@ -278,7 +335,7 @@ ssize_t psock_6lowpan_udp_send(FAR struct socket *psock, FAR const void *buf, to.sin6_port = conn->rport; /* Already network order */ memcpy(to.sin6_addr.in6_u.u6_addr16, conn->u.ipv6.raddr, 16); - return psock_6lowpan_udp_sendto(psock, buf, len, 0, + return psock_6lowpan_udp_sendto(psock, buf, buflen, 0, (FAR const struct sockaddr *)&to, sizeof(struct sockaddr_in6)); }