* [PATCH v4 06/17] net/i40e: restore flow director filter
From: Beilei Xing @ 2016-12-30 3:25 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483068352-32272-1-git-send-email-beilei.xing@intel.com>
Add support of restoring flow director filter.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 1 +
drivers/net/i40e/i40e_ethdev.h | 1 +
drivers/net/i40e/i40e_fdir.c | 31 +++++++++++++++++++++++++++++++
3 files changed, 33 insertions(+)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 67e1b37..153322a 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10135,4 +10135,5 @@ i40e_filter_restore(struct i40e_pf *pf)
{
i40e_ethertype_filter_restore(pf);
i40e_tunnel_filter_restore(pf);
+ i40e_fdir_filter_restore(pf);
}
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index b79fbd6..92f6f55 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -670,6 +670,7 @@ int i40e_fdir_ctrl_func(struct rte_eth_dev *dev,
int i40e_select_filter_input_set(struct i40e_hw *hw,
struct rte_eth_input_set_conf *conf,
enum rte_filter_type filter);
+void i40e_fdir_filter_restore(struct i40e_pf *pf);
int i40e_hash_filter_inset_select(struct i40e_hw *hw,
struct rte_eth_input_set_conf *conf);
int i40e_fdir_filter_inset_select(struct i40e_pf *pf,
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index 4a29b37..f89dbc9 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -1586,3 +1586,34 @@ i40e_fdir_ctrl_func(struct rte_eth_dev *dev,
}
return ret;
}
+
+/* Restore flow director filter */
+void
+i40e_fdir_filter_restore(struct i40e_pf *pf)
+{
+ struct rte_eth_dev *dev = I40E_VSI_TO_ETH_DEV(pf->main_vsi);
+ struct i40e_fdir_filter_list *fdir_list = &pf->fdir.fdir_list;
+ struct i40e_fdir_filter *f;
+#ifdef RTE_LIBRTE_I40E_DEBUG_DRIVER
+ struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+ uint32_t fdstat;
+ uint32_t guarant_cnt; /**< Number of filters in guaranteed spaces. */
+ uint32_t best_cnt; /**< Number of filters in best effort spaces. */
+#endif /* RTE_LIBRTE_I40E_DEBUG_DRIVER */
+
+ TAILQ_FOREACH(f, fdir_list, rules)
+ i40e_add_del_fdir_filter(dev, &f->fdir, TRUE);
+
+#ifdef RTE_LIBRTE_I40E_DEBUG_DRIVER
+ fdstat = I40E_READ_REG(hw, I40E_PFQF_FDSTAT);
+ guarant_cnt =
+ (uint32_t)((fdstat & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >>
+ I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT);
+ best_cnt =
+ (uint32_t)((fdstat & I40E_PFQF_FDSTAT_BEST_CNT_MASK) >>
+ I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);
+#endif /* RTE_LIBRTE_I40E_DEBUG_DRIVER */
+
+ PMD_DRV_LOG(INFO, "FDIR: Guarant count: %d, Best count: %d\n",
+ guarant_cnt, best_cnt);
+}
--
2.5.5
^ permalink raw reply related
* [PATCH v4 04/17] net/i40e: restore ethertype filter
From: Beilei Xing @ 2016-12-30 3:25 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483068352-32272-1-git-send-email-beilei.xing@intel.com>
Add support of restoring ethertype filter in case filter
dropped accidentally, as all filters need to be added and
removed by user obviously for generic filter API.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 44 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index fb7d794..189d110 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -474,6 +474,9 @@ static int i40e_tunnel_filter_convert(
static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
struct i40e_tunnel_filter *tunnel_filter);
+static void i40e_ethertype_filter_restore(struct i40e_pf *pf);
+static void i40e_filter_restore(struct i40e_pf *pf);
+
static const struct rte_pci_id pci_id_i40e_map[] = {
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710) },
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QEMU) },
@@ -1955,6 +1958,8 @@ i40e_dev_start(struct rte_eth_dev *dev)
/* enable uio intr after callback register */
rte_intr_enable(intr_handle);
+ i40e_filter_restore(pf);
+
return I40E_SUCCESS;
err_up:
@@ -10071,3 +10076,42 @@ i40e_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
return ret;
}
+
+/* Restore ethertype filter */
+static void
+i40e_ethertype_filter_restore(struct i40e_pf *pf)
+{
+ struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+ struct i40e_ethertype_filter_list
+ *ethertype_list = &pf->ethertype.ethertype_list;
+ struct i40e_ethertype_filter *f;
+ struct i40e_control_filter_stats stats;
+ uint16_t flags;
+
+ TAILQ_FOREACH(f, ethertype_list, rules) {
+ flags = 0;
+ if (!(f->flags & RTE_ETHTYPE_FLAGS_MAC))
+ flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC;
+ if (f->flags & RTE_ETHTYPE_FLAGS_DROP)
+ flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_DROP;
+ flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TO_QUEUE;
+
+ memset(&stats, 0, sizeof(stats));
+ i40e_aq_add_rem_control_packet_filter(hw,
+ f->input.mac_addr.addr_bytes,
+ f->input.ether_type,
+ flags, pf->main_vsi->seid,
+ f->queue, 1, &stats, NULL);
+ }
+ PMD_DRV_LOG(INFO, "Ethertype filter:"
+ " mac_etype_used = %u, etype_used = %u,"
+ " mac_etype_free = %u, etype_free = %u\n",
+ stats.mac_etype_used, stats.etype_used,
+ stats.mac_etype_free, stats.etype_free);
+}
+
+static void
+i40e_filter_restore(struct i40e_pf *pf)
+{
+ i40e_ethertype_filter_restore(pf);
+}
--
2.5.5
^ permalink raw reply related
* [PATCH v4 05/17] net/i40e: restore tunnel filter
From: Beilei Xing @ 2016-12-30 3:25 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483068352-32272-1-git-send-email-beilei.xing@intel.com>
Add support of restoring tunnel filter.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 189d110..67e1b37 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -475,6 +475,7 @@ static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
struct i40e_tunnel_filter *tunnel_filter);
static void i40e_ethertype_filter_restore(struct i40e_pf *pf);
+static void i40e_tunnel_filter_restore(struct i40e_pf *pf);
static void i40e_filter_restore(struct i40e_pf *pf);
static const struct rte_pci_id pci_id_i40e_map[] = {
@@ -10110,8 +10111,28 @@ i40e_ethertype_filter_restore(struct i40e_pf *pf)
stats.mac_etype_free, stats.etype_free);
}
+/* Restore tunnel filter */
+static void
+i40e_tunnel_filter_restore(struct i40e_pf *pf)
+{
+ struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+ struct i40e_vsi *vsi = pf->main_vsi;
+ struct i40e_tunnel_filter_list
+ *tunnel_list = &pf->tunnel.tunnel_list;
+ struct i40e_tunnel_filter *f;
+ struct i40e_aqc_add_remove_cloud_filters_element_data cld_filter;
+
+ TAILQ_FOREACH(f, tunnel_list, rules) {
+ memset(&cld_filter, 0, sizeof(cld_filter));
+ rte_memcpy(&cld_filter, &f->input, sizeof(f->input));
+ cld_filter.queue_number = f->queue;
+ i40e_aq_add_cloud_filters(hw, vsi->seid, &cld_filter, 1);
+ }
+}
+
static void
i40e_filter_restore(struct i40e_pf *pf)
{
i40e_ethertype_filter_restore(pf);
+ i40e_tunnel_filter_restore(pf);
}
--
2.5.5
^ permalink raw reply related
* [PATCH v4 03/17] net/i40e: store flow director filter
From: Beilei Xing @ 2016-12-30 3:25 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483068352-32272-1-git-send-email-beilei.xing@intel.com>
Currently there's no flow director filter stored in SW. This
patch stores flow director filters in SW with cuckoo hash,
also adds protection if a flow director filter has been added.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 48 +++++++++++++++++++
drivers/net/i40e/i40e_ethdev.h | 14 ++++++
drivers/net/i40e/i40e_fdir.c | 105 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 167 insertions(+)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 2bdb4d6..fb7d794 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -953,6 +953,7 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
uint8_t aq_fail = 0;
struct i40e_ethertype_rule *ethertype_rule = &pf->ethertype;
struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
+ struct i40e_fdir_info *fdir_info = &pf->fdir;
PMD_INIT_FUNC_TRACE();
@@ -972,6 +973,14 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
.hash_func = rte_hash_crc,
};
+ char fdir_hash_name[RTE_HASH_NAMESIZE];
+ struct rte_hash_parameters fdir_hash_params = {
+ .name = fdir_hash_name,
+ .entries = I40E_MAX_FDIR_FILTER_NUM,
+ .key_len = sizeof(struct rte_eth_fdir_input),
+ .hash_func = rte_hash_crc,
+ };
+
dev->dev_ops = &i40e_eth_dev_ops;
dev->rx_pkt_burst = i40e_recv_pkts;
dev->tx_pkt_burst = i40e_xmit_pkts;
@@ -1253,8 +1262,33 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
goto err_tunnel_hash_map_alloc;
}
+ /* Initialize flow director filter rule list and hash */
+ TAILQ_INIT(&fdir_info->fdir_list);
+ snprintf(fdir_hash_name, RTE_HASH_NAMESIZE,
+ "fdir_%s", dev->data->name);
+ fdir_info->hash_table = rte_hash_create(&fdir_hash_params);
+ if (!fdir_info->hash_table) {
+ PMD_INIT_LOG(ERR, "Failed to create fdir hash table!");
+ ret = -EINVAL;
+ goto err_fdir_hash_table_create;
+ }
+ fdir_info->hash_map = rte_zmalloc("i40e_fdir_hash_map",
+ sizeof(struct i40e_fdir_filter *) *
+ I40E_MAX_FDIR_FILTER_NUM,
+ 0);
+ if (!fdir_info->hash_map) {
+ PMD_INIT_LOG(ERR,
+ "Failed to allocate memory for fdir hash map!");
+ ret = -ENOMEM;
+ goto err_fdir_hash_map_alloc;
+ }
+
return 0;
+err_fdir_hash_map_alloc:
+ rte_hash_free(fdir_info->hash_table);
+err_fdir_hash_table_create:
+ rte_free(tunnel_rule->hash_map);
err_tunnel_hash_map_alloc:
rte_hash_free(tunnel_rule->hash_table);
err_tunnel_hash_table_create:
@@ -1291,10 +1325,12 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
struct i40e_filter_control_settings settings;
struct i40e_ethertype_filter *p_ethertype;
struct i40e_tunnel_filter *p_tunnel;
+ struct i40e_fdir_filter *p_fdir;
int ret;
uint8_t aq_fail = 0;
struct i40e_ethertype_rule *ethertype_rule;
struct i40e_tunnel_rule *tunnel_rule;
+ struct i40e_fdir_info *fdir_info;
PMD_INIT_FUNC_TRACE();
@@ -1306,6 +1342,7 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
pci_dev = dev->pci_dev;
ethertype_rule = &pf->ethertype;
tunnel_rule = &pf->tunnel;
+ fdir_info = &pf->fdir;
if (hw->adapter_stopped == 0)
i40e_dev_close(dev);
@@ -1333,6 +1370,17 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
rte_free(p_tunnel);
}
+ /* Remove all flow director rules and hash */
+ if (fdir_info->hash_map)
+ rte_free(fdir_info->hash_map);
+ if (fdir_info->hash_table)
+ rte_hash_free(fdir_info->hash_table);
+
+ while ((p_fdir = TAILQ_FIRST(&fdir_info->fdir_list))) {
+ TAILQ_REMOVE(&fdir_info->fdir_list, p_fdir, rules);
+ rte_free(p_fdir);
+ }
+
dev->dev_ops = NULL;
dev->rx_pkt_burst = NULL;
dev->tx_pkt_burst = NULL;
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 83f3594..b79fbd6 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -377,6 +377,14 @@ struct i40e_fdir_flex_mask {
};
#define I40E_FILTER_PCTYPE_MAX 64
+#define I40E_MAX_FDIR_FILTER_NUM (1024 * 8)
+
+struct i40e_fdir_filter {
+ TAILQ_ENTRY(i40e_fdir_filter) rules;
+ struct rte_eth_fdir_filter fdir;
+};
+
+TAILQ_HEAD(i40e_fdir_filter_list, i40e_fdir_filter);
/*
* A structure used to define fields of a FDIR related info.
*/
@@ -395,6 +403,10 @@ struct i40e_fdir_info {
*/
struct i40e_fdir_flex_pit flex_set[I40E_MAX_FLXPLD_LAYER * I40E_MAX_FLXPLD_FIED];
struct i40e_fdir_flex_mask flex_mask[I40E_FILTER_PCTYPE_MAX];
+
+ struct i40e_fdir_filter_list fdir_list;
+ struct i40e_fdir_filter **hash_map;
+ struct rte_hash *hash_table;
};
/* Ethertype filter number HW supports */
@@ -674,6 +686,8 @@ i40e_sw_ethertype_filter_lookup(struct i40e_ethertype_rule *ethertype_rule,
const struct i40e_ethertype_filter_input *input);
int i40e_sw_ethertype_filter_del(struct i40e_pf *pf,
struct i40e_ethertype_filter_input *input);
+int i40e_sw_fdir_filter_del(struct i40e_pf *pf,
+ struct rte_eth_fdir_input *input);
struct i40e_tunnel_filter *
i40e_sw_tunnel_filter_lookup(struct i40e_tunnel_rule *tunnel_rule,
const struct i40e_tunnel_filter_input *input);
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index 335bf15..4a29b37 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -121,6 +121,14 @@ static int i40e_fdir_filter_programming(struct i40e_pf *pf,
bool add);
static int i40e_fdir_flush(struct rte_eth_dev *dev);
+static int i40e_fdir_filter_convert(const struct rte_eth_fdir_filter *input,
+ struct i40e_fdir_filter *filter);
+static struct i40e_fdir_filter *
+i40e_sw_fdir_filter_lookup(struct i40e_fdir_info *fdir_info,
+ const struct rte_eth_fdir_input *input);
+static int i40e_sw_fdir_filter_insert(struct i40e_pf *pf,
+ struct i40e_fdir_filter *filter);
+
static int
i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq)
{
@@ -1017,6 +1025,74 @@ i40e_check_fdir_programming_status(struct i40e_rx_queue *rxq)
return ret;
}
+static int
+i40e_fdir_filter_convert(const struct rte_eth_fdir_filter *input,
+ struct i40e_fdir_filter *filter)
+{
+ rte_memcpy(&filter->fdir, input, sizeof(struct rte_eth_fdir_filter));
+ return 0;
+}
+
+/* Check if there exists the flow director filter */
+static struct i40e_fdir_filter *
+i40e_sw_fdir_filter_lookup(struct i40e_fdir_info *fdir_info,
+ const struct rte_eth_fdir_input *input)
+{
+ int ret;
+
+ ret = rte_hash_lookup(fdir_info->hash_table, (const void *)input);
+ if (ret < 0)
+ return NULL;
+
+ return fdir_info->hash_map[ret];
+}
+
+/* Add a flow director filter into the SW list */
+static int
+i40e_sw_fdir_filter_insert(struct i40e_pf *pf, struct i40e_fdir_filter *filter)
+{
+ struct i40e_fdir_info *fdir_info = &pf->fdir;
+ int ret;
+
+ ret = rte_hash_add_key(fdir_info->hash_table,
+ &filter->fdir.input);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR,
+ "Failed to insert fdir filter to hash table %d!",
+ ret);
+ return ret;
+ }
+ fdir_info->hash_map[ret] = filter;
+
+ TAILQ_INSERT_TAIL(&fdir_info->fdir_list, filter, rules);
+
+ return 0;
+}
+
+/* Delete a flow director filter from the SW list */
+int
+i40e_sw_fdir_filter_del(struct i40e_pf *pf, struct rte_eth_fdir_input *input)
+{
+ struct i40e_fdir_info *fdir_info = &pf->fdir;
+ struct i40e_fdir_filter *filter;
+ int ret;
+
+ ret = rte_hash_del_key(fdir_info->hash_table, input);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR,
+ "Failed to delete fdir filter to hash table %d!",
+ ret);
+ return ret;
+ }
+ filter = fdir_info->hash_map[ret];
+ fdir_info->hash_map[ret] = NULL;
+
+ TAILQ_REMOVE(&fdir_info->fdir_list, filter, rules);
+ rte_free(filter);
+
+ return 0;
+}
+
/*
* i40e_add_del_fdir_filter - add or remove a flow director filter.
* @pf: board private structure
@@ -1032,6 +1108,9 @@ i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
unsigned char *pkt = (unsigned char *)pf->fdir.prg_pkt;
enum i40e_filter_pctype pctype;
+ struct i40e_fdir_info *fdir_info = &pf->fdir;
+ struct i40e_fdir_filter *fdir_filter, *node;
+ struct i40e_fdir_filter check_filter; /* Check if the filter exists */
int ret = 0;
if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT) {
@@ -1054,6 +1133,22 @@ i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
return -EINVAL;
}
+ /* Check if there is the filter in SW list */
+ memset(&check_filter, 0, sizeof(check_filter));
+ i40e_fdir_filter_convert(filter, &check_filter);
+ node = i40e_sw_fdir_filter_lookup(fdir_info, &check_filter.fdir.input);
+ if (add && node) {
+ PMD_DRV_LOG(ERR,
+ "Conflict with existing flow director rules!");
+ return -EINVAL;
+ }
+
+ if (!add && !node) {
+ PMD_DRV_LOG(ERR,
+ "There's no corresponding flow firector filter!");
+ return -EINVAL;
+ }
+
memset(pkt, 0, I40E_FDIR_PKT_LEN);
ret = i40e_fdir_construct_pkt(pf, &filter->input, pkt);
@@ -1077,6 +1172,16 @@ i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
pctype);
return ret;
}
+
+ if (add) {
+ fdir_filter = rte_zmalloc("fdir_filter",
+ sizeof(*fdir_filter), 0);
+ rte_memcpy(fdir_filter, &check_filter, sizeof(check_filter));
+ ret = i40e_sw_fdir_filter_insert(pf, fdir_filter);
+ } else {
+ ret = i40e_sw_fdir_filter_del(pf, &node->fdir.input);
+ }
+
return ret;
}
--
2.5.5
^ permalink raw reply related
* [PATCH v4 02/17] net/i40e: store tunnel filter
From: Beilei Xing @ 2016-12-30 3:25 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483068352-32272-1-git-send-email-beilei.xing@intel.com>
Currently there's no tunnel filter stored in SW.
This patch stores tunnel filter in SW with cuckoo
hash, also adds protection if a tunnel filter has
been added.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 169 ++++++++++++++++++++++++++++++++++++++++-
drivers/net/i40e/i40e_ethdev.h | 32 ++++++++
2 files changed, 198 insertions(+), 3 deletions(-)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index e43b4d9..2bdb4d6 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -468,6 +468,12 @@ static int i40e_ethertype_filter_convert(
static int i40e_sw_ethertype_filter_insert(struct i40e_pf *pf,
struct i40e_ethertype_filter *filter);
+static int i40e_tunnel_filter_convert(
+ struct i40e_aqc_add_remove_cloud_filters_element_data *cld_filter,
+ struct i40e_tunnel_filter *tunnel_filter);
+static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
+ struct i40e_tunnel_filter *tunnel_filter);
+
static const struct rte_pci_id pci_id_i40e_map[] = {
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710) },
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QEMU) },
@@ -946,6 +952,7 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
uint32_t len;
uint8_t aq_fail = 0;
struct i40e_ethertype_rule *ethertype_rule = &pf->ethertype;
+ struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
PMD_INIT_FUNC_TRACE();
@@ -957,6 +964,14 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
.hash_func = rte_hash_crc,
};
+ char tunnel_hash_name[RTE_HASH_NAMESIZE];
+ struct rte_hash_parameters tunnel_hash_params = {
+ .name = tunnel_hash_name,
+ .entries = I40E_MAX_TUNNEL_FILTER_NUM,
+ .key_len = sizeof(struct i40e_tunnel_filter_input),
+ .hash_func = rte_hash_crc,
+ };
+
dev->dev_ops = &i40e_eth_dev_ops;
dev->rx_pkt_burst = i40e_recv_pkts;
dev->tx_pkt_burst = i40e_xmit_pkts;
@@ -1217,8 +1232,33 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
goto err_ethertype_hash_map_alloc;
}
+ /* Initialize tunnel filter rule list and hash */
+ TAILQ_INIT(&tunnel_rule->tunnel_list);
+ snprintf(tunnel_hash_name, RTE_HASH_NAMESIZE,
+ "tunnel_%s", dev->data->name);
+ tunnel_rule->hash_table = rte_hash_create(&tunnel_hash_params);
+ if (!tunnel_rule->hash_table) {
+ PMD_INIT_LOG(ERR, "Failed to create tunnel hash table!");
+ ret = -EINVAL;
+ goto err_tunnel_hash_table_create;
+ }
+ tunnel_rule->hash_map = rte_zmalloc("i40e_tunnel_hash_map",
+ sizeof(struct i40e_tunnel_filter *) *
+ I40E_MAX_TUNNEL_FILTER_NUM,
+ 0);
+ if (!tunnel_rule->hash_map) {
+ PMD_INIT_LOG(ERR,
+ "Failed to allocate memory for tunnel hash map!");
+ ret = -ENOMEM;
+ goto err_tunnel_hash_map_alloc;
+ }
+
return 0;
+err_tunnel_hash_map_alloc:
+ rte_hash_free(tunnel_rule->hash_table);
+err_tunnel_hash_table_create:
+ rte_free(ethertype_rule->hash_map);
err_ethertype_hash_map_alloc:
rte_hash_free(ethertype_rule->hash_table);
err_ethertype_hash_table_create:
@@ -1250,9 +1290,11 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
struct i40e_hw *hw;
struct i40e_filter_control_settings settings;
struct i40e_ethertype_filter *p_ethertype;
+ struct i40e_tunnel_filter *p_tunnel;
int ret;
uint8_t aq_fail = 0;
struct i40e_ethertype_rule *ethertype_rule;
+ struct i40e_tunnel_rule *tunnel_rule;
PMD_INIT_FUNC_TRACE();
@@ -1263,6 +1305,7 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
pci_dev = dev->pci_dev;
ethertype_rule = &pf->ethertype;
+ tunnel_rule = &pf->tunnel;
if (hw->adapter_stopped == 0)
i40e_dev_close(dev);
@@ -1279,6 +1322,17 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
rte_free(p_ethertype);
}
+ /* Remove all tunnel director rules and hash */
+ if (tunnel_rule->hash_map)
+ rte_free(tunnel_rule->hash_map);
+ if (tunnel_rule->hash_table)
+ rte_hash_free(tunnel_rule->hash_table);
+
+ while ((p_tunnel = TAILQ_FIRST(&tunnel_rule->tunnel_list))) {
+ TAILQ_REMOVE(&tunnel_rule->tunnel_list, p_tunnel, rules);
+ rte_free(p_tunnel);
+ }
+
dev->dev_ops = NULL;
dev->rx_pkt_burst = NULL;
dev->tx_pkt_burst = NULL;
@@ -6478,6 +6532,85 @@ i40e_dev_get_filter_type(uint16_t filter_type, uint16_t *flag)
return 0;
}
+/* Convert tunnel filter structure */
+static int
+i40e_tunnel_filter_convert(struct i40e_aqc_add_remove_cloud_filters_element_data
+ *cld_filter,
+ struct i40e_tunnel_filter *tunnel_filter)
+{
+ ether_addr_copy((struct ether_addr *)&cld_filter->outer_mac,
+ (struct ether_addr *)&tunnel_filter->input.outer_mac);
+ ether_addr_copy((struct ether_addr *)&cld_filter->inner_mac,
+ (struct ether_addr *)&tunnel_filter->input.inner_mac);
+ tunnel_filter->input.inner_vlan = cld_filter->inner_vlan;
+ tunnel_filter->input.flags = cld_filter->flags;
+ tunnel_filter->input.tenant_id = cld_filter->tenant_id;
+ tunnel_filter->queue = cld_filter->queue_number;
+
+ return 0;
+}
+
+/* Check if there exists the tunnel filter */
+struct i40e_tunnel_filter *
+i40e_sw_tunnel_filter_lookup(struct i40e_tunnel_rule *tunnel_rule,
+ const struct i40e_tunnel_filter_input *input)
+{
+ int ret;
+
+ ret = rte_hash_lookup(tunnel_rule->hash_table, (const void *)input);
+ if (ret < 0)
+ return NULL;
+
+ return tunnel_rule->hash_map[ret];
+}
+
+/* Add a tunnel filter into the SW list */
+static int
+i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
+ struct i40e_tunnel_filter *tunnel_filter)
+{
+ struct i40e_tunnel_rule *rule = &pf->tunnel;
+ int ret;
+
+ ret = rte_hash_add_key(rule->hash_table, &tunnel_filter->input);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR,
+ "Failed to insert tunnel filter to hash table %d!",
+ ret);
+ return ret;
+ }
+ rule->hash_map[ret] = tunnel_filter;
+
+ TAILQ_INSERT_TAIL(&rule->tunnel_list, tunnel_filter, rules);
+
+ return 0;
+}
+
+/* Delete a tunnel filter from the SW list */
+int
+i40e_sw_tunnel_filter_del(struct i40e_pf *pf,
+ struct i40e_tunnel_filter_input *input)
+{
+ struct i40e_tunnel_rule *rule = &pf->tunnel;
+ struct i40e_tunnel_filter *tunnel_filter;
+ int ret;
+
+ ret = rte_hash_del_key(rule->hash_table, input);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR,
+ "Failed to delete tunnel filter to hash table %d!",
+ ret);
+ return ret;
+ }
+ tunnel_filter = rule->hash_map[ret];
+ rule->hash_map[ret] = NULL;
+
+ TAILQ_REMOVE(&rule->tunnel_list, tunnel_filter, rules);
+ rte_free(tunnel_filter);
+
+ return 0;
+}
+
static int
i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
struct rte_eth_tunnel_filter_conf *tunnel_filter,
@@ -6493,6 +6626,9 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
struct i40e_vsi *vsi = pf->main_vsi;
struct i40e_aqc_add_remove_cloud_filters_element_data *cld_filter;
struct i40e_aqc_add_remove_cloud_filters_element_data *pfilter;
+ struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
+ struct i40e_tunnel_filter *tunnel, *node;
+ struct i40e_tunnel_filter check_filter; /* Check if filter exists */
cld_filter = rte_zmalloc("tunnel_filter",
sizeof(struct i40e_aqc_add_remove_cloud_filters_element_data),
@@ -6555,11 +6691,38 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
pfilter->tenant_id = rte_cpu_to_le_32(tunnel_filter->tenant_id);
pfilter->queue_number = rte_cpu_to_le_16(tunnel_filter->queue_id);
- if (add)
+ /* Check if there is the filter in SW list */
+ memset(&check_filter, 0, sizeof(check_filter));
+ i40e_tunnel_filter_convert(cld_filter, &check_filter);
+ node = i40e_sw_tunnel_filter_lookup(tunnel_rule, &check_filter.input);
+ if (add && node) {
+ PMD_DRV_LOG(ERR, "Conflict with existing tunnel rules!");
+ return -EINVAL;
+ }
+
+ if (!add && !node) {
+ PMD_DRV_LOG(ERR, "There's no corresponding tunnel filter!");
+ return -EINVAL;
+ }
+
+ if (add) {
ret = i40e_aq_add_cloud_filters(hw, vsi->seid, cld_filter, 1);
- else
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to add a tunnel filter.");
+ return ret;
+ }
+ tunnel = rte_zmalloc("tunnel_filter", sizeof(*tunnel), 0);
+ rte_memcpy(tunnel, &check_filter, sizeof(check_filter));
+ ret = i40e_sw_tunnel_filter_insert(pf, tunnel);
+ } else {
ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
- cld_filter, 1);
+ cld_filter, 1);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to delete a tunnel filter.");
+ return ret;
+ }
+ ret = i40e_sw_tunnel_filter_del(pf, &node->input);
+ }
rte_free(cld_filter);
return ret;
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 3fb20ba..83f3594 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -421,6 +421,32 @@ struct i40e_ethertype_rule {
struct rte_hash *hash_table;
};
+/* Tunnel filter number HW supports */
+#define I40E_MAX_TUNNEL_FILTER_NUM 400
+
+/* Tunnel filter struct */
+struct i40e_tunnel_filter_input {
+ uint8_t outer_mac[6]; /* Outer mac address to match */
+ uint8_t inner_mac[6]; /* Inner mac address to match */
+ uint16_t inner_vlan; /* Inner vlan address to match */
+ uint16_t flags; /* Filter type flag */
+ uint32_t tenant_id; /* Tenant id to match */
+};
+
+struct i40e_tunnel_filter {
+ TAILQ_ENTRY(i40e_tunnel_filter) rules;
+ struct i40e_tunnel_filter_input input;
+ uint16_t queue; /* Queue assigned to when match */
+};
+
+TAILQ_HEAD(i40e_tunnel_filter_list, i40e_tunnel_filter);
+
+struct i40e_tunnel_rule {
+ struct i40e_tunnel_filter_list tunnel_list;
+ struct i40e_tunnel_filter **hash_map;
+ struct rte_hash *hash_table;
+};
+
#define I40E_MIRROR_MAX_ENTRIES_PER_RULE 64
#define I40E_MAX_MIRROR_RULES 64
/*
@@ -492,6 +518,7 @@ struct i40e_pf {
struct i40e_fdir_info fdir; /* flow director info */
struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
+ struct i40e_tunnel_rule tunnel; /* Tunnel filter rule */
struct i40e_fc_conf fc_conf; /* Flow control conf */
struct i40e_mirror_rule_list mirror_list;
uint16_t nb_mirror_rule; /* The number of mirror rules */
@@ -647,6 +674,11 @@ i40e_sw_ethertype_filter_lookup(struct i40e_ethertype_rule *ethertype_rule,
const struct i40e_ethertype_filter_input *input);
int i40e_sw_ethertype_filter_del(struct i40e_pf *pf,
struct i40e_ethertype_filter_input *input);
+struct i40e_tunnel_filter *
+i40e_sw_tunnel_filter_lookup(struct i40e_tunnel_rule *tunnel_rule,
+ const struct i40e_tunnel_filter_input *input);
+int i40e_sw_tunnel_filter_del(struct i40e_pf *pf,
+ struct i40e_tunnel_filter_input *input);
/* I40E_DEV_PRIVATE_TO */
#define I40E_DEV_PRIVATE_TO_PF(adapter) \
--
2.5.5
^ permalink raw reply related
* [PATCH v4 01/17] net/i40e: store ethertype filter
From: Beilei Xing @ 2016-12-30 3:25 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483068352-32272-1-git-send-email-beilei.xing@intel.com>
Currently there's no ethertype filter stored in SW.
This patch stores ethertype filter with cuckoo hash
in SW, also adds protection if an ethertype filter
has been added.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/Makefile | 1 +
drivers/net/i40e/i40e_ethdev.c | 166 ++++++++++++++++++++++++++++++++++++++++-
drivers/net/i40e/i40e_ethdev.h | 31 ++++++++
3 files changed, 197 insertions(+), 1 deletion(-)
diff --git a/drivers/net/i40e/Makefile b/drivers/net/i40e/Makefile
index 66997b6..11175c4 100644
--- a/drivers/net/i40e/Makefile
+++ b/drivers/net/i40e/Makefile
@@ -117,5 +117,6 @@ DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_eal lib/librte_ether
DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_mempool lib/librte_mbuf
DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_net
DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_kvargs
+DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_hash
include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 8033c35..e43b4d9 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -51,6 +51,7 @@
#include <rte_dev.h>
#include <rte_eth_ctrl.h>
#include <rte_tailq.h>
+#include <rte_hash_crc.h>
#include "i40e_logs.h"
#include "base/i40e_prototype.h"
@@ -461,6 +462,12 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
static int i40e_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
+static int i40e_ethertype_filter_convert(
+ const struct rte_eth_ethertype_filter *input,
+ struct i40e_ethertype_filter *filter);
+static int i40e_sw_ethertype_filter_insert(struct i40e_pf *pf,
+ struct i40e_ethertype_filter *filter);
+
static const struct rte_pci_id pci_id_i40e_map[] = {
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710) },
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QEMU) },
@@ -938,9 +945,18 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
int ret;
uint32_t len;
uint8_t aq_fail = 0;
+ struct i40e_ethertype_rule *ethertype_rule = &pf->ethertype;
PMD_INIT_FUNC_TRACE();
+ char ethertype_hash_name[RTE_HASH_NAMESIZE];
+ struct rte_hash_parameters ethertype_hash_params = {
+ .name = ethertype_hash_name,
+ .entries = I40E_MAX_ETHERTYPE_FILTER_NUM,
+ .key_len = sizeof(struct i40e_ethertype_filter_input),
+ .hash_func = rte_hash_crc,
+ };
+
dev->dev_ops = &i40e_eth_dev_ops;
dev->rx_pkt_burst = i40e_recv_pkts;
dev->tx_pkt_burst = i40e_xmit_pkts;
@@ -1180,8 +1196,33 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
pf->flags &= ~I40E_FLAG_DCB;
}
+ /* Initialize ethertype filter rule list and hash */
+ TAILQ_INIT(ðertype_rule->ethertype_list);
+ snprintf(ethertype_hash_name, RTE_HASH_NAMESIZE,
+ "ethertype_%s", dev->data->name);
+ ethertype_rule->hash_table = rte_hash_create(ðertype_hash_params);
+ if (!ethertype_rule->hash_table) {
+ PMD_INIT_LOG(ERR, "Failed to create ethertype hash table!");
+ ret = -EINVAL;
+ goto err_ethertype_hash_table_create;
+ }
+ ethertype_rule->hash_map = rte_zmalloc("i40e_ethertype_hash_map",
+ sizeof(struct i40e_ethertype_filter *) *
+ I40E_MAX_ETHERTYPE_FILTER_NUM,
+ 0);
+ if (!ethertype_rule->hash_map) {
+ PMD_INIT_LOG(ERR,
+ "Failed to allocate memory for ethertype hash map!");
+ ret = -ENOMEM;
+ goto err_ethertype_hash_map_alloc;
+ }
+
return 0;
+err_ethertype_hash_map_alloc:
+ rte_hash_free(ethertype_rule->hash_table);
+err_ethertype_hash_table_create:
+ rte_free(dev->data->mac_addrs);
err_mac_alloc:
i40e_vsi_release(pf->main_vsi);
err_setup_pf_switch:
@@ -1204,23 +1245,40 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
static int
eth_i40e_dev_uninit(struct rte_eth_dev *dev)
{
+ struct i40e_pf *pf;
struct rte_pci_device *pci_dev;
struct i40e_hw *hw;
struct i40e_filter_control_settings settings;
+ struct i40e_ethertype_filter *p_ethertype;
int ret;
uint8_t aq_fail = 0;
+ struct i40e_ethertype_rule *ethertype_rule;
PMD_INIT_FUNC_TRACE();
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
return 0;
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
pci_dev = dev->pci_dev;
+ ethertype_rule = &pf->ethertype;
if (hw->adapter_stopped == 0)
i40e_dev_close(dev);
+ /* Remove all ethertype director rules and hash */
+ if (ethertype_rule->hash_map)
+ rte_free(ethertype_rule->hash_map);
+ if (ethertype_rule->hash_table)
+ rte_hash_free(ethertype_rule->hash_table);
+
+ while ((p_ethertype = TAILQ_FIRST(ðertype_rule->ethertype_list))) {
+ TAILQ_REMOVE(ðertype_rule->ethertype_list,
+ p_ethertype, rules);
+ rte_free(p_ethertype);
+ }
+
dev->dev_ops = NULL;
dev->rx_pkt_burst = NULL;
dev->tx_pkt_burst = NULL;
@@ -7955,6 +8013,82 @@ i40e_hash_filter_ctrl(struct rte_eth_dev *dev,
return ret;
}
+/* Convert ethertype filter structure */
+static int
+i40e_ethertype_filter_convert(const struct rte_eth_ethertype_filter *input,
+ struct i40e_ethertype_filter *filter)
+{
+ rte_memcpy(&filter->input.mac_addr, &input->mac_addr, ETHER_ADDR_LEN);
+ filter->input.ether_type = input->ether_type;
+ filter->flags = input->flags;
+ filter->queue = input->queue;
+
+ return 0;
+}
+
+/* Check if there exists the ehtertype filter */
+struct i40e_ethertype_filter *
+i40e_sw_ethertype_filter_lookup(struct i40e_ethertype_rule *ethertype_rule,
+ const struct i40e_ethertype_filter_input *input)
+{
+ int ret;
+
+ ret = rte_hash_lookup(ethertype_rule->hash_table, (const void *)input);
+ if (ret < 0)
+ return NULL;
+
+ return ethertype_rule->hash_map[ret];
+}
+
+/* Add ethertype filter in SW list */
+static int
+i40e_sw_ethertype_filter_insert(struct i40e_pf *pf,
+ struct i40e_ethertype_filter *filter)
+{
+ struct i40e_ethertype_rule *rule = &pf->ethertype;
+ int ret;
+
+ ret = rte_hash_add_key(rule->hash_table, &filter->input);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR,
+ "Failed to insert ethertype filter"
+ " to hash table %d!",
+ ret);
+ return ret;
+ }
+ rule->hash_map[ret] = filter;
+
+ TAILQ_INSERT_TAIL(&rule->ethertype_list, filter, rules);
+
+ return 0;
+}
+
+/* Delete ethertype filter in SW list */
+int
+i40e_sw_ethertype_filter_del(struct i40e_pf *pf,
+ struct i40e_ethertype_filter_input *input)
+{
+ struct i40e_ethertype_rule *rule = &pf->ethertype;
+ struct i40e_ethertype_filter *filter;
+ int ret;
+
+ ret = rte_hash_del_key(rule->hash_table, input);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR,
+ "Failed to delete ethertype filter"
+ " to hash table %d!",
+ ret);
+ return ret;
+ }
+ filter = rule->hash_map[ret];
+ rule->hash_map[ret] = NULL;
+
+ TAILQ_REMOVE(&rule->ethertype_list, filter, rules);
+ rte_free(filter);
+
+ return 0;
+}
+
/*
* Configure ethertype filter, which can director packet by filtering
* with mac address and ether_type or only ether_type
@@ -7965,6 +8099,9 @@ i40e_ethertype_filter_set(struct i40e_pf *pf,
bool add)
{
struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+ struct i40e_ethertype_rule *ethertype_rule = &pf->ethertype;
+ struct i40e_ethertype_filter *ethertype_filter, *node;
+ struct i40e_ethertype_filter check_filter;
struct i40e_control_filter_stats stats;
uint16_t flags = 0;
int ret;
@@ -7983,6 +8120,21 @@ i40e_ethertype_filter_set(struct i40e_pf *pf,
PMD_DRV_LOG(WARNING, "filter vlan ether_type in first tag is"
" not supported.");
+ /* Check if there is the filter in SW list */
+ memset(&check_filter, 0, sizeof(check_filter));
+ i40e_ethertype_filter_convert(filter, &check_filter);
+ node = i40e_sw_ethertype_filter_lookup(ethertype_rule,
+ &check_filter.input);
+ if (add && node) {
+ PMD_DRV_LOG(ERR, "Conflict with existing ethertype rules!");
+ return -EINVAL;
+ }
+
+ if (!add && !node) {
+ PMD_DRV_LOG(ERR, "There's no corresponding ethertype filter!");
+ return -EINVAL;
+ }
+
if (!(filter->flags & RTE_ETHTYPE_FLAGS_MAC))
flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC;
if (filter->flags & RTE_ETHTYPE_FLAGS_DROP)
@@ -8003,7 +8155,19 @@ i40e_ethertype_filter_set(struct i40e_pf *pf,
stats.mac_etype_free, stats.etype_free);
if (ret < 0)
return -ENOSYS;
- return 0;
+
+ /* Add or delete a filter in SW list */
+ if (add) {
+ ethertype_filter = rte_zmalloc("ethertype_filter",
+ sizeof(*ethertype_filter), 0);
+ rte_memcpy(ethertype_filter, &check_filter,
+ sizeof(check_filter));
+ ret = i40e_sw_ethertype_filter_insert(pf, ethertype_filter);
+ } else {
+ ret = i40e_sw_ethertype_filter_del(pf, &node->input);
+ }
+
+ return ret;
}
/*
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 298cef4..3fb20ba 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -37,6 +37,7 @@
#include <rte_eth_ctrl.h>
#include <rte_time.h>
#include <rte_kvargs.h>
+#include <rte_hash.h>
#define I40E_VLAN_TAG_SIZE 4
@@ -396,6 +397,30 @@ struct i40e_fdir_info {
struct i40e_fdir_flex_mask flex_mask[I40E_FILTER_PCTYPE_MAX];
};
+/* Ethertype filter number HW supports */
+#define I40E_MAX_ETHERTYPE_FILTER_NUM 768
+
+/* Ethertype filter struct */
+struct i40e_ethertype_filter_input {
+ struct ether_addr mac_addr; /* Mac address to match */
+ uint16_t ether_type; /* Ether type to match */
+};
+
+struct i40e_ethertype_filter {
+ TAILQ_ENTRY(i40e_ethertype_filter) rules;
+ struct i40e_ethertype_filter_input input;
+ uint16_t flags; /* Flags from RTE_ETHTYPE_FLAGS_* */
+ uint16_t queue; /* Queue assigned to when match */
+};
+
+TAILQ_HEAD(i40e_ethertype_filter_list, i40e_ethertype_filter);
+
+struct i40e_ethertype_rule {
+ struct i40e_ethertype_filter_list ethertype_list;
+ struct i40e_ethertype_filter **hash_map;
+ struct rte_hash *hash_table;
+};
+
#define I40E_MIRROR_MAX_ENTRIES_PER_RULE 64
#define I40E_MAX_MIRROR_RULES 64
/*
@@ -466,6 +491,7 @@ struct i40e_pf {
struct i40e_vmdq_info *vmdq;
struct i40e_fdir_info fdir; /* flow director info */
+ struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
struct i40e_fc_conf fc_conf; /* Flow control conf */
struct i40e_mirror_rule_list mirror_list;
uint16_t nb_mirror_rule; /* The number of mirror rules */
@@ -616,6 +642,11 @@ void i40e_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
struct rte_eth_rxq_info *qinfo);
void i40e_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
struct rte_eth_txq_info *qinfo);
+struct i40e_ethertype_filter *
+i40e_sw_ethertype_filter_lookup(struct i40e_ethertype_rule *ethertype_rule,
+ const struct i40e_ethertype_filter_input *input);
+int i40e_sw_ethertype_filter_del(struct i40e_pf *pf,
+ struct i40e_ethertype_filter_input *input);
/* I40E_DEV_PRIVATE_TO */
#define I40E_DEV_PRIVATE_TO_PF(adapter) \
--
2.5.5
^ permalink raw reply related
* [PATCH v4 00/17] net/i40e: consistent filter API
From: Beilei Xing @ 2016-12-30 3:25 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483027473-89042-1-git-send-email-beilei.xing@intel.com>
The patch set depends on Adrien's Generic flow API(rte_flow).
The patches mainly finish following functions:
1) Store and restore all kinds of filters.
2) Parse all kinds of filters.
3) Add flow validate function.
4) Add flow create function.
5) Add flow destroy function.
6) Add flow flush function.
v4 changes:
Change I40E_TCI_MASK with 0xFFFF to align with testpmd.
Modidy the stats show when restoring filters.
v3 changes:
Set the related cause pointer to a non-NULL value when error happens.
Change return value when error happens.
Modify filter_del parameter with key.
Malloc filter after checking when delete a filter.
Delete meaningless initialization.
Add return value when there's error.
Change global variable definition.
Modify some function declaration.
v2 changes:
Add i40e_flow.c, all flow ops are implemented in the file.
Change the whole implementation of all parse flow functions.
Update error info for all flow ops.
Add flow_list to store flows created.
Beilei Xing (17):
net/i40e: store ethertype filter
net/i40e: store tunnel filter
net/i40e: store flow director filter
net/i40e: restore ethertype filter
net/i40e: restore tunnel filter
net/i40e: restore flow director filter
net/i40e: add flow validate function
net/i40e: parse flow director filter
net/i40e: parse tunnel filter
net/i40e: add flow create function
net/i40e: add flow destroy function
net/i40e: destroy ethertype filter
net/i40e: destroy tunnel filter
net/i40e: destroy flow directory filter
net/i40e: add flow flush function
net/i40e: flush ethertype filters
net/i40e: flush tunnel filters
drivers/net/i40e/Makefile | 2 +
drivers/net/i40e/i40e_ethdev.c | 519 ++++++++++--
drivers/net/i40e/i40e_ethdev.h | 173 ++++
drivers/net/i40e/i40e_fdir.c | 140 +++-
drivers/net/i40e/i40e_flow.c | 1772 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 2540 insertions(+), 66 deletions(-)
create mode 100644 drivers/net/i40e/i40e_flow.c
--
2.5.5
^ permalink raw reply
* Re: [PATCH 2/2] vhost: start vhost servers once
From: Yuanhan Liu @ 2016-12-30 3:15 UTC (permalink / raw)
To: Charles (Chas) Williams; +Cc: dev, mtetsuyah
In-Reply-To: <bd70f0c1-cb57-728a-2f94-84e688c89648@brocade.com>
On Thu, Dec 29, 2016 at 10:58:11AM -0500, Charles (Chas) Williams wrote:
> On 12/29/2016 03:52 AM, Yuanhan Liu wrote:
> >On Wed, Dec 28, 2016 at 04:10:52PM -0500, Charles (Chas) Williams wrote:
> >>Start a vhost server once during devinit instead of during device start
> >>and stop. Some vhost clients, QEMU, don't re-attaching to sockets when
> >>the vhost server is stopped and later started. Preserve existing behavior
> >>for vhost clients.
> >
> >I didn't quite get the idea what you are going to fix.
>
> The issue I am trying to fix is QEMU interaction when DPDK's vhost is
> acting as a server to QEMU vhost clients. If you create a vhost server
> device, it doesn't create the actual datagram socket until you call
> .dev_start(). If you call .dev_stop() is also deletes those sockets.
> For QEMU, this is a problem since QEMU doesn't know how to re-attach to
> datagram sockets that have gone away.
Thanks! And I'd appreciate it if you could have written the commit log
this way firstly.
> .dev_start()/.dev_stop() seems to roughly means link up and link down
> so I understand why you might want to add/remove the datagram sockets.
> However, in practice, this doesn't seem to make much sense for a DPDK
> vhost server.
Agree.
> This doesn't seem like the right way to indicate link
> status to vhost clients.
>
> It seems like it would just be easier to do this for both clients and
> servers, but I don't know why it was done this way originally so I
> choose to keep the client behavior.
I don't think there are any differences between DPDK acting as client or
server. To me, the right logic seems to be (for both DPDK as server and
client).
For register,
- register the vhost socket at probe stage (either at rte_pmd_vhost_probe
or at eth_dev_vhost_create).
- start the vhost session right after the register when we haven't started
it before.
For unregister,
- invoke rte_vhost_driver_unregister() at rte_pmd_vhost_remove().
For dev_start/stop,
- set allow_queuing to 1/0 for start/stop, respectively.
--yliu
^ permalink raw reply
* Re: Running DPDK as an unprivileged user
From: Stephen Hemminger @ 2016-12-30 1:14 UTC (permalink / raw)
To: Walker, Benjamin; +Cc: dev@dpdk.org
In-Reply-To: <1483044080.11975.1.camel@intel.com>
On Thu, 29 Dec 2016 20:41:21 +0000
"Walker, Benjamin" <benjamin.walker@intel.com> wrote:
> The first open question I have is whether DPDK should allow
> uio at all on recent (4.x) kernels. My current understanding
> is that there is no way to pin memory and hugepages can now
> be moved around, so uio would be unsafe. What does the
> community think here?
DMA access without IOMMU (ie UIO) is not safe from a security
point of view. A malicious app could program device (like Ethernet
NIC) to change its current privledge level in kernel memory.
Therefore ignore UIO as an option if you want to allow unprivileged
access.
But there are many many systems without working IOMMU. Not just broken
motherboards, but virtualization environments (Xen, Hyper-V, and KVM until
very recently) where IOMMU is no going to work. In these environments,
DPDK is still useful where the security risks are known.
If kernel broke pinning of hugepages, then it is an upstream kernel bug.
>
> My second question is whether the user should be allowed to
> mix uio and vfio usage simultaneously. For vfio, the
> physical addresses are really DMA addresses and are best
> when arbitrarily chosen to appear sequential relative to
> their virtual addresses. For uio, they are physical
> addresses and are not chosen at all. It seems that these two
> things are in conflict and that it will be difficult, ugly,
> and maybe impossible to resolve the simultaneous use of
> both.
Unless application is running as privileged user (ie root), UIO
is not going to work. Therefore don't worry about mixed environment.
^ permalink raw reply
* Running DPDK as an unprivileged user
From: Walker, Benjamin @ 2016-12-29 20:41 UTC (permalink / raw)
To: dev@dpdk.org
Hi all,
I've been digging in to what it would take to run DPDK as an
unprivileged user and I have some findings that I thought
were worthy of discussion. The assumptions here are that I'm
using a very recent Linux kernel (4.8.15 to be specific) and
I'm using vfio with my IOMMU enabled. I'm only interested in
making it possible to run as an unprivileged user in this
type of environment.
There are a few key things that DPDK needs to do in order to
run as an unprivileged user:
1) Allocate hugepages
2) Map device resources
3) Map hugepage virtual addresses to DMA addresses.
For #1 and #2, DPDK works just fine today. You simply chown
the relevant resources in sysfs to the desired user and
everything is happy.
The problem is #3. This currently relies on looking up the
mappings in /proc/self/pagemap, but the ability to get
physical addresses in /proc/self/pagemap as an unprivileged
user was removed from the kernel in the 4.x timeframe due to
the Rowhammer vulnerability. At this time, it is not
possible to run DPDK as an unprivileged user on a 4.x Linux
kernel.
There is a way to make this work though, which I'll outline
now. Unfortunately, I think it is going to require some very
significant changes to the initialization flow in the EAL.
One bit of of background before I go into how to fix this -
there are three types of memory addresses - virtual
addresses, physical addresses, and DMA addresses. Sometimes
DMA addresses are called bus addresses or I/O addresses, but
I'll call them DMA addresses because I think that's the
clearest name. In a system without an IOMMU, DMA addresses
and physical addresses are equivalent, but in a system with
an IOMMU any arbitrary DMA address can be chosen by the user
to map to a given physical address. For security reasons
(rowhammer), it is no longer considered safe to expose
physical addresses to userspace, but it is perfectly fine to
expose DMA addresses when an IOMMU is present.
DPDK today begins by allocating all of the required
hugepages, then finds all of the physical addresses for
those hugepages using /proc/self/pagemap, sorts the
hugepages by physical address, then remaps the pages to
contiguous virtual addresses. Later on and if vfio is
enabled, it asks vfio to pin the hugepages and to set their
DMA addresses in the IOMMU to be the physical addresses
discovered earlier. Of course, running as an unprivileged
user means all of the physical addresses in
/proc/self/pagemap are just 0, so this doesn't end up
working. Further, there is no real reason to choose the
physical address as the DMA address in the IOMMU - it would
be better to just count up starting at 0. Also, because the
pages are pinned after the virtual to physical mapping is
looked up, there is a window where a page could be moved.
Hugepage mappings can be moved on more recent kernels (at
least 4.x), and the reliability of hugepages having static
mappings decreases with every kernel release. Note that this
probably means that using uio on recent kernels is subtly
broken and cannot be supported going forward because there
is no uio mechanism to pin the memory.
The first open question I have is whether DPDK should allow
uio at all on recent (4.x) kernels. My current understanding
is that there is no way to pin memory and hugepages can now
be moved around, so uio would be unsafe. What does the
community think here?
My second question is whether the user should be allowed to
mix uio and vfio usage simultaneously. For vfio, the
physical addresses are really DMA addresses and are best
when arbitrarily chosen to appear sequential relative to
their virtual addresses. For uio, they are physical
addresses and are not chosen at all. It seems that these two
things are in conflict and that it will be difficult, ugly,
and maybe impossible to resolve the simultaneous use of
both.
Once we agree on the above two things, we can try to talk
through some solutions in the code.
Thanks,
Ben
^ permalink raw reply
* [PATCH v2 5/5] test: add sgl unit tests for crypto devices
From: Tomasz Kulasek @ 2016-12-29 17:12 UTC (permalink / raw)
To: dev; +Cc: olivier.matz
In-Reply-To: <1483031543-21196-1-git-send-email-tomaszx.kulasek@intel.com>
This patch provides unit tests for set of cipher/hash combinations covering
currently implemented crypto PMD's and allowing to verify scatter gather
support.
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
app/test/test_cryptodev.c | 589 +++++++++++++++++++++++++++-
app/test/test_cryptodev.h | 139 +++++++
app/test/test_cryptodev_aes_test_vectors.h | 54 ++-
app/test/test_cryptodev_blockcipher.c | 181 ++++++---
app/test/test_cryptodev_blockcipher.h | 3 +-
app/test/test_cryptodev_des_test_vectors.h | 29 ++
app/test/test_cryptodev_gcm_test_vectors.h | 557 +++++++++++++++++++++++++-
7 files changed, 1477 insertions(+), 75 deletions(-)
diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index 872f8b4..e419f80 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -1688,6 +1688,10 @@ struct crypto_unittest_params {
TEST_ASSERT_NOT_NULL(sym_op->cipher.iv.data, "no room to prepend iv");
+ /* For OOP operation both buffers must have the same size */
+ if (ut_params->obuf)
+ rte_pktmbuf_prepend(ut_params->obuf, iv_pad_len);
+
memset(sym_op->cipher.iv.data, 0, iv_pad_len);
sym_op->cipher.iv.phys_addr = rte_pktmbuf_mtophys(ut_params->ibuf);
sym_op->cipher.iv.length = iv_pad_len;
@@ -2509,6 +2513,84 @@ struct crypto_unittest_params {
}
static int
+test_kasumi_encryption_sgl(const struct kasumi_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+
+ unsigned int plaintext_pad_len;
+ unsigned int plaintext_len;
+
+ uint8_t buffer[10000];
+ const uint8_t *ciphertext;
+
+ struct rte_cryptodev_info dev_info;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+ if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+ printf("Device doesn't support scatter-gather. "
+ "Test Skipped.\n");
+ return 0;
+ }
+
+ /* Create KASUMI session */
+ retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_CIPHER_KASUMI_F8,
+ tdata->key.data, tdata->key.len);
+ if (retval < 0)
+ return retval;
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+
+
+ /* Append data which is padded to a multiple */
+ /* of the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+ ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 10);
+
+ pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+ /* Create KASUMI operation */
+ retval = create_wireless_algo_cipher_operation(tdata->iv.data,
+ tdata->iv.len,
+ tdata->plaintext.len,
+ tdata->validCipherOffsetLenInBits.len,
+ RTE_CRYPTO_CIPHER_KASUMI_F8);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = ut_params->op->sym->m_dst;
+
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+ plaintext_len, buffer);
+ else
+ ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+ plaintext_len, buffer);
+
+ /* Validate obuf */
+ TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->validCipherLenInBits.len,
+ "KASUMI Ciphertext data not as expected");
+ return 0;
+}
+
+
+static int
test_kasumi_encryption_oop(const struct kasumi_test_data *tdata)
{
struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -2577,6 +2659,81 @@ struct crypto_unittest_params {
}
static int
+test_kasumi_encryption_oop_sgl(const struct kasumi_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ unsigned int plaintext_pad_len;
+ unsigned int plaintext_len;
+
+ const uint8_t *ciphertext;
+ uint8_t buffer[2048];
+
+ struct rte_cryptodev_info dev_info;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+ if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+ printf("Device doesn't support scatter-gather. "
+ "Test Skipped.\n");
+ return 0;
+ }
+
+ /* Create KASUMI session */
+ retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_CIPHER_KASUMI_F8,
+ tdata->key.data, tdata->key.len);
+ if (retval < 0)
+ return retval;
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ /* Append data which is padded to a multiple */
+ /* of the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+ ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 10);
+ ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 3);
+
+ /* Append data which is padded to a multiple */
+ /* of the algorithms block size */
+ pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+ /* Create KASUMI operation */
+ retval = create_wireless_algo_cipher_operation_oop(tdata->iv.data,
+ tdata->iv.len,
+ tdata->plaintext.len,
+ tdata->validCipherOffsetLenInBits.len,
+ RTE_CRYPTO_CIPHER_KASUMI_F8);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = ut_params->op->sym->m_dst;
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+ plaintext_pad_len, buffer);
+ else
+ ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+ plaintext_pad_len, buffer);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->validCipherLenInBits.len,
+ "KASUMI Ciphertext data not as expected");
+ return 0;
+}
+
+
+static int
test_kasumi_decryption_oop(const struct kasumi_test_data *tdata)
{
struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -2849,6 +3006,85 @@ struct crypto_unittest_params {
return 0;
}
+static int
+test_snow3g_encryption_oop_sgl(const struct snow3g_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ unsigned int plaintext_pad_len;
+ unsigned int plaintext_len;
+ uint8_t buffer[10000];
+ const uint8_t *ciphertext;
+
+ struct rte_cryptodev_info dev_info;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+ if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+ printf("Device doesn't support scatter-gather. "
+ "Test Skipped.\n");
+ return 0;
+ }
+
+ /* Create SNOW 3G session */
+ retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ tdata->key.data, tdata->key.len);
+ if (retval < 0)
+ return retval;
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ /* Append data which is padded to a multiple of */
+ /* the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+ ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 10);
+ ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 3);
+
+ TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+ "Failed to allocate input buffer in mempool");
+ TEST_ASSERT_NOT_NULL(ut_params->obuf,
+ "Failed to allocate output buffer in mempool");
+
+ pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+ /* Create SNOW 3G operation */
+ retval = create_wireless_algo_cipher_operation_oop(tdata->iv.data,
+ tdata->iv.len,
+ tdata->validCipherLenInBits.len,
+ tdata->validCipherOffsetLenInBits.len,
+ RTE_CRYPTO_CIPHER_SNOW3G_UEA2);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = ut_params->op->sym->m_dst;
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+ plaintext_len, buffer);
+ else
+ ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+ plaintext_len, buffer);
+
+ TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->validDataLenInBits.len,
+ "SNOW 3G Ciphertext data not as expected");
+
+ return 0;
+}
+
/* Shift right a buffer by "offset" bits, "offset" < 8 */
static void
buffer_shift_right(uint8_t *buffer, uint32_t length, uint8_t offset)
@@ -3504,6 +3740,84 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
}
static int
+test_zuc_encryption_sgl(const struct zuc_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+
+ unsigned int plaintext_pad_len;
+ unsigned int plaintext_len;
+ const uint8_t *ciphertext;
+ uint8_t ciphertext_buffer[2048];
+ struct rte_cryptodev_info dev_info;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+ if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+ printf("Device doesn't support scatter-gather. "
+ "Test Skipped.\n");
+ return 0;
+ }
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+
+ /* Append data which is padded to a multiple */
+ /* of the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+ ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 10);
+
+ pktmbuf_write(ut_params->ibuf, 0, plaintext_len,
+ tdata->plaintext.data);
+
+ /* Create ZUC session */
+ retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ tdata->key.data, tdata->key.len);
+ if (retval < 0)
+ return retval;
+
+ /* Clear mbuf payload */
+
+ pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+ /* Create ZUC operation */
+ retval = create_wireless_algo_cipher_operation(tdata->iv.data,
+ tdata->iv.len, tdata->plaintext.len,
+ tdata->validCipherOffsetLenInBits.len,
+ RTE_CRYPTO_CIPHER_ZUC_EEA3);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = ut_params->op->sym->m_dst;
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_read(ut_params->obuf,
+ tdata->iv.len, plaintext_len, ciphertext_buffer);
+ else
+ ciphertext = rte_pktmbuf_read(ut_params->ibuf,
+ tdata->iv.len, plaintext_len, ciphertext_buffer);
+
+ /* Validate obuf */
+ TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->validCipherLenInBits.len,
+ "ZUC Ciphertext data not as expected");
+
+ return 0;
+}
+
+static int
test_zuc_authentication(const struct zuc_hash_test_data *tdata)
{
struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -3571,12 +3885,24 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
}
static int
+test_kasumi_encryption_test_case_1_sgl(void)
+{
+ return test_kasumi_encryption_sgl(&kasumi_test_case_1);
+}
+
+static int
test_kasumi_encryption_test_case_1_oop(void)
{
return test_kasumi_encryption_oop(&kasumi_test_case_1);
}
static int
+test_kasumi_encryption_test_case_1_oop_sgl(void)
+{
+ return test_kasumi_encryption_oop_sgl(&kasumi_test_case_1);
+}
+
+static int
test_kasumi_encryption_test_case_2(void)
{
return test_kasumi_encryption(&kasumi_test_case_2);
@@ -3648,6 +3974,13 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
}
static int
+test_snow3g_encryption_test_case_1_oop_sgl(void)
+{
+ return test_snow3g_encryption_oop_sgl(&snow3g_test_case_1);
+}
+
+
+static int
test_snow3g_encryption_test_case_1_offset_oop(void)
{
return test_snow3g_encryption_offset_oop(&snow3g_test_case_1);
@@ -3767,6 +4100,12 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
}
static int
+test_zuc_encryption_test_case_6_sgl(void)
+{
+ return test_zuc_encryption_sgl(&zuc_test_case_1);
+}
+
+static int
test_zuc_hash_generate_test_case_1(void)
{
return test_zuc_authentication(&zuc_hash_test_case_1);
@@ -3934,12 +4273,21 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
- sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
- ut_params->ibuf, auth_tag_len);
- TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
- "no room to append digest");
- sym_op->auth.digest.phys_addr = rte_pktmbuf_mtophys_offset(
- ut_params->ibuf, data_pad_len);
+ if (ut_params->obuf) {
+ sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
+ ut_params->obuf, auth_tag_len);
+ TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
+ "no room to append digest");
+ sym_op->auth.digest.phys_addr = sgl_pktmbuf_mtophys_offset(
+ ut_params->obuf, data_pad_len);
+ } else {
+ sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
+ ut_params->ibuf, auth_tag_len);
+ TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
+ "no room to append digest");
+ sym_op->auth.digest.phys_addr = sgl_pktmbuf_mtophys_offset(
+ ut_params->ibuf, data_pad_len);
+ }
sym_op->auth.digest.length = auth_tag_len;
if (op == RTE_CRYPTO_CIPHER_OP_DECRYPT) {
@@ -3986,6 +4334,11 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
TEST_HEXDUMP(stdout, "aad:",
sym_op->auth.aad.data, aad_len);
+ if (ut_params->obuf) {
+ rte_pktmbuf_prepend(ut_params->obuf, iv_pad_len);
+ rte_pktmbuf_prepend(ut_params->obuf, aad_buffer_len);
+ }
+
sym_op->cipher.data.length = data_len;
sym_op->cipher.data.offset = aad_buffer_len + iv_pad_len;
@@ -4085,6 +4438,109 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
}
static int
+test_mb_AES_GCM_authenticated_encryption_sgl(const struct gcm_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+ int retval;
+
+ unsigned int plaintext_len;
+ uint16_t plaintext_pad_len;
+ uint8_t ciphertext_buffer[2048], auth_tag_buffer[2048];
+ const uint8_t *ciphertext, *auth_tag;
+
+ struct rte_cryptodev_info dev_info;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+ if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+ printf("Device doesn't support scatter-gather. "
+ "Test Skipped.\n");
+ return 0;
+ }
+
+ /* Create GCM session */
+ retval = create_gcm_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ tdata->key.data, tdata->key.len,
+ tdata->aad.len, tdata->auth_tag.len,
+ RTE_CRYPTO_AUTH_OP_GENERATE);
+ if (retval < 0)
+ return retval;
+
+ plaintext_len = tdata->plaintext.len;
+
+ /* Append data which is padded to a multiple */
+ /* of the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+ ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 5);
+ pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+ ut_params->obuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ rte_pktmbuf_append(ut_params->obuf, plaintext_pad_len);
+
+ /* Create GCM operation */
+ retval = create_gcm_operation(RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ tdata->auth_tag.data, tdata->auth_tag.len,
+ tdata->iv.data, tdata->iv.len,
+ tdata->aad.data, tdata->aad.len,
+ tdata->plaintext.len, plaintext_pad_len);
+ if (retval < 0) {
+ printf("create operation failed\n");
+ return retval;
+ }
+
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ ut_params->op->sym->m_src = ut_params->ibuf;
+ ut_params->op->sym->m_dst = ut_params->obuf;
+
+ /* Process crypto operation */
+ TEST_ASSERT_NOT_NULL(process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op), "failed to process sym crypto op");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto op processing failed");
+
+ /* Validate obuf */
+ if (ut_params->op->sym->m_dst) {
+ ciphertext = rte_pktmbuf_read(ut_params->op->sym->m_dst,
+ ut_params->op->sym->cipher.data.offset,
+ plaintext_pad_len, ciphertext_buffer);
+ auth_tag = rte_pktmbuf_read(ut_params->op->sym->m_dst,
+ plaintext_pad_len +
+ RTE_ALIGN_CEIL(tdata->iv.len, 16) +
+ ALIGN_POW2_ROUNDUP(tdata->aad.len, 16),
+ tdata->auth_tag.len, auth_tag_buffer);
+ } else {
+ ciphertext = rte_pktmbuf_read(ut_params->op->sym->m_src,
+ ut_params->op->sym->cipher.data.offset,
+ plaintext_pad_len, ciphertext_buffer);
+ auth_tag = rte_pktmbuf_read(ut_params->op->sym->m_src,
+ plaintext_pad_len +
+ RTE_ALIGN_CEIL(tdata->iv.len, 16) +
+ ALIGN_POW2_ROUNDUP(tdata->aad.len, 16),
+ tdata->auth_tag.len, auth_tag_buffer);
+ }
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->ciphertext.len,
+ "GCM Ciphertext data not as expected");
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ auth_tag,
+ tdata->auth_tag.data,
+ tdata->auth_tag.len,
+ "GCM Generated auth tag not as expected");
+
+ return 0;
+
+}
+
+static int
test_mb_AES_GCM_authenticated_encryption_test_case_1(void)
{
return test_mb_AES_GCM_authenticated_encryption(&gcm_test_case_1);
@@ -4127,6 +4583,12 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
}
static int
+test_mb_AES_GCM_authenticated_encryption_test_case_8(void)
+{
+ return test_mb_AES_GCM_authenticated_encryption_sgl(&gcm_test_case_7);
+}
+
+static int
test_mb_AES_GCM_authenticated_decryption(const struct gcm_test_data *tdata)
{
struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -4204,6 +4666,97 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
}
static int
+test_mb_AES_GCM_authenticated_decryption_sgl(const struct gcm_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+ int retval;
+
+ unsigned int ciphertext_len;
+ uint16_t ciphertext_pad_len;
+ uint8_t plaintext_buffer[2048];
+ const uint8_t *plaintext;
+
+ struct rte_cryptodev_info dev_info;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+ if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+ printf("Device doesn't support scatter-gather. "
+ "Test Skipped.\n");
+ return 0;
+ }
+
+ /* Create GCM session */
+ retval = create_gcm_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_DECRYPT,
+ tdata->key.data, tdata->key.len,
+ tdata->aad.len, tdata->auth_tag.len,
+ RTE_CRYPTO_AUTH_OP_VERIFY);
+ if (retval < 0)
+ return retval;
+
+ ciphertext_len = tdata->ciphertext.len;
+
+ /* Append data which is padded to a multiple */
+ /* of the algorithms block size */
+ ciphertext_pad_len = RTE_ALIGN_CEIL(ciphertext_len, 16);
+
+ ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ ciphertext_pad_len, 5);
+ pktmbuf_write(ut_params->ibuf, 0, ciphertext_len,
+ tdata->ciphertext.data);
+
+ ut_params->obuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ rte_pktmbuf_append(ut_params->obuf, ciphertext_pad_len);
+
+ /* Create GCM operation */
+ retval = create_gcm_operation(RTE_CRYPTO_CIPHER_OP_DECRYPT,
+ tdata->auth_tag.data, tdata->auth_tag.len,
+ tdata->iv.data, tdata->iv.len,
+ tdata->aad.data, tdata->aad.len,
+ tdata->ciphertext.len, ciphertext_pad_len);
+ if (retval < 0) {
+ printf("create operation failed\n");
+ return retval;
+ }
+
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ ut_params->op->sym->m_src = ut_params->ibuf;
+ ut_params->op->sym->m_dst = ut_params->obuf;
+
+ /* Process crypto operation */
+ TEST_ASSERT_NOT_NULL(process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op), "failed to process sym crypto op");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto op processing failed");
+
+ /* Validate obuf */
+ if (ut_params->op->sym->m_dst)
+ plaintext = rte_pktmbuf_read(ut_params->op->sym->m_dst,
+ ut_params->op->sym->cipher.data.offset,
+ ciphertext_pad_len, plaintext_buffer);
+ else
+ plaintext = rte_pktmbuf_read(ut_params->op->sym->m_src,
+ ut_params->op->sym->cipher.data.offset,
+ ciphertext_pad_len, plaintext_buffer);
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ plaintext,
+ tdata->plaintext.data,
+ tdata->plaintext.len,
+ "GCM Ciphertext data not as expected");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status,
+ RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "GCM authentication failed");
+
+ return 0;
+
+}
+
+static int
test_mb_AES_GCM_authenticated_decryption_test_case_1(void)
{
return test_mb_AES_GCM_authenticated_decryption(&gcm_test_case_1);
@@ -4246,6 +4799,12 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
}
static int
+test_mb_AES_GCM_authenticated_decryption_test_case_8(void)
+{
+ return test_mb_AES_GCM_authenticated_decryption_sgl(&gcm_test_case_8);
+}
+
+static int
test_stats(void)
{
struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -6224,6 +6783,9 @@ struct test_crypto_vector {
test_mb_AES_GCM_authenticated_encryption_test_case_6),
TEST_CASE_ST(ut_setup, ut_teardown,
test_mb_AES_GCM_authenticated_encryption_test_case_7),
+ /** chained mbuf encrypt tests **/
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_mb_AES_GCM_authenticated_encryption_test_case_8),
/** AES GCM Authenticated Decryption */
TEST_CASE_ST(ut_setup, ut_teardown,
@@ -6240,6 +6802,8 @@ struct test_crypto_vector {
test_mb_AES_GCM_authenticated_decryption_test_case_6),
TEST_CASE_ST(ut_setup, ut_teardown,
test_mb_AES_GCM_authenticated_decryption_test_case_7),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_mb_AES_GCM_authenticated_decryption_test_case_8),
/** AES GMAC Authentication */
TEST_CASE_ST(ut_setup, ut_teardown,
@@ -6297,6 +6861,9 @@ struct test_crypto_vector {
test_mb_AES_GCM_authenticated_encryption_test_case_6),
TEST_CASE_ST(ut_setup, ut_teardown,
test_mb_AES_GCM_authenticated_encryption_test_case_7),
+ /** chained mbuf encrypt tests **/
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_mb_AES_GCM_authenticated_encryption_test_case_8),
/** AES GCM Authenticated Decryption */
TEST_CASE_ST(ut_setup, ut_teardown,
@@ -6327,6 +6894,8 @@ struct test_crypto_vector {
TEST_CASE_ST(ut_setup, ut_teardown,
test_kasumi_encryption_test_case_1),
TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_1_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
test_kasumi_encryption_test_case_2),
TEST_CASE_ST(ut_setup, ut_teardown,
test_kasumi_encryption_test_case_3),
@@ -6349,6 +6918,10 @@ struct test_crypto_vector {
TEST_CASE_ST(ut_setup, ut_teardown,
test_kasumi_encryption_test_case_1_oop),
TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_1_oop_sgl),
+
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
test_kasumi_decryption_test_case_1_oop),
/** KASUMI hash only (UIA1) */
@@ -6401,6 +6974,8 @@ struct test_crypto_vector {
TEST_CASE_ST(ut_setup, ut_teardown,
test_snow3g_encryption_test_case_1_oop),
TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_1_oop_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
test_snow3g_decryption_test_case_1_oop),
TEST_CASE_ST(ut_setup, ut_teardown,
@@ -6478,6 +7053,8 @@ struct test_crypto_vector {
test_zuc_hash_generate_test_case_4),
TEST_CASE_ST(ut_setup, ut_teardown,
test_zuc_hash_generate_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_6_sgl),
TEST_CASES_END() /**< NULL terminate unit test array */
}
};
diff --git a/app/test/test_cryptodev.h b/app/test/test_cryptodev.h
index a9089aa..77cd826 100644
--- a/app/test/test_cryptodev.h
+++ b/app/test/test_cryptodev.h
@@ -71,4 +71,143 @@
#define TRUNCATED_DIGEST_BYTE_LENGTH_SHA384 (24)
#define TRUNCATED_DIGEST_BYTE_LENGTH_SHA512 (32)
+/**
+ * Write (spread) data from buffer to mbuf data
+ *
+ * @param mbuf
+ * Destination mbuf
+ * @param offset
+ * Start offset in mbuf
+ * @param len
+ * Number of bytes to copy
+ * @param buffer
+ * Continuous source buffer
+ */
+static inline void
+pktmbuf_write(struct rte_mbuf *mbuf, int offset, int len, const uint8_t *buffer)
+{
+ int n = len;
+ int l;
+ struct rte_mbuf *m;
+ char *dst;
+
+ for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+ offset -= m->data_len;
+
+ l = m->data_len - offset;
+
+ /* copy data from first segment */
+ dst = rte_pktmbuf_mtod_offset(m, char *, offset);
+ if (len <= l) {
+ rte_memcpy(dst, buffer, len);
+ return;
+ }
+
+ rte_memcpy(dst, buffer, l);
+ buffer += l;
+ n -= l;
+
+ for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+ dst = rte_pktmbuf_mtod(m, char *);
+ l = m->data_len;
+ if (n < l) {
+ rte_memcpy(dst, buffer, n);
+ return;
+ }
+ rte_memcpy(dst, buffer, l);
+ buffer += l;
+ n -= l;
+ }
+}
+
+static inline uint8_t *
+sgl_pktmbuf_mtod_offset(struct rte_mbuf *mbuf, int offset) {
+ struct rte_mbuf *m;
+
+ for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+ offset -= m->data_len;
+
+ if (!m) {
+ printf("sgl_pktmbuf_mtod_offset: offset out of buffer\n");
+ return NULL;
+ }
+ return rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+}
+
+static inline phys_addr_t
+sgl_pktmbuf_mtophys_offset(struct rte_mbuf *mbuf, int offset) {
+ struct rte_mbuf *m;
+
+ for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+ offset -= m->data_len;
+
+ if (!m) {
+ printf("sgl_pktmbuf_mtophys_offset: offset out of buffer\n");
+ return 0;
+ }
+ return rte_pktmbuf_mtophys_offset(m, offset);
+}
+
+static inline struct rte_mbuf *
+create_segmented_mbuf(struct rte_mempool *mbuf_pool, int pkt_len,
+ int nb_segs) {
+
+ struct rte_mbuf *m = NULL, *mbuf = NULL;
+ uint8_t *dst;
+ int data_len = 0;
+ int i, size;
+ int t_len;
+
+ if (pkt_len < 1) {
+ printf("Packet size must be 1 or more (is %d)\n", pkt_len);
+ return NULL;
+ }
+
+ if (nb_segs < 1) {
+ printf("Number of segments must be 1 or more (is %d)\n",
+ nb_segs);
+ return NULL;
+ }
+
+ t_len = pkt_len >= nb_segs ? pkt_len / nb_segs : 1;
+ size = pkt_len;
+
+ /* Create chained mbuf_src and fill it generated data */
+ for (i = 0; size > 0; i++) {
+
+ m = rte_pktmbuf_alloc(mbuf_pool);
+ if (i == 0)
+ mbuf = m;
+
+ if (!m) {
+ printf("Cannot create segment for source mbuf");
+ goto fail;
+ }
+
+ /* Make sure if tailroom is zeroed */
+ memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
+ rte_pktmbuf_tailroom(m));
+
+ data_len = size > t_len ? t_len : size;
+ dst = (uint8_t *)rte_pktmbuf_append(m, data_len);
+ if (!dst) {
+ printf("Cannot append %d bytes to the mbuf\n",
+ data_len);
+ goto fail;
+ }
+
+ if (mbuf != m)
+ rte_pktmbuf_chain(mbuf, m);
+
+ size -= data_len;
+
+ }
+ return mbuf;
+
+fail:
+ if (mbuf)
+ rte_pktmbuf_free(mbuf);
+ return NULL;
+}
+
#endif /* TEST_CRYPTODEV_H_ */
diff --git a/app/test/test_cryptodev_aes_test_vectors.h b/app/test/test_cryptodev_aes_test_vectors.h
index 1c68f93..901412f 100644
--- a/app/test/test_cryptodev_aes_test_vectors.h
+++ b/app/test/test_cryptodev_aes_test_vectors.h
@@ -858,6 +858,16 @@
BLOCKCIPHER_TEST_TARGET_PMD_QAT
},
{
+ .test_descr = "AES-192-CTR XCBC Decryption Digest Verify "
+ "Scatter Gather",
+ .test_data = &aes_test_data_2,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+ BLOCKCIPHER_TEST_FEATURE_OOP,
+ .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+ BLOCKCIPHER_TEST_TARGET_PMD_QAT
+ },
+ {
.test_descr = "AES-256-CTR HMAC-SHA1 Encryption Digest",
.test_data = &aes_test_data_3,
.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
@@ -883,6 +893,18 @@
BLOCKCIPHER_TEST_TARGET_PMD_QAT
},
{
+ .test_descr = "AES-128-CBC HMAC-SHA1 Encryption Digest "
+ "Scatter Gather",
+ .test_data = &aes_test_data_4,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+ BLOCKCIPHER_TEST_FEATURE_OOP,
+ .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+ BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+ BLOCKCIPHER_TEST_TARGET_PMD_QAT
+
+ },
+ {
.test_descr = "AES-128-CBC HMAC-SHA1 Decryption Digest "
"Verify",
.test_data = &aes_test_data_4,
@@ -926,6 +948,17 @@
BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
},
{
+ .test_descr = "AES-128-CBC HMAC-SHA512 Encryption Digest "
+ "Scatter Gather Sessionless",
+ .test_data = &aes_test_data_6,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SESSIONLESS |
+ BLOCKCIPHER_TEST_FEATURE_SG |
+ BLOCKCIPHER_TEST_FEATURE_OOP,
+ .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+ BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+ },
+ {
.test_descr = "AES-128-CBC HMAC-SHA512 Decryption Digest "
"Verify",
.test_data = &aes_test_data_6,
@@ -935,6 +968,17 @@
BLOCKCIPHER_TEST_TARGET_PMD_QAT
},
{
+ .test_descr = "AES-128-CBC HMAC-SHA512 Decryption Digest "
+ "Verify Scatter Gather",
+ .test_data = &aes_test_data_6,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+ BLOCKCIPHER_TEST_FEATURE_OOP,
+ .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+ BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+ BLOCKCIPHER_TEST_TARGET_PMD_QAT
+ },
+ {
.test_descr = "AES-128-CBC XCBC Encryption Digest",
.test_data = &aes_test_data_7,
.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
@@ -1033,9 +1077,17 @@
.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
},
{
- .test_descr = "AES-192-CBC Encryption",
+ .test_descr = "AES-192-CBC",
+ .test_data = &aes_test_data_10,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+ },
+ {
+ .test_descr = "AES-192-CBC Encryption Scater gather",
.test_data = &aes_test_data_10,
.op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+ BLOCKCIPHER_TEST_FEATURE_OOP,
.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
},
{
diff --git a/app/test/test_cryptodev_blockcipher.c b/app/test/test_cryptodev_blockcipher.c
index 37b10cf..bdf97d3 100644
--- a/app/test/test_cryptodev_blockcipher.c
+++ b/app/test/test_cryptodev_blockcipher.c
@@ -41,6 +41,7 @@
#include <rte_cryptodev_pmd.h>
#include "test.h"
+#include "test_cryptodev.h"
#include "test_cryptodev_blockcipher.h"
#include "test_cryptodev_aes_test_vectors.h"
#include "test_cryptodev_des_test_vectors.h"
@@ -63,6 +64,7 @@
struct rte_crypto_sym_op *sym_op = NULL;
struct rte_crypto_op *op = NULL;
struct rte_cryptodev_sym_session *sess = NULL;
+ struct rte_cryptodev_info dev_info;
int status = TEST_SUCCESS;
const struct blockcipher_test_data *tdata = t->test_data;
@@ -72,6 +74,19 @@
uint32_t digest_len = 0;
char *buf_p = NULL;
+ int nb_segs = 3;
+ int nb_segs_oop = 1;
+
+ if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
+ rte_cryptodev_info_get(dev_id, &dev_info);
+ if (!(dev_info.feature_flags &
+ RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+ printf("Device doesn't support scatter-gather. "
+ "Test Skipped.\n");
+ return 0;
+ }
+ }
+
if (tdata->cipher_key.len)
memcpy(cipher_key, tdata->cipher_key.data,
tdata->cipher_key.len);
@@ -96,72 +111,112 @@
}
/* preparing data */
- ibuf = rte_pktmbuf_alloc(mbuf_pool);
- if (!ibuf) {
- snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
- "line %u FAILED: %s",
- __LINE__, "Allocation of rte_mbuf failed");
- status = TEST_FAILED;
- goto error_exit;
- }
if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
buf_len += tdata->iv.len;
if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
buf_len += digest_len;
- buf_p = rte_pktmbuf_append(ibuf, buf_len);
- if (!buf_p) {
- snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
- "line %u FAILED: %s",
- __LINE__, "No room to append mbuf");
- status = TEST_FAILED;
- goto error_exit;
- }
+ if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
- if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
- rte_memcpy(buf_p, tdata->iv.data, tdata->iv.len);
- buf_p += tdata->iv.len;
- }
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
+ ibuf = create_segmented_mbuf(mbuf_pool,
+ tdata->plaintext.len, nb_segs);
+ pktmbuf_write(ibuf, 0, tdata->plaintext.len,
+ tdata->plaintext.data);
+ } else {
+ ibuf = create_segmented_mbuf(mbuf_pool,
+ tdata->ciphertext.len, nb_segs);
+ pktmbuf_write(ibuf, 0, tdata->ciphertext.len,
+ tdata->ciphertext.data);
+ }
- /* only encryption requires plaintext.data input,
- * decryption/(digest gen)/(digest verify) use ciphertext.data
- * to be computed
- */
- if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
- rte_memcpy(buf_p, tdata->plaintext.data,
- tdata->plaintext.len);
- buf_p += tdata->plaintext.len;
- } else {
- rte_memcpy(buf_p, tdata->ciphertext.data,
- tdata->ciphertext.len);
- buf_p += tdata->ciphertext.len;
- }
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
+ rte_memcpy(rte_pktmbuf_prepend(ibuf, tdata->iv.len),
+ tdata->iv.data, tdata->iv.len);
+ }
- if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
- rte_memcpy(buf_p, tdata->digest.data, digest_len);
- else
- memset(buf_p, 0, digest_len);
+ buf_p = rte_pktmbuf_append(ibuf, digest_len);
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
+ rte_memcpy(buf_p, tdata->digest.data, digest_len);
+ else
+ memset(buf_p, 0, digest_len);
- if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
- obuf = rte_pktmbuf_alloc(mbuf_pool);
- if (!obuf) {
- snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
- "FAILED: %s", __LINE__,
- "Allocation of rte_mbuf failed");
+ } else {
+ ibuf = rte_pktmbuf_alloc(mbuf_pool);
+ if (!ibuf) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+ "line %u FAILED: %s",
+ __LINE__,
+ "Allocation of rte_mbuf failed");
status = TEST_FAILED;
goto error_exit;
}
- buf_p = rte_pktmbuf_append(obuf, buf_len);
+ buf_p = rte_pktmbuf_append(ibuf, buf_len);
if (!buf_p) {
- snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
- "FAILED: %s", __LINE__,
- "No room to append mbuf");
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+ "line %u FAILED: %s",
+ __LINE__, "No room to append mbuf");
status = TEST_FAILED;
goto error_exit;
}
- memset(buf_p, 0, buf_len);
+
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
+ rte_memcpy(buf_p, tdata->iv.data, tdata->iv.len);
+ buf_p += tdata->iv.len;
+ }
+
+ /* only encryption requires plaintext.data input,
+ * decryption/(digest gen)/(digest verify) use ciphertext.data
+ * to be computed
+ */
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
+ rte_memcpy(buf_p, tdata->plaintext.data,
+ tdata->plaintext.len);
+ buf_p += tdata->plaintext.len;
+ } else {
+ rte_memcpy(buf_p, tdata->ciphertext.data,
+ tdata->ciphertext.len);
+ buf_p += tdata->ciphertext.len;
+ }
+
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
+ rte_memcpy(buf_p, tdata->digest.data, digest_len);
+ else
+ memset(buf_p, 0, digest_len);
+ }
+
+ if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
+ if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
+ obuf = create_segmented_mbuf(mbuf_pool, buf_len,
+ nb_segs_oop);
+ if (!obuf) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+ "line %u FAILED: %s", __LINE__,
+ "Allocation of rte_mbuf failed");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ } else {
+ obuf = rte_pktmbuf_alloc(mbuf_pool);
+ if (!obuf) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+ "line %u FAILED: %s", __LINE__,
+ "Allocation of rte_mbuf failed");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ buf_p = rte_pktmbuf_append(obuf, buf_len);
+ if (!buf_p) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+ "line %u FAILED: %s", __LINE__,
+ "No room to append mbuf");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ memset(buf_p, 0, buf_len);
+ }
}
/* Generate Crypto op data structure */
@@ -176,7 +231,6 @@
}
sym_op = op->sym;
-
sym_op->m_src = ibuf;
if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
@@ -307,17 +361,17 @@
if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
- sym_op->auth.digest.data = rte_pktmbuf_mtod_offset
- (iobuf, uint8_t *, digest_offset);
+ sym_op->auth.digest.data = sgl_pktmbuf_mtod_offset
+ (iobuf, digest_offset);
sym_op->auth.digest.phys_addr =
- rte_pktmbuf_mtophys_offset(iobuf,
+ sgl_pktmbuf_mtophys_offset(iobuf,
digest_offset);
} else {
auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
- sym_op->auth.digest.data = rte_pktmbuf_mtod_offset
- (sym_op->m_src, uint8_t *, digest_offset);
+ sym_op->auth.digest.data = sgl_pktmbuf_mtod_offset
+ (sym_op->m_src, digest_offset);
sym_op->auth.digest.phys_addr =
- rte_pktmbuf_mtophys_offset(sym_op->m_src,
+ sgl_pktmbuf_mtophys_offset(sym_op->m_src,
digest_offset);
}
@@ -386,13 +440,10 @@
}
if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
- uint8_t *crypto_res;
+ uint8_t buffer[2048];
const uint8_t *compare_ref;
uint32_t compare_len;
- crypto_res = rte_pktmbuf_mtod_offset(iobuf, uint8_t *,
- tdata->iv.len);
-
if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
compare_ref = tdata->ciphertext.data;
compare_len = tdata->ciphertext.len;
@@ -401,7 +452,8 @@
compare_len = tdata->plaintext.len;
}
- if (memcmp(crypto_res, compare_ref, compare_len)) {
+ if (memcmp(rte_pktmbuf_read(iobuf, tdata->iv.len, compare_len,
+ buffer), compare_ref, compare_len)) {
snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
"FAILED: %s", __LINE__,
"Crypto data not as expected");
@@ -414,12 +466,11 @@
uint8_t *auth_res;
if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
- auth_res = rte_pktmbuf_mtod_offset(iobuf,
- uint8_t *,
- tdata->iv.len + tdata->ciphertext.len);
+ auth_res = sgl_pktmbuf_mtod_offset(iobuf,
+ tdata->iv.len + tdata->ciphertext.len);
else
- auth_res = rte_pktmbuf_mtod_offset(iobuf,
- uint8_t *, tdata->ciphertext.len);
+ auth_res = sgl_pktmbuf_mtod_offset(iobuf,
+ tdata->ciphertext.len);
if (memcmp(auth_res, tdata->digest.data, digest_len)) {
snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
diff --git a/app/test/test_cryptodev_blockcipher.h b/app/test/test_cryptodev_blockcipher.h
index 04ff1ee..148fc6d 100644
--- a/app/test/test_cryptodev_blockcipher.h
+++ b/app/test/test_cryptodev_blockcipher.h
@@ -42,9 +42,10 @@
#define BLOCKCIPHER_TEST_OP_AUTH_GEN 0x04
#define BLOCKCIPHER_TEST_OP_AUTH_VERIFY 0x08
-#define BLOCKCIPHER_TEST_FEATURE_OOP 0x01
+#define BLOCKCIPHER_TEST_FEATURE_OOP 0x01
#define BLOCKCIPHER_TEST_FEATURE_SESSIONLESS 0x02
#define BLOCKCIPHER_TEST_FEATURE_STOPPER 0x04 /* stop upon failing */
+#define BLOCKCIPHER_TEST_FEATURE_SG 0x08 /* Scatter Gather */
#define BLOCKCIPHER_TEST_TARGET_PMD_MB 0x0001 /* Multi-buffer flag */
#define BLOCKCIPHER_TEST_TARGET_PMD_QAT 0x0002 /* QAT flag */
diff --git a/app/test/test_cryptodev_des_test_vectors.h b/app/test/test_cryptodev_des_test_vectors.h
index a1d2d97..17bd064 100644
--- a/app/test/test_cryptodev_des_test_vectors.h
+++ b/app/test/test_cryptodev_des_test_vectors.h
@@ -800,6 +800,15 @@
.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
},
{
+ .test_descr = "3DES-192-CBC SHA1 Encryption Digest "
+ "Scatter Gather",
+ .test_data = &triple_des192cbc_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+ BLOCKCIPHER_TEST_FEATURE_OOP,
+ .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+ },
+ {
.test_descr = "3DES-192-CBC SHA1 Decryption Digest Verify",
.test_data = &triple_des192cbc_sha1_test_vector,
.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
@@ -813,6 +822,16 @@
BLOCKCIPHER_TEST_TARGET_PMD_QAT
},
{
+ .test_descr = "3DES-128-CTR HMAC-SHA1 Encryption Digest "
+ "Scatter Gather",
+ .test_data = &triple_des128ctr_hmac_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+ BLOCKCIPHER_TEST_FEATURE_OOP,
+ .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+ BLOCKCIPHER_TEST_TARGET_PMD_QAT
+ },
+ {
.test_descr = "3DES-128-CTR HMAC-SHA1 Decryption Digest Verify",
.test_data = &triple_des128ctr_hmac_sha1_test_vector,
.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
@@ -820,6 +839,16 @@
BLOCKCIPHER_TEST_TARGET_PMD_QAT
},
{
+ .test_descr = "3DES-128-CTR HMAC-SHA1 Decryption "
+ "Digest Verify Scatter Gather",
+ .test_data = &triple_des128ctr_hmac_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+ BLOCKCIPHER_TEST_FEATURE_OOP,
+ .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+ BLOCKCIPHER_TEST_TARGET_PMD_QAT
+ },
+ {
.test_descr = "3DES-128-CTR SHA1 Encryption Digest",
.test_data = &triple_des128ctr_sha1_test_vector,
.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
diff --git a/app/test/test_cryptodev_gcm_test_vectors.h b/app/test/test_cryptodev_gcm_test_vectors.h
index b404242..b2138a2 100644
--- a/app/test/test_cryptodev_gcm_test_vectors.h
+++ b/app/test/test_cryptodev_gcm_test_vectors.h
@@ -52,12 +52,12 @@ struct gcm_test_data {
} aad;
struct {
- uint8_t data[1024];
+ uint8_t data[2048];
unsigned len;
} plaintext;
struct {
- uint8_t data[1024];
+ uint8_t data[2048];
unsigned len;
} ciphertext;
@@ -450,6 +450,559 @@ struct gmac_test_data {
}
};
+static const struct gcm_test_data gcm_test_case_8 = {
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88
+ },
+ .len = 12
+ },
+ .aad = {
+ .data = {
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce
+ },
+ .len = 12
+ },
+ .plaintext = {
+ .data = {
+ 0xC5, 0x34, 0x2E, 0x83, 0xEB, 0x4C, 0x02, 0x03,
+ 0xF7, 0xB2, 0x57, 0x35, 0x26, 0x81, 0x63, 0xAE,
+ 0x1F, 0xCD, 0x2D, 0x02, 0x91, 0x5A, 0xDB, 0x3A,
+ 0xF1, 0x38, 0xD8, 0x75, 0x86, 0x20, 0xCC, 0x1E,
+ 0xE6, 0xDC, 0xFF, 0xB5, 0xEA, 0x0E, 0x18, 0x7A,
+ 0x86, 0x6C, 0xAB, 0x39, 0x2D, 0x90, 0xAC, 0x77,
+ 0x5D, 0xED, 0x65, 0xB3, 0x05, 0x29, 0xBB, 0x09,
+ 0xD0, 0x21, 0x74, 0x6A, 0x67, 0x1C, 0x95, 0x42,
+ 0x55, 0xAD, 0xC8, 0x91, 0x28, 0xFE, 0x16, 0x9A,
+ 0xE1, 0xCB, 0xCD, 0x68, 0x3B, 0xDF, 0x3E, 0x3A,
+ 0x34, 0xFE, 0x9B, 0xFB, 0xF5, 0x15, 0x2A, 0x29,
+ 0x18, 0x99, 0x24, 0xBF, 0xB6, 0x43, 0xDB, 0xD1,
+ 0x69, 0x26, 0x1E, 0x31, 0x2C, 0x8C, 0x3C, 0x6B,
+ 0x7F, 0x06, 0xA6, 0x03, 0xE2, 0x1A, 0x50, 0xFE,
+ 0x7C, 0x69, 0xE5, 0x5F, 0x35, 0x93, 0xE9, 0x20,
+ 0x14, 0xB1, 0xCA, 0x61, 0xE7, 0x9C, 0x89, 0x08,
+ 0xD6, 0xB1, 0xC2, 0x63, 0x1B, 0x86, 0x5E, 0xF1,
+ 0xF5, 0x23, 0x0E, 0x9B, 0xE5, 0xBD, 0x5D, 0x04,
+ 0xF7, 0xEF, 0x8E, 0x46, 0xB0, 0x11, 0x4F, 0x69,
+ 0x62, 0x35, 0x51, 0xB7, 0x24, 0xA2, 0x31, 0xD0,
+ 0x32, 0x4E, 0xB8, 0x44, 0xC7, 0x59, 0xDE, 0x25,
+ 0xEA, 0x2D, 0x00, 0x0E, 0xF1, 0x07, 0xBA, 0xBB,
+ 0x9A, 0xBC, 0x4F, 0x57, 0xB7, 0x13, 0x57, 0xEF,
+ 0xD9, 0xF6, 0x80, 0x69, 0xEA, 0xE8, 0x47, 0x9C,
+ 0x51, 0x71, 0xE6, 0x8F, 0x69, 0x29, 0xB4, 0x60,
+ 0xE8, 0x50, 0xE5, 0xD0, 0x9B, 0xD2, 0x62, 0x6F,
+ 0x09, 0x5C, 0xD1, 0x4B, 0x85, 0xE2, 0xFD, 0xD3,
+ 0xEB, 0x28, 0x55, 0x77, 0x97, 0xCA, 0xD6, 0xA8,
+ 0xDC, 0x35, 0x68, 0xF7, 0x6A, 0xCF, 0x48, 0x3F,
+ 0x49, 0x31, 0x00, 0x65, 0xB7, 0x31, 0x1A, 0x49,
+ 0x75, 0xDE, 0xCE, 0x7F, 0x18, 0xB5, 0x31, 0x9A,
+ 0x64, 0x6D, 0xE5, 0x49, 0x1D, 0x6D, 0xF2, 0x21,
+ 0x9F, 0xF5, 0xFF, 0x7C, 0x41, 0x30, 0x33, 0x06,
+ 0x7B, 0xA4, 0xD8, 0x99, 0xF6, 0xCC, 0xDF, 0xC4,
+ 0x3F, 0xF3, 0xCD, 0xE7, 0x74, 0xC4, 0x4A, 0x19,
+ 0x5C, 0xCA, 0x42, 0x31, 0xF1, 0x3B, 0x65, 0x1C,
+ 0x3D, 0x56, 0x08, 0xBE, 0x15, 0x37, 0x23, 0x50,
+ 0xD6, 0xA3, 0x57, 0x64, 0x25, 0xBE, 0xDA, 0xC2,
+ 0x4E, 0xF5, 0x1A, 0xAD, 0x6F, 0x43, 0x78, 0x21,
+ 0xF9, 0x36, 0x39, 0x1F, 0x5F, 0xF7, 0x1B, 0xA0,
+ 0xEE, 0x8B, 0x4F, 0x8A, 0x9D, 0xD8, 0xED, 0x37,
+ 0xCE, 0x0D, 0x70, 0xE0, 0x3F, 0xE7, 0x11, 0x30,
+ 0x17, 0x1D, 0x03, 0x5E, 0xA0, 0x3D, 0x3F, 0x9E,
+ 0xF5, 0xD3, 0x74, 0x2E, 0xC1, 0xD6, 0xFF, 0xF7,
+ 0x2E, 0xE7, 0x80, 0x88, 0xCF, 0x0E, 0x7F, 0x12,
+ 0x71, 0x62, 0xC7, 0xF1, 0xC4, 0x2B, 0x64, 0x5D,
+ 0x1C, 0x9A, 0xB4, 0xCB, 0xB8, 0x24, 0xB3, 0x0B,
+ 0x33, 0xF2, 0x8A, 0x8F, 0x76, 0xC8, 0x81, 0xDA,
+ 0x1A, 0x10, 0xB5, 0xA9, 0xCD, 0xDC, 0x1A, 0x02,
+ 0xC1, 0xAE, 0x4F, 0x02, 0x1B, 0x13, 0x96, 0x5A,
+ 0x2E, 0x03, 0xA2, 0x68, 0xB2, 0x29, 0xAC, 0x28,
+ 0xB8, 0xDC, 0xD5, 0x27, 0x55, 0xEC, 0x43, 0xDC,
+ 0xB7, 0x49, 0x1D, 0xE1, 0x30, 0x25, 0x81, 0xA6,
+ 0x90, 0x1F, 0x75, 0xBA, 0x19, 0x1E, 0xF7, 0xC5,
+ 0x77, 0x35, 0xEE, 0x68, 0x71, 0x22, 0xA0, 0xB4,
+ 0xCC, 0x99, 0x86, 0x1B, 0x1B, 0xC8, 0x27, 0xFC,
+ 0x6D, 0x8D, 0xE7, 0x8B, 0xC3, 0x40, 0x3D, 0xA8,
+ 0xCB, 0x9B, 0xC4, 0x12, 0x07, 0xDD, 0xA1, 0x92,
+ 0xE5, 0x80, 0x7A, 0xF4, 0xDB, 0x4C, 0xE6, 0xEE,
+ 0xF9, 0xD5, 0x1C, 0x20, 0x18, 0xD3, 0x8F, 0xDF,
+ 0x1C, 0xD3, 0x51, 0x4E, 0x0E, 0xED, 0x06, 0x61,
+ 0xF7, 0xBA, 0x81, 0x3A, 0x2F, 0xEA, 0xED, 0x70,
+ 0xA9, 0xD9, 0x54, 0x4D, 0xFC, 0x1D, 0x19, 0xEA,
+ 0xA6, 0x39, 0x8C, 0x6C, 0x78, 0xA8, 0x05, 0xEB,
+ 0xF2, 0xB5, 0xDE, 0x06, 0x9D, 0x8A, 0x78, 0x2A,
+ 0xF5, 0x50, 0xA4, 0xBD, 0x9B, 0xDA, 0xCA, 0x66,
+ 0xC0, 0x23, 0xAB, 0xE8, 0x95, 0x7E, 0xC9, 0xD2,
+ 0x6F, 0x09, 0xF2, 0x9A, 0x17, 0x89, 0xDA, 0x47,
+ 0x65, 0x8C, 0x20, 0xFA, 0x4E, 0x86, 0x18, 0xEB,
+ 0x7C, 0x08, 0xEC, 0x8A, 0x05, 0x54, 0x96, 0xD2,
+ 0x7A, 0x8A, 0x81, 0x58, 0x75, 0x8C, 0x7B, 0x02,
+ 0xEE, 0x1F, 0x51, 0x88, 0xD0, 0xD1, 0x90, 0x99,
+ 0x0C, 0xAE, 0x51, 0x2E, 0x54, 0x3E, 0xB1, 0x7D,
+ 0xBC, 0xE8, 0x54, 0x93, 0x6D, 0x10, 0x3C, 0xC6,
+ 0x71, 0xF6, 0xF5, 0x0B, 0x07, 0x0A, 0x6E, 0x59,
+ 0x20, 0x45, 0x21, 0x7D, 0x37, 0x64, 0x92, 0x09,
+ 0xA7, 0xE2, 0x34, 0x6F, 0xFC, 0xCC, 0x66, 0x0E,
+ 0x88, 0x1B, 0x19, 0x86, 0x11, 0xD7, 0x81, 0x25,
+ 0xF1, 0x8A, 0x03, 0xB7, 0x7A, 0xF0, 0x98, 0x4A,
+ 0x5C, 0xA1, 0x6D, 0x85, 0xA4, 0x8C, 0x4B, 0x65,
+ 0x9F, 0x72, 0x64, 0x14, 0xBA, 0x74, 0xEE, 0xA3,
+ 0x88, 0xFE, 0x1B, 0xCF, 0x11, 0x4F, 0xD1, 0xAC,
+ 0xFA, 0x14, 0xC3, 0xA7, 0xDD, 0x06, 0x85, 0x4E,
+ 0x64, 0x06, 0x92, 0x9C, 0xDF, 0x06, 0x09, 0xF1,
+ 0x4D, 0xE8, 0xF8, 0x2F, 0x69, 0xB6, 0x8A, 0xAF,
+ 0x25, 0x21, 0xB5, 0x48, 0x59, 0xF8, 0x9D, 0x60,
+ 0xAE, 0x42, 0x11, 0x7A, 0x68, 0x4D, 0x7E, 0x76,
+ 0xB0, 0xD2, 0xE3, 0xD9, 0x24, 0x16, 0x20, 0x0A,
+ 0xEB, 0xE0, 0x68, 0xCB, 0xBC, 0xAB, 0x67, 0xE4,
+ 0xF3, 0x25, 0x1F, 0xD3, 0x85, 0xA7, 0x1D, 0x7E,
+ 0x3C, 0x63, 0xCB, 0xC2, 0x50, 0x90, 0x0F, 0x4B,
+ 0x6E, 0x68, 0x06, 0x84, 0x65, 0xF7, 0xD0, 0xD4,
+ 0x12, 0xED, 0xFA, 0xC9, 0x40, 0xE2, 0xC0, 0xC9,
+ 0x46, 0x22, 0x47, 0x5E, 0x6D, 0xC1, 0x63, 0xDB,
+ 0x51, 0x98, 0xDA, 0x1A, 0xC4, 0xB9, 0xED, 0xE9,
+ 0x09, 0xB9, 0xCF, 0x91, 0x04, 0x1C, 0x63, 0xD8,
+ 0xC5, 0xA5, 0xAE, 0x53, 0x7B, 0xA1, 0x29, 0x83,
+ 0x37, 0xFB, 0xBF, 0x96, 0xBB, 0x24, 0x3D, 0x77,
+ 0x8C, 0x0F, 0xB3, 0x4B, 0x66, 0x9C, 0x54, 0xBB,
+ 0xF6, 0xDD, 0xD1, 0xB4, 0xD2, 0xF6, 0xAA, 0xED,
+ 0x18, 0x56, 0x63, 0x3E, 0x0B, 0xCA, 0xAB, 0x70,
+ 0xBB, 0x63, 0xEA, 0xB1, 0x00, 0x65, 0x90, 0x18,
+ 0xB8, 0x63, 0xA2, 0xF2, 0xB6, 0x1E, 0x61, 0x7B,
+ 0xD5, 0x01, 0xD9, 0x4D, 0xC9, 0x9D, 0x99, 0xC1,
+ 0x57, 0x9D, 0x6F, 0xAE, 0x64, 0xE4, 0x0C, 0x7E,
+ 0xFA, 0x15, 0x5E, 0xB6, 0x43, 0xB8, 0x8B, 0x89,
+ 0x87, 0xCD, 0x4F, 0xAD, 0x30, 0x1E, 0xA5, 0x03,
+ 0x7A, 0xC2, 0x10, 0x42, 0x14, 0x88, 0xD6, 0x7A,
+ 0x6D, 0x56, 0x52, 0x2E, 0x8D, 0x1B, 0x5D, 0x36,
+ 0x27, 0xA0, 0x21, 0x4B, 0x64, 0xF0, 0xC5, 0x41,
+ 0xAD, 0x05, 0x4A, 0x24, 0xE4, 0x70, 0x88, 0x63,
+ 0x12, 0xD0, 0xBC, 0x05, 0x38, 0xD9, 0x41, 0x68,
+ 0x9F, 0x16, 0x9A, 0x54, 0x09, 0x21, 0x64, 0x36,
+ 0x63, 0x97, 0x3A, 0xB5, 0xE0, 0x25, 0x43, 0x8A,
+ 0x6A, 0x59, 0x97, 0xC1, 0x31, 0xA5, 0x66, 0xD2,
+ 0xF0, 0x1C, 0xDF, 0x97, 0x51, 0xD0, 0x61, 0xBA,
+ 0x55, 0x5F, 0xD7, 0x0D, 0xD4, 0x75, 0x8E, 0x79,
+ 0x04, 0x75, 0x00, 0xB9, 0xC0, 0x7A, 0x66, 0x05,
+ 0x9F, 0x2B, 0x44, 0x42, 0x75, 0x0F, 0xD5, 0x15,
+ 0xD6, 0x16, 0x8F, 0x6C, 0x6E, 0xD4, 0x37, 0xCF,
+ 0xB4, 0xDA, 0x93, 0x00, 0x11, 0xFB, 0xBE, 0xEE,
+ 0x3B, 0x6D, 0x1D, 0xBA, 0x33, 0xD1, 0x52, 0x8B,
+ 0x16, 0x39, 0x42, 0x27, 0xE6, 0x56, 0x4C, 0x41,
+ 0x91, 0xB0, 0x98, 0xAE, 0x9B, 0x2D, 0x9B, 0x23,
+ 0x80, 0x4C, 0xEA, 0x98, 0x57, 0x95, 0x28, 0x94,
+ 0x43, 0xD3, 0x88, 0x12, 0xDF, 0x89, 0x5A, 0x7B,
+ 0xC5, 0xCB, 0x36, 0x54, 0x65, 0x74, 0xB8, 0x4E,
+ 0xE2, 0x4D, 0x01, 0xD5, 0x9C, 0x82, 0xB9, 0x1A,
+ 0x09, 0xD2, 0xCE, 0x04, 0x36, 0xD8, 0x41, 0xAC,
+ 0x4C, 0xAD, 0xC6, 0x52, 0x91, 0x1A, 0x06, 0x6D,
+ 0xFC, 0xAB, 0x29, 0x93, 0x87, 0x88, 0xB9, 0x8C,
+ 0xFA, 0x57, 0x2B, 0x05, 0x03, 0xD0, 0x18, 0xED,
+ 0x7A, 0x7B, 0x81, 0x6A, 0x97, 0x65, 0x5B, 0x90,
+ 0xDE, 0xA9, 0xFC, 0x8F, 0xFC, 0xBB, 0x98, 0xD8,
+ 0xFA, 0x32, 0x3F, 0x3F, 0x7F, 0x74, 0x65, 0x38,
+ 0xC4, 0x28, 0xEC, 0x27, 0x1F, 0x28, 0x01, 0xB1,
+ 0xAF, 0x2B, 0x8A, 0x05, 0x38, 0x7B, 0x77, 0xC9,
+ 0x61, 0x77, 0x34, 0x2C, 0x22, 0xE5, 0xEB, 0xDC,
+ 0x9D, 0x18, 0x6E, 0x23, 0x25, 0x52, 0x69, 0xB7,
+ 0x05, 0xDB, 0x66, 0x5D, 0xEA, 0x76, 0x83, 0x82,
+ 0x97, 0x39, 0xAF, 0xC0, 0x50, 0x81, 0x18, 0x0D,
+ 0x22, 0xFA, 0xB7, 0x44, 0x5C, 0x3F, 0x69, 0xF3,
+ 0xAC, 0xC5, 0x63, 0x9F, 0xD8, 0x72, 0x7E, 0x9A,
+ 0xC2, 0xEB, 0x79, 0xD0, 0x74, 0x65, 0xE8, 0xCA,
+ 0xFD, 0xA8, 0x7D, 0x23, 0x07, 0x99, 0x3E, 0xAF,
+ 0xDB, 0x67, 0x10, 0xC0, 0xE5, 0x61, 0x77, 0xC6,
+ 0x8D, 0xC4, 0x0E, 0xAA, 0x55, 0xE3, 0xC0, 0xC7,
+ 0xA5, 0x36, 0x28, 0x61, 0xDB, 0x16, 0x96, 0x5E,
+ 0x01, 0x47, 0x82, 0xE3, 0xEB, 0x20, 0x3F, 0x10,
+ 0xFA, 0x5A, 0xBC, 0xD3, 0xF9, 0xCE, 0x04, 0x87,
+ 0x51, 0x07, 0xF9, 0xD0, 0xE7, 0x6D, 0xCB, 0xCC,
+ 0xC4, 0x15, 0x00, 0xE2, 0xDC, 0x8E, 0x7B, 0x5C,
+ 0x9A, 0xF2, 0x78, 0x70, 0x4D, 0xA1, 0xAA, 0xB5,
+ 0x13, 0xCC, 0x71, 0x66, 0x5A, 0x79, 0x13, 0x3B,
+ 0x12, 0xCD, 0x40, 0x30, 0x5A, 0x49, 0xD4, 0x20,
+ 0xED, 0xCF, 0x4A, 0x75, 0xE6, 0xD5, 0xDD, 0x0F,
+ 0xD4, 0xBE, 0x98, 0x9F, 0xD7, 0x1F, 0xC0, 0x02,
+ 0x31, 0xFA, 0x67, 0x37, 0x25, 0x86, 0x56, 0x85,
+ 0x2B, 0xA2, 0x57, 0xCD, 0x8E, 0x74, 0xE7, 0x69,
+ 0xEE, 0x33, 0x5A, 0x3F, 0xCD, 0x1E, 0xE3, 0xB9,
+ 0xAA, 0x52, 0xF5, 0x22, 0x4E, 0xE3, 0xFF, 0xC8,
+ 0xE3, 0x13, 0xA3, 0x9A, 0x63, 0x23, 0xC3, 0xD7,
+ 0xE5, 0x88, 0x3E, 0x0A, 0x4B, 0xA5, 0x01, 0xE6,
+ 0x13, 0xCF, 0xED, 0xEE, 0x2A, 0x58, 0x09, 0x3F,
+ 0x2F, 0x28, 0xE7, 0xC4, 0x6B, 0xEC, 0x49, 0x51,
+ 0x79, 0x8F, 0xD5, 0x19, 0x5D, 0xA5, 0x10, 0xCE,
+ 0x8E, 0xF6, 0x26, 0x78, 0x7A, 0xA8, 0x11, 0x52,
+ 0x5F, 0x97, 0x14, 0xC9, 0x29, 0x87, 0xB8, 0xA0,
+ 0x2D, 0xE6, 0xA7, 0x2A, 0xD4, 0xFF, 0xEB, 0xBA,
+ 0xFD, 0x58, 0x39, 0x33, 0xB1, 0xCE, 0x0E, 0x78,
+ 0x67, 0x1E, 0xA1, 0x92, 0x77, 0x63, 0xF8, 0xC0,
+ 0x02, 0x49, 0x73, 0xC0, 0xA1, 0x26, 0x83, 0x04,
+ 0x9A, 0x5D, 0x85, 0x68, 0x2A, 0x2F, 0xCB, 0x88,
+ 0x8D, 0x14, 0xB1, 0x33, 0xFA, 0xFB, 0xE9, 0x05,
+ 0xBE, 0x24, 0x1A, 0x6B, 0x29, 0x2B, 0x3F, 0x52,
+ 0x8F, 0xFB, 0xE6, 0x02, 0x77, 0x50, 0x71, 0xDB,
+ 0xE9, 0x92, 0x3F, 0xE1, 0x20, 0x62, 0x80, 0xAE,
+ 0xA4, 0x98, 0xC6, 0xCD, 0xE0, 0xB1, 0xC3, 0x33,
+ 0xB1, 0xC5, 0x91, 0x3C, 0x19, 0x34, 0xA8, 0xD9,
+ 0xB3, 0x25, 0x69, 0xE3, 0x9C, 0x5F, 0x78, 0xD0,
+ 0x83, 0x1F, 0xAB, 0x85, 0x13, 0x56, 0x69, 0xB5,
+ 0x06, 0x47, 0x62, 0x37, 0x27, 0x15, 0x14, 0x05,
+ 0x4A, 0xF4, 0x6A, 0x68, 0x2A, 0x6A, 0xC3, 0x5A,
+ 0xDF, 0xB5, 0xAE, 0x2F, 0x8D, 0x8F, 0x21, 0xDB,
+ 0x33, 0x00, 0x9B, 0xD4, 0xC4, 0x08, 0x3B, 0x81,
+ 0x63, 0x4C, 0xB0, 0x39, 0x4C, 0x0A, 0xD5, 0x71,
+ 0x3E, 0x5A, 0x50, 0x58, 0x9C, 0x07, 0x89, 0x79,
+ 0x79, 0x2F, 0x0B, 0xD9, 0x50, 0xBC, 0xCF, 0x46,
+ 0x7A, 0x68, 0x5C, 0xBF, 0x1E, 0x49, 0x77, 0x92,
+ 0x85, 0x11, 0x39, 0xA6, 0x2F, 0xDA, 0x7B, 0xFA,
+ 0x72, 0x87, 0x06, 0xCD, 0x84, 0x41, 0x20, 0x1B,
+ 0x66, 0x3F, 0x42, 0x0C, 0x9E, 0x19, 0xD3, 0x18,
+ 0x57, 0xA0, 0xEE, 0x16, 0x3A, 0xC7, 0xF9, 0xD3,
+ 0x8B, 0xC9, 0x24, 0x70, 0x70, 0x51, 0x7C, 0x06,
+ 0x68, 0xD3, 0x29, 0xC9, 0x85, 0x9A, 0x1C, 0xE6,
+ 0x8C, 0x17, 0xF4, 0x88, 0xDF, 0xEA, 0xFF, 0x44,
+ 0x8D, 0x54, 0xBE, 0x22, 0x07, 0xA5, 0x7C, 0x0C,
+ 0xF4, 0x8D, 0xB1, 0x0C, 0x07, 0xED, 0xBD, 0x28,
+ 0x19, 0xDA, 0x07, 0x71, 0xA8, 0xA1, 0xE0, 0xDD,
+ 0xEE, 0x08, 0x18, 0xA5, 0xBD, 0xDD, 0x32, 0x0B,
+ 0x70, 0x1C, 0xD9, 0xEE, 0x19, 0xC2, 0xAE, 0x5C,
+ 0xE3, 0x02, 0x74, 0x70, 0x96, 0x61, 0xB1, 0x73,
+ 0x3B, 0xD6, 0x74, 0xC0, 0x82, 0xA9, 0x1F, 0xE0,
+ 0xF1, 0x22, 0x50, 0xF3, 0x9F, 0xE5, 0x13, 0x92,
+ 0xFC, 0x0A, 0x1A, 0x3C, 0xB4, 0x46, 0xFB, 0x81,
+ 0x00, 0x84, 0xA4, 0x5E, 0x6B, 0x8C, 0x25, 0x6E,
+ 0xD7, 0xB7, 0x3B, 0x01, 0x65, 0xFB, 0x0B, 0x46,
+ 0x67, 0x27, 0x2D, 0x51, 0xAD, 0xB5, 0xE0, 0x85,
+ 0xC2, 0x95, 0xA3, 0xE3, 0x68, 0x4D, 0x9E, 0x8C,
+ 0x11, 0x53, 0xF0, 0xB2, 0x85, 0xFA, 0x52, 0x4E,
+ 0xEC, 0xF9, 0xB7, 0x3C, 0x89, 0x2C, 0x4D, 0x32,
+ 0x9A, 0xCB, 0x17, 0xF3, 0x16, 0xBF, 0x44, 0x40,
+ 0xE9, 0x5E, 0x51, 0x8C, 0x1E, 0x52, 0x0A, 0xC2,
+ 0xCD, 0xA5, 0xAA, 0x03, 0x27, 0xB0, 0x8F, 0x64,
+ 0xDB, 0xD7, 0x03, 0x01, 0x8A, 0x24, 0x28, 0x7E,
+ 0x53, 0x6F, 0x24, 0xFD, 0xAA, 0xE3, 0x78, 0xB6,
+ 0xA5, 0x5D, 0x5A, 0x67, 0x20, 0xE2, 0xBE, 0x3A,
+ 0x2B, 0xE7, 0x86, 0x11, 0xDD, 0x96, 0xCB, 0x09,
+ 0x65, 0xA0, 0x36, 0xF9, 0xB0, 0x20, 0x21, 0x8E,
+ 0xDB, 0xC0, 0x73, 0xC7, 0x79, 0xD8, 0xDA, 0xC2,
+ 0x66, 0x13, 0x64, 0x34, 0x0C, 0xE1, 0x22, 0x24,
+ 0x61, 0x67, 0x08, 0x39, 0x97, 0x3F, 0x33, 0x96,
+ 0xF2, 0x44, 0x18, 0x75, 0xBB, 0xF5, 0x6A, 0x5C,
+ 0x2C, 0xAE, 0x2A, 0x79, 0x3D, 0x47, 0x19, 0x53,
+ 0x50, 0x6C, 0x9F, 0xB3, 0x82, 0x55, 0x09, 0x78,
+ 0x7B, 0xAD, 0xBC, 0x05, 0x6F, 0xC8, 0x3D, 0xB6,
+ 0x7B, 0x30, 0xE6, 0xBB, 0x8B, 0xD0, 0x2F, 0xA6,
+ 0x15, 0xCC, 0x77, 0x8C, 0x21, 0xBA, 0x03, 0xED,
+ 0x56, 0x85, 0x82, 0x4F, 0x97, 0x8C, 0x59, 0x4F,
+ 0x53, 0x5A, 0xD2, 0x70, 0xD9, 0x07, 0xB3, 0xBD,
+ 0x1D, 0x3E, 0x97, 0xD4, 0x7D, 0x93, 0x35, 0xA4,
+ 0x82, 0x6E, 0xEA, 0x4B, 0xC8, 0x6C, 0xF5, 0xE6,
+ 0xEB, 0xAF, 0x11, 0xB0, 0xB4, 0x71, 0x8F, 0x7B,
+ 0xC4, 0x8C, 0xE2, 0x66, 0x51, 0x31, 0x99, 0x01,
+ 0x5B, 0xE7, 0x48, 0xF8, 0x4C, 0xE3, 0x9A, 0x77,
+ 0xF1, 0xC6, 0x09, 0xDE, 0x76, 0xD4, 0xE3, 0x5C,
+ 0xDF, 0xA3, 0xEC, 0x3C, 0x86, 0x7C, 0xA5, 0x3F,
+ 0x8D, 0x2A, 0xF3, 0x0B, 0x54, 0xB7, 0x54, 0xA2,
+ 0xC1, 0x69, 0xC0, 0x6F, 0x1C, 0x1C, 0x76, 0xD8,
+ 0x9F, 0x7A, 0x32, 0xB0, 0xA1, 0xA6, 0x9B, 0xB7,
+ 0x21, 0x56, 0x28, 0x2D, 0xB6, 0x97, 0x03, 0x5E,
+ 0x65, 0xE3, 0x74, 0x9A, 0x96, 0x7A, 0xF9, 0xF5,
+ 0xDD, 0x85, 0xCA, 0x4C, 0xB4, 0x03, 0x6A, 0xCD,
+ 0xB6, 0x01, 0xDC, 0x8B, 0xD8, 0x73, 0x8F, 0x4D,
+ 0x7F, 0xD6, 0x71, 0xEC, 0xD7, 0xC6, 0x0B, 0x5F,
+ 0x09, 0x21, 0xB2, 0x78, 0xA8, 0xAF, 0xAD, 0x2C,
+ 0xD4, 0x93, 0x9F, 0x71, 0xF7, 0x05, 0x89, 0x42,
+ 0xC9, 0x15, 0x6F, 0x2D, 0xE0, 0xBA, 0xC3, 0xD6,
+ 0xBF, 0xAC, 0xF8, 0x24, 0x58, 0x79, 0xA9, 0xC4,
+ 0xB4, 0x49, 0x3E, 0x0B, 0x9E, 0x5E, 0xE4, 0xA6,
+ 0x8B, 0xE8, 0xDE, 0xFB, 0x4A, 0xF1, 0x69, 0x9D,
+ 0x4F, 0x77, 0x83, 0x78, 0x55, 0x19, 0x42, 0x45,
+ 0xBF, 0xBD, 0xBD, 0x12, 0x0F, 0xEF, 0x8D, 0x04,
+ 0xD8, 0x5C, 0xF2, 0xC9, 0xF1, 0xA6, 0xE0, 0x3E,
+ 0x22, 0xA8, 0xA2, 0x5E, 0x66, 0xE9, 0xAB, 0xB4,
+ 0x71, 0xBE, 0x4B, 0x3F, 0xBE, 0xC4, 0xBA, 0x4A
+ },
+ .len = 2048
+ },
+ .ciphertext = {
+ .data = {
+ 0x5E, 0x86, 0x02, 0x64, 0x32, 0xBF, 0x70, 0xC2,
+ 0x19, 0x99, 0x7F, 0x47, 0x0D, 0xA4, 0x91, 0xA8,
+ 0x7A, 0xC0, 0xA5, 0x7E, 0xA8, 0x6C, 0x88, 0x00,
+ 0xEA, 0xB5, 0x96, 0x6B, 0x25, 0xBD, 0xE7, 0x42,
+ 0xDB, 0x35, 0xE7, 0x92, 0x2B, 0x00, 0x82, 0x35,
+ 0xD4, 0x2C, 0xCF, 0x47, 0xC8, 0xB2, 0xB3, 0x57,
+ 0xF7, 0x24, 0x83, 0x7F, 0xC5, 0x2E, 0xF1, 0xC9,
+ 0x57, 0x1A, 0xEF, 0xC2, 0x3A, 0x8C, 0x1E, 0x92,
+ 0x88, 0x05, 0xAF, 0x55, 0xE6, 0x0C, 0xA7, 0x6B,
+ 0x59, 0x62, 0x32, 0x21, 0xF1, 0xFF, 0xB5, 0x5B,
+ 0x22, 0x26, 0x6F, 0x0A, 0x36, 0xDC, 0x0D, 0x16,
+ 0x3B, 0x4E, 0x7C, 0xA3, 0x75, 0x30, 0x3F, 0xB0,
+ 0x99, 0x38, 0x42, 0x8E, 0x89, 0xA3, 0x7C, 0x99,
+ 0x2F, 0x0A, 0xA1, 0xC7, 0xFD, 0x2D, 0x21, 0x8F,
+ 0xBD, 0xD4, 0x11, 0xEA, 0x55, 0xF5, 0x6A, 0x50,
+ 0x90, 0x3B, 0x60, 0x57, 0xE1, 0x86, 0x1E, 0x50,
+ 0x28, 0x67, 0x3F, 0xD2, 0xF3, 0xBD, 0xFA, 0xEE,
+ 0xD6, 0x5A, 0x38, 0x30, 0xA3, 0xDD, 0x78, 0xC4,
+ 0x37, 0x59, 0x52, 0xC0, 0x92, 0x54, 0xC7, 0x53,
+ 0xF0, 0xE6, 0xA9, 0x63, 0x1F, 0x9B, 0x97, 0xFB,
+ 0x40, 0x23, 0xFE, 0x52, 0x6A, 0xF0, 0x3A, 0x94,
+ 0xEB, 0x6A, 0x9E, 0x8F, 0xC5, 0x05, 0x9C, 0x04,
+ 0x1B, 0x00, 0x34, 0x96, 0x12, 0xDA, 0x60, 0xC6,
+ 0xAA, 0x1A, 0x3E, 0xEB, 0x70, 0x17, 0x10, 0xBC,
+ 0xF5, 0xC2, 0xE2, 0x71, 0xF3, 0xB8, 0x1D, 0xCE,
+ 0x47, 0x94, 0x21, 0x71, 0x34, 0x8C, 0xCC, 0xDD,
+ 0x27, 0xCE, 0x6F, 0x68, 0xFF, 0x91, 0x4E, 0xC4,
+ 0xA0, 0xCA, 0xB0, 0x4F, 0x17, 0x53, 0x73, 0x92,
+ 0x6C, 0xA8, 0x16, 0x06, 0xE3, 0xD9, 0x92, 0x99,
+ 0xBE, 0xB0, 0x7D, 0x56, 0xF2, 0x72, 0x30, 0xDA,
+ 0xC4, 0x4E, 0xF4, 0xA6, 0x8F, 0xD2, 0xC7, 0x8A,
+ 0xA2, 0xFC, 0xF5, 0x63, 0x17, 0x48, 0x56, 0x4D,
+ 0xBE, 0x94, 0xFE, 0xF5, 0xB1, 0xA9, 0x96, 0xAB,
+ 0x3F, 0x2D, 0xD4, 0x15, 0xEE, 0x4F, 0xFA, 0x2C,
+ 0xBE, 0x91, 0xB7, 0xBC, 0x18, 0xC8, 0xDB, 0x02,
+ 0x20, 0x29, 0xF1, 0xC1, 0x88, 0x8C, 0x8D, 0xD1,
+ 0xB3, 0x4E, 0x93, 0x96, 0xDD, 0x22, 0xAB, 0x55,
+ 0xB5, 0x9F, 0x8B, 0x20, 0xAE, 0xC6, 0x0E, 0x26,
+ 0xC6, 0xFE, 0x2D, 0x5F, 0x95, 0x89, 0x06, 0x15,
+ 0x3D, 0x88, 0x16, 0xEC, 0x9B, 0x4A, 0x1B, 0x5D,
+ 0x2E, 0xB2, 0x13, 0x56, 0x9F, 0x33, 0xB3, 0x45,
+ 0xBF, 0x5F, 0x25, 0x7E, 0x75, 0x22, 0xD2, 0xE6,
+ 0x9F, 0xAC, 0x2D, 0xFD, 0x99, 0xC2, 0x9B, 0xFC,
+ 0xD7, 0x7A, 0x9B, 0x05, 0x30, 0x0F, 0xB7, 0x4A,
+ 0xFE, 0x24, 0xDD, 0x39, 0x9B, 0xBB, 0x2F, 0xDD,
+ 0xF9, 0xFB, 0xCA, 0x6C, 0x87, 0xBA, 0x73, 0xD4,
+ 0x85, 0x7B, 0xB2, 0x6F, 0x5C, 0xD8, 0xFB, 0xE9,
+ 0x41, 0x24, 0x3A, 0x3B, 0x4F, 0x91, 0x77, 0xA2,
+ 0x35, 0x78, 0xE5, 0x4C, 0xFE, 0x8B, 0x04, 0x03,
+ 0xD3, 0x84, 0xA9, 0x1C, 0xA7, 0x7C, 0x45, 0x13,
+ 0x7D, 0xC5, 0x0A, 0x2F, 0x02, 0xF8, 0x56, 0xD5,
+ 0x5F, 0x35, 0xED, 0x06, 0xBF, 0x67, 0xBA, 0x51,
+ 0x02, 0x95, 0x36, 0xF2, 0x9A, 0xBA, 0x9D, 0xF6,
+ 0xD6, 0x77, 0x50, 0xC9, 0xFC, 0x1E, 0x32, 0xB5,
+ 0x2F, 0xEA, 0x3C, 0x76, 0xB4, 0xE1, 0xCC, 0x42,
+ 0xEB, 0x71, 0x79, 0xD3, 0x7D, 0xB7, 0xC0, 0x88,
+ 0x25, 0x81, 0xE8, 0xC0, 0xB8, 0x38, 0x7E, 0x7B,
+ 0xFD, 0x18, 0xAB, 0x08, 0xB2, 0x71, 0xA5, 0xAD,
+ 0xA7, 0xBE, 0x48, 0x5F, 0x86, 0xE2, 0x41, 0x3D,
+ 0x7C, 0x37, 0x7A, 0xAB, 0xDB, 0xE0, 0x3B, 0x3D,
+ 0xB6, 0xE8, 0x23, 0x7C, 0xF1, 0x8F, 0xBA, 0xB7,
+ 0xE9, 0x78, 0x0B, 0xCA, 0x67, 0xA8, 0x10, 0x36,
+ 0xEB, 0x72, 0xED, 0xDD, 0xF0, 0x5C, 0x74, 0x8E,
+ 0xE5, 0x2A, 0xAE, 0x6E, 0xC4, 0xF1, 0xFC, 0xD8,
+ 0xEE, 0x56, 0x07, 0x88, 0x02, 0xDC, 0x9D, 0xB7,
+ 0xF9, 0x13, 0xE1, 0xE1, 0x9D, 0x89, 0x26, 0x0B,
+ 0x23, 0x74, 0x4A, 0x43, 0xAA, 0xA0, 0xA8, 0x97,
+ 0x85, 0x15, 0x58, 0xAB, 0x2B, 0xB5, 0xDA, 0x1A,
+ 0xBA, 0x29, 0x62, 0xCF, 0xDD, 0xA3, 0xBA, 0x9D,
+ 0x7D, 0x83, 0xA5, 0x18, 0xD4, 0x03, 0x0F, 0x61,
+ 0x9F, 0xB1, 0x7E, 0xEC, 0xD2, 0x6E, 0xAF, 0xCF,
+ 0x1E, 0xC1, 0x88, 0x97, 0x99, 0xD6, 0xBF, 0x47,
+ 0xB9, 0x0A, 0x69, 0x11, 0x3A, 0x55, 0x8B, 0x1D,
+ 0x2D, 0xFF, 0x78, 0xC8, 0xDE, 0x82, 0x29, 0xD6,
+ 0x08, 0x3C, 0xC4, 0xCB, 0x2F, 0x01, 0xD0, 0xE8,
+ 0xB1, 0x75, 0x5E, 0x23, 0xE0, 0x37, 0x7C, 0x1C,
+ 0xB6, 0xD9, 0x47, 0xDE, 0x23, 0x87, 0xD3, 0x68,
+ 0x47, 0x46, 0x78, 0xF3, 0xBF, 0x54, 0xA3, 0xB9,
+ 0x54, 0xD5, 0xC5, 0x0A, 0x7C, 0x92, 0x2A, 0xC2,
+ 0x14, 0x76, 0xA6, 0x5C, 0x6D, 0x0B, 0x94, 0x56,
+ 0x00, 0x6B, 0x5C, 0x27, 0xDE, 0x77, 0x9B, 0xF1,
+ 0xB1, 0x8C, 0xA7, 0x49, 0x77, 0xFC, 0x4E, 0x29,
+ 0x23, 0x8F, 0x2F, 0xF7, 0x83, 0x8D, 0x36, 0xD9,
+ 0xAB, 0x0E, 0x78, 0xF5, 0x90, 0x05, 0xB9, 0x79,
+ 0x70, 0x88, 0x59, 0x6F, 0xE2, 0xC5, 0xD7, 0x80,
+ 0x95, 0x04, 0x29, 0xE0, 0xFA, 0x37, 0xE8, 0x8B,
+ 0xC5, 0x21, 0x51, 0x1A, 0x62, 0xCE, 0x93, 0xAF,
+ 0x1A, 0xFE, 0xC3, 0x6F, 0x86, 0x94, 0x5E, 0x13,
+ 0xA6, 0x9A, 0x26, 0xF0, 0xB5, 0x7C, 0x41, 0x9A,
+ 0x80, 0xB8, 0x84, 0x5A, 0x55, 0xA9, 0xB0, 0x6A,
+ 0xFA, 0xEB, 0x46, 0x32, 0x0B, 0xE2, 0x9C, 0x65,
+ 0x86, 0x11, 0x39, 0x7E, 0xAF, 0x93, 0x19, 0x09,
+ 0x70, 0x40, 0x80, 0x14, 0xBA, 0x1D, 0xB3, 0x62,
+ 0x5B, 0xF3, 0x9A, 0x21, 0x98, 0x7E, 0x63, 0xB6,
+ 0x1A, 0xBD, 0x65, 0x98, 0x35, 0x2A, 0xA9, 0x76,
+ 0x29, 0x59, 0x84, 0x25, 0x81, 0xB8, 0xDE, 0x25,
+ 0x32, 0x10, 0x50, 0xB7, 0xD3, 0xB3, 0x69, 0xC8,
+ 0xE1, 0x33, 0xCB, 0x9E, 0x9C, 0x7A, 0x7C, 0xD2,
+ 0x6C, 0x92, 0x97, 0xA9, 0xFA, 0xAF, 0x30, 0xBA,
+ 0x9A, 0xB3, 0x3D, 0x9A, 0xE5, 0x0A, 0x9B, 0x8D,
+ 0x89, 0xE2, 0x2B, 0xB8, 0xBC, 0xF0, 0x23, 0xFF,
+ 0x7B, 0x0D, 0x00, 0x36, 0xEE, 0x79, 0xCB, 0xA5,
+ 0x70, 0x4C, 0x66, 0x02, 0x79, 0x2E, 0x5B, 0x83,
+ 0xCE, 0x55, 0x8B, 0x89, 0xD6, 0xE3, 0x71, 0x63,
+ 0xBC, 0xB1, 0x5F, 0x67, 0xB4, 0x7E, 0x05, 0x0D,
+ 0xAC, 0x6D, 0x4E, 0x2C, 0xA5, 0xF4, 0x47, 0x89,
+ 0xAC, 0x5E, 0xBE, 0x2F, 0xFC, 0x9B, 0x2F, 0x0B,
+ 0xBE, 0x63, 0x54, 0x97, 0xBB, 0x23, 0x27, 0xCD,
+ 0xB9, 0xB2, 0x28, 0x0D, 0xA4, 0x78, 0x2C, 0xAB,
+ 0xD1, 0xC9, 0x94, 0x40, 0x54, 0xF2, 0x35, 0x61,
+ 0x49, 0x01, 0x87, 0x55, 0xA5, 0xB5, 0x1E, 0x84,
+ 0x92, 0x9E, 0xC1, 0xA4, 0x0B, 0x66, 0x2B, 0xF8,
+ 0xAF, 0xC3, 0x1E, 0xAF, 0x66, 0x3F, 0x6F, 0x5F,
+ 0x70, 0xEC, 0x25, 0x29, 0xE4, 0x65, 0xB2, 0x04,
+ 0x47, 0xF6, 0x3C, 0xB5, 0x5F, 0x66, 0x9F, 0xA4,
+ 0x1B, 0xFC, 0xA2, 0xD5, 0x3E, 0x84, 0xBA, 0x88,
+ 0x0D, 0xF1, 0x6A, 0xF2, 0xF6, 0x1D, 0xF1, 0xA3,
+ 0x45, 0xB2, 0x51, 0xD8, 0xA2, 0x8F, 0x55, 0xA6,
+ 0x89, 0xC4, 0x15, 0xD5, 0x73, 0xA8, 0xB1, 0x31,
+ 0x66, 0x9E, 0xC1, 0x43, 0xE1, 0x5D, 0x4E, 0x04,
+ 0x84, 0x8F, 0xF2, 0xBC, 0xE1, 0x4E, 0x4D, 0x60,
+ 0x81, 0xCA, 0x53, 0x34, 0x95, 0x17, 0x3B, 0xAE,
+ 0x8F, 0x95, 0xA7, 0xC6, 0x47, 0xC6, 0xAC, 0x32,
+ 0x12, 0x39, 0xCA, 0xEF, 0xE0, 0x07, 0xBF, 0x17,
+ 0x4F, 0xDC, 0x1B, 0x4E, 0x3C, 0x84, 0xF1, 0x9F,
+ 0x43, 0x70, 0x19, 0xE6, 0xF3, 0x8B, 0x8B, 0x5D,
+ 0xDB, 0xD2, 0x9D, 0xD4, 0xB2, 0x30, 0x45, 0x55,
+ 0xA2, 0x67, 0xA2, 0x76, 0x4A, 0x74, 0xAD, 0x88,
+ 0x71, 0xE6, 0x3E, 0x13, 0x06, 0x30, 0x17, 0xE1,
+ 0xEF, 0xAC, 0x71, 0xFB, 0x43, 0xCD, 0xF6, 0xFA,
+ 0x0E, 0x4C, 0x4E, 0x16, 0xF6, 0x6A, 0x09, 0x86,
+ 0x6B, 0xEA, 0x47, 0x6C, 0x70, 0xE7, 0xAD, 0xA2,
+ 0xE0, 0xFD, 0x7F, 0xF0, 0x5C, 0x21, 0x53, 0x0F,
+ 0x28, 0xA1, 0x43, 0xE1, 0x06, 0xCA, 0x0B, 0x31,
+ 0x88, 0x22, 0xA6, 0xE6, 0x34, 0x5B, 0xE6, 0xCF,
+ 0x25, 0x81, 0x63, 0xFF, 0x78, 0x66, 0x85, 0x19,
+ 0xE2, 0x0A, 0x7E, 0x81, 0x8A, 0x17, 0x1A, 0x18,
+ 0x8A, 0x5F, 0x5D, 0x9E, 0x82, 0x13, 0x10, 0xB9,
+ 0xD3, 0xE6, 0x93, 0x1C, 0xE4, 0x2C, 0xCB, 0x49,
+ 0x1E, 0xB6, 0x36, 0x13, 0xBF, 0x28, 0xEE, 0xCC,
+ 0x49, 0xF5, 0x79, 0xFC, 0x20, 0x65, 0xBD, 0xE8,
+ 0xF0, 0x1B, 0x4E, 0xC0, 0x0D, 0x3E, 0x89, 0x91,
+ 0xCC, 0x64, 0x10, 0xC0, 0x2A, 0x2B, 0xA3, 0xFA,
+ 0x60, 0x3D, 0xC3, 0x52, 0x2F, 0x93, 0xDE, 0xB7,
+ 0x6E, 0x8A, 0xDF, 0x6C, 0x08, 0xCC, 0x8B, 0x3B,
+ 0xC8, 0x50, 0xEF, 0x58, 0x64, 0x9A, 0x3D, 0x16,
+ 0x70, 0x94, 0x11, 0xD8, 0x94, 0x2B, 0x70, 0x91,
+ 0x10, 0x70, 0x88, 0xF0, 0x40, 0x75, 0x9A, 0x2B,
+ 0x39, 0xA1, 0x27, 0x3F, 0x2E, 0x91, 0xEA, 0xA1,
+ 0xCC, 0x12, 0xC1, 0x7F, 0x73, 0x8C, 0x5C, 0x6B,
+ 0xFC, 0xC5, 0x6A, 0x1C, 0x05, 0xF1, 0x3D, 0x30,
+ 0x82, 0x4A, 0x65, 0x35, 0xCE, 0x80, 0x10, 0xBB,
+ 0x41, 0x94, 0xFB, 0x84, 0x80, 0x7B, 0x91, 0xC4,
+ 0x4D, 0xA3, 0x5F, 0xB9, 0xFB, 0xF9, 0xC9, 0x1D,
+ 0x4F, 0x99, 0x1C, 0x1F, 0x47, 0x44, 0x89, 0x0E,
+ 0xED, 0x6D, 0xB5, 0x85, 0x41, 0x94, 0xEF, 0xF9,
+ 0x2E, 0xA0, 0xC8, 0xCA, 0xFB, 0x44, 0x02, 0xC6,
+ 0xBF, 0x96, 0x87, 0x80, 0x1D, 0xEF, 0x2A, 0x81,
+ 0xAB, 0xB2, 0x56, 0xDF, 0x54, 0x8B, 0xAB, 0xAF,
+ 0xFE, 0x18, 0x8C, 0xAA, 0xD4, 0x00, 0x17, 0xBE,
+ 0xCF, 0x06, 0xE5, 0xA6, 0xBF, 0x5A, 0x52, 0x3B,
+ 0x4E, 0xF5, 0x65, 0x60, 0x95, 0xDE, 0x8A, 0x25,
+ 0x88, 0xA5, 0x24, 0x96, 0x29, 0x13, 0x0D, 0x19,
+ 0x45, 0x95, 0x91, 0x08, 0xD2, 0x9C, 0x4C, 0x34,
+ 0x42, 0xF0, 0xA5, 0x72, 0xEB, 0xFB, 0x5E, 0xAA,
+ 0x68, 0x80, 0x82, 0xAC, 0x34, 0xAD, 0x89, 0xF6,
+ 0xAF, 0x54, 0x82, 0xCF, 0x98, 0x8C, 0x75, 0x63,
+ 0x8D, 0xBD, 0x1C, 0x2A, 0xD7, 0x00, 0xA7, 0x8E,
+ 0xB9, 0x33, 0xB6, 0x3B, 0x95, 0x9A, 0x59, 0x1D,
+ 0x3F, 0x23, 0x6B, 0x18, 0xF8, 0x4F, 0x1A, 0x8D,
+ 0xC0, 0x26, 0x9F, 0x87, 0x61, 0xB6, 0xC6, 0x60,
+ 0x38, 0x22, 0x73, 0x1C, 0x99, 0x23, 0xEF, 0xD9,
+ 0xFD, 0xCB, 0x54, 0x74, 0xBB, 0x77, 0x14, 0xA3,
+ 0xA9, 0xE6, 0x7C, 0x7E, 0x03, 0x3A, 0x13, 0x6E,
+ 0x1D, 0x6F, 0x64, 0xB3, 0xFA, 0xFB, 0x52, 0xDE,
+ 0xDF, 0x08, 0xFB, 0x6F, 0xC5, 0xFA, 0x51, 0x6A,
+ 0x69, 0x29, 0x9B, 0x96, 0xE8, 0x16, 0xC8, 0xD1,
+ 0xE4, 0x19, 0xBD, 0x14, 0x74, 0x27, 0xE7, 0x10,
+ 0xF0, 0xC3, 0xE2, 0xA7, 0x60, 0x48, 0xBF, 0xDD,
+ 0xC4, 0x0D, 0xD0, 0xF2, 0xEF, 0xA6, 0xC9, 0xA2,
+ 0x73, 0xD1, 0xCF, 0x41, 0xE1, 0x3B, 0xE5, 0x49,
+ 0x91, 0x5D, 0x09, 0xFD, 0x1D, 0x95, 0x29, 0xDB,
+ 0x52, 0x48, 0xEB, 0xF5, 0x1D, 0xF8, 0x06, 0x67,
+ 0x75, 0xF2, 0x57, 0xA4, 0x20, 0x60, 0xEA, 0xB0,
+ 0x85, 0x93, 0x7C, 0xDD, 0x52, 0x01, 0xD4, 0x57,
+ 0xA8, 0x31, 0x2D, 0xF9, 0x0A, 0xD2, 0x2A, 0xD1,
+ 0x34, 0x18, 0x35, 0x16, 0xB6, 0x8B, 0x0F, 0x0B,
+ 0xCF, 0x50, 0x80, 0xFE, 0x76, 0xCC, 0x4F, 0x30,
+ 0x98, 0x19, 0x16, 0x3D, 0x01, 0xEA, 0x8D, 0x8A,
+ 0x3D, 0xDC, 0xFB, 0x1F, 0x77, 0x8D, 0x72, 0x76,
+ 0x02, 0x3C, 0x5D, 0xEE, 0x55, 0x13, 0x5B, 0x6E,
+ 0x5A, 0x2D, 0xD5, 0x77, 0xD7, 0x01, 0x84, 0x7D,
+ 0x21, 0x8C, 0xDD, 0x94, 0x7D, 0x31, 0x3D, 0xF0,
+ 0xE7, 0x28, 0xF5, 0x72, 0x36, 0x60, 0xE0, 0x59,
+ 0x5F, 0xFE, 0x38, 0xF8, 0x2F, 0xDB, 0x9E, 0x55,
+ 0x5A, 0xD6, 0xBA, 0x6C, 0x87, 0xF3, 0xC0, 0x76,
+ 0x5F, 0xA3, 0x0A, 0xC3, 0xA3, 0x8D, 0x0E, 0x52,
+ 0xA8, 0xDA, 0x26, 0x3A, 0xF9, 0x3E, 0x36, 0xB1,
+ 0x06, 0xF8, 0x20, 0x2D, 0x1C, 0x0B, 0x93, 0xBB,
+ 0xD3, 0x64, 0x77, 0xCE, 0x11, 0xFC, 0xA2, 0x0E,
+ 0x1B, 0x5B, 0x9E, 0x13, 0x9F, 0x20, 0x8B, 0xAA,
+ 0xCD, 0x72, 0xD7, 0xA6, 0xF3, 0x1E, 0x4F, 0x72,
+ 0xC6, 0x49, 0x0F, 0x7B, 0xF0, 0x4C, 0x61, 0x1F,
+ 0x43, 0x0D, 0x4F, 0x0D, 0x33, 0x13, 0xED, 0x63,
+ 0xE5, 0xDB, 0x71, 0xAB, 0xA4, 0x83, 0xEF, 0xDC,
+ 0x86, 0x9D, 0x4B, 0xBD, 0x1B, 0x8A, 0xFE, 0x39,
+ 0xA8, 0x8B, 0xBA, 0x4C, 0x85, 0x28, 0xFC, 0xB3,
+ 0x62, 0x85, 0xD2, 0xF0, 0x38, 0xD0, 0x4B, 0xA4,
+ 0xD1, 0x3B, 0xD4, 0xD0, 0x2C, 0x78, 0x6C, 0x6A,
+ 0xC2, 0x64, 0x2C, 0x31, 0x4A, 0xD8, 0x69, 0x24,
+ 0xED, 0x77, 0x7D, 0x68, 0x9A, 0xA1, 0x78, 0x81,
+ 0xD9, 0x7E, 0x6C, 0xFE, 0x0A, 0x0D, 0x76, 0xF7,
+ 0x4B, 0x58, 0xE7, 0xC9, 0xB5, 0x11, 0x07, 0x87,
+ 0x88, 0x6A, 0x9F, 0x3D, 0xE0, 0xEE, 0xCC, 0x60,
+ 0x6B, 0x6B, 0xE6, 0xB5, 0x54, 0x8B, 0x32, 0x1F,
+ 0x04, 0x1D, 0x0E, 0x9E, 0xFA, 0x6D, 0xB0, 0xE0,
+ 0x6D, 0xF9, 0x79, 0xB4, 0xAB, 0x5E, 0xDF, 0x23,
+ 0x7F, 0x95, 0xAD, 0x80, 0x17, 0x23, 0x90, 0x1F,
+ 0xF0, 0xC3, 0xD9, 0x2D, 0xAC, 0x3F, 0x63, 0xF5,
+ 0x77, 0xC5, 0x05, 0xAC, 0x06, 0xB6, 0xA1, 0xB4,
+ 0xA2, 0x40, 0xB3, 0x99, 0x34, 0x7D, 0x31, 0xD4,
+ 0xB1, 0xD4, 0xC1, 0xBB, 0x71, 0x1E, 0xDA, 0x3F,
+ 0xA9, 0x12, 0x68, 0xFA, 0x5B, 0x20, 0x24, 0x6D,
+ 0x4D, 0x72, 0x43, 0x18, 0xBF, 0x66, 0x71, 0x69,
+ 0x26, 0x7D, 0x77, 0x78, 0xF8, 0xE5, 0x20, 0xAE,
+ 0x56, 0x6C, 0x0F, 0x72, 0x94, 0x42, 0x85, 0x4F,
+ 0xE4, 0xFB, 0x32, 0x26, 0x1B, 0x1C, 0x6E, 0x0B,
+ 0xF0, 0xB8, 0x58, 0x00, 0xD2, 0x36, 0x64, 0xAD,
+ 0xA9, 0x00, 0xCE, 0x35, 0x3C, 0x88, 0x79, 0x94,
+ 0x0C, 0x0C, 0x9B, 0xF2, 0xDA, 0xBD, 0xCA, 0x93,
+ 0x37, 0x26, 0xD3, 0x08, 0x54, 0xD2, 0x0D, 0xBC,
+ 0x5D, 0x43, 0x5F, 0xCF, 0x28, 0xB5, 0xAA, 0x15,
+ 0x28, 0x46, 0x45, 0x6B, 0xE8, 0xDF, 0xE8, 0xCE,
+ 0x8F, 0xC0, 0x1A, 0x53, 0x63, 0x3B, 0x53, 0x75,
+ 0xDD, 0x43, 0x1F, 0x07, 0x0A, 0xD5, 0xA1, 0x2A,
+ 0x6E, 0x28, 0xE1, 0xD7, 0xD0, 0x09, 0xCF, 0x62,
+ 0xC1, 0x5F, 0x21, 0xDB, 0xC5, 0x40, 0x99, 0x48,
+ 0x87, 0x6E, 0x11, 0xF5, 0x5A, 0x4E, 0xBC, 0xF9,
+ 0xA8, 0x02, 0x7C, 0x47, 0x39, 0xA5, 0xD8, 0x52,
+ 0xB1, 0x80, 0xDC, 0xFE, 0x08, 0x4B, 0x5D, 0x09,
+ 0xDE, 0x06, 0xF3, 0x2A, 0xAD, 0x14, 0x76, 0x40,
+ 0x2F, 0x82, 0x28, 0x6A, 0xB6, 0x43, 0xEF, 0x71,
+ 0x63, 0xC2, 0x56, 0xEB, 0x3B, 0x4B, 0x52, 0x2F,
+ 0x93, 0xD3, 0x18, 0x3E, 0x18, 0xA8, 0xF7, 0x58,
+ 0xFC, 0x8B, 0x3D, 0x4D, 0x4B, 0x72, 0xBD, 0xF7,
+ 0x04, 0xC9, 0xB8, 0xD7, 0x6C, 0x8C, 0x67, 0xBB,
+ 0x4C, 0x9B, 0x57, 0xF7, 0x22, 0x4E, 0x41, 0xB6,
+ 0xFD, 0xD9, 0xF8, 0x41, 0x62, 0x0F, 0xFF, 0xAA,
+ 0xC6, 0x87, 0x95, 0xFF, 0xFD, 0x58, 0xD9, 0xB2,
+ 0xBA, 0x47, 0x61, 0x24, 0xEA, 0x92, 0x6E, 0x74,
+ 0xB3, 0xDA, 0xE5, 0x83, 0x99, 0x24, 0xB1, 0x71,
+ 0x2A, 0x33, 0xB2, 0xD5, 0x8F, 0xF0, 0x32, 0xCE,
+ 0x37, 0xCF, 0xC7, 0x1C, 0xE8, 0xDE, 0x46, 0x78,
+ 0x96, 0x97, 0xF6, 0x73, 0x90, 0xE5, 0x71, 0x05,
+ 0xEA, 0x0D, 0xC2, 0x1D, 0x9E, 0x43, 0x34, 0xBC,
+ 0x8F, 0x45, 0xE5, 0x08, 0xCA, 0x20, 0x0C, 0x84
+ },
+ .len = 2048
+ },
+ .auth_tag = {
+ .data = {
+ 0xD0, 0x62, 0x1F, 0x20, 0x1C, 0xE8, 0xDD, 0x36,
+ 0x00, 0x74, 0xF6, 0xD7, 0xFD, 0x2C, 0xA0, 0xAF
+ },
+ .len = 16
+ }
+};
+
/** GMAC Test Vectors */
static uint8_t gmac_plaintext[GMAC_LARGE_PLAINTEXT_LENGTH] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 4/5] crypto: add sgl support in openssl PMD
From: Tomasz Kulasek @ 2016-12-29 17:12 UTC (permalink / raw)
To: dev; +Cc: olivier.matz
In-Reply-To: <1483031543-21196-1-git-send-email-tomaszx.kulasek@intel.com>
Previous implementation uses EVP_EncryptUpdate() on whole source buffer
limiting its usage to the contiguous buffers.
This implementation calls EVP_EncryptUpdate() on each segment for cipher
operations in continous mode, before finalization allowing to provide
chained mbuf as a source.
However, libcrypto library expects continuous destination buffer for
output of cipher operations and implementation of openssl PMD is limited
the same way, requiring contiguous destination mbuf.
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
doc/guides/cryptodevs/openssl.rst | 2 +-
drivers/crypto/openssl/rte_openssl_pmd.c | 329 +++++++++++++++++++++++-------
2 files changed, 258 insertions(+), 73 deletions(-)
diff --git a/doc/guides/cryptodevs/openssl.rst b/doc/guides/cryptodevs/openssl.rst
index d2b5906..05e6d67 100644
--- a/doc/guides/cryptodevs/openssl.rst
+++ b/doc/guides/cryptodevs/openssl.rst
@@ -112,6 +112,6 @@ Limitations
-----------
* Maximum number of sessions is 2048.
-* Chained mbufs are not supported.
+* Chained mbufs are supported only for source mbuf (destination must be contiguous).
* Hash only is not supported for GCM and GMAC.
* Cipher only is not supported for GCM and GMAC.
diff --git a/drivers/crypto/openssl/rte_openssl_pmd.c b/drivers/crypto/openssl/rte_openssl_pmd.c
index 5f8fa33..22639b4 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd.c
@@ -484,22 +484,110 @@
* Process Operations
*------------------------------------------------------------------------------
*/
+static inline int
+process_openssl_encryption_update(struct rte_mbuf *mbuf_src, int offset,
+ uint8_t **dst, int srclen, EVP_CIPHER_CTX *ctx)
+{
+ struct rte_mbuf *m;
+ int dstlen;
+ int l, n = srclen;
+ uint8_t *src;
+
+ for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+ m = m->next)
+ offset -= rte_pktmbuf_data_len(m);
+
+ if (m == 0)
+ return -1;
+
+ src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+ l = rte_pktmbuf_data_len(m) - offset;
+ if (srclen <= l) {
+ if (EVP_EncryptUpdate(ctx, *dst, &dstlen, src, srclen) <= 0)
+ return -1;
+ *dst += l;
+ return 0;
+ }
+
+ if (EVP_EncryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+ return -1;
+
+ *dst += dstlen;
+ n -= l;
+
+ for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+ src = rte_pktmbuf_mtod(m, uint8_t *);
+ l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+ if (EVP_EncryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+ return -1;
+ *dst += dstlen;
+ n -= l;
+ }
+
+ return 0;
+}
+
+static inline int
+process_openssl_decryption_update(struct rte_mbuf *mbuf_src, int offset,
+ uint8_t **dst, int srclen, EVP_CIPHER_CTX *ctx)
+{
+ struct rte_mbuf *m;
+ int dstlen;
+ int l, n = srclen;
+ uint8_t *src;
+
+ for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+ m = m->next)
+ offset -= rte_pktmbuf_data_len(m);
+
+ if (m == 0)
+ return -1;
+
+ src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+ l = rte_pktmbuf_data_len(m) - offset;
+ if (srclen <= l) {
+ if (EVP_DecryptUpdate(ctx, *dst, &dstlen, src, srclen) <= 0)
+ return -1;
+ *dst += l;
+ return 0;
+ }
+
+ if (EVP_DecryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+ return -1;
+
+ *dst += dstlen;
+ n -= l;
+
+ for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+ src = rte_pktmbuf_mtod(m, uint8_t *);
+ l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+ if (EVP_DecryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+ return -1;
+ *dst += dstlen;
+ n -= l;
+ }
+
+ return 0;
+}
/** Process standard openssl cipher encryption */
static int
-process_openssl_cipher_encrypt(uint8_t *src, uint8_t *dst,
- uint8_t *iv, uint8_t *key, int srclen,
+process_openssl_cipher_encrypt(struct rte_mbuf *mbuf_src, uint8_t *dst,
+ int offset, uint8_t *iv, uint8_t *key, int srclen,
EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
{
- int dstlen, totlen;
+ int totlen;
if (EVP_EncryptInit_ex(ctx, algo, NULL, key, iv) <= 0)
goto process_cipher_encrypt_err;
- if (EVP_EncryptUpdate(ctx, dst, &dstlen, src, srclen) <= 0)
+ if (process_openssl_encryption_update(mbuf_src, offset, &dst,
+ srclen, ctx))
goto process_cipher_encrypt_err;
- if (EVP_EncryptFinal_ex(ctx, dst + dstlen, &totlen) <= 0)
+ if (EVP_EncryptFinal_ex(ctx, dst, &totlen) <= 0)
goto process_cipher_encrypt_err;
return 0;
@@ -511,11 +599,11 @@
/** Process standard openssl cipher decryption */
static int
-process_openssl_cipher_decrypt(uint8_t *src, uint8_t *dst,
- uint8_t *iv, uint8_t *key, int srclen,
+process_openssl_cipher_decrypt(struct rte_mbuf *mbuf_src, uint8_t *dst,
+ int offset, uint8_t *iv, uint8_t *key, int srclen,
EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
{
- int dstlen, totlen;
+ int totlen;
if (EVP_DecryptInit_ex(ctx, algo, NULL, key, iv) <= 0)
goto process_cipher_decrypt_err;
@@ -523,12 +611,12 @@
if (EVP_CIPHER_CTX_set_padding(ctx, 0) <= 0)
goto process_cipher_decrypt_err;
- if (EVP_DecryptUpdate(ctx, dst, &dstlen, src, srclen) <= 0)
+ if (process_openssl_decryption_update(mbuf_src, offset, &dst,
+ srclen, ctx))
goto process_cipher_decrypt_err;
- if (EVP_DecryptFinal_ex(ctx, dst + dstlen, &totlen) <= 0)
+ if (EVP_DecryptFinal_ex(ctx, dst, &totlen) <= 0)
goto process_cipher_decrypt_err;
-
return 0;
process_cipher_decrypt_err:
@@ -538,11 +626,25 @@
/** Process cipher des 3 ctr encryption, decryption algorithm */
static int
-process_openssl_cipher_des3ctr(uint8_t *src, uint8_t *dst,
- uint8_t *iv, uint8_t *key, int srclen, EVP_CIPHER_CTX *ctx)
+process_openssl_cipher_des3ctr(struct rte_mbuf *mbuf_src, uint8_t *dst,
+ int offset, uint8_t *iv, uint8_t *key, int srclen,
+ EVP_CIPHER_CTX *ctx)
{
uint8_t ebuf[8], ctr[8];
int unused, n;
+ struct rte_mbuf *m;
+ uint8_t *src;
+ int l;
+
+ for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+ m = m->next)
+ offset -= rte_pktmbuf_data_len(m);
+
+ if (m == 0)
+ goto process_cipher_des3ctr_err;
+
+ src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+ l = rte_pktmbuf_data_len(m) - offset;
/* We use 3DES encryption also for decryption.
* IV is not important for 3DES ecb
@@ -551,9 +653,8 @@
goto process_cipher_des3ctr_err;
memcpy(ctr, iv, 8);
- n = 0;
- while (n < srclen) {
+ for (n = 0; n < srclen; n++) {
if (n % 8 == 0) {
if (EVP_EncryptUpdate(ctx,
(unsigned char *)&ebuf, &unused,
@@ -561,8 +662,16 @@
goto process_cipher_des3ctr_err;
ctr_inc(ctr);
}
- dst[n] = src[n] ^ ebuf[n % 8];
- n++;
+ dst[n] = *(src++) ^ ebuf[n % 8];
+
+ l--;
+ if (!l) {
+ m = m->next;
+ if (m) {
+ src = rte_pktmbuf_mtod(m, uint8_t *);
+ l = rte_pktmbuf_data_len(m);
+ }
+ }
}
return 0;
@@ -574,9 +683,9 @@
/** Process auth/encription aes-gcm algorithm */
static int
-process_openssl_auth_encryption_gcm(uint8_t *src, int srclen,
- uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
- uint8_t *key, uint8_t *dst, uint8_t *tag,
+process_openssl_auth_encryption_gcm(struct rte_mbuf *mbuf_src, int offset,
+ int srclen, uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
+ uint8_t *key, uint8_t *dst, uint8_t *tag,
EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
{
int len = 0, unused = 0;
@@ -591,20 +700,20 @@
if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv) <= 0)
goto process_auth_encryption_gcm_err;
- if (aadlen > 0) {
+ if (aadlen > 0)
if (EVP_EncryptUpdate(ctx, NULL, &len, aad, aadlen) <= 0)
goto process_auth_encryption_gcm_err;
- /* Workaround open ssl bug in version less then 1.0.1f */
- if (EVP_EncryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
- goto process_auth_encryption_gcm_err;
- }
-
if (srclen > 0)
- if (EVP_EncryptUpdate(ctx, dst, &len, src, srclen) <= 0)
+ if (process_openssl_encryption_update(mbuf_src, offset, &dst,
+ srclen, ctx))
goto process_auth_encryption_gcm_err;
- if (EVP_EncryptFinal_ex(ctx, dst + len, &len) <= 0)
+ /* Workaround open ssl bug in version less then 1.0.1f */
+ if (EVP_EncryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
+ goto process_auth_encryption_gcm_err;
+
+ if (EVP_EncryptFinal_ex(ctx, dst, &len) <= 0)
goto process_auth_encryption_gcm_err;
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag) <= 0)
@@ -618,10 +727,10 @@
}
static int
-process_openssl_auth_decryption_gcm(uint8_t *src, int srclen,
- uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
- uint8_t *key, uint8_t *dst, uint8_t *tag,
- EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
+process_openssl_auth_decryption_gcm(struct rte_mbuf *mbuf_src, int offset,
+ int srclen, uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
+ uint8_t *key, uint8_t *dst, uint8_t *tag, EVP_CIPHER_CTX *ctx,
+ const EVP_CIPHER *algo)
{
int len = 0, unused = 0;
uint8_t empty[] = {};
@@ -638,20 +747,20 @@
if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv) <= 0)
goto process_auth_decryption_gcm_err;
- if (aadlen > 0) {
+ if (aadlen > 0)
if (EVP_DecryptUpdate(ctx, NULL, &len, aad, aadlen) <= 0)
goto process_auth_decryption_gcm_err;
- /* Workaround open ssl bug in version less then 1.0.1f */
- if (EVP_DecryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
- goto process_auth_decryption_gcm_err;
- }
-
if (srclen > 0)
- if (EVP_DecryptUpdate(ctx, dst, &len, src, srclen) <= 0)
+ if (process_openssl_decryption_update(mbuf_src, offset, &dst,
+ srclen, ctx))
goto process_auth_decryption_gcm_err;
- if (EVP_DecryptFinal_ex(ctx, dst + len, &len) <= 0)
+ /* Workaround open ssl bug in version less then 1.0.1f */
+ if (EVP_DecryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
+ goto process_auth_decryption_gcm_err;
+
+ if (EVP_DecryptFinal_ex(ctx, dst, &len) <= 0)
goto process_auth_decryption_gcm_final_err;
return 0;
@@ -666,21 +775,50 @@
/** Process standard openssl auth algorithms */
static int
-process_openssl_auth(uint8_t *src, uint8_t *dst,
+process_openssl_auth(struct rte_mbuf *mbuf_src, uint8_t *dst, int offset,
__rte_unused uint8_t *iv, __rte_unused EVP_PKEY * pkey,
int srclen, EVP_MD_CTX *ctx, const EVP_MD *algo)
{
size_t dstlen;
+ struct rte_mbuf *m;
+ int l, n = srclen;
+ uint8_t *src;
+
+ for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+ m = m->next)
+ offset -= rte_pktmbuf_data_len(m);
+
+ if (m == 0)
+ goto process_auth_err;
if (EVP_DigestInit_ex(ctx, algo, NULL) <= 0)
goto process_auth_err;
- if (EVP_DigestUpdate(ctx, (char *)src, srclen) <= 0)
+ src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+ l = rte_pktmbuf_data_len(m) - offset;
+ if (srclen <= l) {
+ if (EVP_DigestUpdate(ctx, (char *)src, srclen) <= 0)
+ goto process_auth_err;
+ goto process_auth_final;
+ }
+
+ if (EVP_DigestUpdate(ctx, (char *)src, l) <= 0)
goto process_auth_err;
+ n -= l;
+
+ for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+ src = rte_pktmbuf_mtod(m, uint8_t *);
+ l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+ if (EVP_DigestUpdate(ctx, (char *)src, l) <= 0)
+ goto process_auth_err;
+ n -= l;
+ }
+
+process_auth_final:
if (EVP_DigestFinal_ex(ctx, dst, (unsigned int *)&dstlen) <= 0)
goto process_auth_err;
-
return 0;
process_auth_err:
@@ -690,18 +828,48 @@
/** Process standard openssl auth algorithms with hmac */
static int
-process_openssl_auth_hmac(uint8_t *src, uint8_t *dst,
+process_openssl_auth_hmac(struct rte_mbuf *mbuf_src, uint8_t *dst, int offset,
__rte_unused uint8_t *iv, EVP_PKEY *pkey,
- int srclen, EVP_MD_CTX *ctx, const EVP_MD *algo)
+ int srclen, EVP_MD_CTX *ctx, const EVP_MD *algo)
{
size_t dstlen;
+ struct rte_mbuf *m;
+ int l, n = srclen;
+ uint8_t *src;
+
+ for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+ m = m->next)
+ offset -= rte_pktmbuf_data_len(m);
+
+ if (m == 0)
+ goto process_auth_err;
if (EVP_DigestSignInit(ctx, NULL, algo, NULL, pkey) <= 0)
goto process_auth_err;
- if (EVP_DigestSignUpdate(ctx, (char *)src, srclen) <= 0)
+ src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+ l = rte_pktmbuf_data_len(m) - offset;
+ if (srclen <= l) {
+ if (EVP_DigestSignUpdate(ctx, (char *)src, srclen) <= 0)
+ goto process_auth_err;
+ goto process_auth_final;
+ }
+
+ if (EVP_DigestSignUpdate(ctx, (char *)src, l) <= 0)
goto process_auth_err;
+ n -= l;
+
+ for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+ src = rte_pktmbuf_mtod(m, uint8_t *);
+ l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+ if (EVP_DigestSignUpdate(ctx, (char *)src, l) <= 0)
+ goto process_auth_err;
+ n -= l;
+ }
+
+process_auth_final:
if (EVP_DigestSignFinal(ctx, dst, &dstlen) <= 0)
goto process_auth_err;
@@ -721,9 +889,18 @@
struct rte_mbuf *mbuf_src, struct rte_mbuf *mbuf_dst)
{
/* cipher */
- uint8_t *src = NULL, *dst = NULL, *iv, *tag, *aad;
+ uint8_t *dst = NULL, *iv, *tag, *aad;
int srclen, ivlen, aadlen, status = -1;
+ /*
+ * Segmented destination buffer is not supported for
+ * encryption/decryption
+ */
+ if (!rte_pktmbuf_is_contiguous(mbuf_dst)) {
+ op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+ return;
+ }
+
iv = op->sym->cipher.iv.data;
ivlen = op->sym->cipher.iv.length;
aad = op->sym->auth.aad.data;
@@ -739,22 +916,22 @@
srclen = 0;
else {
srclen = op->sym->cipher.data.length;
- src = rte_pktmbuf_mtod_offset(mbuf_src, uint8_t *,
- op->sym->cipher.data.offset);
dst = rte_pktmbuf_mtod_offset(mbuf_dst, uint8_t *,
op->sym->cipher.data.offset);
}
if (sess->cipher.direction == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
status = process_openssl_auth_encryption_gcm(
- src, srclen, aad, aadlen, iv, ivlen,
- sess->cipher.key.data, dst, tag,
- sess->cipher.ctx, sess->cipher.evp_algo);
+ mbuf_src, op->sym->cipher.data.offset, srclen,
+ aad, aadlen, iv, ivlen, sess->cipher.key.data,
+ dst, tag, sess->cipher.ctx,
+ sess->cipher.evp_algo);
else
status = process_openssl_auth_decryption_gcm(
- src, srclen, aad, aadlen, iv, ivlen,
- sess->cipher.key.data, dst, tag,
- sess->cipher.ctx, sess->cipher.evp_algo);
+ mbuf_src, op->sym->cipher.data.offset, srclen,
+ aad, aadlen, iv, ivlen, sess->cipher.key.data,
+ dst, tag, sess->cipher.ctx,
+ sess->cipher.evp_algo);
if (status != 0) {
if (status == (-EFAULT) &&
@@ -772,12 +949,19 @@
(struct rte_crypto_op *op, struct openssl_session *sess,
struct rte_mbuf *mbuf_src, struct rte_mbuf *mbuf_dst)
{
- uint8_t *src, *dst, *iv;
+ uint8_t *dst, *iv;
int srclen, status;
+ /*
+ * Segmented destination buffer is not supported for
+ * encryption/decryption
+ */
+ if (!rte_pktmbuf_is_contiguous(mbuf_dst)) {
+ op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+ return;
+ }
+
srclen = op->sym->cipher.data.length;
- src = rte_pktmbuf_mtod_offset(mbuf_src, uint8_t *,
- op->sym->cipher.data.offset);
dst = rte_pktmbuf_mtod_offset(mbuf_dst, uint8_t *,
op->sym->cipher.data.offset);
@@ -785,17 +969,20 @@
if (sess->cipher.mode == OPENSSL_CIPHER_LIB)
if (sess->cipher.direction == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
- status = process_openssl_cipher_encrypt(src, dst, iv,
+ status = process_openssl_cipher_encrypt(mbuf_src, dst,
+ op->sym->cipher.data.offset, iv,
sess->cipher.key.data, srclen,
sess->cipher.ctx,
sess->cipher.evp_algo);
else
- status = process_openssl_cipher_decrypt(src, dst, iv,
+ status = process_openssl_cipher_decrypt(mbuf_src, dst,
+ op->sym->cipher.data.offset, iv,
sess->cipher.key.data, srclen,
sess->cipher.ctx,
sess->cipher.evp_algo);
else
- status = process_openssl_cipher_des3ctr(src, dst, iv,
+ status = process_openssl_cipher_des3ctr(mbuf_src, dst,
+ op->sym->cipher.data.offset, iv,
sess->cipher.key.data, srclen,
sess->cipher.ctx);
@@ -809,12 +996,10 @@
(struct rte_crypto_op *op, struct openssl_session *sess,
struct rte_mbuf *mbuf_src, struct rte_mbuf *mbuf_dst)
{
- uint8_t *src, *dst;
+ uint8_t *dst;
int srclen, status;
srclen = op->sym->auth.data.length;
- src = rte_pktmbuf_mtod_offset(mbuf_src, uint8_t *,
- op->sym->auth.data.offset);
if (sess->auth.operation == RTE_CRYPTO_AUTH_OP_VERIFY)
dst = (uint8_t *)rte_pktmbuf_append(mbuf_src,
@@ -829,13 +1014,14 @@
switch (sess->auth.mode) {
case OPENSSL_AUTH_AS_AUTH:
- status = process_openssl_auth(src, dst,
- NULL, NULL, srclen,
+ status = process_openssl_auth(mbuf_src, dst,
+ op->sym->auth.data.offset, NULL, NULL, srclen,
sess->auth.auth.ctx, sess->auth.auth.evp_algo);
break;
case OPENSSL_AUTH_AS_HMAC:
- status = process_openssl_auth_hmac(src, dst,
- NULL, sess->auth.hmac.pkey, srclen,
+ status = process_openssl_auth_hmac(mbuf_src, dst,
+ op->sym->auth.data.offset, NULL,
+ sess->auth.hmac.pkey, srclen,
sess->auth.hmac.ctx, sess->auth.hmac.evp_algo);
break;
default:
@@ -849,8 +1035,7 @@
op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
}
/* Trim area used for digest from mbuf. */
- rte_pktmbuf_trim(mbuf_src,
- op->sym->auth.digest.length);
+ rte_pktmbuf_trim(mbuf_src, op->sym->auth.digest.length);
}
if (status != 0)
@@ -901,7 +1086,6 @@
op->sym->session = NULL;
}
-
if (op->status == RTE_CRYPTO_OP_STATUS_NOT_PROCESSED)
op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
@@ -995,7 +1179,8 @@
dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
- RTE_CRYPTODEV_FF_CPU_AESNI;
+ RTE_CRYPTODEV_FF_CPU_AESNI |
+ RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER;
/* Set vector instructions mode supported */
internals = dev->data->dev_private;
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 3/5] crypto: add sgl support in sw PMDs
From: Tomasz Kulasek @ 2016-12-29 17:12 UTC (permalink / raw)
To: dev; +Cc: olivier.matz
In-Reply-To: <1483031543-21196-1-git-send-email-tomaszx.kulasek@intel.com>
This patch introduces RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER feature flag
informing that selected crypto device supports segmented mbufs natively
and doesn't need to be coalesced before crypto operation.
While using segmented buffers in crypto devices may have unpredictable
results, for PMDs which doesn't support it natively, additional check is
made for debug compilation.
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
drivers/crypto/aesni_gcm/aesni_gcm_pmd.c | 14 ++++++++++++++
drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c | 19 ++++++++++++++++---
drivers/crypto/kasumi/rte_kasumi_pmd.c | 13 +++++++++++++
drivers/crypto/null/null_crypto_pmd.c | 3 ++-
drivers/crypto/snow3g/rte_snow3g_pmd.c | 15 +++++++++++++++
drivers/crypto/zuc/rte_zuc_pmd.c | 13 +++++++++++++
lib/librte_cryptodev/rte_cryptodev.c | 4 ++--
lib/librte_cryptodev/rte_cryptodev.h | 3 ++-
8 files changed, 77 insertions(+), 7 deletions(-)
diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
index dba5e15..1a6120c 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
@@ -375,6 +375,20 @@
break;
}
+#ifdef RTE_LIBRTE_PMD_AESNI_GCM_DEBUG
+ if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+ (ops[i]->sym->m_dst != NULL &&
+ !rte_pktmbuf_is_contiguous(
+ ops[i]->sym->m_dst))) {
+ ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+ GCM_LOG_ERR("PMD supports only contiguous mbufs, "
+ "op (%p) provides noncontiguous mbuf as "
+ "source/destination buffer.\n", ops[i]);
+ qp->qp_stats.enqueue_err_count++;
+ break;
+ }
+#endif
+
retval = process_gcm_crypto_op(qp, ops[i]->sym, sess);
if (retval < 0) {
ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index f07cd07..b5e115e 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -529,15 +529,28 @@
int i, processed_jobs = 0;
for (i = 0; i < nb_ops; i++) {
-#ifdef RTE_LIBRTE_AESNI_MB_DEBUG
- if (unlikely(op->type != RTE_CRYPTO_OP_TYPE_SYMMETRIC)) {
+#ifdef RTE_LIBRTE_PMD_AESNI_MB_DEBUG
+ if (unlikely(ops[i]->type != RTE_CRYPTO_OP_TYPE_SYMMETRIC)) {
MB_LOG_ERR("PMD only supports symmetric crypto "
"operation requests, op (%p) is not a "
- "symmetric operation.", op);
+ "symmetric operation.", ops[i]);
+ qp->stats.enqueue_err_count++;
+ goto flush_jobs;
+ }
+
+ if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+ (ops[i]->sym->m_dst != NULL &&
+ !rte_pktmbuf_is_contiguous(
+ ops[i]->sym->m_dst))) {
+ MB_LOG_ERR("PMD supports only contiguous mbufs, "
+ "op (%p) provides noncontiguous mbuf as "
+ "source/destination buffer.\n", ops[i]);
+ ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
qp->stats.enqueue_err_count++;
goto flush_jobs;
}
#endif
+
sess = get_session(qp, ops[i]);
if (unlikely(sess == NULL)) {
qp->stats.enqueue_err_count++;
diff --git a/drivers/crypto/kasumi/rte_kasumi_pmd.c b/drivers/crypto/kasumi/rte_kasumi_pmd.c
index b119da2..4bdd7bb 100644
--- a/drivers/crypto/kasumi/rte_kasumi_pmd.c
+++ b/drivers/crypto/kasumi/rte_kasumi_pmd.c
@@ -455,6 +455,19 @@
for (i = 0; i < nb_ops; i++) {
curr_c_op = ops[i];
+#ifdef RTE_LIBRTE_PMD_KASUMI_DEBUG
+ if (!rte_pktmbuf_is_contiguous(curr_c_op->sym->m_src) ||
+ (curr_c_op->sym->m_dst != NULL &&
+ !rte_pktmbuf_is_contiguous(
+ curr_c_op->sym->m_dst))) {
+ KASUMI_LOG_ERR("PMD supports only contiguous mbufs, "
+ "op (%p) provides noncontiguous mbuf as "
+ "source/destination buffer.\n", curr_c_op);
+ curr_c_op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+ break;
+ }
+#endif
+
/* Set status as enqueued (not processed yet) by default. */
curr_c_op->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
diff --git a/drivers/crypto/null/null_crypto_pmd.c b/drivers/crypto/null/null_crypto_pmd.c
index c69606b..c37d3d6 100644
--- a/drivers/crypto/null/null_crypto_pmd.c
+++ b/drivers/crypto/null/null_crypto_pmd.c
@@ -216,7 +216,8 @@
dev->enqueue_burst = null_crypto_pmd_enqueue_burst;
dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
- RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
+ RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
+ RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER;
internals = dev->data->dev_private;
diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd.c b/drivers/crypto/snow3g/rte_snow3g_pmd.c
index 3b4292a..9a6f16d 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd.c
@@ -330,6 +330,21 @@
unsigned i;
unsigned enqueued_ops, processed_ops;
+#ifdef RTE_LIBRTE_PMD_SNOW3G_DEBUG
+ for (i = 0; i < num_ops; i++) {
+ if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+ (ops[i]->sym->m_dst != NULL &&
+ !rte_pktmbuf_is_contiguous(
+ ops[i]->sym->m_dst))) {
+ SNOW3G_LOG_ERR("PMD supports only contiguous mbufs, "
+ "op (%p) provides noncontiguous mbuf as "
+ "source/destination buffer.\n", ops[i]);
+ ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+ return 0;
+ }
+ }
+#endif
+
switch (session->op) {
case SNOW3G_OP_ONLY_CIPHER:
processed_ops = process_snow3g_cipher_op(ops,
diff --git a/drivers/crypto/zuc/rte_zuc_pmd.c b/drivers/crypto/zuc/rte_zuc_pmd.c
index 3849119..bf53f76 100644
--- a/drivers/crypto/zuc/rte_zuc_pmd.c
+++ b/drivers/crypto/zuc/rte_zuc_pmd.c
@@ -211,6 +211,19 @@
break;
}
+#ifdef RTE_LIBRTE_PMD_ZUC_DEBUG
+ if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+ (ops[i]->sym->m_dst != NULL &&
+ !rte_pktmbuf_is_contiguous(
+ ops[i]->sym->m_dst))) {
+ ZUC_LOG_ERR("PMD supports only contiguous mbufs, "
+ "op (%p) provides noncontiguous mbuf as "
+ "source/destination buffer.\n", ops[i]);
+ ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+ break;
+ }
+#endif
+
src[i] = rte_pktmbuf_mtod(ops[i]->sym->m_src, uint8_t *) +
(ops[i]->sym->cipher.data.offset >> 3);
dst[i] = ops[i]->sym->m_dst ?
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index 127e8d0..ebbb822 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -211,13 +211,13 @@ struct rte_cryptodev_callback {
return "CPU_AESNI";
case RTE_CRYPTODEV_FF_HW_ACCELERATED:
return "HW_ACCELERATED";
-
+ case RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER:
+ return "MBUF_SCATTER_GATHER";
default:
return NULL;
}
}
-
int
rte_cryptodev_create_vdev(const char *name, const char *args)
{
diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index 8f63e8f..70ff7fc 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -225,7 +225,8 @@ struct rte_cryptodev_capabilities {
/**< Utilises CPU AES-NI instructions */
#define RTE_CRYPTODEV_FF_HW_ACCELERATED (1ULL << 7)
/**< Operations are off-loaded to an external hardware accelerator */
-
+#define RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER (1ULL << 8)
+/**< Scatter-gather mbufs are supported */
/**
* Get the name of a crypto device feature flag
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 2/5] test: add rte_pktmbuf_linearize unit tests
From: Tomasz Kulasek @ 2016-12-29 17:12 UTC (permalink / raw)
To: dev; +Cc: olivier.matz
In-Reply-To: <1483031543-21196-1-git-send-email-tomaszx.kulasek@intel.com>
This patch tests rte_pktmbuf_coalesce functionality:
1) Creates banch of segmented mbufs with different size and number of
segments.
2) Generates pkt_len bytes of random data.
3) Fills noncontigouos mbuf with randomly generated data.
4) Uses rte_pktmbuf_linearize to coalesce segmented buffer into one
contiguous.
5) Verifies data in linearized buffer.
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
app/test/test_mbuf.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 123 insertions(+)
diff --git a/app/test/test_mbuf.c b/app/test/test_mbuf.c
index c0823ea..39577e7 100644
--- a/app/test/test_mbuf.c
+++ b/app/test/test_mbuf.c
@@ -930,6 +930,124 @@
return 0;
}
+static int
+test_mbuf_linearize(int pkt_len, int nb_segs) {
+
+ struct rte_mbuf *m = NULL, *mbuf_src = NULL;
+ uint8_t data[pkt_len], *src, *dst;
+ int data_len = 0;
+ int i, size;
+ int t_len;
+
+ if (pkt_len < 1) {
+ printf("Packet size must be 1 or more (is %d)\n", pkt_len);
+ return -1;
+ }
+
+ if (nb_segs < 1) {
+ printf("Number of segments must be 1 or more (is %d)\n",
+ nb_segs);
+ return -1;
+ }
+
+ /* Setup buffer */
+ for (i = 0; i < pkt_len; i++)
+ data[i] = (uint8_t) rte_rand();
+
+ t_len = pkt_len >= nb_segs ? pkt_len / nb_segs : 1;
+ src = data;
+ size = pkt_len;
+
+ /* Create chained mbuf_src and fill it generated data */
+ for (i = 0; size > 0; i++) {
+
+ m = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (i == 0)
+ mbuf_src = m;
+
+ if (!m) {
+ printf("Cannot create segment for source mbuf");
+ goto fail;
+ }
+
+ /* Make sure if tailroom is zeroed */
+ memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
+ rte_pktmbuf_tailroom(m));
+
+ data_len = size > t_len ? t_len : size;
+ dst = (uint8_t *)rte_pktmbuf_append(m, data_len);
+ if (!dst) {
+ printf("Cannot append %d bytes to the mbuf\n",
+ data_len);
+ goto fail;
+ }
+
+ rte_memcpy(dst, src, data_len);
+ src += data_len;
+
+ if (mbuf_src != m)
+ rte_pktmbuf_chain(mbuf_src, m);
+
+ size -= data_len;
+
+ }
+
+ /* Create destination buffer to store coalesced data */
+ if (rte_pktmbuf_linearize(mbuf_src)) {
+ printf("Mbuf linearization failed\n");
+ goto fail;
+ }
+
+ if (!rte_pktmbuf_is_contiguous(mbuf_src)) {
+ printf("Source buffer should be contiguous after "
+ "linearization\n");
+ goto fail;
+ }
+
+ src = rte_pktmbuf_mtod(mbuf_src, uint8_t *);
+
+ if (memcmp(src, data, rte_pktmbuf_pkt_len(mbuf_src))) {
+ printf("Incorrect data in coalesced mbuf\n");
+ goto fail;
+ }
+
+ if (mbuf_src)
+ rte_pktmbuf_free(mbuf_src);
+ return 0;
+
+fail:
+ if (mbuf_src)
+ rte_pktmbuf_free(mbuf_src);
+ return -1;
+}
+
+static int
+test_mbuf_linearize_check(void)
+{
+ struct test_mbuf_array {
+ int size;
+ int nb_segs;
+ } mbuf_array[5] = {
+ { 128, 1 },
+ { 64, 64 },
+ { 512, 10 },
+ { 250, 11 },
+ { 123, 8 },
+ };
+ unsigned int i;
+
+ printf("Test mbuf linearize API\n");
+
+ for (i = 0; i < RTE_DIM(mbuf_array); i++)
+ if (test_mbuf_linearize(mbuf_array[i].size,
+ mbuf_array[i].nb_segs)) {
+ printf("Test failed for %d, %d\n", mbuf_array[i].size,
+ mbuf_array[i].nb_segs);
+ return -1;
+ }
+
+ return 0;
+}
static int
test_mbuf(void)
@@ -1023,6 +1141,11 @@
printf("test_failing_mbuf_sanity_check() failed\n");
return -1;
}
+
+ if (test_mbuf_linearize_check() < 0) {
+ printf("test_mbuf_linearize_check() failed\n");
+ return -1;
+ }
return 0;
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 1/5] rte_mbuf: add rte_pktmbuf_linearize
From: Tomasz Kulasek @ 2016-12-29 17:12 UTC (permalink / raw)
To: dev; +Cc: olivier.matz
In-Reply-To: <1483031543-21196-1-git-send-email-tomaszx.kulasek@intel.com>
This patch adds function rte_pktmbuf_linearize to let crypto PMD coalesce
chained mbuf before crypto operation and extend their capabilities to
support segmented mbufs when device cannot handle them natively.
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
lib/librte_mbuf/rte_mbuf.h | 56 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 56 insertions(+)
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index ead7c6e..b11a31d 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -1647,6 +1647,62 @@ static inline int rte_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *tail
}
/**
+ * Linearize data in mbuf.
+ *
+ * This function coalesce mbuf merging data in the first segment, unchaining
+ * rest, and then frees them.
+ *
+ * All operations are done in-place, so the structure of incoming mbuf
+ * is changed.
+ *
+ * @param mbuf
+ * mbuf to linearize
+ * @return
+ * - 0, on success
+ * - -1, on error
+ */
+static inline int
+rte_pktmbuf_linearize(struct rte_mbuf *mbuf)
+{
+ int l, n;
+ struct rte_mbuf *m;
+ struct rte_mbuf *m_next;
+ char *buffer;
+
+ if (rte_pktmbuf_is_contiguous(mbuf))
+ return 0;
+
+ /* Extend first segment to the total packet length
+ */
+ n = rte_pktmbuf_pkt_len(mbuf) - rte_pktmbuf_data_len(mbuf);
+
+ if (unlikely(n > rte_pktmbuf_tailroom(mbuf)))
+ return -1;
+
+ buffer = rte_pktmbuf_mtod_offset(mbuf, char *, mbuf->data_len);
+ mbuf->data_len = (uint16_t)(mbuf->pkt_len);
+
+ /* Append data from next segments to the first one
+ */
+ m = mbuf->next;
+ while (m != NULL) {
+ m_next = m->next;
+
+ l = rte_pktmbuf_data_len(m);
+ rte_memcpy(buffer, rte_pktmbuf_mtod(m, char *), l);
+ buffer += l;
+
+ rte_pktmbuf_free_seg(m);
+ m = m_next;
+ }
+
+ mbuf->next = NULL;
+ mbuf->nb_segs = 1;
+
+ return 0;
+}
+
+/**
* Dump an mbuf structure to a file.
*
* Dump all fields for the given packet mbuf and all its associated
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 0/5] Chained Mbufs support in SW PMDs
From: Tomasz Kulasek @ 2016-12-29 17:12 UTC (permalink / raw)
To: dev; +Cc: olivier.matz
In-Reply-To: <1480698466-17620-1-git-send-email-tomaszx.kulasek@intel.com>
This patch set adds support of scattered-gather list for SW PMDs.
As of now, application needs to reserve continuous block of memory for
mbufs which is not always the case. Hence needed to support chaining of
mbufs which are smaller in size but can be used if chained.
Above work involves:
a) Create mbuf functions to coalesce mbuf chains into a single mbuf.
b) For each software poll mode driver code to detect chained mbufs
support and coalesce these before preforming crypto.
c) Add relevant unit tests to test the functionality.
Known limitations for openssl PMD:
While libcrypto library expects continuous destination buffer for
output of cipher operations, implementation of openssl PMD is limited
the same way, and requires contigous destination mbuf.
changes in v2:
- add support for sgl in openssl PMD
- rte_pktmbuf_coalesce replaced with rte_pktmbuf_linearize
- extended test vector data for aes gcm from 60 to 2048 bytes
Tomasz Kulasek (5):
rte_mbuf: add rte_pktmbuf_linearize
test: add rte_pktmbuf_linearize unit tests
crypto: add sgl support in sw PMDs
crypto: add sgl support in openssl PMD
test: add sgl unit tests for crypto devices
app/test/test_cryptodev.c | 589 +++++++++++++++++++++++++++-
app/test/test_cryptodev.h | 139 +++++++
app/test/test_cryptodev_aes_test_vectors.h | 54 ++-
app/test/test_cryptodev_blockcipher.c | 181 ++++++---
app/test/test_cryptodev_blockcipher.h | 3 +-
app/test/test_cryptodev_des_test_vectors.h | 29 ++
app/test/test_cryptodev_gcm_test_vectors.h | 557 +++++++++++++++++++++++++-
app/test/test_mbuf.c | 123 ++++++
doc/guides/cryptodevs/openssl.rst | 2 +-
drivers/crypto/aesni_gcm/aesni_gcm_pmd.c | 14 +
drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c | 19 +-
drivers/crypto/kasumi/rte_kasumi_pmd.c | 13 +
drivers/crypto/null/null_crypto_pmd.c | 3 +-
drivers/crypto/openssl/rte_openssl_pmd.c | 329 ++++++++++++----
drivers/crypto/snow3g/rte_snow3g_pmd.c | 15 +
drivers/crypto/zuc/rte_zuc_pmd.c | 13 +
lib/librte_cryptodev/rte_cryptodev.c | 4 +-
lib/librte_cryptodev/rte_cryptodev.h | 3 +-
lib/librte_mbuf/rte_mbuf.h | 56 +++
19 files changed, 1991 insertions(+), 155 deletions(-)
--
1.7.9.5
^ permalink raw reply
* [PATCH v3 17/17] net/i40e: flush tunnel filters
From: Beilei Xing @ 2016-12-29 16:04 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483027473-89042-1-git-send-email-beilei.xing@intel.com>
This patch adds i40e_tunnel_filter_flush function
to flush all tunnel filters, including filters in
SW and HW.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_flow.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 947199d..d19d952 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -105,6 +105,7 @@ static int i40e_dev_destroy_tunnel_filter(struct i40e_pf *pf,
struct i40e_tunnel_filter *filter);
static int i40e_fdir_filter_flush(struct i40e_pf *pf);
static int i40e_ethertype_filter_flush(struct i40e_pf *pf);
+static int i40e_tunnel_filter_flush(struct i40e_pf *pf);
const struct rte_flow_ops i40e_flow_ops = {
.validate = i40e_flow_validate,
@@ -1671,6 +1672,14 @@ i40e_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
return -rte_errno;
}
+ ret = i40e_tunnel_filter_flush(pf);
+ if (ret) {
+ rte_flow_error_set(error, -ret,
+ RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+ "Failed to flush tunnel flows.");
+ return -rte_errno;
+ }
+
return ret;
}
@@ -1733,3 +1742,31 @@ i40e_ethertype_filter_flush(struct i40e_pf *pf)
return ret;
}
+
+/* Flush all tunnel filters */
+static int
+i40e_tunnel_filter_flush(struct i40e_pf *pf)
+{
+ struct i40e_tunnel_filter_list
+ *tunnel_list = &pf->tunnel.tunnel_list;
+ struct i40e_tunnel_filter *f;
+ struct i40e_flow *flow;
+ void *temp;
+ int ret = 0;
+
+ while ((f = TAILQ_FIRST(tunnel_list))) {
+ ret = i40e_dev_destroy_tunnel_filter(pf, f);
+ if (ret)
+ return ret;
+ }
+
+ /* Delete tunnel flows in flow list. */
+ TAILQ_FOREACH_SAFE(flow, &pf->flow_list, node, temp) {
+ if (flow->filter_type == RTE_ETH_FILTER_TUNNEL) {
+ TAILQ_REMOVE(&pf->flow_list, flow, node);
+ rte_free(flow);
+ }
+ }
+
+ return ret;
+}
--
2.5.5
^ permalink raw reply related
* [PATCH v3 11/17] net/i40e: add flow destroy function
From: Beilei Xing @ 2016-12-29 16:04 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483027473-89042-1-git-send-email-beilei.xing@intel.com>
This patch adds i40e_flow_destroy function to destroy
a flow for users.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_flow.c | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 8db8e0f..a64ef0e 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -67,6 +67,9 @@ static struct rte_flow *i40e_flow_create(struct rte_eth_dev *dev,
const struct rte_flow_item pattern[],
const struct rte_flow_action actions[],
struct rte_flow_error *error);
+static int i40e_flow_destroy(struct rte_eth_dev *dev,
+ struct rte_flow *flow,
+ struct rte_flow_error *error);
static int i40e_parse_ethertype_pattern(__rte_unused struct rte_eth_dev *dev,
const struct rte_flow_item *pattern,
struct rte_flow_error *error,
@@ -97,6 +100,7 @@ static int i40e_parse_attr(const struct rte_flow_attr *attr,
const struct rte_flow_ops i40e_flow_ops = {
.validate = i40e_flow_validate,
.create = i40e_flow_create,
+ .destroy = i40e_flow_destroy,
};
union i40e_filter_t cons_filter;
@@ -1523,3 +1527,32 @@ i40e_flow_create(struct rte_eth_dev *dev,
rte_free(flow);
return NULL;
}
+
+static int
+i40e_flow_destroy(struct rte_eth_dev *dev,
+ struct rte_flow *flow,
+ struct rte_flow_error *error)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_flow *pmd_flow = (struct i40e_flow *)flow;
+ enum rte_filter_type filter_type = pmd_flow->filter_type;
+ int ret = 0;
+
+ switch (filter_type) {
+ default:
+ PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
+ filter_type);
+ ret = -EINVAL;
+ break;
+ }
+
+ if (!ret) {
+ TAILQ_REMOVE(&pf->flow_list, pmd_flow, node);
+ rte_free(pmd_flow);
+ } else
+ rte_flow_error_set(error, -ret,
+ RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+ "Failed to destroy flow.");
+
+ return ret;
+}
--
2.5.5
^ permalink raw reply related
* [PATCH v3 15/17] net/i40e: add flow flush function
From: Beilei Xing @ 2016-12-29 16:04 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483027473-89042-1-git-send-email-beilei.xing@intel.com>
This patch adds i40e_flow_flush function to flush all
filters for users. And flow director flush function
is involved first.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_ethdev.h | 1 +
drivers/net/i40e/i40e_fdir.c | 4 +---
drivers/net/i40e/i40e_flow.c | 51 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 53 insertions(+), 3 deletions(-)
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index b33910d..57fd796 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -788,6 +788,7 @@ int i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
int i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
struct rte_eth_tunnel_filter_conf *tunnel_filter,
uint8_t add);
+int i40e_fdir_flush(struct rte_eth_dev *dev);
/* I40E_DEV_PRIVATE_TO */
#define I40E_DEV_PRIVATE_TO_PF(adapter) \
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index e1f97bb..965e3b2 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -119,8 +119,6 @@ static int i40e_fdir_filter_programming(struct i40e_pf *pf,
enum i40e_filter_pctype pctype,
const struct rte_eth_fdir_filter *filter,
bool add);
-static int i40e_fdir_flush(struct rte_eth_dev *dev);
-
static int i40e_fdir_filter_convert(const struct rte_eth_fdir_filter *input,
struct i40e_fdir_filter *filter);
static struct i40e_fdir_filter *
@@ -1325,7 +1323,7 @@ i40e_fdir_filter_programming(struct i40e_pf *pf,
* i40e_fdir_flush - clear all filters of Flow Director table
* @pf: board private structure
*/
-static int
+int
i40e_fdir_flush(struct rte_eth_dev *dev)
{
struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 605ee70..ee463c9 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -68,6 +68,8 @@ static struct rte_flow *i40e_flow_create(struct rte_eth_dev *dev,
const struct rte_flow_item pattern[],
const struct rte_flow_action actions[],
struct rte_flow_error *error);
+static int i40e_flow_flush(struct rte_eth_dev *dev,
+ struct rte_flow_error *error);
static int i40e_flow_destroy(struct rte_eth_dev *dev,
struct rte_flow *flow,
struct rte_flow_error *error);
@@ -101,11 +103,13 @@ static int i40e_dev_destroy_ethertype_filter(struct i40e_pf *pf,
struct i40e_ethertype_filter *filter);
static int i40e_dev_destroy_tunnel_filter(struct i40e_pf *pf,
struct i40e_tunnel_filter *filter);
+static int i40e_fdir_filter_flush(struct i40e_pf *pf);
const struct rte_flow_ops i40e_flow_ops = {
.validate = i40e_flow_validate,
.create = i40e_flow_create,
.destroy = i40e_flow_destroy,
+ .flush = i40e_flow_flush,
};
union i40e_filter_t cons_filter;
@@ -1643,3 +1647,50 @@ i40e_dev_destroy_tunnel_filter(struct i40e_pf *pf,
return ret;
}
+
+static int
+i40e_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ int ret;
+
+ ret = i40e_fdir_filter_flush(pf);
+ if (ret)
+ rte_flow_error_set(error, -ret,
+ RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+ "Failed to flush FDIR flows.");
+
+ return ret;
+}
+
+static int
+i40e_fdir_filter_flush(struct i40e_pf *pf)
+{
+ struct rte_eth_dev *dev = pf->adapter->eth_dev;
+ struct i40e_fdir_info *fdir_info = &pf->fdir;
+ struct i40e_fdir_filter *fdir_filter;
+ struct i40e_flow *flow;
+ void *temp;
+ int ret;
+
+ ret = i40e_fdir_flush(dev);
+ if (!ret) {
+ /* Delete FDIR filters in FDIR list. */
+ while ((fdir_filter = TAILQ_FIRST(&fdir_info->fdir_list))) {
+ ret = i40e_sw_fdir_filter_del(pf,
+ &fdir_filter->fdir.input);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* Delete FDIR flows in flow list. */
+ TAILQ_FOREACH_SAFE(flow, &pf->flow_list, node, temp) {
+ if (flow->filter_type == RTE_ETH_FILTER_FDIR) {
+ TAILQ_REMOVE(&pf->flow_list, flow, node);
+ rte_free(flow);
+ }
+ }
+ }
+
+ return ret;
+}
--
2.5.5
^ permalink raw reply related
* [PATCH v3 16/17] net/i40e: flush ethertype filters
From: Beilei Xing @ 2016-12-29 16:04 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483027473-89042-1-git-send-email-beilei.xing@intel.com>
This patch adds i40e_ethertype_filter_flush function
to flush all ethertype filters, including filters in
SW and HW.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_flow.c | 41 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index ee463c9..947199d 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -104,6 +104,7 @@ static int i40e_dev_destroy_ethertype_filter(struct i40e_pf *pf,
static int i40e_dev_destroy_tunnel_filter(struct i40e_pf *pf,
struct i40e_tunnel_filter *filter);
static int i40e_fdir_filter_flush(struct i40e_pf *pf);
+static int i40e_ethertype_filter_flush(struct i40e_pf *pf);
const struct rte_flow_ops i40e_flow_ops = {
.validate = i40e_flow_validate,
@@ -1655,10 +1656,20 @@ i40e_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
int ret;
ret = i40e_fdir_filter_flush(pf);
- if (ret)
+ if (ret) {
rte_flow_error_set(error, -ret,
RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
"Failed to flush FDIR flows.");
+ return -rte_errno;
+ }
+
+ ret = i40e_ethertype_filter_flush(pf);
+ if (ret) {
+ rte_flow_error_set(error, -ret,
+ RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+ "Failed to ethertype flush flows.");
+ return -rte_errno;
+ }
return ret;
}
@@ -1694,3 +1705,31 @@ i40e_fdir_filter_flush(struct i40e_pf *pf)
return ret;
}
+
+/* Flush all ethertype filters */
+static int
+i40e_ethertype_filter_flush(struct i40e_pf *pf)
+{
+ struct i40e_ethertype_filter_list
+ *ethertype_list = &pf->ethertype.ethertype_list;
+ struct i40e_ethertype_filter *f;
+ struct i40e_flow *flow;
+ void *temp;
+ int ret = 0;
+
+ while ((f = TAILQ_FIRST(ethertype_list))) {
+ ret = i40e_dev_destroy_ethertype_filter(pf, f);
+ if (ret)
+ return ret;
+ }
+
+ /* Delete ethertype flows in flow list. */
+ TAILQ_FOREACH_SAFE(flow, &pf->flow_list, node, temp) {
+ if (flow->filter_type == RTE_ETH_FILTER_ETHERTYPE) {
+ TAILQ_REMOVE(&pf->flow_list, flow, node);
+ rte_free(flow);
+ }
+ }
+
+ return ret;
+}
--
2.5.5
^ permalink raw reply related
* [PATCH v3 12/17] net/i40e: destroy ethertype filter
From: Beilei Xing @ 2016-12-29 16:04 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483027473-89042-1-git-send-email-beilei.xing@intel.com>
This patch adds i40e_dev_destroy_ethertype_filter function
to destroy a ethertype filter for users.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_flow.c | 42 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index a64ef0e..a41d4c2 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -49,6 +49,7 @@
#include "i40e_logs.h"
#include "base/i40e_type.h"
+#include "base/i40e_prototype.h"
#include "i40e_ethdev.h"
#define I40E_IPV4_TC_SHIFT 4
@@ -96,6 +97,8 @@ static int i40e_parse_tunnel_act(struct rte_eth_dev *dev,
struct rte_eth_tunnel_filter_conf *filter);
static int i40e_parse_attr(const struct rte_flow_attr *attr,
struct rte_flow_error *error);
+static int i40e_dev_destroy_ethertype_filter(struct i40e_pf *pf,
+ struct i40e_ethertype_filter *filter);
const struct rte_flow_ops i40e_flow_ops = {
.validate = i40e_flow_validate,
@@ -1539,6 +1542,10 @@ i40e_flow_destroy(struct rte_eth_dev *dev,
int ret = 0;
switch (filter_type) {
+ case RTE_ETH_FILTER_ETHERTYPE:
+ ret = i40e_dev_destroy_ethertype_filter(pf,
+ (struct i40e_ethertype_filter *)pmd_flow->rule);
+ break;
default:
PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
filter_type);
@@ -1556,3 +1563,38 @@ i40e_flow_destroy(struct rte_eth_dev *dev,
return ret;
}
+
+static int
+i40e_dev_destroy_ethertype_filter(struct i40e_pf *pf,
+ struct i40e_ethertype_filter *filter)
+{
+ struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+ struct i40e_ethertype_rule *ethertype_rule = &pf->ethertype;
+ struct i40e_ethertype_filter *node;
+ struct i40e_control_filter_stats stats;
+ uint16_t flags = 0;
+ int ret = 0;
+
+ if (!(filter->flags & RTE_ETHTYPE_FLAGS_MAC))
+ flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC;
+ if (filter->flags & RTE_ETHTYPE_FLAGS_DROP)
+ flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_DROP;
+ flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TO_QUEUE;
+
+ memset(&stats, 0, sizeof(stats));
+ ret = i40e_aq_add_rem_control_packet_filter(hw,
+ filter->input.mac_addr.addr_bytes,
+ filter->input.ether_type,
+ flags, pf->main_vsi->seid,
+ filter->queue, 0, &stats, NULL);
+ if (ret < 0)
+ return ret;
+
+ node = i40e_sw_ethertype_filter_lookup(ethertype_rule, &filter->input);
+ if (!node)
+ return -EINVAL;
+
+ ret = i40e_sw_ethertype_filter_del(pf, &node->input);
+
+ return ret;
+}
--
2.5.5
^ permalink raw reply related
* [PATCH v3 14/17] net/i40e: destroy flow directory filter
From: Beilei Xing @ 2016-12-29 16:04 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483027473-89042-1-git-send-email-beilei.xing@intel.com>
This patch supports destroying a flow directory filter
for users.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_flow.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index e442c5c..605ee70 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1552,6 +1552,10 @@ i40e_flow_destroy(struct rte_eth_dev *dev,
ret = i40e_dev_destroy_tunnel_filter(pf,
(struct i40e_tunnel_filter *)pmd_flow->rule);
break;
+ case RTE_ETH_FILTER_FDIR:
+ ret = i40e_add_del_fdir_filter(dev,
+ &((struct i40e_fdir_filter *)pmd_flow->rule)->fdir, 0);
+ break;
default:
PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
filter_type);
--
2.5.5
^ permalink raw reply related
* [PATCH v3 09/17] net/i40e: parse tunnel filter
From: Beilei Xing @ 2016-12-29 16:04 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483027473-89042-1-git-send-email-beilei.xing@intel.com>
This patch adds i40e_parse_tunnel_filter to check if
a rule is a tunnel rule according to items of the flow
pattern, and the function also gets the tunnel info.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_flow.c | 394 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 394 insertions(+)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 7b872c9..53bfb2b 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -54,6 +54,8 @@
#define I40E_IPV4_TC_SHIFT 4
#define I40E_IPV6_TC_MASK (0x00FF << I40E_IPV4_TC_SHIFT)
#define I40E_IPV6_FRAG_HEADER 44
+#define I40E_TENANT_ARRAY_NUM 3
+#define I40E_TCI_MASK 0x0FFF
static int i40e_flow_validate(struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
@@ -76,6 +78,14 @@ static int i40e_parse_fdir_act(struct rte_eth_dev *dev,
const struct rte_flow_action *actions,
struct rte_flow_error *error,
struct rte_eth_fdir_filter *filter);
+static int i40e_parse_tunnel_pattern(__rte_unused struct rte_eth_dev *dev,
+ const struct rte_flow_item *pattern,
+ struct rte_flow_error *error,
+ struct rte_eth_tunnel_filter_conf *filter);
+static int i40e_parse_tunnel_act(struct rte_eth_dev *dev,
+ const struct rte_flow_action *actions,
+ struct rte_flow_error *error,
+ struct rte_eth_tunnel_filter_conf *filter);
static int i40e_parse_attr(const struct rte_flow_attr *attr,
struct rte_flow_error *error);
@@ -192,6 +202,45 @@ static enum rte_flow_item_type pattern_fdir_ipv6_sctp_ext[] = {
RTE_FLOW_ITEM_TYPE_END,
};
+/* Pattern matched tunnel filter */
+static enum rte_flow_item_type pattern_vxlan_1[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV4,
+ RTE_FLOW_ITEM_TYPE_UDP,
+ RTE_FLOW_ITEM_TYPE_VXLAN,
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_vxlan_2[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV6,
+ RTE_FLOW_ITEM_TYPE_UDP,
+ RTE_FLOW_ITEM_TYPE_VXLAN,
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_vxlan_3[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV4,
+ RTE_FLOW_ITEM_TYPE_UDP,
+ RTE_FLOW_ITEM_TYPE_VXLAN,
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_VLAN,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_vxlan_4[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV6,
+ RTE_FLOW_ITEM_TYPE_UDP,
+ RTE_FLOW_ITEM_TYPE_VXLAN,
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_VLAN,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
static int
i40e_parse_ethertype_filter(struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
@@ -257,6 +306,33 @@ i40e_parse_fdir_filter(struct rte_eth_dev *dev,
return 0;
}
+static int
+i40e_parse_tunnel_filter(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error,
+ union i40e_filter_t *filter)
+{
+ struct rte_eth_tunnel_filter_conf *tunnel_filter =
+ &filter->tunnel_filter;
+ int ret;
+
+ ret = i40e_parse_tunnel_pattern(dev, pattern, error, tunnel_filter);
+ if (ret)
+ return ret;
+
+ ret = i40e_parse_tunnel_act(dev, actions, error, tunnel_filter);
+ if (ret)
+ return ret;
+
+ ret = i40e_parse_attr(attr, error);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
static struct i40e_valid_pattern i40e_supported_patterns[] = {
/* Ethertype */
{ pattern_ethertype, i40e_parse_ethertype_filter },
@@ -277,6 +353,11 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
{ pattern_fdir_ipv6_tcp_ext, i40e_parse_fdir_filter },
{ pattern_fdir_ipv6_sctp, i40e_parse_fdir_filter },
{ pattern_fdir_ipv6_sctp_ext, i40e_parse_fdir_filter },
+ /* tunnel */
+ { pattern_vxlan_1, i40e_parse_tunnel_filter },
+ { pattern_vxlan_2, i40e_parse_tunnel_filter },
+ { pattern_vxlan_3, i40e_parse_tunnel_filter },
+ { pattern_vxlan_4, i40e_parse_tunnel_filter },
};
#define NEXT_ITEM_OF_ACTION(act, actions, index) \
@@ -991,6 +1072,319 @@ i40e_parse_fdir_act(struct rte_eth_dev *dev,
return 0;
}
+/* Parse to get the action info of a tunnle filter */
+static int i40e_parse_tunnel_act(struct rte_eth_dev *dev,
+ const struct rte_flow_action *actions,
+ struct rte_flow_error *error,
+ struct rte_eth_tunnel_filter_conf *filter)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ const struct rte_flow_action *act;
+ const struct rte_flow_action_queue *act_q;
+ uint32_t index = 0;
+
+ /* Check if the first non-void action is QUEUE. */
+ NEXT_ITEM_OF_ACTION(act, actions, index);
+ if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+ act, "Not supported action.");
+ return -rte_errno;
+ }
+
+ act_q = (const struct rte_flow_action_queue *)act->conf;
+ filter->queue_id = act_q->index;
+ if (filter->queue_id >= pf->dev_data->nb_rx_queues) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ act, "Invalid queue ID for tunnel filter");
+ return -rte_errno;
+ }
+
+ /* Check if the next non-void item is END */
+ index++;
+ NEXT_ITEM_OF_ACTION(act, actions, index);
+ if (act->type != RTE_FLOW_ACTION_TYPE_END) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+ act, "Not supported action.");
+ return -rte_errno;
+ }
+
+ return 0;
+}
+
+static int
+i40e_check_tenant_id_mask(const uint8_t *mask)
+{
+ uint32_t j;
+ int is_masked = 0;
+
+ for (j = 0; j < I40E_TENANT_ARRAY_NUM; j++) {
+ if (*(mask + j) == UINT8_MAX) {
+ if (j > 0 && (*(mask + j) != *(mask + j - 1)))
+ return -EINVAL;
+ is_masked = 0;
+ } else if (*(mask + j) == 0) {
+ if (j > 0 && (*(mask + j) != *(mask + j - 1)))
+ return -EINVAL;
+ is_masked = 1;
+ } else {
+ return -EINVAL;
+ }
+ }
+
+ return is_masked;
+}
+
+static int
+i40e_parse_vxlan_pattern(const struct rte_flow_item *pattern,
+ struct rte_flow_error *error,
+ struct rte_eth_tunnel_filter_conf *filter)
+{
+ const struct rte_flow_item *item = pattern;
+ const struct rte_flow_item_eth *eth_spec;
+ const struct rte_flow_item_eth *eth_mask;
+ const struct rte_flow_item_eth *o_eth_spec;
+ const struct rte_flow_item_eth *o_eth_mask;
+ const struct rte_flow_item_vxlan *vxlan_spec;
+ const struct rte_flow_item_vxlan *vxlan_mask;
+ const struct rte_flow_item_eth *i_eth_spec;
+ const struct rte_flow_item_eth *i_eth_mask;
+ const struct rte_flow_item_vlan *vlan_spec = NULL;
+ const struct rte_flow_item_vlan *vlan_mask = NULL;
+ bool is_vni_masked = 0;
+ enum rte_flow_item_type item_type;
+ bool vxlan_flag = 0;
+
+ for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+ if (item->last) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Not support range");
+ return -rte_errno;
+ }
+ item_type = item->type;
+ switch (item_type) {
+ case RTE_FLOW_ITEM_TYPE_ETH:
+ eth_spec = (const struct rte_flow_item_eth *)item->spec;
+ eth_mask = (const struct rte_flow_item_eth *)item->mask;
+ if ((!eth_spec && eth_mask) ||
+ (eth_spec && !eth_mask)) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid ether spec/mask");
+ return -rte_errno;
+ }
+
+ if (eth_spec && eth_mask) {
+ /* DST address of inner MAC shouldn't be masked.
+ * SRC address of Inner MAC should be masked.
+ */
+ if (!is_broadcast_ether_addr(ð_mask->dst) ||
+ !is_zero_ether_addr(ð_mask->src) ||
+ eth_mask->type) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid ether spec/mask");
+ return -rte_errno;
+ }
+
+ if (!vxlan_flag)
+ rte_memcpy(&filter->outer_mac,
+ ð_spec->dst,
+ ETHER_ADDR_LEN);
+ else
+ rte_memcpy(&filter->inner_mac,
+ ð_spec->dst,
+ ETHER_ADDR_LEN);
+ }
+
+ if (!vxlan_flag) {
+ o_eth_spec = eth_spec;
+ o_eth_mask = eth_mask;
+ } else {
+ i_eth_spec = eth_spec;
+ i_eth_mask = eth_mask;
+ }
+
+ break;
+ case RTE_FLOW_ITEM_TYPE_VLAN:
+ vlan_spec =
+ (const struct rte_flow_item_vlan *)item->spec;
+ vlan_mask =
+ (const struct rte_flow_item_vlan *)item->mask;
+ if (vxlan_flag) {
+ vlan_spec =
+ (const struct rte_flow_item_vlan *)item->spec;
+ vlan_mask =
+ (const struct rte_flow_item_vlan *)item->mask;
+ if (!(vlan_spec && vlan_mask)) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid vlan item");
+ return -rte_errno;
+ }
+ } else {
+ if (vlan_spec || vlan_mask)
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid vlan item");
+ return -rte_errno;
+ }
+ break;
+ case RTE_FLOW_ITEM_TYPE_IPV4:
+ case RTE_FLOW_ITEM_TYPE_IPV6:
+ case RTE_FLOW_ITEM_TYPE_UDP:
+ /* IPv4/IPv6/UDP are used to describe protocol,
+ * spec amd mask should be NULL.
+ */
+ if (item->spec || item->mask) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid IPv4 item");
+ return -rte_errno;
+ }
+ break;
+ case RTE_FLOW_ITEM_TYPE_VXLAN:
+ vxlan_spec =
+ (const struct rte_flow_item_vxlan *)item->spec;
+ vxlan_mask =
+ (const struct rte_flow_item_vxlan *)item->mask;
+ /* Check if VXLAN item is used to describe protocol.
+ * If yes, both spec and mask should be NULL.
+ * If no, either spec or mask shouldn't be NULL.
+ */
+ if ((!vxlan_spec && vxlan_mask) ||
+ (vxlan_spec && !vxlan_mask)) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid VXLAN item");
+ return -rte_errno;
+ }
+
+ /* Check if VNI is masked. */
+ if (vxlan_mask) {
+ is_vni_masked =
+ i40e_check_tenant_id_mask(vxlan_mask->vni);
+ if (is_vni_masked < 0) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid VNI mask");
+ return -rte_errno;
+ }
+ }
+ vxlan_flag = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Check specification and mask to get the filter type */
+ if (vlan_spec && vlan_mask &&
+ (vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) {
+ /* If there's inner vlan */
+ filter->inner_vlan = rte_be_to_cpu_16(vlan_spec->tci)
+ & I40E_TCI_MASK;
+ if (vxlan_spec && vxlan_mask && !is_vni_masked) {
+ /* If there's vxlan */
+ rte_memcpy(&filter->tenant_id, vxlan_spec->vni,
+ RTE_DIM(vxlan_spec->vni));
+ if (!o_eth_spec && !o_eth_mask &&
+ i_eth_spec && i_eth_mask)
+ filter->filter_type =
+ RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID;
+ else {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ NULL,
+ "Invalid filter type");
+ return -rte_errno;
+ }
+ } else if (!vxlan_spec && !vxlan_mask) {
+ /* If there's no vxlan */
+ if (!o_eth_spec && !o_eth_mask &&
+ i_eth_spec && i_eth_mask)
+ filter->filter_type =
+ RTE_TUNNEL_FILTER_IMAC_IVLAN;
+ else {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ NULL,
+ "Invalid filter type");
+ return -rte_errno;
+ }
+ } else {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ NULL,
+ "Invalid filter type");
+ return -rte_errno;
+ }
+ } else if ((!vlan_spec && !vlan_mask) ||
+ (vlan_spec && vlan_mask && vlan_mask->tci == 0x0)) {
+ /* If there's no inner vlan */
+ if (vxlan_spec && vxlan_mask && !is_vni_masked) {
+ /* If there's vxlan */
+ rte_memcpy(&filter->tenant_id, vxlan_spec->vni,
+ RTE_DIM(vxlan_spec->vni));
+ if (!o_eth_spec && !o_eth_mask &&
+ i_eth_spec && i_eth_mask)
+ filter->filter_type =
+ RTE_TUNNEL_FILTER_IMAC_TENID;
+ else if (o_eth_spec && o_eth_mask &&
+ i_eth_spec && i_eth_mask)
+ filter->filter_type =
+ RTE_TUNNEL_FILTER_OMAC_TENID_IMAC;
+ } else if (!vxlan_spec && !vxlan_mask) {
+ /* If there's no vxlan */
+ if (!o_eth_spec && !o_eth_mask &&
+ i_eth_spec && i_eth_mask) {
+ filter->filter_type = ETH_TUNNEL_FILTER_IMAC;
+ } else {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+ "Invalid filter type");
+ return -rte_errno;
+ }
+ } else {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+ "Invalid filter type");
+ return -rte_errno;
+ }
+ } else {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+ "Not supported by tunnel filter.");
+ return -rte_errno;
+ }
+
+ filter->tunnel_type = RTE_TUNNEL_TYPE_VXLAN;
+
+ return 0;
+}
+
+static int
+i40e_parse_tunnel_pattern(__rte_unused struct rte_eth_dev *dev,
+ const struct rte_flow_item *pattern,
+ struct rte_flow_error *error,
+ struct rte_eth_tunnel_filter_conf *filter)
+{
+ int ret;
+
+ ret = i40e_parse_vxlan_pattern(pattern, error, filter);
+
+ return ret;
+}
+
static int
i40e_flow_validate(struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
--
2.5.5
^ permalink raw reply related
* [PATCH v3 13/17] net/i40e: destroy tunnel filter
From: Beilei Xing @ 2016-12-29 16:04 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483027473-89042-1-git-send-email-beilei.xing@intel.com>
This patch adds i40e_dev_destroy_tunnel_filter function
to destroy a tunnel filter for users.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_flow.c | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index a41d4c2..e442c5c 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -99,6 +99,8 @@ static int i40e_parse_attr(const struct rte_flow_attr *attr,
struct rte_flow_error *error);
static int i40e_dev_destroy_ethertype_filter(struct i40e_pf *pf,
struct i40e_ethertype_filter *filter);
+static int i40e_dev_destroy_tunnel_filter(struct i40e_pf *pf,
+ struct i40e_tunnel_filter *filter);
const struct rte_flow_ops i40e_flow_ops = {
.validate = i40e_flow_validate,
@@ -1546,6 +1548,10 @@ i40e_flow_destroy(struct rte_eth_dev *dev,
ret = i40e_dev_destroy_ethertype_filter(pf,
(struct i40e_ethertype_filter *)pmd_flow->rule);
break;
+ case RTE_ETH_FILTER_TUNNEL:
+ ret = i40e_dev_destroy_tunnel_filter(pf,
+ (struct i40e_tunnel_filter *)pmd_flow->rule);
+ break;
default:
PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
filter_type);
@@ -1598,3 +1604,38 @@ i40e_dev_destroy_ethertype_filter(struct i40e_pf *pf,
return ret;
}
+
+static int
+i40e_dev_destroy_tunnel_filter(struct i40e_pf *pf,
+ struct i40e_tunnel_filter *filter)
+{
+ struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+ struct i40e_vsi *vsi = pf->main_vsi;
+ struct i40e_aqc_add_remove_cloud_filters_element_data cld_filter;
+ struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
+ struct i40e_tunnel_filter *node;
+ int ret = 0;
+
+ memset(&cld_filter, 0, sizeof(cld_filter));
+ ether_addr_copy((struct ether_addr *)&filter->input.outer_mac,
+ (struct ether_addr *)&cld_filter.outer_mac);
+ ether_addr_copy((struct ether_addr *)&filter->input.inner_mac,
+ (struct ether_addr *)&cld_filter.inner_mac);
+ cld_filter.inner_vlan = filter->input.inner_vlan;
+ cld_filter.flags = filter->input.flags;
+ cld_filter.tenant_id = filter->input.tenant_id;
+ cld_filter.queue_number = filter->queue;
+
+ ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
+ &cld_filter, 1);
+ if (ret < 0)
+ return ret;
+
+ node = i40e_sw_tunnel_filter_lookup(tunnel_rule, &filter->input);
+ if (!node)
+ return -EINVAL;
+
+ ret = i40e_sw_tunnel_filter_del(pf, &node->input);
+
+ return ret;
+}
--
2.5.5
^ permalink raw reply related
* [PATCH v3 10/17] net/i40e: add flow create function
From: Beilei Xing @ 2016-12-29 16:04 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483027473-89042-1-git-send-email-beilei.xing@intel.com>
This patch adds i40e_flow_create function to create a
rule. It will check if a flow matches ethertype filter
or flow director filter or tunnel filter, if the flow
matches some kind of filter, then set the filter to HW.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 9 +++--
drivers/net/i40e/i40e_ethdev.h | 21 ++++++++++++
drivers/net/i40e/i40e_fdir.c | 2 +-
drivers/net/i40e/i40e_flow.c | 77 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 103 insertions(+), 6 deletions(-)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 4a057b4..fa59ee4 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -353,9 +353,6 @@ static int i40e_dev_udp_tunnel_port_add(struct rte_eth_dev *dev,
static int i40e_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,
struct rte_eth_udp_tunnel *udp_tunnel);
static void i40e_filter_input_set_init(struct i40e_pf *pf);
-static int i40e_ethertype_filter_set(struct i40e_pf *pf,
- struct rte_eth_ethertype_filter *filter,
- bool add);
static int i40e_ethertype_filter_handle(struct rte_eth_dev *dev,
enum rte_filter_op filter_op,
void *arg);
@@ -1233,6 +1230,8 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
goto err_fdir_hash_map_alloc;
}
+ TAILQ_INIT(&pf->flow_list);
+
return 0;
err_fdir_hash_map_alloc:
@@ -6611,7 +6610,7 @@ i40e_sw_tunnel_filter_del(struct i40e_pf *pf,
return 0;
}
-static int
+int
i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
struct rte_eth_tunnel_filter_conf *tunnel_filter,
uint8_t add)
@@ -8256,7 +8255,7 @@ i40e_sw_ethertype_filter_del(struct i40e_pf *pf,
* Configure ethertype filter, which can director packet by filtering
* with mac address and ether_type or only ether_type
*/
-static int
+int
i40e_ethertype_filter_set(struct i40e_pf *pf,
struct rte_eth_ethertype_filter *filter,
bool add)
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 9e3a48d..b33910d 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -536,6 +536,17 @@ struct i40e_mirror_rule {
TAILQ_HEAD(i40e_mirror_rule_list, i40e_mirror_rule);
/*
+ * Struct to store flow created.
+ */
+struct i40e_flow {
+ TAILQ_ENTRY(i40e_flow) node;
+ enum rte_filter_type filter_type;
+ void *rule;
+};
+
+TAILQ_HEAD(i40e_flow_list, i40e_flow);
+
+/*
* Structure to store private data specific for PF instance.
*/
struct i40e_pf {
@@ -592,6 +603,7 @@ struct i40e_pf {
bool floating_veb; /* The flag to use the floating VEB */
/* The floating enable flag for the specific VF */
bool floating_veb_list[I40E_MAX_VF];
+ struct i40e_flow_list flow_list;
};
enum pending_msg {
@@ -767,6 +779,15 @@ i40e_sw_tunnel_filter_lookup(struct i40e_tunnel_rule *tunnel_rule,
int i40e_sw_tunnel_filter_del(struct i40e_pf *pf,
struct i40e_tunnel_filter_input *input);
uint64_t i40e_get_default_input_set(uint16_t pctype);
+int i40e_ethertype_filter_set(struct i40e_pf *pf,
+ struct rte_eth_ethertype_filter *filter,
+ bool add);
+int i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
+ const struct rte_eth_fdir_filter *filter,
+ bool add);
+int i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
+ struct rte_eth_tunnel_filter_conf *tunnel_filter,
+ uint8_t add);
/* I40E_DEV_PRIVATE_TO */
#define I40E_DEV_PRIVATE_TO_PF(adapter) \
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index 78ce92c..e1f97bb 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -1099,7 +1099,7 @@ i40e_sw_fdir_filter_del(struct i40e_pf *pf, struct rte_eth_fdir_input *input)
* @filter: fdir filter entry
* @add: 0 - delete, 1 - add
*/
-static int
+int
i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
const struct rte_eth_fdir_filter *filter,
bool add)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 53bfb2b..8db8e0f 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -62,6 +62,11 @@ static int i40e_flow_validate(struct rte_eth_dev *dev,
const struct rte_flow_item pattern[],
const struct rte_flow_action actions[],
struct rte_flow_error *error);
+static struct rte_flow *i40e_flow_create(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error);
static int i40e_parse_ethertype_pattern(__rte_unused struct rte_eth_dev *dev,
const struct rte_flow_item *pattern,
struct rte_flow_error *error,
@@ -91,9 +96,11 @@ static int i40e_parse_attr(const struct rte_flow_attr *attr,
const struct rte_flow_ops i40e_flow_ops = {
.validate = i40e_flow_validate,
+ .create = i40e_flow_create,
};
union i40e_filter_t cons_filter;
+enum rte_filter_type cons_filter_type = RTE_ETH_FILTER_NONE;
/* Pattern matched ethertype filter */
static enum rte_flow_item_type pattern_ethertype[] = {
@@ -267,6 +274,8 @@ i40e_parse_ethertype_filter(struct rte_eth_dev *dev,
if (ret)
return ret;
+ cons_filter_type = RTE_ETH_FILTER_ETHERTYPE;
+
return ret;
}
@@ -294,6 +303,8 @@ i40e_parse_fdir_filter(struct rte_eth_dev *dev,
if (ret)
return ret;
+ cons_filter_type = RTE_ETH_FILTER_FDIR;
+
if (dev->data->dev_conf.fdir_conf.mode !=
RTE_FDIR_MODE_PERFECT) {
rte_flow_error_set(error, ENOTSUP,
@@ -330,6 +341,8 @@ i40e_parse_tunnel_filter(struct rte_eth_dev *dev,
if (ret)
return ret;
+ cons_filter_type = RTE_ETH_FILTER_TUNNEL;
+
return ret;
}
@@ -1446,3 +1459,67 @@ i40e_flow_validate(struct rte_eth_dev *dev,
return ret;
}
+
+static struct rte_flow *
+i40e_flow_create(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_flow *flow;
+ int ret;
+
+ flow = rte_zmalloc("i40e_flow", sizeof(struct i40e_flow), 0);
+ if (!flow) {
+ rte_flow_error_set(error, ENOMEM,
+ RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+ "Failed to allocate memory");
+ return (struct rte_flow *)flow;
+ }
+
+ ret = i40e_flow_validate(dev, attr, pattern, actions, error);
+ if (ret < 0)
+ return NULL;
+
+ switch (cons_filter_type) {
+ case RTE_ETH_FILTER_ETHERTYPE:
+ ret = i40e_ethertype_filter_set(pf,
+ &cons_filter.ethertype_filter, 1);
+ if (ret)
+ goto free_flow;
+ flow->rule = TAILQ_LAST(&pf->ethertype.ethertype_list,
+ i40e_ethertype_filter_list);
+ break;
+ case RTE_ETH_FILTER_FDIR:
+ ret = i40e_add_del_fdir_filter(dev,
+ &cons_filter.fdir_filter, 1);
+ if (ret)
+ goto free_flow;
+ flow->rule = TAILQ_LAST(&pf->fdir.fdir_list,
+ i40e_fdir_filter_list);
+ break;
+ case RTE_ETH_FILTER_TUNNEL:
+ ret = i40e_dev_tunnel_filter_set(pf,
+ &cons_filter.tunnel_filter, 1);
+ if (ret)
+ goto free_flow;
+ flow->rule = TAILQ_LAST(&pf->tunnel.tunnel_list,
+ i40e_tunnel_filter_list);
+ break;
+ default:
+ goto free_flow;
+ }
+
+ flow->filter_type = cons_filter_type;
+ TAILQ_INSERT_TAIL(&pf->flow_list, flow, node);
+ return (struct rte_flow *)flow;
+
+free_flow:
+ rte_flow_error_set(error, -ret,
+ RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+ "Failed to create flow.");
+ rte_free(flow);
+ return NULL;
+}
--
2.5.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox