From 84cacbe34b6bb3071af0313694b119f3872cbb8b Mon Sep 17 00:00:00 2001 From: Viacheslav Ovsiienko Date: Mon, 12 Nov 2018 20:01:40 +0000 Subject: [PATCH] net/mlx5: fix Netlink communication routine While receiving the Netlink reply messages we should stop at DONE or ACK message. The existing implementation stops at DONE message or if no multiple message flag set ( NLM_F_MULTI). It prevents the single query requests from working, these requests send the single reply message without multi-message flag followed by ACK message. This patch fixes receiving part of Netlink communication routine. Fixes: 6e74990b3463 ("net/mlx5: update E-Switch VXLAN netlink routines") Signed-off-by: Viacheslav Ovsiienko Acked-by: Shahaf Shuler --- drivers/net/mlx5/mlx5_flow_tcf.c | 58 ++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow_tcf.c b/drivers/net/mlx5/mlx5_flow_tcf.c index 5a38940ae5..4d154b65ff 100644 --- a/drivers/net/mlx5/mlx5_flow_tcf.c +++ b/drivers/net/mlx5/mlx5_flow_tcf.c @@ -3732,44 +3732,60 @@ flow_tcf_nl_ack(struct mlx5_flow_tcf_context *tcf, { unsigned int portid = mnl_socket_get_portid(tcf->nl); uint32_t seq = tcf->seq++; - int err, ret; + int ret, err = 0; assert(tcf->nl); assert(tcf->buf); - if (!seq) + if (!seq) { /* seq 0 is reserved for kernel event-driven notifications. */ seq = tcf->seq++; + } nlh->nlmsg_seq = seq; nlh->nlmsg_flags |= NLM_F_ACK; ret = mnl_socket_sendto(tcf->nl, nlh, nlh->nlmsg_len); - err = (ret <= 0) ? errno : 0; + if (ret <= 0) { + /* Message send error occurres. */ + rte_errno = errno; + return -rte_errno; + } nlh = (struct nlmsghdr *)(tcf->buf); /* * The following loop postpones non-fatal errors until multipart * messages are complete. */ - if (ret > 0) - while (true) { - ret = mnl_socket_recvfrom(tcf->nl, tcf->buf, - tcf->buf_size); + while (true) { + ret = mnl_socket_recvfrom(tcf->nl, tcf->buf, tcf->buf_size); + if (ret < 0) { + err = errno; + /* + * In case of overflow Will receive till + * end of multipart message. We may lost part + * of reply messages but mark and return an error. + */ + if (err != ENOSPC || + !(nlh->nlmsg_flags & NLM_F_MULTI) || + nlh->nlmsg_type == NLMSG_DONE) + break; + } else { + ret = mnl_cb_run(nlh, ret, seq, portid, cb, arg); + if (!ret) { + /* + * libmnl returns 0 if DONE or + * success ACK message found. + */ + break; + } if (ret < 0) { + /* + * ACK message with error found + * or some error occurred. + */ err = errno; - if (err != ENOSPC) - break; - } - if (!err) { - ret = mnl_cb_run(nlh, ret, seq, portid, - cb, arg); - if (ret < 0) { - err = errno; - break; - } - } - /* Will receive till end of multipart message */ - if (!(nlh->nlmsg_flags & NLM_F_MULTI) || - nlh->nlmsg_type == NLMSG_DONE) break; + } + /* We should continue receiving. */ } + } if (!err) return 0; rte_errno = err; -- 2.20.1