From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pa0-f42.google.com (mail-pa0-f42.google.com [209.85.220.42]) by dpdk.org (Postfix) with ESMTP id A8D5C8E72 for ; Fri, 11 Dec 2015 17:59:16 +0100 (CET) Received: by pacwq6 with SMTP id wq6so67930312pac.1 for ; Fri, 11 Dec 2015 08:59:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=dOAce1npV599FhfWQDBfwyZAIJ6qyFxs+kpTTBKz3iE=; b=QYPhs+Z3owz0w56rEXNJXIo9BO3VlmQ1QzX4Vaxd54drCjhWau2bjc/o2dL4g/+VL5 +RC2QOc/aUpgeQ6E4WFkPftwmb7YAn5PEEFwsCRGcXuVEvIMllu9mUpC8IDG8bpaNslR x0j3JGssUQazWBIhoe4PrrArU06Jf4Vyc/99mJ/0EndMH50X/CYRmoFQ75F7SljRZK9U qJMYTZg3SWBgf432eQq8ivKzmyRLQJEq48NzqiN2p9A1j7Okgf94kcUpVubW1yXcQ2pJ kk/ATWE2lOiGZDqM5Js2wCHweptwLMJWZi5HVseNvCul7+Vpu/syZSINqmf5Ti5L6PV4 bDPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=dOAce1npV599FhfWQDBfwyZAIJ6qyFxs+kpTTBKz3iE=; b=PnH1KJzDRTxFX8X90M6AUdPdCMEzQanHy+zT7tjLZxbgGAxr0zI7VacGV32yDBiGs2 OJGfeSvryf1vIh44mnYvlyO00GED/HA33RLx0DBVGglw5HpnwjW3ffpimif00icEWMmG AN6+36A6QvtR2rhw3hAhlumd/A0p+oTA2GQP8MvN3eUZvKBg3NWm7upFam2wmYH+G8q5 4iC831EsK0REj4Y/ZUwmtI6Rmxv2tGbvZZlozD27mbRvLoxL9C3mQDr/qLticsayD+FV s80mvGZd+Y+lZzpcsokQvOFijbFSTOAxQra0Oa3MykxUcotIn1DIqdnyUV4vuy44RpJC t0rw== X-Gm-Message-State: ALoCoQlVJgrgCS63n7QJTtR7WpNCdpu6sO3KEpXqS9sqkZxwxAk/T//HxJq0CfmkCW70xefomJ4fB/rHUigKcm8pnRgDxZfrnQ== X-Received: by 10.66.150.198 with SMTP id uk6mr26277153pab.70.1449853156050; Fri, 11 Dec 2015 08:59:16 -0800 (PST) Received: from xeon-e3.home.lan (static-50-53-82-155.bvtn.or.frontiernet.net. [50.53.82.155]) by smtp.gmail.com with ESMTPSA id c1sm26686699pas.1.2015.12.11.08.59.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 11 Dec 2015 08:59:14 -0800 (PST) From: Stephen Hemminger To: helin.zhang@intel.com, konstantin.ananyev@intel.com Date: Fri, 11 Dec 2015 08:59:23 -0800 Message-Id: <1449853163-25673-1-git-send-email-stephen@networkplumber.org> X-Mailer: git-send-email 2.1.4 Cc: dev@dpdk.org Subject: [dpdk-dev] [PATCH] ixgbe: Discard SRIOV transparent vlan packet headers. X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 11 Dec 2015 16:59:17 -0000 From: Tom Kiely SRIOV VFs support "transparent" vlans. Traffic from/to a VM associated with a VF is tagged/untagged with the specified vlan in a manner intended to be totally transparent to the VM. The vlan is specified by "ip link set vf vlan ". The VM is not configured for any vlan on the VF and the VM should never see these transparent vlan headers for that reason. However, in practice these vlan headers are being received by the VM which discards the packets as that vlan is unknown to it. The Linux kernel explicitly discards such vlan headers but DPDK does not. This patch mirrors the kernel behaviour for SRIOV VFs only Signed-off-by: Tom Kiely Signed-off-by: Stephen Hemminger --- drivers/net/ixgbe/ixgbe_ethdev.c | 10 ++++---- drivers/net/ixgbe/ixgbe_ethdev.h | 36 +++++++++++++++++++++++++++ drivers/net/ixgbe/ixgbe_rxtx.c | 50 ++++++++++++++++++++++++++++++++++---- drivers/net/ixgbe/ixgbe_rxtx.h | 27 ++++++++++++++++++++ drivers/net/ixgbe/ixgbe_rxtx_vec.c | 10 ++++++++ 5 files changed, 123 insertions(+), 10 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c index 1b6cd8e..0987bf9 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.c +++ b/drivers/net/ixgbe/ixgbe_ethdev.c @@ -516,7 +516,7 @@ static const struct eth_dev_ops ixgbevf_eth_dev_ops = { .vlan_filter_set = ixgbevf_vlan_filter_set, .vlan_strip_queue_set = ixgbevf_vlan_strip_queue_set, .vlan_offload_set = ixgbevf_vlan_offload_set, - .rx_queue_setup = ixgbe_dev_rx_queue_setup, + .rx_queue_setup = ixgbevf_dev_rx_queue_setup, .rx_queue_release = ixgbe_dev_rx_queue_release, .rx_descriptor_done = ixgbe_dev_rx_descriptor_done, .tx_queue_setup = ixgbe_dev_tx_queue_setup, @@ -1492,8 +1492,8 @@ ixgbe_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) uint32_t vid_idx; uint32_t vid_bit; - vid_idx = (uint32_t) ((vlan_id >> 5) & 0x7F); - vid_bit = (uint32_t) (1 << (vlan_id & 0x1F)); + vid_idx = ixgbe_vfta_index(vlan_id); + vid_bit = ixgbe_vfta_bit(vlan_id); vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(vid_idx)); if (on) vfta |= vid_bit; @@ -3965,8 +3965,8 @@ ixgbevf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) PMD_INIT_LOG(ERR, "Unable to set VF vlan"); return ret; } - vid_idx = (uint32_t) ((vlan_id >> 5) & 0x7F); - vid_bit = (uint32_t) (1 << (vlan_id & 0x1F)); + vid_idx = ixgbe_vfta_index(vlan_id); + vid_bit = ixgbe_vfta_bit(vlan_id); /* Save what we set and retore it after device reset */ if (on) diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h index d26771a..44411e4 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.h +++ b/drivers/net/ixgbe/ixgbe_ethdev.h @@ -340,6 +340,11 @@ int ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool); +int ixgbevf_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, + uint16_t nb_rx_desc, unsigned int socket_id, + const struct rte_eth_rxconf *rx_conf, + struct rte_mempool *mb_pool); + int ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, uint16_t nb_tx_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf); @@ -436,4 +441,35 @@ uint32_t ixgbe_convert_vm_rx_mask_to_val(uint16_t rx_mask, uint32_t orig_val); int ixgbe_fdir_ctrl_func(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg); + +/* + * Calculate index in vfta array of the 32 bit value enclosing + * a given vlan id + */ +static inline uint32_t +ixgbe_vfta_index(uint16_t vlan) +{ + return (vlan >> 5) & 0x7f; +} + +/* + * Calculate vfta array entry bitmask for vlan id within the + * enclosing 32 bit entry. + */ +static inline uint32_t +ixgbe_vfta_bit(uint16_t vlan) +{ + return 1 << (vlan & 0x1f); +} + +/* + * Check in the vfta bit array if the bit corresponding to + * the given vlan is set. + */ +static inline bool +ixgbe_vfta_is_vlan_set(const struct ixgbe_vfta *vfta, uint16_t vlan) +{ + return (vfta->vfta[ixgbe_vfta_index(vlan)] & ixgbe_vfta_bit(vlan)) != 0; +} + #endif /* _IXGBE_ETHDEV_H_ */ diff --git a/drivers/net/ixgbe/ixgbe_rxtx.c b/drivers/net/ixgbe/ixgbe_rxtx.c index 52a263c..5ab029d 100644 --- a/drivers/net/ixgbe/ixgbe_rxtx.c +++ b/drivers/net/ixgbe/ixgbe_rxtx.c @@ -1171,14 +1171,21 @@ ixgbe_rx_fill_from_stage(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct rte_mbuf **stage = &rxq->rx_stage[rxq->rx_next_avail]; + const struct rte_eth_dev *dev; + const struct ixgbe_vfta *vfta; int i; + dev = &rte_eth_devices[rxq->port_id]; + vfta = IXGBE_DEV_PRIVATE_TO_VFTA(dev->data->dev_private); + /* how many packets are ready to return? */ nb_pkts = (uint16_t)RTE_MIN(nb_pkts, rxq->rx_nb_avail); /* copy mbuf pointers to the application's packet list */ - for (i = 0; i < nb_pkts; ++i) + for (i = 0; i < nb_pkts; ++i) { rx_pkts[i] = stage[i]; + ixgbe_unknown_vlan_sw_filter_hdr(rx_pkts[i], vfta, rxq); + } /* update internal queue state */ rxq->rx_nb_avail = (uint16_t)(rxq->rx_nb_avail - nb_pkts); @@ -1188,10 +1195,9 @@ ixgbe_rx_fill_from_stage(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts, } static inline uint16_t -rx_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, +rx_recv_pkts(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { - struct ixgbe_rx_queue *rxq = (struct ixgbe_rx_queue *)rx_queue; uint16_t nb_rx = 0; /* Any previously recv'd pkts will be returned from the Rx stage */ @@ -1252,19 +1258,20 @@ ixgbe_recv_pkts_bulk_alloc(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { uint16_t nb_rx; + struct ixgbe_rx_queue *rxq = (struct ixgbe_rx_queue *)rx_queue; if (unlikely(nb_pkts == 0)) return 0; if (likely(nb_pkts <= RTE_PMD_IXGBE_RX_MAX_BURST)) - return rx_recv_pkts(rx_queue, rx_pkts, nb_pkts); + return rx_recv_pkts(rxq, rx_pkts, nb_pkts); /* request is relatively large, chunk it up */ nb_rx = 0; while (nb_pkts) { uint16_t ret, n; n = (uint16_t)RTE_MIN(nb_pkts, RTE_PMD_IXGBE_RX_MAX_BURST); - ret = rx_recv_pkts(rx_queue, &rx_pkts[nb_rx], n); + ret = rx_recv_pkts(rxq, &rx_pkts[nb_rx], n); nb_rx = (uint16_t)(nb_rx + ret); nb_pkts = (uint16_t)(nb_pkts - ret); if (ret < n) @@ -1294,6 +1301,8 @@ ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_rx; uint16_t nb_hold; uint64_t pkt_flags; + const struct rte_eth_dev *dev; + const struct ixgbe_vfta *vfta; nb_rx = 0; nb_hold = 0; @@ -1301,6 +1310,9 @@ ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, rx_id = rxq->rx_tail; rx_ring = rxq->rx_ring; sw_ring = rxq->sw_ring; + dev = &rte_eth_devices[rxq->port_id]; + vfta = IXGBE_DEV_PRIVATE_TO_VFTA(dev->data->dev_private); + while (nb_rx < nb_pkts) { /* * The order of operations here is important as the DD status @@ -1418,6 +1430,8 @@ ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, rxm->ol_flags = pkt_flags; rxm->packet_type = ixgbe_rxd_pkt_info_to_pkt_type(pkt_info); + ixgbe_unknown_vlan_sw_filter_hdr(rxm, vfta, rxq); + if (likely(pkt_flags & PKT_RX_RSS_HASH)) rxm->hash.rss = rte_le_to_cpu_32( rxd.wb.lower.hi_dword.rss); @@ -1557,6 +1571,11 @@ ixgbe_recv_pkts_lro(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts, uint16_t nb_rx = 0; uint16_t nb_hold = rxq->nb_rx_hold; uint16_t prev_id = rxq->rx_tail; + const struct rte_eth_dev *dev; + const struct ixgbe_vfta *vfta; + + dev = &rte_eth_devices[rxq->port_id]; + vfta = IXGBE_DEV_PRIVATE_TO_VFTA(dev->data->dev_private); while (nb_rx < nb_pkts) { bool eop; @@ -1779,6 +1798,8 @@ next_desc: rte_packet_prefetch((char *)first_seg->buf_addr + first_seg->data_off); + ixgbe_unknown_vlan_sw_filter_hdr(first_seg, vfta, rxq); + /* * Store the mbuf address into the next entry of the array * of returned packets. @@ -2480,6 +2501,25 @@ ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev, return 0; } +int __attribute__((cold)) +ixgbevf_dev_rx_queue_setup(struct rte_eth_dev *dev, + uint16_t queue_idx, + uint16_t nb_desc, + unsigned int socket_id, + const struct rte_eth_rxconf *rx_conf, + struct rte_mempool *mp) +{ + struct ixgbe_rx_queue *rxq; + + ixgbe_dev_rx_queue_setup(dev, queue_idx, nb_desc, socket_id, + rx_conf, mp); + + rxq = dev->data->rx_queues[queue_idx]; + rxq->filter_unknown_vlan_hdrs = true; + + return 0; +} + uint32_t ixgbe_dev_rx_queue_count(struct rte_eth_dev *dev, uint16_t rx_queue_id) { diff --git a/drivers/net/ixgbe/ixgbe_rxtx.h b/drivers/net/ixgbe/ixgbe_rxtx.h index 475a800..3bfceda 100644 --- a/drivers/net/ixgbe/ixgbe_rxtx.h +++ b/drivers/net/ixgbe/ixgbe_rxtx.h @@ -146,6 +146,7 @@ struct ixgbe_rx_queue { uint8_t crc_len; /**< 0 if CRC stripped, 4 otherwise. */ uint8_t drop_en; /**< If not 0, set SRRCTL.Drop_En. */ uint8_t rx_deferred_start; /**< not in global dev start. */ + uint8_t filter_unknown_vlan_hdrs; /** need to alloc dummy mbuf, for wraparound when scanning hw ring */ struct rte_mbuf fake_mbuf; /** hold packets to return to application */ @@ -307,5 +308,31 @@ uint16_t ixgbe_xmit_pkts_vec(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); int ixgbe_txq_vec_setup(struct ixgbe_tx_queue *txq); +#define VLAN_VID_MASK 0x0fff + +/* + * Filter out vlan headers if no vlan configured. + * + * One use case for this is SRIOV VFs with transparent + * vlans. These vlan headers are currently seen by the DPDK + * client and may cause affected packets to be dropped as + * that vlan is not configured. + */ +static inline void +ixgbe_unknown_vlan_sw_filter_hdr(struct rte_mbuf *m, + const struct ixgbe_vfta *vfta, + struct ixgbe_rx_queue *rxq) +{ + uint16_t vlan; + + if (rxq->filter_unknown_vlan_hdrs && (m->ol_flags & PKT_RX_VLAN_PKT)) { + vlan = m->vlan_tci & VLAN_VID_MASK; + if (!ixgbe_vfta_is_vlan_set(vfta, vlan)) { + m->vlan_tci = 0; + m->ol_flags &= ~PKT_RX_VLAN_PKT; + } + } +} + #endif /* RTE_IXGBE_INC_VECTOR */ #endif /* _IXGBE_RXTX_H_ */ diff --git a/drivers/net/ixgbe/ixgbe_rxtx_vec.c b/drivers/net/ixgbe/ixgbe_rxtx_vec.c index ccd93c7..a710af1 100644 --- a/drivers/net/ixgbe/ixgbe_rxtx_vec.c +++ b/drivers/net/ixgbe/ixgbe_rxtx_vec.c @@ -206,6 +206,10 @@ static inline uint16_t _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts, uint8_t *split_packet) { + const struct rte_eth_dev *dev + = &rte_eth_devices[rxq->port_id]; + const struct ixgbe_vfta *vfta + = IXGBE_DEV_PRIVATE_TO_VFTA(dev->data->dev_private); volatile union ixgbe_adv_rx_desc *rxdp; struct ixgbe_rx_entry *sw_ring; uint16_t nb_pkts_recd; @@ -350,8 +354,11 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts, /* D.3 copy final 3,4 data to rx_pkts */ _mm_storeu_si128((void *)&rx_pkts[pos+3]->rx_descriptor_fields1, pkt_mb4); + ixgbe_unknown_vlan_sw_filter_hdr(rx_pkts[pos + 3], vfta, rxq); + _mm_storeu_si128((void *)&rx_pkts[pos+2]->rx_descriptor_fields1, pkt_mb3); + ixgbe_unknown_vlan_sw_filter_hdr(rx_pkts[pos + 2], vfta, rxq); /* D.2 pkt 1,2 set in_port/nb_seg and remove crc */ pkt_mb2 = _mm_add_epi16(pkt_mb2, crc_adjust); @@ -391,8 +398,11 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts, /* D.3 copy final 1,2 data to rx_pkts */ _mm_storeu_si128((void *)&rx_pkts[pos+1]->rx_descriptor_fields1, pkt_mb2); + ixgbe_unknown_vlan_sw_filter_hdr(rx_pkts[pos + 1], vfta, rxq); + _mm_storeu_si128((void *)&rx_pkts[pos]->rx_descriptor_fields1, pkt_mb1); + ixgbe_unknown_vlan_sw_filter_hdr(rx_pkts[pos], vfta, rxq); /* C.4 calc avaialbe number of desc */ var = __builtin_popcountll(_mm_cvtsi128_si64(staterr)); -- 2.1.4