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); }
/* * 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; } }
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); } }
/* --- 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; } }
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); }
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; } }
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"); }
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; }
/*初始化路由器列表,包括每个路由器的编号、距离之类的(搭拓扑的时候可能要用)*/ 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); }
/* * 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; }
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]); } } } }
/* * 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; }
/* --- 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; }
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; } }
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); }
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); } }
/* 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"); } }
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"); } } }
/* --- 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"); }
/* * 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; } }