/* * IS THREADSAFE */ int add_local_ip_filter(router_state* rs, struct in_addr* ip, char* name) { if (get_local_ip_filter_by_ip(rs, ip) || get_local_ip_filter_by_name(rs, name)) { return 1; } node* cur = node_create(); local_ip_filter_entry* entry = (local_ip_filter_entry*)calloc(1, sizeof(local_ip_filter_entry)); strncpy(entry->name, name, (LOCAL_IP_FILTER_ENTRY_NAME_LEN - 1)); entry->ip.s_addr = ip->s_addr; cur->data = entry; lock_local_ip_filters(rs); if (!rs->local_ip_filter_list) { rs->local_ip_filter_list = cur; } else { node_push_back(rs->local_ip_filter_list, cur); } unlock_local_ip_filters(rs); trigger_local_ip_filters_change(rs); return 0; }
void register_cli_command(node** head, char* command, cli_command_handler handler) { node* n = node_create(); n->data = create_cli_entry(command, handler); if (!(*head)) { (*head) = n; } else { node_push_back(*head, n); } }
/*初始化路由器列表,包括每个路由器的编号、距离之类的(搭拓扑的时候可能要用)*/ 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); }
/* * NOT THREAD SAFE, LOCK THE ARP CACHE * Return: 0 on success, 1 on failure */ int update_arp_cache(struct sr_instance* sr, struct in_addr* remote_ip, char* remote_mac, int is_static) { assert(sr); assert(remote_ip); assert(remote_mac); router_state *rs = (router_state *)sr->interface_subsystem; arp_cache_entry *arp_entry = 0; arp_entry = in_arp_cache(rs, remote_ip); if(arp_entry) { /* if this remote ip is in the cache, update its data */ memcpy(arp_entry->arp_ha, remote_mac, ETH_ADDR_LEN); if (is_static == 1) { arp_entry->TTL = 0; } else { time(&arp_entry->TTL); } arp_entry->is_static = is_static; } else { /* if this interface is not in the cache, create a new entry */ node* n = node_create(); arp_entry = calloc(1, sizeof(arp_cache_entry)); arp_entry->ip.s_addr = remote_ip->s_addr; memcpy(arp_entry->arp_ha, remote_mac, ETH_ADDR_LEN); if (is_static == 1) { arp_entry->TTL = 0; } else { time(&arp_entry->TTL); } arp_entry->is_static = is_static; n->data = (void *)arp_entry; if(rs->arp_cache == NULL) { rs->arp_cache = n; } else { node_push_back(rs->arp_cache, n); } } /* update the hw arp cache copy */ trigger_arp_cache_modified(rs); return 0; }
/* * Helper function for arp_queue_add, not to be called externally */ void arp_queue_entry_add_packet(arp_queue_entry* aqe, uint8_t* packet, unsigned int len) { node* n = node_create(); arp_queue_packet_entry* aqpe = (arp_queue_packet_entry*)malloc(sizeof(arp_queue_packet_entry)); aqpe->packet = packet; aqpe->len = len; /* set the new nodes data to point to the packet entry */ n->data = aqpe; /* add the new node to the arp queue entry */ if (aqe->head == NULL) { aqe->head = n; } else { node_push_back(aqe->head, n); } }
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); } }
/* --- 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"); }
/*init_add_interface功能:初始化了4个网口的mac地址等信息*/ void init_add_interface(struct sr_instance* sr, struct sr_vns_if* vns_if) { /* do not add any of the cpu interfaces */ if (strstr(vns_if->name, "cpu")) {//函数功能是查name里面是否有cpu这个字符串,没有返回NULL return; } router_state* rs = (router_state*)sr->interface_subsystem; node* n = node_create(); iface_entry* ie = (iface_entry*)malloc(sizeof(iface_entry)); bzero(ie, sizeof(iface_entry)); ie->is_active = 1; ie->ip = vns_if->ip; ie->mask = vns_if->mask; ie->speed = vns_if->speed; ie->is_wan = 0; memcpy(ie->addr, vns_if->addr, ETH_ADDR_LEN); memcpy(ie->name, vns_if->name, IF_LEN); // ie->hello_interval = PWOSPF_NEIGHBOR_TIMEOUT; /* router id is the same as the ip of the 0th iface */ if(strncmp(ie->name, "eth0", IF_LEN) == 0) { rs->router_id = ie->ip; } n->data = ie; if (rs->if_list == NULL) { rs->if_list = n; } else { node_push_back(rs->if_list, n); } if (rs->is_netfpga) { /* set this on hardware */ unsigned int mac_hi = 0; mac_hi |= ((unsigned int)vns_if->addr[0]) << 8; mac_hi |= ((unsigned int)vns_if->addr[1]); unsigned int mac_lo = 0; mac_lo |= ((unsigned int)vns_if->addr[2]) << 24; mac_lo |= ((unsigned int)vns_if->addr[3]) << 16; mac_lo |= ((unsigned int)vns_if->addr[4]) << 8; mac_lo |= ((unsigned int)vns_if->addr[5]); switch (getPortNumber(vns_if->name)) { case 0: writeReg(&rs->netfpga, ROUTER_OP_LUT_MAC_0_HI_REG, mac_hi); writeReg(&rs->netfpga, ROUTER_OP_LUT_MAC_0_LO_REG, mac_lo); break; case 1: writeReg(&rs->netfpga, ROUTER_OP_LUT_MAC_1_HI_REG, mac_hi); writeReg(&rs->netfpga, ROUTER_OP_LUT_MAC_1_LO_REG, mac_lo); break; case 2: writeReg(&rs->netfpga, ROUTER_OP_LUT_MAC_2_HI_REG, mac_hi); writeReg(&rs->netfpga, ROUTER_OP_LUT_MAC_2_LO_REG, mac_lo); break; case 3: writeReg(&rs->netfpga, ROUTER_OP_LUT_MAC_3_HI_REG, mac_hi); writeReg(&rs->netfpga, ROUTER_OP_LUT_MAC_3_LO_REG, mac_lo); break; } } /* add a local ip filter as well */ struct in_addr ip; ip.s_addr = vns_if->ip; add_local_ip_filter(rs, &ip, vns_if->name); }
int main(int argc, char** argv) { int our_rid = atoi(argv[1]); FILE* file = fopen(argv[2], "r"); if (file == NULL) { perror("Failure opening file"); exit(1); } char* buf = (char*)malloc(1024); bzero(buf, 1024); node* iface_list = NULL; node* router_list = NULL; unsigned char is_iface_line = 1; unsigned char is_router_line = 0; unsigned char is_interface_line = 0; pwospf_router* cur_router = NULL; while (fgets(buf, 1024, file) != NULL) { if (buf[0] == '#') { continue; } if (is_iface_line) { iface_entry* iface = (iface_entry*)calloc(1, sizeof(iface_entry)); char* ip_str = NULL; //char* nbr_ip_str = NULL; char* mask_str = NULL; /* FIXME if (sscanf(buf, "%15s %as %as %as %u", iface->name, &ip_str, &nbr_ip_str, &mask_str, &(iface->nbr_router_id)) != 5) { free(iface); cur_router = NULL; is_iface_line = 0; is_router_line = 1; continue; } */ if (inet_pton(AF_INET, ip_str, &(iface->ip)) == 0) { perror("Failure reading ip"); } /* FIXME if (inet_pton(AF_INET, nbr_ip_str, &(iface->nbr_ip)) == 0) { perror("Failure reading nbr_ip"); } */ if (inet_pton(AF_INET, mask_str, &(iface->mask)) == 0) { perror("Failure reading mask"); } iface->is_active = 1; node* n = node_create(); n->data = iface; if (!(iface_list)) { iface_list = n; } else { node_push_back(iface_list, n); } } else if (is_router_line) { cur_router = (pwospf_router*)calloc(1, sizeof(pwospf_router)); unsigned int seq_temp; if (sscanf(buf, "%u %u %u", &(cur_router->router_id), &(cur_router->area_id), &(seq_temp)) != 3) { printf("Failure reading from rtable file\n"); } cur_router->seq = seq_temp; /* add it to the list */ node* n = node_create(); n->data = cur_router; if (!router_list) { router_list = n; } else { node_push_back(router_list, n); } is_router_line = 0; is_interface_line = 1; } else if (is_interface_line) { pwospf_interface* iface = (pwospf_interface*)calloc(1, sizeof(pwospf_interface)); char* subnet_str = NULL; char* mask_str = NULL; if (sscanf(buf, "%as %as %u", &subnet_str, &mask_str, &(iface->router_id)) != 3) { free(iface); cur_router = NULL; is_interface_line = 0; is_router_line = 1; continue; } iface->is_active = 1; if (inet_pton(AF_INET, subnet_str, &(iface->subnet)) == 0) { perror("Failure reading subnet"); } if (inet_pton(AF_INET, mask_str, &(iface->mask)) == 0) { perror("Failure reading mask"); } node* n = node_create(); n->data = iface; /* add it to the current router */ if (!(cur_router->interface_list)) { cur_router->interface_list = n; } else { node_push_back(cur_router->interface_list, n); } } } if (fclose(file) != 0) { perror("Failure closing file"); } print_pwospf_router_list(router_list); node* rtable = compute_rtable(our_rid, router_list, iface_list); router_state rs; rs.rtable = rtable; char* rtable_printout; int len; sprint_rtable(&rs, &rtable_printout, &len); printf("%s\n", rtable_printout); return 0; }
node* compute_rtable(uint32_t our_router_id, node* pwospf_router_list, node* if_list) { /* initialize all the entriest to their max distance, except us */ node* cur = pwospf_router_list; pwospf_router* r = NULL; pwospf_router* r_shortest = NULL; while (cur) { r = (pwospf_router*)cur->data; if (r->router_id == our_router_id) { r->distance = 0; r->shortest_path_found = 1; } else if (r->router_id != 0) { r->distance = 0xFFFFFFFF; r->shortest_path_found = 0; } cur = cur->next; } /* Set our router as the shortest */ r_shortest = get_router_by_rid(our_router_id, pwospf_router_list); while (r_shortest) { /* add this router to N' */ r_shortest->shortest_path_found = 1; /* update the distances to our neighbors */ update_neighbor_distance(r_shortest, pwospf_router_list); /* get the next router with the shortest distance */ r_shortest = get_shortest(pwospf_router_list); } /* now have the shortest path to each router, build the temporary route table */ node* route_wrapper_list = build_route_wrapper_list(our_router_id, pwospf_router_list); //print_wrapper_list(route_wrapper_list); /* we now have a list of wrapped proper entries, but they need specific interface info, * and need to lose the wrapping */ node* route_list = NULL; cur = route_wrapper_list; while (cur) { route_wrapper* wrapper = (route_wrapper*)cur->data; rtable_entry* new_entry = (rtable_entry*)calloc(1, sizeof(rtable_entry)); /* just blast the entry information across */ memcpy(new_entry, &(wrapper->entry), sizeof(rtable_entry)); /* get the new stuff */ iface_entry* iface = get_iface_by_rid(wrapper->next_rid, if_list); if (!iface) { iface = get_iface_by_subnet_mask(&(wrapper->entry.ip), &(wrapper->entry.mask), if_list); if (!iface) { /* most likely the default entry, assume its static, so just continue */ free(new_entry); cur = cur->next; continue; } } assert(iface); memcpy(new_entry->iface, iface->name, IF_LEN); if (wrapper->directly_connected) { new_entry->gw.s_addr = 0; } else { nbr_router* nbr = get_nbr_by_rid(iface, wrapper->next_rid); assert(nbr); new_entry->gw.s_addr = nbr->ip.s_addr; } new_entry->is_active = 1; new_entry->is_static = 0; /* grab a new node, add it to the list */ node* temp = node_create(); temp->data = new_entry; if (!route_list) { route_list = temp; } else { node_push_back(route_list, temp); } cur = cur->next; } /* run through and free the wrapper list */ cur = route_wrapper_list; while (cur) { node* next = cur->next; node_remove(&route_wrapper_list, cur); cur = next; } return route_list; }
void add_route_wrappers(uint32_t our_rid, node** head, pwospf_router* r) { node* cur = r->interface_list; while (cur) { pwospf_interface* i = (pwospf_interface*)cur->data; /* check if we have an existing route matching this subnet and mask */ node* temp_node = get_route_wrapper(*head, &(i->subnet), &(i->mask)); if (temp_node) { /* if our distance is longer, just continue to the next interface */ route_wrapper* wrapper = (route_wrapper*)temp_node->data; if (r->distance >= wrapper->distance) { cur = cur->next; continue; } else { /* replace the existing entries data with ours */ wrapper->distance = r->distance; /* walk down until the next router is the source */ pwospf_router* cur_router = r; if (!cur_router->prev_router) { wrapper->next_rid = i->router_id; } else { while (cur_router->prev_router->distance != 0) { cur_router = cur_router->prev_router; } wrapper->next_rid = cur_router->router_id; } /* set that this is directly connected to us */ if (our_rid == r->router_id) { wrapper->directly_connected = 1; } } } else { node* new_node = node_create(); /* no existing route wrapper, create a new one for this route */ route_wrapper* new_route = (route_wrapper*)calloc(1, sizeof(route_wrapper)); new_route->entry.ip.s_addr = i->subnet.s_addr & i->mask.s_addr; new_route->entry.mask.s_addr = i->mask.s_addr; new_route->distance = r->distance; /* walk down until the next router is the source */ pwospf_router* cur_router = r; if (!cur_router->prev_router) { new_route->next_rid = i->router_id; } else { while (cur_router->prev_router->distance != 0) { cur_router = cur_router->prev_router; } new_route->next_rid = cur_router->router_id; } /* set that this is directly connected to us */ if (our_rid == r->router_id) { new_route->directly_connected = 1; } /* point the node's data at our route wrapper */ new_node->data = new_route; if (!(*head)) { (*head) = new_node; } else { node_push_back(*head, new_node); } } cur = cur->next; } }