[dpdk-dev] [PATCH] i40e: bug fix of querying reta
There is a bug in querying reta, of storing the data to the correct entry. Code changes is straightforward for this bug. Signed-off-by: Helin Zhang --- lib/librte_pmd_i40e/i40e_ethdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c index 899cb42..008d62c 100644 --- a/lib/librte_pmd_i40e/i40e_ethdev.c +++ b/lib/librte_pmd_i40e/i40e_ethdev.c @@ -1924,7 +1924,7 @@ i40e_dev_rss_reta_query(struct rte_eth_dev *dev, lut = I40E_READ_REG(hw, I40E_PFQF_HLUT(i >> 2)); for (j = 0; j < I40E_4_BIT_WIDTH; j++) { if (mask & (0x1 << j)) - reta_conf[idx].reta[shift] = ((lut >> + reta_conf[idx].reta[shift + j] = ((lut >> (CHAR_BIT * j)) & I40E_8_BIT_MASK); } } -- 1.9.3
[dpdk-dev] [RFC PATCH 00/17] Single virtio implementation
Hi Thomas, > -Original Message- > From: Thomas Monjalon [mailto:thomas.monjalon at 6wind.com] > Sent: Monday, December 8, 2014 5:31 PM > To: Ouyang, Changchun > Cc: dev at dpdk.org > Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio implementation > > Hi Changchun, > > 2014-12-08 14:21, Ouyang Changchun: > > This patch set bases on two original RFC patch sets from Stephen > Hemminger[stephen at networkplumber.org] > > Refer to [http://dpdk.org/ml/archives/dev/2014-August/004845.html ] for > the original one. > > This patch set also resolves some conflict with latest codes and removed > duplicated codes. > > As you sent the patches, you appear as the author. > But I guess Stephen should be the author for some of them. > Please check who has contributed the most in each patch to decide. You are right, most of patches originate from Stephen's patchset, except for the last one, To be honest, I am ok whoever is the author of this patch set, :-), We could co-own the feature of Single virtio if you all agree with it, and I think we couldn't finish Such a feature without collaboration among us, this is why I tried to communicate with most of you to collect more feedback, suggestion and comments for this feature. Very appreciate for all kinds of feedback, suggestion here, especially for patch set from Stephen. According to your request, how could we make this patch set looks more like Stephen as the author? Currently I add Stephen as Signed-off-by list in each patch(I got the agreement from Stephen before doing this :-)). Need I send all patchset to Stephen and let Stephen send out them to dpdk.org? Or any other better solution? If you has better suggestion, I assume it works for all subsequent RFC and normal patch set. Any other suggestions are welcome. Thanks Changchun
[dpdk-dev] [PATCH v3] mbuf: fix of enabling all newly added RX error flags
Hi Thomas > -Original Message- > From: Thomas Monjalon [mailto:thomas.monjalon at 6wind.com] > Sent: Monday, December 8, 2014 6:51 PM > To: Zhang, Helin > Cc: dev at dpdk.org > Subject: Re: [dpdk-dev] [PATCH v3] mbuf: fix of enabling all newly added RX > error flags > > Hi Helin, > > 2014-12-06 09:33, Helin Zhang: > > Before redefining mbuf structure, there was lack of free bits in 'ol_flags' > > (32 bits in total) for new RX or TX flags. So it tried to reuse > > existant bits as most as possible, or even assigning 0 to some of bit > > flags. After new mbuf structure defined, there are quite a lot of free > > bits. So those newly added bit flags should be assigned with correct > > and valid bit values, and getting their names should be enabled as > > well. Note that 'RECIP' should be removed, as nowhere will use it. > > 'PKT_RX_ERR' is defined to replace all other error bit flags, e.g. MAC > > error, Oversize error, header buffer overflow error. > > > > Signed-off-by: Helin Zhang > [...] > > --- a/lib/librte_mbuf/rte_mbuf.h > > +++ b/lib/librte_mbuf/rte_mbuf.h > > @@ -84,11 +84,6 @@ extern "C" { > > #define PKT_RX_FDIR (1ULL << 2) /**< RX packet with FDIR > match indicate. */ > > #define PKT_RX_L4_CKSUM_BAD (1ULL << 3) /**< L4 cksum of RX pkt. > is > > not OK. */ #define PKT_RX_IP_CKSUM_BAD (1ULL << 4) /**< IP cksum > of > > RX pkt. is not OK. */ -#define PKT_RX_EIP_CKSUM_BAD (0ULL << 0) /**< > External IP header checksum error. */ > > -#define PKT_RX_OVERSIZE (0ULL << 0) /**< Num of desc of an RX > pkt oversize. */ > > -#define PKT_RX_HBUF_OVERFLOW (0ULL << 0) /**< Header buffer > overflow. */ > > -#define PKT_RX_RECIP_ERR (0ULL << 0) /**< Hardware processing > error. */ > > -#define PKT_RX_MAC_ERR (0ULL << 0) /**< MAC error. */ > > #define PKT_RX_IPV4_HDR (1ULL << 5) /**< RX packet with IPv4 > header. */ > > #define PKT_RX_IPV4_HDR_EXT (1ULL << 6) /**< RX packet with > extended IPv4 header. */ > > #define PKT_RX_IPV6_HDR (1ULL << 7) /**< RX packet with IPv6 > header. */ > > @@ -99,6 +94,8 @@ extern "C" { > > #define PKT_RX_TUNNEL_IPV6_HDR (1ULL << 12) /**< RX tunnel packet > with IPv6 header. */ > > #define PKT_RX_FDIR_ID (1ULL << 13) /**< FD id reported if FDIR > match. */ > > #define PKT_RX_FDIR_FLX (1ULL << 14) /**< Flexible bytes reported > if FDIR match. */ > > +#define PKT_RX_EIP_CKSUM_BAD (1ULL << 15) /**< External IP header > > +checksum error. */ > > Could PKT_RX_EIP_CKSUM_BAD be aggregated with > PKT_RX_IP_CKSUM_BAD? I tend to say no, but I would listen to comments from others. For tunneling case (e.g. IP over IP), it is a bit similar to the case of L3/L4 (e.g. UDP over IP). For L3/L4 case, we have PKT_RX_IP_CKSUM_BAD and PKT_RX_L4_CKSUM_BAD to indicate the checksum error is in L3 or L4. So I'd prefer to have PKT_RX_IP_CKSUM_BAD and PKT_RX_EIP_CKSUM_BAD to indicate the checksum error is in outer or inner header. Otherwise we have no chance to know where the checksum error is, based on mbuf. > The conclusion is the same: the packet is corrupted. > And some hardwares could not detect the encapsulation and use > PKT_RX_IP_CKSUM_BAD. If the hardware don't know it is a tunneling packet, it will just treat it as an IP packet. But if hardware supports tunneling, it would be better for apps to know that more about the packet which can be offloaded by hardware. > > Another interesting improvement would be to have PKT_RX_IP_CKSUM_OK. > I think we'll have to think about this kind of flag for next version. For checksum OK, if no 'BAD' indicated, we can assume it is OK. Any other hints from you? > > Note that this patch is an API change and shouldn't be applied for 1.8.0. > But we can do an exception as it has no impact on existing applications and > fixes the 0 flags. Agree with you! > > -- > Thomas Thank you very much for thinking so much about this! Regards, Helin
[dpdk-dev] [PATCH v3] mbuf: fix of enabling all newly added RX error flags
> -Original Message- > From: Ananyev, Konstantin > Sent: Monday, December 8, 2014 6:45 PM > To: Zhang, Helin; dev at dpdk.org > Cc: Cao, Waterman; Cao, Min; olivier.matz at 6wind.com > Subject: RE: [PATCH v3] mbuf: fix of enabling all newly added RX error flags > > Hi Helin, > > > -Original Message- > > From: Zhang, Helin > > Sent: Saturday, December 06, 2014 1:34 AM > > To: dev at dpdk.org > > Cc: Cao, Waterman; Cao, Min; olivier.matz at 6wind.com; Ananyev, > > Konstantin; Zhang, Helin > > Subject: [PATCH v3] mbuf: fix of enabling all newly added RX error > > flags > > > > Before redefining mbuf structure, there was lack of free bits in 'ol_flags' > > (32 bits in total) for new RX or TX flags. So it tried to reuse > > existant bits as most as possible, or even assigning 0 to some of bit > > flags. After new mbuf structure defined, there are quite a lot of free > > bits. So those newly added bit flags should be assigned with correct > > and valid bit values, and getting their names should be enabled as > > well. Note that 'RECIP' should be removed, as nowhere will use it. > > 'PKT_RX_ERR' is defined to replace all other error bit flags, e.g. MAC > > error, Oversize error, header buffer overflow error. > > > > Signed-off-by: Helin Zhang > > --- > > lib/librte_mbuf/rte_mbuf.c | 7 ++- > > lib/librte_mbuf/rte_mbuf.h | 7 ++- > > lib/librte_pmd_i40e/i40e_rxtx.c | 15 --- > > 3 files changed, 8 insertions(+), 21 deletions(-) > > > > v2 changes: > > * Removed error flag of 'ECIPE' processing only in both i40e PMD and mbuf. > All > > other error flags were added back. > > * Assigned error flags with correct and valid values, as their previous > > values > > were invalid. > > * Enabled getting all error flag names. > > > > v3 changes: > > * 'PKT_RX_ERR' is defined to replace error bit flags of MAC error, Oversize > > error, header buffer overflow error. > > * Removed assigning values to PKT_TX_* bit flags, as it has already been > done > > in another packet set. > > > > diff --git a/lib/librte_mbuf/rte_mbuf.c b/lib/librte_mbuf/rte_mbuf.c > > index 1b14e02..5e6b5d0 100644 > > --- a/lib/librte_mbuf/rte_mbuf.c > > +++ b/lib/librte_mbuf/rte_mbuf.c > > @@ -210,11 +210,8 @@ const char *rte_get_rx_ol_flag_name(uint64_t > mask) > > case PKT_RX_FDIR: return "PKT_RX_FDIR"; > > case PKT_RX_L4_CKSUM_BAD: return "PKT_RX_L4_CKSUM_BAD"; > > case PKT_RX_IP_CKSUM_BAD: return "PKT_RX_IP_CKSUM_BAD"; > > - /* case PKT_RX_EIP_CKSUM_BAD: return "PKT_RX_EIP_CKSUM_BAD"; */ > > - /* case PKT_RX_OVERSIZE: return "PKT_RX_OVERSIZE"; */ > > - /* case PKT_RX_HBUF_OVERFLOW: return "PKT_RX_HBUF_OVERFLOW"; > */ > > - /* case PKT_RX_RECIP_ERR: return "PKT_RX_RECIP_ERR"; */ > > - /* case PKT_RX_MAC_ERR: return "PKT_RX_MAC_ERR"; */ > > + case PKT_RX_EIP_CKSUM_BAD: return "PKT_RX_EIP_CKSUM_BAD"; > > + case PKT_RX_ERR: return "PKT_RX_ERR"; > > case PKT_RX_IPV4_HDR: return "PKT_RX_IPV4_HDR"; > > case PKT_RX_IPV4_HDR_EXT: return "PKT_RX_IPV4_HDR_EXT"; > > case PKT_RX_IPV6_HDR: return "PKT_RX_IPV6_HDR"; diff --git > > a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h index > > efdefc4..5e647a9 100644 > > --- a/lib/librte_mbuf/rte_mbuf.h > > +++ b/lib/librte_mbuf/rte_mbuf.h > > @@ -84,11 +84,6 @@ extern "C" { > > #define PKT_RX_FDIR (1ULL << 2) /**< RX packet with FDIR > match indicate. */ > > #define PKT_RX_L4_CKSUM_BAD (1ULL << 3) /**< L4 cksum of RX pkt. > is > > not OK. */ #define PKT_RX_IP_CKSUM_BAD (1ULL << 4) /**< IP cksum > of > > RX pkt. is not OK. */ -#define PKT_RX_EIP_CKSUM_BAD (0ULL << 0) /**< > External IP header checksum error. */ > > -#define PKT_RX_OVERSIZE (0ULL << 0) /**< Num of desc of an RX > pkt oversize. */ > > -#define PKT_RX_HBUF_OVERFLOW (0ULL << 0) /**< Header buffer > overflow. */ > > -#define PKT_RX_RECIP_ERR (0ULL << 0) /**< Hardware processing > error. */ > > -#define PKT_RX_MAC_ERR (0ULL << 0) /**< MAC error. */ > > #define PKT_RX_IPV4_HDR (1ULL << 5) /**< RX packet with IPv4 > header. */ > > #define PKT_RX_IPV4_HDR_EXT (1ULL << 6) /**< RX packet with > extended IPv4 header. */ > > #define PKT_RX_IPV6_HDR (1ULL << 7) /**< RX packet with IPv6 > header. */ > > @@ -99,6 +94,8 @@ extern "C" { > > #define PKT_RX_TUNNEL_IPV6_HDR (1ULL << 12) /**< RX tunnel packet > with IPv6 header. */ > > #define PKT_RX_FDIR_ID (1ULL << 13) /**< FD id reported if FDIR > match. */ > > #define PKT_RX_FDIR_FLX (1ULL << 14) /**< Flexible bytes reported > if FDIR match. */ > > +#define PKT_RX_EIP_CKSUM_BAD (1ULL << 15) /**< External IP header > checksum error. */ > > +#define PKT_RX_ERR (1ULL << 16) /**< Other errors, e.g. > MAC error. */ > > /* add new RX flags here */ > > > > /* add new TX flags here */ > > diff --git a/lib/librte_pmd_i40e/i40e_rxtx.c > > b/lib/librte_pmd_i40e/i40e_rxtx.c index 2beae3c..5d99bd2 100644 > > --- a/lib/librte_pmd_i40e/i40e_rxtx.c >
[dpdk-dev] [PATCH v2 2/2] mbuf: assign valid bit values for some RX and TX flags
> -Original Message- > From: Ananyev, Konstantin > Sent: Monday, December 8, 2014 6:55 PM > To: Zhang, Helin; dev at dpdk.org > Cc: Cao, Waterman; Cao, Min; Wu, Jingjing; Liu, Jijiang; > olivier.matz at 6wind.com > Subject: RE: [PATCH v2 2/2] mbuf: assign valid bit values for some RX and TX > flags > > > > > -Original Message- > > From: Zhang, Helin > > Sent: Saturday, December 06, 2014 1:08 AM > > To: Ananyev, Konstantin; dev at dpdk.org > > Cc: Cao, Waterman; Cao, Min; Wu, Jingjing; Liu, Jijiang; > > olivier.matz at 6wind.com > > Subject: RE: [PATCH v2 2/2] mbuf: assign valid bit values for some RX > > and TX flags > > > > > > > > > -Original Message- > > > From: Zhang, Helin > > > Sent: Saturday, December 6, 2014 8:40 AM > > > To: Ananyev, Konstantin; dev at dpdk.org > > > Cc: Cao, Waterman; Cao, Min; Wu, Jingjing; Liu, Jijiang; > > > olivier.matz at 6wind.com > > > Subject: RE: [PATCH v2 2/2] mbuf: assign valid bit values for some > > > RX and TX flags > > > > > > OK. I will send out another patch according to your comments. Thanks a > > > lot! > > > > > > Regards, > > > Helin > > > > > > > -Original Message- > > > > From: Ananyev, Konstantin > > > > Sent: Friday, December 5, 2014 6:50 PM > > > > To: Zhang, Helin; dev at dpdk.org > > > > Cc: Cao, Waterman; Cao, Min; Wu, Jingjing; Liu, Jijiang; > > > > olivier.matz at 6wind.com > > > > Subject: RE: [PATCH v2 2/2] mbuf: assign valid bit values for some > > > > RX and TX flags > > > > > > > > Hi Helin, > > > > > > > > > -Original Message- > > > > > From: Zhang, Helin > > > > > Sent: Friday, December 05, 2014 1:46 AM > > > > > To: dev at dpdk.org > > > > > Cc: Cao, Waterman; Cao, Min; Wu, Jingjing; Liu, Jijiang; > > > > > Ananyev, Konstantin; olivier.matz at 6wind.com; Zhang, Helin > > > > > Subject: [PATCH v2 2/2] mbuf: assign valid bit values for some > > > > > RX and TX flags > > > > > > > > > > Before redefining mbuf structure, there was lack of free bits in > > > > > 'ol_flags' (32 bits in total) for new RX or TX flags. So it > > > > > tried to reuse existant bits as most as possible, or even > > > > > assigning 0 to some of bit flags. After new mbuf structure > > > > > defined, there are quite a lot of free bits. So those newly > > > > > added bit flags should be assigned with correct and valid bit > > > > > values, and getting their names should be enabled as well. Note > > > > > that 'RECIP' should be removed, as nowhere will use it. > > > > > > > > > > Signed-off-by: Helin Zhang > > > > > --- > > > > > lib/librte_mbuf/rte_mbuf.c | 9 - > > > > > lib/librte_mbuf/rte_mbuf.h > > > > > | 19 +-- > > > > > 2 files changed, 13 insertions(+), 15 deletions(-) > > > > > > > > > > v2 changes: > > > > > * Removed error flag of 'ECIPE' processing only in mbuf. All other > > > > > error > flags > > > > > were added back. > > > > > * Assigned error flags with correct and valid values, as their > > > > > previous > values > > > > > were invalid. > > > > > * Enabled getting all error flag names. > > > > > > > > > > diff --git a/lib/librte_mbuf/rte_mbuf.c > > > > > b/lib/librte_mbuf/rte_mbuf.c index 87c2963..3ce7c8d 100644 > > > > > --- a/lib/librte_mbuf/rte_mbuf.c > > > > > +++ b/lib/librte_mbuf/rte_mbuf.c > > > > > @@ -210,11 +210,10 @@ const char > > > > > *rte_get_rx_ol_flag_name(uint64_t > > > > mask) > > > > > case PKT_RX_FDIR: return "PKT_RX_FDIR"; > > > > > case PKT_RX_L4_CKSUM_BAD: return "PKT_RX_L4_CKSUM_BAD"; > > > > > case PKT_RX_IP_CKSUM_BAD: return "PKT_RX_IP_CKSUM_BAD"; > > > > > - /* case PKT_RX_EIP_CKSUM_BAD: return > "PKT_RX_EIP_CKSUM_BAD"; */ > > > > > - /* case PKT_RX_OVERSIZE: return "PKT_RX_OVERSIZE"; */ > > > > > - /* case PKT_RX_HBUF_OVERFLOW: return > "PKT_RX_HBUF_OVERFLOW"; > > > > */ > > > > > - /* case PKT_RX_RECIP_ERR: return "PKT_RX_RECIP_ERR"; */ > > > > > - /* case PKT_RX_MAC_ERR: return "PKT_RX_MAC_ERR"; */ > > > > > + case PKT_RX_EIP_CKSUM_BAD: return "PKT_RX_EIP_CKSUM_BAD"; > > > > > + case PKT_RX_OVERSIZE: return "PKT_RX_OVERSIZE"; > > > > > + case PKT_RX_HBUF_OVERFLOW: return > > > "PKT_RX_HBUF_OVERFLOW"; > > > > > + case PKT_RX_MAC_ERR: return "PKT_RX_MAC_ERR"; > > > > > case PKT_RX_IPV4_HDR: return "PKT_RX_IPV4_HDR"; > > > > > case PKT_RX_IPV4_HDR_EXT: return "PKT_RX_IPV4_HDR_EXT"; > > > > > case PKT_RX_IPV6_HDR: return "PKT_RX_IPV6_HDR"; diff --git > > > > > a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h index > > > > > 2e5fce5..c9591c0 100644 > > > > > --- a/lib/librte_mbuf/rte_mbuf.h > > > > > +++ b/lib/librte_mbuf/rte_mbuf.h > > > > > @@ -84,11 +84,6 @@ extern "C" { > > > > > #define PKT_RX_FDIR (1ULL << 2) /**< RX packet with > FDIR > > > > match indicate. */ > > > > > #define PKT_RX_L4_CKSUM_BAD (1ULL << 3) /**< L4 cksum of RX > pkt. > > > > is > > > > > not OK. */ #define PKT_RX_IP_CKSUM_BAD (1ULL << 4) /**< IP > > > > > cksum > > > > of > > >
[dpdk-dev] [PATCH v2] VFIO: Avoid to enable vfio while the module not loaded
On 12/9/2014 2:47 AM, Burakov, Anatoly wrote: > Hi Michael > >> I don't think so, if we check module "vfio", but if given module name is >> "vfio_xx", it will also correct if use strncmp. > Sorry I missed this the last time. I don't think that is the case. If you do > strncmp on sizeof(buffer), strncmp will always check 30 bytes. That way if > you check vfio against vfio_xx, you'll get a mismatch. Of course, replacing Yes, you are right, strncmp() will check 30 bytes if use sizeof(buffer). But any issue of strcmp() ? This rountin cares about exactly match. I think no need to convert to strncmp() if it does have other issue. > fscanf with fgets would be better too, to make sure we never go over our > buffer size when dealing with /proc/modules. If we use fgets, we need additional efforts to get the modname, for potential overflow issue, we can limit counts of fscanf(). like below: fscanf(fd, "%30s %*[^\n]", mod_name); Thanks, Michael > > Thanks, > Anatoly >
[dpdk-dev] [RFC PATCH 00/17] Single virtio implementation
On 12/9/2014 9:11 AM, Ouyang, Changchun wrote: > Hi Thomas, > >> -Original Message- >> From: Thomas Monjalon [mailto:thomas.monjalon at 6wind.com] >> Sent: Monday, December 8, 2014 5:31 PM >> To: Ouyang, Changchun >> Cc: dev at dpdk.org >> Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio implementation >> >> Hi Changchun, >> >> 2014-12-08 14:21, Ouyang Changchun: >>> This patch set bases on two original RFC patch sets from Stephen >> Hemminger[stephen at networkplumber.org] >>> Refer to [http://dpdk.org/ml/archives/dev/2014-August/004845.html ] for >> the original one. >>> This patch set also resolves some conflict with latest codes and removed >> duplicated codes. >> >> As you sent the patches, you appear as the author. >> But I guess Stephen should be the author for some of them. >> Please check who has contributed the most in each patch to decide. > You are right, most of patches originate from Stephen's patchset, except for > the last one, > To be honest, I am ok whoever is the author of this patch set, :-), > We could co-own the feature of Single virtio if you all agree with it, and I > think we couldn't finish > Such a feature without collaboration among us, this is why I tried to > communicate with most of you > to collect more feedback, suggestion and comments for this feature. > Very appreciate for all kinds of feedback, suggestion here, especially for > patch set from Stephen. > > According to your request, how could we make this patch set looks more like > Stephen as the author? > Currently I add Stephen as Signed-off-by list in each patch(I got the > agreement from Stephen before doing this :-)). Hi Ouyang, "Signed-off-by" should be added by himself, because the one who in the Signed-off-by list should take responsibility for it(like potential bugs/issues). Although, lots of patches are originate from Stephen, we still need himself add this line :) If DPDK community's Signed-off-by" rule is different from linux(qemu, etc.), please ignore my comment :) Thanks, Michael > Need I send all patchset to Stephen and let Stephen send out them to dpdk.org? > Or any other better solution? > If you has better suggestion, I assume it works for all subsequent RFC and > normal patch set. > > Any other suggestions are welcome. > > Thanks > Changchun > > > >
[dpdk-dev] [PATCH v2 00/28] Port Hotplug Framework
This patch series adds a dynamic port hotplug framework to DPDK. With the patches, DPDK apps can attach or detach ports at runtime. The basic concept of the port hotplug is like followings. - DPDK apps must have responsibility to manage ports. DPDK apps only know which ports are attached or detached at the moment. The port hotplug framework is implemented to allow DPDK apps to manage ports. For example, when DPDK apps call port attach function, attached port number will be returned. Also DPDK apps can detach port by port number. - Kernel support is needed for attaching or detaching physical device ports. To attach new device, the device will be recognized by kernel at first and controlled by kernel driver. Then user can bind the device to igb_uio by 'dpdk_nic_bind.py'. Finally, DPDK apps can call the port hotplug functions to attach ports. For detaching, steps are vice versa. - Before detach ports, ports must be stopped and closed. DPDK application must call rte_eth_dev_stop() and rte_eth_dev_close() before detaching ports. These function will call finalization codes of PMDs. But so far, no PMD frees all resources allocated by initialization. It means PMDs are needed to be fixed to support the port hotplug. 'RTE_PCI_DRV_DETACHABLE' is a new flag indicating a PMD supports detaching. Without this flag, detaching will be failed. - Mustn't affect legacy DPDK apps. No DPDK EAL behavior is changed, if the port hotplug functions are't called. So all legacy DPDK apps can still work without modifications. And few limitations. - The port hotplug functions are not thread safe. DPDK apps should handle it. - Only support Linux and igb_uio so far. BSD and VFIO is not supported. I will send VFIO patches at least, but I don't have a plan to submit BSD patch so far. Here is port hotplug APIs. --- /** * Attach a new device. * * @param devargs * A pointer to a strings array describing the new device * to be attached. The strings should be a pci address like * ':01:00.0' or virtual device name like 'eth_pcap0'. * @param port_id * A pointer to a port identifier actually attached. * @return * 0 on success and port_id is filled, negative on error */ int rte_eal_dev_attach(const char *devargs, uint8_t *port_id); /** * Detach a device. * * @param port_id * The port identifier of the device to detach. * @param addr * A pointer to a device name actually detached. * @return * 0 on success and devname is filled, negative on error */ int rte_eal_dev_detach(uint8_t port_id, char *devname); --- This patch series are for DPDK EAL. To use port hotplug function by DPDK apps, each PMD should be fixed to support 'RTE_PCI_DRV_DETACHABLE' flag. Please check a patch for pcap PMD. Also please check testpmd patch. It will show you how to fix your legacy applications to support port hotplug feature. PATCH v2 chages: - Replace rte_eal_dev_attach_pdev(), rte_eal_dev_detach_pdev, rte_eal_dev_attach_vdev() and rte_eal_dev_detach_vdev() to rte_eal_dev_attach() and rte_eal_dev_detach(). - Add parameter values checking. - Refashion a few functions. (Thanks to Iremonger, Bernard) PATCH v1 Chages: - Fix error checking code of librte_eth APIs. - Fix issue that port from pcap PMD cannot be detached correctly. - Fix issue that testpmd could hang after forwarding, if attaching and detaching is repeatedly. - Fix if-condition of rte_eth_dev_get_port_by_addr(). (Thanks to Mark Enright) RFC PATCH v2 Changes: - remove 'rte_eth_dev_validate_port()', and cleanup codes. Tetsuya Mukawa (28): eal/pci: Add a new flag indicating a driver can detach devices at runtime. ethdev: Remove assumption that port will not be detached eal/pci: Replace pci address comparison code by eal_compare_pci_addr ethdev: Add rte_eth_dev_free to free specified device eal,ethdev: Add function pointer for closing a device ethdev: Add rte_eth_dev_shutdown for closing PCI devices. ethdev: Add functions to know which port is attached or detached ethdev: Add rte_eth_dev_get_addr_by_port ethdev: Add rte_eth_dev_get_port_by_addr ethdev: Add rte_eth_dev_get_name_by_port ethdev: Add rte_eth_dev_check_detachable ethdev: Change scope of rte_eth_dev_allocated to global eal/pci: Prevent double registration for devargs_list eal/pci: Add rte_eal_devargs_remove eal/pci: Add probe and close function for virtual drivers eal/pci: Add port hotplug functions for virtual devices. eal/linux/pci: Add functions for unmapping igb_uio resources eal/pci: Prevent double registrations for pci_device_list eal/pci: Change scope of rte_eal_pci_scan to global eal/pci: Add rte_eal_pci_close_one_driver eal/pci: Fix pci_probe_all_drivers to share code with closing function eal/pci: Add pci_close_all_drivers eal/pci: Add rte_
[dpdk-dev] [PATCH v2 01/28] eal/pci: Add a new flag indicating a driver can detach devices at runtime.
This patch adds "RTE_PCI_DRV_DETACHABLE" to drv_flags of rte_pci_driver structure. The flags indicates the driver can detach devices at runtime. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/include/rte_pci.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index 66ed793..b819539 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -199,6 +199,8 @@ struct rte_pci_driver { #define RTE_PCI_DRV_FORCE_UNBIND 0x0004 /** Device driver supports link state interrupt */ #define RTE_PCI_DRV_INTR_LSC 0x0008 +/** Device driver supports detaching capablity */ +#define RTE_PCI_DRV_DETACHABLE 0x0010 /**< Internal use only - Macro used by pci addr parsing functions **/ #define GET_PCIADDR_FIELD(in, fd, lim, dlm) \ -- 1.9.1
[dpdk-dev] [PATCH v2 02/28] ethdev: Remove assumption that port will not be detached
To remove assumption, do like followings. - Add 'attached' member to rte_eth_dev structure. This member is used for indicating the port is attached, or not. - Add rte_eth_dev_allocate_new_port(). This function is used for allocating new port. Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 248 -- lib/librte_ether/rte_ethdev.h | 5 + 2 files changed, 149 insertions(+), 104 deletions(-) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 95f2ceb..9f713ae 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -175,6 +175,16 @@ enum { STAT_QMAP_RX }; +enum { + DEV_VALID = 0, + DEV_INVALID +}; + +enum { + DEV_DISCONNECTED = 0, + DEV_CONNECTED +}; + static inline void rte_eth_dev_data_alloc(void) { @@ -201,19 +211,34 @@ rte_eth_dev_allocated(const char *name) { unsigned i; - for (i = 0; i < nb_ports; i++) { - if (strcmp(rte_eth_devices[i].data->name, name) == 0) + for (i = 0; i < RTE_MAX_ETHPORTS; i++) { + if ((rte_eth_devices[i].attached == DEV_CONNECTED) + && strcmp(rte_eth_devices[i].data->name, + name) == 0) return &rte_eth_devices[i]; } return NULL; } +static uint8_t +rte_eth_dev_allocate_new_port(void) +{ + unsigned i; + + for (i = 0; i < RTE_MAX_ETHPORTS; i++) + if (rte_eth_devices[i].attached == DEV_DISCONNECTED) + return i; + return RTE_MAX_ETHPORTS; +} + struct rte_eth_dev * rte_eth_dev_allocate(const char *name) { + uint8_t port_id; struct rte_eth_dev *eth_dev; - if (nb_ports == RTE_MAX_ETHPORTS) { + port_id = rte_eth_dev_allocate_new_port(); + if (port_id == RTE_MAX_ETHPORTS) { PMD_DEBUG_TRACE("Reached maximum number of Ethernet ports\n"); return NULL; } @@ -226,10 +251,12 @@ rte_eth_dev_allocate(const char *name) return NULL; } - eth_dev = &rte_eth_devices[nb_ports]; - eth_dev->data = &rte_eth_dev_data[nb_ports]; + eth_dev = &rte_eth_devices[port_id]; + eth_dev->data = &rte_eth_dev_data[port_id]; snprintf(eth_dev->data->name, sizeof(eth_dev->data->name), "%s", name); - eth_dev->data->port_id = nb_ports++; + eth_dev->data->port_id = port_id; + eth_dev->attached = DEV_CONNECTED; + nb_ports++; return eth_dev; } @@ -283,6 +310,7 @@ rte_eth_dev_init(struct rte_pci_driver *pci_drv, (unsigned) pci_dev->id.device_id); if (rte_eal_process_type() == RTE_PROC_PRIMARY) rte_free(eth_dev->data->dev_private); + eth_dev->attached = DEV_DISCONNECTED; nb_ports--; return diag; } @@ -308,10 +336,22 @@ rte_eth_driver_register(struct eth_driver *eth_drv) rte_eal_pci_register(ð_drv->pci_drv); } +static int +rte_eth_dev_validate_port(uint8_t port_id) +{ + if (port_id >= RTE_MAX_ETHPORTS) + return DEV_INVALID; + + if (rte_eth_devices[port_id].attached == DEV_CONNECTED) + return DEV_VALID; + else + return DEV_INVALID; +} + int rte_eth_dev_socket_id(uint8_t port_id) { - if (port_id >= nb_ports) + if (rte_eth_dev_validate_port(port_id) == DEV_INVALID) return -1; return rte_eth_devices[port_id].pci_dev->numa_node; } @@ -369,7 +409,7 @@ rte_eth_dev_rx_queue_start(uint8_t port_id, uint16_t rx_queue_id) * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); - if (port_id >= nb_ports) { + if (rte_eth_dev_validate_port(port_id) == DEV_INVALID) { PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); return -EINVAL; } @@ -395,7 +435,7 @@ rte_eth_dev_rx_queue_stop(uint8_t port_id, uint16_t rx_queue_id) * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); - if (port_id >= nb_ports) { + if (rte_eth_dev_validate_port(port_id) == DEV_INVALID) { PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); return -EINVAL; } @@ -421,7 +461,7 @@ rte_eth_dev_tx_queue_start(uint8_t port_id, uint16_t tx_queue_id) * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); - if (port_id >= nb_ports) { + if (rte_eth_dev_validate_port(port_id) == DEV_INVALID) { PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); return -EINVAL; } @@ -447,7 +487,7 @@ rte_eth_dev_tx_queue_stop(uint8_t port_id, uint16_t tx_queue_id) * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); - if (port_id >= nb_ports) { + if (rte_eth_dev_validate_port(port_id) == DEV_INVALID)
[dpdk-dev] [PATCH v2 03/28] eal/pci: Replace pci address comparison code by eal_compare_pci_addr
This patch replaces pci_addr_comparison() and memcmp() of pci addresses by eal_compare_pci_addr(). Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/bsdapp/eal/eal_pci.c | 16 +--- lib/librte_eal/common/eal_common_pci.c| 2 +- lib/librte_eal/common/include/rte_pci.h | 29 + lib/librte_eal/linuxapp/eal/eal_pci.c | 16 +--- lib/librte_eal/linuxapp/eal/eal_pci_uio.c | 2 +- 5 files changed, 33 insertions(+), 32 deletions(-) diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c index 74ecce7..7eda513 100644 --- a/lib/librte_eal/bsdapp/eal/eal_pci.c +++ b/lib/librte_eal/bsdapp/eal/eal_pci.c @@ -270,20 +270,6 @@ pci_uio_map_resource(struct rte_pci_device *dev) return (0); } -/* Compare two PCI device addresses. */ -static int -pci_addr_comparison(struct rte_pci_addr *addr, struct rte_pci_addr *addr2) -{ - uint64_t dev_addr = (addr->domain << 24) + (addr->bus << 16) + (addr->devid << 8) + addr->function; - uint64_t dev_addr2 = (addr2->domain << 24) + (addr2->bus << 16) + (addr2->devid << 8) + addr2->function; - - if (dev_addr > dev_addr2) - return 1; - else - return 0; -} - - /* Scan one pci sysfs entry, and fill the devices list from it. */ static int pci_scan_one(int dev_pci_fd, struct pci_conf *conf) @@ -358,7 +344,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf) struct rte_pci_device *dev2 = NULL; TAILQ_FOREACH(dev2, &pci_device_list, next) { - if (pci_addr_comparison(&dev->addr, &dev2->addr)) + if (eal_compare_pci_addr(&dev->addr, &dev2->addr)) continue; else { TAILQ_INSERT_BEFORE(dev2, dev, next); diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c index f3c7f71..f01f258 100644 --- a/lib/librte_eal/common/eal_common_pci.c +++ b/lib/librte_eal/common/eal_common_pci.c @@ -93,7 +93,7 @@ static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev) if (devargs->type != RTE_DEVTYPE_BLACKLISTED_PCI && devargs->type != RTE_DEVTYPE_WHITELISTED_PCI) continue; - if (!memcmp(&dev->addr, &devargs->pci.addr, sizeof(dev->addr))) + if (eal_compare_pci_addr(&dev->addr, &devargs->pci.addr)) return devargs; } return NULL; diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index b819539..fe374a8 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -261,6 +261,35 @@ eal_parse_pci_DomBDF(const char *input, struct rte_pci_addr *dev_addr) } #undef GET_PCIADDR_FIELD +/* Compare two PCI device addresses. */ +/** + * Utility function to compare two PCI device addresses. + * + * @param addr + * The PCI Bus-Device-Function address to compare + * @param addr2 + * The PCI Bus-Device-Function address to compare + * @return + * 0 on equal PCI address. + * Positive on addr is greater than addr2. + * Negative on addr is less than addr2. + */ +static inline int +eal_compare_pci_addr(struct rte_pci_addr *addr, struct rte_pci_addr *addr2) +{ + uint64_t dev_addr = (addr->domain << 24) + (addr->bus << 16) + + (addr->devid << 8) + addr->function; + uint64_t dev_addr2 = (addr2->domain << 24) + (addr2->bus << 16) + + (addr2->devid << 8) + addr2->function; + + if (dev_addr > dev_addr2) + return 1; + else if (dev_addr < dev_addr2) + return -1; + else + return 0; +} + /** * Probe the PCI bus for registered drivers. * diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index b5f5410..23a69e9 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -200,20 +200,6 @@ error: return -1; } -/* Compare two PCI device addresses. */ -static int -pci_addr_comparison(struct rte_pci_addr *addr, struct rte_pci_addr *addr2) -{ - uint64_t dev_addr = (addr->domain << 24) + (addr->bus << 16) + (addr->devid << 8) + addr->function; - uint64_t dev_addr2 = (addr2->domain << 24) + (addr2->bus << 16) + (addr2->devid << 8) + addr2->function; - - if (dev_addr > dev_addr2) - return 1; - else - return 0; -} - - /* Scan one pci sysfs entry, and fill the devices list from it. */ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, @@ -306,7 +292,7 @@ pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, struct rte_pci_device *dev2 = NULL; TAILQ_FOREACH(dev2, &pci_device_list, next) { -
[dpdk-dev] [PATCH v2 04/28] ethdev: Add rte_eth_dev_free to free specified device
This patch adds rte_eth_dev_free(). The function is used for changing a attached status of the device that has specified name. Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 17 + lib/librte_ether/rte_ethdev.h | 11 +++ 2 files changed, 28 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 9f713ae..d5fdb03 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -260,6 +260,23 @@ rte_eth_dev_allocate(const char *name) return eth_dev; } +struct rte_eth_dev * +rte_eth_dev_free(const char *name) +{ + struct rte_eth_dev *eth_dev; + + eth_dev = rte_eth_dev_allocated(name); + if (eth_dev == NULL) { + PMD_DEBUG_TRACE("Ethernet Device with name %s doesn't exist!\n", + name); + return NULL; + } + + eth_dev->attached = 0; + nb_ports--; + return eth_dev; +} + static int rte_eth_dev_init(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 257de86..fb1caea 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1653,6 +1653,17 @@ extern uint8_t rte_eth_dev_count(void); */ struct rte_eth_dev *rte_eth_dev_allocate(const char *name); +/** + * Function for internal use by dummy drivers primarily, e.g. ring-based + * driver. + * Free the specified ethdev and returns the pointer to that slot. + * + * @param nameUnique identifier name for each Ethernet device + * @return + * - Slot in the rte_dev_devices array for the freed device; + */ +struct rte_eth_dev *rte_eth_dev_free(const char *name); + struct eth_driver; /** * @internal -- 1.9.1
[dpdk-dev] [PATCH v2 05/28] eal, ethdev: Add function pointer for closing a device
The patch adds function pointer to rte_pci_driver and eth_driver structure. These function pointers are used when ports are detached. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/include/rte_pci.h | 7 +++ lib/librte_ether/rte_ethdev.h | 24 2 files changed, 31 insertions(+) diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index fe374a8..74720d1 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -181,12 +181,19 @@ struct rte_pci_driver; typedef int (pci_devinit_t)(struct rte_pci_driver *, struct rte_pci_device *); /** + * Shutdown function for the driver called during hotplugging. + */ +typedef int (pci_devshutdown_t)( + struct rte_pci_driver *, struct rte_pci_device *); + +/** * A structure describing a PCI driver. */ struct rte_pci_driver { TAILQ_ENTRY(rte_pci_driver) next; /**< Next in list. */ const char *name; /**< Driver name. */ pci_devinit_t *devinit; /**< Device init. function. */ + pci_devshutdown_t *devshutdown; /**< Device shutdown function. */ struct rte_pci_id *id_table;/**< ID table, NULL terminated. */ uint32_t drv_flags; /**< Flags contolling handling of device. */ }; diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index fb1caea..b329e11 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1702,6 +1702,27 @@ typedef int (*eth_dev_init_t)(struct eth_driver *eth_drv, /** * @internal + * Finalization function of an Ethernet driver invoked for each matching + * Ethernet PCI device detected during the PCI closing phase. + * + * @param eth_drv + * The pointer to the [matching] Ethernet driver structure supplied by + * the PMD when it registered itself. + * @param eth_dev + * The *eth_dev* pointer is the address of the *rte_eth_dev* structure + * associated with the matching device and which have been [automatically] + * allocated in the *rte_eth_devices* array. + * @return + * - 0: Success, the device is properly finalized by the driver. + *In particular, the driver MUST free the *dev_ops* pointer + *of the *eth_dev* structure. + * - <0: Error code of the device initialization failure. + */ +typedef int (*eth_dev_shutdown_t)(struct eth_driver *eth_drv, + struct rte_eth_dev *eth_dev); + +/** + * @internal * The structure associated with a PMD Ethernet driver. * * Each Ethernet driver acts as a PCI driver and is represented by a generic @@ -1711,11 +1732,14 @@ typedef int (*eth_dev_init_t)(struct eth_driver *eth_drv, * * - The *eth_dev_init* function invoked for each matching PCI device. * + * - The *eth_dev_shutdown* function invoked for each matching PCI device. + * * - The size of the private data to allocate for each matching device. */ struct eth_driver { struct rte_pci_driver pci_drv;/**< The PMD is also a PCI driver. */ eth_dev_init_t eth_dev_init; /**< Device init function. */ + eth_dev_shutdown_t eth_dev_shutdown;/**< Device shutdown function. */ unsigned int dev_private_size;/**< Size of device private data. */ }; -- 1.9.1
[dpdk-dev] [PATCH v2 06/28] ethdev: Add rte_eth_dev_shutdown for closing PCI devices.
rte_eth_dev_shutdown() is called when PCI device is closed. Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 37 + 1 file changed, 37 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index d5fdb03..51697e1 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -332,6 +332,42 @@ rte_eth_dev_init(struct rte_pci_driver *pci_drv, return diag; } +static int +rte_eth_dev_shutdown(struct rte_pci_driver *pci_drv, +struct rte_pci_device *pci_dev) +{ + struct eth_driver *eth_drv; + struct rte_eth_dev *eth_dev; + char ethdev_name[RTE_ETH_NAME_MAX_LEN]; + + /* Create unique Ethernet device name using PCI address */ + snprintf(ethdev_name, RTE_ETH_NAME_MAX_LEN, "%d:%d.%d", + pci_dev->addr.bus, pci_dev->addr.devid, + pci_dev->addr.function); + + eth_dev = rte_eth_dev_free(ethdev_name); + if (eth_dev == NULL) + return -ENODEV; + + eth_drv = (struct eth_driver *)pci_drv; + + /* Invoke PMD device shutdown function */ + if (*eth_drv->eth_dev_shutdown) + (*eth_drv->eth_dev_shutdown)(eth_drv, eth_dev); + + /* init user callbacks */ + TAILQ_INIT(&(eth_dev->callbacks)); + + if (rte_eal_process_type() == RTE_PROC_PRIMARY) + rte_free(eth_dev->data->dev_private); + + eth_dev->pci_dev = NULL; + eth_dev->driver = NULL; + eth_dev->data = NULL; + + return 0; +} + /** * Register an Ethernet [Poll Mode] driver. * @@ -350,6 +386,7 @@ void rte_eth_driver_register(struct eth_driver *eth_drv) { eth_drv->pci_drv.devinit = rte_eth_dev_init; + eth_drv->pci_drv.devshutdown = rte_eth_dev_shutdown; rte_eal_pci_register(ð_drv->pci_drv); } -- 1.9.1
[dpdk-dev] [PATCH v2 07/28] ethdev: Add functions to know which port is attached or detached
The patch adds rte_eth_dev_save() and rte_eth_dev_get_changed_port(). rte_eth_dev_save() is used for saving current rte_eth_dev structures. rte_eth_dev_get_changed_port() receives the rte_eth_dev structures, then compare these with current values to know which port is actually attached or detached. Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 21 + lib/librte_ether/rte_ethdev.h | 21 + 2 files changed, 42 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 51697e1..6a3700e 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -416,6 +416,27 @@ rte_eth_dev_count(void) return (nb_ports); } +void +rte_eth_dev_save(struct rte_eth_dev *devs) +{ + if (devs == NULL) + return; + + /* save current rte_eth_devices */ + memcpy(devs, rte_eth_devices, + sizeof(struct rte_eth_dev) * RTE_MAX_ETHPORTS); +} + +int +rte_eth_dev_get_changed_port(struct rte_eth_dev *devs, uint8_t *port_id) +{ + /* check which port was attached or detached */ + for (*port_id = 0; *port_id < RTE_MAX_ETHPORTS; (*port_id)++, devs++) + if (rte_eth_devices[*port_id].attached ^ devs->attached) + return 0; + return 1; +} + static int rte_eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) { diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index b329e11..03c8850 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1642,6 +1642,27 @@ extern struct rte_eth_dev rte_eth_devices[]; extern uint8_t rte_eth_dev_count(void); /** + * Function for internal use by port hotplug functions. + * Copies current ethdev structures to the specified pointer. + * + * @param devsThe pointer to the ethdev structures + */ +extern void rte_eth_dev_save(struct rte_eth_dev *devs); + +/** + * Function for internal use by port hotplug functions. + * Compare the specified ethdev structures with currents. Then + * if there is a port which status is changed, fill the specified pointer + * with the port id of that port. + * @param devsThe pointer to the ethdev structures + * @param port_id The pointer to the port id + * @return + * - 0 on success, negative on error + */ +extern int rte_eth_dev_get_changed_port( + struct rte_eth_dev *devs, uint8_t *port_id); + +/** * Function for internal use by dummy drivers primarily, e.g. ring-based * driver. * Allocates a new ethdev slot for an ethernet device and returns the pointer -- 1.9.1
[dpdk-dev] [PATCH v2 08/28] ethdev: Add rte_eth_dev_get_addr_by_port
The function returns a pci address of a ethdev specified by port identifier. Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 17 + lib/librte_ether/rte_ethdev.h | 13 + 2 files changed, 30 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 6a3700e..ddaf14a 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -437,6 +437,23 @@ rte_eth_dev_get_changed_port(struct rte_eth_dev *devs, uint8_t *port_id) return 1; } +int +rte_eth_dev_get_addr_by_port(uint8_t port_id, struct rte_pci_addr *addr) +{ + if (rte_eth_dev_validate_port(port_id) == DEV_INVALID) { + PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); + return -EINVAL; + } + + if (addr == NULL) { + PMD_DEBUG_TRACE("Null pointer is specified\n"); + return -EINVAL; + } + + *addr = rte_eth_devices[port_id].pci_dev->addr; + return 0; +} + static int rte_eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) { diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 03c8850..30277a2 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1663,6 +1663,19 @@ extern int rte_eth_dev_get_changed_port( struct rte_eth_dev *devs, uint8_t *port_id); /** + * Function for internal use by port hotplug functions. + * Returns a pci address of a ethdev specified by port identifier. + * @param port_id + * The port identifier of the Ethernet device + * @param addr + * The pointer to the pci address + * @return + * - 0 on success, negative on error + */ +extern int rte_eth_dev_get_addr_by_port( + uint8_t port_id, struct rte_pci_addr *addr); + +/** * Function for internal use by dummy drivers primarily, e.g. ring-based * driver. * Allocates a new ethdev slot for an ethernet device and returns the pointer -- 1.9.1
[dpdk-dev] [PATCH v2 09/28] ethdev: Add rte_eth_dev_get_port_by_addr
The function returns a port identifier of a ethdev specified by pci address. v3: - Fix if-condition bug while comparing pci addresses. - Add error checking codes. Reported-by: Mark Enright Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 22 ++ lib/librte_ether/rte_ethdev.h | 13 + 2 files changed, 35 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index ddaf14a..4e9f0f7 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -454,6 +454,28 @@ rte_eth_dev_get_addr_by_port(uint8_t port_id, struct rte_pci_addr *addr) return 0; } +int +rte_eth_dev_get_port_by_addr(struct rte_pci_addr *addr, uint8_t *port_id) +{ + struct rte_pci_addr *tmp; + + if ((addr == NULL) || (port_id == NULL)) { + PMD_DEBUG_TRACE("Null pointer is specified\n"); + return -1; + } + + for (*port_id = 0; *port_id < RTE_MAX_ETHPORTS; (*port_id)++) { + if (!rte_eth_devices[*port_id].attached) + continue; + if (!rte_eth_devices[*port_id].pci_dev) + continue; + tmp = &rte_eth_devices[*port_id].pci_dev->addr; + if (eal_compare_pci_addr(tmp, addr) == 0) + return 0; + } + return -1; +} + static int rte_eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) { diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 30277a2..8c55c56 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1676,6 +1676,19 @@ extern int rte_eth_dev_get_addr_by_port( uint8_t port_id, struct rte_pci_addr *addr); /** + * Function for internal use by port hotplug functions. + * Returns a port identifier of a ethdev specified by pci address. + * @param addr + * The pointer to the pci address of the Ethernet device. + * @param port_id + * The pointer to the port identifier + * @return + * - 0 on success, negative on error + */ +extern int rte_eth_dev_get_port_by_addr( + struct rte_pci_addr *addr, uint8_t *port_id); + +/** * Function for internal use by dummy drivers primarily, e.g. ring-based * driver. * Allocates a new ethdev slot for an ethernet device and returns the pointer -- 1.9.1
[dpdk-dev] [PATCH v2 10/28] ethdev: Add rte_eth_dev_get_name_by_port
The function returns a unique identifier name of a ethdev specified by port identifier. Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 22 ++ lib/librte_ether/rte_ethdev.h | 12 2 files changed, 34 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 4e9f0f7..1d82f69 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -476,6 +476,28 @@ rte_eth_dev_get_port_by_addr(struct rte_pci_addr *addr, uint8_t *port_id) return -1; } +int +rte_eth_dev_get_name_by_port(uint8_t port_id, char *name) +{ + char *tmp; + + if (rte_eth_dev_validate_port(port_id) == DEV_INVALID) { + PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); + return -EINVAL; + } + + if (name == NULL) { + PMD_DEBUG_TRACE("Null pointer is specified\n"); + return -EINVAL; + } + + /* shouldn't check 'rte_eth_devices[i].data', +* because it might be overwritten by VDEV PMD */ + tmp = rte_eth_dev_data[port_id].name; + strncpy(name, tmp, strlen(tmp) + 1); + return 0; +} + static int rte_eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) { diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 8c55c56..bd921d0 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1689,6 +1689,18 @@ extern int rte_eth_dev_get_port_by_addr( struct rte_pci_addr *addr, uint8_t *port_id); /** + * Function for internal use by port hotplug functions. + * Returns a unique identifier name of a ethdev specified by port identifier. + * @param port_id + * The port identifier. + * @param name + * The pointer to the Unique identifier name for each Ethernet device + * @return + * - 0 on success, negative on error + */ +extern int rte_eth_dev_get_name_by_port(uint8_t port_id, char *name); + +/** * Function for internal use by dummy drivers primarily, e.g. ring-based * driver. * Allocates a new ethdev slot for an ethernet device and returns the pointer -- 1.9.1
[dpdk-dev] [PATCH v2 11/28] ethdev: Add rte_eth_dev_check_detachable
The function returns whether a PMD supports detach function, or not. Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 9 + lib/librte_ether/rte_ethdev.h | 11 +++ 2 files changed, 20 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 1d82f69..ed53e66 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -498,6 +498,15 @@ rte_eth_dev_get_name_by_port(uint8_t port_id, char *name) return 0; } +int +rte_eth_dev_check_detachable(uint8_t port_id) +{ + uint32_t drv_flags; + + drv_flags = rte_eth_devices[port_id].driver->pci_drv.drv_flags; + return !(drv_flags & RTE_PCI_DRV_DETACHABLE); +} + static int rte_eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) { diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index bd921d0..404c41f 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1701,6 +1701,17 @@ extern int rte_eth_dev_get_port_by_addr( extern int rte_eth_dev_get_name_by_port(uint8_t port_id, char *name); /** + * Function for internal use by port hotplug functions. + * Check whether or not, a PMD that is handling the ethdev specified by port + * identifier can support detach function. + * @param port_id + * The port identifier + * @return + * - 0 on supporting detach function, negative on not supporting + */ +extern int rte_eth_dev_check_detachable(uint8_t port_id); + +/** * Function for internal use by dummy drivers primarily, e.g. ring-based * driver. * Allocates a new ethdev slot for an ethernet device and returns the pointer -- 1.9.1
[dpdk-dev] [PATCH v2 12/28] ethdev: Change scope of rte_eth_dev_allocated to global
This function is used by virtual PMDs to support port hotplug framework. So change scope of the function to global. Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 2 +- lib/librte_ether/rte_ethdev.h | 10 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index ed53e66..86200e0 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -206,7 +206,7 @@ rte_eth_dev_data_alloc(void) RTE_MAX_ETHPORTS * sizeof(*rte_eth_dev_data)); } -static struct rte_eth_dev * +struct rte_eth_dev * rte_eth_dev_allocated(const char *name) { unsigned i; diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 404c41f..47622a2 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1712,6 +1712,16 @@ extern int rte_eth_dev_get_name_by_port(uint8_t port_id, char *name); extern int rte_eth_dev_check_detachable(uint8_t port_id); /** + * Function for internal use by port hotplug functions. + * Returns a ethdev slot specified by the unique identifier name. + * @param name + * The pointer to the Unique identifier name for each Ethernet device + * @return + * - The pointer to the ethdev slot, on success. NULL on error + */ +extern struct rte_eth_dev *rte_eth_dev_allocated(const char *name); + +/** * Function for internal use by dummy drivers primarily, e.g. ring-based * driver. * Allocates a new ethdev slot for an ethernet device and returns the pointer -- 1.9.1
[dpdk-dev] [PATCH v2 13/28] eal/pci: Prevent double registration for devargs_list
The patch fixes rte_eal_devargs_add() not to register same device twice. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_devargs.c | 35 ++ 1 file changed, 35 insertions(+) diff --git a/lib/librte_eal/common/eal_common_devargs.c b/lib/librte_eal/common/eal_common_devargs.c index 4c7d11a..f95a12d 100644 --- a/lib/librte_eal/common/eal_common_devargs.c +++ b/lib/librte_eal/common/eal_common_devargs.c @@ -44,6 +44,35 @@ struct rte_devargs_list devargs_list = TAILQ_HEAD_INITIALIZER(devargs_list); + +/* find a entry specified by pci address or device name */ +static struct rte_devargs * +rte_eal_devargs_find(enum rte_devtype devtype, void *args) +{ + struct rte_devargs *devargs; + + if (args == NULL) + return NULL; + + TAILQ_FOREACH(devargs, &devargs_list, next) { + switch (devtype) { + case RTE_DEVTYPE_WHITELISTED_PCI: + case RTE_DEVTYPE_BLACKLISTED_PCI: + if (eal_compare_pci_addr(&devargs->pci.addr, args) == 0) + goto found; + break; + case RTE_DEVTYPE_VIRTUAL: + if (memcmp(&devargs->virtual.drv_name, args, + strlen((char *)args)) == 0) + goto found; + break; + } + } + return NULL; +found: + return devargs; +} + /* store a whitelist parameter for later parsing */ int rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str) @@ -101,6 +130,12 @@ rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str) break; } + /* make sure there is no same entry */ + if (rte_eal_devargs_find(devtype, &devargs->pci.addr)) { + RTE_LOG(ERR, EAL, "device already registered: <%s>\n", buf); + return -1; + } + TAILQ_INSERT_TAIL(&devargs_list, devargs, next); return 0; } -- 1.9.1
[dpdk-dev] [PATCH v2 14/28] eal/pci: Add rte_eal_devargs_remove
The function removes a specified devargs from devargs_list. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_devargs.c | 16 lib/librte_eal/common/include/rte_devargs.h | 18 ++ 2 files changed, 34 insertions(+) diff --git a/lib/librte_eal/common/eal_common_devargs.c b/lib/librte_eal/common/eal_common_devargs.c index f95a12d..5fd2a2c 100644 --- a/lib/librte_eal/common/eal_common_devargs.c +++ b/lib/librte_eal/common/eal_common_devargs.c @@ -140,6 +140,22 @@ rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str) return 0; } +/* remove it from the devargs_list */ +void +rte_eal_devargs_remove(enum rte_devtype devtype, void *args) +{ + struct rte_devargs *devargs; + + if (args == NULL) + return; + + devargs = rte_eal_devargs_find(devtype, args); + if (devargs == NULL) + return; + + TAILQ_REMOVE(&devargs_list, devargs, next); +} + /* count the number of devices of a specified type */ unsigned int rte_eal_devargs_type_count(enum rte_devtype devtype) diff --git a/lib/librte_eal/common/include/rte_devargs.h b/lib/librte_eal/common/include/rte_devargs.h index 9f9c98f..1066efd 100644 --- a/lib/librte_eal/common/include/rte_devargs.h +++ b/lib/librte_eal/common/include/rte_devargs.h @@ -123,6 +123,24 @@ extern struct rte_devargs_list devargs_list; int rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str); /** + * Remove a device from the user device list + * + * For PCI devices, the format of arguments string is "PCI_ADDR". It shouldn't + * involves parameters for the device. Example: "08:00.1". + * + * For virtual devices, the format of arguments string is "DRIVER_NAME*". It + * shouldn't involves parameters for the device. Example: "eth_ring". The + * validity of the driver name is not checked by this function, it is done + * when closing the drivers. + * + * @param devtype + * The type of the device. + * @param name + * The name of the device. + */ +void rte_eal_devargs_remove(enum rte_devtype devtype, void *args); + +/** * Count the number of user devices of a specified type * * @param devtype -- 1.9.1
[dpdk-dev] [PATCH v2 15/28] eal/pci: Add probe and close function for virtual drivers
The patch adds rte_eal_dev_init_one() and rte_eal_dev_close_one(). These are used for attaching and detaching virtual devices. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_dev.c | 66 + lib/librte_eal/common/include/rte_dev.h | 6 +++ lib/librte_eal/linuxapp/eal/Makefile| 1 + 3 files changed, 73 insertions(+) diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c index eae5656..f573a54 100644 --- a/lib/librte_eal/common/eal_common_dev.c +++ b/lib/librte_eal/common/eal_common_dev.c @@ -32,10 +32,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include +#include #include #include #include +#include #include #include #include @@ -107,3 +110,66 @@ rte_eal_dev_init(void) } return 0; } + +/* So far, linux only supports DPDK hotplug function. */ +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) + +#define INVOKE_PROBE (0) +#define INVOKE_CLOSE (1) + +static void +rte_eal_dev_invoke(struct rte_driver *driver, + struct rte_devargs *devargs, int type) +{ + if ((driver == NULL) || (devargs == NULL)) + return; + + switch (type) { + case INVOKE_PROBE: + driver->init(devargs->virtual.drv_name, devargs->args); + break; + case INVOKE_CLOSE: + driver->close(devargs->virtual.drv_name, devargs->args); + break; + } +} + +static int +rte_eal_dev_find_and_invoke(const char *name, int type) +{ + struct rte_devargs *devargs; + struct rte_driver *driver; + + if (name == NULL) + return -EINVAL; + + /* call the init function for each virtual device */ + TAILQ_FOREACH(devargs, &devargs_list, next) { + + if (devargs->type != RTE_DEVTYPE_VIRTUAL) + continue; + + if (strncmp(name, devargs->virtual.drv_name, strlen(name))) + continue; + + TAILQ_FOREACH(driver, &dev_driver_list, next) { + if (driver->type != PMD_VDEV) + continue; + + /* search a driver prefix in virtual device name */ + if (!strncmp(driver->name, devargs->virtual.drv_name, + strlen(driver->name))) { + rte_eal_dev_invoke(driver, devargs, type); + break; + } + } + + if (driver == NULL) { + RTE_LOG(WARNING, EAL, "no driver found for %s\n", + devargs->virtual.drv_name); + } + return 0; + } + return 1; +} +#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h index f7e3a10..71d40c3 100644 --- a/lib/librte_eal/common/include/rte_dev.h +++ b/lib/librte_eal/common/include/rte_dev.h @@ -57,6 +57,11 @@ TAILQ_HEAD(rte_driver_list, rte_driver); typedef int (rte_dev_init_t)(const char *name, const char *args); /** + * Close function called for each device driver once. + */ +typedef int (rte_dev_close_t)(const char *name, const char *args); + +/** * Driver type enumeration */ enum pmd_type { @@ -72,6 +77,7 @@ struct rte_driver { enum pmd_type type;/**< PMD Driver type */ const char *name; /**< Driver name. */ rte_dev_init_t *init; /**< Device init. function. */ + rte_dev_close_t *close;/**< Device close. function. */ }; /** diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile index 72ecf3a..0ec83b5 100644 --- a/lib/librte_eal/linuxapp/eal/Makefile +++ b/lib/librte_eal/linuxapp/eal/Makefile @@ -41,6 +41,7 @@ CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include CFLAGS += -I$(RTE_SDK)/lib/librte_ring CFLAGS += -I$(RTE_SDK)/lib/librte_mempool CFLAGS += -I$(RTE_SDK)/lib/librte_malloc +CFLAGS += -I$(RTE_SDK)/lib/librte_mbuf CFLAGS += -I$(RTE_SDK)/lib/librte_ether CFLAGS += -I$(RTE_SDK)/lib/librte_ivshmem CFLAGS += -I$(RTE_SDK)/lib/librte_pmd_ring -- 1.9.1
[dpdk-dev] [PATCH v2 16/28] eal/pci: Add port hotplug functions for virtual devices.
The patch adds rte_eal_dev_attach_vdev() and rte_eal_dev_detach_vdev(). rte_eal_dev_attach_vdev() receives virtual device name and parameters, and returns an attached port number. rte_eal_dev_detach_vdev() receives a port number, and returns device name actually detached. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_dev.c | 86 + lib/librte_eal/common/include/rte_dev.h | 29 +++ 2 files changed, 115 insertions(+) diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c index f573a54..4ea3502 100644 --- a/lib/librte_eal/common/eal_common_dev.c +++ b/lib/librte_eal/common/eal_common_dev.c @@ -172,4 +172,90 @@ rte_eal_dev_find_and_invoke(const char *name, int type) } return 1; } + +static void +get_vdev_name(char *vdevargs) +{ + char *sep; + + if (vdevargs == NULL) + return; + + /* set the first ',' to '\0' to split name and arguments */ + sep = strchr(vdevargs, ','); + if (sep != NULL) + sep[0] = '\0'; +} + +/* attach the new virtual device, then store port_id of the device */ +int +rte_eal_dev_attach_vdev(const char *vdevargs, uint8_t *port_id) +{ + char *args; + uint8_t new_port_id; + struct rte_eth_dev devs[RTE_MAX_ETHPORTS]; + + if ((vdevargs == NULL) || (port_id == NULL)) + goto err0; + + args = strdup(vdevargs); + if (args == NULL) + goto err0; + + /* save current port status */ + rte_eth_dev_save(devs); + /* add the vdevargs to devargs_list */ + if (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL, args)) + goto err1; + /* parse vdevargs, then retrieve device name */ + get_vdev_name(args); + /* walk around dev_driver_list to find the driver of the device, +* then invoke probe function o the driver */ + if (rte_eal_dev_find_and_invoke(args, INVOKE_PROBE)) + goto err2; + /* get port_id enabled by above procedures */ + if (rte_eth_dev_get_changed_port(devs, &new_port_id)) + goto err2; + + free(args); + *port_id = new_port_id; + return 0; +err2: + rte_eal_devargs_remove(RTE_DEVTYPE_VIRTUAL, args); +err1: + free(args); +err0: + RTE_LOG(ERR, EAL, "Drver, cannot detach the device\n"); + return -1; +} + +/* detach the new virtual device, then store the name of the device */ +int +rte_eal_dev_detach_vdev(uint8_t port_id, char *vdevname) +{ + char name[RTE_ETH_NAME_MAX_LEN]; + + if (vdevname == NULL) + goto err; + + /* check whether the driver supports detach feature, or not */ + if (rte_eth_dev_check_detachable(port_id)) + goto err; + + /* get device name by port id */ + if (rte_eth_dev_get_name_by_port(port_id, name)) + goto err; + /* walk around dev_driver_list to find the driver of the device, +* then invoke close function o the driver */ + if (rte_eal_dev_find_and_invoke(name, INVOKE_CLOSE)) + goto err; + /* remove the vdevname from devargs_list */ + rte_eal_devargs_remove(RTE_DEVTYPE_VIRTUAL, name); + + strncpy(vdevname, name, sizeof(name)); + return 0; +err: + RTE_LOG(ERR, EAL, "Drver, cannot detach the device\n"); + return -1; +} #endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h index 71d40c3..159d5a5 100644 --- a/lib/librte_eal/common/include/rte_dev.h +++ b/lib/librte_eal/common/include/rte_dev.h @@ -98,6 +98,35 @@ void rte_eal_driver_register(struct rte_driver *driver); */ void rte_eal_driver_unregister(struct rte_driver *driver); +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) + +/** + * Attach a new virtual device. + * + * @param vdevargs + * A pointer to a strings array describing the new device + * to be attached. + * @param port_id + * A pointer to a port identifier actually attached. + * @return + * 0 on success and port_id is filled, negative on error + */ +int rte_eal_dev_attach_vdev(const char *vdevargs, uint8_t *port_id); + +/** + * Detach a virtual device. + * + * @param port_id + * The port identifier of the virtual device to detach. + * @param addr + * A pointer to a virtual device name actually detached. + * @return + * 0 on success and vdevname is filled, negative on error + */ +int rte_eal_dev_detach_vdev(uint8_t port_id, char *vdevname); + +#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ + /** * Initalize all the registered drivers in this process */ -- 1.9.1
[dpdk-dev] [PATCH v2 17/28] eal/linux/pci: Add functions for unmapping igb_uio resources
The patch adds functions for unmapping igb_uio resources. The patch is only for Linux and igb_uio environment. VFIO and BSD are not supported. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/linuxapp/eal/eal_pci.c | 35 lib/librte_eal/linuxapp/eal/eal_pci_init.h | 7 lib/librte_eal/linuxapp/eal/eal_pci_uio.c | 65 ++ 3 files changed, 107 insertions(+) diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index 23a69e9..fe212d1 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -137,6 +137,22 @@ pci_map_resource(void *requested_addr, int fd, off_t offset, size_t size) return mapaddr; } +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) +/* unmap a particular resource */ +void +pci_unmap_resource(void *requested_addr, size_t size) +{ + /* Unmap the PCI memory resource of device */ + if (munmap(requested_addr, size)) { + RTE_LOG(ERR, EAL, "%s(): cannot munmap(%p, 0x%lx): %s\n", + __func__, requested_addr, (unsigned long)size, + strerror(errno)); + } else + RTE_LOG(DEBUG, EAL, " PCI memory mapped at %p\n", + requested_addr); +} +#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ + /* parse the "resource" sysfs file */ #define IORESOURCE_MEM 0x0200 @@ -507,6 +523,25 @@ pci_map_device(struct rte_pci_device *dev) return 0; } +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) +static void +pci_unmap_device(struct rte_pci_device *dev) +{ + if (dev == NULL) + return; + + /* try unmapping the NIC resources using VFIO if it exists */ +#ifdef VFIO_PRESENT + if (pci_vfio_is_enabled()) { + RTE_LOG(ERR, EAL, "%s() doesn't support vfio yet.\n", + __func__); + return; + } +#endif + pci_uio_unmap_resource(dev); +} +#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ + /* * If vendor/device ID match, call the devinit() function of the * driver. diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_init.h b/lib/librte_eal/linuxapp/eal/eal_pci_init.h index 1070eb8..c733ac3 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci_init.h +++ b/lib/librte_eal/linuxapp/eal/eal_pci_init.h @@ -71,6 +71,13 @@ void *pci_map_resource(void *requested_addr, int fd, off_t offset, /* map IGB_UIO resource prototype */ int pci_uio_map_resource(struct rte_pci_device *dev); +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) +void pci_unmap_resource(void *requested_addr, size_t size); + +/* unmap IGB_UIO resource prototype */ +void pci_uio_unmap_resource(struct rte_pci_device *dev); +#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ + #ifdef VFIO_PRESENT #define VFIO_MAX_GROUPS 64 diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c index 1da3507..77e7389 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c @@ -404,6 +404,71 @@ pci_uio_map_resource(struct rte_pci_device *dev) return 0; } +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) +static void +pci_uio_unmap(struct mapped_pci_resource *uio_res) +{ + int i; + + if (uio_res == NULL) + return; + + for (i = 0; i != uio_res->nb_maps; i++) + pci_unmap_resource(uio_res->maps[i].addr, + (size_t)uio_res->maps[i].size); +} + +static struct mapped_pci_resource * +pci_uio_find_resource(struct rte_pci_device *dev) +{ + struct mapped_pci_resource *uio_res; + + if (dev == NULL) + return NULL; + + TAILQ_FOREACH(uio_res, pci_res_list, next) { + + /* skip this element if it doesn't match our PCI address */ + if (!eal_compare_pci_addr(&uio_res->pci_addr, &dev->addr)) + return uio_res; + } + return NULL; +} + +/* unmap the PCI resource of a PCI device in virtual memory */ +void +pci_uio_unmap_resource(struct rte_pci_device *dev) +{ + struct mapped_pci_resource *uio_res; + + if (dev == NULL) + return; + + /* find an entry for the device */ + uio_res = pci_uio_find_resource(dev); + if (uio_res == NULL) + return; + + /* secondary processes - just free maps */ + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return pci_uio_unmap(uio_res); + + TAILQ_REMOVE(pci_res_list, uio_res, next); + + /* unmap all resources */ + pci_uio_unmap(uio_res); + + /* free uio resource */ + rte_free(uio_res); + + /* close fd if in primary process */ + close(dev->intr_handle.fd); + + dev->intr_handle.fd = -1; + dev
[dpdk-dev] [PATCH v2 18/28] eal/pci: Prevent double registrations for pci_device_list
The patch fixes pci_scan_one() not to register same pci devices twice. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/linuxapp/eal/eal_pci.c | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index fe212d1..355c858 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -306,14 +306,17 @@ pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, } else { struct rte_pci_device *dev2 = NULL; + int ret; TAILQ_FOREACH(dev2, &pci_device_list, next) { - if (eal_compare_pci_addr(&dev->addr, &dev2->addr) != 0) + ret = eal_compare_pci_addr(&dev->addr, &dev2->addr); + if (ret > 0) continue; - else { + else if (ret < 0) { TAILQ_INSERT_BEFORE(dev2, dev, next); return 0; - } + } else /* already registered */ + return 0; } TAILQ_INSERT_TAIL(&pci_device_list, dev, next); } -- 1.9.1
[dpdk-dev] [PATCH v2 19/28] eal/pci: Change scope of rte_eal_pci_scan to global
The function is called by port hotplug framework, so change scope of the function to global. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_private.h | 11 +++ lib/librte_eal/linuxapp/eal/eal_pci.c | 6 +++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h index 232fcec..a1127ab 100644 --- a/lib/librte_eal/common/eal_private.h +++ b/lib/librte_eal/common/eal_private.h @@ -154,6 +154,17 @@ struct rte_pci_driver; struct rte_pci_device; /** + * Scan the content of the PCI bus, and the devices in the devices + * list + * + * This function is private to EAL. + * + * @return + * 0 on success, negative on error + */ +int rte_eal_pci_scan(void); + +/** * Mmap memory for single PCI device * * This function is private to EAL. diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index 355c858..8d683f5 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -375,8 +375,8 @@ error: * Scan the content of the PCI bus, and the devices in the devices * list */ -static int -pci_scan(void) +int +rte_eal_pci_scan(void) { struct dirent *e; DIR *dir; @@ -629,7 +629,7 @@ rte_eal_pci_init(void) if (internal_config.no_pci) return 0; - if (pci_scan() < 0) { + if (rte_eal_pci_scan() < 0) { RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__); return -1; } -- 1.9.1
[dpdk-dev] [PATCH v2 20/28] eal/pci: Add rte_eal_pci_close_one_driver
The function is used for closing the specified driver and device. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_private.h | 15 + lib/librte_eal/linuxapp/eal/eal_pci.c | 61 +++ 2 files changed, 76 insertions(+) diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h index a1127ab..f892ac4 100644 --- a/lib/librte_eal/common/eal_private.h +++ b/lib/librte_eal/common/eal_private.h @@ -176,6 +176,21 @@ int rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev); /** + * Munmap memory for single PCI device + * + * This function is private to EAL. + * + * @param dr + * The pointer to the pci driver structure + * @param dev + * The pointer to the pci device structure + * @return + * 0 on success, negative on error + */ +int rte_eal_pci_close_one_driver(struct rte_pci_driver *dr, + struct rte_pci_device *dev); + +/** * Init tail queues for non-EAL library structures. This is to allow * the rings, mempools, etc. lists to be shared among multiple processes * diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index 8d683f5..93456f3 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -616,6 +616,67 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *d return 1; } +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) +/* + * If vendor/device ID match, call the devshutdown() function of the + * driver. + */ +int +rte_eal_pci_close_one_driver(struct rte_pci_driver *dr, + struct rte_pci_device *dev) +{ + struct rte_pci_id *id_table; + + if ((dr == NULL) || (dev == NULL)) + return -EINVAL; + + for (id_table = dr->id_table ; id_table->vendor_id != 0; id_table++) { + + /* check if device's identifiers match the driver's ones */ + if (id_table->vendor_id != dev->id.vendor_id && + id_table->vendor_id != PCI_ANY_ID) + continue; + if (id_table->device_id != dev->id.device_id && + id_table->device_id != PCI_ANY_ID) + continue; + if (id_table->subsystem_vendor_id != + dev->id.subsystem_vendor_id && + id_table->subsystem_vendor_id != PCI_ANY_ID) + continue; + if (id_table->subsystem_device_id != + dev->id.subsystem_device_id && + id_table->subsystem_device_id != PCI_ANY_ID) + continue; + + struct rte_pci_addr *loc = &dev->addr; + + RTE_LOG(DEBUG, EAL, + "PCI device "PCI_PRI_FMT" on NUMA socket %i\n", + loc->domain, loc->bus, loc->devid, + loc->function, dev->numa_node); + + RTE_LOG(DEBUG, EAL, " remove driver: %x:%x %s\n", + dev->id.vendor_id, dev->id.device_id, + dr->name); + + /* call the driver devshutdown() function */ + if (dr->devshutdown && (dr->devshutdown(dr, dev) < 0)) + return -1; /* negative value is an error */ + + /* clear driver structure */ + dev->driver = NULL; + + if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) + /* unmap resources for devices that use igb_uio */ + pci_unmap_device(dev); + + return 0; + } + /* return positive value if driver is not found */ + return 1; +} +#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ + /* Init the PCI EAL subsystem */ int rte_eal_pci_init(void) -- 1.9.1
[dpdk-dev] [PATCH v2 21/28] eal/pci: Fix pci_probe_all_drivers to share code with closing function
pci_close_all_drivers() will be implemented after the patch. To share a part of code between thses 2 functions, The patch fixes pci_probe_all_drivers() first. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_pci.c | 28 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c index f01f258..1e3efea 100644 --- a/lib/librte_eal/common/eal_common_pci.c +++ b/lib/librte_eal/common/eal_common_pci.c @@ -99,19 +99,20 @@ static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev) return NULL; } -/* - * If vendor/device ID match, call the devinit() function of all - * registered driver for the given device. Return -1 if initialization - * failed, return 1 if no driver is found for this device. - */ +#define INVOKE_PROBE (0) + static int -pci_probe_all_drivers(struct rte_pci_device *dev) +pci_invoke_all_drivers(struct rte_pci_device *dev, int type) { struct rte_pci_driver *dr = NULL; - int rc; + int rc = 0; TAILQ_FOREACH(dr, &pci_driver_list, next) { - rc = rte_eal_pci_probe_one_driver(dr, dev); + switch (type) { + case INVOKE_PROBE: + rc = rte_eal_pci_probe_one_driver(dr, dev); + break; + } if (rc < 0) /* negative value is an error */ return -1; @@ -124,6 +125,17 @@ pci_probe_all_drivers(struct rte_pci_device *dev) } /* + * If vendor/device ID match, call the devinit() function of all + * registered driver for the given device. Return -1 if initialization + * failed, return 1 if no driver is found for this device. + */ +static int +pci_probe_all_drivers(struct rte_pci_device *dev) +{ + return pci_invoke_all_drivers(dev, INVOKE_PROBE); +} + +/* * Scan the content of the PCI bus, and call the devinit() function for * all registered drivers that have a matching entry in its id_table * for discovered devices. -- 1.9.1
[dpdk-dev] [PATCH v2 22/28] eal/pci: Add pci_close_all_drivers
The function tries to find a driver for the specified device, and then close the driver. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_pci.c | 19 +++ 1 file changed, 19 insertions(+) diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c index 1e3efea..b404ee0 100644 --- a/lib/librte_eal/common/eal_common_pci.c +++ b/lib/librte_eal/common/eal_common_pci.c @@ -100,6 +100,7 @@ static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev) } #define INVOKE_PROBE (0) +#define INVOKE_CLOSE (1) static int pci_invoke_all_drivers(struct rte_pci_device *dev, int type) @@ -112,6 +113,11 @@ pci_invoke_all_drivers(struct rte_pci_device *dev, int type) case INVOKE_PROBE: rc = rte_eal_pci_probe_one_driver(dr, dev); break; +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) + case INVOKE_CLOSE: + rc = rte_eal_pci_close_one_driver(dr, dev); + break; +#endif } if (rc < 0) /* negative value is an error */ @@ -135,6 +141,19 @@ pci_probe_all_drivers(struct rte_pci_device *dev) return pci_invoke_all_drivers(dev, INVOKE_PROBE); } +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) +/* + * If vendor/device ID match, call the devclose() function of all + * registered driver for the given device. Return -1 if initialization + * failed, return 1 if no driver is found for this device. + */ +static int +pci_close_all_drivers(struct rte_pci_device *dev) +{ + return pci_invoke_all_drivers(dev, INVOKE_CLOSE); +} +#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ + /* * Scan the content of the PCI bus, and call the devinit() function for * all registered drivers that have a matching entry in its id_table -- 1.9.1
[dpdk-dev] [PATCH v2 23/28] eal/pci: Add rte_eal_pci_probe_one and rte_eal_pci_close_one
The functions are used for probe and close a device. First the function tries to find a device that has the specfied PCI address. Then, probe or close the device. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_pci.c | 58 + lib/librte_eal/common/include/rte_pci.h | 26 +++ 2 files changed, 84 insertions(+) diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c index b404ee0..5ff7b49 100644 --- a/lib/librte_eal/common/eal_common_pci.c +++ b/lib/librte_eal/common/eal_common_pci.c @@ -152,6 +152,64 @@ pci_close_all_drivers(struct rte_pci_device *dev) { return pci_invoke_all_drivers(dev, INVOKE_CLOSE); } + +static int +rte_eal_pci_invoke_one(struct rte_pci_addr *addr, int type) +{ + struct rte_pci_device *dev = NULL; + int ret = 0; + + TAILQ_FOREACH(dev, &pci_device_list, next) { + if (eal_compare_pci_addr(&dev->addr, addr)) + continue; + + switch (type) { + case INVOKE_PROBE: + ret = pci_probe_all_drivers(dev); + break; + case INVOKE_CLOSE: + ret = pci_close_all_drivers(dev); + break; + } + if (ret < 0) + goto invoke_err_return; + if (type == INVOKE_CLOSE) + goto remove_dev; + return 0; + } + + return -1; + +invoke_err_return: + RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT + " cannot be used\n", dev->addr.domain, dev->addr.bus, + dev->addr.devid, dev->addr.function); + return -1; + +remove_dev: + TAILQ_REMOVE(&pci_device_list, dev, next); + return 0; +} + +/* + * Find the pci device specified by pci address, then invoke probe function of + * the driver of the devive. + */ +int +rte_eal_pci_probe_one(struct rte_pci_addr *addr) +{ + return rte_eal_pci_invoke_one(addr, INVOKE_PROBE); +} + +/* + * Find the pci device specified by pci address, then invoke close function of + * the driver of the devive. + */ +int +rte_eal_pci_close_one(struct rte_pci_addr *addr) +{ + return rte_eal_pci_invoke_one(addr, INVOKE_CLOSE); +} #endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ /* diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index 74720d1..5a7e06f 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -311,6 +311,32 @@ eal_compare_pci_addr(struct rte_pci_addr *addr, struct rte_pci_addr *addr2) int rte_eal_pci_probe(void); /** + * Probe the single PCI device. + * + * Scan the content of the PCI bus, and find the pci device specified by pci + * address, then call the probe() function for registered driver that has a + * matching entry in its id_table for discovered device. + * + * @return + * - 0 on success. + * - Negative on error. + */ +int rte_eal_pci_probe_one(struct rte_pci_addr *addr); + +/** + * Close the single PCI device. + * + * Scan the content of the PCI bus, and find the pci device specified by pci + * address, then call the close() function for registered driver that has a + * matching entry in its id_table for discovered device. + * + * @return + * - 0 on success. + * - Negative on error. + */ +int rte_eal_pci_close_one(struct rte_pci_addr *addr); + +/** * Dump the content of the PCI bus. * * @param f -- 1.9.1
[dpdk-dev] [PATCH v2 24/28] eal/pci: Add port hotplug functions for physical devices.
The patch adds rte_eal_dev_attach_pdev() and rte_eal_dev_detach_pdev(). rte_eal_dev_attach_pdev() receives a PCI address of the device and returns an attached port number. rte_eal_dev_detach_pdev() receives a port number, and returns a PCI address actually detached. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_dev.c | 64 + lib/librte_eal/common/include/rte_dev.h | 26 ++ 2 files changed, 90 insertions(+) diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c index 4ea3502..9ff03ed 100644 --- a/lib/librte_eal/common/eal_common_dev.c +++ b/lib/librte_eal/common/eal_common_dev.c @@ -173,6 +173,70 @@ rte_eal_dev_find_and_invoke(const char *name, int type) return 1; } +/* attach the new physical device, then store port_id of the device */ +int +rte_eal_dev_attach_pdev(struct rte_pci_addr *addr, uint8_t *port_id) +{ + uint8_t new_port_id; + struct rte_eth_dev devs[RTE_MAX_ETHPORTS]; + + if ((addr == NULL) || (port_id == NULL)) + goto err; + + /* save current port status */ + rte_eth_dev_save(devs); + /* re-construct pci_device_list */ + if (rte_eal_pci_scan()) + goto err; + /* invoke probe func of the driver can handle the new device */ + if (rte_eal_pci_probe_one(addr)) + goto err; + /* get port_id enabled by above procedures */ + if (rte_eth_dev_get_changed_port(devs, &new_port_id)) + goto err; + + *port_id = new_port_id; + return 0; +err: + RTE_LOG(ERR, EAL, "Drver, cannot attach the device\n"); + return -1; +} + +/* detach the new physical device, then store pci_addr of the device */ +int +rte_eal_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr) +{ + struct rte_pci_addr freed_addr; + struct rte_pci_addr vp; + + if (addr == NULL) + goto err; + + /* check whether the driver supports detach feature, or not */ + if (rte_eth_dev_check_detachable(port_id)) + goto err; + + /* get pci address by port id */ + if (rte_eth_dev_get_addr_by_port(port_id, &freed_addr)) + goto err; + + /* Zerod pci addr means the port comes from virtual device */ + vp.domain = vp.bus = vp.devid = vp.function = 0; + if (eal_compare_pci_addr(&vp, &freed_addr) == 0) + goto err; + + /* invoke close func of the driver, +* also remove the device from pci_device_list */ + if (rte_eal_pci_close_one(&freed_addr)) + goto err; + + *addr = freed_addr; + return 0; +err: + RTE_LOG(ERR, EAL, "Drver, cannot detach the device\n"); + return -1; +} + static void get_vdev_name(char *vdevargs) { diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h index 159d5a5..f0677cb 100644 --- a/lib/librte_eal/common/include/rte_dev.h +++ b/lib/librte_eal/common/include/rte_dev.h @@ -47,6 +47,7 @@ extern "C" { #endif #include +#include /** Double linked list of device drivers. */ TAILQ_HEAD(rte_driver_list, rte_driver); @@ -101,6 +102,19 @@ void rte_eal_driver_unregister(struct rte_driver *driver); #if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) /** + * Attach a new physical device. + * + * @param addr + * A pointer to a pci address structure describing the new + * device to be attached. + * @param port_id + * A pointer to a port identifier actually attached. + * @return + * 0 on success and port_id is filled, negative on error + */ +int rte_eal_dev_attach_pdev(struct rte_pci_addr *addr, uint8_t *port_id); + +/** * Attach a new virtual device. * * @param vdevargs @@ -114,6 +128,18 @@ void rte_eal_driver_unregister(struct rte_driver *driver); int rte_eal_dev_attach_vdev(const char *vdevargs, uint8_t *port_id); /** + * Detach a physical device. + * + * @param port_id + * The port identifier of the physical device to detach. + * @param addr + * A pointer to a pci address structure actually detached. + * @return + * 0 on success and addr is filled, negative on error + */ +int rte_eal_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr); + +/** * Detach a virtual device. * * @param port_id -- 1.9.1
[dpdk-dev] [PATCH v2 25/28] eal/pci: Remove pci_probe/close_all_drivers()
These functions are actually wrappers of pci_invoke_all_drivers(). Just call it directly. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_pci.c | 30 -- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c index 5ff7b49..5044d8e 100644 --- a/lib/librte_eal/common/eal_common_pci.c +++ b/lib/librte_eal/common/eal_common_pci.c @@ -130,29 +130,7 @@ pci_invoke_all_drivers(struct rte_pci_device *dev, int type) return 1; } -/* - * If vendor/device ID match, call the devinit() function of all - * registered driver for the given device. Return -1 if initialization - * failed, return 1 if no driver is found for this device. - */ -static int -pci_probe_all_drivers(struct rte_pci_device *dev) -{ - return pci_invoke_all_drivers(dev, INVOKE_PROBE); -} - #if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) -/* - * If vendor/device ID match, call the devclose() function of all - * registered driver for the given device. Return -1 if initialization - * failed, return 1 if no driver is found for this device. - */ -static int -pci_close_all_drivers(struct rte_pci_device *dev) -{ - return pci_invoke_all_drivers(dev, INVOKE_CLOSE); -} - static int rte_eal_pci_invoke_one(struct rte_pci_addr *addr, int type) { @@ -165,10 +143,10 @@ rte_eal_pci_invoke_one(struct rte_pci_addr *addr, int type) switch (type) { case INVOKE_PROBE: - ret = pci_probe_all_drivers(dev); + ret = pci_invoke_all_drivers(dev, INVOKE_PROBE); break; case INVOKE_CLOSE: - ret = pci_close_all_drivers(dev); + ret = pci_invoke_all_drivers(dev, INVOKE_CLOSE); break; } if (ret < 0) @@ -237,10 +215,10 @@ rte_eal_pci_probe(void) /* probe all or only whitelisted devices */ if (probe_all) - ret = pci_probe_all_drivers(dev); + ret = pci_invoke_all_drivers(dev, INVOKE_PROBE); else if (devargs != NULL && devargs->type == RTE_DEVTYPE_WHITELISTED_PCI) - ret = pci_probe_all_drivers(dev); + ret = pci_invoke_all_drivers(dev, INVOKE_PROBE); if (ret < 0) rte_exit(EXIT_FAILURE, "Requested device " PCI_PRI_FMT " cannot be used\n", dev->addr.domain, dev->addr.bus, -- 1.9.1
[dpdk-dev] [PATCH v2 26/28] eal/pci: Add rte_eal_dev_attach/detach() functions
This functions wraps attaching and detaching functions for physical and virtual device. When rte_eal_dev_attach() is called, the function tries to realize the device name as pci address. If this is done successfully, rte_eal_dev_attach() will call rte_eal_dev_attach_pdev(). If not, calls rte_eal_dev_attach_vdev(). When rte_eal_dev_detach() is called, the function gets the device type of this port to know whether the port is came from physical or virtual. And then rte_eal_dev_detach_pdev() or rte_eal_dev_detach_vdev() will be called. Signed-off-by: Tetsuya Mukawa --- app/test/virtual_pmd.c | 2 +- lib/librte_eal/common/eal_common_dev.c | 34 lib/librte_eal/common/include/rte_dev.h | 25 lib/librte_ether/rte_ethdev.c| 14 ++-- lib/librte_ether/rte_ethdev.h| 24 +++- lib/librte_pmd_af_packet/rte_eth_af_packet.c | 2 +- lib/librte_pmd_bond/rte_eth_bond_api.c | 2 +- lib/librte_pmd_pcap/rte_eth_pcap.c | 2 +- lib/librte_pmd_ring/rte_eth_ring.c | 2 +- lib/librte_pmd_xenvirt/rte_eth_xenvirt.c | 2 +- 10 files changed, 100 insertions(+), 9 deletions(-) diff --git a/app/test/virtual_pmd.c b/app/test/virtual_pmd.c index ade6cb0..ff8f747 100644 --- a/app/test/virtual_pmd.c +++ b/app/test/virtual_pmd.c @@ -556,7 +556,7 @@ virtual_ethdev_create(const char *name, struct ether_addr *mac_addr, goto err; /* reserve an ethdev entry */ - eth_dev = rte_eth_dev_allocate(name); + eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_PHYSICAL); if (eth_dev == NULL) goto err; diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c index 9ff03ed..c9d4894 100644 --- a/lib/librte_eal/common/eal_common_dev.c +++ b/lib/librte_eal/common/eal_common_dev.c @@ -322,4 +322,38 @@ err: RTE_LOG(ERR, EAL, "Drver, cannot detach the device\n"); return -1; } + +/* attach the new device, then store port_id of the device */ +int +rte_eal_dev_attach(const char *devargs, uint8_t *port_id) +{ + struct rte_pci_addr addr; + + if (eal_parse_pci_DomBDF(devargs, &addr) == 0) + return rte_eal_dev_attach_pdev(&addr, port_id); + else + return rte_eal_dev_attach_vdev(devargs, port_id); +} + +/* detach the device, then store the name of the device */ +int +rte_eal_dev_detach(uint8_t port_id, char *name) +{ + struct rte_pci_addr addr; + int ret; + + if (rte_eth_dev_get_device_type(port_id) == RTE_ETH_DEV_PHYSICAL) { + ret = rte_eth_dev_get_addr_by_port(port_id, &addr); + if (ret < 0) + return ret; + + ret = rte_eal_dev_detach_pdev(port_id, &addr); + if (ret == 0) + snprintf(name, RTE_ETH_NAME_MAX_LEN, "%04x.%02x.%02x.%d", + addr.domain, addr.bus, addr.devid, addr.function); + + return ret; + } else + return rte_eal_dev_detach_vdev(port_id, name); +} #endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h index f0677cb..1f8f24a 100644 --- a/lib/librte_eal/common/include/rte_dev.h +++ b/lib/librte_eal/common/include/rte_dev.h @@ -151,6 +151,31 @@ int rte_eal_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr); */ int rte_eal_dev_detach_vdev(uint8_t port_id, char *vdevname); +/** + * Attach a new device. + * + * @param devargs + * A pointer to a strings array describing the new device + * to be attached. + * @param port_id + * A pointer to a port identifier actually attached. + * @return + * 0 on success and port_id is filled, negative on error + */ +int rte_eal_dev_attach(const char *devargs, uint8_t *port_id); + +/** + * Detach a device. + * + * @param port_id + * The port identifier of the device to detach. + * @param addr + * A pointer to a device name actually detached. + * @return + * 0 on success and devname is filled, negative on error + */ +int rte_eal_dev_detach(uint8_t port_id, char *devname); + #endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ /** diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 86200e0..cd5ef67 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -232,7 +232,7 @@ rte_eth_dev_allocate_new_port(void) } struct rte_eth_dev * -rte_eth_dev_allocate(const char *name) +rte_eth_dev_allocate(const char *name, enum rte_eth_dev_type type) { uint8_t port_id; struct rte_eth_dev *eth_dev; @@ -256,6 +256,7 @@ rte_eth_dev_allocate(const char *name) snprintf(eth_dev->data->name, sizeof(eth_dev->data->name), "%s", name); eth_dev->data->port_id = port_id; eth_dev->attached = DEV_CONNECTED; + eth
[dpdk-dev] [PATCH v2 27/28] eal/pci: Remove rte_eal_dev_attach/detach_pdev() and rte_eal_dev_attach/detach_vdev()
These functions are wrapped by rte_eal_dev_attach/detach(). So delete these. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_dev.c | 8 +++--- lib/librte_eal/common/include/rte_dev.h | 50 - 2 files changed, 4 insertions(+), 54 deletions(-) diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c index c9d4894..7481fb7 100644 --- a/lib/librte_eal/common/eal_common_dev.c +++ b/lib/librte_eal/common/eal_common_dev.c @@ -174,7 +174,7 @@ rte_eal_dev_find_and_invoke(const char *name, int type) } /* attach the new physical device, then store port_id of the device */ -int +static int rte_eal_dev_attach_pdev(struct rte_pci_addr *addr, uint8_t *port_id) { uint8_t new_port_id; @@ -203,7 +203,7 @@ err: } /* detach the new physical device, then store pci_addr of the device */ -int +static int rte_eal_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr) { struct rte_pci_addr freed_addr; @@ -252,7 +252,7 @@ get_vdev_name(char *vdevargs) } /* attach the new virtual device, then store port_id of the device */ -int +static int rte_eal_dev_attach_vdev(const char *vdevargs, uint8_t *port_id) { char *args; @@ -294,7 +294,7 @@ err0: } /* detach the new virtual device, then store the name of the device */ -int +static int rte_eal_dev_detach_vdev(uint8_t port_id, char *vdevname) { char name[RTE_ETH_NAME_MAX_LEN]; diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h index 1f8f24a..9da518d 100644 --- a/lib/librte_eal/common/include/rte_dev.h +++ b/lib/librte_eal/common/include/rte_dev.h @@ -102,56 +102,6 @@ void rte_eal_driver_unregister(struct rte_driver *driver); #if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) /** - * Attach a new physical device. - * - * @param addr - * A pointer to a pci address structure describing the new - * device to be attached. - * @param port_id - * A pointer to a port identifier actually attached. - * @return - * 0 on success and port_id is filled, negative on error - */ -int rte_eal_dev_attach_pdev(struct rte_pci_addr *addr, uint8_t *port_id); - -/** - * Attach a new virtual device. - * - * @param vdevargs - * A pointer to a strings array describing the new device - * to be attached. - * @param port_id - * A pointer to a port identifier actually attached. - * @return - * 0 on success and port_id is filled, negative on error - */ -int rte_eal_dev_attach_vdev(const char *vdevargs, uint8_t *port_id); - -/** - * Detach a physical device. - * - * @param port_id - * The port identifier of the physical device to detach. - * @param addr - * A pointer to a pci address structure actually detached. - * @return - * 0 on success and addr is filled, negative on error - */ -int rte_eal_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr); - -/** - * Detach a virtual device. - * - * @param port_id - * The port identifier of the virtual device to detach. - * @param addr - * A pointer to a virtual device name actually detached. - * @return - * 0 on success and vdevname is filled, negative on error - */ -int rte_eal_dev_detach_vdev(uint8_t port_id, char *vdevname); - -/** * Attach a new device. * * @param devargs -- 1.9.1
[dpdk-dev] [PATCH v2 28/28] eal: Enable port hotplug framework in Linux
The patch enables CONFIG_RTE_LIBRTE_EAL_HOTPLUG in Linux configuration. Signed-off-by: Tetsuya Mukawa --- config/common_linuxapp | 5 + 1 file changed, 5 insertions(+) diff --git a/config/common_linuxapp b/config/common_linuxapp index 2f9643b..27d05be 100644 --- a/config/common_linuxapp +++ b/config/common_linuxapp @@ -114,6 +114,11 @@ CONFIG_RTE_PCI_MAX_READ_REQUEST_SIZE=0 CONFIG_RTE_LIBRTE_EAL_LINUXAPP=y # +# Compile Environment Abstraction Layer to support hotplug +# +CONFIG_RTE_LIBRTE_EAL_HOTPLUG=y + +# # Compile Environment Abstraction Layer to support Vmware TSC map # CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=y -- 1.9.1
[dpdk-dev] [PATCH v2] librte_pmd_pcap: Add port hotplug support
This patch adds finalization code to free resources allocated by the PMD. Signed-off-by: Tetsuya Mukawa --- lib/librte_pmd_pcap/rte_eth_pcap.c | 40 ++ 1 file changed, 40 insertions(+) diff --git a/lib/librte_pmd_pcap/rte_eth_pcap.c b/lib/librte_pmd_pcap/rte_eth_pcap.c index 0f34f73..c92ebb7 100644 --- a/lib/librte_pmd_pcap/rte_eth_pcap.c +++ b/lib/librte_pmd_pcap/rte_eth_pcap.c @@ -499,6 +499,13 @@ static struct eth_dev_ops ops = { .stats_reset = eth_stats_reset, }; +static struct eth_driver rte_pcap_pmd = { + .pci_drv = { + .name = "rte_pcap_pmd", + .drv_flags = RTE_PCI_DRV_DETACHABLE, + }, +}; + /* * Function handler that opens the pcap file for reading a stores a * reference of it for use it later on. @@ -714,6 +721,10 @@ rte_pmd_init_internals(const char *name, const unsigned nb_rx_queues, if (*eth_dev == NULL) goto error; + /* check length of device name */ + if ((strlen((*eth_dev)->data->name) + 1) > sizeof(data->name)) + goto error; + /* now put it all together * - store queue data in internals, * - store numa_node info in pci_driver @@ -739,10 +750,13 @@ rte_pmd_init_internals(const char *name, const unsigned nb_rx_queues, data->nb_tx_queues = (uint16_t)nb_tx_queues; data->dev_link = pmd_link; data->mac_addrs = ð_addr; + strncpy(data->name, + (*eth_dev)->data->name, strlen((*eth_dev)->data->name)); (*eth_dev)->data = data; (*eth_dev)->dev_ops = &ops; (*eth_dev)->pci_dev = pci_dev; + (*eth_dev)->driver = &rte_pcap_pmd; return 0; @@ -927,10 +941,36 @@ rte_pmd_pcap_devinit(const char *name, const char *params) } +static int +rte_pmd_pcap_devclose(const char *name, const char *params __rte_unused) +{ + struct rte_eth_dev *eth_dev = NULL; + + RTE_LOG(INFO, PMD, "Closing pcap ethdev on numa socket %u\n", + rte_socket_id()); + + if (name == NULL) + return -1; + + /* reserve an ethdev entry */ + eth_dev = rte_eth_dev_allocated(name); + if (eth_dev == NULL) + return -1; + + rte_free(eth_dev->data->dev_private); + rte_free(eth_dev->data); + rte_free(eth_dev->pci_dev); + + rte_eth_dev_free(name); + + return 0; +} + static struct rte_driver pmd_pcap_drv = { .name = "eth_pcap", .type = PMD_VDEV, .init = rte_pmd_pcap_devinit, + .close = rte_pmd_pcap_devclose, }; PMD_REGISTER_DRIVER(pmd_pcap_drv); -- 1.9.1
[dpdk-dev] [PATCH v2] testpmd: Add port hotplug support
The patch introduces following commands. - port attach [ident] - port detach [port_id] - attach: attaching a port - detach: detaching a port - ident: pci address of physical device. Or device name and paramerters of virtual device. (ex. :02:00.0, eth_pcap0,iface=eth0) - port_id: port identifier Signed-off-by: Tetsuya Mukawa --- app/test-pmd/cmdline.c| 133 +-- app/test-pmd/config.c | 116 +++ app/test-pmd/parameters.c | 21 +++-- app/test-pmd/testpmd.c| 199 +++--- app/test-pmd/testpmd.h| 18 - 5 files changed, 357 insertions(+), 130 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index f79ea3e..40c2db7 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -572,6 +572,12 @@ static void cmd_help_long_parsed(void *parsed_result, "port close (port_id|all)\n" "Close all ports or port_id.\n\n" + "port add (p|a) (ident)\n" + "Add physical or virtual dev by pci address or virtual device name\n\n" + + "port del (p|a) (port_id)\n" + "Del physical or virtual dev by port_id\n\n" + "port config (port_id|all)" " speed (10|100|1000|1|4|auto)" " duplex (half|full|auto)\n" @@ -853,6 +859,89 @@ cmdline_parse_inst_t cmd_operate_specific_port = { }, }; +/* *** attach a specificied port *** */ +struct cmd_operate_attach_port_result { + cmdline_fixed_string_t port; + cmdline_fixed_string_t keyword; + cmdline_fixed_string_t identifier; +}; + +static void cmd_operate_attach_port_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_operate_attach_port_result *res = parsed_result; + + if (!strcmp(res->keyword, "attach")) + attach_port(res->identifier); + else + printf("Unknown parameter\n"); +} + +cmdline_parse_token_string_t cmd_operate_attach_port_port = + TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result, + port, "port"); +cmdline_parse_token_string_t cmd_operate_attach_port_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result, + keyword, "attach"); +cmdline_parse_token_string_t cmd_operate_attach_port_identifier = + TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result, + identifier, NULL); + +cmdline_parse_inst_t cmd_operate_attach_port = { + .f = cmd_operate_attach_port_parsed, + .data = NULL, + .help_str = "port attach identifier, " + "identifier: pci address or virtual dev name", + .tokens = { + (void *)&cmd_operate_attach_port_port, + (void *)&cmd_operate_attach_port_keyword, + (void *)&cmd_operate_attach_port_identifier, + NULL, + }, +}; + +/* *** detach a specificied port *** */ +struct cmd_operate_detach_port_result { + cmdline_fixed_string_t port; + cmdline_fixed_string_t keyword; + uint8_t port_id; +}; + +static void cmd_operate_detach_port_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_operate_detach_port_result *res = parsed_result; + + if (!strcmp(res->keyword, "detach")) + detach_port(res->port_id); + else + printf("Unknown parameter\n"); +} + +cmdline_parse_token_string_t cmd_operate_detach_port_port = + TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result, + port, "port"); +cmdline_parse_token_string_t cmd_operate_detach_port_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result, + keyword, "detach"); +cmdline_parse_token_num_t cmd_operate_detach_port_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_operate_detach_port_result, + port_id, UINT8); + +cmdline_parse_inst_t cmd_operate_detach_port = { + .f = cmd_operate_detach_port_parsed, + .data = NULL, + .help_str = "port detach port_id", + .tokens = { + (void *)&cmd_operate_detach_port_port, + (void *)&cmd_operate_detach_port_keyword, + (void *)&cmd_operate_detach_port_port_id, + NULL, + }, +}; + /* *** configure speed for all ports *** */ struct cmd_config_speed_all { cmdline_fixed_string_t port; @@ -907,7 +996,7 @@ cmd_config_speed_all_parsed(void *parsed_result, return; } - for (pid = 0; p
[dpdk-dev] [PATCH v2 02/28] ethdev: Remove assumption that port will not be detached
> -Original Message- > From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Tetsuya Mukawa > Sent: Tuesday, December 9, 2014 11:42 AM > To: dev at dpdk.org > Cc: nakajima.yoshihiro at lab.ntt.co.jp; menrigh at brocade.com; > masutani.hitoshi at lab.ntt.co.jp > Subject: [dpdk-dev] [PATCH v2 02/28] ethdev: Remove assumption that port will > not be detached > > To remove assumption, do like followings. > > - Add 'attached' member to rte_eth_dev structure. > This member is used for indicating the port is attached, or not. > - Add rte_eth_dev_allocate_new_port(). > This function is used for allocating new port. > > Signed-off-by: Tetsuya Mukawa > --- > lib/librte_ether/rte_ethdev.c | 248 > -- > lib/librte_ether/rte_ethdev.h | 5 + > 2 files changed, 149 insertions(+), 104 deletions(-) > > diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c > index > 95f2ceb..9f713ae 100644 > --- a/lib/librte_ether/rte_ethdev.c > +++ b/lib/librte_ether/rte_ethdev.c > @@ -175,6 +175,16 @@ enum { > STAT_QMAP_RX > }; > > +enum { > + DEV_VALID = 0, > + DEV_INVALID > +}; Would it be safer to define DEV_INVALID = 0, then DEV_VALID after it? Or even as below? Enum { DEV_UNKNOWN = 0, DEV_VALID, DEV_INVALID }; Regards, Helin > + > +enum { > + DEV_DISCONNECTED = 0, > + DEV_CONNECTED > +}; > + > static inline void > rte_eth_dev_data_alloc(void) > { > @@ -201,19 +211,34 @@ rte_eth_dev_allocated(const char *name) { > unsigned i; > > - for (i = 0; i < nb_ports; i++) { > - if (strcmp(rte_eth_devices[i].data->name, name) == 0) > + for (i = 0; i < RTE_MAX_ETHPORTS; i++) { > + if ((rte_eth_devices[i].attached == DEV_CONNECTED) > + && strcmp(rte_eth_devices[i].data->name, > + name) == 0) > return &rte_eth_devices[i]; > } > return NULL; > } > > +static uint8_t > +rte_eth_dev_allocate_new_port(void) > +{ > + unsigned i; > + > + for (i = 0; i < RTE_MAX_ETHPORTS; i++) > + if (rte_eth_devices[i].attached == DEV_DISCONNECTED) > + return i; > + return RTE_MAX_ETHPORTS; > +} > + > struct rte_eth_dev * > rte_eth_dev_allocate(const char *name) > { > + uint8_t port_id; > struct rte_eth_dev *eth_dev; > > - if (nb_ports == RTE_MAX_ETHPORTS) { > + port_id = rte_eth_dev_allocate_new_port(); > + if (port_id == RTE_MAX_ETHPORTS) { > PMD_DEBUG_TRACE("Reached maximum number of Ethernet > ports\n"); > return NULL; > } > @@ -226,10 +251,12 @@ rte_eth_dev_allocate(const char *name) > return NULL; > } > > - eth_dev = &rte_eth_devices[nb_ports]; > - eth_dev->data = &rte_eth_dev_data[nb_ports]; > + eth_dev = &rte_eth_devices[port_id]; > + eth_dev->data = &rte_eth_dev_data[port_id]; > snprintf(eth_dev->data->name, sizeof(eth_dev->data->name), "%s", > name); > - eth_dev->data->port_id = nb_ports++; > + eth_dev->data->port_id = port_id; > + eth_dev->attached = DEV_CONNECTED; > + nb_ports++; > return eth_dev; > } > > @@ -283,6 +310,7 @@ rte_eth_dev_init(struct rte_pci_driver *pci_drv, > (unsigned) pci_dev->id.device_id); > if (rte_eal_process_type() == RTE_PROC_PRIMARY) > rte_free(eth_dev->data->dev_private); > + eth_dev->attached = DEV_DISCONNECTED; > nb_ports--; > return diag; > } > @@ -308,10 +336,22 @@ rte_eth_driver_register(struct eth_driver *eth_drv) > rte_eal_pci_register(ð_drv->pci_drv); > } > > +static int > +rte_eth_dev_validate_port(uint8_t port_id) { > + if (port_id >= RTE_MAX_ETHPORTS) > + return DEV_INVALID; > + > + if (rte_eth_devices[port_id].attached == DEV_CONNECTED) > + return DEV_VALID; > + else > + return DEV_INVALID; > +} > + > int > rte_eth_dev_socket_id(uint8_t port_id) > { > - if (port_id >= nb_ports) > + if (rte_eth_dev_validate_port(port_id) == DEV_INVALID) > return -1; > return rte_eth_devices[port_id].pci_dev->numa_node; > } > @@ -369,7 +409,7 @@ rte_eth_dev_rx_queue_start(uint8_t port_id, uint16_t > rx_queue_id) >* in a multi-process setup*/ > PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); > > - if (port_id >= nb_ports) { > + if (rte_eth_dev_validate_port(port_id) == DEV_INVALID) { > PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); > return -EINVAL; > } > @@ -395,7 +435,7 @@ rte_eth_dev_rx_queue_stop(uint8_t port_id, uint16_t > rx_queue_id) >* in a multi-process setup*/ > PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); > > - if (port_id >= nb_ports) { > + if (rte_eth_dev_validate_port(port_id) == DEV_INVALID) { > PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); >
[dpdk-dev] [RFC PATCH 00/17] Single virtio implementation
Hi > -Original Message- > From: Qiu, Michael > Sent: Tuesday, December 9, 2014 11:23 AM > To: Ouyang, Changchun; Thomas Monjalon; Stephen Hemminger > Cc: dev at dpdk.org > Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio implementation > > On 12/9/2014 9:11 AM, Ouyang, Changchun wrote: > > Hi Thomas, > > > >> -Original Message- > >> From: Thomas Monjalon [mailto:thomas.monjalon at 6wind.com] > >> Sent: Monday, December 8, 2014 5:31 PM > >> To: Ouyang, Changchun > >> Cc: dev at dpdk.org > >> Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio > >> implementation > >> > >> Hi Changchun, > >> > >> 2014-12-08 14:21, Ouyang Changchun: > >>> This patch set bases on two original RFC patch sets from Stephen > >> Hemminger[stephen at networkplumber.org] > >>> Refer to [http://dpdk.org/ml/archives/dev/2014-August/004845.html ] > >>> for > >> the original one. > >>> This patch set also resolves some conflict with latest codes and > >>> removed > >> duplicated codes. > >> > >> As you sent the patches, you appear as the author. > >> But I guess Stephen should be the author for some of them. > >> Please check who has contributed the most in each patch to decide. > > You are right, most of patches originate from Stephen's patchset, > > except for the last one, To be honest, I am ok whoever is the author > > of this patch set, :-), We could co-own the feature of Single virtio > > if you all agree with it, and I think we couldn't finish Such a > > feature without collaboration among us, this is why I tried to communicate > with most of you to collect more feedback, suggestion and comments for this > feature. > > Very appreciate for all kinds of feedback, suggestion here, especially for > patch set from Stephen. > > > > According to your request, how could we make this patch set looks more > like Stephen as the author? > > Currently I add Stephen as Signed-off-by list in each patch(I got the > agreement from Stephen before doing this :-)). > > Hi Ouyang, > > "Signed-off-by" should be added by himself, because the one who in the > Signed-off-by list should take responsibility for it(like potential > bugs/issues). > > Although, lots of patches are originate from Stephen, we still need himself > add this line :) Hi Thomas, It that right? I can't add Stephen into Signed-off-by list even if I have gotten the agreement from Stephen, What 's the strict rule here? Thanks Changchun
[dpdk-dev] [PATCH v2] bond: fix for mac assignment to slaves device
Tested-by: Jiajia, SunX - Tested Commit: 505c3d03dc7ae8e06c68006e44fd80738a3d70a3 - OS: Fedora20 3.11.10-301.fc20.x86_64 - GCC: gcc version 4.8.3 - CPU: Intel(R) Xeon(R) CPU E5-2680 v2 @ 2.80GHz - NIC: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection [8086:10fb] - Default x86_64-native-linuxapp-gcc configuration - Total 22 cases, 22 passed, 0 failed TOPO: * Connections ports between tester/ixia and DUT - TESTER(Or IXIA)---DUT - portA--port0 - portB--port1 - portC--port2 - portD--port3 Test Setup#1 for Functional test Tester has 4 ports(portA--portD), and DUT has 4 ports(port0--port3), then connect portA to port0, portB to port1, portC to port2, portD to port3. - Case: Basic bonding--Create bonded devices and slaves Description: Use Setup#1. Create bonded device and add some ports as salve of bonded device, Then removed slaves or added slaves or change the bonding primary slave Or change bonding mode and so on. Expected test result: Verify the basic functions are normal. - Case: Basic bonding--MAC Address Test Description: Use Setup#1. Create bonded device and add some ports as slaves of bonded device, Check that the changes of the bonded device and slave MAC Expected test result: Verify the behavior of bonded device and slave according to the mode. - Case: Basic bonding--Device Promiscuous Mode Test Description: Use Setup#1. Create bonded device and add some ports as slaves of bonded device, Set promiscuous mode on or off, then send packets to the bonded device Or slaves. Expected test result: Verify the RX/TX status of bonded device and slaves according to the mode. - Case: Mode 0(Round Robin) TX/RX test Description: Use Setup#1. Create bonded device with mode 0 and add 3 ports as slaves of bonded device, Forward packets between bonded device and unbounded device, start to forward, And send packets to unbound device or slaves. Expected test result: Verify the RX/TX status of bonded device and slaves in mode 0. - Case: Mode 0(Round Robin) Bring one slave link down Description: Use Setup#1. Create bonded device with mode 0 and add 3 ports as slaves of bonded device, Forward packets between bonded device and unbounded device, start to forward, Bring the link on either port 0, 1 or 2 down. And send packets to unbound device or slaves. Expected test result: Verify the RX/TX status of bonded device and slaves in mode 0. - Case: Mode 0(Round Robin) Bring all slave links down Description: Use Setup#1. Create bonded device with mode 0 and add 3 ports as slaves of bonded device, Forward packets between bonded device and unbounded device, start to forward, Bring the links down on all bonded ports. And send packets to unbound device or slaves. Expected test result: Verify the RX/TX status of bonded device and slaves in mode 0. - Case: Mode 1(Active Backup) TX/RX Test Description: Use Setup#1. Create bonded device with mode 1 and add 3 ports as slaves of bonded device, Forward packets between bonded device and unbounded device, start to forward, And send packets to unbound device or slaves. Expected test result: Verify the RX/TX status of bonded device and slaves in mode 1. - Case: Mode 1(Active Backup) Change active slave, RX/TX test Description: Use Setup#1. Continuing from previous test case.Change the active slave port from port0 to port1.Verify that the bonded device's MAC has changed to slave1's MAC. testpmd> set bonding primary 1 4 Repeat the transmission and reception(TX/RX) test verify that data is now transmitted and received through the new active slave and no longer through port0 Expected test result: Verify the RX/TX status of bonded device and slaves in mode 1. - Case: Mode 1(Active Backup) Link up/down active eth dev Description: Use Setup#1. Bring link between port A and port0 down. If tester is ixia, can use IxExplorer to set the "Simulate Cable Disconnect" at the port property. Verify that the active slave has been changed from port0. Repeat the transmission and reception test verify that data is now transmitted and received through the new active slave and no longer through port0 Bring port0 to link down at the remote
[dpdk-dev] [PATCH v2 02/28] ethdev: Remove assumption that port will not be detached
Hi Zhang, Thanks to your comment. I will submit again soon. Thanks, Tetsuya (2014/12/09 14:07), Zhang, Helin wrote: > >> -Original Message- >> From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Tetsuya Mukawa >> Sent: Tuesday, December 9, 2014 11:42 AM >> To: dev at dpdk.org >> Cc: nakajima.yoshihiro at lab.ntt.co.jp; menrigh at brocade.com; >> masutani.hitoshi at lab.ntt.co.jp >> Subject: [dpdk-dev] [PATCH v2 02/28] ethdev: Remove assumption that port will >> not be detached >> >> To remove assumption, do like followings. >> >> - Add 'attached' member to rte_eth_dev structure. >> This member is used for indicating the port is attached, or not. >> - Add rte_eth_dev_allocate_new_port(). >> This function is used for allocating new port. >> >> Signed-off-by: Tetsuya Mukawa >> --- >> lib/librte_ether/rte_ethdev.c | 248 >> -- >> lib/librte_ether/rte_ethdev.h | 5 + >> 2 files changed, 149 insertions(+), 104 deletions(-) >> >> diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c >> index >> 95f2ceb..9f713ae 100644 >> --- a/lib/librte_ether/rte_ethdev.c >> +++ b/lib/librte_ether/rte_ethdev.c >> @@ -175,6 +175,16 @@ enum { >> STAT_QMAP_RX >> }; >> >> +enum { >> +DEV_VALID = 0, >> +DEV_INVALID >> +}; > Would it be safer to define DEV_INVALID = 0, then DEV_VALID after it? > Or even as below? > Enum { > DEV_UNKNOWN = 0, > DEV_VALID, > DEV_INVALID > }; > > Regards, > Helin > >> + >> +enum { >> +DEV_DISCONNECTED = 0, >> +DEV_CONNECTED >> +}; >> + >> static inline void >> rte_eth_dev_data_alloc(void) >> { >> @@ -201,19 +211,34 @@ rte_eth_dev_allocated(const char *name) { >> unsigned i; >> >> -for (i = 0; i < nb_ports; i++) { >> -if (strcmp(rte_eth_devices[i].data->name, name) == 0) >> +for (i = 0; i < RTE_MAX_ETHPORTS; i++) { >> +if ((rte_eth_devices[i].attached == DEV_CONNECTED) >> +&& strcmp(rte_eth_devices[i].data->name, >> +name) == 0) >> return &rte_eth_devices[i]; >> } >> return NULL; >> } >> >> +static uint8_t >> +rte_eth_dev_allocate_new_port(void) >> +{ >> +unsigned i; >> + >> +for (i = 0; i < RTE_MAX_ETHPORTS; i++) >> +if (rte_eth_devices[i].attached == DEV_DISCONNECTED) >> +return i; >> +return RTE_MAX_ETHPORTS; >> +} >> + >> struct rte_eth_dev * >> rte_eth_dev_allocate(const char *name) >> { >> +uint8_t port_id; >> struct rte_eth_dev *eth_dev; >> >> -if (nb_ports == RTE_MAX_ETHPORTS) { >> +port_id = rte_eth_dev_allocate_new_port(); >> +if (port_id == RTE_MAX_ETHPORTS) { >> PMD_DEBUG_TRACE("Reached maximum number of Ethernet >> ports\n"); >> return NULL; >> } >> @@ -226,10 +251,12 @@ rte_eth_dev_allocate(const char *name) >> return NULL; >> } >> >> -eth_dev = &rte_eth_devices[nb_ports]; >> -eth_dev->data = &rte_eth_dev_data[nb_ports]; >> +eth_dev = &rte_eth_devices[port_id]; >> +eth_dev->data = &rte_eth_dev_data[port_id]; >> snprintf(eth_dev->data->name, sizeof(eth_dev->data->name), "%s", >> name); >> -eth_dev->data->port_id = nb_ports++; >> +eth_dev->data->port_id = port_id; >> +eth_dev->attached = DEV_CONNECTED; >> +nb_ports++; >> return eth_dev; >> } >> >> @@ -283,6 +310,7 @@ rte_eth_dev_init(struct rte_pci_driver *pci_drv, >> (unsigned) pci_dev->id.device_id); >> if (rte_eal_process_type() == RTE_PROC_PRIMARY) >> rte_free(eth_dev->data->dev_private); >> +eth_dev->attached = DEV_DISCONNECTED; >> nb_ports--; >> return diag; >> } >> @@ -308,10 +336,22 @@ rte_eth_driver_register(struct eth_driver *eth_drv) >> rte_eal_pci_register(ð_drv->pci_drv); >> } >> >> +static int >> +rte_eth_dev_validate_port(uint8_t port_id) { >> +if (port_id >= RTE_MAX_ETHPORTS) >> +return DEV_INVALID; >> + >> +if (rte_eth_devices[port_id].attached == DEV_CONNECTED) >> +return DEV_VALID; >> +else >> +return DEV_INVALID; >> +} >> + >> int >> rte_eth_dev_socket_id(uint8_t port_id) >> { >> -if (port_id >= nb_ports) >> +if (rte_eth_dev_validate_port(port_id) == DEV_INVALID) >> return -1; >> return rte_eth_devices[port_id].pci_dev->numa_node; >> } >> @@ -369,7 +409,7 @@ rte_eth_dev_rx_queue_start(uint8_t port_id, uint16_t >> rx_queue_id) >> * in a multi-process setup*/ >> PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); >> >> -if (port_id >= nb_ports) { >> +if (rte_eth_dev_validate_port(port_id) == DEV_INVALID) { >> PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); >> return -EINVAL; >> } >> @@ -395,7 +435,7 @@ rte_eth_dev_rx_queue_stop(uint8_t port_id, uint16_t >> rx_queue_id) >> * in a multi-process setup*/ >> PROC_PRIMARY_OR_ERR_
[dpdk-dev] [RFC PATCH 00/17] Single virtio implementation
2014-12-09 05:41, Ouyang, Changchun: > Hi > > > -Original Message- > > From: Qiu, Michael > > Sent: Tuesday, December 9, 2014 11:23 AM > > To: Ouyang, Changchun; Thomas Monjalon; Stephen Hemminger > > Cc: dev at dpdk.org > > Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio implementation > > > > On 12/9/2014 9:11 AM, Ouyang, Changchun wrote: > > > Hi Thomas, > > > > > >> -Original Message- > > >> From: Thomas Monjalon [mailto:thomas.monjalon at 6wind.com] > > >> Sent: Monday, December 8, 2014 5:31 PM > > >> To: Ouyang, Changchun > > >> Cc: dev at dpdk.org > > >> Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio > > >> implementation > > >> > > >> Hi Changchun, > > >> > > >> 2014-12-08 14:21, Ouyang Changchun: > > >>> This patch set bases on two original RFC patch sets from Stephen > > >> Hemminger[stephen at networkplumber.org] > > >>> Refer to [http://dpdk.org/ml/archives/dev/2014-August/004845.html ] > > >>> for > > >> the original one. > > >>> This patch set also resolves some conflict with latest codes and > > >>> removed > > >> duplicated codes. > > >> > > >> As you sent the patches, you appear as the author. > > >> But I guess Stephen should be the author for some of them. > > >> Please check who has contributed the most in each patch to decide. > > > You are right, most of patches originate from Stephen's patchset, > > > except for the last one, To be honest, I am ok whoever is the author > > > of this patch set, :-), We could co-own the feature of Single virtio > > > if you all agree with it, and I think we couldn't finish Such a > > > feature without collaboration among us, this is why I tried to communicate > > with most of you to collect more feedback, suggestion and comments for this > > feature. > > > Very appreciate for all kinds of feedback, suggestion here, especially for > > patch set from Stephen. > > > > > > According to your request, how could we make this patch set looks more > > like Stephen as the author? > > > Currently I add Stephen as Signed-off-by list in each patch(I got the > > agreement from Stephen before doing this :-)). > > > > Hi Ouyang, > > > > "Signed-off-by" should be added by himself, because the one who in the > > Signed-off-by list should take responsibility for it(like potential > > bugs/issues). > > > > Although, lots of patches are originate from Stephen, we still need himself > > add this line :) > > Hi Thomas, > It that right? I can't add Stephen into Signed-off-by list even if I have > gotten the agreement from Stephen, > What 's the strict rule here? Stephen sent the patches with his Signed-off, then you added yours. This is OK. Using git am, author would have been Stephen. To change author now, you can edit each commit with interactive rebase and "git commit --amend --author=Stephen". No need to resend now. Please check it for next version of the patchset. -- Thomas
[dpdk-dev] [PATCH v3] mbuf: fix of enabling all newly added RX error flags
2014-12-09 02:14, Zhang, Helin: > From: Thomas Monjalon [mailto:thomas.monjalon at 6wind.com] > > 2014-12-06 09:33, Helin Zhang: > > > Before redefining mbuf structure, there was lack of free bits in > > > 'ol_flags' > > > (32 bits in total) for new RX or TX flags. So it tried to reuse > > > existant bits as most as possible, or even assigning 0 to some of bit > > > flags. After new mbuf structure defined, there are quite a lot of free > > > bits. So those newly added bit flags should be assigned with correct > > > and valid bit values, and getting their names should be enabled as > > > well. Note that 'RECIP' should be removed, as nowhere will use it. > > > 'PKT_RX_ERR' is defined to replace all other error bit flags, e.g. MAC > > > error, Oversize error, header buffer overflow error. > > > > > > Signed-off-by: Helin Zhang > > [...] > > > --- a/lib/librte_mbuf/rte_mbuf.h > > > +++ b/lib/librte_mbuf/rte_mbuf.h > > > @@ -84,11 +84,6 @@ extern "C" { > > > #define PKT_RX_FDIR (1ULL << 2) /**< RX packet with FDIR > > match indicate. */ > > > #define PKT_RX_L4_CKSUM_BAD (1ULL << 3) /**< L4 cksum of RX pkt. > > is > > > not OK. */ #define PKT_RX_IP_CKSUM_BAD (1ULL << 4) /**< IP cksum > > of > > > RX pkt. is not OK. */ -#define PKT_RX_EIP_CKSUM_BAD (0ULL << 0) /**< > > External IP header checksum error. */ > > > -#define PKT_RX_OVERSIZE (0ULL << 0) /**< Num of desc of an RX > > pkt oversize. */ > > > -#define PKT_RX_HBUF_OVERFLOW (0ULL << 0) /**< Header buffer > > overflow. */ > > > -#define PKT_RX_RECIP_ERR (0ULL << 0) /**< Hardware processing > > error. */ > > > -#define PKT_RX_MAC_ERR (0ULL << 0) /**< MAC error. */ > > > #define PKT_RX_IPV4_HDR (1ULL << 5) /**< RX packet with IPv4 > > header. */ > > > #define PKT_RX_IPV4_HDR_EXT (1ULL << 6) /**< RX packet with > > extended IPv4 header. */ > > > #define PKT_RX_IPV6_HDR (1ULL << 7) /**< RX packet with IPv6 > > header. */ > > > @@ -99,6 +94,8 @@ extern "C" { > > > #define PKT_RX_TUNNEL_IPV6_HDR (1ULL << 12) /**< RX tunnel packet > > with IPv6 header. */ > > > #define PKT_RX_FDIR_ID (1ULL << 13) /**< FD id reported if FDIR > > match. */ > > > #define PKT_RX_FDIR_FLX (1ULL << 14) /**< Flexible bytes reported > > if FDIR match. */ > > > +#define PKT_RX_EIP_CKSUM_BAD (1ULL << 15) /**< External IP header > > > +checksum error. */ > > > > Could PKT_RX_EIP_CKSUM_BAD be aggregated with > > PKT_RX_IP_CKSUM_BAD? > > I tend to say no, but I would listen to comments from others. > For tunneling case (e.g. IP over IP), it is a bit similar to the case of > L3/L4 (e.g. UDP over IP). > For L3/L4 case, we have PKT_RX_IP_CKSUM_BAD and PKT_RX_L4_CKSUM_BAD to > indicate the checksum error is in L3 or L4. > So I'd prefer to have PKT_RX_IP_CKSUM_BAD and PKT_RX_EIP_CKSUM_BAD to indicate > the checksum error is in outer or inner header. I think OUTER_IP would be more consistent than EIP. > Otherwise we have no chance to know where the checksum error is, based on > mbuf. > > > The conclusion is the same: the packet is corrupted. > > And some hardwares could not detect the encapsulation and use > > PKT_RX_IP_CKSUM_BAD. > > If the hardware don't know it is a tunneling packet, it will just treat it as > an IP packet. But if > hardware supports tunneling, it would be better for apps to know that more > about the > packet which can be offloaded by hardware. > > > > > Another interesting improvement would be to have PKT_RX_IP_CKSUM_OK. > > I think we'll have to think about this kind of flag for next version. > > For checksum OK, if no 'BAD' indicated, we can assume it is OK. Any other > hints from you? No, having no BAD can indicate also that it hasn't been checked (i.e. check not enabled or not supported). > > Note that this patch is an API change and shouldn't be applied for 1.8.0. > > But we can do an exception as it has no impact on existing applications and > > fixes the 0 flags. > Agree with you! > > Thank you very much for thinking so much about this! > > Regards, > Helin -- Thomas
[dpdk-dev] [PATCH v3 00/28] Port Hotplug Framework
This patch series adds a dynamic port hotplug framework to DPDK. With the patches, DPDK apps can attach or detach ports at runtime. The basic concept of the port hotplug is like followings. - DPDK apps must have responsibility to manage ports. DPDK apps only know which ports are attached or detached at the moment. The port hotplug framework is implemented to allow DPDK apps to manage ports. For example, when DPDK apps call port attach function, attached port number will be returned. Also DPDK apps can detach port by port number. - Kernel support is needed for attaching or detaching physical device ports. To attach new device, the device will be recognized by kernel at first and controlled by kernel driver. Then user can bind the device to igb_uio by 'dpdk_nic_bind.py'. Finally, DPDK apps can call the port hotplug functions to attach ports. For detaching, steps are vice versa. - Before detach ports, ports must be stopped and closed. DPDK application must call rte_eth_dev_stop() and rte_eth_dev_close() before detaching ports. These function will call finalization codes of PMDs. But so far, no PMD frees all resources allocated by initialization. It means PMDs are needed to be fixed to support the port hotplug. 'RTE_PCI_DRV_DETACHABLE' is a new flag indicating a PMD supports detaching. Without this flag, detaching will be failed. - Mustn't affect legacy DPDK apps. No DPDK EAL behavior is changed, if the port hotplug functions are't called. So all legacy DPDK apps can still work without modifications. And a few limitations. - The port hotplug functions are not thread safe. DPDK apps should handle it. - Only support Linux and igb_uio so far. BSD and VFIO is not supported. I will send VFIO patches at least, but I don't have a plan to submit BSD patch so far. Here is port hotplug APIs. --- /** * Attach a new device. * * @param devargs * A pointer to a strings array describing the new device * to be attached. The strings should be a pci address like * ':01:00.0' or virtual device name like 'eth_pcap0'. * @param port_id * A pointer to a port identifier actually attached. * @return * 0 on success and port_id is filled, negative on error */ int rte_eal_dev_attach(const char *devargs, uint8_t *port_id); /** * Detach a device. * * @param port_id * The port identifier of the device to detach. * @param addr * A pointer to a device name actually detached. * @return * 0 on success and devname is filled, negative on error */ int rte_eal_dev_detach(uint8_t port_id, char *devname); --- This patch series are for DPDK EAL. To use port hotplug function by DPDK apps, each PMD should be fixed to support 'RTE_PCI_DRV_DETACHABLE' flag. Please check a patch for pcap PMD. Also please check testpmd patch. It will show you how to fix your legacy applications to support port hotplug feature. PATCH v3 chages: - Fix enum definition used in rte_ethdev.c. (Thanks to Zhang, Helin) PATCH v2 chages: - Replace rte_eal_dev_attach_pdev(), rte_eal_dev_detach_pdev, rte_eal_dev_attach_vdev() and rte_eal_dev_detach_vdev() to rte_eal_dev_attach() and rte_eal_dev_detach(). - Add parameter values checking. - Refashion a few functions. (Thanks to Iremonger, Bernard) PATCH v1 Chages: - Fix error checking code of librte_eth APIs. - Fix issue that port from pcap PMD cannot be detached correctly. - Fix issue that testpmd could hang after forwarding, if attaching and detaching is repeatedly. - Fix if-condition of rte_eth_dev_get_port_by_addr(). (Thanks to Mark Enright) RFC PATCH v2 Changes: - remove 'rte_eth_dev_validate_port()', and cleanup codes. Tetsuya Mukawa (28): eal/pci: Add a new flag indicating a driver can detach devices at runtime. ethdev: Remove assumption that port will not be detached eal/pci: Replace pci address comparison code by eal_compare_pci_addr ethdev: Add rte_eth_dev_free to free specified device eal,ethdev: Add function pointer for closing a device ethdev: Add rte_eth_dev_shutdown for closing PCI devices. ethdev: Add functions to know which port is attached or detached ethdev: Add rte_eth_dev_get_addr_by_port ethdev: Add rte_eth_dev_get_port_by_addr ethdev: Add rte_eth_dev_get_name_by_port ethdev: Add rte_eth_dev_check_detachable ethdev: Change scope of rte_eth_dev_allocated to global eal/pci: Prevent double registration for devargs_list eal/pci: Add rte_eal_devargs_remove eal/pci: Add probe and close function for virtual drivers eal/pci: Add port hotplug functions for virtual devices. eal/linux/pci: Add functions for unmapping igb_uio resources eal/pci: Prevent double registrations for pci_device_list eal/pci: Change scope of rte_eal_pci_scan to global eal/pci: Add rte_eal_pci_close_one_driver eal/pci: Fix pci_probe_all_drivers
[dpdk-dev] [PATCH v3 01/28] eal/pci: Add a new flag indicating a driver can detach devices at runtime.
This patch adds "RTE_PCI_DRV_DETACHABLE" to drv_flags of rte_pci_driver structure. The flags indicates the driver can detach devices at runtime. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/include/rte_pci.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index 66ed793..b819539 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -199,6 +199,8 @@ struct rte_pci_driver { #define RTE_PCI_DRV_FORCE_UNBIND 0x0004 /** Device driver supports link state interrupt */ #define RTE_PCI_DRV_INTR_LSC 0x0008 +/** Device driver supports detaching capablity */ +#define RTE_PCI_DRV_DETACHABLE 0x0010 /**< Internal use only - Macro used by pci addr parsing functions **/ #define GET_PCIADDR_FIELD(in, fd, lim, dlm) \ -- 1.9.1
[dpdk-dev] [PATCH v3 02/28] ethdev: Remove assumption that port will not be detached
To remove assumption, do like followings. - Add 'attached' member to rte_eth_dev structure. This member is used for indicating the port is attached, or not. - Add rte_eth_dev_allocate_new_port(). This function is used for allocating new port. Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 248 -- lib/librte_ether/rte_ethdev.h | 5 + 2 files changed, 149 insertions(+), 104 deletions(-) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 95f2ceb..9f713ae 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -175,6 +175,16 @@ enum { STAT_QMAP_RX }; +enum { + DEV_VALID = 0, + DEV_INVALID +}; + +enum { + DEV_DISCONNECTED = 0, + DEV_CONNECTED +}; + static inline void rte_eth_dev_data_alloc(void) { @@ -201,19 +211,34 @@ rte_eth_dev_allocated(const char *name) { unsigned i; - for (i = 0; i < nb_ports; i++) { - if (strcmp(rte_eth_devices[i].data->name, name) == 0) + for (i = 0; i < RTE_MAX_ETHPORTS; i++) { + if ((rte_eth_devices[i].attached == DEV_CONNECTED) + && strcmp(rte_eth_devices[i].data->name, + name) == 0) return &rte_eth_devices[i]; } return NULL; } +static uint8_t +rte_eth_dev_allocate_new_port(void) +{ + unsigned i; + + for (i = 0; i < RTE_MAX_ETHPORTS; i++) + if (rte_eth_devices[i].attached == DEV_DISCONNECTED) + return i; + return RTE_MAX_ETHPORTS; +} + struct rte_eth_dev * rte_eth_dev_allocate(const char *name) { + uint8_t port_id; struct rte_eth_dev *eth_dev; - if (nb_ports == RTE_MAX_ETHPORTS) { + port_id = rte_eth_dev_allocate_new_port(); + if (port_id == RTE_MAX_ETHPORTS) { PMD_DEBUG_TRACE("Reached maximum number of Ethernet ports\n"); return NULL; } @@ -226,10 +251,12 @@ rte_eth_dev_allocate(const char *name) return NULL; } - eth_dev = &rte_eth_devices[nb_ports]; - eth_dev->data = &rte_eth_dev_data[nb_ports]; + eth_dev = &rte_eth_devices[port_id]; + eth_dev->data = &rte_eth_dev_data[port_id]; snprintf(eth_dev->data->name, sizeof(eth_dev->data->name), "%s", name); - eth_dev->data->port_id = nb_ports++; + eth_dev->data->port_id = port_id; + eth_dev->attached = DEV_CONNECTED; + nb_ports++; return eth_dev; } @@ -283,6 +310,7 @@ rte_eth_dev_init(struct rte_pci_driver *pci_drv, (unsigned) pci_dev->id.device_id); if (rte_eal_process_type() == RTE_PROC_PRIMARY) rte_free(eth_dev->data->dev_private); + eth_dev->attached = DEV_DISCONNECTED; nb_ports--; return diag; } @@ -308,10 +336,22 @@ rte_eth_driver_register(struct eth_driver *eth_drv) rte_eal_pci_register(ð_drv->pci_drv); } +static int +rte_eth_dev_validate_port(uint8_t port_id) +{ + if (port_id >= RTE_MAX_ETHPORTS) + return DEV_INVALID; + + if (rte_eth_devices[port_id].attached == DEV_CONNECTED) + return DEV_VALID; + else + return DEV_INVALID; +} + int rte_eth_dev_socket_id(uint8_t port_id) { - if (port_id >= nb_ports) + if (rte_eth_dev_validate_port(port_id) == DEV_INVALID) return -1; return rte_eth_devices[port_id].pci_dev->numa_node; } @@ -369,7 +409,7 @@ rte_eth_dev_rx_queue_start(uint8_t port_id, uint16_t rx_queue_id) * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); - if (port_id >= nb_ports) { + if (rte_eth_dev_validate_port(port_id) == DEV_INVALID) { PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); return -EINVAL; } @@ -395,7 +435,7 @@ rte_eth_dev_rx_queue_stop(uint8_t port_id, uint16_t rx_queue_id) * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); - if (port_id >= nb_ports) { + if (rte_eth_dev_validate_port(port_id) == DEV_INVALID) { PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); return -EINVAL; } @@ -421,7 +461,7 @@ rte_eth_dev_tx_queue_start(uint8_t port_id, uint16_t tx_queue_id) * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); - if (port_id >= nb_ports) { + if (rte_eth_dev_validate_port(port_id) == DEV_INVALID) { PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); return -EINVAL; } @@ -447,7 +487,7 @@ rte_eth_dev_tx_queue_stop(uint8_t port_id, uint16_t tx_queue_id) * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); - if (port_id >= nb_ports) { + if (rte_eth_dev_validate_port(port_id) == DEV_INVALID)
[dpdk-dev] [PATCH v3 03/28] eal/pci: Replace pci address comparison code by eal_compare_pci_addr
This patch replaces pci_addr_comparison() and memcmp() of pci addresses by eal_compare_pci_addr(). Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/bsdapp/eal/eal_pci.c | 16 +--- lib/librte_eal/common/eal_common_pci.c| 2 +- lib/librte_eal/common/include/rte_pci.h | 29 + lib/librte_eal/linuxapp/eal/eal_pci.c | 16 +--- lib/librte_eal/linuxapp/eal/eal_pci_uio.c | 2 +- 5 files changed, 33 insertions(+), 32 deletions(-) diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c index 74ecce7..7eda513 100644 --- a/lib/librte_eal/bsdapp/eal/eal_pci.c +++ b/lib/librte_eal/bsdapp/eal/eal_pci.c @@ -270,20 +270,6 @@ pci_uio_map_resource(struct rte_pci_device *dev) return (0); } -/* Compare two PCI device addresses. */ -static int -pci_addr_comparison(struct rte_pci_addr *addr, struct rte_pci_addr *addr2) -{ - uint64_t dev_addr = (addr->domain << 24) + (addr->bus << 16) + (addr->devid << 8) + addr->function; - uint64_t dev_addr2 = (addr2->domain << 24) + (addr2->bus << 16) + (addr2->devid << 8) + addr2->function; - - if (dev_addr > dev_addr2) - return 1; - else - return 0; -} - - /* Scan one pci sysfs entry, and fill the devices list from it. */ static int pci_scan_one(int dev_pci_fd, struct pci_conf *conf) @@ -358,7 +344,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf) struct rte_pci_device *dev2 = NULL; TAILQ_FOREACH(dev2, &pci_device_list, next) { - if (pci_addr_comparison(&dev->addr, &dev2->addr)) + if (eal_compare_pci_addr(&dev->addr, &dev2->addr)) continue; else { TAILQ_INSERT_BEFORE(dev2, dev, next); diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c index f3c7f71..f01f258 100644 --- a/lib/librte_eal/common/eal_common_pci.c +++ b/lib/librte_eal/common/eal_common_pci.c @@ -93,7 +93,7 @@ static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev) if (devargs->type != RTE_DEVTYPE_BLACKLISTED_PCI && devargs->type != RTE_DEVTYPE_WHITELISTED_PCI) continue; - if (!memcmp(&dev->addr, &devargs->pci.addr, sizeof(dev->addr))) + if (eal_compare_pci_addr(&dev->addr, &devargs->pci.addr)) return devargs; } return NULL; diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index b819539..fe374a8 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -261,6 +261,35 @@ eal_parse_pci_DomBDF(const char *input, struct rte_pci_addr *dev_addr) } #undef GET_PCIADDR_FIELD +/* Compare two PCI device addresses. */ +/** + * Utility function to compare two PCI device addresses. + * + * @param addr + * The PCI Bus-Device-Function address to compare + * @param addr2 + * The PCI Bus-Device-Function address to compare + * @return + * 0 on equal PCI address. + * Positive on addr is greater than addr2. + * Negative on addr is less than addr2. + */ +static inline int +eal_compare_pci_addr(struct rte_pci_addr *addr, struct rte_pci_addr *addr2) +{ + uint64_t dev_addr = (addr->domain << 24) + (addr->bus << 16) + + (addr->devid << 8) + addr->function; + uint64_t dev_addr2 = (addr2->domain << 24) + (addr2->bus << 16) + + (addr2->devid << 8) + addr2->function; + + if (dev_addr > dev_addr2) + return 1; + else if (dev_addr < dev_addr2) + return -1; + else + return 0; +} + /** * Probe the PCI bus for registered drivers. * diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index b5f5410..23a69e9 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -200,20 +200,6 @@ error: return -1; } -/* Compare two PCI device addresses. */ -static int -pci_addr_comparison(struct rte_pci_addr *addr, struct rte_pci_addr *addr2) -{ - uint64_t dev_addr = (addr->domain << 24) + (addr->bus << 16) + (addr->devid << 8) + addr->function; - uint64_t dev_addr2 = (addr2->domain << 24) + (addr2->bus << 16) + (addr2->devid << 8) + addr2->function; - - if (dev_addr > dev_addr2) - return 1; - else - return 0; -} - - /* Scan one pci sysfs entry, and fill the devices list from it. */ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, @@ -306,7 +292,7 @@ pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, struct rte_pci_device *dev2 = NULL; TAILQ_FOREACH(dev2, &pci_device_list, next) { -
[dpdk-dev] [PATCH v3 04/28] ethdev: Add rte_eth_dev_free to free specified device
This patch adds rte_eth_dev_free(). The function is used for changing a attached status of the device that has specified name. Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 17 + lib/librte_ether/rte_ethdev.h | 11 +++ 2 files changed, 28 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 9f713ae..d5fdb03 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -260,6 +260,23 @@ rte_eth_dev_allocate(const char *name) return eth_dev; } +struct rte_eth_dev * +rte_eth_dev_free(const char *name) +{ + struct rte_eth_dev *eth_dev; + + eth_dev = rte_eth_dev_allocated(name); + if (eth_dev == NULL) { + PMD_DEBUG_TRACE("Ethernet Device with name %s doesn't exist!\n", + name); + return NULL; + } + + eth_dev->attached = 0; + nb_ports--; + return eth_dev; +} + static int rte_eth_dev_init(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 257de86..fb1caea 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1653,6 +1653,17 @@ extern uint8_t rte_eth_dev_count(void); */ struct rte_eth_dev *rte_eth_dev_allocate(const char *name); +/** + * Function for internal use by dummy drivers primarily, e.g. ring-based + * driver. + * Free the specified ethdev and returns the pointer to that slot. + * + * @param nameUnique identifier name for each Ethernet device + * @return + * - Slot in the rte_dev_devices array for the freed device; + */ +struct rte_eth_dev *rte_eth_dev_free(const char *name); + struct eth_driver; /** * @internal -- 1.9.1
[dpdk-dev] [PATCH v3 05/28] eal, ethdev: Add function pointer for closing a device
The patch adds function pointer to rte_pci_driver and eth_driver structure. These function pointers are used when ports are detached. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/include/rte_pci.h | 7 +++ lib/librte_ether/rte_ethdev.h | 24 2 files changed, 31 insertions(+) diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index fe374a8..74720d1 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -181,12 +181,19 @@ struct rte_pci_driver; typedef int (pci_devinit_t)(struct rte_pci_driver *, struct rte_pci_device *); /** + * Shutdown function for the driver called during hotplugging. + */ +typedef int (pci_devshutdown_t)( + struct rte_pci_driver *, struct rte_pci_device *); + +/** * A structure describing a PCI driver. */ struct rte_pci_driver { TAILQ_ENTRY(rte_pci_driver) next; /**< Next in list. */ const char *name; /**< Driver name. */ pci_devinit_t *devinit; /**< Device init. function. */ + pci_devshutdown_t *devshutdown; /**< Device shutdown function. */ struct rte_pci_id *id_table;/**< ID table, NULL terminated. */ uint32_t drv_flags; /**< Flags contolling handling of device. */ }; diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index fb1caea..b329e11 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1702,6 +1702,27 @@ typedef int (*eth_dev_init_t)(struct eth_driver *eth_drv, /** * @internal + * Finalization function of an Ethernet driver invoked for each matching + * Ethernet PCI device detected during the PCI closing phase. + * + * @param eth_drv + * The pointer to the [matching] Ethernet driver structure supplied by + * the PMD when it registered itself. + * @param eth_dev + * The *eth_dev* pointer is the address of the *rte_eth_dev* structure + * associated with the matching device and which have been [automatically] + * allocated in the *rte_eth_devices* array. + * @return + * - 0: Success, the device is properly finalized by the driver. + *In particular, the driver MUST free the *dev_ops* pointer + *of the *eth_dev* structure. + * - <0: Error code of the device initialization failure. + */ +typedef int (*eth_dev_shutdown_t)(struct eth_driver *eth_drv, + struct rte_eth_dev *eth_dev); + +/** + * @internal * The structure associated with a PMD Ethernet driver. * * Each Ethernet driver acts as a PCI driver and is represented by a generic @@ -1711,11 +1732,14 @@ typedef int (*eth_dev_init_t)(struct eth_driver *eth_drv, * * - The *eth_dev_init* function invoked for each matching PCI device. * + * - The *eth_dev_shutdown* function invoked for each matching PCI device. + * * - The size of the private data to allocate for each matching device. */ struct eth_driver { struct rte_pci_driver pci_drv;/**< The PMD is also a PCI driver. */ eth_dev_init_t eth_dev_init; /**< Device init function. */ + eth_dev_shutdown_t eth_dev_shutdown;/**< Device shutdown function. */ unsigned int dev_private_size;/**< Size of device private data. */ }; -- 1.9.1
[dpdk-dev] [PATCH v3 06/28] ethdev: Add rte_eth_dev_shutdown for closing PCI devices.
rte_eth_dev_shutdown() is called when PCI device is closed. Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 37 + 1 file changed, 37 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index d5fdb03..51697e1 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -332,6 +332,42 @@ rte_eth_dev_init(struct rte_pci_driver *pci_drv, return diag; } +static int +rte_eth_dev_shutdown(struct rte_pci_driver *pci_drv, +struct rte_pci_device *pci_dev) +{ + struct eth_driver *eth_drv; + struct rte_eth_dev *eth_dev; + char ethdev_name[RTE_ETH_NAME_MAX_LEN]; + + /* Create unique Ethernet device name using PCI address */ + snprintf(ethdev_name, RTE_ETH_NAME_MAX_LEN, "%d:%d.%d", + pci_dev->addr.bus, pci_dev->addr.devid, + pci_dev->addr.function); + + eth_dev = rte_eth_dev_free(ethdev_name); + if (eth_dev == NULL) + return -ENODEV; + + eth_drv = (struct eth_driver *)pci_drv; + + /* Invoke PMD device shutdown function */ + if (*eth_drv->eth_dev_shutdown) + (*eth_drv->eth_dev_shutdown)(eth_drv, eth_dev); + + /* init user callbacks */ + TAILQ_INIT(&(eth_dev->callbacks)); + + if (rte_eal_process_type() == RTE_PROC_PRIMARY) + rte_free(eth_dev->data->dev_private); + + eth_dev->pci_dev = NULL; + eth_dev->driver = NULL; + eth_dev->data = NULL; + + return 0; +} + /** * Register an Ethernet [Poll Mode] driver. * @@ -350,6 +386,7 @@ void rte_eth_driver_register(struct eth_driver *eth_drv) { eth_drv->pci_drv.devinit = rte_eth_dev_init; + eth_drv->pci_drv.devshutdown = rte_eth_dev_shutdown; rte_eal_pci_register(ð_drv->pci_drv); } -- 1.9.1
[dpdk-dev] [PATCH v3 07/28] ethdev: Add functions to know which port is attached or detached
The patch adds rte_eth_dev_save() and rte_eth_dev_get_changed_port(). rte_eth_dev_save() is used for saving current rte_eth_dev structures. rte_eth_dev_get_changed_port() receives the rte_eth_dev structures, then compare these with current values to know which port is actually attached or detached. Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 21 + lib/librte_ether/rte_ethdev.h | 21 + 2 files changed, 42 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 51697e1..6a3700e 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -416,6 +416,27 @@ rte_eth_dev_count(void) return (nb_ports); } +void +rte_eth_dev_save(struct rte_eth_dev *devs) +{ + if (devs == NULL) + return; + + /* save current rte_eth_devices */ + memcpy(devs, rte_eth_devices, + sizeof(struct rte_eth_dev) * RTE_MAX_ETHPORTS); +} + +int +rte_eth_dev_get_changed_port(struct rte_eth_dev *devs, uint8_t *port_id) +{ + /* check which port was attached or detached */ + for (*port_id = 0; *port_id < RTE_MAX_ETHPORTS; (*port_id)++, devs++) + if (rte_eth_devices[*port_id].attached ^ devs->attached) + return 0; + return 1; +} + static int rte_eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) { diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index b329e11..03c8850 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1642,6 +1642,27 @@ extern struct rte_eth_dev rte_eth_devices[]; extern uint8_t rte_eth_dev_count(void); /** + * Function for internal use by port hotplug functions. + * Copies current ethdev structures to the specified pointer. + * + * @param devsThe pointer to the ethdev structures + */ +extern void rte_eth_dev_save(struct rte_eth_dev *devs); + +/** + * Function for internal use by port hotplug functions. + * Compare the specified ethdev structures with currents. Then + * if there is a port which status is changed, fill the specified pointer + * with the port id of that port. + * @param devsThe pointer to the ethdev structures + * @param port_id The pointer to the port id + * @return + * - 0 on success, negative on error + */ +extern int rte_eth_dev_get_changed_port( + struct rte_eth_dev *devs, uint8_t *port_id); + +/** * Function for internal use by dummy drivers primarily, e.g. ring-based * driver. * Allocates a new ethdev slot for an ethernet device and returns the pointer -- 1.9.1
[dpdk-dev] [PATCH v3 08/28] ethdev: Add rte_eth_dev_get_addr_by_port
The function returns a pci address of a ethdev specified by port identifier. Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 17 + lib/librte_ether/rte_ethdev.h | 13 + 2 files changed, 30 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 6a3700e..ddaf14a 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -437,6 +437,23 @@ rte_eth_dev_get_changed_port(struct rte_eth_dev *devs, uint8_t *port_id) return 1; } +int +rte_eth_dev_get_addr_by_port(uint8_t port_id, struct rte_pci_addr *addr) +{ + if (rte_eth_dev_validate_port(port_id) == DEV_INVALID) { + PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); + return -EINVAL; + } + + if (addr == NULL) { + PMD_DEBUG_TRACE("Null pointer is specified\n"); + return -EINVAL; + } + + *addr = rte_eth_devices[port_id].pci_dev->addr; + return 0; +} + static int rte_eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) { diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 03c8850..30277a2 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1663,6 +1663,19 @@ extern int rte_eth_dev_get_changed_port( struct rte_eth_dev *devs, uint8_t *port_id); /** + * Function for internal use by port hotplug functions. + * Returns a pci address of a ethdev specified by port identifier. + * @param port_id + * The port identifier of the Ethernet device + * @param addr + * The pointer to the pci address + * @return + * - 0 on success, negative on error + */ +extern int rte_eth_dev_get_addr_by_port( + uint8_t port_id, struct rte_pci_addr *addr); + +/** * Function for internal use by dummy drivers primarily, e.g. ring-based * driver. * Allocates a new ethdev slot for an ethernet device and returns the pointer -- 1.9.1
[dpdk-dev] [PATCH v3 09/28] ethdev: Add rte_eth_dev_get_port_by_addr
The function returns a port identifier of a ethdev specified by pci address. v3: - Fix if-condition bug while comparing pci addresses. - Add error checking codes. Reported-by: Mark Enright Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 22 ++ lib/librte_ether/rte_ethdev.h | 13 + 2 files changed, 35 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index ddaf14a..4e9f0f7 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -454,6 +454,28 @@ rte_eth_dev_get_addr_by_port(uint8_t port_id, struct rte_pci_addr *addr) return 0; } +int +rte_eth_dev_get_port_by_addr(struct rte_pci_addr *addr, uint8_t *port_id) +{ + struct rte_pci_addr *tmp; + + if ((addr == NULL) || (port_id == NULL)) { + PMD_DEBUG_TRACE("Null pointer is specified\n"); + return -1; + } + + for (*port_id = 0; *port_id < RTE_MAX_ETHPORTS; (*port_id)++) { + if (!rte_eth_devices[*port_id].attached) + continue; + if (!rte_eth_devices[*port_id].pci_dev) + continue; + tmp = &rte_eth_devices[*port_id].pci_dev->addr; + if (eal_compare_pci_addr(tmp, addr) == 0) + return 0; + } + return -1; +} + static int rte_eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) { diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 30277a2..8c55c56 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1676,6 +1676,19 @@ extern int rte_eth_dev_get_addr_by_port( uint8_t port_id, struct rte_pci_addr *addr); /** + * Function for internal use by port hotplug functions. + * Returns a port identifier of a ethdev specified by pci address. + * @param addr + * The pointer to the pci address of the Ethernet device. + * @param port_id + * The pointer to the port identifier + * @return + * - 0 on success, negative on error + */ +extern int rte_eth_dev_get_port_by_addr( + struct rte_pci_addr *addr, uint8_t *port_id); + +/** * Function for internal use by dummy drivers primarily, e.g. ring-based * driver. * Allocates a new ethdev slot for an ethernet device and returns the pointer -- 1.9.1
[dpdk-dev] [PATCH v3 10/28] ethdev: Add rte_eth_dev_get_name_by_port
The function returns a unique identifier name of a ethdev specified by port identifier. Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 22 ++ lib/librte_ether/rte_ethdev.h | 12 2 files changed, 34 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 4e9f0f7..1d82f69 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -476,6 +476,28 @@ rte_eth_dev_get_port_by_addr(struct rte_pci_addr *addr, uint8_t *port_id) return -1; } +int +rte_eth_dev_get_name_by_port(uint8_t port_id, char *name) +{ + char *tmp; + + if (rte_eth_dev_validate_port(port_id) == DEV_INVALID) { + PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); + return -EINVAL; + } + + if (name == NULL) { + PMD_DEBUG_TRACE("Null pointer is specified\n"); + return -EINVAL; + } + + /* shouldn't check 'rte_eth_devices[i].data', +* because it might be overwritten by VDEV PMD */ + tmp = rte_eth_dev_data[port_id].name; + strncpy(name, tmp, strlen(tmp) + 1); + return 0; +} + static int rte_eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) { diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 8c55c56..bd921d0 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1689,6 +1689,18 @@ extern int rte_eth_dev_get_port_by_addr( struct rte_pci_addr *addr, uint8_t *port_id); /** + * Function for internal use by port hotplug functions. + * Returns a unique identifier name of a ethdev specified by port identifier. + * @param port_id + * The port identifier. + * @param name + * The pointer to the Unique identifier name for each Ethernet device + * @return + * - 0 on success, negative on error + */ +extern int rte_eth_dev_get_name_by_port(uint8_t port_id, char *name); + +/** * Function for internal use by dummy drivers primarily, e.g. ring-based * driver. * Allocates a new ethdev slot for an ethernet device and returns the pointer -- 1.9.1
[dpdk-dev] [PATCH v3 11/28] ethdev: Add rte_eth_dev_check_detachable
The function returns whether a PMD supports detach function, or not. Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 9 + lib/librte_ether/rte_ethdev.h | 11 +++ 2 files changed, 20 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 1d82f69..ed53e66 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -498,6 +498,15 @@ rte_eth_dev_get_name_by_port(uint8_t port_id, char *name) return 0; } +int +rte_eth_dev_check_detachable(uint8_t port_id) +{ + uint32_t drv_flags; + + drv_flags = rte_eth_devices[port_id].driver->pci_drv.drv_flags; + return !(drv_flags & RTE_PCI_DRV_DETACHABLE); +} + static int rte_eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) { diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index bd921d0..404c41f 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1701,6 +1701,17 @@ extern int rte_eth_dev_get_port_by_addr( extern int rte_eth_dev_get_name_by_port(uint8_t port_id, char *name); /** + * Function for internal use by port hotplug functions. + * Check whether or not, a PMD that is handling the ethdev specified by port + * identifier can support detach function. + * @param port_id + * The port identifier + * @return + * - 0 on supporting detach function, negative on not supporting + */ +extern int rte_eth_dev_check_detachable(uint8_t port_id); + +/** * Function for internal use by dummy drivers primarily, e.g. ring-based * driver. * Allocates a new ethdev slot for an ethernet device and returns the pointer -- 1.9.1
[dpdk-dev] [PATCH v3 12/28] ethdev: Change scope of rte_eth_dev_allocated to global
This function is used by virtual PMDs to support port hotplug framework. So change scope of the function to global. Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 2 +- lib/librte_ether/rte_ethdev.h | 10 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index ed53e66..86200e0 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -206,7 +206,7 @@ rte_eth_dev_data_alloc(void) RTE_MAX_ETHPORTS * sizeof(*rte_eth_dev_data)); } -static struct rte_eth_dev * +struct rte_eth_dev * rte_eth_dev_allocated(const char *name) { unsigned i; diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 404c41f..47622a2 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1712,6 +1712,16 @@ extern int rte_eth_dev_get_name_by_port(uint8_t port_id, char *name); extern int rte_eth_dev_check_detachable(uint8_t port_id); /** + * Function for internal use by port hotplug functions. + * Returns a ethdev slot specified by the unique identifier name. + * @param name + * The pointer to the Unique identifier name for each Ethernet device + * @return + * - The pointer to the ethdev slot, on success. NULL on error + */ +extern struct rte_eth_dev *rte_eth_dev_allocated(const char *name); + +/** * Function for internal use by dummy drivers primarily, e.g. ring-based * driver. * Allocates a new ethdev slot for an ethernet device and returns the pointer -- 1.9.1
[dpdk-dev] [PATCH v3 13/28] eal/pci: Prevent double registration for devargs_list
The patch fixes rte_eal_devargs_add() not to register same device twice. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_devargs.c | 35 ++ 1 file changed, 35 insertions(+) diff --git a/lib/librte_eal/common/eal_common_devargs.c b/lib/librte_eal/common/eal_common_devargs.c index 4c7d11a..f95a12d 100644 --- a/lib/librte_eal/common/eal_common_devargs.c +++ b/lib/librte_eal/common/eal_common_devargs.c @@ -44,6 +44,35 @@ struct rte_devargs_list devargs_list = TAILQ_HEAD_INITIALIZER(devargs_list); + +/* find a entry specified by pci address or device name */ +static struct rte_devargs * +rte_eal_devargs_find(enum rte_devtype devtype, void *args) +{ + struct rte_devargs *devargs; + + if (args == NULL) + return NULL; + + TAILQ_FOREACH(devargs, &devargs_list, next) { + switch (devtype) { + case RTE_DEVTYPE_WHITELISTED_PCI: + case RTE_DEVTYPE_BLACKLISTED_PCI: + if (eal_compare_pci_addr(&devargs->pci.addr, args) == 0) + goto found; + break; + case RTE_DEVTYPE_VIRTUAL: + if (memcmp(&devargs->virtual.drv_name, args, + strlen((char *)args)) == 0) + goto found; + break; + } + } + return NULL; +found: + return devargs; +} + /* store a whitelist parameter for later parsing */ int rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str) @@ -101,6 +130,12 @@ rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str) break; } + /* make sure there is no same entry */ + if (rte_eal_devargs_find(devtype, &devargs->pci.addr)) { + RTE_LOG(ERR, EAL, "device already registered: <%s>\n", buf); + return -1; + } + TAILQ_INSERT_TAIL(&devargs_list, devargs, next); return 0; } -- 1.9.1
[dpdk-dev] [PATCH v3 14/28] eal/pci: Add rte_eal_devargs_remove
The function removes a specified devargs from devargs_list. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_devargs.c | 16 lib/librte_eal/common/include/rte_devargs.h | 18 ++ 2 files changed, 34 insertions(+) diff --git a/lib/librte_eal/common/eal_common_devargs.c b/lib/librte_eal/common/eal_common_devargs.c index f95a12d..5fd2a2c 100644 --- a/lib/librte_eal/common/eal_common_devargs.c +++ b/lib/librte_eal/common/eal_common_devargs.c @@ -140,6 +140,22 @@ rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str) return 0; } +/* remove it from the devargs_list */ +void +rte_eal_devargs_remove(enum rte_devtype devtype, void *args) +{ + struct rte_devargs *devargs; + + if (args == NULL) + return; + + devargs = rte_eal_devargs_find(devtype, args); + if (devargs == NULL) + return; + + TAILQ_REMOVE(&devargs_list, devargs, next); +} + /* count the number of devices of a specified type */ unsigned int rte_eal_devargs_type_count(enum rte_devtype devtype) diff --git a/lib/librte_eal/common/include/rte_devargs.h b/lib/librte_eal/common/include/rte_devargs.h index 9f9c98f..1066efd 100644 --- a/lib/librte_eal/common/include/rte_devargs.h +++ b/lib/librte_eal/common/include/rte_devargs.h @@ -123,6 +123,24 @@ extern struct rte_devargs_list devargs_list; int rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str); /** + * Remove a device from the user device list + * + * For PCI devices, the format of arguments string is "PCI_ADDR". It shouldn't + * involves parameters for the device. Example: "08:00.1". + * + * For virtual devices, the format of arguments string is "DRIVER_NAME*". It + * shouldn't involves parameters for the device. Example: "eth_ring". The + * validity of the driver name is not checked by this function, it is done + * when closing the drivers. + * + * @param devtype + * The type of the device. + * @param name + * The name of the device. + */ +void rte_eal_devargs_remove(enum rte_devtype devtype, void *args); + +/** * Count the number of user devices of a specified type * * @param devtype -- 1.9.1
[dpdk-dev] [PATCH v3 15/28] eal/pci: Add probe and close function for virtual drivers
The patch adds rte_eal_dev_init_one() and rte_eal_dev_close_one(). These are used for attaching and detaching virtual devices. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_dev.c | 66 + lib/librte_eal/common/include/rte_dev.h | 6 +++ lib/librte_eal/linuxapp/eal/Makefile| 1 + 3 files changed, 73 insertions(+) diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c index eae5656..f573a54 100644 --- a/lib/librte_eal/common/eal_common_dev.c +++ b/lib/librte_eal/common/eal_common_dev.c @@ -32,10 +32,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include +#include #include #include #include +#include #include #include #include @@ -107,3 +110,66 @@ rte_eal_dev_init(void) } return 0; } + +/* So far, linux only supports DPDK hotplug function. */ +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) + +#define INVOKE_PROBE (0) +#define INVOKE_CLOSE (1) + +static void +rte_eal_dev_invoke(struct rte_driver *driver, + struct rte_devargs *devargs, int type) +{ + if ((driver == NULL) || (devargs == NULL)) + return; + + switch (type) { + case INVOKE_PROBE: + driver->init(devargs->virtual.drv_name, devargs->args); + break; + case INVOKE_CLOSE: + driver->close(devargs->virtual.drv_name, devargs->args); + break; + } +} + +static int +rte_eal_dev_find_and_invoke(const char *name, int type) +{ + struct rte_devargs *devargs; + struct rte_driver *driver; + + if (name == NULL) + return -EINVAL; + + /* call the init function for each virtual device */ + TAILQ_FOREACH(devargs, &devargs_list, next) { + + if (devargs->type != RTE_DEVTYPE_VIRTUAL) + continue; + + if (strncmp(name, devargs->virtual.drv_name, strlen(name))) + continue; + + TAILQ_FOREACH(driver, &dev_driver_list, next) { + if (driver->type != PMD_VDEV) + continue; + + /* search a driver prefix in virtual device name */ + if (!strncmp(driver->name, devargs->virtual.drv_name, + strlen(driver->name))) { + rte_eal_dev_invoke(driver, devargs, type); + break; + } + } + + if (driver == NULL) { + RTE_LOG(WARNING, EAL, "no driver found for %s\n", + devargs->virtual.drv_name); + } + return 0; + } + return 1; +} +#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h index f7e3a10..71d40c3 100644 --- a/lib/librte_eal/common/include/rte_dev.h +++ b/lib/librte_eal/common/include/rte_dev.h @@ -57,6 +57,11 @@ TAILQ_HEAD(rte_driver_list, rte_driver); typedef int (rte_dev_init_t)(const char *name, const char *args); /** + * Close function called for each device driver once. + */ +typedef int (rte_dev_close_t)(const char *name, const char *args); + +/** * Driver type enumeration */ enum pmd_type { @@ -72,6 +77,7 @@ struct rte_driver { enum pmd_type type;/**< PMD Driver type */ const char *name; /**< Driver name. */ rte_dev_init_t *init; /**< Device init. function. */ + rte_dev_close_t *close;/**< Device close. function. */ }; /** diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile index 72ecf3a..0ec83b5 100644 --- a/lib/librte_eal/linuxapp/eal/Makefile +++ b/lib/librte_eal/linuxapp/eal/Makefile @@ -41,6 +41,7 @@ CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include CFLAGS += -I$(RTE_SDK)/lib/librte_ring CFLAGS += -I$(RTE_SDK)/lib/librte_mempool CFLAGS += -I$(RTE_SDK)/lib/librte_malloc +CFLAGS += -I$(RTE_SDK)/lib/librte_mbuf CFLAGS += -I$(RTE_SDK)/lib/librte_ether CFLAGS += -I$(RTE_SDK)/lib/librte_ivshmem CFLAGS += -I$(RTE_SDK)/lib/librte_pmd_ring -- 1.9.1
[dpdk-dev] [PATCH v3 16/28] eal/pci: Add port hotplug functions for virtual devices.
The patch adds rte_eal_dev_attach_vdev() and rte_eal_dev_detach_vdev(). rte_eal_dev_attach_vdev() receives virtual device name and parameters, and returns an attached port number. rte_eal_dev_detach_vdev() receives a port number, and returns device name actually detached. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_dev.c | 86 + lib/librte_eal/common/include/rte_dev.h | 29 +++ 2 files changed, 115 insertions(+) diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c index f573a54..4ea3502 100644 --- a/lib/librte_eal/common/eal_common_dev.c +++ b/lib/librte_eal/common/eal_common_dev.c @@ -172,4 +172,90 @@ rte_eal_dev_find_and_invoke(const char *name, int type) } return 1; } + +static void +get_vdev_name(char *vdevargs) +{ + char *sep; + + if (vdevargs == NULL) + return; + + /* set the first ',' to '\0' to split name and arguments */ + sep = strchr(vdevargs, ','); + if (sep != NULL) + sep[0] = '\0'; +} + +/* attach the new virtual device, then store port_id of the device */ +int +rte_eal_dev_attach_vdev(const char *vdevargs, uint8_t *port_id) +{ + char *args; + uint8_t new_port_id; + struct rte_eth_dev devs[RTE_MAX_ETHPORTS]; + + if ((vdevargs == NULL) || (port_id == NULL)) + goto err0; + + args = strdup(vdevargs); + if (args == NULL) + goto err0; + + /* save current port status */ + rte_eth_dev_save(devs); + /* add the vdevargs to devargs_list */ + if (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL, args)) + goto err1; + /* parse vdevargs, then retrieve device name */ + get_vdev_name(args); + /* walk around dev_driver_list to find the driver of the device, +* then invoke probe function o the driver */ + if (rte_eal_dev_find_and_invoke(args, INVOKE_PROBE)) + goto err2; + /* get port_id enabled by above procedures */ + if (rte_eth_dev_get_changed_port(devs, &new_port_id)) + goto err2; + + free(args); + *port_id = new_port_id; + return 0; +err2: + rte_eal_devargs_remove(RTE_DEVTYPE_VIRTUAL, args); +err1: + free(args); +err0: + RTE_LOG(ERR, EAL, "Drver, cannot detach the device\n"); + return -1; +} + +/* detach the new virtual device, then store the name of the device */ +int +rte_eal_dev_detach_vdev(uint8_t port_id, char *vdevname) +{ + char name[RTE_ETH_NAME_MAX_LEN]; + + if (vdevname == NULL) + goto err; + + /* check whether the driver supports detach feature, or not */ + if (rte_eth_dev_check_detachable(port_id)) + goto err; + + /* get device name by port id */ + if (rte_eth_dev_get_name_by_port(port_id, name)) + goto err; + /* walk around dev_driver_list to find the driver of the device, +* then invoke close function o the driver */ + if (rte_eal_dev_find_and_invoke(name, INVOKE_CLOSE)) + goto err; + /* remove the vdevname from devargs_list */ + rte_eal_devargs_remove(RTE_DEVTYPE_VIRTUAL, name); + + strncpy(vdevname, name, sizeof(name)); + return 0; +err: + RTE_LOG(ERR, EAL, "Drver, cannot detach the device\n"); + return -1; +} #endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h index 71d40c3..159d5a5 100644 --- a/lib/librte_eal/common/include/rte_dev.h +++ b/lib/librte_eal/common/include/rte_dev.h @@ -98,6 +98,35 @@ void rte_eal_driver_register(struct rte_driver *driver); */ void rte_eal_driver_unregister(struct rte_driver *driver); +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) + +/** + * Attach a new virtual device. + * + * @param vdevargs + * A pointer to a strings array describing the new device + * to be attached. + * @param port_id + * A pointer to a port identifier actually attached. + * @return + * 0 on success and port_id is filled, negative on error + */ +int rte_eal_dev_attach_vdev(const char *vdevargs, uint8_t *port_id); + +/** + * Detach a virtual device. + * + * @param port_id + * The port identifier of the virtual device to detach. + * @param addr + * A pointer to a virtual device name actually detached. + * @return + * 0 on success and vdevname is filled, negative on error + */ +int rte_eal_dev_detach_vdev(uint8_t port_id, char *vdevname); + +#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ + /** * Initalize all the registered drivers in this process */ -- 1.9.1
[dpdk-dev] [PATCH v3 17/28] eal/linux/pci: Add functions for unmapping igb_uio resources
The patch adds functions for unmapping igb_uio resources. The patch is only for Linux and igb_uio environment. VFIO and BSD are not supported. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/linuxapp/eal/eal_pci.c | 35 lib/librte_eal/linuxapp/eal/eal_pci_init.h | 7 lib/librte_eal/linuxapp/eal/eal_pci_uio.c | 65 ++ 3 files changed, 107 insertions(+) diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index 23a69e9..fe212d1 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -137,6 +137,22 @@ pci_map_resource(void *requested_addr, int fd, off_t offset, size_t size) return mapaddr; } +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) +/* unmap a particular resource */ +void +pci_unmap_resource(void *requested_addr, size_t size) +{ + /* Unmap the PCI memory resource of device */ + if (munmap(requested_addr, size)) { + RTE_LOG(ERR, EAL, "%s(): cannot munmap(%p, 0x%lx): %s\n", + __func__, requested_addr, (unsigned long)size, + strerror(errno)); + } else + RTE_LOG(DEBUG, EAL, " PCI memory mapped at %p\n", + requested_addr); +} +#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ + /* parse the "resource" sysfs file */ #define IORESOURCE_MEM 0x0200 @@ -507,6 +523,25 @@ pci_map_device(struct rte_pci_device *dev) return 0; } +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) +static void +pci_unmap_device(struct rte_pci_device *dev) +{ + if (dev == NULL) + return; + + /* try unmapping the NIC resources using VFIO if it exists */ +#ifdef VFIO_PRESENT + if (pci_vfio_is_enabled()) { + RTE_LOG(ERR, EAL, "%s() doesn't support vfio yet.\n", + __func__); + return; + } +#endif + pci_uio_unmap_resource(dev); +} +#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ + /* * If vendor/device ID match, call the devinit() function of the * driver. diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_init.h b/lib/librte_eal/linuxapp/eal/eal_pci_init.h index 1070eb8..c733ac3 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci_init.h +++ b/lib/librte_eal/linuxapp/eal/eal_pci_init.h @@ -71,6 +71,13 @@ void *pci_map_resource(void *requested_addr, int fd, off_t offset, /* map IGB_UIO resource prototype */ int pci_uio_map_resource(struct rte_pci_device *dev); +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) +void pci_unmap_resource(void *requested_addr, size_t size); + +/* unmap IGB_UIO resource prototype */ +void pci_uio_unmap_resource(struct rte_pci_device *dev); +#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ + #ifdef VFIO_PRESENT #define VFIO_MAX_GROUPS 64 diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c index 1da3507..77e7389 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c @@ -404,6 +404,71 @@ pci_uio_map_resource(struct rte_pci_device *dev) return 0; } +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) +static void +pci_uio_unmap(struct mapped_pci_resource *uio_res) +{ + int i; + + if (uio_res == NULL) + return; + + for (i = 0; i != uio_res->nb_maps; i++) + pci_unmap_resource(uio_res->maps[i].addr, + (size_t)uio_res->maps[i].size); +} + +static struct mapped_pci_resource * +pci_uio_find_resource(struct rte_pci_device *dev) +{ + struct mapped_pci_resource *uio_res; + + if (dev == NULL) + return NULL; + + TAILQ_FOREACH(uio_res, pci_res_list, next) { + + /* skip this element if it doesn't match our PCI address */ + if (!eal_compare_pci_addr(&uio_res->pci_addr, &dev->addr)) + return uio_res; + } + return NULL; +} + +/* unmap the PCI resource of a PCI device in virtual memory */ +void +pci_uio_unmap_resource(struct rte_pci_device *dev) +{ + struct mapped_pci_resource *uio_res; + + if (dev == NULL) + return; + + /* find an entry for the device */ + uio_res = pci_uio_find_resource(dev); + if (uio_res == NULL) + return; + + /* secondary processes - just free maps */ + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return pci_uio_unmap(uio_res); + + TAILQ_REMOVE(pci_res_list, uio_res, next); + + /* unmap all resources */ + pci_uio_unmap(uio_res); + + /* free uio resource */ + rte_free(uio_res); + + /* close fd if in primary process */ + close(dev->intr_handle.fd); + + dev->intr_handle.fd = -1; + dev
[dpdk-dev] [PATCH v3 18/28] eal/pci: Prevent double registrations for pci_device_list
The patch fixes pci_scan_one() not to register same pci devices twice. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/linuxapp/eal/eal_pci.c | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index fe212d1..355c858 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -306,14 +306,17 @@ pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, } else { struct rte_pci_device *dev2 = NULL; + int ret; TAILQ_FOREACH(dev2, &pci_device_list, next) { - if (eal_compare_pci_addr(&dev->addr, &dev2->addr) != 0) + ret = eal_compare_pci_addr(&dev->addr, &dev2->addr); + if (ret > 0) continue; - else { + else if (ret < 0) { TAILQ_INSERT_BEFORE(dev2, dev, next); return 0; - } + } else /* already registered */ + return 0; } TAILQ_INSERT_TAIL(&pci_device_list, dev, next); } -- 1.9.1
[dpdk-dev] [PATCH v3 19/28] eal/pci: Change scope of rte_eal_pci_scan to global
The function is called by port hotplug framework, so change scope of the function to global. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_private.h | 11 +++ lib/librte_eal/linuxapp/eal/eal_pci.c | 6 +++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h index 232fcec..a1127ab 100644 --- a/lib/librte_eal/common/eal_private.h +++ b/lib/librte_eal/common/eal_private.h @@ -154,6 +154,17 @@ struct rte_pci_driver; struct rte_pci_device; /** + * Scan the content of the PCI bus, and the devices in the devices + * list + * + * This function is private to EAL. + * + * @return + * 0 on success, negative on error + */ +int rte_eal_pci_scan(void); + +/** * Mmap memory for single PCI device * * This function is private to EAL. diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index 355c858..8d683f5 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -375,8 +375,8 @@ error: * Scan the content of the PCI bus, and the devices in the devices * list */ -static int -pci_scan(void) +int +rte_eal_pci_scan(void) { struct dirent *e; DIR *dir; @@ -629,7 +629,7 @@ rte_eal_pci_init(void) if (internal_config.no_pci) return 0; - if (pci_scan() < 0) { + if (rte_eal_pci_scan() < 0) { RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__); return -1; } -- 1.9.1
[dpdk-dev] [PATCH v3 20/28] eal/pci: Add rte_eal_pci_close_one_driver
The function is used for closing the specified driver and device. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_private.h | 15 + lib/librte_eal/linuxapp/eal/eal_pci.c | 61 +++ 2 files changed, 76 insertions(+) diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h index a1127ab..f892ac4 100644 --- a/lib/librte_eal/common/eal_private.h +++ b/lib/librte_eal/common/eal_private.h @@ -176,6 +176,21 @@ int rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev); /** + * Munmap memory for single PCI device + * + * This function is private to EAL. + * + * @param dr + * The pointer to the pci driver structure + * @param dev + * The pointer to the pci device structure + * @return + * 0 on success, negative on error + */ +int rte_eal_pci_close_one_driver(struct rte_pci_driver *dr, + struct rte_pci_device *dev); + +/** * Init tail queues for non-EAL library structures. This is to allow * the rings, mempools, etc. lists to be shared among multiple processes * diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index 8d683f5..93456f3 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -616,6 +616,67 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *d return 1; } +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) +/* + * If vendor/device ID match, call the devshutdown() function of the + * driver. + */ +int +rte_eal_pci_close_one_driver(struct rte_pci_driver *dr, + struct rte_pci_device *dev) +{ + struct rte_pci_id *id_table; + + if ((dr == NULL) || (dev == NULL)) + return -EINVAL; + + for (id_table = dr->id_table ; id_table->vendor_id != 0; id_table++) { + + /* check if device's identifiers match the driver's ones */ + if (id_table->vendor_id != dev->id.vendor_id && + id_table->vendor_id != PCI_ANY_ID) + continue; + if (id_table->device_id != dev->id.device_id && + id_table->device_id != PCI_ANY_ID) + continue; + if (id_table->subsystem_vendor_id != + dev->id.subsystem_vendor_id && + id_table->subsystem_vendor_id != PCI_ANY_ID) + continue; + if (id_table->subsystem_device_id != + dev->id.subsystem_device_id && + id_table->subsystem_device_id != PCI_ANY_ID) + continue; + + struct rte_pci_addr *loc = &dev->addr; + + RTE_LOG(DEBUG, EAL, + "PCI device "PCI_PRI_FMT" on NUMA socket %i\n", + loc->domain, loc->bus, loc->devid, + loc->function, dev->numa_node); + + RTE_LOG(DEBUG, EAL, " remove driver: %x:%x %s\n", + dev->id.vendor_id, dev->id.device_id, + dr->name); + + /* call the driver devshutdown() function */ + if (dr->devshutdown && (dr->devshutdown(dr, dev) < 0)) + return -1; /* negative value is an error */ + + /* clear driver structure */ + dev->driver = NULL; + + if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) + /* unmap resources for devices that use igb_uio */ + pci_unmap_device(dev); + + return 0; + } + /* return positive value if driver is not found */ + return 1; +} +#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ + /* Init the PCI EAL subsystem */ int rte_eal_pci_init(void) -- 1.9.1
[dpdk-dev] [PATCH v3 21/28] eal/pci: Fix pci_probe_all_drivers to share code with closing function
pci_close_all_drivers() will be implemented after the patch. To share a part of code between thses 2 functions, The patch fixes pci_probe_all_drivers() first. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_pci.c | 28 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c index f01f258..1e3efea 100644 --- a/lib/librte_eal/common/eal_common_pci.c +++ b/lib/librte_eal/common/eal_common_pci.c @@ -99,19 +99,20 @@ static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev) return NULL; } -/* - * If vendor/device ID match, call the devinit() function of all - * registered driver for the given device. Return -1 if initialization - * failed, return 1 if no driver is found for this device. - */ +#define INVOKE_PROBE (0) + static int -pci_probe_all_drivers(struct rte_pci_device *dev) +pci_invoke_all_drivers(struct rte_pci_device *dev, int type) { struct rte_pci_driver *dr = NULL; - int rc; + int rc = 0; TAILQ_FOREACH(dr, &pci_driver_list, next) { - rc = rte_eal_pci_probe_one_driver(dr, dev); + switch (type) { + case INVOKE_PROBE: + rc = rte_eal_pci_probe_one_driver(dr, dev); + break; + } if (rc < 0) /* negative value is an error */ return -1; @@ -124,6 +125,17 @@ pci_probe_all_drivers(struct rte_pci_device *dev) } /* + * If vendor/device ID match, call the devinit() function of all + * registered driver for the given device. Return -1 if initialization + * failed, return 1 if no driver is found for this device. + */ +static int +pci_probe_all_drivers(struct rte_pci_device *dev) +{ + return pci_invoke_all_drivers(dev, INVOKE_PROBE); +} + +/* * Scan the content of the PCI bus, and call the devinit() function for * all registered drivers that have a matching entry in its id_table * for discovered devices. -- 1.9.1
[dpdk-dev] [PATCH v3 22/28] eal/pci: Add pci_close_all_drivers
The function tries to find a driver for the specified device, and then close the driver. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_pci.c | 19 +++ 1 file changed, 19 insertions(+) diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c index 1e3efea..b404ee0 100644 --- a/lib/librte_eal/common/eal_common_pci.c +++ b/lib/librte_eal/common/eal_common_pci.c @@ -100,6 +100,7 @@ static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev) } #define INVOKE_PROBE (0) +#define INVOKE_CLOSE (1) static int pci_invoke_all_drivers(struct rte_pci_device *dev, int type) @@ -112,6 +113,11 @@ pci_invoke_all_drivers(struct rte_pci_device *dev, int type) case INVOKE_PROBE: rc = rte_eal_pci_probe_one_driver(dr, dev); break; +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) + case INVOKE_CLOSE: + rc = rte_eal_pci_close_one_driver(dr, dev); + break; +#endif } if (rc < 0) /* negative value is an error */ @@ -135,6 +141,19 @@ pci_probe_all_drivers(struct rte_pci_device *dev) return pci_invoke_all_drivers(dev, INVOKE_PROBE); } +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) +/* + * If vendor/device ID match, call the devclose() function of all + * registered driver for the given device. Return -1 if initialization + * failed, return 1 if no driver is found for this device. + */ +static int +pci_close_all_drivers(struct rte_pci_device *dev) +{ + return pci_invoke_all_drivers(dev, INVOKE_CLOSE); +} +#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ + /* * Scan the content of the PCI bus, and call the devinit() function for * all registered drivers that have a matching entry in its id_table -- 1.9.1
[dpdk-dev] [PATCH v3 23/28] eal/pci: Add rte_eal_pci_probe_one and rte_eal_pci_close_one
The functions are used for probe and close a device. First the function tries to find a device that has the specfied PCI address. Then, probe or close the device. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_pci.c | 58 + lib/librte_eal/common/include/rte_pci.h | 26 +++ 2 files changed, 84 insertions(+) diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c index b404ee0..5ff7b49 100644 --- a/lib/librte_eal/common/eal_common_pci.c +++ b/lib/librte_eal/common/eal_common_pci.c @@ -152,6 +152,64 @@ pci_close_all_drivers(struct rte_pci_device *dev) { return pci_invoke_all_drivers(dev, INVOKE_CLOSE); } + +static int +rte_eal_pci_invoke_one(struct rte_pci_addr *addr, int type) +{ + struct rte_pci_device *dev = NULL; + int ret = 0; + + TAILQ_FOREACH(dev, &pci_device_list, next) { + if (eal_compare_pci_addr(&dev->addr, addr)) + continue; + + switch (type) { + case INVOKE_PROBE: + ret = pci_probe_all_drivers(dev); + break; + case INVOKE_CLOSE: + ret = pci_close_all_drivers(dev); + break; + } + if (ret < 0) + goto invoke_err_return; + if (type == INVOKE_CLOSE) + goto remove_dev; + return 0; + } + + return -1; + +invoke_err_return: + RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT + " cannot be used\n", dev->addr.domain, dev->addr.bus, + dev->addr.devid, dev->addr.function); + return -1; + +remove_dev: + TAILQ_REMOVE(&pci_device_list, dev, next); + return 0; +} + +/* + * Find the pci device specified by pci address, then invoke probe function of + * the driver of the devive. + */ +int +rte_eal_pci_probe_one(struct rte_pci_addr *addr) +{ + return rte_eal_pci_invoke_one(addr, INVOKE_PROBE); +} + +/* + * Find the pci device specified by pci address, then invoke close function of + * the driver of the devive. + */ +int +rte_eal_pci_close_one(struct rte_pci_addr *addr) +{ + return rte_eal_pci_invoke_one(addr, INVOKE_CLOSE); +} #endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ /* diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index 74720d1..5a7e06f 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -311,6 +311,32 @@ eal_compare_pci_addr(struct rte_pci_addr *addr, struct rte_pci_addr *addr2) int rte_eal_pci_probe(void); /** + * Probe the single PCI device. + * + * Scan the content of the PCI bus, and find the pci device specified by pci + * address, then call the probe() function for registered driver that has a + * matching entry in its id_table for discovered device. + * + * @return + * - 0 on success. + * - Negative on error. + */ +int rte_eal_pci_probe_one(struct rte_pci_addr *addr); + +/** + * Close the single PCI device. + * + * Scan the content of the PCI bus, and find the pci device specified by pci + * address, then call the close() function for registered driver that has a + * matching entry in its id_table for discovered device. + * + * @return + * - 0 on success. + * - Negative on error. + */ +int rte_eal_pci_close_one(struct rte_pci_addr *addr); + +/** * Dump the content of the PCI bus. * * @param f -- 1.9.1
[dpdk-dev] [PATCH v3 24/28] eal/pci: Add port hotplug functions for physical devices.
The patch adds rte_eal_dev_attach_pdev() and rte_eal_dev_detach_pdev(). rte_eal_dev_attach_pdev() receives a PCI address of the device and returns an attached port number. rte_eal_dev_detach_pdev() receives a port number, and returns a PCI address actually detached. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_dev.c | 64 + lib/librte_eal/common/include/rte_dev.h | 26 ++ 2 files changed, 90 insertions(+) diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c index 4ea3502..9ff03ed 100644 --- a/lib/librte_eal/common/eal_common_dev.c +++ b/lib/librte_eal/common/eal_common_dev.c @@ -173,6 +173,70 @@ rte_eal_dev_find_and_invoke(const char *name, int type) return 1; } +/* attach the new physical device, then store port_id of the device */ +int +rte_eal_dev_attach_pdev(struct rte_pci_addr *addr, uint8_t *port_id) +{ + uint8_t new_port_id; + struct rte_eth_dev devs[RTE_MAX_ETHPORTS]; + + if ((addr == NULL) || (port_id == NULL)) + goto err; + + /* save current port status */ + rte_eth_dev_save(devs); + /* re-construct pci_device_list */ + if (rte_eal_pci_scan()) + goto err; + /* invoke probe func of the driver can handle the new device */ + if (rte_eal_pci_probe_one(addr)) + goto err; + /* get port_id enabled by above procedures */ + if (rte_eth_dev_get_changed_port(devs, &new_port_id)) + goto err; + + *port_id = new_port_id; + return 0; +err: + RTE_LOG(ERR, EAL, "Drver, cannot attach the device\n"); + return -1; +} + +/* detach the new physical device, then store pci_addr of the device */ +int +rte_eal_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr) +{ + struct rte_pci_addr freed_addr; + struct rte_pci_addr vp; + + if (addr == NULL) + goto err; + + /* check whether the driver supports detach feature, or not */ + if (rte_eth_dev_check_detachable(port_id)) + goto err; + + /* get pci address by port id */ + if (rte_eth_dev_get_addr_by_port(port_id, &freed_addr)) + goto err; + + /* Zerod pci addr means the port comes from virtual device */ + vp.domain = vp.bus = vp.devid = vp.function = 0; + if (eal_compare_pci_addr(&vp, &freed_addr) == 0) + goto err; + + /* invoke close func of the driver, +* also remove the device from pci_device_list */ + if (rte_eal_pci_close_one(&freed_addr)) + goto err; + + *addr = freed_addr; + return 0; +err: + RTE_LOG(ERR, EAL, "Drver, cannot detach the device\n"); + return -1; +} + static void get_vdev_name(char *vdevargs) { diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h index 159d5a5..f0677cb 100644 --- a/lib/librte_eal/common/include/rte_dev.h +++ b/lib/librte_eal/common/include/rte_dev.h @@ -47,6 +47,7 @@ extern "C" { #endif #include +#include /** Double linked list of device drivers. */ TAILQ_HEAD(rte_driver_list, rte_driver); @@ -101,6 +102,19 @@ void rte_eal_driver_unregister(struct rte_driver *driver); #if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) /** + * Attach a new physical device. + * + * @param addr + * A pointer to a pci address structure describing the new + * device to be attached. + * @param port_id + * A pointer to a port identifier actually attached. + * @return + * 0 on success and port_id is filled, negative on error + */ +int rte_eal_dev_attach_pdev(struct rte_pci_addr *addr, uint8_t *port_id); + +/** * Attach a new virtual device. * * @param vdevargs @@ -114,6 +128,18 @@ void rte_eal_driver_unregister(struct rte_driver *driver); int rte_eal_dev_attach_vdev(const char *vdevargs, uint8_t *port_id); /** + * Detach a physical device. + * + * @param port_id + * The port identifier of the physical device to detach. + * @param addr + * A pointer to a pci address structure actually detached. + * @return + * 0 on success and addr is filled, negative on error + */ +int rte_eal_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr); + +/** * Detach a virtual device. * * @param port_id -- 1.9.1
[dpdk-dev] [PATCH v3 25/28] eal/pci: Remove pci_probe/close_all_drivers()
These functions are actually wrappers of pci_invoke_all_drivers(). Just call it directly. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_pci.c | 30 -- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c index 5ff7b49..5044d8e 100644 --- a/lib/librte_eal/common/eal_common_pci.c +++ b/lib/librte_eal/common/eal_common_pci.c @@ -130,29 +130,7 @@ pci_invoke_all_drivers(struct rte_pci_device *dev, int type) return 1; } -/* - * If vendor/device ID match, call the devinit() function of all - * registered driver for the given device. Return -1 if initialization - * failed, return 1 if no driver is found for this device. - */ -static int -pci_probe_all_drivers(struct rte_pci_device *dev) -{ - return pci_invoke_all_drivers(dev, INVOKE_PROBE); -} - #if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) -/* - * If vendor/device ID match, call the devclose() function of all - * registered driver for the given device. Return -1 if initialization - * failed, return 1 if no driver is found for this device. - */ -static int -pci_close_all_drivers(struct rte_pci_device *dev) -{ - return pci_invoke_all_drivers(dev, INVOKE_CLOSE); -} - static int rte_eal_pci_invoke_one(struct rte_pci_addr *addr, int type) { @@ -165,10 +143,10 @@ rte_eal_pci_invoke_one(struct rte_pci_addr *addr, int type) switch (type) { case INVOKE_PROBE: - ret = pci_probe_all_drivers(dev); + ret = pci_invoke_all_drivers(dev, INVOKE_PROBE); break; case INVOKE_CLOSE: - ret = pci_close_all_drivers(dev); + ret = pci_invoke_all_drivers(dev, INVOKE_CLOSE); break; } if (ret < 0) @@ -237,10 +215,10 @@ rte_eal_pci_probe(void) /* probe all or only whitelisted devices */ if (probe_all) - ret = pci_probe_all_drivers(dev); + ret = pci_invoke_all_drivers(dev, INVOKE_PROBE); else if (devargs != NULL && devargs->type == RTE_DEVTYPE_WHITELISTED_PCI) - ret = pci_probe_all_drivers(dev); + ret = pci_invoke_all_drivers(dev, INVOKE_PROBE); if (ret < 0) rte_exit(EXIT_FAILURE, "Requested device " PCI_PRI_FMT " cannot be used\n", dev->addr.domain, dev->addr.bus, -- 1.9.1
[dpdk-dev] [PATCH v3 26/28] eal/pci: Add rte_eal_dev_attach/detach() functions
This functions wraps attaching and detaching functions for physical and virtual device. When rte_eal_dev_attach() is called, the function tries to realize the device name as pci address. If this is done successfully, rte_eal_dev_attach() will call rte_eal_dev_attach_pdev(). If not, calls rte_eal_dev_attach_vdev(). When rte_eal_dev_detach() is called, the function gets the device type of this port to know whether the port is came from physical or virtual. And then rte_eal_dev_detach_pdev() or rte_eal_dev_detach_vdev() will be called. Signed-off-by: Tetsuya Mukawa --- app/test/virtual_pmd.c | 2 +- lib/librte_eal/common/eal_common_dev.c | 34 lib/librte_eal/common/include/rte_dev.h | 25 lib/librte_ether/rte_ethdev.c| 14 ++-- lib/librte_ether/rte_ethdev.h| 24 +++- lib/librte_pmd_af_packet/rte_eth_af_packet.c | 2 +- lib/librte_pmd_bond/rte_eth_bond_api.c | 2 +- lib/librte_pmd_pcap/rte_eth_pcap.c | 2 +- lib/librte_pmd_ring/rte_eth_ring.c | 2 +- lib/librte_pmd_xenvirt/rte_eth_xenvirt.c | 2 +- 10 files changed, 100 insertions(+), 9 deletions(-) diff --git a/app/test/virtual_pmd.c b/app/test/virtual_pmd.c index ade6cb0..ff8f747 100644 --- a/app/test/virtual_pmd.c +++ b/app/test/virtual_pmd.c @@ -556,7 +556,7 @@ virtual_ethdev_create(const char *name, struct ether_addr *mac_addr, goto err; /* reserve an ethdev entry */ - eth_dev = rte_eth_dev_allocate(name); + eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_PHYSICAL); if (eth_dev == NULL) goto err; diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c index 9ff03ed..c9d4894 100644 --- a/lib/librte_eal/common/eal_common_dev.c +++ b/lib/librte_eal/common/eal_common_dev.c @@ -322,4 +322,38 @@ err: RTE_LOG(ERR, EAL, "Drver, cannot detach the device\n"); return -1; } + +/* attach the new device, then store port_id of the device */ +int +rte_eal_dev_attach(const char *devargs, uint8_t *port_id) +{ + struct rte_pci_addr addr; + + if (eal_parse_pci_DomBDF(devargs, &addr) == 0) + return rte_eal_dev_attach_pdev(&addr, port_id); + else + return rte_eal_dev_attach_vdev(devargs, port_id); +} + +/* detach the device, then store the name of the device */ +int +rte_eal_dev_detach(uint8_t port_id, char *name) +{ + struct rte_pci_addr addr; + int ret; + + if (rte_eth_dev_get_device_type(port_id) == RTE_ETH_DEV_PHYSICAL) { + ret = rte_eth_dev_get_addr_by_port(port_id, &addr); + if (ret < 0) + return ret; + + ret = rte_eal_dev_detach_pdev(port_id, &addr); + if (ret == 0) + snprintf(name, RTE_ETH_NAME_MAX_LEN, "%04x.%02x.%02x.%d", + addr.domain, addr.bus, addr.devid, addr.function); + + return ret; + } else + return rte_eal_dev_detach_vdev(port_id, name); +} #endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h index f0677cb..1f8f24a 100644 --- a/lib/librte_eal/common/include/rte_dev.h +++ b/lib/librte_eal/common/include/rte_dev.h @@ -151,6 +151,31 @@ int rte_eal_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr); */ int rte_eal_dev_detach_vdev(uint8_t port_id, char *vdevname); +/** + * Attach a new device. + * + * @param devargs + * A pointer to a strings array describing the new device + * to be attached. + * @param port_id + * A pointer to a port identifier actually attached. + * @return + * 0 on success and port_id is filled, negative on error + */ +int rte_eal_dev_attach(const char *devargs, uint8_t *port_id); + +/** + * Detach a device. + * + * @param port_id + * The port identifier of the device to detach. + * @param addr + * A pointer to a device name actually detached. + * @return + * 0 on success and devname is filled, negative on error + */ +int rte_eal_dev_detach(uint8_t port_id, char *devname); + #endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ /** diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 86200e0..cd5ef67 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -232,7 +232,7 @@ rte_eth_dev_allocate_new_port(void) } struct rte_eth_dev * -rte_eth_dev_allocate(const char *name) +rte_eth_dev_allocate(const char *name, enum rte_eth_dev_type type) { uint8_t port_id; struct rte_eth_dev *eth_dev; @@ -256,6 +256,7 @@ rte_eth_dev_allocate(const char *name) snprintf(eth_dev->data->name, sizeof(eth_dev->data->name), "%s", name); eth_dev->data->port_id = port_id; eth_dev->attached = DEV_CONNECTED; + eth
[dpdk-dev] [PATCH v3 27/28] eal/pci: Remove rte_eal_dev_attach/detach_pdev() and rte_eal_dev_attach/detach_vdev()
These functions are wrapped by rte_eal_dev_attach/detach(). So delete these. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_dev.c | 8 +++--- lib/librte_eal/common/include/rte_dev.h | 50 - 2 files changed, 4 insertions(+), 54 deletions(-) diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c index c9d4894..7481fb7 100644 --- a/lib/librte_eal/common/eal_common_dev.c +++ b/lib/librte_eal/common/eal_common_dev.c @@ -174,7 +174,7 @@ rte_eal_dev_find_and_invoke(const char *name, int type) } /* attach the new physical device, then store port_id of the device */ -int +static int rte_eal_dev_attach_pdev(struct rte_pci_addr *addr, uint8_t *port_id) { uint8_t new_port_id; @@ -203,7 +203,7 @@ err: } /* detach the new physical device, then store pci_addr of the device */ -int +static int rte_eal_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr) { struct rte_pci_addr freed_addr; @@ -252,7 +252,7 @@ get_vdev_name(char *vdevargs) } /* attach the new virtual device, then store port_id of the device */ -int +static int rte_eal_dev_attach_vdev(const char *vdevargs, uint8_t *port_id) { char *args; @@ -294,7 +294,7 @@ err0: } /* detach the new virtual device, then store the name of the device */ -int +static int rte_eal_dev_detach_vdev(uint8_t port_id, char *vdevname) { char name[RTE_ETH_NAME_MAX_LEN]; diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h index 1f8f24a..9da518d 100644 --- a/lib/librte_eal/common/include/rte_dev.h +++ b/lib/librte_eal/common/include/rte_dev.h @@ -102,56 +102,6 @@ void rte_eal_driver_unregister(struct rte_driver *driver); #if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) /** - * Attach a new physical device. - * - * @param addr - * A pointer to a pci address structure describing the new - * device to be attached. - * @param port_id - * A pointer to a port identifier actually attached. - * @return - * 0 on success and port_id is filled, negative on error - */ -int rte_eal_dev_attach_pdev(struct rte_pci_addr *addr, uint8_t *port_id); - -/** - * Attach a new virtual device. - * - * @param vdevargs - * A pointer to a strings array describing the new device - * to be attached. - * @param port_id - * A pointer to a port identifier actually attached. - * @return - * 0 on success and port_id is filled, negative on error - */ -int rte_eal_dev_attach_vdev(const char *vdevargs, uint8_t *port_id); - -/** - * Detach a physical device. - * - * @param port_id - * The port identifier of the physical device to detach. - * @param addr - * A pointer to a pci address structure actually detached. - * @return - * 0 on success and addr is filled, negative on error - */ -int rte_eal_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr); - -/** - * Detach a virtual device. - * - * @param port_id - * The port identifier of the virtual device to detach. - * @param addr - * A pointer to a virtual device name actually detached. - * @return - * 0 on success and vdevname is filled, negative on error - */ -int rte_eal_dev_detach_vdev(uint8_t port_id, char *vdevname); - -/** * Attach a new device. * * @param devargs -- 1.9.1
[dpdk-dev] [PATCH v3 28/28] eal: Enable port hotplug framework in Linux
The patch enables CONFIG_RTE_LIBRTE_EAL_HOTPLUG in Linux configuration. Signed-off-by: Tetsuya Mukawa --- config/common_linuxapp | 5 + 1 file changed, 5 insertions(+) diff --git a/config/common_linuxapp b/config/common_linuxapp index 2f9643b..27d05be 100644 --- a/config/common_linuxapp +++ b/config/common_linuxapp @@ -114,6 +114,11 @@ CONFIG_RTE_PCI_MAX_READ_REQUEST_SIZE=0 CONFIG_RTE_LIBRTE_EAL_LINUXAPP=y # +# Compile Environment Abstraction Layer to support hotplug +# +CONFIG_RTE_LIBRTE_EAL_HOTPLUG=y + +# # Compile Environment Abstraction Layer to support Vmware TSC map # CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=y -- 1.9.1
[dpdk-dev] [PATCH v3] librte_pmd_pcap: Add port hotplug support
This patch adds finalization code to free resources allocated by the PMD. Signed-off-by: Tetsuya Mukawa --- lib/librte_pmd_pcap/rte_eth_pcap.c | 40 ++ 1 file changed, 40 insertions(+) diff --git a/lib/librte_pmd_pcap/rte_eth_pcap.c b/lib/librte_pmd_pcap/rte_eth_pcap.c index 0f34f73..c92ebb7 100644 --- a/lib/librte_pmd_pcap/rte_eth_pcap.c +++ b/lib/librte_pmd_pcap/rte_eth_pcap.c @@ -499,6 +499,13 @@ static struct eth_dev_ops ops = { .stats_reset = eth_stats_reset, }; +static struct eth_driver rte_pcap_pmd = { + .pci_drv = { + .name = "rte_pcap_pmd", + .drv_flags = RTE_PCI_DRV_DETACHABLE, + }, +}; + /* * Function handler that opens the pcap file for reading a stores a * reference of it for use it later on. @@ -714,6 +721,10 @@ rte_pmd_init_internals(const char *name, const unsigned nb_rx_queues, if (*eth_dev == NULL) goto error; + /* check length of device name */ + if ((strlen((*eth_dev)->data->name) + 1) > sizeof(data->name)) + goto error; + /* now put it all together * - store queue data in internals, * - store numa_node info in pci_driver @@ -739,10 +750,13 @@ rte_pmd_init_internals(const char *name, const unsigned nb_rx_queues, data->nb_tx_queues = (uint16_t)nb_tx_queues; data->dev_link = pmd_link; data->mac_addrs = ð_addr; + strncpy(data->name, + (*eth_dev)->data->name, strlen((*eth_dev)->data->name)); (*eth_dev)->data = data; (*eth_dev)->dev_ops = &ops; (*eth_dev)->pci_dev = pci_dev; + (*eth_dev)->driver = &rte_pcap_pmd; return 0; @@ -927,10 +941,36 @@ rte_pmd_pcap_devinit(const char *name, const char *params) } +static int +rte_pmd_pcap_devclose(const char *name, const char *params __rte_unused) +{ + struct rte_eth_dev *eth_dev = NULL; + + RTE_LOG(INFO, PMD, "Closing pcap ethdev on numa socket %u\n", + rte_socket_id()); + + if (name == NULL) + return -1; + + /* reserve an ethdev entry */ + eth_dev = rte_eth_dev_allocated(name); + if (eth_dev == NULL) + return -1; + + rte_free(eth_dev->data->dev_private); + rte_free(eth_dev->data); + rte_free(eth_dev->pci_dev); + + rte_eth_dev_free(name); + + return 0; +} + static struct rte_driver pmd_pcap_drv = { .name = "eth_pcap", .type = PMD_VDEV, .init = rte_pmd_pcap_devinit, + .close = rte_pmd_pcap_devclose, }; PMD_REGISTER_DRIVER(pmd_pcap_drv); -- 1.9.1
[dpdk-dev] [PATCH v3] testpmd: Add port hotplug support
The patch introduces following commands. - port attach [ident] - port detach [port_id] - attach: attaching a port - detach: detaching a port - ident: pci address of physical device. Or device name and paramerters of virtual device. (ex. :02:00.0, eth_pcap0,iface=eth0) - port_id: port identifier Signed-off-by: Tetsuya Mukawa --- app/test-pmd/cmdline.c| 133 +-- app/test-pmd/config.c | 116 +++ app/test-pmd/parameters.c | 21 +++-- app/test-pmd/testpmd.c| 199 +++--- app/test-pmd/testpmd.h| 18 - 5 files changed, 357 insertions(+), 130 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index f79ea3e..40c2db7 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -572,6 +572,12 @@ static void cmd_help_long_parsed(void *parsed_result, "port close (port_id|all)\n" "Close all ports or port_id.\n\n" + "port add (p|a) (ident)\n" + "Add physical or virtual dev by pci address or virtual device name\n\n" + + "port del (p|a) (port_id)\n" + "Del physical or virtual dev by port_id\n\n" + "port config (port_id|all)" " speed (10|100|1000|1|4|auto)" " duplex (half|full|auto)\n" @@ -853,6 +859,89 @@ cmdline_parse_inst_t cmd_operate_specific_port = { }, }; +/* *** attach a specificied port *** */ +struct cmd_operate_attach_port_result { + cmdline_fixed_string_t port; + cmdline_fixed_string_t keyword; + cmdline_fixed_string_t identifier; +}; + +static void cmd_operate_attach_port_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_operate_attach_port_result *res = parsed_result; + + if (!strcmp(res->keyword, "attach")) + attach_port(res->identifier); + else + printf("Unknown parameter\n"); +} + +cmdline_parse_token_string_t cmd_operate_attach_port_port = + TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result, + port, "port"); +cmdline_parse_token_string_t cmd_operate_attach_port_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result, + keyword, "attach"); +cmdline_parse_token_string_t cmd_operate_attach_port_identifier = + TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result, + identifier, NULL); + +cmdline_parse_inst_t cmd_operate_attach_port = { + .f = cmd_operate_attach_port_parsed, + .data = NULL, + .help_str = "port attach identifier, " + "identifier: pci address or virtual dev name", + .tokens = { + (void *)&cmd_operate_attach_port_port, + (void *)&cmd_operate_attach_port_keyword, + (void *)&cmd_operate_attach_port_identifier, + NULL, + }, +}; + +/* *** detach a specificied port *** */ +struct cmd_operate_detach_port_result { + cmdline_fixed_string_t port; + cmdline_fixed_string_t keyword; + uint8_t port_id; +}; + +static void cmd_operate_detach_port_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_operate_detach_port_result *res = parsed_result; + + if (!strcmp(res->keyword, "detach")) + detach_port(res->port_id); + else + printf("Unknown parameter\n"); +} + +cmdline_parse_token_string_t cmd_operate_detach_port_port = + TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result, + port, "port"); +cmdline_parse_token_string_t cmd_operate_detach_port_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result, + keyword, "detach"); +cmdline_parse_token_num_t cmd_operate_detach_port_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_operate_detach_port_result, + port_id, UINT8); + +cmdline_parse_inst_t cmd_operate_detach_port = { + .f = cmd_operate_detach_port_parsed, + .data = NULL, + .help_str = "port detach port_id", + .tokens = { + (void *)&cmd_operate_detach_port_port, + (void *)&cmd_operate_detach_port_keyword, + (void *)&cmd_operate_detach_port_port_id, + NULL, + }, +}; + /* *** configure speed for all ports *** */ struct cmd_config_speed_all { cmdline_fixed_string_t port; @@ -907,7 +996,7 @@ cmd_config_speed_all_parsed(void *parsed_result, return; } - for (pid = 0; p
[dpdk-dev] [RFC PATCH 00/17] Single virtio implementation
> -Original Message- > From: Thomas Monjalon [mailto:thomas.monjalon at 6wind.com] > Sent: Tuesday, December 9, 2014 2:12 PM > To: Ouyang, Changchun > Cc: Qiu, Michael; Stephen Hemminger; dev at dpdk.org > Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio implementation > > 2014-12-09 05:41, Ouyang, Changchun: > > Hi > > > > > -Original Message- > > > From: Qiu, Michael > > > Sent: Tuesday, December 9, 2014 11:23 AM > > > To: Ouyang, Changchun; Thomas Monjalon; Stephen Hemminger > > > Cc: dev at dpdk.org > > > Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio > > > implementation > > > > > > On 12/9/2014 9:11 AM, Ouyang, Changchun wrote: > > > > Hi Thomas, > > > > > > > >> -Original Message- > > > >> From: Thomas Monjalon [mailto:thomas.monjalon at 6wind.com] > > > >> Sent: Monday, December 8, 2014 5:31 PM > > > >> To: Ouyang, Changchun > > > >> Cc: dev at dpdk.org > > > >> Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio > > > >> implementation > > > >> > > > >> Hi Changchun, > > > >> > > > >> 2014-12-08 14:21, Ouyang Changchun: > > > >>> This patch set bases on two original RFC patch sets from Stephen > > > >> Hemminger[stephen at networkplumber.org] > > > >>> Refer to > > > >>> [http://dpdk.org/ml/archives/dev/2014-August/004845.html ] for > > > >> the original one. > > > >>> This patch set also resolves some conflict with latest codes and > > > >>> removed > > > >> duplicated codes. > > > >> > > > >> As you sent the patches, you appear as the author. > > > >> But I guess Stephen should be the author for some of them. > > > >> Please check who has contributed the most in each patch to decide. > > > > You are right, most of patches originate from Stephen's patchset, > > > > except for the last one, To be honest, I am ok whoever is the > > > > author of this patch set, :-), We could co-own the feature of > > > > Single virtio if you all agree with it, and I think we couldn't > > > > finish Such a feature without collaboration among us, this is why > > > > I tried to communicate > > > with most of you to collect more feedback, suggestion and comments > > > for this feature. > > > > Very appreciate for all kinds of feedback, suggestion here, > > > > especially for > > > patch set from Stephen. > > > > > > > > According to your request, how could we make this patch set looks > > > > more > > > like Stephen as the author? > > > > Currently I add Stephen as Signed-off-by list in each patch(I got > > > > the > > > agreement from Stephen before doing this :-)). > > > > > > Hi Ouyang, > > > > > > "Signed-off-by" should be added by himself, because the one who in > > > the Signed-off-by list should take responsibility for it(like potential > bugs/issues). > > > > > > Although, lots of patches are originate from Stephen, we still need > > > himself add this line :) > > > > Hi Thomas, > > It that right? I can't add Stephen into Signed-off-by list even if I > > have gotten the agreement from Stephen, What 's the strict rule here? > > Stephen sent the patches with his Signed-off, then you added yours. > This is OK. > Using git am, author would have been Stephen. To change author now, you > can edit each commit with interactive rebase and "git commit --amend -- > author=Stephen". > No need to resend now. Please check it for next version of the patchset. > So I understand correctly, Stephen need care for from patches from 1 to 16, I need care for the 17th patch from next version. What I mean "caring for" above is: debug and validate them and send out patches Thanks Changchun
[dpdk-dev] lib: include rte_memory.h for __rte_cache_aligned
Hi Neil, On 12/08/2014 04:04 PM, Neil Horman wrote: > On Fri, Nov 07, 2014 at 09:28:09AM -0800, Jia Yu wrote: >> Include rte_memory.h for lib files that use __rte_cache_aligned >> attribute. >> >> Signed-off-by: Jia Yu >> > Why? I presume there was a build break or something. Please repost with a > changelog that details what this patch is for. > Neil I don't know if Yu's issue was the same, but I had a very "fun" issue with __rte_cache_aligned in my application. Consider the following code: struct per_core_foo { ... } __rte_cache_aligned; struct global_foo { struct per_core_foo foo[RTE_MAX_CORE]; }; If __rte_cache_aligned is not defined (rte_memory.h is not included), the code compiles but the structure is not aligned... it defines the structure and creates a global variable called __rte_cache_aligned. And this can lead to really bad things if this code is in a .h that is included by files that may or may not include rte_memory.h I have no idea about how we could prevent this issue, except using __attribute__((aligned(CACHE_LINE))) instead of __rte_cache_aligned. Anyway this could probably explain the willing to include rte_memory.h everywhere. Regards, Olivier
[dpdk-dev] [RFC PATCH 00/17] Single virtio implementation
2014-12-09 06:40, Ouyang, Changchun: > > > -Original Message- > > From: Thomas Monjalon [mailto:thomas.monjalon at 6wind.com] > > Sent: Tuesday, December 9, 2014 2:12 PM > > To: Ouyang, Changchun > > Cc: Qiu, Michael; Stephen Hemminger; dev at dpdk.org > > Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio implementation > > > > 2014-12-09 05:41, Ouyang, Changchun: > > > Hi > > > > > > > -Original Message- > > > > From: Qiu, Michael > > > > Sent: Tuesday, December 9, 2014 11:23 AM > > > > To: Ouyang, Changchun; Thomas Monjalon; Stephen Hemminger > > > > Cc: dev at dpdk.org > > > > Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio > > > > implementation > > > > > > > > On 12/9/2014 9:11 AM, Ouyang, Changchun wrote: > > > > > Hi Thomas, > > > > > > > > > >> -Original Message- > > > > >> From: Thomas Monjalon [mailto:thomas.monjalon at 6wind.com] > > > > >> Sent: Monday, December 8, 2014 5:31 PM > > > > >> To: Ouyang, Changchun > > > > >> Cc: dev at dpdk.org > > > > >> Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio > > > > >> implementation > > > > >> > > > > >> Hi Changchun, > > > > >> > > > > >> 2014-12-08 14:21, Ouyang Changchun: > > > > >>> This patch set bases on two original RFC patch sets from Stephen > > > > >> Hemminger[stephen at networkplumber.org] > > > > >>> Refer to > > > > >>> [http://dpdk.org/ml/archives/dev/2014-August/004845.html ] for > > > > >> the original one. > > > > >>> This patch set also resolves some conflict with latest codes and > > > > >>> removed > > > > >> duplicated codes. > > > > >> > > > > >> As you sent the patches, you appear as the author. > > > > >> But I guess Stephen should be the author for some of them. > > > > >> Please check who has contributed the most in each patch to decide. > > > > > You are right, most of patches originate from Stephen's patchset, > > > > > except for the last one, To be honest, I am ok whoever is the > > > > > author of this patch set, :-), We could co-own the feature of > > > > > Single virtio if you all agree with it, and I think we couldn't > > > > > finish Such a feature without collaboration among us, this is why > > > > > I tried to communicate > > > > with most of you to collect more feedback, suggestion and comments > > > > for this feature. > > > > > Very appreciate for all kinds of feedback, suggestion here, > > > > > especially for > > > > patch set from Stephen. > > > > > > > > > > According to your request, how could we make this patch set looks > > > > > more > > > > like Stephen as the author? > > > > > Currently I add Stephen as Signed-off-by list in each patch(I got > > > > > the > > > > agreement from Stephen before doing this :-)). > > > > > > > > Hi Ouyang, > > > > > > > > "Signed-off-by" should be added by himself, because the one who in > > > > the Signed-off-by list should take responsibility for it(like potential > > bugs/issues). > > > > > > > > Although, lots of patches are originate from Stephen, we still need > > > > himself add this line :) > > > > > > Hi Thomas, > > > It that right? I can't add Stephen into Signed-off-by list even if I > > > have gotten the agreement from Stephen, What 's the strict rule here? > > > > Stephen sent the patches with his Signed-off, then you added yours. > > This is OK. > > Using git am, author would have been Stephen. To change author now, you > > can edit each commit with interactive rebase and "git commit --amend -- > > author=Stephen". > > No need to resend now. Please check it for next version of the patchset. > > > > So I understand correctly, Stephen need care for from patches from 1 to 16, > I need care for the 17th patch from next version. > What I mean "caring for" above is: debug and validate them and send out > patches Just to be clear: you can send patches with Stephen's authorship. That's not a problem. Please try to change --author and check how it looks when you send them. -- Thomas
[dpdk-dev] [PATCH] enic: fix of compile error
Compile warnings/errors was found on gcc 4.7.2 as follows. Variables was reported of being used but uninitialized. Assigning an initial value to it is needed. lib/librte_pmd_enic/vnic/vnic_dev.c: In function vnic_dev_get_mac_addr: lib/librte_pmd_enic/vnic/vnic_dev.c:393:16: error: a1 may be used uninitialized in this function [-Werror=uninitialized] lib/librte_pmd_enic/vnic/vnic_dev.c:629:10: note: a1 was declared here lib/librte_pmd_enic/vnic/vnic_dev.c: In function vnic_dev_set_mac_addr: lib/librte_pmd_enic/vnic/vnic_dev.c:393:16: error: a1 may be used uninitialized in this function [-Werror=uninitialized] lib/librte_pmd_enic/vnic/vnic_dev.c:980:10: note: a1 was declared here Signed-off-by: Helin Zhang --- lib/librte_pmd_enic/vnic/vnic_dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/librte_pmd_enic/vnic/vnic_dev.c b/lib/librte_pmd_enic/vnic/vnic_dev.c index b1cd63f..6407994 100644 --- a/lib/librte_pmd_enic/vnic/vnic_dev.c +++ b/lib/librte_pmd_enic/vnic/vnic_dev.c @@ -626,7 +626,7 @@ int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done) int vnic_dev_get_mac_addr(struct vnic_dev *vdev, u8 *mac_addr) { - u64 a0, a1; + u64 a0, a1 = 0; int wait = 1000; int err, i; @@ -977,7 +977,7 @@ struct rte_pci_device *vnic_dev_get_pdev(struct vnic_dev *vdev) int vnic_dev_set_mac_addr(struct vnic_dev *vdev, u8 *mac_addr) { - u64 a0, a1; + u64 a0, a1 = 0; int wait = 1000; int i; -- 1.8.1.4
[dpdk-dev] lib: include rte_memory.h for __rte_cache_aligned
Yes, Olivier?s observation is consistent with ours. Compilation didn?t complain if rte_memory.h is not included. Currently, the lib files indirectly included rte_mbuf.h or rte_mempool.h. These two header files already included rte_memory.h. Therefore without this patch, things still work (as validated by parole). For good practice, it?s better to explicitly include rte_memory.h to avoid the problem. Thanks, Jia On 12/9/14, 12:53 AM, "Olivier MATZ" wrote: >Hi Neil, > >On 12/08/2014 04:04 PM, Neil Horman wrote: >> On Fri, Nov 07, 2014 at 09:28:09AM -0800, Jia Yu wrote: >>> Include rte_memory.h for lib files that use __rte_cache_aligned >>> attribute. >>> >>> Signed-off-by: Jia Yu >>> >> Why? I presume there was a build break or something. Please repost >>with a >> changelog that details what this patch is for. >> Neil > >I don't know if Yu's issue was the same, but I had a very "fun" issue >with __rte_cache_aligned in my application. Consider the following code: > > struct per_core_foo { > ... > } __rte_cache_aligned; > > struct global_foo { > struct per_core_foo foo[RTE_MAX_CORE]; > }; > >If __rte_cache_aligned is not defined (rte_memory.h is not included), >the code compiles but the structure is not aligned... it defines the >structure and creates a global variable called __rte_cache_aligned. >And this can lead to really bad things if this code is in a .h that >is included by files that may or may not include rte_memory.h > >I have no idea about how we could prevent this issue, except using >__attribute__((aligned(CACHE_LINE))) instead of __rte_cache_aligned. > >Anyway this could probably explain the willing to include rte_memory.h >everywhere. > >Regards, >Olivier >
[dpdk-dev] error: value computed is not used
Any other comments on this issue? Thanks, Michael On 12/8/2014 5:07 PM, Qiu, Michael wrote: > Hi all, > My platform is: > > uname -a > Linux suse-11-sp3 3.0.77-0.11-xen #1 SMP Tue Mar 11 16:48:56 CST 2014 > x86_64 x86_64 x86_64 GNU/Linux > > gcc -v > Using built-in specs. > COLLECT_GCC=gcc > COLLECT_LTO_WRAPPER=/usr/lib64/gcc/x86_64-suse-linux/4.5/lto-wrapper > Target: x86_64-suse-linux > Configured with: ../configure --prefix=/usr --infodir=/usr/share/info > --mandir=/usr/share/man --libdir=/usr/lib64 --libexecdir=/usr/lib64 > --enable-languages=c,c++,objc,fortran,obj-c++,java,ada > --enable-checking=release --with-gxx-include-dir=/usr/include/c++/4.5 > --enable-ssp --disable-libssp --disable-plugin > --with-bugurl=http://bugs.opensuse.org/ --with-pkgversion='SUSE Linux' > --disable-libgcj --disable-libmudflap --with-slibdir=/lib64 > --with-system-zlib --enable-__cxa_atexit > --enable-libstdcxx-allocator=new --disable-libstdcxx-pch > --enable-version-specific-runtime-libs --program-suffix=-4.5 > --enable-linux-futex --without-system-libunwind --enable-gold > --with-plugin-ld=/usr/bin/gold --with-arch-32=i586 --with-tune=generic > --build=x86_64-suse-linux > Thread model: posix > gcc version 4.5.1 20101208 [gcc-4_5-branch revision 167585] (SUSE Linux) > > When I try to compile the source code to x86_64 linuxapp, I got this > error message: > > lib/librte_pmd_enic/enic_main.c: In function ?enic_set_rsskey?: > lib/librte_pmd_enic/enic_main.c:862:2: error: value computed is not used > > I dig out that, it was ome issue of the macros rte_memcpy() > #define rte_memcpy(dst, src, n) \ > ((__builtin_constant_p(n)) ? \ > memcpy((dst), (src), (n)) : \ > rte_memcpy_func((dst), (src), (n))) > > When I use only (n) instead of (__builtin_constant_p(n), it will pass( I > know that it was incorrect, just a experiment). > > But I try to use inline function instead of macros: > static inline void * rte_memcpy(void *dst, const void *src, size_t n) > { > return __builtin_constant_p(n) ? memcpy(dst, src, n) : > rte_memcpy_func(dst, src, n); > } > > It will pass:), and works, this could be one potential workaround fix. > > Who knows why? The root cause is what? > > I've no idea about this. > > Thanks, > Michael >
[dpdk-dev] [RFC PATCH 00/17] Single virtio implementation
On Tue, Dec 09, 2014 at 06:40:23AM +, Ouyang, Changchun wrote: > > > > -Original Message- > > From: Thomas Monjalon [mailto:thomas.monjalon at 6wind.com] > > Sent: Tuesday, December 9, 2014 2:12 PM > > To: Ouyang, Changchun > > Cc: Qiu, Michael; Stephen Hemminger; dev at dpdk.org > > Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio implementation > > > > 2014-12-09 05:41, Ouyang, Changchun: > > > Hi > > > > > > > -Original Message- > > > > From: Qiu, Michael > > > > Sent: Tuesday, December 9, 2014 11:23 AM > > > > To: Ouyang, Changchun; Thomas Monjalon; Stephen Hemminger > > > > Cc: dev at dpdk.org > > > > Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio > > > > implementation > > > > > > > > On 12/9/2014 9:11 AM, Ouyang, Changchun wrote: > > > > > Hi Thomas, > > > > > > > > > >> -Original Message- > > > > >> From: Thomas Monjalon [mailto:thomas.monjalon at 6wind.com] > > > > >> Sent: Monday, December 8, 2014 5:31 PM > > > > >> To: Ouyang, Changchun > > > > >> Cc: dev at dpdk.org > > > > >> Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio > > > > >> implementation > > > > >> > > > > >> Hi Changchun, > > > > >> > > > > >> 2014-12-08 14:21, Ouyang Changchun: > > > > >>> This patch set bases on two original RFC patch sets from Stephen > > > > >> Hemminger[stephen at networkplumber.org] > > > > >>> Refer to > > > > >>> [http://dpdk.org/ml/archives/dev/2014-August/004845.html ] for > > > > >> the original one. > > > > >>> This patch set also resolves some conflict with latest codes and > > > > >>> removed > > > > >> duplicated codes. > > > > >> > > > > >> As you sent the patches, you appear as the author. > > > > >> But I guess Stephen should be the author for some of them. > > > > >> Please check who has contributed the most in each patch to decide. > > > > > You are right, most of patches originate from Stephen's patchset, > > > > > except for the last one, To be honest, I am ok whoever is the > > > > > author of this patch set, :-), We could co-own the feature of > > > > > Single virtio if you all agree with it, and I think we couldn't > > > > > finish Such a feature without collaboration among us, this is why > > > > > I tried to communicate > > > > with most of you to collect more feedback, suggestion and comments > > > > for this feature. > > > > > Very appreciate for all kinds of feedback, suggestion here, > > > > > especially for > > > > patch set from Stephen. > > > > > > > > > > According to your request, how could we make this patch set looks > > > > > more > > > > like Stephen as the author? > > > > > Currently I add Stephen as Signed-off-by list in each patch(I got > > > > > the > > > > agreement from Stephen before doing this :-)). > > > > > > > > Hi Ouyang, > > > > > > > > "Signed-off-by" should be added by himself, because the one who in > > > > the Signed-off-by list should take responsibility for it(like potential > > bugs/issues). > > > > > > > > Although, lots of patches are originate from Stephen, we still need > > > > himself add this line :) > > > > > > Hi Thomas, > > > It that right? I can't add Stephen into Signed-off-by list even if I > > > have gotten the agreement from Stephen, What 's the strict rule here? > > > > Stephen sent the patches with his Signed-off, then you added yours. > > This is OK. > > Using git am, author would have been Stephen. To change author now, you > > can edit each commit with interactive rebase and "git commit --amend -- > > author=Stephen". > > No need to resend now. Please check it for next version of the patchset. > > > > So I understand correctly, Stephen need care for from patches from 1 to 16, > I need care for the 17th patch from next version. > What I mean "caring for" above is: debug and validate them and send out > patches > > Thanks > Changchun > Just to clarify Thomas point here about use of "git am". If you get a patch from someone to test or work on, use "git am" to apply it, rather than "git apply", since "git am" generates a commit in your local repo and thereby maintains the original authorship of the patch. If you do "git apply" and subsequently commit yourself, you - rather than the original author - will appear as the "author" of the patch, and you need to amend the commit as Thomas suggests to fix this. So in short: * git am == good * git apply == bad Regards, /Bruce
[dpdk-dev] [PATCH v2] VFIO: Avoid to enable vfio while the module not loaded
Hi Michael, > > Yes, you are right, strncmp() will check 30 bytes if use sizeof(buffer). > > But any issue of strcmp() ? This rountin cares about exactly match. I think no > need to convert to strncmp() if it does have other issue. > > > fscanf with fgets would be better too, to make sure we never go over our > buffer size when dealing with /proc/modules. > > If we use fgets, we need additional efforts to get the modname, for > potential overflow issue, we can limit counts of fscanf(). like below: > > fscanf(fd, "%30s %*[^\n]", mod_name); > As long as it doesn't cause easy buffer overruns, I'm fine with it :-) Thanks, Anatoly
[dpdk-dev] DDPK use of MAP_FIXED in mmap
On Mon, Dec 08, 2014 at 07:02:38PM +, Karmarkar Suyash wrote: > Hello, > > In DPDK when we use mmap why are we passing the MAP_FIXED flag when Linux man > page itself says that the option is discouraged? Any specific reason for > passing the MAP_FIXED flag? > > > http://linux.die.net/man/2/mmap > > MAP_FIXED > Don't interpret addr as a hint: place the mapping at exactly that address. > addr must be a multiple of the page size. If the memory region specified by > addr and len overlaps pages of any existing mapping(s), then the overlapped > part of the existing mapping(s) will be discarded. If the specified address > cannot be used, mmap() will fail. Because requiring a fixed address for a > mapping is less portable, the use of this option is discouraged. > > > Regards > Suyash Karmarkar I won't comment on every occurance of "MAP_FIXED" in DPDK, but it's main use is when mapping the hugepages into memory inside EAL init. In this case, we are ok to use it, as we take good care to ensure that our mapping space is free. What we do is, once we know how many contiguous hugepages we need to map, we request a mapping from /dev/zero for that particular size. We then record the address of the mapping we get, and then unmap /dev/zero again - thereby freeing up the entire address range. At this point, we then use MAP_FIXED to explicitly mmap in the hugepages into this region that we have just freed up - thereby guaranteeing contiguous hugepage mappings in the correct order. [The reason for doing things this way is that we found on some systems - particularly with 32-bit code, the regular mmaps of pages we being done in reverse order, meaning each page became it's own segment]. On the other hand, it's also good to note where we don't use MAP_FIXED. We don't use map fixed when initializing a secondary process and are mapping the hugepage memory into it. In this case, although we know where the memory has to be placed, we don't know if it is safe to use or not. Instead of using MAP_FIXED, we instead hint to the kernel our preferred address and check if the request was satisfied at that address. Hope this clarifies things a bit, /Bruce
[dpdk-dev] [PATCH v2] app/test: fix memory needs after RTE_MAX_LCORE was increased to 128
Since commit b91c67e5a693211862aa7dc3b78630b4e856c2af, maximum number of cores is 128, which has increase the total memory necessary for a rte_mempool structure, as the per-lcore local cache has been doubled in size. Therefore, eal_flags unit test was broken since it needed to use more hugepages. Changes in v2: Increased memory to 18MB, as that is the actual minimum memory necessary (depending on the physical memory segments, DPDK may need less memory) Signed-off-by: Pablo de Lara --- app/test/test_eal_flags.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/app/test/test_eal_flags.c b/app/test/test_eal_flags.c index 6e2a8f2..0a8269c 100644 --- a/app/test/test_eal_flags.c +++ b/app/test/test_eal_flags.c @@ -55,7 +55,7 @@ #ifdef RTE_LIBRTE_XEN_DOM0 #define DEFAULT_MEM_SIZE "30" #else -#define DEFAULT_MEM_SIZE "8" +#define DEFAULT_MEM_SIZE "18" #endif #define mp_flag "--proc-type=secondary" #define no_hpet "--no-hpet" -- 1.7.4.1
[dpdk-dev] [PATCH 11/15] eal/tile: add EAL support for global mPIPE initialization
On Mon, Dec 08, 2014 at 01:32:30PM -0800, Cyril Chemparathy wrote: > Hi Neil, > > > On 12/8/2014 12:03 PM, Neil Horman wrote: > >On Mon, Dec 08, 2014 at 04:59:34PM +0800, Zhigang Lu wrote: > >>The TileGx mPIPE hardware provides Ethernet connectivity, > >>packet classification, and packet load balancing services. > >> > >>Signed-off-by: Zhigang Lu > >>Signed-off-by: Cyril Chemparathy > >>--- > >> .../common/include/arch/tile/rte_mpipe.h | 67 ++ > >> lib/librte_eal/linuxapp/eal/Makefile | 3 + > >> lib/librte_eal/linuxapp/eal/eal.c | 9 ++ > >> lib/librte_eal/linuxapp/eal/eal_mpipe_tile.c | 147 > >> + > >> mk/rte.app.mk | 4 + > >> 5 files changed, 230 insertions(+) > >> create mode 100644 lib/librte_eal/common/include/arch/tile/rte_mpipe.h > >> create mode 100644 lib/librte_eal/linuxapp/eal/eal_mpipe_tile.c > >> > >This seems like the wrong way to implement mpip access. If you want to use > >it > >for networking access, you should create a pmd to talk to it. If you just > >want > >raw gxio access, you already have a gxio library that applications can > >interface > >to. Theres no need to create addtional DPDK api services just to wrap it up, > >especially given that those surfaces won't exist outside of the tile arch > >(i.e. > >this allows for the creation of very non-portable applications). > > Thanks for the taking a look. > > The mPIPE hardware block includes hardware managed buffer pools, which we've > abstracted under the mempool interface in the very next patch in the series. > As a result of this mempool dependency, mPIPE needs to be globally > initialized on TileGX architecture. > Ok, but you already have a mechanism to do that, in that the application can use the gxio library to do the initialization itself, and you don't need to provide additional wrapper calls that are arch specific in a common library. > The alternative is to not include support for the hardware managed buffer > pool, but that decision incurs a significant performance hit. > No, there are plenty of alternatives to just not doing it. In fact, you can create a constructor to do this initialization work, and manage the instance id's so that the user never has to see it Neil > Thanks > -- Cyril. >
[dpdk-dev] [PATCH v3 3/3] doc: add VM power mgmt app
Added new section in sample app UG for the new VM power management app. Signed-off-by: Alan Carew Signed-off-by: Pablo de Lara --- doc/guides/rel_notes/rel_description.rst |2 + doc/guides/sample_app_ug/index.rst |5 + doc/guides/sample_app_ug/vm_power_management.rst | 361 ++ 3 files changed, 368 insertions(+), 0 deletions(-) create mode 100644 doc/guides/sample_app_ug/vm_power_management.rst diff --git a/doc/guides/rel_notes/rel_description.rst b/doc/guides/rel_notes/rel_description.rst index 07c897b..d159b3c 100644 --- a/doc/guides/rel_notes/rel_description.rst +++ b/doc/guides/rel_notes/rel_description.rst @@ -149,6 +149,8 @@ The following is a list of Intel? DPDK documents in the suggested reading order * Kernel NIC Interface (KNI) +* VM Power Management + In addition, there are some other applications that are built when the libraries are created. The source for these applications is in the DPDK/app directory and are called: diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst index db88b0d..c3b50e2 100644 --- a/doc/guides/sample_app_ug/index.rst +++ b/doc/guides/sample_app_ug/index.rst @@ -101,6 +101,7 @@ Copyright ? 2012 - 2014, Intel Corporation. All rights reserved. internet_proto_ip_pipeline test_pipeline dist_app +vm_power_management **Figures** @@ -152,6 +153,10 @@ Copyright ? 2012 - 2014, Intel Corporation. All rights reserved. :ref:`Figure 23.Distributor Sample Application Layout ` +:ref:`Figure 24.High level Solution ` + +:ref:`Figure 25.VM request to scale frequency ` + **Tables** :ref:`Table 1.Output Traffic Marking ` diff --git a/doc/guides/sample_app_ug/vm_power_management.rst b/doc/guides/sample_app_ug/vm_power_management.rst new file mode 100644 index 000..f5b5200 --- /dev/null +++ b/doc/guides/sample_app_ug/vm_power_management.rst @@ -0,0 +1,361 @@ +.. BSD LICENSE +Copyright(c) 2010-2014 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. + +VM Power Management Application +=== + +Introduction + + +Applications running in Virtual Environments have an abstract view of +the underlying hardware on the Host, in particular applications cannot see +the binding of virtual to physical hardware. +When looking at CPU resourcing, the pinning of Virtual CPUs(vCPUs) to +Host Physical CPUs(pCPUS) is not apparent to an application +and this pinning may change over time. +Furthermore, Operating Systems on virtual machines do not have the ability +to govern their own power policy; the Machine Specific Registers (MSRs) +for enabling P-State transitions are not exposed to Operating Systems +running on Virtual Machines(VMs). + +The Virtual Machine Power Management solution shows an example of +how a DPDK application can indicate its processing requirements using VM local +only information(vCPU/lcore) to a Host based Monitor which is responsible +for accepting requests for frequency changes for a vCPU, translating the vCPU +to a pCPU via libvirt and affecting the change in frequency. + +The solution is comprised of two high-level components: + +#. Example Host Application + + Using a Command Line Interface(CLI) for VM->Host communication channel management + allows adding channels to the Monitor, setting and querying the vCPU to pCPU pinning, + inspecting and manually changing t
[dpdk-dev] [PATCH v3 2/3] doc: add vm power mgmt request sequence svg
Added second of the two figures in the VM power management app UG VM power management request sequence Signed-off-by: Alan Carew Signed-off-by: Pablo de Lara --- .../img/vm_power_mgr_vm_request_seq.svg| 927 1 files changed, 927 insertions(+), 0 deletions(-) create mode 100644 doc/guides/sample_app_ug/img/vm_power_mgr_vm_request_seq.svg diff --git a/doc/guides/sample_app_ug/img/vm_power_mgr_vm_request_seq.svg b/doc/guides/sample_app_ug/img/vm_power_mgr_vm_request_seq.svg new file mode 100644 index 000..fe2e0de --- /dev/null +++ b/doc/guides/sample_app_ug/img/vm_power_mgr_vm_request_seq.svg @@ -0,0 +1,927 @@ + + + + +http://purl.org/dc/elements/1.1/"; + xmlns:cc="http://creativecommons.org/ns#"; + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"; + xmlns:svg="http://www.w3.org/2000/svg"; + xmlns="http://www.w3.org/2000/svg"; + xmlns:xlink="http://www.w3.org/1999/xlink"; + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"; + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"; + version="1.1" + width="912.44751" + height="664.9787" + id="svg5187" + inkscape:version="0.48.5 r10040" + sodipodi:docname="vm_power_mgr_vm_request_seq.svg"> + + + +image/svg+xml +http://purl.org/dc/dcmitype/StillImage"; /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Loop: for each epoll event + + + + + + + + + + + + + + + librte_power(VM) + + + +Sequence + + + + + + + + + + + + + + guest_channel(VM) + + + + + + + + + + + + + + + channel_monitor(Host) + + + + + + + + + + + + + + + + channel_manager(Host) + + + + + + + + + + + + + + + + power_manager(Host) + + + + + + + + + + + + + + + process_request + + + + + + + + + + + get_pcpu_mask() + + + + + + + + + + + + + + + pcpu_mask + + + + + + + + + + + + + + + librte_power(Host) + + + + + + + + + + + scale_freq_up(pcpu_mask) + + + + + + + + + + + + + + + rte_power_freq_up() + + + + + + + + + + + + + + + + + + + guest_channel_send_msg() + + + + + + + + + + + status + + + + + + + + + + + status + + + + + + + + + + + + + + + rte_power_freq_up() + + + + + + + + + + + status + + + -- 1.7.4.1
[dpdk-dev] [PATCH v3 0/3] doc: add VM power mgmt app
This patchset adds a new sample app UG, contaning explanation of the new two sample apps added in the VM power management patchset Changes in v3: Scaled svg files Removed trailing whitespaces Replaced directives for code blocks Separate svg files in different commits Fixed numbered lists Changes in v2: Corrected svg files Pablo de Lara (3): doc: add vm power mgmt overview svg doc: add vm power mgmt request sequence svg doc: add VM power mgmt app doc/guides/rel_notes/rel_description.rst |2 + .../sample_app_ug/img/vm_power_mgr_highlevel.svg | 742 .../img/vm_power_mgr_vm_request_seq.svg| 927 doc/guides/sample_app_ug/index.rst |5 + doc/guides/sample_app_ug/vm_power_management.rst | 361 5 files changed, 2037 insertions(+), 0 deletions(-) create mode 100644 doc/guides/sample_app_ug/img/vm_power_mgr_highlevel.svg create mode 100644 doc/guides/sample_app_ug/img/vm_power_mgr_vm_request_seq.svg create mode 100644 doc/guides/sample_app_ug/vm_power_management.rst -- 1.7.4.1
[dpdk-dev] [PATCH v3 1/3] doc: add vm power mgmt overview svg
Added first of the two figures in the VM power management app UG: VM power mangament highlevel overview Signed-off-by: Alan Carew Signed-off-by: Pablo de Lara --- .../sample_app_ug/img/vm_power_mgr_highlevel.svg | 742 1 files changed, 742 insertions(+), 0 deletions(-) create mode 100644 doc/guides/sample_app_ug/img/vm_power_mgr_highlevel.svg diff --git a/doc/guides/sample_app_ug/img/vm_power_mgr_highlevel.svg b/doc/guides/sample_app_ug/img/vm_power_mgr_highlevel.svg new file mode 100644 index 000..bc07dfe --- /dev/null +++ b/doc/guides/sample_app_ug/img/vm_power_mgr_highlevel.svg @@ -0,0 +1,742 @@ + +http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd";> + + + + +http://www.w3.org/2000/svg"; xmlns:xlink="http://www.w3.org/1999/xlink"; xmlns:ev="http://www.w3.org/2001/xml-events"; + width="7.96928in" height="6.37479in" viewBox="0 0 573.788 458.985" xml:space="preserve" color-interpolation-filters="sRGB" + class="st28"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Page-1 + + Box +
[dpdk-dev] [PATCH v2 0/3] enhance TX checksum command and csum forwarding engine
In the current codes, the "tx_checksum set (ip|udp|tcp|sctp|vxlan) (hw|sw) (port-id)" command is not easy to understand and extend, so the patch set enhances the tx_checksum command and reworks csum forwarding engine due to the change of tx_checksum command. The main changes of the tx_checksum command are listed below, 1> add "tx_checksum set tunnel (hw|sw|none) (port-id)" command The command is used to set/clear tunnel flag that is used to tell the NIC that the packetg is a tunneing packet and application want hardware TX checksum offload for outer layer, or inner layer, or both. The 'none' option means that user treat tunneling packet as ordinary packet when using the csum forward engine. for example, let say we have a tunnel packet: eth_hdr_out/ipv4_hdr_out/udp_hdr_out/vxlan_hdr/ehtr_hdr_in/ipv4_hdr_in/tcp_hdr_in. one of several scenarios: 1) User requests HW offload for ipv4_hdr_out checksum, and doesn't care is it a tunnelled packet or not. So he sets: tx_checksum set tunnel none 0 tx_checksum set ip hw 0 So for such case we should set tx_tunnel to 'none'. 2> add "tx_checksum set outer-ip (hw|sw) (port-id)" command The command is used to set/clear outer IP flag that is used to tell the NIC that application want hardware offload for outer layer. 3> remove the 'vxlan' option from the "tx_checksum set (ip|udp|tcp|sctp|vxlan) (hw|sw) (port-id)" command The command is used to set IP, UDP, TCP and SCTP TX checksum flag. In the case of tunneling packet, the IP, UDP, TCP and SCTP flags always concern inner layer. Moreover, replace the TESTPMD_TX_OFFLOAD_VXLAN_CKSUM flag with TESTPMD_TX_OFFLOAD_TUNNEL_CKSUM flag and add the TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM and TESTPMD_TX_OFFLOAD_NON_TUNNEL_CKSUM flag in test-pmd application. v2 change: redefine the 'none' behaviour for "tx_checksum set tunnel (hw|sw|none) (port-id)" command. Jijiang Liu (3): add outer IP offload capability in librte_ether. add outer IP checksum capability in i40e PMD testpmd command lines of the tx_checksum and csum forwarding rework app/test-pmd/cmdline.c| 201 +++-- app/test-pmd/csumonly.c | 35 --- app/test-pmd/testpmd.h|6 +- lib/librte_ether/rte_ethdev.h |1 + lib/librte_pmd_i40e/i40e_ethdev.c |3 +- 5 files changed, 218 insertions(+), 28 deletions(-) -- 1.7.7.6
[dpdk-dev] [PATCH v2 1/3] librte_ether:add outer IP offload capability flag
If the flag is set in a PMD, which means the NIC(s) support TX checksum offload of tunneling packet. Signed-off-by: Jijiang Liu --- lib/librte_ether/rte_ethdev.h |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index f66805d..bae59c3 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -916,6 +916,7 @@ struct rte_eth_conf { #define DEV_TX_OFFLOAD_SCTP_CKSUM 0x0010 #define DEV_TX_OFFLOAD_TCP_TSO 0x0020 #define DEV_TX_OFFLOAD_UDP_TSO 0x0040 +#define DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM 0x0080 /**< Used for tunneling packet. */ struct rte_eth_dev_info { struct rte_pci_device *pci_dev; /**< Device PCI information. */ -- 1.7.7.6
[dpdk-dev] [PATCH v2 3/3] app/testpmd:change tx_checksum command and csum forwarding engine
The patch enhances the tx_checksum command and reworks csum forwarding engine due to the change of tx_checksum command. The main changes of the tx_checksum command are listed below, 1. add "tx_checksum set tunnel (hw|sw|none) (port-id)" command 2. add "tx_checksum set outer-ip (hw|sw) (port-id)" command 3. remove the "vxlan" option from the "tx_checksum set(ip|udp|tcp|sctp|vxlan) (hw|sw) (port-id)" command Moreover, replace the TESTPMD_TX_OFFLOAD_VXLAN_CKSUM flag with TESTPMD_TX_OFFLOAD_TUNNEL_CKSUM flag, and add the TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM and TESTPMD_TX_OFFLOAD_NON_TUNNEL_CKSUM flag. Signed-off-by: Jijiang Liu --- app/test-pmd/cmdline.c | 209 --- app/test-pmd/csumonly.c | 38 ++--- app/test-pmd/testpmd.h | 14 +++- 3 files changed, 234 insertions(+), 27 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index f79ea3e..9bfa9ef 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -316,16 +316,30 @@ static void cmd_help_long_parsed(void *parsed_result, "Disable hardware insertion of a VLAN header in" " packets sent on a port.\n\n" - "tx_cksum set (ip|udp|tcp|sctp|vxlan) (hw|sw) (port_id)\n" + "tx_cksum set (ip|udp|tcp|sctp) (hw|sw) (port_id)\n" "Select hardware or software calculation of the" " checksum with when transmitting a packet using the" " csum forward engine.\n" - "ip|udp|tcp|sctp always concern the inner layer.\n" - "vxlan concerns the outer IP and UDP layer (in" - " case the packet is recognized as a vxlan packet by" - " the forward engine)\n" + "In the case of tunneling packet, ip|udp|tcp|sctp" + " always concern the inner layer.\n\n" + + "tx_cksum set tunnel (hw|sw|none) (port_id)\n" + " Select hardware or software calculation of the" + " checksum with when transmitting a tunneling packet" + " using the csum forward engine.\n" + " The none option means treat tunneling packet as ordinary + " packet when using the csum forward engine. + "Tunneling packet concerns the outer IP, inner IP" + " and inner L4\n" "Please check the NIC datasheet for HW limits.\n\n" + "tx_cksum set (outer-ip) (hw|sw) (port_id)\n" + "Select hardware or software calculation of the" + " checksum with when transmitting a packet using the" + " csum forward engine.\n" + "outer-ip always concern the outer layer of" + " tunneling packet.\n\n" + "tx_checksum show (port_id)\n" "Display tx checksum offload configuration\n\n" @@ -2861,6 +2875,181 @@ cmdline_parse_inst_t cmd_tx_vlan_reset = { }, }; +/* ENABLE HARDWARE INSERTION OF CHECKSUM IN TX PACKETS FOR TUNNELING */ +struct cmd_tx_cksum_tunnel_result { + cmdline_fixed_string_t tx_cksum; + cmdline_fixed_string_t mode; + cmdline_fixed_string_t type; + cmdline_fixed_string_t hwsw; + uint8_t port_id; +}; + +static void +cmd_tx_cksum_tunnel_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_tx_cksum_tunnel_result *res = parsed_result; + int hw = 0; + uint16_t ol_flags, mask = 0; + + if (port_id_is_invalid(res->port_id)) { + printf("invalid port %d\n", res->port_id); + return; + } + + if (!strcmp(res->mode, "set")) { + + if (!strcmp(res->hwsw, "hw")) + hw = 1; + else if (!strcmp(res->hwsw, "none")) { + ports[res->port_id].tx_ol_flags &= + ~(TESTPMD_TX_OFFLOAD_TUNNEL_CKSUM + | TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM); + ports[res->port_id].tx_ol_flags |= + TESTPMD_TX_OFFLOAD_NON_TUNNEL_CKSUM; + return; + } + + ports[res->port_id].tx_ol_flags &= + ~TESTPMD_TX_OFFLOAD_NON_TUNNEL_CKSUM; + mask = TESTPMD_TX_OFFLOAD_TUNNEL_CKSUM; + + if (hw) + ports[res->port_id].tx_ol_flags |= mask; + else + ports[res->port_id].tx_ol_flags &= (~mask); + } + + ol_flags = ports[res->port_id].tx_ol_flags; + printf("
[dpdk-dev] [PATCH v2 2/3] i40e:support outer IPv4 checksum capability
The DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM flag is added in i40e capability set, which means the i40e supports TX checksum offload of tunneling packet. Signed-off-by: Jijiang Liu --- lib/librte_pmd_i40e/i40e_ethdev.c |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c index 87e750a..deddd0b 100644 --- a/lib/librte_pmd_i40e/i40e_ethdev.c +++ b/lib/librte_pmd_i40e/i40e_ethdev.c @@ -1491,7 +1491,8 @@ i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM | DEV_TX_OFFLOAD_TCP_CKSUM | - DEV_TX_OFFLOAD_SCTP_CKSUM; + DEV_TX_OFFLOAD_SCTP_CKSUM | + DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM; dev_info->reta_size = pf->hash_lut_size; dev_info->default_rxconf = (struct rte_eth_rxconf) { -- 1.7.7.6
[dpdk-dev] [PATCH] doc: fix typos in ring lib
Ring library section in PG had a couple of typos, in the text and in one of the images Signed-off-by: Pablo de Lara --- doc/guides/prog_guide/img/ring-modulo1.svg |2 +- doc/guides/prog_guide/ring_lib.rst |2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/guides/prog_guide/img/ring-modulo1.svg b/doc/guides/prog_guide/img/ring-modulo1.svg index 768318d..614b7bf 100644 --- a/doc/guides/prog_guide/img/ring-modulo1.svg +++ b/doc/guides/prog_guide/img/ring-modulo1.svg @@ -785,7 +785,7 @@ sodipodi:role="line" x="78.791893" y="528.97369" - id="tspan5287">free_entries = (mask + ct - ph) % 65536 = 8383 + id="tspan5287">free_entries = (mask + ct - ph) % 65536 = 5383 prod_head* and ring->cons_tail are copied in local variabl The prod_next local variable points to the next element of the table, or several elements after in the case of bulk enqueue. -If there are not enough objects in the ring (this is detected by checking cons_tail), it returns an error. +If there is not enough room in the ring (this is detected by checking cons_tail), it returns an error. .. image12_png has been replaced -- 1.7.4.1
[dpdk-dev] [PATCH 12/15] eal/tile: add mPIPE buffer stack mempool provider
On Mon, Dec 08, 2014 at 04:59:35PM +0800, Zhigang Lu wrote: > TileGX: Modified mempool to allow for variable metadata. > Signed-off-by: Zhigang Lu > Signed-off-by: Cyril Chemparathy > --- > app/test-pmd/mempool_anon.c | 2 +- > app/test/Makefile | 6 +- > app/test/test_mempool_tile.c | 217 > lib/Makefile | 5 + > lib/librte_eal/linuxapp/eal/Makefile | 4 + > lib/librte_mempool_tile/Makefile | 48 +++ > lib/librte_mempool_tile/rte_mempool.c | 381 > lib/librte_mempool_tile/rte_mempool.h | 634 > ++ > 8 files changed, 1295 insertions(+), 2 deletions(-) > create mode 100644 app/test/test_mempool_tile.c > create mode 100644 lib/librte_mempool_tile/Makefile > create mode 100644 lib/librte_mempool_tile/rte_mempool.c > create mode 100644 lib/librte_mempool_tile/rte_mempool.h > NAK, this creates an alternate, parallel implementation of the mempool api, that re-implements some aspects of the mempool api, but not others. This will make for completely no-portable applications (both to and from the tile arch), and create maintnence problems, in that features for mempool will need to be implemented in multiple libraries. I understand wanting to use mpipe, and thats perfectly fine, but creating no-portable apis to do so isn't the right way to go. Instead, why not just allow applications to use mpipe by initalizing it via the gxio library and crating a mempool using the existing libraries' rte_mempool_xmem_create api call, which allows for existing allocated memory space to be managed as a mempool? Neil
[dpdk-dev] [RFC PATCH 00/17] Single virtio implementation
Hi Bruce, > -Original Message- > From: Richardson, Bruce > Sent: Tuesday, December 9, 2014 5:47 PM > To: Ouyang, Changchun > Cc: Thomas Monjalon; dev at dpdk.org > Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio implementation > > On Tue, Dec 09, 2014 at 06:40:23AM +, Ouyang, Changchun wrote: > > > > > > > -Original Message- > > > From: Thomas Monjalon [mailto:thomas.monjalon at 6wind.com] > > > Sent: Tuesday, December 9, 2014 2:12 PM > > > To: Ouyang, Changchun > > > Cc: Qiu, Michael; Stephen Hemminger; dev at dpdk.org > > > Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio > > > implementation > > > > > > 2014-12-09 05:41, Ouyang, Changchun: > > > > Hi > > > > > > > > > -Original Message- > > > > > From: Qiu, Michael > > > > > Sent: Tuesday, December 9, 2014 11:23 AM > > > > > To: Ouyang, Changchun; Thomas Monjalon; Stephen Hemminger > > > > > Cc: dev at dpdk.org > > > > > Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio > > > > > implementation > > > > > > > > > > On 12/9/2014 9:11 AM, Ouyang, Changchun wrote: > > > > > > Hi Thomas, > > > > > > > > > > > >> -Original Message- > > > > > >> From: Thomas Monjalon [mailto:thomas.monjalon at 6wind.com] > > > > > >> Sent: Monday, December 8, 2014 5:31 PM > > > > > >> To: Ouyang, Changchun > > > > > >> Cc: dev at dpdk.org > > > > > >> Subject: Re: [dpdk-dev] [RFC PATCH 00/17] Single virtio > > > > > >> implementation > > > > > >> > > > > > >> Hi Changchun, > > > > > >> > > > > > >> 2014-12-08 14:21, Ouyang Changchun: > > > > > >>> This patch set bases on two original RFC patch sets from > > > > > >>> Stephen > > > > > >> Hemminger[stephen at networkplumber.org] > > > > > >>> Refer to > > > > > >>> [http://dpdk.org/ml/archives/dev/2014-August/004845.html ] > > > > > >>> for > > > > > >> the original one. > > > > > >>> This patch set also resolves some conflict with latest codes > > > > > >>> and removed > > > > > >> duplicated codes. > > > > > >> > > > > > >> As you sent the patches, you appear as the author. > > > > > >> But I guess Stephen should be the author for some of them. > > > > > >> Please check who has contributed the most in each patch to > decide. > > > > > > You are right, most of patches originate from Stephen's > > > > > > patchset, except for the last one, To be honest, I am ok > > > > > > whoever is the author of this patch set, :-), We could co-own > > > > > > the feature of Single virtio if you all agree with it, and I > > > > > > think we couldn't finish Such a feature without collaboration > > > > > > among us, this is why I tried to communicate > > > > > with most of you to collect more feedback, suggestion and > > > > > comments for this feature. > > > > > > Very appreciate for all kinds of feedback, suggestion here, > > > > > > especially for > > > > > patch set from Stephen. > > > > > > > > > > > > According to your request, how could we make this patch set > > > > > > looks more > > > > > like Stephen as the author? > > > > > > Currently I add Stephen as Signed-off-by list in each patch(I > > > > > > got the > > > > > agreement from Stephen before doing this :-)). > > > > > > > > > > Hi Ouyang, > > > > > > > > > > "Signed-off-by" should be added by himself, because the one who > > > > > in the Signed-off-by list should take responsibility for it(like > > > > > potential > > > bugs/issues). > > > > > > > > > > Although, lots of patches are originate from Stephen, we still > > > > > need himself add this line :) > > > > > > > > Hi Thomas, > > > > It that right? I can't add Stephen into Signed-off-by list even if > > > > I have gotten the agreement from Stephen, What 's the strict rule here? > > > > > > Stephen sent the patches with his Signed-off, then you added yours. > > > This is OK. > > > Using git am, author would have been Stephen. To change author now, > > > you can edit each commit with interactive rebase and "git commit > > > --amend -- author=Stephen". > > > No need to resend now. Please check it for next version of the patchset. > > > > > > > So I understand correctly, Stephen need care for from patches from 1 > > to 16, I need care for the 17th patch from next version. > > What I mean "caring for" above is: debug and validate them and send > > out patches > > > > Thanks > > Changchun > > > Just to clarify Thomas point here about use of "git am". If you get a patch > from someone to test or work on, use "git am" to apply it, rather than "git > apply", since "git am" generates a commit in your local repo and thereby > maintains the original authorship of the patch. If you do "git apply" and > subsequently commit yourself, you - rather than the original author - will > appear as the "author" of the patch, and you need to amend the commit as > Thomas suggests to fix this. > > So in short: > * git am == good > * git apply == bad Thanks very much for the clarification. I will use git am for next version. Changchun
[dpdk-dev] [PATCH v3 03/28] eal/pci: Replace pci address comparison code by eal_compare_pci_addr
On 2014/12/9 14:32, Tetsuya Mukawa wrote: > This patch replaces pci_addr_comparison() and memcmp() of pci addresses by > eal_compare_pci_addr(). > > Signed-off-by: Tetsuya Mukawa > --- > lib/librte_eal/bsdapp/eal/eal_pci.c | 16 +--- > lib/librte_eal/common/eal_common_pci.c| 2 +- > lib/librte_eal/common/include/rte_pci.h | 29 + > lib/librte_eal/linuxapp/eal/eal_pci.c | 16 +--- > lib/librte_eal/linuxapp/eal/eal_pci_uio.c | 2 +- > 5 files changed, 33 insertions(+), 32 deletions(-) > > diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c > b/lib/librte_eal/bsdapp/eal/eal_pci.c > index 74ecce7..7eda513 100644 > --- a/lib/librte_eal/bsdapp/eal/eal_pci.c > +++ b/lib/librte_eal/bsdapp/eal/eal_pci.c > @@ -270,20 +270,6 @@ pci_uio_map_resource(struct rte_pci_device *dev) > return (0); > } > > -/* Compare two PCI device addresses. */ > -static int > -pci_addr_comparison(struct rte_pci_addr *addr, struct rte_pci_addr *addr2) > -{ > - uint64_t dev_addr = (addr->domain << 24) + (addr->bus << 16) + > (addr->devid << 8) + addr->function; > - uint64_t dev_addr2 = (addr2->domain << 24) + (addr2->bus << 16) + > (addr2->devid << 8) + addr2->function; > - > - if (dev_addr > dev_addr2) > - return 1; > - else > - return 0; > -} > - > - > /* Scan one pci sysfs entry, and fill the devices list from it. */ > static int > pci_scan_one(int dev_pci_fd, struct pci_conf *conf) > @@ -358,7 +344,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf) > struct rte_pci_device *dev2 = NULL; > > TAILQ_FOREACH(dev2, &pci_device_list, next) { > - if (pci_addr_comparison(&dev->addr, &dev2->addr)) > + if (eal_compare_pci_addr(&dev->addr, &dev2->addr)) > continue; > else { > TAILQ_INSERT_BEFORE(dev2, dev, next); > diff --git a/lib/librte_eal/common/eal_common_pci.c > b/lib/librte_eal/common/eal_common_pci.c > index f3c7f71..f01f258 100644 > --- a/lib/librte_eal/common/eal_common_pci.c > +++ b/lib/librte_eal/common/eal_common_pci.c > @@ -93,7 +93,7 @@ static struct rte_devargs *pci_devargs_lookup(struct > rte_pci_device *dev) > if (devargs->type != RTE_DEVTYPE_BLACKLISTED_PCI && > devargs->type != RTE_DEVTYPE_WHITELISTED_PCI) > continue; > - if (!memcmp(&dev->addr, &devargs->pci.addr, sizeof(dev->addr))) > + if (eal_compare_pci_addr(&dev->addr, &devargs->pci.addr)) > return devargs; > } > return NULL; > diff --git a/lib/librte_eal/common/include/rte_pci.h > b/lib/librte_eal/common/include/rte_pci.h > index b819539..fe374a8 100644 > --- a/lib/librte_eal/common/include/rte_pci.h > +++ b/lib/librte_eal/common/include/rte_pci.h > @@ -261,6 +261,35 @@ eal_parse_pci_DomBDF(const char *input, struct > rte_pci_addr *dev_addr) > } > #undef GET_PCIADDR_FIELD > > +/* Compare two PCI device addresses. */ > +/** > + * Utility function to compare two PCI device addresses. > + * > + * @param addr > + * The PCI Bus-Device-Function address to compare > + * @param addr2 > + * The PCI Bus-Device-Function address to compare > + * @return > + * 0 on equal PCI address. > + * Positive on addr is greater than addr2. > + * Negative on addr is less than addr2. > + */ > +static inline int > +eal_compare_pci_addr(struct rte_pci_addr *addr, struct rte_pci_addr *addr2) > +{ > + uint64_t dev_addr = (addr->domain << 24) + (addr->bus << 16) + > + (addr->devid << 8) + addr->function; > + uint64_t dev_addr2 = (addr2->domain << 24) + (addr2->bus << 16) + > + (addr2->devid << 8) + addr2->function; > + Here I prefer: uint64_t dev_addr = (addr->domain << 24) | (addr->bus << 16) | (addr->devid << 8) | addr->function; Thanks, Michael > + if (dev_addr > dev_addr2) > + return 1; > + else if (dev_addr < dev_addr2) > + return -1; > + else > + return 0; > +} > + > /** > * Probe the PCI bus for registered drivers. > * > diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c > b/lib/librte_eal/linuxapp/eal/eal_pci.c > index b5f5410..23a69e9 100644 > --- a/lib/librte_eal/linuxapp/eal/eal_pci.c > +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c > @@ -200,20 +200,6 @@ error: > return -1; > } > > -/* Compare two PCI device addresses. */ > -static int > -pci_addr_comparison(struct rte_pci_addr *addr, struct rte_pci_addr *addr2) > -{ > - uint64_t dev_addr = (addr->domain << 24) + (addr->bus << 16) + > (addr->devid << 8) + addr->function; > - uint64_t dev_addr2 = (addr2->domain << 24) + (addr2->bus << 16) + > (addr2->devid << 8) + addr2->function; > - > - if (dev_addr > dev_addr2) > - return 1; > - else > - return 0; > -}
[dpdk-dev] [PATCH v3 07/28] ethdev: Add functions to know which port is attached or detached
On 2014/12/9 14:32, Tetsuya Mukawa wrote: > The patch adds rte_eth_dev_save() and rte_eth_dev_get_changed_port(). > rte_eth_dev_save() is used for saving current rte_eth_dev structures. > rte_eth_dev_get_changed_port() receives the rte_eth_dev structures, then > compare these with current values to know which port is actually > attached or detached. > > Signed-off-by: Tetsuya Mukawa > --- > lib/librte_ether/rte_ethdev.c | 21 + > lib/librte_ether/rte_ethdev.h | 21 + > 2 files changed, 42 insertions(+) > > diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c > index 51697e1..6a3700e 100644 > --- a/lib/librte_ether/rte_ethdev.c > +++ b/lib/librte_ether/rte_ethdev.c > @@ -416,6 +416,27 @@ rte_eth_dev_count(void) > return (nb_ports); > } > > +void > +rte_eth_dev_save(struct rte_eth_dev *devs) > +{ > + if (devs == NULL) > + return; > + > + /* save current rte_eth_devices */ > + memcpy(devs, rte_eth_devices, > + sizeof(struct rte_eth_dev) * RTE_MAX_ETHPORTS); > +} > + > +int > +rte_eth_dev_get_changed_port(struct rte_eth_dev *devs, uint8_t *port_id) > +{ > + /* check which port was attached or detached */ > + for (*port_id = 0; *port_id < RTE_MAX_ETHPORTS; (*port_id)++, devs++) > + if (rte_eth_devices[*port_id].attached ^ devs->attached) > + return 0; Can we have more than one port changed? If so, your logic should do little modify. Thanks, Michael > + return 1; > +} > + > static int > rte_eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) > { > diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h > index b329e11..03c8850 100644 > --- a/lib/librte_ether/rte_ethdev.h > +++ b/lib/librte_ether/rte_ethdev.h > @@ -1642,6 +1642,27 @@ extern struct rte_eth_dev rte_eth_devices[]; > extern uint8_t rte_eth_dev_count(void); > > /** > + * Function for internal use by port hotplug functions. > + * Copies current ethdev structures to the specified pointer. > + * > + * @paramdevsThe pointer to the ethdev structures > + */ > +extern void rte_eth_dev_save(struct rte_eth_dev *devs); > + > +/** > + * Function for internal use by port hotplug functions. > + * Compare the specified ethdev structures with currents. Then > + * if there is a port which status is changed, fill the specified pointer > + * with the port id of that port. > + * @paramdevsThe pointer to the ethdev structures > + * @paramport_id The pointer to the port id > + * @return > + * - 0 on success, negative on error > + */ > +extern int rte_eth_dev_get_changed_port( > + struct rte_eth_dev *devs, uint8_t *port_id); > + > +/** > * Function for internal use by dummy drivers primarily, e.g. ring-based > * driver. > * Allocates a new ethdev slot for an ethernet device and returns the pointer
[dpdk-dev] [PATCH v2 0/3] enhance TX checksum command and csum forwarding engine
> From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Jijiang Liu > Sent: Tuesday, December 09, 2014 1:18 PM > To: dev at dpdk.org > Subject: [dpdk-dev] [PATCH v2 0/3] enhance TX checksum command and csum > forwarding engine > > In the current codes, the "tx_checksum set (ip|udp|tcp|sctp|vxlan) (hw|sw) > (port-id)" command is not easy to understand and > extend, so the patch set enhances the tx_checksum command and reworks csum > forwarding engine due to the change of > tx_checksum command. > The main changes of the tx_checksum command are listed below, > > 1> add "tx_checksum set tunnel (hw|sw|none) (port-id)" command > > The command is used to set/clear tunnel flag that is used to tell the NIC > that the packetg is a tunneing packet and application want > hardware TX checksum offload for outer layer, or inner layer, or both. > > The 'none' option means that user treat tunneling packet as ordinary packet > when using the csum forward engine. > for example, let say we have a tunnel packet: > eth_hdr_out/ipv4_hdr_out/udp_hdr_out/vxlan_hdr/ehtr_hdr_in/ipv4_hdr_in/tcp_hdr_in. > one of several scenarios: > > 1) User requests HW offload for ipv4_hdr_out checksum, and doesn't care is > it a tunnelled packet or not. So he sets: > > tx_checksum set tunnel none 0 > > tx_checksum set ip hw 0 > > So for such case we should set tx_tunnel to 'none'. > > 2> add "tx_checksum set outer-ip (hw|sw) (port-id)" command > > The command is used to set/clear outer IP flag that is used to tell the NIC > that application want hardware offload for outer layer. > > 3> remove the 'vxlan' option from the "tx_checksum set > (ip|udp|tcp|sctp|vxlan) (hw|sw) (port-id)" command > > The command is used to set IP, UDP, TCP and SCTP TX checksum flag. In the > case of tunneling packet, the IP, UDP, TCP and SCTP flags > always concern inner layer. > > Moreover, replace the TESTPMD_TX_OFFLOAD_VXLAN_CKSUM flag with > TESTPMD_TX_OFFLOAD_TUNNEL_CKSUM flag and add the > TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM and TESTPMD_TX_OFFLOAD_NON_TUNNEL_CKSUM > flag in test-pmd application. > > v2 change: > redefine the 'none' behaviour for "tx_checksum set tunnel (hw|sw|none) > (port-id)" command. > > Jijiang Liu (3): > add outer IP offload capability in librte_ether. > add outer IP checksum capability in i40e PMD > testpmd command lines of the tx_checksum and csum forwarding rework > > app/test-pmd/cmdline.c| 201 > +++-- > app/test-pmd/csumonly.c | 35 --- > app/test-pmd/testpmd.h|6 +- > lib/librte_ether/rte_ethdev.h |1 + > lib/librte_pmd_i40e/i40e_ethdev.c |3 +- > 5 files changed, 218 insertions(+), 28 deletions(-) > Acked-by: Konstantin Ananyev > -- > 1.7.7.6