Rename "subsystems" directory to "base"
[oonf.git] / src / generic / layer2_generator / layer2_generator.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 <stdio.h>
47
48 #include <oonf/libcommon/autobuf.h>
49 #include <oonf/oonf.h>
50 #include <oonf/libcommon/netaddr.h>
51 #include <oonf/libcommon/string.h>
52 #include <oonf/libcommon/template.h>
53
54 #include <oonf/libconfig/cfg_schema.h>
55 #include <oonf/libcore/oonf_logging.h>
56 #include <oonf/libcore/oonf_subsystem.h>
57 #include <oonf/base/oonf_clock.h>
58 #include <oonf/base/oonf_layer2.h>
59 #include <oonf/base/oonf_timer.h>
60
61 #include <oonf/generic/layer2_generator/layer2_generator.h>
62
63 /* Definitions */
64 #define LOG_L2GEN _layer2_generator_subsystem.logging
65
66 /* prototypes */
67 static int _init(void);
68 static void _cleanup(void);
69
70 static void _cb_l2gen_event(struct oonf_timer_instance *);
71
72 static void _cb_config_changed(void);
73
74 /**
75  * Configuration of layer2 generator
76  */
77 struct _l2_generator_config {
78   /*! interval between two layer2 event generations */
79   uint64_t interval;
80
81   /*! true if generator is active */
82   bool active;
83
84   /*! name of interface for event generation */
85   char interface[IF_NAMESIZE];
86
87   /*! neighbor mac address for event generation */
88   struct netaddr neighbor;
89
90   /*! proxied MAC behind neighbor for event generation */
91   struct netaddr destination;
92 };
93
94 static struct oonf_timer_class _l2gen_timer_info = {
95   .name = "L2 Generator event",
96   .callback = _cb_l2gen_event,
97   .periodic = true,
98 };
99
100 static struct oonf_timer_instance _l2gen_timer = {
101   .class = &_l2gen_timer_info,
102 };
103
104 /* configuration */
105 static struct _l2_generator_config _l2gen_config;
106
107 static struct cfg_schema_entry _l2gen_entries[] = {
108   CFG_MAP_CLOCK_MIN(_l2_generator_config, interval, "interval", "3.000", "Interval between L2 generator events", 500),
109   CFG_MAP_STRING_ARRAY(_l2_generator_config, interface, "interface", "eth0", "Interface of example radio", IF_NAMESIZE),
110   CFG_MAP_NETADDR_MAC48(
111     _l2_generator_config, neighbor, "neighbor", "02:00:00:00:00:01", "Mac address of example radio", false, false),
112   CFG_MAP_NETADDR_MAC48(_l2_generator_config, destination, "destination", "02:00:00:00:00:02",
113     "Mac address of example radio destination", false, true),
114   CFG_MAP_BOOL(_l2_generator_config, active, "active", "false", "Activates artificially generated layer2 data"),
115 };
116
117 static struct cfg_schema_section _l2gen_section = {
118   .type = OONF_L2GEN_SUBSYSTEM,
119   .cb_delta_handler = _cb_config_changed,
120   .entries = _l2gen_entries,
121   .entry_count = ARRAYSIZE(_l2gen_entries),
122 };
123
124 /* plugin declaration */
125 static const char *_dependencies[] = {
126   OONF_CLOCK_SUBSYSTEM,
127   OONF_LAYER2_SUBSYSTEM,
128   OONF_TIMER_SUBSYSTEM,
129 };
130
131 static struct oonf_subsystem _layer2_generator_subsystem = {
132   .name = OONF_L2GEN_SUBSYSTEM,
133   .dependencies = _dependencies,
134   .dependencies_count = ARRAYSIZE(_dependencies),
135   .descr = "OONF layer2-generator plugin",
136   .author = "Henning Rogge",
137
138   .cfg_section = &_l2gen_section,
139
140   .init = _init,
141   .cleanup = _cleanup,
142 };
143 DECLARE_OONF_PLUGIN(_layer2_generator_subsystem);
144
145 static struct oonf_layer2_origin _origin = {
146   .name = "layer2 generator",
147   .proactive = true,
148   .priority = OONF_LAYER2_ORIGIN_CONFIGURED,
149 };
150
151 /**
152  * Constructor of plugin
153  * @return 0 if initialization was successful, -1 otherwise
154  */
155 static int
156 _init(void) {
157   memset(&_l2gen_config, 0, sizeof(_l2gen_config));
158
159   oonf_layer2_origin_add(&_origin);
160   oonf_timer_add(&_l2gen_timer_info);
161   oonf_timer_start(&_l2gen_timer, 5000);
162   return 0;
163 }
164
165 /**
166  * Destructor of plugin
167  */
168 static void
169 _cleanup(void) {
170   oonf_layer2_origin_remove(&_origin);
171   oonf_timer_stop(&_l2gen_timer);
172   oonf_timer_remove(&_l2gen_timer_info);
173 }
174
175 static void
176 _set_data(struct oonf_layer2_data *data, enum oonf_layer2_data_type type, int64_t value) {
177   switch (type) {
178     case OONF_LAYER2_INTEGER_DATA:
179       oonf_layer2_data_set_int64(data, &_origin, value);
180       break;
181     case OONF_LAYER2_BOOLEAN_DATA:
182       oonf_layer2_data_set_bool(data, &_origin, (value & 1) != 0);
183       break;
184     default:
185       break;
186   }
187 }
188
189 /**
190  * Callback for generating new layer2 test data
191  * @param ptr timer instance that fired
192  */
193 static void
194 _cb_l2gen_event(struct oonf_timer_instance *ptr __attribute((unused))) {
195   static uint64_t event_counter = 100;
196   enum oonf_layer2_network_index net_idx;
197   enum oonf_layer2_neighbor_index neigh_idx;
198   struct oonf_layer2_net *net;
199   struct oonf_layer2_neigh *neigh;
200 #ifdef OONF_LOG_DEBUG_INFO
201   struct netaddr_str buf1;
202 #endif
203
204   if (oonf_layer2_origin_is_added(&_origin)) {
205     return;
206   }
207
208   event_counter++;
209
210   OONF_DEBUG(LOG_L2GEN, "L2Gen-Event triggered (%s/%s/%" PRIu64 ")", _l2gen_config.interface,
211     netaddr_to_string(&buf1, &_l2gen_config.neighbor), event_counter);
212
213   net = oonf_layer2_net_add(_l2gen_config.interface);
214   if (net == NULL) {
215     OONF_WARN(LOG_L2GEN, "Cannot allocate layer2_network");
216     return;
217   }
218
219   strscpy(net->if_ident, "Interface generated by layer2-generator plugin", sizeof(net->if_ident));
220   net->if_type = OONF_LAYER2_TYPE_UNDEFINED;
221   net->last_seen = oonf_clock_getNow();
222
223   for (net_idx = 0; net_idx < OONF_LAYER2_NET_COUNT; net_idx++) {
224     _set_data(&net->data[net_idx], oonf_layer2_net_metadata_get(net_idx)->type, event_counter);
225   }
226   for (neigh_idx = 0; neigh_idx < OONF_LAYER2_NEIGH_COUNT; neigh_idx++) {
227     _set_data(&net->neighdata[neigh_idx], oonf_layer2_neigh_metadata_get(neigh_idx)->type, event_counter);
228   }
229
230   if (oonf_layer2_net_commit(net)) {
231     /* something bad has happened, l2net was removed */
232     OONF_WARN(LOG_L2GEN, "Could not commit interface %s", _l2gen_config.interface);
233     return;
234   }
235
236   neigh = oonf_layer2_neigh_add(net, &_l2gen_config.neighbor);
237   if (neigh == NULL) {
238     OONF_WARN(LOG_L2GEN, "Cannot allocate layer2_neighbor");
239     return;
240   }
241
242   if (netaddr_get_address_family(&_l2gen_config.destination) == AF_MAC48) {
243     oonf_layer2_destination_add(neigh, &_l2gen_config.destination, &_origin);
244   }
245   memcpy(&neigh->key.addr, &_l2gen_config.neighbor, sizeof(neigh->key.addr));
246   neigh->key.link_id[0] = event_counter & 0xff;
247   neigh->key.link_id_length = 1;
248   neigh->last_seen = oonf_clock_getNow();
249
250   for (neigh_idx = 0; neigh_idx < OONF_LAYER2_NEIGH_COUNT; neigh_idx++) {
251     _set_data(&neigh->data[neigh_idx], oonf_layer2_neigh_metadata_get(neigh_idx)->type, event_counter);
252   }
253   oonf_layer2_neigh_commit(neigh);
254 }
255
256 static void
257 _cb_config_changed(void) {
258   if (cfg_schema_tobin(&_l2gen_config, _l2gen_section.post, _l2gen_entries, ARRAYSIZE(_l2gen_entries))) {
259     OONF_WARN(LOG_L2GEN, "Could not convert " OONF_L2GEN_SUBSYSTEM " plugin configuration");
260     return;
261   }
262
263   cfg_get_phy_if(_l2gen_config.interface, _l2gen_config.interface);
264
265   OONF_DEBUG(LOG_L2GEN, "Generator is now %s for interface %s\n", _l2gen_config.active ? "active" : "inactive",
266     _l2gen_config.interface);
267
268   if (!oonf_layer2_origin_is_added(&_origin) && _l2gen_config.active) {
269     oonf_layer2_origin_add(&_origin);
270   }
271   else if (oonf_layer2_origin_is_added(&_origin) && !_l2gen_config.active) {
272     oonf_layer2_origin_remove(&_origin);
273   }
274
275   /* set new interval */
276   oonf_timer_set(&_l2gen_timer, _l2gen_config.interval);
277 }