void pktgen_process_arp( struct rte_mbuf * m, uint32_t pid, uint32_t vlan ) { port_info_t * info = &pktgen.info[pid]; pkt_seq_t * pkt; struct ether_hdr *eth = rte_pktmbuf_mtod(m, struct ether_hdr *); arpPkt_t * arp = (arpPkt_t *)ð[1]; /* Adjust for a vlan header if present */ if ( vlan ) arp = (arpPkt_t *)((char *)arp + sizeof(struct vlan_hdr)); // Process all ARP requests if they are for us. if ( arp->op == htons(ARP_REQUEST) ) { if ((rte_atomic32_read(&info->port_flags) & PROCESS_GARP_PKTS) && (arp->tpa._32 == arp->spa._32) ) { /* Must be a GARP packet */ pkt = pktgen_find_matching_ipdst(info, arp->spa._32); /* Found a matching packet, replace the dst address */ if ( pkt ) { rte_memcpy(&pkt->eth_dst_addr, &arp->sha, 6); pktgen_set_q_flags(info, wr_get_txque(pktgen.l2p, rte_lcore_id(), pid), DO_TX_CLEANUP); pktgen_redisplay(0); } return; } pkt = pktgen_find_matching_ipsrc(info, arp->tpa._32); /* ARP request not for this interface. */ if ( likely(pkt != NULL) ) { /* Grab the source MAC address as the destination address for the port. */ if ( unlikely(pktgen.flags & MAC_FROM_ARP_FLAG) ) { uint32_t i; rte_memcpy(&pkt->eth_dst_addr, &arp->sha, 6); for (i = 0; i < info->seqCnt; i++) pktgen_packet_ctor(info, i, -1); } // Swap the two MAC addresses ethAddrSwap(&arp->sha, &arp->tha); // Swap the two IP addresses inetAddrSwap(&arp->tpa._32, &arp->spa._32); // Set the packet to ARP reply arp->op = htons(ARP_REPLY); // Swap the MAC addresses ethAddrSwap(ð->d_addr, ð->s_addr); // Copy in the MAC address for the reply. rte_memcpy(&arp->sha, &pkt->eth_src_addr, 6); rte_memcpy(ð->s_addr, &pkt->eth_src_addr, 6); pktgen_send_mbuf(m, pid, 0); // Flush all of the packets in the queue. pktgen_set_q_flags(info, 0, DO_TX_FLUSH); // No need to free mbuf as it was reused return; } } else if ( arp->op == htons(ARP_REPLY) ) { pkt = pktgen_find_matching_ipsrc(info, arp->tpa._32); // ARP request not for this interface. if ( likely(pkt != NULL) ) { // Grab the real destination MAC address if ( pkt->ip_dst_addr == ntohl(arp->spa._32) ) rte_memcpy(&pkt->eth_dst_addr, &arp->sha, 6); pktgen.flags |= PRINT_LABELS_FLAG; } } }
void pktgen_process_ping4( struct rte_mbuf * m, uint32_t pid, uint32_t vlan ) { port_info_t * info = &pktgen.info[pid]; pkt_seq_t * pkt; struct ether_hdr *eth = rte_pktmbuf_mtod(m, struct ether_hdr *); ipHdr_t * ip = (ipHdr_t *)ð[1]; char buff[24]; /* Adjust for a vlan header if present */ if ( vlan ) ip = (ipHdr_t *)((char *)ip + sizeof(struct vlan_hdr)); // Look for a ICMP echo requests, but only if enabled. if ( (rte_atomic32_read(&info->port_flags) & ICMP_ECHO_ENABLE_FLAG) && (ip->proto == PG_IPPROTO_ICMP) ) { #if !defined(RTE_ARCH_X86_64) icmpv4Hdr_t * icmp = (icmpv4Hdr_t *)((uint32_t)ip + sizeof(ipHdr_t)); #else icmpv4Hdr_t * icmp = (icmpv4Hdr_t *)((uint64_t)ip + sizeof(ipHdr_t)); #endif // We do not handle IP options, which will effect the IP header size. if ( unlikely(cksum(icmp, (m->data_len - sizeof(struct ether_hdr) - sizeof(ipHdr_t)), 0)) ) { pktgen_log_error("ICMP checksum failed"); return; } if ( unlikely(icmp->type == ICMP4_ECHO) ) { if ( ntohl(ip->dst) == INADDR_BROADCAST ) { pktgen_log_warning("IP address %s is a Broadcast", inet_ntop4(buff, sizeof(buff), ip->dst, INADDR_BROADCAST)); return; } // Toss all broadcast addresses and requests not for this port pkt = pktgen_find_matching_ipsrc(info, ip->dst); // ARP request not for this interface. if ( unlikely(pkt == NULL) ) { pktgen_log_warning("IP address %s not found", inet_ntop4(buff, sizeof(buff), ip->dst, INADDR_BROADCAST)); return; } info->stats.echo_pkts++; icmp->type = ICMP4_ECHO_REPLY; /* Recompute the ICMP checksum */ icmp->cksum = 0; icmp->cksum = cksum(icmp, (m->data_len - sizeof(struct ether_hdr) - sizeof(ipHdr_t)), 0); // Swap the IP addresses. inetAddrSwap(&ip->src, &ip->dst); // Bump the ident value ip->ident = htons(ntohs(ip->ident) + m->data_len); // Recompute the IP checksum ip->cksum = 0; ip->cksum = cksum(ip, sizeof(ipHdr_t), 0); // Swap the MAC addresses ethAddrSwap(ð->d_addr, ð->s_addr); pktgen_send_mbuf(m, pid, 0); pktgen_set_q_flags(info, 0, DO_TX_FLUSH); // No need to free mbuf as it was reused. return; } else if ( unlikely(icmp->type == ICMP4_ECHO_REPLY) ) { info->stats.echo_pkts++; } } }