@@ -26,22 +26,32 @@ static bool handle_control_packet(worker_t *w, pktbuf_t *b) {
2626
2727 /* Handling of ARP packets */
2828 if (ethertype == ETH_TYPE_ARP ) {
29- if (b -> len >= sizeof (struct eth_hdr ) + sizeof (struct arp_hdr )) {
30- struct arp_hdr * arp = (struct arp_hdr * )(b -> data + sizeof (struct eth_hdr ));
31-
32- /* Hardware Type 1 (Ethernet), Protocol 0x0800 (IPv4), HW Len 6, Proto Len 4 */
33- if (ntohs (arp -> htype ) == 1 && ntohs (arp -> ptype ) == ETH_TYPE_IPV4 &&
34- arp -> hlen == ARP_HW_LEN_ETH && arp -> plen == ARP_PROTO_LEN ) {
35- uint32_t spa = ntohl (arp -> spa ); /* Sender Protocol Address (IP) */
36- arp_update (w -> arpt , spa , arp -> sha );
37- log_msg (LOG_DEBUG , "Learned ARP: %08X -> %02X:%02X:%02X:%02X:%02X:%02X" , spa ,
38- arp -> sha [0 ], arp -> sha [1 ], arp -> sha [2 ], arp -> sha [3 ], arp -> sha [4 ],
39- arp -> sha [5 ]);
29+ struct arp_hdr * arp = (struct arp_hdr * )(b -> data + sizeof (struct eth_hdr ));
30+
31+ if (ntohs (arp -> htype ) == ARP_HW_ETHERNET && ntohs (arp -> ptype ) == ETH_TYPE_IPV4 &&
32+ arp -> hlen == ARP_HW_LEN_ETH && arp -> plen == ARP_PROTO_LEN ) {
33+ /* Learn the sender's MAC/IP mapping */
34+ uint32_t spa = ntohl (arp -> spa );
35+ arp_update (w -> arpt , spa , arp -> sha );
36+ log_msg (LOG_DEBUG , "Learned ARP: %08X -> %02X:%02X:%02X:%02X:%02X:%02X" , spa ,
37+ arp -> sha [0 ], arp -> sha [1 ], arp -> sha [2 ], arp -> sha [3 ], arp -> sha [4 ], arp -> sha [5 ]);
38+
39+ /* If ARP request is for local IP: Re-use incoming buffer to build a reply in-place */
40+ if (ntohs (arp -> op ) == ARP_OP_REQUEST && w -> tx -> ip4_addr != 0 &&
41+ ntohl (arp -> tpa ) == w -> tx -> ip4_addr ) {
42+ memcpy (eth -> dst , eth -> src , 6 );
43+ memcpy (eth -> src , w -> tx -> eth_addr , 6 );
44+
45+ arp -> op = htons (ARP_OP_REPLY );
46+ memcpy (arp -> tha , arp -> sha , 6 );
47+ arp -> tpa = arp -> spa ;
48+ memcpy (arp -> sha , w -> tx -> eth_addr , 6 );
49+ arp -> spa = htonl (w -> tx -> ip4_addr );
50+
51+ tx_send (w -> tx , b -> data , b -> len );
52+ log_msg (LOG_DEBUG , "Sent ARP reply for %08X" , w -> tx -> ip4_addr );
4053 }
4154 }
42- /* Consume the packet */
43- pktbuf_free (w -> pool , b );
44- return true;
4555 }
4656
4757 /* Handling for IPv6 NDP packets (Neighbor Advertisement/Solicitation) */
@@ -220,8 +230,8 @@ static void process_packet(worker_t *w, pktbuf_t *b) {
220230 }
221231 }
222232
223- /* Latency is recorded before queuing for TX (sendmmsg() is kernel/NIC latency, should not
224- * be included in the dataplane latency.)*/
233+ /* Latency is recorded before queuing for TX (sendmmsg() is kernel/NIC latency, should
234+ * not be included in the dataplane latency.)*/
225235 if (b -> timestamp > 0 ) {
226236 latency_record (& w -> latency_hist , rdtsc () - b -> timestamp , g_cycles_per_ns );
227237 }
0 commit comments