diff options
-rw-r--r-- | VNFs/DPPD-PROX/cmd_parser.c | 42 | ||||
-rw-r--r-- | VNFs/DPPD-PROX/defaults.h | 1 | ||||
-rw-r--r-- | VNFs/DPPD-PROX/handle_gen.c | 395 | ||||
-rw-r--r-- | VNFs/DPPD-PROX/handle_gen.h | 1 | ||||
-rw-r--r-- | VNFs/DPPD-PROX/log.c | 22 | ||||
-rw-r--r-- | VNFs/DPPD-PROX/log.h | 3 | ||||
-rw-r--r-- | VNFs/DPPD-PROX/prox_args.c | 28 | ||||
-rw-r--r-- | VNFs/DPPD-PROX/task_init.h | 2 |
8 files changed, 373 insertions, 121 deletions
diff --git a/VNFs/DPPD-PROX/cmd_parser.c b/VNFs/DPPD-PROX/cmd_parser.c index 0dd173f3..8c72f7bf 100644 --- a/VNFs/DPPD-PROX/cmd_parser.c +++ b/VNFs/DPPD-PROX/cmd_parser.c @@ -536,6 +536,47 @@ static int parse_cmd_pkt_size(const char *str, struct input *input) return 0; } +static int parse_cmd_imix(const char *str, struct input *input) +{ + unsigned lcores[RTE_MAX_LCORE], lcore_id, task_id, nb_cores; + uint32_t pkt_sizes[MAX_IMIX_PKTS], tmp; + uint32_t pkt_index = 0; + + if (parse_cores_task(str, lcores, &task_id, &nb_cores)) + return -1; + if (!(str = strchr_skip_twice(str, ' '))) + return -1; + while (pkt_index < MAX_IMIX_PKTS) { + if (sscanf(str, "%d", &pkt_sizes[pkt_index]) != 1) + break; + pkt_index++; + if ((str = strchr(str, ',')) == NULL) + break; + str = str + 1; + } + if (pkt_index == 0) { + plog_err("No pkt size found\n"); + return -1; + } + if ((pkt_index == MAX_IMIX_PKTS) && (str) && (sscanf(str, "%d", &tmp) == 1)) { + plog_err("Too many inputs - unexpected inputs starting at %s\n", str); + return -1; + } + + if (cores_task_are_valid(lcores, task_id, nb_cores)) { + for (unsigned int i = 0; i < nb_cores; i++) { + lcore_id = lcores[i]; + if ((!task_is_mode_and_submode(lcore_id, task_id, "gen", "")) && (!task_is_mode_and_submode(lcore_id, task_id, "gen", "l3"))) { + plog_err("Core %u task %u is not generating packets\n", lcore_id, task_id); + } else { + struct task_base *tbase = lcore_cfg[lcore_id].tasks_all[task_id]; + task_gen_set_imix(tbase, pkt_index, pkt_sizes); /* error printed within function */ + } + } + } + return 0; +} + static int parse_cmd_speed(const char *str, struct input *input) { unsigned lcores[RTE_MAX_LCORE], task_id, lcore_id, nb_cores; @@ -2143,6 +2184,7 @@ static struct cmd_str cmd_strings[] = { {"bypass", "<core_id> <task_id>", "Bypass task", parse_cmd_bypass}, {"reconnect", "<core_id> <task_id>", "Reconnect task", parse_cmd_reconnect}, {"pkt_size", "<core_id> <task_id> <pkt_size>", "Set the packet size to <pkt_size>", parse_cmd_pkt_size}, + {"imix", "<core_id> <task_id> <pkt_size,pkt_size ... >", "Set the packet sizes to <pkt_size>", parse_cmd_imix}, {"speed", "<core_id> <task_id> <speed percentage>", "Change the speed to <speed percentage> at which packets are being generated on core <core_id> in task <task_id>.", parse_cmd_speed}, {"speed_byte", "<core_id> <task_id> <speed>", "Change speed to <speed>. The speed is specified in units of bytes per second.", parse_cmd_speed_byte}, {"set value", "<core_id> <task_id> <offset> <value> <value_len>", "Set <value_len> bytes to <value> at offset <offset> in packets generated on <core_id> <task_id>", parse_cmd_set_value}, diff --git a/VNFs/DPPD-PROX/defaults.h b/VNFs/DPPD-PROX/defaults.h index 18dae530..69017710 100644 --- a/VNFs/DPPD-PROX/defaults.h +++ b/VNFs/DPPD-PROX/defaults.h @@ -31,6 +31,7 @@ void set_port_defaults(void); #define MAX_PKT_BURST 64 #define MAX_RING_BURST 64 #define DUMP_PKT_LEN MAX_PKT_SIZE +#define MAX_IMIX_PKTS 128 #if MAX_RING_BURST < MAX_PKT_BURST #error MAX_RING_BURST < MAX_PKT_BURST diff --git a/VNFs/DPPD-PROX/handle_gen.c b/VNFs/DPPD-PROX/handle_gen.c index 3bcb231f..1546dce7 100644 --- a/VNFs/DPPD-PROX/handle_gen.c +++ b/VNFs/DPPD-PROX/handle_gen.c @@ -22,6 +22,7 @@ #include <rte_byteorder.h> #include <rte_ether.h> #include <rte_hash_crc.h> +#include <rte_malloc.h> #include "prox_shared.h" #include "random.h" @@ -56,6 +57,12 @@ struct pkt_template { #define IP4(x) x & 0xff, (x >> 8) & 0xff, (x >> 16) & 0xff, x >> 24 +#define DO_PANIC 1 +#define DO_NOT_PANIC 0 + +#define FROM_PCAP 1 +#define NOT_FROM_PCAP 0 + #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) @@ -78,6 +85,7 @@ struct task_gen_pcap { uint32_t n_pkts; uint64_t last_tsc; uint64_t *proto_tsc; + uint32_t socket_id; }; struct task_gen { @@ -91,6 +99,7 @@ struct task_gen { uint64_t new_rate_bps; uint64_t pkt_queue_index; uint32_t n_pkts; /* number of packets in pcap */ + uint32_t orig_n_pkts; /* number of packets in pcap */ uint32_t pkt_idx; /* current packet from pcap */ uint32_t pkt_count; /* how many pakets to generate */ uint32_t max_frame_size; @@ -100,6 +109,7 @@ struct task_gen { uint16_t accur_pos; uint16_t sig_pos; uint32_t sig; + uint32_t socket_id; uint8_t generator_id; uint8_t n_rands; /* number of randoms */ uint8_t min_bulk_size; @@ -121,6 +131,9 @@ struct task_gen { uint8_t cksum_offload; struct prox_port_cfg *port; uint64_t *bytes_to_tsc; + uint32_t imix_pkt_sizes[MAX_IMIX_PKTS]; + uint32_t imix_nb_pkts; + uint32_t new_imix_nb_pkts; } __rte_cache_aligned; static inline uint8_t ipv4_get_hdr_len(prox_rte_ipv4_hdr *ip) @@ -266,7 +279,7 @@ static inline uint64_t bytes_to_tsc(struct task_gen *task, uint32_t bytes) static uint32_t task_gen_next_pkt_idx(const struct task_gen *task, uint32_t pkt_idx) { - return pkt_idx + 1 == task->n_pkts? 0 : pkt_idx + 1; + return pkt_idx + 1 >= task->n_pkts? 0 : pkt_idx + 1; } static uint32_t task_gen_offset_pkt_idx(const struct task_gen *task, uint32_t offset) @@ -541,10 +554,196 @@ static void task_gen_build_packets(struct task_gen *task, struct rte_mbuf **mbuf } } +static int task_gen_allocate_templates(struct task_gen *task, uint32_t orig_nb_pkts, uint32_t nb_pkts, int do_panic, int pcap) +{ + size_t mem_size = nb_pkts * sizeof(*task->pkt_template); + size_t orig_mem_size = orig_nb_pkts * sizeof(*task->pkt_template); + task->pkt_template = prox_zmalloc(mem_size, task->socket_id); + task->pkt_template_orig = prox_zmalloc(orig_mem_size, task->socket_id); + + if (task->pkt_template == NULL || task->pkt_template_orig == NULL) { + plog_err_or_panic(do_panic, "Failed to allocate %lu bytes (in huge pages) for %s\n", mem_size, pcap ? "pcap file":"packet template"); + return -1; + } + + for (size_t i = 0; i < orig_nb_pkts; i++) { + task->pkt_template_orig[i].buf = prox_zmalloc(task->max_frame_size, task->socket_id); + if (task->pkt_template_orig[i].buf == NULL) { + plog_err_or_panic(do_panic, "Failed to allocate %u bytes (in huge pages) for %s\n", task->max_frame_size, pcap ? "packet from pcap": "packet"); + return -1; + } + } + for (size_t i = 0; i < nb_pkts; i++) { + task->pkt_template[i].buf = prox_zmalloc(task->max_frame_size, task->socket_id); + if (task->pkt_template[i].buf == NULL) { + plog_err_or_panic(do_panic, "Failed to allocate %u bytes (in huge pages) for %s\n", task->max_frame_size, pcap ? "packet from pcap": "packet"); + return -1; + } + } + return 0; +} + +static int task_gen_reallocate_templates(struct task_gen *task, uint32_t nb_pkts, int do_panic) +{ + // Need to free up bufs allocated in previous (longer) imix + for (size_t i = nb_pkts; i < task->n_pkts; i++) { + if (task->pkt_template[i].buf) { + rte_free(task->pkt_template[i].buf); + task->pkt_template[i].buf = NULL; + } + } + + size_t mem_size = nb_pkts * sizeof(*task->pkt_template); + struct pkt_template *ptr; + // re-allocate memory for new pkt_template (this might allocate additional memory or free up some...) + if ((ptr = rte_realloc_socket(task->pkt_template, mem_size, RTE_CACHE_LINE_SIZE, task->socket_id)) != NULL) { + task->pkt_template = ptr; + } else { + plog_err_or_panic(do_panic, "Failed to allocate %lu bytes (in huge pages) for packet template for IMIX\n", mem_size); + return -1; + } + + // Need to allocate bufs for new template but no need to reallocate for existing ones + for (size_t i = task->n_pkts; i < nb_pkts; ++i) { + task->pkt_template[i].buf = prox_zmalloc(task->max_frame_size, task->socket_id); + if (task->pkt_template[i].buf == NULL) { + plog_err_or_panic(do_panic, "Failed to allocate %u bytes (in huge pages) for packet %zd in IMIX\n", task->max_frame_size, i); + return -1; + } + } + return 0; +} + +static int check_pkt_size(struct task_gen *task, uint32_t pkt_size, int do_panic) +{ + const uint16_t min_len = sizeof(prox_rte_ether_hdr) + sizeof(prox_rte_ipv4_hdr); + const uint16_t max_len = task->max_frame_size; + + if (do_panic) { + PROX_PANIC(pkt_size == 0, "Invalid packet size length (no packet defined?)\n"); + PROX_PANIC(pkt_size > max_len, "pkt_size out of range (must be <= %u)\n", max_len); + PROX_PANIC(pkt_size < min_len, "pkt_size out of range (must be >= %u)\n", min_len); + return 0; + } else { + if (pkt_size == 0) { + plog_err("Invalid packet size length (no packet defined?)\n"); + return -1; + } + if (pkt_size > max_len) { + if (pkt_size > PROX_RTE_ETHER_MAX_LEN + 2 * PROX_VLAN_TAG_SIZE - 4) + plog_err("pkt_size too high and jumbo frames disabled\n"); + else + plog_err("pkt_size out of range (must be <= (mtu=%u))\n", max_len); + return -1; + } + if (pkt_size < min_len) { + plog_err("pkt_size out of range (must be >= %u)\n", min_len); + return -1; + } + return 0; + } +} + +static int check_fields_in_bounds(struct task_gen *task, uint32_t pkt_size, int do_panic) +{ + if (task->lat_enabled) { + uint32_t pos_beg = task->lat_pos; + uint32_t pos_end = task->lat_pos + 3U; + + 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; + + 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; + + 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 int task_gen_set_eth_ip_udp_sizes(struct task_gen *task, uint32_t n_orig_pkts, uint32_t nb_pkt_sizes, uint32_t *pkt_sizes) +{ + size_t k; + uint32_t l4_len; + prox_rte_ipv4_hdr *ip; + struct pkt_template *template; + + for (size_t j = 0; j < nb_pkt_sizes; ++j) { + for (size_t i = 0; i < n_orig_pkts; ++i) { + k = j * n_orig_pkts + i; + template = &task->pkt_template[k]; + template->len = pkt_sizes[j]; + rte_memcpy(template->buf, task->pkt_template_orig[i].buf, pkt_sizes[j]); + parse_l2_l3_len(template->buf, &template->l2_len, &template->l3_len, template->len); + if (template->l2_len == 0) + continue; + ip = (prox_rte_ipv4_hdr *)(template->buf + template->l2_len); + ip->total_length = rte_bswap16(pkt_sizes[j] - template->l2_len); + l4_len = pkt_sizes[j] - template->l2_len - template->l3_len; + ip->hdr_checksum = 0; + prox_ip_cksum_sw(ip); + + if (ip->next_proto_id == IPPROTO_UDP) { + prox_rte_udp_hdr *udp = (prox_rte_udp_hdr *)(((uint8_t *)ip) + template->l3_len); + udp->dgram_len = rte_bswap16(l4_len); + prox_udp_cksum_sw(udp, l4_len, ip->src_addr, ip->dst_addr); + } else if (ip->next_proto_id == IPPROTO_TCP) { + prox_rte_tcp_hdr *tcp = (prox_rte_tcp_hdr *)(((uint8_t *)ip) + template->l3_len); + prox_tcp_cksum_sw(tcp, l4_len, ip->src_addr, ip->dst_addr); + } + } + } + return 0; +} + +static int task_gen_apply_imix(struct task_gen *task, int do_panic) +{ + struct pkt_template *ptr; + int rc; + task->imix_nb_pkts = task->new_imix_nb_pkts; + uint32_t n_pkts = task->imix_nb_pkts * task->orig_n_pkts; + + if ((n_pkts != task->n_pkts) && ((rc = task_gen_reallocate_templates(task, n_pkts, do_panic)) < 0)) + return rc; + + task->n_pkts = n_pkts; + if (task->pkt_idx >= n_pkts) + task->pkt_idx = 0; + task_gen_set_eth_ip_udp_sizes(task, task->orig_n_pkts, task->imix_nb_pkts, task->imix_pkt_sizes); + return 0; +} + static void task_gen_update_config(struct task_gen *task) { if (task->token_time.cfg.bpp != task->new_rate_bps) task_gen_reset_token_time(task); + if (task->new_imix_nb_pkts) + task_gen_apply_imix(task, DO_NOT_PANIC); + task->new_imix_nb_pkts = 0; } static inline void build_value(struct task_gen *task, uint32_t mask, int bit_pos, uint32_t val, uint32_t fixed_bits) @@ -759,33 +958,6 @@ static int pcap_read_pkts(pcap_t *handle, const char *file_name, uint32_t n_pkts return 0; } -static int check_pkt_size(struct task_gen *task, uint32_t pkt_size, int do_panic) -{ - const uint16_t min_len = sizeof(prox_rte_ether_hdr) + sizeof(prox_rte_ipv4_hdr); - const uint16_t max_len = task->max_frame_size; - - if (do_panic) { - PROX_PANIC(pkt_size == 0, "Invalid packet size length (no packet defined?)\n"); - PROX_PANIC(pkt_size > max_len, "pkt_size out of range (must be <= %u)\n", max_len); - PROX_PANIC(pkt_size < min_len, "pkt_size out of range (must be >= %u)\n", min_len); - return 0; - } else { - if (pkt_size == 0) { - plog_err("Invalid packet size length (no packet defined?)\n"); - return -1; - } - if (pkt_size > max_len) { - plog_err("pkt_size out of range (must be <= %u)\n", max_len); - return -1; - } - if (pkt_size < min_len) { - plog_err("pkt_size out of range (must be >= %u)\n", min_len); - return -1; - } - return 0; - } -} - static int check_all_pkt_size(struct task_gen *task, int do_panic) { int rc; @@ -796,43 +968,12 @@ static int check_all_pkt_size(struct task_gen *task, int do_panic) return 0; } -static int check_fields_in_bounds(struct task_gen *task, uint32_t pkt_size, int do_panic) +static int check_all_fields_in_bounds(struct task_gen *task, int do_panic) { - if (task->lat_enabled) { - uint32_t pos_beg = task->lat_pos; - uint32_t pos_end = task->lat_pos + 3U; - - 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; - - 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; - - 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; - } + int rc; + for (uint32_t i = 0; i < task->n_pkts;++i) { + if ((rc = check_fields_in_bounds(task, task->pkt_template[i].len, do_panic)) != 0) + return rc; } return 0; } @@ -894,10 +1035,12 @@ static void task_gen_reset_pkt_templates_len(struct task_gen *task) { struct pkt_template *src, *dst; - for (size_t i = 0; i < task->n_pkts; ++i) { - src = &task->pkt_template_orig[i]; - dst = &task->pkt_template[i]; - dst->len = src->len; + for (size_t j = 0; j < task->n_pkts / task->orig_n_pkts; ++j) { + for (size_t i = 0; i < task->orig_n_pkts; ++i) { + src = &task->pkt_template_orig[i]; + dst = &task->pkt_template[j * task->orig_n_pkts + i]; + dst->len = src->len; + } } } @@ -905,11 +1048,13 @@ static void task_gen_reset_pkt_templates_content(struct task_gen *task) { struct pkt_template *src, *dst; - 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, RTE_MAX(src->len, dst->len)); - task_gen_apply_sig(task, dst); + for (size_t j = 0; j < task->n_pkts / task->orig_n_pkts; ++j) { + for (size_t i = 0; i < task->orig_n_pkts; ++i) { + src = &task->pkt_template_orig[i]; + dst = &task->pkt_template[j * task->orig_n_pkts + i]; + memcpy(dst->buf, src->buf, RTE_MAX(src->len, dst->len)); + task_gen_apply_sig(task, dst); + } } } @@ -922,71 +1067,57 @@ static void task_gen_reset_pkt_templates(struct task_gen *task) static void task_init_gen_load_pkt_inline(struct task_gen *task, struct task_args *targ) { - const int socket_id = rte_lcore_to_socket_id(targ->lconf->id); - - task->n_pkts = 1; - - size_t mem_size = task->n_pkts * sizeof(*task->pkt_template); - task->pkt_template = prox_zmalloc(mem_size, socket_id); - task->pkt_template_orig = prox_zmalloc(mem_size, socket_id); - - PROX_PANIC(task->pkt_template == NULL || - task->pkt_template_orig == NULL, - "Failed to allocate %lu bytes (in huge pages) for packet template\n", mem_size); - - task->pkt_template->buf = prox_zmalloc(task->max_frame_size, socket_id); - task->pkt_template_orig->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 packet\n", task->max_frame_size); + int rc; - PROX_PANIC(targ->pkt_size > task->max_frame_size, - targ->pkt_size > PROX_RTE_ETHER_MAX_LEN + 2 * PROX_VLAN_TAG_SIZE - 4 ? - "pkt_size too high and jumbo frames disabled" : "pkt_size > mtu"); + task->orig_n_pkts = 1; + if (task->imix_nb_pkts == 0) { + task->n_pkts = 1; + task->imix_pkt_sizes[0] = targ->pkt_size; + } else { + task->n_pkts = task->imix_nb_pkts; + } + task_gen_allocate_templates(task, task->orig_n_pkts, task->n_pkts, DO_PANIC, NOT_FROM_PCAP); - rte_memcpy(task->pkt_template_orig[0].buf, targ->pkt_inline, targ->pkt_size); - task->pkt_template_orig[0].len = targ->pkt_size; + rte_memcpy(task->pkt_template_orig[0].buf, targ->pkt_inline, task->max_frame_size); + task->pkt_template_orig[0].len = task->imix_pkt_sizes[0]; task_gen_reset_pkt_templates(task); - check_all_pkt_size(task, 1); - check_fields_in_bounds(task, task->pkt_template[0].len, 1); + check_all_pkt_size(task, DO_PANIC); + check_all_fields_in_bounds(task, DO_PANIC); + + // If IMIX was not specified then pkt_size is specified using pkt_size parameter or the length of pkt_inline + // In that case, for backward compatibility, we do NOT adapt the length of IP and UDP to the length of the packet + task_gen_set_eth_ip_udp_sizes(task, task->orig_n_pkts, task->imix_nb_pkts, task->imix_pkt_sizes); } static void task_init_gen_load_pcap(struct task_gen *task, struct task_args *targ) { - const int socket_id = rte_lcore_to_socket_id(targ->lconf->id); char err[PCAP_ERRBUF_SIZE]; uint32_t max_frame_size; pcap_t *handle = pcap_open_offline(targ->pcap_file, err); 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'; max frame size=%d\n", task->n_pkts, targ->pcap_file, max_frame_size); + task->orig_n_pkts = pcap_count_pkts(handle, &max_frame_size); + plogx_info("%u packets in pcap file '%s'; max frame size=%d\n", task->orig_n_pkts, targ->pcap_file, max_frame_size); PROX_PANIC(max_frame_size > task->max_frame_size, max_frame_size > PROX_RTE_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); - 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); - task->pkt_template_orig = prox_zmalloc(mem_size, socket_id); - PROX_PANIC(task->pkt_template == NULL || - task->pkt_template_orig == NULL, - "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(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); + task->orig_n_pkts = RTE_MIN(task->orig_n_pkts, targ->n_pkts); + if (task->imix_nb_pkts == 0) { + task->n_pkts = task->orig_n_pkts; + } else { + task->n_pkts = task->imix_nb_pkts * task->orig_n_pkts; } + task_gen_allocate_templates(task, task->orig_n_pkts, task->n_pkts, DO_PANIC, FROM_PCAP); + plogx_info("Loading %u packets from pcap\n", task->n_pkts); - pcap_read_pkts(handle, targ->pcap_file, task->n_pkts, task->pkt_template_orig, NULL, max_frame_size); + pcap_read_pkts(handle, targ->pcap_file, task->orig_n_pkts, task->pkt_template_orig, NULL, max_frame_size); pcap_close(handle); task_gen_reset_pkt_templates(task); + check_all_pkt_size(task, DO_PANIC); + check_all_fields_in_bounds(task, DO_PANIC); + task_gen_set_eth_ip_udp_sizes(task, task->orig_n_pkts, task->imix_nb_pkts, task->imix_pkt_sizes); } static struct rte_mempool *task_gen_create_mempool(struct task_args *targ, uint16_t max_frame_size) @@ -1037,6 +1168,23 @@ int task_gen_set_pkt_size(struct task_base *tbase, uint32_t pkt_size) return 0; } +int task_gen_set_imix(struct task_base *tbase, uint32_t nb_pkt_sizes, uint32_t *pkt_sizes) +{ + struct task_gen *task = (struct task_gen *)tbase; + int rc; + + memcpy(task->imix_pkt_sizes, pkt_sizes, nb_pkt_sizes * sizeof(uint32_t)); + for (size_t i = 0; i < nb_pkt_sizes; ++i) { + if ((rc = check_pkt_size(task, pkt_sizes[i], DO_NOT_PANIC)) != 0) + return rc; + if ((rc = check_fields_in_bounds(task, pkt_sizes[i], DO_NOT_PANIC)) != 0) + return rc; + } + // only set new_imix_nb_pkts if checks of pkt sizes succeeded + task->new_imix_nb_pkts = nb_pkt_sizes; + return 0; +} + void task_gen_set_rate(struct task_base *tbase, uint64_t bps) { struct task_gen *task = (struct task_gen *)tbase; @@ -1096,7 +1244,7 @@ uint32_t task_gen_get_n_randoms(struct task_base *tbase) static void init_task_gen_pcap(struct task_base *tbase, struct task_args *targ) { struct task_gen_pcap *task = (struct task_gen_pcap *)tbase; - const uint32_t sockid = rte_lcore_to_socket_id(targ->lconf->id); + task->socket_id = rte_lcore_to_socket_id(targ->lconf->id); uint32_t max_frame_size; task->loop = targ->loop; @@ -1122,14 +1270,14 @@ static void init_task_gen_pcap(struct task_base *tbase, struct task_args *targ) 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)); - uint8_t *mem = prox_zmalloc(mem_size, sockid); + uint8_t *mem = prox_zmalloc(mem_size, task->socket_id); PROX_PANIC(mem == NULL, "Failed to allocate %lu bytes (in huge pages) for pcap file\n", mem_size); task->proto = (struct pkt_template *) mem; task->proto_tsc = (uint64_t *)(mem + task->n_pkts * sizeof(*task->proto)); for (uint i = 0; i < targ->n_pkts; i++) { - task->proto[i].buf = prox_zmalloc(max_frame_size, sockid); + task->proto[i].buf = prox_zmalloc(max_frame_size, task->socket_id); PROX_PANIC(task->proto[i].buf == NULL, "Failed to allocate %u bytes (in huge pages) for pcap file\n", max_frame_size); } @@ -1229,6 +1377,7 @@ static void init_task_gen_early(struct task_args *targ) static void init_task_gen(struct task_base *tbase, struct task_args *targ) { struct task_gen *task = (struct task_gen *)tbase; + task->socket_id = rte_lcore_to_socket_id(targ->lconf->id); task->packet_id_pos = targ->packet_id_pos; @@ -1282,7 +1431,7 @@ static void init_task_gen(struct task_base *tbase, struct task_args *targ) plog_info("\tGenerator id = %d\n", task->generator_id); // Allocate array holding bytes to tsc for supported frame sizes - task->bytes_to_tsc = prox_zmalloc(task->max_frame_size * MAX_PKT_BURST * sizeof(task->bytes_to_tsc[0]), rte_lcore_to_socket_id(targ->lconf->id)); + task->bytes_to_tsc = prox_zmalloc(task->max_frame_size * MAX_PKT_BURST * sizeof(task->bytes_to_tsc[0]), task->socket_id); PROX_PANIC(task->bytes_to_tsc == NULL, "Failed to allocate %u bytes (in huge pages) for bytes_to_tsc\n", task->max_frame_size); @@ -1304,6 +1453,10 @@ static void init_task_gen(struct task_base *tbase, struct task_args *targ) task->bytes_to_tsc[i] = (task->hz * i * 0.99) / bytes_per_hz; } + task->imix_nb_pkts = targ->imix_nb_pkts; + for (uint32_t i = 0; i < targ->imix_nb_pkts; i++) { + task->imix_pkt_sizes[i] = targ->imix_pkt_sizes[i]; + } if (!strcmp(targ->pcap_file, "")) { plog_info("\tUsing inline definition of a packet\n"); task_init_gen_load_pkt_inline(task, targ); diff --git a/VNFs/DPPD-PROX/handle_gen.h b/VNFs/DPPD-PROX/handle_gen.h index 5083fea9..bb85b0ca 100644 --- a/VNFs/DPPD-PROX/handle_gen.h +++ b/VNFs/DPPD-PROX/handle_gen.h @@ -38,6 +38,7 @@ struct task_base; void task_gen_set_pkt_count(struct task_base *tbase, uint32_t count); int task_gen_set_pkt_size(struct task_base *tbase, uint32_t pkt_size); +int task_gen_set_imix(struct task_base *tbase, uint32_t nb_pkts, uint32_t *pkt_size); void task_gen_set_rate(struct task_base *tbase, uint64_t bps); void task_gen_reset_randoms(struct task_base *tbase); void task_gen_reset_values(struct task_base *tbase); diff --git a/VNFs/DPPD-PROX/log.c b/VNFs/DPPD-PROX/log.c index 2094c185..2fa63f34 100644 --- a/VNFs/DPPD-PROX/log.c +++ b/VNFs/DPPD-PROX/log.c @@ -25,6 +25,7 @@ #include <rte_mbuf.h> #include "log.h" +#include "quit.h" #include "display.h" #include "defaults.h" #include "etypes.h" @@ -212,6 +213,10 @@ static int vplog(int lvl, const char *format, va_list ap, const struct rte_mbuf ret--; ret += dump_pkt(buf + ret, sizeof(buf) - ret, mbuf); } + + if (lvl == PROX_LOG_PANIC) + PROX_PANIC(1, "%s", buf); + plog_buf(buf); if (lvl == PROX_LOG_WARN) { @@ -278,6 +283,23 @@ int plog_err(const char *fmt, ...) return ret; } +int plog_err_or_panic(int do_panic, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + if (do_panic) { + ret = vplog(PROX_LOG_PANIC, fmt, ap, NULL, 0); + va_end(ap); + return ret; + } else { + ret = vplog(PROX_LOG_ERR, fmt, ap, NULL, 0); + va_end(ap); + return ret; + } +} + int plogx_err(const char *fmt, ...) { va_list ap; diff --git a/VNFs/DPPD-PROX/log.h b/VNFs/DPPD-PROX/log.h index 0d2fba18..b270462e 100644 --- a/VNFs/DPPD-PROX/log.h +++ b/VNFs/DPPD-PROX/log.h @@ -17,6 +17,7 @@ #ifndef _LOG_H_ #define _LOG_H_ +#define PROX_LOG_PANIC -1 #define PROX_LOG_ERR 0 #define PROX_LOG_WARN 1 #define PROX_LOG_INFO 2 @@ -33,11 +34,13 @@ const char* get_warning(int i); struct rte_mbuf; #if PROX_MAX_LOG_LVL >= PROX_LOG_ERR +int plog_err_or_panic(int do_panic, const char *fmt, ...) __attribute__((format(printf, 2, 3), cold)); int plog_err(const char *fmt, ...) __attribute__((format(printf, 1, 2), cold)); int plogx_err(const char *fmt, ...) __attribute__((format(printf, 1, 2), cold)); int plogd_err(const struct rte_mbuf *mbuf, const char *fmt, ...) __attribute__((format(printf, 2, 3), cold)); int plogdx_err(const struct rte_mbuf *mbuf, const char *fmt, ...) __attribute__((format(printf, 2, 3), cold)); #else +__attribute__((format(printf, 2, 3))) static inline int plog_err_or_panic(__attribute__((unused)) int do_panic, __attribute__((unused)) const char *fmt, ...) {return 0;} __attribute__((format(printf, 1, 2))) static inline int plog_err(__attribute__((unused)) const char *fmt, ...) {return 0;} __attribute__((format(printf, 1, 2))) static inline int plogx_err(__attribute__((unused)) const char *fmt, ...) {return 0;} __attribute__((format(printf, 2, 3))) static inline int plogd_err(__attribute__((unused)) const struct rte_mbuf *mbuf, __attribute__((unused)) const char *fmt, ...) {return 0;} diff --git a/VNFs/DPPD-PROX/prox_args.c b/VNFs/DPPD-PROX/prox_args.c index cb0dcb31..cc8b3b25 100644 --- a/VNFs/DPPD-PROX/prox_args.c +++ b/VNFs/DPPD-PROX/prox_args.c @@ -1009,6 +1009,34 @@ static int get_core_cfg(unsigned sindex, char *str, void *data) if (STR_EQ(str, "pcap file")) { return parse_str(targ->pcap_file, pkey, sizeof(targ->pcap_file)); } + if (STR_EQ(str, "imix")) { + char pkey2[MAX_CFG_STRING_LEN], *ptr; + if (parse_str(pkey2, pkey, sizeof(pkey2)) != 0) { + set_errf("Error while parsing imix, too long\n"); + return -1; + } + const size_t pkey_len = strlen(pkey2); + targ->imix_nb_pkts = 0; + ptr = pkey2; + while (targ->imix_nb_pkts < MAX_IMIX_PKTS) { + if (parse_int(&targ->imix_pkt_sizes[targ->imix_nb_pkts], ptr) != 0) + break; + targ->imix_nb_pkts++; + if ((ptr = strchr(ptr, ',')) == NULL) + break; + ptr++; + if (targ->imix_nb_pkts == MAX_IMIX_PKTS) { + set_errf("Too many packet sizes specified"); + return -1; + } + } + plog_info("%d IMIX packets:", targ->imix_nb_pkts); + for (size_t i = 0; i < targ->imix_nb_pkts; ++i) { + plog_info("%d ", targ->imix_pkt_sizes[i]); + } + plog_info("\n"); + return 0; + } if (STR_EQ(str, "pkt inline")) { char pkey2[MAX_CFG_STRING_LEN]; if (parse_str(pkey2, pkey, sizeof(pkey2)) != 0) { diff --git a/VNFs/DPPD-PROX/task_init.h b/VNFs/DPPD-PROX/task_init.h index 98c0a8dc..e6261c2a 100644 --- a/VNFs/DPPD-PROX/task_init.h +++ b/VNFs/DPPD-PROX/task_init.h @@ -236,6 +236,8 @@ struct task_args { struct task_base *tmaster; char sub_mode_str[PROX_MODE_LEN]; uint32_t igmp_address; + uint32_t imix_nb_pkts; + uint32_t imix_pkt_sizes[MAX_IMIX_PKTS]; }; /* Return the first port that is reachable through the task. If the |