diff options
author | Magnus Karlsson <magnus.karlsson@intel.com> | 2018-05-02 07:01:35 -0400 |
---|---|---|
committer | Alexei Starovoitov <ast@kernel.org> | 2018-05-03 18:55:25 -0400 |
commit | af75d9e02d08dc55ce6a1e42e485465c630d7349 (patch) | |
tree | 7185c5ca061b68c48b239ae8d2df958ac19223a8 /net/xdp | |
parent | 35fcde7f8deb51b707b161bf19cbd22363aef2df (diff) |
xsk: statistics support
In this commit, a new getsockopt is added: XDP_STATISTICS. This is
used to obtain stats from the sockets.
v2: getsockopt now returns size of stats structure.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'net/xdp')
-rw-r--r-- | net/xdp/xsk.c | 45 | ||||
-rw-r--r-- | net/xdp/xsk_queue.h | 5 |
2 files changed, 49 insertions, 1 deletions
diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c index b33c535c7996..009c5af5bba5 100644 --- a/net/xdp/xsk.c +++ b/net/xdp/xsk.c | |||
@@ -468,6 +468,49 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname, | |||
468 | return -ENOPROTOOPT; | 468 | return -ENOPROTOOPT; |
469 | } | 469 | } |
470 | 470 | ||
471 | static int xsk_getsockopt(struct socket *sock, int level, int optname, | ||
472 | char __user *optval, int __user *optlen) | ||
473 | { | ||
474 | struct sock *sk = sock->sk; | ||
475 | struct xdp_sock *xs = xdp_sk(sk); | ||
476 | int len; | ||
477 | |||
478 | if (level != SOL_XDP) | ||
479 | return -ENOPROTOOPT; | ||
480 | |||
481 | if (get_user(len, optlen)) | ||
482 | return -EFAULT; | ||
483 | if (len < 0) | ||
484 | return -EINVAL; | ||
485 | |||
486 | switch (optname) { | ||
487 | case XDP_STATISTICS: | ||
488 | { | ||
489 | struct xdp_statistics stats; | ||
490 | |||
491 | if (len < sizeof(stats)) | ||
492 | return -EINVAL; | ||
493 | |||
494 | mutex_lock(&xs->mutex); | ||
495 | stats.rx_dropped = xs->rx_dropped; | ||
496 | stats.rx_invalid_descs = xskq_nb_invalid_descs(xs->rx); | ||
497 | stats.tx_invalid_descs = xskq_nb_invalid_descs(xs->tx); | ||
498 | mutex_unlock(&xs->mutex); | ||
499 | |||
500 | if (copy_to_user(optval, &stats, sizeof(stats))) | ||
501 | return -EFAULT; | ||
502 | if (put_user(sizeof(stats), optlen)) | ||
503 | return -EFAULT; | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | default: | ||
508 | break; | ||
509 | } | ||
510 | |||
511 | return -EOPNOTSUPP; | ||
512 | } | ||
513 | |||
471 | static int xsk_mmap(struct file *file, struct socket *sock, | 514 | static int xsk_mmap(struct file *file, struct socket *sock, |
472 | struct vm_area_struct *vma) | 515 | struct vm_area_struct *vma) |
473 | { | 516 | { |
@@ -524,7 +567,7 @@ static const struct proto_ops xsk_proto_ops = { | |||
524 | .listen = sock_no_listen, | 567 | .listen = sock_no_listen, |
525 | .shutdown = sock_no_shutdown, | 568 | .shutdown = sock_no_shutdown, |
526 | .setsockopt = xsk_setsockopt, | 569 | .setsockopt = xsk_setsockopt, |
527 | .getsockopt = sock_no_getsockopt, | 570 | .getsockopt = xsk_getsockopt, |
528 | .sendmsg = xsk_sendmsg, | 571 | .sendmsg = xsk_sendmsg, |
529 | .recvmsg = sock_no_recvmsg, | 572 | .recvmsg = sock_no_recvmsg, |
530 | .mmap = xsk_mmap, | 573 | .mmap = xsk_mmap, |
diff --git a/net/xdp/xsk_queue.h b/net/xdp/xsk_queue.h index 3497e8808608..7aa9a535db0e 100644 --- a/net/xdp/xsk_queue.h +++ b/net/xdp/xsk_queue.h | |||
@@ -36,6 +36,11 @@ struct xsk_queue { | |||
36 | 36 | ||
37 | /* Common functions operating for both RXTX and umem queues */ | 37 | /* Common functions operating for both RXTX and umem queues */ |
38 | 38 | ||
39 | static inline u64 xskq_nb_invalid_descs(struct xsk_queue *q) | ||
40 | { | ||
41 | return q ? q->invalid_descs : 0; | ||
42 | } | ||
43 | |||
39 | static inline u32 xskq_nb_avail(struct xsk_queue *q, u32 dcnt) | 44 | static inline u32 xskq_nb_avail(struct xsk_queue *q, u32 dcnt) |
40 | { | 45 | { |
41 | u32 entries = q->prod_tail - q->cons_tail; | 46 | u32 entries = q->prod_tail - q->cons_tail; |