Fix extrapolation used in latency measurements
[samplevnf.git] / VNFs / DPPD-PROX / handle_gen.c
index f8c99ee..0f70ee6 100644 (file)
@@ -122,6 +122,7 @@ struct task_gen {
        struct ether_addr  src_mac;
        uint8_t flags;
        uint8_t cksum_offload;
+       struct prox_port_cfg *port;
 } __rte_cache_aligned;
 
 static inline uint8_t ipv4_get_hdr_len(struct ipv4_hdr *ip)
@@ -790,31 +791,45 @@ static int check_all_pkt_size(struct task_gen *task, int do_panic)
        return 0;
 }
 
-static void check_fields_in_bounds(struct task_gen *task)
+static int check_fields_in_bounds(struct task_gen *task, uint32_t pkt_size, int do_panic)
 {
-       const uint32_t pkt_size = task->pkt_template[0].len;
-
        if (task->lat_enabled) {
                uint32_t pos_beg = task->lat_pos;
                uint32_t pos_end = task->lat_pos + 3U;
 
-               PROX_PANIC(pkt_size <= pos_end, "Writing latency at %u-%u, but packet size is %u bytes\n",
+               if (do_panic)
+                       PROX_PANIC(pkt_size <= pos_end, "Writing latency at %u-%u, but packet size is %u bytes\n",
                           pos_beg, pos_end, pkt_size);
+               else if (pkt_size <= pos_end) {
+                       plog_err("Writing latency at %u-%u, but packet size is %u bytes\n", pos_beg, pos_end, pkt_size);
+                       return -1;
+               }
        }
        if (task->packet_id_pos) {
                uint32_t pos_beg = task->packet_id_pos;
                uint32_t pos_end = task->packet_id_pos + 4U;
 
-               PROX_PANIC(pkt_size <= pos_end, "Writing packet at %u-%u, but packet size is %u bytes\n",
+               if (do_panic)
+                       PROX_PANIC(pkt_size <= pos_end, "Writing packet at %u-%u, but packet size is %u bytes\n",
                           pos_beg, pos_end, pkt_size);
+               else if (pkt_size <= pos_end) {
+                       plog_err("Writing packet at %u-%u, but packet size is %u bytes\n", pos_beg, pos_end, pkt_size);
+                       return -1;
+               }
        }
        if (task->accur_pos) {
                uint32_t pos_beg = task->accur_pos;
                uint32_t pos_end = task->accur_pos + 3U;
 
-               PROX_PANIC(pkt_size <= pos_end, "Writing accuracy at %u%-u, but packet size is %u bytes\n",
+               if (do_panic)
+                       PROX_PANIC(pkt_size <= pos_end, "Writing accuracy at %u%-u, but packet size is %u bytes\n",
                           pos_beg, pos_end, pkt_size);
+               else if (pkt_size <= pos_end) {
+                       plog_err("Writing accuracy at %u%-u, but packet size is %u bytes\n", pos_beg, pos_end, pkt_size);
+                       return -1;
+               }
        }
+       return 0;
 }
 
 static void task_gen_pkt_template_recalc_metadata(struct task_gen *task)
@@ -919,7 +934,7 @@ static void task_init_gen_load_pkt_inline(struct task_gen *task, struct task_arg
        task->pkt_template_orig[0].len = targ->pkt_size;
        task_gen_reset_pkt_templates(task);
        check_all_pkt_size(task, 1);
-       check_fields_in_bounds(task);
+       check_fields_in_bounds(task, task->pkt_template[0].len, 1);
 }
 
 static void task_init_gen_load_pcap(struct task_gen *task, struct task_args *targ)
@@ -976,10 +991,11 @@ int task_gen_set_pkt_size(struct task_base *tbase, uint32_t pkt_size)
        struct task_gen *task = (struct task_gen *)tbase;
        int rc;
 
-       task->pkt_template[0].len = pkt_size;
-       if ((rc = check_all_pkt_size(task, 0)) != 0)
+       if ((rc = check_pkt_size(task, pkt_size, 0)) != 0)
+               return rc;
+       if ((rc = check_fields_in_bounds(task, pkt_size, 0)) != 0)
                return rc;
-       check_fields_in_bounds(task);
+       task->pkt_template[0].len = pkt_size;
        return rc;
 }
 
@@ -1129,6 +1145,12 @@ static void start(struct task_base *tbase)
        if (tbase->l3.tmaster) {
                register_all_ip_to_ctrl_plane(task);
        }
+       if (task->port) {
+               // task->port->link->speed reports the link speed in Mbps e.g. 40k for a 40 Gbps NIC
+               // task->link_speed reported link speed in Bytes per sec.
+               task->link_speed = task->port->link_speed * 125000L;
+               plog_info("\tGenerating at %ld Mbps\n", 8 * task->link_speed / 1000000);
+       }
        /* TODO
           Handle the case when two tasks transmit to the same port
           and one of them is stopped. In that case ARP (requests or replies)
@@ -1175,9 +1197,16 @@ static void init_task_gen(struct task_base *tbase, struct task_args *targ)
        task->sig = targ->sig;
        task->new_rate_bps = targ->rate_bps;
 
+       /*
+        * For tokens, use 10 Gbps as base rate
+        * Scripts can then use speed command, with speed=100 as 10 Gbps and speed=400 as 40 Gbps
+        * Script can query prox "port info" command to find out the port link speed to know
+        * at which rate to start. Note that virtio running on OVS returns 10 Gbps, so a script has
+        * probably also to check the driver (as returned by the same "port info" command.
+        */
        struct token_time_cfg tt_cfg = token_time_cfg_create(1250000000, rte_get_tsc_hz(), -1);
-
        token_time_init(&task->token_time, &tt_cfg);
+
        init_task_gen_seeds(task);
 
        task->min_bulk_size = targ->min_bulk_size;
@@ -1196,8 +1225,6 @@ static void init_task_gen(struct task_base *tbase, struct task_args *targ)
 
        task->generator_id = targ->generator_id;
        task->link_speed = UINT64_MAX;
-       if (targ->nb_txrings == 0 && targ->nb_txports == 1)
-               task->link_speed = 1250000000;
 
        if (!strcmp(targ->pcap_file, "")) {
                plog_info("\tUsing inline definition of a packet\n");
@@ -1222,6 +1249,7 @@ static void init_task_gen(struct task_base *tbase, struct task_args *targ)
        struct prox_port_cfg *port = find_reachable_port(targ);
        if (port) {
                task->cksum_offload = port->capabilities.tx_offload_cksum;
+               task->port = port;
        }
 }