"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-udp.c" (15 Mar 2019, 6188 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-udp.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.51_vs_0.09.52.

    1 /*
    2  * Copyright (C) 2013-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 /* See bugs section of udplite(7) */
   28 #if !defined(SOL_UDPLITE)
   29 #define SOL_UDPLITE     (136)
   30 #endif
   31 #if !defined(UDPLITE_SEND_CSCOV)
   32 #define UDPLITE_SEND_CSCOV  (10)
   33 #endif
   34 #if !defined(UDPLITE_RECV_CSCOV)
   35 #define UDPLITE_RECV_CSCOV  (11)
   36 #endif
   37 
   38 int stress_set_udp_port(const char *opt)
   39 {
   40     int udp_port;
   41 
   42     stress_set_net_port("udp-port", opt,
   43         MIN_UDP_PORT, MAX_UDP_PORT - STRESS_PROCS_MAX,
   44         &udp_port);
   45     return set_setting("udp-port", TYPE_ID_INT, &udp_port);
   46 }
   47 
   48 /*
   49  *  stress_set_udp_domain()
   50  *  set the udp domain option
   51  */
   52 int stress_set_udp_domain(const char *name)
   53 {
   54     int ret, udp_domain;
   55 
   56     ret = stress_set_net_domain(DOMAIN_ALL, "udp-domain", name, &udp_domain);
   57     set_setting("udp-domain", TYPE_ID_INT, &udp_domain);
   58 
   59     return ret;
   60 }
   61 
   62 /*
   63  *  stress_udp
   64  *  stress by heavy udp ops
   65  */
   66 static int stress_udp(const args_t *args)
   67 {
   68     int udp_port = DEFAULT_SOCKET_PORT;
   69     int udp_domain = AF_INET;
   70     pid_t pid, ppid = getppid();
   71     int rc = EXIT_SUCCESS;
   72 #if defined(IPPROTO_UDPLITE)
   73     int proto = (g_opt_flags & OPT_FLAGS_UDP_LITE) ?
   74         IPPROTO_UDPLITE : IPPROTO_UDP;
   75 #else
   76     int proto = 0;
   77 #endif
   78 
   79     (void)get_setting("udp-port", &udp_port);
   80     (void)get_setting("udp-domain", &udp_domain);
   81 
   82 #if defined(IPPROTO_UDPLITE)
   83     if ((proto == IPPROTO_UDPLITE) &&
   84         (udp_domain == AF_UNIX)) {
   85         proto = 0;
   86         if (args->instance == 0) {
   87             pr_inf("%s: disabling UDP-Lite as it is not "
   88                 "available for UNIX domain UDP\n",
   89                 args->name);
   90         }
   91     }
   92 #endif
   93 
   94     pr_dbg("%s: process [%d] using udp port %d\n",
   95         args->name, (int)args->pid, udp_port + args->instance);
   96 
   97 again:
   98     pid = fork();
   99     if (pid < 0) {
  100         if (g_keep_stressing_flag && (errno == EAGAIN))
  101             goto again;
  102         pr_fail_dbg("fork");
  103         return EXIT_FAILURE;
  104     } else if (pid == 0) {
  105         /* Child, client */
  106         struct sockaddr *addr = NULL;
  107 
  108         (void)setpgid(0, g_pgrp);
  109         stress_parent_died_alarm();
  110 
  111         do {
  112             char buf[UDP_BUF];
  113             socklen_t len;
  114             int fd;
  115             int j = 0;
  116 
  117             if ((fd = socket(udp_domain, SOCK_DGRAM, proto)) < 0) {
  118                 pr_fail_dbg("socket");
  119                 /* failed, kick parent to finish */
  120                 (void)kill(getppid(), SIGALRM);
  121                 _exit(EXIT_FAILURE);
  122             }
  123             stress_set_sockaddr(args->name, args->instance, ppid,
  124                 udp_domain, udp_port,
  125                 &addr, &len, NET_ADDR_ANY);
  126 #if defined(IPPROTO_UDPLITE)
  127             if (proto == IPPROTO_UDPLITE) {
  128                 int val = 8;    /* Just the 8 byte header */
  129                 if (setsockopt(fd, SOL_UDPLITE, UDPLITE_SEND_CSCOV, &val, sizeof(val)) < 0) {
  130                     pr_fail_dbg("setsockopt");
  131                     (void)close(fd);
  132                     (void)kill(getppid(), SIGALRM);
  133                     _exit(EXIT_FAILURE);
  134                 }
  135             }
  136 #endif
  137             do {
  138                 size_t i;
  139 
  140                 for (i = 16; i < sizeof(buf); i += 16, j++) {
  141                     (void)memset(buf, 'A' + (j % 26), sizeof(buf));
  142                     ssize_t ret = sendto(fd, buf, i, 0, addr, len);
  143                     if (ret < 0) {
  144                         if ((errno == EINTR) || (errno == ENETUNREACH))
  145                             break;
  146                         pr_fail_dbg("sendto");
  147                         break;
  148                     }
  149                 }
  150             } while (keep_stressing());
  151             (void)close(fd);
  152         } while (keep_stressing());
  153 
  154 #if defined(AF_UNIX)
  155         if ((udp_domain == AF_UNIX) && addr) {
  156             struct sockaddr_un *addr_un = (struct sockaddr_un *)addr;
  157             (void)unlink(addr_un->sun_path);
  158         }
  159 #endif
  160         /* Inform parent we're all done */
  161         (void)kill(getppid(), SIGALRM);
  162         _exit(EXIT_SUCCESS);
  163     } else {
  164         /* Parent, server */
  165 
  166         char buf[UDP_BUF];
  167         int fd, status;
  168 #if !defined(__minix__)
  169         int so_reuseaddr = 1;
  170 #endif
  171         socklen_t addr_len = 0;
  172         struct sockaddr *addr = NULL;
  173 
  174         (void)setpgid(pid, g_pgrp);
  175 
  176         if (stress_sig_stop_stressing(args->name, SIGALRM) < 0) {
  177             rc = EXIT_FAILURE;
  178             goto die;
  179         }
  180         if ((fd = socket(udp_domain, SOCK_DGRAM, proto)) < 0) {
  181             pr_fail_dbg("socket");
  182             rc = EXIT_FAILURE;
  183             goto die;
  184         }
  185         stress_set_sockaddr(args->name, args->instance, ppid,
  186             udp_domain, udp_port,
  187             &addr, &addr_len, NET_ADDR_ANY);
  188 #if defined(IPPROTO_UDPLITE)
  189         if (proto == IPPROTO_UDPLITE) {
  190             int val = 8;    /* Just the 8 byte header */
  191 
  192             if (setsockopt(fd, SOL_UDPLITE, UDPLITE_RECV_CSCOV, &val, sizeof(val)) < 0) {
  193                 pr_fail_dbg("setsockopt");
  194                 rc = EXIT_FAILURE;
  195                 goto die_close;
  196             }
  197         }
  198 #endif
  199         if (bind(fd, addr, addr_len) < 0) {
  200             pr_fail_dbg("bind");
  201             rc = EXIT_FAILURE;
  202             goto die_close;
  203         }
  204 #if !defined(__minix__)
  205         if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr, sizeof(so_reuseaddr)) < 0) {
  206             /*
  207              *  Some systems don't support SO_REUSEADDR
  208              */
  209             if (errno != EINVAL) {
  210                 pr_fail_dbg("setsockopt");
  211                 rc = EXIT_FAILURE;
  212                 goto die_close;
  213             }
  214         }
  215 #endif
  216 
  217         do {
  218             socklen_t len = addr_len;
  219             ssize_t n = recvfrom(fd, buf, sizeof(buf), 0, addr, &len);
  220             if (n == 0)
  221                 break;
  222             if (n < 0) {
  223                 if (errno != EINTR)
  224                     pr_fail_dbg("recvfrom");
  225                 break;
  226             }
  227             inc_counter(args);
  228         } while (keep_stressing());
  229 
  230 die_close:
  231         (void)close(fd);
  232 die:
  233 #if defined(AF_UNIX)
  234         if ((udp_domain == AF_UNIX) && addr) {
  235             struct sockaddr_un *addr_un = (struct sockaddr_un *)addr;
  236             (void)unlink(addr_un->sun_path);
  237         }
  238 #endif
  239         if (pid) {
  240             (void)kill(pid, SIGKILL);
  241             (void)waitpid(pid, &status, 0);
  242         }
  243     }
  244     return rc;
  245 }
  246 
  247 stressor_info_t stress_udp_info = {
  248     .stressor = stress_udp,
  249     .class = CLASS_NETWORK | CLASS_OS
  250 };