diff options
Diffstat (limited to 'VNFs/DPPD-PROX/handle_lat.c')
-rw-r--r-- | VNFs/DPPD-PROX/handle_lat.c | 115 |
1 files changed, 110 insertions, 5 deletions
diff --git a/VNFs/DPPD-PROX/handle_lat.c b/VNFs/DPPD-PROX/handle_lat.c index ef4da319..04a4848b 100644 --- a/VNFs/DPPD-PROX/handle_lat.c +++ b/VNFs/DPPD-PROX/handle_lat.c @@ -86,6 +86,15 @@ struct rx_pkt_meta_data { uint32_t bytes_after_in_bulk; }; +struct loss_buffer { + uint32_t packet_id; + uint32_t n; +}; + +struct flows { + uint32_t packet_id; +}; + struct task_lat { struct task_base base; uint64_t limit; @@ -111,10 +120,19 @@ struct task_lat { struct rx_pkt_meta_data *rx_pkt_meta; // Following fields are only used when starting or stopping, not in general runtime uint64_t *prev_tx_packet_index; + FILE *fp_loss; FILE *fp_rx; FILE *fp_tx; struct prox_port_cfg *port; uint64_t *bytes_to_tsc; + uint64_t *previous_packet; + uint32_t loss_buffer_size; + struct loss_buffer *loss_buffer; + uint32_t loss_id; + uint32_t packet_id_in_flow_pos; + int32_t flow_id_pos; + uint32_t flow_count; + struct flows *flows; }; /* This function calculate the difference between rx and tx_time * Both values are uint32_t (see handle_lat_bulk) @@ -399,7 +417,14 @@ static void lat_stop(struct task_base *tbase) if (task->unique_id_pos) { task_lat_count_remaining_lost_packets(task); task_lat_reset_eld(task); + memset(task->previous_packet, 0, sizeof(task->previous_packet) * task->generator_count); + } + if (task->loss_id && task->fp_loss) { + for (uint i = 0; i < task->loss_id; i++) { + fprintf(task->fp_loss, "packet %d: %d\n", task->loss_buffer[i].packet_id, task->loss_buffer[i].n); + } } + task->lat_test->lost_packets = 0; if (task->latency_buffer) lat_write_latency_to_file(task); } @@ -440,6 +465,17 @@ static uint32_t task_lat_early_loss_detect(struct task_lat *task, uint32_t packe return early_loss_detect_add(eld, packet_id); } +static void lat_test_check_duplicate(struct task_lat *task, struct lat_test *lat_test, uint32_t packet_id, uint8_t generator_id) +{ + struct early_loss_detect *eld = &task->eld[generator_id]; + uint32_t old_queue_id, queue_pos; + + queue_pos = packet_id & PACKET_QUEUE_MASK; + old_queue_id = eld->entries[queue_pos]; + if ((packet_id >> PACKET_QUEUE_BITS) == old_queue_id) + lat_test->duplicate++; +} + static uint64_t tsc_extrapolate_backward(struct task_lat *task, uint64_t tsc_from, uint64_t bytes, uint64_t tsc_minimum) { #ifdef NO_LAT_EXTRAPOLATION @@ -462,6 +498,24 @@ static void lat_test_histogram_add(struct lat_test *lat_test, uint64_t lat_tsc) lat_test->buckets[bucket_id]++; } +static void lat_test_check_flow_ordering(struct task_lat *task, struct lat_test *lat_test, int32_t flow_id, uint32_t packet_id) +{ + if (packet_id < task->flows[flow_id].packet_id) { + lat_test->mis_ordered++; + lat_test->extent += task->flows[flow_id].packet_id - packet_id; + } + task->flows[flow_id].packet_id = packet_id; +} + +static void lat_test_check_ordering(struct task_lat *task, struct lat_test *lat_test, uint32_t packet_id, uint8_t generator_id) +{ + if (packet_id < task->previous_packet[generator_id]) { + lat_test->mis_ordered++; + lat_test->extent += task->previous_packet[generator_id] - packet_id; + } + task->previous_packet[generator_id] = packet_id; +} + static void lat_test_add_lost(struct lat_test *lat_test, uint64_t lost_packets) { lat_test->lost_packets += lost_packets; @@ -514,6 +568,7 @@ static void task_lat_store_lat(struct task_lat *task, uint64_t rx_packet_index, static int handle_lat_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts) { struct task_lat *task = (struct task_lat *)tbase; + static int max_flows_printed = 0; int rc; if (n_pkts == 0) { @@ -602,6 +657,24 @@ static int handle_lat_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uin uint8_t generator_id; uint32_t packet_id; + int32_t flow_id = -1; + if (task->flow_id_pos) { + flow_id = *(int32_t *)(hdr + task->flow_id_pos); + if (unlikely(flow_id >= (int32_t)(task->flow_count))) { + flow_id = -1; + if (!max_flows_printed) { + plog_info("Too many flows - increase flow count (only printed once)\n"); + max_flows_printed = 1; + } + } + + } + if (task->packet_id_in_flow_pos && (flow_id != -1)) { + uint32_t packet_id_in_flow; + struct unique_id *unique_id = (struct unique_id *)(hdr + task->packet_id_in_flow_pos); + unique_id_get(unique_id, &generator_id, &packet_id_in_flow); + lat_test_check_flow_ordering(task, task->lat_test, flow_id + generator_id * task->generator_count, packet_id_in_flow); + } if (task->unique_id_pos) { struct unique_id *unique_id = (struct unique_id *)(hdr + task->unique_id_pos); unique_id_get(unique_id, &generator_id, &packet_id); @@ -613,8 +686,18 @@ static int handle_lat_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uin // Skip unexpected packet continue; } - - lat_test_add_lost(task->lat_test, task_lat_early_loss_detect(task, packet_id, generator_id)); + if (flow_id == -1) { + lat_test_check_ordering(task, task->lat_test, packet_id, generator_id); + } + lat_test_check_duplicate(task, task->lat_test, packet_id, generator_id); + uint32_t loss = task_lat_early_loss_detect(task, packet_id, generator_id); + if (loss) { + lat_test_add_lost(task->lat_test, loss); + if (task->loss_id < task->loss_buffer_size) { + task->loss_buffer[task->loss_id].packet_id = packet_id; + task->loss_buffer[task->loss_id++].n = loss; + } + } } else { generator_id = 0; packet_id = task->rx_packet_index; @@ -702,7 +785,7 @@ static void task_init_generator_count(struct task_lat *task) plog_info("\tNo generators found, hard-coding to %u generators\n", task->generator_count); } else task->generator_count = *generator_count; - plog_info("\tLatency using %u generators\n", task->generator_count); + plog_info("\t\tLatency using %u generators\n", task->generator_count); } static void task_lat_init_eld(struct task_lat *task, uint8_t socket_id) @@ -734,6 +817,8 @@ static void init_task_lat(struct task_base *tbase, struct task_args *targ) task->accur_pos = targ->accur_pos; task->sig_pos = targ->sig_pos; task->sig = targ->sig; + task->packet_id_in_flow_pos = targ->packet_id_in_flow_pos; + task->flow_id_pos = targ->flow_id_pos; task->unique_id_pos = targ->packet_id_pos; task->latency_buffer_size = targ->latency_buffer_size; @@ -786,6 +871,8 @@ static void init_task_lat(struct task_base *tbase, struct task_args *targ) if (task->unique_id_pos) { task_lat_init_eld(task, socket_id); task_lat_reset_eld(task); + task->previous_packet = prox_zmalloc(sizeof(task->previous_packet) * task->generator_count , socket_id); + PROX_PANIC(task->previous_packet == NULL, "Failed to allocate array for storing previous packet\n"); } task->lat_test = &task->lt[task->using_lt]; @@ -803,13 +890,24 @@ static void init_task_lat(struct task_base *tbase, struct task_args *targ) // It can be UINT32_MAX (virtual devices or not supported by DPDK < 16.04) if (port->max_link_speed != UINT32_MAX) { bytes_per_hz = port->max_link_speed * 125000L; - plog_info("\tPort %u: max link speed is %ld Mbps\n", + plog_info("\t\tPort %u: max link speed is %ld Mbps\n", (uint8_t)(port - prox_port_cfg), 8 * bytes_per_hz / 1000000); } } + task->loss_buffer_size = targ->loss_buffer_size; + if (task->loss_buffer_size) { + char name[256]; + sprintf(name, "loss_%u.txt", targ->lconf->id); + task->fp_loss = fopen(name, "w+"); + PROX_PANIC(task->fp_loss == NULL, "Failed to open %s\n", name); + + task->loss_buffer = prox_zmalloc(task->loss_buffer_size * sizeof(struct loss_buffer), rte_lcore_to_socket_id(targ->lconf->id)); + PROX_PANIC(task->loss_buffer == NULL, + "Failed to allocate %lu bytes (in huge pages) for loss_buffer\n", task->loss_buffer_size * sizeof(struct loss_buffer)); + } task->bytes_to_tsc = prox_zmalloc(max_frame_size * sizeof(task->bytes_to_tsc[0]) * MAX_PKT_BURST, rte_lcore_to_socket_id(targ->lconf->id)); PROX_PANIC(task->bytes_to_tsc == NULL, - "Failed to allocate %u bytes (in huge pages) for bytes_to_tsc\n", max_frame_size); + "Failed to allocate %lu bytes (in huge pages) for bytes_to_tsc\n", max_frame_size * sizeof(task->bytes_to_tsc[0]) * MAX_PKT_BURST); // There are cases where hz estimate might be slighly over-estimated // This results in too much extrapolation @@ -820,6 +918,13 @@ static void init_task_lat(struct task_base *tbase, struct task_args *targ) else task->bytes_to_tsc[i] = (rte_get_tsc_hz() * i * 0.99) / bytes_per_hz; } + task->flow_count = targ->flow_count; + PROX_PANIC(task->flow_id_pos && (task->flow_count == 0), "flow_count must be configured when flow_id_pos is set\n"); + if (task->flow_count) { + task->flows = prox_zmalloc(task->flow_count * sizeof(struct flows) * task->generator_count, rte_lcore_to_socket_id(targ->lconf->id)); + PROX_PANIC(task->flows == NULL, + "Failed to allocate %lu bytes (in huge pages) for flows\n", task->flow_count * sizeof(struct flows) * task->generator_count); + } } static struct task_init task_init_lat = { |