void IP4::transmit(Packet_ptr pckt) { assert(pckt->size() > sizeof(IP4::full_header)); auto ip4_pckt = std::static_pointer_cast<PacketIP4>(pckt); ip4_pckt->make_flight_ready(); IP4::ip_header& hdr = ip4_pckt->ip4_header(); // Create local and target subnets addr target = hdr.daddr & stack_.netmask(); addr local = stack_.ip_addr() & stack_.netmask(); // Compare subnets to know where to send packet pckt->next_hop(target == local ? hdr.daddr : stack_.router()); debug("<IP4 TOP> Next hop for %s, (netmask %s, local IP: %s, gateway: %s) == %s\n", hdr.daddr.str().c_str(), stack_.netmask().str().c_str(), stack_.ip_addr().str().c_str(), stack_.router().str().c_str(), target == local ? "DIRECT" : "GATEWAY"); debug("<IP4 transmit> my ip: %s, Next hop: %s, Packet size: %i IP4-size: %i\n", stack_.ip_addr().str().c_str(), pckt->next_hop().str().c_str(), pckt->size(), ip4_pckt->ip4_segment_size() ); linklayer_out_(pckt); }
void Arp::await_resolution(Packet_ptr pckt, IP4::addr){ auto queue = waiting_packets_.find(pckt->next_hop()); if (queue != waiting_packets_.end()) { debug("<ARP Resolve> Packets allready queueing for this IP\n"); queue->second->chain(pckt); } else { debug("<ARP Resolve> This is the first packet going to that IP\n"); waiting_packets_.emplace(std::make_pair(pckt->next_hop(), pckt)); } }
int Arp::arp_resolve(Packet_ptr pckt){ debug("<ARP RESOLVE> %s \n", pckt->next_hop().str().c_str()); await_resolution(pckt, pckt->next_hop()); auto req = std::static_pointer_cast<PacketArp>(inet_.createPacket(sizeof(header))); req->init(mac_, ip_); req->set_dest_mac(Ethernet::addr::BROADCAST_FRAME); req->set_dest_ip(pckt->next_hop()); req->set_opcode(H_request); linklayer_out_(req); return 0; }
void Arp::arp_resolve(Packet_ptr pckt) { debug("<ARP RESOLVE> %s\n", pckt->next_hop().str().c_str()); const auto next_hop = pckt->next_hop(); await_resolution(std::move(pckt), next_hop); auto req = static_unique_ptr_cast<PacketArp>(inet_.create_packet(sizeof(header))); req->init(mac_, inet_.ip_addr()); req->set_dest_mac(Ethernet::BROADCAST_FRAME); req->set_dest_ip(next_hop); req->set_opcode(H_request); // Stat increment requests sent requests_tx_++; linklayer_out_(std::move(req)); }
int Arp::transmit(Packet_ptr pckt){ assert(pckt->size()); /** Get destination IP from IP header */ IP4::ip_header* iphdr = (IP4::ip_header*)(pckt->buffer() + sizeof(Ethernet::header)); IP4::addr sip = iphdr->saddr; IP4::addr dip = pckt->next_hop(); debug2("<ARP -> physical> Transmitting %i bytes to %s \n", pckt->size(),dip.str().c_str()); Ethernet::addr mac; if (iphdr->daddr == IP4::INADDR_BCAST) { // when broadcasting our source IP should be either // our own IP or 0.0.0.0 static const IP4::addr INADDR_NONE {{0}}; if (sip != ip_ && sip != INADDR_NONE) { debug2("<ARP> Dropping outbound broadcast packet due to " "invalid source IP %s\n", sip.str().c_str()); return -1; } mac = Ethernet::addr::BROADCAST_FRAME; } else { if (sip != ip_) { debug2("<ARP -> physical> Not bound to source IP %s. My IP is %s. DROP!\n", sip.str().c_str(), ip_.str().c_str()); return -1; } // If we don't have a cached IP, get mac from next-hop (Håreks c001 hack) if (!is_valid_cached(dip)) return arp_resolver_(pckt); // Get mac from cache mac = cache_[dip].mac_; } /** Attach next-hop mac and ethertype to ethernet header */ Ethernet::header* ethhdr = (Ethernet::header*)pckt->buffer(); ethhdr->src = mac_; ethhdr->dest.major = mac.major; ethhdr->dest.minor = mac.minor; ethhdr->type = Ethernet::ETH_IP4; debug2("<ARP -> physical> Sending packet to %s \n",mac.str().c_str()); return linklayer_out_(pckt); }
void Arp::transmit(Packet_ptr pckt) { assert(pckt->size()); /** Get destination IP from IP header */ IP4::ip_header* iphdr = reinterpret_cast<IP4::ip_header*>(pckt->buffer() + sizeof(Ethernet::header)); IP4::addr sip = iphdr->saddr; IP4::addr dip = pckt->next_hop(); debug2("<ARP -> physical> Transmitting %i bytes to %s\n", pckt->size(), dip.str().c_str()); Ethernet::addr dest_mac; if (iphdr->daddr == IP4::INADDR_BCAST) { // When broadcasting our source IP should be either // our own IP or 0.0.0.0 if (sip != inet_.ip_addr() && sip != IP4::INADDR_ANY) { debug2("<ARP> Dropping outbound broadcast packet due to " "invalid source IP %s\n", sip.str().c_str()); return; } // mui importante dest_mac = Ethernet::BROADCAST_FRAME; } else { if (sip != inet_.ip_addr()) { debug2("<ARP -> physical> Not bound to source IP %s. My IP is %s. DROP!\n", sip.str().c_str(), inet_.ip_addr().str().c_str()); return; } // If we don't have a cached IP, perform address resolution if (!is_valid_cached(dip)) { arp_resolver_(std::move(pckt)); return; } // Get MAC from cache dest_mac = cache_[dip].mac_; } /** Attach next-hop mac and ethertype to ethernet header */ auto* ethhdr = reinterpret_cast<Ethernet::header*>(pckt->buffer()); ethhdr->src = mac_; ethhdr->dest = dest_mac; ethhdr->type = Ethernet::ETH_IP4; /** Update chain as well */ auto* next = pckt->tail(); while(next) { auto* headur = reinterpret_cast<Ethernet::header*>(next->buffer()); headur->src = mac_; headur->dest = dest_mac; headur->type = Ethernet::ETH_IP4; next = next->tail(); } debug2("<ARP -> physical> Sending packet to %s\n", mac_.str().c_str()); linklayer_out_(std::move(pckt)); }