X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=VNFs%2FDPPD-PROX%2Fhandle_gen.c;h=9bb34fc73e54bb47f386dbe22559ea41d333702c;hb=26f14f6f6f11892fbed6d6e199c5d73f3d1ce70a;hp=e5e43fca84da6f104999fcdc7ef5cf14d0ab8c0a;hpb=cb94e0036256c6a3fb0aadb682a04d8ad30ddd2a;p=samplevnf.git diff --git a/VNFs/DPPD-PROX/handle_gen.c b/VNFs/DPPD-PROX/handle_gen.c index e5e43fca..9bb34fc7 100644 --- a/VNFs/DPPD-PROX/handle_gen.c +++ b/VNFs/DPPD-PROX/handle_gen.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "prox_shared.h" #include "random.h" @@ -45,22 +46,15 @@ #include "local_mbuf.h" #include "arp.h" #include "tx_pkt.h" -#include +#include "handle_master.h" struct pkt_template { - uint64_t dst_mac; - uint32_t ip_src; - uint32_t ip_dst_pos; uint16_t len; uint16_t l2_len; uint16_t l3_len; uint8_t buf[ETHER_MAX_LEN]; }; -#define FLAG_DST_MAC_KNOWN 1 -#define FLAG_L3_GEN 2 -#define FLAG_RANDOM_IPS 4 - #define MAX_TEMPLATE_INDEX 65536 #define TEMPLATE_INDEX_MASK (MAX_TEMPLATE_INDEX - 1) #define MBUF_ARP MAX_TEMPLATE_INDEX @@ -125,14 +119,10 @@ struct task_gen { uint64_t accur[64]; uint64_t pkt_tsc_offset[64]; struct pkt_template *pkt_template_orig; /* packet templates (from inline or from pcap) */ - struct ether_addr gw_mac; struct ether_addr src_mac; - struct rte_hash *mac_hash; - uint64_t *dst_mac; - uint32_t gw_ip; - uint32_t src_ip; uint8_t flags; uint8_t cksum_offload; + struct prox_port_cfg *port; } __rte_cache_aligned; static inline uint8_t ipv4_get_hdr_len(struct ipv4_hdr *ip) @@ -207,22 +197,6 @@ static void task_gen_reset_token_time(struct task_gen *task) token_time_reset(&task->token_time, rte_rdtsc(), 0); } -static void start(struct task_base *tbase) -{ - struct task_gen *task = (struct task_gen *)tbase; - task->pkt_queue_index = 0; - - task_gen_reset_token_time(task); -} - -static void start_pcap(struct task_base *tbase) -{ - struct task_gen_pcap *task = (struct task_gen_pcap *)tbase; - /* When we start, the first packet is sent immediately. */ - task->last_tsc = rte_rdtsc() - task->proto_tsc[0]; - task->pkt_idx = 0; -} - static void task_gen_take_count(struct task_gen *task, uint32_t send_bulk) { if (task->pkt_count == (uint32_t)-1) @@ -337,13 +311,7 @@ static uint32_t task_gen_calc_send_bulk(const struct task_gen *task, uint32_t *t */ for (uint16_t j = 0; j < max_bulk; ++j) { struct pkt_template *pktpl = &task->pkt_template[pkt_idx_tmp]; - if (unlikely((task->flags & (FLAG_L3_GEN | FLAG_DST_MAC_KNOWN)) == FLAG_L3_GEN)) { - // Generator is supposed to get MAC address - MAC is still unknown for this template - // generate ARP Request to gateway instead of the intended packet - pkt_size = 60; - } else { - pkt_size = pktpl->len; - } + pkt_size = pktpl->len; uint32_t pkt_len = pkt_len_to_wire_size(pkt_size); if (pkt_len + would_send_bytes > task->token_time.bytes_now) break; @@ -360,106 +328,6 @@ static uint32_t task_gen_calc_send_bulk(const struct task_gen *task, uint32_t *t return send_bulk; } -static inline void create_arp(struct rte_mbuf *mbuf, uint8_t *pkt_hdr, uint64_t *src_mac, uint32_t ip_dst, uint32_t ip_src) -{ - uint64_t mac_bcast = 0xFFFFFFFFFFFF; - rte_pktmbuf_pkt_len(mbuf) = 42; - rte_pktmbuf_data_len(mbuf) = 42; - init_mbuf_seg(mbuf); - struct ether_hdr_arp *hdr_arp = (struct ether_hdr_arp *)pkt_hdr; - - memcpy(&hdr_arp->ether_hdr.d_addr.addr_bytes, &mac_bcast, 6); - memcpy(&hdr_arp->ether_hdr.s_addr.addr_bytes, src_mac, 6); - hdr_arp->ether_hdr.ether_type = ETYPE_ARP; - hdr_arp->arp.htype = 0x100, - hdr_arp->arp.ptype = 0x0008; - hdr_arp->arp.hlen = 6; - hdr_arp->arp.plen = 4; - hdr_arp->arp.oper = 0x100; - hdr_arp->arp.data.spa = ip_src; - hdr_arp->arp.data.tpa = ip_dst; - memset(&hdr_arp->arp.data.tha, 0, sizeof(struct ether_addr)); - memcpy(&hdr_arp->arp.data.sha, src_mac, sizeof(struct ether_addr)); -} - -static int task_gen_write_dst_mac(struct task_gen *task, struct rte_mbuf **mbufs, uint8_t **pkt_hdr, uint32_t count) -{ - uint32_t ip_dst_pos, ip_src_pos, ip_dst, ip_src; - uint16_t i; - int ret; - - if (task->flags & FLAG_L3_GEN) { - if (task->gw_ip) { - if (unlikely((task->flags & FLAG_DST_MAC_KNOWN) == 0)) { - for (i = 0; i < count; ++i) { - struct pkt_template *pktpl = &task->pkt_template[mbufs[i]->udata64 & TEMPLATE_INDEX_MASK]; - create_arp(mbufs[i], pkt_hdr[i], (uint64_t *)&pktpl->buf[6], task->gw_ip, pktpl->ip_src); - mbufs[i]->udata64 |= MBUF_ARP; - } - } else { - for (i = 0; i < count; ++i) { - struct ether_hdr *hdr = (struct ether_hdr *)pkt_hdr[i]; - memcpy(&hdr->d_addr.addr_bytes, &task->gw_mac, 6); - } - } - } else if (unlikely((task->flags & FLAG_RANDOM_IPS) != 0) || (task->n_pkts >= 4)){ - // Find mac in lookup table. Send ARP if not found - int32_t positions[MAX_PKT_BURST], idx; - void *keys[MAX_PKT_BURST]; - uint32_t key[MAX_PKT_BURST]; - for (i = 0; i < count; ++i) { - uint8_t *hdr = (uint8_t *)pkt_hdr[i]; - struct pkt_template *pktpl = &task->pkt_template[mbufs[i]->udata64 & TEMPLATE_INDEX_MASK]; - ip_dst_pos = pktpl->ip_dst_pos; - ip_dst = *(uint32_t *)(hdr + ip_dst_pos); - key[i] = ip_dst; - keys[i] = &key[i]; - } - ret = rte_hash_lookup_bulk(task->mac_hash, (const void **)&keys, count, positions); - if (unlikely(ret < 0)) { - plogx_err("lookup_bulk failed in mac_hash\n"); - tx_pkt_drop_all((struct task_base *)task, mbufs, count, NULL); - return -1; - } - for (i = 0; i < count; ++i) { - idx = positions[i]; - if (unlikely(idx < 0)) { - // mac not found for this IP - struct pkt_template *pktpl = &task->pkt_template[mbufs[i]->udata64 & TEMPLATE_INDEX_MASK]; - uint8_t *hdr = (uint8_t *)pkt_hdr[i]; - ip_src_pos = pktpl->ip_dst_pos - 4; - ip_src = *(uint32_t *)(hdr + ip_src_pos); - create_arp(mbufs[i], pkt_hdr[i], (uint64_t *)&hdr[6], key[i], ip_src); - mbufs[i]->udata64 |= MBUF_ARP; - } else { - // mac found for this IP - struct ether_hdr_arp *hdr_arp = (struct ether_hdr_arp *)pkt_hdr[i]; - memcpy(&hdr_arp->ether_hdr.d_addr.addr_bytes, &task->dst_mac[idx], 6); - } - } - } else { - for (i = 0; i < count; ++i) { - uint8_t *hdr = (uint8_t *)pkt_hdr[i]; - struct pkt_template *pktpl = &task->pkt_template[mbufs[i]->udata64 & TEMPLATE_INDEX_MASK]; - - // Check if packet template already has the mac - if (unlikely(pktpl->dst_mac == 0)) { - // no random_ip, can take from from packet template but no mac (yet) - uint32_t ip_dst_pos = pktpl->ip_dst_pos; - ip_dst = *(uint32_t *)(hdr + ip_dst_pos); - create_arp(mbufs[i], pkt_hdr[i], (uint64_t *)&pktpl->buf[6], ip_dst, pktpl->ip_src); - mbufs[i]->udata64 |= MBUF_ARP; - } else { - // no random ip, mac known - struct ether_hdr_arp *hdr_arp = (struct ether_hdr_arp *)pkt_hdr[i]; - memcpy(&hdr_arp->ether_hdr.d_addr.addr_bytes, &pktpl->dst_mac, 6); - } - } - } - } - return 0; -} - static void task_gen_apply_random_fields(struct task_gen *task, uint8_t *hdr) { uint32_t ret, ret_tmp; @@ -690,92 +558,79 @@ static void task_gen_update_config(struct task_gen *task) task_gen_reset_token_time(task); } -static inline void handle_arp_pkts(struct task_gen *task, struct rte_mbuf **mbufs, uint16_t n_pkts) +static inline void build_value(struct task_gen *task, uint32_t mask, int bit_pos, uint32_t val, uint32_t fixed_bits) { - int j; - int ret; - struct ether_hdr_arp *hdr; - uint8_t out[MAX_PKT_BURST]; - static struct my_arp_t arp_reply = { - .htype = 0x100, - .ptype = 8, - .hlen = 6, - .plen = 4, - .oper = 0x200 - }; - static struct my_arp_t arp_request = { - .htype = 0x100, - .ptype = 8, - .hlen = 6, - .plen = 4, - .oper = 0x100 - }; - - for (j = 0; j < n_pkts; ++j) { - PREFETCH0(mbufs[j]); - } - for (j = 0; j < n_pkts; ++j) { - PREFETCH0(rte_pktmbuf_mtod(mbufs[j], void *)); + struct task_base *tbase = (struct task_base *)task; + if (bit_pos < 32) { + build_value(task, mask >> 1, bit_pos + 1, val, fixed_bits); + if (mask & 1) { + build_value(task, mask >> 1, bit_pos + 1, val | (1 << bit_pos), fixed_bits); + } + } else { + register_ip_to_ctrl_plane(tbase->l3.tmaster, rte_cpu_to_be_32(val | fixed_bits), tbase->l3.reachable_port_id, tbase->l3.core_id, tbase->l3.task_id); } - for (j = 0; j < n_pkts; ++j) { - hdr = rte_pktmbuf_mtod(mbufs[j], struct ether_hdr_arp *); - if (hdr->ether_hdr.ether_type == ETYPE_ARP) { - if (memcmp(&hdr->arp, &arp_reply, 8) == 0) { - uint32_t ip = hdr->arp.data.spa; - // plog_info("Received ARP Reply for IP %x\n",ip); - if (ip == task->gw_ip) { - memcpy(&task->gw_mac, &hdr->arp.data.sha, 6);; - task->flags |= FLAG_DST_MAC_KNOWN; - out[j] = OUT_HANDLED; - continue; - } else if ((task->n_pkts >= 4) || (task->flags & FLAG_RANDOM_IPS)) { - // Ideally, we should add the key when making the arp request, - // We should only store the mac address key was created. - // Here we are storing MAC we did not asked for... - ret = rte_hash_add_key(task->mac_hash, (const void *)&ip); - if (ret < 0) { - plogx_info("Unable add ip %d.%d.%d.%d in mac_hash\n", IP4(ip)); - out[j] = OUT_DISCARD; - } else { - task->dst_mac[ret] = *(uint64_t *)&(hdr->arp.data.sha); - out[j] = OUT_HANDLED; - } - continue; - } - // Need to find template back... - // Only try this if there are few templates - for (unsigned int idx = 0; idx < task->n_pkts; idx++) { - struct pkt_template *pktpl = &task->pkt_template[idx]; - uint32_t ip_dst_pos = pktpl->ip_dst_pos; - uint32_t *ip_dst = (uint32_t *)(((uint8_t *)pktpl->buf) + ip_dst_pos); - if (*ip_dst == ip) { - pktpl->dst_mac = *(uint64_t *)&(hdr->arp.data.sha); - } - out[j] = OUT_HANDLED; - } - } else if (memcmp(&hdr->arp, &arp_request, 8) == 0) { - struct ether_addr s_addr; - if (!task->src_ip) { - create_mac(hdr, &s_addr); - prepare_arp_reply(hdr, &s_addr); - memcpy(hdr->ether_hdr.d_addr.addr_bytes, hdr->ether_hdr.s_addr.addr_bytes, 6); - memcpy(hdr->ether_hdr.s_addr.addr_bytes, &s_addr, 6); - out[j] = 0; - } else if (hdr->arp.data.tpa == task->src_ip) { - prepare_arp_reply(hdr, &task->src_mac); - memcpy(hdr->ether_hdr.d_addr.addr_bytes, hdr->ether_hdr.s_addr.addr_bytes, 6); - memcpy(hdr->ether_hdr.s_addr.addr_bytes, &task->src_mac, 6); - out[j] = 0; +} +static inline void register_all_ip_to_ctrl_plane(struct task_gen *task) +{ + struct task_base *tbase = (struct task_base *)task; + int i, len, fixed; + unsigned int offset; + uint32_t mask; + + for (uint32_t i = 0; i < task->n_pkts; ++i) { + struct pkt_template *pktpl = &task->pkt_template[i]; + unsigned int ip_src_pos = 0; + int maybe_ipv4 = 0; + unsigned int l2_len = sizeof(struct ether_hdr); + + uint8_t *pkt = pktpl->buf; + struct ether_hdr *eth_hdr = (struct ether_hdr*)pkt; + uint16_t ether_type = eth_hdr->ether_type; + struct vlan_hdr *vlan_hdr; + + // Unstack VLAN tags + while (((ether_type == ETYPE_8021ad) || (ether_type == ETYPE_VLAN)) && (l2_len + sizeof(struct vlan_hdr) < pktpl->len)) { + vlan_hdr = (struct vlan_hdr *)(pkt + l2_len); + l2_len +=4; + ether_type = vlan_hdr->eth_proto; + } + if ((ether_type == ETYPE_MPLSU) || (ether_type == ETYPE_MPLSM)) { + l2_len +=4; + maybe_ipv4 = 1; + } + if ((ether_type != ETYPE_IPv4) && !maybe_ipv4) + continue; + + struct ipv4_hdr *ip = (struct ipv4_hdr *)(pkt + l2_len); + PROX_PANIC(ip->version_ihl >> 4 != 4, "IPv4 ether_type but IP version = %d != 4", ip->version_ihl >> 4); + + // Even if IPv4 header contains options, options are after ip src and dst + ip_src_pos = l2_len + sizeof(struct ipv4_hdr) - 2 * sizeof(uint32_t); + uint32_t *ip_src = ((uint32_t *)(pktpl->buf + ip_src_pos)); + plog_info("\tip_src_pos = %d, ip_src = %x\n", ip_src_pos, *ip_src); + register_ip_to_ctrl_plane(tbase->l3.tmaster, *ip_src, tbase->l3.reachable_port_id, tbase->l3.core_id, tbase->l3.task_id); + + for (int j = 0; j < task->n_rands; j++) { + offset = task->rand[j].rand_offset; + len = task->rand[j].rand_len; + mask = task->rand[j].rand_mask; + fixed = task->rand[j].fixed_bits; + plog_info("offset = %d, len = %d, mask = %x, fixed = %x\n", offset, len, mask, fixed); + if ((offset < ip_src_pos + 4) && (offset + len >= ip_src_pos)) { + if (offset >= ip_src_pos) { + int32_t ip_src_mask = (1 << (4 + ip_src_pos - offset) * 8) - 1; + mask = mask & ip_src_mask; + fixed = (fixed & ip_src_mask) | (rte_be_to_cpu_32(*ip_src) & ~ip_src_mask); + build_value(task, mask, 0, 0, fixed); } else { - out[j] = OUT_DISCARD; - plogx_dbg("Received ARP on unexpected IP %x, expecting %x\n", rte_be_to_cpu_32(hdr->arp.data.tpa), rte_be_to_cpu_32(task->src_ip)); + int32_t bits = ((ip_src_pos + 4 - offset - len) * 8); + mask = mask << bits; + fixed = (fixed << bits) | (rte_be_to_cpu_32(*ip_src) & ((1 << bits) - 1)); + build_value(task, mask, 0, 0, fixed); } } - } else { - out[j] = OUT_DISCARD; } } - ret = task->base.tx_pkt(&task->base, mbufs, n_pkts, out); } static int handle_gen_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts) @@ -786,10 +641,6 @@ static int handle_gen_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uin int i, j; - if (unlikely((task->flags & FLAG_L3_GEN) && (n_pkts != 0))) { - handle_arp_pkts(task, mbufs, n_pkts); - } - task_gen_update_config(task); if (task->pkt_count == 0) { @@ -802,7 +653,7 @@ static int handle_gen_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uin token_time_update(&task->token_time, rte_rdtsc()); uint32_t would_send_bytes; - const uint32_t send_bulk = task_gen_calc_send_bulk(task, &would_send_bytes); + uint32_t send_bulk = task_gen_calc_send_bulk(task, &would_send_bytes); if (send_bulk == 0) return 0; @@ -817,8 +668,6 @@ static int handle_gen_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uin task_gen_load_and_prefetch(new_pkts, pkt_hdr, send_bulk); task_gen_build_packets(task, new_pkts, pkt_hdr, send_bulk); task_gen_apply_all_random_fields(task, pkt_hdr, send_bulk); - if (task_gen_write_dst_mac(task, new_pkts, pkt_hdr, send_bulk) < 0) - return 0; task_gen_apply_all_accur_pos(task, new_pkts, pkt_hdr, send_bulk); task_gen_apply_all_sig(task, new_pkts, pkt_hdr, send_bulk); task_gen_apply_all_unique_id(task, new_pkts, pkt_hdr, send_bulk); @@ -942,31 +791,45 @@ static int check_all_pkt_size(struct task_gen *task, int do_panic) return 0; } -static void check_fields_in_bounds(struct task_gen *task) +static int check_fields_in_bounds(struct task_gen *task, uint32_t pkt_size, int do_panic) { - const uint32_t pkt_size = task->pkt_template[0].len; - if (task->lat_enabled) { uint32_t pos_beg = task->lat_pos; uint32_t pos_end = task->lat_pos + 3U; - PROX_PANIC(pkt_size <= pos_end, "Writing latency at %u-%u, but packet size is %u bytes\n", + 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; - PROX_PANIC(pkt_size <= pos_end, "Writing packet at %u-%u, but packet size is %u bytes\n", + 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; - PROX_PANIC(pkt_size <= pos_end, "Writing accuracy at %u%-u, but packet size is %u bytes\n", + 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 void task_gen_pkt_template_recalc_metadata(struct task_gen *task) @@ -1071,7 +934,7 @@ static void task_init_gen_load_pkt_inline(struct task_gen *task, struct task_arg task->pkt_template_orig[0].len = targ->pkt_size; task_gen_reset_pkt_templates(task); check_all_pkt_size(task, 1); - check_fields_in_bounds(task); + check_fields_in_bounds(task, task->pkt_template[0].len, 1); } static void task_init_gen_load_pcap(struct task_gen *task, struct task_args *targ) @@ -1128,20 +991,14 @@ int task_gen_set_pkt_size(struct task_base *tbase, uint32_t pkt_size) struct task_gen *task = (struct task_gen *)tbase; int rc; - task->pkt_template[0].len = pkt_size; - if ((rc = check_all_pkt_size(task, 0)) != 0) + 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; - check_fields_in_bounds(task); + task->pkt_template[0].len = pkt_size; return rc; } -void task_gen_set_gateway_ip(struct task_base *tbase, uint32_t ip) -{ - struct task_gen *task = (struct task_gen *)tbase; - task->gw_ip = ip; - task->flags &= ~FLAG_DST_MAC_KNOWN; -} - void task_gen_set_rate(struct task_base *tbase, uint64_t bps) { struct task_gen *task = (struct task_gen *)tbase; @@ -1159,7 +1016,6 @@ void task_gen_reset_randoms(struct task_base *tbase) task->rand[i].rand_offset = 0; } task->n_rands = 0; - task->flags &= ~FLAG_RANDOM_IPS; } int task_gen_set_value(struct task_base *tbase, uint32_t value, uint32_t offset, uint32_t len) @@ -1276,22 +1132,50 @@ int task_gen_add_rand(struct task_base *tbase, const char *rand_str, uint32_t of task->rand[task->n_rands].rand_mask = mask; task->rand[task->n_rands].fixed_bits = fixed; - struct pkt_template *pktpl = &task->pkt_template[0]; - if (!((offset >= pktpl->ip_dst_pos + 4) || (offset + len < pktpl->ip_dst_pos))) { - plog_info("\tUsing randoms IP destinations\n"); - task->flags |= FLAG_RANDOM_IPS; - } - task->n_rands++; return 0; } +static void start(struct task_base *tbase) +{ + struct task_gen *task = (struct task_gen *)tbase; + task->pkt_queue_index = 0; + + task_gen_reset_token_time(task); + if (tbase->l3.tmaster) { + register_all_ip_to_ctrl_plane(task); + } + if (task->port && task->port->link_speed) { + // task->port->link->speed reports the link speed in Mbps e.g. 40k for a 40 Gbps NIC + // task->link_speed reported link speed in Bytes per sec. + task->link_speed = task->port->link_speed * 125000L; + plog_info("\tGenerating at %ld Mbps\n", 8 * task->link_speed / 1000000); + } + /* TODO + Handle the case when two tasks transmit to the same port + and one of them is stopped. In that case ARP (requests or replies) + might not be sent. Master will have to keep a list of rings. + stop will have to de-register IP from ctrl plane. + un-registration will remove the ring. when having more than + one active rings, master can always use the first one + */ +} + +static void start_pcap(struct task_base *tbase) +{ + struct task_gen_pcap *task = (struct task_gen_pcap *)tbase; + /* When we start, the first packet is sent immediately. */ + task->last_tsc = rte_rdtsc() - task->proto_tsc[0]; + task->pkt_idx = 0; +} + static void init_task_gen_early(struct task_args *targ) { uint8_t *generator_count = prox_sh_find_system("generator_count"); if (generator_count == NULL) { - generator_count = prox_zmalloc(sizeof(*generator_count), 0); + generator_count = prox_zmalloc(sizeof(*generator_count), rte_lcore_to_socket_id(targ->lconf->id)); + PROX_PANIC(generator_count == NULL, "Failed to allocate generator count\n"); prox_sh_add_system("generator_count", generator_count); } targ->generator_id = *generator_count; @@ -1314,9 +1198,16 @@ static void init_task_gen(struct task_base *tbase, struct task_args *targ) task->sig = targ->sig; task->new_rate_bps = targ->rate_bps; + /* + * For tokens, use 10 Gbps as base rate + * Scripts can then use speed command, with speed=100 as 10 Gbps and speed=400 as 40 Gbps + * Script can query prox "port info" command to find out the port link speed to know + * at which rate to start. Note that virtio running on OVS returns 10 Gbps, so a script has + * probably also to check the driver (as returned by the same "port info" command. + */ struct token_time_cfg tt_cfg = token_time_cfg_create(1250000000, rte_get_tsc_hz(), -1); - token_time_init(&task->token_time, &tt_cfg); + init_task_gen_seeds(task); task->min_bulk_size = targ->min_bulk_size; @@ -1334,9 +1225,8 @@ static void init_task_gen(struct task_base *tbase, struct task_args *targ) PROX_PANIC((task->lat_pos || task->accur_pos) && !task->lat_enabled, "lat not enabled by lat pos or accur pos configured\n"); task->generator_id = targ->generator_id; + plog_info("\tGenerator id = %d\n", task->generator_id); task->link_speed = UINT64_MAX; - if (targ->nb_txrings == 0 && targ->nb_txports == 1) - task->link_speed = 1250000000; if (!strcmp(targ->pcap_file, "")) { plog_info("\tUsing inline definition of a packet\n"); @@ -1353,70 +1243,6 @@ static void init_task_gen(struct task_base *tbase, struct task_args *targ) } } memcpy(&task->src_mac, &prox_port_cfg[task->base.tx_params_hw.tx_port_queue->port].eth_addr, sizeof(struct ether_addr)); - if (!strcmp(targ->task_init->sub_mode_str, "l3")) { - // In L3 GEN, we need to receive ARP replies - task->flags = FLAG_L3_GEN; - task->gw_ip = rte_cpu_to_be_32(targ->gateway_ipv4); - uint32_t n_entries; - - if (targ->number_gen_ip == 0) - n_entries = 1048576; - else - n_entries = targ->number_gen_ip; - - static char hash_name[30]; - sprintf(hash_name, "A%03d_mac_table", targ->lconf->id); - - struct rte_hash_parameters hash_params = { - .name = hash_name, - .entries = n_entries, - .key_len = sizeof(uint32_t), - .hash_func = rte_hash_crc, - .hash_func_init_val = 0, - }; - task->mac_hash = rte_hash_create(&hash_params); - PROX_PANIC(task->mac_hash == NULL, "Failed to set up mac hash table for %d IP\n", n_entries); - - const uint32_t socket = rte_lcore_to_socket_id(targ->lconf->id); - task->dst_mac = (uint64_t *)prox_zmalloc(n_entries * sizeof(uint64_t), socket); - PROX_PANIC(task->dst_mac == NULL, "Failed to allocate mac table for %d IP\n", n_entries); - - for (uint32_t i = 0; i < task->n_pkts; ++i) { - // For all destination IP, ARP request will need to be sent - // Store position of Destination IP in template - int ip_dst_pos = 0; - int maybe_ipv4 = 0; - int l2_len = sizeof(struct ether_hdr); - struct vlan_hdr *vlan_hdr; - uint8_t *pkt = task->pkt_template[i].buf; - struct ether_hdr *eth_hdr = (struct ether_hdr*)pkt; - struct ipv4_hdr *ip; - uint16_t ether_type = eth_hdr->ether_type; - - // Unstack VLAN tags - while (((ether_type == ETYPE_8021ad) || (ether_type == ETYPE_VLAN)) && (l2_len + sizeof(struct vlan_hdr) < task->pkt_template[i].len)) { - vlan_hdr = (struct vlan_hdr *)(pkt + l2_len); - l2_len +=4; - ether_type = vlan_hdr->eth_proto; - } - if ((ether_type == ETYPE_MPLSU) || (ether_type == ETYPE_MPLSM)) { - l2_len +=4; - maybe_ipv4 = 1; - } - if ((ether_type == ETYPE_IPv4) || maybe_ipv4) { - struct ipv4_hdr *ip = (struct ipv4_hdr *)(pkt + l2_len); - PROX_PANIC(ip->version_ihl >> 4 != 4, "IPv4 ether_type but IP version = %d != 4", ip->version_ihl >> 4); - // Even if IPv4 header contains options, options are after ip src and dst - ip_dst_pos = l2_len + sizeof(struct ipv4_hdr) - sizeof(uint32_t); - uint32_t *p = ((uint32_t *)(task->pkt_template[i].buf + ip_dst_pos - sizeof(uint32_t))); - task->pkt_template[i].ip_dst_pos = ip_dst_pos; - task->pkt_template[i].ip_src = *p; - uint32_t *p1 = ((uint32_t *)(task->pkt_template[i].buf + ip_dst_pos)); - plog_info("\tip_dst_pos = %d, ip_dst = %x\n", ip_dst_pos, *p1); - } - } - task->src_ip = rte_cpu_to_be_32(targ->local_ipv4); - } 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"); @@ -1425,6 +1251,7 @@ static void init_task_gen(struct task_base *tbase, struct task_args *targ) struct prox_port_cfg *port = find_reachable_port(targ); if (port) { task->cksum_offload = port->capabilities.tx_offload_cksum; + task->port = port; } } @@ -1433,6 +1260,7 @@ static struct task_init task_init_gen = { .init = init_task_gen, .handle = handle_gen_bulk, .start = start, + .early_init = init_task_gen_early, #ifdef SOFT_CRC // For SOFT_CRC, no offload is needed. If both NOOFFLOADS and NOMULTSEGS flags are set the // vector mode is used by DPDK, resulting (theoretically) in higher performance. @@ -1449,12 +1277,13 @@ static struct task_init task_init_gen_l3 = { .init = init_task_gen, .handle = handle_gen_bulk, .start = start, + .early_init = init_task_gen_early, #ifdef SOFT_CRC // For SOFT_CRC, no offload is needed. If both NOOFFLOADS and NOMULTSEGS flags are set the // vector mode is used by DPDK, resulting (theoretically) in higher performance. - .flag_features = TASK_FEATURE_ZERO_RX | TASK_FEATURE_TXQ_FLAGS_NOOFFLOADS | TASK_FEATURE_TXQ_FLAGS_NOMULTSEGS|TASK_FEATURE_ZERO_RX, + .flag_features = TASK_FEATURE_NEVER_DISCARDS | TASK_FEATURE_NO_RX | TASK_FEATURE_TXQ_FLAGS_NOOFFLOADS | TASK_FEATURE_TXQ_FLAGS_NOMULTSEGS, #else - .flag_features = TASK_FEATURE_ZERO_RX, + .flag_features = TASK_FEATURE_NEVER_DISCARDS | TASK_FEATURE_NO_RX, #endif .size = sizeof(struct task_gen) }; @@ -1465,6 +1294,7 @@ static struct task_init task_init_gen_pcap = { .init = init_task_gen_pcap, .handle = handle_gen_pcap_bulk, .start = start_pcap, + .early_init = init_task_gen_early, #ifdef SOFT_CRC .flag_features = TASK_FEATURE_NEVER_DISCARDS | TASK_FEATURE_NO_RX | TASK_FEATURE_TXQ_FLAGS_NOOFFLOADS | TASK_FEATURE_TXQ_FLAGS_NOMULTSEGS, #else