static void push_message(MSG msg, size_t msgLength){
	if(queue_nitems(msg_queue) < MAX_MSG_QUEUE_SIZE){
		//printf("Pushing a message for %d with length %d\n", msg.dest, msgLength);
		queue_add(msg_queue, &msg, msgLength);
	}
	if(queue_nitems(msg_queue) == MAX_MSG_QUEUE_SIZE){
		CNET_disable_application(nodeinfo.address);
	}
	network_send();
}
void schedule_and_send(int link){
	if(links[link].timeout_occurred == false)
		return;

	//printf("QUEUE SIZES for link %d: %d(a) %d(s) %d(f)\n", link, queue_nitems(links[link].ack_sender), queue_nitems(links[link].sender), queue_nitems(links[link].forwarding_queue));
	//Send ack if it is there -- TOP PRIORITY
	if(queue_nitems(links[link].ack_sender) > 0){
		send_acks(link);
		return;
	}	

	//If ack queue is empty send packets from sender queue OR forwarding queue in priority basis
	if(queue_nitems(links[link].forwarding_queue) == 0 && queue_nitems(links[link].sender) > 0){
		send_frames(link);
	}
	else if (queue_nitems(links[link].forwarding_queue) > 0 && queue_nitems(links[link].sender) == 0){
		forward_frames(link);
	}
	else if (queue_nitems(links[link].forwarding_queue) == 0 && queue_nitems(links[link].sender) == 0){
		return;
	}
	else {
		links[link].packet_to_send = (links[link].packet_to_send + 1) % (PRIORITY + 1);
		//printf("packet to send is ----------------------------------------- %d\n", links[link].packet_to_send);
		//if(links[link].packet_to_send == PRIORITY)
		if(queue_nitems(links[link].forwarding_queue) > queue_nitems(links[link].sender))
		//send forwarding
			forward_frames(link);
		else
		//send normal
			send_frames(link);
	}
}
static bool extract_message(MSG *msg, int *length){
	size_t len;
	if(queue_nitems(msg_queue) == 0)
		return false;
	msg_ptr = (MSG*)(queue_remove(msg_queue, &len));
	msg->dest = msg_ptr->dest;
	memcpy(&msg->data[0], &msg_ptr->data[0], len - MESSAGE_HEADER_SIZE);	
	printf("AL : Message to be sent to %d | size %d\n", msg->dest, len - MESSAGE_HEADER_SIZE);
	if(!app_enabled && queue_nitems(msg_queue) < MAX_MSG_QUEUE_SIZE/2){
		CHECK(CNET_enable_application(ALLNODES));
		app_enabled = true;
	}
	*length = len - MESSAGE_HEADER_SIZE;
	return true;
}
void send_frames(int link){
	//printf("Send frames called for link : %d\n", link);
	size_t len = sizeof(FRAME);
	CnetTime timeout;
	FRAME *f = queue_remove(links[link].sender, &len);
	switch(f->payload.kind){
	case DL_DATA :
		if(!links[link].ack_received[f->payload.A]) {
			CHECK(CNET_write_physical(link, (char*)f, &len));
			timeout = (len*((CnetTime)8000000)/linkinfo[link].bandwidth + linkinfo[link].propagationdelay);
			start_timer(link, timeout);
			queue_add(links[link].sender, f, len);
		}
		else {
			if(queue_nitems(links[link].sender) > 0)
				send_frames(link);
		}
		break;
	case DL_ACK :
		CHECK(CNET_write_physical(link, (char*)f, &len));
                timeout = (len*((CnetTime)8000000)/linkinfo[link].bandwidth + linkinfo[link].propagationdelay);
                start_timer(link, timeout);
		break;
	case RT_DATA:
	//printf("RT packet sending on link : %d\n", link);
		CHECK(CNET_write_physical(link, (char*)f, &len));
                timeout = (len*((CnetTime)8000000)/linkinfo[link].bandwidth + linkinfo[link].propagationdelay);
                start_timer(link, timeout);
		break;
	}
	free(f);
}
Exemple #5
0
//-----------------------------------------------------------------------------
// flush a queue
void flush_datalink_queue(CnetEvent ev, CnetTimerID t1, CnetData data) {
    int current_link = (int) data;
    if (queue_nitems(output_queues[current_link]) > 0) {
        // take a first datalink frame
        size_t containter_len;
        DTG_CONTAINER * dtg_container = queue_remove(output_queues[current_link], &containter_len);

        // write datalink frame to the link
        DL_FRAME frame;
        size_t datagram_length = dtg_container->len;
        frame.checksum = dtg_container->checksum;
        memcpy(&frame.data, dtg_container->data, datagram_length);
        size_t frame_length = datagram_length + DL_FRAME_HEADER_SIZE;

        int link = dtg_container->link;
        CHECK(CNET_write_physical(link, (char *)&frame, &frame_length));

        //compute timeout for the link
        double bandwidth = linkinfo[link].bandwidth;
        CnetTime timeout = 1+8000005.0*(frame_length / bandwidth);
        datalink_timers[link] = CNET_start_timer(EV_DATALINK_FLUSH, timeout, current_link);
        free(dtg_container);
    } else {
        datalink_timers[current_link] = NULLTIMER;
    }
}
static EVENT_HANDLER(application_ready){
	MSG msg;
	size_t len = sizeof(MSG);
	CHECK(CNET_read_application(&msg.dest, &msg.data, &len));
	queue_add(msg_queue, &msg, len + MESSAGE_HEADER_SIZE);
	if(queue_nitems(msg_queue) == MAX_MSG_QUEUE_SIZE){
		CHECK(CNET_disable_application(ALLNODES));
		app_enabled = false;
	}
}
Exemple #7
0
//-----------------------------------------------------------------------------
void shutdown_datalink() {
    int packets[MAX_LINKS_COUNT];
    uint64_t memory_datalink = 0;
    for (int i = 1; i <= nodeinfo.nlinks; i++) {
        packets[i] = queue_nitems(output_queues[i]);
        while(queue_nitems(output_queues[i]) != 0) {
            size_t containter_len;
            DTG_CONTAINER * dtg_container = queue_remove(output_queues[i], &containter_len);
            memory_datalink += containter_len;
            free(dtg_container);
        }
    }

    fprintf(stderr, "\tdatalink memory: %f(MB)\n", (double)memory_datalink/(double)(1024*1024*8));

    for (int i = 1; i <= nodeinfo.nlinks; i++) {
        //fprintf(stderr, "\tlink %d - datalink queue: %d packets max: %lu\n", i, packets[i], output_max[i]);
        queue_free(output_queues[i]);
    }
}
Exemple #8
0
//-----------------------------------------------------------------------------
// write a frame to the link
void write_datalink(int link, char *datagram, uint32_t length) {
    DTG_CONTAINER container;
    container.len = length;
    container.link = link;
    container.checksum = CNET_ccitt((unsigned char *) datagram, (size_t)length);

    size_t datagram_length = length;
    memcpy(&container.data, datagram, datagram_length);

    // check if timer is null to avoid polling
    if (datalink_timers[link] == NULLTIMER) {
        CnetTime timeout_flush = 1;
        datalink_timers[link] = CNET_start_timer(EV_DATALINK_FLUSH, timeout_flush, link);
    }

    output_max[link] = max(output_max[link], queue_nitems(output_queues[link]));

    // add to the link queue
    if(queue_nitems(output_queues[link]) < 5000) {
        size_t container_length = DTG_CONTAINER_SIZE(container);
        queue_add(output_queues[link], &container, container_length);
    }
}
void network_send(){
	if(queue_nitems(msg_queue) == 0){
		CNET_start_timer(EV_TIMER0, 100000, 0);
                return; // do nothing	
	}
	//Fragment each message into a small unit and send along the link designated by the routing table
	size_t len = 0;
	next = queue_peek(msg_queue, &len);
	CnetAddr dest = next->dest;
	int dest_number = find_nodenumber(dest);
	//get link to send from the routing table
	int currLink = find_link(dest);
	//printf("Link to send is : %d\n", currLink);	
	if(queue_nitems(links[currLink].sender) > 0){
		//free(next);
		//printf("Some items in SENDER queue!\n");
		CNET_start_timer(EV_TIMER0, 100000, 0);
		return; // do nothing
	}
	//Remove the topmost message from the queue
	next = queue_remove(msg_queue, &len);
	links[currLink].msg_in_sender_Q = node_buffer[dest_number].mesg_seq_no_to_generate;
	//printf("Message is to be processed! To be sent to %d from %d and size %d and message number is %d\n", dest, nodeinfo.address, len, mesg_seq_no);
	//printf("Creating frames for message #%d\n", mesg_seq_no);	
	int int_len = len - MESSAGE_HEADER_SIZE;	
	char *data_ptr;
	data_ptr = &next->data[0];
	//printf("Message is to be processed! To be sent to %d from %d and size %d and message is %s.\n", dest, nodeinfo.address, len, data);
	//Enable application is message queue grows too small
	if(queue_nitems(msg_queue) < MAX_MSG_QUEUE_SIZE/2){
		application_enabled = true;
		CNET_enable_application(ALLNODES);
	}
	
	size_t frame_len = table[dest_number].min_mtu - FRAME_HEADER_SIZE;
	// removing the length occupied by the destination address in the MESSAGE	
	//printf("Min mtu - FRAME_HEADER_SIZE is  : %d Initial message size was %d, after removing dest part it is %d\n", frame_len, len, int_len);
	//queue packets up
	int seqno;
	for(seqno = 0; int_len > 0; seqno++){
		FRAME f;
		memset(&f.payload.data[0], '\0', MAX_MESSAGE_SIZE);
		f.payload.kind = DL_DATA;
		f.payload.source = nodeinfo.address;
		f.payload.dest = dest;
		f.payload.mesg_seq_no = node_buffer[dest_number].mesg_seq_no_to_generate;
		f.payload.len = (int_len < frame_len) ? int_len : frame_len;
		f.payload.flag_offset = (int_len <= frame_len) ? 1 : 0;
		getcurrtime(&f.payload.timestamp);
		f.payload.A = seqno;
		memcpy(&f.payload.data[0], data_ptr, f.payload.len);
	//printf("Length of frame to send is : %d and the payload is %s (before adding to queue)\n", strlen(f.payload.data) + FRAME_HEADER_SIZE, f.payload.data);	
		f.checksum = 0;
		f.checksum = CNET_ccitt((unsigned char *)&f, (int)(f.payload.len) + FRAME_HEADER_SIZE);
		len = f.payload.len + FRAME_HEADER_SIZE;
		queue_add(links[currLink].sender, &f, len);
		int_len = int_len - frame_len;
		data_ptr = data_ptr + frame_len;
	}
	printf("Message read from application layer destined for address %d | size %d | msg #%d | # frames %d \n", 
			dest, len - MESSAGE_HEADER_SIZE, node_buffer[dest_number].mesg_seq_no_to_generate, seqno);
	//printf("Created %d frames\n", seqno);
	node_buffer[dest_number].mesg_seq_no_to_generate++;
	for(int i = 0; i < seqno; i++)
		links[currLink].ack_received[i] = false;		
	schedule_and_send(currLink);
	CNET_start_timer(EV_TIMER0, 100000, 0);
}
void process_frames(){
	if(queue_nitems(receiver) == 0){
		return;
	}
	size_t len = 0;
	FRAME *f = queue_peek(receiver, &len);
	int source_nodenumber = find_nodenumber(f->payload.source);
	if(node_buffer[source_nodenumber].busy){
		free(f);
		return;
	}
	node_buffer[source_nodenumber].busy = true;
	f = queue_remove(receiver, &len);
	//printf("Received frames for message #%d Expecting %d\n", f->payload.mesg_seq_no, node_buffer[source_nodenumber].mesg_seq_no_to_receive);	
	//If ack has not been received at the sender side and an old frame from an old message has been received
	if(f->payload.mesg_seq_no < node_buffer[source_nodenumber].mesg_seq_no_to_receive){
		//printf("Message received is old, dropped :-( Message #%d\n", f->payload.mesg_seq_no);
		node_buffer[source_nodenumber].busy = false;
		free(f);
		process_frames();
		return;
	}
	if(f->payload.mesg_seq_no > node_buffer[source_nodenumber].mesg_seq_no_to_receive){
		queue_add(receiver, f, len);
		//printf("Message received is new, pushed back ;-) Message #%d\n", f->payload.mesg_seq_no);
		node_buffer[source_nodenumber].busy = false;
		free(f);
                //process_frames();
                return;
	}
	int seq_no = f->payload.A;
	char seq_str[5];
	sprintf(seq_str, "%d", seq_no);
	if(seq_no == node_buffer[source_nodenumber].next_seq_number_to_add){
		//send ack here
		create_ack(f->payload);
		// add to the incomplete data object
		//printf("Frame appending %d with length %d | MSG #%d\n",seq_no, f->payload.len, f->payload.mesg_seq_no);
		memcpy(&node_buffer[source_nodenumber].incomplete_data[0] + node_buffer[source_nodenumber].bytes_added, &f->payload.data[0], f->payload.len);
		node_buffer[source_nodenumber].bytes_added += f->payload.len;
		node_buffer[source_nodenumber].next_seq_number_to_add++;
		while(true){
			int next_seq = node_buffer[source_nodenumber].next_seq_number_to_add;
			char next_seq_str[5];
			sprintf(next_seq_str, "%d", next_seq);
			size_t plen;
			PACKET *pkt = hashtable_find(node_buffer[source_nodenumber].ooo_packets, next_seq_str, &plen);
			if(plen == 0)
				break;
			//printf("In While loop:Next frame %d found in HT\n",next_seq);
			pkt = hashtable_remove(node_buffer[source_nodenumber].ooo_packets, next_seq_str, &plen);
			create_ack(*pkt);
			memcpy(&node_buffer[source_nodenumber].incomplete_data[0] + node_buffer[source_nodenumber].bytes_added, &pkt->data, pkt->len);
			node_buffer[source_nodenumber].bytes_added += pkt->len;
			node_buffer[source_nodenumber].next_seq_number_to_add++;
		}
		// check for the last packet
		if(f->payload.flag_offset == 1) {
			//printf("\t\t\t\t\t\tBytes in reconstructed message is %d and is sent by %d\n",node_buffer[source_nodenumber].bytes_added, source_nodenumber);
			CHECK(CNET_write_application((char*)&node_buffer[source_nodenumber].incomplete_data[0], &node_buffer[source_nodenumber].bytes_added));
			node_buffer[source_nodenumber].next_seq_number_to_add = 0;
			memset(node_buffer[source_nodenumber].incomplete_data, '\0', MAX_MESSAGE_SIZE);
			hashtable_free(node_buffer[source_nodenumber].ooo_packets);
			// Overriding default bucket size of 1023
			node_buffer[source_nodenumber].ooo_packets = hashtable_new(256);
			printf("\t\t\t\t\t\tSuccessfully Written to Application. Bytes in the reconstructed message #%d are %d sent by %d.\n", 
				f->payload.mesg_seq_no, node_buffer[source_nodenumber].bytes_added, source_nodenumber);
			node_buffer[source_nodenumber].bytes_added = 0; 		
			node_buffer[source_nodenumber].mesg_seq_no_to_receive++; //= f->payload.mesg_seq_no;
		}
	} else {
		size_t plen;
		hashtable_find(node_buffer[source_nodenumber].ooo_packets, seq_str, &plen);
		if(plen == 0){
			hashtable_add(node_buffer[source_nodenumber].ooo_packets, seq_str, &f->payload, len - sizeof(uint32_t));
		}
	}
	node_buffer[source_nodenumber].busy = false;
	process_frames();
	free(f);
}