void pktgen_send_ping4( uint32_t pid, uint8_t seq_idx ) { port_info_t * info = &pktgen.info[pid]; pkt_seq_t * ppkt = &info->seq_pkt[PING_PKT]; pkt_seq_t * spkt = &info->seq_pkt[seq_idx]; struct rte_mbuf * m ; uint8_t qid = 0; m = rte_pktmbuf_alloc(info->q[qid].special_mp); if ( unlikely(m == NULL) ) { pktgen_log_warning("No packet buffers found"); return; } *ppkt = *spkt; // Copy the sequence setup to the ping setup. pktgen_packet_ctor(info, PING_PKT, ICMP4_ECHO); rte_memcpy((uint8_t *)m->buf_addr + m->data_off, (uint8_t *)&ppkt->hdr, ppkt->pktSize); m->pkt_len = ppkt->pktSize; m->data_len = ppkt->pktSize; pktgen_send_mbuf(m, pid, qid); pktgen_set_q_flags(info, qid, DO_TX_FLUSH); }
void pktgen_send_arp( uint32_t pid, uint32_t type, uint8_t seq_idx ) { port_info_t * info = &pktgen.info[pid]; pkt_seq_t * pkt; struct rte_mbuf * m ; struct ether_hdr * eth; arpPkt_t * arp; uint32_t addr; uint8_t qid = 0; pkt = &info->seq_pkt[seq_idx]; m = rte_pktmbuf_alloc(info->q[qid].special_mp); if ( unlikely(m == NULL) ) { pktgen_log_warning("No packet buffers found"); return; } eth = rte_pktmbuf_mtod(m, struct ether_hdr *); arp = (arpPkt_t *)ð[1]; /* src and dest addr */ memset(ð->d_addr, 0xFF, 6); ether_addr_copy(&pkt->eth_src_addr, ð->s_addr); eth->ether_type = htons(ETHER_TYPE_ARP); memset(arp, 0, sizeof(arpPkt_t)); rte_memcpy( &arp->sha, &pkt->eth_src_addr, 6 ); addr = htonl(pkt->ip_src_addr); inetAddrCopy(&arp->spa, &addr); if ( likely(type == GRATUITOUS_ARP) ) { rte_memcpy( &arp->tha, &pkt->eth_src_addr, 6 ); addr = htonl(pkt->ip_src_addr); inetAddrCopy(&arp->tpa, &addr); } else { memset( &arp->tha, 0, 6 ); addr = htonl(pkt->ip_dst_addr); inetAddrCopy(&arp->tpa, &addr); } /* Fill in the rest of the ARP packet header */ arp->hrd = htons(ETH_HW_TYPE); arp->pro = htons(ETHER_TYPE_IPv4); arp->hln = 6; arp->pln = 4; arp->op = htons(ARP_REQUEST); m->pkt.pkt_len = 60; m->pkt.data_len = 60; pktgen_send_mbuf(m, pid, qid); pktgen_set_q_flags(info, qid, DO_TX_FLUSH); }
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++; } } }