Porting PicoTCP WIP
This commit is contained in:
259
kernel/picotcp/modules/pico_mcast.c
Normal file
259
kernel/picotcp/modules/pico_mcast.c
Normal file
@ -0,0 +1,259 @@
|
||||
/*********************************************************************
|
||||
PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
|
||||
See COPYING, LICENSE.GPLv2 and LICENSE.GPLv3 for usage.
|
||||
|
||||
This module handles the equalities between the IGMP and the MLD protocol
|
||||
Authors: Roel Postelmans
|
||||
*********************************************************************/
|
||||
|
||||
#include "pico_stack.h"
|
||||
#include "pico_ipv6.h"
|
||||
#include "pico_mld.h"
|
||||
#include "pico_config.h"
|
||||
#include "pico_eth.h"
|
||||
#include "pico_addressing.h"
|
||||
#include "pico_frame.h"
|
||||
#include "pico_tree.h"
|
||||
#include "pico_device.h"
|
||||
#include "pico_socket.h"
|
||||
#include "pico_icmp6.h"
|
||||
#include "pico_dns_client.h"
|
||||
#include "pico_mld.h"
|
||||
#include "pico_igmp.h"
|
||||
#include "pico_constants.h"
|
||||
#include "pico_mcast.h"
|
||||
|
||||
#if (((defined(PICO_SUPPORT_MLD) && defined(PICO_SUPPORT_IPV6)) || defined(PICO_SUPPORT_IGMP)) && defined(PICO_SUPPORT_MCAST))
|
||||
|
||||
#ifdef DEBUG_MCAST
|
||||
#define multicast_dbg dbg
|
||||
#else
|
||||
#define multicast_dbg(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#define MCAST_EVENT_DELETE_GROUP (0x0)
|
||||
#define MCAST_EVENT_CREATE_GROUP (0x1)
|
||||
#define MCAST_EVENT_UPDATE_GROUP (0x2)
|
||||
#define MCAST_EVENT_QUERY_RECV (0x3)
|
||||
#define MCAST_EVENT_REPORT_RECV (0x4)
|
||||
#define MCAST_EVENT_TIMER_EXPIRED (0x5)
|
||||
|
||||
#define MCAST_MODE_IS_INCLUDE (1)
|
||||
#define MCAST_MODE_IS_EXCLUDE (2)
|
||||
#define MCAST_CHANGE_TO_INCLUDE_MODE (3)
|
||||
#define MCAST_CHANGE_TO_EXCLUDE_MODE (4)
|
||||
|
||||
#define MCAST_MODE_IS_INCLUDE (1)
|
||||
#define MCAST_MODE_IS_EXCLUDE (2)
|
||||
#define MCAST_CHANGE_TO_INCLUDE_MODE (3)
|
||||
#define MCAST_CHANGE_TO_EXCLUDE_MODE (4)
|
||||
#define MCAST_ALLOW_NEW_SOURCES (5)
|
||||
#define MCAST_BLOCK_OLD_SOURCES (6)
|
||||
|
||||
typedef int (*mcast_callback)(struct mcast_filter_parameters *);
|
||||
|
||||
static void pico_mcast_src_filtering_cleanup(struct mcast_filter_parameters*mcast )
|
||||
{
|
||||
struct pico_tree_node *index = NULL, *_tmp = NULL;
|
||||
/* cleanup filters */
|
||||
pico_tree_foreach_safe(index, mcast->allow, _tmp)
|
||||
{
|
||||
pico_tree_delete(mcast->allow, index->keyValue);
|
||||
}
|
||||
pico_tree_foreach_safe(index, mcast->block, _tmp)
|
||||
{
|
||||
pico_tree_delete(mcast->block, index->keyValue);
|
||||
}
|
||||
}
|
||||
static int pico_mcast_src_filtering_inc_inc(struct mcast_filter_parameters*mcast )
|
||||
{
|
||||
struct pico_tree_node *index = NULL;
|
||||
union pico_address *source;
|
||||
/* all ADD_SOURCE_MEMBERSHIP had an equivalent DROP_SOURCE_MEMBERSHIP */
|
||||
if (mcast->p->event == MCAST_EVENT_DELETE_GROUP) {
|
||||
/* TO_IN (B) */
|
||||
mcast->record_type = MCAST_CHANGE_TO_INCLUDE_MODE;
|
||||
mcast->filter = mcast->allow;
|
||||
if (mcast->p->MCASTFilter) {
|
||||
pico_tree_foreach(index, mcast->p->MCASTFilter) /* B */
|
||||
{
|
||||
if (pico_tree_insert(mcast->allow, index->keyValue) == &LEAF) {
|
||||
multicast_dbg("MCAST: Failed to insert entry in tree\n");
|
||||
return -1;
|
||||
}
|
||||
mcast->sources++;
|
||||
}
|
||||
} /* else { allow stays empty } */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ALLOW (B-A) */
|
||||
/* if event is CREATE A will be empty, thus only ALLOW (B-A) has sense */
|
||||
if (mcast->p->event == MCAST_EVENT_CREATE_GROUP) /* first ADD_SOURCE_MEMBERSHIP */
|
||||
mcast->record_type = MCAST_CHANGE_TO_INCLUDE_MODE;
|
||||
else
|
||||
mcast->record_type = MCAST_ALLOW_NEW_SOURCES;
|
||||
|
||||
mcast->filter = mcast->allow;
|
||||
pico_tree_foreach(index, mcast->p->MCASTFilter) /* B */
|
||||
{
|
||||
if (pico_tree_insert(mcast->allow, index->keyValue) == &LEAF) {
|
||||
multicast_dbg("MCAST: Failed to insert entry in tree\n");
|
||||
return -1;
|
||||
}
|
||||
mcast->sources++;
|
||||
}
|
||||
pico_tree_foreach(index, &mcast->g->MCASTSources) /* A */
|
||||
{
|
||||
source = pico_tree_findKey(mcast->allow, index->keyValue);
|
||||
if (source) {
|
||||
pico_tree_delete(mcast->allow, source);
|
||||
mcast->sources--;
|
||||
}
|
||||
}
|
||||
if (!pico_tree_empty(mcast->allow)) /* record type is ALLOW */
|
||||
return 0;
|
||||
|
||||
/* BLOCK (A-B) */
|
||||
mcast->record_type = MCAST_BLOCK_OLD_SOURCES;
|
||||
mcast->filter = mcast->block;
|
||||
pico_tree_foreach(index, &mcast->g->MCASTSources) /* A */
|
||||
{
|
||||
if (pico_tree_insert(mcast->block, index->keyValue) == &LEAF) {
|
||||
multicast_dbg("MCAST: Failed to insert entry in tree\n");
|
||||
return -1;
|
||||
}
|
||||
mcast->sources++;
|
||||
}
|
||||
pico_tree_foreach(index, mcast->p->MCASTFilter) /* B */
|
||||
{
|
||||
source = pico_tree_findKey(mcast->block, index->keyValue);
|
||||
if (source) {
|
||||
pico_tree_delete(mcast->block, source);
|
||||
mcast->sources--;
|
||||
}
|
||||
}
|
||||
if (!pico_tree_empty(mcast->block)) /* record type is BLOCK */
|
||||
return 0;
|
||||
|
||||
/* ALLOW (B-A) and BLOCK (A-B) are empty: do not send report */
|
||||
(mcast->p)->f = NULL;
|
||||
return MCAST_NO_REPORT;
|
||||
}
|
||||
|
||||
static int pico_mcast_src_filtering_inc_excl(struct mcast_filter_parameters*mcast )
|
||||
{
|
||||
struct pico_tree_node *index = NULL;
|
||||
mcast->record_type = MCAST_CHANGE_TO_EXCLUDE_MODE;
|
||||
mcast->filter = mcast->block;
|
||||
pico_tree_foreach(index, mcast->p->MCASTFilter) /* B */
|
||||
{
|
||||
if (pico_tree_insert(mcast->block, index->keyValue) == &LEAF) {
|
||||
multicast_dbg("MCAST: Failed to insert entry in tree\n");
|
||||
return -1;
|
||||
}
|
||||
mcast->sources++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int pico_mcast_src_filtering_excl_inc(struct mcast_filter_parameters*mcast )
|
||||
{
|
||||
struct pico_tree_node *index = NULL;
|
||||
mcast->record_type = MCAST_CHANGE_TO_INCLUDE_MODE;
|
||||
mcast->filter = mcast->allow;
|
||||
if (mcast->p->MCASTFilter) {
|
||||
pico_tree_foreach(index, mcast->p->MCASTFilter) /* B */
|
||||
{
|
||||
if (pico_tree_insert(mcast->allow, index->keyValue) == &LEAF) {
|
||||
multicast_dbg("MCAST: Failed to insert entry in tree\n");
|
||||
return -1;
|
||||
}
|
||||
mcast->sources++;
|
||||
}
|
||||
} /* else { allow stays empty } */
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int pico_mcast_src_filtering_excl_excl(struct mcast_filter_parameters*mcast )
|
||||
{
|
||||
struct pico_tree_node *index = NULL;
|
||||
struct pico_ip6 *source = NULL;
|
||||
mcast->record_type = MCAST_BLOCK_OLD_SOURCES;
|
||||
mcast->filter = mcast->block;
|
||||
pico_tree_foreach(index, mcast->p->MCASTFilter)
|
||||
{
|
||||
if (pico_tree_insert(mcast->block, index->keyValue) == &LEAF) {
|
||||
multicast_dbg("MCAST: Failed to insert entry in tree\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mcast->sources++;
|
||||
}
|
||||
pico_tree_foreach(index, &mcast->g->MCASTSources) /* A */
|
||||
{
|
||||
source = pico_tree_findKey(mcast->block, index->keyValue); /* B */
|
||||
if (source) {
|
||||
pico_tree_delete(mcast->block, source);
|
||||
mcast->sources--;
|
||||
}
|
||||
}
|
||||
if (!pico_tree_empty(mcast->block)) /* record type is BLOCK */
|
||||
return 0;
|
||||
|
||||
/* ALLOW (A-B) */
|
||||
mcast->record_type = MCAST_ALLOW_NEW_SOURCES;
|
||||
mcast->filter = mcast->allow;
|
||||
pico_tree_foreach(index, &mcast->g->MCASTSources)
|
||||
{
|
||||
if (pico_tree_insert(mcast->allow, index->keyValue) == &LEAF) {
|
||||
multicast_dbg("MCAST: Failed to insert entry in tree\n");
|
||||
return -1;
|
||||
}
|
||||
mcast->sources++;
|
||||
}
|
||||
pico_tree_foreach(index, mcast->p->MCASTFilter) /* B */
|
||||
{
|
||||
source = pico_tree_findKey(mcast->allow, index->keyValue); /* A */
|
||||
if (source) {
|
||||
pico_tree_delete(mcast->allow, source);
|
||||
mcast->sources--;
|
||||
}
|
||||
}
|
||||
if (!pico_tree_empty(mcast->allow)) /* record type is ALLOW */
|
||||
return 0;
|
||||
|
||||
/* BLOCK (B-A) and ALLOW (A-B) are empty: do not send report */
|
||||
mcast->p->f = NULL;
|
||||
return MCAST_NO_REPORT;
|
||||
}
|
||||
static const mcast_callback mcast_filter_state[2][2] =
|
||||
{
|
||||
{ pico_mcast_src_filtering_excl_excl, pico_mcast_src_filtering_excl_inc},
|
||||
{ pico_mcast_src_filtering_inc_excl, pico_mcast_src_filtering_inc_inc }
|
||||
};
|
||||
int8_t pico_mcast_generate_filter(struct mcast_filter_parameters *filter, struct mcast_parameters *p)
|
||||
{
|
||||
int ret = -1;
|
||||
/* "non-existent" state of filter mode INCLUDE and empty source list */
|
||||
if (p->event == MCAST_EVENT_DELETE_GROUP) {
|
||||
p->filter_mode = PICO_IP_MULTICAST_INCLUDE;
|
||||
p->MCASTFilter = NULL;
|
||||
}
|
||||
|
||||
if (p->event == MCAST_EVENT_QUERY_RECV)
|
||||
return 0;
|
||||
|
||||
pico_mcast_src_filtering_cleanup(filter);
|
||||
|
||||
if(filter->g->filter_mode <= PICO_IP_MULTICAST_INCLUDE )
|
||||
{
|
||||
if(p->filter_mode <= PICO_IP_MULTICAST_INCLUDE)
|
||||
{
|
||||
ret = mcast_filter_state[filter->g->filter_mode][p->filter_mode](filter);
|
||||
}
|
||||
}
|
||||
|
||||
return (int8_t) ret;
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user