| 61 | } |
| 62 | |
| 63 | void ArpResponder::ProcessBatch(Context *ctx, bess::PacketBatch *batch) { |
| 64 | int cnt = batch->cnt(); |
| 65 | for (int i = 0; i < cnt; i++) { |
| 66 | // we should drop-or-emit each packet |
| 67 | bess::Packet *pkt = batch->pkts()[i]; |
| 68 | |
| 69 | Ethernet *eth = pkt->head_data<Ethernet *>(); |
| 70 | if (eth->ether_type != be16_t(Ethernet::Type::kArp)) { |
| 71 | // Currently drop all non ARP packets |
| 72 | DropPacket(ctx, pkt); |
| 73 | continue; |
| 74 | } |
| 75 | |
| 76 | Arp *arp = reinterpret_cast<Arp *>(eth + 1); |
| 77 | if (arp->opcode == be16_t(Arp::Opcode::kRequest)) { |
| 78 | // TODO(galsagie) When learn is added, learn SRC MAC here |
| 79 | |
| 80 | // Try to find target IP in cache, if exists convert request to reply |
| 81 | auto it = entries_.find(arp->target_ip_addr); |
| 82 | if (it != entries_.end()) { |
| 83 | const struct arp_entry &entry = it->second; |
| 84 | arp->opcode = be16_t(Arp::Opcode::kReply); |
| 85 | |
| 86 | eth->dst_addr = eth->src_addr; |
| 87 | eth->src_addr = entry.mac_addr; |
| 88 | |
| 89 | arp->target_hw_addr = arp->sender_hw_addr; |
| 90 | arp->sender_hw_addr = entry.mac_addr; |
| 91 | |
| 92 | arp->target_ip_addr = arp->sender_ip_addr; |
| 93 | arp->sender_ip_addr = entry.ip_addr; |
| 94 | EmitPacket(ctx, pkt, 0); |
| 95 | } else { |
| 96 | // Did not find an ARP entry in cache, drop packet |
| 97 | // TODO(galsagie) Optinally emit packet to next module here |
| 98 | DropPacket(ctx, pkt); |
| 99 | } |
| 100 | } else if (arp->opcode == be16_t(Arp::Opcode::kReply)) { |
| 101 | // TODO(galsagie) When learn is added, learn SRC MAC here |
| 102 | DropPacket(ctx, pkt); |
| 103 | } else { |
| 104 | // TODO(galsagie) Other opcodes are not handled yet. |
| 105 | DropPacket(ctx, pkt); |
| 106 | } |
| 107 | } |
| 108 | } |
| 109 | |
| 110 | ADD_MODULE(ArpResponder, "arp_responder", |
| 111 | "Respond to ARP requests and learns new MAC's") |