int state_machine(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};
    uint64_t timeout;
    uint64_t backoff;
    packet_t *packet;	

    if (nodedata->clock != get_time()) {
        return 0;
    }

    switch (nodedata->state) {
		
    case STATE_IDLE:
        if (nodedata->txbuf == NULL) {
            nodedata->txbuf = (packet_t *) das_pop_FIFO(nodedata->packets);
            if (nodedata->txbuf == NULL) {
                return 0;
            }
        }
        
        if (nodedata->MaxCSMABackoffs != 0) {
            nodedata->state = STATE_BACKOFF;
            nodedata->BE = nodedata->MinBE;
            nodedata->NB = 0;
            backoff = get_random_double() * (pow(2, nodedata->BE) - 1) * aUnitBackoffPeriod;
			
            nodedata->clock = get_time() + backoff;  
            scheduler_add_callback(nodedata->clock, c, state_machine, NULL);
            return 0;	
        } else {
            nodedata->state = STATE_TX;
            nodedata->clock = get_time();  
            scheduler_add_callback(nodedata->clock, c, state_machine, NULL);
            return 0;
        }		

    case STATE_BACKOFF:
        if (check_channel_busy(c)) { 
            if ((++nodedata->BE) > nodedata->MaxBE) {
                nodedata->BE = nodedata->MaxBE;
            } 
            if (++nodedata->NB >= nodedata->MaxCSMABackoffs) {
                packet_dealloc(nodedata->txbuf);            
                nodedata->txbuf = NULL;

                nodedata->state = STATE_IDLE;
                nodedata->clock = get_time();
                state_machine(c,NULL);
                return 0;
            }
            backoff = get_random_double() * (pow(2, nodedata->BE) - 1) * aUnitBackoffPeriod;
            nodedata->clock = get_time() + backoff;
            scheduler_add_callback(nodedata->clock, c, state_machine, NULL);
            return 0;
        }
        
        nodedata->state = STATE_TX;
        nodedata->clock = get_time();  
        state_machine(c,NULL);
        return 0;
        
    case STATE_TX:
        packet = nodedata->txbuf;
        nodedata->txbuf = NULL;
        timeout = packet->size * 8 * radio_get_Tb(&c0) + macMinSIFSPeriod;
        TX(&c0, packet); 

        nodedata->state = STATE_TXING;
        nodedata->clock = get_time() + timeout;
        scheduler_add_callback(nodedata->clock, c, state_machine, NULL);
        return 0;

    case STATE_TXING:
        nodedata->state = STATE_IDLE;
        nodedata->clock = get_time();
        state_machine(c,NULL);
        return 0;

    default:
        break;
    }

    return 0;
}
Exemple #2
0
void MEDIA_TX(call_t *c, packet_t *packet) {
    int i = get_node_count();
    node_t *node = get_node_by_id(c->node);
    uint64_t clock;
    
    /* check wether node is active */
    if (node->state != NODE_ACTIVE) {
        packet_dealloc(packet);
        return;
    }

    /* edit by Loic Lemaitre */
    if (node->worldsens == NODE_LOCAL) {  /* WORLDSENS MODE? -> radio part is simulated in wsim */
        /* fill packet info */
        packet->node = c->node;
	packet->antenna = c->from;
	packet->txdBm = radio_get_power(c);
	packet->channel = radio_get_channel(c);
	packet->modulation = radio_get_modulation(c);
	packet->Tb = radio_get_Tb(c);
	//packet->duration = packet->size * packet->Tb * 8;
	/* edit by Quentin Lampin <*****@*****.**> */
	packet->duration = packet->real_size * packet->Tb;
	/* end of edition */
	packet->clock0 = get_time();
	packet->clock1 = packet->clock0 + packet->duration;

	/* scheduler tx_end event */
	scheduler_add_tx_end(packet->clock1, c, packet);
    }
    /* end of edition */
    
    /* scheduler rx_begin event */
#ifdef N_DAS_O
    if (propagation_range) {
        void *rx_nodes;
        node_t *rx_node;

        rx_nodes = spadas_rangesearch(location, NULL, &(node->position), propagation_range);
        while ((rx_node = (node_t *) das_pop(rx_nodes)) != NULL) {
            double derive = distance(&(node->position), &(rx_node->position)) / 0.3; 
            bundle_t *bundle = get_bundle_by_id(rx_node->bundle);
            int i;
    
            if (rx_node->state == NODE_DEAD) {
                continue;
            }

            for (i = 0; i < bundle->antenna.size; i++) {
                entity_t *entity = get_entity_by_id(bundle->antenna.elts[i]);
                call_t c0 = {entity->id, rx_node->id, -1}; 
                packet_t *packet_rx = packet_rxclone(packet);
                
                clock = packet->clock0 + ((uint64_t) derive);
                packet_rx->clock0 = clock;
                packet_rx->clock1 = clock + packet->duration;
                scheduler_add_rx_begin(clock, &c0, packet_rx);
            }
        }
        das_destroy(rx_nodes);
    } else {
        while (i--) {
            node_t *rx_node = get_node_by_id(i);
            double derive = distance(&(node->position), &(rx_node->position)) / 0.3; 
            bundle_t *bundle = get_bundle_by_id(rx_node->bundle);
            int i;
            
            if (rx_node->state == NODE_DEAD) {
                continue;
            }
            
            for (i = 0; i < bundle->antenna.size; i++) {
                entity_t *entity = get_entity_by_id(bundle->antenna.elts[i]);
                call_t c0 = {entity->id, rx_node->id, -1}; 
                packet_t *packet_rx = packet_rxclone(packet);

                clock = packet->clock0 + ((uint64_t) derive);
                packet_rx->clock0 = clock;
                packet_rx->clock1 = clock + packet->duration;
                scheduler_add_rx_begin(clock, &c0, packet_rx);
            }
        }
    }   
#else /* N_DAS_O */
    while (i--) {
        node_t *rx_node = get_node_by_id(i);
        double dist = distance(&(node->position), &(rx_node->position));
        double derive = dist / 0.3; 
        bundle_t *bundle = get_bundle_by_id(rx_node->bundle);
        int i;

        if (rx_node->state == NODE_DEAD) {
            continue;
        }
        
        if ((propagation_range) && (dist > propagation_range)) {
            continue;
        }
        
        for (i = 0; i < bundle->antenna.size; i++) {
            entity_t *entity = get_entity_by_id(bundle->antenna.elts[i]);
            call_t c0 = {entity->id, rx_node->id, -1}; 
            packet_t *packet_rx = packet_rxclone(packet);
            
            clock = packet->clock0 + ((uint64_t) derive);
            packet_rx->clock0 = clock;
            packet_rx->clock1 = clock + packet->duration;
            scheduler_add_rx_begin(clock, &c0, packet_rx);
        }
    }
#endif /* N_DAS_O */

}