6loWPAN: Add logic to fill in UDP/TCP headers. Still missing some checksum logic.

This commit is contained in:
Gregory Nutt 2017-04-02 13:27:53 -06:00
parent fb42844788
commit 6e2f8f3aa3
3 changed files with 149 additions and 18 deletions

View File

@ -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);
/****************************************************************************

View File

@ -39,11 +39,13 @@
#include <nuttx/config.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#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);

View File

@ -46,6 +46,7 @@
#include <debug.h>
#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));
}