* Re: [PATCH v4] vhost: Add indirect descriptors support to the TX path
From: Xu, Qian Q @ 2016-10-28 6:05 UTC (permalink / raw)
To: Maxime Coquelin, Yuanhan Liu
Cc: dev@dpdk.org, vkaplans@redhat.com, mst@redhat.com
In-Reply-To: <ba08f796-8a0e-85c9-ad75-62a782e6249f@redhat.com>
In my BDW-EP platform(similar to HSW), I can also see the performance drop. So what's the next step now?
Intel CPU GEN:
SNB-->IVB--->HSW-->BDW-EP
-----Original Message-----
From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Maxime Coquelin
Sent: Thursday, October 27, 2016 6:53 PM
To: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Cc: mst@redhat.com; dev@dpdk.org; vkaplans@redhat.com
Subject: Re: [dpdk-dev] [PATCH v4] vhost: Add indirect descriptors support to the TX path
On 10/27/2016 12:33 PM, Yuanhan Liu wrote:
> On Thu, Oct 27, 2016 at 11:10:34AM +0200, Maxime Coquelin wrote:
>> Hi Zhihong,
>>
>> On 10/27/2016 11:00 AM, Wang, Zhihong wrote:
>>> Hi Maxime,
>>>
>>> Seems indirect desc feature is causing serious performance
>>> degradation on Haswell platform, about 20% drop for both mrg=on and
>>> mrg=off (--txqflags=0xf00, non-vector version), both iofwd and
>>> macfwd.
>> I tested PVP (with macswap on guest) and Txonly/Rxonly on an Ivy
>> Bridge platform, and didn't faced such a drop.
>
> I was actually wondering that may be the cause. I tested it with my
> IvyBridge server as well, I saw no drop.
Sorry, mine is a SandyBridge, not IvyBridge.
^ permalink raw reply
* Re: Unable to change source MAC address of packet
From: Lu, Wenzhuo @ 2016-10-28 5:57 UTC (permalink / raw)
To: Padam Jeet Singh, Wiles, Keith; +Cc: dev@dpdk.org
In-Reply-To: <24C3E15F-108D-4812-985B-61B10FDDF69E@inventum.net>
Hi Padam,
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Padam Jeet Singh
> Sent: Thursday, October 27, 2016 10:45 PM
> To: Wiles, Keith
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] Unable to change source MAC address of packet
>
>
> > On 27-Oct-2016, at 7:37 pm, Wiles, Keith <keith.wiles@intel.com> wrote:
> >
> >
> >> On Oct 27, 2016, at 6:33 AM, Padam Jeet Singh <padam.singh@inventum.net>
> wrote:
> >>
> >> Hi,
> >>
> >> I am crafting a packet in which the source MAC address as set in the Ethernet
> header is different than the transmit port’s default MAC address. A packet
> capture of the packets coming out of this port however comes with source MAC
> address of the port’s default MAC address.
> >>
> >> Altering the destination MAC address works fine and shows up correctly in
> packet capture.
> >>
> >> The underlying network interface is an i210 and some logs added to the
> eth_igb_xmit_pkts function show that the packets I have crafted indeed are
> reaching the driver with the source MAC address set in the packet code of the
> application.
> >>
> >> How can I disable this automatic source MAC address setting?
> >
> > The packets sent with rte_eth_tx_burst() are not forced to a give MAC address.
> If you are using something on top of DPDK like Pktgen or OVS or something,
> then it may try to force a source MAC address.
>
> No… not using pktgen or OVS. Plain simple code to take a packets from a KNI,
> change source mac address on all received packets, and then tx_burst them to a
> port.
>
> > Maybe the hardware does it, but we need to know the NIC being used and
> then someone maybe able to answer. I do not know of any Intel NICs do that.
>
> Intel i210 NIC (gigabit Ethernet) is being used. I have gone through the i210
> documentation and can’t see anything specific to setting of MAC address in
> hardware for TX side. For RX side there are validations like MAC filtering, but
> nothing over TX.
>
> >
> > Is this what you are doing.
>
> I agree that rte_eth_tx_burst does not overwrite the source MAC as I was able
> to trace all the way to the IGB driver that source mac makes it intact. There is no
> offload flags enabled in the mbuf. Yet the packets to the other side comes out
> as with source mac address of the port.
>
> Is there any standard DPDK app which crafts packets with different source MAC
> than the port’s physical mac? (I checked the l2fwd example loads the port mac
> before transmitting and then uses the same in TX function).
I don’t have a i210 on hand, so I checked the datasheet of i210. I don't find any description about HW will change the MAC address in the frame. I believe HW should send the frame provided by SW except doing some offload like checksum...
May I suggest to use testpmd forwarding a packet which has a different src MAC than the port's?
>
> >
> >>
> >> Thanks,
> >> Padam
> >
> > Regards,
> > Keith
> >
^ permalink raw reply
* [PATCH v3 2/2] net/i40e: fix VF bonded device link down
From: Qiming Yang @ 2016-10-28 4:18 UTC (permalink / raw)
To: dev
In-Reply-To: <1477628339-5816-1-git-send-email-qiming.yang@intel.com>
If VF device is used as slave of a bond device, it will be polled
periodically through alarm. Interrupt is involved here. And then
VF will send I40E_VIRTCHNL_OP_GET_LINK_STAT message to
PF to query the status. The response is handled by interrupt
callback. Interrupt is involved here again. That's why bond
device cannot bring up.
This patch removes I40E_VIRTCHNL_OP_GET_LINK_STAT
message. Link status in VF driver will be updated when PF driver
notify it, and VF stores this link status locally. VF driver just
returns the local status when being required.
Fixes: 4861cde46116 ("i40e: new poll mode driver")
Signed-off-by: Qiming Yang <qiming.yang@intel.com>
---
Change in v3:
* resolved the conflict with other changes, rework based
on version: 16.11-rc2
---
---
drivers/net/i40e/i40e_ethdev.c | 22 ++++++++++-
drivers/net/i40e/i40e_ethdev.h | 4 +-
drivers/net/i40e/i40e_ethdev_vf.c | 81 +++++++++++++--------------------------
drivers/net/i40e/i40e_pf.c | 33 ++++++++--------
drivers/net/i40e/i40e_pf.h | 3 +-
5 files changed, 67 insertions(+), 76 deletions(-)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 078c581..99183b1 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -5441,6 +5441,24 @@ i40e_dev_handle_vfr_event(struct rte_eth_dev *dev)
}
static void
+i40e_notify_all_vfs_link_status(struct rte_eth_dev *dev)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_virtchnl_pf_event event;
+ int i;
+
+ event.event = I40E_VIRTCHNL_EVENT_LINK_CHANGE;
+ event.event_data.link_event.link_status =
+ dev->data->dev_link.link_status;
+ event.event_data.link_event.link_speed =
+ dev->data->dev_link.link_speed;
+
+ for (i = 0; i < pf->vf_num; i++)
+ i40e_pf_host_send_msg_to_vf(&pf->vfs[i], I40E_VIRTCHNL_OP_EVENT,
+ I40E_SUCCESS, (uint8_t *)&event, sizeof(event));
+}
+
+static void
i40e_dev_handle_aq_msg(struct rte_eth_dev *dev)
{
struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -5478,9 +5496,11 @@ i40e_dev_handle_aq_msg(struct rte_eth_dev *dev)
break;
case i40e_aqc_opc_get_link_status:
ret = i40e_dev_link_update(dev, 0);
- if (!ret)
+ if (!ret) {
+ i40e_notify_all_vfs_link_status(dev);
_rte_eth_dev_callback_process(dev,
RTE_ETH_EVENT_INTR_LSC, NULL);
+ }
break;
default:
PMD_DRV_LOG(ERR, "Request %u is not supported yet",
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 24b8580..298cef4 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -609,7 +609,9 @@ int i40e_hash_filter_inset_select(struct i40e_hw *hw,
struct rte_eth_input_set_conf *conf);
int i40e_fdir_filter_inset_select(struct i40e_pf *pf,
struct rte_eth_input_set_conf *conf);
-
+int i40e_pf_host_send_msg_to_vf(struct i40e_pf_vf *vf, uint32_t opcode,
+ uint32_t retval, uint8_t *msg,
+ uint16_t msglen);
void i40e_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
struct rte_eth_rxq_info *qinfo);
void i40e_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 4b835cb..aa306d6 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -126,8 +126,6 @@ static void i40evf_dev_promiscuous_enable(struct rte_eth_dev *dev);
static void i40evf_dev_promiscuous_disable(struct rte_eth_dev *dev);
static void i40evf_dev_allmulticast_enable(struct rte_eth_dev *dev);
static void i40evf_dev_allmulticast_disable(struct rte_eth_dev *dev);
-static int i40evf_get_link_status(struct rte_eth_dev *dev,
- struct rte_eth_link *link);
static int i40evf_init_vlan(struct rte_eth_dev *dev);
static int i40evf_dev_rx_queue_start(struct rte_eth_dev *dev,
uint16_t rx_queue_id);
@@ -1084,31 +1082,6 @@ i40evf_del_vlan(struct rte_eth_dev *dev, uint16_t vlanid)
return err;
}
-static int
-i40evf_get_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link)
-{
- struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
- int err;
- struct vf_cmd_info args;
- struct rte_eth_link *new_link;
-
- args.ops = (enum i40e_virtchnl_ops)I40E_VIRTCHNL_OP_GET_LINK_STAT;
- args.in_args = NULL;
- args.in_args_size = 0;
- args.out_buffer = vf->aq_resp;
- args.out_size = I40E_AQ_BUF_SZ;
- err = i40evf_execute_vf_cmd(dev, &args);
- if (err) {
- PMD_DRV_LOG(ERR, "fail to execute command OP_GET_LINK_STAT");
- return err;
- }
-
- new_link = (struct rte_eth_link *)args.out_buffer;
- (void)rte_memcpy(link, new_link, sizeof(*link));
-
- return 0;
-}
-
static const struct rte_pci_id pci_id_i40evf_map[] = {
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_VF) },
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_VF_HV) },
@@ -2146,35 +2119,33 @@ i40evf_dev_link_update(struct rte_eth_dev *dev,
* DPDK pf host provide interfacet to acquire link status
* while Linux driver does not
*/
- if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
- i40evf_get_link_status(dev, &new_link);
- else {
- /* Linux driver PF host */
- switch (vf->link_speed) {
- case I40E_LINK_SPEED_100MB:
- new_link.link_speed = ETH_SPEED_NUM_100M;
- break;
- case I40E_LINK_SPEED_1GB:
- new_link.link_speed = ETH_SPEED_NUM_1G;
- break;
- case I40E_LINK_SPEED_10GB:
- new_link.link_speed = ETH_SPEED_NUM_10G;
- break;
- case I40E_LINK_SPEED_20GB:
- new_link.link_speed = ETH_SPEED_NUM_20G;
- break;
- case I40E_LINK_SPEED_40GB:
- new_link.link_speed = ETH_SPEED_NUM_40G;
- break;
- default:
- new_link.link_speed = ETH_SPEED_NUM_100M;
- break;
- }
- /* full duplex only */
- new_link.link_duplex = ETH_LINK_FULL_DUPLEX;
- new_link.link_status = vf->link_up ? ETH_LINK_UP :
- ETH_LINK_DOWN;
+
+ /* Linux driver PF host */
+ switch (vf->link_speed) {
+ case I40E_LINK_SPEED_100MB:
+ new_link.link_speed = ETH_SPEED_NUM_100M;
+ break;
+ case I40E_LINK_SPEED_1GB:
+ new_link.link_speed = ETH_SPEED_NUM_1G;
+ break;
+ case I40E_LINK_SPEED_10GB:
+ new_link.link_speed = ETH_SPEED_NUM_10G;
+ break;
+ case I40E_LINK_SPEED_20GB:
+ new_link.link_speed = ETH_SPEED_NUM_20G;
+ break;
+ case I40E_LINK_SPEED_40GB:
+ new_link.link_speed = ETH_SPEED_NUM_40G;
+ break;
+ default:
+ new_link.link_speed = ETH_SPEED_NUM_100M;
+ break;
}
+ /* full duplex only */
+ new_link.link_duplex = ETH_LINK_FULL_DUPLEX;
+ new_link.link_status = vf->link_up ? ETH_LINK_UP :
+ ETH_LINK_DOWN;
+
i40evf_dev_atomic_write_link_status(dev, &new_link);
return 0;
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index d5b2d45..350f6a0 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -250,7 +250,7 @@ i40e_pf_host_vf_reset(struct i40e_pf_vf *vf, bool do_hw_reset)
return ret;
}
-static int
+int
i40e_pf_host_send_msg_to_vf(struct i40e_pf_vf *vf,
uint32_t opcode,
uint32_t retval,
@@ -847,18 +847,6 @@ i40e_pf_host_process_cmd_get_stats(struct i40e_pf_vf *vf)
return I40E_SUCCESS;
}
-static void
-i40e_pf_host_process_cmd_get_link_status(struct i40e_pf_vf *vf)
-{
- struct rte_eth_dev *dev = I40E_VSI_TO_ETH_DEV(vf->pf->main_vsi);
-
- /* Update link status first to acquire latest link change */
- i40e_dev_link_update(dev, 1);
- i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_LINK_STAT,
- I40E_SUCCESS, (uint8_t *)&dev->data->dev_link,
- sizeof(struct rte_eth_link));
-}
-
static int
i40e_pf_host_process_cmd_cfg_vlan_offload(
struct i40e_pf_vf *vf,
@@ -909,6 +897,20 @@ send_msg:
return ret;
}
+static void
+i40e_notify_vf_link_status(struct rte_eth_dev *dev, struct i40e_pf_vf *vf)
+{
+ struct i40e_virtchnl_pf_event event;
+
+ event.event = I40E_VIRTCHNL_EVENT_LINK_CHANGE;
+ event.event_data.link_event.link_status =
+ dev->data->dev_link.link_status;
+ event.event_data.link_event.link_speed =
+ dev->data->dev_link.link_speed;
+ i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_EVENT,
+ I40E_SUCCESS, (uint8_t *)&event, sizeof(event));
+}
+
void
i40e_pf_host_handle_vf_msg(struct rte_eth_dev *dev,
uint16_t abs_vf_id, uint32_t opcode,
@@ -964,6 +966,7 @@ i40e_pf_host_handle_vf_msg(struct rte_eth_dev *dev,
case I40E_VIRTCHNL_OP_ENABLE_QUEUES:
PMD_DRV_LOG(INFO, "OP_ENABLE_QUEUES received");
i40e_pf_host_process_cmd_enable_queues(vf, msg, msglen);
+ i40e_notify_vf_link_status(dev, vf);
break;
case I40E_VIRTCHNL_OP_DISABLE_QUEUES:
PMD_DRV_LOG(INFO, "OP_DISABLE_QUEUE received");
@@ -993,10 +996,6 @@ i40e_pf_host_handle_vf_msg(struct rte_eth_dev *dev,
PMD_DRV_LOG(INFO, "OP_GET_STATS received");
i40e_pf_host_process_cmd_get_stats(vf);
break;
- case I40E_VIRTCHNL_OP_GET_LINK_STAT:
- PMD_DRV_LOG(INFO, "OP_GET_LINK_STAT received");
- i40e_pf_host_process_cmd_get_link_status(vf);
- break;
case I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD:
PMD_DRV_LOG(INFO, "OP_CFG_VLAN_OFFLOAD received");
i40e_pf_host_process_cmd_cfg_vlan_offload(vf, msg, msglen);
diff --git a/drivers/net/i40e/i40e_pf.h b/drivers/net/i40e/i40e_pf.h
index 9c01829..cddc45c 100644
--- a/drivers/net/i40e/i40e_pf.h
+++ b/drivers/net/i40e/i40e_pf.h
@@ -59,9 +59,8 @@ enum i40e_virtchnl_ops_dpdk {
* Keep some gap between Linux PF commands and
* DPDK PF extended commands.
*/
- I40E_VIRTCHNL_OP_GET_LINK_STAT = I40E_VIRTCHNL_OP_VERSION +
+ I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD = I40E_VIRTCHNL_OP_VERSION +
I40E_DPDK_OFFSET,
- I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD,
I40E_VIRTCHNL_OP_CFG_VLAN_PVID,
I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT,
};
--
2.5.5
^ permalink raw reply related
* [PATCH v3 1/2] net/i40e: fix link status change interrupt
From: Qiming Yang @ 2016-10-28 4:18 UTC (permalink / raw)
To: dev
In-Reply-To: <1477369146-63317-2-git-send-email-qiming.yang@intel.com>
Previously, link status interrupt in i40e is achieved by checking
LINK_STAT_CHANGE_MASK in PFINT_ICR0 register which is provided only
for diagnostic use. Instead, drivers need to get the link status
change notification by using LSE (Link Status Event).
This patch enables LSE and calls LSC callback when the event is
received. This patch also removes the processing on
LINK_STAT_CHANGE_MASK.
Fixes: 4861cde46116 ("i40e: new poll mode driver")
Signed-off-by: Qiming Yang <qiming.yang@intel.com>
---
Change in v3:
* resolved the conflict with other changes, rework based
on version: 16.11-rc2
---
---
drivers/net/i40e/i40e_ethdev.c | 96 +++++++++---------------------------------
1 file changed, 19 insertions(+), 77 deletions(-)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index bb81b15..078c581 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -108,7 +108,6 @@
I40E_PFINT_ICR0_ENA_GRST_MASK | \
I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK | \
I40E_PFINT_ICR0_ENA_STORM_DETECT_MASK | \
- I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK | \
I40E_PFINT_ICR0_ENA_HMC_ERR_MASK | \
I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK | \
I40E_PFINT_ICR0_ENA_VFLR_MASK | \
@@ -1777,6 +1776,16 @@ i40e_dev_start(struct rte_eth_dev *dev)
if (dev->data->dev_conf.intr_conf.lsc != 0)
PMD_INIT_LOG(INFO, "lsc won't enable because of"
" no intr multiplex\n");
+ } else if (dev->data->dev_conf.intr_conf.lsc != 0) {
+ ret = i40e_aq_set_phy_int_mask(hw,
+ ~(I40E_AQ_EVENT_LINK_UPDOWN |
+ I40E_AQ_EVENT_MODULE_QUAL_FAIL |
+ I40E_AQ_EVENT_MEDIA_NA), NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(WARNING, "Fail to set phy mask");
+
+ /* Call get_link_info aq commond to enable LSE */
+ i40e_dev_link_update(dev, 0);
}
/* enable uio intr after callback register */
@@ -1995,6 +2004,7 @@ i40e_dev_link_update(struct rte_eth_dev *dev,
struct rte_eth_link link, old;
int status;
unsigned rep_cnt = MAX_REPEAT_TIME;
+ bool enable_lse = dev->data->dev_conf.intr_conf.lsc ? true : false;
memset(&link, 0, sizeof(link));
memset(&old, 0, sizeof(old));
@@ -2003,7 +2013,8 @@ i40e_dev_link_update(struct rte_eth_dev *dev,
do {
/* Get link status information from hardware */
- status = i40e_aq_get_link_info(hw, false, &link_status, NULL);
+ status = i40e_aq_get_link_info(hw, enable_lse,
+ &link_status, NULL);
if (status != I40E_SUCCESS) {
link.link_speed = ETH_SPEED_NUM_100M;
link.link_duplex = ETH_LINK_FULL_DUPLEX;
@@ -5465,6 +5476,12 @@ i40e_dev_handle_aq_msg(struct rte_eth_dev *dev)
info.msg_buf,
info.msg_len);
break;
+ case i40e_aqc_opc_get_link_status:
+ ret = i40e_dev_link_update(dev, 0);
+ if (!ret)
+ _rte_eth_dev_callback_process(dev,
+ RTE_ETH_EVENT_INTR_LSC, NULL);
+ break;
default:
PMD_DRV_LOG(ERR, "Request %u is not supported yet",
opcode);
@@ -5474,57 +5491,6 @@ i40e_dev_handle_aq_msg(struct rte_eth_dev *dev)
rte_free(info.msg_buf);
}
-/*
- * Interrupt handler is registered as the alarm callback for handling LSC
- * interrupt in a definite of time, in order to wait the NIC into a stable
- * state. Currently it waits 1 sec in i40e for the link up interrupt, and
- * no need for link down interrupt.
- */
-static void
-i40e_dev_interrupt_delayed_handler(void *param)
-{
- struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
- struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- uint32_t icr0;
-
- /* read interrupt causes again */
- icr0 = I40E_READ_REG(hw, I40E_PFINT_ICR0);
-
-#ifdef RTE_LIBRTE_I40E_DEBUG_DRIVER
- if (icr0 & I40E_PFINT_ICR0_ECC_ERR_MASK)
- PMD_DRV_LOG(ERR, "ICR0: unrecoverable ECC error\n");
- if (icr0 & I40E_PFINT_ICR0_MAL_DETECT_MASK)
- PMD_DRV_LOG(ERR, "ICR0: malicious programming detected\n");
- if (icr0 & I40E_PFINT_ICR0_GRST_MASK)
- PMD_DRV_LOG(INFO, "ICR0: global reset requested\n");
- if (icr0 & I40E_PFINT_ICR0_PCI_EXCEPTION_MASK)
- PMD_DRV_LOG(INFO, "ICR0: PCI exception\n activated\n");
- if (icr0 & I40E_PFINT_ICR0_STORM_DETECT_MASK)
- PMD_DRV_LOG(INFO, "ICR0: a change in the storm control "
- "state\n");
- if (icr0 & I40E_PFINT_ICR0_HMC_ERR_MASK)
- PMD_DRV_LOG(ERR, "ICR0: HMC error\n");
- if (icr0 & I40E_PFINT_ICR0_PE_CRITERR_MASK)
- PMD_DRV_LOG(ERR, "ICR0: protocol engine critical error\n");
-#endif /* RTE_LIBRTE_I40E_DEBUG_DRIVER */
-
- if (icr0 & I40E_PFINT_ICR0_VFLR_MASK) {
- PMD_DRV_LOG(INFO, "INT:VF reset detected\n");
- i40e_dev_handle_vfr_event(dev);
- }
- if (icr0 & I40E_PFINT_ICR0_ADMINQ_MASK) {
- PMD_DRV_LOG(INFO, "INT:ADMINQ event\n");
- i40e_dev_handle_aq_msg(dev);
- }
-
- /* handle the link up interrupt in an alarm callback */
- i40e_dev_link_update(dev, 0);
- _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
-
- i40e_pf_enable_irq0(hw);
- rte_intr_enable(&(dev->pci_dev->intr_handle));
-}
-
/**
* Interrupt handler triggered by NIC for handling
* specific interrupt.
@@ -5582,30 +5548,6 @@ i40e_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
i40e_dev_handle_aq_msg(dev);
}
- /* Link Status Change interrupt */
- if (icr0 & I40E_PFINT_ICR0_LINK_STAT_CHANGE_MASK) {
-#define I40E_US_PER_SECOND 1000000
- struct rte_eth_link link;
-
- PMD_DRV_LOG(INFO, "ICR0: link status changed\n");
- memset(&link, 0, sizeof(link));
- rte_i40e_dev_atomic_read_link_status(dev, &link);
- i40e_dev_link_update(dev, 0);
-
- /*
- * For link up interrupt, it needs to wait 1 second to let the
- * hardware be a stable state. Otherwise several consecutive
- * interrupts can be observed.
- * For link down interrupt, no need to wait.
- */
- if (!link.link_status && rte_eal_alarm_set(I40E_US_PER_SECOND,
- i40e_dev_interrupt_delayed_handler, (void *)dev) >= 0)
- return;
- else
- _rte_eth_dev_callback_process(dev,
- RTE_ETH_EVENT_INTR_LSC, NULL);
- }
-
done:
/* Enable interrupt */
i40e_pf_enable_irq0(hw);
--
2.5.5
^ permalink raw reply related
* Re: [RFC] [PATCH v2] libeventdev: event driven programming model framework for DPDK
From: Jerin Jacob @ 2016-10-28 3:01 UTC (permalink / raw)
To: Bruce Richardson
Cc: Vangati, Narender, dev@dpdk.org, Eads, Gage,
thomas.monjalon@6wind.com
In-Reply-To: <20161026125414.GB33288@bricha3-MOBL3.ger.corp.intel.com>
On Wed, Oct 26, 2016 at 01:54:14PM +0100, Bruce Richardson wrote:
> On Wed, Oct 26, 2016 at 05:54:17PM +0530, Jerin Jacob wrote:
> > On Wed, Oct 26, 2016 at 12:11:03PM +0000, Van Haaren, Harry wrote:
> > > > -----Original Message-----
> > > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Jerin Jacob
> Thanks. One other suggestion is that it might be useful to provide
> support for having typed queues explicitly in the API. Right now, when
> you create an queue, the queue_conf structure takes as parameters how
> many atomic flows that are needed for the queue, or how many reorder
> slots need to be reserved for it. This implicitly hints at the type of
> traffic which will be sent to the queue, but I'm wondering if it's
> better to make it explicit. There are certain optimisations that can be
> looked at if we know that a queue only handles packets of a particular
> type. [Not having to handle reordering when pulling events from a core
> can be a big win for software!].
If it helps in SW implementation, then I think we can add this in queue
configuration.
>
> How about adding: "allowed_event_types" as a field to
> rte_event_queue_conf, with possible values:
> * atomic
> * ordered
> * parallel
> * mixed - allowing all 3 types. I think allowing 2 of three types might
> make things too complicated.
>
> An open question would then be how to behave when the queue type and
> requested event type conflict. We can either throw an error, or just
> ignore the event type and always treat enqueued events as being of the
> queue type. I prefer the latter, because it's faster not having to
> error-check, and it pushes the responsibility on the app to know what
> it's doing.
How about making default as "mixed" and let application configures what
is not required?. That way application responsibility is clear.
something similar to ETH_TXQ_FLAGS_NOMULTSEGS, ETH_TXQ_FLAGS_NOREFCOUNT
with default.
/Jerin
>
> /Bruce
^ permalink raw reply
* [PATCH] net/bonding: not handle vlan slow packet
From: linhaifeng @ 2016-10-28 2:57 UTC (permalink / raw)
To: dev@dpdk.org, declan.doherty
If rx vlan offload is enable we should not handle vlan slow
packets too.
Signed-off-by: Haifeng Lin <haifeng.lin@huawei.com>
---
drivers/net/bonding/rte_eth_bond_pmd.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
index 09ce7bf..7765017 100644
--- a/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -169,10 +169,11 @@ bond_ethdev_rx_burst_8023ad(void *queue, struct rte_mbuf **bufs,
/* Remove packet from array if it is slow packet or slave is not
* in collecting state or bondign interface is not in promiscus
* mode and packet address does not match. */
- if (unlikely(hdr->ether_type == ether_type_slow_be ||
+ if (unlikely(!bufs[j]->vlan_tci &&
+ (hdr->ether_type == ether_type_slow_be ||
!collecting || (!promisc &&
!is_multicast_ether_addr(&hdr->d_addr) &&
- !is_same_ether_addr(&bond_mac, &hdr->d_addr)))) {
+ !is_same_ether_addr(&bond_mac, &hdr->d_addr))))) {
if (hdr->ether_type == ether_type_slow_be) {
bond_mode_8023ad_handle_slow_pkt(internals, slaves[i],
--
1.8.3.1
^ permalink raw reply related
* Re: [RFC PATCH v2 2/3] lib: add bitrate statistics library
From: Stephen Hemminger @ 2016-10-28 1:12 UTC (permalink / raw)
To: Remy Horton; +Cc: dev
In-Reply-To: <1477616671-9547-3-git-send-email-remy.horton@intel.com>
On Fri, 28 Oct 2016 09:04:30 +0800
Remy Horton <remy.horton@intel.com> wrote:
> +
> +struct rte_stats_bitrate_s {
> + uint64_t last_ibytes;
> + uint64_t last_obytes;
> + uint64_t peak_ibits;
> + uint64_t peak_obits;
> + uint64_t ewma_ibits;
> + uint64_t ewma_obits;
> +};
> +
Reader/write access of 64 bit values is not safe on 32 bit platforms.
I think you need to add a generation counter (see Linux kernel syncp)
to handle 32 bit architecture. If done correctly, it would be a nop
on 64 bit platforms.
^ permalink raw reply
* [RFC PATCH v2 3/3] app/test-pmd: add support for bitrate statistics
From: Remy Horton @ 2016-10-28 1:04 UTC (permalink / raw)
To: dev
In-Reply-To: <1477616671-9547-1-git-send-email-remy.horton@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
---
app/test-pmd/testpmd.c | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index e2403c3..940dc3b 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -78,6 +78,8 @@
#ifdef RTE_LIBRTE_PDUMP
#include <rte_pdump.h>
#endif
+#include <rte_metrics.h>
+#include <rte_bitrate.h>
#include "testpmd.h"
@@ -322,6 +324,9 @@ uint16_t nb_rx_queue_stats_mappings = 0;
unsigned max_socket = 0;
+/* Bitrate statistics */
+struct rte_stats_bitrates_s *bitrate_data;
+
/* Forward function declarations */
static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port);
static void check_all_ports_link_status(uint32_t port_mask);
@@ -921,12 +926,26 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
struct fwd_stream **fsm;
streamid_t nb_fs;
streamid_t sm_id;
-
+ uint64_t tics_per_1sec;
+ uint64_t tics_datum;
+ uint64_t tics_current;
+ uint8_t idx_port, cnt_ports;
+
+ cnt_ports = rte_eth_dev_count();
+ tics_datum = rte_rdtsc();
+ tics_per_1sec = rte_get_timer_hz();
fsm = &fwd_streams[fc->stream_idx];
nb_fs = fc->stream_nb;
do {
for (sm_id = 0; sm_id < nb_fs; sm_id++)
(*pkt_fwd)(fsm[sm_id]);
+ tics_current = rte_rdtsc();
+ if (tics_current - tics_datum >= tics_per_1sec) {
+ /* Periodic bitrate calculation */
+ for (idx_port = 0; idx_port < cnt_ports; idx_port++)
+ rte_stats_bitrate_calc(bitrate_data, idx_port);
+ tics_datum = tics_current;
+ }
} while (! fc->stopped);
}
@@ -2119,6 +2138,15 @@ main(int argc, char** argv)
FOREACH_PORT(port_id, ports)
rte_eth_promiscuous_enable(port_id);
+ /* Setup bitrate stats */
+ bitrate_data = rte_stats_bitrate_create();
+ if (bitrate_data == NULL)
+ rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n");
+ rte_stats_bitrate_reg(bitrate_data);
+ int id_const = rte_metrics_reg_metric("constant");
+ rte_metrics_update_metric(55, id_const, 0xdeadbeef);
+
+
#ifdef RTE_LIBRTE_CMDLINE
if (interactive == 1) {
if (auto_start) {
--
2.5.5
^ permalink raw reply related
* [RFC PATCH v2 2/3] lib: add bitrate statistics library
From: Remy Horton @ 2016-10-28 1:04 UTC (permalink / raw)
To: dev
In-Reply-To: <1477616671-9547-1-git-send-email-remy.horton@intel.com>
This patch adds a library that calculates peak and average data-rate
statistics. For ethernet devices. These statistics are reported using
the metrics library.
Signed-off-by: Remy Horton <remy.horton@intel.com>
---
config/common_base | 5 +
doc/api/doxy-api-index.md | 1 +
doc/api/doxy-api.conf | 1 +
lib/Makefile | 1 +
lib/librte_bitratestats/Makefile | 53 +++++++++
lib/librte_bitratestats/rte_bitrate.c | 126 +++++++++++++++++++++
lib/librte_bitratestats/rte_bitrate.h | 80 +++++++++++++
.../rte_bitratestats_version.map | 9 ++
lib/librte_metrics/rte_metrics.c | 22 ++--
lib/librte_metrics/rte_metrics.h | 4 +-
mk/rte.app.mk | 1 +
11 files changed, 291 insertions(+), 12 deletions(-)
create mode 100644 lib/librte_bitratestats/Makefile
create mode 100644 lib/librte_bitratestats/rte_bitrate.c
create mode 100644 lib/librte_bitratestats/rte_bitrate.h
create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map
diff --git a/config/common_base b/config/common_base
index c23a632..e778c00 100644
--- a/config/common_base
+++ b/config/common_base
@@ -597,3 +597,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
# Compile the device metrics library
#
CONFIG_RTE_LIBRTE_METRICS=y
+
+#
+# Compile the bitrate statistics library
+#
+CONFIG_RTE_LIBRTE_BITRATE=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index ca50fa6..91e8ea6 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -148,4 +148,5 @@ There are many libraries, so their headers may be grouped by topics:
[ABI compat] (@ref rte_compat.h),
[keepalive] (@ref rte_keepalive.h),
[Device Metrics] (@ref rte_metrics.h),
+ [Bitrate Statistics] (@ref rte_bitrate.h),
[version] (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index fe830eb..8765ddd 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -58,6 +58,7 @@ INPUT = doc/api/doxy-api-index.md \
lib/librte_ring \
lib/librte_sched \
lib/librte_metrics \
+ lib/librte_bitratestats \
lib/librte_table \
lib/librte_timer \
lib/librte_vhost
diff --git a/lib/Makefile b/lib/Makefile
index 5d85dcf..e211bc0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
+DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile
new file mode 100644
index 0000000..b725d4e
--- /dev/null
+++ b/lib/librte_bitratestats/Makefile
@@ -0,0 +1,53 @@
+# BSD LICENSE
+#
+# Copyright(c) 2016 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_bitratestats.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_bitratestats_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c
new file mode 100644
index 0000000..fcdf401
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.c
@@ -0,0 +1,126 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_common.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_bitrate.h>
+
+
+struct rte_stats_bitrate_s {
+ uint64_t last_ibytes;
+ uint64_t last_obytes;
+ uint64_t peak_ibits;
+ uint64_t peak_obits;
+ uint64_t ewma_ibits;
+ uint64_t ewma_obits;
+};
+
+struct rte_stats_bitrates_s {
+ struct rte_stats_bitrate_s port_stats[RTE_MAX_ETHPORTS];
+ uint16_t id_stats_set;
+};
+
+
+struct rte_stats_bitrates_s *rte_stats_bitrate_create(void)
+{
+ return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s), 0);
+}
+
+
+int
+rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data)
+{
+ const char *names[] = {
+ "mean_bits_in", "mean_bits_out",
+ "peak_bits_in", "peak_bits_out",
+ };
+ int return_value;
+
+ bitrate_data = rte_stats_bitrate_create();
+ if (bitrate_data == NULL)
+ rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n");
+ return_value = rte_metrics_reg_metrics(&names[0], 4);
+ if (return_value >= 0)
+ bitrate_data->id_stats_set = return_value;
+ return return_value;
+}
+
+
+int
+rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data,
+ uint8_t port_id)
+{
+ struct rte_stats_bitrate_s *port_data;
+ struct rte_eth_stats eth_stats;
+ int ret_code;
+ uint64_t cnt_bits;
+ int64_t delta;
+ const int64_t alpha_percent = 20;
+ uint64_t values[4];
+
+ ret_code = rte_eth_stats_get(port_id, ð_stats);
+ if (ret_code != 0)
+ return ret_code;
+
+ port_data = &bitrate_data->port_stats[port_id];
+
+ /* Incoming */
+ cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3;
+ port_data->last_ibytes = eth_stats.ibytes;
+ if (cnt_bits > port_data->peak_ibits)
+ port_data->peak_ibits = cnt_bits;
+ delta = cnt_bits;
+ delta -= port_data->ewma_ibits;
+ delta = (delta * alpha_percent) / 100;
+ port_data->ewma_ibits += delta;
+
+ /* Outgoing */
+ cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3;
+ port_data->last_obytes = eth_stats.obytes;
+ if (cnt_bits > port_data->peak_obits)
+ port_data->peak_obits = cnt_bits;
+ delta = cnt_bits;
+ delta -= port_data->ewma_obits;
+ delta = (delta * alpha_percent) / 100;
+ port_data->ewma_obits += delta;
+
+ values[0] = port_data->ewma_ibits;
+ values[1] = port_data->ewma_obits;
+ values[2] = port_data->peak_ibits;
+ values[3] = port_data->peak_obits;
+ rte_metrics_update_metrics(port_id, bitrate_data->id_stats_set,
+ values, 4);
+ return 0;
+}
diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h
new file mode 100644
index 0000000..cd566d6
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.h
@@ -0,0 +1,80 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+/**
+ * Bitrate statistics data structure
+ */
+struct rte_stats_bitrates_s;
+
+
+/**
+ * Allocate a bitrate statistics structure
+ *
+ * @return
+ * - Pointer to structure on success
+ * - NULL on error (zmalloc failure)
+ */
+struct rte_stats_bitrates_s *rte_stats_bitrate_create(void);
+
+
+/**
+ * Register bitrate statistics
+ *
+ * @param bitrate_data
+ * Pointer allocated by rte_stats_create()
+ *
+ * @return
+ * Zero on success
+ * Negative on error
+ */
+int rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data);
+
+
+/**
+ * Calculate statistics for current time window. The period this function
+ * is called should be the intended time window width.
+ *
+ * @param bitrate_data
+ * Bitrate statistics data pointer
+ *
+ * @param port_id
+ * Port id to calculate statistics for
+ *
+ * @return
+ * - Zero on success
+ * - Negative value on error
+ */
+int rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data,
+ uint8_t port_id);
diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map
new file mode 100644
index 0000000..9de6be9
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitratestats_version.map
@@ -0,0 +1,9 @@
+DPDK_16.11 {
+ global:
+
+ rte_stats_bitrate_calc;
+ rte_stats_bitrate_create;
+ rte_stats_bitrate_reg;
+
+ local: *;
+};
diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c
index 354ba47..7dce738 100644
--- a/lib/librte_metrics/rte_metrics.c
+++ b/lib/librte_metrics/rte_metrics.c
@@ -44,6 +44,8 @@
#define RTE_METRICS_MAX_METRICS 256
+#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS"
+
/**
* Internal stats metadata and value entry.
*
@@ -62,7 +64,7 @@
* having a separate set metadata table doesn't save any memory.
*/
struct rte_metrics_meta_s {
- struct rte_stat_name name;
+ char name[RTE_METRICS_MAX_NAME_LEN];
uint64_t value[RTE_MAX_ETHPORTS];
uint16_t idx_next_set;
uint16_t idx_next_stat;
@@ -100,10 +102,10 @@ rte_metrics_init(void)
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
return;
- memzone = rte_memzone_lookup("RTE_STATS");
+ memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
if (memzone != NULL)
return;
- memzone = rte_memzone_reserve("RTE_STATS",
+ memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME,
sizeof(struct rte_metrics_data_s), rte_socket_id(), 0);
if (memzone == NULL)
rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n");
@@ -135,7 +137,7 @@ rte_metrics_reg_metrics(const char **names, uint16_t cnt_names)
return -EINVAL;
rte_metrics_init();
- memzone = rte_memzone_lookup("RTE_STATS");
+ memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
if (memzone == NULL)
return -EIO;
stats = memzone->addr;
@@ -150,7 +152,7 @@ rte_metrics_reg_metrics(const char **names, uint16_t cnt_names)
for (idx_name = 0; idx_name < cnt_names; idx_name++) {
entry = &stats->metadata[idx_name + stats->cnt_stats];
- strncpy(entry->name.name, names[idx_name],
+ strncpy(entry->name, names[idx_name],
RTE_METRICS_MAX_NAME_LEN);
memset(entry->value, 0, sizeof(entry->value));
entry->idx_next_stat = idx_name + stats->cnt_stats + 1;
@@ -184,7 +186,7 @@ rte_metrics_update_metrics(int port_id,
uint16_t cnt_setsize;
rte_metrics_init();
- memzone = rte_memzone_lookup("RTE_STATS");
+ memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
if (memzone == NULL)
return -EIO;
stats = memzone->addr;
@@ -211,14 +213,14 @@ rte_metrics_update_metrics(int port_id,
int
-rte_metrics_get_names(struct rte_stat_name *names,
+rte_metrics_get_names(struct rte_metric_name *names,
uint16_t capacity)
{
struct rte_metrics_data_s *stats;
const struct rte_memzone *memzone;
uint16_t idx_name;
- memzone = rte_memzone_lookup("RTE_STATS");
+ memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
/* If not allocated, fail silently */
if (memzone == NULL)
return 0;
@@ -229,7 +231,7 @@ rte_metrics_get_names(struct rte_stat_name *names,
return -ERANGE;
for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++)
strncpy(names[idx_name].name,
- stats->metadata[idx_name].name.name,
+ stats->metadata[idx_name].name,
RTE_METRICS_MAX_NAME_LEN);
}
return stats->cnt_stats;
@@ -246,7 +248,7 @@ rte_metrics_get_values(int port_id,
const struct rte_memzone *memzone;
uint16_t idx_name;
- memzone = rte_memzone_lookup("RTE_STATS");
+ memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
/* If not allocated, fail silently */
if (memzone == NULL)
return 0;
diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h
index e8888eb..348db30 100644
--- a/lib/librte_metrics/rte_metrics.h
+++ b/lib/librte_metrics/rte_metrics.h
@@ -52,7 +52,7 @@
/**
* Statistic name
*/
-struct rte_stat_name {
+struct rte_metric_name {
/** String describing statistic */
char name[RTE_METRICS_MAX_NAME_LEN];
};
@@ -130,7 +130,7 @@ int rte_metrics_reg_metrics(const char **names, uint16_t cnt_names);
* - Negative: Failure
*/
int rte_metrics_get_names(
- struct rte_stat_name *names,
+ struct rte_metric_name *names,
uint16_t capacity);
/**
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 11d0c80..c499c69 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -98,6 +98,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal
_LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline
_LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile
_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics
+_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats
_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond
--
2.5.5
^ permalink raw reply related
* [RFC PATCH v2 1/3] lib: add information metrics library
From: Remy Horton @ 2016-10-28 1:04 UTC (permalink / raw)
To: dev
In-Reply-To: <1477616671-9547-1-git-send-email-remy.horton@intel.com>
This patch adds a new information metric library that allows other
modules to register named metrics and update their values. It is
intended to be independent of ethdev, rather than mixing ethdev
and non-ethdev information in xstats.
Signed-off-by: Remy Horton <remy.horton@intel.com>
---
config/common_base | 5 +
doc/api/doxy-api-index.md | 1 +
doc/api/doxy-api.conf | 1 +
lib/Makefile | 1 +
lib/librte_metrics/Makefile | 51 ++++++
lib/librte_metrics/rte_metrics.c | 265 +++++++++++++++++++++++++++++
lib/librte_metrics/rte_metrics.h | 200 ++++++++++++++++++++++
lib/librte_metrics/rte_metrics_version.map | 13 ++
mk/rte.app.mk | 2 +
9 files changed, 539 insertions(+)
create mode 100644 lib/librte_metrics/Makefile
create mode 100644 lib/librte_metrics/rte_metrics.c
create mode 100644 lib/librte_metrics/rte_metrics.h
create mode 100644 lib/librte_metrics/rte_metrics_version.map
diff --git a/config/common_base b/config/common_base
index f5d2eff..c23a632 100644
--- a/config/common_base
+++ b/config/common_base
@@ -592,3 +592,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
CONFIG_RTE_TEST_PMD=y
CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
+
+#
+# Compile the device metrics library
+#
+CONFIG_RTE_LIBRTE_METRICS=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 6675f96..ca50fa6 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -147,4 +147,5 @@ There are many libraries, so their headers may be grouped by topics:
[common] (@ref rte_common.h),
[ABI compat] (@ref rte_compat.h),
[keepalive] (@ref rte_keepalive.h),
+ [Device Metrics] (@ref rte_metrics.h),
[version] (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index 9dc7ae5..fe830eb 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -57,6 +57,7 @@ INPUT = doc/api/doxy-api-index.md \
lib/librte_reorder \
lib/librte_ring \
lib/librte_sched \
+ lib/librte_metrics \
lib/librte_table \
lib/librte_timer \
lib/librte_vhost
diff --git a/lib/Makefile b/lib/Makefile
index 990f23a..5d85dcf 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table
DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
+DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile
new file mode 100644
index 0000000..8d6e23a
--- /dev/null
+++ b/lib/librte_metrics/Makefile
@@ -0,0 +1,51 @@
+# BSD LICENSE
+#
+# Copyright(c) 2016 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_metrics.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_metrics_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c
new file mode 100644
index 0000000..354ba47
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.c
@@ -0,0 +1,265 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_lcore.h>
+#include <rte_memzone.h>
+
+
+#define RTE_METRICS_MAX_METRICS 256
+
+
+/**
+ * Internal stats metadata and value entry.
+ *
+ * @internal
+ * @param name
+ * Name of metric
+ * @param value
+ * Current value for metric
+ * @param idx_next_set
+ * Index of next root element (zero for none)
+ * @param idx_next_metric
+ * Index of next metric in set (zero for none)
+ *
+ * Only the root of each set needs idx_next_set but since it has to be
+ * assumed that number of sets could equal total number of metrics,
+ * having a separate set metadata table doesn't save any memory.
+ */
+struct rte_metrics_meta_s {
+ struct rte_stat_name name;
+ uint64_t value[RTE_MAX_ETHPORTS];
+ uint16_t idx_next_set;
+ uint16_t idx_next_stat;
+};
+
+/**
+ * Internal stats info structure.
+ *
+ * @internal
+ * @param idx_last_set
+ * Index of last metadata entry with valid data. This value is
+ * not valid if cnt_stats is zero.
+ * @param cnt_stats
+ * Number of metrics.
+ * @param metadata
+ * Stat data memory block.
+ *
+ * Offsets into metadata are used instead of pointers because ASLR
+ * means that having the same physical addresses in different
+ * processes is not guaranteed.
+ */
+struct rte_metrics_data_s {
+ uint16_t idx_last_set;
+ uint16_t cnt_stats;
+ struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS];
+};
+
+
+void
+rte_metrics_init(void)
+{
+ struct rte_metrics_data_s *stats;
+ const struct rte_memzone *memzone;
+
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+ return;
+
+ memzone = rte_memzone_lookup("RTE_STATS");
+ if (memzone != NULL)
+ return;
+ memzone = rte_memzone_reserve("RTE_STATS",
+ sizeof(struct rte_metrics_data_s), rte_socket_id(), 0);
+ if (memzone == NULL)
+ rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n");
+ stats = memzone->addr;
+ memset(stats, 0, sizeof(struct rte_metrics_data_s));
+}
+
+
+int
+rte_metrics_reg_metric(const char *name)
+{
+ const char *list_names[] = {name};
+
+ return rte_metrics_reg_metrics(list_names, 1);
+}
+
+
+int
+rte_metrics_reg_metrics(const char **names, uint16_t cnt_names)
+{
+ struct rte_metrics_meta_s *entry;
+ struct rte_metrics_data_s *stats;
+ const struct rte_memzone *memzone;
+ uint16_t idx_name;
+ uint16_t idx_base;
+
+ /* Some sanity checks */
+ if (cnt_names < 1 || names == NULL)
+ return -EINVAL;
+
+ rte_metrics_init();
+ memzone = rte_memzone_lookup("RTE_STATS");
+ if (memzone == NULL)
+ return -EIO;
+ stats = memzone->addr;
+
+ if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS)
+ return -ENOMEM;
+
+ /* Overwritten later if this is actually first set.. */
+ stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats;
+
+ stats->idx_last_set = idx_base = stats->cnt_stats;
+
+ for (idx_name = 0; idx_name < cnt_names; idx_name++) {
+ entry = &stats->metadata[idx_name + stats->cnt_stats];
+ strncpy(entry->name.name, names[idx_name],
+ RTE_METRICS_MAX_NAME_LEN);
+ memset(entry->value, 0, sizeof(entry->value));
+ entry->idx_next_stat = idx_name + stats->cnt_stats + 1;
+ }
+ entry->idx_next_stat = 0;
+ entry->idx_next_set = 0;
+ stats->cnt_stats += cnt_names;
+
+ return idx_base;
+}
+
+
+int
+rte_metrics_update_metric(int port_id, uint16_t key, const uint64_t value)
+{
+ return rte_metrics_update_metrics(port_id, key, &value, 1);
+}
+
+
+int
+rte_metrics_update_metrics(int port_id,
+ uint16_t key,
+ const uint64_t *values,
+ uint32_t count)
+{
+ struct rte_metrics_meta_s *entry;
+ struct rte_metrics_data_s *stats;
+ const struct rte_memzone *memzone;
+ uint16_t idx_metric;
+ uint16_t idx_value;
+ uint16_t cnt_setsize;
+
+ rte_metrics_init();
+ memzone = rte_memzone_lookup("RTE_STATS");
+ if (memzone == NULL)
+ return -EIO;
+ stats = memzone->addr;
+
+ idx_metric = key;
+ cnt_setsize = 1;
+ while (idx_metric < stats->cnt_stats) {
+ entry = &stats->metadata[idx_metric];
+ if (entry->idx_next_stat == 0)
+ break;
+ cnt_setsize++;
+ idx_metric++;
+ }
+ /* Check update does not cross set border */
+ if (count > cnt_setsize)
+ return -ERANGE;
+
+ for (idx_value = 0; idx_value < count; idx_value++) {
+ idx_metric = key + idx_value;
+ stats->metadata[idx_metric].value[port_id] = values[idx_value];
+ }
+ return 0;
+}
+
+
+int
+rte_metrics_get_names(struct rte_stat_name *names,
+ uint16_t capacity)
+{
+ struct rte_metrics_data_s *stats;
+ const struct rte_memzone *memzone;
+ uint16_t idx_name;
+
+ memzone = rte_memzone_lookup("RTE_STATS");
+ /* If not allocated, fail silently */
+ if (memzone == NULL)
+ return 0;
+ stats = memzone->addr;
+
+ if (names != NULL) {
+ if (capacity < stats->cnt_stats)
+ return -ERANGE;
+ for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++)
+ strncpy(names[idx_name].name,
+ stats->metadata[idx_name].name.name,
+ RTE_METRICS_MAX_NAME_LEN);
+ }
+ return stats->cnt_stats;
+}
+
+
+int
+rte_metrics_get_values(int port_id,
+ struct rte_stat_value *values,
+ uint16_t capacity)
+{
+ struct rte_metrics_meta_s *entry;
+ struct rte_metrics_data_s *stats;
+ const struct rte_memzone *memzone;
+ uint16_t idx_name;
+
+ memzone = rte_memzone_lookup("RTE_STATS");
+ /* If not allocated, fail silently */
+ if (memzone == NULL)
+ return 0;
+ stats = memzone->addr;
+
+ if (values != NULL) {
+ if (capacity < stats->cnt_stats)
+ return -ERANGE;
+ for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++) {
+ entry = &stats->metadata[idx_name];
+ values[idx_name].key = idx_name;
+ values[idx_name].value = entry->value[port_id];
+ }
+ }
+ return stats->cnt_stats;
+}
diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h
new file mode 100644
index 0000000..e8888eb
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.h
@@ -0,0 +1,200 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ *
+ * RTE Statistics module
+ *
+ * Statistic information is populated using callbacks, each of which
+ * is associated with one or more metric names. When queried, the
+ * callback is used to update all metric in the set at once. Currently
+ * only bulk querying of all metric is supported.
+ *
+ */
+
+#ifndef _RTE_METRICS_H_
+#define _RTE_METRICS_H_
+
+/** Maximum length of statistic name (including null-terminator) */
+#define RTE_METRICS_MAX_NAME_LEN 64
+
+/**
+ * Statistic name
+ */
+struct rte_stat_name {
+ /** String describing statistic */
+ char name[RTE_METRICS_MAX_NAME_LEN];
+};
+
+
+/**
+ * Statistic name.
+ */
+struct rte_stat_value {
+ /** Numeric identifier of statistic */
+ uint16_t key;
+ /** Value for statistic */
+ uint64_t value;
+};
+
+
+/**
+ * Initialises statistic module. This only has to be explicitly called if you
+ * intend to use rte_metrics_reg_metric() or rte_metrics_reg_metrics() from a
+ * secondary process.
+ */
+void rte_metrics_init(void);
+
+
+/**
+ * Register a statistic and its associated callback.
+ *
+ * @param name
+ * Statistic name
+ *
+ * @param callback
+ * Callback to use when fetching statistic
+ *
+ * @param data
+ * Data pointer to pass to callback
+ *
+ * @return
+ * - Zero or positive: Success
+ * - Negative: Failure
+ */
+int rte_metrics_reg_metric(const char *name);
+
+/**
+ * Register a set of statistic and their associated callback.
+ *
+ * @param names
+ * List of statistic names
+ *
+ * @param cnt_names
+ * Number of statistics in set
+ *
+ * @param callback
+ * Callback to use when fetching statsitics
+ *
+ * @param data
+ * Data pointer to pass to callback
+ *
+ * @return
+ * - Zero or positive: Success
+ * - Negative: Failure
+ */
+int rte_metrics_reg_metrics(const char **names, uint16_t cnt_names);
+
+/**
+ * Get statistic name-key lookup table.
+ *
+ * @param names
+ * Array of names to receive key names
+ *
+ * @param capacity
+ * Space available in names
+ *
+ * @return
+ * - Non-negative: Success (number of names)
+ * - Negative: Failure
+ */
+int rte_metrics_get_names(
+ struct rte_stat_name *names,
+ uint16_t capacity);
+
+/**
+ * Fetch statistics.
+ *
+ * @param port_id
+ * Port id to query
+ *
+ * @param values
+ * Array to receive values and their keys
+ *
+ * @param capacity
+ * Space available in values
+ *
+ * @return
+ * - Non-negative: Success (number of names)
+ * - Negative: Failure
+ */
+int rte_metrics_get_values(
+ int port_id,
+ struct rte_stat_value *values,
+ uint16_t capacity);
+
+/**
+ * Updates a statistic metric
+ *
+ * @param port_id
+ * Port to update statistics for
+ * @param key
+ * Id of statistic metric to update
+ * @param value
+ * New value
+ *
+ * @return
+ * - -EIO if unable to access shared statistics memory
+ * - Zero on success
+ */
+int rte_metrics_update_metric(
+ int port_id,
+ uint16_t key,
+ const uint64_t value);
+
+/**
+ * Updates a statistic metric set. Note that it is an error to try to
+ * update across a set boundary.
+ *
+ * @param port_id
+ * Port to update statistics for
+ * @param key
+ * Base id of statistics set to update
+ * @param values
+ * Set of new values
+ * @param count
+ * Number of new values
+ *
+ * @return
+ * - -ERANGE if count exceeds statistic set size
+ * - -EIO if upable to access shared statistics memory
+ * - Zero on success
+ */
+int rte_metrics_update_metrics(
+ int port_id,
+ uint16_t key,
+ const uint64_t *values,
+ uint32_t count);
+
+#endif
diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map
new file mode 100644
index 0000000..a31a80a
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics_version.map
@@ -0,0 +1,13 @@
+DPDK_16.11 {
+ global:
+
+ rte_metrics_get_names;
+ rte_metrics_get_values;
+ rte_metrics_init;
+ rte_metrics_reg_metric;
+ rte_metrics_reg_metrics;
+ rte_metrics_update_metric;
+ rte_metrics_update_metrics;
+
+ local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index ac50a21..11d0c80 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -97,6 +97,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring
_LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal
_LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline
_LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile
+_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics
+
_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond
_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt -lxenstore
--
2.5.5
^ permalink raw reply related
* [PATCH v2 0/3] expanded statistic reporting
From: Remy Horton @ 2016-10-28 1:04 UTC (permalink / raw)
To: dev; +Cc: thomas.monjalon
In-Reply-To: <1472050682-21420-1-git-send-email-remy.horton@intel.com>
This patchset extends statistics reporting to include peak and
average data-rate metrics. It comes in two parts: a statistics
reporting library, and a bitrate calculation library that uses
it. This structure is intended to seperate statistic reporting
from ethdev and allow more flexible metric registration.
--
v2 changes:
* Uses a new metrics library rather than being part of ethdev
Remy Horton (3):
lib: add information metrics library
lib: add bitrate statistics library
app/test-pmd: add support for bitrate statistics
app/test-pmd/testpmd.c | 30 ++-
config/common_base | 10 +
doc/api/doxy-api-index.md | 2 +
doc/api/doxy-api.conf | 2 +
lib/Makefile | 2 +
lib/librte_bitratestats/Makefile | 53 ++++
lib/librte_bitratestats/rte_bitrate.c | 126 ++++++++++
lib/librte_bitratestats/rte_bitrate.h | 80 ++++++
.../rte_bitratestats_version.map | 9 +
lib/librte_metrics/Makefile | 51 ++++
lib/librte_metrics/rte_metrics.c | 267 +++++++++++++++++++++
lib/librte_metrics/rte_metrics.h | 200 +++++++++++++++
lib/librte_metrics/rte_metrics_version.map | 13 +
mk/rte.app.mk | 3 +
14 files changed, 847 insertions(+), 1 deletion(-)
create mode 100644 lib/librte_bitratestats/Makefile
create mode 100644 lib/librte_bitratestats/rte_bitrate.c
create mode 100644 lib/librte_bitratestats/rte_bitrate.h
create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map
create mode 100644 lib/librte_metrics/Makefile
create mode 100644 lib/librte_metrics/rte_metrics.c
create mode 100644 lib/librte_metrics/rte_metrics.h
create mode 100644 lib/librte_metrics/rte_metrics_version.map
--
2.5.5
^ permalink raw reply
* Re: [PATCH v4] vhost: Add indirect descriptors support to the TX path
From: Wang, Zhihong @ 2016-10-28 0:49 UTC (permalink / raw)
To: Yuanhan Liu, Maxime Coquelin
Cc: mst@redhat.com, dev@dpdk.org, vkaplans@redhat.com
In-Reply-To: <20161027104621.GN16751@yliu-dev.sh.intel.com>
> -----Original Message-----
> From: Yuanhan Liu [mailto:yuanhan.liu@linux.intel.com]
> Sent: Thursday, October 27, 2016 6:46 PM
> To: Maxime Coquelin <maxime.coquelin@redhat.com>
> Cc: Wang, Zhihong <zhihong.wang@intel.com>;
> stephen@networkplumber.org; Pierre Pfister (ppfister)
> <ppfister@cisco.com>; Xie, Huawei <huawei.xie@intel.com>; dev@dpdk.org;
> vkaplans@redhat.com; mst@redhat.com
> Subject: Re: [dpdk-dev] [PATCH v4] vhost: Add indirect descriptors support
> to the TX path
>
> On Thu, Oct 27, 2016 at 12:35:11PM +0200, Maxime Coquelin wrote:
> >
> >
> > On 10/27/2016 12:33 PM, Yuanhan Liu wrote:
> > >On Thu, Oct 27, 2016 at 11:10:34AM +0200, Maxime Coquelin wrote:
> > >>Hi Zhihong,
> > >>
> > >>On 10/27/2016 11:00 AM, Wang, Zhihong wrote:
> > >>>Hi Maxime,
> > >>>
> > >>>Seems indirect desc feature is causing serious performance
> > >>>degradation on Haswell platform, about 20% drop for both
> > >>>mrg=on and mrg=off (--txqflags=0xf00, non-vector version),
> > >>>both iofwd and macfwd.
> > >>I tested PVP (with macswap on guest) and Txonly/Rxonly on an Ivy
> Bridge
> > >>platform, and didn't faced such a drop.
> > >
> > >I was actually wondering that may be the cause. I tested it with
> > >my IvyBridge server as well, I saw no drop.
> > >
> > >Maybe you should find a similar platform (Haswell) and have a try?
> > Yes, that's why I asked Zhihong whether he could test Txonly in guest to
> > see if issue is reproducible like this.
>
> I have no Haswell box, otherwise I could do a quick test for you. IIRC,
> he tried to disable the indirect_desc feature, then the performance
> recovered. So, it's likely the indirect_desc is the culprit here.
>
> > I will be easier for me to find an Haswell machine if it has not to be
> > connected back to back to and HW/SW packet generator.
In fact simple loopback test will also do, without pktgen.
Start testpmd in both host and guest, and do "start" in one
and "start tx_first 32" in another.
Perf drop is about 24% in my test.
>
> Makes sense.
>
> --yliu
> >
> > Thanks,
> > Maxime
> >
> > >
> > > --yliu
> > >
> > >>Have you tried to pass indirect_desc=off to qemu cmdline to see if you
> > >>recover the performance?
> > >>
> > >>Yuanhan, which platform did you use when you tested it with zero copy?
> > >>
> > >>>
> > >>>I'm using RC2, and the CPU is Xeon E5-2699 v3 @ 2.30GHz.
> > >>>
> > >>>Could you please verify if this is true in your test?
> > >>I'll try -rc1/-rc2 on my platform, and let you know.
> > >>
> > >>Thanks,
> > >>Maxime
> > >>
> > >>>
> > >>>
> > >>>Thanks
> > >>>Zhihong
> > >>>
> > >>>>-----Original Message-----
> > >>>>From: Maxime Coquelin [mailto:maxime.coquelin@redhat.com]
> > >>>>Sent: Monday, October 17, 2016 10:15 PM
> > >>>>To: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> > >>>>Cc: Wang, Zhihong <zhihong.wang@intel.com>; Xie, Huawei
> > >>>><huawei.xie@intel.com>; dev@dpdk.org; vkaplans@redhat.com;
> > >>>>mst@redhat.com; stephen@networkplumber.org
> > >>>>Subject: Re: [dpdk-dev] [PATCH v4] vhost: Add indirect descriptors
> support
> > >>>>to the TX path
> > >>>>
> > >>>>
> > >>>>
> > >>>>On 10/17/2016 03:21 PM, Yuanhan Liu wrote:
> > >>>>>On Mon, Oct 17, 2016 at 01:23:23PM +0200, Maxime Coquelin wrote:
> > >>>>>>>On my side, I just setup 2 Windows 2016 VMs, and confirm the
> issue.
> > >>>>>>>I'll continue the investigation early next week.
> > >>>>>>
> > >>>>>>The root cause is identified.
> > >>>>>>When INDIRECT_DESC feature is negotiated, Windows guest uses
> indirect
> > >>>>>>for both Tx and Rx descriptors, whereas Linux guests (Virtio PMD &
> > >>>>>>virtio-net kernel driver) use indirect only for Tx.
> > >>>>>>I'll implement indirect support for the Rx path in vhost lib, but the
> > >>>>>>change will be too big for -rc release.
> > >>>>>>I propose in the mean time to disable INDIRECT_DESC feature in
> vhost
> > >>>>>>lib, we can still enable it locally for testing.
> > >>>>>>
> > >>>>>>Yuanhan, is it ok for you?
> > >>>>>
> > >>>>>That's okay.
> > >>>>I'll send a patch to disable it then.
> > >>>>
> > >>>>>
> > >>>>>>
> > >>>>>>>Has anyone already tested Windows guest with vhost-net, which
> also
> > >>>>has
> > >>>>>>>indirect descs support?
> > >>>>>>
> > >>>>>>I tested and confirm it works with vhost-net.
> > >>>>>
> > >>>>>I'm a bit confused then. IIRC, vhost-net also doesn't support indirect
> > >>>>>for Rx path, right?
> > >>>>
> > >>>>No, it does support it actually.
> > >>>>I thought it didn't support too, I misread the Kernel implementation of
> > >>>>vhost-net and virtio-net. Acutally, virtio-net makes use of indirect
> > >>>>in Rx path when mergeable buffers is disabled.
> > >>>>
> > >>>>The confusion certainly comes from me, sorry about that.
> > >>>>
> > >>>>Maxime
^ permalink raw reply
* Re: [PATCH v11 1/6] ethdev: add Tx preparation
From: Kulasek, TomaszX @ 2016-10-27 16:39 UTC (permalink / raw)
To: Ananyev, Konstantin, Thomas Monjalon; +Cc: dev@dpdk.org
In-Reply-To: <2601191342CEEE43887BDE71AB9772583F0CE8E3@irsmsx105.ger.corp.intel.com>
Hi
> -----Original Message-----
> From: Ananyev, Konstantin
> Sent: Thursday, October 27, 2016 18:24
> To: Thomas Monjalon <thomas.monjalon@6wind.com>
> Cc: Kulasek, TomaszX <tomaszx.kulasek@intel.com>; dev@dpdk.org
> Subject: RE: [dpdk-dev] [PATCH v11 1/6] ethdev: add Tx preparation
>
>
>
> > -----Original Message-----
> > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > Sent: Thursday, October 27, 2016 5:02 PM
> > To: Ananyev, Konstantin <konstantin.ananyev@intel.com>
> > Cc: Kulasek, TomaszX <tomaszx.kulasek@intel.com>; dev@dpdk.org
> > Subject: Re: [dpdk-dev] [PATCH v11 1/6] ethdev: add Tx preparation
> >
> > 2016-10-27 15:52, Ananyev, Konstantin:
> > >
> > > >
> > > > Hi Tomasz,
> > > >
> > > > This is a major new function in the API and I still have some
> comments.
> > > >
> > > > 2016-10-26 14:56, Tomasz Kulasek:
> > > > > --- a/config/common_base
> > > > > +++ b/config/common_base
> > > > > +CONFIG_RTE_ETHDEV_TX_PREP=y
> > > >
> > > > We cannot enable it until it is implemented in every drivers.
> > >
> > > Not sure why?
> > > If tx_pkt_prep == NULL, then rte_eth_tx_prep() would just act as noop.
> > > Right now it is not mandatory for the PMD to implement it.
> >
> > If it is not implemented, the application must do the preparation by
> itself.
> > From patch 6:
> > "
> > Removed pseudo header calculation for udp/tcp/tso packets from
> > application and used Tx preparation API for packet preparation and
> > verification.
> > "
> > So how does it behave with other drivers?
>
> Hmm so it seems that we broke testpmd csumonly mode for non-intel
> drivers..
> My bad, missed that part completely.
> Yes, then I suppose for now we'll need to support both (with and without)
> code paths for testpmd.
> Probably a new fwd mode or just extra parameter for the existing one?
> Any other suggestions?
>
I had sent txprep engine in v2 (http://dpdk.org/dev/patchwork/patch/15775/), but I'm opened on the suggestions. If you like it I can resent it in place of csumonly modification.
Tomasz
> >
> > > > > 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 */
> > > >
> > > > Could you confirm why tx_pkt_prep is not in dev_ops?
> > > > I guess we want to have several implementations?
> > >
> > > Yes, it depends on configuration options, same as tx_pkt_burst.
> > >
> > > >
> > > > Shouldn't we have a const struct control_dev_ops and a struct
> datapath_dev_ops?
> > >
> > > That's probably a good idea, but I suppose it is out of scope for that
> patch.
> >
> > No it's not out of scope.
> > It answers to the question "why is it added in this structure and not
> dev_ops".
> > We won't do this change when nothing else is changed in the struct.
>
> Not sure I understood you here:
> Are you saying datapath_dev_ops/controlpath_dev_ops have to be introduced
> as part of that patch?
> But that's a lot of changes all over rte_ethdev.[h,c].
> It definitely worse a separate patch (might be some discussion) for me.
> Konstantin
>
>
^ permalink raw reply
* Re: [PATCH v11 1/6] ethdev: add Tx preparation
From: Thomas Monjalon @ 2016-10-27 16:39 UTC (permalink / raw)
To: Ananyev, Konstantin; +Cc: dev
In-Reply-To: <2601191342CEEE43887BDE71AB9772583F0CE8E3@irsmsx105.ger.corp.intel.com>
2016-10-27 16:24, Ananyev, Konstantin:
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > 2016-10-27 15:52, Ananyev, Konstantin:
> > > > Hi Tomasz,
> > > >
> > > > This is a major new function in the API and I still have some comments.
> > > >
> > > > 2016-10-26 14:56, Tomasz Kulasek:
> > > > > --- a/config/common_base
> > > > > +++ b/config/common_base
> > > > > +CONFIG_RTE_ETHDEV_TX_PREP=y
> > > >
> > > > We cannot enable it until it is implemented in every drivers.
> > >
> > > Not sure why?
> > > If tx_pkt_prep == NULL, then rte_eth_tx_prep() would just act as noop.
> > > Right now it is not mandatory for the PMD to implement it.
> >
> > If it is not implemented, the application must do the preparation by itself.
> > From patch 6:
> > "
> > Removed pseudo header calculation for udp/tcp/tso packets from
> > application and used Tx preparation API for packet preparation and
> > verification.
> > "
> > So how does it behave with other drivers?
>
> Hmm so it seems that we broke testpmd csumonly mode for non-intel drivers..
> My bad, missed that part completely.
> Yes, then I suppose for now we'll need to support both (with and without) code paths for testpmd.
> Probably a new fwd mode or just extra parameter for the existing one?
> Any other suggestions?
Please think how we can use it in every applications.
It is not ready.
Either we introduce the API without enabling it, or we implement it
in every drivers.
> > > > > 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 */
> > > >
> > > > Could you confirm why tx_pkt_prep is not in dev_ops?
> > > > I guess we want to have several implementations?
> > >
> > > Yes, it depends on configuration options, same as tx_pkt_burst.
> > >
> > > >
> > > > Shouldn't we have a const struct control_dev_ops and a struct datapath_dev_ops?
> > >
> > > That's probably a good idea, but I suppose it is out of scope for that patch.
> >
> > No it's not out of scope.
> > It answers to the question "why is it added in this structure and not dev_ops".
> > We won't do this change when nothing else is changed in the struct.
>
> Not sure I understood you here:
> Are you saying datapath_dev_ops/controlpath_dev_ops have to be introduced as part of that patch?
> But that's a lot of changes all over rte_ethdev.[h,c].
> It definitely worse a separate patch (might be some discussion) for me.
Yes it could be a separate patch in the same patchset.
^ permalink raw reply
* Re: [PATCH v11 1/6] ethdev: add Tx preparation
From: Kulasek, TomaszX @ 2016-10-27 16:29 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev@dpdk.org
In-Reply-To: <1499338.8Le0ABsxDG@xps13>
Hi Thomas,
> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Thursday, October 27, 2016 17:01
> To: Kulasek, TomaszX <tomaszx.kulasek@intel.com>
> Cc: dev@dpdk.org; olivier.matz@6wind.com
> Subject: Re: [dpdk-dev] [PATCH v11 1/6] ethdev: add Tx preparation
>
> Hi Tomasz,
>
> This is a major new function in the API and I still have some comments.
>
> 2016-10-26 14:56, Tomasz Kulasek:
> > --- a/config/common_base
> > +++ b/config/common_base
> > +CONFIG_RTE_ETHDEV_TX_PREP=y
>
> We cannot enable it until it is implemented in every drivers.
>
For most of drivers it's safe to enable it by default and if this feature is not supported, no checks/modifications are done. In that meaning the processing path is the same as without using Tx preparation.
Introducing this macro was discussed in the threads:
http://dpdk.org/ml/archives/dev/2016-September/046437.html
http://dpdk.org/dev/patchwork/patch/15770/
Short conclusion:
Jerin Jacob pointed, that it can have significant impact on some architectures (such a low-end ARMv7, ARMv8 targets which may not have PCIE-RC support and have only integrated NIC controller), even if this feature is not implemented.
We've added this macro to provide an ability to use NOOP operation and allow turn off this feature if will have adverse effect on specific configuration/hardware.
> > 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 */
>
> Could you confirm why tx_pkt_prep is not in dev_ops?
> I guess we want to have several implementations?
>
Yes, the implementation may vary on selected tx_burst path (e.g. vector implementation, simple implementation, full featured, and so on, and can have another requirements, such a implemented features, performance requirements for each implementation).
The path is chosen based on the application requirements transparently and we have a pair of callbacks -- tx_burst and corresponding callback (which depends directly on tx_burst path).
> Shouldn't we have a const struct control_dev_ops and a struct
> datapath_dev_ops?
>
> > +rte_eth_tx_prep(uint8_t port_id, uint16_t queue_id, struct rte_mbuf
> **tx_pkts,
> > + uint16_t nb_pkts)
>
> The word "prep" can be understood as "prepend".
> Why not rte_eth_tx_prepare?
>
I do not mind.
> > +/**
> > + * 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, are not fragmented and can be safely modified.
>
> What happens otherwise?
>
There are requirements for this helper function. For Tx preparation callback we check this requirement and if it fails, -NOTSUP errno is returned.
> > + *
> > + * @param m
> > + * The packet mbuf to be fixed.
> > + * @return
> > + * 0 if checksum is initialized properly
> > + */
> > +static inline int
> > +rte_phdr_cksum_fix(struct rte_mbuf *m)
>
> Could we find a better name for this function?
> - About the prefix, rte_ip_ ?
> - About the scope, where this phdr_cksum is specified?
> Isn't it an intel_phdr_cksum to match what hardware expects?
> - About the verb, is it really fixing something broken?
> Or just writing into a mbuf?
> I would suggest rte_ip_intel_cksum_prepare.
Fixes in the meaning of requirements for offloads, which states e.g. that to use specific Tx offload we should to fill checksums in a proper way, if not, thee settings are not valid and should be fixed.
But you're right, prepare is better word.
About the function name, maybe rte_net_intel_chksum_prepare will be better while it prepares also tcp/udp headers and is placed in rte_net.h?
Tomasz
^ permalink raw reply
* Re: [PATCH v11 1/6] ethdev: add Tx preparation
From: Ananyev, Konstantin @ 2016-10-27 16:24 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev@dpdk.org
In-Reply-To: <2078955.d1Aiqtukxu@xps13>
> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Thursday, October 27, 2016 5:02 PM
> To: Ananyev, Konstantin <konstantin.ananyev@intel.com>
> Cc: Kulasek, TomaszX <tomaszx.kulasek@intel.com>; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v11 1/6] ethdev: add Tx preparation
>
> 2016-10-27 15:52, Ananyev, Konstantin:
> >
> > >
> > > Hi Tomasz,
> > >
> > > This is a major new function in the API and I still have some comments.
> > >
> > > 2016-10-26 14:56, Tomasz Kulasek:
> > > > --- a/config/common_base
> > > > +++ b/config/common_base
> > > > +CONFIG_RTE_ETHDEV_TX_PREP=y
> > >
> > > We cannot enable it until it is implemented in every drivers.
> >
> > Not sure why?
> > If tx_pkt_prep == NULL, then rte_eth_tx_prep() would just act as noop.
> > Right now it is not mandatory for the PMD to implement it.
>
> If it is not implemented, the application must do the preparation by itself.
> From patch 6:
> "
> Removed pseudo header calculation for udp/tcp/tso packets from
> application and used Tx preparation API for packet preparation and
> verification.
> "
> So how does it behave with other drivers?
Hmm so it seems that we broke testpmd csumonly mode for non-intel drivers..
My bad, missed that part completely.
Yes, then I suppose for now we'll need to support both (with and without) code paths for testpmd.
Probably a new fwd mode or just extra parameter for the existing one?
Any other suggestions?
>
> > > > 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 */
> > >
> > > Could you confirm why tx_pkt_prep is not in dev_ops?
> > > I guess we want to have several implementations?
> >
> > Yes, it depends on configuration options, same as tx_pkt_burst.
> >
> > >
> > > Shouldn't we have a const struct control_dev_ops and a struct datapath_dev_ops?
> >
> > That's probably a good idea, but I suppose it is out of scope for that patch.
>
> No it's not out of scope.
> It answers to the question "why is it added in this structure and not dev_ops".
> We won't do this change when nothing else is changed in the struct.
Not sure I understood you here:
Are you saying datapath_dev_ops/controlpath_dev_ops have to be introduced as part of that patch?
But that's a lot of changes all over rte_ethdev.[h,c].
It definitely worse a separate patch (might be some discussion) for me.
Konstantin
^ permalink raw reply
* Re: PCIe Hot Insert/Remove Support
From: Thomas Monjalon @ 2016-10-27 16:08 UTC (permalink / raw)
To: Walker, Benjamin; +Cc: dev
In-Reply-To: <1477332995.71904.36.camel@intel.com>
Hi Benjamin,
2016-10-24 18:16, Walker, Benjamin:
> 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?
Yes it seems to be a reasonnable fix.
However we could improve this design a lot.
I'll try to describe the big picture around PCI hotplugging below.
PCI was too much mixed in DPDK code, so we are sorting out what is generic
to every buses and devices, and what is specific to PCI.
Then we want to manage PCI devices as any other device (real or virtual).
>From a generic perspective, we should be able to manage startup and hotplug
with few API functions:
- scan a bus or all of them (called at startup)
note: scanning for vdev is an argument parsing
- receive a notification (callback registered by the application)
note: whitelist/blacklist can be handled here at the application level
- match the device with a driver
- initialize the device in the matching driver
note: some drivers require binding with a kernel module, and that must
be implemented in EAL
The last missing part for a true hotplug is receiving hardware events
so that we don't need to manually scan anymore.
Hope it will answer your question.
We are waiting for contributions to progress in this direction. Thanks
^ permalink raw reply
* Re: [PATCH v11 1/6] ethdev: add Tx preparation
From: Thomas Monjalon @ 2016-10-27 16:02 UTC (permalink / raw)
To: Ananyev, Konstantin; +Cc: dev
In-Reply-To: <2601191342CEEE43887BDE71AB9772583F0CD83D@irsmsx105.ger.corp.intel.com>
2016-10-27 15:52, Ananyev, Konstantin:
>
> >
> > Hi Tomasz,
> >
> > This is a major new function in the API and I still have some comments.
> >
> > 2016-10-26 14:56, Tomasz Kulasek:
> > > --- a/config/common_base
> > > +++ b/config/common_base
> > > +CONFIG_RTE_ETHDEV_TX_PREP=y
> >
> > We cannot enable it until it is implemented in every drivers.
>
> Not sure why?
> If tx_pkt_prep == NULL, then rte_eth_tx_prep() would just act as noop.
> Right now it is not mandatory for the PMD to implement it.
If it is not implemented, the application must do the preparation by itself.
>From patch 6:
"
Removed pseudo header calculation for udp/tcp/tso packets from
application and used Tx preparation API for packet preparation and
verification.
"
So how does it behave with other drivers?
> > > 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 */
> >
> > Could you confirm why tx_pkt_prep is not in dev_ops?
> > I guess we want to have several implementations?
>
> Yes, it depends on configuration options, same as tx_pkt_burst.
>
> >
> > Shouldn't we have a const struct control_dev_ops and a struct datapath_dev_ops?
>
> That's probably a good idea, but I suppose it is out of scope for that patch.
No it's not out of scope.
It answers to the question "why is it added in this structure and not dev_ops".
We won't do this change when nothing else is changed in the struct.
^ permalink raw reply
* Re: [PATCH v11 1/6] ethdev: add Tx preparation
From: Ananyev, Konstantin @ 2016-10-27 15:52 UTC (permalink / raw)
To: Thomas Monjalon, Kulasek, TomaszX; +Cc: dev@dpdk.org
In-Reply-To: <1499338.8Le0ABsxDG@xps13>
>
> Hi Tomasz,
>
> This is a major new function in the API and I still have some comments.
>
> 2016-10-26 14:56, Tomasz Kulasek:
> > --- a/config/common_base
> > +++ b/config/common_base
> > +CONFIG_RTE_ETHDEV_TX_PREP=y
>
> We cannot enable it until it is implemented in every drivers.
Not sure why?
If tx_pkt_prep == NULL, then rte_eth_tx_prep() would just act as noop.
Right now it is not mandatory for the PMD to implement it.
>
> > 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 */
>
> Could you confirm why tx_pkt_prep is not in dev_ops?
> I guess we want to have several implementations?
Yes, it depends on configuration options, same as tx_pkt_burst.
>
> Shouldn't we have a const struct control_dev_ops and a struct datapath_dev_ops?
That's probably a good idea, but I suppose it is out of scope for that patch.
Konstantin
^ permalink raw reply
* [PATCH v6 21/21] eal/crypto: Support rte_soc_driver/device for cryptodev
From: Shreyansh Jain @ 2016-10-27 15:17 UTC (permalink / raw)
To: dev; +Cc: Shreyansh Jain, thomas.monjalon, viktorin
In-Reply-To: <1477581467-12588-1-git-send-email-shreyansh.jain@nxp.com>
- rte_cryptodev_driver/rte_cryptodev_dev embeds rte_soc_driver/device for
linking SoC PMDs to crypto devices.
- Add probe and remove functions linked
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
lib/librte_cryptodev/rte_cryptodev.c | 122 ++++++++++++++++++++++++-
lib/librte_cryptodev/rte_cryptodev.h | 3 +
lib/librte_cryptodev/rte_cryptodev_pmd.h | 18 +++-
lib/librte_cryptodev/rte_cryptodev_version.map | 2 +
4 files changed, 140 insertions(+), 5 deletions(-)
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index 127e8d0..77ec9fe 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -422,7 +422,8 @@ rte_cryptodev_pci_probe(struct rte_pci_driver *pci_drv,
int retval;
- cryptodrv = (struct rte_cryptodev_driver *)pci_drv;
+ cryptodrv = container_of(pci_drv, struct rte_cryptodev_driver,
+ pci_drv);
if (cryptodrv == NULL)
return -ENODEV;
@@ -489,7 +490,8 @@ rte_cryptodev_pci_remove(struct rte_pci_device *pci_dev)
if (cryptodev == NULL)
return -ENODEV;
- cryptodrv = (const struct rte_cryptodev_driver *)pci_dev->driver;
+ cryptodrv = container_of(pci_dev->driver, struct rte_cryptodev_driver,
+ pci_drv);
if (cryptodrv == NULL)
return -ENODEV;
@@ -513,6 +515,111 @@ rte_cryptodev_pci_remove(struct rte_pci_device *pci_dev)
return 0;
}
+
+int
+rte_cryptodev_soc_probe(struct rte_soc_driver *soc_drv,
+ struct rte_soc_device *soc_dev)
+{
+ struct rte_cryptodev_driver *cryptodrv;
+ struct rte_cryptodev *cryptodev;
+
+ char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
+
+ int retval;
+
+ cryptodrv = container_of(soc_drv, struct rte_cryptodev_driver,
+ soc_drv);
+
+ rte_eal_soc_device_name(&soc_dev->addr, cryptodev_name,
+ sizeof(cryptodev_name));
+
+ cryptodev = rte_cryptodev_pmd_allocate(cryptodev_name,
+ rte_socket_id());
+ if (cryptodev == NULL)
+ return -ENOMEM;
+
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ cryptodev->data->dev_private =
+ rte_zmalloc_socket(
+ "cryptodev private structure",
+ cryptodrv->dev_private_size,
+ RTE_CACHE_LINE_SIZE,
+ rte_socket_id());
+
+ if (cryptodev->data->dev_private == NULL)
+ rte_panic("Cannot allocate memzone for private "
+ "device data");
+ }
+
+ cryptodev->soc_dev = soc_dev;
+ cryptodev->driver = cryptodrv;
+
+ /* init user callbacks */
+ TAILQ_INIT(&(cryptodev->link_intr_cbs));
+
+ /* Invoke PMD device initialization function */
+ retval = (*cryptodrv->cryptodev_init)(cryptodrv, cryptodev);
+ if (retval == 0)
+ return 0;
+
+ CDEV_LOG_ERR("driver %s: cryptodev_init(%s) failed\n",
+ soc_drv->driver.name,
+ soc_dev->addr.name);
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ rte_free(cryptodev->data->dev_private);
+
+ cryptodev->attached = RTE_CRYPTODEV_DETACHED;
+ cryptodev_globals.nb_devs--;
+
+ return -ENXIO;
+}
+
+int
+rte_cryptodev_soc_remove(struct rte_soc_device *soc_dev)
+{
+ const struct rte_cryptodev_driver *cryptodrv;
+ struct rte_cryptodev *cryptodev;
+ char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
+ int ret;
+
+ if (soc_dev == NULL)
+ return -EINVAL;
+
+ rte_eal_soc_device_name(&soc_dev->addr, cryptodev_name,
+ sizeof(cryptodev_name));
+
+ cryptodev = rte_cryptodev_pmd_get_named_dev(cryptodev_name);
+ if (cryptodev == NULL)
+ return -ENODEV;
+
+ cryptodrv = container_of(soc_dev->driver,
+ struct rte_cryptodev_driver, soc_drv);
+ if (cryptodrv == NULL)
+ return -ENODEV;
+
+ /* Invoke PMD device uninit function */
+ if (*cryptodrv->cryptodev_uninit) {
+ ret = (*cryptodrv->cryptodev_uninit)(cryptodrv, cryptodev);
+ if (ret)
+ return ret;
+ }
+
+ /* free crypto device */
+ rte_cryptodev_pmd_release_device(cryptodev);
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ rte_free(cryptodev->data->dev_private);
+
+ cryptodev->pci_dev = NULL;
+ cryptodev->soc_dev = NULL;
+ cryptodev->driver = NULL;
+ cryptodev->data = NULL;
+
+ return 0;
+}
+
uint16_t
rte_cryptodev_queue_pair_count(uint8_t dev_id)
{
@@ -868,8 +975,15 @@ rte_cryptodev_info_get(uint8_t dev_id, struct rte_cryptodev_info *dev_info)
(*dev->dev_ops->dev_infos_get)(dev, dev_info);
dev_info->pci_dev = dev->pci_dev;
- if (dev->driver)
- dev_info->driver_name = dev->driver->pci_drv.driver.name;
+ dev_info->soc_dev = dev->soc_dev;
+ if (dev->driver) {
+ if (dev->soc_dev)
+ dev_info->driver_name
+ = dev->driver->soc_drv.driver.name;
+ else
+ dev_info->driver_name
+ = dev->driver->pci_drv.driver.name;
+ }
}
diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index 8f63e8f..85ce5cb 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -244,6 +244,7 @@ struct rte_cryptodev_info {
const char *driver_name; /**< Driver name. */
enum rte_cryptodev_type dev_type; /**< Device type */
struct rte_pci_device *pci_dev; /**< PCI information. */
+ struct rte_soc_device *soc_dev; /**< SoC information. */
uint64_t feature_flags; /**< Feature flags */
@@ -623,6 +624,8 @@ struct rte_cryptodev {
/**< Supported features */
struct rte_pci_device *pci_dev;
/**< PCI info. supplied by probing */
+ struct rte_soc_device *soc_dev;
+ /**< SoC info. supplied by probing/Scanning */
enum rte_cryptodev_type dev_type;
/**< Crypto device type */
diff --git a/lib/librte_cryptodev/rte_cryptodev_pmd.h b/lib/librte_cryptodev/rte_cryptodev_pmd.h
index abfe2dc..a8af2ce 100644
--- a/lib/librte_cryptodev/rte_cryptodev_pmd.h
+++ b/lib/librte_cryptodev/rte_cryptodev_pmd.h
@@ -48,6 +48,7 @@ extern "C" {
#include <rte_dev.h>
#include <rte_pci.h>
+#include <rte_soc.h>
#include <rte_malloc.h>
#include <rte_mbuf.h>
#include <rte_mempool.h>
@@ -131,7 +132,8 @@ typedef int (*cryptodev_uninit_t)(const struct rte_cryptodev_driver *drv,
* - The size of the private data to allocate for each matching device.
*/
struct rte_cryptodev_driver {
- struct rte_pci_driver pci_drv; /**< The PMD is also a PCI driver. */
+ struct rte_pci_driver pci_drv; /**< The PMD is PCI type driver. */
+ struct rte_soc_driver soc_drv; /**< The PMD is SoC type driver. */
unsigned dev_private_size; /**< Size of device private data. */
cryptodev_init_t cryptodev_init; /**< Device init function. */
@@ -519,6 +521,20 @@ int rte_cryptodev_pci_probe(struct rte_pci_driver *pci_drv,
*/
int rte_cryptodev_pci_remove(struct rte_pci_device *pci_dev);
+/**
+ * Wrapper for use by SoC drivers as a .devinit function to attach to a
+ * cryptodev interface.
+ */
+int rte_cryptodev_soc_probe(struct rte_soc_driver *soc_drv,
+ struct rte_soc_device *soc_dev);
+
+/**
+ * Wrapper for use by SoC drivers as a .devuninit function to detach a
+ * cryptodev interface.
+ */
+int rte_cryptodev_soc_remove(struct rte_soc_device *soc_dev);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/librte_cryptodev/rte_cryptodev_version.map b/lib/librte_cryptodev/rte_cryptodev_version.map
index 9dde0e7..d81073e 100644
--- a/lib/librte_cryptodev/rte_cryptodev_version.map
+++ b/lib/librte_cryptodev/rte_cryptodev_version.map
@@ -44,5 +44,7 @@ DPDK_16.11 {
rte_cryptodev_pci_probe;
rte_cryptodev_pci_remove;
+ rte_cryptodev_soc_probe;
+ rte_cryptodev_soc_remove;
} DPDK_16.07;
--
2.7.4
^ permalink raw reply related
* [PATCH v6 20/21] ether: introduce ethernet dev probe remove
From: Shreyansh Jain @ 2016-10-27 15:17 UTC (permalink / raw)
To: dev; +Cc: Shreyansh Jain, thomas.monjalon, viktorin
In-Reply-To: <1477581467-12588-1-git-send-email-shreyansh.jain@nxp.com>
From: Jan Viktorin <viktorin@rehivetech.com>
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>
---
lib/librte_ether/rte_ethdev.c | 148 +++++++++++++++++++++++++++++++++++++++++-
lib/librte_ether/rte_ethdev.h | 31 +++++++++
2 files changed, 177 insertions(+), 2 deletions(-)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 4c61246..972e916 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -325,6 +325,101 @@ rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
}
int
+rte_eth_dev_soc_probe(struct rte_soc_driver *soc_drv,
+ struct rte_soc_device *soc_dev)
+{
+ struct eth_driver *eth_drv;
+ struct rte_eth_dev *eth_dev;
+ char ethdev_name[RTE_ETH_NAME_MAX_LEN];
+
+ int diag;
+
+ eth_drv = container_of(soc_drv, struct eth_driver, soc_drv);
+
+ rte_eal_soc_device_name(&soc_dev->addr, ethdev_name,
+ sizeof(ethdev_name));
+
+ eth_dev = rte_eth_dev_allocate(ethdev_name);
+ if (eth_dev == NULL)
+ return -ENOMEM;
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ eth_dev->data->dev_private = rte_zmalloc(
+ "ethdev private structure",
+ eth_drv->dev_private_size,
+ RTE_CACHE_LINE_SIZE);
+ if (eth_dev->data->dev_private == NULL)
+ rte_panic("Cannot allocate memzone for private port "
+ "data\n");
+ }
+ eth_dev->soc_dev = soc_dev;
+ eth_dev->driver = eth_drv;
+ eth_dev->data->rx_mbuf_alloc_failed = 0;
+
+ /* init user callbacks */
+ TAILQ_INIT(&(eth_dev->link_intr_cbs));
+
+ /*
+ * Set the default MTU.
+ */
+ eth_dev->data->mtu = ETHER_MTU;
+
+ /* Invoke PMD device initialization function */
+ diag = (*eth_drv->eth_dev_init)(eth_dev);
+ if (diag == 0)
+ return 0;
+
+ RTE_PMD_DEBUG_TRACE("driver %s: eth_dev_init(%s) failed\n",
+ soc_drv->driver.name,
+ soc_dev->addr.name);
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ rte_free(eth_dev->data->dev_private);
+ rte_eth_dev_release_port(eth_dev);
+ return diag;
+}
+
+int
+rte_eth_dev_soc_remove(struct rte_soc_device *soc_dev)
+{
+ const struct eth_driver *eth_drv;
+ struct rte_eth_dev *eth_dev;
+ char ethdev_name[RTE_ETH_NAME_MAX_LEN];
+ int ret;
+
+ if (soc_dev == NULL)
+ return -EINVAL;
+
+ rte_eal_soc_device_name(&soc_dev->addr, ethdev_name,
+ sizeof(ethdev_name));
+
+ eth_dev = rte_eth_dev_allocated(ethdev_name);
+ if (eth_dev == NULL)
+ return -ENODEV;
+
+ eth_drv = container_of(soc_dev->driver, struct eth_driver, soc_drv);
+
+ /* Invoke PMD device uninit function */
+ if (*eth_drv->eth_dev_uninit) {
+ ret = (*eth_drv->eth_dev_uninit)(eth_dev);
+ if (ret)
+ return ret;
+ }
+
+ /* free ether device */
+ rte_eth_dev_release_port(eth_dev);
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ rte_free(eth_dev->data->dev_private);
+
+ eth_dev->soc_dev = NULL;
+ eth_dev->driver = NULL;
+ eth_dev->data = NULL;
+
+ return 0;
+}
+
+
+int
rte_eth_dev_is_valid_port(uint8_t port_id)
{
if (port_id >= RTE_MAX_ETHPORTS ||
@@ -1557,6 +1652,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
(*dev->dev_ops->dev_infos_get)(dev, dev_info);
dev_info->pci_dev = dev->pci_dev;
+ dev_info->soc_dev = dev->soc_dev;
dev_info->driver_name = dev->data->drv_name;
dev_info->nb_rx_queues = dev->data->nb_rx_queues;
dev_info->nb_tx_queues = dev->data->nb_tx_queues;
@@ -2535,8 +2631,15 @@ _rte_eth_dev_callback_process(struct rte_eth_dev *dev,
static inline
struct rte_intr_handle *eth_dev_get_intr_handle(struct rte_eth_dev *dev)
{
- if (dev->pci_dev)
+ if (dev->pci_dev) {
+ RTE_ASSERT(dev->soc_dev == NULL);
return &dev->pci_dev->intr_handle;
+ }
+
+ if (dev->soc_dev) {
+ RTE_ASSERT(dev->pci_dev == NULL);
+ return &dev->soc_dev->intr_handle;
+ }
RTE_ASSERT(0);
return NULL;
@@ -2573,6 +2676,23 @@ rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data)
return 0;
}
+static inline
+const char *eth_dev_get_driver_name(const struct rte_eth_dev *dev)
+{
+ if (dev->pci_dev) {
+ RTE_ASSERT(dev->soc_dev == NULL);
+ return dev->driver->pci_drv.driver.name;
+ }
+
+ if (dev->soc_dev) {
+ RTE_ASSERT(dev->pci_dev == NULL);
+ return dev->driver->soc_drv.driver.name;
+ }
+
+ RTE_ASSERT(0);
+ return NULL;
+}
+
const struct rte_memzone *
rte_eth_dma_zone_reserve(const struct rte_eth_dev *dev, const char *ring_name,
uint16_t queue_id, size_t size, unsigned align,
@@ -2580,9 +2700,11 @@ rte_eth_dma_zone_reserve(const struct rte_eth_dev *dev, const char *ring_name,
{
char z_name[RTE_MEMZONE_NAMESIZE];
const struct rte_memzone *mz;
+ const char *drv_name;
+ drv_name = eth_dev_get_driver_name(dev);
snprintf(z_name, sizeof(z_name), "%s_%s_%d_%d",
- dev->driver->pci_drv.driver.name, ring_name,
+ drv_name, ring_name,
dev->data->port_id, queue_id);
mz = rte_memzone_lookup(z_name);
@@ -3229,6 +3351,28 @@ rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_de
eth_dev->data->drv_name = pci_dev->driver->driver.name;
}
+void
+rte_eth_copy_soc_info(struct rte_eth_dev *eth_dev,
+ struct rte_soc_device *soc_dev)
+{
+ if ((eth_dev == NULL) || (soc_dev == NULL)) {
+ RTE_PMD_DEBUG_TRACE("NULL pointer eth_dev=%p soc_dev=%p\n",
+ eth_dev, soc_dev);
+ return;
+ }
+
+ RTE_ASSERT(eth_dev->soc_dev != NULL);
+
+ eth_dev->data->dev_flags = 0;
+ if (soc_dev->driver->drv_flags & RTE_SOC_DRV_INTR_LSC)
+ eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
+ if (soc_dev->driver->drv_flags & RTE_SOC_DRV_DETACHABLE)
+ eth_dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE;
+
+ eth_dev->data->numa_node = soc_dev->device.numa_node;
+ eth_dev->data->drv_name = soc_dev->driver->driver.name;
+}
+
int
rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
struct rte_eth_l2_tunnel_conf *l2_tunnel)
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index f893fe0..ff7958f 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -180,6 +180,7 @@ extern "C" {
#include <rte_log.h>
#include <rte_interrupts.h>
#include <rte_pci.h>
+#include <rte_soc.h>
#include <rte_dev.h>
#include <rte_devargs.h>
#include "rte_ether.h"
@@ -877,6 +878,7 @@ struct rte_eth_conf {
*/
struct rte_eth_dev_info {
struct rte_pci_device *pci_dev; /**< Device PCI information. */
+ struct rte_soc_device *soc_dev; /**< Device SoC information. */
const char *driver_name; /**< Device Driver name. */
unsigned int if_index; /**< Index to bound host interface, or 0 if none.
Use if_indextoname() to translate into an interface name. */
@@ -1626,6 +1628,7 @@ struct rte_eth_dev {
const struct eth_driver *driver;/**< Driver for this device */
const struct eth_dev_ops *dev_ops; /**< Functions exported by PMD */
struct rte_pci_device *pci_dev; /**< PCI info. supplied by probing */
+ struct rte_soc_device *soc_dev; /**< SoC info. supplied by probing */
/** User application callbacks for NIC interrupts */
struct rte_eth_dev_cb_list link_intr_cbs;
/**
@@ -1860,6 +1863,7 @@ typedef int (*eth_dev_uninit_t)(struct rte_eth_dev *eth_dev);
*/
struct eth_driver {
struct rte_pci_driver pci_drv; /**< The PMD is also a PCI driver. */
+ struct rte_soc_driver soc_drv; /**< The PMD is also a SoC driver. */
eth_dev_init_t eth_dev_init; /**< Device init function. */
eth_dev_uninit_t eth_dev_uninit; /**< Device uninit function. */
unsigned int dev_private_size; /**< Size of device private data. */
@@ -4262,6 +4266,20 @@ void rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev,
struct rte_pci_device *pci_dev);
/**
+ * Copy SoC device info to the Ethernet device data.
+ *
+ * @param eth_dev
+ * The *eth_dev* pointer is the address of the *rte_eth_dev* structure.
+ * @param soc_dev
+ * The *soc_dev* pointer is the address of the *rte_soc_device* structure.
+ *
+ * @return
+ * - 0 on success, negative on error
+ */
+void rte_eth_copy_soc_info(struct rte_eth_dev *eth_dev,
+ struct rte_soc_device *soc_dev);
+
+/**
* Create memzone for HW rings.
* malloc can't be used as the physical address is needed.
* If the memzone is already created, then this function returns a ptr
@@ -4376,6 +4394,19 @@ int rte_eth_dev_pci_probe(struct rte_pci_driver *pci_drv,
*/
int rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev);
+/**
+ * Wrapper for use by SoC drivers as a .devinit function to attach to a ethdev
+ * interface.
+ */
+int rte_eth_dev_soc_probe(struct rte_soc_driver *soc_drv,
+ struct rte_soc_device *soc_dev);
+
+/**
+ * Wrapper for use by SoC drivers as a .devuninit function to detach a ethdev
+ * interface.
+ */
+int rte_eth_dev_soc_remove(struct rte_soc_device *soc_dev);
+
#ifdef __cplusplus
}
#endif
--
2.7.4
^ permalink raw reply related
* [PATCH v6 19/21] ether: extract function eth_dev_get_intr_handle
From: Shreyansh Jain @ 2016-10-27 15:17 UTC (permalink / raw)
To: dev; +Cc: Shreyansh Jain, thomas.monjalon, viktorin
In-Reply-To: <1477581467-12588-1-git-send-email-shreyansh.jain@nxp.com>
From: Jan Viktorin <viktorin@rehivetech.com>
We abstract access to the intr_handle here as we want to get
it either from the pci_dev or soc_dev.
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>
---
lib/librte_ether/rte_ethdev.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index a1e3aaf..4c61246 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2532,6 +2532,16 @@ _rte_eth_dev_callback_process(struct rte_eth_dev *dev,
rte_spinlock_unlock(&rte_eth_dev_cb_lock);
}
+static inline
+struct rte_intr_handle *eth_dev_get_intr_handle(struct rte_eth_dev *dev)
+{
+ if (dev->pci_dev)
+ return &dev->pci_dev->intr_handle;
+
+ RTE_ASSERT(0);
+ return NULL;
+}
+
int
rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data)
{
@@ -2544,7 +2554,7 @@ rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data)
RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
dev = &rte_eth_devices[port_id];
- intr_handle = &dev->pci_dev->intr_handle;
+ intr_handle = eth_dev_get_intr_handle(dev);
if (!intr_handle->intr_vec) {
RTE_PMD_DEBUG_TRACE("RX Intr vector unset\n");
return -EPERM;
@@ -2604,7 +2614,7 @@ rte_eth_dev_rx_intr_ctl_q(uint8_t port_id, uint16_t queue_id,
return -EINVAL;
}
- intr_handle = &dev->pci_dev->intr_handle;
+ intr_handle = eth_dev_get_intr_handle(dev);
if (!intr_handle->intr_vec) {
RTE_PMD_DEBUG_TRACE("RX Intr vector unset\n");
return -EPERM;
--
2.7.4
^ permalink raw reply related
* [PATCH v6 18/21] ether: verify we copy info from a PCI device
From: Shreyansh Jain @ 2016-10-27 15:17 UTC (permalink / raw)
To: dev; +Cc: Shreyansh Jain, thomas.monjalon, viktorin
In-Reply-To: <1477581467-12588-1-git-send-email-shreyansh.jain@nxp.com>
From: Jan Viktorin <viktorin@rehivetech.com>
Now that different types of ethdev exist, check for presence of PCI dev
while copying out the info.
Similar would be done for SoC.
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>
---
lib/librte_ether/rte_ethdev.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 347c230..a1e3aaf 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3206,6 +3206,8 @@ rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_de
return;
}
+ RTE_VERIFY(eth_dev->pci_dev != NULL);
+
eth_dev->data->dev_flags = 0;
if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)
eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
--
2.7.4
^ permalink raw reply related
* [PATCH v6 17/21] ether: utilize container_of for pci_drv
From: Shreyansh Jain @ 2016-10-27 15:17 UTC (permalink / raw)
To: dev; +Cc: Shreyansh Jain, thomas.monjalon, viktorin
In-Reply-To: <1477581467-12588-1-git-send-email-shreyansh.jain@nxp.com>
From: Jan Viktorin <viktorin@rehivetech.com>
It is not necessary to place the rte_pci_driver at the beginning
of the rte_eth_dev struct anymore as we use the container_of macro
to get the parent pointer.
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>
---
lib/librte_ether/rte_ethdev.c | 4 ++--
lib/librte_ether/rte_ethdev.h | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index fde8112..347c230 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -241,7 +241,7 @@ rte_eth_dev_pci_probe(struct rte_pci_driver *pci_drv,
int diag;
- eth_drv = (struct eth_driver *)pci_drv;
+ eth_drv = container_of(pci_drv, struct eth_driver, pci_drv);
rte_eal_pci_device_name(&pci_dev->addr, ethdev_name,
sizeof(ethdev_name));
@@ -302,7 +302,7 @@ rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
if (eth_dev == NULL)
return -ENODEV;
- eth_drv = (const struct eth_driver *)pci_dev->driver;
+ eth_drv = container_of(pci_dev->driver, struct eth_driver, pci_drv);
/* Invoke PMD device uninit function */
if (*eth_drv->eth_dev_uninit) {
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 38641e8..f893fe0 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1850,7 +1850,7 @@ typedef int (*eth_dev_uninit_t)(struct rte_eth_dev *eth_dev);
* Each Ethernet driver acts as a PCI driver and is represented by a generic
* *eth_driver* structure that holds:
*
- * - An *rte_pci_driver* structure (which must be the first field).
+ * - An *rte_pci_driver* structure.
*
* - The *eth_dev_init* function invoked for each matching PCI device.
*
--
2.7.4
^ permalink raw reply related
* [PATCH v6 16/21] eal/soc: additional features for SoC
From: Shreyansh Jain @ 2016-10-27 15:17 UTC (permalink / raw)
To: dev; +Cc: Shreyansh Jain, thomas.monjalon, viktorin
In-Reply-To: <1477581467-12588-1-git-send-email-shreyansh.jain@nxp.com>
From: Jan Viktorin <viktorin@rehivetech.com>
Additional features introduced:
- Find kernel driver through sysfs bindings
- Dummy implementation for mapping to kernel driver
- DMA coherency value from sysfs
- Numa node number from sysfs
- Support for updating device during probe if already registered
Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
[Shreyansh: merge multiple patches into single set]
Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
lib/librte_eal/common/eal_common_soc.c | 30 ++++++++
lib/librte_eal/common/eal_private.h | 23 ++++++
lib/librte_eal/common/include/rte_soc.h | 28 +++++++
lib/librte_eal/linuxapp/eal/eal_soc.c | 129 ++++++++++++++++++++++++++++++++
4 files changed, 210 insertions(+)
diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
index 44f5559..29c38e0 100644
--- a/lib/librte_eal/common/eal_common_soc.c
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -114,6 +114,26 @@ rte_eal_soc_probe_one_driver(struct rte_soc_driver *drv,
return ret;
}
+ if (!dev->is_dma_coherent) {
+ if (!(drv->drv_flags & RTE_SOC_DRV_ACCEPT_NONCC)) {
+ RTE_LOG(DEBUG, EAL,
+ " device is not DMA coherent, skipping\n");
+ return 1;
+ }
+ }
+
+ if (drv->drv_flags & RTE_SOC_DRV_NEED_MAPPING) {
+ /* map resources */
+ ret = rte_eal_soc_map_device(dev);
+ if (ret)
+ return ret;
+ } else if (drv->drv_flags & RTE_SOC_DRV_FORCE_UNBIND
+ && rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ /* unbind */
+ if (soc_unbind_kernel_driver(dev) < 0)
+ return -1;
+ }
+
dev->driver = drv;
RTE_VERIFY(drv->probe != NULL);
return drv->probe(drv, dev);
@@ -166,6 +186,10 @@ rte_eal_soc_detach_dev(struct rte_soc_driver *drv,
if (drv->remove && (drv->remove(dev) < 0))
return -1; /* negative value is an error */
+ if (drv->drv_flags & RTE_SOC_DRV_NEED_MAPPING)
+ /* unmap resources for devices */
+ rte_eal_soc_unmap_device(dev);
+
/* clear driver structure */
dev->driver = NULL;
@@ -241,6 +265,12 @@ rte_eal_soc_probe_one(const struct rte_soc_addr *addr)
if (addr == NULL)
return -1;
+ /* update current SoC device in global list, kernel bindings might have
+ * changed since last time we looked at it.
+ */
+ if (soc_update_device(addr) < 0)
+ goto err_return;
+
TAILQ_FOREACH(dev, &soc_device_list, next) {
if (rte_eal_compare_soc_addr(&dev->addr, addr))
continue;
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index d810f9f..30c648d 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -159,6 +159,29 @@ int pci_update_device(const struct rte_pci_addr *addr);
int pci_unbind_kernel_driver(struct rte_pci_device *dev);
/**
+ * Update a soc device object by asking the kernel for the latest information.
+ *
+ * This function is private to EAL.
+ *
+ * @param addr
+ * The SoC address to look for
+ * @return
+ * - 0 on success.
+ * - negative on error.
+ */
+int soc_update_device(const struct rte_soc_addr *addr);
+
+/**
+ * Unbind kernel driver for this device
+ *
+ * This function is private to EAL.
+ *
+ * @return
+ * 0 on success, negative on error
+ */
+int soc_unbind_kernel_driver(struct rte_soc_device *dev);
+
+/**
* Map the PCI resource of a PCI device in virtual memory
*
* This function is private to EAL.
diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index 8be3db7..d7f7ec8 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -46,9 +46,11 @@ extern "C" {
#include <stdio.h>
#include <stdlib.h>
+#include <sys/queue.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
+#include <limits.h>
#include <rte_dev.h>
#include <rte_eal.h>
@@ -63,6 +65,14 @@ extern struct soc_device_list soc_device_list;
TAILQ_HEAD(soc_driver_list, rte_soc_driver); /**< SoC drivers in D-linked Q. */
TAILQ_HEAD(soc_device_list, rte_soc_device); /**< SoC devices in D-linked Q. */
+#define SOC_MAX_RESOURCE 6
+
+struct rte_soc_resource {
+ uint64_t phys_addr;
+ uint64_t len;
+ void *addr;
+};
+
struct rte_soc_id {
union {
const char *compatible; /**< OF compatible specification */
@@ -84,8 +94,12 @@ struct rte_soc_device {
struct rte_device device; /**< Inherit code device */
struct rte_soc_addr addr; /**< SoC device Location */
struct rte_soc_id *id; /**< SoC device ID list */
+ struct rte_soc_resource mem_resource[SOC_MAX_RESOURCE];
struct rte_intr_handle intr_handle; /**< Interrupt handle */
struct rte_soc_driver *driver; /**< Associated driver */
+ int numa_node; /**< NUMA node connection */
+ int is_dma_coherent; /**< DMA coherent device */
+ enum rte_kernel_driver kdrv; /**< Kernel driver */
};
struct rte_soc_driver;
@@ -139,6 +153,8 @@ struct rte_soc_driver {
#define RTE_SOC_DRV_INTR_LSC 0x0008
/** Device driver supports detaching capability */
#define RTE_SOC_DRV_DETACHABLE 0x0010
+/** Device driver accepts DMA non-coherent devices */
+#define RTE_SOC_DRV_ACCEPT_NONCC 0x0020
/**
* Utility function to write a SoC device name, this device name can later be
@@ -256,6 +272,18 @@ int rte_eal_soc_probe_one(const struct rte_soc_addr *addr);
int rte_eal_soc_detach(const struct rte_soc_addr *addr);
/**
+ * Map SoC device resources into userspace.
+ *
+ * This is called by the EAL if (drv_flags & RTE_SOC_DRV_NEED_MAPPING).
+ */
+int rte_eal_soc_map_device(struct rte_soc_device *dev);
+
+/**
+ * Unmap the device resources.
+ */
+void rte_eal_soc_unmap_device(struct rte_soc_device *dev);
+
+/**
* Dump discovered SoC devices.
*
* @param f
diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c
index d8dfe97..95f7565 100644
--- a/lib/librte_eal/linuxapp/eal/eal_soc.c
+++ b/lib/librte_eal/linuxapp/eal/eal_soc.c
@@ -63,6 +63,45 @@ soc_get_sysfs_path(void)
return path;
}
+int
+soc_unbind_kernel_driver(struct rte_soc_device *dev)
+{
+ char devpath[PATH_MAX];
+
+ snprintf(devpath, sizeof(devpath), "%s/%s",
+ soc_get_sysfs_path(), dev->addr.name);
+
+ return rte_eal_unbind_kernel_driver(devpath, dev->addr.name);
+}
+
+int
+rte_eal_soc_map_device(struct rte_soc_device *dev)
+{
+ int ret = -1;
+
+ /* try mapping the NIC resources using VFIO if it exists */
+ switch (dev->kdrv) {
+ default:
+ RTE_LOG(DEBUG, EAL,
+ " Not managed by a supported kernel driver, skipped\n");
+ ret = 1;
+ break;
+ }
+
+ return ret;
+}
+
+void
+rte_eal_soc_unmap_device(struct rte_soc_device *dev)
+{
+ switch (dev->kdrv) {
+ default:
+ RTE_LOG(DEBUG, EAL,
+ " Not managed by a supported kernel driver, skipped\n");
+ break;
+ }
+}
+
static char *
dev_read_uevent(const char *dirname)
{
@@ -260,6 +299,68 @@ dev_content_free(struct rte_soc_device *dev)
}
}
+static int
+dev_setup_associated_driver(struct rte_soc_device *dev, const char *dirname)
+{
+ char filename[PATH_MAX];
+ char driver[PATH_MAX];
+ int ret;
+
+ /* parse driver */
+ snprintf(filename, sizeof(filename), "%s/driver", dirname);
+ ret = rte_eal_get_kernel_driver_by_path(filename, driver);
+ if (ret < 0) {
+ RTE_LOG(ERR, EAL, "Fail to get kernel driver for %s\n",
+ dirname);
+ return 1;
+ }
+
+ if (!ret)
+ dev->kdrv = RTE_KDRV_UNKNOWN;
+ else
+ dev->kdrv = RTE_KDRV_NONE;
+
+ return 0;
+}
+
+static int
+dev_setup_numa_node(struct rte_soc_device *dev, const char *dirname)
+{
+ char filename[PATH_MAX];
+
+ /* if no NUMA support, set default to 0 */
+ unsigned long tmp = 0;
+ int ret = 0;
+
+ /* get numa node */
+ snprintf(filename, sizeof(filename), "%s/numa_node", dirname);
+
+ if (eal_parse_sysfs_value(filename, &tmp) < 0)
+ ret = 1;
+
+ dev->numa_node = tmp;
+ return ret;
+}
+
+static int
+dev_detect_is_coherent(struct rte_soc_device *dev)
+{
+ char filename[PATH_MAX];
+ FILE *f;
+
+ if (dev->addr.fdt_path == NULL)
+ return 0; /* no way to detect */
+
+ snprintf(filename, sizeof(filename), "%s%s/dma-coherent",
+ "/proc/device-tree", dev->addr.fdt_path);
+ f = fopen(filename, "r");
+ if (f == NULL)
+ return 0;
+
+ fclose(f);
+ return 1;
+}
+
/**
* Scan one SoC sysfs entry, and fill the devices list from it.
* We require to have the uevent file with records: OF_FULLNAME and
@@ -299,6 +400,18 @@ soc_scan_one(const char *dirname, const char *name)
goto fail;
free(uevent); /* not needed anymore */
+ ret = dev_setup_associated_driver(dev, dirname);
+ if (ret)
+ goto fail;
+
+ ret = dev_setup_numa_node(dev, dirname);
+ if (ret < 0)
+ goto fail;
+
+ dev->is_dma_coherent = dev_detect_is_coherent(dev);
+ RTE_LOG(DEBUG, EAL, " DMA %s\n",
+ dev->is_dma_coherent ? "coherent" : "non-coherent");
+
/* device is valid, add in list (sorted) */
if (TAILQ_EMPTY(&soc_device_list)) {
TAILQ_INSERT_TAIL(&soc_device_list, dev, next);
@@ -313,6 +426,11 @@ soc_scan_one(const char *dirname, const char *name)
if (ret < 0) {
TAILQ_INSERT_BEFORE(dev2, dev, next);
} else { /* already registered */
+ dev2->kdrv = dev->kdrv;
+ dev2->is_dma_coherent = dev->is_dma_coherent;
+ memmove(dev2->mem_resource, dev->mem_resource,
+ sizeof(dev->mem_resource));
+
dev_content_free(dev2);
dev2->addr.fdt_path = dev->addr.fdt_path;
dev2->id = dev->id;
@@ -333,6 +451,17 @@ fail:
}
int
+soc_update_device(const struct rte_soc_addr *addr)
+{
+ char filename[PATH_MAX];
+
+ snprintf(filename, sizeof(filename), "%s/%s",
+ soc_get_sysfs_path(), addr->name);
+
+ return soc_scan_one(filename, addr->name);
+}
+
+int
rte_eal_soc_scan_platform_bus(void)
{
struct dirent *e;
--
2.7.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox