void __forwarding_table_hw_write_a(uint32_t subnet, uint32_t mask, uint32_t next_hop, char * interface, void * userdata, int * finished) { struct __forwarding_table_hw_write_i * hwi = (struct __forwarding_table_hw_write_i *)userdata; struct nf2device * device = &ROUTER(hwi->sr)->device; if(hwi->count >= ROUTER_OP_LUT_ROUTE_TABLE_DEPTH) { *finished = 1; } else if(subnet > 0) { writeReg(device, ROUTER_OP_LUT_ROUTE_TABLE_ENTRY_IP, ntohl(subnet)); writeReg(device, ROUTER_OP_LUT_ROUTE_TABLE_ENTRY_MASK, ntohl(mask)); writeReg(device, ROUTER_OP_LUT_ROUTE_TABLE_ENTRY_NEXT_HOP_IP, ntohl(next_hop)); writeReg(device, ROUTER_OP_LUT_ROUTE_TABLE_ENTRY_OUTPUT_PORT, interface_list_get_output_port(hwi->sr, interface)); writeReg(device, ROUTER_OP_LUT_ROUTE_TABLE_WR_ADDR, hwi->count); hwi->count += 1; } if(subnet == 0) { hwi->def = 1; hwi->next_hop = next_hop; hwi->port = interface_list_get_output_port(hwi->sr, interface); } }
static void forwarding_table_hw_write(struct sr_instance * sr) { #ifdef _CPUMODE_ struct __forwarding_table_hw_write_i hwi = {0,sr,0,0,0}; struct nf2device * device = &ROUTER(sr)->device; struct assoc_array * array = assoc_array_create(__forwarding_table_get_key_mask,assoc_array_key_comp_int); int i; __forwarding_table_loop(FORWARDING_TABLE(sr)->array_d, __combine_arrays, array); __forwarding_table_loop(FORWARDING_TABLE(sr)->array_s, __combine_arrays, array); __forwarding_table_loop(array, __forwarding_table_hw_write_a, &hwi); if(hwi.def) { writeReg(device, ROUTER_OP_LUT_ROUTE_TABLE_ENTRY_IP, 0); writeReg(device, ROUTER_OP_LUT_ROUTE_TABLE_ENTRY_MASK, 0); writeReg(device, ROUTER_OP_LUT_ROUTE_TABLE_ENTRY_NEXT_HOP_IP, ntohl(hwi.next_hop)); writeReg(device, ROUTER_OP_LUT_ROUTE_TABLE_ENTRY_OUTPUT_PORT, hwi.port); writeReg(device, ROUTER_OP_LUT_ROUTE_TABLE_WR_ADDR, hwi.count >= ROUTER_OP_LUT_ROUTE_TABLE_DEPTH ? ROUTER_OP_LUT_ROUTE_TABLE_DEPTH - 1 : hwi.count); hwi.count ++; } for(i = hwi.count; i < ROUTER_OP_LUT_ROUTE_TABLE_DEPTH; i++) { writeReg(device, ROUTER_OP_LUT_ROUTE_TABLE_ENTRY_IP, 0); writeReg(device, ROUTER_OP_LUT_ROUTE_TABLE_ENTRY_MASK, 0xffffffff); writeReg(device, ROUTER_OP_LUT_ROUTE_TABLE_ENTRY_NEXT_HOP_IP, 0); writeReg(device, ROUTER_OP_LUT_ROUTE_TABLE_ENTRY_OUTPUT_PORT, 0); writeReg(device, ROUTER_OP_LUT_ROUTE_TABLE_WR_ADDR, i); } assoc_array_delete_array(array,__delete_forwarding_table); #endif }
void ip_handle_incoming_packet(struct sr_packet * packet) { struct ip * ip_hdr = IP_HDR(packet); if(ip_hdr->ip_sum != checksum_ipheader(ip_hdr)) { printf("\nchecksums differ %x, %x\n", ip_hdr->ip_sum, checksum_ipheader(ip_hdr)); } else if(ip_hdr->ip_v != 4) { printf("\nip version is %d; only accepting 4\n",ip_hdr->ip_v); } else { if(dhcp_packet(packet)) { dhcp_handle_incoming(packet); } /* if packet is not for one of our interfaces then forward */ else if(!interface_list_ip_exists(ROUTER(packet->sr)->iflist, ip_hdr->ip_dst.s_addr) && ntohl(ip_hdr->ip_dst.s_addr) != OSPF_AllSPFRouters) { if(ip_hdr->ip_ttl <= 1) { icmp_send_time_exceeded(packet); } else { if(ip_hdr->ip_p == IP_P_TCP || ip_hdr->ip_p == IP_P_UDP) { tcp_handle_incoming_not_for_us(packet); } else { ip_forward(packet); } } } else { switch(ip_hdr->ip_p) { case IP_P_ICMP: icmp_handle_incoming_packet(packet); break; case IP_P_TCP: case IP_P_UDP: tcp_handle_incoming_for_us(packet); break; case IP_P_OSPF: ospf_handle_incoming_packet(packet); break; default: icmp_send_port_unreachable(packet); } } } }
void forwarding_table_create(struct sr_instance * sr) { NEW_STRUCT(ret,forwarding_table); ROUTER(sr)->fwd_table = ret; ret->array_s = assoc_array_create(__forwarding_table_get_key_mask,assoc_array_key_comp_int); ret->array_d = assoc_array_create(__forwarding_table_get_key_mask,assoc_array_key_comp_int); ret->array_nat = assoc_array_create(__forwarding_table_get_key_mask,assoc_array_key_comp_int); ret->mutex = mutex_create(); ret->running_dijkstra = 0; }
/* look up arp and send */ void ip_send(struct sr_packet * packet, uint32_t next_hop, char * thru_interface) { struct sr_ethernet_hdr * eth_hdr = ETH_HDR(packet); if(!arp_cache_get_MAC_from_ip(ROUTER(packet->sr)->a_cache, next_hop, eth_hdr->ether_dhost)) { arp_request_handler_make_request(packet,next_hop,thru_interface); } else { if(interface_list_get_MAC_and_IP_from_name(ROUTER(packet->sr)->iflist,thru_interface,eth_hdr->ether_shost,NULL)) { if(sr_integ_low_level_output(packet->sr,packet->packet,packet->len,thru_interface) == -1) { printf("\nfailed to send packet\n"); } } } }
/* if packet->interface = NULL then the packet has been generated by the router */ void ip_forward(struct sr_packet * packet) { struct ip * ip_hdr = IP_HDR(packet); uint32_t next_hop; char thru_interface[SR_NAMELEN]; /* if the destination is to one of our ports, then just forward it there */ if(interface_list_get_interface_by_ip(INTERFACE_LIST(packet->sr), ip_hdr->ip_dst.s_addr)) { ip_handle_incoming_packet(packet); } else { if(forwarding_table_lookup_next_hop(ROUTER(packet->sr)->fwd_table, ip_hdr->ip_dst.s_addr, &next_hop, thru_interface, interface_list_inbound(packet->sr, packet->interface)) && interface_list_forward_packet(packet->sr, packet->interface, thru_interface)) { if(next_hop == 0) { next_hop = ip_hdr->ip_dst.s_addr; } ip_hdr->ip_ttl --; ip_hdr->ip_sum = checksum_ipheader(ip_hdr); ip_send(packet,next_hop,thru_interface); } else { if(forwarding_table_lookup_next_hop(ROUTER(packet->sr)->fwd_table, ip_hdr->ip_src.s_addr, 0,0, interface_list_inbound(packet->sr, packet->interface))) { icmp_send_host_unreachable(packet); } } } }
int ip_send_packet(struct sr_packet * packet) { struct ip * ip_hdr = IP_HDR(packet); uint32_t next_hop; char thru_interface[SR_NAMELEN]; if(forwarding_table_lookup_next_hop(ROUTER(packet->sr)->fwd_table, ip_hdr->ip_dst.s_addr, &next_hop, thru_interface, 0)) { if(next_hop == 0) { next_hop = ip_hdr->ip_dst.s_addr; } ip_send(packet,next_hop,thru_interface); return 1; } return 0; }
tt_assert(router_is_already_dir_fetching(NULL, 1, 1) == 0); tt_assert(router_is_already_dir_fetching(&null_addr_ap, 1, 1) == 0); tt_assert(router_is_already_dir_fetching(&zero_port_ap, 1, 1) == 0); done: /* If a connection is never set up, connection_free chokes on it. */ if (mocked_connection) { buf_free(mocked_connection->inbuf); buf_free(mocked_connection->outbuf); } tor_free(mocked_connection); UNMOCK(connection_get_by_type_addr_port_purpose); } #undef TEST_ADDR_STR #undef TEST_DIR_PORT #define NODE(name, flags) \ { #name, test_routerlist_##name, (flags), NULL, NULL } #define ROUTER(name,flags) \ { #name, test_router_##name, (flags), NULL, NULL } struct testcase_t routerlist_tests[] = { NODE(initiate_descriptor_downloads, 0), NODE(launch_descriptor_downloads, 0), NODE(router_is_already_dir_fetching, TT_FORK), ROUTER(pick_directory_server_impl, TT_FORK), END_OF_TESTCASES };