numam-dpdk/app/test-flow-perf/actions_gen.c
Wisam Jaddo ef9ae0cf57 app/flow-perf: support header modify actions
Introduce headers modify actions in the app.
All header modify actions will add different value
for each flow, to make sure each flow will create
and use it's own actions.

Signed-off-by: Wisam Jaddo <wisamm@mellanox.com>
Acked-by: Alexander Kozyrev <akozyrev@nvidia.com>
2020-09-18 18:55:10 +02:00

627 lines
14 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright 2020 Mellanox Technologies, Ltd
*
* The file contains the implementations of actions generators.
* Each generator is responsible for preparing it's action instance
* and initializing it with needed data.
*/
#include <sys/types.h>
#include <rte_malloc.h>
#include <rte_flow.h>
#include <rte_ethdev.h>
#include "actions_gen.h"
#include "flow_gen.h"
#include "config.h"
/* Storage for additional parameters for actions */
struct additional_para {
uint16_t queue;
uint16_t next_table;
uint16_t *queues;
uint16_t queues_number;
uint32_t counter;
};
/* Storage for struct rte_flow_action_rss including external data. */
struct action_rss_data {
struct rte_flow_action_rss conf;
uint8_t key[40];
uint16_t queue[128];
};
static void
add_mark(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static struct rte_flow_action_mark mark_action;
do {
mark_action.id = MARK_ID;
} while (0);
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_MARK;
actions[actions_counter].conf = &mark_action;
}
static void
add_queue(struct rte_flow_action *actions,
uint8_t actions_counter,
struct additional_para para)
{
static struct rte_flow_action_queue queue_action;
do {
queue_action.index = para.queue;
} while (0);
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_QUEUE;
actions[actions_counter].conf = &queue_action;
}
static void
add_jump(struct rte_flow_action *actions,
uint8_t actions_counter,
struct additional_para para)
{
static struct rte_flow_action_jump jump_action;
do {
jump_action.group = para.next_table;
} while (0);
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_JUMP;
actions[actions_counter].conf = &jump_action;
}
static void
add_rss(struct rte_flow_action *actions,
uint8_t actions_counter,
struct additional_para para)
{
static struct rte_flow_action_rss *rss_action;
static struct action_rss_data *rss_data;
uint16_t queue;
rss_data = rte_malloc("rss_data",
sizeof(struct action_rss_data), 0);
if (rss_data == NULL)
rte_exit(EXIT_FAILURE, "No Memory available!");
*rss_data = (struct action_rss_data){
.conf = (struct rte_flow_action_rss){
.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
.level = 0,
.types = GET_RSS_HF(),
.key_len = sizeof(rss_data->key),
.queue_num = para.queues_number,
.key = rss_data->key,
.queue = rss_data->queue,
},
.key = { 1 },
.queue = { 0 },
};
for (queue = 0; queue < para.queues_number; queue++)
rss_data->queue[queue] = para.queues[queue];
rss_action = &rss_data->conf;
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_RSS;
actions[actions_counter].conf = rss_action;
}
static void
add_set_meta(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static struct rte_flow_action_set_meta meta_action;
do {
meta_action.data = RTE_BE32(META_DATA);
meta_action.mask = RTE_BE32(0xffffffff);
} while (0);
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_META;
actions[actions_counter].conf = &meta_action;
}
static void
add_set_tag(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static struct rte_flow_action_set_tag tag_action;
do {
tag_action.data = RTE_BE32(META_DATA);
tag_action.mask = RTE_BE32(0xffffffff);
tag_action.index = TAG_INDEX;
} while (0);
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_TAG;
actions[actions_counter].conf = &tag_action;
}
static void
add_port_id(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static struct rte_flow_action_port_id port_id;
do {
port_id.id = PORT_ID_DST;
} while (0);
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_PORT_ID;
actions[actions_counter].conf = &port_id;
}
static void
add_drop(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_DROP;
}
static void
add_count(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static struct rte_flow_action_count count_action;
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_COUNT;
actions[actions_counter].conf = &count_action;
}
static void
add_set_src_mac(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static struct rte_flow_action_set_mac set_mac;
uint32_t mac = para.counter;
uint16_t i;
/* Mac address to be set is random each time */
for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) {
set_mac.mac_addr[i] = mac & 0xff;
mac = mac >> 8;
}
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_MAC_SRC;
actions[actions_counter].conf = &set_mac;
}
static void
add_set_dst_mac(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static struct rte_flow_action_set_mac set_mac;
uint32_t mac = para.counter;
uint16_t i;
/* Mac address to be set is random each time */
for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) {
set_mac.mac_addr[i] = mac & 0xff;
mac = mac >> 8;
}
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_MAC_DST;
actions[actions_counter].conf = &set_mac;
}
static void
add_set_src_ipv4(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static struct rte_flow_action_set_ipv4 set_ipv4;
/* IPv4 value to be set is random each time */
set_ipv4.ipv4_addr = RTE_BE32(para.counter + 1);
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC;
actions[actions_counter].conf = &set_ipv4;
}
static void
add_set_dst_ipv4(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static struct rte_flow_action_set_ipv4 set_ipv4;
/* IPv4 value to be set is random each time */
set_ipv4.ipv4_addr = RTE_BE32(para.counter + 1);
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_IPV4_DST;
actions[actions_counter].conf = &set_ipv4;
}
static void
add_set_src_ipv6(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static struct rte_flow_action_set_ipv6 set_ipv6;
uint32_t ipv6 = para.counter;
uint8_t i;
/* IPv6 value to set is random each time */
for (i = 0; i < 16; i++) {
set_ipv6.ipv6_addr[i] = ipv6 & 0xff;
ipv6 = ipv6 >> 8;
}
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC;
actions[actions_counter].conf = &set_ipv6;
}
static void
add_set_dst_ipv6(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static struct rte_flow_action_set_ipv6 set_ipv6;
uint32_t ipv6 = para.counter;
uint8_t i;
/* IPv6 value to set is random each time */
for (i = 0; i < 16; i++) {
set_ipv6.ipv6_addr[i] = ipv6 & 0xff;
ipv6 = ipv6 >> 8;
}
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_IPV6_DST;
actions[actions_counter].conf = &set_ipv6;
}
static void
add_set_src_tp(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static struct rte_flow_action_set_tp set_tp;
uint32_t tp = para.counter;
/* TP src port is random each time */
if (tp > 0xffff)
tp = tp >> 16;
set_tp.port = RTE_BE16(tp & 0xffff);
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_TP_SRC;
actions[actions_counter].conf = &set_tp;
}
static void
add_set_dst_tp(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static struct rte_flow_action_set_tp set_tp;
uint32_t tp = para.counter;
/* TP src port is random each time */
if (tp > 0xffff)
tp = tp >> 16;
set_tp.port = RTE_BE16(tp & 0xffff);
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_TP_DST;
actions[actions_counter].conf = &set_tp;
}
static void
add_inc_tcp_ack(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static rte_be32_t value = RTE_BE32(1);
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_INC_TCP_ACK;
actions[actions_counter].conf = &value;
}
static void
add_dec_tcp_ack(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static rte_be32_t value = RTE_BE32(1);
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK;
actions[actions_counter].conf = &value;
}
static void
add_inc_tcp_seq(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static rte_be32_t value = RTE_BE32(1);
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ;
actions[actions_counter].conf = &value;
}
static void
add_dec_tcp_seq(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static rte_be32_t value = RTE_BE32(1);
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ;
actions[actions_counter].conf = &value;
}
static void
add_set_ttl(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static struct rte_flow_action_set_ttl set_ttl;
uint32_t ttl_value = para.counter;
/* Set ttl to random value each time */
while (ttl_value > 0xff)
ttl_value = ttl_value >> 8;
set_ttl.ttl_value = ttl_value;
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_TTL;
actions[actions_counter].conf = &set_ttl;
}
static void
add_dec_ttl(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_DEC_TTL;
}
static void
add_set_ipv4_dscp(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static struct rte_flow_action_set_dscp set_dscp;
uint32_t dscp_value = para.counter;
/* Set dscp to random value each time */
while (dscp_value > 0xff)
dscp_value = dscp_value >> 8;
set_dscp.dscp = dscp_value;
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP;
actions[actions_counter].conf = &set_dscp;
}
static void
add_set_ipv6_dscp(struct rte_flow_action *actions,
uint8_t actions_counter,
__rte_unused struct additional_para para)
{
static struct rte_flow_action_set_dscp set_dscp;
uint32_t dscp_value = para.counter;
/* Set dscp to random value each time */
while (dscp_value > 0xff)
dscp_value = dscp_value >> 8;
set_dscp.dscp = dscp_value;
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP;
actions[actions_counter].conf = &set_dscp;
}
void
fill_actions(struct rte_flow_action *actions, uint64_t *flow_actions,
uint32_t counter, uint16_t next_table, uint16_t hairpinq)
{
struct additional_para additional_para_data;
uint8_t actions_counter = 0;
uint16_t hairpin_queues[hairpinq];
uint16_t queues[RXQ_NUM];
uint16_t i, j;
for (i = 0; i < RXQ_NUM; i++)
queues[i] = i;
for (i = 0; i < hairpinq; i++)
hairpin_queues[i] = i + RXQ_NUM;
additional_para_data = (struct additional_para){
.queue = counter % RXQ_NUM,
.next_table = next_table,
.queues = queues,
.queues_number = RXQ_NUM,
.counter = counter,
};
if (hairpinq != 0) {
additional_para_data.queues = hairpin_queues;
additional_para_data.queues_number = hairpinq;
additional_para_data.queue = (counter % hairpinq) + RXQ_NUM;
}
static const struct actions_dict {
uint64_t mask;
void (*funct)(
struct rte_flow_action *actions,
uint8_t actions_counter,
struct additional_para para
);
} actions_list[] = {
{
.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_MARK),
.funct = add_mark,
},
{
.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_COUNT),
.funct = add_count,
},
{
.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_SET_META),
.funct = add_set_meta,
},
{
.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_SET_TAG),
.funct = add_set_tag,
},
{
.mask = FLOW_ACTION_MASK(
RTE_FLOW_ACTION_TYPE_SET_MAC_SRC
),
.funct = add_set_src_mac,
},
{
.mask = FLOW_ACTION_MASK(
RTE_FLOW_ACTION_TYPE_SET_MAC_DST
),
.funct = add_set_dst_mac,
},
{
.mask = FLOW_ACTION_MASK(
RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC
),
.funct = add_set_src_ipv4,
},
{
.mask = FLOW_ACTION_MASK(
RTE_FLOW_ACTION_TYPE_SET_IPV4_DST
),
.funct = add_set_dst_ipv4,
},
{
.mask = FLOW_ACTION_MASK(
RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC
),
.funct = add_set_src_ipv6,
},
{
.mask = FLOW_ACTION_MASK(
RTE_FLOW_ACTION_TYPE_SET_IPV6_DST
),
.funct = add_set_dst_ipv6,
},
{
.mask = FLOW_ACTION_MASK(
RTE_FLOW_ACTION_TYPE_SET_TP_SRC
),
.funct = add_set_src_tp,
},
{
.mask = FLOW_ACTION_MASK(
RTE_FLOW_ACTION_TYPE_SET_TP_DST
),
.funct = add_set_dst_tp,
},
{
.mask = FLOW_ACTION_MASK(
RTE_FLOW_ACTION_TYPE_INC_TCP_ACK
),
.funct = add_inc_tcp_ack,
},
{
.mask = FLOW_ACTION_MASK(
RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK
),
.funct = add_dec_tcp_ack,
},
{
.mask = FLOW_ACTION_MASK(
RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ
),
.funct = add_inc_tcp_seq,
},
{
.mask = FLOW_ACTION_MASK(
RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ
),
.funct = add_dec_tcp_seq,
},
{
.mask = FLOW_ACTION_MASK(
RTE_FLOW_ACTION_TYPE_SET_TTL
),
.funct = add_set_ttl,
},
{
.mask = FLOW_ACTION_MASK(
RTE_FLOW_ACTION_TYPE_DEC_TTL
),
.funct = add_dec_ttl,
},
{
.mask = FLOW_ACTION_MASK(
RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP
),
.funct = add_set_ipv4_dscp,
},
{
.mask = FLOW_ACTION_MASK(
RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP
),
.funct = add_set_ipv6_dscp,
},
{
.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_QUEUE),
.funct = add_queue,
},
{
.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_RSS),
.funct = add_rss,
},
{
.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_JUMP),
.funct = add_jump,
},
{
.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_PORT_ID),
.funct = add_port_id
},
{
.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_DROP),
.funct = add_drop,
},
{
.mask = HAIRPIN_QUEUE_ACTION,
.funct = add_queue,
},
{
.mask = HAIRPIN_RSS_ACTION,
.funct = add_rss,
},
};
for (j = 0; j < MAX_ACTIONS_NUM; j++) {
if (flow_actions[j] == 0)
break;
for (i = 0; i < RTE_DIM(actions_list); i++) {
if ((flow_actions[j] &
actions_list[i].mask) == 0)
continue;
actions_list[i].funct(
actions, actions_counter++,
additional_para_data
);
break;
}
}
actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_END;
}