Пример #1
0
/* Execute a group entry of type INDIRECT. */
static void
execute_indirect(struct group_entry *entry, struct packet *pkt) {

    if (entry->desc->buckets_num > 0) {
        struct ofl_bucket *bucket = entry->desc->buckets[0];
        struct packet *p = packet_clone(pkt);

        if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) {
            char *b = ofl_structs_bucket_to_string(bucket, entry->dp->exp);
            VLOG_DBG_RL(LOG_MODULE, &rl, "Writing bucket: %s.", b);
            free(b);
        }

        action_set_write_actions(p->action_set, bucket->actions_num, bucket->actions);

        entry->stats->byte_count += p->buffer->size;
        entry->stats->packet_count++;
        entry->stats->counters[0]->byte_count += p->buffer->size;
        entry->stats->counters[0]->packet_count++;

        action_set_execute(p->action_set, p);
        packet_destroy(p);
    } else {
        VLOG_DBG_RL(LOG_MODULE, &rl, "No bucket in group.");
    }
}
/* ************************************************** */
void rx(call_t *c, packet_t *packet) {
    struct nodedata *nodedata = get_node_private_data(c);
    struct _802_15_4_header *header = (struct _802_15_4_header *) packet->data;
    array_t *up = get_entity_bindings_up(c);
    int i = up->size;

    /* cf p171 ref 802.15.4-2006: discard packet while in backoff */
    if (nodedata->state != STATE_IDLE) {
        packet_dealloc(packet);
        return;
        
    }

    if ((header->dst != c->node) && (header->dst != BROADCAST_ADDR)) {
        packet_dealloc(packet);
        return;
    }
    
    while (i--) {
        call_t c_up = {up->elts[i], c->node, c->entity};
        packet_t *packet_up;
        
        if (i > 0) {
            packet_up = packet_clone(packet);         
        } else {
            packet_up = packet;
        }
        RX(&c_up, packet_up);
    }

    return;
}
Пример #3
0
/* Execute a group entry of type FAILFAST. */
static void
execute_ff(struct group_entry *entry, struct packet *pkt) {
    size_t b  = select_from_ff_group(entry);

    if (b != -1) {
        struct ofl_bucket *bucket = entry->desc->buckets[b];
        struct packet *p = packet_clone(pkt);

        if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) {
            char *b = ofl_structs_bucket_to_string(bucket, entry->dp->exp);
            VLOG_DBG_RL(LOG_MODULE, &rl, "Writing bucket: %s.", b);
            free(b);
        }

        action_set_write_actions(p->action_set, bucket->actions_num, bucket->actions);

        entry->stats->byte_count += p->buffer->size;
        entry->stats->packet_count++;
        entry->stats->counters[b]->byte_count += p->buffer->size;
        entry->stats->counters[b]->packet_count++;
        /* Cookie field is set 0xffffffffffffffff
           because we cannot associate to any
           particular flow */
        action_set_execute(p->action_set, p, 0xffffffffffffffff);
        packet_destroy(p);
    } else {
        VLOG_DBG_RL(LOG_MODULE, &rl, "No bucket in group.");
    }
}
/* ************************************************** */
void tx(call_t *c, packet_t *packet) {
    struct nodedata *nodedata = get_node_private_data(c);
    array_t *down = get_entity_bindings_down(c);
    int i = down->size;
    
    /* radio sleep */
    if (nodedata->sleep) {
        packet_dealloc(packet);
        return;
    }

    /* radio activity */
    cs_init(c);
    nodedata->tx_busy = packet->id;

    /* log tx */
    PRINT_REPLAY("radio-tx0 %"PRId64" %d 50\n", get_time(), c->node);

    /* transmit to antenna */
    while (i--) {
        packet_t *packet_down;
        
        if (i > 0) {
            packet_down = packet_clone(packet);         
        } else {
            packet_down = packet;
        }
        c->from = down->elts[i];
        MEDIA_TX(c, packet_down);
    }

    return;
}
/* ************************************************** */
void rx(call_t *c, packet_t *packet) {
    struct nodedata *nodedata = get_node_private_data(c);
    array_t *up = get_entity_bindings_up(c);
    int i = up->size;
    struct routing_header *header = (struct routing_header *) 
        (packet->data + nodedata->overhead);

    /* Forward packet if node is not the recipient */
	if ((header->dst != BROADCAST_ADDR) && (header->dst != c->node) ) {
        forward(c, packet);
        return;
    }
        
    while (i--) {
        call_t c_up = {up->elts[i], c->node, c->entity};
        packet_t *packet_up;	     
        if (i > 0) {
            packet_up = packet_clone(packet);         
        } else {
            packet_up = packet;
        }

        RX(&c_up, packet_up);
    }

    return;
}
Пример #6
0
/* Executes a group entry of type ALL. */
static void
execute_all(struct group_entry *entry, struct packet *pkt) {
    size_t i;

    /* TODO Zoltan: Currently packets are always cloned. However it should
     * be possible to see if cloning is necessary, or not, based on bucket actions. */
    for (i=0; i<entry->desc->buckets_num; i++) {
        struct ofl_bucket *bucket = entry->desc->buckets[i];
        struct packet *p = packet_clone(pkt);

        if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) {
            char *b = ofl_structs_bucket_to_string(bucket, entry->dp->exp);
            VLOG_DBG_RL(LOG_MODULE, &rl, "Writing bucket: %s.", b);
            free(b);
        }

        action_set_write_actions(p->action_set, bucket->actions_num, bucket->actions);

        entry->stats->byte_count += p->buffer->size;
        entry->stats->packet_count++;
        entry->stats->counters[i]->byte_count += p->buffer->size;
        entry->stats->counters[i]->packet_count++;

        /* Cookie field is set 0xffffffffffffffff
           because we cannot associate to any
           particular flow */
        action_set_execute(p->action_set, p, 0xffffffffffffffff);

        packet_destroy(p);
    }
}
/* ************************************************** */
void rx(call_t *c, packet_t *packet) {
    struct nodedata *nodedata = get_node_private_data(c);
    array_t *up = get_entity_bindings_up(c);
    int i = up->size;

    /* radio sleep */
    if (nodedata->sleep) {
        packet_dealloc(packet);
        return;
    }

    /* half-duplex */
    if (nodedata->tx_busy != -1) {
        packet_dealloc(packet);
        return;
    }
    
    /* handle carrier sense */
    if (nodedata->rx_busy == packet->id) {
        nodedata->rx_busy = -1;
        nodedata->rxdBm   = MIN_DBM;
        /* log rx */
        PRINT_REPLAY("radio-rx1 %"PRId64" %d\n", get_time(), c->node);
        /* consume energy */
        battery_consume_rx(c, packet->duration);
    } else {
        packet_dealloc(packet);
        return;
    }

    /* check wether the reception has killed us */
    if (!is_node_alive(c->node)) {
        packet_dealloc(packet);
        return;
    }

    /* drop packet depending on the FER */
    if (get_random_double() < packet->PER) {
        packet_dealloc(packet);
        return;
    }    

    /* forward to upper layers */
    while (i--) {
        call_t c_up = {up->elts[i], c->node, c->entity};
        packet_t *packet_up;

        if (i > 0) {
            packet_up = packet_clone(packet);         
        } else {
            packet_up = packet;
        }
        RX(&c_up, packet_up);
    }

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

    /* delivers packet to application layer */
    if (n_hop == NULL) {
        array_t *up = get_entity_bindings_up(c);
        int i = up->size;
        
        while (i--) {
            call_t c_up = {up->elts[i], c->node, c->entity};
            packet_t *packet_up;
            
            if (i > 0) {
                packet_up = packet_clone(packet);         
            } else {
                packet_up = packet;
            }
            
            RX(&c_up, packet_up);
        }

        return;
    }
    
    /* update hop count */
    header->hop--;
    if (header->hop == 0) {
        nodedata->data_hop++;
        packet_dealloc(packet);
        return;
    }
    

    /* set mac header */
    destination.id = n_hop->id;
    destination.position.x = -1;
    destination.position.y = -1;
    destination.position.z = -1;
    if (SET_HEADER(&c0, packet, &destination) == -1) {
        packet_dealloc(packet);
        return;
    }
    
    /* forwarding packet */
    nodedata->data_tx++;
    TX(&c0, packet);
}
Пример #9
0
static packet_t wpk_clone(packet_t p){
	if(packet_type(p) == WPACKET){
		wpacket_t _w = (wpacket_t)p;
		wpacket_t w = (wpacket_t)CALLOC(g_wpk_allocator,1,sizeof(*w));//calloc(1,sizeof(*w));
		//w->writebuf = NULL;
		//w->len = NULL;
		packet_begpos(w) = packet_begpos(_w);
		packet_buf(w) = buffer_acquire(NULL,packet_buf(_w));
		//packet_next(w) = NULL;
		packet_type(w) = WPACKET;
		packet_datasize(w) = packet_datasize(_w);
		packet_clone(w) = wpk_clone;
		packet_makeforwrite(w) = wpk_clone;
		packet_makeforread(w) = wpk_makeforread;		
		return (packet_t)w;		
	}else
		return NULL;
}
Пример #10
0
void rx(call_t *c, packet_t *packet) {
    array_t *up = get_entity_bindings_up(c);
    int i = up->size;
    
    while (i--) {
        call_t c_up = {up->elts[i], c->node, c->entity};
        packet_t *packet_up;
        
        if (i > 0) {
            packet_up = packet_clone(packet);           
        } else {
            packet_up = packet;
        }
        RX(&c_up, packet_up);
    }
    
    return;
}
Пример #11
0
packet_t rpk_makeforwrite(packet_t p){
	if(packet_type(p) == RPACKET){
		rpacket_t r = (rpacket_t)p;
		wpacket_t w = (wpacket_t)CALLOC(g_wpk_allocator,1,sizeof(*w));//calloc(1,sizeof(*w));	
		//w->writebuf = NULL;
		//w->len = NULL;//触发拷贝之前len没有作用
		//w->wpos = 0;
		//packet_next(w) = NULL;
		packet_type(w) = WPACKET;
		packet_begpos(w) = packet_begpos(r);
		packet_buf(w) = buffer_acquire(NULL,packet_buf(r));
		packet_datasize(w) = kn_ntoh32(r->len) + sizeof(r->len);
		packet_clone(w) = wpk_clone;
		packet_makeforwrite(w) = wpk_clone;
		packet_makeforread(w) = wpk_makeforread;		
		return (packet_t)w;		
	}else
		return NULL;
}
Пример #12
0
int node_disconnect(struct node *node)
{
	int i, ret;
	struct device *dev;
	struct packet *pkt, *notify;
	struct daemon *daemon = node->daemon;

	log_error("%s: disconnect node %d\n", __func__, node->id);
	pkt = alloc_packet0();
	if (!pkt) {
		log_error("Error: %s alloc packet failed", __func__);
		return -ENOMEM;
	}
	pkt->type = P_KMOD_DISCONN;
	pkt->dev_id = MAX_DEVICES;
	pkt->node_from = node->id;
	pkt->kmod_from = INVALID_ID;	//FIXME 是否导入了不一致?
	pkt->node_to = daemon->local_node->id;

	for (i = 0; i < daemon->dev_list->dev_num; i++) {
		dev = daemon->dev_list->devs[i];
		if (!device_want_recv(dev))
			continue;
		notify = packet_clone(pkt);
		if (!notify) {
			log_error("alloc disconnect notify packet failed.");
			ret = -ENOMEM;
			goto out;
		}
		notify->kmod_to = (1 << dev->id);
		ret = dev_put_meta_packet(dev, notify);
		if (ret < 0) {
			log_error("Error: put meta packet failed.");
			goto out;
		}

	}
out:
	free_packet(pkt);
	return ret;

}
Пример #13
0
wpacket_t wpk_create(uint32_t size)
{
	size = size_of_pow2(size);
	if(size < 64) size = 64;
	wpacket_t w = (wpacket_t)CALLOC(g_wpk_allocator,1,sizeof(*w));//calloc(1,sizeof(*w));
	packet_buf(w) = buffer_create(size);
	w->writebuf = packet_buf(w);//buffer_acquire(NULL,packet_buf(w));
	//packet_begpos(w)= 0;
	//packet_next(w) = NULL;
	packet_type(w) = WPACKET;
	w->wpos = sizeof(*(w->len));
	w->len = (uint32_t*)packet_buf(w)->buf;
	*(w->len) = 0;
	packet_buf(w)->size = sizeof(*(w->len));
	packet_datasize(w) = sizeof(*(w->len));
	packet_clone(w) = wpk_clone;
	packet_makeforwrite(w) = wpk_clone;
	packet_makeforread(w) = wpk_makeforread;	
	return w;
}
Пример #14
0
wpacket_t wpk_create_by_bin(int8_t *addr,uint32_t size)
{	
	uint32_t datasize = size;
	size = size_of_pow2(size);
	if(size < 64) size = 64;
	wpacket_t w = (wpacket_t)CALLOC(g_wpk_allocator,1,sizeof(*w));//calloc(1,sizeof(*w));	
	packet_buf(w) = buffer_create(size);
	w->writebuf = packet_buf(w);//buffer_acquire(NULL,packet_buf(w));
	//packet_begpos(w)= 0;
	//packet_next(w) = NULL;
	packet_type(w) = WPACKET;
	memcpy(&w->writebuf->buf[0],addr,datasize);		
	w->len = (uint32_t*)packet_buf(w)->buf;
	w->wpos = datasize;
	packet_buf(w)->size = datasize;
	packet_datasize(w) = datasize;
	packet_clone(w) = wpk_clone;
	packet_makeforwrite(w) = wpk_clone;
	packet_makeforread(w) = wpk_makeforread;		
	return w;	
}
/* ************************************************** */
void rx(call_t *c, packet_t *packet) {
    struct nodedata *nodedata = get_node_private_data(c);
    array_t *up = get_entity_bindings_up(c);
    int i = up->size;
    struct routing_header *header = (struct routing_header *) (packet->data + nodedata->overhead);

    switch(header->type) {
    case HELLO_PACKET:         
        nodedata->hello_rx++;
        add_neighbor(c, header);
        packet_dealloc(packet);
        break;

    case DATA_PACKET : 
        nodedata->data_rx++;

	if ((header->dst != BROADCAST_ADDR) && (header->dst != c->node) ) {
            forward(c, packet);
            return;
        }
        
        while (i--) {
            call_t c_up = {up->elts[i], c->node, c->entity};
            packet_t *packet_up;	     
            if (i > 0) {
                packet_up = packet_clone(packet);         
            } else {
                packet_up = packet;
            }
            RX(&c_up, packet_up);
        }
        break;

    default : 
        break;       
    }

    return;
}
Пример #16
0
int packet_stream_process_packet(struct packet_stream *stream, struct packet *pkt, struct proto_process_stack *stack, unsigned int stack_index, uint32_t seq, uint32_t ack) {

	if (!stream || !pkt || !stack)
		return PROTO_ERR;

	debug_stream("thread %p, entry %p, packet %u.%06u, seq %u, ack %u : start", pthread_self(), stream, pkt->ts.tv_sec, pkt->ts.tv_usec, seq, ack);

	struct proto_process_stack *cur_stack = &stack[stack_index];
	int direction = cur_stack->direction;

	int must_wait = 0;

	pom_mutex_lock(&stream->wait_lock);

	int res = pthread_mutex_trylock(&stream->lock);
	if (res == EBUSY) {
		// Already locked, let's wait a bit
		must_wait = 1;
	} else if (res) {
		pomlog(POMLOG_ERR "Error while locking packet stream lock : %s", pom_strerror(errno));
		abort();
		return POM_ERR;
	} else {

		// We got the processing lock. But was it really this thread's turn ?

		struct packet_stream_thread_wait *tmp = stream->wait_list_head;
		// A thread with a packet preceding ours is waiting
		if (tmp && (tmp->ts.tv_sec < pkt->ts.tv_sec || (tmp->ts.tv_sec == pkt->ts.tv_sec && tmp->ts.tv_usec < pkt->ts.tv_usec))) {
			// No it wasn't, release it and signal the right thread
			must_wait = 2;
			pom_mutex_unlock(&stream->lock);
			debug_stream("thread %p, entry %p : signaling thread %p", pthread_self(), stream, stream->wait_list_head->thread);
			pthread_cond_broadcast(&stream->wait_list_head->cond);
		} else {
			// Yes it was. YAY !
			pom_mutex_unlock(&stream->wait_lock);
		}

	}


	if (must_wait) {

		// Add ourself in the waiting list
		struct packet_stream_thread_wait *lst = NULL;
		if (stream->wait_list_unused) {
			lst = stream->wait_list_unused;
			stream->wait_list_unused = lst->next;
			lst->next = NULL;
		} else {
			lst = malloc(sizeof(struct packet_stream_thread_wait));
			if (!lst) {
				pom_oom(sizeof(struct packet_stream_thread_wait));
				pom_mutex_unlock(&stream->wait_lock);
				return POM_ERR;
			}
			memset(lst, 0, sizeof(struct packet_stream_thread_wait));
			
			if (pthread_cond_init(&lst->cond, NULL)) {
				pomlog(POMLOG_ERR "Error while initializing wait list condition : %s", pom_strerror(errno));
				free(lst);
				return POM_ERR;
			}
		}
		memcpy(&lst->ts, &pkt->ts, sizeof(struct timeval));
		lst->thread = pthread_self();

		struct packet_stream_thread_wait *tmp;
		for (tmp = stream->wait_list_head; tmp && (tmp->ts.tv_sec < lst->ts.tv_sec || (tmp->ts.tv_sec == lst->ts.tv_sec && tmp->ts.tv_usec < lst->ts.tv_usec)); tmp = tmp->next);
		if (tmp) {

			lst->prev = tmp->prev;
			if (lst->prev)
				lst->prev->next = lst;
			else
				stream->wait_list_head = lst;

			lst->next = tmp;
			lst->next->prev = lst;
		} else {
			lst->prev = stream->wait_list_tail;
			if (lst->prev)
				lst->prev->next = lst;
			else
				stream->wait_list_head = lst;

			stream->wait_list_tail = lst;
		}


		while (1) {
			debug_stream("thread %p, entry %p, packet %u.%06u, seq %u, ack %u : waiting", pthread_self(), stream, pkt->ts.tv_sec, pkt->ts.tv_usec, seq, ack);
			if (pthread_cond_wait(&lst->cond, &stream->wait_lock)) {
				pomlog(POMLOG_ERR "Error while waiting for the packet stream wait cond : %s", pom_strerror(errno));
				abort();
				return POM_ERR;
			}

			if (stream->wait_list_head != lst) {
				// There is a small chance that another stream lock stream->wait_lock while pthread_cond_wait acquires it
				// If we are not the right thread, then simply signal the right one and wait again for our turn
				debug_stream("thread %p, entry %p, packet %u.%06u, seq %u, ack %u : wrong thread woke up", pthread_self(), stream, pkt->ts.tv_sec, pkt->ts.tv_usec, seq, ack);
				pthread_cond_broadcast(&stream->wait_list_head->cond);
				continue;
			}
			break;
		}

		tmp = stream->wait_list_head;
		stream->wait_list_head = tmp->next;
		if (stream->wait_list_head)
			stream->wait_list_head->prev = NULL;
		else
			stream->wait_list_tail = NULL;

		tmp->next = stream->wait_list_unused;
		tmp->prev = NULL;
		stream->wait_list_unused = tmp;

		pom_mutex_unlock(&stream->wait_lock);
		pom_mutex_lock(&stream->lock);

	}

	debug_stream("thread %p, entry %p, packet %u.%06u, seq %u, ack %u : start locked", pthread_self(), stream, pkt->ts.tv_sec, pkt->ts.tv_usec, seq, ack);

	// Update the stream flags
	if (stream->flags & PACKET_FLAG_STREAM_BIDIR) {

		// Update flags
		if (direction == POM_DIR_FWD && !(stream->flags & PACKET_FLAG_STREAM_GOT_FWD_DIR)) {
			stream->flags |= PACKET_FLAG_STREAM_GOT_FWD_DIR;
		} else if (direction == POM_DIR_REV && !(stream->flags & PACKET_FLAG_STREAM_GOT_REV_DIR)) {
			stream->flags |= PACKET_FLAG_STREAM_GOT_REV_DIR;
		}

	}

	// Put this packet in our struct packet_stream_pkt
	struct packet_stream_pkt spkt = {0};
	spkt.pkt = pkt;
	spkt.seq = seq;
	spkt.ack = ack;
	spkt.plen = cur_stack->plen;
	spkt.stack = stack;
	spkt.stack_index = stack_index;


	// Check if the packet is worth processing
	uint32_t cur_seq = stream->cur_seq[direction];
	if (cur_seq != seq) {
		if (packet_stream_is_packet_old_dupe(stream, &spkt, direction)) {
			// cur_seq is after the end of the packet, discard it
			packet_stream_end_process_packet(stream);
			debug_stream("thread %p, entry %p, packet %u.%06u, seq %u, ack %u : discard", pthread_self(), stream, pkt->ts.tv_sec, pkt->ts.tv_usec, seq, ack);
			return PROTO_OK;
		}

		if (packet_stream_remove_dupe_bytes(stream, &spkt, direction) == POM_ERR) {
			packet_stream_end_process_packet(stream);
			return PROTO_ERR;
		}
	}


	// Ok let's process it then

	// Check if it is the packet we're waiting for
	if (packet_stream_is_packet_next(stream, &spkt, direction)) {

		// Process it
		stream->cur_seq[direction] += cur_stack->plen;
		stream->cur_ack[direction] = ack;
		debug_stream("thread %p, entry %p, packet %u.%06u, seq %u, ack %u : process", pthread_self(), stream, pkt->ts.tv_sec, pkt->ts.tv_usec, seq, ack);

		int res = stream->handler(stream->ce, pkt, stack, stack_index);
		if (res == PROTO_ERR) {
			packet_stream_end_process_packet(stream);
			return PROTO_ERR;
		}

		// Check if additional packets can be processed
		struct packet_stream_pkt *p = NULL;
		unsigned int cur_dir = direction, additional_processed = 0;
		while ((p = packet_stream_get_next(stream, &cur_dir))) {


			debug_stream("thread %p, entry %p, packet %u.%06u, seq %u, ack %u : process additional", pthread_self(), stream, p->pkt->ts.tv_sec, p->pkt->ts.tv_usec, p->seq, p->ack);

			if (stream->handler(stream->ce, p->pkt, p->stack, p->stack_index) == POM_ERR) {
				packet_stream_end_process_packet(stream);
				return PROTO_ERR;
			}

			stream->cur_seq[cur_dir] += p->plen;
			stream->cur_ack[cur_dir] = p->ack;
	
			packet_stream_free_packet(p);

			additional_processed = 1;
		}

		if (additional_processed) {
			if (!stream->head[POM_DIR_FWD] && !stream->head[POM_DIR_REV])
				conntrack_timer_dequeue(stream->t);
			else
				conntrack_timer_queue(stream->t, stream->same_dir_timeout);
		}

		packet_stream_end_process_packet(stream);
		debug_stream("thread %p, entry %p, packet %u.%06u, seq %u, ack %u : done processed", pthread_self(), stream, pkt->ts.tv_sec, pkt->ts.tv_usec, seq, ack);
		return res;
	}

	// Queue the packet then

	debug_stream("thread %p, entry %p, packet %u.%06u, seq %u, ack %u : queue", pthread_self(), stream, pkt->ts.tv_sec, pkt->ts.tv_usec, seq, ack);

	struct packet_stream_pkt *p = malloc(sizeof(struct packet_stream_pkt));
	if (!p) {
		pom_oom(sizeof(struct packet_stream_pkt));
		packet_stream_end_process_packet(stream);
		return PROTO_ERR;
	}
	memset(p, 0 , sizeof(struct packet_stream_pkt));


	if (cur_stack->plen) {
		// No need to backup this if there is no payload
		p->pkt = packet_clone(pkt, stream->flags);
		if (!p->pkt) {
			packet_stream_end_process_packet(stream);
			free(p);
			return PROTO_ERR;
		}
		p->stack = core_stack_backup(stack, pkt, p->pkt);
		if (!p->stack) {
			packet_stream_end_process_packet(stream);
			packet_pool_release(p->pkt);
			free(p);
			return PROTO_ERR;
		}
	}


	p->plen = cur_stack->plen;
	p->seq = seq;
	p->ack = ack;
	p->stack_index = stack_index;


	if (!stream->tail[direction]) {
		stream->head[direction] = p;
		stream->tail[direction] = p;
	} else { 

		struct packet_stream_pkt *tmp = stream->tail[direction];
		while ( tmp && 
			((tmp->seq >= seq && tmp->seq - seq < PACKET_HALF_SEQ)
			|| (tmp->seq <= seq && seq - tmp->seq > PACKET_HALF_SEQ))) {

			tmp = tmp->prev;

		}

		if (!tmp) {
			// Packet goes at the begining of the list
			p->next = stream->head[direction];
			if (p->next)
				p->next->prev = p;
			else
				stream->tail[direction] = p;
			stream->head[direction] = p;

		} else {
			// Insert the packet after the current one
			p->next = tmp->next;
			p->prev = tmp;

			if (p->next)
				p->next->prev = p;
			else
				stream->tail[direction] = p;

			tmp->next = p;

		}
	}
	
	stream->cur_buff_size += cur_stack->plen;

	
	if (stream->cur_buff_size >= stream->max_buff_size) {
		// Buffer overflow
		debug_stream("thread %p, entry %p, packet %u.%06u, seq %u, ack %u : buffer overflow, forced dequeue", pthread_self(), stream, pkt->ts.tv_sec, pkt->ts.tv_usec, seq, ack);
		if (packet_stream_force_dequeue(stream) != POM_OK) {
			packet_stream_end_process_packet(stream);
			return POM_ERR;
		}

		if (stream->t)
			conntrack_timer_dequeue(stream->t);
	}

	// Add timeout
	if (stream->t && (stream->head[POM_DIR_FWD] || stream->head[POM_DIR_REV])) 
		conntrack_timer_queue(stream->t, stream->same_dir_timeout);
	packet_stream_end_process_packet(stream);

	debug_stream("thread %p, entry %p, packet %u.%06u, seq %u, ack %u : done queued", pthread_self(),  stream, pkt->ts.tv_sec, pkt->ts.tv_usec, seq, ack);
	return PROTO_OK;
}
Пример #17
0
/* 从对端 server 的 data 链路收到数据,把它放到对应的 kmod 节点中 */
void node_data_handler(evutil_socket_t fd, short event, void *args)
{
	struct node *node;
	struct daemon *daemon;
	struct device_list *dev_list;
	struct device *dev;
	struct packet *pkt;
	struct packet *pkt_clone;
	int i, ret, full;
	cb_fn *cb;

	node = (struct node *)args;
	daemon = node->daemon;
	dev_list = daemon->dev_list;

	pkt = handler_recv(node->dfd);
	if (!pkt) {
		node_del_data_event(node);
		log_error("receive data from server node %d failed", node->id);
		return;
	}

	/* FIXME 如果某个device的queue满了,在这里就会等待,从而造成两个问题:
	 *	1. 这是event的call back函数,如果等待会造成event base的阻塞
	 *	2. 单个device队列满而影响到所有其它device,不公平
	 * 是否可以这样?
	 *   提前获取队列一个空位,如果失败的话,直接返回,
	 *   当队列有剩余空间时再加入该event
	 * 但是,device互相影响的问题还是没能解决,满了直接断连?
	 */
	full = 0;
	for (i = 0; i < dev_list->dev_num; i++) {
		//FIXME 查找效率很低,可考虑序号对应下标,并且判读是否是只有单个device
		dev = dev_list->devs[i];
		if (!device_is_target(dev, pkt->kmod_to))
			continue;
		if (!device_want_recv(dev))
			continue;
		pkt_clone = packet_clone(pkt);
		if (!pkt_clone) {
			log_error("send to kmod node %d failed: no memory", dev->id);
			free_packet(pkt_clone);
			goto out;
		}
		cb = full ? NULL : node_data_handle_force_cb;
		ret = dev_put_data_packet_force(dev, pkt_clone, cb, node);
		if (ret < 0) {
			log_error("kmod node %d data queue is NOT start", dev->id);
			goto out;
		} else if (ret > 0) {
			log_info("%s force handle for node %d", __func__, node->id);
			full = 1;
		}
	}

out:
	free_packet(pkt);
	if (!full) {
		ret = event_add(node->data_event, NULL);
		if (ret < 0) {
			log_error("failed to add data event on node %d", node->id);
			node_del_data_event(node);
		}
	}
}
Пример #18
0
int packet_multipart_add_packet(struct packet_multipart *multipart, struct packet *pkt, size_t offset, size_t len, size_t pkt_buff_offset) {

    struct packet_multipart_pkt *tmp = multipart->tail;

    // Check where to add the packet

    while (tmp) {

        if (tmp->offset + tmp->len <= offset)
            break; // Packet is after is one

        if (tmp->offset == offset) {
            if (tmp->len != len)
                pomlog(POMLOG_WARN "Size missmatch for packet already in the buffer");
            return POM_OK;
        }

        tmp = tmp->prev;

    }

    struct packet_multipart_pkt *res = malloc(sizeof(struct packet_multipart_pkt));
    if (!res) {
        pom_oom(sizeof(struct packet_multipart_pkt));
        return POM_ERR;
    }
    memset(res, 0, sizeof(struct packet_multipart_pkt));

    res->offset = offset;
    res->pkt_buff_offset = pkt_buff_offset;
    res->len = len;


    // Copy the packet


    res->pkt = packet_clone(pkt, multipart->flags);
    if (!res->pkt) {
        free(res);
        return POM_ERR;
    }

    multipart->cur += len;

    if (tmp) {
        // Packet is after this one, add it

        res->prev = tmp;
        res->next = tmp->next;

        tmp->next = res;

        if (res->next) {
            res->next->prev = res;

            if ((res->next->offset == res->offset + res->len) &&
                    (res->prev->offset + res->prev->len == res->offset))
                // A gap was filled
                multipart->gaps--;
            else if ((res->next->offset > res->offset + res->len) &&
                     (res->prev->offset + res->prev->len < res->offset))
                // A gap was created
                multipart->gaps++;

        } else {

            if (tmp->offset + tmp->len < res->offset)
                multipart->gaps++;

            multipart->tail = res;
        }


        return POM_OK;
    } else {
        // Add it at the head
        res->next = multipart->head;
        if (res->next)
            res->next->prev = res;
        else
            multipart->tail = res;
        multipart->head = res;

        if (res->offset) {
            // There is a gap at the begining
            multipart->gaps++;
        } else if (res->next && res->len == res->next->offset) {
            // Gap filled
            multipart->gaps--;
        }
    }

    return POM_OK;
}
/* ************************************************** */
void rx(call_t *c, packet_t *packet) {
	if(!is_node_alive(c->node))
		return;
    struct nodedata *nodedata = get_node_private_data(c);
    struct protocoleData *entitydata = get_entity_private_data(c);
	
	array_t *up = get_entity_bindings_up(c);
	
    packet_PROTOCOLE *data = (packet_PROTOCOLE *) (packet->data + nodedata->overhead);
	
	switch(data->type)
	{	
		case HELLO:
		{
			//printf("BIP - Paquet de type HELLO recu par %d depuis %d\n", c->node, data->src);
			rx_hello(c,packet);
			break;
		}
		case HELLO2:
		{
			//printf("BIP - Paquet de type HELLO2 recu par %d depuis %d\n", c->node, data->src);
			rx_two_hop(c,packet);
			break;
		}
		case APP:
		{
			//printf("DLBIP - Paquet de type APP recu par %d depuis %d ; source : %d et destine a %d\n", c->node, data->pred, data->src, data->dst);
			nodedata->energiesRem[data->pred] = data->energyRem;
			if(nodedata->lastIDs[data->src] == data->id || data->src == c->node)
			{
				break;
			}
			else
			{
				nodedata->lastIDs[data->src] = data->id;
			}
			if(data->dst == BROADCAST_ADDR)
			{
				SHOW_GRAPH("G: %d %d\n",data->pred,c->node);
				double cout;
				listeNodes* trans = data->askedToRedirect;
				listeNodes* trans2 = data->needsToBeCovered;
				while(trans != 0)
				{
					position_t p1, p2;
					p1.x = trans->values.x;
					p1.y = trans->values.y;
					p1.z = trans->values.z;
					p2.x = trans2->values.x;
					p2.y = trans2->values.y;
					p2.z = trans2->values.z;
					cout = getCoutFromDistance(distance(&p1, &p2), entitydata->alpha, entitydata->c);
					//printf("cout estime de (%d,%d)\n", );
					nodedata->energiesRem[trans->values.node] -= cout;
					
					trans = trans->suiv;
					trans2 = trans2->suiv;
				}
				
				//SHOW_GRAPH("G: %d %d\n",data->pred,c->node);
				
				// faire remonter le paquet a la couche application
				call_t c_up = {up->elts[0], c->node, c->entity};
				RX(&c_up, packet_clone(packet));
				
				if(listeNodes_recherche(data->askedToRedirect, c->node)) // si le paquet contient des instructions pour ce noeud
				{
					forward(c, packet);
				}
			}
			else
			{
				printf("Message non broadcaste pas traite ... TODO\n");
			}
			
			//packet_dealloc(packet);
			break;
		}
		default:
			printf("%d a recu un packet de type %d NON reconnu\n", c->node, data->type);
			break;
	}
	
	/*printf("estimation de l'energie restante depuis %d :\n", c->node);
	int i;
	for(i = 0 ; i < get_node_count() ; i++)
	{
		printf("\t%d : %.1lf\n", i, nodedata->energiesRem[i]);
	}*/
}