Reworking layer2 subsystem
[oonf.git] / src-api / subsystems / oonf_layer2.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2013, the olsr.org team - see HISTORY file
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 #include "common/avl.h"
43 #include "common/avl_comp.h"
44 #include "common/common_types.h"
45 #include "common/netaddr.h"
46 #include "config/cfg_schema.h"
47 #include "core/oonf_subsystem.h"
48 #include "subsystems/oonf_class.h"
49 #include "subsystems/oonf_layer2.h"
50
51 /* prototypes */
52 static int _init(void);
53 static void _cleanup(void);
54
55 static void _net_remove(struct oonf_layer2_net *l2net);
56 static void _neigh_remove(struct oonf_layer2_neigh *l2neigh);
57
58 /* subsystem definition */
59 struct oonf_subsystem oonf_layer2_subsystem = {
60     .name = "layer2",
61     .init = _init,
62     .cleanup = _cleanup,
63 };
64
65 /* l2neigh string keys */
66 const struct oonf_layer2_metadata oonf_layer2_metadata_neigh[OONF_LAYER2_NEIGH_COUNT] = {
67   [OONF_LAYER2_NEIGH_SIGNAL]     = { .key = OONF_LAYER2_NEIGH_SIGNAL_KEY, .unit = "dBm", .fraction = 1 },
68   [OONF_LAYER2_NEIGH_TX_BITRATE] = { .key = OONF_LAYER2_NEIGH_TX_BITRATE_KEY, .unit = "bit/s", .binary = true },
69   [OONF_LAYER2_NEIGH_RX_BITRATE] = { .key = OONF_LAYER2_NEIGH_RX_BITRATE_KEY, .unit = "bit/s", .binary = true },
70   [OONF_LAYER2_NEIGH_TX_BYTES]   = { .key = OONF_LAYER2_NEIGH_TX_BYTES_KEY, .unit = "byte", .binary = true },
71   [OONF_LAYER2_NEIGH_RX_BYTES]   = { .key = OONF_LAYER2_NEIGH_RX_BYTES_KEY, .unit = "byte", .binary = true },
72   [OONF_LAYER2_NEIGH_TX_FRAMES]  = { .key = OONF_LAYER2_NEIGH_TX_FRAMES_KEY },
73   [OONF_LAYER2_NEIGH_RX_FRAMES]  = { .key = OONF_LAYER2_NEIGH_RX_FRAMES_KEY },
74   [OONF_LAYER2_NEIGH_TX_RETRIES] = { .key = OONF_LAYER2_NEIGH_TX_RETRIES_KEY },
75   [OONF_LAYER2_NEIGH_TX_FAILED]  = { .key = OONF_LAYER2_NEIGH_TX_FAILED_KEY },
76 };
77
78 const struct oonf_layer2_metadata oonf_layer2_metadata_net[OONF_LAYER2_NET_COUNT] = {
79   [OONF_LAYER2_NET_FREQUENCY]    = { .key = OONF_LAYER2_NET_FREQUENCY_KEY, .unit = "Hz" },
80   [OONF_LAYER2_NET_MAX_BITRATE]  = { .key = OONF_LAYER2_NET_MAX_BITRATE_KEY, .unit = "bit/s", .binary = true },
81 };
82
83 /* infrastructure for l2net/l2neigh tree */
84 static struct oonf_class _l2network_class = {
85   .name = LAYER2_CLASS_NETWORK,
86   .size = sizeof(struct oonf_layer2_net),
87 };
88 static struct oonf_class _l2neighbor_class = {
89   .name = LAYER2_CLASS_NEIGHBOR,
90   .size = sizeof(struct oonf_layer2_neigh),
91 };
92
93 struct avl_tree oonf_layer2_net_tree;
94
95 static uint32_t _next_origin = 0;
96
97 /**
98  * Subsystem constructor
99  * @return always returns 0
100  */
101 static int
102 _init(void) {
103   oonf_class_add(&_l2network_class);
104   oonf_class_add(&_l2neighbor_class);
105
106   avl_init(&oonf_layer2_net_tree, avl_comp_netaddr, false);
107   return 0;
108 }
109
110 /**
111  * Subsystem destructor
112  */
113 static void
114 _cleanup(void) {
115   struct oonf_layer2_net *l2net, *l2n_it;
116
117   avl_for_each_element_safe(&oonf_layer2_net_tree, l2net, _node, l2n_it) {
118     _net_remove(l2net);
119   }
120
121   oonf_class_remove(&_l2neighbor_class);
122   oonf_class_remove(&_l2network_class);
123 }
124
125 /**
126  * Register a new originator number for layer2 data
127  * @return originator number
128  */
129 uint32_t
130 oonf_layer2_register_origin(void) {
131   _next_origin++;
132   return _next_origin;
133 }
134
135 /**
136  * Unregister an originator number and remove all layer2 data associated
137  * with this originator
138  * @param origin originator number
139  */
140 void
141 oonf_layer2_unregister_origin(uint32_t origin) {
142   struct oonf_layer2_net *l2net, *l2net_it;
143
144   avl_for_each_element_safe(&oonf_layer2_net_tree, l2net, _node, l2net_it) {
145     oonf_layer2_net_remove(l2net, origin);
146   }
147 }
148
149 /**
150  * Add a layer-2 addr to the database
151  * @param addr local mac address of addr
152  * @return layer-2 addr object
153  */
154 struct oonf_layer2_net *
155 oonf_layer2_net_add(struct netaddr *network) {
156   struct oonf_layer2_net *l2net;
157
158   l2net = avl_find_element(&oonf_layer2_net_tree, network, l2net, _node);
159   if (l2net) {
160     return l2net;
161   }
162
163   l2net = oonf_class_malloc(&_l2network_class);
164   if (!l2net) {
165     return NULL;
166   }
167
168   memcpy(&l2net->addr, network, sizeof(*network));
169   l2net->_node.key = &l2net->addr;
170   avl_insert(&oonf_layer2_net_tree, &l2net->_node);
171
172   avl_init(&l2net->neighbors, avl_comp_netaddr, false);
173   avl_init(&l2net->_ip_defaults, avl_comp_netaddr, false);
174
175   oonf_class_event(&_l2network_class, l2net, OONF_OBJECT_ADDED);
176
177   return l2net;
178 }
179
180 /**
181  * Remove all information of a certain originator from a layer-2 addr
182  * object. Remove the object if its empty and has no neighbors anymore.
183  * @param l2net layer-2 addr object
184  * @param origin originator number
185  */
186 void
187 oonf_layer2_net_remove(struct oonf_layer2_net *l2net, uint32_t origin) {
188   struct oonf_layer2_neigh *l2neigh, *l2neigh_it;
189   int i;
190
191   avl_for_each_element_safe(&l2net->neighbors, l2neigh, _node, l2neigh_it) {
192     oonf_layer2_neigh_remove(l2neigh, origin);
193   }
194
195   for (i=0; i<OONF_LAYER2_NET_COUNT; i++) {
196     if (l2net->data[i]._origin == origin) {
197       oonf_layer2_reset_value(&l2net->data[i]);
198     }
199   }
200   oonf_layer2_net_commit(l2net);
201 }
202
203 /**
204  * Commit all changes to a layer-2 addr object. This might remove the
205  * object from the database if all data has been removed from the object.
206  * @param l2net layer-2 addr object
207  * @return true if the object has been removed, false otherwise
208  */
209 bool
210 oonf_layer2_net_commit(struct oonf_layer2_net *l2net) {
211   size_t i;
212
213   if (l2net->neighbors.count > 0) {
214     oonf_class_event(&_l2network_class, l2net, OONF_OBJECT_CHANGED);
215     return false;
216   }
217
218   for (i=0; i<OONF_LAYER2_NET_COUNT; i++) {
219     if (oonf_layer2_has_value(&l2net->data[i])) {
220       oonf_class_event(&_l2network_class, l2net, OONF_OBJECT_CHANGED);
221       return false;
222     }
223   }
224
225   _net_remove(l2net);
226   return true;
227 }
228
229 /**
230  * Add a layer-2 neighbor to a addr.
231  * @param l2net layer-2 addr object
232  * @param neigh mac address of layer-2 neighbor
233  * @return layer-2 neighbor object
234  */
235 struct oonf_layer2_neigh *
236 oonf_layer2_neigh_add(struct oonf_layer2_net *l2net,
237     struct netaddr *neigh) {
238   struct oonf_layer2_neigh *l2neigh;
239
240   if (netaddr_get_address_family(neigh) != AF_MAC48
241       && netaddr_get_address_family(neigh) != AF_EUI64) {
242     return NULL;
243   }
244
245   l2neigh = oonf_layer2_neigh_get(l2net, neigh);
246   if (l2neigh) {
247     return l2neigh;
248   }
249
250   l2neigh = oonf_class_malloc(&_l2neighbor_class);
251   if (!l2neigh) {
252     return NULL;
253   }
254
255   memcpy(&l2neigh->addr, neigh, sizeof(*neigh));
256   l2neigh->_node.key = &l2neigh->addr;
257   l2neigh->network = l2net;
258
259   avl_insert(&l2net->neighbors, &l2neigh->_node);
260
261   if (netaddr_get_address_family(neigh) == AF_MAC48
262       || netaddr_get_address_family(neigh) == AF_EUI64) {
263     /* initialize ring for IP addresses of neighbor */
264     list_init_head(&l2neigh->_neigh_ring);
265   }
266
267   oonf_class_event(&_l2neighbor_class, l2neigh, OONF_OBJECT_ADDED);
268
269   return l2neigh;
270 }
271
272 /**
273  * Remove all information of a certain originator from a layer-2 neighbor
274  * object. Remove the object if its empty.
275  * @param l2neigh layer-2 neighbor object
276  * @param origin originator number
277  */
278 void
279 oonf_layer2_neigh_remove(struct oonf_layer2_neigh *l2neigh, uint32_t origin) {
280   int i;
281
282   for (i=0; i<OONF_LAYER2_NEIGH_COUNT; i++) {
283     if (l2neigh->data[i]._origin == origin) {
284       oonf_layer2_reset_value(&l2neigh->data[i]);
285     }
286   }
287   oonf_layer2_neigh_commit(l2neigh);
288 }
289
290 /**
291  * Commit all changes to a layer-2 neighbor object. This might remove the
292  * object from the database if all data has been removed from the object.
293  * @param l2neigh layer-2 neighbor object
294  * @return true if the object has been removed, false otherwise
295  */
296 bool
297 oonf_layer2_neigh_commit(struct oonf_layer2_neigh *l2neigh) {
298   size_t i;
299
300   for (i=0; i<OONF_LAYER2_NET_COUNT; i++) {
301     if (oonf_layer2_has_value(&l2neigh->data[i])) {
302       oonf_class_event(&_l2neighbor_class, l2neigh, OONF_OBJECT_CHANGED);
303       return false;
304     }
305   }
306
307   _neigh_remove(l2neigh);
308   return true;
309 }
310
311 const struct oonf_layer2_data *
312 oonf_layer2_neigh_query(const struct netaddr *l2net_addr,
313     const struct netaddr *l2neigh_addr, enum oonf_layer2_neighbor_index idx) {
314   struct oonf_layer2_net *l2net;
315   struct oonf_layer2_neigh *l2neigh;
316   struct oonf_layer2_data *data;
317
318   /* query layer2 database about neighbor */
319   l2net = oonf_layer2_net_get(l2net_addr);
320   if (l2net == NULL) {
321     return 0;
322   }
323
324   l2neigh = oonf_layer2_neigh_get(l2net, l2neigh_addr);
325   if (l2neigh == NULL) {
326     data = &l2neigh->data[idx];
327     if (oonf_layer2_has_value(data)) {
328       return data;
329     }
330   }
331
332   data = &l2neigh->network->neighdata[idx];
333   if (oonf_layer2_has_value(data)) {
334     return data;
335   }
336   return NULL;
337 }
338
339 /**
340  * Removes a layer-2 addr object from the database.
341  * @param l2net layer-2 addr object
342  */
343 static void
344 _net_remove(struct oonf_layer2_net *l2net) {
345   struct oonf_layer2_neigh *l2neigh, *l2n_it;
346
347   /* free all embedded neighbors */
348   avl_for_each_element_safe(&l2net->neighbors, l2neigh, _node, l2n_it) {
349     _neigh_remove(l2neigh);
350   }
351
352   oonf_class_event(&_l2network_class, l2net, OONF_OBJECT_REMOVED);
353
354   /* free addr */
355   avl_remove(&oonf_layer2_net_tree, &l2net->_node);
356   oonf_class_free(&_l2network_class, l2net);
357 }
358
359 /**
360  * Removes a layer-2 neighbor object from the database
361  * @param l2neigh layer-2 neighbor object
362  */
363 static void
364 _neigh_remove(struct oonf_layer2_neigh *l2neigh) {
365   struct oonf_layer2_neigh *neigh, *n_it;
366
367   /* inform user that mac entry will be removed */
368   oonf_class_event(&_l2neighbor_class, l2neigh, OONF_OBJECT_REMOVED);
369
370   /* remove all connected IP defaults */
371   list_for_each_element_safe(&l2neigh->_neigh_ring, neigh, _neigh_ring, n_it) {
372     list_remove(&neigh->_neigh_ring);
373   }
374
375   /* free resources for mac entry */
376   avl_remove(&l2neigh->network->neighbors, &l2neigh->_node);
377   oonf_class_free(&_l2neighbor_class, l2neigh);
378 }