2016-06-23 16:06:24 +03:00
|
|
|
/** @file
|
|
|
|
* @brief 6lopan related functions
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2016 Intel Corporation
|
|
|
|
*
|
2017-01-18 17:01:01 -08:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2016-06-23 16:06:24 +03:00
|
|
|
*/
|
|
|
|
|
2018-07-06 11:35:07 +03:00
|
|
|
#define LOG_MODULE_NAME net_6lo
|
|
|
|
#define NET_LOG_LEVEL CONFIG_NET_6LO_LOG_LEVEL
|
2016-06-23 16:06:24 +03:00
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <net/net_core.h>
|
|
|
|
#include <net/net_if.h>
|
|
|
|
#include <net/net_stats.h>
|
2017-06-30 17:46:01 +03:00
|
|
|
#include <net/udp.h>
|
2016-06-23 16:06:24 +03:00
|
|
|
|
|
|
|
#include "net_private.h"
|
|
|
|
#include "6lo.h"
|
|
|
|
#include "6lo_private.h"
|
|
|
|
|
2016-10-05 17:20:06 +03:00
|
|
|
#if defined(CONFIG_NET_6LO_CONTEXT)
|
|
|
|
struct net_6lo_context {
|
|
|
|
struct in6_addr prefix;
|
|
|
|
struct net_if *iface;
|
2017-04-21 09:27:50 -05:00
|
|
|
u16_t lifetime;
|
|
|
|
u8_t is_used : 1;
|
|
|
|
u8_t compress : 1;
|
|
|
|
u8_t cid : 4;
|
|
|
|
u8_t unused : 2;
|
2016-10-05 17:20:06 +03:00
|
|
|
} __packed;
|
|
|
|
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t get_6co_compress(struct net_icmpv6_nd_opt_6co *opt)
|
2016-10-05 17:20:06 +03:00
|
|
|
{
|
2017-03-14 10:44:41 -07:00
|
|
|
return (opt->flag & 0x10) >> 4;
|
2016-10-05 17:20:06 +03:00
|
|
|
}
|
|
|
|
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t get_6co_cid(struct net_icmpv6_nd_opt_6co *opt)
|
2016-10-05 17:20:06 +03:00
|
|
|
{
|
|
|
|
return opt->flag & 0x0F;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct net_6lo_context ctx_6co[CONFIG_NET_MAX_6LO_CONTEXTS];
|
|
|
|
#endif
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
/* TODO: Unicast-Prefix based IPv6 Multicast(dst) address compression
|
|
|
|
* Mesh header compression
|
|
|
|
*/
|
|
|
|
|
2016-06-23 16:06:24 +03:00
|
|
|
static inline bool net_6lo_ll_prefix_padded_with_zeros(struct in6_addr *addr)
|
|
|
|
{
|
2017-04-10 17:13:35 +03:00
|
|
|
return ((UNALIGNED_GET(&addr->s6_addr16[1]) == 0x00) &&
|
|
|
|
(UNALIGNED_GET(&addr->s6_addr32[1]) == 0x00));
|
2016-06-23 16:06:24 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool net_6lo_addr_16_bit_compressible(struct in6_addr *addr)
|
|
|
|
{
|
2017-04-10 17:13:35 +03:00
|
|
|
return ((UNALIGNED_GET(&addr->s6_addr32[2]) == htonl(0xFF)) &&
|
|
|
|
(UNALIGNED_GET(&addr->s6_addr16[6]) == htons(0xFE00)));
|
2016-06-23 16:06:24 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool net_6lo_maddr_8_bit_compressible(struct in6_addr *addr)
|
|
|
|
{
|
|
|
|
return ((addr->s6_addr[1] == 0x02) &&
|
2017-04-10 17:13:35 +03:00
|
|
|
(UNALIGNED_GET(&addr->s6_addr16[1]) == 0x00) &&
|
|
|
|
(UNALIGNED_GET(&addr->s6_addr32[1]) == 0x00) &&
|
|
|
|
(UNALIGNED_GET(&addr->s6_addr32[2]) == 0x00) &&
|
2016-06-23 16:06:24 +03:00
|
|
|
(addr->s6_addr[14] == 0x00));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool net_6lo_maddr_32_bit_compressible(struct in6_addr *addr)
|
|
|
|
{
|
2017-04-10 17:13:35 +03:00
|
|
|
return ((UNALIGNED_GET(&addr->s6_addr32[1]) == 0x00) &&
|
|
|
|
(UNALIGNED_GET(&addr->s6_addr32[2]) == 0x00) &&
|
2016-06-23 16:06:24 +03:00
|
|
|
(addr->s6_addr[12] == 0x00));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool net_6lo_maddr_48_bit_compressible(struct in6_addr *addr)
|
|
|
|
{
|
2017-04-10 17:13:35 +03:00
|
|
|
return ((UNALIGNED_GET(&addr->s6_addr32[1]) == 0x00) &&
|
|
|
|
(UNALIGNED_GET(&addr->s6_addr16[4]) == 0x00) &&
|
2016-06-23 16:06:24 +03:00
|
|
|
(addr->s6_addr[10] == 0x00));
|
|
|
|
}
|
|
|
|
|
2016-10-05 17:20:06 +03:00
|
|
|
#if defined(CONFIG_NET_6LO_CONTEXT)
|
|
|
|
/* RFC 6775, 4.2, 5.4.2, 5.4.3 and 7.2*/
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline void set_6lo_context(struct net_if *iface, u8_t index,
|
2016-10-05 17:20:06 +03:00
|
|
|
struct net_icmpv6_nd_opt_6co *context)
|
|
|
|
|
|
|
|
{
|
|
|
|
ctx_6co[index].is_used = true;
|
|
|
|
ctx_6co[index].iface = iface;
|
|
|
|
|
|
|
|
/*TODO: Start timer */
|
|
|
|
ctx_6co[index].lifetime = context->lifetime;
|
|
|
|
ctx_6co[index].compress = get_6co_compress(context);
|
|
|
|
ctx_6co[index].cid = get_6co_cid(context);
|
|
|
|
|
|
|
|
net_ipaddr_copy(&ctx_6co[index].prefix, &context->prefix);
|
|
|
|
}
|
|
|
|
|
|
|
|
void net_6lo_set_context(struct net_if *iface,
|
|
|
|
struct net_icmpv6_nd_opt_6co *context)
|
|
|
|
{
|
|
|
|
int unused = -1;
|
2017-04-21 09:27:50 -05:00
|
|
|
u8_t i;
|
2016-10-05 17:20:06 +03:00
|
|
|
|
|
|
|
/* If the context information already exists, update or remove
|
|
|
|
* as per data.
|
|
|
|
*/
|
2018-11-29 11:23:03 -08:00
|
|
|
for (i = 0U; i < CONFIG_NET_MAX_6LO_CONTEXTS; i++) {
|
2016-10-05 17:20:06 +03:00
|
|
|
if (!ctx_6co[i].is_used) {
|
|
|
|
unused = i;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx_6co[i].iface == iface &&
|
|
|
|
ctx_6co[i].cid == get_6co_cid(context)) {
|
|
|
|
/* Remove if lifetime is zero */
|
|
|
|
if (!context->lifetime) {
|
|
|
|
ctx_6co[i].is_used = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update the context */
|
|
|
|
set_6lo_context(iface, i, context);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Cache the context information. */
|
|
|
|
if (unused != -1) {
|
|
|
|
set_6lo_context(iface, unused, context);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
NET_DBG("Either no free slots in the table or exceeds limit");
|
|
|
|
}
|
2016-10-05 11:43:00 +03:00
|
|
|
|
|
|
|
/* Get the context by matching cid */
|
|
|
|
static inline struct net_6lo_context *
|
2017-04-21 09:27:50 -05:00
|
|
|
get_6lo_context_by_cid(struct net_if *iface, u8_t cid)
|
2016-10-05 11:43:00 +03:00
|
|
|
{
|
2017-04-21 09:27:50 -05:00
|
|
|
u8_t i;
|
2016-10-05 11:43:00 +03:00
|
|
|
|
2018-11-29 11:23:03 -08:00
|
|
|
for (i = 0U; i < CONFIG_NET_MAX_6LO_CONTEXTS; i++) {
|
2016-10-05 11:43:00 +03:00
|
|
|
if (!ctx_6co[i].is_used) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx_6co[i].iface == iface && ctx_6co[i].cid == cid) {
|
|
|
|
return &ctx_6co[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the context by addr */
|
|
|
|
static inline struct net_6lo_context *
|
|
|
|
get_6lo_context_by_addr(struct net_if *iface, struct in6_addr *addr)
|
|
|
|
{
|
2017-04-21 09:27:50 -05:00
|
|
|
u8_t i;
|
2016-10-05 11:43:00 +03:00
|
|
|
|
2018-11-29 11:23:03 -08:00
|
|
|
for (i = 0U; i < CONFIG_NET_MAX_6LO_CONTEXTS; i++) {
|
2016-10-05 11:43:00 +03:00
|
|
|
if (!ctx_6co[i].is_used) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx_6co[i].iface == iface &&
|
|
|
|
!memcmp(ctx_6co[i].prefix.s6_addr, addr->s6_addr, 8)) {
|
|
|
|
return &ctx_6co[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-10-05 17:20:06 +03:00
|
|
|
#endif
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
/* Helper routine to compress Traffic class and Flow label */
|
|
|
|
/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* |Version| Traffic Class | Flow Label |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* version: 4 bits, Traffic Class: 8 bits, Flow label: 20 bits
|
|
|
|
* The Traffic Class field in the IPv6 header comprises 6 bits of
|
|
|
|
* Diffserv extension [RFC2474] and 2 bits of Explicit Congestion
|
|
|
|
* Notification (ECN) [RFC3168]
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* IPHC (compressed) format of traffic class is ECN, DSCP but original
|
|
|
|
* IPv6 traffic class format is DSCP, ECN.
|
|
|
|
* DSCP(6), ECN(2).
|
|
|
|
*/
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t compress_tfl(struct net_ipv6_hdr *ipv6,
|
2016-10-04 11:25:51 +03:00
|
|
|
struct net_buf *frag,
|
2017-04-21 09:27:50 -05:00
|
|
|
u8_t offset)
|
2016-06-23 16:06:24 +03:00
|
|
|
{
|
2017-04-21 09:27:50 -05:00
|
|
|
u8_t tcl;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
|
|
|
tcl = ((ipv6->vtc & 0x0F) << 4) | ((ipv6->tcflow & 0xF0) >> 4);
|
|
|
|
tcl = (tcl << 6) | (tcl >> 2); /* ECN(2), DSCP(6) */
|
|
|
|
|
|
|
|
if (((ipv6->tcflow & 0x0F) == 0) && (ipv6->flow == 0)) {
|
|
|
|
if (((ipv6->vtc & 0x0F) == 0) && ((ipv6->tcflow & 0xF0) == 0)) {
|
|
|
|
NET_DBG("Trafic class and Flow label elided");
|
|
|
|
|
|
|
|
/* Trafic class and Flow label elided */
|
2016-07-08 17:20:38 +03:00
|
|
|
IPHC[0] |= NET_6LO_IPHC_TF_11;
|
2016-06-23 16:06:24 +03:00
|
|
|
} else {
|
|
|
|
NET_DBG("Flow label elided");
|
|
|
|
|
|
|
|
/* Flow label elided */
|
2016-07-08 17:20:38 +03:00
|
|
|
IPHC[0] |= NET_6LO_IPHC_TF_10;
|
2016-06-23 16:06:24 +03:00
|
|
|
IPHC[offset++] = tcl;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (((ipv6->vtc & 0x0F) == 0) && (ipv6->tcflow & 0x30)) {
|
|
|
|
NET_DBG("ECN + 2-bit Pad + Flow Label, DSCP is elided");
|
|
|
|
|
|
|
|
/* ECN + 2-bit Pad + Flow Label, DSCP is elided.*/
|
2016-07-08 17:20:38 +03:00
|
|
|
IPHC[0] |= NET_6LO_IPHC_TF_01;
|
2016-06-23 16:06:24 +03:00
|
|
|
IPHC[offset++] = (tcl & 0xC0) | (ipv6->tcflow & 0x0F);
|
|
|
|
|
|
|
|
memcpy(&IPHC[offset], &ipv6->flow, 2);
|
|
|
|
offset += 2;
|
|
|
|
} else {
|
|
|
|
NET_DBG("ECN + DSCP + 4-bit Pad + Flow Label");
|
|
|
|
|
|
|
|
/* ECN + DSCP + 4-bit Pad + Flow Label */
|
2016-07-08 17:20:38 +03:00
|
|
|
IPHC[0] |= NET_6LO_IPHC_TF_00;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
|
|
|
/* Elide the version field */
|
|
|
|
IPHC[offset++] = tcl;
|
|
|
|
IPHC[offset++] = ipv6->tcflow & 0x0F;
|
|
|
|
|
|
|
|
memcpy(&IPHC[offset], &ipv6->flow, 2);
|
|
|
|
offset += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
return offset;
|
|
|
|
}
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
/* Helper to compress Hop limit */
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t compress_hoplimit(struct net_ipv6_hdr *ipv6,
|
2017-08-08 14:41:23 +03:00
|
|
|
struct net_buf *frag,
|
|
|
|
u8_t offset)
|
2016-10-04 11:25:51 +03:00
|
|
|
{
|
2016-06-23 16:06:24 +03:00
|
|
|
/* Hop Limit */
|
|
|
|
switch (ipv6->hop_limit) {
|
|
|
|
case 1:
|
2016-07-08 17:20:38 +03:00
|
|
|
IPHC[0] |= NET_6LO_IPHC_HLIM1;
|
2016-06-23 16:06:24 +03:00
|
|
|
break;
|
|
|
|
case 64:
|
2016-07-08 17:20:38 +03:00
|
|
|
IPHC[0] |= NET_6LO_IPHC_HLIM64;
|
2016-06-23 16:06:24 +03:00
|
|
|
break;
|
|
|
|
case 255:
|
2016-07-08 17:20:38 +03:00
|
|
|
IPHC[0] |= NET_6LO_IPHC_HLIM255;
|
2016-06-23 16:06:24 +03:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
IPHC[offset++] = ipv6->hop_limit;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Helper to compress Next header */
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t compress_nh(struct net_ipv6_hdr *ipv6,
|
2017-08-08 14:41:23 +03:00
|
|
|
struct net_buf *frag, u8_t offset)
|
2016-10-04 11:25:51 +03:00
|
|
|
{
|
|
|
|
/* Next header */
|
|
|
|
if (ipv6->nexthdr == IPPROTO_UDP) {
|
|
|
|
IPHC[0] |= NET_6LO_IPHC_NH_1;
|
|
|
|
} else {
|
|
|
|
IPHC[offset++] = ipv6->nexthdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
/* Helpers to compress Source Address */
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t compress_sa(struct net_ipv6_hdr *ipv6,
|
2017-08-08 14:41:23 +03:00
|
|
|
struct net_pkt *pkt,
|
|
|
|
struct net_buf *frag,
|
|
|
|
u8_t offset)
|
2016-10-04 11:25:51 +03:00
|
|
|
{
|
2018-11-02 16:05:58 +02:00
|
|
|
if (net_ipv6_is_addr_unspecified(&ipv6->src)) {
|
2016-10-05 11:43:00 +03:00
|
|
|
NET_DBG("SAM_00, SAC_1 unspecified src address");
|
|
|
|
|
|
|
|
/* Unspecified IPv6 src address */
|
|
|
|
IPHC[1] |= NET_6LO_IPHC_SAC_1;
|
|
|
|
IPHC[1] |= NET_6LO_IPHC_SAM_00;
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2016-06-23 16:06:24 +03:00
|
|
|
/* If address is link-local prefix and padded with zeros */
|
2018-11-02 16:05:58 +02:00
|
|
|
if (net_ipv6_is_ll_addr(&ipv6->src) &&
|
2016-06-23 16:06:24 +03:00
|
|
|
net_6lo_ll_prefix_padded_with_zeros(&ipv6->src)) {
|
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
NET_DBG("SAC_0 src is ll_addr and padded with zeros");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
/* Following 64 bits are 0000:00ff:fe00:XXXX */
|
2016-06-23 16:06:24 +03:00
|
|
|
if (net_6lo_addr_16_bit_compressible(&ipv6->src)) {
|
2016-10-05 11:43:00 +03:00
|
|
|
NET_DBG("SAM_10 src addr 16 bit compressible");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-07-08 17:20:38 +03:00
|
|
|
IPHC[1] |= NET_6LO_IPHC_SAM_10;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
|
|
|
memcpy(&IPHC[offset], &ipv6->src.s6_addr[14], 2);
|
|
|
|
offset += 2;
|
|
|
|
} else {
|
2018-09-11 09:16:03 +02:00
|
|
|
if (!net_pkt_lladdr_src(pkt)) {
|
2017-01-26 16:12:23 +01:00
|
|
|
NET_ERR("Invalid src ll address");
|
2017-01-25 14:50:42 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-09-11 09:16:03 +02:00
|
|
|
if (net_ipv6_addr_based_on_ll(
|
|
|
|
&ipv6->src, net_pkt_lladdr_src(pkt))) {
|
2016-10-05 11:43:00 +03:00
|
|
|
NET_DBG("SAM_11 src address is fully elided");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
|
|
|
/* Address is fully elided */
|
2016-07-08 17:20:38 +03:00
|
|
|
IPHC[1] |= NET_6LO_IPHC_SAM_11;
|
2016-06-23 16:06:24 +03:00
|
|
|
} else {
|
2016-10-05 11:43:00 +03:00
|
|
|
NET_DBG("SAM_01 src 64 bits are inlined");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
/* Remaining 64 bits are in-line */
|
2016-07-08 17:20:38 +03:00
|
|
|
IPHC[1] |= NET_6LO_IPHC_SAM_01;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
|
|
|
memcpy(&IPHC[offset], &ipv6->src.s6_addr[8], 8);
|
|
|
|
offset += 8;
|
|
|
|
}
|
|
|
|
}
|
2016-10-05 11:43:00 +03:00
|
|
|
} else {
|
|
|
|
NET_DBG("SAM_00 full src address is carried in-line");
|
|
|
|
/* full address is carried in-line */
|
2016-07-08 17:20:38 +03:00
|
|
|
IPHC[1] |= NET_6LO_IPHC_SAM_00;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
memcpy(&IPHC[offset], ipv6->src.s6_addr,
|
|
|
|
sizeof(struct in6_addr));
|
|
|
|
offset += sizeof(struct in6_addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(CONFIG_NET_6LO_CONTEXT)
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t compress_sa_ctx(struct net_ipv6_hdr *ipv6,
|
2017-08-08 14:41:23 +03:00
|
|
|
struct net_pkt *pkt,
|
|
|
|
struct net_buf *frag,
|
|
|
|
u8_t offset,
|
|
|
|
struct net_6lo_context *src)
|
2016-10-05 11:43:00 +03:00
|
|
|
{
|
|
|
|
if (!src) {
|
2017-04-05 08:37:44 +02:00
|
|
|
return compress_sa(ipv6, pkt, frag, offset);
|
2016-10-05 11:43:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
IPHC[1] |= NET_6LO_IPHC_SAC_1;
|
|
|
|
|
|
|
|
/* Following 64 bits are 0000:00ff:fe00:XXXX */
|
|
|
|
if (net_6lo_addr_16_bit_compressible(&ipv6->src)) {
|
|
|
|
NET_DBG("SAM_10 src addr 16 bit compressible");
|
|
|
|
|
|
|
|
IPHC[1] |= NET_6LO_IPHC_SAM_10;
|
|
|
|
|
|
|
|
memcpy(&IPHC[offset], &ipv6->src.s6_addr[14], 2);
|
|
|
|
offset += 2;
|
|
|
|
} else if (net_ipv6_addr_based_on_ll(&ipv6->src,
|
2018-09-11 09:16:03 +02:00
|
|
|
net_pkt_lladdr_src(pkt))) {
|
2016-10-05 11:43:00 +03:00
|
|
|
NET_DBG("SAM_11 src address is fully elided");
|
|
|
|
|
|
|
|
/* Address is fully elided */
|
|
|
|
IPHC[1] |= NET_6LO_IPHC_SAM_11;
|
2016-06-23 16:06:24 +03:00
|
|
|
} else {
|
2016-10-05 11:43:00 +03:00
|
|
|
NET_DBG("SAM_01 src remaining 64 bits are inlined");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
/* Remaining 64 bits are in-line */
|
|
|
|
IPHC[1] |= NET_6LO_IPHC_SAM_01;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
memcpy(&IPHC[offset], &ipv6->src.s6_addr[8], 8);
|
|
|
|
offset += 8;
|
2016-06-23 16:06:24 +03:00
|
|
|
}
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
return offset;
|
|
|
|
}
|
2016-10-05 11:43:00 +03:00
|
|
|
#endif
|
2016-10-04 11:25:51 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
/* Helpers to compress Destination Address */
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t compress_da_mcast(struct net_ipv6_hdr *ipv6,
|
2017-08-08 14:41:23 +03:00
|
|
|
struct net_pkt *pkt,
|
|
|
|
struct net_buf *frag,
|
|
|
|
u8_t offset)
|
2016-10-04 11:25:51 +03:00
|
|
|
{
|
2016-10-05 11:43:00 +03:00
|
|
|
IPHC[1] |= NET_6LO_IPHC_M_1;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
NET_DBG("M_1 dst is mcast");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
if (net_6lo_maddr_8_bit_compressible(&ipv6->dst)) {
|
|
|
|
NET_DBG("DAM_11 dst maddr 8 bit compressible");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
/* last byte */
|
|
|
|
IPHC[1] |= NET_6LO_IPHC_DAM_11;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
memcpy(&IPHC[offset], &ipv6->dst.s6_addr[15], 1);
|
|
|
|
offset++;
|
|
|
|
} else if (net_6lo_maddr_32_bit_compressible(&ipv6->dst)) {
|
|
|
|
NET_DBG("DAM_10 4 bytes: 2nd byte + last three bytes");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
/* 4 bytes: 2nd byte + last three bytes */
|
|
|
|
IPHC[1] |= NET_6LO_IPHC_DAM_10;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
memcpy(&IPHC[offset], &ipv6->dst.s6_addr[1], 1);
|
|
|
|
offset++;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
memcpy(&IPHC[offset], &ipv6->dst.s6_addr[13], 3);
|
|
|
|
offset += 3;
|
|
|
|
} else if (net_6lo_maddr_48_bit_compressible(&ipv6->dst)) {
|
|
|
|
NET_DBG("DAM_01 6 bytes: 2nd byte + last five bytes");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
/* 6 bytes: 2nd byte + last five bytes */
|
|
|
|
IPHC[1] |= NET_6LO_IPHC_DAM_01;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
memcpy(&IPHC[offset], &ipv6->dst.s6_addr[1], 1);
|
|
|
|
offset++;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
memcpy(&IPHC[offset], &ipv6->dst.s6_addr[11], 5);
|
|
|
|
offset += 5;
|
|
|
|
} else {
|
|
|
|
NET_DBG("DAM_00 dst complete addr inlined");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
/* complete address IPHC[1] |= NET_6LO_IPHC_DAM_00 */
|
|
|
|
memcpy(&IPHC[offset], &ipv6->dst.s6_addr[0], 16);
|
|
|
|
offset += 16;
|
|
|
|
}
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
return offset;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t compress_da(struct net_ipv6_hdr *ipv6,
|
2017-08-08 14:41:23 +03:00
|
|
|
struct net_pkt *pkt,
|
|
|
|
struct net_buf *frag,
|
|
|
|
u8_t offset)
|
2016-10-05 11:43:00 +03:00
|
|
|
{
|
2017-01-26 10:27:39 +02:00
|
|
|
/* If destination address is multicast */
|
2018-11-02 16:05:58 +02:00
|
|
|
if (net_ipv6_is_addr_mcast(&ipv6->dst)) {
|
2017-04-05 08:37:44 +02:00
|
|
|
return compress_da_mcast(ipv6, pkt, frag, offset);
|
2016-10-05 11:43:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* If address is link-local prefix and padded with zeros */
|
2018-11-02 16:05:58 +02:00
|
|
|
if (net_ipv6_is_ll_addr(&ipv6->dst) &&
|
2016-10-05 11:43:00 +03:00
|
|
|
net_6lo_ll_prefix_padded_with_zeros(&ipv6->dst)) {
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
NET_DBG("Dst is ll_addr and padded with zeros");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
/* Following 64 bits are 0000:00ff:fe00:XXXX */
|
2016-06-23 16:06:24 +03:00
|
|
|
if (net_6lo_addr_16_bit_compressible(&ipv6->dst)) {
|
2016-10-05 11:43:00 +03:00
|
|
|
NET_DBG("DAM_10 dst addr 16 bit compressible");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-07-08 17:20:38 +03:00
|
|
|
IPHC[1] |= NET_6LO_IPHC_DAM_10;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
|
|
|
memcpy(&IPHC[offset], &ipv6->dst.s6_addr[14], 2);
|
|
|
|
offset += 2;
|
|
|
|
} else {
|
2018-09-11 09:16:03 +02:00
|
|
|
if (!net_pkt_lladdr_dst(pkt)) {
|
2017-01-26 16:12:23 +01:00
|
|
|
NET_ERR("Invalid dst ll address");
|
2017-01-25 14:50:42 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-09-11 09:16:03 +02:00
|
|
|
if (net_ipv6_addr_based_on_ll(
|
|
|
|
&ipv6->dst, net_pkt_lladdr_dst(pkt))) {
|
2016-10-05 11:43:00 +03:00
|
|
|
NET_DBG("DAM_11 dst addr fully elided");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
|
|
|
/* Address is fully elided */
|
2016-07-08 17:20:38 +03:00
|
|
|
IPHC[1] |= NET_6LO_IPHC_DAM_11;
|
2016-06-23 16:06:24 +03:00
|
|
|
} else {
|
2016-10-05 11:43:00 +03:00
|
|
|
NET_DBG("DAM_01 remaining 64 bits are inlined");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
/* Remaining 64 bits are in-line */
|
2016-07-08 17:20:38 +03:00
|
|
|
IPHC[1] |= NET_6LO_IPHC_DAM_01;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
|
|
|
memcpy(&IPHC[offset], &ipv6->dst.s6_addr[8], 8);
|
|
|
|
offset += 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2016-10-05 11:43:00 +03:00
|
|
|
NET_DBG("DAM_00 dst full addr inlined");
|
|
|
|
IPHC[1] |= NET_6LO_IPHC_DAM_00;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
|
|
|
memcpy(&IPHC[offset], &ipv6->dst.s6_addr[0], 16);
|
|
|
|
offset += 16;
|
|
|
|
}
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
return offset;
|
|
|
|
}
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
#if defined(CONFIG_NET_6LO_CONTEXT)
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t compress_da_ctx(struct net_ipv6_hdr *ipv6,
|
2017-08-08 14:41:23 +03:00
|
|
|
struct net_pkt *pkt,
|
|
|
|
struct net_buf *frag,
|
|
|
|
u8_t offset,
|
|
|
|
struct net_6lo_context *dst)
|
2016-10-05 11:43:00 +03:00
|
|
|
{
|
|
|
|
if (!dst) {
|
2017-04-05 08:37:44 +02:00
|
|
|
return compress_da(ipv6, pkt, frag, offset);
|
2016-10-05 11:43:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
IPHC[1] |= NET_6LO_IPHC_DAC_1;
|
|
|
|
|
|
|
|
/* Following 64 bits are 0000:00ff:fe00:XXXX */
|
|
|
|
if (net_6lo_addr_16_bit_compressible(&ipv6->dst)) {
|
|
|
|
NET_DBG("DAM_10 dst addr 16 bit compressible");
|
|
|
|
|
|
|
|
IPHC[1] |= NET_6LO_IPHC_DAM_10;
|
|
|
|
|
|
|
|
memcpy(&IPHC[offset], &ipv6->dst.s6_addr[14], 2);
|
|
|
|
offset += 2;
|
|
|
|
} else {
|
|
|
|
if (net_ipv6_addr_based_on_ll(&ipv6->dst,
|
2018-09-11 09:16:03 +02:00
|
|
|
net_pkt_lladdr_dst(pkt))) {
|
2016-10-05 11:43:00 +03:00
|
|
|
NET_DBG("DAM_11 dst addr fully elided");
|
|
|
|
|
|
|
|
/* Address is fully elided */
|
|
|
|
IPHC[1] |= NET_6LO_IPHC_DAM_11;
|
|
|
|
} else {
|
|
|
|
NET_DBG("DAM_01 remaining 64 bits are inlined");
|
|
|
|
|
|
|
|
/* Remaining 64 bits are in-line */
|
|
|
|
IPHC[1] |= NET_6LO_IPHC_DAM_01;
|
|
|
|
|
|
|
|
memcpy(&IPHC[offset], &ipv6->dst.s6_addr[8], 8);
|
|
|
|
offset += 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
/* Helper to compress Next header UDP */
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t compress_nh_udp(struct net_udp_hdr *udp,
|
2017-08-08 14:41:23 +03:00
|
|
|
struct net_buf *frag, u8_t offset)
|
2016-10-04 11:25:51 +03:00
|
|
|
{
|
2017-04-21 09:27:50 -05:00
|
|
|
u8_t tmp;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
/* 4.3.3 UDP LOWPAN_NHC Format
|
|
|
|
* 0 1 2 3 4 5 6 7
|
|
|
|
* +---+---+---+---+---+---+---+---+
|
|
|
|
* | 1 | 1 | 1 | 1 | 0 | C | P |
|
|
|
|
* +---+---+---+---+---+---+---+---+
|
|
|
|
*/
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
/* Port compression
|
|
|
|
* 00: All 16 bits for src and dst are inlined.
|
|
|
|
* 01: All 16 bits for src port inlined. First 8 bits of dst port is
|
|
|
|
* 0xf0 and elided. The remaining 8 bits of dst port inlined.
|
|
|
|
* 10: First 8 bits of src port 0xf0 and elided. The remaining 8 bits
|
|
|
|
* of src port inlined. All 16 bits of dst port inlined.
|
|
|
|
* 11: First 12 bits of both src and dst are 0xf0b and elided. The
|
|
|
|
* remaining 4 bits for each are inlined.
|
|
|
|
*/
|
2016-06-23 16:06:24 +03:00
|
|
|
|
|
|
|
if ((((htons(udp->src_port) >> 4) & 0xFFF) ==
|
2016-07-08 17:20:38 +03:00
|
|
|
NET_6LO_NHC_UDP_4_BIT_PORT) &&
|
2016-06-23 16:06:24 +03:00
|
|
|
(((htons(udp->dst_port) >> 4) & 0xFFF) ==
|
2016-07-08 17:20:38 +03:00
|
|
|
NET_6LO_NHC_UDP_4_BIT_PORT)) {
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2017-01-26 10:27:39 +02:00
|
|
|
NET_DBG("UDP ports src and dst 4 bits inlined");
|
2016-06-23 16:06:24 +03:00
|
|
|
/** src: first 16 bits elided, next 4 bits inlined
|
|
|
|
* dst: first 16 bits elided, next 4 bits inlined
|
|
|
|
*/
|
2016-07-08 17:20:38 +03:00
|
|
|
IPHC[offset] |= NET_6LO_NHC_UDP_PORT_11;
|
2016-06-23 16:06:24 +03:00
|
|
|
offset++;
|
|
|
|
|
2017-04-21 09:27:50 -05:00
|
|
|
tmp = (u8_t)(htons(udp->src_port));
|
2016-06-23 16:06:24 +03:00
|
|
|
tmp = tmp << 4;
|
|
|
|
|
2017-04-21 09:27:50 -05:00
|
|
|
tmp |= (((u8_t)(htons(udp->dst_port))) & 0x0F);
|
2016-06-23 16:06:24 +03:00
|
|
|
IPHC[offset++] = tmp;
|
|
|
|
} else if (((htons(udp->dst_port) >> 8) & 0xFF) ==
|
2016-07-08 17:20:38 +03:00
|
|
|
NET_6LO_NHC_UDP_8_BIT_PORT) {
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2017-01-26 10:27:39 +02:00
|
|
|
NET_DBG("UDP ports src full, dst 8 bits inlined");
|
|
|
|
/* dst: first 8 bits elided, next 8 bits inlined
|
|
|
|
* src: fully carried inline
|
|
|
|
*/
|
2016-07-08 17:20:38 +03:00
|
|
|
IPHC[offset] |= NET_6LO_NHC_UDP_PORT_01;
|
2016-06-23 16:06:24 +03:00
|
|
|
offset++;
|
|
|
|
|
|
|
|
memcpy(&IPHC[offset], &udp->src_port, 2);
|
|
|
|
offset += 2;
|
|
|
|
|
2017-04-21 09:27:50 -05:00
|
|
|
IPHC[offset++] = (u8_t)(htons(udp->dst_port));
|
2016-06-23 16:06:24 +03:00
|
|
|
} else if (((htons(udp->src_port) >> 8) & 0xFF) ==
|
2016-07-08 17:20:38 +03:00
|
|
|
NET_6LO_NHC_UDP_8_BIT_PORT) {
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2017-01-26 10:27:39 +02:00
|
|
|
NET_DBG("UDP ports src 8bits, dst full inlined");
|
|
|
|
/* src: first 8 bits elided, next 8 bits inlined
|
|
|
|
* dst: fully carried inline
|
|
|
|
*/
|
2016-07-08 17:20:38 +03:00
|
|
|
IPHC[offset] |= NET_6LO_NHC_UDP_PORT_10;
|
2016-06-23 16:06:24 +03:00
|
|
|
offset++;
|
|
|
|
|
2017-04-21 09:27:50 -05:00
|
|
|
IPHC[offset++] = (u8_t)(htons(udp->src_port));
|
2016-06-23 16:06:24 +03:00
|
|
|
|
|
|
|
memcpy(&IPHC[offset], &udp->dst_port, 2);
|
|
|
|
offset += 2;
|
|
|
|
} else {
|
2017-01-26 10:27:39 +02:00
|
|
|
NET_DBG("Can not compress ports, ports are inlined");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
|
|
|
/* can not compress ports, ports are inlined */
|
|
|
|
offset++;
|
|
|
|
memcpy(&IPHC[offset], &udp->src_port, 4);
|
|
|
|
offset += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* All 16 bits of udp chksum are inlined, length is elided */
|
|
|
|
memcpy(&IPHC[offset], &udp->chksum, 2);
|
|
|
|
offset += 2;
|
2016-10-04 11:25:51 +03:00
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
#if defined(CONFIG_NET_6LO_CONTEXT)
|
|
|
|
static inline bool is_src_and_dst_addr_ctx_based(struct net_ipv6_hdr *ipv6,
|
2017-04-05 08:37:44 +02:00
|
|
|
struct net_pkt *pkt,
|
2016-10-05 11:43:00 +03:00
|
|
|
struct net_buf *frag,
|
|
|
|
struct net_6lo_context **src,
|
|
|
|
struct net_6lo_context **dst)
|
|
|
|
{
|
|
|
|
/* If compress flag is unset means use only in uncompression. */
|
|
|
|
|
2017-04-05 08:37:44 +02:00
|
|
|
*src = get_6lo_context_by_addr(net_pkt_iface(pkt), &ipv6->src);
|
2016-10-05 11:43:00 +03:00
|
|
|
if (*src && !((*src)->compress)) {
|
|
|
|
*src = NULL;
|
|
|
|
}
|
|
|
|
|
2017-04-05 08:37:44 +02:00
|
|
|
*dst = get_6lo_context_by_addr(net_pkt_iface(pkt), &ipv6->dst);
|
2016-10-05 11:43:00 +03:00
|
|
|
if (*dst && !((*dst)->compress)) {
|
|
|
|
*dst = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!*src && !*dst) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
NET_DBG("Context based compression");
|
|
|
|
IPHC[1] |= NET_6LO_IPHC_CID_1;
|
|
|
|
IPHC[2] = 0;
|
|
|
|
|
|
|
|
if (*src) {
|
|
|
|
NET_DBG("Src addr context cid %d", (*src)->cid);
|
|
|
|
IPHC[2] = (*src)->cid << 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*dst) {
|
|
|
|
NET_DBG("Dst addr context cid %d", (*dst)->cid);
|
|
|
|
IPHC[2] |= (*dst)->cid;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
/* RFC 6282 LOWPAN IPHC Encoding format (3.1)
|
|
|
|
* Base Format
|
|
|
|
* 0 1
|
|
|
|
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
|
|
|
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
* | 0 | 1 | 1 | TF |NH | HLIM |CID|SAC| SAM | M |DAC| DAM |
|
|
|
|
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
*/
|
2017-04-05 08:37:44 +02:00
|
|
|
static inline bool compress_IPHC_header(struct net_pkt *pkt,
|
2016-10-04 11:25:51 +03:00
|
|
|
fragment_handler_t fragment)
|
|
|
|
{
|
2016-10-05 11:43:00 +03:00
|
|
|
#if defined(CONFIG_NET_6LO_CONTEXT)
|
|
|
|
struct net_6lo_context *src = NULL;
|
|
|
|
struct net_6lo_context *dst = NULL;
|
|
|
|
#endif
|
2017-04-10 13:03:41 +02:00
|
|
|
struct net_ipv6_hdr *ipv6 = NET_IPV6_HDR(pkt);
|
2018-11-29 11:23:03 -08:00
|
|
|
u8_t offset = 0U;
|
2016-10-04 11:25:51 +03:00
|
|
|
struct net_buf *frag;
|
2017-04-21 09:27:50 -05:00
|
|
|
u8_t compressed;
|
2016-10-04 11:25:51 +03:00
|
|
|
|
2017-04-05 08:37:44 +02:00
|
|
|
if (pkt->frags->len < NET_IPV6H_LEN) {
|
2017-01-26 16:12:23 +01:00
|
|
|
NET_ERR("Invalid length %d, min %d",
|
2017-04-05 08:37:44 +02:00
|
|
|
pkt->frags->len, NET_IPV6H_LEN);
|
2016-10-04 11:25:51 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ipv6->nexthdr == IPPROTO_UDP &&
|
2017-04-05 08:37:44 +02:00
|
|
|
pkt->frags->len < NET_IPV6UDPH_LEN) {
|
2017-01-26 16:12:23 +01:00
|
|
|
NET_ERR("Invalid length %d, min %d",
|
2017-04-05 08:37:44 +02:00
|
|
|
pkt->frags->len, NET_IPV6UDPH_LEN);
|
2016-10-04 11:25:51 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-04-05 08:37:44 +02:00
|
|
|
frag = net_pkt_get_frag(pkt, K_FOREVER);
|
2017-08-17 23:12:58 -03:00
|
|
|
if (!frag) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-10-04 11:25:51 +03:00
|
|
|
|
|
|
|
IPHC[offset++] = NET_6LO_DISPATCH_IPHC;
|
|
|
|
IPHC[offset++] = 0;
|
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
#if defined(CONFIG_NET_6LO_CONTEXT)
|
2017-04-05 08:37:44 +02:00
|
|
|
if (is_src_and_dst_addr_ctx_based(ipv6, pkt, frag, &src, &dst)) {
|
2016-10-05 11:43:00 +03:00
|
|
|
offset++;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
/* Compress Traffic class and Flow lablel */
|
|
|
|
offset = compress_tfl(ipv6, frag, offset);
|
|
|
|
|
|
|
|
/* Next Header */
|
|
|
|
offset = compress_nh(ipv6, frag, offset);
|
|
|
|
|
2017-03-03 11:39:00 +02:00
|
|
|
/* Hop limit */
|
|
|
|
offset = compress_hoplimit(ipv6, frag, offset);
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
/* Source Address Compression */
|
2016-10-05 11:43:00 +03:00
|
|
|
#if defined(CONFIG_NET_6LO_CONTEXT)
|
2017-04-05 08:37:44 +02:00
|
|
|
offset = compress_sa_ctx(ipv6, pkt, frag, offset, src);
|
2016-10-05 11:43:00 +03:00
|
|
|
#else
|
2017-04-05 08:37:44 +02:00
|
|
|
offset = compress_sa(ipv6, pkt, frag, offset);
|
2016-10-05 11:43:00 +03:00
|
|
|
#endif
|
2017-01-25 14:50:42 +02:00
|
|
|
if (!offset) {
|
2017-04-05 08:37:44 +02:00
|
|
|
net_pkt_frag_unref(frag);
|
2017-01-25 14:50:42 +02:00
|
|
|
return false;
|
|
|
|
}
|
2016-10-04 11:25:51 +03:00
|
|
|
|
|
|
|
/* Destination Address Compression */
|
2016-10-05 11:43:00 +03:00
|
|
|
#if defined(CONFIG_NET_6LO_CONTEXT)
|
2017-04-05 08:37:44 +02:00
|
|
|
offset = compress_da_ctx(ipv6, pkt, frag, offset, dst);
|
2016-10-05 11:43:00 +03:00
|
|
|
#else
|
2017-04-05 08:37:44 +02:00
|
|
|
offset = compress_da(ipv6, pkt, frag, offset);
|
2016-10-05 11:43:00 +03:00
|
|
|
#endif
|
2016-10-04 11:25:51 +03:00
|
|
|
|
2017-01-25 14:50:42 +02:00
|
|
|
if (!offset) {
|
2017-04-05 08:37:44 +02:00
|
|
|
net_pkt_frag_unref(frag);
|
2017-01-25 14:50:42 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
compressed = NET_IPV6H_LEN;
|
|
|
|
|
|
|
|
if (ipv6->nexthdr != IPPROTO_UDP) {
|
|
|
|
NET_DBG("next header is not UDP (%u)", ipv6->nexthdr);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* UDP header compression */
|
2017-06-30 17:46:01 +03:00
|
|
|
if (IS_ENABLED(CONFIG_NET_UDP)) {
|
|
|
|
struct net_udp_hdr hdr, *udp;
|
2016-10-04 11:25:51 +03:00
|
|
|
|
2017-06-30 17:46:01 +03:00
|
|
|
udp = net_udp_get_hdr(pkt, &hdr);
|
2018-02-27 15:28:41 -08:00
|
|
|
if (!udp) {
|
|
|
|
NET_ERR("could not get UDP header");
|
|
|
|
return false;
|
|
|
|
}
|
2017-06-30 17:46:01 +03:00
|
|
|
|
|
|
|
IPHC[offset] = NET_6LO_NHC_UDP_BARE;
|
|
|
|
offset = compress_nh_udp(udp, frag, offset);
|
|
|
|
|
|
|
|
compressed += NET_UDPH_LEN;
|
|
|
|
|
|
|
|
net_udp_set_hdr(pkt, udp);
|
|
|
|
}
|
2016-06-23 16:06:24 +03:00
|
|
|
|
|
|
|
end:
|
|
|
|
net_buf_add(frag, offset);
|
2016-10-04 11:25:51 +03:00
|
|
|
|
2017-01-26 10:27:39 +02:00
|
|
|
/* Copy the rest of the data to compressed fragment */
|
2017-04-05 08:37:44 +02:00
|
|
|
memcpy(&IPHC[offset], pkt->frags->data + compressed,
|
|
|
|
pkt->frags->len - compressed);
|
|
|
|
net_buf_add(frag, pkt->frags->len - compressed);
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 14:37:30 +03:00
|
|
|
/* Delete uncompressed(original) header fragment */
|
2017-04-05 08:37:44 +02:00
|
|
|
net_pkt_frag_del(pkt, NULL, pkt->frags);
|
2016-10-05 14:37:30 +03:00
|
|
|
|
|
|
|
/* Insert compressed header fragment */
|
2017-04-05 08:37:44 +02:00
|
|
|
net_pkt_frag_insert(pkt, frag);
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
/* Compact the fragments, so that gaps will be filled */
|
2017-04-05 08:37:44 +02:00
|
|
|
net_pkt_compact(pkt);
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-07-11 11:21:57 +03:00
|
|
|
if (fragment) {
|
2017-04-05 08:37:44 +02:00
|
|
|
return fragment(pkt, compressed - offset);
|
2016-07-11 11:21:57 +03:00
|
|
|
}
|
|
|
|
|
2016-07-07 18:14:08 +03:00
|
|
|
return true;
|
2016-06-23 16:06:24 +03:00
|
|
|
}
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
/* Helper to uncompress Traffic class and Flow label */
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t uncompress_tfl(struct net_pkt *pkt,
|
2017-08-08 14:41:23 +03:00
|
|
|
struct net_ipv6_hdr *ipv6,
|
|
|
|
u8_t offset)
|
2016-06-23 16:06:24 +03:00
|
|
|
{
|
2017-04-21 09:27:50 -05:00
|
|
|
u8_t tcl;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
/* Uncompress tcl and flow label */
|
2016-07-08 17:20:38 +03:00
|
|
|
switch (CIPHC[0] & NET_6LO_IPHC_TF_11) {
|
|
|
|
case NET_6LO_IPHC_TF_00:
|
2016-06-23 16:06:24 +03:00
|
|
|
NET_DBG("ECN + DSCP + 4-bit Pad + Flow Label");
|
|
|
|
|
|
|
|
tcl = CIPHC[offset++];
|
|
|
|
tcl = (tcl >> 6) | (tcl << 2);
|
|
|
|
|
|
|
|
ipv6->vtc |= ((tcl & 0xF0) >> 4);
|
|
|
|
ipv6->tcflow = ((tcl & 0x0F) << 4) | (CIPHC[offset++] & 0x0F);
|
|
|
|
|
|
|
|
memcpy(&ipv6->flow, &CIPHC[offset], 2);
|
|
|
|
offset += 2;
|
|
|
|
break;
|
2016-07-08 17:20:38 +03:00
|
|
|
case NET_6LO_IPHC_TF_01:
|
2016-06-23 16:06:24 +03:00
|
|
|
NET_DBG("ECN + 2-bit Pad + Flow Label, DSCP is elided");
|
|
|
|
|
|
|
|
tcl = ((CIPHC[offset] & 0xF0) >> 6);
|
|
|
|
ipv6->tcflow = ((tcl & 0x0F) << 4) | (CIPHC[offset++] & 0x0F);
|
|
|
|
|
|
|
|
memcpy(&ipv6->flow, &CIPHC[offset], 2);
|
|
|
|
offset += 2;
|
|
|
|
break;
|
2016-07-08 17:20:38 +03:00
|
|
|
case NET_6LO_IPHC_TF_10:
|
2016-06-23 16:06:24 +03:00
|
|
|
NET_DBG("Flow label elided");
|
|
|
|
|
|
|
|
tcl = CIPHC[offset];
|
|
|
|
tcl = (tcl >> 6) | (tcl << 2);
|
|
|
|
|
|
|
|
ipv6->vtc |= ((tcl & 0xF0) >> 4);
|
|
|
|
ipv6->tcflow = (tcl & 0x0F) << 4;
|
|
|
|
ipv6->flow = 0;
|
|
|
|
offset++;
|
|
|
|
break;
|
2016-07-08 17:20:38 +03:00
|
|
|
case NET_6LO_IPHC_TF_11:
|
2016-06-23 16:06:24 +03:00
|
|
|
NET_DBG("Tcl and Flow label elided");
|
|
|
|
|
|
|
|
ipv6->tcflow = 0;
|
|
|
|
ipv6->flow = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
return offset;
|
|
|
|
}
|
2016-07-13 15:28:30 +02:00
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
/* Helper to uncompress Hoplimit */
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t uncompress_hoplimit(struct net_pkt *pkt,
|
2017-08-08 14:41:23 +03:00
|
|
|
struct net_ipv6_hdr *ipv6,
|
|
|
|
u8_t offset)
|
2016-10-04 11:25:51 +03:00
|
|
|
{
|
2016-07-08 17:20:38 +03:00
|
|
|
switch (CIPHC[0] & NET_6LO_IPHC_HLIM255) {
|
|
|
|
case NET_6LO_IPHC_HLIM:
|
2017-03-03 11:44:08 +02:00
|
|
|
ipv6->hop_limit = CIPHC[offset++];
|
2016-06-23 16:06:24 +03:00
|
|
|
break;
|
2016-07-08 17:20:38 +03:00
|
|
|
case NET_6LO_IPHC_HLIM1:
|
2016-06-23 16:06:24 +03:00
|
|
|
ipv6->hop_limit = 1;
|
|
|
|
break;
|
2016-07-08 17:20:38 +03:00
|
|
|
case NET_6LO_IPHC_HLIM64:
|
2016-06-23 16:06:24 +03:00
|
|
|
ipv6->hop_limit = 64;
|
|
|
|
break;
|
2016-07-08 17:20:38 +03:00
|
|
|
case NET_6LO_IPHC_HLIM255:
|
2016-06-23 16:06:24 +03:00
|
|
|
ipv6->hop_limit = 255;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
return offset;
|
|
|
|
}
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
/* Helper to uncompress Source Address */
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t uncompress_sa(struct net_pkt *pkt,
|
2017-08-08 14:41:23 +03:00
|
|
|
struct net_ipv6_hdr *ipv6,
|
|
|
|
u8_t offset)
|
2016-10-04 11:25:51 +03:00
|
|
|
{
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
NET_DBG("SAC_0");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
switch (CIPHC[1] & NET_6LO_IPHC_SAM_11) {
|
|
|
|
case NET_6LO_IPHC_SAM_00:
|
|
|
|
NET_DBG("SAM_00 full src addr inlined");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
memcpy(ipv6->src.s6_addr, &CIPHC[offset], 16);
|
|
|
|
offset += 16;
|
|
|
|
break;
|
|
|
|
case NET_6LO_IPHC_SAM_01:
|
|
|
|
NET_DBG("SAM_01 last 64 bits are inlined");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
ipv6->src.s6_addr[0] = 0xFE;
|
|
|
|
ipv6->src.s6_addr[1] = 0x80;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
memcpy(&ipv6->src.s6_addr[8], &CIPHC[offset], 8);
|
|
|
|
offset += 8;
|
|
|
|
break;
|
|
|
|
case NET_6LO_IPHC_SAM_10:
|
|
|
|
NET_DBG("SAM_10 src addr 16 bit compressed");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
ipv6->src.s6_addr[0] = 0xFE;
|
|
|
|
ipv6->src.s6_addr[1] = 0x80;
|
|
|
|
ipv6->src.s6_addr[11] = 0xFF;
|
|
|
|
ipv6->src.s6_addr[12] = 0xFE;
|
|
|
|
|
|
|
|
memcpy(&ipv6->src.s6_addr[14], &CIPHC[offset], 2);
|
|
|
|
offset += 2;
|
|
|
|
break;
|
|
|
|
case NET_6LO_IPHC_SAM_11:
|
|
|
|
NET_DBG("SAM_11 generate src addr from ll");
|
|
|
|
|
2018-09-11 09:16:03 +02:00
|
|
|
net_ipv6_addr_create_iid(&ipv6->src, net_pkt_lladdr_src(pkt));
|
2016-10-05 11:43:00 +03:00
|
|
|
break;
|
2016-06-23 16:06:24 +03:00
|
|
|
}
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
return offset;
|
|
|
|
}
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
#if defined(CONFIG_NET_6LO_CONTEXT)
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t uncompress_sa_ctx(struct net_pkt *pkt,
|
2017-08-08 14:41:23 +03:00
|
|
|
struct net_ipv6_hdr *ipv6,
|
|
|
|
u8_t offset,
|
|
|
|
struct net_6lo_context *ctx)
|
2016-10-04 11:25:51 +03:00
|
|
|
{
|
2016-10-05 11:43:00 +03:00
|
|
|
switch (CIPHC[1] & NET_6LO_IPHC_SAM_11) {
|
|
|
|
case NET_6LO_IPHC_SAM_01:
|
|
|
|
NET_DBG("SAM_01 last 64 bits are inlined");
|
|
|
|
|
|
|
|
/* First 8 bytes are from context */
|
|
|
|
memcpy(&ipv6->src.s6_addr[0], &ctx->prefix.s6_addr[0], 8);
|
|
|
|
|
2017-03-03 11:47:10 +02:00
|
|
|
/* And the rest are carried in-line*/
|
2016-10-05 11:43:00 +03:00
|
|
|
memcpy(&ipv6->src.s6_addr[8], &CIPHC[offset], 8);
|
|
|
|
offset += 8;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case NET_6LO_IPHC_SAM_10:
|
|
|
|
NET_DBG("SAM_10 src addr 16 bit compressed");
|
|
|
|
|
|
|
|
/* First 8 bytes are from context */
|
|
|
|
memcpy(&ipv6->src.s6_addr[0], &ctx->prefix.s6_addr[0], 8);
|
|
|
|
|
|
|
|
ipv6->src.s6_addr[11] = 0xFF;
|
|
|
|
ipv6->src.s6_addr[12] = 0xFE;
|
|
|
|
|
2017-03-03 11:47:10 +02:00
|
|
|
/* And the rest are carried in-line */
|
2016-10-05 11:43:00 +03:00
|
|
|
memcpy(&ipv6->src.s6_addr[14], &CIPHC[offset], 2);
|
|
|
|
offset += 2;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case NET_6LO_IPHC_SAM_11:
|
|
|
|
NET_DBG("SAM_11 generate src addr from ll");
|
|
|
|
/* RFC 6282, 3.1.1. If SAC = 1 and SAM = 11
|
|
|
|
* Derive addr using context information and
|
|
|
|
* the encapsulating header.
|
|
|
|
* (e.g., 802.15.4 or IPv6 source address).
|
|
|
|
*/
|
2018-09-11 09:16:03 +02:00
|
|
|
net_ipv6_addr_create_iid(&ipv6->src, net_pkt_lladdr_src(pkt));
|
2016-10-05 11:43:00 +03:00
|
|
|
|
|
|
|
/* net_ipv6_addr_create_iid will copy first 8 bytes
|
|
|
|
* as link local prefix.
|
|
|
|
* Overwrite first 8 bytes from context prefix here.
|
|
|
|
*/
|
|
|
|
memcpy(&ipv6->src.s6_addr[0], &ctx->prefix.s6_addr[0], 8);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Helpers to uncompress Destination Address */
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t uncompress_da_mcast(struct net_pkt *pkt,
|
2017-08-08 14:41:23 +03:00
|
|
|
struct net_ipv6_hdr *ipv6,
|
|
|
|
u8_t offset)
|
2016-10-05 11:43:00 +03:00
|
|
|
{
|
|
|
|
NET_DBG("Dst is multicast");
|
|
|
|
|
|
|
|
if (CIPHC[1] & NET_6LO_IPHC_DAC_1) {
|
2017-01-26 16:12:23 +01:00
|
|
|
NET_WARN("Unsupported DAM options");
|
2016-10-05 11:43:00 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-01-26 10:27:39 +02:00
|
|
|
/* If M=1 and DAC=0:
|
|
|
|
* 00: 128 bits, The full address is carried in-line.
|
|
|
|
* 01: 48 bits, The address takes the form ffXX::00XX:XXXX:XXXX.
|
|
|
|
* 10: 32 bits, The address takes the form ffXX::00XX:XXXX.
|
|
|
|
* 11: 8 bits, The address takes the form ff02::00XX.
|
|
|
|
*/
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
switch (CIPHC[1] & NET_6LO_IPHC_DAM_11) {
|
|
|
|
case NET_6LO_IPHC_DAM_00:
|
|
|
|
NET_DBG("DAM_00 full dst addr inlined");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
memcpy(&ipv6->dst.s6_addr[0], &CIPHC[offset], 16);
|
|
|
|
offset += 16;
|
|
|
|
break;
|
|
|
|
case NET_6LO_IPHC_DAM_01:
|
|
|
|
NET_DBG("DAM_01 2nd byte and last five bytes");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
ipv6->dst.s6_addr[0] = 0xFF;
|
|
|
|
ipv6->dst.s6_addr[1] = CIPHC[offset++];
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
memcpy(&ipv6->dst.s6_addr[11], &CIPHC[offset], 5);
|
|
|
|
offset += 5;
|
|
|
|
break;
|
|
|
|
case NET_6LO_IPHC_DAM_10:
|
|
|
|
NET_DBG("DAM_10 2nd byte and last three bytes");
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
ipv6->dst.s6_addr[0] = 0xFF;
|
|
|
|
ipv6->dst.s6_addr[1] = CIPHC[offset++];
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
memcpy(&ipv6->dst.s6_addr[13], &CIPHC[offset], 3);
|
|
|
|
offset += 3;
|
|
|
|
break;
|
|
|
|
case NET_6LO_IPHC_DAM_11:
|
|
|
|
NET_DBG("DAM_11 8 bit compressed");
|
|
|
|
|
|
|
|
ipv6->dst.s6_addr[0] = 0xFF;
|
|
|
|
ipv6->dst.s6_addr[1] = 0x02;
|
|
|
|
ipv6->dst.s6_addr[15] = CIPHC[offset++];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Helper to uncompress Destination Address */
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t uncompress_da(struct net_pkt *pkt,
|
2017-08-08 14:41:23 +03:00
|
|
|
struct net_ipv6_hdr *ipv6,
|
|
|
|
u8_t offset)
|
2016-10-05 11:43:00 +03:00
|
|
|
{
|
2017-06-05 15:58:16 +03:00
|
|
|
NET_DBG("DAC_0");
|
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
if (CIPHC[1] & NET_6LO_IPHC_M_1) {
|
2017-04-05 08:37:44 +02:00
|
|
|
return uncompress_da_mcast(pkt, ipv6, offset);
|
2016-10-05 11:43:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (CIPHC[1] & NET_6LO_IPHC_DAM_11) {
|
|
|
|
case NET_6LO_IPHC_DAM_00:
|
|
|
|
NET_DBG("DAM_00 full dst addr inlined");
|
|
|
|
|
|
|
|
memcpy(&ipv6->dst.s6_addr[0], &CIPHC[offset], 16);
|
|
|
|
offset += 16;
|
|
|
|
break;
|
|
|
|
case NET_6LO_IPHC_DAM_01:
|
|
|
|
NET_DBG("DAM_01 last 64 bits are inlined");
|
|
|
|
|
|
|
|
ipv6->dst.s6_addr[0] = 0xFE;
|
|
|
|
ipv6->dst.s6_addr[1] = 0x80;
|
|
|
|
|
|
|
|
memcpy(&ipv6->dst.s6_addr[8], &CIPHC[offset], 8);
|
|
|
|
offset += 8;
|
|
|
|
break;
|
|
|
|
case NET_6LO_IPHC_DAM_10:
|
|
|
|
NET_DBG("DAM_10 dst addr 16 bit compressed");
|
|
|
|
|
|
|
|
ipv6->dst.s6_addr[0] = 0xFE;
|
|
|
|
ipv6->dst.s6_addr[1] = 0x80;
|
|
|
|
ipv6->dst.s6_addr[11] = 0xFF;
|
|
|
|
ipv6->dst.s6_addr[12] = 0xFE;
|
|
|
|
|
|
|
|
memcpy(&ipv6->dst.s6_addr[14], &CIPHC[offset], 2);
|
|
|
|
offset += 2;
|
|
|
|
break;
|
|
|
|
case NET_6LO_IPHC_DAM_11:
|
|
|
|
NET_DBG("DAM_11 generate dst addr from ll");
|
|
|
|
|
2018-09-11 09:16:03 +02:00
|
|
|
net_ipv6_addr_create_iid(&ipv6->dst, net_pkt_lladdr_dst(pkt));
|
2016-10-05 11:43:00 +03:00
|
|
|
break;
|
2016-06-23 16:06:24 +03:00
|
|
|
}
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
return offset;
|
|
|
|
}
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
#if defined(CONFIG_NET_6LO_CONTEXT)
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t uncompress_da_ctx(struct net_pkt *pkt,
|
2017-08-08 14:41:23 +03:00
|
|
|
struct net_ipv6_hdr *ipv6,
|
|
|
|
u8_t offset,
|
|
|
|
struct net_6lo_context *ctx)
|
2016-10-05 11:43:00 +03:00
|
|
|
{
|
2017-06-05 15:58:16 +03:00
|
|
|
NET_DBG("DAC_1");
|
2016-10-05 11:43:00 +03:00
|
|
|
|
|
|
|
if (CIPHC[1] & NET_6LO_IPHC_M_1) {
|
2017-04-05 08:37:44 +02:00
|
|
|
return uncompress_da_mcast(pkt, ipv6, offset);
|
2016-10-05 11:43:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (CIPHC[1] & NET_6LO_IPHC_DAM_11) {
|
|
|
|
case NET_6LO_IPHC_DAM_01:
|
|
|
|
NET_DBG("DAM_01 last 64 bits are inlined");
|
|
|
|
|
|
|
|
/* First 8 bytes are from context */
|
|
|
|
memcpy(&ipv6->dst.s6_addr[0], &ctx->prefix.s6_addr[0], 8);
|
|
|
|
|
|
|
|
/* And the rest are carried in-line */
|
|
|
|
memcpy(&ipv6->dst.s6_addr[8], &CIPHC[offset], 8);
|
|
|
|
offset += 8;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case NET_6LO_IPHC_DAM_10:
|
|
|
|
NET_DBG("DAM_10 src addr 16 bit compressed");
|
|
|
|
|
|
|
|
/* First 8 bytes are from context */
|
|
|
|
memcpy(&ipv6->dst.s6_addr[0], &ctx->prefix.s6_addr[0], 8);
|
|
|
|
|
|
|
|
ipv6->dst.s6_addr[11] = 0xFF;
|
|
|
|
ipv6->dst.s6_addr[12] = 0xFE;
|
|
|
|
|
|
|
|
/* And the restare carried in-line */
|
|
|
|
memcpy(&ipv6->dst.s6_addr[14], &CIPHC[offset], 2);
|
|
|
|
offset += 2;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case NET_6LO_IPHC_DAM_11:
|
|
|
|
NET_DBG("DAM_11 generate src addr from ll");
|
|
|
|
|
|
|
|
/* RFC 6282, 3.1.1. If SAC = 1 and SAM = 11
|
|
|
|
* Derive addr using context information and
|
|
|
|
* the encapsulating header.
|
|
|
|
* (e.g., 802.15.4 or IPv6 source address).
|
|
|
|
*/
|
2018-09-11 09:16:03 +02:00
|
|
|
net_ipv6_addr_create_iid(&ipv6->dst, net_pkt_lladdr_dst(pkt));
|
2016-10-05 11:43:00 +03:00
|
|
|
|
|
|
|
/* net_ipv6_addr_create_iid will copy first 8 bytes
|
|
|
|
* as link local prefix.
|
|
|
|
* Overwrite first 8 bytes from context prefix here.
|
|
|
|
*/
|
|
|
|
memcpy(&ipv6->dst.s6_addr[0], &ctx->prefix.s6_addr[0], 8);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
/* Helper to uncompress NH UDP */
|
2017-04-21 09:27:50 -05:00
|
|
|
static inline u8_t uncompress_nh_udp(struct net_pkt *pkt,
|
2017-08-08 14:41:23 +03:00
|
|
|
struct net_udp_hdr *udp,
|
|
|
|
u8_t offset)
|
2016-10-04 11:25:51 +03:00
|
|
|
{
|
|
|
|
/* Port uncompression
|
|
|
|
* 00: All 16 bits for src and dst are inlined
|
|
|
|
* 01: src, 16 bits are lined, dst(0xf0) 8 bits are inlined
|
|
|
|
* 10: dst, 16 bits are lined, src(0xf0) 8 bits are inlined
|
|
|
|
* 11: src, dst (0xf0b) 4 bits are inlined
|
|
|
|
*/
|
2016-06-23 16:06:24 +03:00
|
|
|
|
|
|
|
/* UDP header uncompression */
|
2016-07-08 17:20:38 +03:00
|
|
|
switch (CIPHC[offset++] & NET_6LO_NHC_UDP_PORT_11) {
|
|
|
|
case NET_6LO_NHC_UDP_PORT_00:
|
2016-06-23 16:06:24 +03:00
|
|
|
NET_DBG("src and dst ports are inlined");
|
|
|
|
|
|
|
|
memcpy(&udp->src_port, &CIPHC[offset], 2);
|
|
|
|
offset += 2;
|
|
|
|
|
|
|
|
memcpy(&udp->dst_port, &CIPHC[offset], 2);
|
|
|
|
offset += 2;
|
|
|
|
break;
|
2016-07-08 17:20:38 +03:00
|
|
|
case NET_6LO_NHC_UDP_PORT_01:
|
2016-06-23 16:06:24 +03:00
|
|
|
NET_DBG("src full, dst 8 bits inlined");
|
|
|
|
|
|
|
|
memcpy(&udp->src_port, &CIPHC[offset], 2);
|
|
|
|
offset += 2;
|
|
|
|
|
2017-04-21 09:27:50 -05:00
|
|
|
udp->dst_port = htons(((u16_t)NET_6LO_NHC_UDP_8_BIT_PORT
|
2016-07-08 17:20:38 +03:00
|
|
|
<< 8) | CIPHC[offset]);
|
2016-06-23 16:06:24 +03:00
|
|
|
offset++;
|
|
|
|
break;
|
2016-07-08 17:20:38 +03:00
|
|
|
case NET_6LO_NHC_UDP_PORT_10:
|
2016-06-23 16:06:24 +03:00
|
|
|
NET_DBG("src 8 bits, dst full inlined");
|
|
|
|
|
2017-04-21 09:27:50 -05:00
|
|
|
udp->src_port = htons(((u16_t)NET_6LO_NHC_UDP_8_BIT_PORT
|
2016-07-08 17:20:38 +03:00
|
|
|
<< 8) | CIPHC[offset]);
|
2016-06-23 16:06:24 +03:00
|
|
|
offset++;
|
|
|
|
|
|
|
|
memcpy(&udp->dst_port, &CIPHC[offset], 2);
|
|
|
|
offset += 2;
|
|
|
|
break;
|
2016-07-08 17:20:38 +03:00
|
|
|
case NET_6LO_NHC_UDP_PORT_11:
|
2016-06-23 16:06:24 +03:00
|
|
|
NET_DBG("src and dst 4 bits inlined");
|
|
|
|
|
2016-07-08 17:20:38 +03:00
|
|
|
udp->src_port = htons((NET_6LO_NHC_UDP_4_BIT_PORT << 4) |
|
2016-06-23 16:06:24 +03:00
|
|
|
(CIPHC[offset] >> 4));
|
|
|
|
|
2016-07-08 17:20:38 +03:00
|
|
|
udp->dst_port = htons((NET_6LO_NHC_UDP_4_BIT_PORT << 4) |
|
2016-06-23 16:06:24 +03:00
|
|
|
(CIPHC[offset] & 0x0F));
|
|
|
|
offset++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2016-10-05 11:43:00 +03:00
|
|
|
#if defined(CONFIG_NET_6LO_CONTEXT)
|
|
|
|
/* Helper function to uncompress src and dst contexts */
|
2017-06-05 15:58:16 +03:00
|
|
|
static inline void uncompress_cid(struct net_pkt *pkt,
|
2016-10-05 11:43:00 +03:00
|
|
|
struct net_6lo_context **src,
|
|
|
|
struct net_6lo_context **dst)
|
|
|
|
{
|
2017-04-21 09:27:50 -05:00
|
|
|
u8_t cid;
|
2016-10-05 11:43:00 +03:00
|
|
|
|
|
|
|
/* Extract source and destination Context Index,
|
2017-03-03 11:49:18 +02:00
|
|
|
* Either src or dest address is context based or both.
|
2016-10-05 11:43:00 +03:00
|
|
|
*/
|
|
|
|
cid = (CIPHC[2] >> 4) & 0x0F;
|
2017-04-05 08:37:44 +02:00
|
|
|
*src = get_6lo_context_by_cid(net_pkt_iface(pkt), cid);
|
2017-03-03 11:49:18 +02:00
|
|
|
if (!(*src)) {
|
|
|
|
NET_DBG("Unknown src cid %d", cid);
|
2016-10-05 11:43:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
cid = CIPHC[2] & 0x0F;
|
2017-04-05 08:37:44 +02:00
|
|
|
*dst = get_6lo_context_by_cid(net_pkt_iface(pkt), cid);
|
2017-03-03 11:49:18 +02:00
|
|
|
if (!(*dst)) {
|
|
|
|
NET_DBG("Unknown dst cid %d", cid);
|
2016-10-05 11:43:00 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-04-05 08:37:44 +02:00
|
|
|
static inline bool uncompress_IPHC_header(struct net_pkt *pkt)
|
2016-10-04 11:25:51 +03:00
|
|
|
{
|
|
|
|
struct net_udp_hdr *udp = NULL;
|
2018-11-29 11:23:03 -08:00
|
|
|
u8_t offset = 2U;
|
|
|
|
u8_t chksum = 0U;
|
2016-10-04 11:25:51 +03:00
|
|
|
struct net_ipv6_hdr *ipv6;
|
|
|
|
struct net_buf *frag;
|
2017-04-21 09:27:50 -05:00
|
|
|
u16_t len;
|
2016-10-05 11:43:00 +03:00
|
|
|
#if defined(CONFIG_NET_6LO_CONTEXT)
|
|
|
|
struct net_6lo_context *src = NULL;
|
|
|
|
struct net_6lo_context *dst = NULL;
|
|
|
|
#endif
|
2016-10-04 11:25:51 +03:00
|
|
|
|
|
|
|
if (CIPHC[1] & NET_6LO_IPHC_CID_1) {
|
2016-10-05 11:43:00 +03:00
|
|
|
#if defined(CONFIG_NET_6LO_CONTEXT)
|
2017-06-05 15:58:16 +03:00
|
|
|
uncompress_cid(pkt, &src, &dst);
|
2016-10-05 11:43:00 +03:00
|
|
|
offset++;
|
|
|
|
#else
|
2017-01-26 16:12:23 +01:00
|
|
|
NET_WARN("Context based uncompression not enabled");
|
2016-10-04 11:25:51 +03:00
|
|
|
return false;
|
2016-10-05 11:43:00 +03:00
|
|
|
#endif
|
2016-11-03 15:39:58 +01:00
|
|
|
}
|
2016-10-04 11:25:51 +03:00
|
|
|
|
2017-04-05 08:37:44 +02:00
|
|
|
frag = net_pkt_get_frag(pkt, NET_6LO_RX_PKT_TIMEOUT);
|
2017-02-21 10:34:39 +02:00
|
|
|
if (!frag) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-10-04 11:25:51 +03:00
|
|
|
|
|
|
|
ipv6 = (struct net_ipv6_hdr *)(frag->data);
|
|
|
|
|
|
|
|
/* Version is always 6 */
|
|
|
|
ipv6->vtc = 0x60;
|
2017-04-05 08:37:44 +02:00
|
|
|
net_pkt_set_ip_hdr_len(pkt, NET_IPV6H_LEN);
|
2016-10-04 11:25:51 +03:00
|
|
|
|
|
|
|
/* Uncompress Traffic class and Flow label */
|
2017-04-05 08:37:44 +02:00
|
|
|
offset = uncompress_tfl(pkt, ipv6, offset);
|
2016-10-04 11:25:51 +03:00
|
|
|
|
|
|
|
if (!(CIPHC[0] & NET_6LO_IPHC_NH_1)) {
|
|
|
|
ipv6->nexthdr = CIPHC[offset];
|
|
|
|
offset++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Uncompress Hoplimit */
|
2017-04-05 08:37:44 +02:00
|
|
|
offset = uncompress_hoplimit(pkt, ipv6, offset);
|
2016-10-04 11:25:51 +03:00
|
|
|
|
|
|
|
/* First set to zero and copy relevant bits */
|
2018-09-11 19:09:03 -07:00
|
|
|
(void)memset(&ipv6->src.s6_addr[0], 0, 16);
|
|
|
|
(void)memset(&ipv6->dst.s6_addr[0], 0, 16);
|
2016-10-04 11:25:51 +03:00
|
|
|
|
|
|
|
/* Uncompress Source Address */
|
2017-06-05 15:58:16 +03:00
|
|
|
if (CIPHC[1] & NET_6LO_IPHC_SAC_1) {
|
2017-10-19 12:24:44 +03:00
|
|
|
NET_DBG("SAC_1");
|
|
|
|
|
|
|
|
if ((CIPHC[1] & NET_6LO_IPHC_SAM_11) == NET_6LO_IPHC_SAM_00) {
|
|
|
|
NET_DBG("SAM_00 unspecified address");
|
|
|
|
} else {
|
|
|
|
#if defined(CONFIG_NET_6LO_CONTEXT)
|
|
|
|
if (!src) {
|
|
|
|
NET_ERR("Src context doesn't exists");
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
offset = uncompress_sa_ctx(pkt, ipv6, offset, src);
|
|
|
|
#else
|
|
|
|
NET_WARN("Context based uncompression not enabled");
|
2017-06-05 15:58:16 +03:00
|
|
|
goto fail;
|
2017-10-19 12:24:44 +03:00
|
|
|
#endif
|
2017-06-05 15:58:16 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
offset = uncompress_sa(pkt, ipv6, offset);
|
2016-10-04 11:25:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Uncompress Destination Address */
|
2016-10-05 11:43:00 +03:00
|
|
|
#if defined(CONFIG_NET_6LO_CONTEXT)
|
2017-06-05 15:58:16 +03:00
|
|
|
if (CIPHC[1] & NET_6LO_IPHC_DAC_1) {
|
|
|
|
if (CIPHC[1] & NET_6LO_IPHC_M_1) {
|
|
|
|
/* TODO: DAM00 Unicast-Prefix-based IPv6 Multicast
|
|
|
|
* Addresses. DAM_01, DAM_10 and DAM_11 are reserved.
|
|
|
|
*/
|
|
|
|
NET_ERR("DAC_1 and M_1 is not supported");
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!dst) {
|
|
|
|
NET_ERR("DAC is set but dst context doesn't exists");
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
offset = uncompress_da_ctx(pkt, ipv6, offset, dst);
|
|
|
|
} else {
|
|
|
|
offset = uncompress_da(pkt, ipv6, offset);
|
2016-10-05 11:43:00 +03:00
|
|
|
}
|
|
|
|
#else
|
2017-04-05 08:37:44 +02:00
|
|
|
offset = uncompress_da(pkt, ipv6, offset);
|
2016-10-05 11:43:00 +03:00
|
|
|
#endif
|
2016-10-04 11:25:51 +03:00
|
|
|
|
|
|
|
net_buf_add(frag, NET_IPV6H_LEN);
|
|
|
|
|
|
|
|
if (!(CIPHC[0] & NET_6LO_IPHC_NH_1)) {
|
|
|
|
NET_DBG("No following compressed header");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((CIPHC[offset] & 0xF0) != NET_6LO_NHC_UDP_BARE) {
|
2017-03-03 11:47:10 +02:00
|
|
|
/* Unsupported NH,
|
|
|
|
* Supports only UDP header (next header) compression.
|
|
|
|
*/
|
2017-01-26 16:12:23 +01:00
|
|
|
NET_ERR("Unsupported next header");
|
2016-10-04 11:25:51 +03:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Uncompress UDP header */
|
|
|
|
ipv6->nexthdr = IPPROTO_UDP;
|
|
|
|
|
|
|
|
udp = (struct net_udp_hdr *)(frag->data + NET_IPV6H_LEN);
|
|
|
|
chksum = CIPHC[offset] & NET_6LO_NHC_UDP_CHKSUM_1;
|
2017-04-05 08:37:44 +02:00
|
|
|
offset = uncompress_nh_udp(pkt, udp, offset);
|
2016-10-04 11:25:51 +03:00
|
|
|
|
2016-10-10 14:50:39 +03:00
|
|
|
if (!chksum) {
|
|
|
|
memcpy(&udp->chksum, &CIPHC[offset], 2);
|
|
|
|
offset += 2;
|
2016-06-23 16:06:24 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
net_buf_add(frag, NET_UDPH_LEN);
|
|
|
|
|
|
|
|
end:
|
2017-10-18 15:36:44 +03:00
|
|
|
if (pkt->frags->len < offset) {
|
|
|
|
NET_ERR("pkt %p too short len %d vs %d", pkt,
|
|
|
|
pkt->frags->len, offset);
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2017-01-26 10:27:39 +02:00
|
|
|
/* Move the data to beginning, no need for headers now */
|
2016-07-12 15:59:07 +02:00
|
|
|
NET_DBG("Removing %u bytes of compressed hdr", offset);
|
2017-04-05 08:37:44 +02:00
|
|
|
memmove(pkt->frags->data, pkt->frags->data + offset,
|
|
|
|
pkt->frags->len - offset);
|
|
|
|
pkt->frags->len -= offset;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-07-07 14:33:11 +02:00
|
|
|
/* Copying ll part, if any */
|
2017-04-05 08:37:44 +02:00
|
|
|
if (net_pkt_ll_reserve(pkt)) {
|
|
|
|
memcpy(frag->data - net_pkt_ll_reserve(pkt),
|
|
|
|
net_pkt_ll(pkt), net_pkt_ll_reserve(pkt));
|
2016-07-07 14:33:11 +02:00
|
|
|
}
|
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
/* Insert the fragment (this one holds uncompressed headers) */
|
2017-04-05 08:37:44 +02:00
|
|
|
net_pkt_frag_insert(pkt, frag);
|
|
|
|
net_pkt_compact(pkt);
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2016-10-04 11:25:51 +03:00
|
|
|
/* Set IPv6 header and UDP (if next header is) length */
|
2017-04-05 08:37:44 +02:00
|
|
|
len = net_pkt_get_len(pkt) - NET_IPV6H_LEN;
|
2018-08-13 09:57:00 +03:00
|
|
|
ipv6->len = htons(len);
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2017-01-18 13:23:03 +02:00
|
|
|
if (ipv6->nexthdr == IPPROTO_UDP && udp) {
|
2016-07-08 11:51:20 +03:00
|
|
|
udp->len = htons(len);
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2017-01-18 13:23:03 +02:00
|
|
|
if (chksum) {
|
2017-04-05 08:37:44 +02:00
|
|
|
udp->chksum = ~net_calc_chksum_udp(pkt);
|
2017-01-18 13:23:03 +02:00
|
|
|
}
|
2016-10-10 14:50:39 +03:00
|
|
|
}
|
|
|
|
|
2016-07-07 18:14:08 +03:00
|
|
|
return true;
|
2016-06-23 16:06:24 +03:00
|
|
|
|
|
|
|
fail:
|
2017-04-05 08:37:44 +02:00
|
|
|
net_pkt_frag_unref(frag);
|
2016-07-07 18:14:08 +03:00
|
|
|
return false;
|
2016-06-23 16:06:24 +03:00
|
|
|
}
|
|
|
|
|
2016-07-11 11:03:30 +03:00
|
|
|
/* Adds IPv6 dispatch as first byte and adjust fragments */
|
2017-04-05 08:37:44 +02:00
|
|
|
static inline bool compress_ipv6_header(struct net_pkt *pkt,
|
2016-07-11 11:21:57 +03:00
|
|
|
fragment_handler_t fragment)
|
2016-06-23 16:06:24 +03:00
|
|
|
{
|
2016-07-11 11:03:30 +03:00
|
|
|
struct net_buf *frag;
|
|
|
|
|
2017-04-05 08:37:44 +02:00
|
|
|
frag = net_pkt_get_frag(pkt, K_FOREVER);
|
2017-08-17 23:12:58 -03:00
|
|
|
if (!frag) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-07-11 11:03:30 +03:00
|
|
|
|
2016-07-08 17:20:38 +03:00
|
|
|
frag->data[0] = NET_6LO_DISPATCH_IPV6;
|
2016-07-11 11:03:30 +03:00
|
|
|
net_buf_add(frag, 1);
|
|
|
|
|
2017-04-05 08:37:44 +02:00
|
|
|
net_pkt_frag_insert(pkt, frag);
|
2016-07-11 11:03:30 +03:00
|
|
|
|
2017-01-26 10:27:39 +02:00
|
|
|
/* Compact the fragments, so that gaps will be filled */
|
2017-04-05 08:37:44 +02:00
|
|
|
net_pkt_compact(pkt);
|
2016-07-11 11:03:30 +03:00
|
|
|
|
2016-07-11 11:21:57 +03:00
|
|
|
if (fragment) {
|
2017-04-05 08:37:44 +02:00
|
|
|
return fragment(pkt, -1);
|
2016-07-11 11:21:57 +03:00
|
|
|
}
|
|
|
|
|
2016-07-11 11:03:30 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-04-05 08:37:44 +02:00
|
|
|
static inline bool uncompress_ipv6_header(struct net_pkt *pkt)
|
2016-07-11 11:03:30 +03:00
|
|
|
{
|
2017-04-05 08:37:44 +02:00
|
|
|
struct net_buf *frag = pkt->frags;
|
2016-07-11 11:03:30 +03:00
|
|
|
|
|
|
|
/* Pull off IPv6 dispatch header and adjust data and length */
|
|
|
|
memmove(frag->data, frag->data + 1, frag->len - 1);
|
|
|
|
frag->len -= 1;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-04-05 08:37:44 +02:00
|
|
|
bool net_6lo_compress(struct net_pkt *pkt, bool iphc,
|
2016-07-11 11:21:57 +03:00
|
|
|
fragment_handler_t fragment)
|
2016-07-11 11:03:30 +03:00
|
|
|
{
|
|
|
|
if (iphc) {
|
2017-04-05 08:37:44 +02:00
|
|
|
return compress_IPHC_header(pkt, fragment);
|
2016-07-11 11:03:30 +03:00
|
|
|
} else {
|
2017-04-05 08:37:44 +02:00
|
|
|
return compress_ipv6_header(pkt, fragment);
|
2016-07-11 11:03:30 +03:00
|
|
|
}
|
2016-06-23 16:06:24 +03:00
|
|
|
}
|
|
|
|
|
2017-04-05 08:37:44 +02:00
|
|
|
bool net_6lo_uncompress(struct net_pkt *pkt)
|
2016-06-23 16:06:24 +03:00
|
|
|
{
|
2017-04-05 08:37:44 +02:00
|
|
|
NET_ASSERT(pkt && pkt->frags);
|
2016-06-23 16:06:24 +03:00
|
|
|
|
2017-04-05 08:37:44 +02:00
|
|
|
if ((pkt->frags->data[0] & NET_6LO_DISPATCH_IPHC) ==
|
2016-07-08 17:20:38 +03:00
|
|
|
NET_6LO_DISPATCH_IPHC) {
|
2017-01-26 10:27:39 +02:00
|
|
|
/* Uncompress IPHC header */
|
2017-04-05 08:37:44 +02:00
|
|
|
return uncompress_IPHC_header(pkt);
|
2016-07-11 11:03:30 +03:00
|
|
|
|
2017-04-05 08:37:44 +02:00
|
|
|
} else if ((pkt->frags->data[0] & NET_6LO_DISPATCH_IPV6) ==
|
2016-07-08 17:20:38 +03:00
|
|
|
NET_6LO_DISPATCH_IPV6) {
|
2017-01-26 10:27:39 +02:00
|
|
|
/* Uncompress IPv6 header, it has only IPv6 dispatch in the
|
2016-07-11 11:03:30 +03:00
|
|
|
* beginning */
|
2017-04-05 08:37:44 +02:00
|
|
|
return uncompress_ipv6_header(pkt);
|
2016-06-23 16:06:24 +03:00
|
|
|
}
|
|
|
|
|
2017-04-20 15:36:35 +03:00
|
|
|
NET_DBG("pkt %p is not compressed", pkt);
|
2016-07-07 14:35:29 +02:00
|
|
|
|
|
|
|
return true;
|
2016-06-23 16:06:24 +03:00
|
|
|
}
|