From: Jingjing Wu <jingjing.wu@intel.com>
To: dev@dpdk.org
Subject: [dpdk-dev] [PATCH 5/6] app/test-pmd: add commands and config functions for i40e flow director support
Date: Fri, 1 Aug 2014 15:08:35 +0800 [thread overview]
Message-ID: <1406876916-24869-6-git-send-email-jingjing.wu@intel.com> (raw)
In-Reply-To: <1406876916-24869-1-git-send-email-jingjing.wu@intel.com>
add structure definition to construct programming packet.
add commands to programming 6 flow types for the flow director filters,
which is called PCTYPE in fortville: ipv4, tcpv4, udpv4, ipv6, tcpv6, udpv6
add command to support flushing flow director table
Signed-off-by: jingjing.wu <jingjing.wu@intel.com>
---
app/test-pmd/cmdline.c | 665 +++++++++++++++++++++++++++++++++++++++++++++++++
app/test-pmd/config.c | 54 +++-
app/test-pmd/testpmd.c | 22 ++
app/test-pmd/testpmd.h | 57 +++++
4 files changed, 786 insertions(+), 12 deletions(-)
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 345be11..bf7e45c 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -74,6 +74,14 @@
#include <rte_ethdev.h>
#include <rte_string_fns.h>
#include <rte_devargs.h>
+#include <rte_ip.h>
+#include <rte_udp.h>
+#include <rte_tcp.h>
+#include <rte_sctp.h>
+#include <rte_eth_features.h>
+#ifdef RTE_LIBRTE_I40E_PMD
+#include <rte_i40e.h>
+#endif /* RTE_LIBRTE_I40E_PMD */
#include <cmdline_rdline.h>
#include <cmdline_parse.h>
@@ -655,6 +663,25 @@ static void cmd_help_long_parsed(void *parsed_result,
"get_flex_filter (port_id) index (idx)\n"
" get info of a flex filter.\n\n"
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ "i40e_flow_director_filter (port_id) (add|del)"
+ " flow (ip4|ip6) src (src_ip_address) dst (dst_ip_address)"
+ " flexwords (flexwords_value) (drop|fwd)"
+ " queue (queue_id) fd_id (fd_id_value)\n"
+ " Add/Del a IP type flow director filter for i40e NIC.\n\n"
+
+ "i40e_flow_director_filter (port_id) (add|del)"
+ " flow (udp4|tcp4|udp6|tcp6)"
+ " src (src_ip_address) (src_port)"
+ " dst (dst_ip_address) (dst_port)"
+ " flexwords (flexwords_value) (drop|fwd)"
+ " queue (queue_id) fd_id (fd_id_value)\n"
+ " Add/Del a UDP/TCP type flow director filter for i40e NIC.\n\n"
+
+ "i40e_flush_flow_diretor (port_id)\n"
+ " Flush all flow director entries of a device on i40e NIC.\n\n"
+#endif /* RTE_LIBRTE_I40E_PMD */
);
}
}
@@ -7304,6 +7331,639 @@ cmdline_parse_inst_t cmd_get_flex_filter = {
},
};
+/* *** Classification Filters Control *** */
+#ifdef RTE_LIBRTE_I40E_PMD
+/* *** deal with i40e flow director filter *** */
+struct cmd_i40e_flow_director_result {
+ cmdline_fixed_string_t flow_director_filter;
+ uint8_t port_id;
+ cmdline_fixed_string_t ops;
+ cmdline_fixed_string_t flow;
+ cmdline_fixed_string_t flow_type;
+ cmdline_fixed_string_t src;
+ cmdline_ipaddr_t ip_src;
+ uint16_t port_src;
+ cmdline_fixed_string_t dst;
+ cmdline_ipaddr_t ip_dst;
+ uint16_t port_dst;
+ cmdline_fixed_string_t flexwords;
+ cmdline_fixed_string_t flexwords_value;
+ cmdline_fixed_string_t drop;
+ cmdline_fixed_string_t queue;
+ uint16_t queue_id;
+ cmdline_fixed_string_t fd_id;
+ uint32_t fd_id_value;
+};
+
+static inline int
+parse_flexwords(const char *q_arg, uint16_t *flexwords)
+{
+#define MAX_NUM_WORD 8
+ char s[256];
+ const char *p, *p0 = q_arg;
+ char *end;
+ unsigned long int_fld[MAX_NUM_WORD];
+ char *str_fld[MAX_NUM_WORD];
+ int i;
+ unsigned size;
+ int num_words = -1;
+
+ p = strchr(p0, '(');
+ if (p == NULL)
+ return -1;
+ ++p;
+ p0 = strchr(p, ')');
+ if (p0 == NULL)
+ return -1;
+
+ size = p0 - p;
+ if (size >= sizeof(s))
+ return -1;
+
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ num_words = rte_strsplit(s, sizeof(s), str_fld, MAX_NUM_WORD, ',');
+ if (num_words < 0 || num_words > MAX_NUM_WORD)
+ return -1;
+ for (i = 0; i < num_words; i++) {
+ errno = 0;
+ int_fld[i] = strtoul(str_fld[i], &end, 0);
+ if (errno != 0 || end == str_fld[i] || int_fld[i] > UINT16_MAX)
+ return -1;
+ flexwords[i] = rte_cpu_to_be_16((uint16_t)int_fld[i]);
+ }
+ return num_words;
+}
+
+static inline struct rte_mbuf *
+tx_mbuf_alloc(struct rte_mempool *mp)
+{
+ struct rte_mbuf *m;
+
+ m = __rte_mbuf_raw_alloc(mp);
+ __rte_mbuf_sanity_check_raw(m, RTE_MBUF_PKT, 0);
+ return m;
+}
+
+static inline void
+rte_i40e_fdir_construct_ip4_input(struct ipv4_other_flow *flow,
+ unsigned char *raw_pkt)
+{
+ struct ether_hdr *ether;
+ struct ipv4_hdr *ip;
+ unsigned char *payload;
+
+ ether = (struct ether_hdr *)raw_pkt;
+ ip = (struct ipv4_hdr *)(raw_pkt + sizeof(struct ether_hdr));
+ payload = raw_pkt + sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr);
+
+ ether->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
+ ip->version_ihl = I40E_FDIR_IP_DEFAULT_VERSION_IHL;
+ /* set len to 46 bytes by default */
+ ip->total_length = rte_cpu_to_be_16(I40E_FDIR_IP_DEFAULT_LEN);
+ ip->time_to_live = I40E_FDIR_IP_DEFAULT_TTL;
+
+ /*
+ * The source and destination fields in the transmitted packet need
+ * to be presented in a reversed order with respect to the expected
+ * received packets.
+ */
+ ip->src_addr = flow->dst_ip;
+ ip->dst_addr = flow->src_ip;
+ (void)rte_memcpy(payload,
+ flow->flexwords,
+ BYTES_PER_WORD * flow->num_flexwords);
+}
+
+static inline void
+rte_i40e_fdir_construct_udp4_input(struct ipv4_udp_flow *flow,
+ unsigned char *raw_pkt)
+{
+ struct ether_hdr *ether;
+ struct ipv4_hdr *ip;
+ struct udp_hdr *udp;
+ unsigned char *payload;
+
+ ether = (struct ether_hdr *)raw_pkt;
+ ip = (struct ipv4_hdr *)(raw_pkt + sizeof(struct ether_hdr));
+ udp = (struct udp_hdr *)(raw_pkt + sizeof(struct ether_hdr) +
+ sizeof(struct ipv4_hdr));
+ payload = raw_pkt + sizeof(struct ether_hdr) +
+ sizeof(struct ipv4_hdr) + sizeof(struct udp_hdr);
+
+ ether->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
+ ip->version_ihl = I40E_FDIR_IP_DEFAULT_VERSION_IHL;
+ /* set len to by default */
+ ip->total_length = rte_cpu_to_be_16(I40E_FDIR_IP_DEFAULT_LEN);
+ ip->time_to_live = I40E_FDIR_IP_DEFAULT_TTL;
+
+ /*
+ * The source and destination fields in the transmitted packet need
+ * to be presented in a reversed order with respect to the expected
+ * received packets.
+ */
+ ip->src_addr = flow->dst_ip;
+ ip->dst_addr = flow->src_ip;
+ ip->next_proto_id = IPPROTO_UDP;
+ udp->src_port = flow->dst_port;
+ udp->dst_port = flow->src_port;
+ udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_UDP_DEFAULT_LEN);
+ (void)rte_memcpy(payload,
+ flow->flexwords,
+ BYTES_PER_WORD * flow->num_flexwords);
+}
+
+static inline void
+rte_i40e_fdir_construct_tcp4_input(struct ipv4_tcp_flow *flow,
+ unsigned char *raw_pkt)
+{
+ struct ether_hdr *ether;
+ struct ipv4_hdr *ip;
+ struct tcp_hdr *tcp;
+ unsigned char *payload;
+
+ ether = (struct ether_hdr *)raw_pkt;
+ ip = (struct ipv4_hdr *)(raw_pkt + sizeof(struct ether_hdr));
+ tcp = (struct tcp_hdr *)(raw_pkt + sizeof(struct ether_hdr) +
+ sizeof(struct ipv4_hdr));
+ payload = raw_pkt + sizeof(struct ether_hdr) +
+ sizeof(struct ipv4_hdr) + sizeof(struct tcp_hdr);
+
+ ether->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
+ ip->version_ihl = I40E_FDIR_IP_DEFAULT_VERSION_IHL;
+ /* set len by default */
+ ip->total_length = rte_cpu_to_be_16(I40E_FDIR_IP_DEFAULT_LEN);
+ ip->time_to_live = I40E_FDIR_IP_DEFAULT_TTL;
+
+ /*
+ * The source and destination fields in the transmitted packet need
+ * to be presented in a reversed order with respect to the expected
+ * received packets.
+ */
+ ip->src_addr = flow->dst_ip;
+ ip->dst_addr = flow->src_ip;
+ ip->next_proto_id = IPPROTO_TCP;
+ tcp->src_port = flow->dst_port;
+ tcp->dst_port = flow->src_port;
+ tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF;
+ (void)rte_memcpy(payload,
+ flow->flexwords,
+ BYTES_PER_WORD * flow->num_flexwords);
+}
+
+static inline void
+rte_i40e_fdir_construct_ip6_input(struct ipv6_other_flow *flow,
+ unsigned char *raw_pkt)
+{
+ struct ether_hdr *ether;
+ struct ipv6_hdr *ip;
+ unsigned char *payload;
+
+ ether = (struct ether_hdr *)raw_pkt;
+ ip = (struct ipv6_hdr *)(raw_pkt + sizeof(struct ether_hdr));
+ payload = raw_pkt + sizeof(struct ether_hdr) + sizeof(struct ipv6_hdr);
+
+ ether->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
+ ip->vtc_flow = rte_cpu_to_be_32(I40E_FDIR_IPv6_DEFAULT_VTC_FLOW);
+ ip->payload_len = rte_cpu_to_be_16(I40E_FDIR_IPv6_DEFAULT_PAYLOAD_LEN);
+ ip->hop_limits = I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS;
+
+ /*
+ * The source and destination fields in the transmitted packet need
+ * to be presented in a reversed order with respect to the expected
+ * received packets.
+ */
+ rte_memcpy(&(ip->src_addr), &(flow->dst_ip), IPV6_ADDR_LEN);
+ rte_memcpy(&(ip->dst_addr), &(flow->src_ip), IPV6_ADDR_LEN);
+ (void)rte_memcpy(payload,
+ flow->flexwords,
+ BYTES_PER_WORD * flow->num_flexwords);
+}
+
+static inline void
+rte_i40e_fdir_construct_udp6_input(struct ipv6_udp_flow *flow,
+ unsigned char *raw_pkt)
+{
+ struct ether_hdr *ether;
+ struct ipv6_hdr *ip;
+ struct udp_hdr *udp;
+ unsigned char *payload;
+
+ ether = (struct ether_hdr *)raw_pkt;
+ ip = (struct ipv6_hdr *)(raw_pkt + sizeof(struct ether_hdr));
+ udp = (struct udp_hdr *)(raw_pkt + sizeof(struct ether_hdr) +
+ sizeof(struct ipv6_hdr));
+ payload = raw_pkt + sizeof(struct ether_hdr) +
+ sizeof(struct ipv6_hdr) + sizeof(struct udp_hdr);
+
+ ether->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
+ ip->vtc_flow = rte_cpu_to_be_32(I40E_FDIR_IPv6_DEFAULT_VTC_FLOW);
+ ip->payload_len = rte_cpu_to_be_16(I40E_FDIR_IPv6_DEFAULT_PAYLOAD_LEN);
+ ip->hop_limits = I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS;
+ /*
+ * The source and destination fields in the transmitted packet need
+ * to be presented in a reversed order with respect to the expected
+ * received packets.
+ */
+ rte_memcpy(&(ip->src_addr), &(flow->dst_ip), IPV6_ADDR_LEN);
+ rte_memcpy(&(ip->dst_addr), &(flow->src_ip), IPV6_ADDR_LEN);
+ ip->proto = IPPROTO_UDP;
+ udp->src_port = flow->dst_port;
+ udp->dst_port = flow->src_port;
+ udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_UDP_DEFAULT_LEN);
+ (void)rte_memcpy(payload,
+ flow->flexwords,
+ BYTES_PER_WORD * flow->num_flexwords);
+}
+
+static inline void
+rte_i40e_fdir_construct_tcp6_input(struct ipv6_tcp_flow *flow,
+ unsigned char *raw_pkt)
+{
+ struct ether_hdr *ether;
+ struct ipv6_hdr *ip;
+ struct tcp_hdr *tcp;
+ unsigned char *payload;
+
+ ether = (struct ether_hdr *)raw_pkt;
+ ip = (struct ipv6_hdr *)(raw_pkt + sizeof(struct ether_hdr));
+ tcp = (struct tcp_hdr *)(raw_pkt + sizeof(struct ether_hdr) +
+ sizeof(struct ipv6_hdr));
+ payload = raw_pkt + sizeof(struct ether_hdr) +
+ sizeof(struct ipv6_hdr) + sizeof(struct tcp_hdr);
+
+ ether->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
+ ip->vtc_flow = rte_cpu_to_be_32(I40E_FDIR_IPv6_DEFAULT_VTC_FLOW);
+ ip->payload_len = rte_cpu_to_be_16(I40E_FDIR_IPv6_DEFAULT_PAYLOAD_LEN);
+ ip->hop_limits = I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS;
+ /*
+ * The source and destination fields in the transmitted packet need
+ * to be presented in a reversed order with respect to the expected
+ * received packets.
+ */
+ rte_memcpy(&(ip->src_addr), &(flow->dst_ip), IPV6_ADDR_LEN);
+ rte_memcpy(&(ip->dst_addr), &(flow->src_ip), IPV6_ADDR_LEN);
+ ip->proto = IPPROTO_TCP;
+ tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF;
+ tcp->src_port = flow->dst_port;
+ tcp->dst_port = flow->src_port;
+ (void)rte_memcpy(payload,
+ flow->flexwords,
+ BYTES_PER_WORD * flow->num_flexwords);
+}
+
+static void
+cmd_i40e_flow_director_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_i40e_flow_director_result *res = parsed_result;
+ struct rte_port *port;
+ struct rte_i40e_fdir_entry entry;
+ struct rte_mbuf *m_pkt = NULL;
+ uint16_t flexwords[8];
+ enum rte_eth_command cmd;
+ int num_flexwords;
+ int ret = 0;
+
+ memset(flexwords, 0, sizeof(flexwords));
+ memset(&entry, 0, sizeof(struct rte_i40e_fdir_entry));
+ num_flexwords = parse_flexwords(res->flexwords_value, flexwords);
+ if (num_flexwords < 0) {
+ printf("error: Cannot pase flexwords input.\n");
+ return;
+ }
+ port = &ports[res->port_id];
+ m_pkt = tx_mbuf_alloc(port->i40e_fdir_mp);
+ if (m_pkt == NULL) {
+ printf("error: Cannot malloc mbuf for fdir.\n");
+ return;
+ }
+
+ if (!strcmp(res->flow_type, "ip4")) {
+ struct ipv4_other_flow ip4_flow;
+ memset(&ip4_flow, 0, sizeof(struct ipv4_other_flow));
+ /* no need to convert, already big endian. */
+ if (res->ip_dst.family == AF_INET)
+ ip4_flow.dst_ip = res->ip_dst.addr.ipv4.s_addr;
+ else {
+ printf("error paramters.\n");
+ goto pktbuf_free;
+ }
+ if (res->ip_src.family == AF_INET)
+ ip4_flow.src_ip = res->ip_src.addr.ipv4.s_addr;
+ else {
+ printf("error paramters.\n");
+ goto pktbuf_free;
+ }
+ ip4_flow.num_flexwords = num_flexwords;
+ rte_memcpy(ip4_flow.flexwords,
+ flexwords,
+ num_flexwords);
+ rte_i40e_fdir_construct_ip4_input(&ip4_flow, m_pkt->pkt.data);
+ entry.input.pctype = ETH_PCTYPE_NONF_IPV4_OTHER;
+ } else if (!strcmp(res->flow_type, "udp4")) {
+ struct ipv4_udp_flow udp4_flow;
+ memset(&udp4_flow, 0, sizeof(struct ipv4_udp_flow));
+ /* no need to convert, already big endian. */
+ if (res->ip_dst.family == AF_INET)
+ udp4_flow.dst_ip = res->ip_dst.addr.ipv4.s_addr;
+ else {
+ printf("error paramters.\n");
+ goto pktbuf_free;
+ }
+ if (res->ip_src.family == AF_INET)
+ udp4_flow.src_ip = res->ip_src.addr.ipv4.s_addr;
+ else {
+ printf("error paramters.\n");
+ goto pktbuf_free;
+ }
+ /* need convert to big endian. */
+ udp4_flow.dst_port = rte_cpu_to_be_16(res->port_dst);
+ udp4_flow.src_port = rte_cpu_to_be_16(res->port_src);
+ udp4_flow.num_flexwords = num_flexwords;
+ rte_memcpy(udp4_flow.flexwords,
+ flexwords,
+ udp4_flow.num_flexwords);
+ rte_i40e_fdir_construct_udp4_input(&udp4_flow, m_pkt->pkt.data);
+ entry.input.pctype = ETH_PCTYPE_NONF_IPV4_UDP;
+ } else if (!strcmp(res->flow_type, "tcp4")) {
+ struct ipv4_tcp_flow tcp4_flow;
+ memset(&tcp4_flow, 0, sizeof(struct ipv4_tcp_flow));
+ if (res->ip_dst.family == AF_INET)
+ tcp4_flow.dst_ip = res->ip_dst.addr.ipv4.s_addr;
+ else {
+ printf("error paramters.\n");
+ goto pktbuf_free;
+ }
+ if (res->ip_src.family == AF_INET)
+ tcp4_flow.src_ip = res->ip_src.addr.ipv4.s_addr;
+ else {
+ printf("error paramters.\n");
+ goto pktbuf_free;
+ }
+ /* need convert to big endian. */
+ tcp4_flow.dst_port = rte_cpu_to_be_16(res->port_dst);
+ tcp4_flow.src_port = rte_cpu_to_be_16(res->port_src);
+ tcp4_flow.num_flexwords = num_flexwords;
+ rte_memcpy(tcp4_flow.flexwords,
+ flexwords,
+ tcp4_flow.num_flexwords);
+ rte_i40e_fdir_construct_tcp4_input(&tcp4_flow, m_pkt->pkt.data);
+ entry.input.pctype = ETH_PCTYPE_NONF_IPV4_TCP;
+ } else if (!strcmp(res->flow_type, "ip6")) {
+ struct ipv6_other_flow ip6_flow;
+ memset(&ip6_flow, 0, sizeof(struct ipv6_other_flow));
+ if (res->ip_src.family == AF_INET6)
+ (void)rte_memcpy(&(ip6_flow.src_ip),
+ &(res->ip_src.addr.ipv6),
+ sizeof(struct in6_addr));
+ else {
+ printf("error paramters.\n");
+ goto pktbuf_free;
+ }
+ if (res->ip_dst.family == AF_INET6)
+ (void)rte_memcpy(&(ip6_flow.dst_ip),
+ &(res->ip_dst.addr.ipv6),
+ sizeof(struct in6_addr));
+ else {
+ printf("error paramters.\n");
+ goto pktbuf_free;
+ }
+ ip6_flow.num_flexwords = num_flexwords;
+ rte_memcpy(ip6_flow.flexwords,
+ flexwords,
+ ip6_flow.num_flexwords);
+ rte_i40e_fdir_construct_ip6_input(&ip6_flow, m_pkt->pkt.data);
+ entry.input.pctype = ETH_PCTYPE_NONF_IPV6_OTHER;
+ } else if (!strcmp(res->flow_type, "udp6")) {
+ struct ipv6_udp_flow udp6_flow;
+ memset(&udp6_flow, 0, sizeof(struct ipv6_udp_flow));
+ if (res->ip_src.family == AF_INET6)
+ (void)rte_memcpy(&(udp6_flow.src_ip),
+ &(res->ip_src.addr.ipv6),
+ sizeof(struct in6_addr));
+ else {
+ printf("error paramters.\n");
+ goto pktbuf_free;
+ }
+ if (res->ip_dst.family == AF_INET6)
+ (void)rte_memcpy(&(udp6_flow.dst_ip),
+ &(res->ip_dst.addr.ipv6),
+ sizeof(struct in6_addr));
+ else {
+ printf("error paramters.\n");
+ goto pktbuf_free;
+ }
+ udp6_flow.dst_port = rte_cpu_to_be_16(res->port_dst);
+ udp6_flow.src_port = rte_cpu_to_be_16(res->port_src);
+ udp6_flow.num_flexwords = num_flexwords;
+ rte_memcpy(udp6_flow.flexwords,
+ flexwords,
+ udp6_flow.num_flexwords);
+ rte_i40e_fdir_construct_udp6_input(&udp6_flow, m_pkt->pkt.data);
+ entry.input.pctype = ETH_PCTYPE_NONF_IPV6_UDP;
+ } else if (!strcmp(res->flow_type, "tcp6")) {
+ struct ipv6_tcp_flow tcp6_flow;
+ memset(&tcp6_flow, 0, sizeof(struct ipv6_tcp_flow));
+ if (res->ip_src.family == AF_INET6)
+ (void)rte_memcpy(&(tcp6_flow.src_ip),
+ &(res->ip_src.addr.ipv6),
+ sizeof(struct in6_addr));
+ else {
+ printf("error paramters.\n");
+ goto pktbuf_free;
+ }
+ if (res->ip_dst.family == AF_INET6)
+ (void)rte_memcpy(&(tcp6_flow.dst_ip),
+ &(res->ip_dst.addr.ipv6),
+ sizeof(struct in6_addr));
+ else {
+ printf("error paramters.\n");
+ goto pktbuf_free;
+ }
+ tcp6_flow.dst_port = rte_cpu_to_be_16(res->port_dst);
+ tcp6_flow.src_port = rte_cpu_to_be_16(res->port_src);
+ tcp6_flow.num_flexwords = num_flexwords;
+ rte_memcpy(tcp6_flow.flexwords,
+ flexwords,
+ tcp6_flow.num_flexwords);
+ rte_i40e_fdir_construct_tcp6_input(&tcp6_flow, m_pkt->pkt.data);
+ entry.input.pctype = ETH_PCTYPE_NONF_IPV6_TCP;
+ }
+ m_pkt->pkt.data_len = I40E_FDIR_PKT_LEN;
+ m_pkt->pkt.next = NULL;
+
+ entry.input.data = m_pkt;
+ entry.input.dest_vsi = 0; /* if set to 0, will use main vsi by default*/
+ entry.input.flex_off = 0; /*use 0 by default*/
+ if (!strcmp(res->drop, "drop"))
+ entry.action.drop = RTE_I40E_DEST_DROP_PACKET;
+ else
+ entry.action.drop = RTE_I40E_DEST_DIRECT_PACKET_QINDEX;
+ /* set to report FD ID by default temporary*/
+ entry.action.report_status = RTE_I40E_FDIR_REPORT_FD_ID;
+ entry.action.rx_queue = res->queue_id;
+ /* use 0 by default, will set it to fdir counter per dev */
+ entry.action.cnt_index = 0;
+ entry.soft_id = res->fd_id_value;
+ if (!strcmp(res->ops, "add"))
+ cmd = RTE_CMD_FDIR_RULE_ADD;
+ else
+ cmd = RTE_CMD_FDIR_RULE_DEL;
+ ret = rte_eth_dev_rx_classification_filter_ctl(res->port_id, cmd, &entry);
+ if (ret < 0)
+ printf("i40e flow director programming error,"
+ " return code = %d \n", ret);
+pktbuf_free:
+ rte_pktmbuf_free(entry.input.data);
+}
+
+cmdline_parse_token_string_t cmd_i40e_flow_director_filter =
+ TOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,
+ flow_director_filter, "i40e_flow_director_filter");
+cmdline_parse_token_num_t cmd_i40e_flow_director_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_i40e_flow_director_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_i40e_flow_director_ops =
+ TOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,
+ ops, "add#del");
+cmdline_parse_token_string_t cmd_i40e_flow_director_flow =
+ TOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,
+ flow, "flow");
+cmdline_parse_token_string_t cmd_i40e_flow_director_flow_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,
+ flow_type, "ip4#tcp4#udp4#ip6#tcp6#udp6");
+cmdline_parse_token_string_t cmd_i40e_flow_director_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,
+ src, "src");
+cmdline_parse_token_ipaddr_t cmd_i40e_flow_director_ip_src =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_i40e_flow_director_result,
+ ip_src);
+cmdline_parse_token_num_t cmd_i40e_flow_director_port_src =
+ TOKEN_NUM_INITIALIZER(struct cmd_i40e_flow_director_result,
+ port_src, UINT16);
+cmdline_parse_token_string_t cmd_i40e_flow_director_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,
+ dst, "dst");
+cmdline_parse_token_ipaddr_t cmd_i40e_flow_director_ip_dst =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_i40e_flow_director_result,
+ ip_dst);
+cmdline_parse_token_num_t cmd_i40e_flow_director_port_dst =
+ TOKEN_NUM_INITIALIZER(struct cmd_i40e_flow_director_result,
+ port_dst, UINT16);
+cmdline_parse_token_string_t cmd_i40e_flow_director_flexwords =
+ TOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,
+ flexwords, "flexwords");
+cmdline_parse_token_string_t cmd_i40e_flow_director_flexwords_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,
+ flexwords_value, NULL);
+cmdline_parse_token_string_t cmd_i40e_flow_director_drop =
+ TOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,
+ drop, "drop#fwd");
+cmdline_parse_token_string_t cmd_i40e_flow_director_queue =
+ TOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,
+ queue, "queue");
+cmdline_parse_token_num_t cmd_i40e_flow_director_queue_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_i40e_flow_director_result,
+ queue_id, UINT16);
+cmdline_parse_token_string_t cmd_i40e_flow_director_fd_id =
+ TOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,
+ fd_id, "fd_id");
+cmdline_parse_token_num_t cmd_i40e_flow_director_fd_id_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_i40e_flow_director_result,
+ fd_id_value, UINT32);
+
+cmdline_parse_inst_t cmd_i40e_add_del_ip_flow_director = {
+ .f = cmd_i40e_flow_director_parsed,
+ .data = NULL,
+ .help_str = "add or delete a ip flow director entry on i40e NIC",
+ .tokens = {
+ (void *)&cmd_i40e_flow_director_filter,
+ (void *)&cmd_i40e_flow_director_port_id,
+ (void *)&cmd_i40e_flow_director_ops,
+ (void *)&cmd_i40e_flow_director_flow,
+ (void *)&cmd_i40e_flow_director_flow_type,
+ (void *)&cmd_i40e_flow_director_src,
+ (void *)&cmd_i40e_flow_director_ip_src,
+ (void *)&cmd_i40e_flow_director_dst,
+ (void *)&cmd_i40e_flow_director_ip_dst,
+ (void *)&cmd_i40e_flow_director_flexwords,
+ (void *)&cmd_i40e_flow_director_flexwords_value,
+ (void *)&cmd_i40e_flow_director_drop,
+ (void *)&cmd_i40e_flow_director_queue,
+ (void *)&cmd_i40e_flow_director_queue_id,
+ (void *)&cmd_i40e_flow_director_fd_id,
+ (void *)&cmd_i40e_flow_director_fd_id_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_i40e_add_del_udp_flow_director = {
+ .f = cmd_i40e_flow_director_parsed,
+ .data = NULL,
+ .help_str = "add or delete a udp/tcp flow director entry on i40e NIC",
+ .tokens = {
+ (void *)&cmd_i40e_flow_director_filter,
+ (void *)&cmd_i40e_flow_director_port_id,
+ (void *)&cmd_i40e_flow_director_ops,
+ (void *)&cmd_i40e_flow_director_flow,
+ (void *)&cmd_i40e_flow_director_flow_type,
+ (void *)&cmd_i40e_flow_director_src,
+ (void *)&cmd_i40e_flow_director_ip_src,
+ (void *)&cmd_i40e_flow_director_port_src,
+ (void *)&cmd_i40e_flow_director_dst,
+ (void *)&cmd_i40e_flow_director_ip_dst,
+ (void *)&cmd_i40e_flow_director_port_dst,
+ (void *)&cmd_i40e_flow_director_flexwords,
+ (void *)&cmd_i40e_flow_director_flexwords_value,
+ (void *)&cmd_i40e_flow_director_drop,
+ (void *)&cmd_i40e_flow_director_queue,
+ (void *)&cmd_i40e_flow_director_queue_id,
+ (void *)&cmd_i40e_flow_director_fd_id,
+ (void *)&cmd_i40e_flow_director_fd_id_value,
+ NULL,
+ },
+};
+
+struct cmd_i40e_flush_flow_director_result {
+ cmdline_fixed_string_t flush_flow_director;
+ uint8_t port_id;
+};
+
+cmdline_parse_token_string_t cmd_i40e_flush_flow_director_flush =
+ TOKEN_STRING_INITIALIZER(struct cmd_i40e_flush_flow_director_result,
+ flush_flow_director, "i40e_flush_flow_director");
+cmdline_parse_token_num_t cmd_i40e_flush_flow_director_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_i40e_flush_flow_director_result,
+ port_id, UINT8);
+
+static void
+cmd_i40e_flush_flow_director_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_i40e_flow_director_result *res = parsed_result;
+ int ret = 0;
+
+ ret = rte_eth_dev_rx_classification_filter_ctl(res->port_id,
+ RTE_CMD_FDIR_FLUSH, NULL);
+ if (ret < 0)
+ printf("i40e flow director table flushing error,"
+ " return code = %d \n", ret);
+}
+
+cmdline_parse_inst_t cmd_i40e_flush_flow_director = {
+ .f = cmd_i40e_flush_flow_director_parsed,
+ .data = NULL,
+ .help_str = "flush all flow director entries of a device on i40e NIC",
+ .tokens = {
+ (void *)&cmd_i40e_flush_flow_director_flush,
+ (void *)&cmd_i40e_flush_flow_director_port_id,
+ NULL,
+ },
+};
+#endif /* RTE_LIBRTE_I40E_PMD */
+
/* ******************************************************************************** */
/* list of instructions */
@@ -7429,6 +8089,11 @@ cmdline_parse_ctx_t main_ctx[] = {
(cmdline_parse_inst_t *)&cmd_add_flex_filter,
(cmdline_parse_inst_t *)&cmd_remove_flex_filter,
(cmdline_parse_inst_t *)&cmd_get_flex_filter,
+#ifdef RTE_LIBRTE_I40E_PMD
+ (cmdline_parse_inst_t *)&cmd_i40e_add_del_ip_flow_director,
+ (cmdline_parse_inst_t *)&cmd_i40e_add_del_udp_flow_director,
+ (cmdline_parse_inst_t *)&cmd_i40e_flush_flow_director,
+#endif /* RTE_LIBRTE_I40E_PMD */
NULL,
};
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index c72f6ee..4c40afe 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -93,6 +93,10 @@
#include <rte_ether.h>
#include <rte_ethdev.h>
#include <rte_string_fns.h>
+#include <rte_eth_features.h>
+#ifdef RTE_LIBRTE_I40E_PMD
+#include <rte_i40e.h>
+#endif /* RTE_LIBRTE_I40E_PMD */
#include "testpmd.h"
@@ -1781,26 +1785,52 @@ fdir_remove_signature_filter(portid_t port_id,
void
fdir_get_infos(portid_t port_id)
{
- struct rte_eth_fdir fdir_infos;
+ struct rte_eth_dev_info dev_info;
static const char *fdir_stats_border = "########################";
if (port_id_is_invalid(port_id))
return;
- rte_eth_dev_fdir_get_infos(port_id, &fdir_infos);
-
printf("\n %s FDIR infos for port %-2d %s\n",
fdir_stats_border, port_id, fdir_stats_border);
-
- printf(" collision: %-10"PRIu64" free: %"PRIu64"\n"
- " maxhash: %-10"PRIu64" maxlen: %"PRIu64"\n"
- " add: %-10"PRIu64" remove: %"PRIu64"\n"
- " f_add: %-10"PRIu64" f_remove: %"PRIu64"\n",
- (uint64_t)(fdir_infos.collision), (uint64_t)(fdir_infos.free),
- (uint64_t)(fdir_infos.maxhash), (uint64_t)(fdir_infos.maxlen),
- fdir_infos.add, fdir_infos.remove,
- fdir_infos.f_add, fdir_infos.f_remove);
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(port_id, &dev_info);
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (strstr(dev_info.driver_name, "i40e") != NULL) {
+ struct rte_i40e_fdir_info i40e_fdir_info;
+ memset(&i40e_fdir_info, 0, sizeof(struct rte_i40e_fdir_info));
+ rte_eth_dev_rx_classification_filter_ctl(port_id,
+ RTE_CMD_FDIR_INFO_GET, (void *)&i40e_fdir_info);
+ if (i40e_fdir_info.mode) {
+ printf(" FDIR is enabled\n");
+ printf(" guarant_space: %-10"PRIu16
+ " best_space: %"PRIu16"\n",
+ i40e_fdir_info.guarant_spc,
+ i40e_fdir_info.best_spc);
+ printf(" guarant_count: %-10"PRIu16
+ " best_count: %"PRIu16"\n",
+ i40e_fdir_info.guarant_cnt,
+ i40e_fdir_info.best_cnt);
+ } else
+ printf(" FDIR is disabled\n");
+ } else {
+#endif /* RTE_LIBRTE_I40E_PMD */
+ struct rte_eth_fdir fdir_infos;
+
+ rte_eth_dev_fdir_get_infos(port_id, &fdir_infos);
+
+ printf(" collision: %-10"PRIu64" free: %"PRIu64"\n"
+ " maxhash: %-10"PRIu64" maxlen: %"PRIu64"\n"
+ " add: %-10"PRIu64" remove: %"PRIu64"\n"
+ " f_add: %-10"PRIu64" f_remove: %"PRIu64"\n",
+ (uint64_t)(fdir_infos.collision), (uint64_t)(fdir_infos.free),
+ (uint64_t)(fdir_infos.maxhash), (uint64_t)(fdir_infos.maxlen),
+ fdir_infos.add, fdir_infos.remove,
+ fdir_infos.f_add, fdir_infos.f_remove);
+#ifdef RTE_LIBRTE_I40E_PMD
+ }
+#endif /* RTE_LIBRTE_I40E_PMD */
printf(" %s############################%s\n",
fdir_stats_border, fdir_stats_border);
}
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index e8a4b45..d0d4fc1 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -1676,6 +1676,28 @@ init_port_config(void)
port = &ports[pid];
port->dev_conf.rxmode = rx_mode;
port->dev_conf.fdir_conf = fdir_conf;
+#ifdef RTE_LIBRTE_I40E_PMD
+#define I40E_FDIR_NB_MBUF 4
+#define I40E_FDIR_MBUF_SIZE (512 + sizeof(struct rte_mbuf))
+#define I40E_FDIR_PKT_LEN 512
+#define MEMPOOL_CACHE_SIZE 256
+#define I40E_FDIR_MBUF_NAME "FDIR_MBUF_POOL"
+
+ port->i40e_fdir_mp = rte_mempool_lookup(I40E_FDIR_MBUF_NAME);
+ if (port->i40e_fdir_mp == NULL) {
+ port->i40e_fdir_mp = rte_mempool_create(I40E_FDIR_MBUF_NAME,
+ I40E_FDIR_NB_MBUF, I40E_FDIR_MBUF_SIZE,
+ MEMPOOL_CACHE_SIZE,
+ sizeof(struct rte_pktmbuf_pool_private),
+ rte_pktmbuf_pool_init, NULL,
+ rte_pktmbuf_init, NULL,
+ 0, 0);
+
+ if (port->i40e_fdir_mp == NULL)
+ printf("error: Cannot init mbuf pool for"
+ "i40e flow director.\n");
+ }
+#endif /* RTE_LIBRTE_I40E_PMD */
if (nb_rxq > 1) {
port->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL;
port->dev_conf.rx_adv_conf.rss_conf.rss_hf = rss_hf;
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index ac86bfe..1e6d16f 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -73,6 +73,9 @@ int main(int argc, char **argv);
#define NUMA_NO_CONFIG 0xFF
#define UMA_NO_CONFIG 0xFF
+#define BYTES_PER_WORD 2
+#define IPV6_ADDR_LEN 16
+
typedef uint8_t lcoreid_t;
typedef uint8_t portid_t;
typedef uint16_t queueid_t;
@@ -155,6 +158,9 @@ struct rte_port {
uint8_t dcb_flag; /**< enable dcb */
struct rte_eth_rxconf rx_conf; /**< rx configuration */
struct rte_eth_txconf tx_conf; /**< tx configuration */
+#ifdef RTE_LIBRTE_I40E_PMD
+ struct rte_mempool *i40e_fdir_mp; /**< mempool used for fdir programing */
+#endif /* RTE_LIBRTE_I40E_PMD */
};
/**
@@ -352,6 +358,57 @@ extern uint32_t param_total_num_mbufs;
extern struct rte_fdir_conf fdir_conf;
+#ifdef RTE_LIBRTE_I40E_PMD
+struct ipv4_udp_flow {
+ uint32_t src_ip; /**< IPv4 source address to match. */
+ uint32_t dst_ip; /**< IPv4 destination address to match. */
+ uint16_t src_port; /**< UDP Source port to match. */
+ uint16_t dst_port; /**< UDP Destination port to match. */
+ uint8_t num_flexwords; /**< number of the flexwords. */
+ uint16_t flexwords[8]; /**< flexwords in payload. */
+};
+
+struct ipv4_tcp_flow {
+ uint32_t src_ip; /**< IPv4 source address to match. */
+ uint32_t dst_ip; /**< IPv4 destination address to match. */
+ uint16_t src_port; /**< TCP Source port to match. */
+ uint16_t dst_port; /**< TCP Destination port to match. */
+ uint8_t num_flexwords; /**< number of the flexwords. */
+ uint16_t flexwords[8]; /**< flexwords in payload. */
+};
+
+struct ipv4_other_flow {
+ uint32_t src_ip; /**< IPv4 source address to match. */
+ uint32_t dst_ip; /**< IPv4 destination address to match. */
+ uint8_t num_flexwords; /**< number of the flexwords. */
+ uint16_t flexwords[8]; /**< flexwords in payload. */
+};
+
+struct ipv6_udp_flow {
+ uint32_t src_ip[4]; /**< IPv6 source address to match. */
+ uint32_t dst_ip[4]; /**< IPv6 destination address to match. */
+ uint16_t src_port; /**< UDP Source port to match. */
+ uint16_t dst_port; /**< UDP Destination port to match. */
+ uint8_t num_flexwords; /**< number of the flexwords. */
+ uint16_t flexwords[8]; /**< flexwords in payload. */
+};
+
+struct ipv6_tcp_flow {
+ uint32_t src_ip[4]; /**< IPv6 source address to match. */
+ uint32_t dst_ip[4]; /**< IPv6 destination address to match. */
+ uint16_t src_port; /**< TCP Source port to match. */
+ uint16_t dst_port; /**< TCP Destination port to match. */
+ uint8_t num_flexwords; /**< number of the flexwords. */
+ uint16_t flexwords[8]; /**< flexwords in payload. */
+};
+
+struct ipv6_other_flow {
+ uint32_t src_ip[4]; /**< IPv6 source address to match. */
+ uint32_t dst_ip[4]; /**< IPv6 destination address to match. */
+ uint8_t num_flexwords; /**< number of the flexwords. */
+ uint16_t flexwords[8]; /**< flexwords in payload. */
+};
+#endif /* RTE_LIBRTE_I40E_PMD */
/*
* Configuration of packet segments used by the "txonly" processing engine.
*/
--
1.8.1.4
next prev parent reply other threads:[~2014-08-01 7:07 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-01 7:08 [dpdk-dev] [PATCH 0/6] Support flow director programming on fortville Jingjing Wu
2014-08-01 7:08 ` [dpdk-dev] [PATCH 1/6] i40e: flow director resource reserve and initialize on i40e Jingjing Wu
2014-08-01 7:08 ` [dpdk-dev] [PATCH 2/6] lib/librte_net: fix the Marco conflict Jingjing Wu
2014-08-01 7:08 ` [dpdk-dev] [PATCH 3/6] ethdev: define new ethdev API rx_classification_filter_ctl Jingjing Wu
2014-08-01 7:08 ` [dpdk-dev] [PATCH 4/6] i40e: function implement in i40e for flow director filter programming Jingjing Wu
2014-08-01 7:08 ` Jingjing Wu [this message]
2014-08-01 7:08 ` [dpdk-dev] [PATCH 6/6] i40e: support FD ID report and match counter for i40e flow director Jingjing Wu
2014-08-15 1:33 ` [dpdk-dev] [PATCH 0/6] Support flow director programming on fortville Cao, Min
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1406876916-24869-6-git-send-email-jingjing.wu@intel.com \
--to=jingjing.wu@intel.com \
--cc=dev@dpdk.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).