36ec9621a6904744a96ad3632aa1b3983dcdc352
[oonf.git] / src / base / oonf_layer2.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon version 2 (olsrd2)
4  * Copyright (c) 2004-2015, 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 /**
43  * @file
44  */
45
46 #include <oonf/libcommon/avl.h>
47 #include <oonf/libcommon/avl_comp.h>
48 #include <oonf/oonf.h>
49 #include <oonf/libcommon/json.h>
50 #include <oonf/libcommon/netaddr.h>
51 #include <oonf/libconfig/cfg_schema.h>
52 #include <oonf/libcore/oonf_subsystem.h>
53 #include <oonf/base/oonf_class.h>
54 #include <oonf/base/os_interface.h>
55
56 #include <oonf/base/oonf_layer2.h>
57
58 /* Definitions */
59 #define LOG_LAYER2 _oonf_layer2_subsystem.logging
60
61 /* prototypes */
62 static int _init(void);
63 static void _cleanup(void);
64
65 static void _net_remove(struct oonf_layer2_net *l2net);
66 static void _neigh_remove(struct oonf_layer2_neigh *l2neigh);
67
68 /* subsystem definition */
69 static const char *_dependencies[] = {
70   OONF_CLASS_SUBSYSTEM,
71   OONF_OS_INTERFACE_SUBSYSTEM,
72 };
73
74 static struct oonf_subsystem _oonf_layer2_subsystem = {
75   .name = OONF_LAYER2_SUBSYSTEM,
76   .dependencies = _dependencies,
77   .dependencies_count = ARRAYSIZE(_dependencies),
78   .init = _init,
79   .cleanup = _cleanup,
80 };
81 DECLARE_OONF_PLUGIN(_oonf_layer2_subsystem);
82
83 /* layer2 neighbor metadata */
84 static const struct oonf_layer2_metadata _metadata_neigh[OONF_LAYER2_NEIGH_COUNT] = {
85   [OONF_LAYER2_NEIGH_TX_SIGNAL] = { .key = "tx_signal", .type = OONF_LAYER2_INTEGER_DATA, .unit = "dBm", .scaling = 1000 },
86   [OONF_LAYER2_NEIGH_RX_SIGNAL] = { .key = "rx_signal", .type = OONF_LAYER2_INTEGER_DATA, .unit = "dBm", .scaling = 1000 },
87   [OONF_LAYER2_NEIGH_TX_SNR] = { .key = "tx_snr", .type = OONF_LAYER2_INTEGER_DATA, .unit = "dB", .scaling = 1000 },
88   [OONF_LAYER2_NEIGH_RX_SNR] = { .key = "rx_snr", .type = OONF_LAYER2_INTEGER_DATA, .unit = "dB", .scaling = 1000 },
89   [OONF_LAYER2_NEIGH_TX_BITRATE] = { .key = "tx_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s", .scaling = 1 },
90   [OONF_LAYER2_NEIGH_RX_BITRATE] = { .key = "rx_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s", .scaling = 1 },
91   [OONF_LAYER2_NEIGH_TX_MAX_BITRATE] = { .key = "tx_max_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s", .scaling = 1 },
92   [OONF_LAYER2_NEIGH_RX_MAX_BITRATE] = { .key = "rx_max_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s", .scaling = 1 },
93   [OONF_LAYER2_NEIGH_TX_BYTES] = { .key = "tx_bytes", .type = OONF_LAYER2_INTEGER_DATA, .unit = "byte", .scaling = 1 },
94   [OONF_LAYER2_NEIGH_RX_BYTES] = { .key = "rx_bytes", .type = OONF_LAYER2_INTEGER_DATA, .unit = "byte", .scaling = 1 },
95   [OONF_LAYER2_NEIGH_TX_FRAMES] = { .key = "tx_frames", .type = OONF_LAYER2_INTEGER_DATA, .scaling = 1 },
96   [OONF_LAYER2_NEIGH_RX_FRAMES] = { .key = "rx_frames", .type = OONF_LAYER2_INTEGER_DATA, .scaling = 1 },
97   [OONF_LAYER2_NEIGH_TX_THROUGHPUT] = { .key = "tx_throughput", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s", .scaling = 1 },
98   [OONF_LAYER2_NEIGH_RX_THROUGHPUT] = { .key = "rx_throughput", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s", .scaling = 1 },
99   [OONF_LAYER2_NEIGH_TX_RETRIES] = { .key = "tx_retries", .type = OONF_LAYER2_INTEGER_DATA, .scaling = 1 },
100   [OONF_LAYER2_NEIGH_RX_RETRIES] = { .key = "rx_retries", .type = OONF_LAYER2_INTEGER_DATA, .scaling = 1 },
101   [OONF_LAYER2_NEIGH_TX_FAILED] = { .key = "tx_failed", .type = OONF_LAYER2_INTEGER_DATA, .scaling = 1 },
102   [OONF_LAYER2_NEIGH_RX_FAILED] = { .key = "rx_failed", .type = OONF_LAYER2_INTEGER_DATA, .scaling = 1 },
103   [OONF_LAYER2_NEIGH_TX_RLQ] = { .key = "tx_rlq", .type = OONF_LAYER2_INTEGER_DATA, .scaling = 1 },
104   [OONF_LAYER2_NEIGH_RX_RLQ] = { .key = "rx_rlq", .type = OONF_LAYER2_INTEGER_DATA, .scaling = 1 },
105   [OONF_LAYER2_NEIGH_RX_BC_BITRATE] = { .key = "rx_bc_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s", .scaling = 1 },
106   [OONF_LAYER2_NEIGH_RX_BC_LOSS] = { .key = "rx_bc_loss", .type = OONF_LAYER2_INTEGER_DATA, .scaling = 1000 },
107   [OONF_LAYER2_NEIGH_LATENCY] = { .key = "latency", .type = OONF_LAYER2_INTEGER_DATA, .unit = "s", .scaling = 1000000 },
108   [OONF_LAYER2_NEIGH_RESOURCES] = { .key = "resources", .type = OONF_LAYER2_INTEGER_DATA, .scaling = 1 },
109   [OONF_LAYER2_NEIGH_RADIO_HOPCOUNT] = { .key = "radio_hopcount", .type = OONF_LAYER2_INTEGER_DATA, .scaling = 1 },
110   [OONF_LAYER2_NEIGH_IP_HOPCOUNT] = { .key = "ip_hopcount", .type = OONF_LAYER2_INTEGER_DATA, .scaling = 1 },
111 };
112
113 /* layer2 network metadata */
114 static const struct oonf_layer2_metadata _metadata_net[OONF_LAYER2_NET_COUNT] = {
115   [OONF_LAYER2_NET_FREQUENCY_1] = { .key = "frequency1", .type = OONF_LAYER2_INTEGER_DATA, .unit = "Hz", .scaling = 1 },
116   [OONF_LAYER2_NET_FREQUENCY_2] = { .key = "frequency2", .type = OONF_LAYER2_INTEGER_DATA, .unit = "Hz", .scaling = 1 },
117   [OONF_LAYER2_NET_BANDWIDTH_1] = { .key = "bandwidth1", .type = OONF_LAYER2_INTEGER_DATA, .unit = "Hz", .scaling = 1 },
118   [OONF_LAYER2_NET_BANDWIDTH_2] = { .key = "bandwidth2", .type = OONF_LAYER2_INTEGER_DATA, .unit = "Hz", .scaling = 1 },
119   [OONF_LAYER2_NET_NOISE] = { .key = "noise", .type = OONF_LAYER2_INTEGER_DATA, .unit = "dBm", .scaling = 1000 },
120   [OONF_LAYER2_NET_CHANNEL_ACTIVE] = { .key = "ch_active",
121     .type = OONF_LAYER2_INTEGER_DATA,
122     .unit = "s",
123     .scaling = 1000000000 },
124   [OONF_LAYER2_NET_CHANNEL_BUSY] = { .key = "ch_busy", .type = OONF_LAYER2_INTEGER_DATA, .unit = "s", .scaling = 1000000000 },
125   [OONF_LAYER2_NET_CHANNEL_RX] = { .key = "ch_rx", .type = OONF_LAYER2_INTEGER_DATA, .unit = "s", .scaling = 1000000000 },
126   [OONF_LAYER2_NET_CHANNEL_TX] = { .key = "ch_tx", .type = OONF_LAYER2_INTEGER_DATA, .unit = "s", .scaling = 1000000000 },
127   [OONF_LAYER2_NET_TX_BC_BITRATE] = { .key = "tx_bc_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s", .scaling = 1 },
128   [OONF_LAYER2_NET_MTU] = { .key = "mtu", .type = OONF_LAYER2_INTEGER_DATA, .unit = "byte", .scaling = 1 },
129   [OONF_LAYER2_NET_MCS_BY_PROBING] = { .key = "mcs_by_probing", .type = OONF_LAYER2_BOOLEAN_DATA },
130   [OONF_LAYER2_NET_RX_ONLY_UNICAST] = { .key = "rx_only_unicast", .type = OONF_LAYER2_BOOLEAN_DATA },
131   [OONF_LAYER2_NET_TX_ONLY_UNICAST] = { .key = "tx_only_unicast", .type = OONF_LAYER2_BOOLEAN_DATA },
132   [OONF_LAYER2_NET_RADIO_MULTIHOP] = { .key = "radio_multihop", .type = OONF_LAYER2_BOOLEAN_DATA },
133   [OONF_LAYER2_NET_BAND_UP_DOWN] = { .key = "band_updown", .type = OONF_LAYER2_BOOLEAN_DATA },
134 };
135
136 static const char *_network_type[OONF_LAYER2_TYPE_COUNT] = {
137   [OONF_LAYER2_TYPE_UNDEFINED] = "undefined",
138   [OONF_LAYER2_TYPE_WIRELESS] = "wireless",
139   [OONF_LAYER2_TYPE_ETHERNET] = "ethernet",
140   [OONF_LAYER2_TYPE_TUNNEL] = "tunnel",
141 };
142
143 static const char *_data_comparators[OONF_LAYER2_DATA_CMP_COUNT] = {
144   [OONF_LAYER2_DATA_CMP_EQUALS] = "==",
145   [OONF_LAYER2_DATA_CMP_NOT_EQUALS] = "!=",
146   [OONF_LAYER2_DATA_CMP_LESSER] = "<",
147   [OONF_LAYER2_DATA_CMP_LESSER_OR_EQUALS] = "<=",
148   [OONF_LAYER2_DATA_CMP_GREATER] = ">",
149   [OONF_LAYER2_DATA_CMP_GREATER_OR_EQUALS] = ">=",
150 };
151
152 static const char *_data_types[OONF_LAYER2_DATA_TYPE_COUNT] = {
153   [OONF_LAYER2_INTEGER_DATA] = "integer",
154   [OONF_LAYER2_BOOLEAN_DATA] = "boolean",
155   [OONF_LAYER2_NETWORK_DATA] = "network",
156 };
157
158 /* infrastructure for l2net/l2neigh tree */
159 static struct oonf_class _l2network_class = {
160   .name = LAYER2_CLASS_NETWORK,
161   .size = sizeof(struct oonf_layer2_net),
162 };
163 static struct oonf_class _l2neighbor_class = {
164   .name = LAYER2_CLASS_NEIGHBOR,
165   .size = sizeof(struct oonf_layer2_neigh),
166 };
167 static struct oonf_class _l2dst_class = {
168   .name = LAYER2_CLASS_DESTINATION,
169   .size = sizeof(struct oonf_layer2_destination),
170 };
171 static struct oonf_class _l2net_addr_class = {
172   .name = LAYER2_CLASS_NETWORK_ADDRESS,
173   .size = sizeof(struct oonf_layer2_peer_address),
174 };
175 static struct oonf_class _l2neigh_addr_class = {
176   .name = LAYER2_CLASS_NEIGHBOR_ADDRESS,
177   .size = sizeof(struct oonf_layer2_neighbor_address),
178 };
179 static struct oonf_class _lid_class = {
180   .name = LAYER2_CLASS_LID,
181   .size = sizeof(struct oonf_layer2_lid),
182 };
183
184 static struct avl_tree _oonf_layer2_net_tree;
185
186 static struct avl_tree _oonf_originator_tree;
187
188 static struct avl_tree _local_peer_ips_tree;
189
190 static struct avl_tree _lid_tree;
191
192 static uint32_t _lid_originator_count;
193
194 /**
195  * Subsystem constructor
196  * @return always returns 0
197  */
198 static int
199 _init(void) {
200   oonf_class_add(&_l2network_class);
201   oonf_class_add(&_l2neighbor_class);
202   oonf_class_add(&_l2dst_class);
203   oonf_class_add(&_l2net_addr_class);
204   oonf_class_add(&_l2neigh_addr_class);
205   oonf_class_add(&_lid_class);
206
207   avl_init(&_oonf_layer2_net_tree, avl_comp_strcasecmp, false);
208   avl_init(&_oonf_originator_tree, avl_comp_strcasecmp, false);
209   avl_init(&_local_peer_ips_tree, avl_comp_netaddr, true);
210   avl_init(&_lid_tree, avl_comp_netaddr, false);
211
212   _lid_originator_count = 0;
213   return 0;
214 }
215
216 /**
217  * Subsystem destructor
218  */
219 static void
220 _cleanup(void) {
221   struct oonf_layer2_net *l2net, *l2n_it;
222   struct oonf_layer2_lid *lid, *lid_it;
223
224   avl_for_each_element_safe(&_oonf_layer2_net_tree, l2net, _node, l2n_it) {
225     _net_remove(l2net);
226   }
227   avl_for_each_element_safe(&_lid_tree, lid, _node, lid_it) {
228     avl_remove(&_lid_tree, &lid->_node);
229     oonf_class_free(&_lid_class, lid);
230   }
231
232   oonf_class_remove(&_lid_class);
233   oonf_class_remove(&_l2neigh_addr_class);
234   oonf_class_remove(&_l2net_addr_class);
235   oonf_class_remove(&_l2dst_class);
236   oonf_class_remove(&_l2neighbor_class);
237   oonf_class_remove(&_l2network_class);
238 }
239
240 /**
241  * Register a new data originator number for layer2 data
242  * @param origin layer2 originator
243  */
244 void
245 oonf_layer2_origin_add(struct oonf_layer2_origin *origin) {
246   origin->_node.key = origin->name;
247   avl_insert(&_oonf_originator_tree, &origin->_node);
248
249   if (origin->lid) {
250     origin->lid_index = _lid_originator_count;
251     _lid_originator_count++;
252   }
253 }
254
255 /**
256  * Removes all layer2 data associated with this data originator
257  * @param origin originator
258  */
259 void
260 oonf_layer2_origin_remove(struct oonf_layer2_origin *origin) {
261   struct oonf_layer2_net *l2net, *l2net_it;
262
263   if (!avl_is_node_added(&origin->_node)) {
264     return;
265   }
266
267   avl_for_each_element_safe(&_oonf_layer2_net_tree, l2net, _node, l2net_it) {
268     oonf_layer2_net_remove(l2net, origin);
269   }
270
271   avl_remove(&_oonf_originator_tree, &origin->_node);
272 }
273
274 /**
275  * Parse a string into a layer2 data object
276  * @param value target buffer for layer2 data
277  * @param meta metadata for layer2 data
278  * @param input input string
279  * @return -1 if an error happened, 0 otherwise
280  */
281 int
282 oonf_layer2_data_parse_string(
283   union oonf_layer2_value *value, const struct oonf_layer2_metadata *meta, const char *input) {
284   memset(value, 0, sizeof(*value));
285
286   switch (meta->type) {
287     case OONF_LAYER2_INTEGER_DATA:
288       return isonumber_to_s64(&value->integer, input, meta->scaling);
289
290     case OONF_LAYER2_BOOLEAN_DATA:
291       if (!cfg_is_bool(input)) {
292         return -1;
293       }
294       value->boolean = cfg_get_bool(input);
295       return 0;
296
297     default:
298       return -1;
299   }
300 }
301
302 /**
303  * Convert a layer2 data object into a string representation
304  * @param buffer destination string buffer
305  * @param length length of string buffer
306  * @param data layer2 data
307  * @param meta layer2 metadata
308  * @param raw true for raw conversion (switch of isoprefix conversion)
309  * @return pointer to output buffer, NULL if an error happened
310  */
311 const char *
312 oonf_layer2_data_to_string(
313   char *buffer, size_t length, const struct oonf_layer2_data *data, const struct oonf_layer2_metadata *meta, bool raw) {
314   struct isonumber_str iso_str;
315
316   switch (meta->type) {
317     case OONF_LAYER2_INTEGER_DATA:
318       if (!isonumber_from_s64(&iso_str, data->_value.integer, meta->unit, meta->scaling, raw)) {
319         return NULL;
320       }
321       return strscpy(buffer, iso_str.buf, length);
322
323     case OONF_LAYER2_BOOLEAN_DATA:
324       return strscpy(buffer, json_getbool(data->_value.boolean), length);
325
326     default:
327       return NULL;
328   }
329 }
330
331 /**
332  * (Over)write the value of a layer2 data object
333  * @param l2data layer2 data object
334  * @param origin origin of new data
335  * @param meta metainformation of data
336  * @param input new data value
337  * @return true if data changed, false otherwise
338  */
339 bool
340 oonf_layer2_data_set(struct oonf_layer2_data *l2data, const struct oonf_layer2_origin *origin,
341   const struct oonf_layer2_metadata *meta, const union oonf_layer2_value *input) {
342   bool changed = false;
343
344   if (meta == NULL) {
345     OONF_ASSERT(l2data->_meta != NULL, LOG_LAYER2, "Tried to set layer2 data without metadata (origin: %s)", origin->name);
346     meta = l2data->_meta;
347   }
348   if (l2data->_meta == NULL || l2data->_origin == NULL || l2data->_origin == origin ||
349       l2data->_origin->priority < origin->priority) {
350     changed = l2data->_meta != meta || memcmp(&l2data->_value, input, sizeof(*input)) != 0;
351     memcpy(&l2data->_value, input, sizeof(*input));
352     l2data->_meta = meta;
353     l2data->_origin = origin;
354   }
355   return changed;
356 }
357
358 /**
359  * Set the value of a layer-2 data object
360  * @param l2data layer-2 data object
361  * @param origin originator of value
362  * @param integer new value for data object
363  * @param scaling scaling of the fixpoint interger arithmetics, 0 for same as metadata
364  * @return true if value was overwrite, false otherwise
365  */
366 bool
367 oonf_layer2_data_set_int64(struct oonf_layer2_data *l2data, const struct oonf_layer2_origin *origin,
368     const struct oonf_layer2_metadata *meta, int64_t integer, uint64_t scaling) {
369   union oonf_layer2_value value = { 0 };
370
371   if (meta == NULL) {
372     OONF_ASSERT(l2data->_meta != NULL, LOG_LAYER2, "Tried to set layer2 data without metadata (origin: %s)", origin->name);
373     meta = l2data->_meta;
374   }
375   if (scaling == 0) {
376     value.integer = integer;
377   }
378   else if (scaling > meta->scaling) {
379     value.integer = integer / (scaling / meta->scaling);
380   }
381   else {
382     value.integer = integer * (meta->scaling / scaling);
383   }
384
385   return oonf_layer2_data_set(l2data, origin, meta, &value);
386 }
387
388 /**
389  * Compare two layer2 data objects
390  * @param left left parameter for comparator
391  * @param right right parameter for comparator
392  * @param comparator comparator type
393  * @param data_type data type for comparison
394  * @return comparator result, false if not valid
395  *   (e.g. comparing different types of data)
396  */
397 bool
398 oonf_layer2_data_compare(const union oonf_layer2_value *left, const union oonf_layer2_value *right,
399   enum oonf_layer2_data_comparator_type comparator, enum oonf_layer2_data_type data_type) {
400   int result;
401
402   switch (data_type) {
403     case OONF_LAYER2_INTEGER_DATA:
404       if (left->integer > right->integer) {
405         result = 1;
406       }
407       else if (left->integer < right->integer) {
408         result = -1;
409       }
410       else {
411         result = 0;
412       }
413       break;
414     case OONF_LAYER2_BOOLEAN_DATA:
415       result = memcmp(&left->boolean, &right->boolean, sizeof(left->boolean));
416       break;
417     case OONF_LAYER2_NETWORK_DATA:
418       result = memcmp(&left->addr, &right->addr, sizeof(left->addr));
419       break;
420     default:
421       return false;
422   }
423
424   switch (comparator) {
425     case OONF_LAYER2_DATA_CMP_EQUALS:
426       return result == 0;
427     case OONF_LAYER2_DATA_CMP_NOT_EQUALS:
428       return result != 0;
429     case OONF_LAYER2_DATA_CMP_LESSER:
430       return result < 0;
431     case OONF_LAYER2_DATA_CMP_LESSER_OR_EQUALS:
432       return result <= 0;
433     case OONF_LAYER2_DATA_CMP_GREATER:
434       return result > 0;
435     case OONF_LAYER2_DATA_CMP_GREATER_OR_EQUALS:
436       return result >= 0;
437     default:
438       return false;
439   }
440 }
441
442 /**
443  * Get comparator type from string
444  * @param string string (C) representation of comparator
445  * @return comparator type
446  */
447 enum oonf_layer2_data_comparator_type
448 oonf_layer2_data_get_comparator(const char *string)
449 {
450   enum oonf_layer2_data_comparator_type i;
451
452   for (i = 0; i < OONF_LAYER2_DATA_CMP_COUNT; i++) {
453     if (strcmp(string, _data_comparators[i]) == 0) {
454       return i;
455     }
456   }
457   return OONF_LAYER2_DATA_CMP_ILLEGAL;
458 }
459
460 /**
461  * @param type layer2 comparator type
462  * @return string representation of comparator
463  */
464 const char *
465 oonf_layer2_data_get_comparator_string(enum oonf_layer2_data_comparator_type type) {
466   return _data_comparators[type];
467 }
468
469 /**
470  * @param meta type index of layer2 metadata
471  * @return the string name of a layer2 data type
472  */
473 const char *
474 oonf_layer2_data_get_type_string(const struct oonf_layer2_metadata *meta) {
475   static const char NONE[] = "NONE";
476   if (!meta) {
477     return NONE;
478   }
479   return _data_types[meta->type];
480 }
481
482 /**
483  * Add a layer-2 network to the database
484  * @param ifname name of interface
485  * @return layer-2 network object
486  */
487 struct oonf_layer2_net *
488 oonf_layer2_net_add(const char *ifname) {
489   struct oonf_layer2_net *l2net;
490   enum oonf_layer2_network_index netidx;
491   enum oonf_layer2_neighbor_index neighidx;
492
493   if (!ifname) {
494     return NULL;
495   }
496
497   l2net = avl_find_element(&_oonf_layer2_net_tree, ifname, l2net, _node);
498   if (l2net) {
499     return l2net;
500   }
501
502   l2net = oonf_class_malloc(&_l2network_class);
503   if (!l2net) {
504     return NULL;
505   }
506
507   /* initialize key */
508   strscpy(l2net->name, ifname, sizeof(l2net->name));
509
510   /* add to global l2net tree */
511   l2net->_node.key = l2net->name;
512   avl_insert(&_oonf_layer2_net_tree, &l2net->_node);
513
514   /* initialize tree of neighbors, ips and proxies */
515   avl_init(&l2net->neighbors, oonf_layer2_avlcmp_neigh_key, false);
516   avl_init(&l2net->local_peer_ips, avl_comp_netaddr, false);
517   avl_init(&l2net->remote_neighbor_ips, avl_comp_netaddr, true);
518
519   /* initialize interface listener */
520   l2net->if_listener.name = l2net->name;
521   os_interface_add(&l2net->if_listener);
522
523   /* initialize data sections */
524   for (netidx=0; netidx<OONF_LAYER2_NET_COUNT; netidx++) {
525     l2net->data[netidx]._meta = oonf_layer2_net_metadata_get(netidx);
526   }
527   for (neighidx=0; neighidx<OONF_LAYER2_NEIGH_COUNT; neighidx++) {
528     l2net->neighdata[neighidx]._meta = oonf_layer2_neigh_metadata_get(neighidx);
529   }
530
531   oonf_class_event(&_l2network_class, l2net, OONF_OBJECT_ADDED);
532
533   return l2net;
534 }
535
536 /**
537  * Remove all data objects of a certain originator from a layer-2 network
538  * object.
539  * @param l2net layer-2 addr object
540  * @param origin originator number
541  * @param cleanup_neigh true to cleanup neighbor data too
542  * @return true if a value was removed, false otherwise
543  */
544 bool
545 oonf_layer2_net_cleanup(struct oonf_layer2_net *l2net, const struct oonf_layer2_origin *origin, bool cleanup_neigh) {
546   struct oonf_layer2_neigh *l2neigh;
547   bool changed = false;
548   int i;
549
550   for (i = 0; i < OONF_LAYER2_NET_COUNT; i++) {
551     if (l2net->data[i]._origin == origin) {
552       oonf_layer2_data_reset(&l2net->data[i]);
553       changed = true;
554     }
555   }
556   for (i = 0; i < OONF_LAYER2_NEIGH_COUNT; i++) {
557     if (l2net->neighdata[i]._origin == origin) {
558       oonf_layer2_data_reset(&l2net->neighdata[i]);
559       changed = true;
560     }
561   }
562
563   if (cleanup_neigh) {
564     avl_for_each_element(&l2net->neighbors, l2neigh, _node) {
565       changed |= oonf_layer2_neigh_cleanup(l2neigh, origin);
566     }
567   }
568   return changed;
569 }
570
571 /**
572  * Remove all information of a certain originator from a layer-2 addr
573  * object. Remove the object if its empty and has no neighbors anymore.
574  * @param l2net layer-2 addr object
575  * @param origin originator identifier
576  * @return true if something changed, false otherwise
577  */
578 bool
579 oonf_layer2_net_remove(struct oonf_layer2_net *l2net, const struct oonf_layer2_origin *origin) {
580   struct oonf_layer2_neigh *l2neigh, *l2neigh_it;
581   bool changed = false;
582
583   if (!avl_is_node_added(&l2net->_node)) {
584     return false;
585   }
586
587   avl_for_each_element_safe(&l2net->neighbors, l2neigh, _node, l2neigh_it) {
588     if (oonf_layer2_neigh_remove(l2neigh, origin)) {
589       changed = true;
590     }
591   }
592
593   if (oonf_layer2_net_cleanup(l2net, origin, false)) {
594     changed = true;
595   }
596
597   if (changed) {
598     oonf_layer2_net_commit(l2net);
599   }
600   return changed;
601 }
602
603 /**
604  * Commit all changes to a layer-2 addr object. This might remove the
605  * object from the database if all data has been removed from the object.
606  * @param l2net layer-2 addr object
607  * @return true if the object has been removed, false otherwise
608  */
609 bool
610 oonf_layer2_net_commit(struct oonf_layer2_net *l2net) {
611   size_t i;
612
613   if (l2net->neighbors.count > 0) {
614     oonf_class_event(&_l2network_class, l2net, OONF_OBJECT_CHANGED);
615     return false;
616   }
617
618   for (i = 0; i < OONF_LAYER2_NET_COUNT; i++) {
619     if (oonf_layer2_data_has_value(&l2net->data[i])) {
620       oonf_class_event(&_l2network_class, l2net, OONF_OBJECT_CHANGED);
621       return false;
622     }
623   }
624
625   for (i = 0; i < OONF_LAYER2_NEIGH_COUNT; i++) {
626     if (oonf_layer2_data_has_value(&l2net->neighdata[i])) {
627       oonf_class_event(&_l2network_class, l2net, OONF_OBJECT_CHANGED);
628       return false;
629     }
630   }
631
632   _net_remove(l2net);
633   return true;
634 }
635
636 /**
637  * Relabel all network data (including neighbor data)
638  * of one origin to another one
639  * @param l2net layer2 network object
640  * @param new_origin new origin
641  * @param old_origin old origin to overwrite
642  */
643 void
644 oonf_layer2_net_relabel(struct oonf_layer2_net *l2net, const struct oonf_layer2_origin *new_origin,
645   const struct oonf_layer2_origin *old_origin) {
646   struct oonf_layer2_neigh *l2neigh;
647   struct oonf_layer2_peer_address *peer_ip;
648   size_t i;
649
650   for (i = 0; i < OONF_LAYER2_NET_COUNT; i++) {
651     if (oonf_layer2_data_get_origin(&l2net->data[i]) == old_origin) {
652       oonf_layer2_data_set_origin(&l2net->data[i], new_origin);
653     }
654   }
655
656   for (i = 0; i < OONF_LAYER2_NEIGH_COUNT; i++) {
657     if (oonf_layer2_data_get_origin(&l2net->neighdata[i]) == old_origin) {
658       oonf_layer2_data_set_origin(&l2net->neighdata[i], new_origin);
659     }
660   }
661
662   avl_for_each_element(&l2net->local_peer_ips, peer_ip, _net_node) {
663     if (peer_ip->origin == old_origin) {
664       peer_ip->origin = new_origin;
665     }
666   }
667
668   avl_for_each_element(&l2net->neighbors, l2neigh, _node) {
669     oonf_layer2_neigh_relabel(l2neigh, new_origin, old_origin);
670   }
671 }
672
673 /**
674  * Add an IP address or prefix to a layer-2 interface. This represents
675  * an address of the local radio or modem.
676  * @param l2net layer-2 network object
677  * @param ip ip address or prefix
678  * @return layer2 ip address object, NULL if out of memory
679  */
680 struct oonf_layer2_peer_address *
681 oonf_layer2_net_add_ip(
682   struct oonf_layer2_net *l2net, const struct oonf_layer2_origin *origin, const struct netaddr *ip) {
683   struct oonf_layer2_peer_address *l2addr;
684
685   l2addr = oonf_layer2_net_get_local_ip(l2net, ip);
686   if (!l2addr) {
687     l2addr = oonf_class_malloc(&_l2net_addr_class);
688     if (!l2addr) {
689       return NULL;
690     }
691
692     /* copy data */
693     memcpy(&l2addr->ip, ip, sizeof(*ip));
694
695     /* set back reference */
696     l2addr->l2net = l2net;
697
698     /* add to tree */
699     l2addr->_net_node.key = &l2addr->ip;
700     avl_insert(&l2net->local_peer_ips, &l2addr->_net_node);
701
702     l2addr->_global_node.key = &l2addr->ip;
703     avl_insert(&_local_peer_ips_tree, &l2addr->_global_node);
704
705     oonf_class_event(&_l2net_addr_class, l2addr, OONF_OBJECT_ADDED);
706   }
707
708   l2addr->origin = origin;
709   return l2addr;
710 }
711
712 /**
713  * Remove a peer IP address from a layer2 network
714  * @param ip ip address or prefix
715  * @param origin origin of IP address
716  * @return 0 if IP was removed, -1 if it was registered to a different origin
717  */
718 int
719 oonf_layer2_net_remove_ip(struct oonf_layer2_peer_address *ip, const struct oonf_layer2_origin *origin) {
720   if (ip->origin != origin) {
721     return -1;
722   }
723
724   oonf_class_event(&_l2net_addr_class, ip, OONF_OBJECT_REMOVED);
725
726   avl_remove(&ip->l2net->local_peer_ips, &ip->_net_node);
727   avl_remove(&_local_peer_ips_tree, &ip->_global_node);
728   oonf_class_free(&_l2net_addr_class, ip);
729   return 0;
730 }
731
732 /**
733  * Look for the best matching prefix in all layer2 neighbor addresses
734  * that contains a specific address
735  * @param addr ip address to look for
736  * @return layer2 neighbor address object, NULL if no match was found
737  */
738 struct oonf_layer2_neighbor_address *
739 oonf_layer2_net_get_best_neighbor_match(const struct netaddr *addr) {
740   struct oonf_layer2_neighbor_address *best_match, *l2addr;
741   struct oonf_layer2_neigh *l2neigh;
742   struct oonf_layer2_net *l2net;
743   int prefix_length;
744
745   prefix_length = 256;
746   best_match = NULL;
747
748   avl_for_each_element(&_oonf_layer2_net_tree, l2net, _node) {
749     avl_for_each_element(&l2net->neighbors, l2neigh, _node) {
750       avl_for_each_element(&l2neigh->remote_neighbor_ips, l2addr, _neigh_node) {
751         if (netaddr_is_in_subnet(&l2addr->ip, addr) && netaddr_get_prefix_length(&l2addr->ip) < prefix_length) {
752           best_match = l2addr;
753           prefix_length = netaddr_get_prefix_length(&l2addr->ip);
754         }
755       }
756     }
757   }
758   return best_match;
759 }
760
761 /**
762  * Generate a layer2 key based on an originator and a MAC. Enumerate
763  * new keys without explicitly storing them.
764  * @param key destination buffer for key
765  * @param origin originator for link-id creation
766  * @param mac mac address part of key
767  * @return -1 if an error happened, 0 otherwise
768  */
769 int
770 oonf_layer2_neigh_generate_lid(struct oonf_layer2_neigh_key *key,
771     struct oonf_layer2_origin *origin, const struct netaddr *mac) {
772   struct oonf_layer2_lid *lid;
773   uint32_t u32;
774
775   if (!origin->lid) {
776     return -1;
777   }
778
779   if (netaddr_get_address_family(mac) != AF_MAC48 && netaddr_get_address_family(mac) != AF_EUI64) {
780     return -1;
781   }
782
783   if (!(lid = avl_find_element(&_lid_tree, mac, lid, _node))) {
784     lid = oonf_class_malloc(&_lid_class);
785     if (!lid) {
786       return -1;
787     }
788
789     memcpy(&lid->mac, mac, sizeof(*mac));
790     lid->_node.key = &lid->mac;
791     avl_insert(&_lid_tree, &lid->_node);
792     lid->next_id = 1;
793   }
794
795   memset(key, 0, sizeof(*key));
796
797   /* copy mac */
798   memcpy(&key->addr, mac, sizeof(*mac));
799
800   /* TODO: make LID length configurable */
801
802   /* generate new link-id */
803   u32 = htonl(lid->next_id);
804   memcpy(&key->link_id[0], &u32, 4);
805   key->link_id_length = 4;
806
807   /* keep track which originator orderer this LID */
808   key->link_id[0] = origin->lid_index & 0xff;
809
810   lid->next_id++;
811   return 0;
812 }
813
814 /**
815  * Add a layer-2 neighbor to a addr.
816  * @param l2net layer-2 addr object
817  * @param key unique key for neighbor
818  * @return layer-2 neighbor object
819  */
820 struct oonf_layer2_neigh *
821 oonf_layer2_neigh_add_lid(struct oonf_layer2_net *l2net, const struct oonf_layer2_neigh_key *key) {
822   struct oonf_layer2_neigh *l2neigh;
823   enum oonf_layer2_neighbor_index neighidx;
824
825   if (netaddr_get_address_family(&key->addr) != AF_MAC48 && netaddr_get_address_family(&key->addr) != AF_EUI64) {
826     return NULL;
827   }
828
829   l2neigh = oonf_layer2_neigh_get_lid(l2net, key);
830   if (l2neigh) {
831     return l2neigh;
832   }
833
834   l2neigh = oonf_class_malloc(&_l2neighbor_class);
835   if (!l2neigh) {
836     return NULL;
837   }
838
839   memcpy(&l2neigh->key, key, sizeof(*key));
840   l2neigh->_node.key = &l2neigh->key;
841   l2neigh->network = l2net;
842
843   avl_insert(&l2net->neighbors, &l2neigh->_node);
844
845   avl_init(&l2neigh->destinations, avl_comp_netaddr, false);
846   avl_init(&l2neigh->remote_neighbor_ips, avl_comp_netaddr, false);
847
848   /* initialize metadata */
849   for (neighidx=0; neighidx<OONF_LAYER2_NEIGH_COUNT; neighidx++) {
850     l2neigh->data[neighidx]._meta = oonf_layer2_neigh_metadata_get(neighidx);
851   }
852
853   oonf_class_event(&_l2neighbor_class, l2neigh, OONF_OBJECT_ADDED);
854
855   return l2neigh;
856 }
857
858 /**
859  * Remove all data objects of a certain originator from a layer-2 neighbor
860  * object.
861  * @param l2neigh layer-2 neighbor
862  * @param origin originator number
863  * @return true if a value was resetted, false otherwise
864  */
865 bool
866 oonf_layer2_neigh_cleanup(struct oonf_layer2_neigh *l2neigh, const struct oonf_layer2_origin *origin) {
867   bool changed = false;
868   int i;
869
870   for (i = 0; i < OONF_LAYER2_NEIGH_COUNT; i++) {
871     if (l2neigh->data[i]._origin == origin) {
872       oonf_layer2_data_reset(&l2neigh->data[i]);
873       changed = true;
874     }
875   }
876   return changed;
877 }
878
879 /**
880  * Remove all information of a certain originator from a layer-2 neighbor
881  * object. Remove the object if its empty.
882  * @param l2neigh layer-2 neighbor object
883  * @param origin originator number
884  * @return true if something was change, false otherwise
885  */
886 bool
887 oonf_layer2_neigh_remove(struct oonf_layer2_neigh *l2neigh, const struct oonf_layer2_origin *origin) {
888   struct oonf_layer2_destination *l2dst, *l2dst_it;
889   struct oonf_layer2_neighbor_address *l2ip, *l2ip_it;
890
891   bool changed = false;
892
893   if (!avl_is_node_added(&l2neigh->_node)) {
894     return false;
895   }
896
897   avl_for_each_element_safe(&l2neigh->destinations, l2dst, _node, l2dst_it) {
898     if (l2dst->origin == origin) {
899       oonf_layer2_destination_remove(l2dst);
900       changed = true;
901     }
902   }
903
904   avl_for_each_element_safe(&l2neigh->remote_neighbor_ips, l2ip, _neigh_node, l2ip_it) {
905     if (oonf_layer2_neigh_remove_ip(l2ip, origin) == 0) {
906       changed = true;
907     }
908   }
909
910   if (oonf_layer2_neigh_cleanup(l2neigh, origin)) {
911     changed = true;
912   }
913
914   if (changed) {
915     oonf_layer2_neigh_commit(l2neigh);
916   }
917   return changed;
918 }
919
920 /**
921  * Commit all changes to a layer-2 neighbor object. This might remove the
922  * object from the database if all data has been removed from the object.
923  * @param l2neigh layer-2 neighbor object
924  * @return true if the object has been removed, false otherwise
925  */
926 bool
927 oonf_layer2_neigh_commit(struct oonf_layer2_neigh *l2neigh) {
928   size_t i;
929
930   if (l2neigh->destinations.count > 0 || l2neigh->remote_neighbor_ips.count > 0) {
931     oonf_class_event(&_l2neighbor_class, l2neigh, OONF_OBJECT_CHANGED);
932     l2neigh->modified = OONF_LAYER2_NEIGH_MODIFY_NONE;
933     return false;
934   }
935
936   for (i = 0; i < OONF_LAYER2_NEIGH_COUNT; i++) {
937     if (oonf_layer2_data_has_value(&l2neigh->data[i])) {
938       oonf_class_event(&_l2neighbor_class, l2neigh, OONF_OBJECT_CHANGED);
939       l2neigh->modified = OONF_LAYER2_NEIGH_MODIFY_NONE;
940       return false;
941     }
942   }
943
944   _neigh_remove(l2neigh);
945   return true;
946 }
947
948 /**
949  * Relabel all neighbor data of one origin to another one
950  * @param l2neigh layer2 neighbor object
951  * @param new_origin new origin
952  * @param old_origin old origin to overwrite
953  */
954 void
955 oonf_layer2_neigh_relabel(struct oonf_layer2_neigh *l2neigh, const struct oonf_layer2_origin *new_origin,
956   const struct oonf_layer2_origin *old_origin) {
957   struct oonf_layer2_neighbor_address *neigh_ip;
958   struct oonf_layer2_destination *l2dst;
959   size_t i;
960
961   for (i = 0; i < OONF_LAYER2_NEIGH_COUNT; i++) {
962     if (oonf_layer2_data_get_origin(&l2neigh->data[i]) == old_origin) {
963       oonf_layer2_data_set_origin(&l2neigh->data[i], new_origin);
964     }
965   }
966
967   avl_for_each_element(&l2neigh->remote_neighbor_ips, neigh_ip, _neigh_node) {
968     if (neigh_ip->origin == old_origin) {
969       neigh_ip->origin = new_origin;
970     }
971   }
972
973   avl_for_each_element(&l2neigh->destinations, l2dst, _node) {
974     if (l2dst->origin == old_origin) {
975       l2dst->origin = new_origin;
976     }
977   }
978 }
979
980 /**
981 * Sets the (ip) next hop of a neighbor, you should call oonf_layer2_neigh_commit after a
982 * successful change.
983 * @param neigh layer2 neighbor
984 * @param nexthop next hop, should be IPv4 or IPv6
985 * @return -1 if nothing was changed, 0 if the next hop was updated.
986 */
987 int
988 oonf_layer2_neigh_set_nexthop(struct oonf_layer2_neigh *neigh, const struct netaddr *nexthop) {
989   enum oonf_layer2_neigh_mods mod;
990   struct netaddr *nh;
991
992   switch (netaddr_get_address_family(nexthop)) {
993     case AF_INET:
994       nh = &neigh->_next_hop_v4;
995       mod = OONF_LAYER2_NEIGH_MODIFY_NEXTHOP_V4;
996       break;
997     case AF_INET6:
998       nh = &neigh->_next_hop_v6;
999       mod = OONF_LAYER2_NEIGH_MODIFY_NEXTHOP_V6;
1000       break;
1001     default:
1002       return -1;
1003   }
1004
1005   if (memcmp(nh, nexthop, sizeof(*nexthop)) == 0) {
1006     return -1;
1007   }
1008
1009   memcpy(nh, nexthop, sizeof(*nexthop));
1010   neigh->modified |= mod;
1011   return 0;
1012 }
1013
1014
1015 /**
1016  * Add an IP address or prefix to a layer-2 interface. This represents
1017  * an address of the local radio or modem.
1018  * @param l2neigh layer-2 neighbor object
1019  * @param origin layer2 data origin
1020  * @param ip ip address or prefix
1021  * @return layer2 ip address object, NULL if out of memory
1022  */
1023 struct oonf_layer2_neighbor_address *
1024 oonf_layer2_neigh_add_ip(
1025   struct oonf_layer2_neigh *l2neigh, const struct oonf_layer2_origin *origin, const struct netaddr *ip) {
1026   struct oonf_layer2_neighbor_address *l2addr;
1027
1028   l2addr = oonf_layer2_neigh_get_remote_ip(l2neigh, ip);
1029   if (l2addr) {
1030     l2addr->origin = origin;
1031     return l2addr;
1032   }
1033
1034   l2addr = oonf_class_malloc(&_l2neigh_addr_class);
1035   if (!l2addr) {
1036     return NULL;
1037   }
1038
1039   /* copy data */
1040   memcpy(&l2addr->ip, ip, sizeof(*ip));
1041
1042   /* set back reference */
1043   l2addr->l2neigh = l2neigh;
1044
1045   /* add to tree */
1046   l2addr->_neigh_node.key = &l2addr->ip;
1047   avl_insert(&l2neigh->remote_neighbor_ips, &l2addr->_neigh_node);
1048   l2addr->_net_node.key = &l2addr->ip;
1049   avl_insert(&l2neigh->network->remote_neighbor_ips, &l2addr->_net_node);
1050
1051   /* remember originator */
1052   l2addr->origin = origin;
1053
1054   oonf_class_event(&_l2neigh_addr_class, l2addr, OONF_OBJECT_ADDED);
1055   return l2addr;
1056 }
1057
1058 /**
1059  * Remove a neighbor IP address from a layer2 neighbor
1060  * @param ip ip address or prefix
1061  * @param origin origin of IP address
1062  * @return 0 if IP was removed, -1 if it was registered to a different origin
1063  */
1064 int
1065 oonf_layer2_neigh_remove_ip(struct oonf_layer2_neighbor_address *ip, const struct oonf_layer2_origin *origin) {
1066   if (ip->origin != origin) {
1067     return -1;
1068   }
1069
1070   oonf_class_event(&_l2neigh_addr_class, ip, OONF_OBJECT_REMOVED);
1071
1072   avl_remove(&ip->l2neigh->remote_neighbor_ips, &ip->_neigh_node);
1073   avl_remove(&ip->l2neigh->network->remote_neighbor_ips, &ip->_net_node);
1074   oonf_class_free(&_l2neigh_addr_class, ip);
1075   return 0;
1076 }
1077
1078 /**
1079  * add a layer2 destination (a MAC address behind a neighbor) to
1080  * the layer2 database
1081  * @param l2neigh layer2 neighbor of the destination
1082  * @param destination destination address
1083  * @param origin layer2 origin
1084  * @return layer2 destination, NULL if out of memory
1085  */
1086 struct oonf_layer2_destination *
1087 oonf_layer2_destination_add(
1088   struct oonf_layer2_neigh *l2neigh, const struct netaddr *destination, const struct oonf_layer2_origin *origin) {
1089   struct oonf_layer2_destination *l2dst;
1090
1091   l2dst = oonf_layer2_destination_get(l2neigh, destination);
1092   if (l2dst) {
1093     return l2dst;
1094   }
1095
1096   l2dst = oonf_class_malloc(&_l2dst_class);
1097   if (!l2dst) {
1098     return NULL;
1099   }
1100
1101   /* copy data into destination storage */
1102   memcpy(&l2dst->destination, destination, sizeof(*destination));
1103   l2dst->origin = origin;
1104
1105   /* add back-pointer */
1106   l2dst->neighbor = l2neigh;
1107
1108   /* add to neighbor tree */
1109   l2dst->_node.key = &l2dst->destination;
1110   avl_insert(&l2neigh->destinations, &l2dst->_node);
1111
1112   oonf_class_event(&_l2dst_class, l2dst, OONF_OBJECT_ADDED);
1113   return l2dst;
1114 }
1115
1116 /**
1117  * Remove a layer2 destination
1118  * @param l2dst layer2 destination
1119  */
1120 void
1121 oonf_layer2_destination_remove(struct oonf_layer2_destination *l2dst) {
1122   if (!avl_is_node_added(&l2dst->_node)) {
1123     return;
1124   }
1125   oonf_class_event(&_l2dst_class, l2dst, OONF_OBJECT_REMOVED);
1126
1127   avl_remove(&l2dst->neighbor->destinations, &l2dst->_node);
1128   oonf_class_free(&_l2dst_class, l2dst);
1129 }
1130
1131 /**
1132  * Get neighbor specific data, either from neighbor or from the networks default
1133  * @param ifname name of interface
1134  * @param l2neigh_addr neighbor mac address
1135  * @param idx data index
1136  * @param get_default true to return default (net) data if no neighbor data available
1137  * @return pointer to linklayer data, NULL if no value available
1138  */
1139 struct oonf_layer2_data *
1140 oonf_layer2_neigh_query(const char *ifname, const struct netaddr *l2neigh_addr,
1141       enum oonf_layer2_neighbor_index idx, bool get_default) {
1142   struct oonf_layer2_net *l2net;
1143   struct oonf_layer2_neigh *l2neigh;
1144   struct oonf_layer2_data *data;
1145
1146   /* query layer2 database about neighbor */
1147   l2net = oonf_layer2_net_get(ifname);
1148   if (l2net == NULL) {
1149     return NULL;
1150   }
1151
1152   /* look for neighbor specific data */
1153   l2neigh = oonf_layer2_neigh_get(l2net, l2neigh_addr);
1154   if (l2neigh != NULL) {
1155     data = &l2neigh->data[idx];
1156     if (oonf_layer2_data_has_value(data)) {
1157       return data;
1158     }
1159   }
1160
1161   if (!get_default) {
1162     return NULL;
1163   }
1164
1165   /* look for network specific default */
1166   data = &l2net->neighdata[idx];
1167   if (oonf_layer2_data_has_value(data)) {
1168     return data;
1169   }
1170   return NULL;
1171 }
1172
1173 /**
1174  * Get neighbor specific data, add interface and neighbor if necessary
1175  * @param ifname name of interface
1176  * @param l2neigh_addr neighbor mac address
1177  * @param idx data index
1178  * @return pointer to linklayer data, NULL if no value available
1179  */
1180 struct oonf_layer2_data *
1181 oonf_layer2_neigh_add_path(const char *ifname, const struct netaddr *l2neigh_addr, enum oonf_layer2_neighbor_index idx) {
1182     struct oonf_layer2_net *l2net;
1183   struct oonf_layer2_neigh *l2neigh;
1184
1185   /* query layer2 database about neighbor */
1186   l2net = oonf_layer2_net_add(ifname);
1187   if (l2net == NULL) {
1188     return NULL;
1189   }
1190
1191   /* look for neighbor specific data */
1192   l2neigh = oonf_layer2_neigh_add(l2net, l2neigh_addr);
1193   if (l2neigh == NULL) {
1194     return NULL;
1195   }
1196
1197   return &l2neigh->data[idx];
1198 }
1199
1200 /**
1201  * Get neighbor specific data, either from neighbor or from the networks default
1202  * @param l2neigh pointer to layer2 neighbor
1203  * @param idx data index
1204  * @return pointer to linklayer data, NULL if no value available
1205  */
1206 struct oonf_layer2_data *
1207 oonf_layer2_neigh_get_data(struct oonf_layer2_neigh *l2neigh, enum oonf_layer2_neighbor_index idx) {
1208   struct oonf_layer2_data *data;
1209
1210   data = &l2neigh->data[idx];
1211   if (oonf_layer2_data_has_value(data)) {
1212     return data;
1213   }
1214
1215   /* look for network specific default */
1216   data = &l2neigh->network->neighdata[idx];
1217   if (oonf_layer2_data_has_value(data)) {
1218     return data;
1219   }
1220   return NULL;
1221 }
1222
1223 /**
1224  * get neighbor metric metadata
1225  * @param idx neighbor metric index
1226  * @return metadata object
1227  */
1228 const struct oonf_layer2_metadata *
1229 oonf_layer2_neigh_metadata_get(enum oonf_layer2_neighbor_index idx) {
1230   return &_metadata_neigh[idx];
1231 }
1232
1233 /**
1234  * get network metric metadata
1235  * @param idx network metric index
1236  * @return metadata object
1237  */
1238 const struct oonf_layer2_metadata *
1239 oonf_layer2_net_metadata_get(enum oonf_layer2_network_index idx) {
1240   return &_metadata_net[idx];
1241 }
1242
1243 /**
1244  * Callback for configuration choice of layer2 network key
1245  * @param idx index
1246  * @param unused not used
1247  * @return pointer to network key
1248  */
1249 const char *
1250 oonf_layer2_cfg_get_l2net_key(size_t idx, const void *unused __attribute__((unused))) {
1251   return _metadata_net[idx].key;
1252 }
1253
1254 /**
1255  * Callback for configuration choice of layer2 neighbor key
1256  * @param idx index
1257  * @param unused not used
1258  * @return pointer to neighbor key
1259  */
1260 const char *
1261 oonf_layer2_cfg_get_l2neigh_key(size_t idx, const void *unused __attribute__((unused))) {
1262   return _metadata_neigh[idx].key;
1263 }
1264
1265 /**
1266  * Callback for configuration choice of layer2 neighbor key
1267  * @param idx index
1268  * @param unused not used
1269  * @return pointer to neighbor key
1270  */
1271 const char *
1272 oonf_layer2_cfg_get_l2comp(size_t idx, const void *unused __attribute__((unused))) {
1273   return _data_comparators[idx];
1274 }
1275
1276 /**
1277  * get text representation of network type
1278  * @param type network type
1279  * @return text representation
1280  */
1281 const char *
1282 oonf_layer2_net_get_type_name(enum oonf_layer2_network_type type) {
1283   return _network_type[type];
1284 }
1285
1286 /**
1287  * get tree of layer2 networks
1288  * @return network tree
1289  */
1290 struct avl_tree *
1291 oonf_layer2_get_net_tree(void) {
1292   return &_oonf_layer2_net_tree;
1293 }
1294
1295 /**
1296  * get tree of layer2 originators
1297  * @return originator tree
1298  */
1299 struct avl_tree *
1300 oonf_layer2_get_origin_tree(void) {
1301   return &_oonf_originator_tree;
1302 }
1303
1304 /**
1305  * Compares two layer2 neighbor keys
1306  * @param p1 pointer to first neighbor key
1307  * @param p2 pointer to second neighbor key
1308  * @return result of memcmp comparison
1309  */
1310 int
1311 oonf_layer2_avlcmp_neigh_key(const void *p1, const void *p2) {
1312   const struct oonf_layer2_neigh_key *k1 = p1;
1313   const struct oonf_layer2_neigh_key *k2 = p2;
1314
1315   return memcmp(k1, k2, sizeof(*k1));
1316 }
1317
1318 /**
1319  * Converts a layer2 neighbor key into a string representation
1320  * @param buf buffer for output string
1321  * @param key layer2 neighbor key
1322  * @param show_mac true to show MAC and Link ID, false to only show LID
1323  * @return pointer to output string
1324  */
1325 const char *
1326 oonf_layer2_neigh_key_to_string(union oonf_layer2_neigh_key_str *buf,
1327     const struct oonf_layer2_neigh_key *key, bool show_mac) {
1328   static const char HEX[17] = "0123456789ABCDEF";
1329   static const char NONE[] = "-";
1330   size_t str_idx, lid_idx;
1331   uint8_t af;
1332
1333   if (key == NULL) {
1334     return NONE;
1335   }
1336
1337   af = netaddr_get_address_family(&key->addr);
1338   if (af != AF_MAC48 && af != AF_EUI64) {
1339     return NONE;
1340   }
1341
1342   if (show_mac) {
1343     netaddr_to_string(&buf->nbuf, &key->addr);
1344   }
1345   else {
1346     buf->buf[0] = 0;
1347   }
1348
1349   if (key->link_id_length == 0) {
1350     return buf->buf;
1351   }
1352
1353   str_idx = strlen(buf->buf);
1354   lid_idx = 0;
1355
1356   if (show_mac) {
1357     buf->buf[str_idx++] = ' ';
1358     buf->buf[str_idx++] = '[';
1359     buf->buf[str_idx++] = '0';
1360     buf->buf[str_idx++] = 'x';
1361   }
1362
1363   while (str_idx + 4 < sizeof(*buf) && lid_idx < key->link_id_length) {
1364     buf->buf[str_idx++] = HEX[key->link_id[lid_idx] >> 4];
1365     buf->buf[str_idx++] = HEX[key->link_id[lid_idx] & 15];
1366     lid_idx++;
1367   }
1368
1369   if (show_mac) {
1370     buf->buf[str_idx++] = ']';
1371     buf->buf[str_idx++] = 0;
1372   }
1373   return buf->buf;
1374 }
1375
1376 /**
1377  * Removes a layer-2 addr object from the database.
1378  * @param l2net layer-2 addr object
1379  */
1380 static void
1381 _net_remove(struct oonf_layer2_net *l2net) {
1382   struct oonf_layer2_neigh *l2neigh, *l2n_it;
1383   struct oonf_layer2_peer_address *l2peer, *l2peer_it;
1384
1385   /* free all embedded neighbors */
1386   avl_for_each_element_safe(&l2net->neighbors, l2neigh, _node, l2n_it) {
1387     _neigh_remove(l2neigh);
1388   }
1389
1390   /* free all attached peer addresses */
1391   avl_for_each_element_safe(&l2net->local_peer_ips, l2peer, _net_node, l2peer_it) {
1392     oonf_layer2_net_remove_ip(l2peer, l2peer->origin);
1393   }
1394
1395   oonf_class_event(&_l2network_class, l2net, OONF_OBJECT_REMOVED);
1396
1397   /* remove interface listener */
1398   os_interface_remove(&l2net->if_listener);
1399
1400   /* free addr */
1401   avl_remove(&_oonf_layer2_net_tree, &l2net->_node);
1402   oonf_class_free(&_l2network_class, l2net);
1403 }
1404
1405 /**
1406  * Removes a layer-2 neighbor object from the database
1407  * @param l2neigh layer-2 neighbor object
1408  */
1409 static void
1410 _neigh_remove(struct oonf_layer2_neigh *l2neigh) {
1411   struct oonf_layer2_destination *l2dst, *l2dst_it;
1412   struct oonf_layer2_neighbor_address *l2addr, *l2addr_it;
1413
1414   /* free all embedded destinations */
1415   avl_for_each_element_safe(&l2neigh->destinations, l2dst, _node, l2dst_it) {
1416     oonf_layer2_destination_remove(l2dst);
1417   }
1418
1419   /* free all attached neighbor addresses */
1420   avl_for_each_element_safe(&l2neigh->remote_neighbor_ips, l2addr, _neigh_node, l2addr_it) {
1421     oonf_layer2_neigh_remove_ip(l2addr, l2addr->origin);
1422   }
1423
1424   /* inform user that mac entry will be removed */
1425   oonf_class_event(&_l2neighbor_class, l2neigh, OONF_OBJECT_REMOVED);
1426
1427   /* free resources for mac entry */
1428   avl_remove(&l2neigh->network->neighbors, &l2neigh->_node);
1429   oonf_class_free(&_l2neighbor_class, l2neigh);
1430 }