#include <stdio.h>
#include <stdlib.h>
#include <rte_ip.h>
#include "flow.h"
#include "ipsec-secgw.h"
#include "parser.h"
#define FLOW_RULES_MAX 128
struct flow_rule_entry {
uint8_t is_eth;
uint8_t is_ipv4;
uint8_t is_ipv6;
union {
struct {
} ipv4;
struct {
} ipv6;
};
uint16_t port;
uint16_t queue;
bool is_queue_set;
bool enable_count;
bool enable_mark;
bool set_security_action;
bool set_mark_action;
uint32_t mark_action_val;
struct rte_flow *flow;
} flow_rule_tbl[FLOW_RULES_MAX];
int nb_flow_rule;
static void
ipv4_hdr_print(struct rte_ipv4_hdr *hdr)
{
char a, b, c, d;
uint32_t_to_char(
rte_bswap32(hdr->src_addr), &a, &b, &c, &d);
printf("src: %3hhu.%3hhu.%3hhu.%3hhu \t", a, b, c, d);
uint32_t_to_char(
rte_bswap32(hdr->dst_addr), &a, &b, &c, &d);
printf("dst: %3hhu.%3hhu.%3hhu.%3hhu", a, b, c, d);
}
static int
struct parse_status *status)
{
struct in_addr ip;
uint32_t depth;
APP_CHECK(parse_ipv4_addr(token, &ip, &depth) == 0, status,
"unrecognized input \"%s\", expect valid ipv4 addr", token);
if (status->status < 0)
return -1;
if (depth > 32)
return -1;
*spec = ip.s_addr;
if (depth < 32)
*mask = htonl(*mask << (32 - depth));
return 0;
}
static void
ipv6_hdr_print(struct rte_ipv6_hdr *hdr)
{
}
static int
struct parse_status *status)
{
uint32_t depth, i;
APP_CHECK(parse_ipv6_addr(token, &ip, &depth) == 0, status,
"unrecognized input \"%s\", expect valid ipv6 address", token);
if (status->status < 0)
return -1;
*spec = ip;
for (i = 0; i < depth && (i%8 <= sizeof(*mask)); i++)
mask->
a[i/8] &= ~(1 << (7-i%8));
return 0;
}
void
parse_flow_tokens(char **tokens, uint32_t n_tokens,
struct parse_status *status)
{
struct flow_rule_entry *rule;
uint32_t ti = 0;
if (nb_flow_rule >= FLOW_RULES_MAX) {
printf("Too many flow rules\n");
return;
}
rule = &flow_rule_tbl[nb_flow_rule];
memset(rule, 0, sizeof(*rule));
for (ti = 0; ti < n_tokens; ti++) {
if (strcmp(tokens[ti], "mark") == 0) {
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
if (status->status < 0)
return;
APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
if (status->status < 0)
return;
rule->mark_val.id = atoi(tokens[ti]);
rule->enable_mark = true;
continue;
}
if (strcmp(tokens[ti], "eth") == 0) {
rule->is_eth = true;
continue;
}
if (strcmp(tokens[ti], "ipv4") == 0) {
rule->is_ipv4 = true;
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
if (status->status < 0)
return;
if (strcmp(tokens[ti], "src") == 0) {
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
if (status->status < 0)
return;
if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.src_addr,
&rule->ipv4.mask.hdr.src_addr,
tokens[ti], status))
return;
}
if (strcmp(tokens[ti], "dst") == 0) {
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
if (status->status < 0)
return;
if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.dst_addr,
&rule->ipv4.mask.hdr.dst_addr,
tokens[ti], status))
return;
}
continue;
}
if (strcmp(tokens[ti], "ipv6") == 0) {
rule->is_ipv6 = true;
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
if (status->status < 0)
return;
if (strcmp(tokens[ti], "src") == 0) {
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
if (status->status < 0)
return;
if (ipv6_addr_cpy(&rule->ipv6.spec.hdr.src_addr,
&rule->ipv6.mask.hdr.src_addr,
tokens[ti], status))
return;
}
if (strcmp(tokens[ti], "dst") == 0) {
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
if (status->status < 0)
return;
if (ipv6_addr_cpy(&rule->ipv6.spec.hdr.dst_addr,
&rule->ipv6.mask.hdr.dst_addr,
tokens[ti], status))
return;
}
continue;
}
if (strcmp(tokens[ti], "port") == 0) {
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
if (status->status < 0)
return;
APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
if (status->status < 0)
return;
rule->port = atoi(tokens[ti]);
continue;
}
if (strcmp(tokens[ti], "queue") == 0) {
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
if (status->status < 0)
return;
APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
if (status->status < 0)
return;
rule->queue = atoi(tokens[ti]);
rule->is_queue_set = true;
continue;
}
if (strcmp(tokens[ti], "count") == 0) {
rule->enable_count = true;
continue;
}
if (strcmp(tokens[ti], "security") == 0) {
rule->set_security_action = true;
continue;
}
if (strcmp(tokens[ti], "set_mark") == 0) {
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
if (status->status < 0)
return;
APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
if (status->status < 0)
return;
rule->set_mark_action = true;
rule->mark_action_val = atoi(tokens[ti]);
continue;
}
sprintf(status->parse_msg, "Unrecognized input:%s\n",
tokens[ti]);
status->status = -1;
return;
}
printf("\n");
nb_flow_rule++;
}
#define MAX_RTE_FLOW_PATTERN (5)
#define MAX_RTE_FLOW_ACTIONS (5)
static void
flow_init_single(struct flow_rule_entry *rule)
{
int ret, pattern_idx = 0, act_idx = 0;
if (rule->is_queue_set) {
queue_action.index = rule->queue;
action[act_idx].
conf = &queue_action;
act_idx++;
}
if (rule->enable_count) {
act_idx++;
}
if (rule->set_security_action) {
action[act_idx].
conf = NULL;
act_idx++;
}
if (rule->set_mark_action) {
mark_action.id = rule->mark_action_val;
action[act_idx].
conf = &mark_action;
act_idx++;
}
action[act_idx].
conf = NULL;
if (rule->enable_mark) {
mark_mask.id = UINT32_MAX;
pattern[pattern_idx].
spec = &rule->mark_val;
pattern[pattern_idx].
mask = &mark_mask;
pattern_idx++;
}
if (rule->is_eth) {
pattern_idx++;
}
if (rule->is_ipv4) {
pattern[pattern_idx].
spec = &rule->ipv4.spec;
pattern[pattern_idx].
mask = &rule->ipv4.mask;
pattern_idx++;
} else if (rule->is_ipv6) {
pattern[pattern_idx].
spec = &rule->ipv6.spec;
pattern[pattern_idx].
mask = &rule->ipv6.mask;
pattern_idx++;
}
if (rule->set_security_action) {
pattern[pattern_idx].
spec = NULL;
pattern[pattern_idx].
mask = NULL;
pattern[pattern_idx].
last = NULL;
pattern_idx++;
}
if (ret < 0) {
rule->flow = 0;
return;
}
if (rule->flow == NULL)
}
void
flow_print_counters(void)
{
struct flow_rule_entry *rule;
int i = 0, ret = 0;
for (i = 0; i < nb_flow_rule; i++) {
rule = &flow_rule_tbl[i];
if (!rule->flow || !rule->enable_count)
continue;
memset(&error, 0x55, sizeof(error));
memset(&count_query, 0, sizeof(count_query));
&count_query, &error);
if (ret)
"Failed to get flow counter "
" for port %u, err msg: %s\n",
rule->port, error.message);
printf("Flow #%3d:", i);
if (rule->is_ipv4) {
printf(" spec ipv4 ");
ipv4_hdr_print(&rule->ipv4.spec.hdr);
}
if (rule->is_ipv6) {
printf(" spec ipv6 ");
ipv6_hdr_print(&rule->ipv6.spec.hdr);
}
if (rule->set_security_action)
printf(" Security action set,");
if (rule->enable_mark)
printf(" Mark Enabled");
printf(" Port: %d,", rule->port);
if (rule->is_queue_set)
printf(" Queue: %d", rule->queue);
printf(" Hits: %"PRIu64"\n", count_query.hits);
}
}
void
flow_init(void)
{
struct flow_rule_entry *rule;
int i;
for (i = 0; i < nb_flow_rule; i++) {
rule = &flow_rule_tbl[i];
flow_init_single(rule);
}
for (i = 0; i < nb_flow_rule; i++) {
rule = &flow_rule_tbl[i];
printf("Flow #%3d: ", i);
if (rule->is_ipv4) {
printf("spec ipv4 ");
ipv4_hdr_print(&rule->ipv4.spec.hdr);
printf("\n");
printf(" mask ipv4 ");
ipv4_hdr_print(&rule->ipv4.mask.hdr);
}
if (rule->is_ipv6) {
printf("spec ipv6 ");
ipv6_hdr_print(&rule->ipv6.spec.hdr);
printf("\n");
printf(" mask ipv6 ");
ipv6_hdr_print(&rule->ipv6.mask.hdr);
}
if (rule->enable_mark)
printf(", Mark enabled");
printf("\tPort: %d,", rule->port);
if (rule->is_queue_set)
printf(" Queue: %d,", rule->queue);
if (rule->set_security_action)
printf(" Security action set,");
if (rule->set_mark_action)
printf(" Mark: %d,", rule->mark_action_val);
if (rule->enable_count)
printf(" Counter enabled,");
if (rule->flow == NULL)
printf(" [UNSUPPORTED]");
printf("\n");
}
}
static uint32_t rte_bswap32(uint32_t x)
int rte_flow_validate(uint16_t port_id, const struct rte_flow_attr *attr, const struct rte_flow_item pattern[], const struct rte_flow_action actions[], struct rte_flow_error *error)
@ RTE_FLOW_ACTION_TYPE_COUNT
@ RTE_FLOW_ACTION_TYPE_MARK
@ RTE_FLOW_ACTION_TYPE_QUEUE
@ RTE_FLOW_ACTION_TYPE_END
@ RTE_FLOW_ACTION_TYPE_SECURITY
static const struct rte_flow_item_ipv6 rte_flow_item_ipv6_mask
int rte_flow_query(uint16_t port_id, struct rte_flow *flow, const struct rte_flow_action *action, void *data, struct rte_flow_error *error)
static const struct rte_flow_item_ipv4 rte_flow_item_ipv4_mask
struct rte_flow * rte_flow_create(uint16_t port_id, const struct rte_flow_attr *attr, const struct rte_flow_item pattern[], const struct rte_flow_action actions[], struct rte_flow_error *error)
@ RTE_FLOW_ITEM_TYPE_IPV4
@ RTE_FLOW_ITEM_TYPE_MARK
@ RTE_FLOW_ITEM_TYPE_IPV6
#define RTE_IPV6_ADDR_SPLIT(ip)
#define RTE_IPV6_ADDR_FMT
#define RTE_LOG(l, t,...)
enum rte_flow_action_type type
enum rte_flow_item_type type