Beispiel #1
0
olsr_bool search_mpr_set_handler(void *olsr, void *arg_a, void *arg_b)
{
  OLSR_MPR_TUPLE *data = NULL, *search = NULL;

  data = (OLSR_MPR_TUPLE *)arg_a;
  search = (OLSR_MPR_TUPLE *)arg_b;

  return (olsr_bool)(equal_ip_addr((struct olsrv2 *)olsr,
                   &data->MPR_if_addr, &search->MPR_if_addr)
             && equal_ip_addr((struct olsrv2 *)olsr,
                      &data->local_iface_addr,
                      &search->local_iface_addr));
}
olsr_bool search_topology_set_handler(void* olsr, void *arg_a, void *arg_b)
{
    OLSR_TOPOLOGY_TUPLE *data = NULL, *param = NULL;

    data = (OLSR_TOPOLOGY_TUPLE *)arg_a;
    param = (OLSR_TOPOLOGY_TUPLE *)arg_b;

    return (olsr_bool)(equal_ip_addr((struct olsrv2* )olsr,
                                     &data->T_dest_iface_addr,
                                     &param->T_dest_iface_addr) &&
                       equal_ip_addr((struct olsrv2* )olsr,
                                     &data->T_last_iface_addr,
                                     &param->T_last_iface_addr));
}
Beispiel #3
0
//yowada
olsr_bool match_local_iface_addr(void *olsr, olsr_ip_addr *neigh_addr)
{
  struct olsrv2* olsr1 = (struct olsrv2* ) olsr;
  union olsr_ip_addr *local_addr = NULL;
  int ifnum,i;
  ifnum = ((struct olsrv2 *)olsr)->iface_num;
  for (i=0; i < ifnum; i++){
    local_addr = &((struct olsrv2 *)olsr)->iface_addr[i];
  if (DEBUG_OLSRV2)
  {
    if (olsr1->olsr_cnf->ip_version == AF_INET)
    {
      char str1[INET_ADDRSTRLEN], str2[INET_ADDRSTRLEN];
      ConvertIpv4AddressToString(local_addr->v4, str1);
      ConvertIpv4AddressToString(neigh_addr->v4, str2);
      olsr_printf("Local addr %s,\tNeigh addr %s\n",str1, str2);
    }
    else if (olsr1->olsr_cnf->ip_version == AF_INET6)
    {
      char str1[INET6_ADDRSTRLEN], str2[INET6_ADDRSTRLEN];
      ConvertIpv6AddressToString(&local_addr->v6, str1, OLSR_FALSE);
      ConvertIpv6AddressToString(&neigh_addr->v6, str2, OLSR_FALSE);
      olsr_printf("Local addr %s,\tNeigh addr %s\n",str1, str2);
    }
  }
  if (equal_ip_addr((struct olsrv2 *)olsr, neigh_addr ,local_addr) == OLSR_TRUE)
      return OLSR_TRUE;
  }
  return OLSR_FALSE;
}
Beispiel #4
0
//WIN FIX: changed type from void* to char*
olsr_bool search_proc_set_handler(void *olsr, void *arg_a, void *arg_vb)
{
  OLSR_PROC_TUPLE *data = NULL;
  union olsr_ip_addr *orig_addr = NULL;
  olsr_u16_t *seq_number = NULL;
  olsr_u8_t *type = NULL;

  //WIN FIX: changed type from void* to char*
  char *arg_b = (char *)arg_vb;

  data = (OLSR_PROC_TUPLE *)arg_a;
  orig_addr = (union olsr_ip_addr *)arg_b;
  arg_b += sizeof(union olsr_ip_addr);
  seq_number = (olsr_u16_t *)arg_b;
  arg_b += sizeof(olsr_u16_t);
  type = (olsr_u8_t *)arg_b;

  arg_b -= sizeof(olsr_u16_t);
  arg_b -= sizeof(union olsr_ip_addr);

  //WIN FIX: explicit typecast required
  return (olsr_bool)(equal_ip_addr((struct olsrv2* )olsr, &data->P_addr, orig_addr)
      && data->P_seq_number == *seq_number
      && data->P_type == *type);
}
Beispiel #5
0
olsr_bool search_routing_set_for_next_and_dest_handler(void* olsr,
                               void *arg_a,
                               void *arg_b)
{
  OLSR_ROUTING_TUPLE *data = NULL, *param = NULL;


  data = (OLSR_ROUTING_TUPLE *)arg_a;
  param = (OLSR_ROUTING_TUPLE *)arg_b;

  return (olsr_bool)(equal_ip_addr((struct olsrv2* )olsr,
                   &data->R_dest_iface_addr,
                   &param->R_dest_iface_addr) &&
             equal_ip_addr((struct olsrv2* )olsr,
                   &data->R_next_iface_addr,
                   &param->R_next_iface_addr));

}
Beispiel #6
0
olsr_bool search_mprN2_handler(void *olsr, void *arg_a, void *arg_b)
{
  OLSR_MPR_N2_TUPLE *data = NULL;
  union olsr_ip_addr *search = NULL;

  data = (OLSR_MPR_N2_TUPLE *)arg_a;
  search = (union olsr_ip_addr *)arg_b;

  return (olsr_bool)equal_ip_addr((struct olsrv2 *)olsr, &data->addr, search);
}
olsr_bool delete_relay_set_handler(void *olsr, void *arg_a, void *arg_b)
{
  OLSR_RELAY_TUPLE *data = NULL;
  union olsr_ip_addr *neighbor_iface_addr;

  data = (OLSR_RELAY_TUPLE *)arg_a;
  neighbor_iface_addr = (union olsr_ip_addr *)arg_b;
  return (olsr_bool)(equal_ip_addr((struct olsrv2 *)olsr, &data->RS_if_addr,
            neighbor_iface_addr));
}
Beispiel #8
0
olsr_bool delete_mprN2_handler(void *olsr, void *arg_a, void *arg_b)
{
  OLSR_MPR_N2_TUPLE *data = NULL;
  union olsr_ip_addr *todelete = NULL;

  data = (OLSR_MPR_N2_TUPLE *)arg_a;
  todelete = (union olsr_ip_addr *)arg_b;

  return (olsr_bool)equal_ip_addr((struct olsrv2 *)olsr, &data->addr, todelete);
}
Beispiel #9
0
void insert_routing_set(struct olsrv2 *olsr,
            union olsr_ip_addr *dest_iface_addr,
            const union olsr_ip_addr *next_iface_addr,
            olsr_u8_t prefix_length,
            olsr_u16_t dist,
            const union olsr_ip_addr *iface_addr)
{
  OLSR_ROUTING_TUPLE data;

  //Multi path check
  if (OLSR_TRUE)
  {
    if (search_routing_set_for_dest_exist(olsr, dest_iface_addr) == OLSR_TRUE ||//yowada add
       match_local_iface_addr(olsr, dest_iface_addr) == OLSR_TRUE)
      {
      if (DEBUG_OLSRV2)
      {
          char* paddr = olsr_niigata_ip_to_string(olsr, dest_iface_addr);
          olsr_printf("Route %s has already exist! hopcount = %d\n",paddr,dist);
          free(paddr);
      }

      return;
      //olsr_error("Multi path!!\n");
      }
  }
//Fix for Solaris
  //data.R_dest_iface_addr = *dest_iface_addr;
  //data.R_next_iface_addr = *next_iface_addr;
  olsr_ip_copy(olsr, &data.R_dest_iface_addr, dest_iface_addr);
  olsr_ip_copy(olsr, &data.R_next_iface_addr, next_iface_addr);
  data.R_prefix_length = prefix_length;
  data.R_dist = dist;
  //data.R_iface_addr = *iface_addr;
  olsr_ip_copy(olsr, &data.R_iface_addr, iface_addr);

  /*
    assert(equal_ip_addr(olsr_cnf->ip_version,
    data.R_dest_iface_addr,
    data.R_iface_addr) == OLSR_FALSE);
  */
  if (equal_ip_addr(olsr,
           &data.R_dest_iface_addr,
           &data.R_iface_addr))
  {
      return;
  }

  OLSR_InsertList(&olsr->routing_set[olsr_hashing(olsr,&data.R_dest_iface_addr)].list,
          &data, sizeof(OLSR_ROUTING_TUPLE));
  /*   OLSR_InsertList_Sort(&olsr->routing_set, */
  /*               &data, */
  /*               sizeof(OLSR_ROUTING_TUPLE), */
  /*               sort_routing_set_handler); */
}
olsr_bool delete_association_set_for_addr_handler(void* olsr, void *arg_a, void *arg_b){

  olsr_ip_addr *data = NULL, *param = NULL;

  data = (olsr_ip_addr *)arg_a;
  param = (olsr_ip_addr *)arg_b;
  return (olsr_bool)equal_ip_addr((struct olsrv2* )olsr,
                  data,
                  param);

}
olsr_bool search_association_set_for_addr_handler(void* olsr,
                          void *arg_a, void *arg_b){
  OLSR_ASSOCIATION_TUPLE *data = NULL, *param = NULL;

  data = (OLSR_ASSOCIATION_TUPLE *)arg_a;
  param = (OLSR_ASSOCIATION_TUPLE *)arg_b;

  return (olsr_bool)equal_ip_addr((struct olsrv2* )olsr,
                  &data->NA_iface_addr,
                  &param->NA_iface_addr);
}
olsr_bool lookup_topology_set_handler(void* olsr, void *arg_a,void *arg_b)
{
    OLSR_TOPOLOGY_TUPLE *data = NULL;
    union olsr_ip_addr *T_last_addr = NULL;

    data = (OLSR_TOPOLOGY_TUPLE *)arg_a;
    T_last_addr = (union olsr_ip_addr *)arg_b;

    return (olsr_bool)(equal_ip_addr((struct olsrv2* )olsr,
                                     &data->T_last_iface_addr,
                                     T_last_addr));
}
Beispiel #13
0
olsr_bool search_routing_set_for_dest_handler(void *olsr, void *arg_a, void *arg_b)
{
  OLSR_ROUTING_TUPLE *data = NULL;
  union olsr_ip_addr *addr = NULL;

  data = (OLSR_ROUTING_TUPLE *)arg_a;
  addr = (union olsr_ip_addr *)arg_b;

  return (olsr_bool)equal_ip_addr((struct olsrv2* )olsr,
                  &data->R_dest_iface_addr,
                  addr);
}
olsr_bool delete_topology_set_for_same_entry_handler(void* olsr,
        void *arg_a, void *arg_b)
{
    OLSR_TOPOLOGY_TUPLE *data = NULL, *param = NULL;

    data = (OLSR_TOPOLOGY_TUPLE *)arg_a;
    param = (OLSR_TOPOLOGY_TUPLE *)arg_b;

    return (olsr_bool)(equal_ip_addr((struct olsrv2* )olsr,
                                     &data->T_last_iface_addr,
                                     &param->T_last_iface_addr) &&
                       data->T_seq < param->T_seq);
}
Beispiel #15
0
void proc_routing_set(struct olsrv2 *olsr)
{
  OLSR_LIST_ENTRY *tmp_A = NULL, *tmp_B = NULL;

  OLSR_LINK_TUPLE *link_data = NULL, *link_data_2hop = NULL;
  OLSR_2NEIGH_TUPLE *two_nei_data = NULL;
  //OLSR_ASSOCI_TUPLE *associ_data;
  OLSR_ASSOCIATION_TUPLE *associ_data = NULL, *list_data = NULL;
  OLSR_TOPOLOGY_TUPLE *topology_data = NULL;
  OLSR_ROUTING_TUPLE *routing_data = NULL;
  olsr_u8_t default_prefix;
  olsr_u32_t index;
  int i;

  OLSR_LIST *retList = NULL, *link_retList = NULL;

  olsr_time_t time;
  int hash_index;

  int h;
  olsr_bool insert;;

  get_current_time(olsr, &time);
  // block signals until routing calcuration is finished
  if (olsr->olsr_cnf->ip_version == AF_INET)
  {
      default_prefix = 32;
  }else
  {
      default_prefix = 128;
  }


  //14
  //14.1

  for (hash_index = 0; hash_index < HASHSIZE; hash_index++)
  {
      delete_routing_set_for_all_entry(olsr, &olsr->routing_set[hash_index].list);
  }

  //14.2
  tmp_A = olsr->link_set.head;

  while (tmp_A)
  {
      link_data = (OLSR_LINK_TUPLE *)tmp_A->data;
      if (get_link_status(time,
             link_data->L_SYM_time,
             link_data->L_ASYM_time,
             link_data->L_LOST_LINK_time) == SYMMETRIC)
      {
      if (DEBUG_OLSRV2)
      {
          olsr_printf("------call insert_routing_set---------\n");
      }
      insert_routing_set(olsr,
                 &link_data->L_neighbor_iface_addr,
                 &link_data->L_neighbor_iface_addr,
                 default_prefix,
                 1,
                 &link_data->L_local_iface_addr);

      }

      tmp_A = tmp_A->next;
  }

  //14.3 (XXX)
  // for each neighbor address association tuple, for which two
  // addresses A1 and A2 exist in I_neighbor_iface_addr_list where:

  for (index=0; index < HASHSIZE; index++)
  {
      union olsr_ip_addr A_addr, B_addr;

      tmp_A = olsr->associ_set[index].list.head;
      while (tmp_A)
      {
      associ_data = (OLSR_ASSOCIATION_TUPLE *)tmp_A->data;
      olsr_ip_copy(olsr, &A_addr, &associ_data->NA_iface_addr);

      for (i = 0; i < associ_data->num_NAlist; i++)
      {
          tmp_B = associ_data->NA_list[i];
          list_data = (OLSR_ASSOCIATION_TUPLE *)tmp_B->data;
          olsr_ip_copy(olsr, &B_addr, &list_data->NA_iface_addr);

          if (!equal_ip_addr(olsr, &A_addr, &B_addr))
          {
          retList = search_routing_set_for_dest(olsr, &A_addr);

          if (retList != NULL)
          {
              routing_data = (OLSR_ROUTING_TUPLE *)retList->head->data;
              OLSR_DeleteList_Search(retList);

              insert_routing_set(olsr,
                     &B_addr,
                     &routing_data->R_next_iface_addr,
                     default_prefix,
                     routing_data->R_dist,
                     &routing_data->R_iface_addr);
              assert(routing_data->R_dist == 1);
          }
          }
      }
      tmp_A = tmp_A->next;
      }
  }

  for (hash_index = 0; hash_index < HASHSIZE; hash_index++)
  {
      tmp_A = olsr->routing_set[hash_index].list.head;

      while (tmp_A)
      {
      routing_data = (OLSR_ROUTING_TUPLE *)tmp_A->data;
      retList = search_2neigh_set_for_mpr_n(olsr,
                        &routing_data->R_iface_addr,
                        &routing_data->R_next_iface_addr);
      if (retList)
      {
          tmp_B = retList->head;
          while (tmp_B)
          {
          two_nei_data = (OLSR_2NEIGH_TUPLE *)tmp_B->data;
          link_retList = search_link_set(olsr,
                         &two_nei_data->N2_2hop_iface_addr);
          if (link_retList)
          {
              link_data_2hop = (OLSR_LINK_TUPLE *)link_retList->head->data;
              OLSR_DeleteList_Search(link_retList);
              if (get_link_status(
                 time,
                 link_data_2hop->L_SYM_time,
                 link_data_2hop->L_ASYM_time,
                 link_data_2hop->L_LOST_LINK_time) == SYMMETRIC)
              {
              tmp_B = tmp_B->next;
              continue;
              }
          }

          insert_routing_set(olsr,
                     &two_nei_data->N2_2hop_iface_addr,
                     &routing_data->R_next_iface_addr,
                     default_prefix,
                     2,
                     &routing_data->R_iface_addr);

          tmp_B = tmp_B->next;
          }
          OLSR_DeleteList_Search(retList);
      }
      tmp_A = tmp_A->next;
      }
  }

  //14.5
  //14.5.1

  h = 2;
  insert = OLSR_TRUE;

  while (insert == OLSR_TRUE)
  {
      insert = OLSR_FALSE;

      for (hash_index = 0; hash_index  < HASHSIZE; hash_index++)
      {
      tmp_A = olsr->routing_set[hash_index].list.head;

      while (tmp_A)
      {
          routing_data = (OLSR_ROUTING_TUPLE *)tmp_A->data;

          tmp_A = tmp_A->next;

          if (routing_data->R_dist != h)
          {
          continue;
          }

          retList = search_topology_set_for_last(olsr, &routing_data->R_dest_iface_addr);

          if (retList)
          {
          tmp_B = retList->head;
          while (tmp_B)
          {
              topology_data = (OLSR_TOPOLOGY_TUPLE *)tmp_B->data;

              if (search_routing_set_for_dest_exist(
                 olsr, &topology_data->T_dest_iface_addr) == OLSR_FALSE)
              {
              insert_routing_set(olsr,
                         &topology_data->T_dest_iface_addr,
                         &routing_data->R_next_iface_addr,
                         default_prefix,
                         routing_data->R_dist+1,
                         &routing_data->R_iface_addr);
              insert = OLSR_TRUE;
              }
              tmp_B = tmp_B->next;
          }
          OLSR_DeleteList_Search(retList);
          }
      }//while
      }//for

      h++;
  }
  //14.5.2

}
static olsr_bool
process_hello(struct olsrv2 *olsr, struct hello_message *hello,
          union olsr_ip_addr *in_if,
          union olsr_ip_addr *from_addr)
{
  struct hello_neighbor *hello_neigh = NULL;
  OLSR_LIST* retList = NULL;
  OLSR_LIST_ENTRY *entry = NULL;
  OLSR_LOCAL_INTERFACE_BLOCK_ENTRY *local_entry = NULL;
  OLSR_SYMMETRIC_NEIGHBOR_TUPLE *sym_data = NULL;
  olsr_time_t time;
  olsr_bool change_assn = OLSR_FALSE, selected_mpr = OLSR_FALSE;


  //codexxx
	// before processing hello message add the queue length of the corresponding originator to the OLSR_LIST "queue_set"
  olsr_bool IPfound = OLSR_FALSE;
  struct queue_info *queueInf = NULL, *tempo= NULL ;
  OLSR_LIST_ENTRY *queueEntry = NULL; 
  
  queueInf = (queue_info *)olsr_malloc(sizeof(queue_info), __FUNCTION__);
  
  queueInf->orig_IP = hello->orig_addr ;
  queueInf->Qlength = hello->queuelength;
 
  if(olsr->queue_set.numEntry == 0) 
  	{ // insert to the list directly
  	  OLSR_InsertList(&olsr->queue_set,queueInf,sizeof(queue_info));
	  
  }else{ // liste deja contient des element ...donc trouver si deja existe
		
		queueEntry = olsr->queue_set.head ;
		while(queueEntry != NULL)  /////
			{ 
			tempo = (queue_info *)queueEntry->data ;
			if(!cmp_ip_addr(olsr,&tempo->orig_IP,&queueInf->orig_IP)) ////
			{  // on a trouver cet originator IP ds la liste alors update le queue et sortir de la boucle
			   tempo->Qlength = queueInf->Qlength;
			   IPfound = OLSR_TRUE;
			   break;

			}
		queueEntry = queueEntry->next ;
	  }
		
			if(IPfound == OLSR_FALSE)
				{ // cet IP n'existe pas deja dans la liste => l'introduire
				
					 OLSR_InsertList(&olsr->queue_set,queueInf,sizeof(queue_info));
			}
			

	  }
  

  
  //end codexxx


  if (own_ip_addr(olsr, &hello->source_addr))
    { // wiss: ma3neta el source address byetaba2 ma3 wa7ed men el intrface address taba3 node
        if(DEBUG_OLSRV2){
            char* paddr = olsr_niigata_ip_to_string(olsr, &olsr->main_addr);
            olsr_printf("Received Hello, but this Hello is sent from ME!!\n[%s]",paddr);
            free(paddr);
        }
      return OLSR_FALSE; // wiss: betla3 men process_hello
    }

  if(search_link_set_local_for_exist(olsr,
                     in_if,
                     &hello->source_addr) == OLSR_FALSE){ // wiss:ma  la2a bel  olsr linkset entry 3enda local_if= "in_if" w neigbor_if=&hello->source_addr 
                     // wiss: ma la2a jar 3endou ip hello->source_addr ma3neta el link da3
    proc_link_set(olsr,
          in_if,
          &hello->source_addr,
          LOST,
          hello->willingness,
          hello->vtime,
          hello->htime);
  }

  // neighbor address
  hello_neigh = hello->neighbors;
  while (hello_neigh){


    if(equal_ip_addr(olsr,
             &hello_neigh->address,
             in_if
             ))
      { // wiss: hello_neigh->address, byetaba2 ma3 in_if
    proc_link_set(olsr,
              in_if,
              &hello->source_addr,
              hello_neigh->status,
              hello->willingness,
              hello->vtime,
              hello->htime);

    //update symmetric neighbor set
    proc_symmetric_neighbor_set(olsr,
                    in_if,
                    hello_neigh->status,
                    hello);
    break; // wiss : so iza fet hon ya3ni la2a el neighbor so break... so iza ma la2an byente2el 3al neigh->next
      }

    hello_neigh = hello_neigh->next;
  }


  //update neighbor address association set
  proc_association_set(olsr, &hello->local_iface_list, hello->vtime);


  hello_neigh = hello->neighbors;
  while (hello_neigh){

    //process 2hop Neighbor set
    proc_2neigh_set(olsr,
            in_if,
            &hello->source_addr,
            &hello_neigh->address,
            hello_neigh->status,
            hello_neigh->other_neigh,
            hello->vtime);

    //check: own interfaces is selected MPR by source nodes.
    if(selected_mpr == OLSR_FALSE &&
       own_ip_addr(olsr, &hello_neigh->address) == OLSR_TRUE &&
       hello_neigh->is_mpr == OLSR_TRUE) {
      selected_mpr = OLSR_TRUE;
    }

    //next pointer
    hello_neigh = hello_neigh->next;
  }

  //update mpr selector set , relay set, advertise neighbor set
  if(selected_mpr == OLSR_TRUE) {
    entry = hello->local_iface_list.head;
    while(entry) {
      local_entry = (OLSR_LOCAL_INTERFACE_BLOCK_ENTRY *)entry->data;
      retList = search_symmetric_neighbor_set(olsr,
                          in_if,
                          &local_entry->iface_addr);

      if(retList) {
    if(retList->numEntry != 1) {
      olsr_error("process_hello():5");
    }
    get_current_time(olsr, &time);
    sym_data = (OLSR_SYMMETRIC_NEIGHBOR_TUPLE *)retList->head->data;
    OLSR_DeleteList_Search(retList);

    if(get_neighbor_status(&time, &sym_data->N_time) == SYMMETRIC) {
        proc_mpr_selector_set(olsr, &local_entry->iface_addr);

        if(olsr->change_mpr_selector_set) {
        if(proc_adv_neigh_set(olsr, &local_entry->iface_addr)){
            proc_relay_set(olsr, &local_entry->iface_addr);
          change_assn = OLSR_TRUE;
          }
      }
    }//if(get_neigh...)
      }

      //next entry
      entry = entry->next;
    }//while
  }
  else{  // wiss: ici selected_mpr==false
    entry = hello->local_iface_list.head;
    while(entry) {
      local_entry = (OLSR_LOCAL_INTERFACE_BLOCK_ENTRY *)entry->data;
      delete_mpr_selector_set(olsr, &local_entry->iface_addr);
      if(olsr->change_mpr_selector_set) {
    delete_adv_neigh_set(olsr, &local_entry->iface_addr);
    if(olsr->change_adv_neigh_set) {
      change_assn = OLSR_TRUE;
      delete_relay_set(olsr, &local_entry->iface_addr);
    }
      }
      //next entry
      entry = entry->next;
    }//while
  }

  /* if I am selecetd as MPR by someone,
     I_am_MPR_flag turns ON and send TC message every TC_INTERVAL */
  if (olsr->I_am_MPR_flag == OLSR_FALSE &&
      olsr->adv_neigh_set.head != NULL){
    olsr->I_am_MPR_flag = OLSR_TRUE;
  }

  if(DEBUG_OLSRV2)
  {
      olsr_printf("\tassn[%d]\n", get_local_assn(olsr));
  }

  if (change_assn == OLSR_TRUE)
    increment_local_assn(olsr);

  return OLSR_TRUE;
}
Beispiel #17
0
OLSR_LIST *proc_mpr_set_per_interface(struct olsrv2 *olsr,
                      union olsr_ip_addr *local_iface_addr)
{
  OLSR_LIST *MPR_set = NULL, N, N2;

  OLSR_LIST *retList = NULL;
  OLSR_LIST_ENTRY *tmp = NULL, *retList_tmp = NULL;
  OLSR_LINK_TUPLE *link_data = NULL;
  OLSR_2NEIGH_TUPLE *two_neigh_data = NULL;
  OLSR_MPR_N_TUPLE *mpr_n_data = NULL;
  OLSR_MPR_N2_TUPLE *mpr_n2_data = NULL;

  int hash_index;
  olsr_time_t time;
  get_current_time(olsr, &time);

  if (DEBUG_OLSRV2)
  {
      olsr_printf("\n[Start MPR selection per interface]\n");
  }

  //Init MPR set
  MPR_set = (OLSR_LIST *)olsr_malloc(sizeof(OLSR_LIST), __FUNCTION__);
  OLSR_InitList(MPR_set);

  //Create MPR N
  // N - the set of such neighbor interfaces
  if (DEBUG_OLSRV2)
  {
      olsr_printf("[Create N]\n");
      olsr_printf("[Appendix A.2]\n");
  }
  OLSR_InitList(&N);

  tmp = olsr->link_set.head;
  while (tmp != NULL){
    link_data = (OLSR_LINK_TUPLE *)tmp->data;
    if (link_data->L_willingness > WILL_NEVER &&
       get_link_status(time,
               link_data->L_SYM_time,
               link_data->L_ASYM_time,
               link_data->L_LOST_LINK_time) == SYMMETRIC){
      if (equal_ip_addr(olsr, &link_data->L_local_iface_addr,
               local_iface_addr)){


    if (search_mprN_for_exist(olsr, &N, &link_data->L_neighbor_iface_addr)
       == OLSR_FALSE){


      // Calculate D(y), where y is a member of N, for all interfaces in N.
      int retNum = check_2neigh_set_for_mpr_n_exist_num_entry(olsr, local_iface_addr,
                                &link_data->L_neighbor_iface_addr);
      if (retNum > 0){
        insert_mprN(&N, &link_data->L_neighbor_iface_addr,
            /*retList->numEntry*/retNum, 0,
            link_data->L_willingness);

      }
    }
      }
    }
    tmp = tmp->next;
  }

  //print_mprN(olsr, &N);

  //Create MPR N2
  // N2 - the set of such 2-hop neighbor interfaces
  if (DEBUG_OLSRV2)
  {
      olsr_printf("[Create N2]\n");
  }

  OLSR_InitList(&N2);
  for (hash_index = 0; hash_index < HASHSIZE; hash_index++)
    {
      tmp = olsr->two_neigh_set[hash_index].list.head;
      while (tmp != NULL){
    two_neigh_data = (OLSR_2NEIGH_TUPLE *)tmp->data;

    if (search_mprN_for_exist(olsr, &N, &two_neigh_data->N2_neighbor_iface_addr)
       == OLSR_TRUE &&
       search_association_set_for_addr_exist(olsr, &two_neigh_data->N2_2hop_iface_addr)
       == OLSR_FALSE){

      if (equal_ip_addr(olsr, &two_neigh_data->N2_local_iface_addr,
               local_iface_addr)){
        if (search_mprN_for_exist(olsr, &N, &two_neigh_data->N2_2hop_iface_addr)
           == OLSR_TRUE){
          tmp = tmp->next;
          continue;
        }


        if (search_mprN2_for_exist(olsr, &N2, &two_neigh_data->N2_2hop_iface_addr) == OLSR_FALSE)
        {
          insert_mprN2(&N2, &two_neigh_data->N2_2hop_iface_addr);
        }
      }

    }
    tmp = tmp->next;
      }
    }
  //print_mprN2(olsr, &N2);


  //Appendix A.1
  // Start with an MPR set made of all members of N with N_willingness
  // equal to WILL_ALWAYS
  if (DEBUG_OLSRV2)
  {
      olsr_printf("[Appendix A.1]\n");
  }

  tmp = N.head;
  while (tmp != NULL){
    mpr_n_data = (OLSR_MPR_N_TUPLE *)tmp->data;
    if (mpr_n_data->willingness == WILL_ALWAYS)
      insert_mpr_set_per_interface(MPR_set, local_iface_addr, &mpr_n_data->addr);
    tmp = tmp->next;
  }

  update_mprN2(olsr,
           &N2, MPR_set, local_iface_addr);

  //print_mprN2(olsr, &N2);

  //Appendix A.3
  // Add to the MPR set those interfaces in N, which are the *only*
  // nodes to provide reachability to an interface in N2.  For
  // example, if interface B in N2 can be reached only through a
  // symmetric link to interface A in N, then add interface B to the
  // MPR set.  Remove the interfaces from N2 which are now covered by
  // a interface in the MPR set.
  if (DEBUG_OLSRV2)
  {
      olsr_printf("[Appendix A.3]\n");
  }

  tmp = N2.head;
  while (tmp != NULL){
    mpr_n2_data = (OLSR_MPR_N2_TUPLE *)tmp->data;
    retList =
      search_2neigh_set_for_mpr_n2(olsr,
                   local_iface_addr,
                   &mpr_n2_data->addr);
    if (retList != NULL){
      if (retList->numEntry == 1){

    two_neigh_data = (OLSR_2NEIGH_TUPLE *)retList->head->data;
    insert_mpr_set_per_interface(MPR_set,
                     local_iface_addr,
                     &two_neigh_data->N2_neighbor_iface_addr);
    update_mprN2_locally(olsr,
                 &N2,
                 local_iface_addr,
                 &two_neigh_data->N2_neighbor_iface_addr);
    tmp = N2.head;
    OLSR_DeleteList_Search(retList);
    continue;
      }
      OLSR_DeleteList_Search(retList);
    }

    tmp = tmp->next;
  }

  //print_mprN2(olsr, &N2);

  //Appendix A.4
  // While there exist interfaces in N2 which are not covered by at
  // least one interface in the MPR set:
  if (DEBUG_OLSRV2)
  {
      olsr_printf("[Appendix A.4]\n");
  }

  while (N2.head != NULL){
    //Appendix A.4.1
    // For each interface in N, calculate the reachability, i.e.,
    // the number of interfaces in N2 which are not yet covered by
    // at least one node in the MPR set, and which are reachable
    // through this neighbor interface;
    //OLSR_LIST *ret;

    olsr_u32_t max_willingness, max_reachability, max_D;
    olsr_u32_t i;
    union olsr_ip_addr mpr_addr;
    union olsr_ip_addr random_mpr[OLSR_MAX_DUPLICATE_MPR];

    memset(&mpr_addr, 0, sizeof(olsr_ip_addr));

    if (DEBUG_OLSRV2)
    {
    olsr_printf("[Appendix A.4.1]\n");
    }


    tmp = N.head;
    while (tmp != NULL){
      mpr_n_data = (OLSR_MPR_N_TUPLE *)tmp->data;
      mpr_n_data->reachability = 0;

      retList =
    search_2neigh_set_for_mpr_n(olsr,
                    local_iface_addr,
                    &mpr_n_data->addr);

      if (retList != NULL){
    retList_tmp = retList->head;
    while (retList_tmp != NULL){
      two_neigh_data = (OLSR_2NEIGH_TUPLE *)retList_tmp->data;

      if (search_mprN2_for_exist(olsr, &N2, &two_neigh_data->N2_2hop_iface_addr)
         == OLSR_TRUE){
        mpr_n_data->reachability++;
      }

      retList_tmp = retList_tmp->next;
    }
    OLSR_DeleteList_Search(retList);
      }

      tmp = tmp->next;
    }

    //print_mprN(olsr, &N);


    //Appendix A.4.2(XXX)
    // Select as a MPR the interface with highest N_willingness
    // among the interfaces in N with non-zero reachability.
    // In case of multiple choice select the interface which provides
    // reachability to the maximum number of interfaces in N2.
    // In case of multiple interfaces providing the same amount of
    // reachability, select the interface as MPR whose D(y) is
    // greater.
    // Remove the interfaces from N2 which are now covered by an interface in the MPR set.

    tmp = N.head;
    max_willingness = WILL_NEVER; //0
    max_reachability = 0;
    max_D = 0;
    i = 0;

    while (tmp != NULL){
      mpr_n_data = (OLSR_MPR_N_TUPLE *)tmp->data;

      if (mpr_n_data->reachability == 0){
    tmp = tmp->next;
    continue;
      }

      //check willingness
      if (mpr_n_data->willingness > max_willingness){
    max_willingness = mpr_n_data->willingness;
    max_reachability = mpr_n_data->reachability;
    max_D = mpr_n_data->D;
    i = 0;
    mpr_addr = mpr_n_data->addr;
      }
      else if (mpr_n_data->willingness == max_willingness){

    //check reachability
    if (mpr_n_data->reachability > max_reachability){
      max_reachability = mpr_n_data->reachability;
      max_D = mpr_n_data->D;
      i = 0;
      mpr_addr = mpr_n_data->addr;
    }
    else if (mpr_n_data->reachability == max_reachability){

      //check D(y)
      if (mpr_n_data->D > max_D){
        max_D = mpr_n_data->D;
        i = 0;
        mpr_addr = mpr_n_data->addr;
      }
      else if (mpr_n_data->D == max_D){

        if (i == 0){
          random_mpr[i++] = mpr_addr;
        }
        if (i < OLSR_MAX_DUPLICATE_MPR){
          random_mpr[i++] = mpr_n_data->addr;
        }

      }
    }
      }
      tmp = tmp->next;

    }// ....now checked duplication

    if (max_willingness == WILL_NEVER){
      olsr_error("MPR selection is wrong "
         "there is no MPR which have available willingness, "
         "or non-zero-reachability");
    }

    if (i != 0){
      i = (olsr_u32_t)(random(olsr)%i);
      mpr_addr = random_mpr[i];
    }

    insert_mpr_set_per_interface(MPR_set,
                 local_iface_addr,
                 &mpr_addr);

    update_mprN2_locally(olsr,
             &N2,
             local_iface_addr,
             &mpr_addr);

    //print_mpr_set_per_interface(olsr, MPR_set);
  }

  //print_mpr_set_per_interface(olsr, MPR_set);

  if (DEBUG_OLSRV2)
  {
      olsr_printf("[Complete MPR selection per interface]\n\n");
  }

  OLSR_DeleteList_Static(&N);
  OLSR_DeleteList_Static(&N2);

  return MPR_set;
}