6LoWPAN: Add missing IPv6 address creation to HC1 decode logic.

This commit is contained in:
Gregory Nutt 2017-06-23 09:44:36 -06:00
parent 66f3186c76
commit 1a46ea644d
7 changed files with 198 additions and 45 deletions

View File

@ -476,12 +476,12 @@ Configurations
2017-06-21: Basic functionality has been achieved. The following
configurations have been tested:
DATE
TEST DATE
COMPRESSION ADDRESSING UDP TCP
----------- ---------- ---- ----
hc06 short 6/21 ---
extended 6/22 ---
hc1 short --- ---
hc1 short 6/23 ---
extended --- ---
ipv6 short --- ---
extended --- ---

View File

@ -126,15 +126,39 @@
#define SIXLOWPAN_DISPATCH_FRAGN 0xe0 /* 11100xxx Fragmentation header (subsequent) */
#define SIXLOWPAN_DISPATCH_FRAG_MASK 0xf8 /* 11111000 */
/* HC1 encoding */
/* HC1 encoding (RFC4944)
*
* PI: Prefix carried in-line
* PC: Prefix compressed (link-local prefix assumed)
* II: Interface identifier carried in-line
* IC: Interface identifier elided (derivable from the corresponding
* link-layer address).
*/
#define SIXLOWPAN_HC1_NH_UDP 0x02
#define SIXLOWPAN_HC1_NH_TCP 0x06
#define SIXLOWPAN_HC1_NH_ICMP6 0x04
#define SIXLOWPAN_HC1_SRCADDR_MASK 0xc0 /* Bits 0-1: IPv6 source address */
# define SIXLOWPAN_HC1_SRCADDR_PIII 0x00 /* PI,II */
# define SIXLOWPAN_HC1_SRCADDR_PIIC 0x40 /* PI,IC */
# define SIXLOWPAN_HC1_SRCADDR_PCII 0x80 /* PC,II */
# define SIXLOWPAN_HC1_SRCADDR_PCIC 0xc0 /* PC,IC */
#define SIXLOWPAN_HC1_DESTADDR_MASK 0x30 /* Bits 2-3: IPv6 destination address */
# define SIXLOWPAN_HC1_DESTADDR_PIII 0x00 /* PI,II */
# define SIXLOWPAN_HC1_DESTADDR_PIIC 0x10 /* PI,IC */
# define SIXLOWPAN_HC1_DESTADDR_PCII 0x20 /* PC,II */
# define SIXLOWPAN_HC1_DESTADDR_PCIC 0x30 /* PC,IC */
#define SIXLOWPAN_HC1_TCFL_C 0x08 /* Traffic class and flow label are zero */
#define SIXLOWPAN_HC1_NH_MASK 0x06 /* Bits 5-6: Next HC1 header type */
# define SIXLOWPAN_HC1_NH_NC 0x00 /* Not compressed */
# define SIXLOWPAN_HC1_NH_UDP 0x02 /* UDP */
# define SIXLOWPAN_HC1_NH_ICMPv6 0x04 /* ICMPv6 */
# define SIXLOWPAN_HC1_NH_TCP 0x06 /* TCP */
#define SIXLOWPAN_HC1_H2ENCODE 0x01 /* Bit 0: HC2 encoding follows */
/* HC_UDP encoding (works together with HC1) */
#define SIXLOWPAN_HC_UDP_ALL_C 0xe0
#define SIXLOWPAN_HC_UDP_SRCPORT_C 0x80 /* Source port compressed to 4 bits */
#define SIXLOWPAN_HC_UDP_DESTPORT_C 0x40 /* Destination port compressed to 4 bits */
#define SIXLOWPAN_HC_UDP_LENGTH _C 0x20 /* Elided, compute from IPv6 length */
#define SIXLOWPAN_HC_UDP_ALL_C 0xe0 /* All commpressed */
/* IPHC encoding
*

View File

@ -57,6 +57,31 @@
#ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC1
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: sixlowpan_uncompress_addr
*
* Description:
* Uncompress a link-local, MAC-based IPv6 address.
*
****************************************************************************/
static void sixlowpan_uncompress_addr(FAR const struct ieee802154_addr_s *addr,
FAR net_ipv6addr_t ipaddr)
{
if (addr->mode == IEEE802154_ADDRMODE_SHORT)
{
sixlowpan_ipfromsaddr(addr->saddr, ipaddr);
}
else
{
sixlowpan_ipfromeaddr(addr->eaddr, ipaddr);
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -82,21 +107,21 @@
* - Next header is either ICMP, UDP or TCP
*
* Moreover, if next header is UDP, we try to compress it using HC_UDP.
* This is feasible is both ports are between F0B0 and F0B0 + 15\n\n
* This is feasible is both ports are between F0B0 and F0B0 + 15
*
* Resulting header structure:
* - For ICMP, TCP, non compressed UDP\n
* HC1 encoding = 11111010 (UDP) 11111110 (TCP) 11111100 (ICMP)\n
* HC1 encoding = 11111010 (UDP) 11111110 (TCP) 11111100 (ICMP)
* 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | LoWPAN HC1 Dsp | HC1 encoding | IPv6 Hop limit| L4 hdr + data|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ...
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* - For compressed UDP
* HC1 encoding = 11111011, HC_UDP encoding = 11100000\n
* HC1 encoding = 11111011, HC_UDP encoding = 11100000
* 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@ -140,6 +165,8 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
* nothing, copy IPv6 header into the frame buffer
*/
nwarn("WARNING: Fall back to IPv6 dispatch\n");
/* IPv6 dispatch header (1 byte) */
hc1[SIXLOWPAN_HC1_DISPATCH] = SIXLOWPAN_DISPATCH_IPV6;
@ -164,8 +191,8 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
/* HC1 encoding and ttl */
hc1[SIXLOWPAN_HC1_ENCODING] = 0xfc;
hc1[SIXLOWPAN_HC1_TTL] = ipv6->ttl;
g_frame_hdrlen += SIXLOWPAN_HC1_HDR_LEN;
hc1[SIXLOWPAN_HC1_TTL] = ipv6->ttl;
g_frame_hdrlen += SIXLOWPAN_HC1_HDR_LEN;
break;
#if CONFIG_NET_TCP
@ -173,8 +200,8 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
/* HC1 encoding and ttl */
hc1[SIXLOWPAN_HC1_ENCODING] = 0xfe;
hc1[SIXLOWPAN_HC1_TTL] = ipv6->ttl;
g_frame_hdrlen += SIXLOWPAN_HC1_HDR_LEN;
hc1[SIXLOWPAN_HC1_TTL] = ipv6->ttl;
g_frame_hdrlen += SIXLOWPAN_HC1_HDR_LEN;
break;
#endif /* CONFIG_NET_TCP */
@ -190,7 +217,7 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
* 15
*/
ninfo("local/remote port %u/%u\n", udp->srcport, udp->destport);
ninfo("local/remote port %04x/%04x\n", udp->srcport, udp->destport);
if (ntohs(udp->srcport) >= CONFIG_NET_6LOWPAN_MINPORT &&
ntohs(udp->srcport) < (CONFIG_NET_6LOWPAN_MINPORT + 16) &&
@ -213,8 +240,8 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
memcpy(&hcudp[SIXLOWPAN_HC1_HC_UDP_CHKSUM], &udp->udpchksum, 2);
g_frame_hdrlen += SIXLOWPAN_HC1_HC_UDP_HDR_LEN;
g_uncomp_hdrlen += UDP_HDRLEN;
g_frame_hdrlen += SIXLOWPAN_HC1_HC_UDP_HDR_LEN;
g_uncomp_hdrlen += UDP_HDRLEN;
}
else
{
@ -222,7 +249,7 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
hc1[SIXLOWPAN_HC1_ENCODING] = 0xfa;
hc1[SIXLOWPAN_HC1_TTL] = ipv6->ttl;
g_frame_hdrlen += SIXLOWPAN_HC1_HDR_LEN;
g_frame_hdrlen += SIXLOWPAN_HC1_HDR_LEN;
}
}
break;
@ -244,6 +271,7 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
* are set to the appropriate values
*
* Input Parameters:
* ind - MAC header meta data including node addressing information.
* iplen - Equal to 0 if the packet is not a fragment (IP length is then
* inferred from the L2 length), non 0 if the packet is a 1st
* fragment.
@ -258,12 +286,15 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
*
****************************************************************************/
int sixlowpan_uncompresshdr_hc1(uint16_t iplen, FAR struct iob_s *iob,
int sixlowpan_uncompresshdr_hc1(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 struct ipv6_hdr_s *ipv6 = (FAR struct ipv6_hdr_s *)bptr;
FAR uint8_t *hc1 = fptr + g_frame_hdrlen;
ninfo("fptr=%p g_frame_hdrlen=%u\n", fptr, g_frame_hdrlen);
/* Format the IPv6 header in the device d_buf */
/* Set version, traffic clase, and flow label */
@ -277,7 +308,7 @@ int sixlowpan_uncompresshdr_hc1(uint16_t iplen, FAR struct iob_s *iob,
switch (hc1[SIXLOWPAN_HC1_ENCODING] & 0x06)
{
case SIXLOWPAN_HC1_NH_ICMP6:
case SIXLOWPAN_HC1_NH_ICMPv6:
ipv6->proto = IP_PROTO_ICMP6;
ipv6->ttl = hc1[SIXLOWPAN_HC1_TTL];
g_frame_hdrlen += SIXLOWPAN_HC1_HDR_LEN;
@ -298,6 +329,9 @@ int sixlowpan_uncompresshdr_hc1(uint16_t iplen, FAR struct iob_s *iob,
FAR uint8_t *hcudp = fptr + g_frame_hdrlen;
ipv6->proto = IP_PROTO_UDP;
/* Check for HC_UDP encoding */
if ((hcudp[SIXLOWPAN_HC1_HC_UDP_HC1_ENCODING] & 0x01) != 0)
{
/* UDP header is compressed with HC_UDP */
@ -320,6 +354,8 @@ int sixlowpan_uncompresshdr_hc1(uint16_t iplen, FAR struct iob_s *iob,
udp->destport =
htons(CONFIG_NET_6LOWPAN_MINPORT + (hcudp[SIXLOWPAN_HC1_HC_UDP_PORTS] & 0x0F));
ninfo("UDP srcport=%04x destport=%04x\n", udp->srcport, udp->destport);
memcpy(&udp->udpchksum, &hcudp[SIXLOWPAN_HC1_HC_UDP_CHKSUM], 2);
g_uncomp_hdrlen += UDP_HDRLEN;
@ -337,6 +373,46 @@ int sixlowpan_uncompresshdr_hc1(uint16_t iplen, FAR struct iob_s *iob,
return -EPROTONOSUPPORT;
}
/* Re-create the link-local, mac-based IP address from src/dest node
* addresses.
*
* PC: Prefix compressed (link-local prefix assumed)
* IC: Interface identifier elided (derivable from the corresponding
* link-layer address).
*/
if ((hc1[SIXLOWPAN_HC1_ENCODING] & SIXLOWPAN_HC1_SRCADDR_MASK) ==
SIXLOWPAN_HC1_SRCADDR_PCIC)
{
sixlowpan_uncompress_addr(&ind->src, ipv6->srcipaddr);
}
else
{
nwarn("HC1 srcipaddr encoding not supported: %02x\n",
hc1[SIXLOWPAN_HC1_ENCODING]);
}
ninfo("srcipaddr=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
ipv6->srcipaddr[0], ipv6->srcipaddr[1], ipv6->srcipaddr[2],
ipv6->srcipaddr[3], ipv6->srcipaddr[4], ipv6->srcipaddr[5],
ipv6->srcipaddr[6], ipv6->srcipaddr[7]);
if ((hc1[SIXLOWPAN_HC1_ENCODING] & SIXLOWPAN_HC1_DESTADDR_MASK) ==
SIXLOWPAN_HC1_DESTADDR_PCIC)
{
sixlowpan_uncompress_addr(&ind->dest, ipv6->destipaddr);
}
else
{
nwarn("HC1 destipaddr encoding not supported: %02x\n",
hc1[SIXLOWPAN_HC1_ENCODING]);
}
ninfo("destipaddr=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
ipv6->destipaddr[0], ipv6->destipaddr[1], ipv6->destipaddr[2],
ipv6->destipaddr[3], ipv6->destipaddr[4], ipv6->destipaddr[5],
ipv6->destipaddr[6], ipv6->destipaddr[7]);
/* IP length field. */
if (iplen == 0)
@ -355,6 +431,8 @@ int sixlowpan_uncompresshdr_hc1(uint16_t iplen, FAR struct iob_s *iob,
ipv6->len[1] = (iplen - IPv6_HDRLEN) & 0x00FF;
}
ninfo("IPv6 len=%02x:%02x\n", ipv6->len[0], ipv6->len[1]);
#if CONFIG_NET_UDP
/* Length field in UDP header */
@ -362,6 +440,8 @@ int sixlowpan_uncompresshdr_hc1(uint16_t iplen, FAR struct iob_s *iob,
{
FAR struct udp_hdr_s *udp = (FAR struct udp_hdr_s *)(bptr + IPv6_HDRLEN);
memcpy(&udp->udplen, &ipv6->len[0], 2);
ninfo("IPv6 len=%04x\n", udp->udplen);
}
#endif

View File

@ -541,7 +541,7 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee,
if (hc1[SIXLOWPAN_HC1_DISPATCH] == SIXLOWPAN_DISPATCH_HC1)
{
ninfo("HC1 Dispatch\n");
sixlowpan_uncompresshdr_hc1(fragsize, iob, fptr, bptr);
sixlowpan_uncompresshdr_hc1(ind, fragsize, iob, fptr, bptr);
}
else
#endif /* CONFIG_NET_6LOWPAN_COMPRESSION_HC1 */
@ -581,9 +581,6 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee,
g_uncomp_hdrlen = ieee->i_boffset;
}
#endif /* CONFIG_NET_6LOWPAN_FRAG */
/* Copy "payload" from the frame buffer to the IEEE802.15.4 MAC driver's
@ -689,7 +686,7 @@ static int sixlowpan_dispatch(FAR struct ieee802154_driver_s *ieee)
/* We only accept IPv6 packets. */
ninfo("Iv6 packet dispatch\n");
ninfo("IPv6 packet dispatch\n");
NETDEV_RXIPV6(&ieee->i_dev);
/* Give the IPv6 packet to the network layer. NOTE: If there is a

View File

@ -503,6 +503,7 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
* are set to the appropriate values
*
* Input Parameters:
* ind - MAC header meta data including node addressing information.
* iplen - Equal to 0 if the packet is not a fragment (IP length is then
* inferred from the L2 length), non 0 if the packet is a 1st
* fragment.
@ -518,7 +519,8 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
****************************************************************************/
#ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC1
int sixlowpan_uncompresshdr_hc1(uint16_t iplen, FAR struct iob_s *iob,
int sixlowpan_uncompresshdr_hc1(FAR const struct ieee802154_data_ind_s *ind,
uint16_t iplen, FAR struct iob_s *iob,
FAR uint8_t *fptr, FAR uint8_t *bptr);
#endif
@ -527,11 +529,14 @@ int sixlowpan_uncompresshdr_hc1(uint16_t iplen, FAR struct iob_s *iob,
* sixlowpan_ismacbased
*
* Description:
* sixlowpan_addrfromip(): Extract the IEEE 802.15.14 address from a MAC
* based IPv6 address. sixlowpan_addrfromip() is intended to handle a
* tagged address or any size; sixlowpan_saddrfromip() and
* sixlowpan_eaddrfromip() specifically handle short and extended
* addresses.
* sixlowpan_{s|e]addrfromip(): Extract the IEEE 802.15.14 address from a
* MAC-based IPv6 address. sixlowpan_addrfromip() is intended to handle a
* tagged address; sixlowpan_saddrfromip() and sixlowpan_eaddrfromip()
* specifically handle short and extended addresses, respectively.
*
* sixlowpan_ipfrom[s|e]addr(): Create a link-local, MAC-based IPv6
* address from an IEEE802.15.4 short address (saddr) or extended address
* (eaddr).
*
* sixlowpan_islinklocal() and sixlowpan_ismacbased() will return true for
* address created in this fashion. sixlowpan_addrfromip() is intended to
@ -550,12 +555,17 @@ int sixlowpan_uncompresshdr_hc1(uint16_t iplen, FAR struct iob_s *iob,
#define sixlowpan_islinklocal(ipaddr) ((ipaddr)[0] == NTOHS(0xfe80))
void sixlowpan_saddrfromip(const net_ipv6addr_t ipaddr,
FAR struct sixlowpan_saddr_s *saddr);
FAR struct sixlowpan_saddr_s *saddr);
void sixlowpan_eaddrfromip(const net_ipv6addr_t ipaddr,
FAR struct sixlowpan_eaddr_s *eaddr);
FAR struct sixlowpan_eaddr_s *eaddr);
void sixlowpan_addrfromip(const net_ipv6addr_t ipaddr,
FAR struct sixlowpan_tagaddr_s *addr);
void sixlowpan_ipfromsaddr(FAR const uint8_t *saddr,
FAR net_ipv6addr_t ipaddr);
void sixlowpan_ipfromeaddr(FAR const uint8_t *eaddr,
FAR net_ipv6addr_t ipaddr);
bool sixlowpan_issaddrbased(const net_ipv6addr_t ipaddr,
FAR const struct sixlowpan_saddr_s *saddr);
bool sixlowpan_iseaddrbased(const net_ipv6addr_t ipaddr,

View File

@ -68,14 +68,13 @@
****************************************************************************/
/****************************************************************************
* Name: sixlowpan_addrfromip
* Name: sixlowpan_{s|e]addrfromip
*
* Description:
* sixlowpan_addrfromip(): Extract the IEEE 802.15.14 address from a MAC
* based IPv6 address. sixlowpan_addrfromip() is intended to handle a
* tagged address or and size; sixlowpan_saddrfromip() and
* sixlowpan_eaddrfromip() specifically handler short and extended
* addresses.
* sixlowpan_{s|e]addrfromip(): Extract the IEEE 802.15.14 address from a
* MAC-based IPv6 address. sixlowpan_addrfromip() is intended to handle a
* tagged address; sixlowpan_saddrfromip() and sixlowpan_eaddrfromip()
* specifically handle short and extended addresses, respectively.
*
* 128 112 96 80 64 48 32 16
* ---- ---- ---- ---- ---- ---- ---- ----
@ -132,6 +131,49 @@ void sixlowpan_addrfromip(const net_ipv6addr_t ipaddr,
}
}
/****************************************************************************
* Name: sixlowpan_ipfrom[s|e]addr
*
* Description:
* sixlowpan_ipfrom[s|e]addr(): Create a link-local, MAC-based IPv6
* address from an IEEE802.15.4 short address (saddr) or extended address
* (eaddr).
*
* 128 112 96 80 64 48 32 16
* ---- ---- ---- ---- ---- ---- ---- ----
* fe80 0000 0000 0000 0000 00ff fe00 xxxx 2-byte short address IEEE 48-bit MAC
* fe80 0000 0000 0000 xxxx xxxx xxxx xxxx 8-byte extended address IEEE EUI-64
*
****************************************************************************/
void sixlowpan_ipfromsaddr(FAR const uint8_t *saddr,
FAR net_ipv6addr_t ipaddr)
{
ipaddr[0] = HTONS(0xfe80);
ipaddr[1] = 0;
ipaddr[2] = 0;
ipaddr[3] = 0;
ipaddr[4] = 0;
ipaddr[5] = HTONS(0x00ff);
ipaddr[6] = HTONS(0xfe00);
ipaddr[7] = (uint16_t)saddr[0] << 8 | (uint16_t)saddr[1];
ipaddr[7] ^= 0x200;
}
void sixlowpan_ipfromeaddr(FAR const uint8_t *eaddr,
FAR net_ipv6addr_t ipaddr)
{
ipaddr[0] = HTONS(0xfe80);
ipaddr[1] = 0;
ipaddr[2] = 0;
ipaddr[3] = 0;
ipaddr[4] = (uint16_t)eaddr[0] << 8 | (uint16_t)eaddr[1];
ipaddr[5] = (uint16_t)eaddr[2] << 8 | (uint16_t)eaddr[3];
ipaddr[6] = (uint16_t)eaddr[4] << 8 | (uint16_t)eaddr[5];
ipaddr[7] = (uint16_t)eaddr[6] << 8 | (uint16_t)eaddr[6];
ipaddr[4] ^= 0x200;
}
/****************************************************************************
* Name: sixlowpan_ismacbased
*

View File

@ -210,10 +210,10 @@ static void lo_addr2ip(FAR struct net_driver_s *dev)
dev->d_ipv6addr[1] = 0;
dev->d_ipv6addr[2] = 0;
dev->d_ipv6addr[3] = 0;
dev->d_ipv6addr[4] = (uint16_t)g_eaddr[0] << 8 | (uint16_t)g_eaddr[1];
dev->d_ipv6addr[5] = (uint16_t)g_eaddr[2] << 8 | (uint16_t)g_eaddr[3];
dev->d_ipv6addr[6] = (uint16_t)g_eaddr[4] << 8 | (uint16_t)g_eaddr[5];
dev->d_ipv6addr[7] = (uint16_t)g_eaddr[6] << 8 | (uint16_t)g_eaddr[6];
dev->d_ipv6addr[4] = (uint16_t)g_eaddr[0] << 8 | (uint16_t)g_eaddr[1];
dev->d_ipv6addr[5] = (uint16_t)g_eaddr[2] << 8 | (uint16_t)g_eaddr[3];
dev->d_ipv6addr[6] = (uint16_t)g_eaddr[4] << 8 | (uint16_t)g_eaddr[5];
dev->d_ipv6addr[7] = (uint16_t)g_eaddr[6] << 8 | (uint16_t)g_eaddr[6];
dev->d_ipv6addr[4] ^= 0x200;
memcpy(dev->d_mac.ieee802154, g_eaddr, IEEE802154_EADDRSIZE);
@ -234,7 +234,7 @@ static void lo_addr2ip(FAR struct net_driver_s *dev)
dev->d_ipv6addr[4] = 0;
dev->d_ipv6addr[5] = HTONS(0x00ff);
dev->d_ipv6addr[6] = HTONS(0xfe00);
dev->d_ipv6addr[7] = (uint16_t)g_saddr[0] << 8 | (uint16_t)g_saddr[1];
dev->d_ipv6addr[7] = (uint16_t)g_saddr[0] << 8 | (uint16_t)g_saddr[1];
dev->d_ipv6addr[7] ^= 0x200;
}
#endif