- if ((hdr_arp->arp.data.tpa == ip) || (ip == 0)) {
- build_arp_reply(hdr_arp, s_addr);
- return 0;
- } else if (task->runtime_flags & TASK_MULTIPLE_MAC) {
- struct ether_addr tmp_s_addr;
- create_mac(hdr_arp, &tmp_s_addr);
- build_arp_reply(hdr_arp, &tmp_s_addr);
- return 0;
- } else {
- plogx_dbg("Received ARP on unexpected IP %x, expecting %x\n", rte_be_to_cpu_32(hdr_arp->arp.data.tpa), rte_be_to_cpu_32(ip));
- return OUT_DISCARD;
+ // MAC address is 01:00:5e followed by 23 LSB of IP address
+ uint64_t mac = 0x0000005e0001L | ((ip & 0xFFFF7F00L) << 16);
+ memcpy(dst_mac, &mac, sizeof(prox_rte_ether_addr));
+}
+
+static inline void build_icmp_reply_message(struct task_base *tbase, struct rte_mbuf *mbuf)
+{
+ struct task_swap *task = (struct task_swap *)tbase;
+ prox_rte_ether_hdr *hdr = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
+ prox_rte_ether_addr dst_mac;
+ prox_rte_ether_addr_copy(&hdr->s_addr, &dst_mac);
+ prox_rte_ether_addr_copy(&hdr->d_addr, &hdr->s_addr);
+ prox_rte_ether_addr_copy(&dst_mac, &hdr->d_addr);
+ prox_rte_ipv4_hdr *ip_hdr = (prox_rte_ipv4_hdr *)(hdr + 1);
+ ip_hdr->dst_addr = ip_hdr->src_addr;
+ ip_hdr->src_addr = task->local_ipv4;
+ prox_rte_icmp_hdr *picmp = (prox_rte_icmp_hdr *)(ip_hdr + 1);
+ picmp->icmp_type = PROX_RTE_IP_ICMP_ECHO_REPLY;
+}
+
+static inline void build_igmp_message(struct task_base *tbase, struct rte_mbuf *mbuf, uint32_t ip, uint8_t igmp_message)
+{
+ struct task_swap *task = (struct task_swap *)tbase;
+ prox_rte_ether_hdr *hdr = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
+ prox_rte_ether_addr dst_mac;
+ build_mcast_mac(ip, &dst_mac);
+
+ rte_pktmbuf_pkt_len(mbuf) = 46;
+ rte_pktmbuf_data_len(mbuf) = 46;
+ init_mbuf_seg(mbuf);
+
+ prox_rte_ether_addr_copy(&dst_mac, &hdr->d_addr);
+ prox_rte_ether_addr_copy((prox_rte_ether_addr *)&task->src_dst_mac[6], &hdr->s_addr);
+ hdr->ether_type = ETYPE_IPv4;
+
+ prox_rte_ipv4_hdr *ip_hdr = (prox_rte_ipv4_hdr *)(hdr + 1);
+ ip_hdr->version_ihl = 0x45; /**< version and header length */
+ ip_hdr->type_of_service = 0; /**< type of service */
+ ip_hdr->total_length = rte_cpu_to_be_16(32); /**< length of packet */
+ ip_hdr->packet_id = 0; /**< packet ID */
+ ip_hdr->fragment_offset = 0; /**< fragmentation offset */
+ ip_hdr->time_to_live = 1; /**< time to live */
+ ip_hdr->next_proto_id = IPPROTO_IGMP; /**< protocol ID */
+ ip_hdr->hdr_checksum = 0; /**< header checksum */
+ ip_hdr->src_addr = task->local_ipv4; /**< source address */
+ ip_hdr->dst_addr = ip; /**< destination address */
+ struct igmpv2_hdr *pigmp = (struct igmpv2_hdr *)(ip_hdr + 1);
+ pigmp->type = igmp_message;
+ pigmp->max_resp_time = 0;
+ pigmp->checksum = 0;
+ pigmp->group_address = ip;
+ prox_ip_udp_cksum(mbuf, ip_hdr, sizeof(prox_rte_ether_hdr), sizeof(prox_rte_ipv4_hdr), task->offload_crc);
+}
+
+static void stop_swap(struct task_base *tbase)
+{
+ struct task_swap *task = (struct task_swap *)tbase;
+ if (task->igmp_pool) {
+ rte_mempool_free(task->igmp_pool);
+ task->igmp_pool = NULL;