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 "olsr_spf.h"
00047 #include "lq_packet.h"
00048 #include "olsr.h"
00049 #include "olsr_logging.h"
00050 #include "lq_plugin_etx_float.h"
00051
00052 #define PLUGIN_DESCR "Floating point based ETX metric with exponential aging"
00053 #define PLUGIN_AUTHOR "Henning Rogge and others"
00054
00055 #define LQ_PLUGIN_LC_MULTIPLIER 1024
00056
00057 #define LQ_FLOAT_DEFAULT_AGING 0.05
00058 #define LQ_FLOAT_QUICKSTART_AGING 0.25
00059 #define LQ_QUICKSTART_STEPS 12
00060
00061 static int set_plugin_float(const char *, void *, set_plugin_parameter_addon);
00062 static int lq_etxfloat_enable(void);
00063
00064 static olsr_linkcost lq_etxfloat_calc_link_entry_cost(struct link_entry *);
00065 static olsr_linkcost lq_etxfloat_calc_lq_hello_neighbor_cost(struct lq_hello_neighbor *);
00066 static olsr_linkcost lq_etxfloat_calc_tc_edge_entry_cost(struct tc_edge_entry *);
00067
00068 static void lq_etxfloat_hello_handler(struct link_entry *, bool);
00069
00070 static void lq_etxfloat_memorize_foreign_hello(struct link_entry *, struct lq_hello_neighbor *);
00071 static void lq_etxfloat_copy_link_entry_lq_into_tc_edge_entry(struct tc_edge_entry *target, struct link_entry *source);
00072
00073 static void lq_etxfloat_serialize_hello_lq(uint8_t **curr, struct link_entry *link);
00074 static void lq_etxfloat_serialize_tc_lq(uint8_t **curr, struct link_entry *link);
00075 static void lq_etxfloat_deserialize_hello_lq(uint8_t const **curr, struct lq_hello_neighbor *lq);
00076 static void lq_etxfloat_deserialize_tc_lq(uint8_t const **curr, struct tc_edge_entry *lq);
00077
00078 static int lq_etxfloat_get_linkentry_data(struct link_entry *, int);
00079 static const char *lq_etxfloat_print_cost(olsr_linkcost cost, char *buffer, size_t bufsize);
00080 static const char *lq_etxfloat_print_link_entry_lq(struct link_entry *entry, int index, char *buffer, size_t bufsize);
00081
00082
00083 struct lq_linkdata_type lq_etxfloat_linktypes[] = {
00084 { "ETX", 5, 1000, 1000*2, 1000*4, INT32_MAX },
00085 { "LQ", 5, 255, 240, 192, 0 },
00086 { "NLQ", 5, 255, 240, 192, 0 }
00087 };
00088
00089 struct lq_handler lq_etxfloat_handler = {
00090 "etx (float)",
00091
00092 NULL,
00093 NULL,
00094
00095 &lq_etxfloat_calc_link_entry_cost,
00096 &lq_etxfloat_calc_lq_hello_neighbor_cost,
00097 &lq_etxfloat_calc_tc_edge_entry_cost,
00098
00099 &lq_etxfloat_hello_handler,
00100
00101 &lq_etxfloat_memorize_foreign_hello,
00102 &lq_etxfloat_copy_link_entry_lq_into_tc_edge_entry,
00103
00104 NULL,
00105 NULL,
00106 NULL,
00107
00108 &lq_etxfloat_serialize_hello_lq,
00109 &lq_etxfloat_serialize_tc_lq,
00110 &lq_etxfloat_deserialize_hello_lq,
00111 &lq_etxfloat_deserialize_tc_lq,
00112
00113 &lq_etxfloat_get_linkentry_data,
00114 &lq_etxfloat_print_cost,
00115 &lq_etxfloat_print_link_entry_lq,
00116
00117 lq_etxfloat_linktypes,
00118 ARRAYSIZE(lq_etxfloat_linktypes),
00119
00120 sizeof(struct lq_etxfloat_tc_edge),
00121 sizeof(struct lq_etxfloat_lq_hello_neighbor),
00122 sizeof(struct lq_etxfloat_link_entry),
00123
00124 LQ_HELLO_MESSAGE,
00125 LQ_TC_MESSAGE,
00126
00127 4,4
00128 };
00129
00130 static float lq_aging = LQ_FLOAT_DEFAULT_AGING;
00131
00132 static const struct olsrd_plugin_parameters plugin_parameters[] = {
00133 {.name = "LinkQualityAging",.set_plugin_parameter = &set_plugin_float,.data = &lq_aging},
00134 };
00135
00136 OLSR_PLUGIN6(plugin_parameters) {
00137 .descr = PLUGIN_DESCR,
00138 .author = PLUGIN_AUTHOR,
00139 .enable = lq_etxfloat_enable,
00140 .type = PLUGIN_TYPE_LQ
00141 };
00142
00143 static int
00144 set_plugin_float(const char *value, void *data, set_plugin_parameter_addon addon __attribute__ ((unused)))
00145 {
00146 if (data != NULL) {
00147 sscanf(value, "%f", (float *)data);
00148 OLSR_INFO(LOG_LQ_PLUGINS, "%s float %f\n", "Got", *(float *)data);
00149 } else {
00150 OLSR_INFO(LOG_LQ_PLUGINS, "%s float %s\n", "Ignored", value);
00151 }
00152 return 0;
00153 }
00154
00155 static int
00156 lq_etxfloat_enable(void) {
00157 active_lq_handler = &lq_etxfloat_handler;
00158 return false;
00159 }
00160
00161 static olsr_linkcost
00162 lq_etxfloat_calc_linkcost(struct lq_etxfloat_linkquality *lq)
00163 {
00164 olsr_linkcost cost;
00165
00166 if (lq->valueLq < MINIMAL_USEFUL_LQ || lq->valueNlq < MINIMAL_USEFUL_LQ) {
00167 return LINK_COST_BROKEN;
00168 }
00169
00170 cost = (olsr_linkcost) (1.0 / (lq->valueLq * lq->valueNlq) * LQ_PLUGIN_LC_MULTIPLIER);
00171
00172 if (cost > LINK_COST_BROKEN)
00173 return LINK_COST_BROKEN;
00174 if (cost == 0) {
00175 return 1;
00176 }
00177 return cost;
00178 }
00179
00180 static olsr_linkcost
00181 lq_etxfloat_calc_link_entry_cost(struct link_entry *link)
00182 {
00183 struct lq_etxfloat_link_entry *lq_link = (struct lq_etxfloat_link_entry *)link;
00184
00185 return lq_etxfloat_calc_linkcost(&lq_link->lq);
00186 }
00187
00188 static olsr_linkcost
00189 lq_etxfloat_calc_lq_hello_neighbor_cost(struct lq_hello_neighbor *neigh)
00190 {
00191 struct lq_etxfloat_lq_hello_neighbor *lq_neigh = (struct lq_etxfloat_lq_hello_neighbor *)neigh;
00192
00193 return lq_etxfloat_calc_linkcost(&lq_neigh->lq);
00194 }
00195
00196 static olsr_linkcost
00197 lq_etxfloat_calc_tc_edge_entry_cost(struct tc_edge_entry *edge)
00198 {
00199 struct lq_etxfloat_tc_edge *lq_edge = (struct lq_etxfloat_tc_edge *)edge;
00200
00201 return lq_etxfloat_calc_linkcost(&lq_edge->lq);
00202 }
00203
00204 static void
00205 lq_etxfloat_hello_handler(struct link_entry *link, bool loss)
00206 {
00207 struct lq_etxfloat_link_entry *lq_link = (struct lq_etxfloat_link_entry *)link;
00208
00209 float alpha = lq_aging;
00210
00211 if (lq_link->quickstart < LQ_QUICKSTART_STEPS) {
00212
00213 alpha = LQ_FLOAT_QUICKSTART_AGING;
00214 lq_link->quickstart++;
00215 }
00216
00217 lq_link->lq.valueLq *= (1 - alpha);
00218 if (!loss) {
00219 lq_link->lq.valueLq += (alpha * link->loss_link_multiplier / 65536);
00220 }
00221 link->linkcost = lq_etxfloat_calc_linkcost(&lq_link->lq);
00222 olsr_neighbor_cost_may_changed(link->neighbor);
00223 }
00224
00225 static void
00226 lq_etxfloat_memorize_foreign_hello(struct link_entry *target, struct lq_hello_neighbor *source)
00227 {
00228 struct lq_etxfloat_link_entry *lq_target = (struct lq_etxfloat_link_entry *)target;
00229 struct lq_etxfloat_lq_hello_neighbor *lq_source = (struct lq_etxfloat_lq_hello_neighbor *)source;
00230
00231 if (source) {
00232 lq_target->lq.valueNlq = lq_source->lq.valueLq;
00233 } else {
00234 lq_target->lq.valueNlq = 0;
00235 }
00236
00237 }
00238
00239 static void
00240 lq_etxfloat_copy_link_entry_lq_into_tc_edge_entry(struct tc_edge_entry *target, struct link_entry *source)
00241 {
00242 struct lq_etxfloat_tc_edge *lq_target = (struct lq_etxfloat_tc_edge *)target;
00243 struct lq_etxfloat_link_entry *lq_source = (struct lq_etxfloat_link_entry *)source;
00244
00245 lq_target->lq = lq_source->lq;
00246 }
00247
00248 static void
00249 lq_etxfloat_serialize_hello_lq(uint8_t **curr, struct link_entry *link)
00250 {
00251 struct lq_etxfloat_link_entry *lq_link = (struct lq_etxfloat_link_entry *)link;
00252
00253 pkt_put_u8(curr, (unsigned char)(lq_link->lq.valueLq * 255));
00254 pkt_put_u8(curr, (unsigned char)(lq_link->lq.valueNlq * 255));
00255 pkt_put_u8(curr, 0);
00256 pkt_put_u8(curr, 0);
00257 }
00258
00259 static void
00260 lq_etxfloat_serialize_tc_lq(uint8_t **curr, struct link_entry *link)
00261 {
00262 struct lq_etxfloat_link_entry *lq_link = (struct lq_etxfloat_link_entry *)link;
00263
00264 pkt_put_u8(curr, (unsigned char)(lq_link->lq.valueLq * 255));
00265 pkt_put_u8(curr, (unsigned char)(lq_link->lq.valueNlq * 255));
00266 pkt_put_u8(curr, 0);
00267 pkt_put_u8(curr, 0);
00268 }
00269
00270 static void
00271 lq_etxfloat_deserialize_hello_lq(uint8_t const **curr, struct lq_hello_neighbor *neigh)
00272 {
00273 struct lq_etxfloat_lq_hello_neighbor *lq_neigh = (struct lq_etxfloat_lq_hello_neighbor *)neigh;
00274
00275 uint8_t lq_value, nlq_value;
00276
00277 pkt_get_u8(curr, &lq_value);
00278 pkt_get_u8(curr, &nlq_value);
00279 pkt_ignore_u16(curr);
00280
00281 lq_neigh->lq.valueLq = (float)lq_value / 255.0;
00282 lq_neigh->lq.valueNlq = (float)nlq_value / 255.0;
00283 }
00284
00285 static void
00286 lq_etxfloat_deserialize_tc_lq(uint8_t const **curr, struct tc_edge_entry *edge)
00287 {
00288 struct lq_etxfloat_tc_edge *lq_edge = (struct lq_etxfloat_tc_edge *)edge;
00289
00290 uint8_t lq_value, nlq_value;
00291
00292 pkt_get_u8(curr, &lq_value);
00293 pkt_get_u8(curr, &nlq_value);
00294 pkt_ignore_u16(curr);
00295
00296 lq_edge->lq.valueLq = (float)lq_value / 255.0;
00297 lq_edge->lq.valueNlq = (float)nlq_value / 255.0;
00298 }
00299
00300 static int lq_etxfloat_get_linkentry_data(struct link_entry *link, int idx) {
00301 struct lq_etxfloat_link_entry *lq_link = (struct lq_etxfloat_link_entry *)link;
00302 float value = idx == 1 ? lq_link->lq.valueLq : lq_link->lq.valueNlq;
00303
00304 return (int)(value * 1000);
00305 }
00306
00307 static const char *
00308 lq_etxfloat_print_link_entry_lq(struct link_entry *link, int idx, char *buffer, size_t bufsize)
00309 {
00310 struct lq_etxfloat_link_entry *lq_link = (struct lq_etxfloat_link_entry *)link;
00311 snprintf(buffer, bufsize, "%2.3f",
00312 idx==1 ? lq_link->lq.valueLq : lq_link->lq.valueNlq);
00313 return buffer;
00314 }
00315
00316 static const char *
00317 lq_etxfloat_print_cost(olsr_linkcost cost, char *buffer, size_t bufsize)
00318 {
00319 snprintf(buffer, bufsize, "%2.3f", ((float)cost) / LQ_PLUGIN_LC_MULTIPLIER);
00320 return buffer;
00321 }
00322
00323
00324
00325
00326
00327
00328