95df1d78c6
Static analysis shows that once instance of rte_zmalloc is missing a return value check in the code. This is fixed by adding a return value check. The malloc call itself is moved to earlier in the function so that no work is done unless all memory allocation requests have succeeded - thereby removing the need for rollback on error. Signed-off-by: Bruce Richardson <bruce.richardson@intel.com> Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
1983 lines
53 KiB
C
1983 lines
53 KiB
C
/*-
|
|
* BSD LICENSE
|
|
*
|
|
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* * Neither the name of Intel Corporation nor the names of its
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <termios.h>
|
|
#include <inttypes.h>
|
|
#include <string.h>
|
|
#include <netinet/in.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
#include <rte_ether.h>
|
|
#include <rte_byteorder.h>
|
|
#include <rte_ring.h>
|
|
#include <rte_mbuf.h>
|
|
#include <rte_malloc.h>
|
|
#include <rte_string_fns.h>
|
|
#include <cmdline_rdline.h>
|
|
#include <cmdline_parse.h>
|
|
#include <cmdline_parse_num.h>
|
|
#include <cmdline_parse_string.h>
|
|
#include <cmdline_parse_ipaddr.h>
|
|
#include <cmdline_parse_etheraddr.h>
|
|
#include <cmdline_socket.h>
|
|
#include <cmdline.h>
|
|
|
|
#include "main.h"
|
|
|
|
#define IS_RULE_PRESENT(res, rule_key, table, type) \
|
|
do { \
|
|
struct app_rule *it; \
|
|
\
|
|
(res) = NULL; \
|
|
TAILQ_FOREACH(it, &table, entries) { \
|
|
if (memcmp(&rule_key, &it->type.key, sizeof(rule_key)) == 0) {\
|
|
(res) = it; \
|
|
break; \
|
|
} \
|
|
} \
|
|
} while (0)
|
|
|
|
/* Rules */
|
|
static void
|
|
app_init_rule_tables(void);
|
|
|
|
TAILQ_HEAD(linked_list, app_rule) arp_table, routing_table, firewall_table,
|
|
flow_table;
|
|
|
|
uint32_t n_arp_rules;
|
|
uint32_t n_routing_rules;
|
|
uint32_t n_firewall_rules;
|
|
uint32_t n_flow_rules;
|
|
|
|
struct app_arp_rule {
|
|
struct {
|
|
uint8_t out_iface;
|
|
uint32_t nh_ip;
|
|
} key;
|
|
|
|
struct ether_addr nh_arp;
|
|
};
|
|
|
|
struct app_routing_rule {
|
|
struct {
|
|
uint32_t ip;
|
|
uint8_t depth;
|
|
} key;
|
|
|
|
uint8_t port;
|
|
uint32_t nh_ip;
|
|
};
|
|
|
|
struct app_firewall_rule {
|
|
struct {
|
|
uint32_t src_ip;
|
|
uint32_t src_ip_mask;
|
|
uint32_t dst_ip;
|
|
uint32_t dst_ip_mask;
|
|
uint16_t src_port_from;
|
|
uint16_t src_port_to;
|
|
uint16_t dst_port_from;
|
|
uint16_t dst_port_to;
|
|
uint8_t proto;
|
|
uint8_t proto_mask;
|
|
} key;
|
|
|
|
int32_t priority;
|
|
uint8_t port;
|
|
};
|
|
|
|
struct app_flow_rule {
|
|
struct {
|
|
uint32_t src_ip;
|
|
uint32_t dst_ip;
|
|
uint16_t src_port;
|
|
uint16_t dst_port;
|
|
uint8_t proto;
|
|
} key;
|
|
|
|
uint8_t port;
|
|
};
|
|
|
|
struct app_rule {
|
|
union {
|
|
struct app_arp_rule arp;
|
|
struct app_routing_rule routing;
|
|
struct app_firewall_rule firewall;
|
|
struct app_flow_rule flow;
|
|
};
|
|
|
|
TAILQ_ENTRY(app_rule) entries;
|
|
};
|
|
|
|
/* Initialization */
|
|
static void
|
|
app_init_rule_tables(void)
|
|
{
|
|
TAILQ_INIT(&arp_table);
|
|
TAILQ_INIT(&routing_table);
|
|
TAILQ_INIT(&firewall_table);
|
|
TAILQ_INIT(&flow_table);
|
|
|
|
n_arp_rules = 0;
|
|
n_routing_rules = 0;
|
|
n_firewall_rules = 0;
|
|
n_flow_rules = 0;
|
|
}
|
|
|
|
/* Printing */
|
|
static void
|
|
print_arp_rule(struct app_arp_rule rule)
|
|
{
|
|
printf("(Iface = %u, Address = %u.%u.%u.%u) => "
|
|
"HWaddress = %02x:%02x:%02x:%02x:%02x:%02x\n",
|
|
rule.key.out_iface,
|
|
(rule.key.nh_ip >> 24) & 0xFF,
|
|
(rule.key.nh_ip >> 16) & 0xFF,
|
|
(rule.key.nh_ip >> 8) & 0xFF,
|
|
rule.key.nh_ip & 0xFF,
|
|
|
|
rule.nh_arp.addr_bytes[0],
|
|
rule.nh_arp.addr_bytes[1],
|
|
rule.nh_arp.addr_bytes[2],
|
|
rule.nh_arp.addr_bytes[3],
|
|
rule.nh_arp.addr_bytes[4],
|
|
rule.nh_arp.addr_bytes[5]);
|
|
}
|
|
|
|
static void
|
|
print_routing_rule(struct app_routing_rule rule)
|
|
{
|
|
printf("IP Prefix = %u.%u.%u.%u/%u => "
|
|
"(Iface = %u, Gateway = %u.%u.%u.%u)\n",
|
|
(rule.key.ip >> 24) & 0xFF,
|
|
(rule.key.ip >> 16) & 0xFF,
|
|
(rule.key.ip >> 8) & 0xFF,
|
|
rule.key.ip & 0xFF,
|
|
|
|
rule.key.depth,
|
|
rule.port,
|
|
|
|
(rule.nh_ip >> 24) & 0xFF,
|
|
(rule.nh_ip >> 16) & 0xFF,
|
|
(rule.nh_ip >> 8) & 0xFF,
|
|
rule.nh_ip & 0xFF);
|
|
}
|
|
|
|
#ifdef RTE_LIBRTE_ACL
|
|
|
|
static void
|
|
print_firewall_rule(struct app_firewall_rule rule)
|
|
{
|
|
printf("Priority %d: (IP Src = %u.%u.%u.%u/%u, "
|
|
"IP Dst = %u.%u.%u.%u/%u, "
|
|
"Port Src = %u-%u, Port Dst = %u-%u, Proto = %u (%u)) => "
|
|
"Port = %u\n",
|
|
rule.priority,
|
|
|
|
(rule.key.src_ip >> 24) & 0xFF,
|
|
(rule.key.src_ip >> 16) & 0xFF,
|
|
(rule.key.src_ip >> 8) & 0xFF,
|
|
rule.key.src_ip & 0xFF,
|
|
rule.key.src_ip_mask,
|
|
|
|
(rule.key.dst_ip >> 24) & 0xFF,
|
|
(rule.key.dst_ip >> 16) & 0xFF,
|
|
(rule.key.dst_ip >> 8) & 0xFF,
|
|
rule.key.dst_ip & 0xFF,
|
|
rule.key.dst_ip_mask,
|
|
|
|
rule.key.src_port_from,
|
|
rule.key.src_port_to,
|
|
rule.key.dst_port_from,
|
|
rule.key.dst_port_to,
|
|
rule.key.proto,
|
|
rule.key.proto_mask,
|
|
rule.port);
|
|
}
|
|
|
|
#endif
|
|
|
|
static void
|
|
print_flow_rule(struct app_flow_rule rule)
|
|
{
|
|
printf("(IP Src = %u.%u.%u.%u, IP Dst = %u.%u.%u.%u, Port Src = %u, "
|
|
"Port Dst = %u, Proto = %u) => Port = %u\n",
|
|
(rule.key.src_ip >> 24) & 0xFF,
|
|
(rule.key.src_ip >> 16) & 0xFF,
|
|
(rule.key.src_ip >> 8) & 0xFF,
|
|
rule.key.src_ip & 0xFF,
|
|
|
|
(rule.key.dst_ip >> 24) & 0xFF,
|
|
(rule.key.dst_ip >> 16) & 0xFF,
|
|
(rule.key.dst_ip >> 8) & 0xFF,
|
|
rule.key.dst_ip & 0xFF,
|
|
|
|
rule.key.src_port,
|
|
rule.key.dst_port,
|
|
(uint32_t) rule.key.proto,
|
|
rule.port);
|
|
}
|
|
|
|
/* Commands */
|
|
|
|
/* *** Run file (script) *** */
|
|
struct cmd_run_file_result {
|
|
cmdline_fixed_string_t run_string;
|
|
char file_path[100];
|
|
};
|
|
|
|
static void
|
|
cmd_run_file_parsed(
|
|
void *parsed_result,
|
|
struct cmdline *cl,
|
|
__attribute__((unused)) void *data)
|
|
{
|
|
struct cmd_run_file_result *params = parsed_result;
|
|
struct cmdline *file_cl;
|
|
int fd;
|
|
|
|
/* Check params */
|
|
if (!params->file_path) {
|
|
printf("Illegal value for file path (%s)\n", params->file_path);
|
|
return;
|
|
}
|
|
|
|
fd = open(params->file_path, O_RDONLY, 0);
|
|
if (fd < 0) {
|
|
printf("Illegal value for file path (%s)\n", params->file_path);
|
|
return;
|
|
}
|
|
|
|
file_cl = cmdline_new(cl->ctx, "", fd, 1);
|
|
cmdline_interact(file_cl);
|
|
close(fd);
|
|
}
|
|
|
|
cmdline_parse_token_string_t cmd_run_file_run_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, run_string, "run");
|
|
|
|
cmdline_parse_token_string_t cmd_run_file_file_path =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, file_path, NULL);
|
|
|
|
cmdline_parse_inst_t cmd_run_file = {
|
|
.f = cmd_run_file_parsed,
|
|
.data = NULL,
|
|
.help_str = "Run commands from file",
|
|
.tokens = {
|
|
(void *)&cmd_run_file_run_string,
|
|
(void *)&cmd_run_file_file_path,
|
|
NULL,
|
|
},
|
|
};
|
|
|
|
/* *** Link - Enable *** */
|
|
struct cmd_link_enable_result {
|
|
cmdline_fixed_string_t link_string;
|
|
uint8_t port;
|
|
cmdline_fixed_string_t up_string;
|
|
};
|
|
|
|
static void
|
|
cmd_link_enable_parsed(
|
|
void *parsed_result,
|
|
__attribute__((unused)) struct cmdline *cl,
|
|
__attribute__((unused)) void *data)
|
|
{
|
|
struct cmd_link_enable_result *params = parsed_result;
|
|
void *msg;
|
|
struct app_msg_req *req;
|
|
struct app_msg_resp *resp;
|
|
int status;
|
|
|
|
uint32_t core_id = app_get_first_core_id(APP_CORE_RX);
|
|
|
|
if (core_id == RTE_MAX_LCORE) {
|
|
printf("RX core not preformed by any CPU core\n");
|
|
return;
|
|
}
|
|
|
|
struct rte_ring *ring_req = app_get_ring_req(core_id);
|
|
struct rte_ring *ring_resp = app_get_ring_resp(core_id);
|
|
|
|
/* Check params */
|
|
if (params->port >= app.n_ports) {
|
|
printf("Illegal value for port parameter (%u)\n", params->port);
|
|
return;
|
|
}
|
|
|
|
printf("Enabling port %d\n", params->port);
|
|
|
|
/* Allocate message buffer */
|
|
msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
|
|
if (msg == NULL)
|
|
rte_panic("Unable to allocate new message\n");
|
|
|
|
/* Fill request message */
|
|
req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
|
|
req->type = APP_MSG_REQ_RX_PORT_ENABLE;
|
|
req->rx_up.port = params->port;
|
|
|
|
/* Send request */
|
|
do {
|
|
status = rte_ring_sp_enqueue(ring_req, msg);
|
|
} while (status == -ENOBUFS);
|
|
|
|
/* Wait for response */
|
|
do {
|
|
status = rte_ring_sc_dequeue(ring_resp, &msg);
|
|
} while (status != 0);
|
|
resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
|
|
/* Check response */
|
|
if (resp->result != 0)
|
|
printf("Request LINK_UP failed (%u)\n", resp->result);
|
|
|
|
/* Free message buffer */
|
|
rte_ctrlmbuf_free(msg);
|
|
}
|
|
|
|
cmdline_parse_token_string_t cmd_link_enable_link_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_link_enable_result, link_string,
|
|
"link");
|
|
|
|
cmdline_parse_token_num_t cmd_link_enable_port =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_link_enable_result, port, UINT8);
|
|
|
|
cmdline_parse_token_string_t cmd_link_enable_up_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_link_enable_result, up_string,
|
|
"up");
|
|
|
|
cmdline_parse_inst_t cmd_link_enable = {
|
|
.f = cmd_link_enable_parsed,
|
|
.data = NULL,
|
|
.help_str = "Link down",
|
|
.tokens = {
|
|
(void *)&cmd_link_enable_link_string,
|
|
(void *)&cmd_link_enable_port,
|
|
(void *)&cmd_link_enable_up_string,
|
|
NULL,
|
|
},
|
|
};
|
|
|
|
/* *** Link - Disable *** */
|
|
struct cmd_link_disable_result {
|
|
cmdline_fixed_string_t link_string;
|
|
uint8_t port;
|
|
cmdline_fixed_string_t down_string;
|
|
};
|
|
|
|
static void
|
|
cmd_link_disable_parsed(
|
|
void *parsed_result,
|
|
__attribute__((unused)) struct cmdline *cl,
|
|
__attribute__((unused)) void *data)
|
|
{
|
|
struct cmd_link_disable_result *params = parsed_result;
|
|
struct app_msg_req *req;
|
|
struct app_msg_resp *resp;
|
|
void *msg;
|
|
int status;
|
|
|
|
uint32_t core_id = app_get_first_core_id(APP_CORE_RX);
|
|
|
|
if (core_id == RTE_MAX_LCORE) {
|
|
printf("RX not performed by any CPU core\n");
|
|
return;
|
|
}
|
|
|
|
struct rte_ring *ring_req = app_get_ring_req(core_id);
|
|
struct rte_ring *ring_resp = app_get_ring_resp(core_id);
|
|
|
|
/* Check params */
|
|
if (params->port >= app.n_ports) {
|
|
printf("Illegal value for port parameter (%u)\n", params->port);
|
|
return;
|
|
}
|
|
|
|
printf("Disabling port %d\n", params->port);
|
|
|
|
/* Allocate message buffer */
|
|
msg = rte_ctrlmbuf_alloc(app.msg_pool);
|
|
if (msg == NULL)
|
|
rte_panic("Unable to allocate new message\n");
|
|
|
|
/* Fill request message */
|
|
req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
|
|
req->type = APP_MSG_REQ_RX_PORT_DISABLE;
|
|
req->rx_down.port = params->port;
|
|
|
|
/* Send request */
|
|
do {
|
|
status = rte_ring_sp_enqueue(ring_req, msg);
|
|
} while (status == -ENOBUFS);
|
|
|
|
/* Wait for response */
|
|
do {
|
|
status = rte_ring_sc_dequeue(ring_resp, &msg);
|
|
} while (status != 0);
|
|
resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
|
|
|
|
/* Check response */
|
|
if (resp->result != 0)
|
|
printf("Request LINK_DOWN failed (%u)\n", resp->result);
|
|
|
|
/* Free message buffer */
|
|
rte_ctrlmbuf_free((struct rte_mbuf *)msg);
|
|
}
|
|
|
|
cmdline_parse_token_string_t cmd_link_disable_link_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_link_disable_result, link_string,
|
|
"link");
|
|
|
|
cmdline_parse_token_num_t cmd_link_disable_port =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_link_disable_result, port, UINT8);
|
|
|
|
cmdline_parse_token_string_t cmd_link_disable_down_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_link_disable_result, down_string,
|
|
"down");
|
|
|
|
cmdline_parse_inst_t cmd_link_disable = {
|
|
.f = cmd_link_disable_parsed,
|
|
.data = NULL,
|
|
.help_str = "Link up",
|
|
.tokens = {
|
|
(void *)&cmd_link_disable_link_string,
|
|
(void *)&cmd_link_disable_port,
|
|
(void *)&cmd_link_disable_down_string,
|
|
NULL,
|
|
},
|
|
};
|
|
|
|
|
|
/* *** ARP - Add *** */
|
|
struct cmd_arp_add_result {
|
|
cmdline_fixed_string_t arp_string;
|
|
cmdline_fixed_string_t add_string;
|
|
uint8_t out_iface;
|
|
cmdline_ipaddr_t nh_ip;
|
|
struct ether_addr nh_arp;
|
|
|
|
};
|
|
|
|
static void
|
|
cmd_arp_add_parsed(
|
|
void *parsed_result,
|
|
__attribute__((unused)) struct cmdline *cl,
|
|
__attribute__((unused)) void *data)
|
|
{
|
|
struct cmd_arp_add_result *params = parsed_result;
|
|
struct app_rule rule, *old_rule;
|
|
struct app_msg_req *req;
|
|
struct app_msg_resp *resp;
|
|
void *msg;
|
|
int status;
|
|
|
|
uint32_t core_id = app_get_first_core_id(APP_CORE_RT);
|
|
|
|
if (core_id == RTE_MAX_LCORE) {
|
|
printf("ARP not performed by any CPU core\n");
|
|
return;
|
|
}
|
|
|
|
struct rte_ring *ring_req = app_get_ring_req(core_id);
|
|
struct rte_ring *ring_resp = app_get_ring_resp(core_id);
|
|
|
|
/* Check params */
|
|
if (params->out_iface >= app.n_ports) {
|
|
printf("Illegal value for output interface parameter (%u)\n",
|
|
params->out_iface);
|
|
return;
|
|
}
|
|
|
|
/* Create rule */
|
|
memset(&rule, 0, sizeof(rule));
|
|
rule.arp.key.out_iface = params->out_iface;
|
|
rule.arp.key.nh_ip =
|
|
rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr);
|
|
rule.arp.nh_arp = params->nh_arp;
|
|
|
|
/* Check rule existence */
|
|
IS_RULE_PRESENT(old_rule, rule.arp.key, arp_table, arp);
|
|
if ((old_rule == NULL) && (n_arp_rules == app.max_arp_rules)) {
|
|
printf("ARP table is full.\n");
|
|
return;
|
|
}
|
|
|
|
printf("Adding ARP entry: ");
|
|
print_arp_rule(rule.arp);
|
|
|
|
/* Allocate message buffer */
|
|
msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
|
|
if (msg == NULL)
|
|
rte_panic("Unable to allocate new message\n");
|
|
|
|
/* Fill request message */
|
|
req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
|
|
req->type = APP_MSG_REQ_ARP_ADD;
|
|
req->arp_add.out_iface = rule.arp.key.out_iface;
|
|
req->arp_add.nh_ip = rule.arp.key.nh_ip;
|
|
req->arp_add.nh_arp = rule.arp.nh_arp;
|
|
|
|
/* Send request */
|
|
do {
|
|
status = rte_ring_sp_enqueue(ring_req, msg);
|
|
} while (status == -ENOBUFS);
|
|
|
|
/* Wait for response */
|
|
do {
|
|
status = rte_ring_sc_dequeue(ring_resp, &msg);
|
|
} while (status != 0);
|
|
resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
|
|
|
|
/* Check response */
|
|
if (resp->result != 0)
|
|
printf("Request ARP_ADD failed (%u)\n", resp->result);
|
|
else {
|
|
if (old_rule == NULL) {
|
|
struct app_rule *new_rule = (struct app_rule *)
|
|
rte_zmalloc_socket("CLI",
|
|
sizeof(struct app_rule),
|
|
RTE_CACHE_LINE_SIZE,
|
|
rte_socket_id());
|
|
|
|
if (new_rule == NULL)
|
|
rte_panic("Unable to allocate new rule\n");
|
|
|
|
memcpy(new_rule, &rule, sizeof(rule));
|
|
TAILQ_INSERT_TAIL(&arp_table, new_rule, entries);
|
|
n_arp_rules++;
|
|
} else
|
|
old_rule->arp.nh_arp = rule.arp.nh_arp;
|
|
}
|
|
|
|
/* Free message buffer */
|
|
rte_ctrlmbuf_free((struct rte_mbuf *) msg);
|
|
}
|
|
|
|
cmdline_parse_token_string_t cmd_arp_add_arp_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, arp_string, "arp");
|
|
|
|
cmdline_parse_token_string_t cmd_arp_add_add_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, add_string, "add");
|
|
|
|
cmdline_parse_token_num_t cmd_arp_add_out_iface =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_arp_add_result, out_iface, UINT8);
|
|
|
|
cmdline_parse_token_ipaddr_t cmd_arp_add_nh_ip =
|
|
TOKEN_IPADDR_INITIALIZER(struct cmd_arp_add_result, nh_ip);
|
|
|
|
cmdline_parse_token_etheraddr_t cmd_arp_add_nh_arp =
|
|
TOKEN_ETHERADDR_INITIALIZER(struct cmd_arp_add_result, nh_arp);
|
|
|
|
cmdline_parse_inst_t cmd_arp_add = {
|
|
.f = cmd_arp_add_parsed,
|
|
.data = NULL,
|
|
.help_str = "ARP add",
|
|
.tokens = {
|
|
(void *)&cmd_arp_add_arp_string,
|
|
(void *)&cmd_arp_add_add_string,
|
|
(void *)&cmd_arp_add_out_iface,
|
|
(void *)&cmd_arp_add_nh_ip,
|
|
(void *)&cmd_arp_add_nh_arp,
|
|
NULL,
|
|
},
|
|
};
|
|
|
|
/* *** ARP - Del *** */
|
|
struct cmd_arp_del_result {
|
|
cmdline_fixed_string_t arp_string;
|
|
cmdline_fixed_string_t del_string;
|
|
uint8_t out_iface;
|
|
cmdline_ipaddr_t nh_ip;
|
|
};
|
|
|
|
static void
|
|
cmd_arp_del_parsed(
|
|
void *parsed_result,
|
|
__attribute__((unused)) struct cmdline *cl,
|
|
__attribute__((unused)) void *data)
|
|
{
|
|
struct cmd_arp_del_result *params = parsed_result;
|
|
struct app_rule rule, *old_rule;
|
|
struct app_msg_req *req;
|
|
struct app_msg_resp *resp;
|
|
void *msg;
|
|
int status;
|
|
|
|
uint32_t core_id = app_get_first_core_id(APP_CORE_RT);
|
|
|
|
if (core_id == RTE_MAX_LCORE) {
|
|
printf("ARP not performed by any CPU core\n");
|
|
return;
|
|
}
|
|
|
|
struct rte_ring *ring_req = app_get_ring_req(core_id);
|
|
struct rte_ring *ring_resp = app_get_ring_resp(core_id);
|
|
|
|
/* Check params */
|
|
if (params->out_iface > app.n_ports) {
|
|
printf("Illegal value for output interface parameter (%u)\n",
|
|
params->out_iface);
|
|
return;
|
|
}
|
|
|
|
/* Create rule */
|
|
memset(&rule, 0, sizeof(rule));
|
|
rule.arp.key.out_iface = params->out_iface;
|
|
rule.arp.key.nh_ip =
|
|
rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr);
|
|
|
|
/* Check rule existence */
|
|
IS_RULE_PRESENT(old_rule, rule.arp.key, arp_table, arp);
|
|
if (old_rule == NULL)
|
|
return;
|
|
|
|
printf("Deleting ARP entry: ");
|
|
print_arp_rule(old_rule->arp);
|
|
|
|
/* Allocate message buffer */
|
|
msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
|
|
if (msg == NULL)
|
|
rte_panic("Unable to allocate new message\n");
|
|
|
|
/* Fill request message */
|
|
req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
|
|
req->type = APP_MSG_REQ_ARP_DEL;
|
|
req->arp_del.out_iface = rule.arp.key.out_iface;
|
|
req->arp_del.nh_ip = rule.arp.key.nh_ip;
|
|
|
|
/* Send request */
|
|
do {
|
|
status = rte_ring_sp_enqueue(ring_req, msg);
|
|
} while (status == -ENOBUFS);
|
|
|
|
/* Wait for response */
|
|
do {
|
|
status = rte_ring_sc_dequeue(ring_resp, &msg);
|
|
} while (status != 0);
|
|
resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
|
|
|
|
/* Check response */
|
|
if (resp->result != 0)
|
|
printf("Request ARP_DEL failed (%u)\n", resp->result);
|
|
else {
|
|
TAILQ_REMOVE(&arp_table, old_rule, entries);
|
|
n_arp_rules--;
|
|
rte_free(old_rule);
|
|
}
|
|
|
|
/* Free message buffer */
|
|
rte_ctrlmbuf_free((struct rte_mbuf *) msg);
|
|
}
|
|
|
|
cmdline_parse_token_string_t cmd_arp_del_arp_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, arp_string, "arp");
|
|
|
|
cmdline_parse_token_string_t cmd_arp_del_del_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, del_string, "del");
|
|
|
|
cmdline_parse_token_num_t cmd_arp_del_out_iface =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_arp_del_result, out_iface, UINT8);
|
|
|
|
cmdline_parse_token_ipaddr_t cmd_arp_del_nh_ip =
|
|
TOKEN_IPADDR_INITIALIZER(struct cmd_arp_del_result, nh_ip);
|
|
|
|
cmdline_parse_inst_t cmd_arp_del = {
|
|
.f = cmd_arp_del_parsed,
|
|
.data = NULL,
|
|
.help_str = "ARP delete",
|
|
.tokens = {
|
|
(void *)&cmd_arp_del_arp_string,
|
|
(void *)&cmd_arp_del_del_string,
|
|
(void *)&cmd_arp_del_out_iface,
|
|
(void *)&cmd_arp_del_nh_ip,
|
|
NULL,
|
|
},
|
|
};
|
|
|
|
/* *** ARP - Print *** */
|
|
struct cmd_arp_print_result {
|
|
cmdline_fixed_string_t arp_string;
|
|
cmdline_fixed_string_t print_string;
|
|
};
|
|
|
|
static void
|
|
cmd_arp_print_parsed(
|
|
__attribute__((unused)) void *parsed_result,
|
|
__attribute__((unused)) struct cmdline *cl,
|
|
__attribute__((unused)) void *data)
|
|
{
|
|
struct app_rule *it;
|
|
|
|
TAILQ_FOREACH(it, &arp_table, entries) {
|
|
print_arp_rule(it->arp);
|
|
}
|
|
}
|
|
|
|
cmdline_parse_token_string_t cmd_arp_print_arp_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_arp_print_result, arp_string,
|
|
"arp");
|
|
|
|
cmdline_parse_token_string_t cmd_arp_print_print_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_arp_print_result, print_string,
|
|
"ls");
|
|
|
|
cmdline_parse_inst_t cmd_arp_print = {
|
|
.f = cmd_arp_print_parsed,
|
|
.data = NULL,
|
|
.help_str = "ARP list",
|
|
.tokens = {
|
|
(void *)&cmd_arp_print_arp_string,
|
|
(void *)&cmd_arp_print_print_string,
|
|
NULL,
|
|
},
|
|
};
|
|
|
|
/* *** Routing - Add *** */
|
|
struct cmd_route_add_result {
|
|
cmdline_fixed_string_t route_string;
|
|
cmdline_fixed_string_t add_string;
|
|
cmdline_ipaddr_t ip;
|
|
uint8_t depth;
|
|
uint8_t port;
|
|
cmdline_ipaddr_t nh_ip;
|
|
};
|
|
|
|
static void
|
|
cmd_route_add_parsed(
|
|
void *parsed_result,
|
|
__attribute__((unused)) struct cmdline *cl,
|
|
__attribute__((unused)) void *data)
|
|
{
|
|
struct cmd_route_add_result *params = parsed_result;
|
|
struct app_rule rule, *old_rule;
|
|
struct app_msg_req *req;
|
|
struct app_msg_resp *resp;
|
|
void *msg;
|
|
int status;
|
|
|
|
uint32_t core_id = app_get_first_core_id(APP_CORE_RT);
|
|
|
|
if (core_id == RTE_MAX_LCORE) {
|
|
printf("Routing not performed by any CPU core\n");
|
|
return;
|
|
}
|
|
|
|
struct rte_ring *ring_req = app_get_ring_req(core_id);
|
|
struct rte_ring *ring_resp = app_get_ring_resp(core_id);
|
|
|
|
/* Check params */
|
|
if ((params->depth == 0) || (params->depth > 32)) {
|
|
printf("Illegal value for depth parameter (%u)\n",
|
|
params->depth);
|
|
return;
|
|
}
|
|
|
|
if (params->port >= app.n_ports) {
|
|
printf("Illegal value for port parameter (%u)\n", params->port);
|
|
return;
|
|
}
|
|
|
|
/* Create rule */
|
|
memset(&rule, 0, sizeof(rule));
|
|
rule.routing.key.ip = rte_bswap32((uint32_t)
|
|
params->ip.addr.ipv4.s_addr);
|
|
rule.routing.key.depth = params->depth;
|
|
rule.routing.port = params->port;
|
|
rule.routing.nh_ip =
|
|
rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr);
|
|
|
|
/* Check rule existence */
|
|
IS_RULE_PRESENT(old_rule, rule.routing.key, routing_table, routing);
|
|
if ((old_rule == NULL) && (n_routing_rules == app.max_routing_rules)) {
|
|
printf("Routing table is full.\n");
|
|
return;
|
|
}
|
|
|
|
printf("Adding route: ");
|
|
print_routing_rule(rule.routing);
|
|
|
|
/* Allocate message buffer */
|
|
msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
|
|
if (msg == NULL)
|
|
rte_panic("Unable to allocate new message\n");
|
|
|
|
/* Fill request message */
|
|
req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
|
|
req->type = APP_MSG_REQ_RT_ADD;
|
|
req->routing_add.ip = rule.routing.key.ip;
|
|
req->routing_add.depth = rule.routing.key.depth;
|
|
req->routing_add.port = rule.routing.port;
|
|
req->routing_add.nh_ip = rule.routing.nh_ip;
|
|
|
|
/* Send request */
|
|
do {
|
|
status = rte_ring_sp_enqueue(ring_req, msg);
|
|
} while (status == -ENOBUFS);
|
|
|
|
/* Wait for response */
|
|
do {
|
|
status = rte_ring_sc_dequeue(ring_resp, &msg);
|
|
} while (status != 0);
|
|
resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
|
|
|
|
/* Check response */
|
|
if (resp->result != 0)
|
|
printf("Request ROUTE_ADD failed (%u)\n", resp->result);
|
|
else {
|
|
if (old_rule == NULL) {
|
|
struct app_rule *new_rule = (struct app_rule *)
|
|
rte_zmalloc_socket("CLI",
|
|
sizeof(struct app_rule),
|
|
RTE_CACHE_LINE_SIZE,
|
|
rte_socket_id());
|
|
|
|
if (new_rule == NULL)
|
|
rte_panic("Unable to allocate new rule\n");
|
|
|
|
memcpy(new_rule, &rule, sizeof(rule));
|
|
TAILQ_INSERT_TAIL(&routing_table, new_rule, entries);
|
|
n_routing_rules++;
|
|
} else {
|
|
old_rule->routing.port = rule.routing.port;
|
|
old_rule->routing.nh_ip = rule.routing.nh_ip;
|
|
}
|
|
}
|
|
|
|
/* Free message buffer */
|
|
rte_ctrlmbuf_free((struct rte_mbuf *) msg);
|
|
}
|
|
|
|
cmdline_parse_token_string_t cmd_route_add_route_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_route_add_result, route_string,
|
|
"route");
|
|
|
|
cmdline_parse_token_string_t cmd_route_add_add_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_route_add_result, add_string,
|
|
"add");
|
|
|
|
cmdline_parse_token_ipaddr_t cmd_route_add_ip =
|
|
TOKEN_IPADDR_INITIALIZER(struct cmd_route_add_result, ip);
|
|
|
|
cmdline_parse_token_num_t cmd_route_add_depth =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_route_add_result, depth, UINT8);
|
|
|
|
cmdline_parse_token_num_t cmd_route_add_port =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_route_add_result, port, UINT8);
|
|
|
|
cmdline_parse_token_ipaddr_t cmd_route_add_nh_ip =
|
|
TOKEN_IPADDR_INITIALIZER(struct cmd_route_add_result, nh_ip);
|
|
|
|
cmdline_parse_inst_t cmd_route_add = {
|
|
.f = cmd_route_add_parsed,
|
|
.data = NULL,
|
|
.help_str = "Route add",
|
|
.tokens = {
|
|
(void *)&cmd_route_add_route_string,
|
|
(void *)&cmd_route_add_add_string,
|
|
(void *)&cmd_route_add_ip,
|
|
(void *)&cmd_route_add_depth,
|
|
(void *)&cmd_route_add_port,
|
|
(void *)&cmd_route_add_nh_ip,
|
|
NULL,
|
|
},
|
|
};
|
|
|
|
/* *** Routing - Del *** */
|
|
struct cmd_route_del_result {
|
|
cmdline_fixed_string_t route_string;
|
|
cmdline_fixed_string_t del_string;
|
|
cmdline_ipaddr_t ip;
|
|
uint8_t depth;
|
|
};
|
|
|
|
static void
|
|
cmd_route_del_parsed(
|
|
void *parsed_result,
|
|
__attribute__((unused)) struct cmdline *cl,
|
|
__attribute__((unused)) void *data)
|
|
{
|
|
struct cmd_route_del_result *params = parsed_result;
|
|
struct app_rule rule, *old_rule;
|
|
struct app_msg_req *req;
|
|
struct app_msg_resp *resp;
|
|
void *msg;
|
|
int status;
|
|
|
|
uint32_t core_id = app_get_first_core_id(APP_CORE_RT);
|
|
|
|
if (core_id == RTE_MAX_LCORE) {
|
|
printf("Routing not performed by any CPU core\n");
|
|
return;
|
|
}
|
|
|
|
struct rte_ring *ring_req = app_get_ring_req(core_id);
|
|
struct rte_ring *ring_resp = app_get_ring_resp(core_id);
|
|
|
|
/* Check params */
|
|
if ((params->depth == 0) || (params->depth > 32)) {
|
|
printf("Illegal value for depth parameter (%u)\n",
|
|
params->depth);
|
|
return;
|
|
}
|
|
|
|
/* Create rule */
|
|
memset(&rule, 0, sizeof(rule));
|
|
rule.routing.key.ip = rte_bswap32((uint32_t)
|
|
params->ip.addr.ipv4.s_addr);
|
|
rule.routing.key.depth = params->depth;
|
|
|
|
/* Check rule existence */
|
|
IS_RULE_PRESENT(old_rule, rule.routing.key, routing_table, routing);
|
|
if (old_rule == NULL)
|
|
return;
|
|
|
|
printf("Deleting route: ");
|
|
print_routing_rule(old_rule->routing);
|
|
|
|
/* Allocate message buffer */
|
|
msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
|
|
if (msg == NULL)
|
|
rte_panic("Unable to allocate new message\n");
|
|
|
|
/* Fill request message */
|
|
req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
|
|
req->type = APP_MSG_REQ_RT_DEL;
|
|
req->routing_del.ip = rule.routing.key.ip;
|
|
req->routing_del.depth = rule.routing.key.depth;
|
|
|
|
/* Send request */
|
|
do {
|
|
status = rte_ring_sp_enqueue(ring_req, msg);
|
|
} while (status == -ENOBUFS);
|
|
|
|
/* Wait for response */
|
|
do {
|
|
status = rte_ring_sc_dequeue(ring_resp, &msg);
|
|
} while (status != 0);
|
|
resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
|
|
|
|
/* Check response */
|
|
if (resp->result != 0)
|
|
printf("Request ROUTE_DEL failed %u)\n", resp->result);
|
|
else {
|
|
TAILQ_REMOVE(&routing_table, old_rule, entries);
|
|
rte_free(old_rule);
|
|
n_routing_rules--;
|
|
}
|
|
|
|
/* Free message buffer */
|
|
rte_ctrlmbuf_free((struct rte_mbuf *)msg);
|
|
}
|
|
|
|
cmdline_parse_token_string_t cmd_route_del_route_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_route_del_result, route_string,
|
|
"route");
|
|
|
|
cmdline_parse_token_string_t cmd_route_del_del_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_route_del_result, del_string,
|
|
"del");
|
|
|
|
cmdline_parse_token_ipaddr_t cmd_route_del_ip =
|
|
TOKEN_IPADDR_INITIALIZER(struct cmd_route_del_result, ip);
|
|
|
|
cmdline_parse_token_num_t cmd_route_del_depth =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_route_del_result, depth, UINT8);
|
|
|
|
cmdline_parse_inst_t cmd_route_del = {
|
|
.f = cmd_route_del_parsed,
|
|
.data = NULL,
|
|
.help_str = "Route delete",
|
|
.tokens = {
|
|
(void *)&cmd_route_del_route_string,
|
|
(void *)&cmd_route_del_del_string,
|
|
(void *)&cmd_route_del_ip,
|
|
(void *)&cmd_route_del_depth,
|
|
NULL,
|
|
},
|
|
};
|
|
|
|
/* *** Routing - Print *** */
|
|
struct cmd_routing_print_result {
|
|
cmdline_fixed_string_t routing_string;
|
|
cmdline_fixed_string_t print_string;
|
|
};
|
|
|
|
static void
|
|
cmd_routing_print_parsed(
|
|
__attribute__((unused)) void *parsed_result,
|
|
__attribute__((unused)) struct cmdline *cl,
|
|
__attribute__((unused)) void *data)
|
|
{
|
|
struct app_rule *it;
|
|
|
|
TAILQ_FOREACH(it, &routing_table, entries) {
|
|
print_routing_rule(it->routing);
|
|
}
|
|
}
|
|
|
|
cmdline_parse_token_string_t cmd_routing_print_routing_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_routing_print_result,
|
|
routing_string, "route");
|
|
|
|
cmdline_parse_token_string_t cmd_routing_print_print_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_routing_print_result, print_string,
|
|
"ls");
|
|
|
|
cmdline_parse_inst_t cmd_routing_print = {
|
|
.f = cmd_routing_print_parsed,
|
|
.data = NULL,
|
|
.help_str = "Route list",
|
|
.tokens = {
|
|
(void *)&cmd_routing_print_routing_string,
|
|
(void *)&cmd_routing_print_print_string,
|
|
NULL,
|
|
},
|
|
};
|
|
|
|
#ifdef RTE_LIBRTE_ACL
|
|
|
|
/* *** Firewall - Add *** */
|
|
struct cmd_firewall_add_result {
|
|
cmdline_fixed_string_t firewall_string;
|
|
cmdline_fixed_string_t add_string;
|
|
int32_t priority;
|
|
cmdline_ipaddr_t src_ip;
|
|
uint32_t src_ip_mask;
|
|
cmdline_ipaddr_t dst_ip;
|
|
uint32_t dst_ip_mask;
|
|
uint16_t src_port_from;
|
|
uint16_t src_port_to;
|
|
uint16_t dst_port_from;
|
|
uint16_t dst_port_to;
|
|
uint8_t proto;
|
|
uint8_t proto_mask;
|
|
uint8_t port;
|
|
};
|
|
|
|
static void
|
|
cmd_firewall_add_parsed(
|
|
void *parsed_result,
|
|
__attribute__((unused)) struct cmdline *cl,
|
|
__attribute__((unused)) void *data)
|
|
{
|
|
struct cmd_firewall_add_result *params = parsed_result;
|
|
struct app_rule rule, *old_rule, *new_rule = NULL;
|
|
struct rte_mbuf *msg;
|
|
struct app_msg_req *req;
|
|
struct app_msg_resp *resp;
|
|
int status;
|
|
|
|
uint32_t core_id = app_get_first_core_id(APP_CORE_FW);
|
|
|
|
if (core_id == RTE_MAX_LCORE) {
|
|
printf("Firewall not performed by any CPU core\n");
|
|
return;
|
|
}
|
|
|
|
struct rte_ring *ring_req = app_get_ring_req(core_id);
|
|
struct rte_ring *ring_resp = app_get_ring_resp(core_id);
|
|
|
|
/* Check params */
|
|
if (params->port >= app.n_ports) {
|
|
printf("Illegal value for port parameter (%u)\n", params->port);
|
|
return;
|
|
}
|
|
|
|
/* Create rule */
|
|
memset(&rule, 0, sizeof(rule));
|
|
rule.firewall.priority = params->priority;
|
|
rule.firewall.key.src_ip =
|
|
rte_bswap32((uint32_t)params->src_ip.addr.ipv4.s_addr);
|
|
rule.firewall.key.src_ip_mask = params->src_ip_mask;
|
|
rule.firewall.key.dst_ip =
|
|
rte_bswap32((uint32_t)params->dst_ip.addr.ipv4.s_addr);
|
|
rule.firewall.key.dst_ip_mask = params->dst_ip_mask;
|
|
rule.firewall.key.src_port_from = params->src_port_from;
|
|
rule.firewall.key.src_port_to = params->src_port_to;
|
|
rule.firewall.key.dst_port_from = params->dst_port_from;
|
|
rule.firewall.key.dst_port_to = params->dst_port_to;
|
|
rule.firewall.key.proto = params->proto;
|
|
rule.firewall.key.proto_mask = params->proto_mask;
|
|
rule.firewall.port = params->port;
|
|
|
|
/* Check rule existence */
|
|
IS_RULE_PRESENT(old_rule, rule.firewall.key, firewall_table, firewall);
|
|
if ((old_rule == NULL) &&
|
|
(n_firewall_rules == app.max_firewall_rules)) {
|
|
printf("Firewall table is full.\n");
|
|
return;
|
|
}
|
|
|
|
printf("Adding firewall rule: ");
|
|
print_firewall_rule(rule.firewall);
|
|
|
|
/* Allocate message buffer */
|
|
msg = rte_ctrlmbuf_alloc(app.msg_pool);
|
|
if (msg == NULL)
|
|
rte_panic("Unable to allocate new message\n");
|
|
|
|
/* if we need a new rule structure, allocate it before we go further */
|
|
if (old_rule == NULL) {
|
|
new_rule = rte_zmalloc_socket("CLI", sizeof(struct app_rule),
|
|
RTE_CACHE_LINE_SIZE, rte_socket_id());
|
|
if (new_rule == NULL) {
|
|
printf("Cannot allocate memory for new rule\n");
|
|
rte_ctrlmbuf_free(msg);
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
/* Fill request message */
|
|
req = (struct app_msg_req *)rte_ctrlmbuf_data(msg);
|
|
req->type = APP_MSG_REQ_FW_ADD;
|
|
req->firewall_add.add_params.priority = rule.firewall.priority;
|
|
req->firewall_add.add_params.field_value[1].value.u32 =
|
|
rule.firewall.key.src_ip;
|
|
req->firewall_add.add_params.field_value[1].mask_range.u32 =
|
|
rule.firewall.key.src_ip_mask;
|
|
req->firewall_add.add_params.field_value[2].value.u32 =
|
|
rule.firewall.key.dst_ip;
|
|
req->firewall_add.add_params.field_value[2].mask_range.u32 =
|
|
rule.firewall.key.dst_ip_mask;
|
|
req->firewall_add.add_params.field_value[3].value.u16 =
|
|
rule.firewall.key.src_port_from;
|
|
req->firewall_add.add_params.field_value[3].mask_range.u16 =
|
|
rule.firewall.key.src_port_to;
|
|
req->firewall_add.add_params.field_value[4].value.u16 =
|
|
rule.firewall.key.dst_port_from;
|
|
req->firewall_add.add_params.field_value[4].mask_range.u16 =
|
|
rule.firewall.key.dst_port_to;
|
|
req->firewall_add.add_params.field_value[0].value.u8 =
|
|
rule.firewall.key.proto;
|
|
req->firewall_add.add_params.field_value[0].mask_range.u8 =
|
|
rule.firewall.key.proto_mask;
|
|
req->firewall_add.port = rule.firewall.port;
|
|
|
|
/* Send request */
|
|
do {
|
|
status = rte_ring_sp_enqueue(ring_req, (void *) msg);
|
|
} while (status == -ENOBUFS);
|
|
|
|
/* Wait for response */
|
|
do {
|
|
status = rte_ring_sc_dequeue(ring_resp, (void **) &msg);
|
|
} while (status != 0);
|
|
resp = (struct app_msg_resp *)rte_ctrlmbuf_data(msg);
|
|
|
|
/* Check response */
|
|
if (resp->result != 0)
|
|
printf("Request FIREWALL_ADD failed (%u)\n", resp->result);
|
|
else {
|
|
if (old_rule == NULL) {
|
|
memcpy(new_rule, &rule, sizeof(rule));
|
|
TAILQ_INSERT_TAIL(&firewall_table, new_rule, entries);
|
|
n_firewall_rules++;
|
|
} else {
|
|
old_rule->firewall.priority = rule.firewall.priority;
|
|
old_rule->firewall.port = rule.firewall.port;
|
|
}
|
|
}
|
|
|
|
/* Free message buffer */
|
|
rte_ctrlmbuf_free(msg);
|
|
}
|
|
|
|
cmdline_parse_token_string_t cmd_firewall_add_firewall_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_result,
|
|
firewall_string, "firewall");
|
|
|
|
cmdline_parse_token_string_t cmd_firewall_add_add_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_result, add_string,
|
|
"add");
|
|
|
|
cmdline_parse_token_num_t cmd_firewall_add_priority =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, priority, INT32);
|
|
|
|
cmdline_parse_token_ipaddr_t cmd_firewall_add_src_ip =
|
|
TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_add_result, src_ip);
|
|
cmdline_parse_token_num_t cmd_firewall_add_src_ip_mask =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, src_ip_mask,
|
|
UINT32);
|
|
|
|
cmdline_parse_token_ipaddr_t cmd_firewall_add_dst_ip =
|
|
TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_add_result, dst_ip);
|
|
cmdline_parse_token_num_t cmd_firewall_add_dst_ip_mask =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, dst_ip_mask,
|
|
UINT32);
|
|
|
|
cmdline_parse_token_num_t cmd_firewall_add_src_port_from =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, src_port_from,
|
|
UINT16);
|
|
cmdline_parse_token_num_t cmd_firewall_add_src_port_to =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, src_port_to,
|
|
UINT16);
|
|
|
|
cmdline_parse_token_num_t cmd_firewall_add_dst_port_from =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, dst_port_from,
|
|
UINT16);
|
|
cmdline_parse_token_num_t cmd_firewall_add_dst_port_to =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, dst_port_to,
|
|
UINT16);
|
|
|
|
cmdline_parse_token_num_t cmd_firewall_add_proto =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, proto, UINT8);
|
|
cmdline_parse_token_num_t cmd_firewall_add_proto_mask =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, proto_mask,
|
|
UINT8);
|
|
cmdline_parse_token_num_t cmd_firewall_add_port =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, port, UINT8);
|
|
|
|
cmdline_parse_inst_t cmd_firewall_add = {
|
|
.f = cmd_firewall_add_parsed,
|
|
.data = NULL,
|
|
.help_str = "Firewall rule add",
|
|
.tokens = {
|
|
(void *)&cmd_firewall_add_firewall_string,
|
|
(void *)&cmd_firewall_add_add_string,
|
|
(void *)&cmd_firewall_add_priority,
|
|
(void *)&cmd_firewall_add_src_ip,
|
|
(void *)&cmd_firewall_add_src_ip_mask,
|
|
(void *)&cmd_firewall_add_dst_ip,
|
|
(void *)&cmd_firewall_add_dst_ip_mask,
|
|
(void *)&cmd_firewall_add_src_port_from,
|
|
(void *)&cmd_firewall_add_src_port_to,
|
|
(void *)&cmd_firewall_add_dst_port_from,
|
|
(void *)&cmd_firewall_add_dst_port_to,
|
|
(void *)&cmd_firewall_add_proto,
|
|
(void *)&cmd_firewall_add_proto_mask,
|
|
(void *)&cmd_firewall_add_port,
|
|
NULL,
|
|
},
|
|
};
|
|
|
|
/* *** firewall - Del *** */
|
|
struct cmd_firewall_del_result {
|
|
cmdline_fixed_string_t firewall_string;
|
|
cmdline_fixed_string_t del_string;
|
|
cmdline_ipaddr_t src_ip;
|
|
uint32_t src_ip_mask;
|
|
cmdline_ipaddr_t dst_ip;
|
|
uint32_t dst_ip_mask;
|
|
uint16_t src_port_from;
|
|
uint16_t src_port_to;
|
|
uint16_t dst_port_from;
|
|
uint16_t dst_port_to;
|
|
uint8_t proto;
|
|
uint8_t proto_mask;
|
|
};
|
|
|
|
static void
|
|
cmd_firewall_del_parsed(
|
|
void *parsed_result,
|
|
__attribute__((unused)) struct cmdline *cl,
|
|
__attribute__((unused)) void *data)
|
|
{
|
|
struct cmd_firewall_del_result *params = parsed_result;
|
|
struct app_rule rule, *old_rule;
|
|
struct rte_mbuf *msg;
|
|
struct app_msg_req *req;
|
|
struct app_msg_resp *resp;
|
|
int status;
|
|
|
|
uint32_t core_id = app_get_first_core_id(APP_CORE_FW);
|
|
|
|
if (core_id == RTE_MAX_LCORE) {
|
|
printf("Firewall not performed by any CPU core\n");
|
|
return;
|
|
}
|
|
|
|
struct rte_ring *ring_req = app_get_ring_req(core_id);
|
|
struct rte_ring *ring_resp = app_get_ring_resp(core_id);
|
|
|
|
/* Check params */
|
|
|
|
/* Create rule */
|
|
memset(&rule, 0, sizeof(rule));
|
|
rule.firewall.key.src_ip =
|
|
rte_bswap32((uint32_t) params->src_ip.addr.ipv4.s_addr);
|
|
rule.firewall.key.src_ip_mask = params->src_ip_mask;
|
|
rule.firewall.key.dst_ip =
|
|
rte_bswap32((uint32_t) params->dst_ip.addr.ipv4.s_addr);
|
|
rule.firewall.key.dst_ip_mask = params->dst_ip_mask;
|
|
rule.firewall.key.src_port_from = params->src_port_from;
|
|
rule.firewall.key.src_port_to = params->src_port_to;
|
|
rule.firewall.key.dst_port_from = params->dst_port_from;
|
|
rule.firewall.key.dst_port_to = params->dst_port_to;
|
|
rule.firewall.key.proto = params->proto;
|
|
rule.firewall.key.proto_mask = params->proto_mask;
|
|
|
|
/* Check rule existence */
|
|
IS_RULE_PRESENT(old_rule, rule.firewall.key, firewall_table, firewall);
|
|
if (old_rule == NULL)
|
|
return;
|
|
|
|
printf("Deleting firewall rule: ");
|
|
print_firewall_rule(old_rule->firewall);
|
|
|
|
/* Allocate message buffer */
|
|
msg = rte_ctrlmbuf_alloc(app.msg_pool);
|
|
if (msg == NULL)
|
|
rte_panic("Unable to allocate new message\n");
|
|
|
|
/* Fill request message */
|
|
req = (struct app_msg_req *)rte_ctrlmbuf_data(msg);
|
|
memset(&req->firewall_del, 0, sizeof(req->firewall_del));
|
|
req->type = APP_MSG_REQ_FW_DEL;
|
|
req->firewall_del.delete_params.field_value[1].value.u32 =
|
|
rule.firewall.key.src_ip;
|
|
req->firewall_del.delete_params.field_value[1].mask_range.u32 =
|
|
rule.firewall.key.src_ip_mask;
|
|
req->firewall_del.delete_params.field_value[2].value.u32 =
|
|
rule.firewall.key.dst_ip;
|
|
req->firewall_del.delete_params.field_value[2].mask_range.u32 =
|
|
rule.firewall.key.dst_ip_mask;
|
|
req->firewall_del.delete_params.field_value[3].value.u16 =
|
|
rule.firewall.key.src_port_from;
|
|
req->firewall_del.delete_params.field_value[3].mask_range.u16 =
|
|
rule.firewall.key.src_port_to;
|
|
req->firewall_del.delete_params.field_value[4].value.u16 =
|
|
rule.firewall.key.dst_port_from;
|
|
req->firewall_del.delete_params.field_value[4].mask_range.u16 =
|
|
rule.firewall.key.dst_port_to;
|
|
req->firewall_del.delete_params.field_value[0].value.u8 =
|
|
rule.firewall.key.proto;
|
|
req->firewall_del.delete_params.field_value[0].mask_range.u8 =
|
|
rule.firewall.key.proto_mask;
|
|
|
|
/* Send request */
|
|
do {
|
|
status = rte_ring_sp_enqueue(ring_req, (void *) msg);
|
|
} while (status == -ENOBUFS);
|
|
|
|
/* Wait for response */
|
|
do {
|
|
status = rte_ring_sc_dequeue(ring_resp, (void **) &msg);
|
|
} while (status != 0);
|
|
resp = (struct app_msg_resp *)rte_ctrlmbuf_data(msg);
|
|
|
|
/* Check response */
|
|
if (resp->result != 0)
|
|
printf("Request FIREWALL_DEL failed %u)\n", resp->result);
|
|
else {
|
|
TAILQ_REMOVE(&firewall_table, old_rule, entries);
|
|
rte_free(old_rule);
|
|
n_firewall_rules--;
|
|
}
|
|
|
|
/* Free message buffer */
|
|
rte_ctrlmbuf_free(msg);
|
|
}
|
|
|
|
cmdline_parse_token_string_t cmd_firewall_del_firewall_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_result,
|
|
firewall_string, "firewall");
|
|
|
|
cmdline_parse_token_string_t cmd_firewall_del_del_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_result, del_string,
|
|
"del");
|
|
|
|
cmdline_parse_token_ipaddr_t cmd_firewall_del_src_ip =
|
|
TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_del_result, src_ip);
|
|
cmdline_parse_token_num_t cmd_firewall_del_src_ip_mask =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, src_ip_mask,
|
|
UINT32);
|
|
|
|
cmdline_parse_token_ipaddr_t cmd_firewall_del_dst_ip =
|
|
TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_del_result, dst_ip);
|
|
cmdline_parse_token_num_t cmd_firewall_del_dst_ip_mask =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, dst_ip_mask,
|
|
UINT32);
|
|
|
|
cmdline_parse_token_num_t cmd_firewall_del_src_port_from =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, src_port_from,
|
|
UINT16);
|
|
cmdline_parse_token_num_t cmd_firewall_del_src_port_to =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, src_port_to,
|
|
UINT16);
|
|
|
|
cmdline_parse_token_num_t cmd_firewall_del_dst_port_from =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, dst_port_from,
|
|
UINT16);
|
|
cmdline_parse_token_num_t cmd_firewall_del_dst_port_to =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, dst_port_to,
|
|
UINT16);
|
|
|
|
cmdline_parse_token_num_t cmd_firewall_del_proto =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, proto, UINT8);
|
|
cmdline_parse_token_num_t cmd_firewall_del_proto_mask =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, proto_mask,
|
|
UINT8);
|
|
|
|
cmdline_parse_inst_t cmd_firewall_del = {
|
|
.f = cmd_firewall_del_parsed,
|
|
.data = NULL,
|
|
.help_str = "Firewall rule delete",
|
|
.tokens = {
|
|
(void *)&cmd_firewall_del_firewall_string,
|
|
(void *)&cmd_firewall_del_del_string,
|
|
(void *)&cmd_firewall_del_src_ip,
|
|
(void *)&cmd_firewall_del_src_ip_mask,
|
|
(void *)&cmd_firewall_del_dst_ip,
|
|
(void *)&cmd_firewall_del_dst_ip_mask,
|
|
(void *)&cmd_firewall_del_src_port_from,
|
|
(void *)&cmd_firewall_del_src_port_to,
|
|
(void *)&cmd_firewall_del_dst_port_from,
|
|
(void *)&cmd_firewall_del_dst_port_to,
|
|
(void *)&cmd_firewall_del_proto,
|
|
(void *)&cmd_firewall_del_proto_mask,
|
|
NULL,
|
|
},
|
|
};
|
|
|
|
/* *** Firewall - Print *** */
|
|
struct cmd_firewall_print_result {
|
|
cmdline_fixed_string_t firewall_string;
|
|
cmdline_fixed_string_t print_string;
|
|
};
|
|
|
|
static void
|
|
cmd_firewall_print_parsed(
|
|
__attribute__((unused)) void *parsed_result,
|
|
__attribute__((unused)) struct cmdline *cl,
|
|
__attribute__((unused)) void *data)
|
|
{
|
|
struct app_rule *it;
|
|
|
|
TAILQ_FOREACH(it, &firewall_table, entries) {
|
|
print_firewall_rule(it->firewall);
|
|
}
|
|
}
|
|
|
|
cmdline_parse_token_string_t cmd_firewall_print_firewall_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_firewall_print_result,
|
|
firewall_string, "firewall");
|
|
|
|
cmdline_parse_token_string_t cmd_firewall_print_print_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_firewall_print_result, print_string,
|
|
"ls");
|
|
|
|
cmdline_parse_inst_t cmd_firewall_print = {
|
|
.f = cmd_firewall_print_parsed,
|
|
.data = NULL,
|
|
.help_str = "Firewall rules list",
|
|
.tokens = {
|
|
(void *)&cmd_firewall_print_firewall_string,
|
|
(void *)&cmd_firewall_print_print_string,
|
|
NULL,
|
|
},
|
|
};
|
|
|
|
#endif
|
|
|
|
/* *** Flow Classification - Add All *** */
|
|
struct cmd_flow_add_all_result {
|
|
cmdline_fixed_string_t flow_string;
|
|
cmdline_fixed_string_t add_string;
|
|
cmdline_fixed_string_t all_string;
|
|
};
|
|
|
|
static void
|
|
cmd_flow_add_all_parsed(
|
|
__attribute__((unused)) void *parsed_result,
|
|
__attribute__((unused)) struct cmdline *cl,
|
|
__attribute__((unused)) void *data)
|
|
{
|
|
struct app_msg_req *req;
|
|
struct app_msg_resp *resp;
|
|
void *msg;
|
|
int status;
|
|
|
|
struct rte_ring *ring_req =
|
|
app_get_ring_req(app_get_first_core_id(APP_CORE_FC));
|
|
struct rte_ring *ring_resp =
|
|
app_get_ring_resp(app_get_first_core_id(APP_CORE_FC));
|
|
|
|
/* Allocate message buffer */
|
|
msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
|
|
if (msg == NULL)
|
|
rte_panic("Unable to allocate new message\n");
|
|
|
|
/* Fill request message */
|
|
req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
|
|
memset(req, 0, sizeof(struct app_msg_req));
|
|
|
|
req->type = APP_MSG_REQ_FC_ADD_ALL;
|
|
|
|
/* Send request */
|
|
do {
|
|
status = rte_ring_sp_enqueue(ring_req, msg);
|
|
} while (status == -ENOBUFS);
|
|
|
|
/* Wait for response */
|
|
do {
|
|
status = rte_ring_sc_dequeue(ring_resp, &msg);
|
|
} while (status != 0);
|
|
resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
|
|
|
|
/* Check response */
|
|
if (resp->result != 0)
|
|
printf("Request FLOW_ADD_ALL failed (%u)\n", resp->result);
|
|
|
|
/* Free message buffer */
|
|
rte_ctrlmbuf_free((struct rte_mbuf *)msg);
|
|
}
|
|
|
|
cmdline_parse_token_string_t cmd_flow_add_all_flow_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_flow_add_all_result, flow_string,
|
|
"flow");
|
|
|
|
cmdline_parse_token_string_t cmd_flow_add_all_add_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_flow_add_all_result, add_string,
|
|
"add");
|
|
|
|
cmdline_parse_token_string_t cmd_flow_add_all_all_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_flow_add_all_result, all_string,
|
|
"all");
|
|
|
|
cmdline_parse_inst_t cmd_flow_add_all = {
|
|
.f = cmd_flow_add_all_parsed,
|
|
.data = NULL,
|
|
.help_str = "Flow table initialization based on hard-coded rule",
|
|
.tokens = {
|
|
(void *)&cmd_flow_add_all_flow_string,
|
|
(void *)&cmd_flow_add_all_add_string,
|
|
(void *)&cmd_flow_add_all_all_string,
|
|
NULL,
|
|
},
|
|
};
|
|
|
|
/* *** Flow Classification - Add *** */
|
|
struct cmd_flow_add_result {
|
|
cmdline_fixed_string_t flow_string;
|
|
cmdline_fixed_string_t add_string;
|
|
cmdline_ipaddr_t src_ip;
|
|
cmdline_ipaddr_t dst_ip;
|
|
uint16_t src_port;
|
|
uint16_t dst_port;
|
|
uint8_t proto;
|
|
uint8_t port;
|
|
};
|
|
|
|
static void
|
|
cmd_flow_add_parsed(
|
|
void *parsed_result,
|
|
__attribute__((unused)) struct cmdline *cl,
|
|
__attribute__((unused)) void *data)
|
|
{
|
|
struct cmd_flow_add_result *params = parsed_result;
|
|
struct app_rule rule, *old_rule;
|
|
struct app_msg_req *req;
|
|
struct app_msg_resp *resp;
|
|
void *msg;
|
|
int status;
|
|
|
|
uint32_t core_id = app_get_first_core_id(APP_CORE_FC);
|
|
|
|
if (core_id == RTE_MAX_LCORE) {
|
|
printf("Flow classification not performed by any CPU core\n");
|
|
return;
|
|
}
|
|
|
|
struct rte_ring *ring_req = app_get_ring_req(core_id);
|
|
struct rte_ring *ring_resp = app_get_ring_resp(core_id);
|
|
|
|
/* Check params */
|
|
if (params->port >= app.n_ports) {
|
|
printf("Illegal value for port parameter (%u)\n", params->port);
|
|
return;
|
|
}
|
|
|
|
/* Create rule */
|
|
memset(&rule, 0, sizeof(rule));
|
|
rule.flow.key.src_ip =
|
|
rte_bswap32((uint32_t)params->src_ip.addr.ipv4.s_addr);
|
|
rule.flow.key.dst_ip =
|
|
rte_bswap32((uint32_t)params->dst_ip.addr.ipv4.s_addr);
|
|
rule.flow.key.src_port = params->src_port;
|
|
rule.flow.key.dst_port = params->dst_port;
|
|
rule.flow.key.proto = params->proto;
|
|
rule.flow.port = params->port;
|
|
|
|
/* Check rule existence */
|
|
IS_RULE_PRESENT(old_rule, rule.flow.key, flow_table, flow);
|
|
if ((old_rule == NULL) && (n_flow_rules == app.max_flow_rules)) {
|
|
printf("Flow table is full.\n");
|
|
return;
|
|
}
|
|
|
|
printf("Adding flow: ");
|
|
print_flow_rule(rule.flow);
|
|
|
|
/* Allocate message buffer */
|
|
msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
|
|
if (msg == NULL)
|
|
rte_panic("Unable to allocate new message\n");
|
|
|
|
/* Fill request message */
|
|
req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
|
|
memset(req, 0, sizeof(struct app_msg_req));
|
|
|
|
req->type = APP_MSG_REQ_FC_ADD;
|
|
req->flow_classif_add.key.ip_src = rte_bswap32(rule.flow.key.src_ip);
|
|
req->flow_classif_add.key.ip_dst = rte_bswap32(rule.flow.key.dst_ip);
|
|
req->flow_classif_add.key.port_src =
|
|
rte_bswap16(rule.flow.key.src_port);
|
|
req->flow_classif_add.key.port_dst =
|
|
rte_bswap16(rule.flow.key.dst_port);
|
|
req->flow_classif_add.key.proto = rule.flow.key.proto;
|
|
req->flow_classif_add.port = rule.flow.port;
|
|
|
|
/* Send request */
|
|
do {
|
|
status = rte_ring_sp_enqueue(ring_req, msg);
|
|
} while (status == -ENOBUFS);
|
|
|
|
/* Wait for response */
|
|
do {
|
|
status = rte_ring_sc_dequeue(ring_resp, &msg);
|
|
} while (status != 0);
|
|
resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
|
|
|
|
/* Check response */
|
|
if (resp->result != 0)
|
|
printf("Request FLOW_ADD failed (%u)\n", resp->result);
|
|
else {
|
|
if (old_rule == NULL) {
|
|
struct app_rule *new_rule = (struct app_rule *)
|
|
rte_zmalloc_socket("CLI",
|
|
sizeof(struct app_rule),
|
|
RTE_CACHE_LINE_SIZE,
|
|
rte_socket_id());
|
|
|
|
if (new_rule == NULL)
|
|
rte_panic("Unable to allocate new rule\n");
|
|
|
|
memcpy(new_rule, &rule, sizeof(rule));
|
|
TAILQ_INSERT_TAIL(&flow_table, new_rule, entries);
|
|
n_flow_rules++;
|
|
} else
|
|
old_rule->flow.port = rule.flow.port;
|
|
}
|
|
|
|
/* Free message buffer */
|
|
rte_ctrlmbuf_free((struct rte_mbuf *)msg);
|
|
}
|
|
|
|
cmdline_parse_token_string_t cmd_flow_add_flow_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_flow_add_result, flow_string,
|
|
"flow");
|
|
|
|
cmdline_parse_token_string_t cmd_flow_add_add_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_flow_add_result, add_string, "add");
|
|
|
|
cmdline_parse_token_ipaddr_t cmd_flow_add_src_ip =
|
|
TOKEN_IPADDR_INITIALIZER(struct cmd_flow_add_result, src_ip);
|
|
|
|
cmdline_parse_token_ipaddr_t cmd_flow_add_dst_ip =
|
|
TOKEN_IPADDR_INITIALIZER(struct cmd_flow_add_result, dst_ip);
|
|
|
|
cmdline_parse_token_num_t cmd_flow_add_src_port =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_flow_add_result, src_port, UINT16);
|
|
|
|
cmdline_parse_token_num_t cmd_flow_add_dst_port =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_flow_add_result, dst_port, UINT16);
|
|
|
|
cmdline_parse_token_num_t cmd_flow_add_proto =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_flow_add_result, proto, UINT8);
|
|
|
|
cmdline_parse_token_num_t cmd_flow_add_port =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_flow_add_result, port, UINT8);
|
|
|
|
cmdline_parse_inst_t cmd_flow_add = {
|
|
.f = cmd_flow_add_parsed,
|
|
.data = NULL,
|
|
.help_str = "Flow add",
|
|
.tokens = {
|
|
(void *)&cmd_flow_add_flow_string,
|
|
(void *)&cmd_flow_add_add_string,
|
|
(void *)&cmd_flow_add_src_ip,
|
|
(void *)&cmd_flow_add_dst_ip,
|
|
(void *)&cmd_flow_add_src_port,
|
|
(void *)&cmd_flow_add_dst_port,
|
|
(void *)&cmd_flow_add_proto,
|
|
(void *)&cmd_flow_add_port,
|
|
NULL,
|
|
},
|
|
};
|
|
|
|
/* *** Flow Classification - Del *** */
|
|
struct cmd_flow_del_result {
|
|
cmdline_fixed_string_t flow_string;
|
|
cmdline_fixed_string_t del_string;
|
|
cmdline_ipaddr_t src_ip;
|
|
cmdline_ipaddr_t dst_ip;
|
|
uint16_t src_port;
|
|
uint16_t dst_port;
|
|
uint8_t proto;
|
|
};
|
|
|
|
static void
|
|
cmd_flow_del_parsed(
|
|
void *parsed_result,
|
|
__attribute__((unused)) struct cmdline *cl,
|
|
__attribute__((unused)) void *data)
|
|
{
|
|
struct cmd_flow_del_result *params = parsed_result;
|
|
struct app_rule rule, *old_rule;
|
|
struct app_msg_req *req;
|
|
struct app_msg_resp *resp;
|
|
void *msg;
|
|
int status;
|
|
|
|
uint32_t core_id = app_get_first_core_id(APP_CORE_FC);
|
|
|
|
if (core_id == RTE_MAX_LCORE) {
|
|
printf("Flow classification not performed by any CPU core.\n");
|
|
return;
|
|
}
|
|
|
|
struct rte_ring *ring_req = app_get_ring_req(core_id);
|
|
struct rte_ring *ring_resp = app_get_ring_resp(core_id);
|
|
|
|
/* Create rule */
|
|
memset(&rule, 0, sizeof(rule));
|
|
rule.flow.key.src_ip =
|
|
rte_bswap32((uint32_t)params->src_ip.addr.ipv4.s_addr);
|
|
rule.flow.key.dst_ip =
|
|
rte_bswap32((uint32_t)params->dst_ip.addr.ipv4.s_addr);
|
|
rule.flow.key.src_port = params->src_port;
|
|
rule.flow.key.dst_port = params->dst_port;
|
|
rule.flow.key.proto = params->proto;
|
|
|
|
/* Check rule existence */
|
|
IS_RULE_PRESENT(old_rule, rule.flow.key, flow_table, flow);
|
|
if (old_rule == NULL)
|
|
return;
|
|
|
|
printf("Deleting flow: ");
|
|
print_flow_rule(old_rule->flow);
|
|
|
|
/* Allocate message buffer */
|
|
msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
|
|
if (msg == NULL)
|
|
rte_panic("Unable to allocate new message\n");
|
|
|
|
/* Fill request message */
|
|
req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
|
|
memset(req, 0, sizeof(struct app_msg_req));
|
|
|
|
req->type = APP_MSG_REQ_FC_DEL;
|
|
req->flow_classif_del.key.ip_src = rte_bswap32(rule.flow.key.src_ip);
|
|
req->flow_classif_del.key.ip_dst = rte_bswap32(rule.flow.key.dst_ip);
|
|
req->flow_classif_del.key.port_src =
|
|
rte_bswap32(rule.flow.key.src_port);
|
|
req->flow_classif_del.key.port_dst =
|
|
rte_bswap32(rule.flow.key.dst_port);
|
|
req->flow_classif_del.key.proto = rule.flow.key.proto;
|
|
|
|
/* Send request */
|
|
do {
|
|
status = rte_ring_sp_enqueue(ring_req, msg);
|
|
} while (status == -ENOBUFS);
|
|
|
|
/* Wait for response */
|
|
do {
|
|
status = rte_ring_sc_dequeue(ring_resp, &msg);
|
|
} while (status != 0);
|
|
resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
|
|
|
|
/* Check response */
|
|
if (resp->result != 0)
|
|
printf("Request FLOW_DEL failed (%u)\n", resp->result);
|
|
else {
|
|
TAILQ_REMOVE(&flow_table, old_rule, entries);
|
|
rte_free(old_rule);
|
|
n_flow_rules--;
|
|
}
|
|
|
|
/* Free message buffer */
|
|
rte_ctrlmbuf_free((struct rte_mbuf *)msg);
|
|
}
|
|
|
|
cmdline_parse_token_string_t cmd_flow_del_flow_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_flow_del_result, flow_string,
|
|
"flow");
|
|
|
|
cmdline_parse_token_string_t cmd_flow_del_del_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_flow_del_result, del_string, "del");
|
|
|
|
cmdline_parse_token_ipaddr_t cmd_flow_del_src_ip =
|
|
TOKEN_IPADDR_INITIALIZER(struct cmd_flow_del_result, src_ip);
|
|
|
|
cmdline_parse_token_ipaddr_t cmd_flow_del_dst_ip =
|
|
TOKEN_IPADDR_INITIALIZER(struct cmd_flow_del_result, dst_ip);
|
|
|
|
cmdline_parse_token_num_t cmd_flow_del_src_port =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_flow_del_result, src_port, UINT16);
|
|
|
|
cmdline_parse_token_num_t cmd_flow_del_dst_port =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_flow_del_result, dst_port, UINT16);
|
|
|
|
cmdline_parse_token_num_t cmd_flow_del_proto =
|
|
TOKEN_NUM_INITIALIZER(struct cmd_flow_del_result, proto, UINT8);
|
|
|
|
cmdline_parse_inst_t cmd_flow_del = {
|
|
.f = cmd_flow_del_parsed,
|
|
.data = NULL,
|
|
.help_str = "Flow delete",
|
|
.tokens = {
|
|
(void *)&cmd_flow_del_flow_string,
|
|
(void *)&cmd_flow_del_del_string,
|
|
(void *)&cmd_flow_del_src_ip,
|
|
(void *)&cmd_flow_del_dst_ip,
|
|
(void *)&cmd_flow_del_src_port,
|
|
(void *)&cmd_flow_del_dst_port,
|
|
(void *)&cmd_flow_del_proto,
|
|
NULL,
|
|
},
|
|
};
|
|
|
|
/* *** Flow Classification - Print *** */
|
|
struct cmd_flow_print_result {
|
|
cmdline_fixed_string_t flow_string;
|
|
cmdline_fixed_string_t print_string;
|
|
};
|
|
|
|
static void
|
|
cmd_flow_print_parsed(
|
|
__attribute__((unused)) void *parsed_result,
|
|
__attribute__((unused)) struct cmdline *cl,
|
|
__attribute__((unused)) void *data)
|
|
{
|
|
struct app_rule *it;
|
|
|
|
TAILQ_FOREACH(it, &flow_table, entries) {
|
|
print_flow_rule(it->flow);
|
|
}
|
|
}
|
|
|
|
cmdline_parse_token_string_t cmd_flow_print_flow_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_flow_print_result, flow_string,
|
|
"flow");
|
|
|
|
cmdline_parse_token_string_t cmd_flow_print_print_string =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_flow_print_result, print_string,
|
|
"ls");
|
|
|
|
cmdline_parse_inst_t cmd_flow_print = {
|
|
.f = cmd_flow_print_parsed,
|
|
.data = NULL,
|
|
.help_str = "Flow list",
|
|
.tokens = {
|
|
(void *)&cmd_flow_print_flow_string,
|
|
(void *)&cmd_flow_print_print_string,
|
|
NULL,
|
|
},
|
|
};
|
|
|
|
/* *** QUIT *** */
|
|
struct cmd_quit_result {
|
|
cmdline_fixed_string_t quit;
|
|
};
|
|
|
|
static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result,
|
|
struct cmdline *cl,
|
|
__attribute__((unused)) void *data)
|
|
{
|
|
cmdline_quit(cl);
|
|
}
|
|
|
|
cmdline_parse_token_string_t cmd_quit_quit =
|
|
TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit");
|
|
|
|
cmdline_parse_inst_t cmd_quit = {
|
|
.f = cmd_quit_parsed,
|
|
.data = NULL,
|
|
.help_str = "Exit application",
|
|
.tokens = {
|
|
(void *)&cmd_quit_quit,
|
|
NULL,
|
|
},
|
|
};
|
|
|
|
/* List of commands */
|
|
cmdline_parse_ctx_t main_ctx[] = {
|
|
(cmdline_parse_inst_t *)&cmd_flow_add,
|
|
(cmdline_parse_inst_t *)&cmd_flow_del,
|
|
(cmdline_parse_inst_t *)&cmd_flow_add_all,
|
|
(cmdline_parse_inst_t *)&cmd_flow_print,
|
|
#ifdef RTE_LIBRTE_ACL
|
|
(cmdline_parse_inst_t *)&cmd_firewall_add,
|
|
(cmdline_parse_inst_t *)&cmd_firewall_del,
|
|
(cmdline_parse_inst_t *)&cmd_firewall_print,
|
|
#endif
|
|
(cmdline_parse_inst_t *)&cmd_route_add,
|
|
(cmdline_parse_inst_t *)&cmd_route_del,
|
|
(cmdline_parse_inst_t *)&cmd_routing_print,
|
|
(cmdline_parse_inst_t *)&cmd_arp_add,
|
|
(cmdline_parse_inst_t *)&cmd_arp_del,
|
|
(cmdline_parse_inst_t *)&cmd_arp_print,
|
|
(cmdline_parse_inst_t *)&cmd_run_file,
|
|
(cmdline_parse_inst_t *)&cmd_link_enable,
|
|
(cmdline_parse_inst_t *)&cmd_link_disable,
|
|
(cmdline_parse_inst_t *)&cmd_quit,
|
|
NULL,
|
|
};
|
|
|
|
/* Main loop */
|
|
void
|
|
app_main_loop_cmdline(void)
|
|
{
|
|
struct cmdline *cl;
|
|
uint32_t core_id = rte_lcore_id();
|
|
|
|
RTE_LOG(INFO, USER1, "Core %u is running the command line interface\n",
|
|
core_id);
|
|
|
|
n_arp_rules = 0;
|
|
n_routing_rules = 0;
|
|
n_firewall_rules = 0;
|
|
n_flow_rules = 0;
|
|
|
|
app_init_rule_tables();
|
|
|
|
cl = cmdline_stdin_new(main_ctx, "pipeline> ");
|
|
if (cl == NULL)
|
|
return;
|
|
cmdline_interact(cl);
|
|
cmdline_stdin_exit(cl);
|
|
}
|