dpdk-22.07.0-testpmd测试进程响应icmp请求

编译dpdk

meson build
ninja -C build

mkdir -p /dev/hugepages
mountpoint -q /dev/hugepages || mount -t hugetlbfs nodev /dev/hugepages
echo 64 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages

ninja app/dpdk-testpmd

环境搭建

1.先通过./usertools/dpdk-devbind.py -s获取网卡的总线地址
2.用ifconfig ens34 down 命令将eth接口down掉
3.modprobe uio.ko
4.下载dpdk-kmods源码,并进入目录编译生成igb_uio.ko模块
5.insmod igb_uio.ko
6.dpdk-devbind.py --bind=igb_uio xxxx:xx:xx.x 绑定网卡总线地址
7.运行./app/dpdk-testpmd – -i --forward-mode=icmpecho
8.set verbose 2

testpmd> show port info all

********************* Infos for port 0  *********************
MAC address: 00:0C:29:A8:09:8A
Device name: 0000:02:06.0
Driver name: net_e1000_em
Firmware-version: not available
Connect to socket: 0
memory allocation on the socket: 0
Link status: up
Link speed: 1 Gbps
Link duplex: full-duplex
Autoneg status: On
MTU: 1500
Promiscuous mode: enabled
Allmulticast mode: disabled
Maximum number of MAC addresses: 15
Maximum number of MAC addresses of hash filtering: 0
VLAN offload:
  strip off, filter off, extend off, qinq strip off
No RSS offload flow type is supported.
Minimum size of RX buffer: 256
Maximum configurable length of RX packet: 16128
Maximum configurable size of LRO aggregated packet: 0
Current number of RX queues: 1
Max possible RX queues: 1
Max possible number of RXDs per queue: 4096
Min possible number of RXDs per queue: 32
RXDs number alignment: 8
Current number of TX queues: 1
Max possible TX queues: 1
Max possible number of TXDs per queue: 4096
Min possible number of TXDs per queue: 32
TXDs number alignment: 8
Max segment number per packet: 255
Max segment number per MTU/TSO: 255
Device capabilities: 0x0( )

8.获取MAC地址调用命令绑定arp表 arp -s 192.168.139.133 00:0C:29:A8:09:8A 并ping 192.168.139.133地址

9.打印信息

testpmd> start
icmpecho packet forwarding - ports=1 - cores=1 - streams=1 - NUMA support enabled, MP allocation mode: native
Logical Core 1 (socket 0) forwards packets on 1 streams:
  RX P=0/Q=0 (socket 0) -> TX P=0/Q=0 (socket 0) peer=02:00:00:00:00:00

  icmpecho packet forwarding packets/burst=32
  nb forwarding cores=1 - nb forwarding ports=1
  port 0: RX queue number: 1 Tx queue number: 1
    Rx offloads=0x0 Tx offloads=0x0
    RX queue: 0
      RX desc=256 - RX free threshold=0
      RX threshold registers: pthresh=0 hthresh=0  wthresh=0
      RX Offloads=0x0
    TX queue: 0
      TX desc=256 - TX free threshold=32
      TX threshold registers: pthresh=0 hthresh=0  wthresh=0
      TX offloads=0x0 - TX RS bit threshold=32
testpmd>
tanjun hello world   Port 0 pkt-len=247 nb-segs=1
  ETH:  src=00:0C:29:A8:09:94 dst=FF:FF:FF:FF:FF:FF type=0x0800
  IPV4: src=192.168.139.131 dst=192.168.139.255 proto=17 (UDP)

tanjun hello world   Port 0 pkt-len=247 nb-segs=1
  ETH:  src=00:0C:29:A8:09:94 dst=FF:FF:FF:FF:FF:FF type=0x0800
  IPV4: src=192.168.139.131 dst=192.168.139.255 proto=17 (UDP)

tanjun hello world   Port 0 pkt-len=247 nb-segs=1
  ETH:  src=00:0C:29:A8:09:94 dst=FF:FF:FF:FF:FF:FF type=0x0800
  IPV4: src=192.168.139.131 dst=192.168.139.255 proto=17 (UDP)

代码解析

reply_to_icmp_echo_rqsts(struct fwd_stream *fs)
{
	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
	struct rte_mbuf *pkt;
	struct rte_ether_hdr *eth_h;
	struct rte_vlan_hdr *vlan_h;
	struct rte_arp_hdr  *arp_h;
	struct rte_ipv4_hdr *ip_h;
	struct rte_icmp_hdr *icmp_h;
	struct rte_ether_addr eth_addr;
	uint32_t retry;
	uint32_t ip_addr;
	uint16_t nb_rx;
	uint16_t nb_tx;
	uint16_t nb_replies;
	uint16_t eth_type;
	uint16_t vlan_id;
	uint16_t arp_op;
	uint16_t arp_pro;
	uint32_t cksum;
	uint8_t  i;
	int l2_len;
	uint64_t start_tsc = 0;

	get_start_cycles(&start_tsc);
	int tanjun_test=verbose_level;
	verbose_level=1;
	/*
	 * First, receive a burst of packets.
	 */
	nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst,
				 nb_pkt_per_burst);
	inc_rx_burst_stats(fs, nb_rx);
	if (unlikely(nb_rx == 0))
		return;

	fs->rx_packets += nb_rx;
	nb_replies = 0;
	for (i = 0; i < nb_rx; i++) {
		if (likely(i < nb_rx - 1))
			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
						       void *));
		pkt = pkts_burst[i];
		eth_h = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
		eth_type = RTE_BE_TO_CPU_16(eth_h->ether_type);
		l2_len = sizeof(struct rte_ether_hdr);
		if (verbose_level > 0) {
			printf("\ntanjun hello world   Port %d pkt-len=%u nb-segs=%u\n",
			       fs->rx_port, pkt->pkt_len, pkt->nb_segs);
			ether_addr_dump("  ETH:  src=", &eth_h->src_addr);
			ether_addr_dump(" dst=", &eth_h->dst_addr);
		}
		if (eth_type == RTE_ETHER_TYPE_VLAN) {
			vlan_h = (struct rte_vlan_hdr *)
				((char *)eth_h + sizeof(struct rte_ether_hdr));
			l2_len  += sizeof(struct rte_vlan_hdr);
			eth_type = rte_be_to_cpu_16(vlan_h->eth_proto);
			if (verbose_level > 0) {
				vlan_id = rte_be_to_cpu_16(vlan_h->vlan_tci)
					& 0xFFF;
				printf(" [vlan id=%u]", vlan_id);
			}
		}
		if (verbose_level > 0) {
			printf(" type=0x%04x\n", eth_type);
		}

		/* Reply to ARP requests */
		if (eth_type == RTE_ETHER_TYPE_ARP) {
			arp_h = (struct rte_arp_hdr *) ((char *)eth_h + l2_len);
			arp_op = RTE_BE_TO_CPU_16(arp_h->arp_opcode);
			arp_pro = RTE_BE_TO_CPU_16(arp_h->arp_protocol);
			if (verbose_level > 0) {
				printf("  ARP:  hrd=%d proto=0x%04x hln=%d "
				       "pln=%d op=%u (%s)\n",
				       RTE_BE_TO_CPU_16(arp_h->arp_hardware),
				       arp_pro, arp_h->arp_hlen,
				       arp_h->arp_plen, arp_op,
				       arp_op_name(arp_op));
			}
			if ((RTE_BE_TO_CPU_16(arp_h->arp_hardware) !=
			     RTE_ARP_HRD_ETHER) ||
			    (arp_pro != RTE_ETHER_TYPE_IPV4) ||
			    (arp_h->arp_hlen != 6) ||
			    (arp_h->arp_plen != 4)
			    ) {
				rte_pktmbuf_free(pkt);
				if (verbose_level > 0)
					printf("\n");
				continue;
			}
			if (verbose_level > 0) {
				rte_ether_addr_copy(&arp_h->arp_data.arp_sha,
						&eth_addr);
				ether_addr_dump("        sha=", &eth_addr);
				ip_addr = arp_h->arp_data.arp_sip;
				ipv4_addr_dump(" sip=", ip_addr);
				printf("\n");
				rte_ether_addr_copy(&arp_h->arp_data.arp_tha,
						&eth_addr);
				ether_addr_dump("        tha=", &eth_addr);
				ip_addr = arp_h->arp_data.arp_tip;
				ipv4_addr_dump(" tip=", ip_addr);
				printf("\n");
			}
			if (arp_op != RTE_ARP_OP_REQUEST) {
				rte_pktmbuf_free(pkt);
				continue;
			}

			/*
			 * Build ARP reply.
			 */

			/* Use source MAC address as destination MAC address. */
			rte_ether_addr_copy(&eth_h->src_addr, &eth_h->dst_addr);
			/* Set source MAC address with MAC address of TX port */
			rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
					&eth_h->src_addr);

			arp_h->arp_opcode = rte_cpu_to_be_16(RTE_ARP_OP_REPLY);
			rte_ether_addr_copy(&arp_h->arp_data.arp_tha,
					&eth_addr);
			rte_ether_addr_copy(&arp_h->arp_data.arp_sha,
					&arp_h->arp_data.arp_tha);
			rte_ether_addr_copy(&eth_h->src_addr,
					&arp_h->arp_data.arp_sha);

			/* Swap IP addresses in ARP payload */
			ip_addr = arp_h->arp_data.arp_sip;
			arp_h->arp_data.arp_sip = arp_h->arp_data.arp_tip;
			arp_h->arp_data.arp_tip = ip_addr;
			pkts_burst[nb_replies++] = pkt;
			continue;
		}

		if (eth_type != RTE_ETHER_TYPE_IPV4) {
			rte_pktmbuf_free(pkt);
			continue;
		}
		ip_h = (struct rte_ipv4_hdr *) ((char *)eth_h + l2_len);
		if (verbose_level > 0) {
			ipv4_addr_dump("  IPV4: src=", ip_h->src_addr);
			ipv4_addr_dump(" dst=", ip_h->dst_addr);
			printf(" proto=%d (%s)\n",
			       ip_h->next_proto_id,
			       ip_proto_name(ip_h->next_proto_id));
		}

		/*
		 * Check if packet is a ICMP echo request.
		 */
		icmp_h = (struct rte_icmp_hdr *) ((char *)ip_h +
					      sizeof(struct rte_ipv4_hdr));
		if (! ((ip_h->next_proto_id == IPPROTO_ICMP) &&
		       (icmp_h->icmp_type == RTE_IP_ICMP_ECHO_REQUEST) &&
		       (icmp_h->icmp_code == 0))) {
			rte_pktmbuf_free(pkt);
			continue;
		}

		if (verbose_level > 0)
			printf("  ICMP: echo request seq id=%d\n",
			       rte_be_to_cpu_16(icmp_h->icmp_seq_nb));

		/*
		 * Prepare ICMP echo reply to be sent back.
		 * - switch ethernet source and destinations addresses,
		 * - use the request IP source address as the reply IP
		 *    destination address,
		 * - if the request IP destination address is a multicast
		 *   address:
		 *     - choose a reply IP source address different from the
		 *       request IP source address,
		 *     - re-compute the IP header checksum.
		 *   Otherwise:
		 *     - switch the request IP source and destination
		 *       addresses in the reply IP header,
		 *     - keep the IP header checksum unchanged.
		 * - set RTE_IP_ICMP_ECHO_REPLY in ICMP header.
		 * ICMP checksum is computed by assuming it is valid in the
		 * echo request and not verified.
		 */
		rte_ether_addr_copy(&eth_h->src_addr, &eth_addr);
		rte_ether_addr_copy(&eth_h->dst_addr, &eth_h->src_addr);
		rte_ether_addr_copy(&eth_addr, &eth_h->dst_addr);
		ip_addr = ip_h->src_addr;
		if (is_multicast_ipv4_addr(ip_h->dst_addr)) {
			uint32_t ip_src;

			ip_src = rte_be_to_cpu_32(ip_addr);
			if ((ip_src & 0x00000003) == 1)
				ip_src = (ip_src & 0xFFFFFFFC) | 0x00000002;
			else
				ip_src = (ip_src & 0xFFFFFFFC) | 0x00000001;
			ip_h->src_addr = rte_cpu_to_be_32(ip_src);
			ip_h->dst_addr = ip_addr;
			ip_h->hdr_checksum = ipv4_hdr_cksum(ip_h);
		} else {
			ip_h->src_addr = ip_h->dst_addr;
			ip_h->dst_addr = ip_addr;
		}
		icmp_h->icmp_type = RTE_IP_ICMP_ECHO_REPLY;
		cksum = ~icmp_h->icmp_cksum & 0xffff;
		cksum += ~RTE_BE16(RTE_IP_ICMP_ECHO_REQUEST << 8) & 0xffff;
		cksum += RTE_BE16(RTE_IP_ICMP_ECHO_REPLY << 8);
		cksum = (cksum & 0xffff) + (cksum >> 16);
		cksum = (cksum & 0xffff) + (cksum >> 16);
		icmp_h->icmp_cksum = ~cksum;
		pkts_burst[nb_replies++] = pkt;
	}

	/* Send back ICMP echo replies, if any. */
	if (nb_replies > 0) {
		nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst,
					 nb_replies);
		/*
		 * Retry if necessary
		 */
		if (unlikely(nb_tx < nb_replies) && fs->retry_enabled) {
			retry = 0;
			while (nb_tx < nb_replies &&
					retry++ < burst_tx_retry_num) {
				rte_delay_us(burst_tx_delay_time);
				nb_tx += rte_eth_tx_burst(fs->tx_port,
						fs->tx_queue,
						&pkts_burst[nb_tx],
						nb_replies - nb_tx);
			}
		}
		fs->tx_packets += nb_tx;
		inc_tx_burst_stats(fs, nb_tx);
		if (unlikely(nb_tx < nb_replies)) {
			fs->fwd_dropped += (nb_replies - nb_tx);
			do {
				rte_pktmbuf_free(pkts_burst[nb_tx]);
			} while (++nb_tx < nb_replies);
		}
	}
	verbose_level=tanjun_test;
	get_end_cycles(fs, start_tsc);
}

verbose_level变量为控制打印信息的开关

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值