Ejemplo n.º 1
0
/* ************************************************** */
void medium_compute_rxdBm(packet_t *packet, call_t *c) {
    call_t c0 = {packet->antenna, packet->node, -1};
    double rxdBm = packet->txdBm;
    position_t *pos_tx = get_node_position(packet->node);
    position_t *pos_rx = get_node_position(c->node);

    /* antenna tx white noise */
    rxdBm += antenna_get_loss(&c0);

    /* antenna tx gain (TODO: angle au moment de l'?mission) */
    rxdBm += antenna_gain_tx(&c0, pos_rx);

    /* propagation */
    c0.entity = propagation_entity->id;
    if (c->node != packet->node) {
        rxdBm = propagation_entity->methods->propagation.propagation(&c0, packet, 
                                                                     packet->node,
                                                                     c->node, rxdBm);
    }

    /* TODO: add shadowing & fading only if > MIN_DBM */

    /* antenna rx gain */
    rxdBm += antenna_gain_rx(c, pos_tx);

    /* antenna rx white noise */
    rxdBm += antenna_get_loss(c);

    /* rx power */
    packet->rxdBm = rxdBm;
    packet->rxmW = dBm2mW(rxdBm);
}
/* Find all the neighbors (i.e. nodes in range) of the current node */
int find_neighbors(call_t *c) {
    struct nodedata *nodedata = get_node_private_data(c);
    struct neighbor *neighbor = NULL;    
    nodeid_t i;
    double dist = 0;
    int nb_neigh = 0;

    /* Parse all the nodes in the simulation: and find the ones 
     * that are in range of that node
     */
    for(i = 0; i < get_node_count(); i++) {
        /* Do not include myself */
        if (i == c->node) {
            continue;
        }

        dist = distance(get_node_position(c->node), get_node_position(i));
        if (dist <= nodedata->range) {
            /* Add the node in the list of neighbors */
            neighbor = (struct neighbor *) malloc(sizeof(struct neighbor));
            neighbor->id = i;
            neighbor->position.x = get_node_position(i)->x;
            neighbor->position.y = get_node_position(i)->y;
            neighbor->position.z = get_node_position(i)->z;
            neighbor->time = get_time();
            //PRINT_ROUTING("Node %d is added to neighbor list of node %d\n",
            //              neighbor->id, c->node);    
            das_insert(nodedata->neighbors, (void *) neighbor);
            nb_neigh++;
        }
    }

    return nb_neigh;
}
/* ************************************************** */
int set_header(call_t *c, packet_t *packet, destination_t *dst) {
    struct nodedata *nodedata = get_node_private_data(c);
    struct neighbor *n_hop = get_nexthop(c, &(dst->position));
    destination_t destination;
    struct routing_header *header = (struct routing_header *) (packet->data + nodedata->overhead);
    call_t c0 = {get_entity_bindings_down(c)->elts[0], c->node, c->entity};

    /* if no route, return -1 */
    if (dst->id != BROADCAST_ADDR && n_hop == NULL) {
        nodedata->data_noroute++;
        return -1;
    }
    else if (dst->id == BROADCAST_ADDR) {
      n_hop->id = BROADCAST_ADDR;
    }

    /* set routing header */
    header->dst = dst->id;
    header->dst_pos.x = dst->position.x;
    header->dst_pos.y = dst->position.y;
    header->dst_pos.z = dst->position.z;
    header->src = c->node;
    header->src_pos.x = get_node_position(c->node)->x;
    header->src_pos.y = get_node_position(c->node)->y;
    header->src_pos.z = get_node_position(c->node)->z;
    header->type = DATA_PACKET;
    header->hop = nodedata->hop;

    /* Set mac header */
    destination.id = n_hop->id;
    destination.position.x = -1;
    destination.position.y = -1;
    destination.position.z = -1;
    return SET_HEADER(&c0, packet, &destination);
}
/* ************************************************** */
int setnode(call_t *c, void *params) {
    int id, found = 0;
    double x, y, z;
    struct entitydata *entitydata = get_entity_private_data(c);
    char str[128];

    /* position at the beginning */
    fseek(entitydata->file, 0L, SEEK_SET);
    while (fgets(str, 128, entitydata->file) != NULL) {
        sscanf(str, "%d %lf %lf %lf\n",  &id, &x, &y, &z);
        if (id == c->node) {
            found = 1;
            get_node_position(c->node)->x = x;
            get_node_position(c->node)->y = y;
            get_node_position(c->node)->z = z;
            break; 
        }
    }

    if (found == 0) {
        fprintf(stderr, "filestatic: node %d position not found (setnode())\n", c->node);
        return -1;       
    }

    return 0;
}
/* *********************************************** */
int set_header( call_t *c , packet_t * packet , destination_t * dst )
{
    struct nodedata *nodedata = get_node_private_data(c);
    struct protocoleData *entitydata =get_entity_private_data(c);

    packet_PROTOCOLE *data = (packet_PROTOCOLE *) (packet->data + nodedata->overhead);
    //augmenter le nbr d'evenement
    nodedata->nbr_evenement++;

    if(entitydata->debug)
        DBG("RBOP - %d SET HEADER  \n",c->node);

    //Fixé le rayon
    if(nodedata->range<0)
    {

        listeNodes *tmp=nodedata->oneHopNeighbourhood;
        position_t pos1 = *get_node_position(c->node);
        double distMax = 0;
        while(tmp)
        {
            if(list_recherche(nodedata->RNG,tmp->values.node))
            {
                position_t pos2= {tmp->values.x,tmp->values.y,tmp->values.z};
                double dist=distance(&pos1,&pos2);
                if(distMax<dist)    distMax=dist;
            }
            tmp=tmp->suiv;
        }
        set_range_Tr(c,distMax);
        nodedata->range=get_range_Tr(c);
        if(entitydata->debug)
            DBG("RBOP  - %d FIXE RANGE TO %.2lf  \n",c->node,get_range_Tr(c));
    }



    //remplissage de data
    data->type=RBOP;
    data->src=c->node;
    data->src_pos=*get_node_position(c->node);
    data->seq=nodedata->nbr_evenement;
    data->redirected_by=c->node;

    data->destinations=Nullptr(list);
    list_copy(&data->destinations,nodedata->RNG);

    list_PACKET_insert_tout(&nodedata->paquets,data->src,data->seq,data->redirected_by);



    call_t c0 = {get_entity_bindings_down(c)->elts[0], c->node, c->entity};

    destination_t destination = {BROADCAST_ADDR, {-1, -1, -1}};

    return SET_HEADER(&c0, packet, &destination);
}
Ejemplo n.º 6
0
/* ************************************************** */
int bootstrap(call_t *c) {
    struct nodedata *nodedata = get_node_private_data(c);

    PRINT_REPLAY("mobility %"PRId64" %d %lf %lf %lf\n", get_time(), c->node, 
                 get_node_position(c->node)->x, get_node_position(c->node)->y, 
                 get_node_position(c->node)->z);
    
    nodedata->lupdate = get_time();
    nodedata->nupdate = get_time() + nodedata->pausetime;
    return 0;
}
Ejemplo n.º 7
0
int log_energymap(call_t *c) {
    struct entitydata *entitydata = get_entity_private_data(c);
    int i = get_node_count();
    FILE *file = NULL;
    char file_map[100];
    double time = get_time() * 0.000001;
    
    /* create file */
    sprintf(file_map, "%s/%s.%.0lf.data", entitydata->directory, entitydata->map_prefix, time);    
    if ((file = fopen(file_map, "w+")) == NULL) {
        fprintf(stderr, "My monitor: can not open file %s in monitor_event()\n", file_map);
        return -1;
    }
    
    /* log energy map */
    while (i--) {
        call_t c0 = {-1, i, -1};
        position_t *position = get_node_position(c0.node);
        fprintf(file, "%d %lf %lf %lf %lf\n", c0.node, position->x, position->y, position->z, battery_status(&c0));
    }

    /* log virtual nodes for the 4 area corners */
    fprintf(file, "%d %lf %lf %lf %lf\n", -1, 0.0, 0.0, 0.0, 1.0);
    fprintf(file, "%d %lf %lf %lf %lf\n", -1, get_topology_area()->x, 0.0, 0.0, 1.0);
    fprintf(file, "%d %lf %lf %lf %lf\n", -1, 0.0, get_topology_area()->y, 0.0, 1.0);
    fprintf(file, "%d %lf %lf %lf %lf\n", -1, get_topology_area()->x, get_topology_area()->y, 0.0, 1.0);
    
    fclose(file);
    return 0;
}
Ejemplo n.º 8
0
/* Greedy geographic routing => computing the nexthop */ 
struct xy_neighbor *xy_next_hop(call_t *c, position_t *position) {
    struct nodedata *nodedata = get_node_private_data(c);
    struct xy_neighbor *neighbor = NULL, *n_hop = NULL;
    double dist = distance(get_node_position(c->node), position);
    double d = dist;
    uint64_t clock = get_time();

    /* parse neighbors */
    das_init_traverse(nodedata->neighbors);    

    while ((neighbor = (struct xy_neighbor *) das_traverse(nodedata->neighbors)) != NULL) {

#ifdef CHECK_ACTIVE_NODE
        if ( !is_node_alive(neighbor->id) || ((nodedata->h_timeout > 0) && (clock - neighbor->time) >= nodedata->h_timeout) ) {
            continue;
        }
#else
        if ((nodedata->h_timeout > 0) && (clock - neighbor->time) >= nodedata->h_timeout ) {
            continue;
        }
#endif
        
        /* choose next hop */
        if ((d = distance(&(neighbor->position), position)) < dist) {
            dist = d;
            n_hop = neighbor;
        }
    }    
    
    return n_hop;
}
double setRangeToFarestNeighbour(call_t *c, graphe* g, arbre* bipTree)
{
	struct nodedata *nodedata = get_node_private_data(c);
	struct protocoleData *entitydata = get_entity_private_data(c);
	
	// calcul de la distance entre ce noeud et son voisin 1-hop (dans l'arbre de BIP) le plus eloigne
	list *fils = 0;
	double distMax = 0, dist;
	position_t pos;
	arbre_get_fils(&fils, bipTree, c->node);
	while(fils != 0)
	{
		pos = listeNodes_getPos(nodedata->oneHopNeighbourhood, fils->val);
		dist = distance(get_node_position(c->node), &pos);
		if(dist > distMax)
		{
			distMax = dist;
		}
		fils = fils->suiv;
	}
	
	
	// set le range du module propagation a la valeur desiree
	set_range_Tr(c, distMax);
	//printf("rayon d'emission de %d fixe a %lf\n", c->node, macdata->range);
	
	return distMax;
}
Ejemplo n.º 10
0
/* ************************************************** */
double propagation(call_t *c, packet_t *packet, nodeid_t src, nodeid_t dst, double rxdBm) {
    struct entitydata *entitydata = get_entity_private_data(c);
    double dist = distance(get_node_position(src), get_node_position(dst));

    /*
     *  Pr_dBm(d) = Pr_dBm(d0) - 10 * beta * log10(d/d0)
     *
     *  Note: rxdBm = [Pt + Gt + Gr]_dBm, and L = 1
     *
     *  cf p102-104 ref "Wireless Communications: Principles and Practice", Theodore Rappaport, 1996.
     *
     */
    if (dist <= 1) {
        return entitydata->Pr0 + rxdBm;
    } else {
        return entitydata->Pr0 + rxdBm - 10.0 * entitydata->pathloss * log10(dist);
    }
}
Ejemplo n.º 11
0
//RECEPTION et REPONDRE AU PACKET HELLO
int rx_one_hop(call_t *c, packet_t *packet) {
    struct nodedata *nodedata = get_node_private_data(c);

    //RECEPTION  DE PACKET HELLO
    struct packet_hello *hello = (struct packet_hello *) (packet->data + nodedata->overhead[0]);

    DEBUG;
    /*printf("NOde %d a recu un HELLO de %d (%lf %lf %lf) at %lf\n",c->node,
           hello->source,
           get_node_position(hello->source)->x,get_node_position(hello->source)->y,get_node_position(hello->source)->z,
           get_time_now_second());//*/


    //l'ajoute de voisin
    if(!list_recherche(nodedata->N1,hello->source))
        list_insert(&nodedata->N1,hello->source);


    //REPONSE DE PAKET HELLO

    //recuperer le support de communication MAC
     entityid_t *down = get_entity_links_down(c);
     call_t c0 = {down[0], c->node};

     //destination de paquet
     destination_t destination = {hello->source, {get_node_position(hello->source)->x,get_node_position(hello->source)->y,get_node_position(hello->source)->z}};

     //creation de paquet et initialisation de son data
     packet_t *rpacket = packet_alloc(c, nodedata->overhead[0] + sizeof(struct packet_hello));
     struct packet_hello *rhello = (struct packet_hello *) (rpacket->data + nodedata->overhead[0]);

     //initilailser les données
     rhello->type     =   REP_HELLO;
     rhello->source   =   c->node;

     if (SET_HEADER(&c0, rpacket, &destination) == -1) {
         packet_dealloc(rpacket);
         return -1;
     }

     DEBUG;
     /*printf("Node %d (%lf %lf %lf) repond a %d  packet hello, at %lf\n", c->node,                               //id de Noeud de noeud encours
                get_node_position(c->node)->x,get_node_position(c->node)->y,get_node_position(c->node)->z,           //la postion x, y,z de Noeud
                hello->source,                                                                                       //id de noued de destination
                get_time_now_second()); //*/                                                                             //l'instant d'envoi.

     //L'envoi
     TX(&c0,rpacket);

    //liberer le packet
    packet_dealloc(packet);

    //tous c'est bien passé
    return 1;

}
/* ************************************************** */
double compute_freespace(struct entitydata *entitydata, nodeid_t src, nodeid_t dst, double rxdBm) {
    /*
     *           Pt * Gt * Gr * lambda^2
     *  Pr(d) = -------------------------
     *             (4 * pi * d)^2 * L
     *
     *  Note: rxdBm = [Pt + Gt + Gr]_dBm, and L = 1
     *
     *  cf p71 ref "Wireless Communications: Principles and Practice", Theodore Rappaport, 1996.
     *
     */
    double dist = distance(get_node_position(src), get_node_position(dst));

    if (dist == 0) {
      return (rxdBm);
    } else {
      return (rxdBm + 2 * mW2dBm(entitydata->factor / dist));
    }
}
/* ************************************************** */
double compute_logdistance_pathloss(struct entitydata *entitydata, nodeid_t src, nodeid_t dst, double rxdBm) {
    /*
     *  Pr_dBm(d) = Pr_dBm(d0) - 10 * beta * log10(d/d0)
     *
     *  Note: rxdBm = [Pt + Gt + Gr]_dBm, and L = 1
     *
     *  cf p102-104 ref "Wireless Communications: Principles and Practice", Theodore Rappaport, 1996.
     *
     */
    double dist;

    if (rxdBm != entitydata->last_rxdBm) {
        entitydata->Pr0  = freespace(entitydata, entitydata->dist0, dBm2mW(rxdBm));
        entitydata->last_rxdBm = rxdBm;
    }

    dist = distance(get_node_position(src), get_node_position(dst));

    return mW2dBm(entitydata->Pr0) - 10.0 * entitydata->pathloss * log10(dist/entitydata->dist0);
}
Ejemplo n.º 14
0
/* ************************************************** */
void xy_stats(call_t *c) {
   struct nodedata *nodedata = get_node_private_data(c);
   position_t *position = get_node_position(c->node);

   if (nodedata->type == INLINE_NODE) {
     printf("INLINE node %d (%lf,%lf,%lf)  Group_id=%d   Neighbors=%d\n", c->node, position->x, position->y, position->z, nodedata->group_id, das_getsize(nodedata->neighbors));
   } else {
     printf("SENSOR node %d (%lf,%lf,%lf)  Neighbors=%d\n", c->node, position->x, position->y, position->z, das_getsize(nodedata->neighbors));

   }
}
Ejemplo n.º 15
0
/* ************************************************** */
void update_position(call_t *c) {
    struct nodedata *nodedata = get_node_private_data(c);
        
    while  (nodedata->lupdate < get_time()) {
      
        if (nodedata->nupdate <= get_time()) {
            nodedata->lupdate = nodedata->nupdate;
            nodedata->nupdate += nodedata->pausetime;

            get_node_position(c->node)->x = get_random_x_position();
            get_node_position(c->node)->y = get_random_y_position();
            get_node_position(c->node)->z = get_random_z_position();
            PRINT_REPLAY("mobility %"PRId64" %d %lf %lf %lf\n", nodedata->lupdate, c->node, get_node_position(c->node)->x, get_node_position(c->node)->y, get_node_position(c->node)->z);
        } else {
            nodedata->lupdate = get_time();
            break;
        }
    }

    return;
}
Ejemplo n.º 16
0
//INITIALISATION DE NOEUD DE FICHIER XML
int setnode(call_t *c, void *params) {
    struct nodedata *nodedata = malloc(sizeof(struct nodedata));

    nodedata->overhead = -1;
    nodedata->range = -1;
    //les packets
    nodedata->paquets   = Nullptr(list_PACKET);

    //les voisinages
    nodedata->oneHopNeighbourhood = Nullptr(listeNodes);

    nodedata->RNG = Nullptr(list);
//STATS
    nodedata->nbr_evenement = 0;

    set_node_private_data(c, nodedata);

    SHOW_GRAPH("N: %d %lf %f\n",c->node,get_node_position(c->node)->x,get_node_position(c->node)->y);

    return 0;
}
Ejemplo n.º 17
0
/* ************************************************** */
int setnode(call_t *c, void *params) {
    struct nodedata *nodedata = malloc(sizeof(struct nodedata));
    param_t *param;
    uint64_t min_pausetime, max_pausetime;
    
    /* default values */
    get_node_position(c->node)->x = get_random_x_position();
    get_node_position(c->node)->y = get_random_y_position();
    get_node_position(c->node)->z = get_random_z_position();

    nodedata->pausetime = 2000000000;
    min_pausetime       = 0;
    max_pausetime       = 0;

    /* get parameters */
    das_init_traverse(params);
    while ((param = (param_t *) das_traverse(params)) != NULL) {
        if (!strcmp(param->key, "x")) {
            if (get_param_x_position(param->value, &(get_node_position(c->node)->x))) {
                goto error;
            }
        }
        if (!strcmp(param->key, "y")) {
            if (get_param_y_position(param->value, &(get_node_position(c->node)->y))) {
                goto error;
            }
        }
        if (!strcmp(param->key, "z")) {
            if (get_param_z_position(param->value, &(get_node_position(c->node)->z))) {
                goto error;
            }
        }
        if (!strcmp(param->key, "pausetime")) {
            if (get_param_time(param->value, &(nodedata->pausetime))) {
                goto error;
            }
        }
        if (!strcmp(param->key, "min-pausetime")) {
            if (get_param_time(param->value, &min_pausetime)) {
                goto error;
            }
        }
        if (!strcmp(param->key, "max-pausetime")) {
            if (get_param_time(param->value, &max_pausetime)) {
                goto error;
            }
        }
    }
    
    if (min_pausetime < max_pausetime ) {
        nodedata->pausetime = get_random_time_range(min_pausetime, max_pausetime);
    }
    
    set_node_private_data(c, nodedata);
    return 0;

 error:
    free(nodedata);
    return -1;
}
Ejemplo n.º 18
0
/* ************************************************** */
double propagation(call_t *c, packet_t *packet, nodeid_t src, nodeid_t dst, double rxdBm) {
    struct entitydata *entitydata = get_entity_private_data(c);
    double dist, powerloss_dbm;
    /*
     *  Pr_dBm(d) = Pr_dBm(d0) - 10 * beta * log10(d/d0) + X
     *
     *  Note: rxdBm = [Pt + Gt + Gr]_dBm, L = 1, and X a normal distributed RV (in dBm)
     *
     *  cf p104-105 ref "Wireless Communications: Principles and Practice", Theodore Rappaport, 1996.
     *
     */
    if (rxdBm != entitydata->last_rxdBm) {
        entitydata->Pr0  = freespace(c, packet, entitydata->dist0, dBm2mW(rxdBm));
        entitydata->last_rxdBm = rxdBm;
    }

    dist = distance(get_node_position(src), get_node_position(dst));

    powerloss_dbm = -10.0 * entitydata->pathloss * log10(dist/entitydata->dist0) + normal(0.0, entitydata->deviation);
    
    return mW2dBm(entitydata->Pr0) + powerloss_dbm;
}
/* ************************************************** */
double compute_tworayground(struct entitydata *entitydata, nodeid_t src, nodeid_t dst, double rxdBm) {
    /*
     * Cross over distance:
     *
     *        4 * pi * ht * hr
     *  dc = ------------------
     *             lambda
     *                               Pt * Gt * Gr * (ht * hr)^2
     *  Case 1: d >= dc  => Pr(d) = -----------------------------
     *                                        d^4 * L
     *
     *                               Pt * Gt * Gr * lambda^2
     *  Case 2: d < dc   => Pr(d) = -------------------------
     *                                 (4 * pi * d)^2 * L
     *
     *  Note: rxmW = Pt * Gt * Gr, and L = 1
     *  
     *  cf p89 ref "Wireless Communications: Principles and Practice", Theodore Rappaport, 1996.
     *
     */
    double dist;

    dist = distance(get_node_position(src), get_node_position(dst));

    if (dist == 0) {
      return rxdBm;
    } 
    else if (dist < entitydata->crossover_distance) {
        /* uses friis formula for distance < crossover distance or if (ht == hr == 0) */
        return (rxdBm + 2 * mW2dBm(entitydata->factor / dist));
    } 
    else {
        /* else two-ray ground model is more accurate for distance > crossover distance */
        return (rxdBm + mW2dBm(entitydata->ht * entitydata->ht * 
                               entitydata->hr * entitydata->hr / pow(dist, 4.0)));
    }
}
// initialisation des noeuds a partir du fichier xml
int setnode(call_t *c, void *params) {
    struct nodedata *nodedata = malloc(sizeof(struct nodedata));
    struct protocoleData *entitydata = malloc(sizeof(struct protocoleData));
	
	nodedata->overhead = -1;
    nodedata->oneHopNeighbourhood = 0;
	nodedata->twoHopNeighbourhood = 0;
	nodedata->g2hop = malloc(sizeof(graphe));
	initGraphe(nodedata->g2hop, c->node);
	nodedata->BIP_tree = 0;
	nodedata->nbr_evenement = 0; //STATS
	nodedata->lastIDs = malloc(get_node_count()*sizeof(int));
	nodedata->energiesRem = malloc(get_node_count()*sizeof(double));
	
	
    set_node_private_data(c, nodedata);
	
	
    SHOW_GRAPH("N: %d %lf %f\n",c->node,get_node_position(c->node)->x,get_node_position(c->node)->y);
	
//	printf("Node %d at ( %.1lf ; %.1lf ; %.1lf )\n", c->node,get_node_position(c->node)->x,get_node_position(c->node)->y,get_node_position(c->node)->z);
	
    return 0;
}
Ejemplo n.º 21
0
int xy_is_nearest(call_t *c, position_t *sink_position) {
  struct nodedata *nodedata = get_node_private_data(c);
  struct xy_neighbor *neighbor = NULL;
  double dist = distance(get_node_position(c->node), sink_position);

  das_init_traverse(nodedata->neighbors);    

  while ((neighbor = (struct xy_neighbor *) das_traverse(nodedata->neighbors)) != NULL) {
    if ((distance(&(neighbor->position), sink_position) < dist) && (is_node_alive(neighbor->id))) {
      return 0;
    }
  }
    
  return 1;
}
int advert_callback(call_t *c, void *args) {
    struct nodedata *nodedata = get_node_private_data(c);
    call_t c0 = {get_entity_bindings_down(c)->elts[0], c->node, c->entity};
    destination_t destination = {BROADCAST_ADDR, {-1, -1, -1}};
    packet_t *packet = packet_create(c, nodedata->overhead + sizeof(struct routing_header), -1);
    struct routing_header *header = (struct routing_header*) (packet->data + nodedata->overhead);
        
    /* set mac header */
    if (SET_HEADER(&c0, packet, &destination) == -1) {
        packet_dealloc(packet);
        return -1;
    }

    /* set routing header */
    header->dst = BROADCAST_ADDR;
    header->dst_pos.x = -1;
    header->dst_pos.y = -1;
    header->dst_pos.z = -1;
    header->src = c->node;
    header->src_pos.x = get_node_position(c->node)->x;
    header->src_pos.y = get_node_position(c->node)->y;
    header->src_pos.z = get_node_position(c->node)->z;
    header->type = HELLO_PACKET;
    header->hop = 1;
    
    /* send hello */
    TX(&c0, packet);
    nodedata->hello_tx++;

    /* check neighbors timeout  */
    das_selective_delete(nodedata->neighbors, neighbor_timeout, (void *) c);

    /* schedules hello */
    scheduler_add_callback(get_time() + nodedata->period, c, advert_callback, NULL);
    return 0;
}
Ejemplo n.º 23
0
/* Periodic exchange of hello packets */
int hello_callback(call_t *c, void *args) {
    struct entitydata *entitydata = get_entity_private_data(c);
    struct nodedata *nodedata = get_node_private_data(c);

    entityid_t *down = get_entity_links_down(c);
    call_t c0 = {down[0], c->node, c->entity};

    destination_t destination = {BROADCAST_ADDR, {-1, -1, -1}};

    packet_t *packet = packet_create(c, nodedata->overhead + sizeof(struct xy_hello_p), -1);
    struct xy_hello_p *hello = (struct xy_hello_p *) (packet->data + nodedata->overhead);
    position_t *pos = get_node_position(c->node);

    /* set mac header */
    if (SET_HEADER(&c0, packet, &destination) == -1) {
        packet_dealloc(packet);
        return -1;
    }
    
    /* set header */
    hello->type       = XY_HELLO_TYPE;
    hello->src        = c->node;
    hello->position.x = pos->x;
    hello->position.y = pos->y;
    hello->position.z = pos->z;

    TX(&c0, packet);	   
    entitydata->TX_hello++;

    /* check neighbors timeout */
    if (nodedata->h_timeout > 0) {
        das_selective_delete(nodedata->neighbors, neighbor_timeout, (void *) c);
    }
    
    /* schedules hello */
    if (nodedata->h_nbr > 0) {
        nodedata->h_nbr --;
    }

    if (nodedata->h_nbr == -1 || nodedata->h_nbr > 0) {
      scheduler_add_callback(get_time() + nodedata->h_period, c, hello_callback, NULL);
    }

    return 0;
}
/* ************************************************** */
struct neighbor* get_nexthop(call_t *c, position_t *dst) {
    struct nodedata *nodedata = get_node_private_data(c);
    struct neighbor *neighbor = NULL, *n_hop = NULL;
    uint64_t clock = get_time();
    double dist = distance(get_node_position(c->node), dst);
    double d = dist;

    /* parse neighbors */
    das_init_traverse(nodedata->neighbors);    
    while ((neighbor = (struct neighbor *) das_traverse(nodedata->neighbors)) != NULL) {        
        if ((nodedata->timeout > 0)
            && (clock - neighbor->time) >= nodedata->timeout ) {
            continue;
        }
        
        /* choose next hop */
        if ((d = distance(&(neighbor->position), dst)) < dist) {
            dist = d;
            n_hop = neighbor;
        }
    }    
    
    return n_hop;
}
Ejemplo n.º 25
0
/* received a request from a sensor */
void rx_xy_request(call_t *c, packet_t *packet) {
    struct nodedata *nodedata = get_node_private_data(c);
    struct entitydata *entitydata = get_entity_private_data(c);

    struct xy_request_p *request = (struct xy_request_p *) (packet->data + nodedata->overhead);
    position_t rdv_position;
    struct xy_neighbor *n_hop;
    entityid_t *down = get_entity_links_down(c);
    call_t c0 = {down[0], c->node, c->entity};

    /* are we the next hop */
    if (request->n_hop != c->node) {
        packet_dealloc(packet);
        return;
    }

    /* do we have the requested data (or some more recent data) ? */
    if (request->d_seq <= nodedata->d_seq[request->metadata]) {

	packet_t *packet0;
	destination_t dst = {BROADCAST_ADDR, {-1, -1, -1}};
	
	n_hop = xy_next_hop(c, &(request->position));   
	
	if (n_hop == NULL) {
	    struct sensor_data_p *data;
	    
	    packet0 = packet_create(c, nodedata->overhead + sizeof(struct sensor_data_p), -1);
	    data = (struct sensor_data_p *) (packet0->data + nodedata->overhead);
	    if (SET_HEADER(&c0, packet0, &dst) == -1) {
	      packet_dealloc(packet);
	      packet_dealloc(packet0);
	      return;
	    }
	    data->type     = SENSOR_DATA_TYPE;
	    data->metadata = request->metadata;
	    data->sink     = request->sink;
	    data->r_seq    = request->r_seq;
	    data->source   = nodedata->d_source[request->metadata];
	    data->d_seq    = nodedata->d_seq[request->metadata];
	    data->d_value  = nodedata->d_value[request->metadata];
	    data->delay    = nodedata->d_time[request->metadata];
	    data->hop      = nodedata->d_hop[request->metadata];
	    
#ifdef LOG_APPLICATION_REQUEST
	    printf("[XY] Node %d (%lf,%lf) : broadcasting DATA REPLY (%d,%d,%d) to sink %d (%lf,%lf)\n", c->node, (get_node_position(c->node))->x, (get_node_position(c->node))->y, nodedata->d_source[request->metadata], request->metadata, nodedata->d_seq[request->metadata], request->sink, (get_node_position(request->sink))->x, (get_node_position(request->sink))->y);
#endif
	    TX(&c0, packet0);
	    entitydata->TX_sensor_data++;

	    packet_dealloc(packet);
	    return;

	} else {

	  struct xy_response_p *response;
            
	  /* reply */
	  packet0 = packet_create(c, nodedata->overhead + sizeof(struct xy_response_p), -1);
	  response = (struct xy_response_p *) (packet0->data + nodedata->overhead);
	  if (SET_HEADER(&c0, packet0, &dst) == -1) {
	    packet_dealloc(packet);
	    packet_dealloc(packet0);
	    return;
	  }
	  response->type       = XY_RESPONSE_TYPE;
	  response->n_hop      = n_hop->id;
	  response->metadata   = request->metadata;
	  response->sink       = request->sink;
	  response->r_seq      = request->r_seq;
	  response->source     = nodedata->d_source[request->metadata];
	  response->d_seq      = nodedata->d_seq[request->metadata];
	  response->d_value    = nodedata->d_value[request->metadata];
	  response->time       = nodedata->d_time[request->metadata];
	  response->hop        = nodedata->d_hop[request->metadata];
	  response->position.x = request->position.x;
	  response->position.y = request->position.y;
	  response->position.z = request->position.z;

	  TX(&c0, packet0);
	  entitydata->TX_response++;

	  packet_dealloc(packet);
	  return;

	}
	
    } 
    /* forwards the query towards the specified direction */
    else {

	switch(request->direction){
	    case DIRECTION_EAST: 
	      rdv_position.x = (get_topology_area())->x;
	      rdv_position.y = (get_node_position(c->node))->y; 
	      rdv_position.z = 0.0;
	      break;
	    case DIRECTION_WEST: 
	      rdv_position.x = 0.0;
	      rdv_position.y = (get_node_position(c->node))->y; 
	      rdv_position.z = 0.0;
	      break;
	    default:
#ifdef LOG_APPLICATION_REQUEST_ROUTING
	      printf("[XY] Node %d (%lf,%lf) received a DATA with incorrect forwarding direction (%c) !\n",c->node,(get_node_position(c->node))->x,(get_node_position(c->node))->y,request->direction);
#endif
	      packet_dealloc(packet);
	      return;
	}

	/* get next hop */
	n_hop = xy_next_hop(c, &rdv_position);

	if (n_hop != NULL) {

#ifdef LOG_APPLICATION_REQUEST_ROUTING
	    printf("[XY] node %d (%lf,%lf) : forwarding request towards direction %c via node %d \n", c->node,(get_node_position(c->node))->x,(get_node_position(c->node))->y,request->direction,n_hop->id);
#endif
	    destination_t dst = {BROADCAST_ADDR, {-1, -1, -1}};

	    /* forward data */
	    if (SET_HEADER(&c0, packet, &dst) == -1) {
	      packet_dealloc(packet);
	      return;
	    }
	    request->n_hop = n_hop->id;

	    TX(&c0, packet);
	    entitydata->TX_query++;
	    
	} else {
#ifdef LOG_APPLICATION_REQUEST_ROUTING
	  printf("[XY] node %d (%lf,%lf) : no path towards %c direction\n", c->node,(get_node_position(c->node))->x,(get_node_position(c->node))->y,request->direction);
#endif
	}
		
    }
    
    return;
}
Ejemplo n.º 26
0
/* Received a request from a sink */
void rx_sink_adv(call_t *c, packet_t *packet) {
    struct nodedata *nodedata = get_node_private_data(c);
    struct entitydata *entitydata = get_entity_private_data(c);
    struct sink_adv_p *sink = (struct sink_adv_p *) (packet->data + nodedata->overhead);
    entityid_t *down = get_entity_links_down(c);
    call_t c0 = {down[0], c->node, c->entity};
            
    /* starts home node election */
    if (sink->home == -1) {

        packet_t *packet0;
        struct home_adv_p *adv;
        destination_t dst = {BROADCAST_ADDR, {-1, -1, -1}};
        
        /* check request sequence */
        if (sink->r_seq <= nodedata->r_seq[sink->sink]) {
            /* old request */
            packet_dealloc(packet);
            return;
        }
        nodedata->r_seq[sink->sink] = sink->r_seq;

	packet0 = packet_create(c, nodedata->overhead + sizeof(struct home_adv_p), -1);
	adv = (struct home_adv_p *) (packet0->data + nodedata->overhead);
	if (SET_HEADER(&c0, packet0, &dst) == -1) {
	  packet_dealloc(packet);
	  packet_dealloc(packet0);
	  return;
	}

	adv->type   = HOME_ADV_TYPE;
	adv->sensor = c->node;
	adv->sink   = sink->sink;
	adv->r_seq  = sink->r_seq;
	
	TX(&c0, packet0);	
	entitydata->TX_home_adv++;

        packet_dealloc(packet);
        return;
    } else if (sink->home == c->node) {
      
        /* do we have the requested data (or some more recent data) ? */
        if (sink->d_seq <= nodedata->d_seq[sink->metadata]) {
	    packet_t *packet0;
	    struct sensor_data_p *data;
	    destination_t dst = {BROADCAST_ADDR, {-1, -1, -1}};

	    packet0 = packet_create(c, nodedata->overhead + sizeof(struct sensor_data_p), -1);
	    data = (struct sensor_data_p *) (packet0->data + nodedata->overhead);
	    if (SET_HEADER(&c0, packet0, &dst) == -1) {
	      packet_dealloc(packet);
	      packet_dealloc(packet0);
	      return;
	    }
	    data->type     = SENSOR_DATA_TYPE;
	    data->metadata = sink->metadata;
	    data->sink     = sink->sink;
	    data->r_seq    = sink->r_seq;
	    data->source   = nodedata->d_source[sink->metadata];
	    data->d_seq    = nodedata->d_seq[sink->metadata];
	    data->d_value  = nodedata->d_value[sink->metadata];
	    data->delay    = (get_time()-nodedata->d_time[sink->metadata])*0.000001;
	    data->hop      = nodedata->d_hop[sink->metadata];

#ifdef LOG_APPLICATION_REQUEST
	    printf("[XY] Home-Node %d (%lf,%lf) : broadcasting DATA REPLY (%d,%d,%d) to sink %d (%lf,%lf)\n", c->node, (get_node_position(c->node))->x, (get_node_position(c->node))->y, nodedata->d_source[sink->metadata], sink->metadata, nodedata->d_seq[sink->metadata], sink->sink,(get_node_position(sink->sink))->x, (get_node_position(sink->sink))->y);
#endif
	    TX(&c0, packet0);
	    entitydata->TX_sensor_data++;

	    packet_dealloc(packet);
	    return;
	
	} else {
	    position_t rdv_position;
	    struct xy_neighbor *n_hop = NULL;
	    destination_t dst = {BROADCAST_ADDR, {-1, -1, -1}};
      
	    /* forwards the query to EAST direction */
	    rdv_position.x = (get_topology_area())->x; 
	    rdv_position.y = (get_node_position(c->node))->y;
	    rdv_position.z = -1;
	    
	    n_hop = xy_next_hop(c, &rdv_position);
	    
	    if (n_hop != NULL) {

	      packet_t *packet0 = packet_create(c, nodedata->overhead + sizeof(struct xy_request_p), -1);
	      struct xy_request_p *request =  (struct xy_request_p *) (packet0->data + nodedata->overhead);
	      position_t *pos = get_node_position(c->node);
	      /* create request */
	      if (SET_HEADER(&c0, packet0, &dst) == -1) {
		packet_dealloc(packet);
		packet_dealloc(packet0);
		return;
	      }
	      request->type       = XY_REQUEST_TYPE;
	      request->n_hop      = n_hop->id;
	      request->sink       = sink->sink;
	      request->r_seq      = sink->r_seq;
	      request->metadata   = sink->metadata;
	      request->d_seq      = sink->d_seq;
	      request->position.x = pos->x;
	      request->position.y = pos->y;
	      request->position.z = pos->z;
	      request->direction  = DIRECTION_EAST;

#ifdef LOG_APPLICATION_REQUEST_ROUTING
	      printf("[XY] Node %d (%lf,%lf) : forwarding REQUEST(sink=%d,%d,%d) to EAST direction via node %d (%lf,%lf)\n", c->node, get_node_position(c->node)->x, get_node_position(c->node)->y, sink->sink, sink->metadata, sink->r_seq, n_hop->id, get_node_position(n_hop->id)->x, get_node_position(n_hop->id)->y);
#endif
	      TX(&c0, packet0);    
	      entitydata->TX_query++;

	    } else {
#ifdef LOG_APPLICATION_REQUEST
	      printf("[XY] Node %d : no path towards EAST direction\n", c->node);
#endif
	    }


	    /* forwards the query to WEST direction */
	    rdv_position.x = 0.0; 
	    rdv_position.y = (get_node_position(c->node))->y;
	    rdv_position.z = -1;
	    
	    n_hop = xy_next_hop(c, &rdv_position);
	    
	    if (n_hop != NULL) {

	      packet_t *packet0 = packet_create(c, nodedata->overhead + sizeof(struct xy_request_p), -1);
	      struct xy_request_p *request =  (struct xy_request_p *) (packet0->data + nodedata->overhead);
	      position_t *pos = get_node_position(c->node);
	      /* create request */
	      if (SET_HEADER(&c0, packet0, &dst) == -1) {
		packet_dealloc(packet);
		packet_dealloc(packet0);
		return;
	      }
	      request->type       = XY_REQUEST_TYPE;
	      request->n_hop      = n_hop->id;
	      request->sink       = sink->sink;
	      request->r_seq      = sink->r_seq;
	      request->metadata   = sink->metadata;
	      request->d_seq      = sink->d_seq;
	      request->position.x = pos->x;
	      request->position.y = pos->y;
	      request->position.z = pos->z;
	      request->direction  = DIRECTION_WEST;

#ifdef LOG_APPLICATION_REQUEST_ROUTING
	      printf("[XY] Node %d (%lf,%lf) : forwarding REQUEST(sink=%d,%d,%d) to WEST direction via node %d (%lf,%lf)\n", c->node, get_node_position(c->node)->x, get_node_position(c->node)->y, sink->sink, sink->metadata, sink->r_seq, n_hop->id, get_node_position(n_hop->id)->x, get_node_position(n_hop->id)->y);
#endif
	      TX(&c0, packet0);    
	      entitydata->TX_query++;

	    } else {
#ifdef LOG_APPLICATION_REQUEST
	      printf("[XY] Node %d : no path towards WEST direction\n", c->node);
#endif
	    }

	    packet_dealloc(packet);
	    return;
	}

    } else {
        packet_dealloc(packet);
        return;
    }
}
Ejemplo n.º 27
0
/* Received a DATA report from a sensor */
void rx_xy_data(call_t *c, packet_t *packet) {
    struct nodedata *nodedata = get_node_private_data(c);
    struct entitydata *entitydata = get_entity_private_data(c);
    struct xy_data_p *data = (struct xy_data_p *) (packet->data + nodedata->overhead);
    position_t rdv_position;
    struct xy_neighbor *n_hop;

    /* stores the received data */
    if (data->d_seq > nodedata->d_seq[data->metadata]) {
        nodedata->d_seq[data->metadata]    = data->d_seq;
	nodedata->d_source[data->metadata] = data->source;
	nodedata->d_value[data->metadata]  = data->d_value;
	nodedata->d_hop[data->metadata]    = data->hop;
	nodedata->d_time[data->metadata]   = data->time;
    }

   /* check sensor */
    if (data->n_hop != c->node) {
        /* not for us */
        packet_dealloc(packet);
        return;
    }
    
#ifdef LOG_APPLICATION_DISSEMINATION_ROUTING
    printf("[XY] Node %d (%lf,%lf) received a DATA from sensor %d => replication towards %c direction\n",c->node,(get_node_position(c->node))->x,(get_node_position(c->node))->y,data->source,data->direction);
#endif

    /* replicates the DATA towards the choosed direction */

    switch(data->direction){
       case DIRECTION_NORTH: 
	 rdv_position.x = (get_node_position(c->node))->x;
	 rdv_position.y = 0.0; 
	 rdv_position.z = 0.0;
	 break;
       case DIRECTION_SOUTH: 
	 rdv_position.x = (get_node_position(c->node))->x;
	 rdv_position.y = (get_topology_area())->y; 
	 rdv_position.z = 0.0;
	 break;
       default:
#ifdef LOG_APPLICATION_DISSEMINATION_ROUTING
         printf("[XY] Node %d (%lf,%lf) received a DATA from source %d with incorrect forwarding direction (%d) !\n",c->node,(get_node_position(c->node))->x,(get_node_position(c->node))->y,data->source,data->direction);
#endif
	 packet_dealloc(packet);
	 return;
    }

    /* get next hop */
    n_hop = xy_next_hop(c, &rdv_position);

    if (n_hop != NULL) {

#ifdef LOG_APPLICATION_DISSEMINATION_ROUTING
        printf("[XY] node %d (%lf,%lf) : forwardind data towards direction %c via node %d \n", c->node,(get_node_position(c->node))->x,(get_node_position(c->node))->y,data->direction,n_hop->id);
#endif
        destination_t dst = {BROADCAST_ADDR, {-1, -1, -1}};
	entityid_t *down = get_entity_links_down(c);
        call_t c0 = {down[0], c->node, c->entity};
        /* forward data */
        if (SET_HEADER(&c0, packet, &dst) == -1) {
            packet_dealloc(packet);
            return;
        }
        data->n_hop = n_hop->id;
	data->hop++;
        TX(&c0, packet);
	entitydata->TX_data++;

    } else {
#ifdef LOG_APPLICATION_DISSEMINATION_ROUTING
      printf("[XY] node %d (%lf,%lf) : no path towards %c direction\n", c->node,(get_node_position(c->node))->x,(get_node_position(c->node))->y,data->direction);
#endif
    }

    return;
}
Ejemplo n.º 28
0
/* received a DATA report from a source node => forwarding towards the rendez-vous area */
void rx_source_data(call_t *c, packet_t *packet) {
    struct nodedata *nodedata = get_node_private_data(c);
    struct entitydata *entitydata = get_entity_private_data(c);
    struct source_data_p *data = (struct source_data_p *) (packet->data + nodedata->overhead);
    position_t rdv_position;
    struct xy_neighbor *n_hop;

    /* stores the received data */
    if (data->d_seq > nodedata->d_seq[data->metadata]) {
        nodedata->d_seq[data->metadata]    = data->d_seq;
        nodedata->d_source[data->metadata] = data->source;
	nodedata->d_value[data->metadata]  = data->d_value;
	nodedata->d_hop[data->metadata]    = 1;
	nodedata->d_time[data->metadata]   = get_time();
    }

    /* check sensor */
    if (data->sensor != c->node) {
        /* not for us */
        packet_dealloc(packet);
        return;
    }

#ifdef LOG_APPLICATION_DISSEMINATION
    printf("[XY] Node %d (%lf,%lf) received a new DATA from source %d => replication towards north and south directions\n",c->node,(get_node_position(c->node))->x,(get_node_position(c->node))->y,data->source);
#endif

    /* replicates data towards north direction */
    rdv_position.x = (get_node_position(c->node))->x;
    rdv_position.y = 0.0;
    rdv_position.z = 0.0;
    
    /* get next hop */
    n_hop = xy_next_hop(c, &rdv_position);

    if (n_hop != NULL) {
        destination_t dst = {BROADCAST_ADDR, {-1, -1, -1}};
	packet_t *packet0 = packet_create(c, nodedata->overhead + sizeof(struct xy_data_p), -1);
        struct xy_data_p *disseminate =  (struct xy_data_p *) (packet0->data + nodedata->overhead);
        entityid_t *down = get_entity_links_down(c);
        call_t c0 = {down[0], c->node, c->entity};
        /* forward data */
        if (SET_HEADER(&c0, packet0, &dst) == -1) {
            packet_dealloc(packet0);
            packet_dealloc(packet);
            return;
        }
        disseminate->type      = XY_DATA_TYPE;
        disseminate->n_hop     = n_hop->id;
        disseminate->source    = data->source;
        disseminate->metadata  = data->metadata;
        disseminate->d_seq     = data->d_seq;
        disseminate->d_value   = data->d_value;
        disseminate->hop       = 2;
        disseminate->time      = get_time();
	disseminate->direction = DIRECTION_NORTH;

        TX(&c0, packet0);
	entitydata->TX_data++;

    } else {
#ifdef LOG_APPLICATION_DISSEMINATION_ROUTING
      printf("[XY] node %d (%lf,%lf) : no path towards NORTH direction\n", c->node,(get_node_position(c->node))->x,(get_node_position(c->node))->y);
#endif
    }

    /* replicates data towards south direction */
    rdv_position.x = (get_node_position(c->node))->x;
    rdv_position.y = (get_topology_area())->y;
    rdv_position.z = 0.0;
    
    /* get next hop */
    n_hop = xy_next_hop(c, &rdv_position);

    if (n_hop != NULL) {
        destination_t dst = {BROADCAST_ADDR, {-1, -1, -1}};
	packet_t *packet0 = packet_create(c, nodedata->overhead + sizeof(struct xy_data_p), -1);
        struct xy_data_p *disseminate =  (struct xy_data_p *) (packet0->data + nodedata->overhead);
        entityid_t *down = get_entity_links_down(c);
        call_t c0 = {down[0], c->node, c->entity};
        /* forward data */
        if (SET_HEADER(&c0, packet0, &dst) == -1) {
            packet_dealloc(packet0);
            packet_dealloc(packet);
            return;
        }
        disseminate->type      = XY_DATA_TYPE;
        disseminate->n_hop     = n_hop->id;
        disseminate->source    = data->source;
        disseminate->metadata  = data->metadata;
        disseminate->d_seq     = data->d_seq;
        disseminate->d_value   = data->d_value;
        disseminate->hop       = 2;
        disseminate->time      = get_time();
	disseminate->direction = DIRECTION_SOUTH;

        TX(&c0, packet0);
	entitydata->TX_data++;

    } else {
#ifdef LOG_APPLICATION_DISSEMINATION_ROUTING
      printf("[XY] node %d (%lf,%lf) : no path towards SOUTH direction\n", c->node,(get_node_position(c->node))->x,(get_node_position(c->node))->y);
#endif
    }

    packet_dealloc(packet);
    return;
}
/* Get the best next hop for a specific destination */
struct neighbor* get_nexthop(call_t *c, nodeid_t dst) {
    struct nodedata *nodedata = get_node_private_data(c);
    struct neighbor *neighbor = NULL, *n_hop = NULL;
    double dist = distance(get_node_position(c->node), get_node_position(dst));
    double d = dist;

    if (nodedata->curr_dst != dst 
            || (nodedata->curr_nexthop != NULL 
                && !is_node_alive(nodedata->curr_nexthop->id))) {
        /* If the destination is different from the last one,
         * or if the current next hop is dead, reinit the 
         * random counters (to force the selection of a 
         * new next_hop) */
        nodedata->random_counter = nodedata->random_nexthop;
    }

    if (nodedata->random_nexthop == 0) {
        /* We keep the current next hop if 
         * - next hop is not randomized
         * - the next hop is is still alive
         * - the destination is the same 
         */
        if (nodedata->curr_nexthop != NULL
                && nodedata->curr_dst == dst
                && is_node_alive(nodedata->curr_nexthop->id)) {
            return nodedata->curr_nexthop;
        }
        
        /* Parse neighbors */
        das_init_traverse(nodedata->neighbors);    
        while ((neighbor = (struct neighbor *) 
                            das_traverse(nodedata->neighbors)) != NULL) {        
            /* Choose next hop (the one the nearest from the final dst) 
             * and verify if it is still alive */
            if ((d = distance(&(neighbor->position), get_node_position(dst))) < dist
                    && is_node_alive(neighbor->id)) {
                dist = d;
                n_hop = neighbor;
            }
        }
    } else if (nodedata->random_counter == nodedata->random_nexthop) {
        void *next_hops = das_create();
        int nh = 0;
        double nexthop_dst = 0;

        /* Random geographic routing : we choose randomly among 
         * the neighbors that are nearer from the destination 
         * than the current node.
         */
        das_init_traverse(nodedata->neighbors);    
        while ((neighbor = (struct neighbor *) 
                            das_traverse(nodedata->neighbors)) != NULL) {        
            /* If the neighbor happens to be the final destination, 
             * then we just choose it as the next hop */
            if (neighbor->id == dst) {
                n_hop = neighbor;
                goto out;
            }

            /* Store the neighbors that are nearer from the destination 
             * and that are still alive */
            nexthop_dst = distance(&(neighbor->position), get_node_position(dst));
            if (nexthop_dst < dist && is_node_alive(neighbor->id)) {
                das_insert(next_hops, (void *) neighbor);
            }
        }
        /* Choose next hop randomly among the list */
        nh = das_getsize(next_hops);
        if (nh > 0) {
            int rnd = get_random_integer_range(1, nh);
            while (rnd--) {
                neighbor = das_pop(next_hops);
            }
            n_hop = neighbor;
        }
        das_destroy(next_hops);
    } else /* nodedata->random_counter != nodedata->random_nexthop */ {
        /* Keep the current next hop */
        n_hop = nodedata->curr_nexthop;
    }

out:
    nodedata->random_counter--;
    if (nodedata->random_counter <= 0) {
        nodedata->random_counter = nodedata->random_nexthop;    
    }

    /* Save the current next hop and destination */
    nodedata->curr_nexthop = n_hop;
    nodedata->curr_dst = dst;
    return n_hop;
}
/* ************************************************** */
int bootstrap(call_t *c) {
    PRINT_REPLAY("mobility %"PRId64" %d %lf %lf %lf\n", get_time(), c->node, 
                 get_node_position(c->node)->x, get_node_position(c->node)->y, 
                 get_node_position(c->node)->z);
    return 0;
}