Contiki 2.5
redundancy_bloomfilter.c
Go to the documentation of this file.
1 /**
2  * \addtogroup redundancy
3  * @{
4  */
5 
6 /**
7  * \defgroup redundancy_bloomfilter Bloomfilter-based redundancy module
8  *
9  * @{
10  */
11 
12 /**
13  * \file
14  * \brief Implementation of a bloomfilter-based redundancy module
15  * \author Wolf-Bastian Poettner <poettner@ibr.cs.tu-bs.de>
16  */
17 
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h> // memset
21 
22 #include "contiki.h"
23 #include "logging.h"
24 
25 #include "hash.h"
26 #include "redundancy.h"
27 
28 /**
29  * How much RAM can we invest into detecting redundant bundles?
30  */
31 #ifdef CONF_REDUNDANCE_SIZE
32 #define REDUNDANCE_SIZE CONF_REDUNDANCE_SIZE
33 #else
34 #define REDUNDANCE_SIZE 128
35 #endif
36 
37 /**
38  * How many bloomfilter shall we use in parallel?
39  */
40 #ifdef CONF_REDUNDANCE_NUMBER
41 #define REDUNDANCE_NUMBER CONF_REDUNDANCE_NUMBER
42 #else
43 #define REDUNDANCE_NUMBER 2
44 #endif
45 
46 /**
47  * How many bundles should go into each of the filters?
48  */
49 #ifdef CONF_REDUNDANCE_LIMIT
50 #define REDUNDANCE_LIMIT CONF_REDUNDANCE_LIMIT
51 #else
52 #define REDUNDANCE_LIMIT 100
53 #endif
54 
55 #define REDUNDANCE_PER_FILTER ((REDUNDANCE_SIZE / REDUNDANCE_NUMBER) * 8)
56 
57 /**
58  * Holds the bloomfilter(s)
59  */
61 
62 /**
63  * Counts the number of bundles in a bloom filter
64  */
65 uint8_t redundance_counter = 0;
66 
67 /**
68  * Points to the filter that is currently in use
69  */
70 uint8_t redundance_pointer = 0;
71 
72 /**
73  * \brief Get the length of each bloomfilter
74  * \return Length of each bloomfilter
75  */
78 }
79 
80 /**
81  * \brief Returns the pointer to the start of a bloom filter
82  * \param filter Number of the bloomfilter
83  * \return Pointer to the filter
84  */
85 char * bloomfilter_get_start(uint8_t filter) {
86  if( filter >= REDUNDANCE_NUMBER) {
87  return NULL;
88  }
89 
90  return &redundance_filters[filter * bloomfilter_get_length()];
91 }
92 
93 /**
94  * \brief Sets a bit in a given bloom filter
95  * \param bit Offset of the bit to set
96  * \param filter Number of the bloomfilter
97  */
98 void bloomfilter_set(uint32_t bit, uint8_t filter) {
99  uint8_t offset = 0;
100  char * bloomfilter = NULL;
101 
102  bit = bit % REDUNDANCE_PER_FILTER;
103 
104  // Calculate the byte where the bit is in
105  offset = bit / 8;
106 
107  // Calculate the bit within the byte
108  bit = bit % 8;
109 
110  // Get the pointer to the beginning of the filter
111  bloomfilter = bloomfilter_get_start(filter);
112 
113  if( bloomfilter == NULL ) {
114  return;
115  }
116 
117  // Set the proper bit
118  *(bloomfilter + offset) |= 1 << bit;
119 }
120 
121 /**
122  * \brief Checks if a certain bit is set in a bloom filter
123  * \param bit Offset of the bit to check
124  * \param filter Number of the filter to look into
125  * \return 1 if set, 0 otherwise
126  */
127 uint8_t bloomfilter_get(uint32_t bit, uint8_t filter) {
128  uint8_t offset = 0;
129  char * bloomfilter = NULL;
130 
131  bit = bit % REDUNDANCE_PER_FILTER;
132 
133  // Calculate the byte where the bit is in
134  offset = bit / 8;
135 
136  // Calculate the bit within the byte
137  bit = bit % 8;
138 
139  // Get the pointer to the beginning of the filter
140  bloomfilter = bloomfilter_get_start(filter);
141 
142  if( bloomfilter == NULL ) {
143  return 0;
144  }
145 
146  if( *(bloomfilter + offset) & (1 << bit) ) {
147  return 1;
148  }
149 
150  return 0;
151 }
152 
153 /**
154  * \brief Clears the content of a bloom filter
155  * \param filter Number of the bloom filter
156  */
157 void bloomfilter_clear(uint8_t filter) {
158  memset((void *) bloomfilter_get_start(filter), 0, bloomfilter_get_length());
159 }
160 
161 /**
162  * \brief checks if bundle was delivered before
163  * \param bundlemem pointer to bundle
164  * \return 1 if bundle was delivered before, 0 otherwise
165  */
167 {
168  uint16_t hash1 = 0;
169  uint16_t hash2 = 0;
170  int i;
171 
172  // Split our bundle number into 2 hashes
173  hash1 = (bundle_number & 0x0000FFFF) >> 0;
174  hash2 = (bundle_number & 0xFFFF0000) >> 16;
175 
176  // Now go and check the filters
177  for(i=0; i<REDUNDANCE_NUMBER; i++) {
178  if( bloomfilter_get(hash1, i) && bloomfilter_get(hash2, i) ) {
179  return 1;
180  }
181  }
182 
183  // If the bundle was found in no filter, it has not been seen before
184  return 0;
185 }
186 
187 /**
188  * \brief saves the bundle in a list of delivered bundles
189  * \param bundlemem pointer to bundle
190  * \return 1 on successor 0 on error
191  */
193 {
194  uint16_t hash1 = 0;
195  uint16_t hash2 = 0;
196 
197  // Split our bundle number into 2 hashes
198  hash1 = (bundle_number & 0x0000FFFF) >> 0;
199  hash2 = (bundle_number & 0xFFFF0000) >> 16;
200 
201  // Set them in the current filter
204 
205  // Increment the number of set bundles
207 
208  // Eventually switch to the next filter, if the previous one is filled up
212  redundance_counter = 0;
213  }
214 
215  return 1;
216 }
217 
218 /**
219  * \brief Initialize the bloomfilters and various other state
220  */
222 {
223  LOG(LOGD_DTN, LOG_AGENT, LOGL_DBG, "REDUNDANCE: starting");
224 
225  // Clear the filters
227  redundance_counter = 0;
228  redundance_pointer = 0;
229 }
230 
231 const struct redundance_check redundancy_bloomfilter ={
232  "REDUNDANCE_BLOOMFILTER",
236 };
237 /** @} */
238 /** @} */