static int rx_thread(void * param) { struct port_configure * pconf = NULL; //(struct port_configure *) param; struct rte_ring* ring_in = NULL; //pconf->ring_in; struct rte_ring* ring_out = NULL; //pconf->ring_out; uint8_t port_id = 0; //pconf->portid; uint16_t nb_rx_pkts; struct rte_mbuf *m; struct ether_hdr *eth_hdr; struct arp_hdr *arp_hdr; int32_t i, j, k, ret; struct rte_mbuf *pkts[MAX_PKTS_BURST]; int32_t ether_type; struct ipv4_hdr *ip_hdr; struct icmp_hdr* icmp_hdr; struct udp_hdr* udp_hdr; while (!quit_signal) { for (k = 0; k < num_config_port; ++k) { pconf = &ports_conf[k]; ring_in = pconf->ring_in; ring_out = pconf->ring_out; port_id = pconf->portid; nb_rx_pkts = rte_eth_rx_burst(port_id, 0, pkts, MAX_PKTS_BURST); if (unlikely(nb_rx_pkts == 0)) { continue; } for (i = 0; i < nb_rx_pkts; ++i) { m = pkts[i]; eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); ether_type = eth_hdr->ether_type; if (unlikely(rte_cpu_to_be_16(ETHER_TYPE_ARP) == ether_type)) { arp_hdr = (struct arp_hdr *) ((char *) (eth_hdr + 1)); if (arp_hdr->arp_op == rte_cpu_to_be_16(ARP_OP_REQUEST)) { if (arp_hdr->arp_data.arp_tip == (pconf->ip)) { arp_hdr->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY); ether_addr_copy(ð_hdr->s_addr, ð_hdr->d_addr); ether_addr_copy(&pconf->addr, ð_hdr->s_addr); ether_addr_copy(&arp_hdr->arp_data.arp_sha, &arp_hdr->arp_data.arp_tha); arp_hdr->arp_data.arp_tip = arp_hdr->arp_data.arp_sip; ether_addr_copy(&pconf->addr, &arp_hdr->arp_data.arp_sha); arp_hdr->arp_data.arp_sip = (pconf->ip); MMENQUEUE(ring_out, m); } else { MMENQUEUE(ring_arp_request, m); } } else if (arp_hdr->arp_op == rte_cpu_to_be_16(ARP_OP_REPLY)) { MMENQUEUE(ring_arp_reply, m); } else { rte_pktmbuf_free(m); } } else if (likely( rte_cpu_to_be_16(ETHER_TYPE_IPv4) == ether_type)) { ip_hdr = (struct ipv4_hdr *) ((char *) (eth_hdr + 1)); switch (ip_hdr->next_proto_id) { case IPPROTO_ICMP: //printf("nhan ban tin ping\n"); icmp_hdr = (struct icmp_hdr *) ((unsigned char *) ip_hdr + sizeof(struct ipv4_hdr)); if (unlikely( wrapsum( checksum(icmp_hdr, (m->data_len - sizeof(struct ether_hdr) - sizeof(struct ipv4_hdr)), 0)))) { printf("ICMP check sum error\n"); rte_pktmbuf_free(m); break; } if (unlikely( icmp_hdr->icmp_type == IP_ICMP_ECHO_REQUEST)) { if (ntohl(ip_hdr->dst_addr) == INADDR_BROADCAST) { rte_pktmbuf_free(m); } else { icmp_hdr->icmp_type = IP_ICMP_ECHO_REPLY; icmp_hdr->icmp_cksum = 0; icmp_hdr->icmp_cksum = wrapsum( checksum(icmp_hdr, (m->data_len - sizeof(struct ether_hdr) - sizeof(struct ipv4_hdr)), 0)); inetAddrSwap(&ip_hdr->src_addr, &ip_hdr->dst_addr); ip_hdr->packet_id = htons( ntohs(ip_hdr->packet_id) + m->data_len); ip_hdr->hdr_checksum = 0; ip_hdr->hdr_checksum = wrapsum( checksum(ip_hdr, sizeof(struct ipv4_hdr), 0)); ethAddrSwap(ð_hdr->d_addr, ð_hdr->s_addr); MMENQUEUE(ring_out, m); } } else { rte_pktmbuf_free(m); } break; case IPPROTO_UDP: MMENQUEUE(ring_in, m) ; break; default: rte_pktmbuf_free(m); } } else { rte_pktmbuf_free(m); } } } } return 0; }
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++; } } }