• 自定义库

自定义库

方便查看dpdk中的数据包内容

头文件 boi.h

#include <stdint.h>
#include <stdlib.h>
#include <rte_ethdev.h>
#include <rte_ether.h>
#include <rte_mbuf.h>
#include <rte_ip.h>

void
boi_ethernet_print(struct rte_mbuf *mbuf);

void
boi_ipv_print(struct rte_mbuf *mbuf);

void
boi_udp_print(struct rte_mbuf *mbuf);

void
boi_icmp_print(struct rte_mbuf *mbuf);

struct rte_mbuf *
boi_icmp_replay(struct rte_mbuf *pkt);

源文件 boi.c

#include "boi.h"


#define is_multicast_ipv4_addr(ipv4_addr) \
	(((rte_be_to_cpu_32((ipv4_addr)) >> 24) & 0x000000FF) == 0xE0)





static uint16_t
ipv4_hdr_cksum(struct rte_ipv4_hdr *ip_h)
{
	uint16_t *v16_h;
	uint32_t ip_cksum;

	/*
	 * Compute the sum of successive 16-bit words of the IPv4 header,
	 * skipping the checksum field of the header.
	 */
	v16_h = (unaligned_uint16_t *) ip_h;
	ip_cksum = v16_h[0] + v16_h[1] + v16_h[2] + v16_h[3] +
		v16_h[4] + v16_h[6] + v16_h[7] + v16_h[8] + v16_h[9];

	/* reduce 32 bit checksum to 16 bits and complement it */
	ip_cksum = (ip_cksum & 0xffff) + (ip_cksum >> 16);
	ip_cksum = (ip_cksum & 0xffff) + (ip_cksum >> 16);
	ip_cksum = (~ip_cksum) & 0x0000FFFF;
	return (ip_cksum == 0) ? 0xFFFF : (uint16_t) ip_cksum;
}

void
boi_ethernet_print(struct rte_mbuf *mbuf);

// 打印 MAC 地址的辅助函数
void print_mac_address(struct rte_ether_addr *mac) {
    printf("%02x:%02x:%02x:%02x:%02x:%02x\n", 
           mac->addr_bytes[0], mac->addr_bytes[1], mac->addr_bytes[2],
           mac->addr_bytes[3], mac->addr_bytes[4], mac->addr_bytes[5]);
}

/* 另一种方式打印mac地址
ret = rte_eth_macaddr_get(i, &mac);
if (ret == 0) {
    char ebuf[RTE_ETHER_ADDR_FMT_SIZE];

    rte_ether_format_addr(ebuf, sizeof(ebuf), &mac);
    printf("\t  -- mac %s\n", ebuf);
}
 */

/*
另一种方式打印ip地址
ipv4_addr_dump("  IPV4: src=", ip_h->src_addr);


static void
ipv4_addr_dump(const char *what, uint32_t be_ipv4_addr)
{
	char buf[16];

	ipv4_addr_to_dot(be_ipv4_addr, buf);
	if (what)
		printf("%s", what);
	printf("%s", buf);
}
 */

void
boi_ethernet_print(struct rte_mbuf *mbuf)
{
    struct rte_ether_hdr *ehdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *);
    printf("boi src mac is : ");
    print_mac_address(&ehdr->src_addr);
    printf("boi dst mac is: ");
    print_mac_address(&ehdr->dst_addr);
    printf("boi bype  is 0x%04x\n", rte_cpu_to_be_16(ehdr->ether_type));
}

void
boi_ipv_print(struct rte_mbuf *mbuf)
{

    struct rte_ipv4_hdr * ip_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr));
    printf("boi ip versision and head length is %x\n", ip_hdr->version_ihl);
    printf("ttl is %d\n", ip_hdr->time_to_live);
    printf("source ip  is %s\n", inet_ntoa(*(struct in_addr*)&ip_hdr->src_addr));
    printf("dest ip is %s\n", inet_ntoa(*(struct in_addr*)&ip_hdr->dst_addr));
    printf("proto id is  %d\n", ip_hdr->next_proto_id);
    printf("packet id is  %d\n", ip_hdr->packet_id);
    printf("fragment offset is  %d\n", ip_hdr->fragment_offset);
    // printf("hdr_checksum is  %x\n", ip_hdr->hdr_checksum); //没意义
}

void
boi_udp_print(struct rte_mbuf *mbuf)
{
    struct rte_ipv4_hdr * ip_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr));
    if (ip_hdr->next_proto_id != IPPROTO_UDP){
        printf("proto id not udp 17\n");
        return;
    }
    struct rte_udp_hdr *udphdr = (struct rte_udp_hdr *)(ip_hdr+1);
    printf("boi src port is %d\n", (rte_be_to_cpu_16(udphdr->src_port)));
    printf("dst port is %d\n", (rte_be_to_cpu_16(udphdr->src_port)));
    printf("length is %d\n", (rte_be_to_cpu_16(udphdr->dgram_len)));
    printf("checksum is %x\n", (rte_be_to_cpu_16(udphdr->dgram_cksum)));
    uint16_t length = udphdr->dgram_len;
    *(char *)(udphdr + length-1) = '\0';
    printf("data is: %s\n", (char *)(udphdr+1));
    printf("------------------------------ \n");
}

void
boi_icmp_print(struct rte_mbuf *mbuf) {

    struct rte_ipv4_hdr * ip_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr));
    // 获取 IPv4 头部
    if (ip_hdr->next_proto_id != IPPROTO_ICMP){
        printf("proto id not icmp 1\n");
        return ;
    }
    struct rte_icmp_hdr *icmp_hdr = (struct rte_icmp_hdr *)(ip_hdr+1);
    // 输出 ICMP 包的相关信息
    printf("ICMP Packet: \n");
    printf("  Type: %u\n", icmp_hdr->icmp_type);
    printf("  Code: %u\n", icmp_hdr->icmp_code);
    printf("  Checksum: %u\n", icmp_hdr->icmp_cksum);
    printf("  request seq id=%d\n",
			       rte_be_to_cpu_16(icmp_hdr->icmp_seq_nb));
}

struct rte_mbuf *
boi_icmp_replay(struct rte_mbuf *pkt)
{
	struct rte_ether_hdr *eth_h;
	struct rte_vlan_hdr *vlan_h;
	struct rte_ipv4_hdr *ip_h;
	struct rte_icmp_hdr *icmp_h;
	struct rte_ether_addr eth_addr;
	uint32_t ip_addr;

	uint16_t eth_type;

	uint32_t cksum;
	int l2_len;


    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 (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);
    }

    ip_h = (struct rte_ipv4_hdr *) ((char *)eth_h + l2_len);


    /*
        * 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);
        printf("now icmp\n");
        return NULL;
    }

    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;
    return pkt;
}