6LoWPAN: Loopback driver needs to initialize the MAC meta data; Address decompression logic must have the MAC address to handle the most common compression cases.

This commit is contained in:
Gregory Nutt
2017-06-22 13:55:08 -06:00
parent bc8ad02ee5
commit 922454d515
4 changed files with 179 additions and 53 deletions
+139 -43
View File
@@ -109,43 +109,58 @@ static FAR uint8_t *g_hc06ptr;
/* Uncompression of linklocal /* Uncompression of linklocal
* *
* 0 -> 16 bytes from packet * 0 -> 16 bytes from packet
* 1 -> 2 bytes from prefix - bunch of zeroes and 8 from packet * 1 -> 2 bytes from prefix - 16 bytes from packet
* 2 -> 2 bytes from prefix - 0000::00ff:fe00:XXXX from packet * 2 -> 2 bytes from prefix - 0000::00ff:fe00:XXXX from packet
* 3 -> 2 bytes from prefix - infer 8 bytes from MAC address * 3 -> 2 bytes from prefix - Infer 2 or 8 bytes from MAC address
* *
* NOTE: => the uncompress function does change 0xf to 0x10 * NOTE: => the uncompress function does change 0xf to 0x10
* NOTE: 0x00 => no-autoconfig => unspecified * NOTE: 0x00 => no-autoconfig => unspecified
*/ */
static const uint8_t g_unc_llconf[] = { 0x0f, 0x28, 0x22, 0x20 }; static const uint16_t g_unc_llconf[] =
{
0x000f, 0x0028, 0x0022, 0x0120
};
/* Uncompression of ctx-based /* Uncompression of ctx-based
* *
* 0 -> 0 bits from packet [unspecified / reserved] * 0 -> 0 bits from packet [unspecified / reserved]
* 1 -> 8 bytes from prefix - bunch of zeroes and 8 from packet * 1 -> 8 bytes from prefix - Bunch of zeroes and 8 bytes from packet
* 2 -> 8 bytes from prefix - 0000::00ff:fe00:XXXX + 2 from packet * 2 -> 8 bytes from prefix - 0000::00ff:fe00:XXXX and 2 bytes from packet
* 3 -> 8 bytes from prefix - infer 8 bytes from MAC address * 3 -> 8 bytes from prefix - Infer 2 or 8 bytes from MAC address
*/ */
static const uint8_t g_unc_ctxconf[] = { 0x00, 0x88, 0x82, 0x80 }; static const uint16_t g_unc_ctxconf[] =
{
0x0000, 0x0088, 0x0082, 0x0180
};
/* Uncompression of ctx-based /* Uncompression of ctx-based
* *
* 0 -> 0 bits from packet * 0 -> 0 bits from packet
* 1 -> 2 bytes from prefix - bunch of zeroes 5 from packet * 1 -> 2 bytes from prefix - Bunch of zeroes 5 bytes from packet
* 2 -> 2 bytes from prefix - zeroes + 3 from packet * 2 -> 2 bytes from prefix - Zeroes + 3 bytes from packet
* 3 -> 2 bytes from prefix - infer 1 bytes from MAC address * 3 -> 2 bytes from prefix - Infer 1 bytes from MAC address
*/ */
static const uint8_t g_unc_mxconf[] = { 0x0f, 0x25, 0x23, 0x21 }; static const uint16_t g_unc_mxconf[] =
{
0x000f, 0x0025, 0x0023, 0x0121
};
/* Link local prefix */ /* Link local prefix */
static const uint8_t g_llprefix[] = { 0xfe, 0x80 }; static const uint8_t g_llprefix[] =
{
0xfe, 0x80
};
/* TTL uncompression values */ /* TTL uncompression values */
static const uint8_t g_ttl_values[] = { 0, 1, 64, 255 }; static const uint8_t g_ttl_values[] =
{
0, 1, 64, 255
};
/**************************************************************************** /****************************************************************************
@@ -297,43 +312,114 @@ static uint8_t compress_laddr(FAR const net_ipv6addr_t ipaddr,
* *
****************************************************************************/ ****************************************************************************/
static void uncompress_addr(FAR net_ipv6addr_t ipaddr, uint8_t const prefix[], static void uncompress_addr(FAR const struct ieee802154_addr_s *addr,
uint8_t prefpost) FAR const uint8_t *prefix, uint16_t prefpost,
FAR net_ipv6addr_t ipaddr)
{ {
uint8_t prefcount = prefpost >> 4; FAR const uint8_t *srcptr;
uint8_t postcount = prefpost & 0x0f; bool fullmac = false;
bool usemac = (prefpost & 0x0100) != 0;
uint8_t prefcount = (prefpost >> 4) & 0xf;
uint8_t postcount = prefpost & 0x0f;
/* The value 16 is encoded as 0xf in the 4 bit-fields. */ /* The value 16 is encoded as 0xf in the 4 bit-fields. */
prefcount = prefcount == 15 ? 16 : prefcount; prefcount = prefcount == 15 ? 16 : prefcount;
postcount = postcount == 15 ? 16 : postcount; postcount = postcount == 15 ? 16 : postcount;
/* Select the data source */
srcptr = g_hc06ptr;
if (usemac)
{
bool saddr = (addr->mode == IEEE802154_ADDRMODE_SHORT);
uint16_t addrsize = saddr ? NET_6LOWPAN_SADDRSIZE: NET_6LOWPAN_EADDRSIZE;
/* Select the source the address data */
srcptr = saddr ? addr->saddr : addr->eaddr;
/* If the provided postcount is zero and we are taking data from the
* MAC address, set postcount to the address length.
*/
if (postcount == 0)
{
postcount = addrsize;
}
/* If we are converting the entire MAC address, then we need to some some
* special bit operations.
*/
fullmac = (postcount == addrsize);
}
/* Copy any prefix */
if (prefcount > 0) if (prefcount > 0)
{ {
memcpy(ipaddr, prefix, prefcount); memcpy(ipaddr, prefix, prefcount);
} }
/* Clear bytes between int prefcount and postcount */
if (prefcount + postcount < 16) if (prefcount + postcount < 16)
{ {
FAR uint8_t *iptr = (FAR uint8_t *)&ipaddr[0]; FAR uint8_t *destptr = (FAR uint8_t *)&ipaddr[0];
memset(&iptr[prefcount], 0, 16 - (prefcount + postcount)); memset(&destptr[prefcount], 0, 16 - (prefcount + postcount));
} }
/* Copy the remaining data from the source */
if (postcount > 0) if (postcount > 0)
{ {
FAR uint8_t *iptr = (FAR uint8_t *)&ipaddr[0];
memcpy(&iptr[16 - postcount], g_hc06ptr, postcount);
if (postcount == 2 && prefcount < 11) if (postcount == 2 && prefcount < 11)
{ {
/* 16 bits uncompression => 0000:00ff:fe00:XXXX */ /* 16 bits uncompression => 0000:00ff:fe00:XXXX */
iptr[11] = 0xff; ipaddr[5] = HTONS(0x00ff);
iptr[12] = 0xfe; ipaddr[6] = HTONS(0xfe00);
} }
g_hc06ptr += postcount; /* If the postcount is even then take extra care with endian-ness */
if ((postcount & 1) == 0)
{
int destndx = 8 - (postcount >> 1);
int i;
for (i = destndx; i < 8; i++)
{
ipaddr[i] = (uint16_t)srcptr[0] << 8 | (uint16_t)srcptr[1];
srcptr += 2;
}
/* If the was a standard MAC based address then toggle */
if (fullmac)
{
ipaddr[destndx] ^= 0x200;
}
}
/* postcount is odd... */
else
{
FAR uint8_t *destptr = (FAR uint8_t *)&ipaddr[0];
int offset = 16 - postcount;
memcpy(&destptr[offset], srcptr, postcount);
}
/* If we took the data from packet, then update the packet pointer */
if (!usemac)
{
g_hc06ptr += postcount;
}
} }
else if (prefcount > 0) else if (prefcount > 0)
{ {
@@ -342,9 +428,10 @@ static void uncompress_addr(FAR net_ipv6addr_t ipaddr, uint8_t const prefix[],
nwarn("WARNING: No IID based configuration\n"); nwarn("WARNING: No IID based configuration\n");
} }
ninfo("Uncompressing %d + %d => %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", ninfo("Uncompressing %d + %d => %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04\n",
prefcount, postcount, ipaddr[0], ipaddr[2], ipaddr[3], ipaddr[5], prefcount, postcount,
ipaddr[5], ipaddr[6], ipaddr[7]); ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3],
ipaddr[4], ipaddr[5], ipaddr[6], ipaddr[7]);
} }
/**************************************************************************** /****************************************************************************
@@ -860,20 +947,22 @@ void sixlowpan_compresshdr_hc06(FAR struct ieee802154_driver_s *ieee,
* appropriate values * appropriate values
* *
* Input Parmeters: * Input Parmeters:
* iplen - Equal to 0 if the packet is not a fragment (IP length is then * ind - MAC header meta data including node addressing information.
* inferred from the L2 length), non 0 if the packet is a first * iplen - Equal to 0 if the packet is not a fragment (IP length is then
* fragment. * inferred from the L2 length), non 0 if the packet is a first
* iob - Pointer to the IOB containing the received frame. * fragment.
* fptr - Pointer to frame to be compressed. * iob - Pointer to the IOB containing the received frame.
* bptr - Output goes here. Normally this is a known offset into d_buf, * fptr - Pointer to frame to be compressed.
* may be redirected to a "bitbucket" on the case of FRAGN frames. * bptr - Output goes here. Normally this is a known offset into d_buf,
* may be redirected to a "bitbucket" on the case of FRAGN frames.
* *
* Returned Value: * Returned Value:
* None * None
* *
****************************************************************************/ ****************************************************************************/
void sixlowpan_uncompresshdr_hc06(uint16_t iplen, FAR struct iob_s *iob, void sixlowpan_uncompresshdr_hc06(FAR const struct ieee802154_data_ind_s *ind,
uint16_t iplen, FAR struct iob_s *iob,
FAR uint8_t *fptr, FAR uint8_t *bptr) FAR uint8_t *fptr, FAR uint8_t *bptr)
{ {
FAR struct ipv6_hdr_s *ipv6 = (FAR struct ipv6_hdr_s *)bptr; FAR struct ipv6_hdr_s *ipv6 = (FAR struct ipv6_hdr_s *)bptr;
@@ -1014,8 +1103,9 @@ void sixlowpan_uncompresshdr_hc06(uint16_t iplen, FAR struct iob_s *iob,
* address. * address.
*/ */
uncompress_addr(ipv6->srcipaddr, uncompress_addr(&ind->src,
tmp != 0 ? addrcontext->prefix : NULL, g_unc_ctxconf[tmp]); tmp != 0 ? addrcontext->prefix : NULL,
g_unc_ctxconf[tmp], ipv6->srcipaddr);
} }
else else
{ {
@@ -1024,7 +1114,8 @@ void sixlowpan_uncompresshdr_hc06(uint16_t iplen, FAR struct iob_s *iob,
* address. * address.
*/ */
uncompress_addr(ipv6->srcipaddr, g_llprefix, g_unc_llconf[tmp]); uncompress_addr(&ind->src, g_llprefix, g_unc_llconf[tmp],
ipv6->srcipaddr);
} }
/* Destination address */ /* Destination address */
@@ -1059,7 +1150,8 @@ void sixlowpan_uncompresshdr_hc06(uint16_t iplen, FAR struct iob_s *iob,
g_hc06ptr++; g_hc06ptr++;
} }
uncompress_addr(ipv6->destipaddr, prefix, g_unc_mxconf[tmp]); uncompress_addr(&ind->dest, prefix, g_unc_mxconf[tmp],
ipv6->destipaddr);
} }
} }
else else
@@ -1082,13 +1174,17 @@ void sixlowpan_uncompresshdr_hc06(uint16_t iplen, FAR struct iob_s *iob,
return; return;
} }
uncompress_addr(ipv6->destipaddr, addrcontext->prefix, g_unc_ctxconf[tmp]); uncompress_addr(&ind->src, addrcontext->prefix,
g_unc_ctxconf[tmp], ipv6->destipaddr);
} }
else else
{ {
/* Not address context based => link local M = 0, DAC = 0 - same as SAC */ /* Not address context based => link local M = 0, DAC = 0 - same
* as SAC.
*/
uncompress_addr(ipv6->destipaddr, g_llprefix, g_unc_llconf[tmp]); uncompress_addr(&ind->src,g_llprefix, g_unc_llconf[tmp],
ipv6->destipaddr);
} }
} }
+1 -1
View File
@@ -532,7 +532,7 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee,
if ((hc1[SIXLOWPAN_HC1_DISPATCH] & SIXLOWPAN_DISPATCH_IPHC_MASK) == SIXLOWPAN_DISPATCH_IPHC) if ((hc1[SIXLOWPAN_HC1_DISPATCH] & SIXLOWPAN_DISPATCH_IPHC_MASK) == SIXLOWPAN_DISPATCH_IPHC)
{ {
ninfo("IPHC Dispatch\n"); ninfo("IPHC Dispatch\n");
sixlowpan_uncompresshdr_hc06(fragsize, iob, fptr, bptr); sixlowpan_uncompresshdr_hc06(ind, fragsize, iob, fptr, bptr);
} }
else else
#endif /* CONFIG_NET_6LOWPAN_COMPRESSION_HC06 */ #endif /* CONFIG_NET_6LOWPAN_COMPRESSION_HC06 */
+10 -8
View File
@@ -441,13 +441,14 @@ void sixlowpan_compresshdr_hc06(FAR struct ieee802154_driver_s *ieee,
* appropriate values * appropriate values
* *
* Input Parmeters: * Input Parmeters:
* iplen - Equal to 0 if the packet is not a fragment (IP length is then * ind - MAC header meta data including node addressing information.
* inferred from the L2 length), non 0 if the packet is a first * iplen - Equal to 0 if the packet is not a fragment (IP length is then
* fragment. * inferred from the L2 length), non 0 if the packet is a first
* iob - Pointer to the IOB containing the received frame. * fragment.
* fptr - Pointer to frame to be compressed. * iob - Pointer to the IOB containing the received frame.
* bptr - Output goes here. Normally this is a known offset into d_buf, * fptr - Pointer to frame to be compressed.
* may be redirected to a "bitbucket" on the case of FRAGN frames. * bptr - Output goes here. Normally this is a known offset into d_buf,
* may be redirected to a "bitbucket" on the case of FRAGN frames.
* *
* Returned Value: * Returned Value:
* None * None
@@ -455,7 +456,8 @@ void sixlowpan_compresshdr_hc06(FAR struct ieee802154_driver_s *ieee,
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC06 #ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC06
void sixlowpan_uncompresshdr_hc06(uint16_t iplen, FAR struct iob_s *iob, void sixlowpan_uncompresshdr_hc06(FAR const struct ieee802154_data_ind_s *ind,
uint16_t iplen, FAR struct iob_s *iob,
FAR uint8_t *fptr, FAR uint8_t *bptr); FAR uint8_t *fptr, FAR uint8_t *bptr);
#endif #endif
+29 -1
View File
@@ -118,7 +118,7 @@ static uint8_t g_iobuffer[CONFIG_NET_6LOWPAN_MTU + CONFIG_NET_GUARDSIZE];
static uint8_t g_eaddr[IEEE802154_EADDRSIZE] = static uint8_t g_eaddr[IEEE802154_EADDRSIZE] =
{ {
0x00, 0xfa, 0xde, 0x00, 0xde, 0xad, 0xbe, 0xef 0x0c, 0xfa, 0xde, 0x00, 0xde, 0xad, 0xbe, 0xef
}; };
static uint8_t g_saddr[IEEE802154_SADDRSIZE] = static uint8_t g_saddr[IEEE802154_SADDRSIZE] =
@@ -131,6 +131,16 @@ static uint8_t g_panid[IEEE802154_PANIDSIZE] =
0xca, 0xfe 0xca, 0xfe
}; };
static const uint8_t g_src_eaddr[IEEE802154_EADDRSIZE] =
{
0x0a, 0xfa, 0xde, 0x00, 0xde, 0xad, 0xbe, 0xef
};
static const uint8_t g_src_saddr[IEEE802154_SADDRSIZE] =
{
0x12, 0x34
};
/**************************************************************************** /****************************************************************************
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
@@ -289,8 +299,26 @@ static int lo_loopback(FAR struct net_driver_s *dev)
FAR struct iob_s *iob; FAR struct iob_s *iob;
int ret; int ret;
/* Create some fake metadata */
memset(&ind, 0, sizeof(struct ieee802154_data_ind_s)); memset(&ind, 0, sizeof(struct ieee802154_data_ind_s));
#ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR
ind.src.mode = IEEE802154_ADDRMODE_EXTENDED;
ind.dest.mode = IEEE802154_ADDRMODE_EXTENDED;
#else
ind.src.mode = IEEE802154_ADDRMODE_SHORT;
ind.dest.mode = IEEE802154_ADDRMODE_SHORT;
#endif
IEEE802154_PANIDCOPY(ind.src.panid, g_panid);
IEEE802154_SADDRCOPY(ind.src.saddr, g_src_saddr);
IEEE802154_EADDRCOPY(ind.src.eaddr, g_src_eaddr);
IEEE802154_PANIDCOPY(ind.dest.panid, g_panid);
IEEE802154_SADDRCOPY(ind.dest.saddr, g_saddr);
IEEE802154_EADDRCOPY(ind.dest.eaddr, g_eaddr);
/* Loop while there framelist to be sent, i.e., while the freme list is not /* Loop while there framelist to be sent, i.e., while the freme list is not
* emtpy. Sending, of course, just means relaying back through the network * emtpy. Sending, of course, just means relaying back through the network
* for this driver. * for this driver.