66
77#ifndef __MTRIE_H__
88
9+ // Short routing table entry resulting from an m-trie
10+ typedef struct _mtrie_entry_t
11+ {
12+ keymask_t keymask ; // Keymask of the entry
13+ uint32_t source ; // Sources of packets in the entry
14+ } mtrie_entry_t ;
15+
916// m-Trie structure
1017typedef struct _mtrie_node_t
1118{
1219 struct _mtrie_node_t * parent ; // Our parent
1320 uint32_t bit ; // Bit represented by this Node
1421 struct _mtrie_node_t * child_0 , * child_1 , * child_X ; // Children of this Node
22+ uint32_t source ; // Source(s) of packets which "reach" this node
1523} mtrie_t ;
1624
1725// Create a new (empty) node
@@ -23,6 +31,7 @@ static inline mtrie_t *mtrie_new_node(mtrie_t *parent, uint32_t bit)
2331 node -> parent = parent ;
2432 node -> bit = bit ;
2533 node -> child_0 = node -> child_1 = node -> child_X = NULL ;
34+ node -> source = 0x0 ;
2635
2736 return node ;
2837}
@@ -69,8 +78,8 @@ static inline unsigned int mtrie_count(mtrie_t *node)
6978}
7079
7180// Extract routing table entries from a trie
72- static inline keymask_t * _get_entries (
73- mtrie_t * node , keymask_t * table , uint32_t pkey , uint32_t pmask
81+ static inline mtrie_entry_t * _get_entries (
82+ mtrie_t * node , mtrie_entry_t * table , uint32_t pkey , uint32_t pmask
7483)
7584{
7685 if (node == NULL )
@@ -81,8 +90,9 @@ static inline keymask_t* _get_entries(
8190 {
8291 // If this is a leaf then add an entry to the table representing this entry
8392 // and return a pointer to the next entry in the table.
84- table -> key = pkey ;
85- table -> mask = pmask ;
93+ table -> keymask .key = pkey ;
94+ table -> keymask .mask = pmask ;
95+ table -> source = node -> source ;
8696
8797 // Point to the next table entry
8898 table ++ ;
@@ -99,7 +109,7 @@ static inline keymask_t* _get_entries(
99109 return table ;
100110}
101111
102- static inline void mtrie_get_entries (mtrie_t * node , keymask_t * table )
112+ static inline void mtrie_get_entries (mtrie_t * node , mtrie_entry_t * table )
103113{
104114 _get_entries (node , table , 0x0 , 0x0 );
105115}
@@ -132,7 +142,7 @@ static inline mtrie_t** get_child(mtrie_t *node, uint32_t key, uint32_t mask)
132142}
133143
134144// Traverse a path through the tree, adding elements as necessary
135- static inline mtrie_t * mtrie_traverse (mtrie_t * node , uint32_t key , uint32_t mask )
145+ static inline mtrie_t * mtrie_traverse (mtrie_t * node , uint32_t key , uint32_t mask , uint32_t source )
136146{
137147 if (node -> bit ) // If not a leaf
138148 {
@@ -152,11 +162,12 @@ static inline mtrie_t* mtrie_traverse(mtrie_t *node, uint32_t key, uint32_t mask
152162 }
153163
154164 // Delegate the traversal to the child
155- return mtrie_traverse (* child , key , mask );
165+ return mtrie_traverse (* child , key , mask , source );
156166 }
157167 else
158168 {
159- // If we are a leaf then return our parent
169+ // If we are a leaf then update our source and return our parent
170+ node -> source |= source ;
160171 return node -> parent ;
161172 }
162173}
@@ -220,6 +231,59 @@ static inline bool mtrie_untraverse(mtrie_t *node, uint32_t key, uint32_t mask)
220231 }
221232}
222233
234+ static inline uint32_t get_source_from_child (mtrie_t * node ,
235+ uint32_t key ,
236+ uint32_t mask )
237+ {
238+ if (node -> bit ) // If not a leaf
239+ {
240+ // See where to turn at this node
241+ mtrie_t * * child = get_child (node , key , mask );
242+
243+ // If there is no child then the path does not exist or the given path was
244+ // invalid.
245+ if (!child || !* child )
246+ {
247+ return false;
248+ }
249+
250+ // Delegate the traversal to the child
251+ return get_source_from_child (* child , key , mask );
252+ }
253+ else
254+ {
255+ // If we are a leaf then return the source
256+ return node -> source ;
257+ }
258+ }
259+
260+ static inline void add_source_to_child (mtrie_t * node ,
261+ uint32_t key ,
262+ uint32_t mask ,
263+ uint32_t source )
264+ {
265+ if (node -> bit ) // If not a leaf
266+ {
267+ // See where to turn at this node
268+ mtrie_t * * child = get_child (node , key , mask );
269+
270+ // If there is no child then the path does not exist or the given path was
271+ // invalid.
272+ if (!child || !* child )
273+ {
274+ return ;
275+ }
276+
277+ // Delegate the traversal to the child
278+ add_source_to_child (* child , key , mask , source );
279+ }
280+ else
281+ {
282+ // If we are a leaf then modify the source
283+ node -> source |= source ;
284+ }
285+ }
286+
223287static inline void untraverse_in_child (mtrie_t * * child , uint32_t key , uint32_t mask )
224288{
225289 if (mtrie_untraverse (* child , key , mask ))
@@ -229,10 +293,13 @@ static inline void untraverse_in_child(mtrie_t **child, uint32_t key, uint32_t m
229293}
230294
231295// Insert a new entry into the trie
232- static inline void mtrie_insert (mtrie_t * root , uint32_t key , uint32_t mask )
296+ static inline void mtrie_insert (mtrie_t * root ,
297+ uint32_t key ,
298+ uint32_t mask ,
299+ uint32_t source )
233300{
234301 // Traverse a path through the trie and keep a reference to the leaf we reach
235- mtrie_t * leaf = mtrie_traverse (root , key , mask );
302+ mtrie_t * leaf = mtrie_traverse (root , key , mask , source );
236303
237304 // Attempt to find overlapping paths
238305 while (leaf )
@@ -244,12 +311,16 @@ static inline void mtrie_insert(mtrie_t *root, uint32_t key, uint32_t mask)
244311 if (* child_0 != NULL && path_exists (* child_0 , key , mask ) &&
245312 * child_1 != NULL && path_exists (* child_1 , key , mask ))
246313 {
314+ // Get the combined sources from the existing children
315+ source = get_source_from_child (* child_0 , key , mask ) |
316+ get_source_from_child (* child_1 , key , mask );
317+
247318 // Traverse the path in X and then untraverse in 0 and 1
248319 if (* child_X == NULL )
249320 {
250321 * child_X = mtrie_new_node (leaf , leaf -> bit >> 1 );
251322 }
252- mtrie_traverse (* child_X , key , mask );
323+ mtrie_traverse (* child_X , key , mask , source );
253324
254325 // Untraverse in `0' and `1'
255326 untraverse_in_child (child_0 , key , mask );
@@ -262,19 +333,31 @@ static inline void mtrie_insert(mtrie_t *root, uint32_t key, uint32_t mask)
262333 else if (* child_X != NULL && path_exists (* child_X , key , mask ) &&
263334 * child_0 != NULL && path_exists (* child_0 , key , mask ))
264335 {
336+ // Get the source for packets matching the `0'
337+ source = get_source_from_child (* child_0 , key , mask );
338+
265339 // Untraverse in `0'
266340 untraverse_in_child (child_0 , key , mask );
267341
342+ // Add the sources to X
343+ add_source_to_child (* child_X , key , mask , source );
344+
268345 // Update the key and mask
269346 key &= ~(leaf -> bit );
270347 mask &= ~(leaf -> bit );
271348 }
272349 else if (* child_X != NULL && path_exists (* child_X , key , mask ) &&
273350 * child_1 != NULL && path_exists (* child_1 , key , mask ))
274351 {
352+ // Get the source for packets matching the `1'
353+ source = get_source_from_child (* child_1 , key , mask );
354+
275355 // Untraverse in `1'
276356 untraverse_in_child (child_1 , key , mask );
277357
358+ // Add the sources to X
359+ add_source_to_child (* child_X , key , mask , source );
360+
278361 // Update the key and mask
279362 key &= ~(leaf -> bit );
280363 mask &= ~(leaf -> bit );
@@ -290,7 +373,7 @@ typedef struct _subtable
290373{
291374 unsigned int n_entries ; // Number of entries in the subtable
292375 uint32_t route ; // Route of all entries in the subtable
293- keymask_t * entries ; // Entries in the subtable
376+ mtrie_entry_t * entries ; // Entries in the subtable
294377
295378 struct _subtable * next ; // Next subtable in the chain
296379} subtable_t ;
@@ -308,7 +391,7 @@ static inline subtable_t* subtable_new(
308391
309392 // Create a new subtable of the desired size
310393 * sb = MALLOC (sizeof (subtable_t ));
311- (* sb )-> entries = MALLOC (sizeof (keymask_t ) * size );
394+ (* sb )-> entries = MALLOC (sizeof (mtrie_entry_t ) * size );
312395 (* sb )-> n_entries = size ;
313396 (* sb )-> route = route ;
314397 (* sb )-> next = NULL ;
@@ -329,8 +412,9 @@ static inline void subtable_expand(subtable_t *sb, table_t *table)
329412 // Expand the current subtable
330413 for (unsigned int i = 0 ; i < sb -> n_entries ; i ++ )
331414 {
332- next -> keymask .key = sb -> entries [i ].key ;
333- next -> keymask .mask = sb -> entries [i ].mask ;
415+ next -> keymask .key = sb -> entries [i ].keymask .key ;
416+ next -> keymask .mask = sb -> entries [i ].keymask .mask ;
417+ next -> source = sb -> entries [i ].source ;
334418 next -> route = sb -> route ;
335419
336420 next ++ ;
@@ -401,7 +485,8 @@ static inline void mtrie_minimise(table_t *table)
401485 // Add to the trie
402486 uint32_t key = table -> entries [j ].keymask .key ;
403487 uint32_t mask = table -> entries [j ].keymask .mask ;
404- mtrie_insert (trie , key , mask );
488+ uint32_t source = table -> entries [j ].source ;
489+ mtrie_insert (trie , key , mask , source );
405490 }
406491 }
407492
0 commit comments