On 01/10/2018 07:39 PM, John Fastabend wrote:
> When testing BPF programs using sockmap I often want to have more
> control over how sendmsg is exercised. This becomes even more useful
> as new sockmap program types are added.
> 
> This adds a test type option to select type of test to run. Currently,
> only "ping" and "sendmsg" are supported, but more can be added as
> needed.
> 
> The new help argument gives the following,
> 
>  Usage: ./sockmap --cgroup <cgroup_path>
>  options:
>  --help         -h
>  --cgroup       -c
>  --rate         -r
>  --verbose      -v
>  --iov_count    -i
>  --length       -l
>  --test         -t
> 
> Signed-off-by: John Fastabend <john.fastab...@gmail.com>
> ---
>  samples/sockmap/sockmap_user.c |  143 
> +++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 140 insertions(+), 3 deletions(-)
> 
> diff --git a/samples/sockmap/sockmap_user.c b/samples/sockmap/sockmap_user.c
> index 5cbe7a5..2d51672 100644
> --- a/samples/sockmap/sockmap_user.c
> +++ b/samples/sockmap/sockmap_user.c
> @@ -56,6 +56,9 @@
>       {"cgroup",      required_argument,      NULL, 'c' },
>       {"rate",        required_argument,      NULL, 'r' },
>       {"verbose",     no_argument,            NULL, 'v' },
> +     {"iov_count",   required_argument,      NULL, 'i' },
> +     {"length",      required_argument,      NULL, 'l' },
> +     {"test",        required_argument,      NULL, 't' },
>       {0, 0, NULL, 0 }
>  };
>  
> @@ -184,6 +187,113 @@ static int sockmap_init_sockets(void)
>       return err;
>  }
>  
> +struct msg_stats {
> +     size_t bytes_sent;
> +     size_t bytes_recvd;
> +};
> +
> +static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
> +                 struct msg_stats *s, bool tx)
> +{
> +     struct msghdr msg = {0};
> +     struct iovec *iov;
> +     int i, flags = 0;
> +
> +     iov = calloc(iov_count, sizeof(struct iovec));
> +     if (!iov)
> +             return -ENOMEM;
> +
> +     for (i = 0; i < iov_count; i++) {
> +             char *d = calloc(iov_length, sizeof(char));
> +
> +             if (!d) {
> +                     fprintf(stderr, "iov_count %i/%i OOM\n", i, iov_count);
> +                     free(iov);

Here, we free() iov, but not prior allocated iov_base from the loop.

> +                     return -ENOMEM;
> +             }
> +             iov[i].iov_base = d;
> +             iov[i].iov_len = iov_length;
> +     }
> +
> +     msg.msg_iov = iov;
> +     msg.msg_iovlen = iov_count;
> +
> +     if (tx) {
> +             for (i = 0; i < cnt; i++) {
> +                     int sent = sendmsg(fd, &msg, flags);
> +
> +                     if (sent < 0) {
> +                             perror("send loop error:");
> +                             return sent;

And here as well as other places where we bail out, we don't free anything.

> +                     }
> +                     s->bytes_sent += sent;
> +             }
> +     } else {
> +             int slct, recv, max_fd = fd;
> +             struct timeval timeout;
> +             float total_bytes;
> +             fd_set w;
> +
> +             total_bytes = (float)iov_count * (float)iov_length * (float)cnt;
> +             while (s->bytes_recvd < total_bytes) {
> +                     timeout.tv_sec = 1;
> +                     timeout.tv_usec = 0;
> +
> +                     /* FD sets */
> +                     FD_ZERO(&w);
> +                     FD_SET(fd, &w);
> +
> +                     slct = select(max_fd + 1, &w, NULL, NULL, &timeout);
> +                     if (slct == -1) {
> +                             perror("select()");
> +                             return slct;
> +                     } else if (!slct) {
> +                             fprintf(stderr, "unexpected timeout\n");
> +                             return slct;
> +                     }
> +
> +                     recv = recvmsg(fd, &msg, flags);
> +                     if (recv < 0) {
> +                             if (errno != EWOULDBLOCK) {
> +                                     perror("recv failed()\n");
> +                                     return errno;
> +                             }
> +                     }
> +
> +                     s->bytes_recvd += recv;
> +             }
> +     }
> +
> +     for (i = 0; i < iov_count; i++)
> +             free(iov[i].iov_base);
> +     free(iov);
> +     return 0;
> +}

Reply via email to