[dpdk-users] IPV4 frag/defrag

Harold Demure harold.demure87 at gmail.com
Wed May 10 21:12:29 CEST 2017


Hello,
  In my application I have to send pieces of data that won't fit a single
ethernet frame.
To this end I am reimplementing a sort-of ipv4 frag/defrag protocol.

Namely, I am spreading my app-level payload across several ipv4 packets and
to keep track of the sequence numbers within my packet I use the
fragment_offset field in the struct ipv4_hdr.

(I am aware my approach is not the correct and portable one, but I would
like to see a dirty code working before refining it).

However, as soon as I assign any value different from zero to
 fragment_offset, I do not see the packets being received anymore.

Do you have any idea of what I am doing wrong?


The function I use to inizialize the ipv4 header is below. Everything works
fine as long as   segment_index is 0  AND  more_frag is false.

Thank you for your help.
Regards,
  Harold

----

My config
Network card is a MLX4
DPDK version is 2.2.0
Linux distro is Ubuntu 16.04
Network driver is MLNX_OFED_LINUX-4.0-2.0.0.1

-------

static inline uint16_t initialize_ipv4_header(struct ipv4_hdr *ip_hdr,
uint32_t src_addr,
                                              uint32_t dst_addr,
uint16_t pkt_data_len, u16 segment_index,
                                              u16 pckt_id, bool more_frag) {
    uint16_t pkt_len;
    uint16_t *ptr16;
    uint32_t ip_cksum;

    /*
     * Initialize IP header.
     */
    pkt_len = (uint16_t)(pkt_data_len + sizeof(struct ipv4_hdr));

    ip_hdr->version_ihl = 0x40 | 0x05;
    ip_hdr->type_of_service = 0;
    if (more_frag) {
        ip_hdr->fragment_offset = (uint16_t)(
rte_cpu_to_be_16(segment_index)| IPV4_HDR_MF_FLAG);
    } else {
        ip_hdr->fragment_offset = (uint16_t)( rte_cpu_to_be_16(segment_index));
    }
    ip_hdr->time_to_live = IP_DEFTTL;
    ip_hdr->next_proto_id = IPPROTO_UDP;
    ip_hdr->packet_id = pckt_id;
    ip_hdr->total_length = rte_cpu_to_be_16(pkt_len);
    ip_hdr->src_addr = rte_cpu_to_be_32(src_addr);
    ip_hdr->dst_addr = rte_cpu_to_be_32(dst_addr);
    /*

     * Compute IP header checksum.
     */
    ptr16 = (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);
    ip_cksum %= 65536;
    ip_cksum = (~ip_cksum) & 0x0000FFFF;
    if (ip_cksum == 0)
        ip_cksum = 0xFFFF;
    ip_hdr->hdr_checksum = (uint16_t) ip_cksum;

    return pkt_len;
}


More information about the users mailing list