6loWPAN: Add logic to fill in UDP/TCP headers. Still missing some checksum logic.
This commit is contained in:
parent
fb42844788
commit
6e2f8f3aa3
@ -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);
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user