Message ID | 20180109065908.19754-2-chrism@mellanox.com |
---|---|
State | Changes Requested, archived |
Delegated to: | David Ahern |
Headers | show |
Series | tc: Add batchsize feature to batch mode | expand |
Hi, On Tue, Jan 09, 2018 at 03:59:07PM +0900, Chris Mi wrote: [...] > diff --git a/lib/libnetlink.c b/lib/libnetlink.c > index 00e6ce0c..ae0059f9 100644 > --- a/lib/libnetlink.c > +++ b/lib/libnetlink.c > @@ -581,39 +581,43 @@ static void rtnl_talk_error(struct nlmsghdr *h, struct nlmsgerr *err, > strerror(-err->error)); > } > > -static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, > - struct nlmsghdr **answer, > - bool show_rtnl_err, nl_ext_ack_fn_t errfn) > +static int __rtnl_talk_msg(struct rtnl_handle *rtnl, struct msghdr *m, > + struct nlmsghdr **answer, > + bool show_rtnl_err, nl_ext_ack_fn_t errfn) > { > - int status; > - unsigned int seq; > - struct nlmsghdr *h; > struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK }; > - struct iovec iov = { > - .iov_base = n, > - .iov_len = n->nlmsg_len > - }; > + int i, status, iovlen = m->msg_iovlen; > + struct iovec iov; > struct msghdr msg = { > .msg_name = &nladdr, > .msg_namelen = sizeof(nladdr), > .msg_iov = &iov, > .msg_iovlen = 1, > }; > - char *buf; > - > - n->nlmsg_seq = seq = ++rtnl->seq; > + unsigned int seq = 0; > + struct nlmsghdr *h; > > - if (answer == NULL) > - n->nlmsg_flags |= NLM_F_ACK; > + for (i = 0; i < iovlen; i++) { > + struct iovec *v; > + v = &m->msg_iov[i]; > + h = v->iov_base; > + h->nlmsg_seq = seq = ++rtnl->seq; > + if (answer == NULL) > + h->nlmsg_flags |= NLM_F_ACK; > + } > > - status = sendmsg(rtnl->fd, &msg, 0); > + status = sendmsg(rtnl->fd, m, 0); > if (status < 0) { > perror("Cannot talk to rtnetlink"); > return -1; > } > > + i = 0; > while (1) { for (i = 1; ; i++) ? > + char *buf; Why did you move this declaration? > +next: Drop this and use 'continue' instead of 'goto next' below? > status = rtnl_recvmsg(rtnl->fd, &msg, &buf); > + ++i; > > if (status < 0) > return status; > @@ -642,7 +646,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, > > if (nladdr.nl_pid != 0 || > h->nlmsg_pid != rtnl->local.nl_pid || > - h->nlmsg_seq != seq) { > + h->nlmsg_seq > seq || h->nlmsg_seq < seq - iovlen) { > /* Don't forget to skip that message. */ > status -= NLMSG_ALIGN(len); > h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len)); > @@ -662,7 +666,10 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, > *answer = (struct nlmsghdr *)buf; > else > free(buf); > - return 0; > + if (h->nlmsg_seq == seq) > + return 0; > + else > + goto next; > } > > if (rtnl->proto != NETLINK_SOCK_DIAG && Cheers, Phil
> -----Original Message----- > From: n0-1@orbyte.nwl.cc [mailto:n0-1@orbyte.nwl.cc] On Behalf Of Phil > Sutter > Sent: Wednesday, January 10, 2018 3:24 AM > To: Chris Mi <chrism@mellanox.com> > Cc: netdev@vger.kernel.org; gerlitz.or@gmail.com; > stephen@networkplumber.org; dsahern@gmail.com; > marcelo.leitner@gmail.com > Subject: Re: [patch iproute2 v7 1/2] lib/libnetlink: Add functions > rtnl_talk_msg and rtnl_talk_iov > > Hi, > > On Tue, Jan 09, 2018 at 03:59:07PM +0900, Chris Mi wrote: > [...] > > diff --git a/lib/libnetlink.c b/lib/libnetlink.c index > > 00e6ce0c..ae0059f9 100644 > > --- a/lib/libnetlink.c > > +++ b/lib/libnetlink.c > > @@ -581,39 +581,43 @@ static void rtnl_talk_error(struct nlmsghdr *h, > struct nlmsgerr *err, > > strerror(-err->error)); > > } > > > > -static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, > > - struct nlmsghdr **answer, > > - bool show_rtnl_err, nl_ext_ack_fn_t errfn) > > +static int __rtnl_talk_msg(struct rtnl_handle *rtnl, struct msghdr *m, > > + struct nlmsghdr **answer, > > + bool show_rtnl_err, nl_ext_ack_fn_t errfn) > > { > > - int status; > > - unsigned int seq; > > - struct nlmsghdr *h; > > struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK }; > > - struct iovec iov = { > > - .iov_base = n, > > - .iov_len = n->nlmsg_len > > - }; > > + int i, status, iovlen = m->msg_iovlen; > > + struct iovec iov; > > struct msghdr msg = { > > .msg_name = &nladdr, > > .msg_namelen = sizeof(nladdr), > > .msg_iov = &iov, > > .msg_iovlen = 1, > > }; > > - char *buf; > > - > > - n->nlmsg_seq = seq = ++rtnl->seq; > > + unsigned int seq = 0; > > + struct nlmsghdr *h; > > > > - if (answer == NULL) > > - n->nlmsg_flags |= NLM_F_ACK; > > + for (i = 0; i < iovlen; i++) { > > + struct iovec *v; > > + v = &m->msg_iov[i]; > > + h = v->iov_base; > > + h->nlmsg_seq = seq = ++rtnl->seq; > > + if (answer == NULL) > > + h->nlmsg_flags |= NLM_F_ACK; > > + } > > > > - status = sendmsg(rtnl->fd, &msg, 0); > > + status = sendmsg(rtnl->fd, m, 0); > > if (status < 0) { > > perror("Cannot talk to rtnetlink"); > > return -1; > > } > > > > + i = 0; > > while (1) { > > for (i = 1; ; i++) ? > > > + char *buf; > > Why did you move this declaration? > > > +next: > > Drop this and use 'continue' instead of 'goto next' below? Actually there are two loops, I need go to the outer while loop instead of the inner for loop. > > > status = rtnl_recvmsg(rtnl->fd, &msg, &buf); > > + ++i; > > > > if (status < 0) > > return status; > > @@ -642,7 +646,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, > > struct nlmsghdr *n, > > > > if (nladdr.nl_pid != 0 || > > h->nlmsg_pid != rtnl->local.nl_pid || > > - h->nlmsg_seq != seq) { > > + h->nlmsg_seq > seq || h->nlmsg_seq < seq - iovlen) > { > > /* Don't forget to skip that message. */ > > status -= NLMSG_ALIGN(len); > > h = (struct nlmsghdr *)((char *)h + > NLMSG_ALIGN(len)); @@ -662,7 > > +666,10 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr > *n, > > *answer = (struct nlmsghdr > *)buf; > > else > > free(buf); > > - return 0; > > + if (h->nlmsg_seq == seq) > > + return 0; > > + else > > + goto next; > > } > > > > if (rtnl->proto != NETLINK_SOCK_DIAG && > > Cheers, Phil
Hi Chris, On Wed, Jan 10, 2018 at 03:00:23AM +0000, Chris Mi wrote: [...] > > Drop this and use 'continue' instead of 'goto next' below? > Actually there are two loops, I need go to the outer while loop instead of the inner for loop. Oh, I missed that. Sorry for the noise! Cheers, Phil
diff --git a/include/libnetlink.h b/include/libnetlink.h index a4d83b9e..e9a63dbc 100644 --- a/include/libnetlink.h +++ b/include/libnetlink.h @@ -96,6 +96,12 @@ int rtnl_dump_filter_nc(struct rtnl_handle *rth, int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, struct nlmsghdr **answer) __attribute__((warn_unused_result)); +int rtnl_talk_msg(struct rtnl_handle *rtnl, struct msghdr *m, + struct nlmsghdr **answer) + __attribute__((warn_unused_result)); +int rtnl_talk_iov(struct rtnl_handle *rtnl, struct iovec *iovec, size_t iovlen, + struct nlmsghdr **answer) + __attribute__((warn_unused_result)); int rtnl_talk_extack(struct rtnl_handle *rtnl, struct nlmsghdr *n, struct nlmsghdr **answer, nl_ext_ack_fn_t errfn) __attribute__((warn_unused_result)); diff --git a/lib/libnetlink.c b/lib/libnetlink.c index 00e6ce0c..ae0059f9 100644 --- a/lib/libnetlink.c +++ b/lib/libnetlink.c @@ -581,39 +581,43 @@ static void rtnl_talk_error(struct nlmsghdr *h, struct nlmsgerr *err, strerror(-err->error)); } -static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, - struct nlmsghdr **answer, - bool show_rtnl_err, nl_ext_ack_fn_t errfn) +static int __rtnl_talk_msg(struct rtnl_handle *rtnl, struct msghdr *m, + struct nlmsghdr **answer, + bool show_rtnl_err, nl_ext_ack_fn_t errfn) { - int status; - unsigned int seq; - struct nlmsghdr *h; struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK }; - struct iovec iov = { - .iov_base = n, - .iov_len = n->nlmsg_len - }; + int i, status, iovlen = m->msg_iovlen; + struct iovec iov; struct msghdr msg = { .msg_name = &nladdr, .msg_namelen = sizeof(nladdr), .msg_iov = &iov, .msg_iovlen = 1, }; - char *buf; - - n->nlmsg_seq = seq = ++rtnl->seq; + unsigned int seq = 0; + struct nlmsghdr *h; - if (answer == NULL) - n->nlmsg_flags |= NLM_F_ACK; + for (i = 0; i < iovlen; i++) { + struct iovec *v; + v = &m->msg_iov[i]; + h = v->iov_base; + h->nlmsg_seq = seq = ++rtnl->seq; + if (answer == NULL) + h->nlmsg_flags |= NLM_F_ACK; + } - status = sendmsg(rtnl->fd, &msg, 0); + status = sendmsg(rtnl->fd, m, 0); if (status < 0) { perror("Cannot talk to rtnetlink"); return -1; } + i = 0; while (1) { + char *buf; +next: status = rtnl_recvmsg(rtnl->fd, &msg, &buf); + ++i; if (status < 0) return status; @@ -642,7 +646,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, if (nladdr.nl_pid != 0 || h->nlmsg_pid != rtnl->local.nl_pid || - h->nlmsg_seq != seq) { + h->nlmsg_seq > seq || h->nlmsg_seq < seq - iovlen) { /* Don't forget to skip that message. */ status -= NLMSG_ALIGN(len); h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len)); @@ -662,7 +666,10 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, *answer = (struct nlmsghdr *)buf; else free(buf); - return 0; + if (h->nlmsg_seq == seq) + return 0; + else + goto next; } if (rtnl->proto != NETLINK_SOCK_DIAG && @@ -671,7 +678,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, errno = -err->error; free(buf); - return -1; + return -i; } if (answer) { @@ -698,12 +705,51 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, } } +static int __rtnl_talk_iov(struct rtnl_handle *rtnl, struct iovec *msg_iov, + size_t iovlen, struct nlmsghdr **answer, + bool show_rtnl_err, nl_ext_ack_fn_t errfn) +{ + struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK }; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = msg_iov, + .msg_iovlen = iovlen, + }; + + return __rtnl_talk_msg(rtnl, &msg, answer, show_rtnl_err, errfn); +} + +static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, + struct nlmsghdr **answer, + bool show_rtnl_err, nl_ext_ack_fn_t errfn) +{ + struct iovec iov = { + .iov_base = n, + .iov_len = n->nlmsg_len + }; + + return __rtnl_talk_iov(rtnl, &iov, 1, answer, show_rtnl_err, errfn); +} + int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, struct nlmsghdr **answer) { return __rtnl_talk(rtnl, n, answer, true, NULL); } +int rtnl_talk_msg(struct rtnl_handle *rtnl, struct msghdr *m, + struct nlmsghdr **answer) +{ + return __rtnl_talk_msg(rtnl, m, answer, true, NULL); +} + +int rtnl_talk_iov(struct rtnl_handle *rtnl, struct iovec *iovec, size_t iovlen, + struct nlmsghdr **answer) +{ + return __rtnl_talk_iov(rtnl, iovec, iovlen, answer, true, NULL); +} + int rtnl_talk_extack(struct rtnl_handle *rtnl, struct nlmsghdr *n, struct nlmsghdr **answer, nl_ext_ack_fn_t errfn)
rtnl_talk can only send a single message to kernel. Add two functions rtnl_talk_msg and rtnl_talk_iov that can send multiple messages to kernel. rtnl_talk_msg takes struct msghdr * as argument. rtnl_talk_iov takes struct iovec * and iovlen as arguments. Signed-off-by: Chris Mi <chrism@mellanox.com> --- include/libnetlink.h | 6 ++++ lib/libnetlink.c | 84 ++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 71 insertions(+), 19 deletions(-)