/** *This function processes the chosen MPRs and updates the counters *used in calculations */ static int olsr_chosen_mpr(struct neighbor_entry *one_hop_neighbor, uint16_t * two_hop_covered_count) { struct neighbor_list_entry *the_one_hop_list; struct neighbor_2_list_entry *second_hop_entries; struct neighbor_entry *dup_neighbor; uint16_t count; struct ipaddr_str buf; count = *two_hop_covered_count; OLSR_PRINTF(1, "Setting %s as MPR\n", olsr_ip_to_string(&buf, &one_hop_neighbor->neighbor_main_addr)); //printf("PRE COUNT: %d\n\n", count); one_hop_neighbor->is_mpr = true; //NBS_MPR; for (second_hop_entries = one_hop_neighbor->neighbor_2_list.next; second_hop_entries != &one_hop_neighbor->neighbor_2_list; second_hop_entries = second_hop_entries->next) { dup_neighbor = olsr_lookup_neighbor_table(&second_hop_entries->neighbor_2->neighbor_2_addr); if ((dup_neighbor != NULL) && (dup_neighbor->status == SYM)) { //OLSR_PRINTF(7, "(2)Skipping 2h neighbor %s - already 1hop\n", olsr_ip_to_string(&buf, &second_hop_entries->neighbor_2->neighbor_2_addr)); continue; } // if(!second_hop_entries->neighbor_2->neighbor_2_state) //if(second_hop_entries->neighbor_2->mpr_covered_count < olsr_cnf->mpr_coverage) //{ /* Now the neighbor is covered by this mpr */ second_hop_entries->neighbor_2->mpr_covered_count++; the_one_hop_list = second_hop_entries->neighbor_2->neighbor_2_nblist.next; //OLSR_PRINTF(1, "[%s](%x) has coverage %d\n", olsr_ip_to_string(&buf, &second_hop_entries->neighbor_2->neighbor_2_addr), second_hop_entries->neighbor_2, second_hop_entries->neighbor_2->mpr_covered_count); if (second_hop_entries->neighbor_2->mpr_covered_count >= olsr_cnf->mpr_coverage) count++; while (the_one_hop_list != &second_hop_entries->neighbor_2->neighbor_2_nblist) { if ((the_one_hop_list->neighbor->status == SYM)) { if (second_hop_entries->neighbor_2->mpr_covered_count >= olsr_cnf->mpr_coverage) { the_one_hop_list->neighbor->neighbor_2_nocov--; } } the_one_hop_list = the_one_hop_list->next; } //} } //printf("POST COUNT %d\n\n", count); *two_hop_covered_count = count; return count; }
/** *Find all 2 hop neighbors with 1 link *connecting them to us trough neighbors *with a given willingness. * *@param willingness the willigness of the neighbors * *@return a linked list of allocated neighbor_2_list_entry structures */ static struct neighbor_2_list_entry * olsr_find_2_hop_neighbors_with_1_link(int willingness) { uint8_t idx; struct neighbor_2_list_entry *two_hop_list_tmp = NULL; struct neighbor_2_list_entry *two_hop_list = NULL; struct neighbor_entry *dup_neighbor; struct neighbor_2_entry *two_hop_neighbor = NULL; for (idx = 0; idx < HASHSIZE; idx++) { for (two_hop_neighbor = two_hop_neighbortable[idx].next; two_hop_neighbor != &two_hop_neighbortable[idx]; two_hop_neighbor = two_hop_neighbor->next) { //two_hop_neighbor->neighbor_2_state=0; //two_hop_neighbor->mpr_covered_count = 0; dup_neighbor = olsr_lookup_neighbor_table(&two_hop_neighbor->neighbor_2_addr); if ((dup_neighbor != NULL) && (dup_neighbor->status != NOT_SYM)) { //OLSR_PRINTF(1, "(1)Skipping 2h neighbor %s - already 1hop\n", olsr_ip_to_string(&buf, &two_hop_neighbor->neighbor_2_addr)); continue; } if (two_hop_neighbor->neighbor_2_pointer == 1) { if ((two_hop_neighbor->neighbor_2_nblist.next->neighbor->willingness == willingness) && (two_hop_neighbor->neighbor_2_nblist.next->neighbor->status == SYM)) { two_hop_list_tmp = olsr_malloc(sizeof(struct neighbor_2_list_entry), "MPR two hop list"); //OLSR_PRINTF(1, "ONE LINK ADDING %s\n", olsr_ip_to_string(&buf, &two_hop_neighbor->neighbor_2_addr)); /* Only queue one way here */ two_hop_list_tmp->neighbor_2 = two_hop_neighbor; two_hop_list_tmp->next = two_hop_list; two_hop_list = two_hop_list_tmp; } } } } return (two_hop_list_tmp); }
/** *Optimize MPR set by removing all entries *where all 2 hop neighbors actually is *covered by enough MPRs already *Described in RFC3626 section 8.3.1 *point 5 * *@return nada */ static void olsr_optimize_mpr_set(void) { struct neighbor_entry *a_neighbor, *dup_neighbor; struct neighbor_2_list_entry *two_hop_list; int i, removeit; #if 0 printf("\n**MPR OPTIMIZING**\n\n"); #endif for (i = WILL_NEVER + 1; i < WILL_ALWAYS; i++) { OLSR_FOR_ALL_NBR_ENTRIES(a_neighbor) { if (a_neighbor->willingness != i) { continue; } if (a_neighbor->is_mpr) { removeit = 1; for (two_hop_list = a_neighbor->neighbor_2_list.next; two_hop_list != &a_neighbor->neighbor_2_list; two_hop_list = two_hop_list->next) { dup_neighbor = olsr_lookup_neighbor_table(&two_hop_list->neighbor_2->neighbor_2_addr); if ((dup_neighbor != NULL) && (dup_neighbor->status != NOT_SYM)) { continue; } //printf("\t[%s] coverage %d\n", olsr_ip_to_string(&buf, &two_hop_list->neighbor_2->neighbor_2_addr), two_hop_list->neighbor_2->mpr_covered_count); /* Do not remove if we find a entry which need this MPR */ if (two_hop_list->neighbor_2->mpr_covered_count <= olsr_cnf->mpr_coverage) { removeit = 0; } } if (removeit) { struct ipaddr_str buf; OLSR_PRINTF(3, "MPR OPTIMIZE: removiong mpr %s\n\n", olsr_ip_to_string(&buf, &a_neighbor->neighbor_main_addr)); a_neighbor->is_mpr = false; } } } OLSR_FOR_ALL_NBR_ENTRIES_END(a_neighbor); } }
/** *This function calculates the number of two hop neighbors */ static uint16_t olsr_calculate_two_hop_neighbors(void) { struct neighbor_entry *a_neighbor, *dup_neighbor; struct neighbor_2_list_entry *twohop_neighbors; uint16_t count = 0; uint16_t n_count = 0; uint16_t sum = 0; /* Clear 2 hop neighs */ olsr_clear_two_hop_processed(); OLSR_FOR_ALL_NBR_ENTRIES(a_neighbor) { if (a_neighbor->status == NOT_SYM) { a_neighbor->neighbor_2_nocov = count; continue; } for (twohop_neighbors = a_neighbor->neighbor_2_list.next; twohop_neighbors != &a_neighbor->neighbor_2_list; twohop_neighbors = twohop_neighbors->next) { dup_neighbor = olsr_lookup_neighbor_table(&twohop_neighbors->neighbor_2->neighbor_2_addr); if ((dup_neighbor == NULL) || (dup_neighbor->status != SYM)) { n_count++; if (!twohop_neighbors->neighbor_2->processed) { count++; twohop_neighbors->neighbor_2->processed = 1; } } } a_neighbor->neighbor_2_nocov = n_count; /* Add the two hop count */ sum += count; } OLSR_FOR_ALL_NBR_ENTRIES_END(a_neighbor); OLSR_PRINTF(3, "Two hop neighbors: %d\n", sum); return sum; }
/** *Check if a message is to be forwarded and forward *it if necessary. * *@param m the OLSR message to be forwarded *@param neighbour we received message from * *@returns positive if forwarded */ int olsr_forward_message(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr) { union olsr_ip_addr *src; struct neighbor_entry *neighbor; int msgsize; struct interface *ifn; bool is_ttl_1 = false; /* * Sven-Ola: We should not flood the mesh with overdue messages. Because * of a bug in parser.c:parse_packet, we have a lot of messages because * all older olsrd's have lq_fish enabled. */ if (AF_INET == olsr_cnf->ip_version) { if (m->v4.ttl < 2 || 255 < (int)m->v4.hopcnt + (int)m->v4.ttl) is_ttl_1 = true; } else { if (m->v6.ttl < 2 || 255 < (int)m->v6.hopcnt + (int)m->v6.ttl) is_ttl_1 = true; } /* Lookup sender address */ src = mid_lookup_main_addr(from_addr); if (!src) src = from_addr; neighbor = olsr_lookup_neighbor_table(src); if (!neighbor) return 0; if (neighbor->status != SYM) return 0; /* Check MPR */ if (olsr_lookup_mprs_set(src) == NULL) { #ifdef DEBUG struct ipaddr_str buf; OLSR_PRINTF(5, "Forward - sender %s not MPR selector\n", olsr_ip_to_string(&buf, src)); #endif return 0; } if (olsr_message_is_duplicate(m)) { return 0; } /* Treat TTL hopcnt except for ethernet link */ if (!is_ttl_1) { if (olsr_cnf->ip_version == AF_INET) { /* IPv4 */ m->v4.hopcnt++; m->v4.ttl--; } else { /* IPv6 */ m->v6.hopcnt++; m->v6.ttl--; } } /* Update packet data */ msgsize = ntohs(m->v4.olsr_msgsize); /* looping trough interfaces */ for (ifn = ifnet; ifn; ifn = ifn->int_next) { /* do not retransmit out through the same interface if it has mode == ether */ if (ifn == in_if && ifn->mode == IF_MODE_ETHER) continue; /* do not forward TTL 1 messages to non-ether interfaces */ if (is_ttl_1 && ifn->mode != IF_MODE_ETHER) continue; if (net_output_pending(ifn)) { /* * Check if message is to big to be piggybacked */ if (net_outbuffer_push(ifn, m, msgsize) != msgsize) { /* Send */ net_output(ifn); /* Buffer message */ set_buffer_timer(ifn); if (net_outbuffer_push(ifn, m, msgsize) != msgsize) { OLSR_PRINTF(1, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msgsize); olsr_syslog(OLSR_LOG_ERR, "Received message to big to be forwarded on %s(%d bytes)!", ifn->int_name, msgsize); } } } else { /* No forwarding pending */ set_buffer_timer(ifn); if (net_outbuffer_push(ifn, m, msgsize) != msgsize) { OLSR_PRINTF(1, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msgsize); olsr_syslog(OLSR_LOG_ERR, "Received message to big to be forwarded on %s(%d bytes)!", ifn->int_name, msgsize); } } } return 1; }