summaryrefslogtreecommitdiff
path: root/cesar/cl/src/cl_eoc_mactotei.c
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/cl/src/cl_eoc_mactotei.c')
-rw-r--r--cesar/cl/src/cl_eoc_mactotei.c328
1 files changed, 328 insertions, 0 deletions
diff --git a/cesar/cl/src/cl_eoc_mactotei.c b/cesar/cl/src/cl_eoc_mactotei.c
new file mode 100644
index 0000000000..5d940c8b2a
--- /dev/null
+++ b/cesar/cl/src/cl_eoc_mactotei.c
@@ -0,0 +1,328 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cl/src/cl_eoc_mactotei.c
+ * \brief MAC to TEI mapping for the Convergence Layer
+ * \ingroup cl
+ *
+ */
+#include "common/std.h"
+#include "cl/inc/context.h"
+#include "cl/cl_eoc_mactotei.h"
+#include "hal/arch/arch.h"
+#include "lib/stats.h"
+
+/** Keep local time updated for entry expiration purpose.
+ * \param ctx CL context
+ */
+PRIVATE void
+cl_eoc_time_update (cl_t *ctx)
+{
+ ctx->cl_eoc_mactotei_table.time_count++;
+}
+
+static inline uint
+cl_eoc_get_time (cl_t *ctx)
+{
+ return ctx->cl_eoc_mactotei_table.time_count;
+}
+
+static inline int
+cl_eoc_is_obsolete (cl_t *ctx, cl_eoc_mactotei_entry_t *entry, uint timestamp)
+{
+ if (ctx->mac_config->sta_mac_address == entry->mac_addr)
+ return 0;
+ else
+ return lesseq_mod2p32(entry->timestamp +
+ ctx->cl_eoc_mactotei_table.max_duration, timestamp);
+}
+
+/** Initialization of EoC mactotei table.
+ * \param ctx CL context
+ */
+void
+cl_eoc_mactotei_init (cl_t *ctx)
+{
+ cl_eoc_mactotei_table_t *mtt_table = &ctx->cl_eoc_mactotei_table;
+ cl_eoc_mactotei_entry_t *entry;
+ int i;
+
+ list_init (&mtt_table->ageing_list);
+ for (i = 0; i < MACTOTEI_HASHSIZE; i++)
+ list_init (&mtt_table->hashing_list[i]);
+ for (i = 0; i < MACTOTEI_NB_ENTRIES; i++)
+ {
+ entry = &mtt_table->cl_eoc_mtt_entries[i];
+ list_init_node (&entry->l_hash);
+ list_init_node (&entry->l_age);
+ entry->timestamp = i;
+ entry->reserved = 0;
+ entry->mac_addr = 0;
+ list_push_back (&mtt_table->ageing_list,&entry->l_age);
+ }
+ mtt_table->num_of_entries = 0;
+ mtt_table->time_count = 0;
+ mtt_table->max_entries = MAC_LIMITATION;
+ cl_eoc_mactotei_set_entry_duration (ctx, DEFAULT_ENTRY_AGE_SEC);
+
+ lib_stats_set_stat_value_notype ("MAC_LIMITATION",
+ &mtt_table->max_entries,
+ LIB_STATS_ACCESS_READ_WRITE,
+ LIB_STATS_DEBUG);
+}
+
+/** Search for an entry in eoc_mactotei table with the given mac address.
+ * \param ctx CL context
+ * \param mac_addr MAC address of the entry to be found in table
+ */
+cl_eoc_mactotei_entry_t *cl_eoc_mactotei_entry_find (cl_t *ctx, mac_t mac_addr)
+{
+
+ u8 index = MACTOTEI_HASHFUNC (mac_addr);
+ cl_eoc_mactotei_entry_t *entry = NULL;
+ list_node_t *list_node = NULL;
+
+ list_node = list_begin (&ctx->cl_eoc_mactotei_table.hashing_list[index]);
+
+ while (list_node != &ctx->cl_eoc_mactotei_table.hashing_list[index].nil)
+ {
+ if (list_node)
+ entry = PARENT_OF (cl_eoc_mactotei_entry_t, l_hash, list_node);
+ if (entry && (mac_addr == entry->mac_addr))
+ return entry;
+ list_node = list_next (list_node);
+ }
+
+ return NULL;
+}
+
+/** Find TEI to which to route packets according to MAC address.
+ * \param ctx CL context
+ * \param mac_addr MAC address to be mapped to TEI
+ */
+uint
+cl_eoc_mactotei_find_tei (cl_t *ctx, mac_t mac_addr)
+{
+ cl_eoc_mactotei_entry_t *entry = NULL;
+
+ entry = cl_eoc_mactotei_entry_find (ctx, mac_addr);
+ if (entry && !cl_eoc_is_obsolete (ctx, entry, cl_eoc_get_time (ctx)))
+ {
+ entry->timestamp = cl_eoc_get_time (ctx);
+ return entry->tei;
+ }
+
+ return MAC_TEI_UNASSOCIATED;
+}
+
+/** Put new MAC address in mactotei table.
+ * \param ctx CL context
+ * \param mac_addr MAC address of the packet
+ * \param tei TEI of the packet
+*/
+bool
+cl_eoc_mactotei_entry_insert (cl_t *ctx, mac_t mac_addr, uint tei)
+{
+ cl_eoc_mactotei_entry_t *entry = NULL;
+ cl_eoc_mactotei_entry_t *entry1 = NULL;
+ uint i;
+ list_node_t *list_node = NULL;
+
+ entry = cl_eoc_mactotei_entry_find (ctx, mac_addr);
+
+ if (!entry || cl_eoc_is_obsolete (ctx, entry, cl_eoc_get_time (ctx)))
+ {
+ /* Check if limit of MAC addresses is reached */
+ if (ctx->mac_config->tei == tei)
+ {
+ if (ctx->cl_eoc_mactotei_table.num_of_entries ==
+ ctx->cl_eoc_mactotei_table.max_entries)
+ {
+ ctx->cl_eoc_mactotei_table.num_of_entries = 0;
+ /* Count number of valid entries */
+ for (i = 0; i < MACTOTEI_HASHSIZE; i++)
+ {
+ list_node = list_begin (&ctx->cl_eoc_mactotei_table.hashing_list[i]);
+ while (list_node != &ctx->cl_eoc_mactotei_table.hashing_list[i].nil)
+ {
+ if (list_node)
+ entry1 = PARENT_OF (cl_eoc_mactotei_entry_t, l_hash,
+ list_node);
+ if ((entry1->tei == tei) &&
+ !cl_eoc_is_obsolete (ctx, entry1, cl_eoc_get_time (ctx)))
+ {
+ ctx->cl_eoc_mactotei_table.num_of_entries++;
+ }
+ if (ctx->cl_eoc_mactotei_table.num_of_entries ==
+ ctx->cl_eoc_mactotei_table.max_entries)
+ return false;
+ list_node = list_next (list_node);
+ }
+ }
+ }
+ ctx->cl_eoc_mactotei_table.num_of_entries++;
+ }
+ }
+
+ u8 index = MACTOTEI_HASHFUNC (mac_addr);
+ if (!entry)
+ {
+ list_node = list_next (&ctx->cl_eoc_mactotei_table.ageing_list.nil);
+ list_remove (&ctx->cl_eoc_mactotei_table.ageing_list, list_node);
+ entry = PARENT_OF (cl_eoc_mactotei_entry_t, l_age, list_node);
+ if (entry->mac_addr)
+ {
+ u8 index1 = MACTOTEI_HASHFUNC (entry->mac_addr);
+ list_remove (&ctx->cl_eoc_mactotei_table.hashing_list[index1],
+ &entry->l_hash);
+ }
+ }
+ else
+ {
+ list_remove (&ctx->cl_eoc_mactotei_table.hashing_list[index],
+ &entry->l_hash);
+ list_remove (&ctx->cl_eoc_mactotei_table.ageing_list, &entry->l_age);
+ }
+ entry->tei = tei;
+ entry->mac_addr = mac_addr;
+ entry->reserved = 0;
+ entry->timestamp = cl_eoc_get_time (ctx);
+ list_push_back (&ctx->cl_eoc_mactotei_table.ageing_list, &entry->l_age);
+ list_push_back (&ctx->cl_eoc_mactotei_table.hashing_list[index],
+ &entry->l_hash);
+ return true;
+}
+
+/** Remove all entries associated with given TEI from ageing and hashing lists
+ * of cl_eoc_mactotei_table
+ * \param ctx CL context
+ * \param tei TEI of the STA whose entries should be removed from the table
+*/
+void
+cl_eoc_mactotei_entry_remove (cl_t *ctx, uint tei)
+{
+ cl_eoc_mactotei_entry_t *entry = NULL;
+ list_node_t *list_node = NULL;
+
+ arch_dsr_lock ();
+ list_node = list_begin (&ctx->cl_eoc_mactotei_table.ageing_list);
+ while (list_node != &ctx->cl_eoc_mactotei_table.ageing_list.nil)
+ {
+ if (list_node)
+ entry = PARENT_OF (cl_eoc_mactotei_entry_t, l_age, list_node);
+ if (entry && (tei == entry->tei))
+ {
+ u8 index = MACTOTEI_HASHFUNC (entry->mac_addr);
+ list_remove (&ctx->cl_eoc_mactotei_table.hashing_list[index],
+ &entry->l_hash);
+ entry->tei = MAC_TEI_UNASSOCIATED;
+ entry->mac_addr = 0;
+ }
+ list_node = list_next (list_node);
+ }
+ arch_dsr_unlock ();
+}
+
+/** Set time during which entry will be valid
+ * \param ctx CL context
+ * \param max_dur_sec maximum duration of entry in seconds
+ */
+void
+cl_eoc_mactotei_set_entry_duration (cl_t * ctx, uint max_dur_sec)
+{
+ if ((max_dur_sec > MIN_ENTRY_AGE_SEC) && (max_dur_sec < MAX_ENTRY_AGE_SEC))
+ ctx->cl_eoc_mactotei_table.max_duration = max_dur_sec;
+}
+
+/**
+ * Remove obsolete/expired entries from the MAC to TEI
+ * \param ctx CL context
+ */
+PRIVATE void
+cl_eoc_mactotei_remove_obsolete (cl_t *ctx)
+{
+ list_node_t *list_node;
+
+ arch_dsr_lock ();
+ list_node = list_rbegin (&ctx->cl_eoc_mactotei_table.ageing_list);
+ while (list_node != &ctx->cl_eoc_mactotei_table.ageing_list.nil)
+ {
+ cl_eoc_mactotei_entry_t *entry
+ = PARENT_OF (cl_eoc_mactotei_entry_t, l_age, list_node);
+
+ if (!entry->mac_addr)
+ break;
+
+ if (cl_eoc_is_obsolete (ctx, entry, cl_eoc_get_time (ctx)))
+ {
+ /* Entry should be removed. */
+ u8 index = MACTOTEI_HASHFUNC (entry->mac_addr);
+ list_remove (&ctx->cl_eoc_mactotei_table.hashing_list[index],
+ &entry->l_hash);
+ entry->tei = MAC_TEI_UNASSOCIATED;
+ entry->mac_addr = 0;
+ }
+ list_node = list_prev (list_node);
+ }
+ arch_dsr_unlock ();
+}
+
+uint
+cl_eoc_mactotei_snapshot_create (cl_t *ctx)
+{
+ uint valid_entries_nb = 0;
+ list_node_t *list_node;
+ cl_eoc_mactotei_snapshot_entry_t *snapshot
+ = ctx->cl_eoc_mactotei_table.mactotei_snapshot;
+
+ arch_dsr_lock ();
+ list_node = list_rbegin (&ctx->cl_eoc_mactotei_table.ageing_list);
+ while (list_node != &ctx->cl_eoc_mactotei_table.ageing_list.nil)
+ {
+ cl_eoc_mactotei_entry_t *entry
+ = PARENT_OF (cl_eoc_mactotei_entry_t, l_age, list_node);
+
+ if (!entry->mac_addr)
+ break;
+
+ if (!cl_eoc_is_obsolete (ctx, entry, cl_eoc_get_time (ctx)))
+ {
+ snapshot[valid_entries_nb].mac = entry->mac_addr;
+ snapshot[valid_entries_nb].tei = entry->tei;
+ valid_entries_nb++;
+ }
+ list_node = list_prev (list_node);
+ }
+ arch_dsr_unlock ();
+
+ return valid_entries_nb;
+}
+
+mac_t
+cl_eoc_mactotei_snapshot_get_mac (cl_t *ctx, uint index)
+{
+ return ctx->cl_eoc_mactotei_table.mactotei_snapshot[index].mac;
+}
+
+void
+cl_eoc_mactotei_snapshot_get_mac_tei (cl_t *ctx, uint index, mac_t *mac,
+ uint *tei)
+{
+ cl_eoc_mactotei_snapshot_entry_t *snapshot_entry
+ = &ctx->cl_eoc_mactotei_table.mactotei_snapshot[index];
+ *mac = snapshot_entry->mac;
+ *tei = snapshot_entry->tei;
+}
+
+void
+cl_eoc_mactotei_periodic_action (cl_t *ctx)
+{
+ dbg_assert (ctx);
+ cl_eoc_time_update (ctx);
+ cl_eoc_mactotei_remove_obsolete (ctx);
+}