Merge branch 'master' of git://github.com/contiki-os/contiki into ds6_period_configurable

This commit is contained in:
Jens Dede 2014-04-18 13:33:01 +02:00
commit 446208dc1c
107 changed files with 8338 additions and 1318 deletions

View file

@ -0,0 +1,114 @@
README file for Contiki's IPv6 multicast core
Author: George Oikonomou
What does it do
===============
These files, alongside some core modifications, add support for IPv6 multicast
to contiki's uIPv6 engine.
Currently, two modes are supported:
* 'Stateless Multicast RPL Forwarding' (SMRF)
RPL in MOP 3 handles group management as per the RPL docs,
SMRF is a lightweight engine which handles datagram forwarding.
SMRF is documented here:
http://dx.doi.org/10.1007/s11277-013-1250-5
and here:
http://dx.doi.org/10.1109/PerComW.2012.6197494
* 'Multicast Forwarding with Trickle' according to the algorithm described
in the internet draft:
http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast
The version of this draft that's currently implementated is documented
in `roll-tm.h`
More engines can (and hopefully will) be added in the future. The first
addition is most likely going to be an updated implementation of MPL
The Big Gotcha
==============
Currently we only support traffic originating and destined inside a single 6LoWPAN
To be able to send multicast traffic from the internet to 6LoWPAN nodes or the other
way round, we need border routers or other gateway devices to be able to achieve
the following:
* Add/Remove Trickle Multicast, RPL or other HBHO headers as necessary for datagrams
entering / exiting the 6LoWPAN
* Advertise multicast group membership to the internet (e.g. with MLD)
These are currently not implemented and are in the ToDo list. Contributions welcome.
Where to Start
==============
The best place in `examples/ipv6/multicast`
There is a cooja example demonstrating basic functionality
How to Use
==========
Look in `core/net/ipv6/multicast/uip-mcast6-engines.h` for a list of supported
multicast engines.
To turn on multicast support, add this line in your `project-` or `contiki-conf.h`
#define UIP_MCAST6_CONF_ENGINE xyz
where xyz is a value from `uip-mcast6-engines.h`
To disable:
#define UIP_MCAST6_CONF_ENGINE 0
You also need to make sure the multicast code gets built. Your example's
(or platform's) Makefile should include this:
MODULES += core/net/ipv6/multicast
How to extend
=============
Let's assume you want to write an engine called foo.
The multicast API defines a multicast engine driver in a fashion similar to
the various NETSTACK layer drivers. This API defines functions for basic
multicast operations (init, in, out).
In order to extend multicast with a new engine, perform the following steps:
- Open `uip-mcast6-engines.h` and assign a unique integer code to your engine
#define UIP_MCAST6_ENGINE_FOO xyz
- Include your engine's `foo.h`
- In `foo.c`, implement:
* `init()`
* `in()`
* `out()`
* Define your driver like so:
`const struct uip_mcast6_driver foo_driver = { ... }`
- If you want to maintain stats:
* Standard multicast stats are maintained in `uip_mcast6_stats`. Don't access
this struct directly, use the macros provided in `uip-mcast6-stats.h` instead
* You can add your own stats extensions. To do so, declare your own stats
struct in your engine's module, e.g `struct foo_stats`
* When you initialise the stats module with `UIP_MCAST6_STATS_INIT`, pass
a pointer to your stats variable as the macro's argument.
An example of how to extend multicast stats, look at the ROLL TM engine
- Open `uip-mcast6.h` and add a section in the `#if` spree. This aims to
configure the uIPv6 core. More specifically, you need to:
* Specify if you want to put RPL in MOP3 by defining
`RPL_CONF_MULTICAST`: 1: MOP 3, 0: non-multicast MOP
* Define your engine details
#define UIP_MCAST6 foo_driver
#define UIP_MCAST6_STATS foo_stats
typedef struct foo_stats uip_mcast6_stats_t;
* Optionally, add a configuration check block to stop builds when the
configuration is not sane.
If you need your engine to perform operations not supported by the generic
UIP_MCAST6 API, you will have to hook those in the uip core manually. As an
example, see how the core is modified so that it can deliver ICMPv6 datagrams
to the ROLL TM engine.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,224 @@
/*
* Copyright (c) 2011, Loughborough University - Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* Header file for IPv6 multicast according to the algorithm in the
* "MCAST Forwarding Using Trickle" internet draft.
*
* The current version of the draft can always be found in
* http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast
*
* This implementation is based on the draft version stored in
* ROLL_TM_VER.
*
* In draft v2, the document was renamed to
* "Multicast Protocol for Low power and Lossy Networks (MPL)"
* Due to very significant changes between draft versions 1 and 2,
* MPL will be implemented as a separate engine and this file here
* will provide legacy support for Draft v1.
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#ifndef ROLL_TM_H_
#define ROLL_TM_H_
#include "contiki-conf.h"
#include "net/ipv6/multicast/uip-mcast6-stats.h"
#include <stdint.h>
/*---------------------------------------------------------------------------*/
/* Protocol Constants */
/*---------------------------------------------------------------------------*/
#define ROLL_TM_VER 1 /* Supported Draft Version */
#define ROLL_TM_ICMP_CODE 0 /* ICMPv6 code field */
#define ROLL_TM_IP_HOP_LIMIT 0xFF /* Hop limit for ICMP messages */
#define ROLL_TM_INFINITE_REDUNDANCY 0xFF
#define ROLL_TM_DGRAM_OUT 0
#define ROLL_TM_DGRAM_IN 1
/*
* The draft does not currently specify a default number for the trickle
* interval nor a way to derive it. Examples however hint at 100 msec.
*
* In draft terminology, we use an 'aggressive' policy (M=0) and a conservative
* one (M=1).
*
* When experimenting with the two policies on the sky platform,
* an interval of 125ms proves to be way too low: When we have traffic,
* doublings happen after the interval end and periodics fire after point T
* within the interval (and sometimes even after interval end). When traffic
* settles down, the code compensates the offsets.
*
* We consider 125, 250ms etc because they are nice divisors of 1 sec
* (quotient is power of two). For some machines (e.g sky/msp430,
* sensinode/cc243x), this is also a nice number of clock ticks
*
* After experimentation, the values of Imin leading to best performance are:
* ContikiMAC: Imin=64 (500ms)
* Null RDC: imin=16 (125ms)
*/
/* Configuration for Timer with M=0 (aggressive) */
#ifdef ROLL_TM_CONF_IMIN_0
#define ROLL_TM_IMIN_0 ROLL_TM_CONF_IMIN_0
#else
#define ROLL_TM_IMIN_0 32 /* 250 msec */
#endif
#ifdef ROLL_TM_CONF_IMAX_0
#define ROLL_TM_IMAX_0 ROLL_TM_CONF_IMAX_0
#else
#define ROLL_TM_IMAX_0 1 /* Imax = 500ms */
#endif
#ifdef ROLL_TM_CONF_K_0
#define ROLL_TM_K_0 ROLL_TM_CONF_K_0
#else
#define ROLL_TM_K_0 ROLL_TM_INFINITE_REDUNDANCY
#endif
#ifdef ROLL_TM_CONF_T_ACTIVE_0
#define ROLL_TM_T_ACTIVE_0 ROLL_TM_CONF_T_ACTIVE_0
#else
#define ROLL_TM_T_ACTIVE_0 3
#endif
#ifdef ROLL_TM_CONF_T_DWELL_0
#define ROLL_TM_T_DWELL_0 ROLL_TM_CONF_T_DWELL_0
#else
#define ROLL_TM_T_DWELL_0 11
#endif
/* Configuration for Timer with M=1 (conservative) */
#ifdef ROLL_TM_CONF_IMIN_1
#define ROLL_TM_IMIN_1 ROLL_TM_CONF_IMIN_1
#else
#define ROLL_TM_IMIN_1 64 /* 500 msec */
#endif
#ifdef ROLL_TM_CONF_IMAX_1
#define ROLL_TM_IMAX_1 ROLL_TM_CONF_IMAX_1
#else
#define ROLL_TM_IMAX_1 9 /* Imax = 256 secs */
#endif
#ifdef ROLL_TM_CONF_K_1
#define ROLL_TM_K_1 ROLL_TM_CONF_K_1
#else
#define ROLL_TM_K_1 1
#endif
#ifdef ROLL_TM_CONF_T_ACTIVE_1
#define ROLL_TM_T_ACTIVE_1 ROLL_TM_CONF_T_ACTIVE_1
#else
#define ROLL_TM_T_ACTIVE_1 3
#endif
#ifdef ROLL_TM_CONF_T_DWELL_1
#define ROLL_TM_T_DWELL_1 ROLL_TM_CONF_T_DWELL_1
#else
#define ROLL_TM_T_DWELL_1 12
#endif
/*---------------------------------------------------------------------------*/
/* Configuration */
/*---------------------------------------------------------------------------*/
/*
* Number of Sliding Windows
* In essence: How many unique sources of simultaneous multicast traffic do we
* want to support for our lowpan
* If a node is seeding two multicast streams, parametrized on different M
* values, then this seed will occupy two different sliding windows
*/
#ifdef ROLL_TM_CONF_WINS
#define ROLL_TM_WINS ROLL_TM_CONF_WINS
#else
#define ROLL_TM_WINS 2
#endif
/*---------------------------------------------------------------------------*/
/*
* Maximum Number of Buffered Multicast Messages
* This buffer is shared across all Seed IDs, therefore a new very active Seed
* may eventually occupy all slots. It would make little sense (if any) to
* define support for fewer buffered messages than seeds*2
*/
#ifdef ROLL_TM_CONF_BUFF_NUM
#define ROLL_TM_BUFF_NUM ROLL_TM_CONF_BUFF_NUM
#else
#define ROLL_TM_BUFF_NUM 6
#endif
/*---------------------------------------------------------------------------*/
/*
* Use Short Seed IDs [short: 2, long: 16 (default)]
* It can be argued that we should (and it would be easy to) support both at
* the same time but the draft doesn't list this as a MUST so we opt for
* code/ram savings
*/
#ifdef ROLL_TM_CONF_SHORT_SEEDS
#define ROLL_TM_SHORT_SEEDS ROLL_TM_CONF_SHORT_SEEDS
#else
#define ROLL_TM_SHORT_SEEDS 0
#endif
/*---------------------------------------------------------------------------*/
/*
* Destination address for our ICMPv6 advertisements. The draft gives us a
* choice between LL all-nodes or LL all-routers
*
* We use allrouters unless a conf directive chooses otherwise
*/
#ifdef ROLL_TM_CONF_DEST_ALL_NODES
#define ROLL_TM_DEST_ALL_NODES ROLL_TM_CONF_DEST_ALL_NODES
#else
#define ROLL_TM_DEST_ALL_NODES 0
#endif
/*---------------------------------------------------------------------------*/
/*
* M param for our outgoing messages
* By default, we set the M bit (conservative). Define this as 0 to clear the
* M bit in our outgoing messages (aggressive)
*/
#ifdef ROLL_TM_CONF_SET_M_BIT
#define ROLL_TM_SET_M_BIT ROLL_TM_CONF_SET_M_BIT
#else
#define ROLL_TM_SET_M_BIT 1
#endif
/*---------------------------------------------------------------------------*/
/* Stats datatype */
/*---------------------------------------------------------------------------*/
struct roll_tm_stats {
UIP_MCAST6_STATS_DATATYPE icmp_in;
UIP_MCAST6_STATS_DATATYPE icmp_out;
UIP_MCAST6_STATS_DATATYPE icmp_bad;
};
#endif /* ROLL_TM_H_ */

View file

@ -0,0 +1,211 @@
/*
* Copyright (c) 2010, Loughborough University - Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* This file implements 'Stateless Multicast RPL Forwarding' (SMRF)
*
* It will only work in RPL networks in MOP 3 "Storing with Multicast"
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#include "contiki.h"
#include "contiki-net.h"
#include "net/ipv6/multicast/uip-mcast6.h"
#include "net/ipv6/multicast/uip-mcast6-route.h"
#include "net/ipv6/multicast/uip-mcast6-stats.h"
#include "net/ipv6/multicast/smrf.h"
#include "net/rpl/rpl.h"
#include "net/netstack.h"
#include <string.h>
#define DEBUG DEBUG_NONE
#include "net/ip/uip-debug.h"
#if UIP_CONF_IPV6
/*---------------------------------------------------------------------------*/
/* Macros */
/*---------------------------------------------------------------------------*/
/* CCI */
#define SMRF_FWD_DELAY() NETSTACK_RDC.channel_check_interval()
/* Number of slots in the next 500ms */
#define SMRF_INTERVAL_COUNT ((CLOCK_SECOND >> 2) / fwd_delay)
/*---------------------------------------------------------------------------*/
/* Internal Data */
/*---------------------------------------------------------------------------*/
static struct ctimer mcast_periodic;
static uint8_t mcast_len;
static uip_buf_t mcast_buf;
static uint8_t fwd_delay;
static uint8_t fwd_spread;
/*---------------------------------------------------------------------------*/
/* uIPv6 Pointers */
/*---------------------------------------------------------------------------*/
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
/*---------------------------------------------------------------------------*/
static void
mcast_fwd(void *p)
{
memcpy(uip_buf, &mcast_buf, mcast_len);
uip_len = mcast_len;
UIP_IP_BUF->ttl--;
tcpip_output(NULL);
uip_len = 0;
}
/*---------------------------------------------------------------------------*/
static uint8_t
in()
{
rpl_dag_t *d; /* Our DODAG */
uip_ipaddr_t *parent_ipaddr; /* Our pref. parent's IPv6 address */
const uip_lladdr_t *parent_lladdr; /* Our pref. parent's LL address */
/*
* Fetch a pointer to the LL address of our preferred parent
*
* ToDo: This rpl_get_any_dag() call is a dirty replacement of the previous
* rpl_get_dag(RPL_DEFAULT_INSTANCE);
* so that things can compile with the new RPL code. This needs updated to
* read instance ID from the RPL HBHO and use the correct parent accordingly
*/
d = rpl_get_any_dag();
if(!d) {
UIP_MCAST6_STATS_ADD(mcast_dropped);
return UIP_MCAST6_DROP;
}
/* Retrieve our preferred parent's LL address */
parent_ipaddr = rpl_get_parent_ipaddr(d->preferred_parent);
parent_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(parent_ipaddr);
if(parent_lladdr == NULL) {
UIP_MCAST6_STATS_ADD(mcast_dropped);
return UIP_MCAST6_DROP;
}
/*
* We accept a datagram if it arrived from our preferred parent, discard
* otherwise.
*/
if(memcmp(parent_lladdr, packetbuf_addr(PACKETBUF_ADDR_SENDER),
UIP_LLADDR_LEN)) {
PRINTF("SMRF: Routable in but SMRF ignored it\n");
UIP_MCAST6_STATS_ADD(mcast_dropped);
return UIP_MCAST6_DROP;
}
if(UIP_IP_BUF->ttl <= 1) {
UIP_MCAST6_STATS_ADD(mcast_dropped);
return UIP_MCAST6_DROP;
}
UIP_MCAST6_STATS_ADD(mcast_in_all);
UIP_MCAST6_STATS_ADD(mcast_in_unique);
/* If we have an entry in the mcast routing table, something with
* a higher RPL rank (somewhere down the tree) is a group member */
if(uip_mcast6_route_lookup(&UIP_IP_BUF->destipaddr)) {
/* If we enter here, we will definitely forward */
UIP_MCAST6_STATS_ADD(mcast_fwd);
/*
* Add a delay (D) of at least SMRF_FWD_DELAY() to compensate for how
* contikimac handles broadcasts. We can't start our TX before the sender
* has finished its own.
*/
fwd_delay = SMRF_FWD_DELAY();
/* Finalise D: D = min(SMRF_FWD_DELAY(), SMRF_MIN_FWD_DELAY) */
#if SMRF_MIN_FWD_DELAY
if(fwd_delay < SMRF_MIN_FWD_DELAY) {
fwd_delay = SMRF_MIN_FWD_DELAY;
}
#endif
if(fwd_delay == 0) {
/* No delay required, send it, do it now, why wait? */
UIP_IP_BUF->ttl--;
tcpip_output(NULL);
UIP_IP_BUF->ttl++; /* Restore before potential upstack delivery */
} else {
/* Randomise final delay in [D , D*Spread], step D */
fwd_spread = SMRF_INTERVAL_COUNT;
if(fwd_spread > SMRF_MAX_SPREAD) {
fwd_spread = SMRF_MAX_SPREAD;
}
if(fwd_spread) {
fwd_delay = fwd_delay * (1 + ((random_rand() >> 11) % fwd_spread));
}
memcpy(&mcast_buf, uip_buf, uip_len);
mcast_len = uip_len;
ctimer_set(&mcast_periodic, fwd_delay, mcast_fwd, NULL);
}
PRINTF("SMRF: %u bytes: fwd in %u [%u]\n",
uip_len, fwd_delay, fwd_spread);
}
/* Done with this packet unless we are a member of the mcast group */
if(!uip_ds6_is_my_maddr(&UIP_IP_BUF->destipaddr)) {
PRINTF("SMRF: Not a group member. No further processing\n");
return UIP_MCAST6_DROP;
} else {
PRINTF("SMRF: Ours. Deliver to upper layers\n");
UIP_MCAST6_STATS_ADD(mcast_in_ours);
return UIP_MCAST6_ACCEPT;
}
}
/*---------------------------------------------------------------------------*/
static void
init()
{
UIP_MCAST6_STATS_INIT(NULL);
uip_mcast6_route_init();
}
/*---------------------------------------------------------------------------*/
static void
out()
{
return;
}
/*---------------------------------------------------------------------------*/
const struct uip_mcast6_driver smrf_driver = {
"SMRF",
init,
out,
in,
};
/*---------------------------------------------------------------------------*/
#endif /* UIP_CONF_IPV6 */

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2011, Loughborough University - Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* Header file for 'Stateless Multicast RPL Forwarding' (SMRF)
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#ifndef SMRF_H_
#define SMRF_H_
#include "contiki-conf.h"
#include <stdint.h>
/*---------------------------------------------------------------------------*/
/* Configuration */
/*---------------------------------------------------------------------------*/
/* Fmin */
#ifdef SMRF_CONF_MIN_FWD_DELAY
#define SMRF_MIN_FWD_DELAY SMRF_CONF_MIN_FWD_DELAY
#else
#define SMRF_MIN_FWD_DELAY 4
#endif
/* Max Spread */
#ifdef SMRF_CONF_MAX_SPREAD
#define SMRF_MAX_SPREAD SMRF_CONF_MAX_SPREAD
#else
#define SMRF_MAX_SPREAD 4
#endif
/*---------------------------------------------------------------------------*/
/* Stats datatype */
/*---------------------------------------------------------------------------*/
struct smrf_stats {
uint16_t mcast_in_unique;
uint16_t mcast_in_all; /* At layer 3 */
uint16_t mcast_in_ours; /* Unique and we are a group member */
uint16_t mcast_fwd; /* Forwarded by us but we are not the seed */
uint16_t mcast_out; /* We are the seed */
uint16_t mcast_bad;
uint16_t mcast_dropped;
};
#endif /* SMRF_H_ */

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2011, Loughborough University - Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* Header file with definition of multicast engine constants
*
* When writing a new engine, add it here with a unique number and
* then modify uip-mcast6.h accordingly
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#ifndef UIP_MCAST6_ENGINES_H_
#define UIP_MCAST6_ENGINES_H_
#define UIP_MCAST6_ENGINE_NONE 0 /* Selecting this disables mcast */
#define UIP_MCAST6_ENGINE_SMRF 1
#define UIP_MCAST6_ENGINE_ROLL_TM 2
#endif /* UIP_MCAST6_ENGINES_H_ */

View file

@ -0,0 +1,133 @@
/*
* Copyright (c) 2011, Loughborough University - Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
* Multicast routing table manipulation
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#include "contiki.h"
#include "lib/list.h"
#include "lib/memb.h"
#include "net/ip/uip.h"
#include "net/ipv6/multicast/uip-mcast6-route.h"
#include <stdint.h>
#include <string.h>
#if UIP_CONF_IPV6
/*---------------------------------------------------------------------------*/
/* Size of the multicast routing table */
#ifdef UIP_MCAST6_ROUTE_CONF_ROUTES
#define UIP_MCAST6_ROUTE_ROUTES UIP_MCAST6_ROUTE_CONF_ROUTES
#else
#define UIP_MCAST6_ROUTE_ROUTES 1
#endif /* UIP_CONF_DS6_MCAST_ROUTES */
/*---------------------------------------------------------------------------*/
LIST(mcast_route_list);
MEMB(mcast_route_memb, uip_mcast6_route_t, UIP_MCAST6_ROUTE_ROUTES);
static uip_mcast6_route_t *locmcastrt;
/*---------------------------------------------------------------------------*/
uip_mcast6_route_t *
uip_mcast6_route_lookup(uip_ipaddr_t *group)
{
locmcastrt = NULL;
for(locmcastrt = list_head(mcast_route_list);
locmcastrt != NULL;
locmcastrt = list_item_next(locmcastrt)) {
if(uip_ipaddr_cmp(&locmcastrt->group, group)) {
return locmcastrt;
}
}
return NULL;
}
/*---------------------------------------------------------------------------*/
uip_mcast6_route_t *
uip_mcast6_route_add(uip_ipaddr_t *group)
{
/* _lookup must return NULL, i.e. the prefix does not exist in our table */
locmcastrt = uip_mcast6_route_lookup(group);
if(locmcastrt == NULL) {
/* Allocate an entry and add the group to the list */
locmcastrt = memb_alloc(&mcast_route_memb);
if(locmcastrt == NULL) {
return NULL;
}
list_add(mcast_route_list, locmcastrt);
}
/* Reaching here means we either found the prefix or allocated a new one */
uip_ipaddr_copy(&(locmcastrt->group), group);
return locmcastrt;
}
/*---------------------------------------------------------------------------*/
void
uip_mcast6_route_rm(uip_mcast6_route_t *route)
{
/* Make sure it's actually in the list */
for(locmcastrt = list_head(mcast_route_list);
locmcastrt != NULL;
locmcastrt = list_item_next(locmcastrt)) {
if(locmcastrt == route) {
list_remove(mcast_route_list, route);
memb_free(&mcast_route_memb, route);
return;
}
}
}
/*---------------------------------------------------------------------------*/
uip_mcast6_route_t *
uip_mcast6_route_list_head(void)
{
return list_head(mcast_route_list);
}
/*---------------------------------------------------------------------------*/
int
uip_mcast6_route_count(void)
{
return list_length(mcast_route_list);
}
/*---------------------------------------------------------------------------*/
void
uip_mcast6_route_init()
{
memb_init(&mcast_route_memb);
list_init(mcast_route_list);
}
/*---------------------------------------------------------------------------*/
#endif /* UIP_CONF_IPV6 */

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2011, Loughborough University - Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
* Multicast routing table manipulation
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#ifndef UIP_MCAST6_ROUTE_H_
#define UIP_MCAST6_ROUTE_H_
#include "contiki.h"
#include "net/ip/uip.h"
#include <stdint.h>
/*---------------------------------------------------------------------------*/
/** \brief An entry in the multicast routing table */
typedef struct uip_mcast6_route {
struct uip_mcast6_route *next;
uip_ipaddr_t group;
uint32_t lifetime; /* seconds */
void *dag; /* Pointer to an rpl_dag_t struct */
} uip_mcast6_route_t;
/*---------------------------------------------------------------------------*/
/** \name Multicast Routing Table Manipulation */
/** @{ */
uip_mcast6_route_t *uip_mcast6_route_lookup(uip_ipaddr_t *group);
uip_mcast6_route_t *uip_mcast6_route_add(uip_ipaddr_t *group);
void uip_mcast6_route_rm(uip_mcast6_route_t *defrt);
int uip_mcast6_route_count(void);
uip_mcast6_route_t *uip_mcast6_route_list_head(void);
/*---------------------------------------------------------------------------*/
/**
* \brief Multicast routing table init routine
*
* Multicast routing tables are not necessarily required by all
* multicast engines. For instance, trickle multicast does not rely on
* the existence of a routing table. Therefore, this function here
* should be invoked by each engine's init routine only if the relevant
* functionality is required. This is also why this function should not
* get hooked into the uip-ds6 core.
*/
void uip_mcast6_route_init(void);
/** @} */
#endif /* UIP_MCAST6_ROUTE_H_ */

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2014, University of Bristol - http://www.bris.ac.uk
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
* IPv6 multicast forwarding stats maintenance
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#include "net/ipv6/multicast/uip-mcast6-stats.h"
#include <string.h>
/*---------------------------------------------------------------------------*/
uip_mcast6_stats_t uip_mcast6_stats;
/*---------------------------------------------------------------------------*/
void
uip_mcast6_stats_init(void *stats)
{
memset(&uip_mcast6_stats, 0, sizeof(uip_mcast6_stats));
uip_mcast6_stats.engine_stats = stats;
}
/*---------------------------------------------------------------------------*/

View file

@ -0,0 +1,91 @@
/*
* Copyright (c) 2014, University of Bristol - http://www.bris.ac.uk
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
* Header file for IPv6 multicast forwarding stats maintenance
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#ifndef UIP_MCAST6_STATS_H_
#define UIP_MCAST6_STATS_H_
/*---------------------------------------------------------------------------*/
#include "contiki-conf.h"
#include <stdint.h>
/*---------------------------------------------------------------------------*/
/* The platform can override the stats datatype */
#ifdef UIP_MCAST6_CONF_STATS_DATATYPE
#define UIP_MCAST6_STATS_DATATYPE UIP_MCAST6_CONF_STATS_DATATYPE
#else
#define UIP_MCAST6_STATS_DATATYPE uint16_t
#endif
/*---------------------------------------------------------------------------*/
#ifdef UIP_MCAST6_CONF_STATS
#define UIP_MCAST6_STATS UIP_MCAST6_CONF_STATS
#else
#define UIP_MCAST6_STATS 0
#endif
/*---------------------------------------------------------------------------*/
/* Stats datatype */
/*---------------------------------------------------------------------------*/
typedef struct uip_mcast6_stats {
UIP_MCAST6_STATS_DATATYPE mcast_in_unique;
UIP_MCAST6_STATS_DATATYPE mcast_in_all; /* At layer 3 */
UIP_MCAST6_STATS_DATATYPE mcast_in_ours; /* Unique and we are a group member */
UIP_MCAST6_STATS_DATATYPE mcast_fwd; /* Forwarded by us but we are not the seed */
UIP_MCAST6_STATS_DATATYPE mcast_out; /* We are the seed */
UIP_MCAST6_STATS_DATATYPE mcast_bad;
UIP_MCAST6_STATS_DATATYPE mcast_dropped;
void *engine_stats; /* Opaque pointer to an engine's additional stats */
} uip_mcast6_stats_t;
/*---------------------------------------------------------------------------*/
/* Access macros */
/*---------------------------------------------------------------------------*/
#if UIP_MCAST6_STATS
/* Don't access this variable directly, use the macros below */
extern uip_mcast6_stats_t uip_mcast6_stats;
#define UIP_MCAST6_STATS_ADD(x) uip_mcast6_stats.x++
#define UIP_MCAST6_STATS_GET(x) uip_mcast6_stats.x
#define UIP_MCAST6_STATS_INIT(s) uip_mcast6_stats_init(s)
#else /* UIP_MCAST6_STATS */
#define UIP_MCAST6_STATS_ADD(x)
#define UIP_MCAST6_STATS_GET(x) 0
#define UIP_MCAST6_STATS_INIT(s)
#endif /* UIP_MCAST6_STATS */
/*---------------------------------------------------------------------------*/
/**
* \brief Initialise multicast stats
* \param stats A pointer to a struct holding an engine's additional statistics
*/
void uip_mcast6_stats_init(void *stats);
/*---------------------------------------------------------------------------*/
#endif /* UIP_MCAST6_STATS_H_ */

View file

@ -0,0 +1,162 @@
/*
* Copyright (c) 2011, Loughborough University - Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* This header file contains configuration directives for uIPv6
* multicast support.
*
* We currently support 2 engines:
* - 'Stateless Multicast RPL Forwarding' (SMRF)
* RPL does group management as per the RPL docs, SMRF handles datagram
* forwarding
* - 'Multicast Forwarding with Trickle' according to the algorithm described
* in the internet draft:
* http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#ifndef UIP_MCAST6_H_
#define UIP_MCAST6_H_
#include "contiki-conf.h"
#include "net/ipv6/multicast/uip-mcast6-engines.h"
#include "net/ipv6/multicast/uip-mcast6-route.h"
#include "net/ipv6/multicast/smrf.h"
#include "net/ipv6/multicast/roll-tm.h"
#include <string.h>
/*---------------------------------------------------------------------------*/
/* Constants */
/*---------------------------------------------------------------------------*/
#define UIP_MCAST6_DROP 0
#define UIP_MCAST6_ACCEPT 1
/*---------------------------------------------------------------------------*/
/* Multicast Address Scopes (RFC 4291 & draft-ietf-6man-multicast-scopes) */
#define UIP_MCAST6_SCOPE_INTERFACE 0x01
#define UIP_MCAST6_SCOPE_LINK_LOCAL 0x02
#define UIP_MCAST6_SCOPE_REALM_LOCAL 0x03 /* draft-ietf-6man-multicast-scopes */
#define UIP_MCAST6_SCOPE_ADMIN_LOCAL 0x04
#define UIP_MCAST6_SCOPE_SITE_LOCAL 0x05
#define UIP_MCAST6_SCOPE_ORG_LOCAL 0x08
#define UIP_MCAST6_SCOPE_GLOBAL 0x0E
/*---------------------------------------------------------------------------*/
/* Choose an engine or turn off based on user configuration */
/*---------------------------------------------------------------------------*/
#ifdef UIP_MCAST6_CONF_ENGINE
#define UIP_MCAST6_ENGINE UIP_MCAST6_CONF_ENGINE
#else
#define UIP_MCAST6_ENGINE UIP_MCAST6_ENGINE_NONE
#endif
/*---------------------------------------------------------------------------*/
/*
* Multicast API. Similar to NETSTACK, each engine must define a driver and
* populate the fields with suitable function pointers
*/
struct uip_mcast6_driver {
char *name;
/** Initialize the multicast engine */
void (* init)(void);
/**
* \brief Process an outgoing datagram with a multicast IPv6 destination
* address
*
* This may be needed if the multicast engine needs to, for example,
* add IPv6 extension headers to the datagram, cache it, decide it
* needs dropped etc.
*
* It is sometimes desirable to let the engine handle datagram
* dispatch instead of letting the networking core do it. If the
* engine decides to send the datagram itself, it must afterwards
* set uip_len = 0 to prevent the networking core from sending too
*/
void (* out)(void);
/**
* \brief Process an incoming multicast datagram and determine whether it
* should be delivered up the stack or not.
*
* \return 0: Drop, 1: Deliver
*
* When a datagram with a multicast destination address is received,
* the forwarding logic in core is bypassed. Instead, we let the
* multicast engine handle forwarding internally if and as necessary.
* This function is where forwarding logic must be hooked in.
*
* Once the engine is done with forwarding, it must signal via the
* return value whether the datagram needs delivered up the network
* stack.
*/
uint8_t (* in)(void);
};
/*---------------------------------------------------------------------------*/
/**
* \brief Get a multicast address' scope.
* a is of type uip_ip6addr_t*
*/
#define uip_mcast6_get_address_scope(a) ((a)->u8[1] & 0x0F)
/*---------------------------------------------------------------------------*/
/* Configure multicast and core/net to play nicely with the selected engine */
#if UIP_MCAST6_ENGINE
/* Enable Multicast hooks in the uip6 core */
#define UIP_CONF_IPV6_MULTICAST 1
#if UIP_MCAST6_ENGINE == UIP_MCAST6_ENGINE_ROLL_TM
#define RPL_CONF_MULTICAST 0 /* Not used by trickle */
#define UIP_CONF_IPV6_ROLL_TM 1 /* ROLL Trickle ICMP type support */
#define UIP_MCAST6 roll_tm_driver
#elif UIP_MCAST6_ENGINE == UIP_MCAST6_ENGINE_SMRF
#define RPL_CONF_MULTICAST 1
#define UIP_MCAST6 smrf_driver
#else
#error "Multicast Enabled with an Unknown Engine."
#error "Check the value of UIP_MCAST6_CONF_ENGINE in conf files."
#endif
#endif /* UIP_MCAST6_ENGINE */
extern const struct uip_mcast6_driver UIP_MCAST6;
/*---------------------------------------------------------------------------*/
/* Configuration Checks */
/*---------------------------------------------------------------------------*/
#if RPL_CONF_MULTICAST && (!UIP_CONF_IPV6_RPL)
#error "The selected Multicast mode requires UIP_CONF_IPV6_RPL != 0"
#error "Check the value of UIP_CONF_IPV6_RPL in conf files."
#endif
/*---------------------------------------------------------------------------*/
#endif /* UIP_MCAST6_H_ */

View file

@ -512,6 +512,10 @@ uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
}
}
}
#if UIP_IPV6_MULTICAST
} else if(uip_is_addr_mcast_routable(dst)) {
matchaddr = uip_ds6_get_global(ADDR_PREFERRED);
#endif
} else {
matchaddr = uip_ds6_get_link_local(ADDR_PREFERRED);
}

View file

@ -74,10 +74,53 @@
static uip_ipaddr_t tmp_ipaddr;
LIST(echo_reply_callback_list);
/*---------------------------------------------------------------------------*/
/* List of input handlers */
LIST(input_handler_list);
/*---------------------------------------------------------------------------*/
static uip_icmp6_input_handler_t *
input_handler_lookup(uint8_t type, uint8_t icode)
{
uip_icmp6_input_handler_t *handler = NULL;
for(handler = list_head(input_handler_list);
handler != NULL;
handler = list_item_next(handler)) {
if(handler->type == type &&
(handler->icode == icode ||
handler->icode == UIP_ICMP6_HANDLER_CODE_ANY)) {
return handler;
}
}
return NULL;
}
/*---------------------------------------------------------------------------*/
uint8_t
uip_icmp6_input(uint8_t type, uint8_t icode)
{
uip_icmp6_input_handler_t *handler = input_handler_lookup(type, icode);
if(handler == NULL) {
return UIP_ICMP6_INPUT_ERROR;
}
if(handler->handler == NULL) {
return UIP_ICMP6_INPUT_ERROR;
}
handler->handler();
return UIP_ICMP6_INPUT_SUCCESS;
}
/*---------------------------------------------------------------------------*/
void
uip_icmp6_echo_request_input(void)
uip_icmp6_register_input_handler(uip_icmp6_input_handler_t *handler)
{
list_add(input_handler_list, handler);
}
/*---------------------------------------------------------------------------*/
static void
echo_request_input(void)
{
#if UIP_CONF_IPV6_RPL
uint8_t temp_ext_len;
@ -275,8 +318,8 @@ uip_icmp6_send(const uip_ipaddr_t *dest, int type, int code, int payload_len)
tcpip_ipv6_output();
}
/*---------------------------------------------------------------------------*/
void
uip_icmp6_echo_reply_input(void)
static void
echo_reply_input(void)
{
int ttl;
uip_ipaddr_t sender;
@ -343,6 +386,8 @@ uip_icmp6_echo_reply_input(void)
}
}
}
uip_len = 0;
return;
}
/*---------------------------------------------------------------------------*/
@ -362,5 +407,18 @@ uip_icmp6_echo_reply_callback_rm(struct uip_icmp6_echo_reply_notification *n)
list_remove(echo_reply_callback_list, n);
}
/*---------------------------------------------------------------------------*/
UIP_ICMP6_HANDLER(echo_request_handler, ICMP6_ECHO_REQUEST,
UIP_ICMP6_HANDLER_CODE_ANY, echo_request_input);
UIP_ICMP6_HANDLER(echo_reply_handler, ICMP6_ECHO_REPLY,
UIP_ICMP6_HANDLER_CODE_ANY, echo_reply_input);
/*---------------------------------------------------------------------------*/
void
uip_icmp6_init()
{
/* Register Echo Request and Reply handlers */
uip_icmp6_register_input_handler(&echo_request_handler);
uip_icmp6_register_input_handler(&echo_reply_handler);
}
/*---------------------------------------------------------------------------*/
/** @} */
#endif /* UIP_CONF_IPV6 */

View file

@ -65,6 +65,11 @@
#define ICMP6_REDIRECT 137 /**< Redirect */
#define ICMP6_RPL 155 /**< RPL */
#define ICMP6_PRIV_EXP_100 100 /**< Private Experimentation */
#define ICMP6_PRIV_EXP_101 101 /**< Private Experimentation */
#define ICMP6_PRIV_EXP_200 200 /**< Private Experimentation */
#define ICMP6_PRIV_EXP_201 201 /**< Private Experimentation */
#define ICMP6_ROLL_TM ICMP6_PRIV_EXP_200 /**< ROLL Trickle Multicast */
/** @} */
@ -104,24 +109,6 @@ typedef struct uip_icmp6_error{
/** \name ICMPv6 RFC4443 Message processing and sending */
/** @{ */
/** \
* brief Process an echo request
*
* Perform a few checks, then send an Echo reply. The reply is
* built here.
*/
void
uip_icmp6_echo_request_input(void);
/** \
* brief Process an echo reply
*
* Perform a few checks, then call applications to inform that an echo
* reply has been received.
*/
void
uip_icmp6_echo_reply_input(void);
/**
* \brief Send an icmpv6 error message
* \param type type of the error message
@ -187,8 +174,66 @@ uip_icmp6_echo_reply_callback_add(struct uip_icmp6_echo_reply_notification *n,
void
uip_icmp6_echo_reply_callback_rm(struct uip_icmp6_echo_reply_notification *n);
/* Generic ICMPv6 input handers */
typedef struct uip_icmp6_input_handler {
struct uip_icmp6_input_handler *next;
uint8_t type;
uint8_t icode;
void (*handler)(void);
} uip_icmp6_input_handler_t;
#define UIP_ICMP6_INPUT_SUCCESS 0
#define UIP_ICMP6_INPUT_ERROR 1
#define UIP_ICMP6_HANDLER_CODE_ANY 0xFF /* Handle all codes for this type */
/*
* Initialise a variable of type uip_icmp6_input_handler, to be used later as
* the argument to uip_icmp6_register_input_handler
*
* The function pointer stored in this variable will get called and will be
* expected to handle incoming ICMPv6 datagrams of the specified type/code
*
* If code has a value of UIP_ICMP6_HANDLER_CODE_ANY, the same function
* will handle all codes for this type. In other words, the ICMPv6
* message's code is "don't care"
*/
#define UIP_ICMP6_HANDLER(name, type, code, func) \
static uip_icmp6_input_handler_t name = { NULL, type, code, func }
/**
* \brief Handle an incoming ICMPv6 message
* \param type The ICMPv6 message type
* \param icode The ICMPv6 message code
* \return Success: UIP_ICMP6_INPUT_SUCCESS, Error: UIP_ICMP6_INPUT_ERROR
*
* Generic handler for unknown ICMPv6 types. It will lookup for a registered
* function capable of handing this message type. The function must have first
* been registered with uip_icmp6_register_input_handler. The function is in
* charge of setting uip_len to 0, otherwise the uIPv6 core will attempt to
* send whatever remains in the UIP_IP_BUF.
*
* A return value of UIP_ICMP6_INPUT_ERROR means that a handler could not be
* invoked. This is most likely because the ICMPv6 type does not have a valid
* handler associated with it.
* UIP_ICMP6_INPUT_SUCCESS signifies that a handler was found for this ICMPv6
* type and that it was invoked. It does NOT provide any indication whatsoever
* regarding whether the handler itself succeeded.
*/
uint8_t uip_icmp6_input(uint8_t type, uint8_t icode);
/**
* \brief Register a handler which can handle a specific ICMPv6 message type
* \param handler A pointer to the handler
*/
void uip_icmp6_register_input_handler(uip_icmp6_input_handler_t *handler);
/**
* \brief Initialise the uIP ICMPv6 core
*/
void uip_icmp6_init(void);
/** @} */

View file

@ -126,8 +126,6 @@ static uip_ds6_prefix_t *prefix; /** Pointer to a prefix list entry */
static uip_ds6_nbr_t *nbr; /** Pointer to a nbr cache entry*/
static uip_ds6_defrt_t *defrt; /** Pointer to a router list entry */
static uip_ds6_addr_t *addr; /** Pointer to an interface address */
/*------------------------------------------------------------------*/
/* create a llao */
static void
@ -143,8 +141,8 @@ create_llao(uint8_t *llao, uint8_t type) {
/*------------------------------------------------------------------*/
void
uip_nd6_ns_input(void)
static void
ns_input(void)
{
uint8_t flags;
PRINTF("Received NS from ");
@ -388,12 +386,26 @@ uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt)
PRINTF("\n");
return;
}
/*------------------------------------------------------------------*/
void
uip_nd6_na_input(void)
/**
* Neighbor Advertisement Processing
*
* we might have to send a pkt that had been buffered while address
* resolution was performed (if we support buffering, see UIP_CONF_QUEUE_PKT)
*
* As per RFC 4861, on link layer that have addresses, TLLAO options MUST be
* included when responding to multicast solicitations, SHOULD be included in
* response to unicast (here we assume it is for now)
*
* NA can be received after sending NS for DAD, Address resolution or NUD. Can
* be unsolicited as well.
* It can trigger update of the state of the neighbor in the neighbor cache,
* router in the router list.
* If the NS was for DAD, it means DAD failed
*
*/
static void
na_input(void)
{
uint8_t is_llchange;
uint8_t is_router;
@ -548,8 +560,8 @@ discard:
#if UIP_CONF_ROUTER
#if UIP_ND6_SEND_RA
/*---------------------------------------------------------------------------*/
void
uip_nd6_rs_input(void)
static void
rs_input(void)
{
PRINTF("Received RS from");
@ -761,11 +773,18 @@ uip_nd6_rs_output(void)
PRINTF("\n");
return;
}
/*---------------------------------------------------------------------------*/
/*
* Process a Router Advertisement
*
* - Possible actions when receiving a RA: add router to router list,
* recalculate reachable time, update link hop limit, update retrans timer.
* - If MTU option: update MTU.
* - If SLLAO option: update entry in neighbor cache
* - If prefix option: start autoconf, add prefix to prefix list
*/
void
uip_nd6_ra_input(void)
ra_input(void)
{
PRINTF("Received RA from");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
@ -969,6 +988,52 @@ discard:
return;
}
#endif /* !UIP_CONF_ROUTER */
/*------------------------------------------------------------------*/
/* ICMPv6 input handlers */
#if UIP_ND6_SEND_NA
UIP_ICMP6_HANDLER(ns_input_handler, ICMP6_NS, UIP_ICMP6_HANDLER_CODE_ANY,
ns_input);
UIP_ICMP6_HANDLER(na_input_handler, ICMP6_NA, UIP_ICMP6_HANDLER_CODE_ANY,
na_input);
#endif
#if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
UIP_ICMP6_HANDLER(rs_input_handler, ICMP6_RS, UIP_ICMP6_HANDLER_CODE_ANY,
rs_input);
#endif
#if !UIP_CONF_ROUTER
UIP_ICMP6_HANDLER(ra_input_handler, ICMP6_RA, UIP_ICMP6_HANDLER_CODE_ANY,
ra_input);
#endif
/*---------------------------------------------------------------------------*/
void
uip_nd6_init()
{
#if UIP_ND6_SEND_NA
/* Only handle NSs if we are prepared to send out NAs */
uip_icmp6_register_input_handler(&ns_input_handler);
/*
* Only handle NAs if we are prepared to send out NAs.
* This is perhaps logically incorrect, but this condition was present in
* uip_process and we keep it until proven wrong
*/
uip_icmp6_register_input_handler(&na_input_handler);
#endif
#if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
/* Only accept RS if we are a router and happy to send out RAs */
uip_icmp6_register_input_handler(&rs_input_handler);
#endif
#if !UIP_CONF_ROUTER
/* Only process RAs if we are not a router */
uip_icmp6_register_input_handler(&ra_input_handler);
#endif
}
/*---------------------------------------------------------------------------*/
/** @} */
#endif /* UIP_CONF_IPV6 */

View file

@ -337,34 +337,8 @@ uip_nd6_ns_input(void);
void
uip_nd6_ns_output(uip_ipaddr_t *src, uip_ipaddr_t *dest, uip_ipaddr_t *tgt);
/**
* \brief Process a Neighbor Advertisement
*
* we might have to send a pkt that had been buffered while address
* resolution was performed (if we support buffering, see UIP_CONF_QUEUE_PKT)
*
* As per RFC 4861, on link layer that have addresses, TLLAO options MUST be
* included when responding to multicast solicitations, SHOULD be included in
* response to unicast (here we assume it is for now)
*
* NA can be received after sending NS for DAD, Address resolution or NUD. Can
* be unsolicited as well.
* It can trigger update of the state of the neighbor in the neighbor cache,
* router in the router list.
* If the NS was for DAD, it means DAD failed
*
*/
void
uip_nd6_na_input(void);
#if UIP_CONF_ROUTER
#if UIP_ND6_SEND_RA
/**
* \brief Process a Router Solicitation
*
*/
void uip_nd6_rs_input(void);
/**
* \brief send a Router Advertisement
*
@ -388,17 +362,9 @@ void uip_nd6_ra_output(uip_ipaddr_t *dest);
void uip_nd6_rs_output(void);
/**
*
* \brief process a Router Advertisement
*
* - Possible actions when receiving a RA: add router to router list,
* recalculate reachable time, update link hop limit, update retrans timer.
* - If MTU option: update MTU.
* - If SLLAO option: update entry in neighbor cache
* - If prefix option: start autoconf, add prefix to prefix list
* \brief Initialise the uIP ND core
*/
void
uip_nd6_ra_input(void);
void uip_nd6_init(void);
/** @} */

View file

@ -75,6 +75,7 @@
#include "net/ipv6/uip-icmp6.h"
#include "net/ipv6/uip-nd6.h"
#include "net/ipv6/uip-ds6.h"
#include "net/ipv6/multicast/uip-mcast6.h"
#include <string.h>
@ -410,6 +411,8 @@ uip_init(void)
{
uip_ds6_init();
uip_icmp6_init();
uip_nd6_init();
#if UIP_TCP
for(c = 0; c < UIP_LISTENPORTS; ++c) {
@ -429,6 +432,10 @@ uip_init(void)
uip_udp_conns[c].lport = 0;
}
#endif /* UIP_UDP */
#if UIP_CONF_IPV6_MULTICAST
UIP_MCAST6.init();
#endif
}
/*---------------------------------------------------------------------------*/
#if UIP_TCP && UIP_ACTIVE_OPEN
@ -1151,6 +1158,28 @@ uip_process(uint8_t flag)
}
}
/*
* Process Packets with a routable multicast destination:
* - We invoke the multicast engine and let it do its thing
* (cache, forward etc).
* - We never execute the datagram forwarding logic in this file here. When
* the engine returns, forwarding has been handled if and as required.
* - Depending on the return value, we either discard or deliver up the stack
*
* All multicast engines must hook in here. After this function returns, we
* expect UIP_BUF to be unmodified
*/
#if UIP_CONF_IPV6_MULTICAST
if(uip_is_addr_mcast_routable(&UIP_IP_BUF->destipaddr)) {
if(UIP_MCAST6.in() == UIP_MCAST6_ACCEPT) {
/* Deliver up the stack */
goto process;
} else {
/* Don't deliver up the stack */
goto drop;
}
}
#endif /* UIP_IPV6_CONF_MULTICAST */
/* TBD Some Parameter problem messages */
if(!uip_ds6_is_my_addr(&UIP_IP_BUF->destipaddr) &&
@ -1220,6 +1249,10 @@ uip_process(uint8_t flag)
uip_ext_bitmap = 0;
#endif /* UIP_CONF_ROUTER */
#if UIP_CONF_IPV6_MULTICAST
process:
#endif
while(1) {
switch(*uip_next_hdr){
#if UIP_TCP
@ -1389,61 +1422,17 @@ uip_process(uint8_t flag)
UIP_ICMP6_APPCALL(UIP_ICMP_BUF->type);
#endif /*UIP_CONF_ICMP6*/
switch(UIP_ICMP_BUF->type) {
case ICMP6_NS:
#if UIP_ND6_SEND_NA
uip_nd6_ns_input();
#else /* UIP_ND6_SEND_NA */
UIP_STAT(++uip_stat.icmp.drop);
uip_len = 0;
#endif /* UIP_ND6_SEND_NA */
break;
case ICMP6_NA:
#if UIP_ND6_SEND_NA
uip_nd6_na_input();
#else /* UIP_ND6_SEND_NA */
UIP_STAT(++uip_stat.icmp.drop);
uip_len = 0;
#endif /* UIP_ND6_SEND_NA */
break;
case ICMP6_RS:
#if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
uip_nd6_rs_input();
#else /* UIP_CONF_ROUTER && UIP_ND6_SEND_RA */
/*
* Search generic input handlers.
* The handler is in charge of setting uip_len to 0
*/
if(uip_icmp6_input(UIP_ICMP_BUF->type,
UIP_ICMP_BUF->icode) == UIP_ICMP6_INPUT_ERROR) {
PRINTF("Unknown ICMPv6 message type/code %d\n", UIP_ICMP_BUF->type);
UIP_STAT(++uip_stat.icmp.drop);
UIP_STAT(++uip_stat.icmp.typeerr);
UIP_LOG("icmp6: unknown ICMPv6 message.");
uip_len = 0;
#endif /* UIP_CONF_ROUTER && UIP_ND6_SEND_RA */
break;
case ICMP6_RA:
#if UIP_CONF_ROUTER
UIP_STAT(++uip_stat.icmp.drop);
uip_len = 0;
#else /* UIP_CONF_ROUTER */
uip_nd6_ra_input();
#endif /* UIP_CONF_ROUTER */
break;
#if UIP_CONF_IPV6_RPL
case ICMP6_RPL:
uip_rpl_input();
break;
#endif /* UIP_CONF_IPV6_RPL */
case ICMP6_ECHO_REQUEST:
uip_icmp6_echo_request_input();
break;
case ICMP6_ECHO_REPLY:
/** Call echo reply input function. */
uip_icmp6_echo_reply_input();
PRINTF("Received an icmp6 echo reply\n");
UIP_STAT(++uip_stat.icmp.recv);
uip_len = 0;
break;
default:
PRINTF("Unknown icmp6 message type %d\n", UIP_ICMP_BUF->type);
UIP_STAT(++uip_stat.icmp.drop);
UIP_STAT(++uip_stat.icmp.typeerr);
UIP_LOG("icmp6: unknown ICMP message.");
uip_len = 0;
break;
}
if(uip_len > 0) {