luigirizzo / netmap

Automatically exported from code.google.com/p/netmap
BSD 2-Clause "Simplified" License
1.86k stars 537 forks source link

pkt-gen IP randomization differs for jumbo vs. standard frames #939

Open brian90013 opened 1 year ago

brian90013 commented 1 year ago

Hello,

This was discovered by observing that setting -z/-Z (OPT_RANDOM_SRC/OPT_RANDOM_DST) with standard (<= 1500 byte) packets causes pkt-gen to randomize the IPs for each slot of each ring at startup (while OPT_COPY is enabled). These IP/UDP headers are re-used for the lifetime of the process. However, if the frame size requires fragments in send_packets(), then the IPs will be randomized after every packet. I'm not sure of the desired behavior, but suggest it should be the same for standard and jumbo frames. I'm happy to prepare a patch if there is consensus of which way to proceed.

A typical pkt-gen command line I use for testing multi-queue NICs is pkt-gen -i iface -f tx -z -Z -l size. If size doesn't require fragmentation then each ring is randomized at startup resulting in a fixed number of unique tuples no matter the runtime. If size requires fragmentation I will see a steady stream of unique tuples.

update_addresses() calls update_ip()/update_ip6() which in turn checks for OPT_RANDOM_SRC/'-z' and OPT_RANDOM_DST/'-Z' before randomizing the IP addresses and ports. Looking at send_packets(), update_addresses() is always called in the fragmented case where frags > 1. However, for unfragmented frames, update_addresses() is only called if OPT_COPY/OPT_MEMCPY/buf_changed is set.


                } else if (frags > 1) {
                        u_int i;
                        const char *f = frame;
                        char *fp = p;
                       ...
                        n -= (frags - 1);
                        p = fp;
                        slot->flags = 0;
                        memcpy(p, f, tosend);
                        update_addresses(pkt, t);
                } else if ((options & (OPT_COPY | OPT_MEMCPY)) || buf_changed) {
                        if (options & OPT_COPY)
                                nm_pkt_copy(frame, p, size);
                        else
                                memcpy(p, frame, size);
                        update_addresses(pkt, t);
                } else if (options & OPT_PREFETCH) {