From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 771F5255 for ; Fri, 30 Jan 2015 05:48:33 +0100 (CET) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga103.fm.intel.com with ESMTP; 29 Jan 2015 20:42:15 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.09,490,1418112000"; d="scan'208";a="520020187" Received: from shvmail01.sh.intel.com ([10.239.29.42]) by orsmga003.jf.intel.com with ESMTP; 29 Jan 2015 20:41:13 -0800 Received: from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com [10.239.29.89]) by shvmail01.sh.intel.com with ESMTP id t0U4mRG5026090; Fri, 30 Jan 2015 12:48:27 +0800 Received: from shecgisg004.sh.intel.com (localhost [127.0.0.1]) by shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP id t0U4mQHa015343; Fri, 30 Jan 2015 12:48:28 +0800 Received: (from zzang@localhost) by shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id t0U4mQGe015339; Fri, 30 Jan 2015 12:48:26 +0800 From: zhida zang To: dev@dpdk.org Date: Fri, 30 Jan 2015 12:48:23 +0800 Message-Id: <1422593303-15308-1-git-send-email-zhida.zang@intel.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: References: Subject: [dpdk-dev] [PATCH] igb: integrate flex filter to new API X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 30 Jan 2015 04:48:35 -0000 changes: igb: remove old functions that deal with flex filter igb: add new functions that deal with flex filter(fit for new API) testpmd: change the entry for flex filter in cmdline testpmd: change function call to get flex filter in config doc: change doc that describes how to use flex filter related functions Signed-off-by: Zhida Zang --- app/test-pmd/cmdline.c | 244 ++++++++++---------- app/test-pmd/config.c | 37 ++-- app/test-pmd/testpmd.h | 2 +- doc/guides/testpmd_app_ug/testpmd_funcs.rst | 56 ++--- lib/librte_ether/rte_eth_ctrl.h | 20 ++ lib/librte_pmd_e1000/e1000_ethdev.h | 20 ++ lib/librte_pmd_e1000/igb_ethdev.c | 331 +++++++++++++++++----------- 7 files changed, 410 insertions(+), 300 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 4beb404..2f99d23 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -691,14 +691,19 @@ static void cmd_help_long_parsed(void *parsed_result, "get_syn_filter (port_id) " " get syn filter info.\n\n" - "add_flex_filter (port_id) len (len_value) bytes (bytes_string) mask (mask_value)" - " priority (prio_value) queue (queue_id) index (idx)\n" + "flex_filter add (port_id) len (len_value)" + " bytes (bytes_string) mask (mask_value)" + " priority (prio_value) queue (queue_id)\n" " add a flex filter.\n\n" - "remove_flex_filter (port_id) index (idx)\n" - " remove a flex filter.\n\n" + "flex_filter del (port_id) len (len_value)" + " bytes (bytes_string) mask (mask_value)" + " priority (prio_value)\n" + " del a flex filter.\n\n" - "get_flex_filter (port_id) index (idx)\n" + "flex_filter get (port_id) len (len_value)" + " bytes (bytes_string) mask (mask_value)" + "priority (prio_value)\n" " get info of a flex filter.\n\n" "flow_director_filter (port_id) (add|del)" @@ -7723,9 +7728,10 @@ cmdline_parse_inst_t cmd_get_5tuple_filter = { }, }; -/* *** ADD/REMOVE A flex FILTER *** */ +/* *** Add/Del/Get flex filter *** */ struct cmd_flex_filter_result { cmdline_fixed_string_t filter; + cmdline_fixed_string_t ops; uint8_t port_id; cmdline_fixed_string_t len; uint8_t len_value; @@ -7737,8 +7743,6 @@ struct cmd_flex_filter_result { uint8_t priority_value; cmdline_fixed_string_t queue; uint16_t queue_id; - cmdline_fixed_string_t index; - uint16_t index_value; }; static int xdigit2val(unsigned char c) @@ -7759,105 +7763,101 @@ cmd_flex_filter_parsed(void *parsed_result, __attribute__((unused)) void *data) { int ret = 0; - struct rte_flex_filter filter; + struct rte_eth_flex_filter filter; struct cmd_flex_filter_result *res = parsed_result; char *bytes_ptr, *mask_ptr; uint16_t len, i, j; char c; - int val, mod = 0; - uint32_t dword = 0; + int val; uint8_t byte = 0; uint8_t hex = 0; - if (!strcmp(res->filter, "add_flex_filter")) { - if (res->len_value > 128) { - printf("the len exceed the max length 128\n"); - return; - } - memset(&filter, 0, sizeof(struct rte_flex_filter)); - filter.len = res->len_value; - filter.priority = res->priority_value; - bytes_ptr = res->bytes_value; - mask_ptr = res->mask_value; - - j = 0; - /* translate bytes string to uint_32 array. */ - if (bytes_ptr[0] == '0' && ((bytes_ptr[1] == 'x') || - (bytes_ptr[1] == 'X'))) - bytes_ptr += 2; - len = strnlen(bytes_ptr, res->len_value * 2); - if (len == 0 || (len % 8 != 0)) { - printf("please check len and bytes input\n"); + if (res->len_value > 128) { + printf("the len exceed the max length 128\n"); + return; + } + memset(&filter, 0, sizeof(struct rte_eth_flex_filter)); + filter.len = res->len_value; + filter.priority = res->priority_value; + filter.queue = res->queue_id; + bytes_ptr = res->bytes_value; + mask_ptr = res->mask_value; + + j = 0; + /* translate bytes string to uint_32 array. */ + if (bytes_ptr[0] == '0' && ((bytes_ptr[1] == 'x') || + (bytes_ptr[1] == 'X'))) + bytes_ptr += 2; + len = strnlen(bytes_ptr, res->len_value * 2); + if (len == 0 || (len % 8 != 0)) { + printf("please check len and bytes input\n"); + return; + } + for (i = 0; i < len; i++) { + c = bytes_ptr[i]; + if (isxdigit(c) == 0) { + /* invalid characters. */ + printf("invalid input\n"); return; } - for (i = 0; i < len; i++) { - c = bytes_ptr[i]; - if (isxdigit(c) == 0) { - /* invalid characters. */ - printf("invalid input\n"); - return; - } - val = xdigit2val(c); - mod = i % 8; - if (i % 2) { - byte |= val; - dword |= byte << (4 * mod - 4); - byte = 0; - } else - byte |= val << 4; - if (mod == 7) { - filter.dwords[j] = dword; - printf("dwords[%d]:%08x ", j, filter.dwords[j]); - j++; - dword = 0; - } - } - printf("\n"); - /* translate mask string to uint8_t array. */ - j = 0; - if (mask_ptr[0] == '0' && ((mask_ptr[1] == 'x') || - (mask_ptr[1] == 'X'))) - mask_ptr += 2; - len = strnlen(mask_ptr, (res->len_value+3)/4); - if (len == 0) { + val = xdigit2val(c); + if (i % 2) { + byte |= val; + filter.bytes[j] = byte; + printf("bytes[%d]:%02x ", j, filter.bytes[j]); + j++; + byte = 0; + } else + byte |= val << 4; + } + printf("\n"); + /* translate mask string to uint8_t array. */ + j = 0; + if (mask_ptr[0] == '0' && ((mask_ptr[1] == 'x') || + (mask_ptr[1] == 'X'))) + mask_ptr += 2; + len = strnlen(mask_ptr, (res->len_value+3)/4); + if (len == 0) { + printf("invalid input\n"); + return; + } + for (i = 0; i < len; i++) { + c = mask_ptr[i]; + if (isxdigit(c) == 0) { + /* invalid characters. */ printf("invalid input\n"); return; } - for (i = 0; i < len; i++) { - c = mask_ptr[i]; - if (isxdigit(c) == 0) { - /* invalid characters. */ - printf("invalid input\n"); - return; - } - val = xdigit2val(c); - hex |= (uint8_t)(val & 0x8) >> 3; - hex |= (uint8_t)(val & 0x4) >> 1; - hex |= (uint8_t)(val & 0x2) << 1; - hex |= (uint8_t)(val & 0x1) << 3; - if (i % 2) { - byte |= hex << 4; - filter.mask[j] = byte; - printf("mask[%d]:%02x ", j, filter.mask[j]); - j++; - byte = 0; - } else - byte |= hex; - hex = 0; - } - printf("\n"); - printf("call function rte_eth_dev_add_flex_filter: " - "index = %d, queue-id = %d, len = %d, priority = %d\n", - res->index_value, res->queue_id, - filter.len, filter.priority); - ret = rte_eth_dev_add_flex_filter(res->port_id, res->index_value, - &filter, res->queue_id); + val = xdigit2val(c); + hex |= (uint8_t)(val & 0x8) >> 3; + hex |= (uint8_t)(val & 0x4) >> 1; + hex |= (uint8_t)(val & 0x2) << 1; + hex |= (uint8_t)(val & 0x1) << 3; + if (i % 2) { + byte |= hex << 4; + filter.mask[j] = byte; + printf("mask[%d]:%02x ", j, filter.mask[j]); + j++; + byte = 0; + } else + byte |= hex; + hex = 0; + } + printf("\n"); - } else if (!strcmp(res->filter, "remove_flex_filter")) - ret = rte_eth_dev_remove_flex_filter(res->port_id, - res->index_value); - else if (!strcmp(res->filter, "get_flex_filter")) - get_flex_filter(res->port_id, res->index_value); + if (!strcmp(res->ops, "add")) + ret = rte_eth_dev_filter_ctrl(res->port_id, + RTE_ETH_FILTER_FLEXIBLE, + RTE_ETH_FILTER_ADD, + &filter); + + else if (!strcmp(res->ops, "del")) + ret = rte_eth_dev_filter_ctrl(res->port_id, + RTE_ETH_FILTER_FLEXIBLE, + RTE_ETH_FILTER_DELETE, + &filter); + else if (!strcmp(res->ops, "get")) + get_flex_filter(res->port_id, &filter); if (ret < 0) printf("flex filter setting error: (%s)\n", strerror(-ret)); @@ -7896,21 +7896,25 @@ cmdline_parse_token_string_t cmd_flex_filter_queue = cmdline_parse_token_num_t cmd_flex_filter_queue_id = TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result, queue_id, UINT16); -cmdline_parse_token_string_t cmd_flex_filter_index = +cmdline_parse_token_string_t cmd_flex_filter_add = TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result, - index, "index"); -cmdline_parse_token_num_t cmd_flex_filter_index_value = - TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result, - index_value, UINT16); -cmdline_parse_token_string_t cmd_flex_filter_add_filter = + ops, "add"); +cmdline_parse_token_string_t cmd_flex_filter_del = + TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result, + ops, "del"); +cmdline_parse_token_string_t cmd_flex_filter_get = TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result, - filter, "add_flex_filter"); + ops, "get"); +cmdline_parse_token_string_t cmd_flex_filter_filter = + TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result, + filter, "flex_filter"); cmdline_parse_inst_t cmd_add_flex_filter = { .f = cmd_flex_filter_parsed, .data = NULL, .help_str = "add a flex filter", .tokens = { - (void *)&cmd_flex_filter_add_filter, + (void *)&cmd_flex_filter_filter, + (void *)&cmd_flex_filter_add, (void *)&cmd_flex_filter_port_id, (void *)&cmd_flex_filter_len, (void *)&cmd_flex_filter_len_value, @@ -7922,40 +7926,44 @@ cmdline_parse_inst_t cmd_add_flex_filter = { (void *)&cmd_flex_filter_priority_value, (void *)&cmd_flex_filter_queue, (void *)&cmd_flex_filter_queue_id, - (void *)&cmd_flex_filter_index, - (void *)&cmd_flex_filter_index_value, NULL, }, }; - -cmdline_parse_token_string_t cmd_flex_filter_remove_filter = - TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result, - filter, "remove_flex_filter"); cmdline_parse_inst_t cmd_remove_flex_filter = { .f = cmd_flex_filter_parsed, .data = NULL, .help_str = "remove a flex filter", .tokens = { - (void *)&cmd_flex_filter_remove_filter, + (void *)&cmd_flex_filter_filter, + (void *)&cmd_flex_filter_del, (void *)&cmd_flex_filter_port_id, - (void *)&cmd_flex_filter_index, - (void *)&cmd_flex_filter_index_value, + (void *)&cmd_flex_filter_len, + (void *)&cmd_flex_filter_len_value, + (void *)&cmd_flex_filter_bytes, + (void *)&cmd_flex_filter_bytes_value, + (void *)&cmd_flex_filter_mask, + (void *)&cmd_flex_filter_mask_value, + (void *)&cmd_flex_filter_priority, + (void *)&cmd_flex_filter_priority_value, NULL, }, }; - -cmdline_parse_token_string_t cmd_flex_filter_get_filter = - TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result, - filter, "get_flex_filter"); cmdline_parse_inst_t cmd_get_flex_filter = { .f = cmd_flex_filter_parsed, .data = NULL, .help_str = "get a flex filter", .tokens = { - (void *)&cmd_flex_filter_get_filter, + (void *)&cmd_flex_filter_filter, + (void *)&cmd_flex_filter_get, (void *)&cmd_flex_filter_port_id, - (void *)&cmd_flex_filter_index, - (void *)&cmd_flex_filter_index_value, + (void *)&cmd_flex_filter_len, + (void *)&cmd_flex_filter_len_value, + (void *)&cmd_flex_filter_bytes, + (void *)&cmd_flex_filter_bytes_value, + (void *)&cmd_flex_filter_mask, + (void *)&cmd_flex_filter_mask_value, + (void *)&cmd_flex_filter_priority, + (void *)&cmd_flex_filter_priority_value, NULL, }, }; diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index c40f819..8a44e4a 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -2252,36 +2252,43 @@ get_5tuple_filter(uint8_t port_id, uint16_t index) filter.priority, filter.tcp_flags, rx_queue); } } -void -get_flex_filter(uint8_t port_id, uint16_t index) +void +get_flex_filter(uint8_t port_id, struct rte_eth_flex_filter *filter) { - struct rte_flex_filter filter; + struct rte_eth_flex_filter flex_filter; int ret = 0; - uint16_t rx_queue; int i, j; - memset(&filter, 0, sizeof(filter)); - ret = rte_eth_dev_get_flex_filter(port_id, index, - &filter, &rx_queue); + memset(&flex_filter, 0, sizeof(flex_filter)); + flex_filter.len = filter->len; + memcpy(flex_filter.bytes, filter->bytes, 128); + memcpy(flex_filter.mask, filter->mask, 16); + flex_filter.priority = filter->priority; + ret = rte_eth_dev_filter_ctrl(port_id, + RTE_ETH_FILTER_FLEXIBLE, + RTE_ETH_FILTER_GET, + &flex_filter); if (ret < 0) { if (ret == (-ENOENT)) - printf("filter[%d] is not enabled\n", index); + printf("filter does not exist\n"); else printf("get flex filter fails(%s)\n", strerror(-ret)); return; } else { - printf("filter[%d]: ", index); - printf("\n length: %d", filter.len); - printf("\n dword[]: 0x"); - for (i = 0; i < 32; i++) - printf("%08x ", (unsigned)rte_be_to_cpu_32(filter.dwords[i])); + printf("filter: "); + printf("\n length: %d", flex_filter.len); + printf("\n byte[]: 0x"); + for (i = 0; i < 8; i++) + printf("%02x ", + (unsigned)flex_filter.bytes[i]); printf("\n mask[]: 0b"); for (i = 0; i < 16; i++) { for (j = 0; j < 8; j++) - printf("%c", (filter.mask[i] & (1 << j)) ? '1' : '0'); + printf("%c", (flex_filter.mask[i] & (1 << j)) + ? '1' : '0'); } printf("\n priority: %d queue: %d\n", - filter.priority, rx_queue); + flex_filter.priority, flex_filter.queue); } } diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 8f5e6c7..3f9697f 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -557,7 +557,7 @@ void get_syn_filter(uint8_t port_id); void get_ethertype_filter(uint8_t port_id, uint16_t index); void get_2tuple_filter(uint8_t port_id, uint16_t index); void get_5tuple_filter(uint8_t port_id, uint16_t index); -void get_flex_filter(uint8_t port_id, uint16_t index); +void get_flex_filter(uint8_t port_id, struct rte_eth_flex_filter *filter); int port_id_is_invalid(portid_t port_id); int rx_queue_id_is_invalid(queueid_t rxq_id); int tx_queue_id_is_invalid(queueid_t txq_id); diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index 218835a..0324fc3 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -1595,15 +1595,18 @@ Example: syn filter: on, priority: high, queue: 3 -add_flex_filter +flex_filter ~~~~~~~~~~~~~~~ Add a Flex filter, which recognizes any arbitrary pattern within the first 128 bytes of the packet and routes packets into one of the receive queues. +or +Del(get) a Flex filter, +which recognizes any arbitrary pattern within the first 128 bytes of the packet -add_flex_filter (port_id) len (len_value) bytes (bytes_string) mask (mask_value) -priority (prio_value) queue (queue_id) index (idx) +flex_filter (add|del|get) (port_id) len (len_value) bytes (bytes_string) +mask (mask_value) priority (prio_value) [queue (queue_id)] The available information parameters are: @@ -1617,49 +1620,18 @@ The available information parameters are: * prio_value: the priority of this filter. -* queue_id: The receive queue associated with this Flex filter. - -* index: the index of this Flex filter +* queue_id: The receive queue associated with this Flex filter.(used when add +while del|get not) Example: .. code-block:: console - testpmd> add_flex_filter 0 len 16 bytes 0x00000000000000000000000008060000 mask 000C priority 3 queue 3 index 0 - -Assign a packet whose 13th and 14th bytes are 0x0806 to queue 3. - -remove_flex_filter -~~~~~~~~~~~~~~~~~~ - -Remove a Flex filter + testpmd> flex_filter add 0 len 16 bytes 0x00000000000000000000000008060000 + mask 000C priority 3 queue 3 -remove_flex_filter (port_id) index (idx) + testpmd> flex_filter del 0 len 16 bytes 0x00000000000000000000000008060000 + mask 000C priority 3 -get_flex_filter -~~~~~~~~~~~~~~~ - -Get and display a Flex filter - -get_flex_filter (port_id) index (idx) - -Example: - -.. code-block:: console - - testpmd> get_flex_filter 0 index 0 - - filter[0]: - - length: 16 - - dword[]: 0x00000000 00000000 00000000 08060000 00000000 00000000 00000000 - 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - - mask[]: - 0b0000000000001100000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000 - - priority: 3 queue: 3 + testpmd> flex_filter get 0 len 16 bytes 0x00000000000000000000000008060000 + mask 000C priority 3 diff --git a/lib/librte_ether/rte_eth_ctrl.h b/lib/librte_ether/rte_eth_ctrl.h index 5d9c387..03c6b66 100644 --- a/lib/librte_ether/rte_eth_ctrl.h +++ b/lib/librte_ether/rte_eth_ctrl.h @@ -55,6 +55,7 @@ enum rte_filter_type { RTE_ETH_FILTER_ETHERTYPE, RTE_ETH_FILTER_TUNNEL, RTE_ETH_FILTER_FDIR, + RTE_ETH_FILTER_FLEXIBLE, RTE_ETH_FILTER_MAX }; @@ -116,6 +117,25 @@ struct rte_eth_ethertype_filter { uint16_t queue; /**< Queue assigned to when match*/ }; +#define RTE_FLEX_FILTER_MAXLEN 128 /**< bytes to use in flex filter. */ +#define RTE_FLEX_FILTER_MASK_SIZE \ + (RTE_ALIGN(RTE_FLEX_FILTER_MAXLEN, sizeof(char)) / sizeof(char)) + /**< mask bytes in flex filter. */ + +/** + * A structure used to define the flex filter entry + * to support RTE_ETH_FILTER_FLEXIBLE with RTE_ETH_FILTER_ADD, + * RTE_ETH_FILTER_DELETE and RTE_ETH_FILTER_GET operations. + */ +struct rte_eth_flex_filter { + uint16_t len; + uint8_t bytes[RTE_FLEX_FILTER_MAXLEN]; /**< flex bytes in big endian.*/ + uint8_t mask[RTE_FLEX_FILTER_MASK_SIZE]; /**< if mask bit is 1b, do + not compare corresponding byte. */ + uint8_t priority; + uint16_t queue; /**< Queue assigned to when match. */ +}; + /** * Tunneled type. */ diff --git a/lib/librte_pmd_e1000/e1000_ethdev.h b/lib/librte_pmd_e1000/e1000_ethdev.h index d155e77..c054aaf 100644 --- a/lib/librte_pmd_e1000/e1000_ethdev.h +++ b/lib/librte_pmd_e1000/e1000_ethdev.h @@ -131,6 +131,24 @@ struct e1000_vf_info { uint16_t tx_rate; }; +TAILQ_HEAD(e1000_flex_filter_list, e1000_flex_filter); + +struct e1000_flex_filter_info { + uint16_t len; + uint32_t dwords[32]; /**< flex bytes in big endian. */ + uint8_t mask[16]; /**< if mask bit is 1b, do not compare + corresponding byte in dwords. */ + uint8_t priority; +}; + +/* Flex filter structure */ +struct e1000_flex_filter { + TAILQ_ENTRY(e1000_flex_filter) entries; + uint16_t index; /* index of flex filter */ + struct e1000_flex_filter_info filter_info; + uint16_t queue; /* rx queue assigned to */ +}; + /* * Structure to store filters' info. */ @@ -138,6 +156,8 @@ struct e1000_filter_info { uint8_t ethertype_mask; /* Bit mask for every used ethertype filter */ /* store used ethertype filters*/ uint16_t ethertype_filters[E1000_MAX_ETQF_FILTERS]; + uint8_t flex_mask; /* Bit mask for every used flex filter */ + struct e1000_flex_filter_list flex_list; }; /* diff --git a/lib/librte_pmd_e1000/igb_ethdev.c b/lib/librte_pmd_e1000/igb_ethdev.c index 2a268b8..eaa8689 100644 --- a/lib/librte_pmd_e1000/igb_ethdev.c +++ b/lib/librte_pmd_e1000/igb_ethdev.c @@ -162,14 +162,14 @@ static int eth_igb_remove_2tuple_filter(struct rte_eth_dev *dev, static int eth_igb_get_2tuple_filter(struct rte_eth_dev *dev, uint16_t index, struct rte_2tuple_filter *filter, uint16_t *rx_queue); -static int eth_igb_add_flex_filter(struct rte_eth_dev *dev, - uint16_t index, - struct rte_flex_filter *filter, uint16_t rx_queue); -static int eth_igb_remove_flex_filter(struct rte_eth_dev *dev, - uint16_t index); -static int eth_igb_get_flex_filter(struct rte_eth_dev *dev, - uint16_t index, - struct rte_flex_filter *filter, uint16_t *rx_queue); +static int eth_igb_flex_filter_set(struct rte_eth_dev *dev, + struct rte_eth_flex_filter *filter, + bool add); +static int eth_igb_flex_filter_get(struct rte_eth_dev *dev, + struct rte_eth_flex_filter *filter); +static int eth_igb_flex_filter_handle(struct rte_eth_dev *dev, + enum rte_filter_op filter_op, + void *arg); static int eth_igb_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index, struct rte_5tuple_filter *filter, uint16_t rx_queue); @@ -271,9 +271,6 @@ static struct eth_dev_ops eth_igb_ops = { .add_2tuple_filter = eth_igb_add_2tuple_filter, .remove_2tuple_filter = eth_igb_remove_2tuple_filter, .get_2tuple_filter = eth_igb_get_2tuple_filter, - .add_flex_filter = eth_igb_add_flex_filter, - .remove_flex_filter = eth_igb_remove_flex_filter, - .get_flex_filter = eth_igb_get_flex_filter, .add_5tuple_filter = eth_igb_add_5tuple_filter, .remove_5tuple_filter = eth_igb_remove_5tuple_filter, .get_5tuple_filter = eth_igb_get_5tuple_filter, @@ -470,6 +467,8 @@ eth_igb_dev_init(__attribute__((unused)) struct eth_driver *eth_drv, E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); struct e1000_vfta * shadow_vfta = E1000_DEV_PRIVATE_TO_VFTA(eth_dev->data->dev_private); + struct e1000_filter_info *filter_info = + E1000_DEV_PRIVATE_TO_FILTER_INFO(eth_dev->data->dev_private); uint32_t ctrl_ext; pci_dev = eth_dev->pci_dev; @@ -601,6 +600,9 @@ eth_igb_dev_init(__attribute__((unused)) struct eth_driver *eth_drv, /* enable support intr */ igb_intr_enable(eth_dev); + TAILQ_INIT(&filter_info->flex_list); + filter_info->flex_mask = 0; + return 0; err_late: @@ -926,7 +928,10 @@ static void eth_igb_stop(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct e1000_filter_info *filter_info = + E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); struct rte_eth_link link; + struct e1000_flex_filter *p_flex; igb_intr_disable(hw); igb_pf_reset_hw(hw); @@ -949,6 +954,13 @@ eth_igb_stop(struct rte_eth_dev *dev) /* clear the recorded link status */ memset(&link, 0, sizeof(link)); rte_igb_dev_atomic_write_link_status(dev, &link); + + /* Remove all flex filters of the device */ + while ((p_flex = TAILQ_FIRST(&filter_info->flex_list))) { + TAILQ_REMOVE(&filter_info->flex_list, p_flex, entries); + rte_free(p_flex); + } + filter_info->flex_mask = 0; } static void @@ -2652,161 +2664,229 @@ eth_igb_get_2tuple_filter(struct rte_eth_dev *dev, uint16_t index, return -ENOENT; } -/* - * add a flex filter - * - * @param - * dev: Pointer to struct rte_eth_dev. - * index: the index the filter allocates. - * filter: ponter to the filter that will be added. - * rx_queue: the queue id the filter assigned to. - * - * @return - * - On success, zero. - * - On failure, a negative value. +/* add/del/get a flex filter */ +static inline struct e1000_flex_filter * +eth_igb_flex_filter_lookup(struct e1000_flex_filter_list *filter_list, + struct e1000_flex_filter_info *key) +{ + struct e1000_flex_filter *it; + + TAILQ_FOREACH(it, filter_list, entries) { + if (memcmp(key, &it->filter_info, + sizeof(struct e1000_flex_filter_info)) == 0) + return it; + } + + return NULL; +} + static int -eth_igb_add_flex_filter(struct rte_eth_dev *dev, uint16_t index, - struct rte_flex_filter *filter, uint16_t rx_queue) +eth_igb_flex_filter_set(struct rte_eth_dev *dev, + struct rte_eth_flex_filter *filter, + bool add) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct e1000_filter_info *filter_info = + E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); + struct e1000_flex_filter *flex_filter, *it; uint32_t wufc, en_bits = 0; uint32_t queueing = 0; uint32_t reg_off = 0; uint8_t i, j = 0; - MAC_TYPE_FILTER_SUP_EXT(hw->mac.type); - - if (index >= E1000_MAX_FLEXIBLE_FILTERS) - return -EINVAL; /* filter index is out of range. */ + flex_filter = rte_zmalloc("e1000_flex_filter", + sizeof(struct e1000_flex_filter), 0); + if (flex_filter == NULL) + return -ENOMEM; - if (filter->len == 0 || filter->len > E1000_MAX_FLEX_FILTER_LEN || - filter->len % 8 != 0 || - filter->priority > E1000_MAX_FLEX_FILTER_PRI) - return -EINVAL; + flex_filter->filter_info.len = filter->len; + flex_filter->filter_info.priority = filter->priority; + memcpy(flex_filter->filter_info.dwords, filter->bytes, filter->len); + memcpy(flex_filter->filter_info.mask, filter->mask, + RTE_ALIGN(filter->len, sizeof(char)) / sizeof(char)); wufc = E1000_READ_REG(hw, E1000_WUFC); - en_bits = E1000_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << index); - if ((wufc & en_bits) == en_bits) - return -EINVAL; /* the filter is in use. */ + if (flex_filter->index < E1000_MAX_FHFT) + reg_off = E1000_FHFT(flex_filter->index); + else + reg_off = E1000_FHFT_EXT(flex_filter->index - E1000_MAX_FHFT); - E1000_WRITE_REG(hw, E1000_WUFC, - wufc | E1000_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << index)); + if (add) { + if (filter->len == 0 || filter->len > E1000_MAX_FLEX_FILTER_LEN + || filter->len % 8 != 0 || + filter->priority > E1000_MAX_FLEX_FILTER_PRI) + return -EINVAL; + + if (eth_igb_flex_filter_lookup(&filter_info->flex_list, + &flex_filter->filter_info) != NULL) { + PMD_DRV_LOG(ERR, "filter exists."); + rte_free(flex_filter); + return -EEXIST; + } - j = 0; - if (index < E1000_MAX_FHFT) - reg_off = E1000_FHFT(index); - else - reg_off = E1000_FHFT_EXT(index - E1000_MAX_FHFT); - - for (i = 0; i < 16; i++) { - E1000_WRITE_REG(hw, reg_off + i*4*4, filter->dwords[j]); - E1000_WRITE_REG(hw, reg_off + (i*4+1)*4, filter->dwords[++j]); - E1000_WRITE_REG(hw, reg_off + (i*4+2)*4, - (uint32_t)filter->mask[i]); - ++j; - } - queueing |= filter->len | - (rx_queue << E1000_FHFT_QUEUEING_QUEUE_SHIFT) | - (filter->priority << E1000_FHFT_QUEUEING_PRIO_SHIFT); - E1000_WRITE_REG(hw, reg_off + E1000_FHFT_QUEUEING_OFFSET, queueing); - return 0; -} + flex_filter->queue = filter->queue; -/* - * remove a flex filter - * - * @param - * dev: Pointer to struct rte_eth_dev. - * index: the index the filter allocates. - * - * @return - * - On success, zero. - * - On failure, a negative value. - */ -static int -eth_igb_remove_flex_filter(struct rte_eth_dev *dev, - uint16_t index) -{ - struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t wufc, reg_off = 0; - uint8_t i; + /* + * look for an unused flex filter index + * and insert the filter into the list. + */ + for (i = 0; i < E1000_MAX_FLEXIBLE_FILTERS; i++) { + if (!(filter_info->flex_mask & (1 << i))) { + filter_info->flex_mask |= 1 << i; + flex_filter->index = i; + TAILQ_INSERT_TAIL(&filter_info->flex_list, + flex_filter, + entries); + break; + } + } + if (i >= E1000_MAX_FLEXIBLE_FILTERS) { + PMD_DRV_LOG(ERR, "flex filters are full."); + rte_free(flex_filter); + return -ENOSYS; + } - MAC_TYPE_FILTER_SUP_EXT(hw->mac.type); + en_bits = E1000_WUFC_FLEX_HQ | + (E1000_WUFC_FLX0 << flex_filter->index); + if ((wufc & en_bits) == en_bits) + return -EINVAL; /* the filter is in use. */ - if (index >= E1000_MAX_FLEXIBLE_FILTERS) - return -EINVAL; /* filter index is out of range. */ + E1000_WRITE_REG(hw, E1000_WUFC, wufc | E1000_WUFC_FLEX_HQ | + (E1000_WUFC_FLX0 << flex_filter->index)); - wufc = E1000_READ_REG(hw, E1000_WUFC); - E1000_WRITE_REG(hw, E1000_WUFC, wufc & (~(E1000_WUFC_FLX0 << index))); + j = 0; - if (index < E1000_MAX_FHFT) - reg_off = E1000_FHFT(index); - else - reg_off = E1000_FHFT_EXT(index - E1000_MAX_FHFT); - for (i = 0; i < 64; i++) - E1000_WRITE_REG(hw, reg_off + i*4, 0); + for (i = 0; i < 16; i++) { + E1000_WRITE_REG(hw, reg_off + i*4*4, + flex_filter->filter_info.dwords[j]); + E1000_WRITE_REG(hw, reg_off + (i*4+1)*4, + flex_filter->filter_info.dwords[++j]); + E1000_WRITE_REG(hw, reg_off + (i*4+2)*4, + (uint32_t)filter->mask[i]); + ++j; + } + queueing |= filter->len | + (filter->queue << E1000_FHFT_QUEUEING_QUEUE_SHIFT) | + (filter->priority << E1000_FHFT_QUEUEING_PRIO_SHIFT); + E1000_WRITE_REG(hw, reg_off + E1000_FHFT_QUEUEING_OFFSET, + queueing); + } else { + it = eth_igb_flex_filter_lookup(&filter_info->flex_list, + &flex_filter->filter_info); + if (it == NULL) { + PMD_DRV_LOG(ERR, "filter doesn't exist."); + rte_free(flex_filter); + return -ENOENT; + } + + E1000_WRITE_REG(hw, E1000_WUFC, wufc & + (~(E1000_WUFC_FLX0 << it->index))); + + for (i = 0; i < 64; i++) + E1000_WRITE_REG(hw, reg_off + i*4, 0); + + filter_info->flex_mask &= ~(1 << it->index); + TAILQ_REMOVE(&filter_info->flex_list, it, entries); + rte_free(it); + rte_free(flex_filter); + } + return 0; } -/* - * get a flex filter - * - * @param - * dev: Pointer to struct rte_eth_dev. - * index: the index the filter allocates. - * filter: ponter to the filter that returns. - * *rx_queue: the pointer of the queue id the filter assigned to. - * - * @return - * - On success, zero. - * - On failure, a negative value. - */ static int -eth_igb_get_flex_filter(struct rte_eth_dev *dev, uint16_t index, - struct rte_flex_filter *filter, uint16_t *rx_queue) +eth_igb_flex_filter_get(struct rte_eth_dev *dev, + struct rte_eth_flex_filter *filter) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct e1000_filter_info *filter_info = + E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); + struct e1000_flex_filter flex_filter, *it; uint32_t wufc, queueing, wufc_en = 0; - uint8_t i, j; - - MAC_TYPE_FILTER_SUP_EXT(hw->mac.type); - if (index >= E1000_MAX_FLEXIBLE_FILTERS) - return -EINVAL; /* filter index is out of range. */ + memset(&flex_filter, 0, sizeof(struct e1000_flex_filter)); + flex_filter.filter_info.len = filter->len; + flex_filter.filter_info.priority = filter->priority; + memcpy(flex_filter.filter_info.dwords, filter->bytes, filter->len); + memcpy(flex_filter.filter_info.mask, filter->mask, + RTE_ALIGN(filter->len, sizeof(char)) / sizeof(char)); + + it = eth_igb_flex_filter_lookup(&filter_info->flex_list, + &flex_filter.filter_info); + if (it == NULL) { + PMD_DRV_LOG(ERR, "filter doesn't exist."); + return -ENOENT; + } wufc = E1000_READ_REG(hw, E1000_WUFC); - wufc_en = E1000_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << index); + wufc_en = E1000_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << it->index); if ((wufc & wufc_en) == wufc_en) { uint32_t reg_off = 0; - j = 0; - if (index < E1000_MAX_FHFT) - reg_off = E1000_FHFT(index); + if (it->index < E1000_MAX_FHFT) + reg_off = E1000_FHFT(it->index); else - reg_off = E1000_FHFT_EXT(index - E1000_MAX_FHFT); - - for (i = 0; i < 16; i++, j = i * 2) { - filter->dwords[j] = - E1000_READ_REG(hw, reg_off + i*4*4); - filter->dwords[j+1] = - E1000_READ_REG(hw, reg_off + (i*4+1)*4); - filter->mask[i] = - E1000_READ_REG(hw, reg_off + (i*4+2)*4); - } + reg_off = E1000_FHFT_EXT(it->index - E1000_MAX_FHFT); + queueing = E1000_READ_REG(hw, reg_off + E1000_FHFT_QUEUEING_OFFSET); - filter->len = queueing & E1000_FHFT_QUEUEING_LEN; - filter->priority = (queueing & E1000_FHFT_QUEUEING_PRIO) >> - E1000_FHFT_QUEUEING_PRIO_SHIFT; - *rx_queue = (queueing & E1000_FHFT_QUEUEING_QUEUE) >> + filter->queue = (queueing & E1000_FHFT_QUEUEING_QUEUE) >> E1000_FHFT_QUEUEING_QUEUE_SHIFT; return 0; } return -ENOENT; } +static int +eth_igb_flex_filter_handle(struct rte_eth_dev *dev, + enum rte_filter_op filter_op, + void *arg) +{ + struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int ret = 0; + + MAC_TYPE_FILTER_SUP(hw->mac.type); + + if (filter_op == RTE_ETH_FILTER_NOP) + return ret; + + if (arg == NULL) { + PMD_DRV_LOG(ERR, "arg shouldn't be NULL for operation %u", + filter_op); + return -EINVAL; + } + + if (((struct rte_eth_flex_filter *)arg)->len == 0) { + PMD_DRV_LOG(ERR, "filter length shouldn't be 0"); + return -EINVAL; + } + + switch (filter_op) { + case RTE_ETH_FILTER_ADD: + ret = eth_igb_flex_filter_set(dev, + (struct rte_eth_flex_filter *)arg, + TRUE); + break; + case RTE_ETH_FILTER_DELETE: + ret = eth_igb_flex_filter_set(dev, + (struct rte_eth_flex_filter *)arg, + FALSE); + break; + case RTE_ETH_FILTER_GET: + ret = eth_igb_flex_filter_get(dev, + (struct rte_eth_flex_filter *)arg); + break; + default: + PMD_DRV_LOG(ERR, "unsupported operation %u\n", filter_op); + ret = -ENOSYS; + break; + } + + return ret; +} + /* * add a 5tuple filter * @@ -3237,6 +3317,9 @@ eth_igb_filter_ctrl(struct rte_eth_dev *dev, case RTE_ETH_FILTER_ETHERTYPE: ret = igb_ethertype_filter_handle(dev, filter_op, arg); break; + case RTE_ETH_FILTER_FLEXIBLE: + ret = eth_igb_flex_filter_handle(dev, filter_op, arg); + break; default: PMD_DRV_LOG(WARNING, "Filter type (%d) not supported", filter_type); -- 1.9.3