Пример #1
0
void process_arp_request( struct sr_instance *sr, const uint8_t *packet, unsigned int len, const char *interface)
{

	assert(sr);
	assert(packet);
	assert(interface);

	arp_hdr* arp = get_arp_hdr(packet, len);
	router_state *rs = get_router_state(sr);

	/* get interface list read lock */
	lock_if_list_rd(rs);

	/* scan the interface list
	 * match the requested ip
	 */
	node* n = get_router_state(sr)->if_list;
	while (n) {
		/* see if we have an interface matching the requested ip */
		if (((iface_entry*)n->data)->ip == arp->arp_tip.s_addr) {
			send_arp_reply(sr, packet, len, (iface_entry*)(n->data));
			break;
		}
		n = n->next;
	}

	/* release the interface list lock */
	unlock_if_list(rs);
}
Пример #2
0
/*
 * NOT THREAD SAFE! Lock cache rd, queue wr
 *
 *
 */
void send_queued_packets(struct sr_instance* sr, struct in_addr* dest_ip, char* dest_mac) {
	node* n = get_router_state(sr)->arp_queue;
	node* next = NULL;

	while (n) {
		next = n->next;

		arp_queue_entry* aqe = (arp_queue_entry*)n->data;

		/* match the arp reply sip to our entry next hop ip */
		if (dest_ip->s_addr == aqe->next_hop.s_addr) {
			node* cur_packet_node = aqe->head;
			node* next_packet_node = NULL;

			while (cur_packet_node) {
				next_packet_node = cur_packet_node->next;

				/* send the packet */
				arp_queue_packet_entry* aqpe = (arp_queue_packet_entry*)cur_packet_node->data;

				send_ip(sr, aqpe->packet, aqpe->len, &(aqe->next_hop), aqe->out_iface_name);
				node_remove(&(aqe->head), cur_packet_node);

				cur_packet_node = next_packet_node;
			}

			/* free the arp queue entry for this destination ip, and patch the list */
			node_remove(&(get_router_state(sr)->arp_queue), n);
		}

		n = next;
	}
}
Пример #3
0
void* arp_thread(void *param) {
	assert(param);
	struct sr_instance *sr = (struct sr_instance *)param;
	router_state *rs = get_router_state(sr);

	while (1) {
		lock_arp_cache_wr(rs);
		expire_arp_cache(sr);
		unlock_arp_cache(rs);

		lock_arp_cache_rd(rs);
		lock_arp_queue_wr(rs);
		lock_if_list_rd(rs);
		lock_rtable_rd(rs); /* because we may send an icmp packet back, requiring get next hop */

		process_arp_queue(sr);

		unlock_rtable(rs);
		unlock_if_list(rs);
		unlock_arp_queue(rs);
		unlock_arp_cache(rs);

		sleep(1);
	}
}
Пример #4
0
/* --- CCDN ,这个是真正的包处理函数,重点是判断mac包头的type字段,分ip包和arp包进行处理 */
void process_packet(struct sr_instance* sr, const uint8_t * packet, unsigned int len, const char* interface) {
  // uint8_t的定义:typedef unsigned char uint_8, interface应该是指进来的端口名,例如eth0之类的吧
	/*
	printf("\n--- Received Packet on iface: %s ---\n", interface);
	print_packet((uint8_t*)packet, len);
	printf("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\n");
	*/

	if (iface_is_active(get_router_state(sr), (char*)interface) == 0) {
		/* drop the packet */
		return;
	}

	/* REQUIRES */
	assert(sr);
	assert(packet);
	assert(interface);

	eth_hdr *ether_hdr = (eth_hdr *) packet;
	switch(ntohs(ether_hdr->eth_type)) {

		case ETH_TYPE_IP:
			printf(" ** -> Received IP packet of length %d\n", len);
			process_ip_packet(sr, packet, len, interface);
			break;

		case ETH_TYPE_ARP:
			printf(" ** -> Received ARP packet of length %d\n", len);
			process_arp_packet(sr, packet, len, interface);
			break;

		default: break;
	}

}
Пример #5
0
arp_cache_entry* get_from_arp_cache(struct sr_instance* sr, struct in_addr* next_hop) {

	assert(sr);
	assert(next_hop);

	return in_arp_cache(get_router_state(sr), next_hop);
}
Пример #6
0
void update_arp_queue(struct sr_instance* sr, arp_hdr* arp_header, const char* interface) {
	router_state* rs = get_router_state(sr);
	node* n = rs->arp_queue;
	node* next = NULL;

	while (n) {
		next = n->next;
		arp_queue_entry* aqe = (arp_queue_entry*)n->data;

		/* Does this arp reply match an entry waiting for it? */
		if (arp_header->arp_sip.s_addr == aqe->next_hop.s_addr) {
			/* send out the packets */
			node* cur_packet_node = aqe->head;
			node* next_packet_node = NULL;

			while (cur_packet_node) {
				next_packet_node = cur_packet_node->next;
				arp_queue_packet_entry* aqpe = (arp_queue_packet_entry*)cur_packet_node->data;

				/* send_ip takes responsibility for the packet so we don't need to free it */
				send_ip(sr, aqpe->packet, aqpe->len, &(aqe->next_hop), aqe->out_iface_name);

				node_remove(&(aqe->head), cur_packet_node);
				cur_packet_node = next_packet_node;
			}

			node_remove(&(rs->arp_queue), n);
		}
		n = next;
	}
}
Пример #7
0
void print_arp_queue(struct sr_instance *sr)
{
	assert(sr);

	printf("ARP QUEUE CONTENTS\n");
	printf("INTERFACE\tIP\t\tREQ_LEF\tHEAD\n");

	router_state *rs = get_router_state(sr);
	node *arp_walker = 0;
	arp_queue_entry *arp_entry = 0;

	arp_walker = rs->arp_queue;
	while(arp_walker)
	{

		arp_entry = (arp_queue_entry *)arp_walker->data;

		printf("%s\t\t", arp_entry->out_iface_name);
		char addr[INET_ADDRSTRLEN];
		printf("%-15s\t", inet_ntop(AF_INET, &(arp_entry->next_hop), addr, INET_ADDRSTRLEN));

		printf("%d\t%X\n", arp_entry->requests, (unsigned int)arp_walker->next);

		arp_walker = arp_walker->next;
	}
	printf("\n");

}
Пример #8
0
int netfpga_output(struct sr_instance* sr, uint8_t* packet, unsigned int len, const char* iface) {
	router_state* rs = get_router_state(sr);
	int written_length = 0;
	int i = 0;

	/* log the packet */
	pthread_mutex_lock(rs->log_dumper_mutex);
	sr_log_packet(sr, packet, len);
	pthread_mutex_unlock(rs->log_dumper_mutex);


	char* internal_names[4] = {"eth0", "eth1", "eth2", "eth3"};
	for (i = 0; i < 4; ++i) {
		if (strcmp(iface, internal_names[i]) == 0) {
			break;
		}
	}

	/* setup select */
	fd_set write_set;
	FD_ZERO(&write_set);

	while (written_length < len) {
		FD_SET(rs->raw_sockets[i], &write_set);

		struct timeval t;
		t.tv_sec = 0;
		t.tv_usec = 500; // timeout every half a millisecond

		if (select(rs->raw_sockets[i]+1, NULL, &write_set, NULL, NULL) < 0) {
			perror("select");
			exit(1);
		}

		if (FD_ISSET(rs->raw_sockets[i], &write_set)) {
			int w = 0;
			if ((w = write(rs->raw_sockets[i], packet+written_length, len-written_length)) == -1) {
				perror("write");
				exit(1);
			}
			written_length += w;
		}

	}



	/*
	if ((written_length = libnet_adv_write_link((libnet_t*)rs->libnet_context[i], packet, len)) != len) {
		printf("Error writing packet using libnet, expected length: %i returned length: %i\n", len, written_length);
	}
	*/
	return 0;
}
Пример #9
0
/*初始化路由器列表,包括每个路由器的编号、距离之类的(搭拓扑的时候可能要用)*/
void init_router_list(struct sr_instance* sr){

	assert(sr);
	router_state *rs = get_router_state(sr);

	/* build an entry for our router */
	pwospf_router *our_router = (pwospf_router *)calloc(1, sizeof(pwospf_router));
	our_router->router_id = rs->router_id;
	our_router->area_id = rs->area_id;
	our_router->seq = 0;
	our_router->distance = 0;
	our_router->shortest_path_found = 0;
	time(&our_router->last_update);


	/* insert our_router in the pwospf router list */
	assert(rs->pwospf_router_list == NULL);
	node *n = node_create();
	n->data = (void *)our_router;
	rs->pwospf_router_list = n;


	/* advertise what's directly connected to us */
	node *il_walker = rs->if_list;
	while(il_walker) {
		iface_entry *ie = (iface_entry *)il_walker->data;

		pwospf_interface *pi = (pwospf_interface *)calloc(1, sizeof(pwospf_interface));
		pi->subnet.s_addr = (ie->ip & ie->mask);
		pi->mask.s_addr = ie->mask;
		pi->router_id = 0;
		pi->is_active = 0;

		node *rl_entry = node_create();
		rl_entry->data = (void *)pi;
		if(our_router->interface_list == NULL) {
			our_router->interface_list = rl_entry;
		}
		else {
			node_push_back(our_router->interface_list, rl_entry);
		}

		il_walker = il_walker->next;
	}


	//char *str; int len;
	//sprint_pwospf_router_list(rs, &str, &len);
	//printf("\nINITIAL ROUTER LIST:\n\n%s\n\n", str);
}
Пример #10
0
/*
 * THIS FUNCTION IS NOT THREAD SAFE
 * Lock the ARP Queue before using it
 */
arp_queue_entry* get_from_arp_queue(struct sr_instance* sr, struct in_addr* next_hop) {
	router_state* rs = get_router_state(sr);
	node* n = rs->arp_queue;

	while (n) {
		arp_queue_entry* aqe = (arp_queue_entry*)n->data;
		if (aqe->next_hop.s_addr == next_hop->s_addr) {
			return aqe;
		}

		n = n->next;
	}

	return NULL;
}
Пример #11
0
void netfpga_input(struct sr_instance* sr) {
	router_state* rs = get_router_state(sr);
	int i;
	char* internal_names[4] = {"eth0", "eth1", "eth2", "eth3"};

	/* setup select */
	fd_set read_set;
	FD_ZERO(&read_set);
	int READ_BUF_SIZE = 16384;
	unsigned char readBuf[READ_BUF_SIZE];

	while (1) {
		for (i = 0; i < 4; ++i) {
			FD_SET(rs->raw_sockets[i], &read_set);
		}

		struct timeval t;
		t.tv_usec = 500; // timeout every half a millisecond

		if (select(getMax(rs->raw_sockets, 4)+1, &read_set, NULL, NULL, NULL) < 0) {
			perror("select");
			exit(1);
		}

		for (i = 0; i < 4; ++i) {
			if (FD_ISSET(rs->raw_sockets[i], &read_set)) {
				// assume each read is a full packet
				int read_bytes = read(rs->raw_sockets[i], readBuf, READ_BUF_SIZE);

				/* log packet */
				pthread_mutex_lock(rs->log_dumper_mutex);
				sr_log_packet(sr, (unsigned char*)readBuf, read_bytes);
				pthread_mutex_unlock(rs->log_dumper_mutex);

				/* send packet */
				sr_integ_input(sr, readBuf, read_bytes, internal_names[i]);
			}
		}

	}

}
Пример #12
0
/*
 * NOT THREAD SAFE
 * Returns: # of deleted arp cache entries (should only be 1)
 */
int del_arp_cache(struct sr_instance* sr, struct in_addr* ip) {
	router_state* rs = get_router_state(sr);
	node* cur = rs->arp_cache;
	node* next = NULL;
	int retval = 0;

	while (cur) {
		next = cur->next;
		arp_cache_entry* entry = (arp_cache_entry*)cur->data;

		if (entry->ip.s_addr == ip->s_addr) {
			node_remove(&(rs->arp_cache), cur);
			++retval;
		}

		cur = next;
	}

	return retval;
}
Пример #13
0
/* --- CCDN,比较重要 发包函数,输入packet,然后把packet发出去 */
int send_packet(struct sr_instance* sr, uint8_t* packet, unsigned int len, const char* iface) {
	router_state* rs = get_router_state(sr);
	if (pthread_mutex_lock(rs->write_lock) != 0) {
		perror("Failure locking write lock\n");
		exit(1);
	}

	int result;

	if (len < 60) {
		int pad_len = 60 - len;
		uint8_t* pad_packet = (uint8_t*)malloc (len + pad_len);
		if (!pad_packet) {
		  perror("Failed to malloc in send_packet().\n");
		  exit(1);
		}

		bzero(pad_packet, len+pad_len);
		memmove(pad_packet, packet, len);

		printf(" ** <- Sending packet of size %u out iface: %s\n", len+pad_len, iface);

		result=sr_integ_low_level_output(sr, pad_packet, len+pad_len, iface);

		free(pad_packet);
	} else {
		printf(" ** <- Sending packet of size %u out iface: %s\n", len, iface);
		result = sr_integ_low_level_output(sr, packet, len, iface);
	}

	/*
	print_packet(packet, len);
	*/

	if (pthread_mutex_unlock(rs->write_lock) != 0) {
		perror("Failure unlocking write lock\n");
		exit(1);
	}

	return result;
}
Пример #14
0
void print_sping_queue(struct sr_instance *sr)
{
	assert(sr);

	printf("\n\n*******\nSPING QUEUE CONTENTS\n");
	router_state *rs = get_router_state(sr);
	node *sping_walker = 0;
	sping_queue_entry *ae = 0;

	sping_walker = rs->sping_queue;
	while(sping_walker)
	{
		ae = (sping_queue_entry *)sping_walker->data;
		uint8_t *data =(uint8_t*) get_icmp_hdr(ae->packet, ae->len);
		data = data+sizeof(icmp_hdr);
		unsigned short *id = (unsigned short *)data;
		printf("%X\n", *id);

		sping_walker = sping_walker->next;
	}
}
Пример #15
0
void process_arp_reply( struct sr_instance *sr, const uint8_t *packet, unsigned int len, const char *interface)
{

	assert(sr);
	assert(packet);
	assert(interface);

	router_state *rs = get_router_state(sr);

	/* update the arp cache */
	arp_hdr *arp = get_arp_hdr(packet, len);

	lock_arp_cache_wr(rs);
	update_arp_cache(sr, &(arp->arp_sip), arp->arp_sha, 0);
	unlock_arp_cache(rs);

	lock_arp_cache_rd(rs);
	lock_arp_queue_wr(rs);
	send_queued_packets(sr, &(arp->arp_sip), arp->arp_sha);
	unlock_arp_queue(rs);
	unlock_arp_cache(rs);
}
Пример #16
0
void arp_queue_add(struct sr_instance* sr, uint8_t* packet, unsigned int len, const char* out_iface_name, struct in_addr *next_hop)
{
	assert(sr);
	assert(packet);
	assert(out_iface_name);
	assert(next_hop);

	router_state *rs = get_router_state(sr);

	/* Is there an existing queue entry for this IP? */
	arp_queue_entry* aqe = get_from_arp_queue(sr, next_hop);
	if (!aqe) {
		/* create a new queue entry */
		aqe = (arp_queue_entry*)malloc(sizeof(arp_queue_entry));
		bzero(aqe, sizeof(arp_queue_entry));
		memcpy(aqe->out_iface_name, out_iface_name, IF_LEN);
		aqe->next_hop = *next_hop;

		/* send a request */
		time(&(aqe->last_req_time));
		aqe->requests = 1;
		send_arp_request(sr, next_hop->s_addr, out_iface_name);

		arp_queue_entry_add_packet(aqe, packet, len);

		/* create a node, add this entry to the node, and push it into our linked list */
		node* n = node_create();
		n->data = aqe;

		if (rs->arp_queue == NULL) {
			rs->arp_queue = n;
		} else {
			node_push_back(rs->arp_queue, n);
		}
	} else {
		/* entry exists, just add the packet */
		arp_queue_entry_add_packet(aqe, packet, len);
	}
}
Пример #17
0
/* cli命令做成了一个list,写了一大堆的cli命令进去,包括ip表的add和del */
void init_cli(struct sr_instance* sr) {
	router_state* rs = get_router_state(sr);

	if(pthread_rwlock_wrlock(rs->cli_commands_lock) != 0) {
		perror("Failure getting CLI commands write lock");
	}


	/* CLI: help ... */
	register_cli_command(&(rs->cli_commands), "help", &cli_help);
	register_cli_command(&(rs->cli_commands), "?", &cli_help);


	/* CLI: show ... */
	register_cli_command(&(rs->cli_commands), "show ?", &cli_show_help);

	/* CLI: show vns ... */
	register_cli_command(&(rs->cli_commands), "show vns ?", &cli_show_vns_help);
	register_cli_command(&(rs->cli_commands), "show vns", &cli_show_vns);
	register_cli_command(&(rs->cli_commands), "show vns user", &cli_show_vns_user);
	register_cli_command(&(rs->cli_commands), "show vns user ?", &cli_show_vns_user_help);
	register_cli_command(&(rs->cli_commands), "show vns lhost", &cli_show_vns_lhost);
	register_cli_command(&(rs->cli_commands), "show vns lhost ?", &cli_show_vns_lhost_help);
	register_cli_command(&(rs->cli_commands), "show vns vhost", &cli_show_vns_vhost);
	register_cli_command(&(rs->cli_commands), "show vns vhost ?", &cli_show_vns_vhost_help);
	register_cli_command(&(rs->cli_commands), "show vns server", &cli_show_vns_server);
	register_cli_command(&(rs->cli_commands), "show vns server ?", &cli_show_vns_server_help);
	register_cli_command(&(rs->cli_commands), "show vns topology", &cli_show_vns_topology);
	register_cli_command(&(rs->cli_commands), "show vns topology ?", &cli_show_vns_topology_help);


	/* CLI: show ip ... */
	register_cli_command(&(rs->cli_commands), "show ip", &cli_show_ip_help);
	register_cli_command(&(rs->cli_commands), "show ip ?", &cli_show_ip_help);
	register_cli_command(&(rs->cli_commands), "show ip arp", &cli_show_ip_arp);
	register_cli_command(&(rs->cli_commands), "show ip arp ?", &cli_show_ip_arp_help);
	register_cli_command(&(rs->cli_commands), "show ip interface", &cli_show_ip_iface);
	register_cli_command(&(rs->cli_commands), "show ip interface ?", &cli_show_ip_iface_help);
	register_cli_command(&(rs->cli_commands), "show ip route", &cli_show_ip_rtable);
	register_cli_command(&(rs->cli_commands), "show ip route ?", &cli_show_ip_rtable_help);


	/* CLI: ip ... */
	register_cli_command(&(rs->cli_commands), "ip ?", &cli_ip_help);


	/* CLI: ip route ... */
	register_cli_command(&(rs->cli_commands), "ip route ?", &cli_ip_route_help);
	register_cli_command(&(rs->cli_commands), "ip route add", &cli_ip_route_add);
	register_cli_command(&(rs->cli_commands), "ip route add ?", &cli_ip_route_add_help);
	register_cli_command(&(rs->cli_commands), "ip route del", &cli_ip_route_del);
	register_cli_command(&(rs->cli_commands), "ip route del ?", &cli_ip_route_del_help);

	/* CLI: ip interface ... */
	register_cli_command(&(rs->cli_commands), "ip interface ?", &cli_ip_interface_help);
	register_cli_command(&(rs->cli_commands), "ip interface", &cli_ip_interface);


	/* CLI: ip arp ... */
	register_cli_command(&(rs->cli_commands), "ip arp ?", &cli_ip_arp_help);
	register_cli_command(&(rs->cli_commands), "ip arp add", &cli_ip_arp_add);
	register_cli_command(&(rs->cli_commands), "ip arp add ?", &cli_ip_arp_add_help);
	register_cli_command(&(rs->cli_commands), "ip arp del", &cli_ip_arp_del);
	register_cli_command(&(rs->cli_commands), "ip arp del ?", &cli_ip_arp_del_help);
	register_cli_command(&(rs->cli_commands), "ip arp set ttl", &cli_ip_arp_set_ttl);


	/* CLI: sping ... */
	register_cli_command(&(rs->cli_commands), "sping", &cli_sping);
	register_cli_command(&(rs->cli_commands), "sping ?", &cli_sping_help);


	/* CLI: pwospf ... */
	register_cli_command(&(rs->cli_commands), "pwospf ?", &cli_pwospf_help);
	register_cli_command(&(rs->cli_commands), "show pwospf iface", &cli_show_pwospf_iface);
	register_cli_command(&(rs->cli_commands), "show pwospf iface ?", &cli_show_pwospf_iface_help);
	register_cli_command(&(rs->cli_commands), "show pwospf router", &cli_show_pwospf_router_list);
	register_cli_command(&(rs->cli_commands), "show pwospf info", &cli_show_pwospf_info);
	register_cli_command(&(rs->cli_commands), "set aid", &cli_pwospf_set_aid);
	register_cli_command(&(rs->cli_commands), "set aid ?", &cli_pwospf_set_aid_help);
	register_cli_command(&(rs->cli_commands), "set hello interval", &cli_pwospf_set_hello);
	register_cli_command(&(rs->cli_commands), "set lsu broadcast", &cli_pwospf_set_lsu_broadcast);
	register_cli_command(&(rs->cli_commands), "set lsu interval", &cli_pwospf_set_lsu_interval);
	register_cli_command(&(rs->cli_commands), "send hello", &cli_pwospf_send_hello);
	register_cli_command(&(rs->cli_commands), "send lsu", &cli_pwospf_send_lsu);


	/* CLI: hw ... */
	register_cli_command(&(rs->cli_commands), "hw info", &cli_hw_info);
	register_cli_command(&(rs->cli_commands), "hw ?", &cli_hw_help);
	register_cli_command(&(rs->cli_commands), "show hw rtable", &cli_show_hw_rtable);
	register_cli_command(&(rs->cli_commands), "show hw arp", &cli_show_hw_arp_cache);
	register_cli_command(&(rs->cli_commands), "nuke arp", &cli_nuke_arp_cache);
	register_cli_command(&(rs->cli_commands), "nuke hw arp", &cli_nuke_hw_arp_cache_entry);
	register_cli_command(&(rs->cli_commands), "show hw iface", &cli_show_hw_interface);
	register_cli_command(&(rs->cli_commands), "hw iface add", &cli_hw_interface_add);
	register_cli_command(&(rs->cli_commands), "hw iface del", &cli_hw_interface_del);
	register_cli_command(&(rs->cli_commands), "hw iface", &cli_hw_interface_set);
	register_cli_command(&(rs->cli_commands), "hw arp miss", &cli_hw_arp_cache_misses);
	register_cli_command(&(rs->cli_commands), "hw pckts fwd", &cli_hw_num_pckts_fwd);

	/* CLI: nat ... */
	/*
	register_cli_command(&(rs->cli_commands), "nat ?", &cli_nat_help);
	register_cli_command(&(rs->cli_commands), "show nat table", &cli_show_nat_table);
	register_cli_command(&(rs->cli_commands), "nat set", &cli_nat_set);
	register_cli_command(&(rs->cli_commands), "nat reset", &cli_nat_reset);
	register_cli_command(&(rs->cli_commands), "nat test", &cli_nat_test);
	register_cli_command(&(rs->cli_commands), "nat add", &cli_nat_add);
	register_cli_command(&(rs->cli_commands), "nat del", &cli_nat_del);
	register_cli_command(&(rs->cli_commands), "show hw nat table", &cli_show_hw_nat_table);
	*/

	/* bubble sort command list */
	int swapped = 0;
	do {
		swapped = 0;
		node* cur = rs->cli_commands;
		while (cur && cur->next) {
			cli_entry* a = (cli_entry*)cur->data;
			cli_entry* b = (cli_entry*)cur->next->data;
			if (strcmp(a->command, b->command) == 1) {
				cur->data = b;
				cur->next->data = a;
				swapped = 1;
			}

			cur = cur->next;
		}
	} while (swapped);



	if(pthread_rwlock_unlock(rs->cli_commands_lock) != 0) {
		perror("Failure unlocking CLI commands lock");
	}
}
Пример #18
0
void init(struct sr_instance* sr)
{
    unsigned int iseed = (unsigned int)time(NULL);
    srand(iseed+1);

    router_state* rs = (router_state*)malloc(sizeof(router_state));//router_state,一个结构体,在or_data_types.h定义
    assert(rs);
    bzero(rs, sizeof(router_state));
    rs->sr = sr;

	#ifdef _CPUMODE_
    init_rawsockets(rs);
	#endif


    /** INITIALIZE LOCKS **/
    rs->write_lock = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
    if (pthread_mutex_init(rs->write_lock, NULL) != 0) {
    	perror("Lock init error");
    	exit(1);
    }

    rs->arp_cache_lock = (pthread_rwlock_t*)malloc(sizeof(pthread_rwlock_t));
    if (pthread_rwlock_init(rs->arp_cache_lock, NULL) != 0) {
    	perror("Lock init error");
    	exit(1);
    }

    rs->arp_queue_lock = (pthread_rwlock_t*)malloc(sizeof(pthread_rwlock_t));
    if (pthread_rwlock_init(rs->arp_queue_lock, NULL) != 0) {
    	perror("Lock init error");
    	exit(1);
    }

    rs->if_list_lock = (pthread_rwlock_t*)malloc(sizeof(pthread_rwlock_t));
    if (pthread_rwlock_init(rs->if_list_lock, NULL) != 0) {
    	perror("Lock init error");
    	exit(1);
    }

    rs->rtable_lock = (pthread_rwlock_t*)malloc(sizeof(pthread_rwlock_t));
    if (pthread_rwlock_init(rs->rtable_lock, NULL) != 0) {
    	perror("Lock init error");
    	exit(1);
    }

    // --- CCDN lock
    rs->ctable_lock = (pthread_rwlock_t*)malloc(sizeof(pthread_rwlock_t));
    if (pthread_rwlock_init(rs->ctable_lock, NULL) != 0) {
    	perror("Lock init error");
    	exit(1);
    }

    rs->cli_commands_lock = (pthread_rwlock_t*)malloc(sizeof(pthread_rwlock_t));
    if (pthread_rwlock_init(rs->cli_commands_lock, NULL) != 0) {
    	perror("Lock init error");
    	exit(1);
    }

    rs->nat_table_mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
    if (pthread_mutex_init(rs->nat_table_mutex, NULL) != 0) {
    	perror("Mutex init error");
    	exit(1);
    }

    rs->nat_table_cond = (pthread_cond_t*)malloc(sizeof(pthread_cond_t));
    if (pthread_cond_init(rs->nat_table_cond, NULL) != 0) {
			perror("Nat Table cond init error");
			exit(1);
    }

    rs->local_ip_filter_list_mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
    if (pthread_mutex_init(rs->local_ip_filter_list_mutex, NULL) != 0) {
			perror("Local IP Filter Mutex init error");
			exit(1);
    }

    rs->log_dumper_mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
    if (pthread_mutex_init(rs->log_dumper_mutex, NULL) != 0) {
			perror("Log dumper mutex init error");
			exit(1);
    }

    rs->sr = sr;
		rs->area_id = PWOSPF_AREA_ID;
		rs->pwospf_hello_interval = PWOSPF_NEIGHBOR_TIMEOUT;
		rs->pwospf_lsu_interval = PWOSPF_LSUINT;
		rs->pwospf_lsu_broadcast = 1;
		rs->arp_ttl = INITIAL_ARP_TIMEOUT;
		rs->nat_timeout = 120;

		/* clear stats */
		int i, j;
		for (i = 0; i < 8; ++i) {
			for (j = 0; j < 4; ++j) {
				rs->stats_last[i][j] = 0;
			}
			for (j = 0; j < 2; ++j) {
				rs->stats_avg[i][j] = 0.0;
			}
		}
		rs->stats_last_time.tv_sec = 0;
		rs->stats_last_time.tv_usec = 0;

		#ifdef _CPUMODE_
			rs->is_netfpga = 1;
			char* name = (char*)calloc(1, 32);
			strncpy(name, sr->interface, 32);
			rs->netfpga.device_name = name;
			rs->netfpga.fd = 0;
			rs->netfpga.net_iface = 0;

			if (check_iface(&(rs->netfpga))) {
				printf("Failure connecting to NETFPGA\n");
				exit(1);
			}

			if (openDescriptor(&(rs->netfpga))) {
				printf("Failure connecting to NETFPGA\n");
				exit(1);
			}

			/* initialize the hardware */
			init_hardware(rs);

		#else
			rs->is_netfpga = 0;
		#endif

		if (rs->is_netfpga) {
			/* Add 224.0.0.5 as a local IP Filter */
			struct in_addr ip;
			inet_pton(AF_INET, "224.0.0.5", &ip);
			add_local_ip_filter(rs, &ip, "pwospf");
		}


    /* Initialize SPING data */
    rs->sping_mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
    if (pthread_mutex_init(rs->sping_mutex, NULL) != 0) {
	perror("Sping mutex init error");
    	exit(1);
    }

    rs->sping_cond = (pthread_cond_t*)malloc(sizeof(pthread_cond_t));
    if (pthread_cond_init(rs->sping_cond, NULL) != 0) {
			perror("Sping cond init error");
			exit(1);
    }

    /* Initialize LSU data */
    rs->pwospf_router_list_lock = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
    if (pthread_mutex_init(rs->pwospf_router_list_lock, NULL) != 0) {
			perror("Routing list mutex init error");
    	exit(1);
    }

    rs->pwospf_lsu_bcast_mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
    if (pthread_mutex_init(rs->pwospf_lsu_bcast_mutex, NULL) != 0) {
			perror("LSU bcast mutex init error");
    	exit(1);
    }

    rs->pwospf_lsu_bcast_cond = (pthread_cond_t*)malloc(sizeof(pthread_cond_t));
    if (pthread_cond_init(rs->pwospf_lsu_bcast_cond, NULL) != 0) {
			perror("LSU bcast cond init error");
			exit(1);
    }

    rs->pwospf_lsu_queue_lock = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
    if (pthread_mutex_init(rs->pwospf_lsu_queue_lock, NULL) != 0) {
			perror("Lsu queue mutex init error");
    	exit(1);
    }


    /* Initialize PWOSPF Dijkstra Thread Mutex/Cond Var */
    rs->dijkstra_mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
    if (pthread_mutex_init(rs->dijkstra_mutex, NULL) != 0) {
			perror("Dijkstra mutex init error");
    	exit(1);
    }

    rs->dijkstra_cond = (pthread_cond_t*)malloc(sizeof(pthread_cond_t));
    if (pthread_cond_init(rs->dijkstra_cond, NULL) != 0) {
			perror("Dijkstra cond init error");
			exit(1);
    }

    /* Initialize WWW Mutex/Cond Var */
    rs->www_mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
    if (pthread_mutex_init(rs->www_mutex, NULL) != 0) {
			perror("WWW mutex init error");
    	exit(1);
    }

    rs->www_cond = (pthread_cond_t*)malloc(sizeof(pthread_cond_t));
    if (pthread_cond_init(rs->www_cond, NULL) != 0) {
			perror("WWW cond init error");
			exit(1);
    }

    /* Initialize Stats Mutex */
    rs->stats_mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
    if (pthread_mutex_init(rs->stats_mutex, NULL) != 0) {
			perror("Stats mutex init error");
    	exit(1);
    }

    // --- CCDN , sr里面有一个指针是sr->interface_subsystem = rs,而main函数的最前面,rs->sr=sr
    sr_set_subsystem(sr, (void*)rs);

    // --- CCDN , pthread_create用于创建一个线程,第一个参数返回线程id,第二个设置线程属性(NULL表默认),第三个指向线程调用的函数,第四个传递参数
    /** SPAWN THE ARP QUEUE THREAD **/
    rs->arp_thread = (pthread_t*)malloc(sizeof(pthread_t));

    if(pthread_create(rs->arp_thread, NULL, arp_thread, (void *)sr) != 0) {
	    perror("Thread create error");
    }


    /** SPAWN THE PWOSPF HELLO BROADCAST THREAD **/
    rs->pwospf_hello_thread = (pthread_t*)malloc(sizeof(pthread_t));
    if(pthread_create(rs->pwospf_hello_thread, NULL, pwospf_hello_thread, (void *)sr) != 0) {
		perror("Thread create error");
    }


    /** SPAWN THE PWOSPF LSU BROADCAST THREAD **/
    rs->pwospf_lsu_thread = (pthread_t*)malloc(sizeof(pthread_t));
    if(pthread_create(rs->pwospf_lsu_thread, NULL, pwospf_lsu_thread, (void *)sr) != 0) {
	    perror("Thread create error");
    }


    /** SPAWN THE PWOSPF LSU BCAST TIMEOUT THREAD **/
    rs->pwospf_lsu_timeout_thread = (pthread_t*)malloc(sizeof(pthread_t));
    if(pthread_create(rs->pwospf_lsu_timeout_thread, NULL, pwospf_lsu_timeout_thread, (void*)sr) != 0) {
	    perror("Thread create error");
    }

    /** SPAWN THE DIJKSTRA THREAD **/
    rs->pwospf_dijkstra_thread = (pthread_t*)malloc(sizeof(pthread_t));
    if(pthread_create(rs->pwospf_dijkstra_thread, NULL, dijkstra_thread, (void*)get_router_state(sr)) != 0) {
	    perror("Thread create error");
    }


    /** SPAWN THE PWOSPF LSU BCAST THREAD **/
    rs->pwospf_lsu_bcast_thread = (pthread_t*)malloc(sizeof(pthread_t));
    if(pthread_create(rs->pwospf_lsu_bcast_thread, NULL, pwospf_lsu_bcast_thread, (void*)sr) != 0) {
	    perror("Thread create error");
    }

    /** Spawn the NAT Maintenance Thread **/
    /*
    rs->nat_maintenance_thread = (pthread_t*)malloc(sizeof(pthread_t));
    if(pthread_create(rs->nat_maintenance_thread, NULL, nat_maintenance_thread, (void*)rs) != 0) {
	    perror("Thread create error");
    }
    */

    /* if we are on the NETFPGA spawn the stats thread */
		if (rs->is_netfpga) {
	    rs->stats_thread = (pthread_t*)malloc(sizeof(pthread_t));
	    if(pthread_create(rs->stats_thread, NULL, netfpga_stats, (void*)rs) != 0) {
		    perror("Thread create error");
	    }
		}
}
Пример #19
0
/* --- CCDN 初始化路由表,将来可以参照
功能:从sr的rtable字段读取名字,在当前工作目录下找到相应的文件,
从文件中读取路由表entry,然后将每条entry加入到table里面*/
void init_rtable(struct sr_instance* sr) {
	/* get the rtable lock */
	lock_rtable_wr(get_router_state(sr));

	/* the sr_instance only holds 32 chars of the path to the rtable file so we have
	 * to pass it in as a relative path to the working directory, which requires
	 * us to get the working directory, do some string manipulation, and append
	 * the relative path to the end of the working directory */
	char path[256];
	bzero(path, 256);
	getcwd(path, 256);//获取当前工作的绝对路径,存到path中
	int len = strlen(path);
	path[len] = '/';
	strcpy(path+len+1, sr->rtable);
	FILE* file = fopen(path, "r");
  if (file == NULL) {
  	perror("Failure opening file");
   	exit(1);
  }
  /* 前面这一大块干的是就是在工作目录下找到一个文件(例如rtable),里面存路由表之类的信息 */

  char buf[1024];
  bzero(buf, 1024);

  router_state* rs = (router_state*)sr->interface_subsystem;

  /* walk through the file one line at a time adding its contents to the rtable */
  /* 下面这个while干的事情是从文件中读取ip表,然后把它们加入到rtable里面 */
  while (fgets(buf, 1024, file) != NULL) {
  	char* ip = NULL;
  	char* gw = NULL;
  	char* mask = NULL;
  	char* iface = NULL;
  	if (sscanf(buf, "%as %as %as %as", &ip, &gw, &mask, &iface) != 4) {
  		printf("Failure reading from rtable file\n");
  	}

  	rtable_entry* entry = (rtable_entry*)malloc(sizeof(rtable_entry));
  	bzero(entry, sizeof(rtable_entry)); // bzero,清空整个地址空间

  	if (inet_pton(AF_INET, ip, &(entry->ip)) == 0) {//点分十进制->整数之间的转换,AF_INET指地址簇,可以理解为IPv4
  		perror("Failure reading rtable");  // perror:标准错误流,会讲错误的原因输出到屏幕上。
  	}
  	if (inet_pton(AF_INET, gw, &(entry->gw)) == 0) {
  		perror("Failure reading rtable");
  	}
  	if (inet_pton(AF_INET, mask, &(entry->mask)) == 0) {
  		perror("Failure reading rtable");
  	}
  	strncpy(entry->iface, iface, 32);

  	entry->is_active = 1;
  	entry->is_static = 1;
  	/* create a node, set data pointer to the new entry */
  	node* n = node_create();
  	n->data = entry;

  	if (rs->rtable == NULL) {
  		rs->rtable = n;
  	} else {
  		node_push_back(rs->rtable, n);
  	}


  	char ip_array[INET_ADDRSTRLEN];
  	char gw_array[INET_ADDRSTRLEN];
  	char mask_array[INET_ADDRSTRLEN];

  	printf("Read: %s ", inet_ntop(AF_INET, &(entry->ip), ip_array, INET_ADDRSTRLEN));
  	printf("%s ", inet_ntop(AF_INET, &(entry->gw), gw_array, INET_ADDRSTRLEN));
  	printf("%s ", inet_ntop(AF_INET, &(entry->mask), mask_array, INET_ADDRSTRLEN));
  	printf("%s\n", entry->iface);
  }


	if (fclose(file) != 0) {
		perror("Failure closing file");
	}

	/* check if we have a default route entry, if so we need to add it to our pwospf router */
	pwospf_interface* default_route = default_route_present(rs);

	/* release the rtable lock */
	unlock_rtable(get_router_state(sr));

	if (default_route) {
		lock_mutex_pwospf_router_list(rs);

		pwospf_router* r = get_router_by_rid(rs->router_id, rs->pwospf_router_list);
		node* n = node_create();
		n->data = default_route;

		if (r->interface_list) {
			node_push_back(r->interface_list, n);
		} else {
			r->interface_list = n;
		}

		unlock_mutex_pwospf_router_list(rs);
	}
	/* tell our dijkstra algorithm to run */
	dijkstra_trigger(rs);
	printf("init_rtable finish \n");
}
Пример #20
0
/*
 * HELPER function called from arp_thread
 */
void process_arp_queue(struct sr_instance* sr) {
	router_state* rs = get_router_state(sr);
	node* n = get_router_state(sr)->arp_queue;
	node* next = NULL;
	time_t now;
	double diff;

	while (n) {
		next = n->next;

		arp_queue_entry* aqe = (arp_queue_entry*)n->data;

		/* has it been over a second since the last arp request was sent? */
		time(&now);
		diff = difftime(now, aqe->last_req_time);
		if (diff > 1) {
			/* have we sent less than 5 arp requests? */
			if (aqe->requests < 5) {
				/* send another */
				time(&(aqe->last_req_time));
				++(aqe->requests);
				send_arp_request(sr, aqe->next_hop.s_addr, aqe->out_iface_name);
			} else {
				/* we have exceeded the max arp requests, return packets to sender */
				node* cur_packet_node = aqe->head;
				node* next_packet_node = NULL;

				while (cur_packet_node) {
					/* send icmp for the packet, free it, and its encasing entry */
					arp_queue_packet_entry* aqpe = (arp_queue_packet_entry*)cur_packet_node->data;

					/* only send an icmp error if the packet is not icmp, or if it is, its an echo request or reply
					 * also ensure we don't send an icmp error back to one of our interfaces
					 */
					if ((get_ip_hdr(aqpe->packet, aqpe->len)->ip_p != IP_PROTO_ICMP) ||
							(get_icmp_hdr(aqpe->packet, aqpe->len)->icmp_type == ICMP_TYPE_ECHO_REPLY) ||
							(get_icmp_hdr(aqpe->packet, aqpe->len)->icmp_type == ICMP_TYPE_ECHO_REQUEST)) {

					 	/* also ensure we don't send an icmp error back to one of our interfaces */
						if (!iface_match_ip(rs, get_ip_hdr(aqpe->packet, aqpe->len)->ip_src.s_addr)) {
							/* Total hack here to increment the TTL since we already decremented it earlier in the pipeline
							 * and the ICMP error should return the original packet.
							 * TODO: Don't decrement the TTL until the packet is ready to be put on the wire
							 * and we have the next hop ARP address, although checking should be done
							 * where it is currently being decremented to minimize effort on a doomed packet */
							ip_hdr *ip = get_ip_hdr(aqpe->packet, aqpe->len);
							if (ip->ip_ttl < 255) {
								ip->ip_ttl++;

								/* recalculate checksum */
								bzero(&ip->ip_sum, sizeof(uint16_t));
								uint16_t checksum = htons(compute_ip_checksum(ip));
								ip->ip_sum = checksum;
							}

							send_icmp_packet(sr, aqpe->packet, aqpe->len, ICMP_TYPE_DESTINATION_UNREACHABLE, ICMP_CODE_HOST_UNREACHABLE);
						}
					}

					free(aqpe->packet);
					next_packet_node = cur_packet_node->next;
					//free(cur_packet_node);   /* IS THIS CORRECT TO FREE IT ? */
					node_remove(&(aqe->head), cur_packet_node);
					cur_packet_node = next_packet_node;
				}

				/* free the arp queue entry for this destination ip, and patch the list */
				node_remove(&(get_router_state(sr)->arp_queue), n);
			}
		}

		n = next;
	}
}