>-----Original Message----- >From: dev <dev-boun...@dpdk.org> On Behalf Of Andrew Rybchenko >Sent: Thursday, October 3, 2019 1:11 PM >To: Pavan Nikhilesh Bhagavatula <pbhagavat...@marvell.com>; Jerin >Jacob Kollanukkaran <jer...@marvell.com>; John McNamara ><john.mcnam...@intel.com>; Marko Kovacevic ><marko.kovace...@intel.com>; Thomas Monjalon ><tho...@monjalon.net>; Ferruh Yigit <ferruh.yi...@intel.com> >Cc: dev@dpdk.org >Subject: Re: [dpdk-dev] [PATCH v8 1/7] ethdev: add set ptype function > >On 10/3/19 12:36 AM, pbhagavat...@marvell.com wrote: >> From: Pavan Nikhilesh <pbhagavat...@marvell.com> >> >> Add `rte_eth_dev_set_supported_ptypes` function that will allow the >> application to inform the PMD the packet types it is interested in. >> Based on the ptypes set PMDs can optimize their Rx path. >> >> -If application doesn’t want any ptype information it can call >> `rte_eth_dev_set_supported_ptypes(ethdev_id, >RTE_PTYPE_UNKNOWN, NULL, 0)` >> and PMD may skip packet type processing and set >rte_mbuf::packet_type to >> RTE_PTYPE_UNKNOWN. >> >> -If application doesn’t call `rte_eth_dev_set_supported_ptypes` PMD >can >> return `rte_mbuf::packet_type` with >`rte_eth_dev_get_supported_ptypes`. >> >> -If application is interested only in L2/L3 layer, it can inform the PMD >> to update `rte_mbuf::packet_type` with L2/L3 ptype by calling >> `rte_eth_dev_set_supported_ptypes(ethdev_id, >> RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK, NULL, >0)`. >> >> Suggested-by: Konstantin Ananyev <konstantin.anan...@intel.com> >> Signed-off-by: Pavan Nikhilesh <pbhagavat...@marvell.com> > >With few fixes below: >Reviewed-by: Andrew Rybchenko <arybche...@solarflare.com> > >[snip] > >> diff --git a/lib/librte_ethdev/rte_ethdev.c >b/lib/librte_ethdev/rte_ethdev.c >> index 17d183e1f..57bc12b56 100644 >> --- a/lib/librte_ethdev/rte_ethdev.c >> +++ b/lib/librte_ethdev/rte_ethdev.c >> @@ -2602,6 +2602,65 @@ >rte_eth_dev_get_supported_ptypes(uint16_t port_id, uint32_t >ptype_mask, >> return j; >> } >> >> +int >> +rte_eth_dev_set_supported_ptypes(uint16_t port_id, uint32_t >ptype_mask, >> + uint32_t *set_ptypes, unsigned int >num) >> +{ >> + unsigned int i, j; >> + struct rte_eth_dev *dev; >> + const uint32_t *all_ptypes; >> + >> + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); >> + dev = &rte_eth_devices[port_id]; >> + >> + if (num > 0 && set_ptypes == NULL) >> + return -EINVAL; >> + >> + if (*dev->dev_ops->dev_supported_ptypes_get == NULL || >> + *dev->dev_ops->dev_supported_ptypes_set >== NULL) { >> + if (num > 0) >> + set_ptypes[0] = RTE_PTYPE_UNKNOWN; >> + return 0; >> + } >> + >> + if (ptype_mask == 0) { >> + if (num > 0) >> + set_ptypes[0] = RTE_PTYPE_UNKNOWN; >> + >> + return (*dev->dev_ops- >>dev_supported_ptypes_set)(dev, >> + ptype_mask); >> + } >> + >> + all_ptypes = (*dev->dev_ops- >>dev_supported_ptypes_get)(dev); >> + if (all_ptypes == NULL) { >> + if (num > 0) >> + set_ptypes[0] = RTE_PTYPE_UNKNOWN; >> + >> + return 0; >> + } >> + >> + /* >> + * Accodommodate as many set_ptypes as possible. If the >supplied >> + * set_ptypes array is insufficient fill it partially. >> + */ >> + for (i = 0, j = 0; set_ptypes != NULL && >> + (all_ptypes[i] != >RTE_PTYPE_UNKNOWN); ++i) { >> + if (ptype_mask & all_ptypes[i]) { >> + if (j < num - 1) { >> + set_ptypes[j] = all_ptypes[i]; >> + j++; >> + continue; >> + } >> + break; >> + } >> + } >> + >> + if (set_ptypes != NULL) >> + set_ptypes[j] = RTE_PTYPE_UNKNOWN; > >Initially I thought that we are safe here, but now realized that we >can write more than num here, e.g. if set_ptypes is not NULL, but num >is 0. >I think the right condition here is (j < num) since it guarantees that >set_ptype is not NULL as well (since num is greater than 0 if unsigned j >is less than num).
Ack will send v9. > >> + >> + return (*dev->dev_ops->dev_supported_ptypes_set)(dev, >ptype_mask); >> +} >> + >> void >> rte_eth_macaddr_get(uint16_t port_id, struct rte_ether_addr >*mac_addr) >> { >> diff --git a/lib/librte_ethdev/rte_ethdev.h >b/lib/librte_ethdev/rte_ethdev.h >> index d9871782e..c577a9172 100644 >> --- a/lib/librte_ethdev/rte_ethdev.h >> +++ b/lib/librte_ethdev/rte_ethdev.h >> @@ -2431,6 +2431,42 @@ int rte_eth_dev_fw_version_get(uint16_t >port_id, >> */ >> int rte_eth_dev_get_supported_ptypes(uint16_t port_id, uint32_t >ptype_mask, >> uint32_t *ptypes, int num); >> +/** >> + * @warning >> + * @b EXPERIMENTAL: this API may change without prior notice. >> + * >> + * Inform Ethernet device of the packet types classification in which >> + * the recipient is interested. >> + * >> + * Application can use this function to set only specific ptypes that it's >> + * interested. This information can be used by the PMD to optimize >Rx path. >> + * >> + * The function accepts an array `set_ptypes` allocated by the caller >to >> + * store the packet types set by the driver, the last element of the >array >> + * is set to RTE_PTYPE_UNKNOWN. The size of the `set_ptype` array >should be >> + * `rte_eth_dev_get_supported_ptypes() + 1` else it might only be >filled >> + * partially. >> + * >> + * @param port_id >> + * The port identifier of the Ethernet device. >> + * @param ptype_mask >> + * The ptype family that application is interested in. > >I think it is better to highlight here that it should be bitwise OR of >RTE_PTYPE_*_MASK or 0. > >BTW, I think it would be useful to check it to avoid misuse of the API >when, for example, RTE_PTYPE_L4_TCP is specified as ptype_mask. I feel the same we could do something like test_ptype_mask = ptype_mask; while (test_ptype_mask) { uint8_t mask = test_ptype_mask & RTE_PTYPE_L2_MASK; if (mask && (mask != RTE_PTYPE_L2_MASK)) { if (num > 0) set_ptypes[0] = RTE_PTYPE_UNKNOWN; return -EINVAL; } test_ptype_mask >>= __builtin_popcount(RTE_PTYPE_L2_MASK); } > >> + * @param set_ptypes >> + * An array pointer to store set packet types, allocated by caller. The >> + * function marks the end of array with RTE_PTYPE_UNKNOWN. >> + * @param num >> + * Size of the array pointed by param ptypes. >> + * Should be rte_eth_dev_get_supported_ptypes() + 1 to >accommodate the >> + * set ptypes. >> + * @return >> + * - (0) if Success. >> + * - (-ENODEV) if *port_id* invalid. >> + * - (-EINVAL) if *ptype_mask* is invalid (or) set_ptypes is NULL and >> + * num > 0. >> + */ >> +__rte_experimental >> +int rte_eth_dev_set_supported_ptypes(uint16_t port_id, uint32_t >ptype_mask, >> + uint32_t *set_ptypes, unsigned int >num); >> >> /** >> * Retrieve the MTU of an Ethernet device. >> diff --git a/lib/librte_ethdev/rte_ethdev_core.h >b/lib/librte_ethdev/rte_ethdev_core.h >> index 2922d5b7c..06afd6a3d 100644 >> --- a/lib/librte_ethdev/rte_ethdev_core.h >> +++ b/lib/librte_ethdev/rte_ethdev_core.h >> @@ -110,6 +110,16 @@ typedef void (*eth_dev_infos_get_t)(struct >rte_eth_dev *dev, >> typedef const uint32_t >*(*eth_dev_supported_ptypes_get_t)(struct rte_eth_dev *dev); >> /**< @internal Get supported ptypes of an Ethernet device. */ >> >> +typedef int (*eth_dev_supported_ptypes_set_t)(struct >rte_eth_dev *dev, >> + uint32_t ptype_mask); >> +/**< @internal Inform an Ethernet device about packet types in >which the >> + * recipient is interested. >> + * Ptype_mask can have any of the following values >RTE_PTYPE_UNKNOWN | >> + * RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK | >RTE_PTYPE_L4_MASK | >> + * RTE_PTYPE_TUNNEL_MASK | RTE_PTYPE_INNER_L2_MASK | >RTE_PTYPE_INNER_L3_MASK | >> + * RTE_PTYPE_INNER_L4_MASK | RTE_PTYPE_ALL_MASK. >> + */ >> + > >I'm sorry for misunderstanding. It should be a comment before the >typedef >which start from /** . So long post comments looks a bit strange. >Please, describe parameters using @param and return values using >@return >and @retval. >Also there is no point to mention all RTE_PTYPE masks here to avoid >duplication and possible unsync if we have more masks. My bad. Will cleanup in v9. > >Will you update a driver to implement it in 19.11 release cycle? >As I understand it is a requirement to add a new API. > Yes, I will add support for net/octeontx2. >> typedef int (*eth_queue_start_t)(struct rte_eth_dev *dev, >> uint16_t queue_id); >> /**< @internal Start rx and tx of a queue of an Ethernet device. */ > >[snip]