Print this page
OS-281


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.

  24  */
  25 
  26 #include <stdio.h>
  27 #include <locale.h>
  28 #include <stdarg.h>
  29 #include <stdlib.h>
  30 #include <fcntl.h>
  31 #include <string.h>
  32 #include <stropts.h>
  33 #include <errno.h>
  34 #include <strings.h>
  35 #include <getopt.h>
  36 #include <unistd.h>
  37 #include <priv.h>
  38 #include <netdb.h>
  39 #include <libintl.h>
  40 #include <libdlflow.h>
  41 #include <libdllink.h>
  42 #include <libdlstat.h>
  43 #include <sys/types.h>


 216 char                    *altroot = NULL;
 217 
 218 /*
 219  * Handle to libdladm.  Opened in main() before the sub-command
 220  * specific function is called.
 221  */
 222 static dladm_handle_t handle = NULL;
 223 
 224 static const char *attr_table[] =
 225         {"local_ip", "remote_ip", "transport", "local_port", "remote_port",
 226             "dsfield"};
 227 
 228 #define NATTR   (sizeof (attr_table)/sizeof (char *))
 229 
 230 static void
 231 usage(void)
 232 {
 233         (void) fprintf(stderr, gettext("usage: flowadm <subcommand>"
 234             " <args>...\n"
 235             "    add-flow       [-t] -l <link> -a <attr>=<value>[,...]\n"
 236             "\t\t   [-p <prop>=<value>,...] <flow>\n"
 237             "    remove-flow    [-t] {-l <link> | <flow>}\n"
 238             "    show-flow      [-p] [-l <link>] "
 239             "[<flow>]\n\n"
 240             "    set-flowprop   [-t] -p <prop>=<value>[,...] <flow>\n"
 241             "    reset-flowprop [-t] [-p <prop>,...] <flow>\n"
 242             "    show-flowprop  [-cP] [-l <link>] [-p <prop>,...] "
 243             "[<flow>]\n"));
 244 
 245         /* close dladm handle if it was opened */
 246         if (handle != NULL)
 247                 dladm_close(handle);
 248 
 249         exit(1);
 250 }
 251 
 252 int
 253 main(int argc, char *argv[])
 254 {
 255         int     i, arglen, cmdlen;
 256         cmd_t   *cmdp;
 257         dladm_status_t status;
 258 


 316         status = dladm_flow_init(handle);
 317         if (status != DLADM_STATUS_OK)
 318                 die_dlerr(status, "flows initialization failed");
 319 }
 320 
 321 static void
 322 do_add_flow(int argc, char *argv[])
 323 {
 324         char                    devname[MAXLINKNAMELEN];
 325         char                    *name = NULL;
 326         uint_t                  index;
 327         datalink_id_t           linkid;
 328 
 329         char                    option;
 330         boolean_t               l_arg = B_FALSE;
 331         char                    propstr[DLADM_STRSIZE];
 332         char                    attrstr[DLADM_STRSIZE];
 333         dladm_arg_list_t        *proplist = NULL;
 334         dladm_arg_list_t        *attrlist = NULL;
 335         dladm_status_t          status;

 336 
 337         bzero(propstr, DLADM_STRSIZE);
 338         bzero(attrstr, DLADM_STRSIZE);
 339 
 340         while ((option = getopt_long(argc, argv, "tR:l:a:p:",
 341             prop_longopts, NULL)) != -1) {
 342                 switch (option) {
 343                 case 't':
 344                         t_arg = B_TRUE;
 345                         break;
 346                 case 'R':
 347                         altroot = optarg;
 348                         break;
 349                 case 'l':
 350                         if (strlcpy(devname, optarg,
 351                             MAXLINKNAMELEN) >= MAXLINKNAMELEN) {
 352                                 die("link name too long");
 353                         }
 354                         if (dladm_name2info(handle, devname, &linkid, NULL,
 355                             NULL, NULL) != DLADM_STATUS_OK)
 356                                 die("invalid link '%s'", devname);
 357                         l_arg = B_TRUE;
 358                         break;
 359                 case 'a':
 360                         (void) strlcat(attrstr, optarg, DLADM_STRSIZE);
 361                         if (strlcat(attrstr, ",", DLADM_STRSIZE) >=
 362                             DLADM_STRSIZE)
 363                                 die("attribute list too long '%s'", attrstr);
 364                         break;
 365                 case 'p':
 366                         (void) strlcat(propstr, optarg, DLADM_STRSIZE);
 367                         if (strlcat(propstr, ",", DLADM_STRSIZE) >=
 368                             DLADM_STRSIZE)
 369                                 die("property list too long '%s'", propstr);
 370                         break;



 371                 default:
 372                         die_opterr(optopt, option);
 373                 }
 374         }
 375         if (!l_arg) {
 376                 die("link is required");
 377         }
 378 




 379         opterr = 0;
 380         index = optind;
 381 
 382         if ((index != (argc - 1)) || match_attr(argv[index]) != NULL) {
 383                 die("flow name is required");
 384         } else {
 385                 /* get flow name; required last argument */
 386                 if (strlen(argv[index]) >= MAXFLOWNAMELEN)
 387                         die("flow name too long");
 388                 name = argv[index];
 389         }
 390 
 391         if (dladm_parse_flow_attrs(attrstr, &attrlist, B_FALSE)
 392             != DLADM_STATUS_OK)
 393                 die("invalid flow attribute specified");
 394         if (dladm_parse_flow_props(propstr, &proplist, B_FALSE)
 395             != DLADM_STATUS_OK)
 396                 die("invalid flow property specified");
 397 
 398         status = dladm_flow_add(handle, linkid, attrlist, proplist, name,
 399             t_arg, altroot);
 400         if (status != DLADM_STATUS_OK)
 401                 die_dlerr(status, "add flow failed");
 402 
 403         dladm_free_attrs(attrlist);
 404         dladm_free_props(proplist);
 405 }
 406 
 407 static void
 408 do_remove_flow(int argc, char *argv[])
 409 {
 410         char                    option;
 411         char                    *flowname = NULL;
 412         char                    linkname[MAXLINKNAMELEN];
 413         datalink_id_t           linkid = DATALINK_ALL_LINKID;
 414         boolean_t               l_arg = B_FALSE;
 415         remove_flow_state_t     state;
 416         dladm_status_t          status;

 417 
 418         bzero(&state, sizeof (state));
 419 
 420         opterr = 0;
 421         while ((option = getopt_long(argc, argv, ":tR:l:",
 422             longopts, NULL)) != -1) {
 423                 switch (option) {
 424                 case 't':
 425                         t_arg = B_TRUE;
 426                         break;
 427                 case 'R':
 428                         altroot = optarg;
 429                         break;
 430                 case 'l':
 431                         if (strlcpy(linkname, optarg,
 432                             MAXLINKNAMELEN) >= MAXLINKNAMELEN) {
 433                                 die("link name too long");
 434                         }
 435                         if (dladm_name2info(handle, linkname, &linkid, NULL,
 436                             NULL, NULL) != DLADM_STATUS_OK) {
 437                                 die("invalid link '%s'", linkname);
 438                         }
 439                         l_arg = B_TRUE;
 440                         break;



 441                 default:
 442                         die_opterr(optopt, option);
 443                         break;
 444                 }
 445         }
 446 
 447         /* when link not specified get flow name */
 448         if (!l_arg) {
 449                 if (optind != (argc-1)) {
 450                         usage();
 451                 } else {
 452                         if (strlen(argv[optind]) >= MAXFLOWNAMELEN)
 453                                 die("flow name too long");
 454                         flowname = argv[optind];
 455                 }
 456                 status = dladm_flow_remove(handle, flowname, t_arg, altroot);
 457         } else {
 458                 /* if link is specified then flow name should not be there */
 459                 if (optind == argc-1)
 460                         usage();






 461                 /* walk the link to find flows and remove them */
 462                 state.fs_tempop = t_arg;
 463                 state.fs_altroot = altroot;
 464                 state.fs_status = DLADM_STATUS_OK;
 465                 status = dladm_walk_flow(remove_flow, handle, linkid, &state,
 466                     B_FALSE);
 467                 /*
 468                  * check if dladm_walk_flow terminated early and see if the
 469                  * walker function as any status for us
 470                  */
 471                 if (status == DLADM_STATUS_OK)
 472                         status = state.fs_status;
 473         }
 474 
 475         if (status != DLADM_STATUS_OK)
 476                 die_dlerr(status, "remove flow failed");
 477 }
 478 
 479 /*
 480  * Walker function for removing a flow through dladm_walk_flow();


 580 
 581         (void) dladm_walk_flow(show_flow, dh, linkid, arg, state->fs_persist);
 582 
 583         return (DLADM_WALK_CONTINUE);
 584 }
 585 
 586 static void
 587 do_show_flow(int argc, char *argv[])
 588 {
 589         char                    flowname[MAXFLOWNAMELEN];
 590         char                    linkname[MAXLINKNAMELEN];
 591         datalink_id_t           linkid = DATALINK_ALL_LINKID;
 592         int                     option;
 593         boolean_t               l_arg = B_FALSE;
 594         boolean_t               o_arg = B_FALSE;
 595         show_flow_state_t       state;
 596         char                    *fields_str = NULL;
 597         ofmt_handle_t           ofmt;
 598         ofmt_status_t           oferr;
 599         uint_t                  ofmtflags = 0;

 600 
 601         bzero(&state, sizeof (state));
 602 
 603         opterr = 0;
 604         while ((option = getopt_long(argc, argv, ":pPl:o:",
 605             longopts, NULL)) != -1) {
 606                 switch (option) {
 607                 case 'p':
 608                         state.fs_parsable = B_TRUE;
 609                         ofmtflags |= OFMT_PARSABLE;
 610                         break;
 611                 case 'P':
 612                         state.fs_persist = B_TRUE;
 613                         break;
 614                 case 'o':
 615                         if (o_arg)
 616                                 die_optdup(option);
 617 
 618                         o_arg = B_TRUE;
 619                         fields_str = optarg;
 620                         break;
 621                 case 'l':
 622                         if (strlcpy(linkname, optarg, MAXLINKNAMELEN)
 623                             >= MAXLINKNAMELEN)
 624                                 die("link name too long\n");
 625                         if (dladm_name2info(handle, linkname, &linkid, NULL,
 626                             NULL, NULL) != DLADM_STATUS_OK)
 627                                 die("invalid link '%s'", linkname);
 628                         l_arg = B_TRUE;
 629                         break;



 630                 default:
 631                         die_opterr(optopt, option);
 632                         break;
 633                 }
 634         }
 635 






 636         /* get flow name (optional last argument */
 637         if (optind == (argc-1)) {
 638                 if (strlcpy(flowname, argv[optind], MAXFLOWNAMELEN)
 639                     >= MAXFLOWNAMELEN)
 640                         die("flow name too long");
 641                 state.fs_flow = flowname;
 642         }
 643 
 644         oferr = ofmt_open(fields_str, flow_fields, ofmtflags, 0, &ofmt);
 645         flowadm_ofmt_check(oferr, state.fs_parsable, ofmt);
 646         state.fs_ofmt = ofmt;
 647 
 648         /* Show attributes of one flow */
 649         if (state.fs_flow != NULL) {
 650                 show_one_flow(&state, state.fs_flow);
 651 
 652         /* Show attributes of flows on one link */
 653         } else if (l_arg) {
 654                 (void) show_flows_onelink(handle, linkid, &state);
 655 




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  * Copyright 2011 Joyent, Inc.  All rights reserved.
  25  */
  26 
  27 #include <stdio.h>
  28 #include <locale.h>
  29 #include <stdarg.h>
  30 #include <stdlib.h>
  31 #include <fcntl.h>
  32 #include <string.h>
  33 #include <stropts.h>
  34 #include <errno.h>
  35 #include <strings.h>
  36 #include <getopt.h>
  37 #include <unistd.h>
  38 #include <priv.h>
  39 #include <netdb.h>
  40 #include <libintl.h>
  41 #include <libdlflow.h>
  42 #include <libdllink.h>
  43 #include <libdlstat.h>
  44 #include <sys/types.h>


 217 char                    *altroot = NULL;
 218 
 219 /*
 220  * Handle to libdladm.  Opened in main() before the sub-command
 221  * specific function is called.
 222  */
 223 static dladm_handle_t handle = NULL;
 224 
 225 static const char *attr_table[] =
 226         {"local_ip", "remote_ip", "transport", "local_port", "remote_port",
 227             "dsfield"};
 228 
 229 #define NATTR   (sizeof (attr_table)/sizeof (char *))
 230 
 231 static void
 232 usage(void)
 233 {
 234         (void) fprintf(stderr, gettext("usage: flowadm <subcommand>"
 235             " <args>...\n"
 236             "    add-flow       [-t] -l <link> -a <attr>=<value>[,...]\n"
 237             "\t\t   [-p <prop>=<value>,...] [-z zonename] <flow>\n"
 238             "    remove-flow    [-t] [-z zonename] {-l <link> | <flow>}\n"
 239             "    show-flow      [-p] [-l <link>] [-z zonename] "
 240             "[<flow>]\n\n"
 241             "    set-flowprop   [-t] -p <prop>=<value>[,...] <flow>\n"
 242             "    reset-flowprop [-t] [-p <prop>,...] <flow>\n"
 243             "    show-flowprop  [-cP] [-l <link>] [-p <prop>,...] "
 244             "[<flow>]\n"));
 245 
 246         /* close dladm handle if it was opened */
 247         if (handle != NULL)
 248                 dladm_close(handle);
 249 
 250         exit(1);
 251 }
 252 
 253 int
 254 main(int argc, char *argv[])
 255 {
 256         int     i, arglen, cmdlen;
 257         cmd_t   *cmdp;
 258         dladm_status_t status;
 259 


 317         status = dladm_flow_init(handle);
 318         if (status != DLADM_STATUS_OK)
 319                 die_dlerr(status, "flows initialization failed");
 320 }
 321 
 322 static void
 323 do_add_flow(int argc, char *argv[])
 324 {
 325         char                    devname[MAXLINKNAMELEN];
 326         char                    *name = NULL;
 327         uint_t                  index;
 328         datalink_id_t           linkid;
 329 
 330         char                    option;
 331         boolean_t               l_arg = B_FALSE;
 332         char                    propstr[DLADM_STRSIZE];
 333         char                    attrstr[DLADM_STRSIZE];
 334         dladm_arg_list_t        *proplist = NULL;
 335         dladm_arg_list_t        *attrlist = NULL;
 336         dladm_status_t          status;
 337         char                    *zonename = NULL;
 338 
 339         bzero(propstr, DLADM_STRSIZE);
 340         bzero(attrstr, DLADM_STRSIZE);
 341 
 342         while ((option = getopt_long(argc, argv, "tR:l:a:p:z:",
 343             prop_longopts, NULL)) != -1) {
 344                 switch (option) {
 345                 case 't':
 346                         t_arg = B_TRUE;
 347                         break;
 348                 case 'R':
 349                         altroot = optarg;
 350                         break;
 351                 case 'l':
 352                         if (strlcpy(devname, optarg,
 353                             MAXLINKNAMELEN) >= MAXLINKNAMELEN) {
 354                                 die("link name too long");
 355                         }



 356                         l_arg = B_TRUE;
 357                         break;
 358                 case 'a':
 359                         (void) strlcat(attrstr, optarg, DLADM_STRSIZE);
 360                         if (strlcat(attrstr, ",", DLADM_STRSIZE) >=
 361                             DLADM_STRSIZE)
 362                                 die("attribute list too long '%s'", attrstr);
 363                         break;
 364                 case 'p':
 365                         (void) strlcat(propstr, optarg, DLADM_STRSIZE);
 366                         if (strlcat(propstr, ",", DLADM_STRSIZE) >=
 367                             DLADM_STRSIZE)
 368                                 die("property list too long '%s'", propstr);
 369                         break;
 370                 case 'z':
 371                         zonename = optarg;
 372                         break;
 373                 default:
 374                         die_opterr(optopt, option);
 375                 }
 376         }
 377         if (!l_arg) {
 378                 die("link is required");
 379         }
 380 
 381         if (dladm_zname2info(handle, zonename, devname, &linkid, NULL,
 382             NULL, NULL) != DLADM_STATUS_OK)
 383                 die("invalid link '%s'", devname);
 384 
 385         opterr = 0;
 386         index = optind;
 387 
 388         if ((index != (argc - 1)) || match_attr(argv[index]) != NULL) {
 389                 die("flow name is required");
 390         } else {
 391                 /* get flow name; required last argument */
 392                 if (strlen(argv[index]) >= MAXFLOWNAMELEN)
 393                         die("flow name too long");
 394                 name = argv[index];
 395         }
 396 
 397         if (dladm_parse_flow_attrs(attrstr, &attrlist, B_FALSE)
 398             != DLADM_STATUS_OK)
 399                 die("invalid flow attribute specified");
 400         if (dladm_parse_flow_props(propstr, &proplist, B_FALSE)
 401             != DLADM_STATUS_OK)
 402                 die("invalid flow property specified");
 403 
 404         status = dladm_flow_add(handle, linkid, attrlist, proplist, name,
 405             t_arg, altroot);
 406         if (status != DLADM_STATUS_OK)
 407                 die_dlerr(status, "add flow failed");
 408 
 409         dladm_free_attrs(attrlist);
 410         dladm_free_props(proplist);
 411 }
 412 
 413 static void
 414 do_remove_flow(int argc, char *argv[])
 415 {
 416         char                    option;
 417         char                    *flowname = NULL;
 418         char                    linkname[MAXLINKNAMELEN];
 419         datalink_id_t           linkid = DATALINK_ALL_LINKID;
 420         boolean_t               l_arg = B_FALSE;
 421         remove_flow_state_t     state;
 422         dladm_status_t          status;
 423         char                    *zonename = NULL;
 424 
 425         bzero(&state, sizeof (state));
 426 
 427         opterr = 0;
 428         while ((option = getopt_long(argc, argv, ":tR:l:z:",
 429             longopts, NULL)) != -1) {
 430                 switch (option) {
 431                 case 't':
 432                         t_arg = B_TRUE;
 433                         break;
 434                 case 'R':
 435                         altroot = optarg;
 436                         break;
 437                 case 'l':
 438                         if (strlcpy(linkname, optarg,
 439                             MAXLINKNAMELEN) >= MAXLINKNAMELEN) {
 440                                 die("link name too long");
 441                         }




 442                         l_arg = B_TRUE;
 443                         break;
 444                 case 'z':
 445                         zonename = optarg;
 446                         break;
 447                 default:
 448                         die_opterr(optopt, option);
 449                         break;
 450                 }
 451         }
 452 
 453         /* when link not specified get flow name */
 454         if (!l_arg) {
 455                 if (optind != (argc-1)) {
 456                         usage();
 457                 } else {
 458                         if (strlen(argv[optind]) >= MAXFLOWNAMELEN)
 459                                 die("flow name too long");
 460                         flowname = argv[optind];
 461                 }
 462                 status = dladm_flow_remove(handle, flowname, t_arg, altroot);
 463         } else {
 464                 /* if link is specified then flow name should not be there */
 465                 if (optind == argc-1)
 466                         usage();
 467 
 468                 if (dladm_zname2info(handle, zonename, linkname, &linkid, NULL,
 469                     NULL, NULL) != DLADM_STATUS_OK) {
 470                         die("invalid link '%s'", linkname);
 471                 }
 472 
 473                 /* walk the link to find flows and remove them */
 474                 state.fs_tempop = t_arg;
 475                 state.fs_altroot = altroot;
 476                 state.fs_status = DLADM_STATUS_OK;
 477                 status = dladm_walk_flow(remove_flow, handle, linkid, &state,
 478                     B_FALSE);
 479                 /*
 480                  * check if dladm_walk_flow terminated early and see if the
 481                  * walker function as any status for us
 482                  */
 483                 if (status == DLADM_STATUS_OK)
 484                         status = state.fs_status;
 485         }
 486 
 487         if (status != DLADM_STATUS_OK)
 488                 die_dlerr(status, "remove flow failed");
 489 }
 490 
 491 /*
 492  * Walker function for removing a flow through dladm_walk_flow();


 592 
 593         (void) dladm_walk_flow(show_flow, dh, linkid, arg, state->fs_persist);
 594 
 595         return (DLADM_WALK_CONTINUE);
 596 }
 597 
 598 static void
 599 do_show_flow(int argc, char *argv[])
 600 {
 601         char                    flowname[MAXFLOWNAMELEN];
 602         char                    linkname[MAXLINKNAMELEN];
 603         datalink_id_t           linkid = DATALINK_ALL_LINKID;
 604         int                     option;
 605         boolean_t               l_arg = B_FALSE;
 606         boolean_t               o_arg = B_FALSE;
 607         show_flow_state_t       state;
 608         char                    *fields_str = NULL;
 609         ofmt_handle_t           ofmt;
 610         ofmt_status_t           oferr;
 611         uint_t                  ofmtflags = 0;
 612         char                    *zonename = NULL;
 613 
 614         bzero(&state, sizeof (state));
 615 
 616         opterr = 0;
 617         while ((option = getopt_long(argc, argv, ":pPl:o:z:",
 618             longopts, NULL)) != -1) {
 619                 switch (option) {
 620                 case 'p':
 621                         state.fs_parsable = B_TRUE;
 622                         ofmtflags |= OFMT_PARSABLE;
 623                         break;
 624                 case 'P':
 625                         state.fs_persist = B_TRUE;
 626                         break;
 627                 case 'o':
 628                         if (o_arg)
 629                                 die_optdup(option);
 630 
 631                         o_arg = B_TRUE;
 632                         fields_str = optarg;
 633                         break;
 634                 case 'l':
 635                         if (strlcpy(linkname, optarg, MAXLINKNAMELEN)
 636                             >= MAXLINKNAMELEN)
 637                                 die("link name too long\n");



 638                         l_arg = B_TRUE;
 639                         break;
 640                 case 'z':
 641                         zonename = optarg;
 642                         break;
 643                 default:
 644                         die_opterr(optopt, option);
 645                         break;
 646                 }
 647         }
 648 
 649         if (l_arg) {
 650                 if (dladm_zname2info(handle, zonename, linkname, &linkid, NULL,
 651                     NULL, NULL) != DLADM_STATUS_OK)
 652                         die("invalid link '%s'", linkname);
 653         }
 654 
 655         /* get flow name (optional last argument */
 656         if (optind == (argc-1)) {
 657                 if (strlcpy(flowname, argv[optind], MAXFLOWNAMELEN)
 658                     >= MAXFLOWNAMELEN)
 659                         die("flow name too long");
 660                 state.fs_flow = flowname;
 661         }
 662 
 663         oferr = ofmt_open(fields_str, flow_fields, ofmtflags, 0, &ofmt);
 664         flowadm_ofmt_check(oferr, state.fs_parsable, ofmt);
 665         state.fs_ofmt = ofmt;
 666 
 667         /* Show attributes of one flow */
 668         if (state.fs_flow != NULL) {
 669                 show_one_flow(&state, state.fs_flow);
 670 
 671         /* Show attributes of flows on one link */
 672         } else if (l_arg) {
 673                 (void) show_flows_onelink(handle, linkid, &state);
 674