6loWPAN: Hook 6loWPAN output into path of output from TCP state machine.

This commit is contained in:
Gregory Nutt 2017-04-02 12:01:04 -06:00
parent 76406af71b
commit 663c48c329
4 changed files with 155 additions and 90 deletions

View File

@ -95,6 +95,7 @@
#include "neighbor/neighbor.h"
#include "tcp/tcp.h"
#include "udp/udp.h"
#include "sixlowpan/sixlowpan.h"
#include "pkt/pkt.h"
#include "icmpv6/icmpv6.h"

View File

@ -53,8 +53,9 @@
* Public Function Prototypes
****************************************************************************/
struct socket; /* Forward reference */
struct sockaddr; /* Forward reference */
struct net_driver_s; /* Forward reference */
struct socket; /* Forward reference */
struct sockaddr; /* Forward reference */
/****************************************************************************
* Name: sixlowpan_initialize
@ -105,6 +106,33 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
size_t len);
#endif
/****************************************************************************
* Function: sixlowpan_tcp_send
*
* Description:
* TCP output comes through two different mechansims. Either from:
*
* 1. TCP socket output. For the case of TCP output to an
* IEEE802.15.4, the TCP output is caught in the socket
* send()/sendto() logic and and redirected to psock_6lowpan_tcp_send().
* 2. TCP output from the TCP state machine. That will occur
* during TCP packet processing by the TCP state meachine. It
* is detected there when ipv6_tcp_input() returns with d_len > 0. This
* will be redirected here.
*
* Parameters:
* dev - An instance of nework device state structure
*
* Returned Value:
* None
*
* Assumptions:
* Called with the network locked.
*
****************************************************************************/
void sixlowpan_tcp_send(FAR struct net_driver_s *dev);
/****************************************************************************
* Function: psock_6lowpan_udp_send
*

View File

@ -91,91 +91,6 @@
* Public Functions
****************************************************************************/
/****************************************************************************
* Function: sixlowpan_isbroadcast
*
* Description:
* Return the address length associated with a 2-bit address mode
*
* Input parameters:
* addrmode - The address mode
*
* Returned Value:
* The address length associated with the address mode.
*
****************************************************************************/
static bool sixlowpan_isbroadcast(uint8_t mode, FAR uint8_t *addr)
{
int i = ((mode == FRAME802154_SHORTADDRMODE) ? 2 : 8);
while (i-- > 0)
{
if (addr[i] != 0xff)
{
return false;
}
}
return true;
}
/****************************************************************************
* Name: sixlowpan_set_pktattrs
*
* Description:
* Setup some packet buffer attributes
*
* Input Parameters:
* ieee - Pointer to IEEE802.15.4 MAC driver structure.
* ipv6 - Pointer to the IPv6 header to "compress"
*
* Returned Value:
* None
*
****************************************************************************/
static void sixlowpan_set_pktattrs(FAR struct ieee802154_driver_s *ieee,
FAR const struct ipv6_hdr_s *ipv6)
{
int attr = 0;
/* Set protocol in NETWORK_ID */
g_pktattrs[PACKETBUF_ATTR_NETWORK_ID] = ipv6->proto;
/* Assign values to the channel attribute (port or type + code) */
if (ipv6->proto == IP_PROTO_UDP)
{
FAR struct udp_hdr_s *udp = &((FAR struct ipv6udp_hdr_s *)ipv6)->udp;
attr = udp->srcport;
if (udp->destport < attr)
{
attr = udp->destport;
}
}
else if (ipv6->proto == IP_PROTO_TCP)
{
FAR struct tcp_hdr_s *tcp = &((FAR struct ipv6tcp_hdr_s *)ipv6)->tcp;
attr = tcp->srcport;
if (tcp->destport < attr)
{
attr = tcp->destport;
}
}
else if (ipv6->proto == IP_PROTO_ICMP6)
{
FAR struct icmpv6_iphdr_s *icmp = &((FAR struct ipv6icmp_hdr_s *)ipv6)->icmp;
attr = icmp->type << 8 | icmp->code;
}
g_pktattrs[PACKETBUF_ATTR_CHANNEL] = attr;
}
/****************************************************************************
* Name: sixlowpan_frame_process
*
@ -691,7 +606,10 @@ int sixlowpan_input(FAR struct ieee802154_driver_s *ieee)
if (ieee->i_dev.d_len > 0)
{
FAR struct ipv6_hdr_s *ipv6hdr;
FAR uint8_t *buffer;
struct rimeaddr_s destmac;
size_t hdrlen;
size_t buflen;
/* The IPv6 header followed by TCP or UDP headers should
* lie at the beginning of d_buf since there is no link
@ -707,10 +625,46 @@ int sixlowpan_input(FAR struct ieee802154_driver_s *ieee)
sixlowpan_rimefromip(ipv6hdr->destipaddr, &destmac);
/* The data payload should follow the IPv6 header plus
* the protocol header.
*/
if (ipv6hdr->proto != IP_PROTO_TCP)
{
hdrlen = IPv6_HDRLEN + TCP_HDRLEN;
}
else if (ipv6hdr->proto != IP_PROTO_UDP)
{
hdrlen = IPv6_HDRLEN + UDP_HDRLEN;
}
else if (ipv6hdr->proto != IP_PROTO_ICMP6)
{
hdrlen = IPv6_HDRLEN + ICMPv6_HDRLEN;
}
else
{
nwarn("WARNING: Unsupported protoype: %u\n",
ipv6hdr->proto);
ret = -EPROTO;
goto drop;
}
if (hdrlen < ieee->i_dev.d_len)
{
nwarn("WARNING: Packet to small: Have %u need >%u\n",
ieee->i_dev.d_len, hdrlen);
ret = -ENOBUFS;
goto drop;
}
/* Convert the outgoing packet into a frame list. */
ret = sixlowpan_queue_frames(ieee, ipv6hdr, ieee->i_dev.d_buf,
ieee->i_dev.d_len, &destmac);
buffer = ieee->i_dev.d_buf + hdrlen;
buflen = ieee->i_dev.d_len - hdrlen;
ret = sixlowpan_queue_frames(ieee, ipv6hdr, buffer, buflen,
&destmac);
drop:
ieee->i_dev.d_len = 0;
}
}

View File

@ -113,7 +113,7 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
conn = (FAR struct tcp_conn_s *)psock->s_conn;
DEBUGASSERT(conn != NULL);
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
#ifdef CONFIG_NET_IPv4
/* Ignore if not IPv6 domain */
if (conn->domain != PF_INET6)
@ -196,4 +196,86 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
return ret;
}
/****************************************************************************
* Function: sixlowpan_tcp_send
*
* Description:
* TCP output comes through two different mechansims. Either from:
*
* 1. TCP socket output. For the case of TCP output to an
* IEEE802.15.4, the TCP output is caught in the socket
* send()/sendto() logic and and redirected to psock_6lowpan_tcp_send().
* 2. TCP output from the TCP state machine. That will occur
* during TCP packet processing by the TCP state meachine. It
* is detected there when ipv6_tcp_input() returns with d_len > 0. This
* will be redirected here.
*
* Parameters:
* dev - An instance of nework device state structure
*
* Returned Value:
* None
*
* Assumptions:
* Called with the network locked.
*
****************************************************************************/
void sixlowpan_tcp_send(FAR struct net_driver_s *dev)
{
DEBUGASSERT(dev != NULL && dev->d_len > 0);
/* Double check */
if (dev != NULL && dev->d_len > 0)
{
FAR struct ipv6_hdr_s *ipv6hdr;
/* The IPv6 header followed by a TCP headers should lie at the
* beginning of d_buf since there is no link layer protocol header
* and the TCP state machine should only response with TCP packets.
*/
ipv6hdr = (FAR struct ipv6_hdr_s *)(dev->d_buf);
/* The TCP data payload should follow the IPv6 header plus the
* protocol header.
*/
if (ipv6hdr->proto != IP_PROTO_TCP)
{
nwarn("WARNING: Expected TCP protoype: %u\n", ipv6hdr->proto);
}
else
{
size_t hdrlen;
hdrlen = IPv6_HDRLEN + TCP_HDRLEN;
if (hdrlen < dev->d_len)
{
nwarn("WARNING: Packet to small: Have %u need >%u\n",
dev->d_len, hdrlen);
}
else
{
struct rimeaddr_s destmac;
/* Get the Rime MAC address of the destination. This assumes
* an encoding of the MAC address in the IPv6 address.
*/
sixlowpan_rimefromip(ipv6hdr->destipaddr, &destmac);
/* Convert the outgoing packet into a frame list. */
(void)sixlowpan_queue_frames(
(FAR struct ieee802154_driver_s *)dev, ipv6hdr,
dev->d_buf + hdrlen, dev->d_len - hdrlen, &destmac);
}
}
}
dev->d_len = 0;
}
#endif /* CONFIG_NET_6LOWPAN && CONFIG_NET_TCP */