[v6,05/10] vhost: checkout and cleanup the resubmit inflight information

Message ID 20190829141224.49700-6-jin.yu@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Maxime Coquelin
Headers
Series vhost: support inflight share memory protocol feature |

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation fail Compilation issues

Commit Message

Jin Yu Aug. 29, 2019, 2:12 p.m. UTC
  This patch shows how to checkout the inflight ring and construct
the resubmit information also include destroying resubmit info.

Signed-off-by: Lin Li <lilin24@baidu.com>
Signed-off-by: Xun Ni <nixun@baidu.com>
Signed-off-by: Yu Zhang <zhangyu31@baidu.com>
Signed-off-by: Jin Yu <jin.yu@intel.com>
---
 lib/librte_vhost/rte_vhost.h  |  19 ++++
 lib/librte_vhost/vhost.c      |  29 ++++-
 lib/librte_vhost/vhost.h      |   9 ++
 lib/librte_vhost/vhost_user.c | 197 ++++++++++++++++++++++++++++++++++
 4 files changed, 253 insertions(+), 1 deletion(-)
  

Comments

Maxime Coquelin Sept. 9, 2019, 10:20 a.m. UTC | #1
On 8/29/19 4:12 PM, JinYu wrote:
> This patch shows how to checkout the inflight ring and construct
> the resubmit information also include destroying resubmit info.
> 
> Signed-off-by: Lin Li <lilin24@baidu.com>
> Signed-off-by: Xun Ni <nixun@baidu.com>
> Signed-off-by: Yu Zhang <zhangyu31@baidu.com>
> Signed-off-by: Jin Yu <jin.yu@intel.com>
> ---
>  lib/librte_vhost/rte_vhost.h  |  19 ++++
>  lib/librte_vhost/vhost.c      |  29 ++++-
>  lib/librte_vhost/vhost.h      |   9 ++
>  lib/librte_vhost/vhost_user.c | 197 ++++++++++++++++++++++++++++++++++
>  4 files changed, 253 insertions(+), 1 deletion(-)
> 
...
> +static int
> +vhost_check_queue_inflights_packed(struct virtio_net *dev,
> +						 struct vhost_virtqueue *vq)
> +{
> +	uint16_t i = 0;
> +	uint16_t resubmit_num = 0, old_used_idx, num;
> +	struct rte_vhost_resubmit_info *resubmit = NULL;
> +	struct inflight_info_packed *inflight_packed;
> +
> +	if (!(dev->protocol_features &
> +		(1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)))
> +		return RTE_VHOST_MSG_RESULT_OK;
> +
> +	if (!vq->inflight_packed->version) {
> +		vq->inflight_packed->version = INFLIGHT_VERSION;
> +		return RTE_VHOST_MSG_RESULT_OK;
> +	}
> +
> +	if ((!vq->inflight_packed))
> +		return RTE_VHOST_MSG_RESULT_ERR;

It needs to be checked before before being dereferenced.

> +
> +	inflight_packed = vq->inflight_packed;
> +	vq->resubmit_inflight = NULL;
> +	vq->global_counter = 0;
> +	old_used_idx = inflight_packed->old_used_idx;
> +
> +	if (inflight_packed->used_idx != old_used_idx) {
> +		if (inflight_packed->desc[old_used_idx].inflight == 0) {
> +			inflight_packed->old_used_idx =
> +				inflight_packed->used_idx;
> +			inflight_packed->old_used_wrap_counter =
> +				inflight_packed->used_wrap_counter;
> +			inflight_packed->old_free_head =
> +				inflight_packed->free_head;
> +		} else {
> +			inflight_packed->used_idx =
> +				inflight_packed->old_used_idx;
> +			inflight_packed->used_wrap_counter =
> +				inflight_packed->old_used_wrap_counter;
> +			inflight_packed->free_head =
> +				inflight_packed->old_free_head;
> +		}
> +	}
> +
> +	for (i = 0; i < inflight_packed->desc_num; i++) {
> +		if (inflight_packed->desc[i].inflight == 1)
> +			resubmit_num++;
> +	}
> +
> +	if (resubmit_num) {
> +		resubmit = calloc(1, sizeof(struct rte_vhost_resubmit_info));
> +		if (resubmit == NULL) {
> +			RTE_LOG(ERR, VHOST_CONFIG,
> +			 "Failed to allocate memory for resubmit info.\n");
> +			return RTE_VHOST_MSG_RESULT_ERR;
> +		}
> +
> +		resubmit->resubmit_list = calloc(resubmit_num,
> +			sizeof(struct rte_vhost_resubmit_desc));
> +		if (resubmit->resubmit_list == NULL) {
> +			RTE_LOG(ERR, VHOST_CONFIG,
> +			 "Failed to allocate memory for resubmit desc.\n");
> +			return RTE_VHOST_MSG_RESULT_ERR;
> +		}
> +
> +		num = 0;
> +		for (i = 0; i < inflight_packed->desc_num; i++) {
> +			if (vq->inflight_packed->desc[i].inflight == 1) {
> +				resubmit->resubmit_list[num].index = i;
> +				resubmit->resubmit_list[num].counter =
> +					inflight_packed->desc[i].counter;
> +				num++;
> +			}
> +		}
> +		resubmit->resubmit_num = num;
> +
> +		if (resubmit->resubmit_num > 1)
> +			qsort(resubmit->resubmit_list, resubmit->resubmit_num,
> +				sizeof(struct rte_vhost_resubmit_desc),
> +				resubmit_desc_compare);
> +
> +		vq->global_counter = resubmit->resubmit_list[0].counter + 1;
> +		vq->resubmit_inflight = resubmit;
> +	}
> +
> +	return RTE_VHOST_MSG_RESULT_OK;
> +}
  
Jin Yu Sept. 11, 2019, 2:50 a.m. UTC | #2
> -----Original Message-----
> From: Maxime Coquelin [mailto:maxime.coquelin@redhat.com]
> Sent: Monday, September 9, 2019 6:21 PM
> To: Yu, Jin <jin.yu@intel.com>; dev@dpdk.org
> Cc: Liu, Changpeng <changpeng.liu@intel.com>; Bie, Tiwei
> <tiwei.bie@intel.com>; Wang, Zhihong <zhihong.wang@intel.com>; Lin Li
> <lilin24@baidu.com>; Xun Ni <nixun@baidu.com>; Yu Zhang
> <zhangyu31@baidu.com>
> Subject: Re: [PATCH v6 05/10] vhost: checkout and cleanup the resubmit inflight
> information
> 
> 
> 
> On 8/29/19 4:12 PM, JinYu wrote:
> > This patch shows how to checkout the inflight ring and construct the
> > resubmit information also include destroying resubmit info.
> >
> > Signed-off-by: Lin Li <lilin24@baidu.com>
> > Signed-off-by: Xun Ni <nixun@baidu.com>
> > Signed-off-by: Yu Zhang <zhangyu31@baidu.com>
> > Signed-off-by: Jin Yu <jin.yu@intel.com>
> > ---
> >  lib/librte_vhost/rte_vhost.h  |  19 ++++
> >  lib/librte_vhost/vhost.c      |  29 ++++-
> >  lib/librte_vhost/vhost.h      |   9 ++
> >  lib/librte_vhost/vhost_user.c | 197
> > ++++++++++++++++++++++++++++++++++
> >  4 files changed, 253 insertions(+), 1 deletion(-)
> >
> ...
> > +static int
> > +vhost_check_queue_inflights_packed(struct virtio_net *dev,
> > +						 struct vhost_virtqueue *vq)
> > +{
> > +	uint16_t i = 0;
> > +	uint16_t resubmit_num = 0, old_used_idx, num;
> > +	struct rte_vhost_resubmit_info *resubmit = NULL;
> > +	struct inflight_info_packed *inflight_packed;
> > +
> > +	if (!(dev->protocol_features &
> > +		(1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)))
> > +		return RTE_VHOST_MSG_RESULT_OK;
> > +
> > +	if (!vq->inflight_packed->version) {
> > +		vq->inflight_packed->version = INFLIGHT_VERSION;
> > +		return RTE_VHOST_MSG_RESULT_OK;
> > +	}
> > +
> > +	if ((!vq->inflight_packed))
> > +		return RTE_VHOST_MSG_RESULT_ERR;
> 
> It needs to be checked before before being dereferenced.
Sorry I don't understand, you means I should check the vq pointer?
> 
> > +
> > +	inflight_packed = vq->inflight_packed;
> > +	vq->resubmit_inflight = NULL;
> > +	vq->global_counter = 0;
> > +	old_used_idx = inflight_packed->old_used_idx;
> > +
> > +	if (inflight_packed->used_idx != old_used_idx) {
> > +		if (inflight_packed->desc[old_used_idx].inflight == 0) {
> > +			inflight_packed->old_used_idx =
> > +				inflight_packed->used_idx;
> > +			inflight_packed->old_used_wrap_counter =
> > +				inflight_packed->used_wrap_counter;
> > +			inflight_packed->old_free_head =
> > +				inflight_packed->free_head;
> > +		} else {
> > +			inflight_packed->used_idx =
> > +				inflight_packed->old_used_idx;
> > +			inflight_packed->used_wrap_counter =
> > +				inflight_packed->old_used_wrap_counter;
> > +			inflight_packed->free_head =
> > +				inflight_packed->old_free_head;
> > +		}
> > +	}
> > +
> > +	for (i = 0; i < inflight_packed->desc_num; i++) {
> > +		if (inflight_packed->desc[i].inflight == 1)
> > +			resubmit_num++;
> > +	}
> > +
> > +	if (resubmit_num) {
> > +		resubmit = calloc(1, sizeof(struct rte_vhost_resubmit_info));
> > +		if (resubmit == NULL) {
> > +			RTE_LOG(ERR, VHOST_CONFIG,
> > +			 "Failed to allocate memory for resubmit info.\n");
> > +			return RTE_VHOST_MSG_RESULT_ERR;
> > +		}
> > +
> > +		resubmit->resubmit_list = calloc(resubmit_num,
> > +			sizeof(struct rte_vhost_resubmit_desc));
> > +		if (resubmit->resubmit_list == NULL) {
> > +			RTE_LOG(ERR, VHOST_CONFIG,
> > +			 "Failed to allocate memory for resubmit desc.\n");
> > +			return RTE_VHOST_MSG_RESULT_ERR;
> > +		}
> > +
> > +		num = 0;
> > +		for (i = 0; i < inflight_packed->desc_num; i++) {
> > +			if (vq->inflight_packed->desc[i].inflight == 1) {
> > +				resubmit->resubmit_list[num].index = i;
> > +				resubmit->resubmit_list[num].counter =
> > +					inflight_packed->desc[i].counter;
> > +				num++;
> > +			}
> > +		}
> > +		resubmit->resubmit_num = num;
> > +
> > +		if (resubmit->resubmit_num > 1)
> > +			qsort(resubmit->resubmit_list, resubmit-
> >resubmit_num,
> > +				sizeof(struct rte_vhost_resubmit_desc),
> > +				resubmit_desc_compare);
> > +
> > +		vq->global_counter = resubmit->resubmit_list[0].counter + 1;
> > +		vq->resubmit_inflight = resubmit;
> > +	}
> > +
> > +	return RTE_VHOST_MSG_RESULT_OK;
> > +}
  
Maxime Coquelin Sept. 11, 2019, 8:43 a.m. UTC | #3
On 9/11/19 4:50 AM, Yu, Jin wrote:
>> -----Original Message-----
>> From: Maxime Coquelin [mailto:maxime.coquelin@redhat.com]
>> Sent: Monday, September 9, 2019 6:21 PM
>> To: Yu, Jin <jin.yu@intel.com>; dev@dpdk.org
>> Cc: Liu, Changpeng <changpeng.liu@intel.com>; Bie, Tiwei
>> <tiwei.bie@intel.com>; Wang, Zhihong <zhihong.wang@intel.com>; Lin Li
>> <lilin24@baidu.com>; Xun Ni <nixun@baidu.com>; Yu Zhang
>> <zhangyu31@baidu.com>
>> Subject: Re: [PATCH v6 05/10] vhost: checkout and cleanup the resubmit inflight
>> information
>>
>>
>>
>> On 8/29/19 4:12 PM, JinYu wrote:
>>> This patch shows how to checkout the inflight ring and construct the
>>> resubmit information also include destroying resubmit info.
>>>
>>> Signed-off-by: Lin Li <lilin24@baidu.com>
>>> Signed-off-by: Xun Ni <nixun@baidu.com>
>>> Signed-off-by: Yu Zhang <zhangyu31@baidu.com>
>>> Signed-off-by: Jin Yu <jin.yu@intel.com>
>>> ---
>>>  lib/librte_vhost/rte_vhost.h  |  19 ++++
>>>  lib/librte_vhost/vhost.c      |  29 ++++-
>>>  lib/librte_vhost/vhost.h      |   9 ++
>>>  lib/librte_vhost/vhost_user.c | 197
>>> ++++++++++++++++++++++++++++++++++
>>>  4 files changed, 253 insertions(+), 1 deletion(-)
>>>
>> ...
>>> +static int
>>> +vhost_check_queue_inflights_packed(struct virtio_net *dev,
>>> +						 struct vhost_virtqueue *vq)
>>> +{
>>> +	uint16_t i = 0;
>>> +	uint16_t resubmit_num = 0, old_used_idx, num;
>>> +	struct rte_vhost_resubmit_info *resubmit = NULL;
>>> +	struct inflight_info_packed *inflight_packed;
>>> +
>>> +	if (!(dev->protocol_features &
>>> +		(1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)))
>>> +		return RTE_VHOST_MSG_RESULT_OK;
>>> +
>>> +	if (!vq->inflight_packed->version) {
>>> +		vq->inflight_packed->version = INFLIGHT_VERSION;
>>> +		return RTE_VHOST_MSG_RESULT_OK;
>>> +	}
>>> +
>>> +	if ((!vq->inflight_packed))
>>> +		return RTE_VHOST_MSG_RESULT_ERR;
>>
>> It needs to be checked before before being dereferenced.
> Sorry I don't understand, you means I should check the vq pointer?

No, I meant vq->inflight_packed should be checked earlier, before
if (!vq->inflight_packed->version) {

>>> +
>>> +	inflight_packed = vq->inflight_packed;
>>> +	vq->resubmit_inflight = NULL;
>>> +	vq->global_counter = 0;
>>> +	old_used_idx = inflight_packed->old_used_idx;
>>> +
>>> +	if (inflight_packed->used_idx != old_used_idx) {
>>> +		if (inflight_packed->desc[old_used_idx].inflight == 0) {
>>> +			inflight_packed->old_used_idx =
>>> +				inflight_packed->used_idx;
>>> +			inflight_packed->old_used_wrap_counter =
>>> +				inflight_packed->used_wrap_counter;
>>> +			inflight_packed->old_free_head =
>>> +				inflight_packed->free_head;
>>> +		} else {
>>> +			inflight_packed->used_idx =
>>> +				inflight_packed->old_used_idx;
>>> +			inflight_packed->used_wrap_counter =
>>> +				inflight_packed->old_used_wrap_counter;
>>> +			inflight_packed->free_head =
>>> +				inflight_packed->old_free_head;
>>> +		}
>>> +	}
>>> +
>>> +	for (i = 0; i < inflight_packed->desc_num; i++) {
>>> +		if (inflight_packed->desc[i].inflight == 1)
>>> +			resubmit_num++;
>>> +	}
>>> +
>>> +	if (resubmit_num) {
>>> +		resubmit = calloc(1, sizeof(struct rte_vhost_resubmit_info));
>>> +		if (resubmit == NULL) {
>>> +			RTE_LOG(ERR, VHOST_CONFIG,
>>> +			 "Failed to allocate memory for resubmit info.\n");
>>> +			return RTE_VHOST_MSG_RESULT_ERR;
>>> +		}
>>> +
>>> +		resubmit->resubmit_list = calloc(resubmit_num,
>>> +			sizeof(struct rte_vhost_resubmit_desc));
>>> +		if (resubmit->resubmit_list == NULL) {
>>> +			RTE_LOG(ERR, VHOST_CONFIG,
>>> +			 "Failed to allocate memory for resubmit desc.\n");
>>> +			return RTE_VHOST_MSG_RESULT_ERR;
>>> +		}
>>> +
>>> +		num = 0;
>>> +		for (i = 0; i < inflight_packed->desc_num; i++) {
>>> +			if (vq->inflight_packed->desc[i].inflight == 1) {
>>> +				resubmit->resubmit_list[num].index = i;
>>> +				resubmit->resubmit_list[num].counter =
>>> +					inflight_packed->desc[i].counter;
>>> +				num++;
>>> +			}
>>> +		}
>>> +		resubmit->resubmit_num = num;
>>> +
>>> +		if (resubmit->resubmit_num > 1)
>>> +			qsort(resubmit->resubmit_list, resubmit-
>>> resubmit_num,
>>> +				sizeof(struct rte_vhost_resubmit_desc),
>>> +				resubmit_desc_compare);
>>> +
>>> +		vq->global_counter = resubmit->resubmit_list[0].counter + 1;
>>> +		vq->resubmit_inflight = resubmit;
>>> +	}
>>> +
>>> +	return RTE_VHOST_MSG_RESULT_OK;
>>> +}
>
  
Jin Yu Sept. 11, 2019, 9:07 a.m. UTC | #4
> -----Original Message-----
> From: Maxime Coquelin [mailto:maxime.coquelin@redhat.com]
> Sent: Wednesday, September 11, 2019 4:44 PM
> To: Yu, Jin <jin.yu@intel.com>; dev@dpdk.org
> Cc: Liu, Changpeng <changpeng.liu@intel.com>; Bie, Tiwei
> <tiwei.bie@intel.com>; Wang, Zhihong <zhihong.wang@intel.com>; Lin Li
> <lilin24@baidu.com>; Xun Ni <nixun@baidu.com>; Yu Zhang
> <zhangyu31@baidu.com>
> Subject: Re: [PATCH v6 05/10] vhost: checkout and cleanup the resubmit inflight
> information
> 
> 
> 
> On 9/11/19 4:50 AM, Yu, Jin wrote:
> >> -----Original Message-----
> >> From: Maxime Coquelin [mailto:maxime.coquelin@redhat.com]
> >> Sent: Monday, September 9, 2019 6:21 PM
> >> To: Yu, Jin <jin.yu@intel.com>; dev@dpdk.org
> >> Cc: Liu, Changpeng <changpeng.liu@intel.com>; Bie, Tiwei
> >> <tiwei.bie@intel.com>; Wang, Zhihong <zhihong.wang@intel.com>; Lin Li
> >> <lilin24@baidu.com>; Xun Ni <nixun@baidu.com>; Yu Zhang
> >> <zhangyu31@baidu.com>
> >> Subject: Re: [PATCH v6 05/10] vhost: checkout and cleanup the
> >> resubmit inflight information
> >>
> >>
> >>
> >> On 8/29/19 4:12 PM, JinYu wrote:
> >>> This patch shows how to checkout the inflight ring and construct the
> >>> resubmit information also include destroying resubmit info.
> >>>
> >>> Signed-off-by: Lin Li <lilin24@baidu.com>
> >>> Signed-off-by: Xun Ni <nixun@baidu.com>
> >>> Signed-off-by: Yu Zhang <zhangyu31@baidu.com>
> >>> Signed-off-by: Jin Yu <jin.yu@intel.com>
> >>> ---
> >>>  lib/librte_vhost/rte_vhost.h  |  19 ++++
> >>>  lib/librte_vhost/vhost.c      |  29 ++++-
> >>>  lib/librte_vhost/vhost.h      |   9 ++
> >>>  lib/librte_vhost/vhost_user.c | 197
> >>> ++++++++++++++++++++++++++++++++++
> >>>  4 files changed, 253 insertions(+), 1 deletion(-)
> >>>
> >> ...
> >>> +static int
> >>> +vhost_check_queue_inflights_packed(struct virtio_net *dev,
> >>> +						 struct vhost_virtqueue *vq)
> >>> +{
> >>> +	uint16_t i = 0;
> >>> +	uint16_t resubmit_num = 0, old_used_idx, num;
> >>> +	struct rte_vhost_resubmit_info *resubmit = NULL;
> >>> +	struct inflight_info_packed *inflight_packed;
> >>> +
> >>> +	if (!(dev->protocol_features &
> >>> +		(1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)))
> >>> +		return RTE_VHOST_MSG_RESULT_OK;
> >>> +
> >>> +	if (!vq->inflight_packed->version) {
> >>> +		vq->inflight_packed->version = INFLIGHT_VERSION;
> >>> +		return RTE_VHOST_MSG_RESULT_OK;
> >>> +	}
> >>> +
> >>> +	if ((!vq->inflight_packed))
> >>> +		return RTE_VHOST_MSG_RESULT_ERR;
> >>
> >> It needs to be checked before before being dereferenced.
> > Sorry I don't understand, you means I should check the vq pointer?
> 
> No, I meant vq->inflight_packed should be checked earlier, before if (!vq-
> >inflight_packed->version) {

Yeah you are right, Thanks. Will fix it in next version.
> 
> >>> +
> >>> +	inflight_packed = vq->inflight_packed;
> >>> +	vq->resubmit_inflight = NULL;
> >>> +	vq->global_counter = 0;
> >>> +	old_used_idx = inflight_packed->old_used_idx;
> >>> +
> >>> +	if (inflight_packed->used_idx != old_used_idx) {
> >>> +		if (inflight_packed->desc[old_used_idx].inflight == 0) {
> >>> +			inflight_packed->old_used_idx =
> >>> +				inflight_packed->used_idx;
> >>> +			inflight_packed->old_used_wrap_counter =
> >>> +				inflight_packed->used_wrap_counter;
> >>> +			inflight_packed->old_free_head =
> >>> +				inflight_packed->free_head;
> >>> +		} else {
> >>> +			inflight_packed->used_idx =
> >>> +				inflight_packed->old_used_idx;
> >>> +			inflight_packed->used_wrap_counter =
> >>> +				inflight_packed->old_used_wrap_counter;
> >>> +			inflight_packed->free_head =
> >>> +				inflight_packed->old_free_head;
> >>> +		}
> >>> +	}
> >>> +
> >>> +	for (i = 0; i < inflight_packed->desc_num; i++) {
> >>> +		if (inflight_packed->desc[i].inflight == 1)
> >>> +			resubmit_num++;
> >>> +	}
> >>> +
> >>> +	if (resubmit_num) {
> >>> +		resubmit = calloc(1, sizeof(struct rte_vhost_resubmit_info));
> >>> +		if (resubmit == NULL) {
> >>> +			RTE_LOG(ERR, VHOST_CONFIG,
> >>> +			 "Failed to allocate memory for resubmit info.\n");
> >>> +			return RTE_VHOST_MSG_RESULT_ERR;
> >>> +		}
> >>> +
> >>> +		resubmit->resubmit_list = calloc(resubmit_num,
> >>> +			sizeof(struct rte_vhost_resubmit_desc));
> >>> +		if (resubmit->resubmit_list == NULL) {
> >>> +			RTE_LOG(ERR, VHOST_CONFIG,
> >>> +			 "Failed to allocate memory for resubmit desc.\n");
> >>> +			return RTE_VHOST_MSG_RESULT_ERR;
> >>> +		}
> >>> +
> >>> +		num = 0;
> >>> +		for (i = 0; i < inflight_packed->desc_num; i++) {
> >>> +			if (vq->inflight_packed->desc[i].inflight == 1) {
> >>> +				resubmit->resubmit_list[num].index = i;
> >>> +				resubmit->resubmit_list[num].counter =
> >>> +					inflight_packed->desc[i].counter;
> >>> +				num++;
> >>> +			}
> >>> +		}
> >>> +		resubmit->resubmit_num = num;
> >>> +
> >>> +		if (resubmit->resubmit_num > 1)
> >>> +			qsort(resubmit->resubmit_list, resubmit-
> >>> resubmit_num,
> >>> +				sizeof(struct rte_vhost_resubmit_desc),
> >>> +				resubmit_desc_compare);
> >>> +
> >>> +		vq->global_counter = resubmit->resubmit_list[0].counter + 1;
> >>> +		vq->resubmit_inflight = resubmit;
> >>> +	}
> >>> +
> >>> +	return RTE_VHOST_MSG_RESULT_OK;
> >>> +}
> >
  

Patch

diff --git a/lib/librte_vhost/rte_vhost.h b/lib/librte_vhost/rte_vhost.h
index 1d6b7a1cf..e090cdfee 100644
--- a/lib/librte_vhost/rte_vhost.h
+++ b/lib/librte_vhost/rte_vhost.h
@@ -145,6 +145,25 @@  struct inflight_info_packed {
 	struct inflight_desc_packed desc[0];
 };
 
+struct rte_vhost_resubmit_desc {
+	uint16_t index;
+	uint64_t counter;
+};
+
+struct rte_vhost_resubmit_info {
+	struct rte_vhost_resubmit_desc *resubmit_list;
+	uint16_t resubmit_num;
+};
+
+struct rte_vhost_ring_inflight {
+	union {
+		struct inflight_info_split *inflight_split;
+		struct inflight_info_packed *inflight_packed;
+	};
+
+	struct rte_vhost_resubmit_info *resubmit_inflight;
+};
+
 struct rte_vhost_vring {
 	union {
 		struct vring_desc *desc;
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 981837b5d..660ac2a07 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -242,6 +242,31 @@  cleanup_vq(struct vhost_virtqueue *vq, int destroy)
 		close(vq->kickfd);
 }
 
+void
+cleanup_vq_inflight(struct virtio_net *dev, struct vhost_virtqueue *vq)
+{
+	if (!(dev->protocol_features &
+		(1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)))
+		return;
+
+	if (vq_is_packed(dev)) {
+		if (vq->inflight_packed)
+			vq->inflight_packed = NULL;
+	} else {
+		if (vq->inflight_split)
+			vq->inflight_split = NULL;
+	}
+
+	if (vq->resubmit_inflight) {
+		if (vq->resubmit_inflight->resubmit_list) {
+			free(vq->resubmit_inflight->resubmit_list);
+			vq->resubmit_inflight->resubmit_list = NULL;
+		}
+		free(vq->resubmit_inflight);
+		vq->resubmit_inflight = NULL;
+	}
+}
+
 /*
  * Unmap any memory, close any file descriptors and
  * free any memory owned by a device.
@@ -253,8 +278,10 @@  cleanup_device(struct virtio_net *dev, int destroy)
 
 	vhost_backend_cleanup(dev);
 
-	for (i = 0; i < dev->nr_vring; i++)
+	for (i = 0; i < dev->nr_vring; i++) {
 		cleanup_vq(dev->virtqueue[i], destroy);
+		cleanup_vq_inflight(dev, dev->virtqueue[i]);
+	}
 }
 
 void
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 39f645b97..0aa8f82cd 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -128,6 +128,14 @@  struct vhost_virtqueue {
 	/* Physical address of used ring, for logging */
 	uint64_t		log_guest_addr;
 
+	/* inflight share memory info */
+	union {
+		struct inflight_info_split *inflight_split;
+		struct inflight_info_packed *inflight_packed;
+	};
+	struct rte_vhost_resubmit_info *resubmit_inflight;
+	uint64_t		global_counter;
+
 	uint16_t		nr_zmbuf;
 	uint16_t		zmbuf_size;
 	uint16_t		last_zmbuf_idx;
@@ -474,6 +482,7 @@  void vhost_destroy_device(int);
 void vhost_destroy_device_notify(struct virtio_net *dev);
 
 void cleanup_vq(struct vhost_virtqueue *vq, int destroy);
+void cleanup_vq_inflight(struct virtio_net *dev, struct vhost_virtqueue *vq);
 void free_vq(struct virtio_net *dev, struct vhost_virtqueue *vq);
 
 int alloc_vring_queue(struct virtio_net *dev, uint32_t vring_idx);
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 647929234..72be891b0 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -327,6 +327,7 @@  vhost_user_set_features(struct virtio_net **pdev, struct VhostUserMsg *msg,
 
 			dev->virtqueue[dev->nr_vring] = NULL;
 			cleanup_vq(vq, 1);
+			cleanup_vq_inflight(dev, vq);
 			free_vq(dev, vq);
 		}
 	}
@@ -1441,6 +1442,188 @@  static int vhost_user_set_vring_err(struct virtio_net **pdev __rte_unused,
 	return RTE_VHOST_MSG_RESULT_OK;
 }
 
+static int
+resubmit_desc_compare(const void *a, const void *b)
+{
+	const struct rte_vhost_resubmit_desc *desc0 =
+		(const struct rte_vhost_resubmit_desc *)a;
+	const struct rte_vhost_resubmit_desc *desc1 =
+		(const struct rte_vhost_resubmit_desc *)b;
+
+	if (desc1->counter > desc0->counter &&
+		(desc1->counter - desc0->counter) < VIRTQUEUE_MAX_SIZE * 2)
+		return 1;
+
+	return -1;
+}
+
+static int
+vhost_check_queue_inflights_split(struct virtio_net *dev,
+	struct vhost_virtqueue *vq)
+{
+	uint16_t i = 0;
+	uint16_t resubmit_num = 0, last_io, num;
+	struct vring_used *used = vq->used;
+	struct rte_vhost_resubmit_info *resubmit = NULL;
+	struct inflight_info_split *inflight_split;
+
+	if (!(dev->protocol_features &
+		(1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)))
+		return RTE_VHOST_MSG_RESULT_OK;
+
+	if ((!vq->inflight_split))
+		return RTE_VHOST_MSG_RESULT_ERR;
+
+	if (!vq->inflight_split->version) {
+		vq->inflight_split->version = INFLIGHT_VERSION;
+		return RTE_VHOST_MSG_RESULT_OK;
+	}
+
+	inflight_split = vq->inflight_split;
+	vq->resubmit_inflight = NULL;
+	vq->global_counter = 0;
+	last_io = inflight_split->last_inflight_io;
+
+	if (inflight_split->used_idx != used->idx) {
+		inflight_split->desc[last_io].inflight = 0;
+		rte_compiler_barrier();
+		inflight_split->used_idx = used->idx;
+	}
+
+	for (i = 0; i < inflight_split->desc_num; i++) {
+		if (inflight_split->desc[i].inflight == 1)
+			resubmit_num++;
+	}
+
+	vq->last_avail_idx += resubmit_num;
+
+	if (resubmit_num) {
+		resubmit  = calloc(1, sizeof(struct rte_vhost_resubmit_info));
+		if (!resubmit) {
+			RTE_LOG(ERR, VHOST_CONFIG,
+			 "Failed to allocate memory for resubmit info.\n");
+			return RTE_VHOST_MSG_RESULT_ERR;
+		}
+
+		resubmit->resubmit_list = calloc(resubmit_num,
+			sizeof(struct rte_vhost_resubmit_desc));
+		if (!resubmit->resubmit_list) {
+			RTE_LOG(ERR, VHOST_CONFIG,
+			 "Failed to allocate memory for inflight desc.\n");
+			return RTE_VHOST_MSG_RESULT_ERR;
+		}
+
+		num = 0;
+		for (i = 0; i < vq->inflight_split->desc_num; i++) {
+			if (vq->inflight_split->desc[i].inflight == 1) {
+				resubmit->resubmit_list[num].index = i;
+				resubmit->resubmit_list[num].counter =
+					inflight_split->desc[i].counter;
+				num++;
+			}
+		}
+		resubmit->resubmit_num = num;
+
+		if (resubmit->resubmit_num > 1)
+			qsort(resubmit->resubmit_list, resubmit->resubmit_num,
+				sizeof(struct rte_vhost_resubmit_desc),
+				resubmit_desc_compare);
+
+		vq->global_counter = resubmit->resubmit_list[0].counter + 1;
+		vq->resubmit_inflight = resubmit;
+	}
+
+	return RTE_VHOST_MSG_RESULT_OK;
+}
+
+static int
+vhost_check_queue_inflights_packed(struct virtio_net *dev,
+						 struct vhost_virtqueue *vq)
+{
+	uint16_t i = 0;
+	uint16_t resubmit_num = 0, old_used_idx, num;
+	struct rte_vhost_resubmit_info *resubmit = NULL;
+	struct inflight_info_packed *inflight_packed;
+
+	if (!(dev->protocol_features &
+		(1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)))
+		return RTE_VHOST_MSG_RESULT_OK;
+
+	if (!vq->inflight_packed->version) {
+		vq->inflight_packed->version = INFLIGHT_VERSION;
+		return RTE_VHOST_MSG_RESULT_OK;
+	}
+
+	if ((!vq->inflight_packed))
+		return RTE_VHOST_MSG_RESULT_ERR;
+
+	inflight_packed = vq->inflight_packed;
+	vq->resubmit_inflight = NULL;
+	vq->global_counter = 0;
+	old_used_idx = inflight_packed->old_used_idx;
+
+	if (inflight_packed->used_idx != old_used_idx) {
+		if (inflight_packed->desc[old_used_idx].inflight == 0) {
+			inflight_packed->old_used_idx =
+				inflight_packed->used_idx;
+			inflight_packed->old_used_wrap_counter =
+				inflight_packed->used_wrap_counter;
+			inflight_packed->old_free_head =
+				inflight_packed->free_head;
+		} else {
+			inflight_packed->used_idx =
+				inflight_packed->old_used_idx;
+			inflight_packed->used_wrap_counter =
+				inflight_packed->old_used_wrap_counter;
+			inflight_packed->free_head =
+				inflight_packed->old_free_head;
+		}
+	}
+
+	for (i = 0; i < inflight_packed->desc_num; i++) {
+		if (inflight_packed->desc[i].inflight == 1)
+			resubmit_num++;
+	}
+
+	if (resubmit_num) {
+		resubmit = calloc(1, sizeof(struct rte_vhost_resubmit_info));
+		if (resubmit == NULL) {
+			RTE_LOG(ERR, VHOST_CONFIG,
+			 "Failed to allocate memory for resubmit info.\n");
+			return RTE_VHOST_MSG_RESULT_ERR;
+		}
+
+		resubmit->resubmit_list = calloc(resubmit_num,
+			sizeof(struct rte_vhost_resubmit_desc));
+		if (resubmit->resubmit_list == NULL) {
+			RTE_LOG(ERR, VHOST_CONFIG,
+			 "Failed to allocate memory for resubmit desc.\n");
+			return RTE_VHOST_MSG_RESULT_ERR;
+		}
+
+		num = 0;
+		for (i = 0; i < inflight_packed->desc_num; i++) {
+			if (vq->inflight_packed->desc[i].inflight == 1) {
+				resubmit->resubmit_list[num].index = i;
+				resubmit->resubmit_list[num].counter =
+					inflight_packed->desc[i].counter;
+				num++;
+			}
+		}
+		resubmit->resubmit_num = num;
+
+		if (resubmit->resubmit_num > 1)
+			qsort(resubmit->resubmit_list, resubmit->resubmit_num,
+				sizeof(struct rte_vhost_resubmit_desc),
+				resubmit_desc_compare);
+
+		vq->global_counter = resubmit->resubmit_list[0].counter + 1;
+		vq->resubmit_inflight = resubmit;
+	}
+
+	return RTE_VHOST_MSG_RESULT_OK;
+}
+
 static int
 vhost_user_set_vring_kick(struct virtio_net **pdev, struct VhostUserMsg *msg,
 			int main_fd __rte_unused)
@@ -1482,6 +1665,20 @@  vhost_user_set_vring_kick(struct virtio_net **pdev, struct VhostUserMsg *msg,
 		close(vq->kickfd);
 	vq->kickfd = file.fd;
 
+	if (vq_is_packed(dev)) {
+		if (vhost_check_queue_inflights_packed(dev, vq)) {
+			RTE_LOG(ERR, VHOST_CONFIG,
+				"Failed to inflights for vq: %d\n", file.index);
+			return RTE_VHOST_MSG_RESULT_ERR;
+		}
+	} else {
+		if (vhost_check_queue_inflights_split(dev, vq)) {
+			RTE_LOG(ERR, VHOST_CONFIG,
+				"Failed to inflights for vq: %d\n", file.index);
+			return RTE_VHOST_MSG_RESULT_ERR;
+		}
+	}
+
 	return RTE_VHOST_MSG_RESULT_OK;
 }