"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-netlink-proc.c" (15 Mar 2019, 5782 Bytes) of package /linux/privat/stress-ng-0.09.56.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "stress-netlink-proc.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.50_vs_0.09.51.

    1 /*
    2  * Copyright (C) 2017-2019 Canonical, Ltd.
    3  *
    4  * This program is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public License
    6  * as published by the Free Software Foundation; either version 2
    7  * of the License, or (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   17  *
   18  * This code is a complete clean re-write of the stress tool by
   19  * Colin Ian King <colin.king@canonical.com> and attempts to be
   20  * backwardly compatible with the stress tool by Amos Waterland
   21  * <apw@rossby.metr.ou.edu> but has more stress tests and more
   22  * functionality.
   23  *
   24  */
   25 #include "stress-ng.h"
   26 
   27 #if defined (__linux__) &&      \
   28     defined(HAVE_LINUX_CONNECTOR_H) &&  \
   29     defined(HAVE_LINUX_NETLINK_H) &&    \
   30     defined(HAVE_LINUX_CN_PROC_H)
   31 
   32 #ifndef LINUX_VERSION_CODE
   33 #define LINUX_VERSION_CODE KERNEL_VERSION(2,0,0)
   34 #endif
   35 
   36 /*
   37  *  stress_netlink_proc_supported()
   38  *  check if we can run this as root
   39  */
   40 static int stress_netlink_proc_supported(void)
   41 {
   42     if (geteuid() != 0) {
   43         pr_inf("netlink-proc stressor will be skipped, "
   44             "need to be running as root for this stressor\n");
   45         return -1;
   46     }
   47     return 0;
   48 }
   49 
   50 /*
   51  *   monitor()
   52  *  monitor system activity
   53  */
   54 static int monitor(const args_t *args, const int sock)
   55 {
   56     struct nlmsghdr *nlmsghdr;
   57 
   58     ssize_t len;
   59     char __attribute__ ((aligned(NLMSG_ALIGNTO)))buf[4096];
   60 
   61     if ((len = recv(sock, buf, sizeof(buf), 0)) == 0)
   62         return 0;
   63 
   64     if (len == -1) {
   65         switch (errno) {
   66         case EINTR:
   67         case ENOBUFS:
   68             return 0;
   69         default:
   70             return -1;
   71         }
   72     }
   73 
   74     for (nlmsghdr = (struct nlmsghdr *)buf;
   75         NLMSG_OK (nlmsghdr, len);
   76         nlmsghdr = NLMSG_NEXT (nlmsghdr, len)) {
   77 
   78         struct cn_msg *cn_msg;
   79         struct proc_event *proc_ev;
   80 
   81         if (!g_keep_stressing_flag)
   82             return 0;
   83 
   84         if ((nlmsghdr->nlmsg_type == NLMSG_ERROR) ||
   85             (nlmsghdr->nlmsg_type == NLMSG_NOOP))
   86             continue;
   87 
   88         cn_msg = NLMSG_DATA(nlmsghdr);
   89         if ((cn_msg->id.idx != CN_IDX_PROC) ||
   90             (cn_msg->id.val != CN_VAL_PROC))
   91             continue;
   92 
   93         proc_ev = (struct proc_event *)cn_msg->data;
   94 
   95         switch (proc_ev->what) {
   96 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
   97         case PROC_EVENT_FORK:
   98         case PROC_EVENT_EXEC:
   99         case PROC_EVENT_EXIT:
  100         case PROC_EVENT_UID:
  101 #endif
  102 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
  103         case PROC_EVENT_SID:
  104 #endif
  105 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
  106         case PROC_EVENT_COREDUMP:
  107 #endif
  108 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0)
  109         case PROC_EVENT_COMM:
  110 #endif
  111 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0)
  112         case PROC_EVENT_PTRACE:
  113 #endif
  114             inc_counter(args);
  115             break;
  116         default:
  117             break;
  118         }
  119     }
  120     return 0;
  121 }
  122 
  123 
  124 /*
  125  *  spawn_several()
  126  *  create a bunch of processes
  127  */
  128 static void spawn_several(const char *name, int n, int max)
  129 {
  130     pid_t pid;
  131 
  132     pid = fork();
  133     if (pid == 0) {
  134         char newname[128];
  135 
  136         (void)snprintf(newname, sizeof(newname), "stress-ng-%d", n);
  137         stress_set_proc_name(newname);
  138 
  139         if (n >= max) {
  140             stress_set_proc_name("stress-ng-dead");
  141             _exit(0);
  142         } else {
  143             stress_set_proc_name("stress-ng-spawn");
  144             spawn_several(name, n + 1, max);
  145         }
  146     } else if (pid < 0) {
  147         return;
  148     } else {
  149         int status;
  150 
  151         if (n != 0)
  152             stress_set_proc_name("stress-ng-wait");
  153         (void)waitpid(pid, &status, 0);
  154         if (n != 0)
  155             _exit(0);
  156     }
  157 }
  158 
  159 /*
  160  *  stress_netlink_proc()
  161  *  stress netlink proc events
  162  */
  163 static int stress_netlink_proc(const args_t *args)
  164 {
  165     int sock = -1;
  166     struct sockaddr_nl addr;
  167     struct iovec iov[3];
  168     struct nlmsghdr nlmsghdr;
  169     struct cn_msg cn_msg;
  170     enum proc_cn_mcast_op op;
  171 
  172     if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR)) < 0) {
  173         if (errno == EPROTONOSUPPORT) {
  174             pr_err("%s: kernel does not support netlink, errno=%d (%s)\n",
  175                 args->name, errno, strerror(errno));
  176             return EXIT_NO_RESOURCE;
  177         }
  178         pr_fail("%s: socket failed: errno=%d (%s)\n",
  179             args->name, errno, strerror(errno));
  180         return EXIT_FAILURE;
  181     }
  182 
  183     (void)memset(&addr, 0, sizeof(addr));
  184     addr.nl_pid = getpid();
  185     addr.nl_family = AF_NETLINK;
  186     addr.nl_groups = CN_IDX_PROC;
  187 
  188     if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
  189         pr_err("%s: bind failed: errno=%d (%s)\n",
  190             args->name, errno, strerror(errno));
  191         (void)close(sock);
  192         return EXIT_FAILURE;
  193     }
  194 
  195     (void)memset(&nlmsghdr, 0, sizeof(nlmsghdr));
  196     nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(cn_msg) + sizeof(op));
  197     nlmsghdr.nlmsg_pid = getpid();
  198     nlmsghdr.nlmsg_type = NLMSG_DONE;
  199     iov[0].iov_base = &nlmsghdr;
  200     iov[0].iov_len = sizeof(nlmsghdr);
  201 
  202     (void)memset(&cn_msg, 0, sizeof(cn_msg));
  203     cn_msg.id.idx = CN_IDX_PROC;
  204     cn_msg.id.val = CN_VAL_PROC;
  205     cn_msg.len = sizeof(enum proc_cn_mcast_op);
  206     iov[1].iov_base = &cn_msg;
  207     iov[1].iov_len = sizeof(cn_msg);
  208 
  209     op = PROC_CN_MCAST_LISTEN;
  210     iov[2].iov_base = &op;
  211     iov[2].iov_len = sizeof(op);
  212 
  213     if (writev(sock, iov, 3) < 0) {
  214         pr_err("%s: writev failed: errno=%d (%s)\n",
  215             args->name, errno, strerror(errno));
  216         (void)close(sock);
  217         return EXIT_FAILURE;
  218     }
  219 
  220     do {
  221         spawn_several(args->name, 0, 5);
  222         if (monitor(args, sock) < 0)
  223             break;
  224     } while (keep_stressing());
  225 
  226     (void)close(sock);
  227 
  228     return EXIT_SUCCESS;
  229 }
  230 
  231 stressor_info_t stress_netlink_proc_info = {
  232     .stressor = stress_netlink_proc,
  233     .supported = stress_netlink_proc_supported,
  234     .class = CLASS_SCHEDULER | CLASS_OS
  235 };
  236 #else
  237 stressor_info_t stress_netlink_proc_info = {
  238     .stressor = stress_not_implemented,
  239     .class = CLASS_SCHEDULER | CLASS_OS
  240 };
  241 #endif