#include <rte_mtr.h>
#include "config.h"
+#include "actions_gen.h"
#include "flow_gen.h"
#define MAX_BATCHES_COUNT 100
static uint64_t encap_data;
static uint64_t decap_data;
+static uint64_t all_actions[RTE_COLORS][MAX_ACTIONS_NUM];
+static char *actions_str[RTE_COLORS];
static uint64_t flow_items[MAX_ITEMS_NUM];
static uint64_t flow_actions[MAX_ACTIONS_NUM];
static uint64_t flow_attrs[MAX_ATTRS_NUM];
+static uint32_t policy_id[MAX_PORTS];
static uint8_t items_idx, actions_idx, attrs_idx;
static uint64_t ports_mask;
+static uint16_t dst_ports[RTE_MAX_ETHPORTS];
static volatile bool force_quit;
static bool dump_iterations;
static bool delete_flag;
static bool dump_socket_mem_flag;
static bool enable_fwd;
static bool unique_data;
+static bool policy_mtr;
+static bool packet_mode;
+
+static uint8_t rx_queues_count;
+static uint8_t tx_queues_count;
+static uint8_t rxd_count;
+static uint8_t txd_count;
+static uint32_t mbuf_size;
+static uint32_t mbuf_cache_size;
+static uint32_t total_mbuf_num;
static struct rte_mempool *mbuf_mp;
static uint32_t nb_lcores;
static uint32_t rules_batch;
static uint32_t hairpin_queues_num; /* total hairpin q number - default: 0 */
static uint32_t nb_lcores;
+static uint8_t max_priority;
+static uint32_t rand_seed;
+static uint64_t meter_profile_values[3]; /* CIR CBS EBS values. */
#define MAX_PKT_BURST 32
#define LCORE_MODE_PKT 1
.cores_count = 1,
};
+static const struct option_dict {
+ const char *str;
+ const uint64_t mask;
+ uint64_t *map;
+ uint8_t *map_idx;
+
+} flow_options[] = {
+ {
+ .str = "ether",
+ .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_ETH),
+ .map = &flow_items[0],
+ .map_idx = &items_idx
+ },
+ {
+ .str = "ipv4",
+ .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_IPV4),
+ .map = &flow_items[0],
+ .map_idx = &items_idx
+ },
+ {
+ .str = "ipv6",
+ .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_IPV6),
+ .map = &flow_items[0],
+ .map_idx = &items_idx
+ },
+ {
+ .str = "vlan",
+ .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_VLAN),
+ .map = &flow_items[0],
+ .map_idx = &items_idx
+ },
+ {
+ .str = "tcp",
+ .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_TCP),
+ .map = &flow_items[0],
+ .map_idx = &items_idx
+ },
+ {
+ .str = "udp",
+ .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_UDP),
+ .map = &flow_items[0],
+ .map_idx = &items_idx
+ },
+ {
+ .str = "vxlan",
+ .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_VXLAN),
+ .map = &flow_items[0],
+ .map_idx = &items_idx
+ },
+ {
+ .str = "vxlan-gpe",
+ .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_VXLAN_GPE),
+ .map = &flow_items[0],
+ .map_idx = &items_idx
+ },
+ {
+ .str = "gre",
+ .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_GRE),
+ .map = &flow_items[0],
+ .map_idx = &items_idx
+ },
+ {
+ .str = "geneve",
+ .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_GENEVE),
+ .map = &flow_items[0],
+ .map_idx = &items_idx
+ },
+ {
+ .str = "gtp",
+ .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_GTP),
+ .map = &flow_items[0],
+ .map_idx = &items_idx
+ },
+ {
+ .str = "meta",
+ .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_META),
+ .map = &flow_items[0],
+ .map_idx = &items_idx
+ },
+ {
+ .str = "tag",
+ .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_TAG),
+ .map = &flow_items[0],
+ .map_idx = &items_idx
+ },
+ {
+ .str = "icmpv4",
+ .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_ICMP),
+ .map = &flow_items[0],
+ .map_idx = &items_idx
+ },
+ {
+ .str = "icmpv6",
+ .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_ICMP6),
+ .map = &flow_items[0],
+ .map_idx = &items_idx
+ },
+ {
+ .str = "ingress",
+ .mask = INGRESS,
+ .map = &flow_attrs[0],
+ .map_idx = &attrs_idx
+ },
+ {
+ .str = "egress",
+ .mask = EGRESS,
+ .map = &flow_attrs[0],
+ .map_idx = &attrs_idx
+ },
+ {
+ .str = "transfer",
+ .mask = TRANSFER,
+ .map = &flow_attrs[0],
+ .map_idx = &attrs_idx
+ },
+ {
+ .str = "port-id",
+ .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_PORT_ID),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "rss",
+ .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_RSS),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "queue",
+ .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_QUEUE),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "jump",
+ .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_JUMP),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "mark",
+ .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_MARK),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "count",
+ .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_COUNT),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "set-meta",
+ .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_SET_META),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "set-tag",
+ .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_SET_TAG),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "drop",
+ .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_DROP),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "set-src-mac",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_SET_MAC_SRC
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "set-dst-mac",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_SET_MAC_DST
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "set-src-ipv4",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "set-dst-ipv4",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_SET_IPV4_DST
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "set-src-ipv6",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "set-dst-ipv6",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_SET_IPV6_DST
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "set-src-tp",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_SET_TP_SRC
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "set-dst-tp",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_SET_TP_DST
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "inc-tcp-ack",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_INC_TCP_ACK
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "dec-tcp-ack",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "inc-tcp-seq",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "dec-tcp-seq",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "set-ttl",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_SET_TTL
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "dec-ttl",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_DEC_TTL
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "set-ipv4-dscp",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "set-ipv6-dscp",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "flag",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_FLAG
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "meter",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_METER
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "vxlan-encap",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+ {
+ .str = "vxlan-decap",
+ .mask = FLOW_ACTION_MASK(
+ RTE_FLOW_ACTION_TYPE_VXLAN_DECAP
+ ),
+ .map = &flow_actions[0],
+ .map_idx = &actions_idx
+ },
+};
+
static void
usage(char *progname)
{
printf(" --enable-fwd: To enable packets forwarding"
" after insertion\n");
printf(" --portmask=N: hexadecimal bitmask of ports used\n");
+ printf(" --random-priority=N,S: use random priority levels "
+ "from 0 to (N - 1) for flows "
+ "and S as seed for pseudo-random number generator\n");
printf(" --unique-data: flag to set using unique data for all"
" actions that support data, such as header modify and encap actions\n");
+ printf(" --meter-profile=cir,cbs,ebs: set CIR CBS EBS parameters in meter"
+ " profile, default values are %d,%d,%d\n", METER_CIR,
+ METER_CIR / 8, 0);
+ printf(" --packet-mode: to enable packet mode for meter profile\n");
printf("To set flow attributes:\n");
printf(" --ingress: set ingress attribute in flows\n");
" default is %d\n", DEFAULT_GROUP);
printf(" --cores=N: to set the number of needed "
"cores to insert rte_flow rules, default is 1\n");
+ printf(" --rxq=N: to set the count of receive queues\n");
+ printf(" --txq=N: to set the count of send queues\n");
+ printf(" --rxd=N: to set the count of rxd\n");
+ printf(" --txd=N: to set the count of txd\n");
+ printf(" --mbuf-size=N: to set the size of mbuf\n");
+ printf(" --mbuf-cache-size=N: to set the size of mbuf cache\n");
+ printf(" --total-mbuf-count=N: to set the count of total mbuf count\n");
+
printf("To set flow items:\n");
printf(" --ether: add ether layer in flow items\n");
"ipv6 dscp value to be set is random each flow\n");
printf(" --flag: add flag action to flow actions\n");
printf(" --meter: add meter action to flow actions\n");
+ printf(" --policy-mtr=\"g1,g2:y1:r1\": to create meter with specified "
+ "colored actions\n");
printf(" --raw-encap=<data>: add raw encap action to flow actions\n"
"Data is the data needed to be encaped\n"
"Example: raw-encap=ether,ipv4,udp,vxlan\n");
printf(" --vxlan-decap: add vxlan_decap action to flow actions\n");
}
+static void
+read_meter_policy(char *prog, char *arg)
+{
+ char *token;
+ size_t i, j, k;
+
+ j = 0;
+ k = 0;
+ policy_mtr = true;
+ token = strsep(&arg, ":\0");
+ while (token != NULL && j < RTE_COLORS) {
+ actions_str[j++] = token;
+ token = strsep(&arg, ":\0");
+ }
+ j = 0;
+ token = strtok(actions_str[0], ",\0");
+ while (token == NULL && j < RTE_COLORS - 1)
+ token = strtok(actions_str[++j], ",\0");
+ while (j < RTE_COLORS && token != NULL) {
+ for (i = 0; i < RTE_DIM(flow_options); i++) {
+ if (!strcmp(token, flow_options[i].str)) {
+ all_actions[j][k++] = flow_options[i].mask;
+ break;
+ }
+ }
+ /* Reached last action with no match */
+ if (i >= RTE_DIM(flow_options)) {
+ fprintf(stderr, "Invalid colored actions: %s\n", token);
+ usage(prog);
+ rte_exit(EXIT_SUCCESS, "Invalid colored actions\n");
+ }
+ token = strtok(NULL, ",\0");
+ while (!token && j < RTE_COLORS - 1) {
+ token = strtok(actions_str[++j], ",\0");
+ k = 0;
+ }
+ }
+}
+
static void
args_parse(int argc, char **argv)
{
- uint64_t pm;
+ uint64_t pm, seed;
char **argvopt;
+ uint32_t prio;
char *token;
char *end;
int n, opt;
int opt_idx;
size_t i;
- static const struct option_dict {
- const char *str;
- const uint64_t mask;
- uint64_t *map;
- uint8_t *map_idx;
-
- } flow_options[] = {
- {
- .str = "ether",
- .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_ETH),
- .map = &flow_items[0],
- .map_idx = &items_idx
- },
- {
- .str = "ipv4",
- .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_IPV4),
- .map = &flow_items[0],
- .map_idx = &items_idx
- },
- {
- .str = "ipv6",
- .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_IPV6),
- .map = &flow_items[0],
- .map_idx = &items_idx
- },
- {
- .str = "vlan",
- .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_VLAN),
- .map = &flow_items[0],
- .map_idx = &items_idx
- },
- {
- .str = "tcp",
- .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_TCP),
- .map = &flow_items[0],
- .map_idx = &items_idx
- },
- {
- .str = "udp",
- .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_UDP),
- .map = &flow_items[0],
- .map_idx = &items_idx
- },
- {
- .str = "vxlan",
- .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_VXLAN),
- .map = &flow_items[0],
- .map_idx = &items_idx
- },
- {
- .str = "vxlan-gpe",
- .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_VXLAN_GPE),
- .map = &flow_items[0],
- .map_idx = &items_idx
- },
- {
- .str = "gre",
- .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_GRE),
- .map = &flow_items[0],
- .map_idx = &items_idx
- },
- {
- .str = "geneve",
- .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_GENEVE),
- .map = &flow_items[0],
- .map_idx = &items_idx
- },
- {
- .str = "gtp",
- .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_GTP),
- .map = &flow_items[0],
- .map_idx = &items_idx
- },
- {
- .str = "meta",
- .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_META),
- .map = &flow_items[0],
- .map_idx = &items_idx
- },
- {
- .str = "tag",
- .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_TAG),
- .map = &flow_items[0],
- .map_idx = &items_idx
- },
- {
- .str = "icmpv4",
- .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_ICMP),
- .map = &flow_items[0],
- .map_idx = &items_idx
- },
- {
- .str = "icmpv6",
- .mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_ICMP6),
- .map = &flow_items[0],
- .map_idx = &items_idx
- },
- {
- .str = "ingress",
- .mask = INGRESS,
- .map = &flow_attrs[0],
- .map_idx = &attrs_idx
- },
- {
- .str = "egress",
- .mask = EGRESS,
- .map = &flow_attrs[0],
- .map_idx = &attrs_idx
- },
- {
- .str = "transfer",
- .mask = TRANSFER,
- .map = &flow_attrs[0],
- .map_idx = &attrs_idx
- },
- {
- .str = "port-id",
- .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_PORT_ID),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "rss",
- .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_RSS),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "queue",
- .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_QUEUE),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "jump",
- .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_JUMP),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "mark",
- .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_MARK),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "count",
- .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_COUNT),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "set-meta",
- .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_SET_META),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "set-tag",
- .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_SET_TAG),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "drop",
- .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_DROP),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "set-src-mac",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_SET_MAC_SRC
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "set-dst-mac",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_SET_MAC_DST
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "set-src-ipv4",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "set-dst-ipv4",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_SET_IPV4_DST
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "set-src-ipv6",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "set-dst-ipv6",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_SET_IPV6_DST
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "set-src-tp",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_SET_TP_SRC
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "set-dst-tp",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_SET_TP_DST
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "inc-tcp-ack",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_INC_TCP_ACK
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "dec-tcp-ack",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "inc-tcp-seq",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "dec-tcp-seq",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "set-ttl",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_SET_TTL
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "dec-ttl",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_DEC_TTL
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "set-ipv4-dscp",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "set-ipv6-dscp",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "flag",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_FLAG
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "meter",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_METER
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "vxlan-encap",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- {
- .str = "vxlan-decap",
- .mask = FLOW_ACTION_MASK(
- RTE_FLOW_ACTION_TYPE_VXLAN_DECAP
- ),
- .map = &flow_actions[0],
- .map_idx = &actions_idx
- },
- };
-
static const struct option lgopts[] = {
/* Control */
{ "help", 0, 0, 0 },
{ "unique-data", 0, 0, 0 },
{ "portmask", 1, 0, 0 },
{ "cores", 1, 0, 0 },
+ { "random-priority", 1, 0, 0 },
+ { "meter-profile-alg", 1, 0, 0 },
+ { "rxq", 1, 0, 0 },
+ { "txq", 1, 0, 0 },
+ { "rxd", 1, 0, 0 },
+ { "txd", 1, 0, 0 },
+ { "mbuf-size", 1, 0, 0 },
+ { "mbuf-cache-size", 1, 0, 0 },
+ { "total-mbuf-count", 1, 0, 0 },
/* Attributes */
{ "ingress", 0, 0, 0 },
{ "egress", 0, 0, 0 },
{ "icmpv4", 0, 0, 0 },
{ "icmpv6", 0, 0, 0 },
/* Actions */
- { "port-id", 0, 0, 0 },
+ { "port-id", 2, 0, 0 },
{ "rss", 0, 0, 0 },
{ "queue", 0, 0, 0 },
{ "jump", 0, 0, 0 },
{ "set-ipv4-dscp", 0, 0, 0 },
{ "set-ipv6-dscp", 0, 0, 0 },
{ "flag", 0, 0, 0 },
- { "meter", 0, 0, 0 },
+ { "meter", 0, 0, 0 },
{ "raw-encap", 1, 0, 0 },
{ "raw-decap", 1, 0, 0 },
{ "vxlan-encap", 0, 0, 0 },
{ "vxlan-decap", 0, 0, 0 },
+ { "policy-mtr", 1, 0, 0 },
+ { "meter-profile", 1, 0, 0 },
+ { "packet-mode", 0, 0, 0 },
+ { 0, 0, 0, 0 },
};
RTE_ETH_FOREACH_DEV(i)
ports_mask |= 1 << i;
+ for (i = 0; i < RTE_MAX_ETHPORTS; i++)
+ dst_ports[i] = PORT_ID_DST;
+
hairpin_queues_num = 0;
argvopt = argv;
/* Control */
if (strcmp(lgopts[opt_idx].name,
"rules-batch") == 0) {
- n = atoi(optarg);
- if (n >= DEFAULT_RULES_BATCH)
- rules_batch = n;
- else {
- rte_exit(EXIT_FAILURE,
- "rules_batch should be >= %d\n",
- DEFAULT_RULES_BATCH);
- }
+ rules_batch = atoi(optarg);
}
if (strcmp(lgopts[opt_idx].name,
"rules-count") == 0) {
- n = atoi(optarg);
- if (n >= (int) rules_batch)
- rules_count = n;
- else {
+ rules_count = atoi(optarg);
+ }
+ if (strcmp(lgopts[opt_idx].name, "random-priority") ==
+ 0) {
+ end = NULL;
+ prio = strtol(optarg, &end, 10);
+ if ((optarg[0] == '\0') || (end == NULL))
rte_exit(EXIT_FAILURE,
- "rules_count should be >= %d\n",
- rules_batch);
- }
+ "Invalid value for random-priority\n");
+ max_priority = prio;
+ token = end + 1;
+ seed = strtoll(token, &end, 10);
+ if ((token[0] == '\0') || (*end != '\0'))
+ rte_exit(EXIT_FAILURE,
+ "Invalid value for random-priority\n");
+ rand_seed = seed;
}
if (strcmp(lgopts[opt_idx].name,
"dump-iterations") == 0)
rte_exit(EXIT_FAILURE, "Invalid fwd port mask\n");
ports_mask = pm;
}
+ if (strcmp(lgopts[opt_idx].name,
+ "port-id") == 0) {
+ uint16_t port_idx = 0;
+ char *token;
+
+ token = strtok(optarg, ",");
+ while (token != NULL) {
+ dst_ports[port_idx++] = atoi(token);
+ token = strtok(NULL, ",");
+ }
+ }
+ if (strcmp(lgopts[opt_idx].name, "rxq") == 0) {
+ n = atoi(optarg);
+ rx_queues_count = (uint8_t) n;
+ }
+ if (strcmp(lgopts[opt_idx].name, "txq") == 0) {
+ n = atoi(optarg);
+ tx_queues_count = (uint8_t) n;
+ }
+ if (strcmp(lgopts[opt_idx].name, "rxd") == 0) {
+ n = atoi(optarg);
+ rxd_count = (uint8_t) n;
+ }
+ if (strcmp(lgopts[opt_idx].name, "txd") == 0) {
+ n = atoi(optarg);
+ txd_count = (uint8_t) n;
+ }
+ if (strcmp(lgopts[opt_idx].name, "mbuf-size") == 0) {
+ n = atoi(optarg);
+ mbuf_size = (uint32_t) n;
+ }
+ if (strcmp(lgopts[opt_idx].name, "mbuf-cache-size") == 0) {
+ n = atoi(optarg);
+ mbuf_cache_size = (uint32_t) n;
+ }
+ if (strcmp(lgopts[opt_idx].name, "total-mbuf-count") == 0) {
+ n = atoi(optarg);
+ total_mbuf_num = (uint32_t) n;
+ }
if (strcmp(lgopts[opt_idx].name, "cores") == 0) {
n = atoi(optarg);
if ((int) rte_lcore_count() <= n) {
RTE_MAX_LCORE);
}
}
+ if (strcmp(lgopts[opt_idx].name, "policy-mtr") == 0)
+ read_meter_policy(argv[0], optarg);
+ if (strcmp(lgopts[opt_idx].name,
+ "meter-profile") == 0) {
+ i = 0;
+ token = strsep(&optarg, ",\0");
+ while (token != NULL && i < sizeof(
+ meter_profile_values) /
+ sizeof(uint64_t)) {
+ meter_profile_values[i++] = atol(token);
+ token = strsep(&optarg, ",\0");
+ }
+ }
+ if (strcmp(lgopts[opt_idx].name, "packet-mode") == 0)
+ packet_mode = true;
break;
default:
usage(argv[0]);
rte_exit(EXIT_FAILURE, "Invalid option: %s\n",
- argv[optind]);
+ argv[optind - 1]);
break;
}
}
+ if (rules_count % rules_batch != 0) {
+ rte_exit(EXIT_FAILURE,
+ "rules_count %% rules_batch should be 0\n");
+ }
+ if (rules_count / rules_batch > MAX_BATCHES_COUNT) {
+ rte_exit(EXIT_FAILURE,
+ "rules_count / rules_batch should be <= %d\n",
+ MAX_BATCHES_COUNT);
+ }
+
printf("end_flow\n");
}
}
}
-
static inline int
has_meter(void)
{
return 0;
}
+static void
+create_meter_policy(void)
+{
+ struct rte_mtr_error error;
+ int ret, port_id;
+ struct rte_mtr_meter_policy_params policy;
+ uint16_t nr_ports;
+ struct rte_flow_action actions[RTE_COLORS][MAX_ACTIONS_NUM];
+ int i;
+
+ memset(actions, 0, sizeof(actions));
+ memset(&policy, 0, sizeof(policy));
+ nr_ports = rte_eth_dev_count_avail();
+ for (port_id = 0; port_id < nr_ports; port_id++) {
+ for (i = 0; i < RTE_COLORS; i++)
+ fill_actions(actions[i], all_actions[i], 0, 0, 0,
+ 0, 0, 0, unique_data, rx_queues_count,
+ dst_ports[port_id]);
+ policy.actions[RTE_COLOR_GREEN] = actions[RTE_COLOR_GREEN];
+ policy.actions[RTE_COLOR_YELLOW] = actions[RTE_COLOR_YELLOW];
+ policy.actions[RTE_COLOR_RED] = actions[RTE_COLOR_RED];
+ policy_id[port_id] = port_id + 10;
+ ret = rte_mtr_meter_policy_add(port_id, policy_id[port_id],
+ &policy, &error);
+ if (ret) {
+ fprintf(stderr, "port %d: failed to create meter policy\n",
+ port_id);
+ policy_id[port_id] = UINT32_MAX;
+ }
+ memset(actions, 0, sizeof(actions));
+ }
+}
+
+static void
+destroy_meter_policy(void)
+{
+ struct rte_mtr_error error;
+ uint16_t nr_ports;
+ int port_id;
+
+ nr_ports = rte_eth_dev_count_avail();
+ for (port_id = 0; port_id < nr_ports; port_id++) {
+ /* If port outside portmask */
+ if (!((ports_mask >> port_id) & 0x1))
+ continue;
+
+ if (rte_mtr_meter_policy_delete
+ (port_id, policy_id[port_id], &error)) {
+ fprintf(stderr, "port %u: failed to delete meter policy\n",
+ port_id);
+ rte_exit(EXIT_FAILURE, "Error: Failed to delete meter policy.\n");
+ }
+ }
+}
+
static void
create_meter_rule(int port_id, uint32_t counter)
{
int ret;
struct rte_mtr_params params;
- uint32_t default_prof_id = 100;
struct rte_mtr_error error;
memset(¶ms, 0, sizeof(struct rte_mtr_params));
params.dscp_table = NULL;
/*create meter*/
- params.meter_profile_id = default_prof_id;
- ret = rte_mtr_create(port_id, counter, ¶ms, 1, &error);
+ params.meter_profile_id = DEFAULT_METER_PROF_ID;
+
+ if (!policy_mtr) {
+ ret = rte_mtr_create(port_id, counter, ¶ms, 1, &error);
+ } else {
+ params.meter_policy_id = policy_id[port_id];
+ ret = rte_mtr_create(port_id, counter, ¶ms, 0, &error);
+ }
+
if (ret != 0) {
printf("Port %u create meter idx(%d) error(%d) message: %s\n",
port_id, counter, error.type,
{
struct rte_mtr_error error;
+ if (policy_mtr && policy_id[port_id] != UINT32_MAX) {
+ if (rte_mtr_meter_policy_delete(port_id, policy_id[port_id],
+ &error))
+ fprintf(stderr, "Error: Failed to delete meter policy\n");
+ policy_id[port_id] = UINT32_MAX;
+ }
if (rte_mtr_destroy(port_id, counter, &error)) {
- printf("Port %u destroy meter(%d) error(%d) message: %s\n",
- port_id, counter, error.type,
- error.message ? error.message : "(no stated reason)");
- rte_exit(EXIT_FAILURE, "Error in deleting meter rule\n");
+ fprintf(stderr, "Port %d: Failed to delete meter.\n",
+ port_id);
+ rte_exit(EXIT_FAILURE, "Error in deleting meter rule");
}
}
/* If port outside portmask */
if (!((ports_mask >> port_id) & 0x1))
continue;
-
mp.alg = RTE_MTR_SRTCM_RFC2697;
- mp.srtcm_rfc2697.cir = METER_CIR;
- mp.srtcm_rfc2697.cbs = METER_CIR / 8;
- mp.srtcm_rfc2697.ebs = 0;
-
+ mp.srtcm_rfc2697.cir = meter_profile_values[0] ?
+ meter_profile_values[0] : METER_CIR;
+ mp.srtcm_rfc2697.cbs = meter_profile_values[1] ?
+ meter_profile_values[1] : METER_CIR / 8;
+ mp.srtcm_rfc2697.ebs = meter_profile_values[2];
+ mp.packet_mode = packet_mode;
ret = rte_mtr_meter_profile_add
(port_id, DEFAULT_METER_PROF_ID, &mp, &error);
if (ret != 0) {
}
static struct rte_flow **
-insert_flows(int port_id, uint8_t core_id)
+insert_flows(int port_id, uint8_t core_id, uint16_t dst_port_id)
{
struct rte_flow **flows_list;
struct rte_flow_error error;
*/
flow = generate_flow(port_id, 0, flow_attrs,
global_items, global_actions,
- flow_group, 0, 0, 0, 0, core_id, unique_data, &error);
+ flow_group, 0, 0, 0, 0, dst_port_id, core_id,
+ rx_queues_count, unique_data, max_priority, &error);
if (flow == NULL) {
print_flow_error(error);
flow = generate_flow(port_id, flow_group,
flow_attrs, flow_items, flow_actions,
JUMP_ACTION_TABLE, counter,
- hairpin_queues_num,
- encap_data, decap_data,
- core_id, unique_data, &error);
+ hairpin_queues_num, encap_data,
+ decap_data, dst_port_id,
+ core_id, rx_queues_count,
+ unique_data, max_priority, &error);
if (!counter) {
first_flow_latency = (double) (rte_get_timer_cycles() - start_batch);
flows_handler(uint8_t core_id)
{
struct rte_flow **flows_list;
+ uint16_t port_idx = 0;
uint16_t nr_ports;
int port_id;
mc_pool.last_alloc[core_id] = (int64_t)dump_socket_mem(stdout);
if (has_meter())
meters_handler(port_id, core_id, METER_CREATE);
- flows_list = insert_flows(port_id, core_id);
+ flows_list = insert_flows(port_id, core_id,
+ dst_ports[port_idx++]);
if (flows_list == NULL)
rte_exit(EXIT_FAILURE, "Error: Insertion Failed!\n");
mc_pool.current_alloc[core_id] = (int64_t)dump_socket_mem(stdout);
* threads time.
*
* Throughput: total count of rte rules divided
- * over the average of the time cosumed by all
+ * over the average of the time consumed by all
* threads time.
*/
double insertion_latency_time;
* logical cores except first core, since it's reserved for
* stats prints.
*/
- nb_fwd_streams = nr_port * RXQ_NUM;
+ nb_fwd_streams = nr_port * rx_queues_count;
if ((int)(nb_lcores - 1) >= nb_fwd_streams)
for (i = 0; i < (int)(nb_lcores - 1); i++) {
lcore = rte_get_next_lcore(lcore, 0, 0);
lcore = rte_get_next_lcore(-1, 0, 0);
for (port = 0; port < nr_port; port++) {
/* Create FWD stream */
- for (queue = 0; queue < RXQ_NUM; queue++) {
+ for (queue = 0; queue < rx_queues_count; queue++) {
if (!lcore_infos[lcore].streams_nb ||
!(stream_id % lcore_infos[lcore].streams_nb)) {
lcore = rte_get_next_lcore(lcore, 0, 0);
struct rte_eth_rxconf rxq_conf;
struct rte_eth_dev_info dev_info;
- nr_queues = RXQ_NUM;
+ nr_queues = rx_queues_count;
if (hairpin_queues_num != 0)
- nr_queues = RXQ_NUM + hairpin_queues_num;
+ nr_queues = rx_queues_count + hairpin_queues_num;
nr_ports = rte_eth_dev_count_avail();
if (nr_ports == 0)
rte_exit(EXIT_FAILURE, "Error: no port detected\n");
mbuf_mp = rte_pktmbuf_pool_create("mbuf_pool",
- TOTAL_MBUF_NUM, MBUF_CACHE_SIZE,
- 0, MBUF_SIZE,
+ total_mbuf_num, mbuf_cache_size,
+ 0, mbuf_size,
rte_socket_id());
if (mbuf_mp == NULL)
rte_exit(EXIT_FAILURE, "Error: can't init mbuf pool\n");
for (port_id = 0; port_id < nr_ports; port_id++) {
+ uint64_t rx_metadata = 0;
+
+ rx_metadata |= RTE_ETH_RX_METADATA_USER_FLAG;
+ rx_metadata |= RTE_ETH_RX_METADATA_USER_MARK;
+
+ ret = rte_eth_rx_metadata_negotiate(port_id, &rx_metadata);
+ if (ret == 0) {
+ if (!(rx_metadata & RTE_ETH_RX_METADATA_USER_FLAG)) {
+ printf(":: flow action FLAG will not affect Rx mbufs on port=%u\n",
+ port_id);
+ }
+
+ if (!(rx_metadata & RTE_ETH_RX_METADATA_USER_MARK)) {
+ printf(":: flow action MARK will not affect Rx mbufs on port=%u\n",
+ port_id);
+ }
+ } else if (ret != -ENOTSUP) {
+ rte_exit(EXIT_FAILURE, "Error when negotiating Rx meta features on port=%u: %s\n",
+ port_id, rte_strerror(-ret));
+ }
+
ret = rte_eth_dev_info_get(port_id, &dev_info);
if (ret != 0)
rte_exit(EXIT_FAILURE,
ret, port_id);
rxq_conf = dev_info.default_rxconf;
- for (std_queue = 0; std_queue < RXQ_NUM; std_queue++) {
- ret = rte_eth_rx_queue_setup(port_id, std_queue, NR_RXD,
+ for (std_queue = 0; std_queue < rx_queues_count; std_queue++) {
+ ret = rte_eth_rx_queue_setup(port_id, std_queue, rxd_count,
rte_eth_dev_socket_id(port_id),
&rxq_conf,
mbuf_mp);
}
txq_conf = dev_info.default_txconf;
- for (std_queue = 0; std_queue < TXQ_NUM; std_queue++) {
- ret = rte_eth_tx_queue_setup(port_id, std_queue, NR_TXD,
+ for (std_queue = 0; std_queue < tx_queues_count; std_queue++) {
+ ret = rte_eth_tx_queue_setup(port_id, std_queue, txd_count,
rte_eth_dev_socket_id(port_id),
&txq_conf);
if (ret < 0)
/*
* Configure peer which represents hairpin Tx.
* Hairpin queue numbers start after standard queues
- * (RXQ_NUM and TXQ_NUM).
+ * (rx_queues_count and tx_queues_count).
*/
- for (hairpin_queue = RXQ_NUM, std_queue = 0;
+ for (hairpin_queue = rx_queues_count, std_queue = 0;
hairpin_queue < nr_queues;
hairpin_queue++, std_queue++) {
hairpin_conf.peers[0].port = port_id;
hairpin_conf.peers[0].queue =
- std_queue + TXQ_NUM;
+ std_queue + tx_queues_count;
ret = rte_eth_rx_hairpin_queue_setup(
port_id, hairpin_queue,
- NR_RXD, &hairpin_conf);
+ rxd_count, &hairpin_conf);
if (ret != 0)
rte_exit(EXIT_FAILURE,
":: Hairpin rx queue setup failed: err=%d, port=%u\n",
ret, port_id);
}
- for (hairpin_queue = TXQ_NUM, std_queue = 0;
+ for (hairpin_queue = tx_queues_count, std_queue = 0;
hairpin_queue < nr_queues;
hairpin_queue++, std_queue++) {
hairpin_conf.peers[0].port = port_id;
hairpin_conf.peers[0].queue =
- std_queue + RXQ_NUM;
+ std_queue + rx_queues_count;
ret = rte_eth_tx_hairpin_queue_setup(
port_id, hairpin_queue,
- NR_TXD, &hairpin_conf);
+ txd_count, &hairpin_conf);
if (ret != 0)
rte_exit(EXIT_FAILURE,
":: Hairpin tx queue setup failed: err=%d, port=%u\n",
flow_group = DEFAULT_GROUP;
unique_data = false;
+ rx_queues_count = (uint8_t) RXQ_NUM;
+ tx_queues_count = (uint8_t) TXQ_NUM;
+ rxd_count = (uint8_t) NR_RXD;
+ txd_count = (uint8_t) NR_TXD;
+ mbuf_size = (uint32_t) MBUF_SIZE;
+ mbuf_cache_size = (uint32_t) MBUF_CACHE_SIZE;
+ total_mbuf_num = (uint32_t) TOTAL_MBUF_NUM;
+
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
printf(":: Flows Count per port: %d\n\n", rules_count);
- if (has_meter())
+ rte_srand(rand_seed);
+
+ if (has_meter()) {
create_meter_profile();
+ if (policy_mtr)
+ create_meter_policy();
+ }
rte_eal_mp_remote_launch(run_rte_flow_handler_cores, NULL, CALL_MAIN);
if (enable_fwd) {
init_lcore_info();
rte_eal_mp_remote_launch(start_forwarding, NULL, CALL_MAIN);
}
- if (has_meter() && delete_flag)
+ if (has_meter() && delete_flag) {
destroy_meter_profile();
+ if (policy_mtr)
+ destroy_meter_policy();
+ }
RTE_ETH_FOREACH_DEV(port) {
rte_flow_flush(port, &error);