3 * The olsr.org Optimized Link-State Routing daemon version 2 (olsrd2)
4 * Copyright (c) 2004-2015, the olsr.org team - see HISTORY file
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 * Visit http://www.olsr.org for more information.
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.
46 #include "common/avl.h"
47 #include "common/avl_comp.h"
48 #include "common/common_types.h"
49 #include "common/json.h"
50 #include "common/netaddr.h"
51 #include "config/cfg_schema.h"
52 #include "core/oonf_subsystem.h"
53 #include "subsystems/oonf_class.h"
54 #include "subsystems/os_interface.h"
56 #include "subsystems/oonf_layer2.h"
59 #define LOG_LAYER2 _oonf_layer2_subsystem.logging
62 static int _init(void);
63 static void _cleanup(void);
65 static void _net_remove(struct oonf_layer2_net *l2net);
66 static void _neigh_remove(struct oonf_layer2_neigh *l2neigh);
68 /* subsystem definition */
69 static const char *_dependencies[] = {
71 OONF_OS_INTERFACE_SUBSYSTEM,
74 static struct oonf_subsystem _oonf_layer2_subsystem = {
75 .name = OONF_LAYER2_SUBSYSTEM,
76 .dependencies = _dependencies,
77 .dependencies_count = ARRAYSIZE(_dependencies),
81 DECLARE_OONF_PLUGIN(_oonf_layer2_subsystem);
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", .fraction = 3 },
86 [OONF_LAYER2_NEIGH_RX_SIGNAL] = { .key = "rx_signal", .type = OONF_LAYER2_INTEGER_DATA, .unit = "dBm", .fraction = 3 },
87 [OONF_LAYER2_NEIGH_TX_BITRATE] = { .key = "tx_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s" },
88 [OONF_LAYER2_NEIGH_RX_BITRATE] = { .key = "rx_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s" },
89 [OONF_LAYER2_NEIGH_RX_BC_BITRATE] = { .key = "rx_bc_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s" },
90 [OONF_LAYER2_NEIGH_TX_MAX_BITRATE] = { .key = "tx_max_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s" },
91 [OONF_LAYER2_NEIGH_RX_MAX_BITRATE] = { .key = "rx_max_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s" },
92 [OONF_LAYER2_NEIGH_TX_BYTES] = { .key = "tx_bytes", .type = OONF_LAYER2_INTEGER_DATA, .unit = "byte" },
93 [OONF_LAYER2_NEIGH_RX_BYTES] = { .key = "rx_bytes", .type = OONF_LAYER2_INTEGER_DATA, .unit = "byte" },
94 [OONF_LAYER2_NEIGH_TX_FRAMES] = { .key = "tx_frames", .type = OONF_LAYER2_INTEGER_DATA },
95 [OONF_LAYER2_NEIGH_RX_FRAMES] = { .key = "rx_frames", .type = OONF_LAYER2_INTEGER_DATA },
96 [OONF_LAYER2_NEIGH_TX_THROUGHPUT] = { .key = "tx_throughput", .type = OONF_LAYER2_INTEGER_DATA , .unit = "bit/s" },
97 [OONF_LAYER2_NEIGH_TX_RETRIES] = { .key = "tx_retries", .type = OONF_LAYER2_INTEGER_DATA },
98 [OONF_LAYER2_NEIGH_TX_FAILED] = { .key = "tx_failed", .type = OONF_LAYER2_INTEGER_DATA },
99 [OONF_LAYER2_NEIGH_LATENCY] = { .key = "latency", .type = OONF_LAYER2_INTEGER_DATA , .unit = "s", .fraction = 6 },
100 [OONF_LAYER2_NEIGH_RESOURCES] = { .key = "resources", .type = OONF_LAYER2_INTEGER_DATA },
101 [OONF_LAYER2_NEIGH_TX_RLQ] = { .key = "tx_rlq", .type = OONF_LAYER2_INTEGER_DATA },
102 [OONF_LAYER2_NEIGH_RX_RLQ] = { .key = "rx_rlq", .type = OONF_LAYER2_INTEGER_DATA },
105 /* layer2 network metadata */
106 static const struct oonf_layer2_metadata _metadata_net[OONF_LAYER2_NET_COUNT] = {
107 [OONF_LAYER2_NET_FREQUENCY_1] = { .key = "frequency1", .type = OONF_LAYER2_INTEGER_DATA , .unit = "Hz" },
108 [OONF_LAYER2_NET_FREQUENCY_2] = { .key = "frequency2", .type = OONF_LAYER2_INTEGER_DATA , .unit = "Hz" },
109 [OONF_LAYER2_NET_BANDWIDTH_1] = { .key = "bandwidth1", .type = OONF_LAYER2_INTEGER_DATA , .unit = "Hz" },
110 [OONF_LAYER2_NET_BANDWIDTH_2] = { .key = "bandwidth2", .type = OONF_LAYER2_INTEGER_DATA , .unit = "Hz" },
111 [OONF_LAYER2_NET_NOISE] = { .key = "noise", .type = OONF_LAYER2_INTEGER_DATA , .unit="dBm", .fraction = 3 },
112 [OONF_LAYER2_NET_CHANNEL_ACTIVE] = { .key = "ch_active", .type = OONF_LAYER2_INTEGER_DATA , .unit="s", .fraction = 9 },
113 [OONF_LAYER2_NET_CHANNEL_BUSY] = { .key = "ch_busy", .type = OONF_LAYER2_INTEGER_DATA , .unit="s", .fraction = 9 },
114 [OONF_LAYER2_NET_CHANNEL_RX] = { .key = "ch_rx", .type = OONF_LAYER2_INTEGER_DATA , .unit="s", .fraction = 9 },
115 [OONF_LAYER2_NET_CHANNEL_TX] = { .key = "ch_tx", .type = OONF_LAYER2_INTEGER_DATA , .unit="s", .fraction = 9 },
116 [OONF_LAYER2_NET_MTU] = { .key = "mtu", .type = OONF_LAYER2_INTEGER_DATA , .unit="byte" },
117 [OONF_LAYER2_NET_MCS_BY_PROBING] = { .key = "mcs_by_probing", .type = OONF_LAYER2_BOOLEAN_DATA },
118 [OONF_LAYER2_NET_RX_ONLY_UNICAST] = { .key = "rx_only_unicast", .type = OONF_LAYER2_BOOLEAN_DATA },
119 [OONF_LAYER2_NET_TX_ONLY_UNICAST] = { .key = "tx_only_unicast", .type = OONF_LAYER2_BOOLEAN_DATA },
122 static const char *_network_type[OONF_LAYER2_TYPE_COUNT] = {
123 [OONF_LAYER2_TYPE_UNDEFINED] = "undefined",
124 [OONF_LAYER2_TYPE_WIRELESS] = "wireless",
125 [OONF_LAYER2_TYPE_ETHERNET] = "ethernet",
126 [OONF_LAYER2_TYPE_TUNNEL] = "tunnel",
129 static const char *_data_comparators[OONF_LAYER2_DATA_CMP_COUNT] = {
130 [OONF_LAYER2_DATA_CMP_EQUALS] = "==",
131 [OONF_LAYER2_DATA_CMP_NOT_EQUALS] = "!=",
132 [OONF_LAYER2_DATA_CMP_LESSER] = "<",
133 [OONF_LAYER2_DATA_CMP_LESSER_OR_EQUALS] = "<=",
134 [OONF_LAYER2_DATA_CMP_GREATER] = ">",
135 [OONF_LAYER2_DATA_CMP_GREATER_OR_EQUALS] = ">=",
138 static const char *_data_types[OONF_LAYER2_DATA_TYPE_COUNT] = {
139 [OONF_LAYER2_NO_DATA] = "none",
140 [OONF_LAYER2_INTEGER_DATA] = "integer",
141 [OONF_LAYER2_BOOLEAN_DATA] = "boolean",
142 [OONF_LAYER2_NETWORK_DATA] = "network",
145 /* infrastructure for l2net/l2neigh tree */
146 static struct oonf_class _l2network_class = {
147 .name = LAYER2_CLASS_NETWORK,
148 .size = sizeof(struct oonf_layer2_net),
150 static struct oonf_class _l2neighbor_class = {
151 .name = LAYER2_CLASS_NEIGHBOR,
152 .size = sizeof(struct oonf_layer2_neigh),
154 static struct oonf_class _l2dst_class = {
155 .name = LAYER2_CLASS_DESTINATION,
156 .size = sizeof(struct oonf_layer2_destination),
158 static struct oonf_class _l2net_addr_class = {
159 .name = LAYER2_CLASS_NETWORK_ADDRESS,
160 .size = sizeof(struct oonf_layer2_peer_address),
162 static struct oonf_class _l2neigh_addr_class = {
163 .name = LAYER2_CLASS_NEIGHBOR_ADDRESS,
164 .size = sizeof(struct oonf_layer2_neighbor_address),
167 static struct avl_tree _oonf_layer2_net_tree;
169 static struct avl_tree _oonf_originator_tree;
171 static struct avl_tree _local_peer_ips_tree;
174 * Subsystem constructor
175 * @return always returns 0
179 oonf_class_add(&_l2network_class);
180 oonf_class_add(&_l2neighbor_class);
181 oonf_class_add(&_l2dst_class);
182 oonf_class_add(&_l2net_addr_class);
183 oonf_class_add(&_l2neigh_addr_class);
185 avl_init(&_oonf_layer2_net_tree, avl_comp_strcasecmp, false);
186 avl_init(&_oonf_originator_tree, avl_comp_strcasecmp, false);
187 avl_init(&_local_peer_ips_tree, avl_comp_netaddr, true);
192 * Subsystem destructor
196 struct oonf_layer2_net *l2net, *l2n_it;
198 avl_for_each_element_safe(&_oonf_layer2_net_tree, l2net, _node, l2n_it) {
202 oonf_class_remove(&_l2neigh_addr_class);
203 oonf_class_remove(&_l2net_addr_class);
204 oonf_class_remove(&_l2dst_class);
205 oonf_class_remove(&_l2neighbor_class);
206 oonf_class_remove(&_l2network_class);
210 * Register a new data originator number for layer2 data
211 * @param origin layer2 originator
214 oonf_layer2_origin_add(struct oonf_layer2_origin *origin) {
215 origin->_node.key = origin->name;
216 avl_insert(&_oonf_originator_tree, &origin->_node);
220 * Removes all layer2 data associated with this data originator
221 * @param origin originator
224 oonf_layer2_origin_remove(struct oonf_layer2_origin *origin) {
225 struct oonf_layer2_net *l2net, *l2net_it;
227 if (!avl_is_node_added(&origin->_node)) {
231 avl_for_each_element_safe(&_oonf_layer2_net_tree, l2net, _node, l2net_it) {
232 oonf_layer2_net_remove(l2net, origin);
235 avl_remove(&_oonf_originator_tree, &origin->_node);
239 * Parse a string into a layer2 data object
240 * @param value target buffer for layer2 data
241 * @param meta metadata for layer2 data
242 * @param input input string
243 * @return -1 if an error happened, 0 otherwise
246 oonf_layer2_data_parse_string(union oonf_layer2_value *value,
247 const struct oonf_layer2_metadata *meta, const char *input) {
248 memset(value, 0, sizeof(*value));
250 switch (meta->type) {
251 case OONF_LAYER2_INTEGER_DATA:
252 return isonumber_to_s64(
253 &value->integer, input, meta->fraction);
255 case OONF_LAYER2_BOOLEAN_DATA:
256 if (!cfg_is_bool(input)) {
259 value->boolean = cfg_get_bool(input);
268 * Convert a layer2 data object into a string representation
269 * @param buffer destination string buffer
270 * @param length length of string buffer
271 * @param data layer2 data
272 * @param meta layer2 metadata
273 * @param raw true for raw conversion (switch of isoprefix conversion)
274 * @return pointer to output buffer, NULL if an error happened
277 oonf_layer2_data_to_string(char *buffer, size_t length,
278 const struct oonf_layer2_data *data,
279 const struct oonf_layer2_metadata *meta, bool raw) {
280 struct isonumber_str iso_str;
282 switch (meta->type) {
283 case OONF_LAYER2_INTEGER_DATA:
284 if (!isonumber_from_s64(&iso_str, data->_value.integer,
285 meta->unit, meta->fraction, raw)) {
288 return strscpy(buffer, iso_str.buf, length);
290 case OONF_LAYER2_BOOLEAN_DATA:
291 return strscpy(buffer, json_getbool(data->_value.boolean), length);
299 * (Over)write the value of a layer2 data object
300 * @param l2data layer2 data object
301 * @param origin origin of new data
302 * @param type type of new data
303 * @param input new data value
304 * @return true if data changed, false otherwise
307 oonf_layer2_data_set(struct oonf_layer2_data *l2data,
308 const struct oonf_layer2_origin *origin,
309 enum oonf_layer2_data_type type,
310 const union oonf_layer2_value *input) {
311 bool changed = false;
313 if (l2data->_type == OONF_LAYER2_NO_DATA
314 || l2data->_origin == NULL
315 || l2data->_origin == origin
316 || l2data->_origin->priority < origin->priority) {
317 changed = l2data->_type != type
318 || memcmp(&l2data->_value, input, sizeof(*input)) != 0;
319 memcpy(&l2data->_value, input, sizeof(*input));
320 l2data->_type = type;
321 l2data->_origin = origin;
327 * Compare two layer2 data objects
328 * @param left left parameter for comparator
329 * @param right right parameter for comparator
330 * @param cmp comparator
331 * @return comparator result, false if not valid
332 * (e.g. comparing different types of data)
335 oonf_layer2_data_compare(const union oonf_layer2_value *left,
336 const union oonf_layer2_value *right,
337 enum oonf_layer2_data_comparator_type comparator,
338 enum oonf_layer2_data_type data_type) {
342 case OONF_LAYER2_INTEGER_DATA:
343 if (left->integer > right->integer) {
346 else if (left->integer < right->integer) {
353 case OONF_LAYER2_BOOLEAN_DATA:
354 result = memcmp(&left->boolean, &right->boolean,
355 sizeof(left->boolean));
357 case OONF_LAYER2_NETWORK_DATA:
358 result = memcmp(&left->addr, &right->addr,
366 switch (comparator) {
367 case OONF_LAYER2_DATA_CMP_EQUALS:
369 case OONF_LAYER2_DATA_CMP_NOT_EQUALS:
371 case OONF_LAYER2_DATA_CMP_LESSER:
373 case OONF_LAYER2_DATA_CMP_LESSER_OR_EQUALS:
375 case OONF_LAYER2_DATA_CMP_GREATER:
377 case OONF_LAYER2_DATA_CMP_GREATER_OR_EQUALS:
385 * Get comparator type from string
386 * @param string string (C) representation of comparator
387 * @return comparator type
389 enum oonf_layer2_data_comparator_type
390 oonf_layer2_data_get_comparator(const char *string) {
391 enum oonf_layer2_data_comparator_type i;
393 for (i=0; i<OONF_LAYER2_DATA_CMP_COUNT; i++) {
394 if (strcmp(string, _data_comparators[i]) == 0) {
398 return OONF_LAYER2_DATA_CMP_ILLEGAL;
402 * @param type layer2 comparator type
403 * @return string representation of comparator
406 oonf_layer2_data_get_comparator_string(enum oonf_layer2_data_comparator_type type) {
407 return _data_comparators[type];
411 * @param type type index of layer2 data
412 * @return the string name of a layer2 data type
415 oonf_layer2_data_get_type_string(enum oonf_layer2_data_type type) {
416 return _data_types[type];
420 * Add a layer-2 network to the database
421 * @param ifname name of interface
422 * @return layer-2 network object
424 struct oonf_layer2_net *
425 oonf_layer2_net_add(const char *ifname) {
426 struct oonf_layer2_net *l2net;
432 l2net = avl_find_element(&_oonf_layer2_net_tree, ifname, l2net, _node);
437 l2net = oonf_class_malloc(&_l2network_class);
443 strscpy(l2net->name, ifname, sizeof(l2net->name));
445 /* add to global l2net tree */
446 l2net->_node.key = l2net->name;
447 avl_insert(&_oonf_layer2_net_tree, &l2net->_node);
449 /* initialize tree of neighbors, ips and proxies */
450 avl_init(&l2net->neighbors, avl_comp_netaddr, false);
451 avl_init(&l2net->local_peer_ips, avl_comp_netaddr, false);
452 avl_init(&l2net->remote_neighbor_ips, avl_comp_netaddr, true);
454 /* initialize interface listener */
455 l2net->if_listener.name = l2net->name;
456 os_interface_add(&l2net->if_listener);
458 oonf_class_event(&_l2network_class, l2net, OONF_OBJECT_ADDED);
464 * Remove all data objects of a certain originator from a layer-2 network
466 * @param l2net layer-2 addr object
467 * @param origin originator number
468 * @param cleanup_neigh true to cleanup neighbor data too
469 * @return true if a value was removed, false otherwise
472 oonf_layer2_net_cleanup(struct oonf_layer2_net *l2net,
473 const struct oonf_layer2_origin *origin, bool cleanup_neigh) {
474 struct oonf_layer2_neigh *l2neigh;
475 bool changed = false;
478 for (i=0; i<OONF_LAYER2_NET_COUNT; i++) {
479 if (l2net->data[i]._origin == origin) {
480 oonf_layer2_data_reset(&l2net->data[i]);
484 for (i=0; i<OONF_LAYER2_NEIGH_COUNT; i++) {
485 if (l2net->neighdata[i]._origin == origin) {
486 oonf_layer2_data_reset(&l2net->neighdata[i]);
492 avl_for_each_element(&l2net->neighbors, l2neigh, _node) {
493 changed |= oonf_layer2_neigh_cleanup(l2neigh, origin);
500 * Remove all information of a certain originator from a layer-2 addr
501 * object. Remove the object if its empty and has no neighbors anymore.
502 * @param l2net layer-2 addr object
503 * @param origin originator identifier
504 * @return true if something changed, false otherwise
507 oonf_layer2_net_remove(struct oonf_layer2_net *l2net,
508 const struct oonf_layer2_origin *origin) {
509 struct oonf_layer2_neigh *l2neigh, *l2neigh_it;
510 bool changed = false;
512 if (!avl_is_node_added(&l2net->_node)) {
516 avl_for_each_element_safe(&l2net->neighbors, l2neigh, _node, l2neigh_it) {
517 if (oonf_layer2_neigh_remove(l2neigh, origin)) {
522 if (oonf_layer2_net_cleanup(l2net, origin, false)) {
527 oonf_layer2_net_commit(l2net);
533 * Commit all changes to a layer-2 addr object. This might remove the
534 * object from the database if all data has been removed from the object.
535 * @param l2net layer-2 addr object
536 * @return true if the object has been removed, false otherwise
539 oonf_layer2_net_commit(struct oonf_layer2_net *l2net) {
542 if (l2net->neighbors.count > 0) {
543 oonf_class_event(&_l2network_class, l2net, OONF_OBJECT_CHANGED);
547 for (i=0; i<OONF_LAYER2_NET_COUNT; i++) {
548 if (oonf_layer2_data_has_value(&l2net->data[i])) {
549 oonf_class_event(&_l2network_class, l2net, OONF_OBJECT_CHANGED);
554 for (i=0; i<OONF_LAYER2_NEIGH_COUNT; i++) {
555 if (oonf_layer2_data_has_value(&l2net->neighdata[i])) {
556 oonf_class_event(&_l2network_class, l2net, OONF_OBJECT_CHANGED);
566 * Relabel all network data (including neighbor data)
567 * of one origin to another one
568 * @param l2net layer2 network object
569 * @param new_origin new origin
570 * @param old_origin old origin to overwrite
573 oonf_layer2_net_relabel(struct oonf_layer2_net *l2net,
574 const struct oonf_layer2_origin *new_origin,
575 const struct oonf_layer2_origin *old_origin) {
576 struct oonf_layer2_neigh *l2neigh;
577 struct oonf_layer2_peer_address *peer_ip;
580 for (i=0; i<OONF_LAYER2_NET_COUNT; i++) {
581 if (oonf_layer2_data_get_origin(&l2net->data[i]) == old_origin) {
582 oonf_layer2_data_set_origin(&l2net->data[i], new_origin);
586 for (i=0; i<OONF_LAYER2_NEIGH_COUNT; i++) {
587 if (oonf_layer2_data_get_origin(&l2net->neighdata[i]) == old_origin) {
588 oonf_layer2_data_set_origin(&l2net->neighdata[i], new_origin);
592 avl_for_each_element(&l2net->local_peer_ips, peer_ip,_net_node) {
593 if (peer_ip->origin == old_origin) {
594 peer_ip->origin = new_origin;
598 avl_for_each_element(&l2net->neighbors, l2neigh, _node) {
599 oonf_layer2_neigh_relabel(l2neigh, new_origin, old_origin);
604 * Add an IP address or prefix to a layer-2 interface. This represents
605 * an address of the local radio or modem.
606 * @param l2net layer-2 network object
607 * @param ip ip address or prefix
608 * @return layer2 ip address object, NULL if out of memory
610 struct oonf_layer2_peer_address *
611 oonf_layer2_net_add_ip(struct oonf_layer2_net *l2net,
612 const struct oonf_layer2_origin *origin, const struct netaddr *ip) {
613 struct oonf_layer2_peer_address *l2addr;
615 l2addr = oonf_layer2_net_get_local_ip(l2net, ip);
617 l2addr = oonf_class_malloc(&_l2net_addr_class);
623 memcpy(&l2addr->ip, ip, sizeof(*ip));
625 /* set back reference */
626 l2addr->l2net = l2net;
629 l2addr->_net_node.key = &l2addr->ip;
630 avl_insert(&l2net->local_peer_ips, &l2addr->_net_node);
632 l2addr->_global_node.key = &l2addr->ip;
633 avl_insert(&_local_peer_ips_tree, &l2addr->_global_node);
635 oonf_class_event(&_l2net_addr_class, l2addr, OONF_OBJECT_ADDED);
638 l2addr->origin = origin;
643 * Remove a peer IP address from a layer2 network
644 * @param ip ip address or prefix
645 * @param origin origin of IP address
646 * @return 0 if IP was removed, -1 if it was registered to a different origin
649 oonf_layer2_net_remove_ip(
650 struct oonf_layer2_peer_address *ip, const struct oonf_layer2_origin *origin) {
651 if (ip->origin != origin) {
655 oonf_class_event(&_l2net_addr_class, ip, OONF_OBJECT_REMOVED);
657 avl_remove(&ip->l2net->local_peer_ips, &ip->_net_node);
658 avl_remove(&_local_peer_ips_tree, &ip->_global_node);
659 oonf_class_free(&_l2net_addr_class, ip);
664 * Look for the best matching prefix in all layer2 neighbor addresses
665 * that contains a specific address
666 * @param addr ip address to look for
667 * @return layer2 neighbor address object, NULL if no match was found
669 struct oonf_layer2_neighbor_address *
670 oonf_layer2_net_get_best_neighbor_match(const struct netaddr *addr) {
671 struct oonf_layer2_neighbor_address *best_match, *l2addr;
672 struct oonf_layer2_neigh *l2neigh;
673 struct oonf_layer2_net *l2net;
679 avl_for_each_element(&_oonf_layer2_net_tree, l2net, _node) {
680 avl_for_each_element(&l2net->neighbors, l2neigh, _node) {
681 avl_for_each_element(&l2neigh->remote_neighbor_ips, l2addr, _neigh_node) {
682 if (netaddr_is_in_subnet(&l2addr->ip, addr)
683 && netaddr_get_prefix_length(&l2addr->ip) < prefix_length) {
685 prefix_length = netaddr_get_prefix_length(&l2addr->ip);
694 * Add a layer-2 neighbor to a addr.
695 * @param l2net layer-2 addr object
696 * @param neigh mac address of layer-2 neighbor
697 * @return layer-2 neighbor object
699 struct oonf_layer2_neigh *
700 oonf_layer2_neigh_add(struct oonf_layer2_net *l2net,
701 const struct netaddr *neigh) {
702 struct oonf_layer2_neigh *l2neigh;
704 if (netaddr_get_address_family(neigh) != AF_MAC48
705 && netaddr_get_address_family(neigh) != AF_EUI64) {
709 l2neigh = oonf_layer2_neigh_get(l2net, neigh);
714 l2neigh = oonf_class_malloc(&_l2neighbor_class);
719 memcpy(&l2neigh->addr, neigh, sizeof(*neigh));
720 l2neigh->_node.key = &l2neigh->addr;
721 l2neigh->network = l2net;
723 avl_insert(&l2net->neighbors, &l2neigh->_node);
725 avl_init(&l2neigh->destinations, avl_comp_netaddr, false);
726 avl_init(&l2neigh->remote_neighbor_ips, avl_comp_netaddr, false);
728 oonf_class_event(&_l2neighbor_class, l2neigh, OONF_OBJECT_ADDED);
734 * Remove all data objects of a certain originator from a layer-2 neighbor
736 * @param l2neigh layer-2 neighbor
737 * @param origin originator number
738 * @return true if a value was resetted, false otherwise
741 oonf_layer2_neigh_cleanup(struct oonf_layer2_neigh *l2neigh,
742 const struct oonf_layer2_origin *origin) {
743 bool changed = false;
746 for (i=0; i<OONF_LAYER2_NEIGH_COUNT; i++) {
747 if (l2neigh->data[i]._origin == origin) {
748 oonf_layer2_data_reset(&l2neigh->data[i]);
757 * Remove all information of a certain originator from a layer-2 neighbor
758 * object. Remove the object if its empty.
759 * @param l2neigh layer-2 neighbor object
760 * @param origin originator number
761 * @return true if something was change, false otherwise
764 oonf_layer2_neigh_remove(struct oonf_layer2_neigh *l2neigh,
765 const struct oonf_layer2_origin *origin) {
766 struct oonf_layer2_destination *l2dst, *l2dst_it;
767 struct oonf_layer2_neighbor_address *l2ip, *l2ip_it;
769 bool changed = false;
771 if (!avl_is_node_added(&l2neigh->_node)) {
775 avl_for_each_element_safe(&l2neigh->destinations, l2dst, _node, l2dst_it) {
776 if (l2dst->origin == origin) {
777 oonf_layer2_destination_remove(l2dst);
782 avl_for_each_element_safe(&l2neigh->remote_neighbor_ips, l2ip, _neigh_node, l2ip_it) {
783 if (oonf_layer2_neigh_remove_ip(l2ip, origin) == 0) {
788 if (oonf_layer2_neigh_cleanup(l2neigh, origin)) {
793 oonf_layer2_neigh_commit(l2neigh);
799 * Commit all changes to a layer-2 neighbor object. This might remove the
800 * object from the database if all data has been removed from the object.
801 * @param l2neigh layer-2 neighbor object
802 * @return true if the object has been removed, false otherwise
805 oonf_layer2_neigh_commit(struct oonf_layer2_neigh *l2neigh) {
808 if (l2neigh->destinations.count > 0 || l2neigh->remote_neighbor_ips.count > 0) {
809 oonf_class_event(&_l2neighbor_class, l2neigh, OONF_OBJECT_CHANGED);
813 for (i=0; i<OONF_LAYER2_NEIGH_COUNT; i++) {
814 if (oonf_layer2_data_has_value(&l2neigh->data[i])) {
815 oonf_class_event(&_l2neighbor_class, l2neigh, OONF_OBJECT_CHANGED);
820 _neigh_remove(l2neigh);
825 * Relabel all neighbor data of one origin to another one
826 * @param l2neigh layer2 neighbor object
827 * @param new_origin new origin
828 * @param old_origin old origin to overwrite
831 oonf_layer2_neigh_relabel(struct oonf_layer2_neigh *l2neigh,
832 const struct oonf_layer2_origin *new_origin,
833 const struct oonf_layer2_origin *old_origin) {
834 struct oonf_layer2_neighbor_address *neigh_ip;
835 struct oonf_layer2_destination *l2dst;
838 for (i=0; i<OONF_LAYER2_NEIGH_COUNT; i++) {
839 if (oonf_layer2_data_get_origin(&l2neigh->data[i]) == old_origin) {
840 oonf_layer2_data_set_origin(&l2neigh->data[i], new_origin);
844 avl_for_each_element(&l2neigh->remote_neighbor_ips, neigh_ip, _neigh_node) {
845 if (neigh_ip->origin == old_origin) {
846 neigh_ip->origin = new_origin;
850 avl_for_each_element(&l2neigh->destinations, l2dst, _node) {
851 if (l2dst->origin == old_origin) {
852 l2dst->origin = new_origin;
858 * Add an IP address or prefix to a layer-2 interface. This represents
859 * an address of the local radio or modem.
860 * @param l2net layer-2 network object
861 * @param ip ip address or prefix
862 * @return layer2 ip address object, NULL if out of memory
864 struct oonf_layer2_neighbor_address *
865 oonf_layer2_neigh_add_ip(struct oonf_layer2_neigh *l2neigh,
866 const struct oonf_layer2_origin *origin, const struct netaddr *ip) {
867 struct oonf_layer2_neighbor_address *l2addr;
869 l2addr = oonf_layer2_neigh_get_remote_ip(l2neigh, ip);
871 l2addr = oonf_class_malloc(&_l2neigh_addr_class);
877 memcpy(&l2addr->ip, ip, sizeof(*ip));
879 /* set back reference */
880 l2addr->l2neigh = l2neigh;
883 l2addr->_neigh_node.key = &l2addr->ip;
884 avl_insert(&l2neigh->remote_neighbor_ips, &l2addr->_neigh_node);
885 l2addr->_net_node.key = &l2addr->ip;
886 avl_insert(&l2neigh->network->remote_neighbor_ips, &l2addr->_net_node);
888 oonf_class_event(&_l2neigh_addr_class, l2addr, OONF_OBJECT_ADDED);
891 l2addr->origin = origin;
896 * Remove a neighbor IP address from a layer2 neighbor
897 * @param ip ip address or prefix
898 * @param origin origin of IP address
899 * @return 0 if IP was removed, -1 if it was registered to a different origin
902 oonf_layer2_neigh_remove_ip(
903 struct oonf_layer2_neighbor_address *ip, const struct oonf_layer2_origin *origin) {
904 if (ip->origin != origin) {
908 oonf_class_event(&_l2neigh_addr_class, ip, OONF_OBJECT_REMOVED);
910 avl_remove(&ip->l2neigh->remote_neighbor_ips, &ip->_neigh_node);
911 avl_remove(&ip->l2neigh->network->remote_neighbor_ips, &ip->_net_node);
912 oonf_class_free(&_l2neigh_addr_class, ip);
917 * add a layer2 destination (a MAC address behind a neighbor) to
918 * the layer2 database
919 * @param l2neigh layer2 neighbor of the destination
920 * @param destination destination address
921 * @param origin layer2 origin
922 * @return layer2 destination, NULL if out of memory
924 struct oonf_layer2_destination *
925 oonf_layer2_destination_add(struct oonf_layer2_neigh *l2neigh,
926 const struct netaddr *destination,
927 const struct oonf_layer2_origin *origin) {
928 struct oonf_layer2_destination *l2dst;
930 l2dst = oonf_layer2_destination_get(l2neigh, destination);
935 l2dst = oonf_class_malloc(&_l2dst_class);
940 /* copy data into destination storage */
941 memcpy(&l2dst->destination, destination, sizeof(*destination));
942 l2dst->origin = origin;
944 /* add back-pointer */
945 l2dst->neighbor = l2neigh;
947 /* add to neighbor tree */
948 l2dst->_node.key = &l2dst->destination;
949 avl_insert(&l2neigh->destinations, &l2dst->_node);
951 oonf_class_event(&_l2dst_class, l2dst, OONF_OBJECT_ADDED);
956 * Remove a layer2 destination
957 * @param l2dst layer2 destination
960 oonf_layer2_destination_remove(struct oonf_layer2_destination *l2dst) {
961 if (!avl_is_node_added(&l2dst->_node)) {
964 oonf_class_event(&_l2dst_class, l2dst, OONF_OBJECT_REMOVED);
966 avl_remove(&l2dst->neighbor->destinations, &l2dst->_node);
967 oonf_class_free(&_l2dst_class, l2dst);
971 * Get neighbor specific data, either from neighbor or from the networks default
972 * @param ifname name of interface
973 * @param l2neigh_addr neighbor mac address
974 * @param idx data index
975 * @return pointer to linklayer data, NULL if no value available
977 const struct oonf_layer2_data *
978 oonf_layer2_neigh_query(const char *ifname,
979 const struct netaddr *l2neigh_addr, enum oonf_layer2_neighbor_index idx) {
980 struct oonf_layer2_net *l2net;
981 struct oonf_layer2_neigh *l2neigh;
982 struct oonf_layer2_data *data;
984 /* query layer2 database about neighbor */
985 l2net = oonf_layer2_net_get(ifname);
990 /* look for neighbor specific data */
991 l2neigh = oonf_layer2_neigh_get(l2net, l2neigh_addr);
992 if (l2neigh != NULL) {
993 data = &l2neigh->data[idx];
994 if (oonf_layer2_data_has_value(data)) {
999 /* look for network specific default */
1000 data = &l2net->neighdata[idx];
1001 if (oonf_layer2_data_has_value(data)) {
1008 * Get neighbor specific data, either from neighbor or from the networks default
1009 * @param l2neigh pointer to layer2 neighbor
1010 * @param idx data index
1011 * @return pointer to linklayer data, NULL if no value available
1013 const struct oonf_layer2_data *
1014 oonf_layer2_neigh_get_data(const struct oonf_layer2_neigh *l2neigh,
1015 enum oonf_layer2_neighbor_index idx) {
1016 const struct oonf_layer2_data *data;
1018 data = &l2neigh->data[idx];
1019 if (oonf_layer2_data_has_value(data)) {
1023 /* look for network specific default */
1024 data = &l2neigh->network->neighdata[idx];
1025 if (oonf_layer2_data_has_value(data)) {
1032 * get neighbor metric metadata
1033 * @param idx neighbor metric index
1034 * @return metadata object
1036 const struct oonf_layer2_metadata *
1037 oonf_layer2_neigh_metadata_get(enum oonf_layer2_neighbor_index idx) {
1038 return &_metadata_neigh[idx];
1042 * get network metric metadata
1043 * @param idx network metric index
1044 * @return metadata object
1046 const struct oonf_layer2_metadata *
1047 oonf_layer2_net_metadata_get(enum oonf_layer2_network_index idx) {
1048 return &_metadata_net[idx];
1052 * Callback for configuration choice of layer2 network key
1054 * @param unused not used
1055 * @return pointer to network key
1058 oonf_layer2_cfg_get_l2net_key(size_t idx, const void *unused __attribute__((unused))) {
1059 return _metadata_net[idx].key;
1063 * Callback for configuration choice of layer2 neighbor key
1065 * @param unused not used
1066 * @return pointer to neighbor key
1069 oonf_layer2_cfg_get_l2neigh_key(size_t idx, const void *unused __attribute__((unused))) {
1070 return _metadata_neigh[idx].key;
1074 * Callback for configuration choice of layer2 neighbor key
1076 * @param unused not used
1077 * @return pointer to neighbor key
1080 oonf_layer2_cfg_get_l2comp(size_t idx, const void *unused __attribute__((unused))) {
1081 return _data_comparators[idx];
1085 * get text representation of network type
1086 * @param type network type
1087 * @return text representation
1090 oonf_layer2_net_get_type_name(enum oonf_layer2_network_type type) {
1091 return _network_type[type];
1095 * get tree of layer2 networks
1096 * @return network tree
1099 oonf_layer2_get_net_tree(void) {
1100 return &_oonf_layer2_net_tree;
1104 * get tree of layer2 originators
1105 * @return originator tree
1108 oonf_layer2_get_origin_tree(void) {
1109 return &_oonf_originator_tree;
1113 * Removes a layer-2 addr object from the database.
1114 * @param l2net layer-2 addr object
1117 _net_remove(struct oonf_layer2_net *l2net) {
1118 struct oonf_layer2_neigh *l2neigh, *l2n_it;
1119 struct oonf_layer2_peer_address *l2peer, *l2peer_it;
1121 /* free all embedded neighbors */
1122 avl_for_each_element_safe(&l2net->neighbors, l2neigh, _node, l2n_it) {
1123 _neigh_remove(l2neigh);
1126 /* free all attached peer addresses */
1127 avl_for_each_element_safe(&l2net->local_peer_ips, l2peer, _net_node, l2peer_it) {
1128 oonf_layer2_net_remove_ip(l2peer, l2peer->origin);
1131 oonf_class_event(&_l2network_class, l2net, OONF_OBJECT_REMOVED);
1133 /* remove interface listener */
1134 os_interface_remove(&l2net->if_listener);
1137 avl_remove(&_oonf_layer2_net_tree, &l2net->_node);
1138 oonf_class_free(&_l2network_class, l2net);
1142 * Removes a layer-2 neighbor object from the database
1143 * @param l2neigh layer-2 neighbor object
1146 _neigh_remove(struct oonf_layer2_neigh *l2neigh) {
1147 struct oonf_layer2_destination *l2dst, *l2dst_it;
1148 struct oonf_layer2_neighbor_address *l2addr, *l2addr_it;
1150 /* free all embedded destinations */
1151 avl_for_each_element_safe(&l2neigh->destinations, l2dst, _node, l2dst_it) {
1152 oonf_layer2_destination_remove(l2dst);
1155 /* free all attached neighbor addresses */
1156 avl_for_each_element_safe(&l2neigh->remote_neighbor_ips, l2addr, _neigh_node, l2addr_it) {
1157 oonf_layer2_neigh_remove_ip(l2addr, l2addr->origin);
1160 /* inform user that mac entry will be removed */
1161 oonf_class_event(&_l2neighbor_class, l2neigh, OONF_OBJECT_REMOVED);
1163 /* free resources for mac entry */
1164 avl_remove(&l2neigh->network->neighbors, &l2neigh->_node);
1165 oonf_class_free(&_l2neighbor_class, l2neigh);