X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=VNFs%2FDPPD-PROX%2Fhandle_irq.c;h=00c192f67b36d3a8b179cb7eabe2cb9fa8c97e86;hb=63b9e164a14d48acc37d325c0cb5387602d8e631;hp=4abf84a120a3afb259e5d318f4b833e7c9b61d6c;hpb=7286b2518ec8e4398b512ce95def9166a7af2e4a;p=samplevnf.git diff --git a/VNFs/DPPD-PROX/handle_irq.c b/VNFs/DPPD-PROX/handle_irq.c index 4abf84a1..00c192f6 100644 --- a/VNFs/DPPD-PROX/handle_irq.c +++ b/VNFs/DPPD-PROX/handle_irq.c @@ -20,35 +20,13 @@ #include "task_base.h" #include "task_init.h" #include "handle_irq.h" +#include "stats_irq.h" #include "log.h" #include "unistd.h" #include "input.h" -#define MAX_INDEX 65535 * 16 - -struct irq_info { - uint64_t tsc; - uint64_t lat; -}; - -struct irq_bucket { - uint64_t index; - struct irq_info info[MAX_INDEX]; -}; - -struct task_irq { - struct task_base base; - uint64_t start_tsc; - uint64_t tsc; - uint64_t max_irq; - uint8_t lcore_id; - volatile uint16_t stats_use_lt; /* which lt to use, */ - volatile uint16_t task_use_lt; /* 0 or 1 depending on which of the 2 result records are used */ - struct irq_bucket buffer[2]; -}; - #define MAX_INTERRUPT_LENGTH 500000 /* Maximum length of an interrupt is (1 / MAX_INTERRUPT_LENGTH) seconds */ - +uint64_t irq_bucket_maxtime_micro[] = {1,5,10,50,100,500,1000,5000,10000,50000,100000,500000,UINT64_MAX}; /* * This module is not handling any packets. * It loops on rdtsc() and checks whether it has been interrupted @@ -57,6 +35,18 @@ struct task_irq { * as been properly configured. */ +static void update_irq_stats(struct task_irq *task, uint64_t irq) +{ + if (irq > task->stats.max_irq) + task->stats.max_irq = irq; + for (uint i = 0; i < IRQ_BUCKETS_COUNT; ++i) { + if (irq < irq_bucket_maxtime_cycles[i]) { + task->stats.irq[i]++; + break; + } + } +} + void task_irq_show_stats(struct task_irq *task_irq, struct input *input) { struct irq_bucket *bucket = &task_irq->buffer[!task_irq->task_use_lt]; @@ -99,27 +89,37 @@ static void irq_stop(struct task_base *tbase) struct task_irq *task = (struct task_irq *)tbase; uint32_t i; uint32_t lcore_id = rte_lcore_id(); + uint64_t lat, max_lat = 0, tot_lat = 0; int bucket_id; - - plog_info("Stopping core %u\n", lcore_id); - plog_info("Core ID; Interrupt (nanosec); Time (msec)\n"); - for (int j = 0; j < 2; j++) { - // Start dumping the oldest bucket first - if (task->buffer[0].info[0].tsc < task->buffer[1].info[0].tsc) - bucket_id = j; - else - bucket_id = !j; - struct irq_bucket *bucket = &task->buffer[bucket_id]; - for (i=0; i< bucket->index;i++) { - if (bucket->info[i].lat != 0) { - plog_info("%d; %ld; %ld\n", - lcore_id, - bucket->info[i].lat * 1000000000 / rte_get_tsc_hz(), - (bucket->info[i].tsc - task->start_tsc) * 1000 / rte_get_tsc_hz()); + int n_lat = 0; + + if (task->irq_debug) { + plog_info("Stopping core %u\n", lcore_id); + sleep(2); // Make sure all cores are stopped before starting to write + plog_info("Core ID; Interrupt (nanosec); Time (msec)\n"); + for (int j = 0; j < 2; j++) { + // Start dumping the oldest bucket first + if (task->buffer[0].info[0].tsc < task->buffer[1].info[0].tsc) + bucket_id = j; + else + bucket_id = !j; + struct irq_bucket *bucket = &task->buffer[bucket_id]; + for (i=0; i< bucket->index;i++) { + if (bucket->info[i].lat != 0) { + lat = bucket->info[i].lat * 1000000000 / rte_get_tsc_hz(); + if (max_lat < lat) + max_lat = lat; + n_lat++; + tot_lat += lat; + plog_info("%d; %ld; %ld\n", lcore_id, lat, + (bucket->info[i].tsc - task->start_tsc) * 1000 / rte_get_tsc_hz()); + } } } + if (n_lat) + tot_lat = tot_lat / n_lat; + plog_info("Core %u stopped. max lat is %ld and average is %ld\n", lcore_id, max_lat, tot_lat); } - plog_info("Core %u stopped\n", lcore_id); } static inline int handle_irq_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts) @@ -133,9 +133,12 @@ static inline int handle_irq_bulk(struct task_base *tbase, struct rte_mbuf **mbu struct irq_bucket *bucket = &task->buffer[task->task_use_lt]; tsc1 = rte_rdtsc(); - if ((task->tsc != 0) && ((tsc1 - task->tsc) > task->max_irq) && (bucket->index < MAX_INDEX)) { - bucket->info[bucket->index].tsc = tsc1; - bucket->info[bucket->index++].lat = tsc1 - task->tsc; + if ((tsc1 > task->first_tsc) && (task->tsc != 0)) { + update_irq_stats(task, tsc1 - task->tsc); + if (((tsc1 - task->tsc) > task->max_irq) && (bucket->index < MAX_INDEX)) { + bucket->info[bucket->index].tsc = tsc1; + bucket->info[bucket->index++].lat = tsc1 - task->tsc; + } } task->tsc = tsc1; return 0; @@ -145,11 +148,17 @@ static void init_task_irq(struct task_base *tbase, __attribute__((unused)) struct task_args *targ) { struct task_irq *task = (struct task_irq *)tbase; - // max_irq expressed in cycles - task->max_irq = rte_get_tsc_hz() / MAX_INTERRUPT_LENGTH; task->start_tsc = rte_rdtsc(); + task->first_tsc = task->start_tsc + 2 * rte_get_tsc_hz(); task->lcore_id = targ->lconf->id; + task->irq_debug = targ->irq_debug; + // max_irq expressed in cycles + task->max_irq = rte_get_tsc_hz() / MAX_INTERRUPT_LENGTH; plog_info("\tusing irq mode with max irq set to %ld cycles\n", task->max_irq); + + for (uint bucket_id = 0; bucket_id < IRQ_BUCKETS_COUNT - 1; bucket_id++) + irq_bucket_maxtime_cycles[bucket_id] = rte_get_tsc_hz() * irq_bucket_maxtime_micro[bucket_id] / 1000000; + irq_bucket_maxtime_cycles[IRQ_BUCKETS_COUNT - 1] = UINT64_MAX; } static struct task_init task_init_irq = {