00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <stdio.h>
00043
00044 #include "tc_set.h"
00045 #include "link_set.h"
00046 #include "lq_plugin.h"
00047 #include "olsr_spf.h"
00048 #include "lq_packet.h"
00049 #include "olsr.h"
00050 #include "parser.h"
00051 #include "mid_set.h"
00052 #include "olsr_timer.h"
00053 #include "olsr_socket.h"
00054 #include "olsr_logging.h"
00055 #include "common/string.h"
00056 #include "neighbor_table.h"
00057 #include "lq_plugin_etx_ff.h"
00058
00059 #define PLUGIN_DESCR "Freifunk ETX metric based on the original design of Elektra and Thomas Lopatic"
00060 #define PLUGIN_AUTHOR "Henning Rogge"
00061
00062 #define LQ_ALGORITHM_ETX_FF_NAME "etx_ff"
00063
00064 #define LQ_FF_QUICKSTART_INIT 4
00065
00066 #define LQ_PLUGIN_RELEVANT_COSTCHANGE_FF 16
00067
00068 static int lq_etxff_enable(void);
00069
00070 static void lq_etxff_initialize(void);
00071 static void lq_etxff_deinitialize(void);
00072
00073 static olsr_linkcost lq_etxff_calc_link_entry_cost(struct link_entry *);
00074 static olsr_linkcost lq_etxff_calc_lq_hello_neighbor_cost(struct lq_hello_neighbor *);
00075 static olsr_linkcost lq_etxff_calc_tc_edge_entry_cost(struct tc_edge_entry *);
00076
00077 static void lq_etxff_hello_handler(struct link_entry *, bool);
00078
00079 static void lq_etxff_memorize_foreign_hello(struct link_entry *, struct lq_hello_neighbor *);
00080 static void lq_etxff_copy_link_entry_lq_into_tc_edge_entry(struct tc_edge_entry *target, struct link_entry *source);
00081
00082 static void lq_etxff_clear_link_entry(struct link_entry *);
00083 static void lq_etxff_clear_tc_edge_entry(struct tc_edge_entry *);
00084
00085 static void lq_etxff_serialize_hello_lq(uint8_t **curr, struct link_entry *link);
00086 static void lq_etxff_serialize_tc_lq(uint8_t **curr, struct link_entry *link);
00087 static void lq_etxff_deserialize_hello_lq(uint8_t const **curr, struct lq_hello_neighbor *lq);
00088 static void lq_etxff_deserialize_tc_lq(uint8_t const **curr, struct tc_edge_entry *lq);
00089
00090 static int lq_etxff_get_linkentry_data(struct link_entry *, int);
00091 static const char *lq_etxff_print_cost(olsr_linkcost cost, char *buffer, size_t bufsize);
00092 static const char *lq_etxff_print_link_entry_lq(struct link_entry *entry, int index, char *buffer, size_t bufsize);
00093
00094 static struct olsr_timer_info *default_lq_ff_timer_info = NULL;
00095
00096 OLSR_PLUGIN6_NP() {
00097 .descr = PLUGIN_DESCR,
00098 .author = PLUGIN_AUTHOR,
00099 .enable = lq_etxff_enable,
00100 .type = PLUGIN_TYPE_LQ
00101 };
00102
00103
00104 struct lq_linkdata_type lq_etxff_linktypes[] = {
00105 { "ETX", 5, 65536, 65536*2, 65536*4, INT32_MAX },
00106 { "LQ", 5, 255, 240, 192, 0 },
00107 { "NLQ", 5, 255, 240, 192, 0 }
00108 };
00109
00110 struct lq_handler lq_etxff_handler = {
00111 "etx (freifunk)",
00112
00113 &lq_etxff_initialize,
00114 &lq_etxff_deinitialize,
00115
00116 &lq_etxff_calc_link_entry_cost,
00117 &lq_etxff_calc_lq_hello_neighbor_cost,
00118 &lq_etxff_calc_tc_edge_entry_cost,
00119
00120 &lq_etxff_hello_handler,
00121
00122 &lq_etxff_memorize_foreign_hello,
00123 &lq_etxff_copy_link_entry_lq_into_tc_edge_entry,
00124
00125 &lq_etxff_clear_link_entry,
00126 NULL,
00127 &lq_etxff_clear_tc_edge_entry,
00128
00129 &lq_etxff_serialize_hello_lq,
00130 &lq_etxff_serialize_tc_lq,
00131 &lq_etxff_deserialize_hello_lq,
00132 &lq_etxff_deserialize_tc_lq,
00133
00134 &lq_etxff_get_linkentry_data,
00135 &lq_etxff_print_cost,
00136 &lq_etxff_print_link_entry_lq,
00137
00138 lq_etxff_linktypes,
00139 ARRAYSIZE(lq_etxff_linktypes),
00140
00141 sizeof(struct lq_etxff_tc_edge),
00142 sizeof(struct lq_etxff_lq_hello_neighbor),
00143 sizeof(struct lq_etxff_link_entry),
00144
00145 LQ_HELLO_MESSAGE,
00146 LQ_TC_MESSAGE,
00147
00148 4,4
00149 };
00150
00151 static int
00152 lq_etxff_enable(void) {
00153 active_lq_handler = &lq_etxff_handler;
00154 return false;
00155 }
00156
00157 static void
00158 lq_etxff_packet_parser(struct olsr_packet *pkt, uint8_t *binary __attribute__ ((unused)),
00159 struct interface *in_if, union olsr_ip_addr *from_addr)
00160 {
00161 const union olsr_ip_addr *main_addr;
00162 struct lq_etxff_link_entry *lnk;
00163 uint32_t seq_diff;
00164 #if !defined(REMOVE_LOG_WARN) || !defined(REMOVE_LOG_DEBUG)
00165 struct ipaddr_str buf;
00166 #endif
00167
00168
00169 main_addr = olsr_lookup_main_addr_by_alias(from_addr);
00170
00171
00172 lnk = (struct lq_etxff_link_entry *)lookup_link_entry(from_addr, main_addr, in_if);
00173 if (lnk == NULL) {
00174 return;
00175 }
00176
00177 if (lnk->last_seq_nr == pkt->seqno) {
00178 OLSR_WARN(LOG_LQ_PLUGINS, "Got package with same sequence number from %s, if=%s, seq=0x%04x\n",
00179 olsr_ip_to_string(&buf, from_addr), in_if->int_name, pkt->seqno);
00180 return;
00181 }
00182 if (lnk->last_seq_nr > pkt->seqno) {
00183 seq_diff = (uint32_t) pkt->seqno + 65536 - lnk->last_seq_nr;
00184 } else {
00185 seq_diff = pkt->seqno - lnk->last_seq_nr;
00186 }
00187
00188 OLSR_DEBUG(LOG_LQ_PLUGINS, "Got package from %s, if=%s, seq=0x%04x, diff=0x%04x\n",
00189 olsr_ip_to_string(&buf, from_addr), in_if->int_name, pkt->seqno, seq_diff);
00190
00191
00192 if (seq_diff > 256) {
00193 seq_diff = 1;
00194 }
00195
00196 lnk->received[lnk->activePtr]++;
00197 lnk->total[lnk->activePtr] += seq_diff;
00198
00199 lnk->last_seq_nr = pkt->seqno;
00200 lnk->missed_seconds = 0;
00201 }
00202
00203 static void
00204 lq_etxff_timer(void __attribute__ ((unused)) * context)
00205 {
00206 struct link_entry *link, *link_iterator;
00207 struct nbr_entry *nbr, *nbr_iterator;
00208
00209 OLSR_FOR_ALL_LINK_ENTRIES(link, link_iterator) {
00210 struct lq_etxff_link_entry *lq_link;
00211 uint32_t ratio;
00212 uint16_t i, received, total;
00213
00214 #ifndef REMOVE_LOG_DEBUG
00215 struct ipaddr_str buf;
00216
00217 #endif
00218 lq_link = (struct lq_etxff_link_entry *)link;
00219
00220 OLSR_DEBUG(LOG_LQ_PLUGINS, "LQ-FF new entry for %s: rec: %d total: %d",
00221 olsr_ip_to_string(&buf, &link->neighbor_iface_addr),
00222 lq_link->received[lq_link->activePtr], lq_link->total[lq_link->activePtr]);
00223
00224 received = 0;
00225 total = 0;
00226
00227
00228 if (lq_link->windowSize < LQ_FF_WINDOW) {
00229 lq_link->windowSize++;
00230 }
00231 for (i = 0; i < lq_link->windowSize; i++) {
00232 received += lq_link->received[i];
00233 total += lq_link->total[i];
00234 }
00235
00236 OLSR_DEBUG(LOG_LQ_PLUGINS, " total-rec: %d total: %d", received, total);
00237
00238
00239 if (total == 0) {
00240 lq_link->lq.valueLq = 0;
00241 } else {
00242
00243
00244 uint32_t missed_hello_cost = lq_link->missed_seconds / ((lq_link->core.link_loss_timer->timer_period + 999) / 1000);
00245 total += missed_hello_cost * missed_hello_cost;
00246
00247
00248 ratio = link->loss_link_multiplier;
00249
00250
00251 ratio = ratio * received;
00252 ratio = ratio / total;
00253 ratio = (ratio * 255) >> 16;
00254
00255 lq_link->lq.valueLq = (uint8_t) (ratio);
00256 }
00257
00258
00259 lq_link->activePtr = (lq_link->activePtr + 1) % LQ_FF_WINDOW;
00260 lq_link->total[lq_link->activePtr] = 0;
00261 lq_link->received[lq_link->activePtr] = 0;
00262 lq_link->missed_seconds++;
00263
00264
00265 link->linkcost = lq_etxff_calc_link_entry_cost(link);
00266 }
00267
00268 OLSR_FOR_ALL_NBR_ENTRIES(nbr, nbr_iterator) {
00269 olsr_neighbor_cost_may_changed(nbr);
00270 }
00271 }
00272
00273 static struct olsr_timer_entry *lq_etxff_timer_struct = NULL;
00274
00275 static void
00276 lq_etxff_initialize(void)
00277 {
00278
00279 olsr_packetparser_add_function(&lq_etxff_packet_parser);
00280 default_lq_ff_timer_info = olsr_timer_add("Default Freifunk LQ", &lq_etxff_timer, true);
00281 lq_etxff_timer_struct = olsr_timer_start(1000, 0, NULL, default_lq_ff_timer_info);
00282 }
00283
00284 static void
00285 lq_etxff_deinitialize(void)
00286 {
00287 olsr_timer_stop(lq_etxff_timer_struct);
00288 olsr_packetparser_remove_function(&lq_etxff_packet_parser);
00289 }
00290
00291 static olsr_linkcost
00292 lq_etxff_calc_linkcost(struct lq_etxff_linkquality *lq)
00293 {
00294 olsr_linkcost cost;
00295
00296 if (lq->valueLq < (unsigned int)(255 * MINIMAL_USEFUL_LQ) || lq->valueNlq < (unsigned int)(255 * MINIMAL_USEFUL_LQ)) {
00297 return LINK_COST_BROKEN;
00298 }
00299
00300 cost = 65536 * 255 / (int)lq->valueLq * 255 / (int)lq->valueNlq;
00301
00302 if (cost > LINK_COST_BROKEN)
00303 return LINK_COST_BROKEN;
00304 if (cost == 0)
00305 return 1;
00306 return cost;
00307 }
00308
00309 static olsr_linkcost
00310 lq_etxff_calc_link_entry_cost(struct link_entry *link)
00311 {
00312 struct lq_etxff_link_entry *lq_link = (struct lq_etxff_link_entry *)link;
00313
00314 return lq_etxff_calc_linkcost(&lq_link->lq);
00315 }
00316
00317 static olsr_linkcost
00318 lq_etxff_calc_lq_hello_neighbor_cost(struct lq_hello_neighbor *neigh)
00319 {
00320 struct lq_etxff_lq_hello_neighbor *lq_neigh = (struct lq_etxff_lq_hello_neighbor *)neigh;
00321
00322 return lq_etxff_calc_linkcost(&lq_neigh->lq);
00323 }
00324
00325 static olsr_linkcost
00326 lq_etxff_calc_tc_edge_entry_cost(struct tc_edge_entry *edge)
00327 {
00328 struct lq_etxff_tc_edge *lq_edge = (struct lq_etxff_tc_edge *)edge;
00329
00330 return lq_etxff_calc_linkcost(&lq_edge->lq);
00331 }
00332
00333 static void
00334 lq_etxff_hello_handler(struct link_entry *link __attribute__ ((unused)), bool loss __attribute__ ((unused)))
00335 {
00336 }
00337
00338 static void
00339 lq_etxff_memorize_foreign_hello(struct link_entry *target, struct lq_hello_neighbor *source)
00340 {
00341 struct lq_etxff_link_entry *lq_target = (struct lq_etxff_link_entry *)target;
00342 struct lq_etxff_lq_hello_neighbor *lq_source = (struct lq_etxff_lq_hello_neighbor *)source;
00343
00344 if (source) {
00345 lq_target->lq.valueNlq = lq_source->lq.valueLq;
00346 } else {
00347 lq_target->lq.valueNlq = 0;
00348 }
00349
00350 }
00351
00352 static void
00353 lq_etxff_copy_link_entry_lq_into_tc_edge_entry(struct tc_edge_entry *target, struct link_entry *source)
00354 {
00355 struct lq_etxff_tc_edge *lq_target = (struct lq_etxff_tc_edge *)target;
00356 struct lq_etxff_link_entry *lq_source = (struct lq_etxff_link_entry *)source;
00357
00358 lq_target->lq = lq_source->lq;
00359 }
00360
00361 static void
00362 lq_etxff_clear_link_entry(struct link_entry *link)
00363 {
00364 struct lq_etxff_link_entry *lq_link = (struct lq_etxff_link_entry *)link;
00365 int i;
00366
00367 lq_link->windowSize = LQ_FF_QUICKSTART_INIT;
00368 for (i = 0; i < LQ_FF_WINDOW; i++) {
00369 lq_link->total[i] = 3;
00370 }
00371 }
00372
00373 static void
00374 lq_etxff_clear_tc_edge_entry(struct tc_edge_entry *edge) {
00375 struct lq_etxff_tc_edge *lq_edge = (struct lq_etxff_tc_edge *)edge;
00376
00377 memset (&lq_edge->lq, 0, sizeof(lq_edge->lq));
00378 }
00379
00380 static void
00381 lq_etxff_serialize_hello_lq(uint8_t **curr, struct link_entry *link)
00382 {
00383 struct lq_etxff_link_entry *lq_link = (struct lq_etxff_link_entry *)link;
00384
00385 pkt_put_u8(curr, lq_link->lq.valueLq);
00386 pkt_put_u8(curr, lq_link->lq.valueNlq);
00387 pkt_put_u16(curr, 0);
00388 }
00389 static void
00390 lq_etxff_serialize_tc_lq(uint8_t **curr, struct link_entry *link)
00391 {
00392 struct lq_etxff_link_entry *lq_link = (struct lq_etxff_link_entry *)link;
00393
00394 pkt_put_u8(curr, lq_link->lq.valueLq);
00395 pkt_put_u8(curr, lq_link->lq.valueNlq);
00396 pkt_put_u16(curr, 0);
00397 }
00398
00399 static void
00400 lq_etxff_deserialize_hello_lq(uint8_t const **curr, struct lq_hello_neighbor *neigh)
00401 {
00402 struct lq_etxff_lq_hello_neighbor *lq_neigh = (struct lq_etxff_lq_hello_neighbor *)neigh;
00403
00404 pkt_get_u8(curr, &lq_neigh->lq.valueLq);
00405 pkt_get_u8(curr, &lq_neigh->lq.valueNlq);
00406 pkt_ignore_u16(curr);
00407
00408 }
00409 static void
00410 lq_etxff_deserialize_tc_lq(uint8_t const **curr, struct tc_edge_entry *edge)
00411 {
00412 struct lq_etxff_tc_edge *lq_edge = (struct lq_etxff_tc_edge *)edge;
00413
00414 pkt_get_u8(curr, &lq_edge->lq.valueLq);
00415 pkt_get_u8(curr, &lq_edge->lq.valueNlq);
00416 pkt_ignore_u16(curr);
00417 }
00418
00419 static int
00420 lq_etxff_get_linkentry_data(struct link_entry *link, int idx) {
00421 struct lq_etxff_link_entry *lq = (struct lq_etxff_link_entry *)link;
00422 return idx == 1 ? lq->lq.valueLq : lq->lq.valueNlq;
00423 }
00424
00425 static const char *
00426 lq_etxff_print_link_entry_lq(struct link_entry *link, int idx, char *buffer, size_t bufsize)
00427 {
00428 struct lq_etxff_link_entry *lq = (struct lq_etxff_link_entry *)link;
00429 uint8_t value;
00430
00431 if (idx == 1) {
00432 value = lq->lq.valueLq;
00433 }
00434 else {
00435 value = lq->lq.valueNlq;
00436 }
00437
00438 if (value == 255) {
00439 strscpy(buffer, "1.000", bufsize);
00440 } else {
00441 snprintf(buffer, bufsize, "0.%03d", (value * 1000) / 255);
00442 }
00443 return buffer;
00444 }
00445
00446 static const char *
00447 lq_etxff_print_cost(olsr_linkcost cost, char *buffer, size_t bufsize)
00448 {
00449
00450 uint32_t roundDown = cost >> 16;
00451 uint32_t fraction = ((cost & 0xffff) * 1000) >> 16;
00452
00453 snprintf(buffer, bufsize, "%u.%03u", roundDown, fraction);
00454 return buffer;
00455 }
00456
00457
00458
00459
00460
00461
00462