From 7286b2518ec8e4398b512ce95def9166a7af2e4a Mon Sep 17 00:00:00 2001 From: Deepak S Date: Thu, 13 Jul 2017 21:26:50 -0700 Subject: Adding PROX(Packet pROcessing eXecution engine) VNF to sampleVNF JIRA: SAMPLEVNF-55 PROX is a DPDK-based application implementing Telco use-cases such as a simplified BRAS/BNG, light-weight AFTR... It also allows configuring finer grained network functions like QoS, Routing, load-balancing... (We are moving PROX version v039 to sampleVNF https://01.org/intel-data-plane-performance-demonstrators/prox-overview) Change-Id: Ia3cb02cf0e49ac5596e922c197ff7e010293d033 Signed-off-by: Deepak S --- VNFs/DPPD-PROX/handle_irq.c | 169 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 VNFs/DPPD-PROX/handle_irq.c (limited to 'VNFs/DPPD-PROX/handle_irq.c') diff --git a/VNFs/DPPD-PROX/handle_irq.c b/VNFs/DPPD-PROX/handle_irq.c new file mode 100644 index 00000000..4abf84a1 --- /dev/null +++ b/VNFs/DPPD-PROX/handle_irq.c @@ -0,0 +1,169 @@ +/* +// Copyright (c) 2010-2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +*/ + +#include + +#include "lconf.h" +#include "task_base.h" +#include "task_init.h" +#include "handle_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 */ + +/* + * This module is not handling any packets. + * It loops on rdtsc() and checks whether it has been interrupted + * for more than (1 / MAX_INTERRUPT_LENGTH) sec. + * This is a debugging only task, useful to check if the system h + * as been properly configured. +*/ + +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]; + if (input->reply) { + char buf[8192] = {0}; + if (bucket->index == 0) { + sprintf(buf, "\n"); + input->reply(input, buf, strlen(buf)); + buf[0] = 0; + } + for (uint64_t i = 0; i < bucket->index; i++) { + sprintf(buf + strlen(buf), "%d; %"PRIu64"""; %ld; %ld; %ld; %ld ;", + task_irq->lcore_id, + i, + bucket->info[i].lat, + bucket->info[i].lat * 1000000 / rte_get_tsc_hz(), + bucket->info[i].tsc - task_irq->start_tsc, + (bucket->info[i].tsc - task_irq->start_tsc) * 1000 / rte_get_tsc_hz()); + sprintf(buf+strlen(buf), "\n"); + input->reply(input, buf, strlen(buf)); + buf[0] = 0; + } + } else { + for (uint64_t i = 0; i < bucket->index; i++) + if (bucket->info[i].lat) + plog_info("[%d]; Interrupt %"PRIu64": %ld cycles (%ld micro-sec) at %ld cycles (%ld msec)\n", + task_irq->lcore_id, + i, + bucket->info[i].lat, + bucket->info[i].lat * 1000000 / rte_get_tsc_hz(), + bucket->info[i].tsc - task_irq->start_tsc, + (bucket->info[i].tsc - task_irq->start_tsc) * 1000 / rte_get_tsc_hz()); + } + task_irq->stats_use_lt = !task_irq->task_use_lt; + bucket->index = 0; +} + +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(); + 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()); + } + } + } + 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) +{ + struct task_irq *task = (struct task_irq *)tbase; + uint64_t tsc1; + uint64_t index; + + if (task->stats_use_lt != task->task_use_lt) + task->task_use_lt = task->stats_use_lt; + 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; + } + task->tsc = tsc1; + return 0; +} + +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->lcore_id = targ->lconf->id; + plog_info("\tusing irq mode with max irq set to %ld cycles\n", task->max_irq); +} + +static struct task_init task_init_irq = { + .mode_str = "irq", + .init = init_task_irq, + .handle = handle_irq_bulk, + .stop = irq_stop, + .flag_features = TASK_FEATURE_NO_RX, + .size = sizeof(struct task_irq) +}; + +static struct task_init task_init_none; + +__attribute__((constructor)) static void reg_task_irq(void) +{ + reg_task(&task_init_irq); +} -- cgit 1.2.3-korg