void generate_pending_ARP_thread() { router_t *router = get_router(); pending_arp_entry_t expiring_arp_entry[router->num_pending_arp]; unsigned i; while (TRUE) { unsigned num_expiring = 0; pthread_mutex_lock(&router->pending_arp_lock); for (i = 0; i < router->num_pending_arp; i++) { pending_arp_entry_t *pending_arp_entry = &router->pending_arp[i]; if (pending_arp_entry->num_sent >= 5) { debug_println("Not responding to ARP request!"); expiring_arp_entry[num_expiring].payload = pending_arp_entry->payload; expiring_arp_entry[num_expiring].len = pending_arp_entry->len; num_expiring++; unsigned j; for (j = i; j < router->num_pending_arp-1; j++) { router->pending_arp[j] = router->pending_arp[j+1]; } router->num_pending_arp--; if (i != router->num_pending_arp) i--; //Don't increase i on next go. continue; } send_ARP_request(pending_arp_entry->ip, ++pending_arp_entry->num_sent); //Shouldn't need lock. } debug_println("num_pending_arp=%d", router->num_pending_arp); pthread_mutex_unlock(&router->pending_arp_lock); for (i = 0; i < num_expiring; i++) { struct ip_hdr *iphdr = (void *)expiring_arp_entry[i].payload; if (router_lookup_interface_via_ip(router, IPH_SRC(iphdr)) == NULL) { //Don't send a response to itself. handle_not_repsponding_to_arp(expiring_arp_entry[i].payload, expiring_arp_entry[i].len); } else { debug_println("NOT sending response, because it originated from own interface."); } free(expiring_arp_entry[i].payload); expiring_arp_entry[i].payload = NULL; } sleep(1); debug_println("Pending ARP thread sleeping for 1s."); } }
int main() { const int port = 8000; http_server svc; //bring up tls machine, this need to be done before server setup int ng = tls_engine_inhale("server-cert.pem", "server-key.pem", 0); assert(ng == 0); setup_server(&svc, "0.0.0.0", port); //the length of path passed explicitly to stop strlen calling router *rtr = get_router(&svc); addroute(rtr, "/redfish", 8, write_res); printf("Listening on %d\n", port); //run forever run(&svc); tls_engine_stop(); return 0; }
int handle_rtm_newroute(const struct nlmsghdr *nl){ const struct rtmsg *rt = NLMSG_DATA(nl); struct rtattr *ra; void *as,*ad,*ag; int rlen,oif; route *r,**prev; size_t flen; oif = -1; if((r = create_route()) == NULL){ return -1; } switch( (r->family = rt->rtm_family) ){ case AF_INET:{ flen = sizeof(uint32_t); as = &((struct sockaddr_in *)&r->sss)->sin_addr; ad = &((struct sockaddr_in *)&r->ssd)->sin_addr; ag = &((struct sockaddr_in *)&r->ssg)->sin_addr; break;}case AF_INET6:{ flen = sizeof(uint32_t) * 4; as = &((struct sockaddr_in6 *)&r->sss)->sin6_addr; ad = &((struct sockaddr_in6 *)&r->ssd)->sin6_addr; ag = &((struct sockaddr_in6 *)&r->ssg)->sin6_addr; break;}case AF_BRIDGE:{ // FIXME wtf is a bridge route diagnostic("got a bridge route hrmmm FIXME"); return -1; // FIXME break;}default:{ flen = 0; break;} } r->maskbits = rt->rtm_dst_len; if(flen == 0 || flen > sizeof(r->sss.__ss_padding)){ diagnostic("Unknown route family %u",rt->rtm_family); return -1; } rlen = nl->nlmsg_len - NLMSG_LENGTH(sizeof(*rt)); ra = (struct rtattr *)((char *)(NLMSG_DATA(nl)) + sizeof(*rt)); memset(&r->ssg,0,sizeof(r->ssg)); memset(&r->ssd,0,sizeof(r->ssd)); memset(&r->sss,0,sizeof(r->sss)); while(RTA_OK(ra,rlen)){ switch(ra->rta_type){ case RTA_DST:{ if(RTA_PAYLOAD(ra) != flen){ diagnostic("Expected %zu dst bytes, got %zu", flen,RTA_PAYLOAD(ra)); break; } if(r->ssd.ss_family){ diagnostic("Got two destinations for route"); break; } memcpy(ad,RTA_DATA(ra),flen); r->ssd.ss_family = r->family; break;}case RTA_PREFSRC: case RTA_SRC:{ // FIXME do we not want to prefer PREFSRC? if(RTA_PAYLOAD(ra) != flen){ diagnostic("Expected %zu src bytes, got %zu", flen,RTA_PAYLOAD(ra)); break; } if(r->sss.ss_family){ diagnostic("Got two sources for route"); break; } memcpy(as,RTA_DATA(ra),flen); r->sss.ss_family = r->family; break;}case RTA_IIF:{ if(RTA_PAYLOAD(ra) != sizeof(int)){ diagnostic("Expected %zu iiface bytes, got %zu", sizeof(int),RTA_PAYLOAD(ra)); break; } // we don't use RTA_OIF: iif = *(int *)RTA_DATA(ra); break;}case RTA_OIF:{ if(RTA_PAYLOAD(ra) != sizeof(int)){ diagnostic("Expected %zu oiface bytes, got %zu", sizeof(int),RTA_PAYLOAD(ra)); break; } oif = *(int *)RTA_DATA(ra); break;}case RTA_GATEWAY:{ if(RTA_PAYLOAD(ra) != flen){ diagnostic("Expected %zu gw bytes, got %zu", flen,RTA_PAYLOAD(ra)); break; } if(r->ssg.ss_family){ diagnostic("Got two gateways for route"); break; } // We get 0.0.0.0 as the gateway when there's no 'via' if(memcmp(ag,RTA_DATA(ra),flen)){ memcpy(ag,RTA_DATA(ra),flen); r->ssg.ss_family = r->family; } break;}case RTA_PRIORITY:{ break;}case RTA_METRICS:{ break;}case RTA_MULTIPATH:{ // break;}case RTA_PROTOINFO:{ // unused break;}case RTA_FLOW:{ break;}case RTA_CACHEINFO:{ // break;}case RTA_SESSION:{ // unused // break;}case RTA_MP_ALGO:{ // unused break;}case RTA_TABLE:{ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) break;}case RTA_MARK:{ #endif break;}case RTA_MFC_STATS:{ break;}case RTA_VIA:{ break;}case RTA_NEWDST:{ break;}case RTA_PREF:{ break;}case RTA_ENCAP_TYPE:{ break;}case RTA_ENCAP:{ break;}case RTA_EXPIRES:{ break;}case RTA_PAD:{ break;}default:{ diagnostic("Unknown rtatype %u",ra->rta_type); break;}} ra = RTA_NEXT(ra,rlen); } if(rlen){ diagnostic("%d excess bytes on newlink message",rlen); } if((r->iface = iface_by_idx(oif)) == NULL){ diagnostic("Unknown output interface %d on %s",oif,r->iface->name); goto err; } { char str[INET6_ADDRSTRLEN],via[INET6_ADDRSTRLEN]; inet_ntop(rt->rtm_family,ad,str,sizeof(str)); inet_ntop(rt->rtm_family,ag,via,sizeof(via)); diagnostic("[%s] new route to %s/%u %ls%ls%s", r->iface->name,str,r->maskbits, rt->rtm_type == RTN_LOCAL ? L"(local)" : rt->rtm_type == RTN_BROADCAST ? L"(broadcast)" : rt->rtm_type == RTN_UNREACHABLE ? L"(unreachable)" : rt->rtm_type == RTN_ANYCAST ? L"(anycast)" : rt->rtm_type == RTN_UNICAST ? L"(unicast)" : rt->rtm_type == RTN_MULTICAST ? L"(multicast)" : rt->rtm_type == RTN_BLACKHOLE ? L"(blackhole)" : rt->rtm_type == RTN_MULTICAST ? L"(multicast)" : L"", r->ssg.ss_family ? L" via " : L"", r->ssg.ss_family ? via : ""); } // We're not interest in blackholes, unreachables, prohibits, NATs yet if(rt->rtm_type != RTN_UNICAST && rt->rtm_type != RTN_LOCAL && rt->rtm_type != RTN_BROADCAST && rt->rtm_type != RTN_ANYCAST && rt->rtm_type != RTN_MULTICAST){ free_route(r); return 0; } assert(r->iface); if(!r->sss.ss_family){ struct routepath rp; if(get_router(r->sss.ss_family,ad,&rp) == 0){ if(r->sss.ss_family == AF_INET){ memcpy(as,rp.src,4); }else if(r->sss.ss_family == AF_INET6){ memcpy(as,rp.src,16); }else{ assert(0); } }else{ // FIXME vicious hackery! if(r->family == AF_INET6){ memcpy(as,r->iface->ip6defsrc,flen); r->sss.ss_family = AF_INET6; } } } if(r->family == AF_INET){ lock_interface(r->iface); if(add_route4(r->iface,ad,r->ssg.ss_family ? ag : NULL, r->sss.ss_family ? as : NULL, r->maskbits)){ unlock_interface(r->iface); diagnostic("Couldn't add route to %s",r->iface->name); goto err; } if(r->ssg.ss_family){ send_arp_req(r->iface,r->iface->bcast,ag,as); } unlock_interface(r->iface); pthread_mutex_lock(&route_lock); prev = &ip_table4; // Order most-specific (largest maskbits) to least-specific (0 maskbits) while(*prev){ if(r->maskbits > (*prev)->maskbits){ break; } prev = &(*prev)->next; } r->next = *prev; *prev = r; if(r->sss.ss_family){ while( *(prev = &(*prev)->next) ){ assert((*prev)->maskbits < r->maskbits); if(!((*prev)->sss.ss_family)){ memcpy(&(*prev)->sss,&r->sss,sizeof(r->sss)); } } } pthread_mutex_unlock(&route_lock); }else if(r->family == AF_INET6){ lock_interface(r->iface); if(add_route6(r->iface,ad,r->ssg.ss_family ? ag : NULL,r->sss.ss_family ? as : NULL,r->maskbits)){ unlock_interface(r->iface); diagnostic("Couldn't add route to %s",r->iface->name); goto err; } unlock_interface(r->iface); pthread_mutex_lock(&route_lock); prev = &ip_table6; // Order most-specific (largest maskbits) to least-specific (0 maskbits) while(*prev){ if(r->maskbits > (*prev)->maskbits){ break; } prev = &(*prev)->next; } r->next = *prev; *prev = r; // FIXME set less-specific sources pthread_mutex_unlock(&route_lock); } return 0; err: free_route(r); return -1; }
// build the network with the parameters given in param Network::Network(void) { success = true; n_of_rows = param.n_of_rows; n_of_cols = param.n_of_cols; n_of_ports = param.n_of_ports; n_of_extra_links = param.n_of_extra_links; topology = param.topology; n_of_switch_ports = param.n_of_switch_ports; n_of_vcs = param.n_of_vcs; Traffic_source::reset_id_base(); Traffic_sink::reset_id_base(); if (param.verbose) cout << "[I] Building network..." << endl; if (topology != mesh) { cerr << ERRO_ARCH_NOT_SUPPORTED; success = false; return; } if (param.verbose) cout << "[I] Creating routers..." << endl; Position pos; // Build all the routers and PEs in the network for (pos.x = 0; pos.x < param.n_of_cols; pos.x++) { for (pos.y = 0; pos.y < param.n_of_rows; pos.y++) { pRouter a_router = new Router(this, pos); routers.push_back(a_router); } } if (param.verbose) cout << "[I] Creating traffic sources/sinks..." << endl; // Build all the traffic sources/sinks in the network for (pos.x = 0; pos.x < param.n_of_cols; pos.x++) { for (pos.y = 0; pos.y < param.n_of_rows; pos.y++) { pTraffic_source a_source = new Traffic_source(pos, param.source_buffer_size); pTraffic_sink a_sink = new Traffic_sink(pos, param.sink_buffer_size); //CPU m_newnode(yyengine, "superH", 0, 0, 0, NULL, 0); //network interface 1 tx/rx queue, network_netnodenewifc(yyengine, yyengine->cp, 0, 0, 0, 0, 0, 0, 0, 0, (param.source_buffer_size * 8/sizeof(FlitPayload) - 1) * 8, 2, 2); //FIXME: how to set those parameters //set memory size m_sizemem(yyengine, yyengine->cp,0x9000000); //load the program load_srec(yyengine, yyengine->cp, "default.sr"); m_run(yyengine, yyengine->cp, ""); //FIXME: add arguments to nodes a_source->state = yyengine->cp; a_sink->state = yyengine->cp; sources.push_back(a_source); sinks.push_back(a_sink); } } if (param.verbose) cout << "[I] Attaching traffic sources/sinks with routers..." << endl; // connect sources and sinks with the router for (pos.x = 0; pos.x < param.n_of_cols; pos.x++) { for (pos.y = 0; pos.y < param.n_of_rows; pos.y++) { pTraffic_source a_source = get_traffic_source(pos); pTraffic_sink a_sink = get_traffic_sink(pos); pRouter a_router = get_router(pos); pIn_port a_in_port = a_router->get_in_port(local); pOut_port a_out_port = a_router->get_out_port(local); connect(a_source, a_in_port); connect(a_out_port, a_sink); } } if (param.verbose) cout << "[I] Connecting routers with links..." << endl; // connect the port of each router to the corresponding output port // of its neighboring router for (pos.x = 0; pos.x < param.n_of_cols; pos.x++) { for (pos.y = 0; pos.y < param.n_of_rows; pos.y++) { pRouter src_router = get_router(pos); for (unsigned int i = 0; i < n_of_ports - n_of_extra_links; i++) { Direction dir = (Direction) i; if (dir == local) // no go for local router continue; pRouter dst_router = src_router->get_router(dir); if (dst_router == 0) continue; pOut_port a_out_port = src_router->get_out_port(dir); pIn_port a_in_port = dst_router->get_in_port(reverse(dir)); connect(a_out_port, a_in_port); } } } if (param.verbose) cout << "[I] Network successfully built..." << endl; param.network = this; }
void Network::calc_channel_load(void) { pInput_channel ch = 0; // first, clear the load parameters of every input channel for (vector<pRouter>::iterator r = routers.begin(); r < routers.end(); r++) { for (Direction dir = local; dir < invalid_dir; dir = (Direction) (((int) dir) + 1)) { ch = (*r)->get_in_channel(dir); ch->reset_load(); } } // clear the load parameters of every sinks for (vector<pTraffic_sink>::iterator iter = sinks.begin(); iter < sinks.end(); iter++) (*iter)->reset_load(); // now enumerate all the traffic transactions between any source/destination pairs for (unsigned int src = 0; src < sources.size(); src++) { pTraffic_source pts = sources[src]; for (unsigned int dst = 0; dst < sinks.size(); dst++) { if (src == dst) continue; double load = pts->get_packet_to_destination_rate(dst); if (load == 0) continue; // now let's update all the input channel load used by this traffic Position src_pos = pts->get_position(); Position dst_pos = sinks[dst]->get_position(); // first, fill in the local input channel in the local router pRouter r = get_router(src_pos); ch = r->get_in_channel(local); pRouting_engine re = ch->get_routing_engine(); Direction out_dir = re->decide_direction(src_pos, dst_pos); ch->add_load(load, out_dir); // now start following the routing path Position cur_pos = src_pos; pRouter cur_r = r; pInput_channel cur_ch = ch; while (cur_pos != dst_pos) { re = cur_ch->get_routing_engine(); out_dir = re->decide_direction(src_pos, dst_pos); pRouter next_r = cur_r->get_router(out_dir); pInput_channel next_ch = next_r->get_in_channel( reverse(out_dir)); re = next_ch->get_routing_engine(); out_dir = re->decide_direction(src_pos, dst_pos); next_ch->add_load(load, out_dir); cur_r = next_r; cur_ch = next_ch; cur_pos = cur_r->get_position(); } assert(cur_pos == dst_pos); assert(out_dir == local); // finally, we need to update the traffic sinks load sinks[dst]->add_load(load); } } }
void handle_ARP_packet(packet_info_t *pi) { /*unsigned i; for (i = 0; i < pi->len; i++) printf("(%d %02X) ", i, (int)*(pi->packet+i)); printf("\n");*/ byte *ARP_packet = pi->packet+14; struct arp_hdr *arhdr = (void *)ARP_packet; addr_ip_t target_ip = ARH_TARGET_IP(arhdr); char target_ip_str[16]; ip_to_string(target_ip_str, target_ip); uint16_t op = ARH_OP(arhdr); router_t *router = get_router(); interface_t *target_intf = router_lookup_interface_via_ip(router, target_ip); addr_mac_t sender_mac = ARH_SENDER_MAC(arhdr); addr_ip_t sender_ip = ARH_SENDER_IP(arhdr); if (target_intf && op == 1) { char sender_ip_str[12]; ip_to_string(sender_ip_str, sender_ip); debug_println("Packet is an ARP request from %s for %s.", sender_ip_str, target_ip_str); if (router_find_arp_entry(router, sender_ip)) { router_delete_arp_entry(router, sender_ip); } router_add_arp_entry(router, sender_mac, sender_ip, TRUE); //Save mac address. ARH_OP_SET(arhdr, 2); swap_bytes(&ARH_SENDER_MAC(arhdr),&ARH_TARGET_MAC(arhdr), ARH_HARD_LEN(arhdr)+ARH_PROTO_LEN(arhdr)); //Swap ARP source and dest mac and ip ARH_SENDER_MAC_SET(arhdr, target_intf->mac); send_packet(pi->packet+14, target_intf->ip, sender_ip, pi->len-14, TRUE, FALSE); } else if (target_intf && op == 2) { char sender_ip_str[12]; ip_to_string(sender_ip_str, sender_ip); debug_println("Packet is an ARP reply from %s for %s.\n", sender_ip_str, target_ip_str); if (router_find_arp_entry(router, sender_ip)) { router_delete_arp_entry(router, sender_ip); } router_add_arp_entry(router, sender_mac, sender_ip, TRUE); //Save mac address. debug_println("about to get lock!"); pthread_mutex_lock(&router->pending_arp_lock); debug_println("num_pending_arp=%d", router->num_pending_arp); unsigned i; for (i = 0; i < router->num_pending_arp; i++) { debug_println("i=%d", i); pending_arp_entry_t *pending_arp_entry = &router->pending_arp[i]; if (pending_arp_entry->ip == sender_ip) { debug_println("Resending packet in entry %d", i); send_packet(pending_arp_entry->payload, pending_arp_entry->src, pending_arp_entry->ip, pending_arp_entry->len, FALSE, FALSE); unsigned j; for (j = i; j < router->num_pending_arp-1; j++) { router->pending_arp[j] = router->pending_arp[j+1]; } router->num_pending_arp--; if (i != router->num_pending_arp) i--; //Don't increase i on next go. } } pthread_mutex_unlock(&router->pending_arp_lock); } }