X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=VNFs%2FDPPD-PROX%2Fhandle_gen.c;h=4fd2c39970b117a7213f42ae9214067660a1ea3a;hb=438a3dcafd3bd943b4f7cadf0520fd9a2e74b079;hp=fcdbcd6259a812d12b085cae62a43df598505dab;hpb=224aad3ead4be1aa86d4af653c4c0ffff783d2ff;p=samplevnf.git diff --git a/VNFs/DPPD-PROX/handle_gen.c b/VNFs/DPPD-PROX/handle_gen.c index fcdbcd62..4fd2c399 100644 --- a/VNFs/DPPD-PROX/handle_gen.c +++ b/VNFs/DPPD-PROX/handle_gen.c @@ -13,7 +13,6 @@ // See the License for the specific language governing permissions and // limitations under the License. */ - #include #include #include @@ -55,11 +54,10 @@ struct pkt_template { uint8_t *buf; }; -#define MAX_TEMPLATE_INDEX 65536 -#define TEMPLATE_INDEX_MASK (MAX_TEMPLATE_INDEX - 1) - #define IP4(x) x & 0xff, (x >> 8) & 0xff, (x >> 16) & 0xff, x >> 24 +#define TASK_OVERWRITE_SRC_MAC_WITH_PORT_MAC 1 + static void pkt_template_init_mbuf(struct pkt_template *pkt_template, struct rte_mbuf *mbuf, uint8_t *pkt) { const uint32_t pkt_size = pkt_template->len; @@ -115,7 +113,7 @@ struct task_gen { uint16_t rand_offset; /* each random has an offset*/ uint8_t rand_len; /* # bytes to take from random (no bias introduced) */ } rand[64]; - uint64_t accur[64]; + uint64_t accur[ACCURACY_WINDOW]; uint64_t pkt_tsc_offset[64]; struct pkt_template *pkt_template_orig; /* packet templates (from inline or from pcap) */ struct ether_addr src_mac; @@ -364,11 +362,11 @@ static void task_gen_apply_all_accur_pos(struct task_gen *task, struct rte_mbuf if (!task->accur_pos) return; - /* The accuracy of task->pkt_queue_index - 64 is stored in - packet task->pkt_queue_index. The ID modulo 64 is the + /* The accuracy of task->pkt_queue_index - ACCURACY_WINDOW is stored in + packet task->pkt_queue_index. The ID modulo ACCURACY_WINDOW is the same. */ for (uint16_t j = 0; j < count; ++j) { - uint32_t accuracy = task->accur[(task->pkt_queue_index + j) & 63]; + uint32_t accuracy = task->accur[(task->pkt_queue_index + j) & (ACCURACY_WINDOW - 1)]; task_gen_apply_accur_pos(task, pkt_hdr[j], accuracy); } } @@ -506,7 +504,7 @@ static void task_gen_store_accuracy(struct task_gen *task, uint32_t count, uint6 uint64_t first_accuracy_idx = task->pkt_queue_index - count; for (uint32_t i = 0; i < count; ++i) { - uint32_t accuracy_idx = (first_accuracy_idx + i) & 63; + uint32_t accuracy_idx = (first_accuracy_idx + i) & (ACCURACY_WINDOW - 1); task->accur[accuracy_idx] = accur; } @@ -530,7 +528,6 @@ static void task_gen_build_packets(struct task_gen *task, struct rte_mbuf **mbuf struct pkt_template *pktpl = &task->pkt_template[task->pkt_idx]; struct pkt_template *pkt_template = &task->pkt_template[task->pkt_idx]; pkt_template_init_mbuf(pkt_template, mbufs[i], pkt_hdr[i]); - mbufs[i]->udata64 = task->pkt_idx & TEMPLATE_INDEX_MASK; struct ether_hdr *hdr = (struct ether_hdr *)pkt_hdr[i]; if (task->lat_enabled) { #ifdef NO_EXTRAPOLATION @@ -669,6 +666,20 @@ static int handle_gen_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uin task_gen_checksum_packets(task, new_pkts, pkt_hdr, send_bulk); ret = task->base.tx_pkt(&task->base, new_pkts, send_bulk, out); task_gen_store_accuracy(task, send_bulk, tsc_before_tx); + + // If we failed to send some packets, we need to do some clean-up: + + if (unlikely(ret)) { + // We need re-use the packets indexes not being sent + // Hence non-sent packets will not be considered as lost by the receiver when it looks at + // packet ids. This should also increase the percentage of packets used for latency measurements + task->pkt_queue_index -= ret; + + // In case of failures, the estimate about when we can send next packet (earliest_tsc_next_pkt) is wrong + // This would result in under-estimated latency (up to 0 or negative) + uint64_t bulk_duration = task_gen_calc_bulk_duration(task, ret); + task->earliest_tsc_next_pkt -= bulk_duration; + } return ret; } @@ -705,7 +716,7 @@ static uint64_t avg_time_stamp(uint64_t *time_stamp, uint32_t n) return (tot_inter_pkt + n / 2)/n; } -static int pcap_read_pkts(pcap_t *handle, const char *file_name, uint32_t n_pkts, struct pkt_template *proto, uint64_t *time_stamp) +static int pcap_read_pkts(pcap_t *handle, const char *file_name, uint32_t n_pkts, struct pkt_template *proto, uint64_t *time_stamp, uint32_t max_frame_size) { struct pcap_pkthdr header; const uint8_t *buf; @@ -716,7 +727,7 @@ static int pcap_read_pkts(pcap_t *handle, const char *file_name, uint32_t n_pkts PROX_PANIC(buf == NULL, "Failed to read packet %d from pcap %s\n", i, file_name); proto[i].len = header.len; - len = RTE_MIN(header.len, sizeof(proto[i].buf)); + len = RTE_MIN(header.len, max_frame_size); if (header.len > len) plogx_warn("Packet truncated from %u to %zu bytes\n", header.len, len); @@ -897,7 +908,7 @@ static void task_gen_reset_pkt_templates_content(struct task_gen *task) for (size_t i = 0; i < task->n_pkts; ++i) { src = &task->pkt_template_orig[i]; dst = &task->pkt_template[i]; - memcpy(dst->buf, src->buf, dst->len); + memcpy(dst->buf, src->buf, RTE_MAX(src->len, dst->len)); task_gen_apply_sig(task, dst); } } @@ -949,14 +960,13 @@ static void task_init_gen_load_pcap(struct task_gen *task, struct task_args *tar PROX_PANIC(handle == NULL, "Failed to open PCAP file: %s\n", err); task->n_pkts = pcap_count_pkts(handle, &max_frame_size); - plogx_info("%u packets in pcap file '%s'\n", task->n_pkts, targ->pcap_file); + plogx_info("%u packets in pcap file '%s'; max frame size=%d\n", task->n_pkts, targ->pcap_file, max_frame_size); PROX_PANIC(max_frame_size > task->max_frame_size, max_frame_size > ETHER_MAX_LEN + 2 * PROX_VLAN_TAG_SIZE -4 ? "pkt_size too high and jumbo frames disabled" : "pkt_size > mtu"); if (targ->n_pkts) task->n_pkts = RTE_MIN(task->n_pkts, targ->n_pkts); - PROX_PANIC(task->n_pkts > MAX_TEMPLATE_INDEX, "Too many packets specified in pcap - increase MAX_TEMPLATE_INDEX\n"); plogx_info("Loading %u packets from pcap\n", task->n_pkts); size_t mem_size = task->n_pkts * sizeof(*task->pkt_template); task->pkt_template = prox_zmalloc(mem_size, socket_id); @@ -966,15 +976,15 @@ static void task_init_gen_load_pcap(struct task_gen *task, struct task_args *tar "Failed to allocate %lu bytes (in huge pages) for pcap file\n", mem_size); for (uint i = 0; i < task->n_pkts; i++) { - task->pkt_template[i].buf = prox_zmalloc(max_frame_size, socket_id); - task->pkt_template_orig[i].buf = prox_zmalloc(max_frame_size, socket_id); + task->pkt_template[i].buf = prox_zmalloc(task->max_frame_size, socket_id); + task->pkt_template_orig[i].buf = prox_zmalloc(task->max_frame_size, socket_id); PROX_PANIC(task->pkt_template->buf == NULL || task->pkt_template_orig->buf == NULL, "Failed to allocate %u bytes (in huge pages) for pcap file\n", task->max_frame_size); } - pcap_read_pkts(handle, targ->pcap_file, task->n_pkts, task->pkt_template_orig, NULL); + pcap_read_pkts(handle, targ->pcap_file, task->n_pkts, task->pkt_template_orig, NULL, max_frame_size); pcap_close(handle); task_gen_reset_pkt_templates(task); } @@ -1015,12 +1025,16 @@ int task_gen_set_pkt_size(struct task_base *tbase, uint32_t pkt_size) struct task_gen *task = (struct task_gen *)tbase; int rc; - 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; - task->pkt_template[0].len = pkt_size; - return rc; + for (size_t i = 0; i < task->n_pkts; ++i) { + 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; + } + for (size_t i = 0; i < task->n_pkts; ++i) { + task->pkt_template[i].len = pkt_size; + } + return 0; } void task_gen_set_rate(struct task_base *tbase, uint64_t bps) @@ -1046,6 +1060,8 @@ int task_gen_set_value(struct task_base *tbase, uint32_t value, uint32_t offset, { struct task_gen *task = (struct task_gen *)tbase; + if (offset + len > task->max_frame_size) + return -1; for (size_t i = 0; i < task->n_pkts; ++i) { uint32_t to_write = rte_cpu_to_be_32(value) >> ((4 - len) * 8); uint8_t *dst = task->pkt_template[i].buf; @@ -1063,6 +1079,11 @@ void task_gen_reset_values(struct task_base *tbase) struct task_gen *task = (struct task_gen *)tbase; task_gen_reset_pkt_templates_content(task); + if (task->flags & TASK_OVERWRITE_SRC_MAC_WITH_PORT_MAC) { + for (uint32_t i = 0; i < task->n_pkts; ++i) { + rte_memcpy(&task->pkt_template[i].buf[sizeof(struct ether_addr)], &task->src_mac, sizeof(struct ether_addr)); + } + } } uint32_t task_gen_get_n_randoms(struct task_base *tbase) @@ -1098,8 +1119,6 @@ static void init_task_gen_pcap(struct task_base *tbase, struct task_args *targ) if (task->n_pkts > targ->n_pkts) task->n_pkts = targ->n_pkts; } - PROX_PANIC(task->n_pkts > MAX_TEMPLATE_INDEX, "Too many packets specified in pcap - increase MAX_TEMPLATE_INDEX\n"); - plogx_info("Loading %u packets from pcap\n", task->n_pkts); size_t mem_size = task->n_pkts * (sizeof(*task->proto) + sizeof(*task->proto_tsc)); @@ -1114,7 +1133,7 @@ static void init_task_gen_pcap(struct task_base *tbase, struct task_args *targ) PROX_PANIC(task->proto[i].buf == NULL, "Failed to allocate %u bytes (in huge pages) for pcap file\n", max_frame_size); } - pcap_read_pkts(handle, targ->pcap_file, task->n_pkts, task->proto, task->proto_tsc); + pcap_read_pkts(handle, targ->pcap_file, task->n_pkts, task->proto, task->proto_tsc, max_frame_size); pcap_close(handle); } @@ -1275,11 +1294,14 @@ static void init_task_gen(struct task_base *tbase, struct task_args *targ) plog_info("\tPort %u: max link speed is %ld Mbps\n", (uint8_t)(task->port - prox_port_cfg), 8 * bytes_per_hz / 1000000); } + // There are cases where hz estimate might be slighly over-estimated + // This results in too much extrapolation + // Only account for 99% of extrapolation to handle cases with up to 1% error clocks for (unsigned int i = 0; i < task->max_frame_size * MAX_PKT_BURST ; i++) { if (bytes_per_hz == UINT64_MAX) task->bytes_to_tsc[i] = 0; else - task->bytes_to_tsc[i] = (task->hz * i) / bytes_per_hz; + task->bytes_to_tsc[i] = (task->hz * i * 0.99) / bytes_per_hz; } if (!strcmp(targ->pcap_file, "")) { @@ -1292,12 +1314,12 @@ static void init_task_gen(struct task_base *tbase, struct task_args *targ) PROX_PANIC(((targ->nb_txrings == 0) && (targ->nb_txports == 0)), "Gen mode requires a tx ring or a tx port"); if ((targ->flags & DSF_KEEP_SRC_MAC) == 0) { - uint8_t *src_addr = prox_port_cfg[tbase->tx_params_hw.tx_port_queue->port].eth_addr.addr_bytes; + task->flags |= TASK_OVERWRITE_SRC_MAC_WITH_PORT_MAC; + memcpy(&task->src_mac, &prox_port_cfg[task->base.tx_params_hw.tx_port_queue->port].eth_addr, sizeof(struct ether_addr)); for (uint32_t i = 0; i < task->n_pkts; ++i) { - rte_memcpy(&task->pkt_template[i].buf[6], src_addr, 6); + rte_memcpy(&task->pkt_template[i].buf[sizeof(struct ether_addr)], &task->src_mac, sizeof(struct ether_addr)); } } - memcpy(&task->src_mac, &prox_port_cfg[task->base.tx_params_hw.tx_port_queue->port].eth_addr, sizeof(struct ether_addr)); for (uint32_t i = 0; i < targ->n_rand_str; ++i) { PROX_PANIC(task_gen_add_rand(tbase, targ->rand_str[i], targ->rand_offset[i], UINT32_MAX), "Failed to add random\n"); @@ -1337,6 +1359,7 @@ static struct task_init task_init_gen_l3 = { .size = sizeof(struct task_gen) }; +/* This mode uses time stamps in the pcap file */ static struct task_init task_init_gen_pcap = { .mode_str = "gen", .sub_mode_str = "pcap",