bf3688f1e8
Add insertion rate calculation feature into flow performance application. The application now provide the ability to test insertion rate of specific rte_flow rule, by stressing it to the NIC, and calculate the insertion rate. The application offers some options in the command line, to configure which rule to apply. After that the application will start producing rules with same pattern but increasing the outer IP source address by 1 each time, thus it will give different flow each time, and all other items will have open masks. The current design have single core insertion rate. Signed-off-by: Wisam Jaddo <wisamm@mellanox.com> Acked-by: Xiaoyu Min <jackmin@mellanox.com>
398 lines
9.6 KiB
C
398 lines
9.6 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
* Copyright 2020 Mellanox Technologies, Ltd
|
|
*
|
|
* This file contain the implementations of the items
|
|
* related methods. Each Item have a method to prepare
|
|
* the item and add it into items array in given index.
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <rte_flow.h>
|
|
|
|
#include "items_gen.h"
|
|
#include "config.h"
|
|
|
|
/* Storage for additional parameters for items */
|
|
struct additional_para {
|
|
rte_be32_t src_ip;
|
|
};
|
|
|
|
static void
|
|
add_ether(struct rte_flow_item *items,
|
|
uint8_t items_counter,
|
|
__rte_unused struct additional_para para)
|
|
{
|
|
static struct rte_flow_item_eth eth_spec;
|
|
static struct rte_flow_item_eth eth_mask;
|
|
|
|
memset(ð_spec, 0, sizeof(struct rte_flow_item_eth));
|
|
memset(ð_mask, 0, sizeof(struct rte_flow_item_eth));
|
|
|
|
items[items_counter].type = RTE_FLOW_ITEM_TYPE_ETH;
|
|
items[items_counter].spec = ð_spec;
|
|
items[items_counter].mask = ð_mask;
|
|
}
|
|
|
|
static void
|
|
add_vlan(struct rte_flow_item *items,
|
|
uint8_t items_counter,
|
|
__rte_unused struct additional_para para)
|
|
{
|
|
static struct rte_flow_item_vlan vlan_spec;
|
|
static struct rte_flow_item_vlan vlan_mask;
|
|
|
|
uint16_t vlan_value = VLAN_VALUE;
|
|
|
|
memset(&vlan_spec, 0, sizeof(struct rte_flow_item_vlan));
|
|
memset(&vlan_mask, 0, sizeof(struct rte_flow_item_vlan));
|
|
|
|
vlan_spec.tci = RTE_BE16(vlan_value);
|
|
vlan_mask.tci = RTE_BE16(0xffff);
|
|
|
|
items[items_counter].type = RTE_FLOW_ITEM_TYPE_VLAN;
|
|
items[items_counter].spec = &vlan_spec;
|
|
items[items_counter].mask = &vlan_mask;
|
|
}
|
|
|
|
static void
|
|
add_ipv4(struct rte_flow_item *items,
|
|
uint8_t items_counter, struct additional_para para)
|
|
{
|
|
static struct rte_flow_item_ipv4 ipv4_spec;
|
|
static struct rte_flow_item_ipv4 ipv4_mask;
|
|
|
|
memset(&ipv4_spec, 0, sizeof(struct rte_flow_item_ipv4));
|
|
memset(&ipv4_mask, 0, sizeof(struct rte_flow_item_ipv4));
|
|
|
|
ipv4_spec.hdr.src_addr = para.src_ip;
|
|
ipv4_mask.hdr.src_addr = RTE_BE32(0xffffffff);
|
|
|
|
items[items_counter].type = RTE_FLOW_ITEM_TYPE_IPV4;
|
|
items[items_counter].spec = &ipv4_spec;
|
|
items[items_counter].mask = &ipv4_mask;
|
|
}
|
|
|
|
|
|
static void
|
|
add_ipv6(struct rte_flow_item *items,
|
|
uint8_t items_counter, struct additional_para para)
|
|
{
|
|
static struct rte_flow_item_ipv6 ipv6_spec;
|
|
static struct rte_flow_item_ipv6 ipv6_mask;
|
|
|
|
memset(&ipv6_spec, 0, sizeof(struct rte_flow_item_ipv6));
|
|
memset(&ipv6_mask, 0, sizeof(struct rte_flow_item_ipv6));
|
|
|
|
/** Set ipv6 src **/
|
|
memset(&ipv6_spec.hdr.src_addr, para.src_ip,
|
|
sizeof(ipv6_spec.hdr.src_addr) / 2);
|
|
|
|
/** Full mask **/
|
|
memset(&ipv6_mask.hdr.src_addr, 0xff,
|
|
sizeof(ipv6_spec.hdr.src_addr));
|
|
|
|
items[items_counter].type = RTE_FLOW_ITEM_TYPE_IPV6;
|
|
items[items_counter].spec = &ipv6_spec;
|
|
items[items_counter].mask = &ipv6_mask;
|
|
}
|
|
|
|
static void
|
|
add_tcp(struct rte_flow_item *items,
|
|
uint8_t items_counter,
|
|
__rte_unused struct additional_para para)
|
|
{
|
|
static struct rte_flow_item_tcp tcp_spec;
|
|
static struct rte_flow_item_tcp tcp_mask;
|
|
|
|
memset(&tcp_spec, 0, sizeof(struct rte_flow_item_tcp));
|
|
memset(&tcp_mask, 0, sizeof(struct rte_flow_item_tcp));
|
|
|
|
items[items_counter].type = RTE_FLOW_ITEM_TYPE_TCP;
|
|
items[items_counter].spec = &tcp_spec;
|
|
items[items_counter].mask = &tcp_mask;
|
|
}
|
|
|
|
static void
|
|
add_udp(struct rte_flow_item *items,
|
|
uint8_t items_counter,
|
|
__rte_unused struct additional_para para)
|
|
{
|
|
static struct rte_flow_item_udp udp_spec;
|
|
static struct rte_flow_item_udp udp_mask;
|
|
|
|
memset(&udp_spec, 0, sizeof(struct rte_flow_item_udp));
|
|
memset(&udp_mask, 0, sizeof(struct rte_flow_item_udp));
|
|
|
|
items[items_counter].type = RTE_FLOW_ITEM_TYPE_UDP;
|
|
items[items_counter].spec = &udp_spec;
|
|
items[items_counter].mask = &udp_mask;
|
|
}
|
|
|
|
static void
|
|
add_vxlan(struct rte_flow_item *items,
|
|
uint8_t items_counter,
|
|
__rte_unused struct additional_para para)
|
|
{
|
|
static struct rte_flow_item_vxlan vxlan_spec;
|
|
static struct rte_flow_item_vxlan vxlan_mask;
|
|
|
|
uint32_t vni_value;
|
|
uint8_t i;
|
|
|
|
vni_value = VNI_VALUE;
|
|
|
|
memset(&vxlan_spec, 0, sizeof(struct rte_flow_item_vxlan));
|
|
memset(&vxlan_mask, 0, sizeof(struct rte_flow_item_vxlan));
|
|
|
|
/* Set standard vxlan vni */
|
|
for (i = 0; i < 3; i++) {
|
|
vxlan_spec.vni[2 - i] = vni_value >> (i * 8);
|
|
vxlan_mask.vni[2 - i] = 0xff;
|
|
}
|
|
|
|
/* Standard vxlan flags */
|
|
vxlan_spec.flags = 0x8;
|
|
|
|
items[items_counter].type = RTE_FLOW_ITEM_TYPE_VXLAN;
|
|
items[items_counter].spec = &vxlan_spec;
|
|
items[items_counter].mask = &vxlan_mask;
|
|
}
|
|
|
|
static void
|
|
add_vxlan_gpe(struct rte_flow_item *items,
|
|
uint8_t items_counter,
|
|
__rte_unused struct additional_para para)
|
|
{
|
|
static struct rte_flow_item_vxlan_gpe vxlan_gpe_spec;
|
|
static struct rte_flow_item_vxlan_gpe vxlan_gpe_mask;
|
|
|
|
uint32_t vni_value;
|
|
uint8_t i;
|
|
|
|
vni_value = VNI_VALUE;
|
|
|
|
memset(&vxlan_gpe_spec, 0, sizeof(struct rte_flow_item_vxlan_gpe));
|
|
memset(&vxlan_gpe_mask, 0, sizeof(struct rte_flow_item_vxlan_gpe));
|
|
|
|
/* Set vxlan-gpe vni */
|
|
for (i = 0; i < 3; i++) {
|
|
vxlan_gpe_spec.vni[2 - i] = vni_value >> (i * 8);
|
|
vxlan_gpe_mask.vni[2 - i] = 0xff;
|
|
}
|
|
|
|
/* vxlan-gpe flags */
|
|
vxlan_gpe_spec.flags = 0x0c;
|
|
|
|
items[items_counter].type = RTE_FLOW_ITEM_TYPE_VXLAN_GPE;
|
|
items[items_counter].spec = &vxlan_gpe_spec;
|
|
items[items_counter].mask = &vxlan_gpe_mask;
|
|
}
|
|
|
|
static void
|
|
add_gre(struct rte_flow_item *items,
|
|
uint8_t items_counter,
|
|
__rte_unused struct additional_para para)
|
|
{
|
|
static struct rte_flow_item_gre gre_spec;
|
|
static struct rte_flow_item_gre gre_mask;
|
|
|
|
uint16_t proto;
|
|
|
|
proto = RTE_ETHER_TYPE_TEB;
|
|
|
|
memset(&gre_spec, 0, sizeof(struct rte_flow_item_gre));
|
|
memset(&gre_mask, 0, sizeof(struct rte_flow_item_gre));
|
|
|
|
gre_spec.protocol = RTE_BE16(proto);
|
|
gre_mask.protocol = RTE_BE16(0xffff);
|
|
|
|
items[items_counter].type = RTE_FLOW_ITEM_TYPE_GRE;
|
|
items[items_counter].spec = &gre_spec;
|
|
items[items_counter].mask = &gre_mask;
|
|
}
|
|
|
|
static void
|
|
add_geneve(struct rte_flow_item *items,
|
|
uint8_t items_counter,
|
|
__rte_unused struct additional_para para)
|
|
{
|
|
static struct rte_flow_item_geneve geneve_spec;
|
|
static struct rte_flow_item_geneve geneve_mask;
|
|
|
|
uint32_t vni_value;
|
|
uint8_t i;
|
|
|
|
vni_value = VNI_VALUE;
|
|
|
|
memset(&geneve_spec, 0, sizeof(struct rte_flow_item_geneve));
|
|
memset(&geneve_mask, 0, sizeof(struct rte_flow_item_geneve));
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
geneve_spec.vni[2 - i] = vni_value >> (i * 8);
|
|
geneve_mask.vni[2 - i] = 0xff;
|
|
}
|
|
|
|
items[items_counter].type = RTE_FLOW_ITEM_TYPE_GENEVE;
|
|
items[items_counter].spec = &geneve_spec;
|
|
items[items_counter].mask = &geneve_mask;
|
|
}
|
|
|
|
static void
|
|
add_gtp(struct rte_flow_item *items,
|
|
uint8_t items_counter,
|
|
__rte_unused struct additional_para para)
|
|
{
|
|
static struct rte_flow_item_gtp gtp_spec;
|
|
static struct rte_flow_item_gtp gtp_mask;
|
|
|
|
uint32_t teid_value;
|
|
|
|
teid_value = TEID_VALUE;
|
|
|
|
memset(>p_spec, 0, sizeof(struct rte_flow_item_gtp));
|
|
memset(>p_mask, 0, sizeof(struct rte_flow_item_gtp));
|
|
|
|
gtp_spec.teid = RTE_BE32(teid_value);
|
|
gtp_mask.teid = RTE_BE32(0xffffffff);
|
|
|
|
items[items_counter].type = RTE_FLOW_ITEM_TYPE_GTP;
|
|
items[items_counter].spec = >p_spec;
|
|
items[items_counter].mask = >p_mask;
|
|
}
|
|
|
|
static void
|
|
add_meta_data(struct rte_flow_item *items,
|
|
uint8_t items_counter,
|
|
__rte_unused struct additional_para para)
|
|
{
|
|
static struct rte_flow_item_meta meta_spec;
|
|
static struct rte_flow_item_meta meta_mask;
|
|
|
|
uint32_t data;
|
|
|
|
data = META_DATA;
|
|
|
|
memset(&meta_spec, 0, sizeof(struct rte_flow_item_meta));
|
|
memset(&meta_mask, 0, sizeof(struct rte_flow_item_meta));
|
|
|
|
meta_spec.data = RTE_BE32(data);
|
|
meta_mask.data = RTE_BE32(0xffffffff);
|
|
|
|
items[items_counter].type = RTE_FLOW_ITEM_TYPE_META;
|
|
items[items_counter].spec = &meta_spec;
|
|
items[items_counter].mask = &meta_mask;
|
|
}
|
|
|
|
|
|
static void
|
|
add_meta_tag(struct rte_flow_item *items,
|
|
uint8_t items_counter,
|
|
__rte_unused struct additional_para para)
|
|
{
|
|
static struct rte_flow_item_tag tag_spec;
|
|
static struct rte_flow_item_tag tag_mask;
|
|
uint32_t data;
|
|
uint8_t index;
|
|
|
|
data = META_DATA;
|
|
index = TAG_INDEX;
|
|
|
|
memset(&tag_spec, 0, sizeof(struct rte_flow_item_tag));
|
|
memset(&tag_mask, 0, sizeof(struct rte_flow_item_tag));
|
|
|
|
tag_spec.data = RTE_BE32(data);
|
|
tag_mask.data = RTE_BE32(0xffffffff);
|
|
tag_spec.index = index;
|
|
tag_mask.index = 0xff;
|
|
|
|
items[items_counter].type = RTE_FLOW_ITEM_TYPE_TAG;
|
|
items[items_counter].spec = &tag_spec;
|
|
items[items_counter].mask = &tag_mask;
|
|
}
|
|
|
|
void
|
|
fill_items(struct rte_flow_item *items,
|
|
uint64_t flow_items, uint32_t outer_ip_src)
|
|
{
|
|
uint8_t items_counter = 0;
|
|
uint8_t i;
|
|
struct additional_para additional_para_data = {
|
|
.src_ip = outer_ip_src,
|
|
};
|
|
|
|
/* Support outer items up to tunnel layer only. */
|
|
static const struct items_dict {
|
|
uint64_t mask;
|
|
void (*funct)(
|
|
struct rte_flow_item *items,
|
|
uint8_t items_counter,
|
|
struct additional_para para
|
|
);
|
|
} flows_items[] = {
|
|
{
|
|
.mask = RTE_FLOW_ITEM_TYPE_META,
|
|
.funct = add_meta_data,
|
|
},
|
|
{
|
|
.mask = RTE_FLOW_ITEM_TYPE_TAG,
|
|
.funct = add_meta_tag,
|
|
},
|
|
{
|
|
.mask = RTE_FLOW_ITEM_TYPE_ETH,
|
|
.funct = add_ether,
|
|
},
|
|
{
|
|
.mask = RTE_FLOW_ITEM_TYPE_VLAN,
|
|
.funct = add_vlan,
|
|
},
|
|
{
|
|
.mask = RTE_FLOW_ITEM_TYPE_IPV4,
|
|
.funct = add_ipv4,
|
|
},
|
|
{
|
|
.mask = RTE_FLOW_ITEM_TYPE_IPV6,
|
|
.funct = add_ipv6,
|
|
},
|
|
{
|
|
.mask = RTE_FLOW_ITEM_TYPE_TCP,
|
|
.funct = add_tcp,
|
|
},
|
|
{
|
|
.mask = RTE_FLOW_ITEM_TYPE_UDP,
|
|
.funct = add_udp,
|
|
},
|
|
{
|
|
.mask = RTE_FLOW_ITEM_TYPE_VXLAN,
|
|
.funct = add_vxlan,
|
|
},
|
|
{
|
|
.mask = RTE_FLOW_ITEM_TYPE_VXLAN_GPE,
|
|
.funct = add_vxlan_gpe,
|
|
},
|
|
{
|
|
.mask = RTE_FLOW_ITEM_TYPE_GRE,
|
|
.funct = add_gre,
|
|
},
|
|
{
|
|
.mask = RTE_FLOW_ITEM_TYPE_GENEVE,
|
|
.funct = add_geneve,
|
|
},
|
|
{
|
|
.mask = RTE_FLOW_ITEM_TYPE_GTP,
|
|
.funct = add_gtp,
|
|
},
|
|
|
|
};
|
|
|
|
for (i = 0; i < RTE_DIM(flows_items); i++) {
|
|
if ((flow_items & FLOW_ITEM_MASK(flows_items[i].mask)) == 0)
|
|
continue;
|
|
flows_items[i].funct(
|
|
items, items_counter++,
|
|
additional_para_data
|
|
);
|
|
}
|
|
|
|
items[items_counter].type = RTE_FLOW_ITEM_TYPE_END;
|
|
}
|