* [PATCH v4] net/i40e: fix the hash filter invalid calculation in X722
From: Jeff Guo @ 2016-10-25 2:26 UTC (permalink / raw)
To: helin.zhang, jingjing.wu; +Cc: dev, jia.guo
In-Reply-To: <1476931738-44140-1-git-send-email-jia.guo@intel.com>
When verifying the Hash filtering on X722, we found a problem that
the hash value in descriptor is incorrect. The root caused is X722
uses different way of hash key word selection comparing with X710/XL710.
This patch fixes it by setting X722 specific key selection.
Signed-off-by: Jeff Guo <jia.guo@intel.com>
---
v4:
refine commit log
---
drivers/net/i40e/i40e_ethdev.c | 60 +++++++++++++++++++++++++++++++++---------
1 file changed, 47 insertions(+), 13 deletions(-)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index db5f808..ca515dd 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -211,6 +211,14 @@
#define I40E_REG_INSET_L3_SRC_IP4 0x0001800000000000ULL
/* Destination IPv4 address */
#define I40E_REG_INSET_L3_DST_IP4 0x0000001800000000ULL
+/* Source IPv4 address for X722 */
+#define I40E_X722_REG_INSET_L3_SRC_IP4 0x0006000000000000ULL
+/* Destination IPv4 address for X722 */
+#define I40E_X722_REG_INSET_L3_DST_IP4 0x0000060000000000ULL
+/* IPv4 Protocol for X722 */
+#define I40E_X722_REG_INSET_L3_IP4_PROTO 0x0010000000000000ULL
+/* IPv4 Time to Live for X722 */
+#define I40E_X722_REG_INSET_L3_IP4_TTL 0x0010000000000000ULL
/* IPv4 Type of Service (TOS) */
#define I40E_REG_INSET_L3_IP4_TOS 0x0040000000000000ULL
/* IPv4 Protocol */
@@ -7568,25 +7576,23 @@ i40e_parse_input_set(uint64_t *inset,
* and vice versa
*/
static uint64_t
-i40e_translate_input_set_reg(uint64_t input)
+i40e_translate_input_set_reg(enum i40e_mac_type type, uint64_t input)
{
uint64_t val = 0;
uint16_t i;
- static const struct {
+ struct inset_map {
uint64_t inset;
uint64_t inset_reg;
- } inset_map[] = {
+ };
+
+ static const struct inset_map inset_map_common[] = {
{I40E_INSET_DMAC, I40E_REG_INSET_L2_DMAC},
{I40E_INSET_SMAC, I40E_REG_INSET_L2_SMAC},
{I40E_INSET_VLAN_OUTER, I40E_REG_INSET_L2_OUTER_VLAN},
{I40E_INSET_VLAN_INNER, I40E_REG_INSET_L2_INNER_VLAN},
{I40E_INSET_LAST_ETHER_TYPE, I40E_REG_INSET_LAST_ETHER_TYPE},
- {I40E_INSET_IPV4_SRC, I40E_REG_INSET_L3_SRC_IP4},
- {I40E_INSET_IPV4_DST, I40E_REG_INSET_L3_DST_IP4},
{I40E_INSET_IPV4_TOS, I40E_REG_INSET_L3_IP4_TOS},
- {I40E_INSET_IPV4_PROTO, I40E_REG_INSET_L3_IP4_PROTO},
- {I40E_INSET_IPV4_TTL, I40E_REG_INSET_L3_IP4_TTL},
{I40E_INSET_IPV6_SRC, I40E_REG_INSET_L3_SRC_IP6},
{I40E_INSET_IPV6_DST, I40E_REG_INSET_L3_DST_IP6},
{I40E_INSET_IPV6_TC, I40E_REG_INSET_L3_IP6_TC},
@@ -7615,13 +7621,40 @@ i40e_translate_input_set_reg(uint64_t input)
{I40E_INSET_FLEX_PAYLOAD_W8, I40E_REG_INSET_FLEX_PAYLOAD_WORD8},
};
+ /* some different registers map in x722*/
+ static const struct inset_map inset_map_diff_x722[] = {
+ {I40E_INSET_IPV4_SRC, I40E_X722_REG_INSET_L3_SRC_IP4},
+ {I40E_INSET_IPV4_DST, I40E_X722_REG_INSET_L3_DST_IP4},
+ {I40E_INSET_IPV4_PROTO, I40E_X722_REG_INSET_L3_IP4_PROTO},
+ {I40E_INSET_IPV4_TTL, I40E_X722_REG_INSET_L3_IP4_TTL},
+ };
+
+ static const struct inset_map inset_map_diff_not_x722[] = {
+ {I40E_INSET_IPV4_SRC, I40E_REG_INSET_L3_SRC_IP4},
+ {I40E_INSET_IPV4_DST, I40E_REG_INSET_L3_DST_IP4},
+ {I40E_INSET_IPV4_PROTO, I40E_REG_INSET_L3_IP4_PROTO},
+ {I40E_INSET_IPV4_TTL, I40E_REG_INSET_L3_IP4_TTL},
+ };
+
if (input == 0)
return val;
/* Translate input set to register aware inset */
- for (i = 0; i < RTE_DIM(inset_map); i++) {
- if (input & inset_map[i].inset)
- val |= inset_map[i].inset_reg;
+ if (type == I40E_MAC_X722) {
+ for (i = 0; i < RTE_DIM(inset_map_diff_x722); i++) {
+ if (input & inset_map_diff_x722[i].inset)
+ val |= inset_map_diff_x722[i].inset_reg;
+ }
+ } else {
+ for (i = 0; i < RTE_DIM(inset_map_diff_not_x722); i++) {
+ if (input & inset_map_diff_not_x722[i].inset)
+ val |= inset_map_diff_not_x722[i].inset_reg;
+ }
+ }
+
+ for (i = 0; i < RTE_DIM(inset_map_common); i++) {
+ if (input & inset_map_common[i].inset)
+ val |= inset_map_common[i].inset_reg;
}
return val;
@@ -7712,7 +7745,8 @@ i40e_filter_input_set_init(struct i40e_pf *pf)
I40E_INSET_MASK_NUM_REG);
if (num < 0)
return;
- inset_reg = i40e_translate_input_set_reg(input_set);
+ inset_reg = i40e_translate_input_set_reg(hw->mac.type,
+ input_set);
i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 0),
(uint32_t)(inset_reg & UINT32_MAX));
@@ -7802,7 +7836,7 @@ i40e_hash_filter_inset_select(struct i40e_hw *hw,
if (num < 0)
return -EINVAL;
- inset_reg |= i40e_translate_input_set_reg(input_set);
+ inset_reg |= i40e_translate_input_set_reg(hw->mac.type, input_set);
i40e_check_write_reg(hw, I40E_GLQF_HASH_INSET(0, pctype),
(uint32_t)(inset_reg & UINT32_MAX));
@@ -7880,7 +7914,7 @@ i40e_fdir_filter_inset_select(struct i40e_pf *pf,
if (num < 0)
return -EINVAL;
- inset_reg |= i40e_translate_input_set_reg(input_set);
+ inset_reg |= i40e_translate_input_set_reg(hw->mac.type, input_set);
i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 0),
(uint32_t)(inset_reg & UINT32_MAX));
--
1.9.3
^ permalink raw reply related
* [PATCH v2] net/i40e: fix fdir configure failed issue in X710
From: Jeff Guo @ 2016-10-25 2:25 UTC (permalink / raw)
To: helin.zhang, jingjing.wu; +Cc: dev, jia.guo
In-Reply-To: <1476931699-44095-1-git-send-email-jia.guo@intel.com>
Because of some register is only supported by X722, such as I40E_GLQF_FD_PCTYPES,
so it need to use the mac type to distinguish the behavior of X722 from X710 and other
NICs, or it would result X710 functional failed.
Fixes: 8c5cb3c11513 (“net/i40e: add packet type translation for X722”)
Signed-off-by: Jeff Guo <jia.guo@intel.com>
---
v2:
refine commit log
decrease some code duplication
---
drivers/net/i40e/i40e_ethdev.c | 103 +++++++++++++++++++++-----------------
drivers/net/i40e/i40e_ethdev.h | 32 +++---------
drivers/net/i40e/i40e_ethdev_vf.c | 16 ++++--
drivers/net/i40e/i40e_fdir.c | 55 ++++++++++++--------
4 files changed, 113 insertions(+), 93 deletions(-)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 5af0e43..db5f808 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -6164,7 +6164,7 @@ DONE:
/* Configure hash enable flags for RSS */
uint64_t
-i40e_config_hena(uint64_t flags)
+i40e_config_hena(uint64_t flags, enum i40e_mac_type type)
{
uint64_t hena = 0;
@@ -6173,42 +6173,42 @@ i40e_config_hena(uint64_t flags)
if (flags & ETH_RSS_FRAG_IPV4)
hena |= 1ULL << I40E_FILTER_PCTYPE_FRAG_IPV4;
- if (flags & ETH_RSS_NONFRAG_IPV4_TCP)
-#ifdef X722_SUPPORT
- hena |= (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) |
- (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK);
-#else
- hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
-#endif
- if (flags & ETH_RSS_NONFRAG_IPV4_UDP)
-#ifdef X722_SUPPORT
- hena |= (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
- (1ULL << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) |
- (1ULL << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP);
-#else
- hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
-#endif
+ if (flags & ETH_RSS_NONFRAG_IPV4_TCP) {
+ if (type == I40E_MAC_X722) {
+ hena |= (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) |
+ (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK);
+ } else
+ hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
+ }
+ if (flags & ETH_RSS_NONFRAG_IPV4_UDP) {
+ if (type == I40E_MAC_X722) {
+ hena |= (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
+ (1ULL << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) |
+ (1ULL << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP);
+ } else
+ hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
+ }
if (flags & ETH_RSS_NONFRAG_IPV4_SCTP)
hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_SCTP;
if (flags & ETH_RSS_NONFRAG_IPV4_OTHER)
hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER;
if (flags & ETH_RSS_FRAG_IPV6)
hena |= 1ULL << I40E_FILTER_PCTYPE_FRAG_IPV6;
- if (flags & ETH_RSS_NONFRAG_IPV6_TCP)
-#ifdef X722_SUPPORT
- hena |= (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) |
- (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK);
-#else
- hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_TCP;
-#endif
- if (flags & ETH_RSS_NONFRAG_IPV6_UDP)
-#ifdef X722_SUPPORT
- hena |= (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) |
- (1ULL << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) |
- (1ULL << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP);
-#else
- hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_UDP;
-#endif
+ if (flags & ETH_RSS_NONFRAG_IPV6_TCP) {
+ if (type == I40E_MAC_X722) {
+ hena |= (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) |
+ (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK);
+ } else
+ hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_TCP;
+ }
+ if (flags & ETH_RSS_NONFRAG_IPV6_UDP) {
+ if (type == I40E_MAC_X722) {
+ hena |= (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) |
+ (1ULL << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) |
+ (1ULL << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP);
+ } else
+ hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_UDP;
+ }
if (flags & ETH_RSS_NONFRAG_IPV6_SCTP)
hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP;
if (flags & ETH_RSS_NONFRAG_IPV6_OTHER)
@@ -6282,7 +6282,10 @@ i40e_pf_disable_rss(struct i40e_pf *pf)
hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0));
hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1))) << 32;
- hena &= ~I40E_RSS_HENA_ALL;
+ if (hw->mac.type == I40E_MAC_X722)
+ hena &= ~I40E_RSS_HENA_ALL_X722;
+ else
+ hena &= ~I40E_RSS_HENA_ALL;
i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), (uint32_t)hena);
i40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), (uint32_t)(hena >> 32));
I40E_WRITE_FLUSH(hw);
@@ -6369,8 +6372,11 @@ i40e_hw_rss_hash_set(struct i40e_pf *pf, struct rte_eth_rss_conf *rss_conf)
rss_hf = rss_conf->rss_hf;
hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0));
hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1))) << 32;
- hena &= ~I40E_RSS_HENA_ALL;
- hena |= i40e_config_hena(rss_hf);
+ if (hw->mac.type == I40E_MAC_X722)
+ hena &= ~I40E_RSS_HENA_ALL_X722;
+ else
+ hena &= ~I40E_RSS_HENA_ALL;
+ hena |= i40e_config_hena(rss_hf, hw->mac.type);
i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), (uint32_t)hena);
i40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), (uint32_t)(hena >> 32));
I40E_WRITE_FLUSH(hw);
@@ -6389,7 +6395,9 @@ i40e_dev_rss_hash_update(struct rte_eth_dev *dev,
hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0));
hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1))) << 32;
- if (!(hena & I40E_RSS_HENA_ALL)) { /* RSS disabled */
+ if (!(hena & ((hw->mac.type == I40E_MAC_X722)
+ ? I40E_RSS_HENA_ALL_X722
+ : I40E_RSS_HENA_ALL))) { /* RSS disabled */
if (rss_hf != 0) /* Enable RSS */
return -EINVAL;
return 0; /* Nothing to do */
@@ -7690,8 +7698,14 @@ i40e_filter_input_set_init(struct i40e_pf *pf)
for (pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
pctype <= I40E_FILTER_PCTYPE_L2_PAYLOAD; pctype++) {
- if (!I40E_VALID_PCTYPE(pctype))
- continue;
+ if (hw->mac.type == I40E_MAC_X722) {
+ if (!I40E_VALID_PCTYPE_X722(pctype))
+ continue;
+ } else {
+ if (!I40E_VALID_PCTYPE(pctype))
+ continue;
+ }
+
input_set = i40e_get_default_input_set(pctype);
num = i40e_generate_inset_mask_reg(input_set, mask_reg,
@@ -7757,14 +7771,13 @@ i40e_hash_filter_inset_select(struct i40e_hw *hw,
return -EINVAL;
}
-#ifdef X722_SUPPORT
- /* get translated pctype value in fd pctype register */
- pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl(hw,
- I40E_GLQF_FD_PCTYPES((int)i40e_flowtype_to_pctype(
- conf->flow_type)));
-#else
- pctype = i40e_flowtype_to_pctype(conf->flow_type);
-#endif
+ if (hw->mac.type == I40E_MAC_X722) {
+ /* get translated pctype value in fd pctype register */
+ pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl(hw,
+ I40E_GLQF_FD_PCTYPES((int)i40e_flowtype_to_pctype(
+ conf->flow_type)));
+ } else
+ pctype = i40e_flowtype_to_pctype(conf->flow_type);
ret = i40e_parse_input_set(&input_set, pctype, conf->field,
conf->inset_size);
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 57a8ae1..24b8580 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -149,30 +149,17 @@ enum i40e_flxpld_layer_idx {
ETH_RSS_NONFRAG_IPV6_OTHER | \
ETH_RSS_L2_PAYLOAD)
-/* All bits of RSS hash enable */
-#ifdef X722_SUPPORT
-#define I40E_RSS_HENA_ALL ( \
+/* All bits of RSS hash enable for X722*/
+#define I40E_RSS_HENA_ALL_X722 ( \
(1ULL << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | \
(1ULL << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) | \
- (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | \
(1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK) | \
- (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) | \
- (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) | \
- (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | \
- (1ULL << I40E_FILTER_PCTYPE_FRAG_IPV4) | \
(1ULL << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | \
(1ULL << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP) | \
- (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | \
(1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK) | \
- (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | \
- (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) | \
- (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | \
- (1ULL << I40E_FILTER_PCTYPE_FRAG_IPV6) | \
- (1ULL << I40E_FILTER_PCTYPE_FCOE_OX) | \
- (1ULL << I40E_FILTER_PCTYPE_FCOE_RX) | \
- (1ULL << I40E_FILTER_PCTYPE_FCOE_OTHER) | \
- (1ULL << I40E_FILTER_PCTYPE_L2_PAYLOAD))
-#else
+ I40E_RSS_HENA_ALL)
+
+/* All bits of RSS hash enable */
#define I40E_RSS_HENA_ALL ( \
(1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | \
(1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) | \
@@ -188,7 +175,6 @@ enum i40e_flxpld_layer_idx {
(1ULL << I40E_FILTER_PCTYPE_FCOE_RX) | \
(1ULL << I40E_FILTER_PCTYPE_FCOE_OTHER) | \
(1ULL << I40E_FILTER_PCTYPE_L2_PAYLOAD))
-#endif
#define I40E_MISC_VEC_ID RTE_INTR_VEC_ZERO_OFFSET
#define I40E_RX_VEC_START RTE_INTR_VEC_RXTX_OFFSET
@@ -601,7 +587,7 @@ int i40e_vsi_vlan_pvid_set(struct i40e_vsi *vsi,
struct i40e_vsi_vlan_pvid_info *info);
int i40e_vsi_config_vlan_stripping(struct i40e_vsi *vsi, bool on);
int i40e_vsi_config_vlan_filter(struct i40e_vsi *vsi, bool on);
-uint64_t i40e_config_hena(uint64_t flags);
+uint64_t i40e_config_hena(uint64_t flags, enum i40e_mac_type type);
uint64_t i40e_parse_hena(uint64_t flags);
enum i40e_status_code i40e_fdir_setup_tx_resources(struct i40e_pf *pf);
enum i40e_status_code i40e_fdir_setup_rx_resources(struct i40e_pf *pf);
@@ -723,8 +709,7 @@ i40e_calc_itr_interval(int16_t interval)
(flow_type) == RTE_ETH_FLOW_NONFRAG_IPV6_OTHER || \
(flow_type) == RTE_ETH_FLOW_L2_PAYLOAD)
-#ifdef X722_SUPPORT
-#define I40E_VALID_PCTYPE(pctype) \
+#define I40E_VALID_PCTYPE_X722(pctype) \
((pctype) == I40E_FILTER_PCTYPE_FRAG_IPV4 || \
(pctype) == I40E_FILTER_PCTYPE_NONF_IPV4_TCP || \
(pctype) == I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK || \
@@ -742,7 +727,7 @@ i40e_calc_itr_interval(int16_t interval)
(pctype) == I40E_FILTER_PCTYPE_NONF_IPV6_SCTP || \
(pctype) == I40E_FILTER_PCTYPE_NONF_IPV6_OTHER || \
(pctype) == I40E_FILTER_PCTYPE_L2_PAYLOAD)
-#else
+
#define I40E_VALID_PCTYPE(pctype) \
((pctype) == I40E_FILTER_PCTYPE_FRAG_IPV4 || \
(pctype) == I40E_FILTER_PCTYPE_NONF_IPV4_TCP || \
@@ -755,7 +740,6 @@ i40e_calc_itr_interval(int16_t interval)
(pctype) == I40E_FILTER_PCTYPE_NONF_IPV6_SCTP || \
(pctype) == I40E_FILTER_PCTYPE_NONF_IPV6_OTHER || \
(pctype) == I40E_FILTER_PCTYPE_L2_PAYLOAD)
-#endif
#define I40E_PHY_TYPE_SUPPORT_40G(phy_type) \
(((phy_type) & I40E_CAP_PHY_TYPE_40GBASE_KR4) || \
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 8eb68a3..4b835cb 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -2548,8 +2548,11 @@ i40evf_hw_rss_hash_set(struct i40e_vf *vf, struct rte_eth_rss_conf *rss_conf)
rss_hf = rss_conf->rss_hf;
hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_VFQF_HENA(0));
hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_VFQF_HENA(1))) << 32;
- hena &= ~I40E_RSS_HENA_ALL;
- hena |= i40e_config_hena(rss_hf);
+ if (hw->mac.type == I40E_MAC_X722)
+ hena &= ~I40E_RSS_HENA_ALL_X722;
+ else
+ hena &= ~I40E_RSS_HENA_ALL;
+ hena |= i40e_config_hena(rss_hf, hw->mac.type);
i40e_write_rx_ctl(hw, I40E_VFQF_HENA(0), (uint32_t)hena);
i40e_write_rx_ctl(hw, I40E_VFQF_HENA(1), (uint32_t)(hena >> 32));
I40EVF_WRITE_FLUSH(hw);
@@ -2565,7 +2568,10 @@ i40evf_disable_rss(struct i40e_vf *vf)
hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_VFQF_HENA(0));
hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_VFQF_HENA(1))) << 32;
- hena &= ~I40E_RSS_HENA_ALL;
+ if (hw->mac.type == I40E_MAC_X722)
+ hena &= ~I40E_RSS_HENA_ALL_X722;
+ else
+ hena &= ~I40E_RSS_HENA_ALL;
i40e_write_rx_ctl(hw, I40E_VFQF_HENA(0), (uint32_t)hena);
i40e_write_rx_ctl(hw, I40E_VFQF_HENA(1), (uint32_t)(hena >> 32));
I40EVF_WRITE_FLUSH(hw);
@@ -2626,7 +2632,9 @@ i40evf_dev_rss_hash_update(struct rte_eth_dev *dev,
hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_VFQF_HENA(0));
hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_VFQF_HENA(1))) << 32;
- if (!(hena & I40E_RSS_HENA_ALL)) { /* RSS disabled */
+ if (!(hena & ((hw->mac.type == I40E_MAC_X722)
+ ? I40E_RSS_HENA_ALL_X722
+ : I40E_RSS_HENA_ALL))) { /* RSS disabled */
if (rss_hf != 0) /* Enable RSS */
return -EINVAL;
return 0;
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index 5a737ab..335bf15 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -353,8 +353,15 @@ i40e_init_flx_pld(struct i40e_pf *pf)
/* initialize the masks */
for (pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
pctype <= I40E_FILTER_PCTYPE_L2_PAYLOAD; pctype++) {
- if (!I40E_VALID_PCTYPE((enum i40e_filter_pctype)pctype))
- continue;
+ if (hw->mac.type == I40E_MAC_X722) {
+ if (!I40E_VALID_PCTYPE_X722(
+ (enum i40e_filter_pctype)pctype))
+ continue;
+ } else {
+ if (!I40E_VALID_PCTYPE(
+ (enum i40e_filter_pctype)pctype))
+ continue;
+ }
pf->fdir.flex_mask[pctype].word_mask = 0;
i40e_write_rx_ctl(hw, I40E_PRTQF_FD_FLXINSET(pctype), 0);
for (i = 0; i < I40E_FDIR_BITMASK_NUM_WORD; i++) {
@@ -664,14 +671,16 @@ i40e_fdir_configure(struct rte_eth_dev *dev)
i40e_set_flx_pld_cfg(pf, &conf->flex_set[i]);
/* configure flex mask*/
for (i = 0; i < conf->nb_flexmasks; i++) {
-#ifdef X722_SUPPORT
- /* get translated pctype value in fd pctype register */
- pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl(hw,
- I40E_GLQF_FD_PCTYPES((int)i40e_flowtype_to_pctype(
- conf->flex_mask[i].flow_type)));
-#else
- pctype = i40e_flowtype_to_pctype(conf->flex_mask[i].flow_type);
-#endif
+ if (hw->mac.type == I40E_MAC_X722) {
+ /* get translated pctype value in fd pctype register */
+ pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl(
+ hw, I40E_GLQF_FD_PCTYPES(
+ (int)i40e_flowtype_to_pctype(
+ conf->flex_mask[i].flow_type)));
+ } else
+ pctype = i40e_flowtype_to_pctype(
+ conf->flex_mask[i].flow_type);
+
i40e_set_flex_mask_on_pctype(pf, pctype, &conf->flex_mask[i]);
}
@@ -1053,14 +1062,14 @@ i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
return ret;
}
-#ifdef X722_SUPPORT
- /* get translated pctype value in fd pctype register */
- pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl(hw,
- I40E_GLQF_FD_PCTYPES((int)i40e_flowtype_to_pctype(
- filter->input.flow_type)));
-#else
- pctype = i40e_flowtype_to_pctype(filter->input.flow_type);
-#endif
+ if (hw->mac.type == I40E_MAC_X722) {
+ /* get translated pctype value in fd pctype register */
+ pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl(
+ hw, I40E_GLQF_FD_PCTYPES(
+ (int)i40e_flowtype_to_pctype(
+ filter->input.flow_type)));
+ } else
+ pctype = i40e_flowtype_to_pctype(filter->input.flow_type);
ret = i40e_fdir_filter_programming(pf, pctype, filter, add);
if (ret < 0) {
@@ -1290,6 +1299,7 @@ i40e_fdir_info_get_flex_mask(struct i40e_pf *pf,
{
struct i40e_fdir_flex_mask *mask;
struct rte_eth_fdir_flex_mask *ptr = flex_mask;
+ struct i40e_hw *hw = I40E_PF_TO_HW(pf);
uint16_t flow_type;
uint8_t i, j;
uint16_t off_bytes, mask_tmp;
@@ -1298,8 +1308,13 @@ i40e_fdir_info_get_flex_mask(struct i40e_pf *pf,
i <= I40E_FILTER_PCTYPE_L2_PAYLOAD;
i++) {
mask = &pf->fdir.flex_mask[i];
- if (!I40E_VALID_PCTYPE((enum i40e_filter_pctype)i))
- continue;
+ if (hw->mac.type == I40E_MAC_X722) {
+ if (!I40E_VALID_PCTYPE_X722((enum i40e_filter_pctype)i))
+ continue;
+ } else {
+ if (!I40E_VALID_PCTYPE((enum i40e_filter_pctype)i))
+ continue;
+ }
flow_type = i40e_pctype_to_flowtype((enum i40e_filter_pctype)i);
for (j = 0; j < I40E_FDIR_MAX_FLEXWORD_NUM; j++) {
if (mask->word_mask & I40E_FLEX_WORD_MASK(j)) {
--
1.9.3
^ permalink raw reply related
* Re: [PATCH] net/i40e: fix the hash filter invalid calculation in X722
From: Guo, Jia @ 2016-10-25 2:11 UTC (permalink / raw)
To: Wu, Jingjing, Zhang, Helin; +Cc: dev@dpdk.org, Yigit, Ferruh
In-Reply-To: <9BB6961774997848B5B42BEC655768F80E293A6B@SHSMSX103.ccr.corp.intel.com>
I will refine the commit log. Other hand, since the issue is not directly related with prior patch, it just because some nic type adding request some special behavior handle. So it is reported issue fix, but may be have not corresponding fix line. Thanks jingjing's review.
Best regards,
Jeff Guo
-----Original Message-----
From: Wu, Jingjing
Sent: Monday, October 24, 2016 5:10 PM
To: Guo, Jia <jia.guo@intel.com>; Zhang, Helin <helin.zhang@intel.com>
Cc: dev@dpdk.org; Yigit, Ferruh <ferruh.yigit@intel.com>
Subject: RE: [PATCH] net/i40e: fix the hash filter invalid calculation in X722
> -----Original Message-----
> From: Guo, Jia
> Sent: Thursday, October 20, 2016 10:49 AM
> To: Zhang, Helin <helin.zhang@intel.com>; Wu, Jingjing
> <jingjing.wu@intel.com>
> Cc: dev@dpdk.org; Guo, Jia <jia.guo@intel.com>; Yigit, Ferruh
> <ferruh.yigit@intel.com>
> Subject: [PATCH] net/i40e: fix the hash filter invalid calculation in
> X722
>
> As X722 extracts IPv4 header to Field Vector different with
> XL710/X710, need to corresponding to modify the fields of IPv4 header
> in input set to map different default Field Vector Table of different NICs.
> Signed-off-by: Jeff Guo <jia.guo@intel.com>
> ---
> v3:
> remove the x722 macro
> v2:
> fix compile error when x722 macro is not defined and simplify the code
> to avoid duplication.
> ---
> drivers/net/i40e/i40e_ethdev.c | 60
> +++++++++++++++++++++++++++++++++---------
> 1 file changed, 47 insertions(+), 13 deletions(-)
>
How about change the commit log it like:
When verifying the Hash filtering on X722, we found the behavior was not expected. For example, the hash value in descriptor is incorrect.
That was because X722 uses different way of hash key word selection comparing with X710/XL710.
This patch fixes it by setting X722 specific key selection.
And few minor comments:
If this is not the first patch, please use [PATCH v3] instead of [PATCH].
And the fixes line is missed.
Thanks
Jingijng
^ permalink raw reply
* Re: rte_kni_tx_burst() hangs because of no freedescriptors
From: Zhang, Helin @ 2016-10-25 1:05 UTC (permalink / raw)
To: yingzhi; +Cc: dev@dpdk.org
In-Reply-To: <tencent_4FBAF506586D43D55053A9AA@qq.com>
From: yingzhi [mailto:kaitoy@qq.com]
Sent: Monday, October 24, 2016 6:39 PM
To: Zhang, Helin
Cc: dev@dpdk.org
Subject: Re: RE: [dpdk-dev] rte_kni_tx_burst() hangs because of no freedescriptors
Hi Helin,
Thanks for your response, to answer your questions:
1. we send only one packet each time calling rte_kni_tx_burst(), which means the last argument is 1.
2. it returns 0 because the free mbuf function inside tx_burst will not free any mbuf:
if (txq->nb_tx_free < txq->tx_free_thresh)
ixgbe_tx_free_bufs(txq);
after this operation, the txq->nb_tx_free is not increased and keeps to be "0" eventually.
I did some tests today, I commented out this section of ixgbe_rxtx_vec_common.h -> ixgbe_tx_free_bufs
status = txq->tx_ring[txq->tx_next_dd].wb.status;
if (!(status & IXGBE_ADVTXD_STAT_DD))
return 0;
After ignoring DD bit check, our app runs for about 6 hours without issue. I suspect there is something wrong in my program set the DD bit somewhere. One of the possible cause currently I suspect is as far as I know, rte_pktmbuf_free(mbuf.array[k]) will free the mbuf of the packet and any fragmented packets following by it. But in our application such as below code snippet:
auto nb_tx = rte_eth_tx_burst(port, queue, mbuf.array, (uint16_t) nb_rx);
if (unlikely(nb_tx < nb_rx)) {
for (unsigned k = nb_tx; k < nb_rx; k++) {
rte_pktmbuf_free(mbuf.array[k]);
}
}
[Zhang, Helin] it seems above code piece has memory leak, if the buffer is chained. After all memory leaked, then the issue comes. Please try to check if this is the root cause!
In this case if there are fragmented packets and failed transmission, may cause a mbuf be freed multiple times.
Above is just my suspect, need to do some tests later today or tomorrow.
Thanks
------------------ Original ------------------
From: "Zhang, Helin";<helin.zhang@intel.com>;
Date: Mon, Oct 24, 2016 11:33 AM
To: "yingzhi"<kaitoy@qq.com>;
Cc: "dev@dpdk.org"<dev@dpdk.org>;
Subject: RE: [dpdk-dev] rte_kni_tx_burst() hangs because of no freedescriptors
Hi Yingzhi
Thank you for the reporting! The description is not so clear at least for me.
Please help to narrown down the issue by youself.
How many packets would it have for calling TX function?
Why it would return 0 after calling TX function? No memory? Or return from else? Have you found anything?
Regards,
Helin
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org]<mailto:[mailto:dev-bounces@dpdk.org]> On Behalf Of yingzhi
> Sent: Sunday, October 23, 2016 9:30 PM
> To: users; dev@dpdk.org<mailto:dev@dpdk.org>
> Subject: [dpdk-dev] rte_kni_tx_burst() hangs because of no free descriptors
>
> -
> Hi Experts,
>
> Background:
>
> We are using DPDK to develop a LoadBalancer following below logic: When
> a new packet is received:
> 1. if the dst_addr is management IP, forward to KNI. 2. if the dst_addr is in
> VIP list, select backend and forward(modify dst mac address). 3. otherwise
> drop the packet.
>
> At this stage, we use one single thread for KNI forwarding and another for
> VIP forwarding(forward to eth).
>
> DPDK version: 16.07
> NIC: 82599ES 10-Gigabit SFI/SFP+ Network Connection
> Linux: 14.04.1-Ubuntu x64
>
> Promblem description:
>
> The program runs correctly for sometime(around 2 hours for 400Mb traffic).
> But it it will hang. When problem happens, rte_eth_tx_burst() will not able to
> send out any packets(always returns 0). We tracked into that function and
> noticed it is actually calling ixgbe driver's ixgbe_xmit_pkts_vec() function in
> our environment, because we use default tx queue configuration, after
> printing some info, we found if the free function works fine:
> tx_rs_thresh: 32, tx_free_thresh: 32, nb_tx_free: 31
>
> it will trigger free and make 32 more free descriptors:
> tx_rs_thresh: 32, tx_free_thresh: 32, nb_tx_free: 62
>
> but when something going wrong, it will no longer free anything:
> tx_rs_thresh: 32, tx_free_thresh: 32, nb_tx_free: 0 tx_rs_thresh: 32,
> tx_free_thresh: 32, nb_tx_free: 0
>
> It may related with the DD flag of the descriptor but we are not quite sure.
>
> Our program logic:
>
> create two mbuf pools on socket 0, one for rx_queue and one for kni. (all
> lcore threads runs on socket0)
>
> init kni interface with rte_kni_alloc()
>
>
> init one NIC interface with
> rte_eth_dev_configure(); rte_eth_rx_queue_setup();
> rte_eth_tx_queue_setup(); rte_eth_dev_start();
>
>
>
> in the eth main loop: (code is simplified)
> while(1) { n = rte_eth_rx_burst(packets); for (i = 0; i < n; ++i) { if
> (SEND_TO_KNI) { m = rte_kni_tx_burst(packets[i]); if (m != 1))
> { rte_pktmbuf_free(packets[i]); } } if (SEND_TO_ETH)
> { // after modify the packet m = rte_eth_tx_burst(packets[i]);
> if (m != 1)) { rte_pktmbuf_free(packets[i]); } } //
> otherwise drop the packet rte_pktmbuf_free(packets[i]); } }
>
>
> Please advise if I'm using DPDK in a wrong way. Sorry if I missed something
> basic, I'm new to DPDK.
>
> Thanks in advance
> Best regards
^ permalink raw reply
* Re: [PATCH v5 0/2] net/ixgbe: VMDq DCB with SRIOV
From: Lu, Wenzhuo @ 2016-10-25 0:31 UTC (permalink / raw)
To: Iremonger, Bernard, dev@dpdk.org, Shah, Rahul R
In-Reply-To: <1476872471-23362-1-git-send-email-bernard.iremonger@intel.com>
Hi,
> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Wednesday, October 19, 2016 6:21 PM
> To: dev@dpdk.org; Shah, Rahul R; Lu, Wenzhuo
> Cc: Iremonger, Bernard
> Subject: [PATCH v5 0/2] net/ixgbe: VMDq DCB with SRIOV
>
> Changes in v5:
> fix enable/disable of the QDE bit in the PFQDE register.
>
> Changes in v4:
> changes to ixgbe patch following comments.
>
> Changes in v3:
> rebase to latest master.
> update commit message for ixgbe patch
> add testpmd patch.
>
> Changes in v2:
> rebase to latest master.
>
> Bernard Iremonger (2):
> net/ixgbe: support multiqueue mode VMDq DCB with SRIOV
> app/test_pmd: fix DCB configuration
>
> app/test-pmd/testpmd.c | 4 ++--
> drivers/net/ixgbe/ixgbe_ethdev.c | 11 ++++++-----
> drivers/net/ixgbe/ixgbe_rxtx.c | 35 ++++++++++++++++++++++-------------
> 3 files changed, 30 insertions(+), 20 deletions(-)
>
> --
> 2.10.1
Series-Acked-by: Wenzhuo Lu <Wenzhuo.lu@intel.com>
^ permalink raw reply
* Re: mbuf changes
From: Morten Brørup @ 2016-10-24 21:47 UTC (permalink / raw)
To: Bruce Richardson, Wiles, Keith; +Cc: dev, Olivier Matz
In-Reply-To: <20161024162538.GA34988@bricha3-MOBL3.ger.corp.intel.com>
Comments inline.
Med venlig hilsen / kind regards
- Morten Brørup
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Bruce Richardson
> Sent: Monday, October 24, 2016 6:26 PM
> To: Wiles, Keith
> Cc: Morten Brørup; dev@dpdk.org; Olivier Matz
> Subject: Re: [dpdk-dev] mbuf changes
>
> On Mon, Oct 24, 2016 at 04:11:33PM +0000, Wiles, Keith wrote:
> >
> > > On Oct 24, 2016, at 10:49 AM, Morten Brørup <mb@smartsharesystems.com>
> wrote:
> > >
> > > First of all: Thanks for a great DPDK Userspace 2016!
> > >
> > >
> > >
> > > Continuing the Userspace discussion about Olivier Matz’s proposed mbuf
> changes...
>
> Thanks for keeping the discussion going!
> > >
> > >
> > >
> > > 1.
> > >
> > > Stephen Hemminger had a noteworthy general comment about keeping
> metadata for the NIC in the appropriate section of the mbuf: Metadata
> generated by the NIC’s RX handler belongs in the first cache line, and
> metadata required by the NIC’s TX handler belongs in the second cache line.
> This also means that touching the second cache line on ingress should be
> avoided if possible; and Bruce Richardson mentioned that for this reason m-
> >next was zeroed on free().
> > >
> Thinking about it, I suspect there are more fields we can reset on free
> to save time on alloc. Refcnt, as discussed below is one of them, but so
> too could be the nb_segs field and possibly others.
Yes. Consider the use of rte_pktmbuf_reset() or add a rte_pktmbuf_prealloc() for this purpose.
> > > 2.
> > >
> > > There seemed to be consensus that the size of m->refcnt should match
> the size of m->port because a packet could be duplicated on all physical
> ports for L3 multicast and L2 flooding.
> > >
> > > Furthermore, although a single physical machine (i.e. a single server)
> with 255 physical ports probably doesn’t exist, it might contain more than
> 255 virtual machines with a virtual port each, so it makes sense extending
> these mbuf fields from 8 to 16 bits.
> >
> > I thought we also talked about removing the m->port from the mbuf as it
> is not really needed.
> >
> Yes, this was mentioned, and also the option of moving the port value to
> the second cacheline, but it appears that NXP are using the port value
> in their NIC drivers for passing in metadata, so we'd need their
> agreement on any move (or removal).
>
If a single driver instance services multiple ports, so the ports are not polled individually, the m->port member will be required to identify the port. In that case, it might also used elsewhere in the ingress path, and thus appropriate having in the first cache line. So yes, this needs further discussion with NXP.
> > > 3.
> > >
> > > Someone (Bruce Richardson?) suggested moving m->refcnt and m->port to
> the second cache line, which then generated questions from the audience
> about the real life purpose of m->port, and if m->port could be removed
> from the mbuf structure.
> > >
> > >
> > >
> > > 4.
> > >
> > > I suggested using offset -1 for m->refcnt, so m->refcnt becomes 0 on
> first allocation. This is based on the assumption that other mbuf fields
> must be zeroed at alloc()/free() anyway, so zeroing m->refcnt is cheaper
> than setting it to 1.
> > >
> > > Furthermore (regardless of m->refcnt offset), I suggested that it is
> not required to modify m->refcnt when allocating and freeing the mbuf, thus
> saving one write operation on both alloc() and free(). However, this
> assumes that m->refcnt debugging, e.g. underrun detection, is not required.
>
> I don't think it really matters what sentinal value is used for the
> refcnt because it can't be blindly assigned on free like other fields.
> However, I think 0 as first reference value becomes more awkward
> than 1, because we need to deal with underflow. Consider the situation
> where we have two references to the mbuf, so refcnt is 1, and both are
> freed at the same time. Since the refcnt is not-zero, then both cores
> will do an atomic decrement simultaneously giving a refcnt of -1. We can
> then set this back to zero before freeing, however, I'd still prefer to
> have refcnt be an accurate value so that it always stays positive, and
> we can still set it to "one" on free to avoid having to set on alloc.
>
Good example. It explains very clearly why my suggested optimization is tricky. My optimization is targeting the most likely scenario where m->refcnt is only "one", but at the expense of some added complexity for the unlikely scenarios. (I only suggested 0 as "one" because I assumed the value could be zeroed faster than set to 1, so forget about that, if you like.)
I still argue that if we keep m->refcnt at "one" value while in the free pool, a write operation can be avoided at both free() and alloc(). Here is a conceptual example (using m->refcnt==1 for "one"):
void __rte_mbuf_raw_free(struct rte_mbuf *m)
{
RTE_ASSERT(rte_mbuf_refcnt_read(m) == 1);
rte_mempool_put(m->pool, m);
}
void __rte_pktmbuf_free_seg_inner(struct rte_mbuf *m)
{
/* if this is an indirect mbuf, it is detached. */
if (RTE_MBUF_INDIRECT(m))
rte_pktmbuf_detach(m);
m->next = NULL; /* Preload to avoid setting in alloc(). */
__rte_mbuf_raw_free(m);
}
void rte_pktmbuf_free_seg(struct rte_mbuf *m)
{
if (likely(rte_mbuf_refcnt_read(m) == 1)) {
/* We have the last reference, so we return it to the free pool. */
__rte_pktmbuf_free_seg_inner(m);
} else {
/* More references, so decrement the refcnt. */
if (unlikely(rte_mbuf_refcnt_update(m, -1) == 0)) {
/* Someone raced to decrement the refcnt before us,
so now we have the last reference,
so we return it to the free pool. */
rte_mbuf_refcnt_set(m, 1); /* Preload to avoid in alloc(). */
__rte_pktmbuf_free_seg_inner(m);
}
}
}
> Also, if we set refcnt on free rather than alloc, it does set itself up
> as a good candidate for moving to the second cacheline. Fast-path
> processing does not normally update the value.
>
Agreed. But also consider that TX handling should be optimized too. And this includes free() processing and preloading values for alloc(); this should only be done in free() instead of alloc() if it provides a total performance improvement. We should not improve RX handling performance if the TX handling performance decreases much more.
> > > 5.
> > >
> > > And here’s something new to think about:
> > >
> > > m->next already reveals if there are more segments to a packet. Which
> purpose does m->nb_segs serve that is not already covered by m->next?
>
> It is duplicate info, but nb_segs can be used to check the validity of
> the next pointer without having to read the second mbuf cacheline.
>
> Whether it's worth having is something I'm happy enough to discuss,
> though.
If anybody needs to check for additional segments (m->next != NULL) without hitting the second cache line, a single bit in the first cache line will suffice. (If this is a common case, they probably need to read the m->next value anyway, and then it would optimally belong in the first cache line. I am just mentioning this. It's not my preference.)
> One other point I'll mention is that we need to have a discussion on
> how/where to add in a timestamp value into the mbuf. Personally, I think
> it can be in a union with the sequence number value, but I also suspect
> that 32-bits of a timestamp is not going to be enough for many.
>
> Thoughts?
Speaking for myself, a high resolution RX timestamp is "nice to have", so I like it, but I would hate to sacrifice the sequence number for it. Generally, I would assume that the sequence number used for reordering is more important than a timestamp, except for applications dealing with timing measurements or high precision packet capturing.
Conversion of timestamps from one unit to another can be relatively expensive, so I recommend keeping timestamps in whatever resolution the NIC hardware provides, leaving the conversion to e.g. nanoseconds up to the applications that use timestamps. A lot of protocols use opaque timestamps, e.g. RTP, so this would not be exceptional. Since the timestamp belongs in the first cache line, I suggest we limit it to 32 bit. This can be the least significant 32 bit of a 64 bit NIC hardware timestamp, leaving it up to the application to keep track of the most significant 32 bit by some other means. If it's counting nanoseconds, 32 bit can hold 4 seconds.
>
> /Bruce
^ permalink raw reply
* Re: why all the other threads except lcore-slave pinned to master lcore?
From: Kevin Traynor @ 2016-10-24 18:25 UTC (permalink / raw)
To: ychen, dev
In-Reply-To: <6ae27513.10577.157f6622474.Coremail.ychen103103@163.com>
On 10/24/2016 12:10 PM, ychen wrote:
> Hi, I am a freshman learning DPDK, when I followed the document INSTALL.DPDK.md to launch openvswitch with dpdk inited, I found that all the threads are pinned to master lcore except lcore-slave and vfio-sync, but I can not find any code to set the affinity for these threads.
> Here is my question:
> 1. why vfio-sync is pinned to a core which is not included in the slave lcore nor master lcore?
> 2. why all other threads pinned to master lcore? is anything I am setting wrong?
Hi - these are probably more appropriate for the ovs-dev list. I
answered the post you put over there.
>
>
> Here is some logs:
> 2016-10-24T10:42:03Z|00001|vlog|INFO|opened log file /var/log/openvswitch/ovs-vswitchd.log
> 2016-10-24T10:42:03Z|00002|ovs_numa|INFO|Discovered 24 CPU cores on NUMA node 0
> 2016-10-24T10:42:03Z|00003|ovs_numa|INFO|Discovered 24 CPU cores on NUMA node 1
> 2016-10-24T10:42:03Z|00004|ovs_numa|INFO|Discovered 2 NUMA nodes and 48 CPU cores
> 2016-10-24T10:42:03Z|00005|reconnect|INFO|unix:/var/run/openvswitch/db.sock: connecting...
> 2016-10-24T10:42:03Z|00006|reconnect|INFO|unix:/var/run/openvswitch/db.sock: connected
> 2016-10-24T10:42:03Z|00007|dpdk|INFO|DPDK Enabled, initializing
> 2016-10-24T10:42:03Z|00008|dpdk|INFO|No vhost-sock-dir provided - defaulting to /var/run/openvswitch
> 2016-10-24T10:42:03Z|00009|dpdk|INFO|EAL ARGS: ovs-vswitchd -c 0xf --socket-mem 1024,1024
> EAL: Detected 48 lcore(s)
> EAL: Probing VFIO support...
> EAL: VFIO support initialized
> PMD: bnxt_rte_pmd_init() called for (null)
> EAL: PCI device 0000:01:00.0 on NUMA socket 0
> EAL: probe driver: 8086:10fb rte_ixgbe_pmd
> EAL: PCI device 0000:01:00.1 on NUMA socket 0
> EAL: probe driver: 8086:10fb rte_ixgbe_pmd
> EAL: PCI device 0000:06:00.0 on NUMA socket 0
> EAL: probe driver: 8086:1521 rte_igb_pmd
> EAL: PCI device 0000:06:00.1 on NUMA socket 0
> EAL: probe driver: 8086:1521 rte_igb_pmd
> 2016-10-24T10:42:06Z|00010|dpdk|INFO|DPDK pdump packet capture enable
>
>
> and the output of the cpu_layout:
> cores = [0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13]
> sockets = [0, 1]
>
>
> Socket 0 Socket 1
> -------- --------
> Core 0 [0, 24] [1, 25]
> Core 1 [2, 26] [3, 27]
> Core 2 [4, 28] [5, 29]
> Core 3 [6, 30] [7, 31]
> Core 4 [8, 32] [9, 33]
> Core 5 [10, 34] [11, 35]
> Core 8 [12, 36] [13, 37]
> Core 9 [14, 38] [15, 39]
> Core 10 [16, 40] [17, 41]
> Core 11 [18, 42] [19, 43]
> Core 12 [20, 44] [21, 45]
> Core 13 [22, 46] [23, 47]
> All the threads and their pinned core for vswitchd:
> 28262 28262 0 ovs-vswitchd
> 28263 28262 39 vfio-sync
> 28297 28262 0 eal-intr-thread
> 28298 28262 1 lcore-slave-1
> 28299 28262 2 lcore-slave-2
> 28300 28262 3 lcore-slave-3
> 28301 28262 0 dpdk_watchdog2
> 28302 28262 0 vhost_thread1
> 28303 28262 0 pdump-thread
> 28304 28262 0 ct_clean3
> 28305 28262 0 urcu4
> 28744 28262 0 handler101
> 28745 28262 0 handler100
> 28746 28262 0 handler99
> 28747 28262 0 handler98
> 28748 28262 0 handler95
> 28749 28262 0 handler77
> 28750 28262 0 handler79
> 28751 28262 0 handler80
> 28752 28262 0 handler81
> 28753 28262 0 handler73
> 28756 28262 0 handler92
> 28757 28262 0 handler82
> 28758 28262 0 handler96
> 28759 28262 0 handler71
> 28760 28262 0 handler61
> 28761 28262 0 handler62
> 28762 28262 0 handler83
> 28763 28262 0 handler63
> 28764 28262 0 handler84
> 28765 28262 0 handler93
> 28766 28262 0 handler64
> 28767 28262 0 handler85
> 28768 28262 0 handler74
> 28769 28262 0 handler65
> 28770 28262 0 handler66
> 28771 28262 0 handler78
> 28772 28262 0 handler86
> 28773 28262 0 handler87
> 28774 28262 0 handler97
> 28775 28262 0 handler88
> 28776 28262 0 handler56
> 28777 28262 0 handler76
> 28778 28262 0 handler67
> 28779 28262 0 handler60
> 28780 28262 0 handler68
> 28781 28262 0 revalidator75
> 28782 28262 0 revalidator57
> 28783 28262 0 revalidator89
> 28784 28262 0 revalidator69
> 28785 28262 0 revalidator54
> 28786 28262 0 revalidator90
> 28787 28262 0 revalidator55
> 28788 28262 0 revalidator58
> 28789 28262 0 revalidator59
> 28790 28262 0 revalidator70
> 28791 28262 0 revalidator94
> 28792 28262 0 revalidator91
> 28793 28262 0 revalidator72
> 28827 28262 4 pmd103
> 28829 28262 6 pmd102
>
^ permalink raw reply
* PCIe Hot Insert/Remove Support
From: Walker, Benjamin @ 2016-10-24 18:16 UTC (permalink / raw)
To: dev@dpdk.org
Hi all,
My name is Ben Walker and I'm the technical lead for SPDK (it's like DPDK, but
for storage devices). SPDK relies on DPDK only for the base functionality in the
EAL - memory management, the rings, and the PCI scanning code. A key feature for
storage devices is support for hot insert and remove, so we're currently working
through how best to implement this for a user space driver. While doing this
work, we've run into a few issues with the current DPDK PCI/device/driver
framework that I'd like to discuss with this list. I'm not entirely ramped up on
all of the current activity in this area or what the future plans are, so please
educate me if something is coming that will address our current issues. I'm
working off of the latest commit on the master branch as of today.
Today, there appears to be two lists - one of PCI devices and one of drivers. To
update the list of PCI devices, you call rte_eal_pci_scan(), which scans the PCI
bus. That call does not attempt to load any drivers. One scan is automatically
performed when the eal is first initialized. To add or remove drivers from the
driver list you call rte_eal_driver_register/unregister. To match drivers in the
driver list to devices in the device list, you call rte_eal_pci_probe.
There are a few problems with how the code works for us. First,
rte_eal_pci_scan's algorithm will not correctly detect devices that are in its
internal list but weren't found by the most recent PCI bus scan (i.e. they were
hot removed). DPDK's scan doesn't seem to comprehend hot remove in any way.
Fortunately there is a public API to remove devices from the device list -
rte_eal_pci_detach. That function will automatically unload any drivers
associated with the device and then remove it from the list. There is a similar
call for adding a device to the list - rte_eal_pci_probe_one, which will add a
device to the device list and then automatically match it to drivers. I think if
rte_eal_pci_scan is going to be a public interface (and it is), it needs to
correctly comprehend the removal of PCI devices. Otherwise, make it a private
API that is only called in response to rte_eal_init and only expose the public
probe_one/detach calls for modifying the list of devices. My preference is for
the former, not the latter.
Second, rte_eal_pci_probe will call the driver initialization functions each
time a probe happens, even if the driver has already been successfully loaded.
This tends to crash a lot of the PMDs. It seems to me like rte_eal_pci_probe is
not safe to call more than once during the lifetime of the program, which is a
real challenge when you have multiple users of the PCI framework. For instance,
an application may manage both storage devices using the rte_eal_pci framework
and NICs, and the initialization routine may go something like:
register NIC drivers
rte_eal_probe()
...
register SSD drivers
rte_eal_probe()
This is almost certainly how any real code is going to function because the code
dealing with NICs is unrelated and probably unaware of the code dealing with the
SSDs. It should be fairly trivial to simply not call the probe() callback for a
device if the driver has already been loaded. Is this a reasonable modification
to make?
Thanks,
Ben
^ permalink raw reply
* Re: [PATCH v2 1/3] drivers: add name alias registration for rte_driver
From: Yuanhan Liu @ 2016-10-24 17:41 UTC (permalink / raw)
To: Jan Blunck
Cc: dev, pablo.de.lara.guarch, thomas.monjalon, john.mcnamara,
maxime.coquelin
In-Reply-To: <1477326143-4571-1-git-send-email-jblunck@infradead.org>
On Mon, Oct 24, 2016 at 12:22:21PM -0400, Jan Blunck wrote:
> This adds infrastructure for drivers to allow being requested by an alias
> so that a renamed driver can still get loaded by its legacy name.
>
> Signed-off-by: Jan Blunck <jblunck@infradead.org>
> Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
> Tested-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
Series Reviewed-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
--yliu
^ permalink raw reply
* Re: [PATCH v10 0/6] add Tx preparation
From: Ananyev, Konstantin @ 2016-10-24 17:26 UTC (permalink / raw)
To: Kulasek, TomaszX, dev@dpdk.org; +Cc: olivier.matz@6wind.com
In-Reply-To: <1477327917-18564-1-git-send-email-tomaszx.kulasek@intel.com>
>
> As discussed in that thread:
>
> http://dpdk.org/ml/archives/dev/2015-September/023603.html
>
> Different NIC models depending on HW offload requested might impose
> different requirements on packets to be TX-ed in terms of:
>
> - Max number of fragments per packet allowed
> - Max number of fragments per TSO segments
> - The way pseudo-header checksum should be pre-calculated
> - L3/L4 header fields filling
> - etc.
>
>
> MOTIVATION:
> -----------
>
> 1) Some work cannot (and didn't should) be done in rte_eth_tx_burst.
> However, this work is sometimes required, and now, it's an
> application issue.
>
> 2) Different hardware may have different requirements for TX offloads,
> other subset can be supported and so on.
>
> 3) Some parameters (e.g. number of segments in ixgbe driver) may hung
> device. These parameters may be vary for different devices.
>
> For example i40e HW allows 8 fragments per packet, but that is after
> TSO segmentation. While ixgbe has a 38-fragment pre-TSO limit.
>
> 4) Fields in packet may require different initialization (like e.g. will
> require pseudo-header checksum precalculation, sometimes in a
> different way depending on packet type, and so on). Now application
> needs to care about it.
>
> 5) Using additional API (rte_eth_tx_prep) before rte_eth_tx_burst let to
> prepare packet burst in acceptable form for specific device.
>
> 6) Some additional checks may be done in debug mode keeping tx_burst
> implementation clean.
>
>
> PROPOSAL:
> ---------
>
> To help user to deal with all these varieties we propose to:
>
> 1) Introduce rte_eth_tx_prep() function to do necessary preparations of
> packet burst to be safely transmitted on device for desired HW
> offloads (set/reset checksum field according to the hardware
> requirements) and check HW constraints (number of segments per
> packet, etc).
>
> While the limitations and requirements may differ for devices, it
> requires to extend rte_eth_dev structure with new function pointer
> "tx_pkt_prep" which can be implemented in the driver to prepare and
> verify packets, in devices specific way, before burst, what should to
> prevent application to send malformed packets.
>
> 2) Also new fields will be introduced in rte_eth_desc_lim:
> nb_seg_max and nb_mtu_seg_max, providing an information about max
> segments in TSO and non-TSO packets acceptable by device.
>
> This information is useful for application to not create/limit
> malicious packet.
>
>
> APPLICATION (CASE OF USE):
> --------------------------
>
> 1) Application should to initialize burst of packets to send, set
> required tx offload flags and required fields, like l2_len, l3_len,
> l4_len, and tso_segsz
>
> 2) Application passes burst to the rte_eth_tx_prep to check conditions
> required to send packets through the NIC.
>
> 3) The result of rte_eth_tx_prep can be used to send valid packets
> and/or restore invalid if function fails.
>
> e.g.
>
> for (i = 0; i < nb_pkts; i++) {
>
> /* initialize or process packet */
>
> bufs[i]->tso_segsz = 800;
> bufs[i]->ol_flags = PKT_TX_TCP_SEG | PKT_TX_IPV4
> | PKT_TX_IP_CKSUM;
> bufs[i]->l2_len = sizeof(struct ether_hdr);
> bufs[i]->l3_len = sizeof(struct ipv4_hdr);
> bufs[i]->l4_len = sizeof(struct tcp_hdr);
> }
>
> /* Prepare burst of TX packets */
> nb_prep = rte_eth_tx_prep(port, 0, bufs, nb_pkts);
>
> if (nb_prep < nb_pkts) {
> printf("tx_prep failed\n");
>
> /* nb_prep indicates here first invalid packet. rte_eth_tx_prep
> * can be used on remaining packets to find another ones.
> */
>
> }
>
> /* Send burst of TX packets */
> nb_tx = rte_eth_tx_burst(port, 0, bufs, nb_prep);
>
> /* Free any unsent packets. */
>
> v10 changes:
> - moved drivers tx calback check in rte_eth_tx_prep after queue_id check
>
> v9 changes:
> - fixed headers structure fragmentation check
> - moved fragmentation check into rte_validate_tx_offload()
>
> v8 changes:
> - mbuf argument in rte_validate_tx_offload declared as const
>
> v7 changes:
> - comments reworded/added
> - changed errno values returned from Tx prep API
> - added check in rte_phdr_cksum_fix if headers are in the first
> data segment and can be safetly modified
> - moved rte_validate_tx_offload to rte_mbuf
> - moved rte_phdr_cksum_fix to rte_net.h
> - removed rte_pkt.h new file as useless
>
> v6 changes:
> - added performance impact test results to the patch description
>
> v5 changes:
> - rebased csum engine modification
> - added information to the csum engine about performance tests
> - some performance improvements
>
> v4 changes:
> - tx_prep is now set to default behavior (NULL) for simple/vector path
> in fm10k, i40e and ixgbe drivers to increase performance, when
> Tx offloads are not intentionally available
>
> v3 changes:
> - reworked csum testpmd engine instead adding new one,
> - fixed checksum initialization procedure to include also outer
> checksum offloads,
> - some minor formattings and optimalizations
>
> v2 changes:
> - rte_eth_tx_prep() returns number of packets when device doesn't
> support tx_prep functionality,
> - introduced CONFIG_RTE_ETHDEV_TX_PREP allowing to turn off tx_prep
>
> Tomasz Kulasek (6):
> ethdev: add Tx preparation
> e1000: add Tx preparation
> fm10k: add Tx preparation
> i40e: add Tx preparation
> ixgbe: add Tx preparation
> testpmd: use Tx preparation in csum engine
>
> app/test-pmd/csumonly.c | 36 ++++++--------
> config/common_base | 1 +
> drivers/net/e1000/e1000_ethdev.h | 11 +++++
> drivers/net/e1000/em_ethdev.c | 5 +-
> drivers/net/e1000/em_rxtx.c | 48 ++++++++++++++++++-
> drivers/net/e1000/igb_ethdev.c | 4 ++
> drivers/net/e1000/igb_rxtx.c | 52 ++++++++++++++++++++-
> drivers/net/fm10k/fm10k.h | 6 +++
> drivers/net/fm10k/fm10k_ethdev.c | 5 ++
> drivers/net/fm10k/fm10k_rxtx.c | 50 +++++++++++++++++++-
> drivers/net/i40e/i40e_ethdev.c | 3 ++
> drivers/net/i40e/i40e_rxtx.c | 72 +++++++++++++++++++++++++++-
> drivers/net/i40e/i40e_rxtx.h | 8 ++++
> drivers/net/ixgbe/ixgbe_ethdev.c | 3 ++
> drivers/net/ixgbe/ixgbe_ethdev.h | 5 +-
> drivers/net/ixgbe/ixgbe_rxtx.c | 58 ++++++++++++++++++++++-
> drivers/net/ixgbe/ixgbe_rxtx.h | 2 +
> lib/librte_ether/rte_ethdev.h | 96 ++++++++++++++++++++++++++++++++++++++
> lib/librte_mbuf/rte_mbuf.h | 64 +++++++++++++++++++++++++
> lib/librte_net/rte_net.h | 85 +++++++++++++++++++++++++++++++++
> 20 files changed, 584 insertions(+), 30 deletions(-)
>
> --
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> 1.7.9.5
^ permalink raw reply
* [PATCH v10 6/6] testpmd: use Tx preparation in csum engine
From: Tomasz Kulasek @ 2016-10-24 16:51 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, olivier.matz
In-Reply-To: <1477327917-18564-1-git-send-email-tomaszx.kulasek@intel.com>
Removed pseudo header calculation for udp/tcp/tso packets from
application and used Tx preparation API for packet preparation and
verification.
Adding additional step to the csum engine costs about 3-4% of performance
drop, on my setup with ixgbe driver. It's caused mostly by the need
of reaccessing and modification of packet data.
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
app/test-pmd/csumonly.c | 36 +++++++++++++-----------------------
1 file changed, 13 insertions(+), 23 deletions(-)
diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c
index 57e6ae2..6f33ae9 100644
--- a/app/test-pmd/csumonly.c
+++ b/app/test-pmd/csumonly.c
@@ -112,15 +112,6 @@ struct simple_gre_hdr {
} __attribute__((__packed__));
static uint16_t
-get_psd_sum(void *l3_hdr, uint16_t ethertype, uint64_t ol_flags)
-{
- if (ethertype == _htons(ETHER_TYPE_IPv4))
- return rte_ipv4_phdr_cksum(l3_hdr, ol_flags);
- else /* assume ethertype == ETHER_TYPE_IPv6 */
- return rte_ipv6_phdr_cksum(l3_hdr, ol_flags);
-}
-
-static uint16_t
get_udptcp_checksum(void *l3_hdr, void *l4_hdr, uint16_t ethertype)
{
if (ethertype == _htons(ETHER_TYPE_IPv4))
@@ -370,32 +361,24 @@ process_inner_cksums(void *l3_hdr, const struct testpmd_offload_info *info,
/* do not recalculate udp cksum if it was 0 */
if (udp_hdr->dgram_cksum != 0) {
udp_hdr->dgram_cksum = 0;
- if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_UDP_CKSUM) {
+ if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_UDP_CKSUM)
ol_flags |= PKT_TX_UDP_CKSUM;
- udp_hdr->dgram_cksum = get_psd_sum(l3_hdr,
- info->ethertype, ol_flags);
- } else {
+ else
udp_hdr->dgram_cksum =
get_udptcp_checksum(l3_hdr, udp_hdr,
info->ethertype);
- }
}
} else if (info->l4_proto == IPPROTO_TCP) {
tcp_hdr = (struct tcp_hdr *)((char *)l3_hdr + info->l3_len);
tcp_hdr->cksum = 0;
- if (tso_segsz) {
+ if (tso_segsz)
ol_flags |= PKT_TX_TCP_SEG;
- tcp_hdr->cksum = get_psd_sum(l3_hdr, info->ethertype,
- ol_flags);
- } else if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_TCP_CKSUM) {
+ else if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_TCP_CKSUM)
ol_flags |= PKT_TX_TCP_CKSUM;
- tcp_hdr->cksum = get_psd_sum(l3_hdr, info->ethertype,
- ol_flags);
- } else {
+ else
tcp_hdr->cksum =
get_udptcp_checksum(l3_hdr, tcp_hdr,
info->ethertype);
- }
} else if (info->l4_proto == IPPROTO_SCTP) {
sctp_hdr = (struct sctp_hdr *)((char *)l3_hdr + info->l3_len);
sctp_hdr->cksum = 0;
@@ -648,6 +631,7 @@ pkt_burst_checksum_forward(struct fwd_stream *fs)
void *l3_hdr = NULL, *outer_l3_hdr = NULL; /* can be IPv4 or IPv6 */
uint16_t nb_rx;
uint16_t nb_tx;
+ uint16_t nb_prep;
uint16_t i;
uint64_t rx_ol_flags, tx_ol_flags;
uint16_t testpmd_ol_flags;
@@ -857,7 +841,13 @@ pkt_burst_checksum_forward(struct fwd_stream *fs)
printf("\n");
}
}
- nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx);
+ nb_prep = rte_eth_tx_prep(fs->tx_port, fs->tx_queue, pkts_burst,
+ nb_rx);
+ if (nb_prep != nb_rx)
+ printf("Preparing packet burst to transmit failed: %s\n",
+ rte_strerror(rte_errno));
+
+ nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_prep);
/*
* Retry if necessary
*/
--
1.7.9.5
^ permalink raw reply related
* [PATCH v10 5/6] ixgbe: add Tx preparation
From: Tomasz Kulasek @ 2016-10-24 16:51 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, olivier.matz
In-Reply-To: <1477327917-18564-1-git-send-email-tomaszx.kulasek@intel.com>
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
drivers/net/ixgbe/ixgbe_ethdev.c | 3 ++
drivers/net/ixgbe/ixgbe_ethdev.h | 5 +++-
drivers/net/ixgbe/ixgbe_rxtx.c | 58 +++++++++++++++++++++++++++++++++++++-
drivers/net/ixgbe/ixgbe_rxtx.h | 2 ++
4 files changed, 66 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 4ca5747..4c6a8e1 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -517,6 +517,8 @@ static const struct rte_eth_desc_lim tx_desc_lim = {
.nb_max = IXGBE_MAX_RING_DESC,
.nb_min = IXGBE_MIN_RING_DESC,
.nb_align = IXGBE_TXD_ALIGN,
+ .nb_seg_max = IXGBE_TX_MAX_SEG,
+ .nb_mtu_seg_max = IXGBE_TX_MAX_SEG,
};
static const struct eth_dev_ops ixgbe_eth_dev_ops = {
@@ -1103,6 +1105,7 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
eth_dev->dev_ops = &ixgbe_eth_dev_ops;
eth_dev->rx_pkt_burst = &ixgbe_recv_pkts;
eth_dev->tx_pkt_burst = &ixgbe_xmit_pkts;
+ eth_dev->tx_pkt_prep = &ixgbe_prep_pkts;
/*
* For secondary processes, we don't initialise any further as primary
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index 4ff6338..e229cf5 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -396,6 +396,9 @@ uint16_t ixgbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
uint16_t ixgbe_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts,
uint16_t nb_pkts);
+uint16_t ixgbe_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts);
+
int ixgbe_dev_rss_hash_update(struct rte_eth_dev *dev,
struct rte_eth_rss_conf *rss_conf);
diff --git a/drivers/net/ixgbe/ixgbe_rxtx.c b/drivers/net/ixgbe/ixgbe_rxtx.c
index 2ce8234..031414c 100644
--- a/drivers/net/ixgbe/ixgbe_rxtx.c
+++ b/drivers/net/ixgbe/ixgbe_rxtx.c
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
* Copyright 2014 6WIND S.A.
* All rights reserved.
*
@@ -70,6 +70,7 @@
#include <rte_string_fns.h>
#include <rte_errno.h>
#include <rte_ip.h>
+#include <rte_net.h>
#include "ixgbe_logs.h"
#include "base/ixgbe_api.h"
@@ -87,6 +88,9 @@
PKT_TX_TCP_SEG | \
PKT_TX_OUTER_IP_CKSUM)
+#define IXGBE_TX_OFFLOAD_NOTSUP_MASK \
+ (PKT_TX_OFFLOAD_MASK ^ IXGBE_TX_OFFLOAD_MASK)
+
#if 1
#define RTE_PMD_USE_PREFETCH
#endif
@@ -905,6 +909,56 @@ end_of_tx:
/*********************************************************************
*
+ * TX prep functions
+ *
+ **********************************************************************/
+uint16_t
+ixgbe_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+ int i, ret;
+ uint64_t ol_flags;
+ struct rte_mbuf *m;
+ struct ixgbe_tx_queue *txq = (struct ixgbe_tx_queue *)tx_queue;
+
+ for (i = 0; i < nb_pkts; i++) {
+ m = tx_pkts[i];
+ ol_flags = m->ol_flags;
+
+ /**
+ * Check if packet meets requirements for number of segments
+ *
+ * NOTE: for ixgbe it's always (40 - WTHRESH) for both TSO and non-TSO
+ */
+
+ if (m->nb_segs > IXGBE_TX_MAX_SEG - txq->wthresh) {
+ rte_errno = -EINVAL;
+ return i;
+ }
+
+ if (ol_flags & IXGBE_TX_OFFLOAD_NOTSUP_MASK) {
+ rte_errno = -ENOTSUP;
+ return i;
+ }
+
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+ ret = rte_validate_tx_offload(m);
+ if (ret != 0) {
+ rte_errno = ret;
+ return i;
+ }
+#endif
+ ret = rte_phdr_cksum_fix(m);
+ if (ret != 0) {
+ rte_errno = ret;
+ return i;
+ }
+ }
+
+ return i;
+}
+
+/*********************************************************************
+ *
* RX functions
*
**********************************************************************/
@@ -2282,6 +2336,7 @@ ixgbe_set_tx_function(struct rte_eth_dev *dev, struct ixgbe_tx_queue *txq)
if (((txq->txq_flags & IXGBE_SIMPLE_FLAGS) == IXGBE_SIMPLE_FLAGS)
&& (txq->tx_rs_thresh >= RTE_PMD_IXGBE_TX_MAX_BURST)) {
PMD_INIT_LOG(DEBUG, "Using simple tx code path");
+ dev->tx_pkt_prep = NULL;
#ifdef RTE_IXGBE_INC_VECTOR
if (txq->tx_rs_thresh <= RTE_IXGBE_TX_MAX_FREE_BUF_SZ &&
(rte_eal_process_type() != RTE_PROC_PRIMARY ||
@@ -2302,6 +2357,7 @@ ixgbe_set_tx_function(struct rte_eth_dev *dev, struct ixgbe_tx_queue *txq)
(unsigned long)txq->tx_rs_thresh,
(unsigned long)RTE_PMD_IXGBE_TX_MAX_BURST);
dev->tx_pkt_burst = ixgbe_xmit_pkts;
+ dev->tx_pkt_prep = ixgbe_prep_pkts;
}
}
diff --git a/drivers/net/ixgbe/ixgbe_rxtx.h b/drivers/net/ixgbe/ixgbe_rxtx.h
index 2608b36..7bbd9b8 100644
--- a/drivers/net/ixgbe/ixgbe_rxtx.h
+++ b/drivers/net/ixgbe/ixgbe_rxtx.h
@@ -80,6 +80,8 @@
#define RTE_IXGBE_WAIT_100_US 100
#define RTE_IXGBE_VMTXSW_REGISTER_COUNT 2
+#define IXGBE_TX_MAX_SEG 40
+
#define IXGBE_PACKET_TYPE_MASK_82599 0X7F
#define IXGBE_PACKET_TYPE_MASK_X550 0X10FF
#define IXGBE_PACKET_TYPE_MASK_TUNNEL 0XFF
--
1.7.9.5
^ permalink raw reply related
* [PATCH v10 4/6] i40e: add Tx preparation
From: Tomasz Kulasek @ 2016-10-24 16:51 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, olivier.matz
In-Reply-To: <1477327917-18564-1-git-send-email-tomaszx.kulasek@intel.com>
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 3 ++
drivers/net/i40e/i40e_rxtx.c | 72 +++++++++++++++++++++++++++++++++++++++-
drivers/net/i40e/i40e_rxtx.h | 8 +++++
3 files changed, 82 insertions(+), 1 deletion(-)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 5af0e43..dab0d48 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -936,6 +936,7 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
dev->dev_ops = &i40e_eth_dev_ops;
dev->rx_pkt_burst = i40e_recv_pkts;
dev->tx_pkt_burst = i40e_xmit_pkts;
+ dev->tx_pkt_prep = i40e_prep_pkts;
/* for secondary processes, we don't initialise any further as primary
* has already done this work. Only check we don't need a different
@@ -2629,6 +2630,8 @@ i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
.nb_max = I40E_MAX_RING_DESC,
.nb_min = I40E_MIN_RING_DESC,
.nb_align = I40E_ALIGN_RING_DESC,
+ .nb_seg_max = I40E_TX_MAX_SEG,
+ .nb_mtu_seg_max = I40E_TX_MAX_MTU_SEG,
};
if (pf->flags & I40E_FLAG_VMDQ) {
diff --git a/drivers/net/i40e/i40e_rxtx.c b/drivers/net/i40e/i40e_rxtx.c
index 7ae7d9f..7f6d3d8 100644
--- a/drivers/net/i40e/i40e_rxtx.c
+++ b/drivers/net/i40e/i40e_rxtx.c
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,8 @@
#include <rte_tcp.h>
#include <rte_sctp.h>
#include <rte_udp.h>
+#include <rte_ip.h>
+#include <rte_net.h>
#include "i40e_logs.h"
#include "base/i40e_prototype.h"
@@ -79,6 +81,17 @@
PKT_TX_TCP_SEG | \
PKT_TX_OUTER_IP_CKSUM)
+#define I40E_TX_OFFLOAD_MASK ( \
+ PKT_TX_IP_CKSUM | \
+ PKT_TX_L4_MASK | \
+ PKT_TX_OUTER_IP_CKSUM | \
+ PKT_TX_TCP_SEG | \
+ PKT_TX_QINQ_PKT | \
+ PKT_TX_VLAN_PKT)
+
+#define I40E_TX_OFFLOAD_NOTSUP_MASK \
+ (PKT_TX_OFFLOAD_MASK ^ I40E_TX_OFFLOAD_MASK)
+
static uint16_t i40e_xmit_pkts_simple(void *tx_queue,
struct rte_mbuf **tx_pkts,
uint16_t nb_pkts);
@@ -1411,6 +1424,61 @@ i40e_xmit_pkts_simple(void *tx_queue,
return nb_tx;
}
+/*********************************************************************
+ *
+ * TX prep functions
+ *
+ **********************************************************************/
+uint16_t
+i40e_prep_pkts(__rte_unused void *tx_queue, struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts)
+{
+ int i, ret;
+ uint64_t ol_flags;
+ struct rte_mbuf *m;
+
+ for (i = 0; i < nb_pkts; i++) {
+ m = tx_pkts[i];
+ ol_flags = m->ol_flags;
+
+ /**
+ * m->nb_segs is uint8_t, so m->nb_segs is always less than
+ * I40E_TX_MAX_SEG.
+ * We check only a condition for m->nb_segs > I40E_TX_MAX_MTU_SEG.
+ */
+ if (!(ol_flags & PKT_TX_TCP_SEG)) {
+ if (m->nb_segs > I40E_TX_MAX_MTU_SEG) {
+ rte_errno = -EINVAL;
+ return i;
+ }
+ } else if ((m->tso_segsz < I40E_MIN_TSO_MSS) ||
+ (m->tso_segsz > I40E_MAX_TSO_MSS)) {
+ /* MSS outside the range (256B - 9674B) are considered malicious */
+ rte_errno = -EINVAL;
+ return i;
+ }
+
+ if (ol_flags & I40E_TX_OFFLOAD_NOTSUP_MASK) {
+ rte_errno = -ENOTSUP;
+ return i;
+ }
+
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+ ret = rte_validate_tx_offload(m);
+ if (ret != 0) {
+ rte_errno = ret;
+ return i;
+ }
+#endif
+ ret = rte_phdr_cksum_fix(m);
+ if (ret != 0) {
+ rte_errno = ret;
+ return i;
+ }
+ }
+ return i;
+}
+
/*
* Find the VSI the queue belongs to. 'queue_idx' is the queue index
* application used, which assume having sequential ones. But from driver's
@@ -2763,9 +2831,11 @@ i40e_set_tx_function(struct rte_eth_dev *dev)
PMD_INIT_LOG(DEBUG, "Simple tx finally be used.");
dev->tx_pkt_burst = i40e_xmit_pkts_simple;
}
+ dev->tx_pkt_prep = NULL;
} else {
PMD_INIT_LOG(DEBUG, "Xmit tx finally be used.");
dev->tx_pkt_burst = i40e_xmit_pkts;
+ dev->tx_pkt_prep = i40e_prep_pkts;
}
}
diff --git a/drivers/net/i40e/i40e_rxtx.h b/drivers/net/i40e/i40e_rxtx.h
index ecdb13c..9df8a56 100644
--- a/drivers/net/i40e/i40e_rxtx.h
+++ b/drivers/net/i40e/i40e_rxtx.h
@@ -63,6 +63,12 @@
#define I40E_MIN_RING_DESC 64
#define I40E_MAX_RING_DESC 4096
+#define I40E_MIN_TSO_MSS 256
+#define I40E_MAX_TSO_MSS 9674
+
+#define I40E_TX_MAX_SEG UINT8_MAX
+#define I40E_TX_MAX_MTU_SEG 8
+
#undef container_of
#define container_of(ptr, type, member) ({ \
typeof(((type *)0)->member)(*__mptr) = (ptr); \
@@ -223,6 +229,8 @@ uint16_t i40e_recv_scattered_pkts(void *rx_queue,
uint16_t i40e_xmit_pkts(void *tx_queue,
struct rte_mbuf **tx_pkts,
uint16_t nb_pkts);
+uint16_t i40e_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts);
int i40e_tx_queue_init(struct i40e_tx_queue *txq);
int i40e_rx_queue_init(struct i40e_rx_queue *rxq);
void i40e_free_tx_resources(struct i40e_tx_queue *txq);
--
1.7.9.5
^ permalink raw reply related
* [PATCH v10 3/6] fm10k: add Tx preparation
From: Tomasz Kulasek @ 2016-10-24 16:51 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, olivier.matz
In-Reply-To: <1477327917-18564-1-git-send-email-tomaszx.kulasek@intel.com>
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
drivers/net/fm10k/fm10k.h | 6 +++++
drivers/net/fm10k/fm10k_ethdev.c | 5 ++++
drivers/net/fm10k/fm10k_rxtx.c | 50 +++++++++++++++++++++++++++++++++++++-
3 files changed, 60 insertions(+), 1 deletion(-)
diff --git a/drivers/net/fm10k/fm10k.h b/drivers/net/fm10k/fm10k.h
index 05aa1a2..c6fed21 100644
--- a/drivers/net/fm10k/fm10k.h
+++ b/drivers/net/fm10k/fm10k.h
@@ -69,6 +69,9 @@
#define FM10K_MAX_RX_DESC (FM10K_MAX_RX_RING_SZ / sizeof(union fm10k_rx_desc))
#define FM10K_MAX_TX_DESC (FM10K_MAX_TX_RING_SZ / sizeof(struct fm10k_tx_desc))
+#define FM10K_TX_MAX_SEG UINT8_MAX
+#define FM10K_TX_MAX_MTU_SEG UINT8_MAX
+
/*
* byte aligment for HW RX data buffer
* Datasheet requires RX buffer addresses shall either be 512-byte aligned or
@@ -356,6 +359,9 @@ fm10k_dev_rx_descriptor_done(void *rx_queue, uint16_t offset);
uint16_t fm10k_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
uint16_t nb_pkts);
+uint16_t fm10k_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts);
+
int fm10k_rxq_vec_setup(struct fm10k_rx_queue *rxq);
int fm10k_rx_vec_condition_check(struct rte_eth_dev *);
void fm10k_rx_queue_release_mbufs_vec(struct fm10k_rx_queue *rxq);
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index c804436..dffb6d1 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -1446,6 +1446,8 @@ fm10k_dev_infos_get(struct rte_eth_dev *dev,
.nb_max = FM10K_MAX_TX_DESC,
.nb_min = FM10K_MIN_TX_DESC,
.nb_align = FM10K_MULT_TX_DESC,
+ .nb_seg_max = FM10K_TX_MAX_SEG,
+ .nb_mtu_seg_max = FM10K_TX_MAX_MTU_SEG,
};
dev_info->speed_capa = ETH_LINK_SPEED_1G | ETH_LINK_SPEED_2_5G |
@@ -2754,8 +2756,10 @@ fm10k_set_tx_function(struct rte_eth_dev *dev)
fm10k_txq_vec_setup(txq);
}
dev->tx_pkt_burst = fm10k_xmit_pkts_vec;
+ dev->tx_pkt_prep = NULL;
} else {
dev->tx_pkt_burst = fm10k_xmit_pkts;
+ dev->tx_pkt_prep = fm10k_prep_pkts;
PMD_INIT_LOG(DEBUG, "Use regular Tx func");
}
}
@@ -2834,6 +2838,7 @@ eth_fm10k_dev_init(struct rte_eth_dev *dev)
dev->dev_ops = &fm10k_eth_dev_ops;
dev->rx_pkt_burst = &fm10k_recv_pkts;
dev->tx_pkt_burst = &fm10k_xmit_pkts;
+ dev->tx_pkt_prep = &fm10k_prep_pkts;
/* only initialize in the primary process */
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
diff --git a/drivers/net/fm10k/fm10k_rxtx.c b/drivers/net/fm10k/fm10k_rxtx.c
index 32cc7ff..5fc4d5a 100644
--- a/drivers/net/fm10k/fm10k_rxtx.c
+++ b/drivers/net/fm10k/fm10k_rxtx.c
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013-2016 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,7 @@
#include <rte_ethdev.h>
#include <rte_common.h>
+#include <rte_net.h>
#include "fm10k.h"
#include "base/fm10k_type.h"
@@ -65,6 +66,15 @@ static inline void dump_rxd(union fm10k_rx_desc *rxd)
}
#endif
+#define FM10K_TX_OFFLOAD_MASK ( \
+ PKT_TX_VLAN_PKT | \
+ PKT_TX_IP_CKSUM | \
+ PKT_TX_L4_MASK | \
+ PKT_TX_TCP_SEG)
+
+#define FM10K_TX_OFFLOAD_NOTSUP_MASK \
+ (PKT_TX_OFFLOAD_MASK ^ FM10K_TX_OFFLOAD_MASK)
+
/* @note: When this function is changed, make corresponding change to
* fm10k_dev_supported_ptypes_get()
*/
@@ -597,3 +607,41 @@ fm10k_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
return count;
}
+
+uint16_t
+fm10k_prep_pkts(__rte_unused void *tx_queue, struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts)
+{
+ int i, ret;
+ struct rte_mbuf *m;
+
+ for (i = 0; i < nb_pkts; i++) {
+ m = tx_pkts[i];
+
+ if ((m->ol_flags & PKT_TX_TCP_SEG) &&
+ (m->tso_segsz < FM10K_TSO_MINMSS)) {
+ rte_errno = -EINVAL;
+ return i;
+ }
+
+ if (m->ol_flags & FM10K_TX_OFFLOAD_NOTSUP_MASK) {
+ rte_errno = -ENOTSUP;
+ return i;
+ }
+
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+ ret = rte_validate_tx_offload(m);
+ if (ret != 0) {
+ rte_errno = ret;
+ return i;
+ }
+#endif
+ ret = rte_phdr_cksum_fix(m);
+ if (ret != 0) {
+ rte_errno = ret;
+ return i;
+ }
+ }
+
+ return i;
+}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v10 2/6] e1000: add Tx preparation
From: Tomasz Kulasek @ 2016-10-24 16:51 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, olivier.matz
In-Reply-To: <1477327917-18564-1-git-send-email-tomaszx.kulasek@intel.com>
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
drivers/net/e1000/e1000_ethdev.h | 11 ++++++++
drivers/net/e1000/em_ethdev.c | 5 +++-
drivers/net/e1000/em_rxtx.c | 48 ++++++++++++++++++++++++++++++++++-
drivers/net/e1000/igb_ethdev.c | 4 +++
drivers/net/e1000/igb_rxtx.c | 52 +++++++++++++++++++++++++++++++++++++-
5 files changed, 117 insertions(+), 3 deletions(-)
diff --git a/drivers/net/e1000/e1000_ethdev.h b/drivers/net/e1000/e1000_ethdev.h
index 6c25c8d..bd0f277 100644
--- a/drivers/net/e1000/e1000_ethdev.h
+++ b/drivers/net/e1000/e1000_ethdev.h
@@ -138,6 +138,11 @@
#define E1000_MISC_VEC_ID RTE_INTR_VEC_ZERO_OFFSET
#define E1000_RX_VEC_START RTE_INTR_VEC_RXTX_OFFSET
+#define IGB_TX_MAX_SEG UINT8_MAX
+#define IGB_TX_MAX_MTU_SEG UINT8_MAX
+#define EM_TX_MAX_SEG UINT8_MAX
+#define EM_TX_MAX_MTU_SEG UINT8_MAX
+
/* structure for interrupt relative data */
struct e1000_interrupt {
uint32_t flags;
@@ -315,6 +320,9 @@ void eth_igb_tx_init(struct rte_eth_dev *dev);
uint16_t eth_igb_xmit_pkts(void *txq, struct rte_mbuf **tx_pkts,
uint16_t nb_pkts);
+uint16_t eth_igb_prep_pkts(void *txq, struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts);
+
uint16_t eth_igb_recv_pkts(void *rxq, struct rte_mbuf **rx_pkts,
uint16_t nb_pkts);
@@ -376,6 +384,9 @@ void eth_em_tx_init(struct rte_eth_dev *dev);
uint16_t eth_em_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
uint16_t nb_pkts);
+uint16_t eth_em_prep_pkts(void *txq, struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts);
+
uint16_t eth_em_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
uint16_t nb_pkts);
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 7cf5f0c..17b45cb 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -300,6 +300,7 @@ eth_em_dev_init(struct rte_eth_dev *eth_dev)
eth_dev->dev_ops = ð_em_ops;
eth_dev->rx_pkt_burst = (eth_rx_burst_t)ð_em_recv_pkts;
eth_dev->tx_pkt_burst = (eth_tx_burst_t)ð_em_xmit_pkts;
+ eth_dev->tx_pkt_prep = (eth_tx_prep_t)ð_em_prep_pkts;
/* for secondary processes, we don't initialise any further as primary
* has already done this work. Only check we don't need a different
@@ -1067,6 +1068,8 @@ eth_em_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
.nb_max = E1000_MAX_RING_DESC,
.nb_min = E1000_MIN_RING_DESC,
.nb_align = EM_TXD_ALIGN,
+ .nb_seg_max = EM_TX_MAX_SEG,
+ .nb_mtu_seg_max = EM_TX_MAX_MTU_SEG,
};
dev_info->speed_capa = ETH_LINK_SPEED_10M_HD | ETH_LINK_SPEED_10M |
diff --git a/drivers/net/e1000/em_rxtx.c b/drivers/net/e1000/em_rxtx.c
index 41f51c0..5bd3c99 100644
--- a/drivers/net/e1000/em_rxtx.c
+++ b/drivers/net/e1000/em_rxtx.c
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -66,6 +66,7 @@
#include <rte_udp.h>
#include <rte_tcp.h>
#include <rte_sctp.h>
+#include <rte_net.h>
#include <rte_string_fns.h>
#include "e1000_logs.h"
@@ -77,6 +78,14 @@
#define E1000_RXDCTL_GRAN 0x01000000 /* RXDCTL Granularity */
+#define E1000_TX_OFFLOAD_MASK ( \
+ PKT_TX_IP_CKSUM | \
+ PKT_TX_L4_MASK | \
+ PKT_TX_VLAN_PKT)
+
+#define E1000_TX_OFFLOAD_NOTSUP_MASK \
+ (PKT_TX_OFFLOAD_MASK ^ E1000_TX_OFFLOAD_MASK)
+
/**
* Structure associated with each descriptor of the RX ring of a RX queue.
*/
@@ -618,6 +627,43 @@ end_of_tx:
/*********************************************************************
*
+ * TX prep functions
+ *
+ **********************************************************************/
+uint16_t
+eth_em_prep_pkts(__rte_unused void *tx_queue, struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts)
+{
+ int i, ret;
+ struct rte_mbuf *m;
+
+ for (i = 0; i < nb_pkts; i++) {
+ m = tx_pkts[i];
+
+ if (m->ol_flags & E1000_TX_OFFLOAD_NOTSUP_MASK) {
+ rte_errno = -ENOTSUP;
+ return i;
+ }
+
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+ ret = rte_validate_tx_offload(m);
+ if (ret != 0) {
+ rte_errno = ret;
+ return i;
+ }
+#endif
+ ret = rte_phdr_cksum_fix(m);
+ if (ret != 0) {
+ rte_errno = ret;
+ return i;
+ }
+ }
+
+ return i;
+}
+
+/*********************************************************************
+ *
* RX functions
*
**********************************************************************/
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 4924396..0afdd09 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -369,6 +369,8 @@ static const struct rte_eth_desc_lim tx_desc_lim = {
.nb_max = E1000_MAX_RING_DESC,
.nb_min = E1000_MIN_RING_DESC,
.nb_align = IGB_RXD_ALIGN,
+ .nb_seg_max = IGB_TX_MAX_SEG,
+ .nb_mtu_seg_max = IGB_TX_MAX_MTU_SEG,
};
static const struct eth_dev_ops eth_igb_ops = {
@@ -760,6 +762,7 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev)
eth_dev->dev_ops = ð_igb_ops;
eth_dev->rx_pkt_burst = ð_igb_recv_pkts;
eth_dev->tx_pkt_burst = ð_igb_xmit_pkts;
+ eth_dev->tx_pkt_prep = ð_igb_prep_pkts;
/* for secondary processes, we don't initialise any further as primary
* has already done this work. Only check we don't need a different
@@ -963,6 +966,7 @@ eth_igbvf_dev_init(struct rte_eth_dev *eth_dev)
eth_dev->dev_ops = &igbvf_eth_dev_ops;
eth_dev->rx_pkt_burst = ð_igb_recv_pkts;
eth_dev->tx_pkt_burst = ð_igb_xmit_pkts;
+ eth_dev->tx_pkt_prep = ð_igb_prep_pkts;
/* for secondary processes, we don't initialise any further as primary
* has already done this work. Only check we don't need a different
diff --git a/drivers/net/e1000/igb_rxtx.c b/drivers/net/e1000/igb_rxtx.c
index dbd37ac..08e47f2 100644
--- a/drivers/net/e1000/igb_rxtx.c
+++ b/drivers/net/e1000/igb_rxtx.c
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -65,6 +65,7 @@
#include <rte_udp.h>
#include <rte_tcp.h>
#include <rte_sctp.h>
+#include <rte_net.h>
#include <rte_string_fns.h>
#include "e1000_logs.h"
@@ -78,6 +79,9 @@
PKT_TX_L4_MASK | \
PKT_TX_TCP_SEG)
+#define IGB_TX_OFFLOAD_NOTSUP_MASK \
+ (PKT_TX_OFFLOAD_MASK ^ IGB_TX_OFFLOAD_MASK)
+
/**
* Structure associated with each descriptor of the RX ring of a RX queue.
*/
@@ -616,6 +620,51 @@ eth_igb_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
/*********************************************************************
*
+ * TX prep functions
+ *
+ **********************************************************************/
+uint16_t
+eth_igb_prep_pkts(__rte_unused void *tx_queue, struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts)
+{
+ int i, ret;
+ struct rte_mbuf *m;
+
+ for (i = 0; i < nb_pkts; i++) {
+ m = tx_pkts[i];
+
+ /* Check some limitations for TSO in hardware */
+ if (m->ol_flags & PKT_TX_TCP_SEG)
+ if ((m->tso_segsz > IGB_TSO_MAX_MSS) || (m->l2_len + m->l3_len +
+ m->l4_len > IGB_TSO_MAX_HDRLEN)) {
+ rte_errno = -EINVAL;
+ return i;
+ }
+
+ if (m->ol_flags & IGB_TX_OFFLOAD_NOTSUP_MASK) {
+ rte_errno = -ENOTSUP;
+ return i;
+ }
+
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+ ret = rte_validate_tx_offload(m);
+ if (ret != 0) {
+ rte_errno = ret;
+ return i;
+ }
+#endif
+ ret = rte_phdr_cksum_fix(m);
+ if (ret != 0) {
+ rte_errno = ret;
+ return i;
+ }
+ }
+
+ return i;
+}
+
+/*********************************************************************
+ *
* RX functions
*
**********************************************************************/
@@ -1364,6 +1413,7 @@ eth_igb_tx_queue_setup(struct rte_eth_dev *dev,
igb_reset_tx_queue(txq, dev);
dev->tx_pkt_burst = eth_igb_xmit_pkts;
+ dev->tx_pkt_prep = ð_igb_prep_pkts;
dev->data->tx_queues[queue_idx] = txq;
return 0;
--
1.7.9.5
^ permalink raw reply related
* [PATCH v10 1/6] ethdev: add Tx preparation
From: Tomasz Kulasek @ 2016-10-24 16:51 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, olivier.matz
In-Reply-To: <1477327917-18564-1-git-send-email-tomaszx.kulasek@intel.com>
Added API for `rte_eth_tx_prep`
uint16_t rte_eth_tx_prep(uint8_t port_id, uint16_t queue_id,
struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
Added fields to the `struct rte_eth_desc_lim`:
uint16_t nb_seg_max;
/**< Max number of segments per whole packet. */
uint16_t nb_mtu_seg_max;
/**< Max number of segments per one MTU */
Added functions:
int rte_validate_tx_offload(struct rte_mbuf *m)
to validate general requirements for tx offload set in mbuf of packet
such a flag completness. In current implementation this function is
called optionaly when RTE_LIBRTE_ETHDEV_DEBUG is enabled.
int rte_phdr_cksum_fix(struct rte_mbuf *m)
to fix pseudo header checksum for TSO and non-TSO tcp/udp packets
before hardware tx checksum offload.
- for non-TSO tcp/udp packets full pseudo-header checksum is
counted and set.
- for TSO the IP payload length is not included.
PERFORMANCE TESTS
-----------------
This feature was tested with modified csum engine from test-pmd.
The packet checksum preparation was moved from application to Tx
preparation step placed before burst.
We may expect some overhead costs caused by:
1) using additional callback before burst,
2) rescanning burst,
3) additional condition checking (packet validation),
4) worse optimization (e.g. packet data access, etc.)
We tested it using ixgbe Tx preparation implementation with some parts
disabled to have comparable information about the impact of diferent
parts of implementation.
IMPACT:
1) For unimplemented Tx preparation callback the performance impact is
negligible,
2) For packet condition check without checksum modifications (nb_segs,
available offloads, etc.) is 14626628/14252168 (~2.62% drop),
3) Full support in ixgbe driver (point 2 + packet checksum
initialization) is 14060924/13588094 (~3.48% drop)
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
config/common_base | 1 +
lib/librte_ether/rte_ethdev.h | 96 +++++++++++++++++++++++++++++++++++++++++
lib/librte_mbuf/rte_mbuf.h | 64 +++++++++++++++++++++++++++
lib/librte_net/rte_net.h | 85 ++++++++++++++++++++++++++++++++++++
4 files changed, 246 insertions(+)
diff --git a/config/common_base b/config/common_base
index c7fd3db..619284b 100644
--- a/config/common_base
+++ b/config/common_base
@@ -120,6 +120,7 @@ CONFIG_RTE_MAX_QUEUES_PER_PORT=1024
CONFIG_RTE_LIBRTE_IEEE1588=n
CONFIG_RTE_ETHDEV_QUEUE_STAT_CNTRS=16
CONFIG_RTE_ETHDEV_RXTX_CALLBACKS=y
+CONFIG_RTE_ETHDEV_TX_PREP=y
#
# Support NIC bypass logic
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 38641e8..c4a8ccd 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -182,6 +182,7 @@ extern "C" {
#include <rte_pci.h>
#include <rte_dev.h>
#include <rte_devargs.h>
+#include <rte_errno.h>
#include "rte_ether.h"
#include "rte_eth_ctrl.h"
#include "rte_dev_info.h"
@@ -699,6 +700,8 @@ struct rte_eth_desc_lim {
uint16_t nb_max; /**< Max allowed number of descriptors. */
uint16_t nb_min; /**< Min allowed number of descriptors. */
uint16_t nb_align; /**< Number of descriptors should be aligned to. */
+ uint16_t nb_seg_max; /**< Max number of segments per whole packet. */
+ uint16_t nb_mtu_seg_max; /**< Max number of segments per one MTU */
};
/**
@@ -1188,6 +1191,11 @@ typedef uint16_t (*eth_tx_burst_t)(void *txq,
uint16_t nb_pkts);
/**< @internal Send output packets on a transmit queue of an Ethernet device. */
+typedef uint16_t (*eth_tx_prep_t)(void *txq,
+ struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts);
+/**< @internal Prepare output packets on a transmit queue of an Ethernet device. */
+
typedef int (*flow_ctrl_get_t)(struct rte_eth_dev *dev,
struct rte_eth_fc_conf *fc_conf);
/**< @internal Get current flow control parameter on an Ethernet device */
@@ -1622,6 +1630,7 @@ struct rte_eth_rxtx_callback {
struct rte_eth_dev {
eth_rx_burst_t rx_pkt_burst; /**< Pointer to PMD receive function. */
eth_tx_burst_t tx_pkt_burst; /**< Pointer to PMD transmit function. */
+ eth_tx_prep_t tx_pkt_prep; /**< Pointer to PMD transmit prepare function. */
struct rte_eth_dev_data *data; /**< Pointer to device data */
const struct eth_driver *driver;/**< Driver for this device */
const struct eth_dev_ops *dev_ops; /**< Functions exported by PMD */
@@ -2816,6 +2825,93 @@ rte_eth_tx_burst(uint8_t port_id, uint16_t queue_id,
return (*dev->tx_pkt_burst)(dev->data->tx_queues[queue_id], tx_pkts, nb_pkts);
}
+/**
+ * Process a burst of output packets on a transmit queue of an Ethernet device.
+ *
+ * The rte_eth_tx_prep() function is invoked to prepare output packets to be
+ * transmitted on the output queue *queue_id* of the Ethernet device designated
+ * by its *port_id*.
+ * The *nb_pkts* parameter is the number of packets to be prepared which are
+ * supplied in the *tx_pkts* array of *rte_mbuf* structures, each of them
+ * allocated from a pool created with rte_pktmbuf_pool_create().
+ * For each packet to send, the rte_eth_tx_prep() function performs
+ * the following operations:
+ *
+ * - Check if packet meets devices requirements for tx offloads.
+ *
+ * - Check limitations about number of segments.
+ *
+ * - Check additional requirements when debug is enabled.
+ *
+ * - Update and/or reset required checksums when tx offload is set for packet.
+ *
+ * The rte_eth_tx_prep() function returns the number of packets ready to be
+ * sent. A return value equal to *nb_pkts* means that all packets are valid and
+ * ready to be sent.
+ *
+ * @param port_id
+ * The port identifier of the Ethernet device.
+ * The value must be a valid port id.
+ * @param queue_id
+ * The index of the transmit queue through which output packets must be
+ * sent.
+ * The value must be in the range [0, nb_tx_queue - 1] previously supplied
+ * to rte_eth_dev_configure().
+ * @param tx_pkts
+ * The address of an array of *nb_pkts* pointers to *rte_mbuf* structures
+ * which contain the output packets.
+ * @param nb_pkts
+ * The maximum number of packets to process.
+ * @return
+ * The number of packets correct and ready to be sent. The return value can be
+ * less than the value of the *tx_pkts* parameter when some packet doesn't
+ * meet devices requirements with rte_errno set appropriately.
+ */
+
+#ifdef RTE_ETHDEV_TX_PREP
+
+static inline uint16_t
+rte_eth_tx_prep(uint8_t port_id, uint16_t queue_id, struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts)
+{
+ struct rte_eth_dev *dev;
+
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ RTE_PMD_DEBUG_TRACE("Invalid TX port_id=%d\n", port_id);
+ rte_errno = -EINVAL;
+ return 0;
+ }
+#endif
+
+ dev = &rte_eth_devices[port_id];
+
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+ if (queue_id >= dev->data->nb_tx_queues) {
+ RTE_PMD_DEBUG_TRACE("Invalid TX queue_id=%d\n", queue_id);
+ rte_errno = -EINVAL;
+ return 0;
+ }
+#endif
+
+ if (!dev->tx_pkt_prep)
+ return nb_pkts;
+
+ return (*dev->tx_pkt_prep)(dev->data->tx_queues[queue_id],
+ tx_pkts, nb_pkts);
+}
+
+#else
+
+static inline uint16_t
+rte_eth_tx_prep(__rte_unused uint8_t port_id, __rte_unused uint16_t queue_id,
+ __rte_unused struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+ return nb_pkts;
+}
+
+#endif
+
typedef void (*buffer_tx_error_fn)(struct rte_mbuf **unsent, uint16_t count,
void *userdata);
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index 109e666..ff9e749 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -283,6 +283,19 @@ extern "C" {
*/
#define PKT_TX_OUTER_IPV6 (1ULL << 60)
+/**
+ * Bit Mask of all supported packet Tx offload features flags, which can be set
+ * for packet.
+ */
+#define PKT_TX_OFFLOAD_MASK ( \
+ PKT_TX_IP_CKSUM | \
+ PKT_TX_L4_MASK | \
+ PKT_TX_OUTER_IP_CKSUM | \
+ PKT_TX_TCP_SEG | \
+ PKT_TX_QINQ_PKT | \
+ PKT_TX_VLAN_PKT | \
+ PKT_TX_TUNNEL_MASK)
+
#define __RESERVED (1ULL << 61) /**< reserved for future mbuf use */
#define IND_ATTACHED_MBUF (1ULL << 62) /**< Indirect attached mbuf */
@@ -1647,6 +1660,57 @@ static inline int rte_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *tail
}
/**
+ * Validate general requirements for tx offload in mbuf.
+ *
+ * This function checks correctness and completeness of Tx offload settings.
+ *
+ * @param m
+ * The packet mbuf to be validated.
+ * @return
+ * 0 if packet is valid
+ */
+static inline int
+rte_validate_tx_offload(const struct rte_mbuf *m)
+{
+ uint64_t ol_flags = m->ol_flags;
+ uint64_t inner_l3_offset = m->l2_len;
+
+ /* Does packet set any of available offloads? */
+ if (!(ol_flags & PKT_TX_OFFLOAD_MASK))
+ return 0;
+
+ if (ol_flags & PKT_TX_OUTER_IP_CKSUM)
+ inner_l3_offset += m->outer_l2_len + m->outer_l3_len;
+
+ /* Headers are fragmented */
+ if (rte_pktmbuf_data_len(m) < inner_l3_offset + m->l3_len + m->l4_len)
+ return -ENOTSUP;
+
+ /* IP checksum can be counted only for IPv4 packet */
+ if ((ol_flags & PKT_TX_IP_CKSUM) && (ol_flags & PKT_TX_IPV6))
+ return -EINVAL;
+
+ /* IP type not set when required */
+ if (ol_flags & (PKT_TX_L4_MASK | PKT_TX_TCP_SEG))
+ if (!(ol_flags & (PKT_TX_IPV4 | PKT_TX_IPV6)))
+ return -EINVAL;
+
+ /* Check requirements for TSO packet */
+ if (ol_flags & PKT_TX_TCP_SEG)
+ if ((m->tso_segsz == 0) ||
+ ((ol_flags & PKT_TX_IPV4) &&
+ !(ol_flags & PKT_TX_IP_CKSUM)))
+ return -EINVAL;
+
+ /* PKT_TX_OUTER_IP_CKSUM set for non outer IPv4 packet. */
+ if ((ol_flags & PKT_TX_OUTER_IP_CKSUM) &&
+ !(ol_flags & PKT_TX_OUTER_IPV4))
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
* Dump an mbuf structure to a file.
*
* Dump all fields for the given packet mbuf and all its associated
diff --git a/lib/librte_net/rte_net.h b/lib/librte_net/rte_net.h
index d4156ae..90af335 100644
--- a/lib/librte_net/rte_net.h
+++ b/lib/librte_net/rte_net.h
@@ -38,6 +38,11 @@
extern "C" {
#endif
+#include <rte_ip.h>
+#include <rte_udp.h>
+#include <rte_tcp.h>
+#include <rte_sctp.h>
+
/**
* Structure containing header lengths associated to a packet, filled
* by rte_net_get_ptype().
@@ -86,6 +91,86 @@ struct rte_net_hdr_lens {
uint32_t rte_net_get_ptype(const struct rte_mbuf *m,
struct rte_net_hdr_lens *hdr_lens, uint32_t layers);
+/**
+ * Fix pseudo header checksum
+ *
+ * This function fixes pseudo header checksum for TSO and non-TSO tcp/udp in
+ * provided mbufs packet data.
+ *
+ * - for non-TSO tcp/udp packets full pseudo-header checksum is counted and set
+ * in packet data,
+ * - for TSO the IP payload length is not included in pseudo header.
+ *
+ * This function expects that used headers are in the first data segment of
+ * mbuf, and are not fragmented.
+ *
+ * @param m
+ * The packet mbuf to be validated.
+ * @return
+ * 0 if checksum is initialized properly
+ */
+static inline int
+rte_phdr_cksum_fix(struct rte_mbuf *m)
+{
+ struct ipv4_hdr *ipv4_hdr;
+ struct ipv6_hdr *ipv6_hdr;
+ struct tcp_hdr *tcp_hdr;
+ struct udp_hdr *udp_hdr;
+ uint64_t ol_flags = m->ol_flags;
+ uint64_t inner_l3_offset = m->l2_len;
+
+ if (ol_flags & PKT_TX_OUTER_IP_CKSUM)
+ inner_l3_offset += m->outer_l2_len + m->outer_l3_len;
+
+ if ((ol_flags & PKT_TX_UDP_CKSUM) == PKT_TX_UDP_CKSUM) {
+ if (ol_flags & PKT_TX_IPV4) {
+ ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *,
+ inner_l3_offset);
+
+ if (ol_flags & PKT_TX_IP_CKSUM)
+ ipv4_hdr->hdr_checksum = 0;
+
+ udp_hdr = (struct udp_hdr *)((char *)ipv4_hdr +
+ m->l3_len);
+ udp_hdr->dgram_cksum = rte_ipv4_phdr_cksum(ipv4_hdr,
+ ol_flags);
+ } else {
+ ipv6_hdr = rte_pktmbuf_mtod_offset(m, struct ipv6_hdr *,
+ inner_l3_offset);
+ /* non-TSO udp */
+ udp_hdr = rte_pktmbuf_mtod_offset(m, struct udp_hdr *,
+ inner_l3_offset + m->l3_len);
+ udp_hdr->dgram_cksum = rte_ipv6_phdr_cksum(ipv6_hdr,
+ ol_flags);
+ }
+ } else if ((ol_flags & PKT_TX_TCP_CKSUM) ||
+ (ol_flags & PKT_TX_TCP_SEG)) {
+ if (ol_flags & PKT_TX_IPV4) {
+ ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *,
+ inner_l3_offset);
+
+ if (ol_flags & PKT_TX_IP_CKSUM)
+ ipv4_hdr->hdr_checksum = 0;
+
+ /* non-TSO tcp or TSO */
+ tcp_hdr = (struct tcp_hdr *)((char *)ipv4_hdr +
+ m->l3_len);
+ tcp_hdr->cksum = rte_ipv4_phdr_cksum(ipv4_hdr,
+ ol_flags);
+ } else {
+ ipv6_hdr = rte_pktmbuf_mtod_offset(m, struct ipv6_hdr *,
+ inner_l3_offset);
+ /* non-TSO tcp or TSO */
+ tcp_hdr = rte_pktmbuf_mtod_offset(m, struct tcp_hdr *,
+ inner_l3_offset + m->l3_len);
+ tcp_hdr->cksum = rte_ipv6_phdr_cksum(ipv6_hdr,
+ ol_flags);
+ }
+ }
+
+ return 0;
+}
+
#ifdef __cplusplus
}
#endif
--
1.7.9.5
^ permalink raw reply related
* [PATCH v10 0/6] add Tx preparation
From: Tomasz Kulasek @ 2016-10-24 16:51 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, olivier.matz
In-Reply-To: <1477317933-14144-1-git-send-email-tomaszx.kulasek@intel.com>
As discussed in that thread:
http://dpdk.org/ml/archives/dev/2015-September/023603.html
Different NIC models depending on HW offload requested might impose
different requirements on packets to be TX-ed in terms of:
- Max number of fragments per packet allowed
- Max number of fragments per TSO segments
- The way pseudo-header checksum should be pre-calculated
- L3/L4 header fields filling
- etc.
MOTIVATION:
-----------
1) Some work cannot (and didn't should) be done in rte_eth_tx_burst.
However, this work is sometimes required, and now, it's an
application issue.
2) Different hardware may have different requirements for TX offloads,
other subset can be supported and so on.
3) Some parameters (e.g. number of segments in ixgbe driver) may hung
device. These parameters may be vary for different devices.
For example i40e HW allows 8 fragments per packet, but that is after
TSO segmentation. While ixgbe has a 38-fragment pre-TSO limit.
4) Fields in packet may require different initialization (like e.g. will
require pseudo-header checksum precalculation, sometimes in a
different way depending on packet type, and so on). Now application
needs to care about it.
5) Using additional API (rte_eth_tx_prep) before rte_eth_tx_burst let to
prepare packet burst in acceptable form for specific device.
6) Some additional checks may be done in debug mode keeping tx_burst
implementation clean.
PROPOSAL:
---------
To help user to deal with all these varieties we propose to:
1) Introduce rte_eth_tx_prep() function to do necessary preparations of
packet burst to be safely transmitted on device for desired HW
offloads (set/reset checksum field according to the hardware
requirements) and check HW constraints (number of segments per
packet, etc).
While the limitations and requirements may differ for devices, it
requires to extend rte_eth_dev structure with new function pointer
"tx_pkt_prep" which can be implemented in the driver to prepare and
verify packets, in devices specific way, before burst, what should to
prevent application to send malformed packets.
2) Also new fields will be introduced in rte_eth_desc_lim:
nb_seg_max and nb_mtu_seg_max, providing an information about max
segments in TSO and non-TSO packets acceptable by device.
This information is useful for application to not create/limit
malicious packet.
APPLICATION (CASE OF USE):
--------------------------
1) Application should to initialize burst of packets to send, set
required tx offload flags and required fields, like l2_len, l3_len,
l4_len, and tso_segsz
2) Application passes burst to the rte_eth_tx_prep to check conditions
required to send packets through the NIC.
3) The result of rte_eth_tx_prep can be used to send valid packets
and/or restore invalid if function fails.
e.g.
for (i = 0; i < nb_pkts; i++) {
/* initialize or process packet */
bufs[i]->tso_segsz = 800;
bufs[i]->ol_flags = PKT_TX_TCP_SEG | PKT_TX_IPV4
| PKT_TX_IP_CKSUM;
bufs[i]->l2_len = sizeof(struct ether_hdr);
bufs[i]->l3_len = sizeof(struct ipv4_hdr);
bufs[i]->l4_len = sizeof(struct tcp_hdr);
}
/* Prepare burst of TX packets */
nb_prep = rte_eth_tx_prep(port, 0, bufs, nb_pkts);
if (nb_prep < nb_pkts) {
printf("tx_prep failed\n");
/* nb_prep indicates here first invalid packet. rte_eth_tx_prep
* can be used on remaining packets to find another ones.
*/
}
/* Send burst of TX packets */
nb_tx = rte_eth_tx_burst(port, 0, bufs, nb_prep);
/* Free any unsent packets. */
v10 changes:
- moved drivers tx calback check in rte_eth_tx_prep after queue_id check
v9 changes:
- fixed headers structure fragmentation check
- moved fragmentation check into rte_validate_tx_offload()
v8 changes:
- mbuf argument in rte_validate_tx_offload declared as const
v7 changes:
- comments reworded/added
- changed errno values returned from Tx prep API
- added check in rte_phdr_cksum_fix if headers are in the first
data segment and can be safetly modified
- moved rte_validate_tx_offload to rte_mbuf
- moved rte_phdr_cksum_fix to rte_net.h
- removed rte_pkt.h new file as useless
v6 changes:
- added performance impact test results to the patch description
v5 changes:
- rebased csum engine modification
- added information to the csum engine about performance tests
- some performance improvements
v4 changes:
- tx_prep is now set to default behavior (NULL) for simple/vector path
in fm10k, i40e and ixgbe drivers to increase performance, when
Tx offloads are not intentionally available
v3 changes:
- reworked csum testpmd engine instead adding new one,
- fixed checksum initialization procedure to include also outer
checksum offloads,
- some minor formattings and optimalizations
v2 changes:
- rte_eth_tx_prep() returns number of packets when device doesn't
support tx_prep functionality,
- introduced CONFIG_RTE_ETHDEV_TX_PREP allowing to turn off tx_prep
Tomasz Kulasek (6):
ethdev: add Tx preparation
e1000: add Tx preparation
fm10k: add Tx preparation
i40e: add Tx preparation
ixgbe: add Tx preparation
testpmd: use Tx preparation in csum engine
app/test-pmd/csumonly.c | 36 ++++++--------
config/common_base | 1 +
drivers/net/e1000/e1000_ethdev.h | 11 +++++
drivers/net/e1000/em_ethdev.c | 5 +-
drivers/net/e1000/em_rxtx.c | 48 ++++++++++++++++++-
drivers/net/e1000/igb_ethdev.c | 4 ++
drivers/net/e1000/igb_rxtx.c | 52 ++++++++++++++++++++-
drivers/net/fm10k/fm10k.h | 6 +++
drivers/net/fm10k/fm10k_ethdev.c | 5 ++
drivers/net/fm10k/fm10k_rxtx.c | 50 +++++++++++++++++++-
drivers/net/i40e/i40e_ethdev.c | 3 ++
drivers/net/i40e/i40e_rxtx.c | 72 +++++++++++++++++++++++++++-
drivers/net/i40e/i40e_rxtx.h | 8 ++++
drivers/net/ixgbe/ixgbe_ethdev.c | 3 ++
drivers/net/ixgbe/ixgbe_ethdev.h | 5 +-
drivers/net/ixgbe/ixgbe_rxtx.c | 58 ++++++++++++++++++++++-
drivers/net/ixgbe/ixgbe_rxtx.h | 2 +
lib/librte_ether/rte_ethdev.h | 96 ++++++++++++++++++++++++++++++++++++++
lib/librte_mbuf/rte_mbuf.h | 64 +++++++++++++++++++++++++
lib/librte_net/rte_net.h | 85 +++++++++++++++++++++++++++++++++
20 files changed, 584 insertions(+), 30 deletions(-)
--
1.7.9.5
^ permalink raw reply
* Re: mbuf changes
From: Bruce Richardson @ 2016-10-24 16:25 UTC (permalink / raw)
To: Wiles, Keith; +Cc: Morten Brørup, dev@dpdk.org, Olivier Matz
In-Reply-To: <7910CF2F-7087-4307-A9AC-DE0287104185@intel.com>
On Mon, Oct 24, 2016 at 04:11:33PM +0000, Wiles, Keith wrote:
>
> > On Oct 24, 2016, at 10:49 AM, Morten Brørup <mb@smartsharesystems.com> wrote:
> >
> > First of all: Thanks for a great DPDK Userspace 2016!
> >
> >
> >
> > Continuing the Userspace discussion about Olivier Matz’s proposed mbuf changes...
Thanks for keeping the discussion going!
> >
> >
> >
> > 1.
> >
> > Stephen Hemminger had a noteworthy general comment about keeping metadata for the NIC in the appropriate section of the mbuf: Metadata generated by the NIC’s RX handler belongs in the first cache line, and metadata required by the NIC’s TX handler belongs in the second cache line. This also means that touching the second cache line on ingress should be avoided if possible; and Bruce Richardson mentioned that for this reason m->next was zeroed on free().
> >
Thinking about it, I suspect there are more fields we can reset on free
to save time on alloc. Refcnt, as discussed below is one of them, but so
too could be the nb_segs field and possibly others.
> >
> >
> > 2.
> >
> > There seemed to be consensus that the size of m->refcnt should match the size of m->port because a packet could be duplicated on all physical ports for L3 multicast and L2 flooding.
> >
> > Furthermore, although a single physical machine (i.e. a single server) with 255 physical ports probably doesn’t exist, it might contain more than 255 virtual machines with a virtual port each, so it makes sense extending these mbuf fields from 8 to 16 bits.
>
> I thought we also talked about removing the m->port from the mbuf as it is not really needed.
>
Yes, this was mentioned, and also the option of moving the port value to
the second cacheline, but it appears that NXP are using the port value
in their NIC drivers for passing in metadata, so we'd need their
agreement on any move (or removal).
> >
> >
> >
> > 3.
> >
> > Someone (Bruce Richardson?) suggested moving m->refcnt and m->port to the second cache line, which then generated questions from the audience about the real life purpose of m->port, and if m->port could be removed from the mbuf structure.
> >
> >
> >
> > 4.
> >
> > I suggested using offset -1 for m->refcnt, so m->refcnt becomes 0 on first allocation. This is based on the assumption that other mbuf fields must be zeroed at alloc()/free() anyway, so zeroing m->refcnt is cheaper than setting it to 1.
> >
> > Furthermore (regardless of m->refcnt offset), I suggested that it is not required to modify m->refcnt when allocating and freeing the mbuf, thus saving one write operation on both alloc() and free(). However, this assumes that m->refcnt debugging, e.g. underrun detection, is not required.
I don't think it really matters what sentinal value is used for the
refcnt because it can't be blindly assigned on free like other fields.
However, I think 0 as first reference value becomes more awkward
than 1, because we need to deal with underflow. Consider the situation
where we have two references to the mbuf, so refcnt is 1, and both are
freed at the same time. Since the refcnt is not-zero, then both cores
will do an atomic decrement simultaneously giving a refcnt of -1. We can
then set this back to zero before freeing, however, I'd still prefer to
have refcnt be an accurate value so that it always stays positive, and
we can still set it to "one" on free to avoid having to set on alloc.
Also, if we set refcnt on free rather than alloc, it does set itself up
as a good candidate for moving to the second cacheline. Fast-path
processing does not normally update the value.
> >
> >
> >
> > 5.
> >
> > And here’s something new to think about:
> >
> > m->next already reveals if there are more segments to a packet. Which purpose does m->nb_segs serve that is not already covered by m->next?
It is duplicate info, but nb_segs can be used to check the validity of
the next pointer without having to read the second mbuf cacheline.
Whether it's worth having is something I'm happy enough to discuss,
though.
One other point I'll mention is that we need to have a discussion on
how/where to add in a timestamp value into the mbuf. Personally, I think
it can be in a union with the sequence number value, but I also suspect
that 32-bits of a timestamp is not going to be enough for many.
Thoughts?
/Bruce
^ permalink raw reply
* Re: [PATCH v5 06/21] eal/soc: introduce very essential SoC infra definitions
From: Jan Viktorin @ 2016-10-24 16:21 UTC (permalink / raw)
To: Shreyansh Jain, david.marchand; +Cc: dev, thomas.monjalon, Hemant Agrawal
In-Reply-To: <1477310380-17944-7-git-send-email-shreyansh.jain@nxp.com>
On Mon, 24 Oct 2016 17:29:25 +0530
Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
> From: Jan Viktorin <viktorin@rehivetech.com>
>
> Define initial structures and functions for the SoC infrastructure.
> This patch supports only a very minimal functions for now.
> More features will be added in the following commits.
>
> Includes rte_device/rte_driver inheritance of
> rte_soc_device/rte_soc_driver.
>
> Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
> ---
> app/test/Makefile | 1 +
> app/test/test_soc.c | 90 +++++++++++++++++++++
> lib/librte_eal/common/Makefile | 2 +-
> lib/librte_eal/common/eal_private.h | 4 +
> lib/librte_eal/common/include/rte_soc.h | 138 ++++++++++++++++++++++++++++++++
> 5 files changed, 234 insertions(+), 1 deletion(-)
> create mode 100644 app/test/test_soc.c
> create mode 100644 lib/librte_eal/common/include/rte_soc.h
>
> diff --git a/app/test/Makefile b/app/test/Makefile
[...]
> +++ b/lib/librte_eal/common/include/rte_soc.h
> @@ -0,0 +1,138 @@
[...]
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <stdint.h>
> +#include <inttypes.h>
> +#include <string.h>
> +
> +#include <rte_dev.h>
> +#include <rte_debug.h>
> +
> +struct rte_soc_id {
> + const char *compatible; /**< OF compatible specification */
> + uint64_t priv_data; /**< SoC Driver specific data */
Do you expect this to be a pointer?
> +};
> +
[...]
> +
> +/**
> + * Initialization function for the driver called during SoC probing.
> + */
> +typedef int (soc_devinit_t)(struct rte_soc_driver *, struct rte_soc_device *);
> +
> +/**
> + * Uninitialization function for the driver called during hotplugging.
> + */
> +typedef int (soc_devuninit_t)(struct rte_soc_device *);
> +
> +/**
> + * A structure describing a SoC driver.
> + */
> +struct rte_soc_driver {
> + TAILQ_ENTRY(rte_soc_driver) next; /**< Next in list */
> + struct rte_driver driver; /**< Inherit core driver. */
> + soc_devinit_t *devinit; /**< Device initialization */
> + soc_devuninit_t *devuninit; /**< Device uninitialization */
Shouldn't those functions be named probe/remove?
> + const struct rte_soc_id *id_table; /**< ID table, NULL terminated */
> +};
> +
[...]
> +#endif
--
Jan Viktorin E-mail: Viktorin@RehiveTech.com
System Architect Web: www.RehiveTech.com
RehiveTech
Brno, Czech Republic
^ permalink raw reply
* [PATCH v2 3/3] drivers: register aliases for renamed cryptodev drivers
From: Jan Blunck @ 2016-10-24 16:22 UTC (permalink / raw)
To: dev
Cc: pablo.de.lara.guarch, thomas.monjalon, yuanhan.liu, john.mcnamara,
maxime.coquelin
In-Reply-To: <1477326143-4571-1-git-send-email-jblunck@infradead.org>
This registers the legacy names of the driver being renamed in
commit 2f45703c17ac ("drivers: make driver names consistent").
Signed-off-by: Jan Blunck <jblunck@infradead.org>
Tested-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
---
drivers/crypto/aesni_gcm/aesni_gcm_pmd.c | 1 +
drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c | 1 +
drivers/crypto/kasumi/rte_kasumi_pmd.c | 1 +
drivers/crypto/null/null_crypto_pmd.c | 1 +
drivers/crypto/snow3g/rte_snow3g_pmd.c | 1 +
5 files changed, 5 insertions(+)
diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
index 0b3fd09..dba5e15 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
@@ -529,6 +529,7 @@ static struct rte_vdev_driver aesni_gcm_pmd_drv = {
};
RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_AESNI_GCM_PMD, aesni_gcm_pmd_drv);
+RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_AESNI_GCM_PMD, cryptodev_aesni_gcm_pmd);
RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_AESNI_GCM_PMD,
"max_nb_queue_pairs=<int> "
"max_nb_sessions=<int> "
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index b936735..f07cd07 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -720,6 +720,7 @@ static struct rte_vdev_driver cryptodev_aesni_mb_pmd_drv = {
};
RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_AESNI_MB_PMD, cryptodev_aesni_mb_pmd_drv);
+RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_AESNI_MB_PMD, cryptodev_aesni_mb_pmd);
RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_AESNI_MB_PMD,
"max_nb_queue_pairs=<int> "
"max_nb_sessions=<int> "
diff --git a/drivers/crypto/kasumi/rte_kasumi_pmd.c b/drivers/crypto/kasumi/rte_kasumi_pmd.c
index 11bbf80..b119da2 100644
--- a/drivers/crypto/kasumi/rte_kasumi_pmd.c
+++ b/drivers/crypto/kasumi/rte_kasumi_pmd.c
@@ -656,6 +656,7 @@ static struct rte_vdev_driver cryptodev_kasumi_pmd_drv = {
};
RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_KASUMI_PMD, cryptodev_kasumi_pmd_drv);
+RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_KASUMI_PMD, cryptodev_kasumi_pmd);
RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_KASUMI_PMD,
"max_nb_queue_pairs=<int> "
"max_nb_sessions=<int> "
diff --git a/drivers/crypto/null/null_crypto_pmd.c b/drivers/crypto/null/null_crypto_pmd.c
index a7d3600..c69606b 100644
--- a/drivers/crypto/null/null_crypto_pmd.c
+++ b/drivers/crypto/null/null_crypto_pmd.c
@@ -274,6 +274,7 @@ static struct rte_vdev_driver cryptodev_null_pmd_drv = {
};
RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_NULL_PMD, cryptodev_null_pmd_drv);
+RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_NULL_PMD, cryptodev_null_pmd);
RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_NULL_PMD,
"max_nb_queue_pairs=<int> "
"max_nb_sessions=<int> "
diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd.c b/drivers/crypto/snow3g/rte_snow3g_pmd.c
index a794251..3b4292a 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd.c
@@ -644,6 +644,7 @@ static struct rte_vdev_driver cryptodev_snow3g_pmd_drv = {
};
RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_SNOW3G_PMD, cryptodev_snow3g_pmd_drv);
+RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_SNOW3G_PMD, cryptodev_snow3g_pmd);
RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_SNOW3G_PMD,
"max_nb_queue_pairs=<int> "
"max_nb_sessions=<int> "
--
2.6.6
^ permalink raw reply related
* [PATCH v2 2/3] drivers: register aliases for renamed VDEV drivers
From: Jan Blunck @ 2016-10-24 16:22 UTC (permalink / raw)
To: dev
Cc: pablo.de.lara.guarch, thomas.monjalon, yuanhan.liu, john.mcnamara,
maxime.coquelin
In-Reply-To: <1477326143-4571-1-git-send-email-jblunck@infradead.org>
This registers the legacy names of the driver being renamed in
commit 2f45703c17ac ("drivers: make driver names consistent").
Signed-off-by: Jan Blunck <jblunck@infradead.org>
---
drivers/net/af_packet/rte_eth_af_packet.c | 1 +
drivers/net/bonding/rte_eth_bond_pmd.c | 1 +
drivers/net/mpipe/mpipe_tilegx.c | 2 ++
drivers/net/null/rte_eth_null.c | 1 +
drivers/net/pcap/rte_eth_pcap.c | 1 +
drivers/net/ring/rte_eth_ring.c | 1 +
drivers/net/vhost/rte_eth_vhost.c | 1 +
drivers/net/virtio/virtio_user_ethdev.c | 1 +
drivers/net/xenvirt/rte_eth_xenvirt.c | 1 +
9 files changed, 10 insertions(+)
diff --git a/drivers/net/af_packet/rte_eth_af_packet.c b/drivers/net/af_packet/rte_eth_af_packet.c
index 201c1be..ff45068 100644
--- a/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/drivers/net/af_packet/rte_eth_af_packet.c
@@ -895,6 +895,7 @@ static struct rte_vdev_driver pmd_af_packet_drv = {
};
RTE_PMD_REGISTER_VDEV(net_af_packet, pmd_af_packet_drv);
+RTE_PMD_REGISTER_ALIAS(net_af_packet, eth_af_packet);
RTE_PMD_REGISTER_PARAM_STRING(net_af_packet,
"iface=<string> "
"qpairs=<int> "
diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
index 9e38ec9..9df245e 100644
--- a/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -2560,6 +2560,7 @@ static struct rte_vdev_driver bond_drv = {
};
RTE_PMD_REGISTER_VDEV(net_bonding, bond_drv);
+RTE_PMD_REGISTER_ALIAS(net_bonding, eth_bond);
RTE_PMD_REGISTER_PARAM_STRING(net_bonding,
"slave=<ifc> "
diff --git a/drivers/net/mpipe/mpipe_tilegx.c b/drivers/net/mpipe/mpipe_tilegx.c
index adf299b..fbbbb00 100644
--- a/drivers/net/mpipe/mpipe_tilegx.c
+++ b/drivers/net/mpipe/mpipe_tilegx.c
@@ -1632,7 +1632,9 @@ static struct rte_vdev_driver pmd_mpipe_gbe_drv = {
};
RTE_PMD_REGISTER_VDEV(net_mpipe_xgbe, pmd_mpipe_xgbe_drv);
+RTE_PMD_REGISTER_ALIAS(net_mpipe_xgbe, xgbe);
RTE_PMD_REGISTER_VDEV(net_mpipe_gbe, pmd_mpipe_gbe_drv);
+RTE_PMD_REGISTER_ALIAS(net_mpipe_gbe, gbe);
static void __attribute__((constructor, used))
mpipe_init_contexts(void)
diff --git a/drivers/net/null/rte_eth_null.c b/drivers/net/null/rte_eth_null.c
index 0b7cc37..836d982 100644
--- a/drivers/net/null/rte_eth_null.c
+++ b/drivers/net/null/rte_eth_null.c
@@ -692,6 +692,7 @@ static struct rte_vdev_driver pmd_null_drv = {
};
RTE_PMD_REGISTER_VDEV(net_null, pmd_null_drv);
+RTE_PMD_REGISTER_ALIAS(net_null, eth_null);
RTE_PMD_REGISTER_PARAM_STRING(net_null,
"size=<int> "
"copy=<int>");
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
index 0c4711d..0162f44 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/rte_eth_pcap.c
@@ -1065,6 +1065,7 @@ static struct rte_vdev_driver pmd_pcap_drv = {
};
RTE_PMD_REGISTER_VDEV(net_pcap, pmd_pcap_drv);
+RTE_PMD_REGISTER_ALIAS(net_pcap, eth_pcap);
RTE_PMD_REGISTER_PARAM_STRING(net_pcap,
ETH_PCAP_RX_PCAP_ARG "=<string> "
ETH_PCAP_TX_PCAP_ARG "=<string> "
diff --git a/drivers/net/ring/rte_eth_ring.c b/drivers/net/ring/rte_eth_ring.c
index ee1fb76..6d2a8c1 100644
--- a/drivers/net/ring/rte_eth_ring.c
+++ b/drivers/net/ring/rte_eth_ring.c
@@ -629,5 +629,6 @@ static struct rte_vdev_driver pmd_ring_drv = {
};
RTE_PMD_REGISTER_VDEV(net_ring, pmd_ring_drv);
+RTE_PMD_REGISTER_ALIAS(net_ring, eth_ring);
RTE_PMD_REGISTER_PARAM_STRING(net_ring,
ETH_RING_NUMA_NODE_ACTION_ARG "=name:node:action(ATTACH|CREATE)");
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 6f58476..766d4ef 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -1244,6 +1244,7 @@ static struct rte_vdev_driver pmd_vhost_drv = {
};
RTE_PMD_REGISTER_VDEV(net_vhost, pmd_vhost_drv);
+RTE_PMD_REGISTER_ALIAS(net_vhost, eth_vhost);
RTE_PMD_REGISTER_PARAM_STRING(net_vhost,
"iface=<ifc> "
"queues=<int>");
diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c
index bfdc3d0..406beea 100644
--- a/drivers/net/virtio/virtio_user_ethdev.c
+++ b/drivers/net/virtio/virtio_user_ethdev.c
@@ -479,6 +479,7 @@ static struct rte_vdev_driver virtio_user_driver = {
};
RTE_PMD_REGISTER_VDEV(net_virtio_user, virtio_user_driver);
+RTE_PMD_REGISTER_ALIAS(net_virtio_user, virtio_user);
RTE_PMD_REGISTER_PARAM_STRING(net_virtio_user,
"path=<path> "
"mac=<mac addr> "
diff --git a/drivers/net/xenvirt/rte_eth_xenvirt.c b/drivers/net/xenvirt/rte_eth_xenvirt.c
index 5a897b9..c08a056 100644
--- a/drivers/net/xenvirt/rte_eth_xenvirt.c
+++ b/drivers/net/xenvirt/rte_eth_xenvirt.c
@@ -765,5 +765,6 @@ static struct rte_vdev_driver pmd_xenvirt_drv = {
};
RTE_PMD_REGISTER_VDEV(net_xenvirt, pmd_xenvirt_drv);
+RTE_PMD_REGISTER_ALIAS(net_xenvirt, eth_xenvirt);
RTE_PMD_REGISTER_PARAM_STRING(net_xenvirt,
"mac=<mac addr>");
--
2.6.6
^ permalink raw reply related
* [PATCH v2 1/3] drivers: add name alias registration for rte_driver
From: Jan Blunck @ 2016-10-24 16:22 UTC (permalink / raw)
To: dev
Cc: pablo.de.lara.guarch, thomas.monjalon, yuanhan.liu, john.mcnamara,
maxime.coquelin
In-Reply-To: <1476956223-30308-1-git-send-email-jblunck@infradead.org>
This adds infrastructure for drivers to allow being requested by an alias
so that a renamed driver can still get loaded by its legacy name.
Signed-off-by: Jan Blunck <jblunck@infradead.org>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
Tested-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
---
lib/librte_eal/common/eal_common_vdev.c | 8 ++++++++
lib/librte_eal/common/include/rte_dev.h | 1 +
lib/librte_eal/common/include/rte_vdev.h | 5 +++++
3 files changed, 14 insertions(+)
diff --git a/lib/librte_eal/common/eal_common_vdev.c b/lib/librte_eal/common/eal_common_vdev.c
index 8b05f50..0ff2377 100644
--- a/lib/librte_eal/common/eal_common_vdev.c
+++ b/lib/librte_eal/common/eal_common_vdev.c
@@ -79,6 +79,14 @@ rte_eal_vdev_init(const char *name, const char *args)
return driver->probe(name, args);
}
+ /* Give new names precedence over aliases. */
+ TAILQ_FOREACH(driver, &vdev_driver_list, next) {
+ if (driver->driver.alias &&
+ !strncmp(driver->driver.alias, name,
+ strlen(driver->driver.alias)))
+ return driver->probe(name, args);
+ }
+
RTE_LOG(ERR, EAL, "no driver found for %s\n", name);
return -EINVAL;
}
diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index b3873bd..8840380 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -149,6 +149,7 @@ void rte_eal_device_remove(struct rte_device *dev);
struct rte_driver {
TAILQ_ENTRY(rte_driver) next; /**< Next in list. */
const char *name; /**< Driver name. */
+ const char *alias; /**< Driver alias. */
};
/**
diff --git a/lib/librte_eal/common/include/rte_vdev.h b/lib/librte_eal/common/include/rte_vdev.h
index 97260b2..784e837 100644
--- a/lib/librte_eal/common/include/rte_vdev.h
+++ b/lib/librte_eal/common/include/rte_vdev.h
@@ -83,13 +83,18 @@ void rte_eal_vdrv_unregister(struct rte_vdev_driver *driver);
#define RTE_PMD_REGISTER_VDEV(nm, vdrv)\
RTE_INIT(vdrvinitfn_ ##vdrv);\
+static const char *vdrvinit_ ## nm ## _alias;\
static void vdrvinitfn_ ##vdrv(void)\
{\
(vdrv).driver.name = RTE_STR(nm);\
+ (vdrv).driver.alias = vdrvinit_ ## nm ## _alias;\
rte_eal_vdrv_register(&vdrv);\
} \
RTE_PMD_EXPORT_NAME(nm, __COUNTER__)
+#define RTE_PMD_REGISTER_ALIAS(nm, alias)\
+static const char *vdrvinit_ ## nm ## _alias = RTE_STR(alias)
+
#ifdef __cplusplus
}
#endif
--
2.6.6
^ permalink raw reply related
* Re: [PATCH v5 01/21] eal: generalize PCI kernel driver enum to EAL
From: Jan Viktorin @ 2016-10-24 16:13 UTC (permalink / raw)
To: Shreyansh Jain; +Cc: dev, thomas.monjalon, david.marchand
In-Reply-To: <1477310380-17944-2-git-send-email-shreyansh.jain@nxp.com>
On Mon, 24 Oct 2016 17:29:20 +0530
Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
> From: Jan Viktorin <viktorin@rehivetech.com>
>
> Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
I think, there is no reason to prevent merging this. Feel free to add:
Acked-by: Jan Viktorin <viktorin@rehivetech.com>
^ permalink raw reply
* Re: [PATCH v4 11/17] eal/soc: add default scan for Soc devices
From: Jan Viktorin @ 2016-10-24 16:11 UTC (permalink / raw)
To: Shreyansh Jain
Cc: dev@dpdk.org, thomas.monjalon@6wind.com, david.marchand@6wind.com
In-Reply-To: <78be76eb-2ce5-59be-5a74-fd7670364710@nxp.com>
On Mon, 24 Oct 2016 17:38:29 +0530
Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
> Hi Jan,
>
> On Sunday 16 October 2016 12:42 PM, Shreyansh Jain wrote:
> > Hi Jan,
> >
[...]
> >>
> >>> +
> >>> +int
> >>> +rte_eal_soc_scan(void)
> >>
> >> What about naming it rte_eal_soc_scan_default? This would underline the
> >> fact that this function can be replaced.
> >
> > Yes, that would be in sync with match default. I will do it.
>
> In v5 I have replaced the name with rte_eal_soc_platform_bus(). This is
> long but it does exactly what the name states - scan for platform bus.
> This is still a helper.
OK.
>
> >
> >>
> >> Second, this is for the 7/17 patch:
> >>
> >> -/* register a driver */
> >> void
> >> rte_eal_soc_register(struct rte_soc_driver *driver)
> >> {
> >> + /* For a valid soc driver, match and scan function
> >> + * should be provided.
> >> + */
> >> + RTE_VERIFY(driver != NULL);
> >> + RTE_VERIFY(driver->match_fn != NULL);
> >> + RTE_VERIFY(driver->scan_fn != NULL);
> >>
> >> What about setting the match_fn and scan_fn to default implementations if
> >> they
> >> are NULL? This would make the standard/default approach easier to use.
> >>
> >> TAILQ_INSERT_TAIL(&soc_driver_list, driver, next);
> >> }
> >
> > I am not in favor of a forced default. What if user never intended it - it would lead to wrong scan being used and only intimation which can provided to user is a log.
> > Selecting such functions should be a model of PMD - one which is enforced.
>
> As mentioned before, I am not in favor of a 'default' implementation.
> Thus, I would rather call these functions as 'helpers' rather than defaults.
Hmm, OK.
Jan
>
> [...]
>
> -
> Shreyansh
--
Jan Viktorin E-mail: Viktorin@RehiveTech.com
System Architect Web: www.RehiveTech.com
RehiveTech
Brno, Czech Republic
^ permalink raw reply
* Re: mbuf changes
From: Wiles, Keith @ 2016-10-24 16:11 UTC (permalink / raw)
To: Morten Brørup; +Cc: dev@dpdk.org, Olivier Matz
In-Reply-To: <98CBD80474FA8B44BF855DF32C47DC359EA8B1@smartserver.smartshare.dk>
> On Oct 24, 2016, at 10:49 AM, Morten Brørup <mb@smartsharesystems.com> wrote:
>
> First of all: Thanks for a great DPDK Userspace 2016!
>
>
>
> Continuing the Userspace discussion about Olivier Matz’s proposed mbuf changes...
>
>
>
> 1.
>
> Stephen Hemminger had a noteworthy general comment about keeping metadata for the NIC in the appropriate section of the mbuf: Metadata generated by the NIC’s RX handler belongs in the first cache line, and metadata required by the NIC’s TX handler belongs in the second cache line. This also means that touching the second cache line on ingress should be avoided if possible; and Bruce Richardson mentioned that for this reason m->next was zeroed on free().
>
>
>
> 2.
>
> There seemed to be consensus that the size of m->refcnt should match the size of m->port because a packet could be duplicated on all physical ports for L3 multicast and L2 flooding.
>
> Furthermore, although a single physical machine (i.e. a single server) with 255 physical ports probably doesn’t exist, it might contain more than 255 virtual machines with a virtual port each, so it makes sense extending these mbuf fields from 8 to 16 bits.
I thought we also talked about removing the m->port from the mbuf as it is not really needed.
>
>
>
> 3.
>
> Someone (Bruce Richardson?) suggested moving m->refcnt and m->port to the second cache line, which then generated questions from the audience about the real life purpose of m->port, and if m->port could be removed from the mbuf structure.
>
>
>
> 4.
>
> I suggested using offset -1 for m->refcnt, so m->refcnt becomes 0 on first allocation. This is based on the assumption that other mbuf fields must be zeroed at alloc()/free() anyway, so zeroing m->refcnt is cheaper than setting it to 1.
>
> Furthermore (regardless of m->refcnt offset), I suggested that it is not required to modify m->refcnt when allocating and freeing the mbuf, thus saving one write operation on both alloc() and free(). However, this assumes that m->refcnt debugging, e.g. underrun detection, is not required.
>
>
>
> 5.
>
> And here’s something new to think about:
>
> m->next already reveals if there are more segments to a packet. Which purpose does m->nb_segs serve that is not already covered by m->next?
>
>
>
>
>
> Med venlig hilsen / kind regards
>
>
>
> Morten Brørup
>
> CTO
>
>
>
>
>
> SmartShare Systems A/S
>
> Tonsbakken 16-18
>
> DK-2740 Skovlunde
>
> Denmark
>
>
>
> Office +45 70 20 00 93
>
> Direct +45 89 93 50 22
>
> Mobile +45 25 40 82 12
>
>
>
> mb@smartsharesystems.com <mailto:mb@smartsharesystems.com>
>
> www.smartsharesystems.com <https://www.smartsharesystems.com/>
>
>
>
Regards,
Keith
^ permalink raw reply
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