-1

Code image

Hello DPDK Users, I was trying to generate the incremental data value of UDP packets via DPDK. But when I am transmitting it, I verified the same frames in Wireshark. The data part of packets is changing illogically. No sequence can be seen in data. It is optimized the data value which I was wrote. The last value i tried to write was there in all the bytes of payload, not as expected in incremental order. Can anyone help me, why is this occurring and what could be the easiest way to generate incremental DPDK packets? The Code is given in the image file above.

  • 1
    it would help a lot to have you code in the question (not as a picture..) – The Fabio Nov 05 '19 at 13:11
  • 1
    Please copy the code from the image into the question so people can run and debug it themselves. – LW001 Nov 05 '19 at 14:29
  • Hey @TheFabio and LW001 I am newbie on stackoverflow don't know much about how to frame code in question. So for now I am attaching latest complete code, where with packetsend_withSequence() I am trying to transmit UDP packets with incremental data but I am receiving packets in incorrect sequence. ( I am attaching code in answer please have a look.) – Sarvesh Verma Nov 07 '19 at 04:40

1 Answers1

0
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>

#include <inttypes.h> 
#include<assert.h>                            
uint64_t temp1;
uint64_t temp2;                                   
int temp3;
int test_type;
double sec;
time_t start_t,end_t;
double diff_t;

#include<time.h>                                 
#include<signal.h>
#include<linux/kernel.h>                          


#include <rte_memory.h>
#include <rte_launch.h>
#include <rte_eal.h>
#include <rte_per_lcore.h>
#include <rte_lcore.h>
#include <rte_ethdev.h>
#include <rte_udp.h>
#include <rte_tcp.h>                                                                   
#include <rte_ip.h>                                                                     
#include <rte_arp.h>                                                                   
#include <rte_icmp.h>                                                                  
#include <rte_cycles.h>                                                                 
#include <rte_lcore.h>                                                                 
#include <rte_mbuf.h>                                                                   


#define RX_RING_SIZE 2028 
#define TX_RING_SIZE 2048

#define NUM_MBUFS 8191
#define MBUF_CACHE_SIZE 250
#define BURST_SIZE 32

#define UDP_SRC_PORT 6666
#define UDP_DST_PORT 6666
#define TCP_SRC_PORT 6666
#define TCP_DST_PORT 6666                                                              
#define IP_DEFTTL  64   
#define IP_VERSION 0x40
#define IP_HDRLEN  0x05 
#define IP_VHL_DEF (IP_VERSION | IP_HDRLEN)

#define TX_PACKET_LENGTH 64
#define ETHER_MAX_LEN 1518
#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
#define RTE_BE_TO_CPU_16(be_16_v)  (be_16_v)
#define RTE_CPU_TO_BE_16(cpu_16_v) (cpu_16_v)
#else
#define RTE_BE_TO_CPU_16(be_16_v) \
        (uint16_t) ((((be_16_v) & 0xFF) << 8) | ((be_16_v) >> 8))
#define RTE_CPU_TO_BE_16(cpu_16_v) \
        (uint16_t) ((((cpu_16_v) & 0xFF) << 8) | ((cpu_16_v) >> 8))
#endif
#define rte_ctrlmbuf_data(m) ((char *)((m)->buf_addr)+(m)->data_off)

// convert a quad-dot IP string to uint32_t IP address
uint32_t string_to_ip(char *s) {
    unsigned char a[4];
    int rc = sscanf(s, "%d.%d.%d.%d",a+0,a+1,a+2,a+3);  
    if(rc != 4){
            fprintf(stderr, "bad source IP address format. Use like: -s 198.19.111.179\n");
            exit(1);
    }

    return
        (uint32_t)(a[0]) << 24 |
        (uint32_t)(a[1]) << 16 |
        (uint32_t)(a[2]) << 8 |
        (uint32_t)(a[3]);

}

// convert six colon separated hex bytes string to uint64_t Ethernet MAC address
uint64_t string_to_mac(char *s) {
    unsigned char a[6];
    int rc = sscanf(s, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
                    a + 0, a + 1, a + 2, a + 3, a + 4, a + 5);
    if(rc !=6 ){
    fprintf(stderr, "bad MAC address format. Use like: -m 0a:38:ca:f6:f3:20\n");
    exit(1);
    }

    return
        (uint64_t)(a[0]) << 40 |
        (uint64_t)(a[1]) << 32 |
        (uint64_t)(a[2]) << 24 |
        (uint64_t)(a[3]) << 16 |
        (uint64_t)(a[4]) << 8 |
        (uint64_t)(a[5]);
}

uint64_t DST_MAC;
uint32_t IP_SRC_ADDR,IP_DST_ADDR;


static const struct rte_eth_conf port_conf_default = {
        .rxmode = { .max_rx_pkt_len = RTE_ETHER_MAX_LEN }
};

static struct rte_ipv4_hdr  pkt_ip_hdr;  
static struct rte_udp_hdr pkt_udp_hdr;

struct rte_ether_addr my_addr; 
struct rte_mempool *mbuf_pool;
struct rte_data_hdr pkt_data_hdr;



static void setup_pkt_udp_ip_headers(struct rte_ipv4_hdr *ip_hdr,
              struct rte_udp_hdr *pudp_hdr,
              uint16_t pkt_data_len)
{
    uint16_t *ptr16;
    uint32_t ip_cksum;
    uint16_t pkt_len;

    int sizeof_=sizeof(struct rte_udp_hdr);
    int sizeof__=sizeof(struct rte_ipv4_hdr);

        //initialize udp headers
        pkt_len = (uint16_t) (pkt_data_len + sizeof_);
        pudp_hdr->src_port = rte_cpu_to_be_16(UDP_SRC_PORT);
        pudp_hdr->dst_port = rte_cpu_to_be_16(UDP_DST_PORT);
        pudp_hdr->dgram_len      = RTE_CPU_TO_BE_16(pkt_len);
        pudp_hdr->dgram_cksum    = 32; // No udp checksum. 

    //Initialize IP header.
        pkt_len = (uint16_t) (pkt_len + sizeof__);
        ip_hdr->version_ihl   = IP_VHL_DEF;
        ip_hdr->type_of_service   = 0;
        ip_hdr->fragment_offset = 0;
        ip_hdr->time_to_live   = IP_DEFTTL;
        ip_hdr->next_proto_id = IPPROTO_UDP;
        ip_hdr->packet_id = 0;
        ip_hdr->total_length   = RTE_CPU_TO_BE_16(pkt_len);
        ip_hdr->src_addr = rte_cpu_to_be_32(IP_SRC_ADDR);
        ip_hdr->dst_addr = rte_cpu_to_be_32(IP_DST_ADDR);

    //Compute IP header checksum.
        ptr16 = (unaligned_uint16_t*) ip_hdr;
        ip_cksum = 0;
        ip_cksum += ptr16[0]; ip_cksum += ptr16[1];
        ip_cksum += ptr16[2]; ip_cksum += ptr16[3];
        ip_cksum += ptr16[4];
        ip_cksum += ptr16[6]; ip_cksum += ptr16[7];
        ip_cksum += ptr16[8]; ip_cksum += ptr16[9];

    //Reduce 32 bit checksum to 16 bits and complement it.
        ip_cksum = ((ip_cksum & 0xFFFF0000) >> 16) +
                (ip_cksum & 0x0000FFFF);
        if (ip_cksum > 65535)
                ip_cksum -= 65535;
        ip_cksum = (~ip_cksum) & 0x0000FFFF;
        if (ip_cksum == 0)
                ip_cksum = 0xFFFF;
        ip_hdr->hdr_checksum = (uint16_t) ip_cksum;
}


union {
         uint64_t as_int;
         struct rte_ether_addr as_addr;
} dst_eth_addr;
static void packetsend_withSequence()
{
 int counter=1;
 int pkt_drop_counter=0;    


            struct rte_ether_hdr eth_hdr;
            struct rte_mbuf *pkt=NULL;
            struct rte_mbuf *pkts_burst[1];
            struct rte_mbuf *m;
            char *data;
            char temppacketdata[100];

          while(1){    

                pkt = rte_pktmbuf_alloc(mbuf_pool);
                if(pkt == NULL) {printf("trouble at rte_mbuf_raw_alloc\n");}
                data = rte_pktmbuf_append(pkt, TX_PACKET_LENGTH);
                if(data == NULL ) {printf("trouble at data alloc\n");}

                // set up addresses 
        printf("\n rte_pktmbuf_pkt_len is %d", rte_pktmbuf_pkt_len(pkt));
                dst_eth_addr.as_int=rte_cpu_to_be_64(DST_MAC);
                rte_ether_addr_copy(&dst_eth_addr,&eth_hdr.d_addr);
                rte_ether_addr_copy(&my_addr, &eth_hdr.s_addr);
                eth_hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);

                memset(temppacketdata,0x0,sizeof(temppacketdata));                    

                memcpy(temppacketdata, &eth_hdr,(size_t)sizeof(eth_hdr)); //copy eth header
                memcpy(temppacketdata+(size_t)sizeof(eth_hdr), &pkt_ip_hdr,(size_t)sizeof(pkt_ip_hdr)); //copy IP header
                 memcpy(temppacketdata+(size_t)sizeof(eth_hdr)+(size_t)sizeof(pkt_ip_hdr), &pkt_udp_hdr,(size_t)sizeof(pkt_udp_hdr)); //copy UDP header

                memcpy(temppacketdata+(size_t)sizeof(eth_hdr)+(size_t)sizeof(pkt_ip_hdr)+(size_t)sizeof(pkt_udp_hdr), &counter,(size_t)sizeof(counter)); //copy int data 

        memcpy(data,temppacketdata,rte_pktmbuf_pkt_len(pkt));


        pkts_burst[0] = pkt;
                const uint16_t nb_tx = rte_eth_tx_burst(0, 0, pkts_burst,1);

                if (unlikely(nb_tx < 1)) 
                {
                pkt_drop_counter++;
            rte_pktmbuf_free(pkt);  // This frees chained segs
            }
        else{
            counter++;
            printf("%d",nb_tx);
        }
        if(counter > 1000)
                        break;

        }       
       printf(" pkt_drop_counter = %d counter =%d",pkt_drop_counter,counter); 
}

// Initialize Port
static inline int
port_init(uint16_t port, struct rte_mempool *mbuf_pool)
{
        struct rte_eth_conf port_conf = port_conf_default;
        const uint16_t rx_rings = 1, tx_rings = 1;
    uint16_t nb_rxd = RX_RING_SIZE;
        uint16_t nb_txd = TX_RING_SIZE;
        int retval;
        uint16_t q;
        struct rte_eth_dev_info dev_info;
        struct rte_eth_txconf txconf;

        if (!rte_eth_dev_is_valid_port(port))
                return -1;

        rte_eth_dev_info_get(port, &dev_info);
        if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
                port_conf.txmode.offloads |=
                        DEV_TX_OFFLOAD_MBUF_FAST_FREE;

        /* Configure the Ethernet device. */
        retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
        if (retval != 0)
                return retval;

        retval = rte_eth_dev_adjust_nb_rx_tx_desc(port, &nb_rxd, &nb_txd);
        if (retval != 0)
                return retval;

        txconf = dev_info.default_txconf;
        txconf.offloads = port_conf.txmode.offloads;

        //Allocate and set up 1 TX queue
        for (q = 0; q < tx_rings; q++) {
                retval = rte_eth_tx_queue_setup(port, q, nb_txd,
                                rte_eth_dev_socket_id(port), &txconf);
                if (retval < 0)
                        return retval;
        }
        /* Allocate and set up 1 RX queue per Ethernet port. */
    for (q = 0; q < rx_rings; q++) {
        retval = rte_eth_rx_queue_setup(port, q, nb_rxd,
                rte_eth_dev_socket_id(port), NULL, mbuf_pool);
        if (retval < 0)
            return retval;
    }

        /* Start the Ethernet port. */
        retval = rte_eth_dev_start(port);
        if (retval < 0)
                return retval;

        /* get the port MAC address. */
        rte_eth_macaddr_get(port, &my_addr);
        printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
                           " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n",
                        port,
                        my_addr.addr_bytes[0], my_addr.addr_bytes[1],
                        my_addr.addr_bytes[2], my_addr.addr_bytes[3],
                        my_addr.addr_bytes[4], my_addr.addr_bytes[5]);

        return 0;
}


int main(int argc, char **argv)
{       
    int ret,c;
    uint16_t pkt_data_len;
    int mac_flag=0,ip_src_flag=0,ip_dst_flag=0;

    ret = rte_eal_init(argc, argv);
    if (ret < 0)
        rte_panic("Cannot init EAL\n");

    argc -= ret;
    argv += ret;




    while ((c = getopt(argc, argv, "m:s:d:h")) != -1)
        switch(c) {
        case 'm':
            // note, not quite sure why last two bytes are zero, but that is how DPDK likes it
            DST_MAC=0ULL;
            DST_MAC=string_to_mac(optarg)<<16;  
            mac_flag=1; 
            break;
        case 's':
            IP_SRC_ADDR=string_to_ip(optarg);
            ip_src_flag=1;
            break;
                case 'd':
                        IP_DST_ADDR=string_to_ip(optarg);
                        ip_dst_flag=1;
                        break;
        case 'h':
            printf("usage -- -m [dst MAC] -s [src IP] -d [dst IP]\n");
            exit(0);
            break;
        }

    if(mac_flag==0) {
        fprintf(stderr, "missing -m for destination MAC adress\n");
        exit(1);
    }
    if(ip_src_flag==0) {
                fprintf(stderr, "missing -s for IP source adress\n");
                exit(1);
        }
        if(ip_dst_flag==0) {
                fprintf(stderr, "missing -d for IP destination adress\n");
                exit(1);
        }

        /* Creates a new mempool in memory to hold the mbufs. */
        mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS,
                MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());

        if (mbuf_pool == NULL)
                rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");

    // initialize port 0
    if (port_init(0,mbuf_pool) != 0)
        rte_exit(EXIT_FAILURE, "Cannot init port 0\n");
/* Initialize all ports. */

        if (port_init(1, mbuf_pool) != 0)
            rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu16 "\n",
                    1);




        pkt_data_len = (uint16_t) (TX_PACKET_LENGTH - (sizeof(struct rte_ether_hdr) +
                                                    sizeof(struct rte_ipv4_hdr) +
                                                    sizeof(struct rte_udp_hdr)));                        
        setup_pkt_udp_ip_headers(&pkt_ip_hdr, &pkt_udp_hdr, pkt_data_len);

    packetsend_withSequence();
  //     send_packet();
    return(0);
}
  • should not you have `counter` as static variable in `packetsend_withSequence`? couple of other things to point out 1) after `rte_mbufpkt_alloc` its incorrect to continue if `pkt==null` 2) after alloc, you should use `rte_pktmbuf_mtod` to get the pointer location to memcopy the data 3) update `pkt_len` and `data_len` to total packet size 4) re-llok into logic of `memset` and `memcpy` especially DST_MAC having type case of uint64_t 5) set udp `dgram_cksum` to 0 – Vipin Varghese May 07 '20 at 02:22