]> rtime.felk.cvut.cz Git - lisovros/iproute2_canprio.git/blobdiff - misc/ss.c
ss: use new INET_DIAG_SKMEMINFO option to get more memory information for tcp socket
[lisovros/iproute2_canprio.git] / misc / ss.c
index eb42fd66f2f53b3f0910d4bc3ef2c3df39d9c136..cf529ef7bb49537890ed95ce8a1f9abcabe96a2e 100644 (file)
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -1336,7 +1336,17 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r)
        parse_rtattr(tb, INET_DIAG_MAX, (struct rtattr*)(r+1),
                     nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
 
-       if (tb[INET_DIAG_MEMINFO]) {
+       if (tb[INET_DIAG_SKMEMINFO]) {
+               const __u32 *skmeminfo =  RTA_DATA(tb[INET_DIAG_SKMEMINFO]);
+               printf(" skmem:(r%u,rb%u,t%u,tb%u,f%u,w%u,o%u)",
+                       skmeminfo[SK_MEMINFO_RMEM_ALLOC],
+                       skmeminfo[SK_MEMINFO_RCVBUF],
+                       skmeminfo[SK_MEMINFO_WMEM_ALLOC],
+                       skmeminfo[SK_MEMINFO_SNDBUF],
+                       skmeminfo[SK_MEMINFO_FWD_ALLOC],
+                       skmeminfo[SK_MEMINFO_WMEM_QUEUED],
+                       skmeminfo[SK_MEMINFO_OPTMEM]);
+       }else if (tb[INET_DIAG_MEMINFO]) {
                const struct inet_diag_meminfo *minfo
                        = RTA_DATA(tb[INET_DIAG_MEMINFO]);
                printf(" mem:(r%u,w%u,f%u,t%u)",
@@ -1370,7 +1380,7 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r)
                }
 
                if (tb[INET_DIAG_CONG])
-                       printf(" %s", (char *) RTA_DATA(tb[INET_DIAG_CONG]));
+                       printf(" %s", rta_getattr_str(tb[INET_DIAG_CONG]));
 
                if (info->tcpi_options & TCPI_OPT_WSCALE)
                        printf(" wscale:%d,%d", info->tcpi_snd_wscale,
@@ -1505,8 +1515,10 @@ static int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype)
        memset(&req.r, 0, sizeof(req.r));
        req.r.idiag_family = AF_INET;
        req.r.idiag_states = f->states;
-       if (show_mem)
+       if (show_mem) {
                req.r.idiag_ext |= (1<<(INET_DIAG_MEMINFO-1));
+               req.r.idiag_ext |= (1<<(INET_DIAG_SKMEMINFO-1));
+       }
 
        if (show_tcpinfo) {
                req.r.idiag_ext |= (1<<(INET_DIAG_INFO-1));
@@ -1534,8 +1546,10 @@ static int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype)
                .msg_iovlen = f->f ? 3 : 1,
        };
 
-       if (sendmsg(fd, &msg, 0) < 0)
+       if (sendmsg(fd, &msg, 0) < 0) {
+               close(fd);
                return -1;
+       }
 
        iov[0] = (struct iovec){
                .iov_base = buf,
@@ -1563,6 +1577,7 @@ static int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype)
                }
                if (status == 0) {
                        fprintf(stderr, "EOF on netlink\n");
+                       close(fd);
                        return 0;
                }
 
@@ -1578,16 +1593,23 @@ static int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype)
                            h->nlmsg_seq != 123456)
                                goto skip_it;
 
-                       if (h->nlmsg_type == NLMSG_DONE)
+                       if (h->nlmsg_type == NLMSG_DONE) {
+                               close(fd);
                                return 0;
+                       }
                        if (h->nlmsg_type == NLMSG_ERROR) {
                                struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
                                if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
                                        fprintf(stderr, "ERROR truncated\n");
                                } else {
                                        errno = -err->error;
+                                       if (errno == EOPNOTSUPP) {
+                                               close(fd);
+                                               return -1;
+                                       }
                                        perror("TCPDIAG answers");
                                }
+                               close(fd);
                                return 0;
                        }
                        if (!dump_fp) {
@@ -1596,8 +1618,10 @@ static int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype)
                                        continue;
                                }
                                err = tcp_show_sock(h, NULL);
-                               if (err < 0)
+                               if (err < 0) {
+                                       close(fd);
                                        return err;
+                               }
                        }
 
 skip_it:
@@ -1612,6 +1636,7 @@ skip_it:
                        exit(1);
                }
        }
+       close(fd);
        return 0;
 }
 
@@ -2054,67 +2079,38 @@ static int unix_show_sock(struct nlmsghdr *nlh, struct filter *f)
 static int unix_show_netlink(struct filter *f, FILE *dump_fp)
 {
        int fd;
-       struct sockaddr_nl nladdr;
        struct {
                struct nlmsghdr nlh;
                struct unix_diag_req r;
        } req;
-       struct msghdr msg;
        char    buf[8192];
-       struct iovec iov[3];
 
        if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0)
                return -1;
 
-       memset(&nladdr, 0, sizeof(nladdr));
-       nladdr.nl_family = AF_NETLINK;
-
+       memset(&req, 0, sizeof(req));
        req.nlh.nlmsg_len = sizeof(req);
        req.nlh.nlmsg_type = SOCK_DIAG_BY_FAMILY;
        req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
-       req.nlh.nlmsg_pid = 0;
        req.nlh.nlmsg_seq = 123456;
-       memset(&req.r, 0, sizeof(req.r));
+
        req.r.sdiag_family = AF_UNIX;
-       req.r.sdiag_protocol = 0; /* ignored */
        req.r.udiag_states = f->states;
        req.r.udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_PEER | UDIAG_SHOW_RQLEN;
 
-       iov[0] = (struct iovec){
-               .iov_base = &req,
-               .iov_len = sizeof(req)
-       };
-
-       msg = (struct msghdr) {
-               .msg_name = (void*)&nladdr,
-               .msg_namelen = sizeof(nladdr),
-               .msg_iov = iov,
-               .msg_iovlen = f->f ? 3 : 1,
-       };
-
-       if (sendmsg(fd, &msg, 0) < 0) {
+       if (send(fd, &req, sizeof(req), 0) < 0) {
                close(fd);
                return -1;
        }
 
-       iov[0] = (struct iovec){
-               .iov_base = buf,
-               .iov_len = sizeof(buf)
-       };
-
        while (1) {
-               int status;
+               ssize_t status;
                struct nlmsghdr *h;
+               struct sockaddr_nl nladdr;
+               socklen_t slen = sizeof(nladdr);
 
-               msg = (struct msghdr) {
-                       (void*)&nladdr, sizeof(nladdr),
-                       iov,    1,
-                       NULL,   0,
-                       0
-               };
-
-               status = recvmsg(fd, &msg, 0);
-
+               status = recvfrom(fd, buf, sizeof(buf), 0,
+                                 (struct sockaddr *) &nladdr, &slen);
                if (status < 0) {
                        if (errno == EINTR)
                                continue;
@@ -2123,8 +2119,7 @@ static int unix_show_netlink(struct filter *f, FILE *dump_fp)
                }
                if (status == 0) {
                        fprintf(stderr, "EOF on netlink\n");
-                       close(fd);
-                       return 0;
+                       goto close_it;
                }
 
                if (dump_fp)
@@ -2138,10 +2133,9 @@ static int unix_show_netlink(struct filter *f, FILE *dump_fp)
                            h->nlmsg_seq != 123456)
                                goto skip_it;
 
-                       if (h->nlmsg_type == NLMSG_DONE) {
-                               close(fd);
-                               return 0;
-                       }
+                       if (h->nlmsg_type == NLMSG_DONE)
+                               goto close_it;
+
                        if (h->nlmsg_type == NLMSG_ERROR) {
                                struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
                                if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
@@ -2165,15 +2159,14 @@ static int unix_show_netlink(struct filter *f, FILE *dump_fp)
 skip_it:
                        h = NLMSG_NEXT(h, status);
                }
-               if (msg.msg_flags & MSG_TRUNC) {
-                       fprintf(stderr, "Message truncated\n");
-                       continue;
-               }
+
                if (status) {
-                       fprintf(stderr, "!!!Remnant of size %d\n", status);
+                       fprintf(stderr, "!!!Remnant of size %zd\n", status);
                        exit(1);
                }
        }
+
+close_it:
        close(fd);
        return 0;
 }