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
00043
00044
00045
00046 #include "defs.h"
00047 #include "link_set.h"
00048 #include "mid_set.h"
00049 #include "neighbor_table.h"
00050 #include "olsr.h"
00051 #include "olsr_timer.h"
00052 #include "olsr_socket.h"
00053 #include "olsr_spf.h"
00054 #include "net_olsr.h"
00055 #include "ipcalc.h"
00056 #include "lq_plugin.h"
00057 #include "common/string.h"
00058 #include "olsr_logging.h"
00059
00060 #include <assert.h>
00061
00062 static void olsr_expire_link_entry(void *context);
00063 static void olsr_expire_link_loss_timer(void *context);
00064 static void olsr_expire_link_sym_timer(void *context);
00065
00066
00067 struct list_entity link_entry_head;
00068
00069 static struct olsr_timer_info *link_dead_timer_info = NULL;
00070 static struct olsr_timer_info *link_loss_timer_info = NULL;
00071 static struct olsr_timer_info *link_sym_timer_info = NULL;
00072
00073 bool link_changes;
00074
00075 void
00076 signal_link_changes(bool val)
00077 {
00078 link_changes = val;
00079 }
00080
00081
00082 static int check_link_status(const struct lq_hello_message *message, const struct interface *in_if);
00083 static struct link_entry *add_link_entry(const union olsr_ip_addr *,
00084 const union olsr_ip_addr *,
00085 union olsr_ip_addr *, uint32_t, uint32_t, struct interface *);
00086
00087 void
00088 olsr_init_link_set(void)
00089 {
00090 OLSR_INFO(LOG_LINKS, "Initialize linkset...\n");
00091
00092
00093 list_init_head(&link_entry_head);
00094
00095 link_dead_timer_info = olsr_timer_add("Link dead", &olsr_expire_link_entry, false);
00096 link_loss_timer_info = olsr_timer_add("Link loss", &olsr_expire_link_loss_timer, true);
00097 link_sym_timer_info = olsr_timer_add("Link SYM", &olsr_expire_link_sym_timer, false);
00098
00099 }
00100
00101
00109 int
00110 lookup_link_status(const struct link_entry *entry)
00111 {
00112 if (entry == NULL || list_is_empty(&link_entry_head)) {
00113 return UNSPEC_LINK;
00114 }
00115
00116 if (entry->link_sym_timer) {
00117 return SYM_LINK;
00118 }
00119
00120 if (!olsr_clock_isPast(entry->ASYM_time)) {
00121 return ASYM_LINK;
00122 }
00123
00124 return LOST_LINK;
00125 }
00126
00130 struct link_entry *
00131 get_best_link_to_neighbor_ip(const union olsr_ip_addr *remote)
00132 {
00133 struct nbr_entry *nbr;
00134
00135 nbr = olsr_lookup_nbr_entry(remote, true);
00136 return get_best_link_to_neighbor(nbr);
00137 }
00138
00142 struct link_entry *
00143 get_best_link_to_neighbor(struct nbr_entry *nbr)
00144 {
00145 struct link_entry *walker, *good_link, *iterator;
00146 olsr_linkcost curr_lcost = LINK_COST_BROKEN;
00147
00148
00149 good_link = NULL;
00150
00151
00152 OLSR_FOR_ALL_LINK_ENTRIES(walker, iterator) {
00153
00154 if (walker->neighbor != nbr || lookup_link_status(walker) != SYM_LINK)
00155 continue;
00156
00157
00158
00159
00160 if (walker->linkcost < curr_lcost) {
00161
00162 curr_lcost = walker->linkcost;
00163 good_link = walker;
00164 }
00165 }
00166
00167
00168
00169
00170 return good_link;
00171 }
00172
00173 static void
00174 set_loss_link_multiplier(struct link_entry *entry)
00175 {
00176 struct interface *inter;
00177 struct olsr_if_config *cfg_inter;
00178 struct olsr_lq_mult *mult;
00179 uint32_t val = 0;
00180
00181
00182 inter = if_ifwithaddr(&entry->local_iface_addr);
00183
00184
00185 for (cfg_inter = olsr_cnf->if_configs; cfg_inter; cfg_inter = cfg_inter->next) {
00186 if (cfg_inter->interf == inter) {
00187 break;
00188 }
00189 }
00190
00191
00192 for (mult = cfg_inter->cnf->lq_mult; mult != NULL; mult = mult->next) {
00193
00194
00195
00196
00197 if ((val == 0 && olsr_ipcmp(&mult->addr, &all_zero) == 0) || olsr_ipcmp(&mult->addr, &entry->neighbor_iface_addr) == 0) {
00198 val = mult->value;
00199 }
00200 }
00201
00202
00203 if (val == 0) {
00204 val = LINK_LOSS_MULTIPLIER;
00205 }
00206
00207
00208 entry->loss_link_multiplier = val;
00209 }
00210
00211
00212
00213
00214 static void
00215 olsr_delete_link_entry(struct link_entry *link)
00216 {
00217
00218
00219
00220 olsr_delete_routing_table(&link->neighbor_iface_addr, 8 * olsr_cnf->ipsize,
00221 &link->neighbor->nbr_addr, OLSR_RT_ORIGIN_LINK);
00222
00223
00224 link->neighbor->linkcount--;
00225 if (link->is_mprs) {
00226 link->neighbor->mprs_count --;
00227 }
00228
00229
00230 if (link->neighbor->linkcount == 0) {
00231 olsr_delete_nbr_entry(link->neighbor);
00232 }
00233
00234
00235 olsr_timer_stop(link->link_timer);
00236 link->link_timer = NULL;
00237
00238 olsr_timer_stop(link->link_sym_timer);
00239 link->link_sym_timer = NULL;
00240
00241 olsr_timer_stop(link->link_loss_timer);
00242 link->link_loss_timer = NULL;
00243
00244 list_remove(&link->link_list);
00245
00246
00247 unlock_interface(link->inter);
00248 link->inter = NULL;
00249
00250 free(link->if_name);
00251 olsr_free_link_entry(link);
00252
00253 changes_neighborhood = true;
00254 }
00255
00259 void
00260 olsr_delete_link_entry_by_if(const struct interface *ifp)
00261 {
00262 struct link_entry *link, *iterator;
00263 #if !defined REMOVE_LOG_DEBUG
00264 struct ipaddr_str buf;
00265 #endif
00266
00267 OLSR_FOR_ALL_LINK_ENTRIES(link, iterator) {
00268 if (ifp == link->inter) {
00269 OLSR_DEBUG(LOG_LINKS, "Removing link %s of interface %s\n",
00270 olsr_ip_to_string(&buf, &link->neighbor_iface_addr), ifp->int_name);
00271 olsr_delete_link_entry(link);
00272 }
00273 }
00274 }
00275
00279 static void
00280 olsr_expire_link_loss_timer(void *context)
00281 {
00282 struct link_entry *link;
00283
00284 link = (struct link_entry *)context;
00285
00286
00287 olsr_lq_hello_handler(link, true);
00288
00289
00290 olsr_timer_change(link->link_loss_timer, link->loss_helloint, OLSR_LINK_LOSS_JITTER);
00291 }
00292
00296 static void
00297 olsr_expire_link_sym_timer(void *context)
00298 {
00299 struct link_entry *link;
00300
00301 link = (struct link_entry *)context;
00302 link->link_sym_timer = NULL;
00303
00304 if (link->status != SYM_LINK) {
00305 return;
00306 }
00307
00308 link->status = lookup_link_status(link);
00309 olsr_update_nbr_status(link->neighbor);
00310 changes_neighborhood = true;
00311 }
00312
00316 void
00317 olsr_expire_link_hello_timer(void *context)
00318 {
00319 struct link_entry *link;
00320
00321 link = (struct link_entry *)context;
00322
00323
00324 olsr_update_nbr_status(link->neighbor);
00325 }
00326
00330 static void
00331 olsr_expire_link_entry(void *context)
00332 {
00333 struct link_entry *link;
00334
00335 link = (struct link_entry *)context;
00336 link->link_timer = NULL;
00337
00338 olsr_delete_link_entry(link);
00339 }
00340
00344 static void
00345 olsr_set_link_timer(struct link_entry *link, unsigned int rel_timer)
00346 {
00347 olsr_timer_set(&link->link_timer, rel_timer, OLSR_LINK_JITTER,
00348 link, link_dead_timer_info);
00349 }
00350
00363 static struct link_entry *
00364 add_link_entry(const union olsr_ip_addr *local,
00365 const union olsr_ip_addr *remote,
00366 union olsr_ip_addr *remote_main, uint32_t vtime, uint32_t htime, struct interface *local_if)
00367 {
00368 struct link_entry *link;
00369 struct nbr_entry *neighbor;
00370 #if !defined REMOVE_LOG_DEBUG
00371 struct ipaddr_str localbuf, rembuf;
00372 #endif
00373
00374 link = lookup_link_entry(remote, remote_main, local_if);
00375 if (link) {
00376 return link;
00377 }
00378
00379
00380
00381
00382
00383
00384 OLSR_DEBUG(LOG_LINKS, "Adding %s=>%s to link set\n", olsr_ip_to_string(&localbuf, local), olsr_ip_to_string(&rembuf, remote));
00385
00386
00387 link = olsr_malloc_link_entry();
00388
00389
00390 if (local_if->int_name) {
00391 link->if_name = strdup(local_if->int_name);
00392 } else {
00393 link->if_name = NULL;
00394 }
00395
00396 link->inter = local_if;
00397 lock_interface(local_if);
00398
00399
00400
00401
00402
00403 link->local_iface_addr = *local;
00404
00405
00406 link->neighbor_iface_addr = *remote;
00407
00408
00409 olsr_set_link_timer(link, vtime);
00410
00411 link->status = ASYM_LINK;
00412
00413 link->loss_helloint = htime;
00414
00415 olsr_timer_set(&link->link_loss_timer, htime + htime / 2,
00416 OLSR_LINK_LOSS_JITTER, link, link_loss_timer_info);
00417
00418 set_loss_link_multiplier(link);
00419
00420 link->linkcost = LINK_COST_BROKEN;
00421
00422 link->is_mprs = false;
00423
00424
00425 list_add_before(&link_entry_head, &link->link_list);
00426
00427
00428
00429
00430
00431
00432
00433 neighbor = olsr_lookup_nbr_entry(remote_main, true);
00434 if (!neighbor) {
00435 OLSR_DEBUG(LOG_LINKS, "ADDING NEW NEIGHBOR ENTRY %s FROM LINK SET\n", olsr_ip_to_string(&rembuf, remote_main));
00436 neighbor = olsr_add_nbr_entry(remote_main);
00437 }
00438
00439 assert(neighbor->tc_edge);
00440
00441 neighbor->linkcount++;
00442 link->neighbor = neighbor;
00443
00444
00445
00446
00447
00448
00449 olsr_insert_routing_table(remote, 8 * olsr_cnf->ipsize, remote_main, OLSR_RT_ORIGIN_LINK);
00450
00451 changes_neighborhood = true;
00452 return link;
00453 }
00454
00455
00462 int
00463 check_neighbor_link(const union olsr_ip_addr *int_addr)
00464 {
00465 struct link_entry *link, *iterator;
00466
00467 OLSR_FOR_ALL_LINK_ENTRIES(link, iterator) {
00468 if (olsr_ipcmp(int_addr, &link->neighbor_iface_addr) == 0) {
00469 return lookup_link_status(link);
00470 }
00471 }
00472
00473 return UNSPEC_LINK;
00474 }
00475
00484 struct link_entry *
00485 lookup_link_entry(const union olsr_ip_addr *remote, const union olsr_ip_addr *remote_main, const struct interface *local)
00486 {
00487 struct link_entry *link, *iterator;
00488
00489 OLSR_FOR_ALL_LINK_ENTRIES(link, iterator) {
00490 if (olsr_ipcmp(remote, &link->neighbor_iface_addr) == 0 && (link->if_name ? !strcmp(link->if_name, local->int_name)
00491 : olsr_ipcmp(&local->ip_addr, &link->local_iface_addr) == 0)) {
00492
00493 if (NULL != remote_main && olsr_ipcmp(remote_main, &link->neighbor->nbr_addr) != 0) {
00494
00495 #if !defined REMOVE_LOG_DEBUG
00496 struct ipaddr_str oldbuf, newbuf;
00497 #endif
00498 OLSR_DEBUG(LOG_LINKS, "Neighbor changed main_ip, updating %s -> %s\n",
00499 olsr_ip_to_string(&oldbuf, &link->neighbor->nbr_addr), olsr_ip_to_string(&newbuf, remote_main));
00500 link->neighbor->nbr_addr = *remote_main;
00501 }
00502 return link;
00503 }
00504 }
00505
00506 return NULL;
00507 }
00508
00520 struct link_entry *
00521 update_link_entry(const union olsr_ip_addr *local,
00522 const union olsr_ip_addr *remote, struct lq_hello_message *message, struct interface *in_if)
00523 {
00524 struct link_entry *entry;
00525
00526
00527 entry = add_link_entry(local, remote, &message->comm->originator, message->comm->vtime, message->htime, in_if);
00528
00529
00530 entry->vtime = message->comm->vtime;
00531 entry->ASYM_time = olsr_clock_getAbsolute(message->comm->vtime);
00532
00533 entry->status = check_link_status(message, in_if);
00534
00535 switch (entry->status) {
00536 case (LOST_LINK):
00537 olsr_timer_stop(entry->link_sym_timer);
00538 entry->link_sym_timer = NULL;
00539 break;
00540 case (SYM_LINK):
00541 case (ASYM_LINK):
00542
00543
00544 olsr_timer_set(&entry->link_sym_timer, message->comm->vtime,
00545 OLSR_LINK_SYM_JITTER, entry, link_sym_timer_info);
00546
00547
00548 olsr_set_link_timer(entry, message->comm->vtime + NEIGHB_HOLD_TIME);
00549 break;
00550 default:;
00551 }
00552
00553
00554 if (entry->link_timer && (entry->link_timer->timer_clock < entry->ASYM_time)) {
00555 olsr_set_link_timer(entry, olsr_clock_getRelative(entry->ASYM_time));
00556 }
00557
00558
00559 olsr_update_nbr_status(entry->neighbor);
00560
00561 return entry;
00562 }
00563
00564
00574 int
00575 replace_neighbor_link_set(const struct nbr_entry *old, struct nbr_entry *new)
00576 {
00577 struct link_entry *link, *iterator;
00578 int retval = 0;
00579
00580 if (list_is_empty(&link_entry_head)) {
00581 return retval;
00582 }
00583
00584 OLSR_FOR_ALL_LINK_ENTRIES(link, iterator) {
00585 if (link->neighbor == old) {
00586 link->neighbor = new;
00587 retval++;
00588 }
00589 }
00590
00591 return retval;
00592 }
00593
00594
00603 static int
00604 check_link_status(const struct lq_hello_message *message, const struct interface *in_if)
00605 {
00606 int ret = UNSPEC_LINK;
00607 struct lq_hello_neighbor *neighbors;
00608
00609 neighbors = message->neigh;
00610 while (neighbors) {
00611
00612
00613
00614
00615
00616 if (olsr_ipcmp(&neighbors->addr, &in_if->ip_addr) == 0
00617 && neighbors->link_type != UNSPEC_LINK) {
00618 ret = neighbors->link_type;
00619 if (SYM_LINK == ret) {
00620 break;
00621 }
00622 }
00623 neighbors = neighbors->next;
00624 }
00625
00626 return ret;
00627 }
00628
00629 void
00630 olsr_print_link_set(void)
00631 {
00632 #if !defined REMOVE_LOG_INFO
00633
00634 struct link_entry *walker, *iterator;
00635 char totaltxt[256] = { 0 };
00636 const char *txt;
00637 int addrsize;
00638 struct timeval_buf timebuf;
00639 size_t i, j, length, max, totaltxt_len;
00640 addrsize = olsr_cnf->ip_version == AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN;
00641
00642
00643 totaltxt[0] = 0;
00644 totaltxt_len = 0;
00645 for (i=1; i<olsr_get_linklabel_count(); i++) {
00646 txt = olsr_get_linklabel(i);
00647 max = olsr_get_linklabel_maxlength(i);
00648
00649 length = strlen(txt);
00650
00651
00652 if (i != 1) {
00653 totaltxt[totaltxt_len++] = '/';
00654 }
00655
00656
00657 if (max > length) {
00658 for (j=0; j<max; j++) {
00659 totaltxt[totaltxt_len + j] = '-';
00660 }
00661 }
00662
00663
00664 strncpy(&totaltxt[totaltxt_len + max/2 - length/2], txt, length);
00665 totaltxt_len += max;
00666 }
00667 totaltxt[totaltxt_len] = 0;
00668
00669 OLSR_INFO(LOG_LINKS, "\n--- %s ---------------------------------------------------- LINKS\n\n",
00670 olsr_clock_getWallclockString(&timebuf));
00671 OLSR_INFO_NH(LOG_LINKS, "%-*s %s %s\n", addrsize, "IP address", totaltxt , olsr_get_linklabel(0));
00672
00673 OLSR_FOR_ALL_LINK_ENTRIES(walker, iterator) {
00674 struct ipaddr_str buf;
00675 char lqbuffer[LQTEXT_MAXLENGTH];
00676
00677
00678 totaltxt[0] = 0;
00679 totaltxt_len = 0;
00680 for (i=1; i<olsr_get_linklabel_count(); i++) {
00681 txt = olsr_get_linkdata_text(walker, i, lqbuffer, sizeof(lqbuffer));
00682 max = olsr_get_linklabel_maxlength(i);
00683
00684 length = strlen(txt);
00685
00686
00687 if (i != 1) {
00688 totaltxt[totaltxt_len++] = '/';
00689 }
00690
00691
00692 if (max > length) {
00693 for (j=0; j<max; j++) {
00694 totaltxt[totaltxt_len + j] = ' ';
00695 }
00696 }
00697
00698
00699 strncpy(&totaltxt[totaltxt_len + max/2 - length/2], txt, length);
00700 totaltxt_len += max;
00701 }
00702 totaltxt[totaltxt_len] = 0;
00703 OLSR_INFO_NH(LOG_LINKS, "%-*s %s %s\n",
00704 addrsize, olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
00705 totaltxt, olsr_get_linkcost_text(walker->linkcost, false, lqbuffer, sizeof(lqbuffer)));
00706 }
00707 #endif
00708 }
00709
00710
00711
00712
00713
00714 void
00715 olsr_update_packet_loss_hello_int(struct link_entry *entry, uint32_t loss_hello_int)
00716 {
00717 entry->loss_helloint = loss_hello_int;
00718 }
00719
00720 void
00721 olsr_update_packet_loss(struct link_entry *entry)
00722 {
00723 olsr_lq_hello_handler(entry, false);
00724
00725
00726 olsr_timer_set(&entry->link_loss_timer, entry->loss_helloint + entry->loss_helloint / 2,
00727 OLSR_LINK_LOSS_JITTER, entry, link_loss_timer_info);
00728 }
00729
00730 void
00731 generate_hello(void *p) {
00732 struct interface *ifp = p;
00733 uint8_t msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE] __attribute__ ((aligned));
00734 struct olsr_message msg;
00735 uint8_t *curr = msg_buffer;
00736 uint8_t *length_field, *last;
00737 struct link_entry *link, *iterator;
00738 uint8_t writeLinkType, writeNeighType;
00739 OLSR_INFO(LOG_PACKET_CREATION, "Building Hello for %s\n-------------------\n", ifp->int_name);
00740
00741 msg.type = olsr_get_Hello_MessageId();
00742 msg.vtime = ifp->hello_validity;
00743 msg.size = 0;
00744 msg.originator = olsr_cnf->router_id;
00745 msg.ttl = 1;
00746 msg.hopcnt = 0;
00747 msg.seqno = get_msg_seqno();
00748
00749 length_field = olsr_put_msg_hdr(&curr, &msg);
00750
00751 pkt_put_u16(&curr, 0);
00752 pkt_put_reltime(&curr, ifp->hello_interval);
00753 pkt_put_u8(&curr, olsr_cnf->willingness);
00754
00755 last = msg_buffer + sizeof(msg_buffer) - olsr_cnf->ipsize;
00756
00757
00758 OLSR_FOR_ALL_LINK_ENTRIES(link, iterator) {
00759 if (olsr_ipcmp(&link->local_iface_addr, &ifp->ip_addr) != 0) {
00760 link->iflocal_link_status = UNSPEC_LINK;
00761 }
00762 else {
00763 link->iflocal_link_status = lookup_link_status(link);
00764 }
00765
00766 if (link->neighbor->is_mpr) {
00767 link->iflocal_neigh_status = MPR_NEIGH;
00768 }
00769 else if (link->neighbor->is_sym) {
00770 link->iflocal_neigh_status = SYM_NEIGH;
00771 }
00772 else {
00773 link->iflocal_neigh_status = NOT_NEIGH;
00774 }
00775 }
00776
00777 for (writeNeighType = 0; writeNeighType < COUNT_NEIGH_TYPES; writeNeighType++) {
00778 for (writeLinkType = 0; writeLinkType < COUNT_LINK_TYPES; writeLinkType++) {
00779 bool first = true;
00780 uint8_t *linkstart = NULL;
00781
00782 OLSR_FOR_ALL_LINK_ENTRIES(link, iterator) {
00783 if (link->iflocal_link_status != writeLinkType
00784 || link->iflocal_neigh_status != writeNeighType) {
00785 continue;
00786 }
00787
00788 if (first) {
00789 pkt_put_u8(&curr, CREATE_LINK_CODE(writeNeighType, writeLinkType));
00790 pkt_put_u8(&curr, 0);
00791 first = false;
00792
00793
00794 linkstart = curr;
00795 pkt_put_u16(&curr, 0);
00796 }
00797
00798 pkt_put_ipaddress(&curr, &link->neighbor_iface_addr);
00799 olsr_serialize_hello_lq_pair(&curr, link);
00800 }
00801
00802
00803 if (linkstart != NULL) {
00804 pkt_put_u16(&linkstart, (uint16_t)(curr + 2 - linkstart));
00805 }
00806 }
00807 }
00808
00809
00810 pkt_put_u16(&length_field, curr - msg_buffer);
00811
00812
00813 if (net_outbuffer_bytes_left(ifp) < curr - msg_buffer) {
00814 net_output(ifp);
00815 }
00816 net_outbuffer_push(ifp, msg_buffer, curr - msg_buffer);
00817 net_output(ifp);
00818 }
00819
00820
00821
00822
00823
00824