iproute2/tipc/link.c
<<
>>
Prefs
   1/*
   2 * link.c       TIPC link functionality.
   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
   7 *              2 of the License, or (at your option) any later version.
   8 *
   9 * Authors:     Richard Alpe <richard.alpe@ericsson.com>
  10 */
  11
  12#include <stdio.h>
  13#include <stdlib.h>
  14#include <string.h>
  15#include <errno.h>
  16
  17#include <linux/tipc_netlink.h>
  18#include <linux/tipc.h>
  19#include <linux/genetlink.h>
  20#include <libmnl/libmnl.h>
  21
  22#include "mnl_utils.h"
  23#include "cmdl.h"
  24#include "msg.h"
  25#include "link.h"
  26#include "bearer.h"
  27#include "utils.h"
  28
  29#define PRIORITY_STR "priority"
  30#define TOLERANCE_STR "tolerance"
  31#define WINDOW_STR "window"
  32#define BROADCAST_STR "broadcast"
  33
  34static const char tipc_bclink_name[] = "broadcast-link";
  35
  36static int link_list_cb(const struct nlmsghdr *nlh, void *data)
  37{
  38        struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
  39        struct nlattr *info[TIPC_NLA_MAX + 1] = {};
  40        struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1] = {};
  41
  42        mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
  43        if (!info[TIPC_NLA_LINK])
  44                return MNL_CB_ERROR;
  45
  46        mnl_attr_parse_nested(info[TIPC_NLA_LINK], parse_attrs, attrs);
  47        if (!attrs[TIPC_NLA_LINK_NAME])
  48                return MNL_CB_ERROR;
  49
  50        print_string(PRINT_FP, NULL, "%s: ",
  51                             mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME]));
  52        if (attrs[TIPC_NLA_LINK_UP])
  53                print_string(PRINT_ANY,
  54                         mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME]),"%s\n", "up");
  55        else
  56                print_string(PRINT_ANY,
  57                         mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME]), "%s\n", "down");
  58        return MNL_CB_OK;
  59}
  60
  61static int cmd_link_list(struct nlmsghdr *nlh, const struct cmd *cmd,
  62                         struct cmdl *cmdl, void *data)
  63{
  64        int err = 0;
  65
  66        if (help_flag) {
  67                fprintf(stderr, "Usage: %s link list\n", cmdl->argv[0]);
  68                return -EINVAL;
  69        }
  70
  71        nlh = msg_init(TIPC_NL_LINK_GET);
  72        if (!nlh) {
  73                fprintf(stderr, "error, message initialisation failed\n");
  74                return -1;
  75        }
  76
  77        new_json_obj(json);
  78        open_json_object(NULL);
  79        err = msg_dumpit(nlh, link_list_cb, NULL);
  80        close_json_object();
  81        delete_json_obj();
  82        return err;
  83}
  84
  85static int link_get_cb(const struct nlmsghdr *nlh, void *data)
  86{
  87        int *prop = data;
  88        struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
  89        struct nlattr *info[TIPC_NLA_MAX + 1] = {};
  90        struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1] = {};
  91        struct nlattr *props[TIPC_NLA_PROP_MAX + 1] = {};
  92
  93        mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
  94        if (!info[TIPC_NLA_LINK])
  95                return MNL_CB_ERROR;
  96
  97        mnl_attr_parse_nested(info[TIPC_NLA_LINK], parse_attrs, attrs);
  98        if (!attrs[TIPC_NLA_LINK_PROP])
  99                return MNL_CB_ERROR;
 100
 101        mnl_attr_parse_nested(attrs[TIPC_NLA_LINK_PROP], parse_attrs, props);
 102        if (!props[*prop])
 103                return MNL_CB_ERROR;
 104
 105        new_json_obj(json);
 106        open_json_object(NULL);
 107        switch (*prop) {
 108                case TIPC_NLA_PROP_PRIO:
 109                        print_uint(PRINT_ANY, PRIORITY_STR, "%u\n", mnl_attr_get_u32(props[*prop]));
 110                break;
 111                case TIPC_NLA_PROP_TOL:
 112                        print_uint(PRINT_ANY, TOLERANCE_STR, "%u\n", mnl_attr_get_u32(props[*prop]));
 113                break;
 114                case TIPC_NLA_PROP_WIN:
 115                        print_uint(PRINT_ANY, WINDOW_STR, "%u\n", mnl_attr_get_u32(props[*prop]));
 116                break;
 117                default:
 118                        break;
 119        }
 120        close_json_object();
 121        delete_json_obj();
 122        return MNL_CB_OK;
 123}
 124
 125static int cmd_link_get_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
 126                             struct cmdl *cmdl, void *data)
 127{
 128        int prop;
 129        struct nlattr *attrs;
 130        struct opt *opt;
 131        struct opt opts[] = {
 132                { "link",               OPT_KEYVAL,     NULL },
 133                { NULL }
 134        };
 135
 136        if (strcmp(cmd->cmd, PRIORITY_STR) == 0)
 137                prop = TIPC_NLA_PROP_PRIO;
 138        else if ((strcmp(cmd->cmd, TOLERANCE_STR) == 0))
 139                prop = TIPC_NLA_PROP_TOL;
 140        else if ((strcmp(cmd->cmd, WINDOW_STR) == 0))
 141                prop = TIPC_NLA_PROP_WIN;
 142        else
 143                return -EINVAL;
 144
 145        if (help_flag) {
 146                (cmd->help)(cmdl);
 147                return -EINVAL;
 148        }
 149
 150        if (parse_opts(opts, cmdl) < 0)
 151                return -EINVAL;
 152
 153        nlh = msg_init(TIPC_NL_LINK_GET);
 154        if (!nlh) {
 155                fprintf(stderr, "error, message initialisation failed\n");
 156                return -1;
 157        }
 158
 159        opt = get_opt(opts, "link");
 160        if (!opt) {
 161                fprintf(stderr, "error, missing link\n");
 162                return -EINVAL;
 163        }
 164        attrs = mnl_attr_nest_start(nlh, TIPC_NLA_LINK);
 165        mnl_attr_put_strz(nlh, TIPC_NLA_LINK_NAME, opt->val);
 166        mnl_attr_nest_end(nlh, attrs);
 167
 168        return msg_doit(nlh, link_get_cb, &prop);
 169}
 170
 171static void cmd_link_get_help(struct cmdl *cmdl)
 172{
 173        fprintf(stderr, "Usage: %s link get PPROPERTY link LINK\n\n"
 174                "PROPERTIES\n"
 175                " tolerance             - Get link tolerance\n"
 176                " priority              - Get link priority\n"
 177                " window                - Get link window\n"
 178                " broadcast             - Get link broadcast\n",
 179                cmdl->argv[0]);
 180}
 181
 182static int cmd_link_get_bcast_cb(const struct nlmsghdr *nlh, void *data)
 183{
 184        int *prop = data;
 185        int prop_ratio = TIPC_NLA_PROP_BROADCAST_RATIO;
 186        struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
 187        struct nlattr *info[TIPC_NLA_MAX + 1] = {};
 188        struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1] = {};
 189        struct nlattr *props[TIPC_NLA_PROP_MAX + 1] = {};
 190        int bc_mode;
 191
 192        mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
 193        if (!info[TIPC_NLA_LINK])
 194                return MNL_CB_ERROR;
 195
 196        mnl_attr_parse_nested(info[TIPC_NLA_LINK], parse_attrs, attrs);
 197        if (!attrs[TIPC_NLA_LINK_PROP])
 198                return MNL_CB_ERROR;
 199
 200        mnl_attr_parse_nested(attrs[TIPC_NLA_LINK_PROP], parse_attrs, props);
 201        if (!props[*prop])
 202                return MNL_CB_ERROR;
 203
 204        bc_mode = mnl_attr_get_u32(props[*prop]);
 205
 206        new_json_obj(json);
 207        open_json_object(NULL);
 208        switch (bc_mode) {
 209        case 0x1:
 210                print_string(PRINT_ANY, "method", "%s\n", "BROADCAST");
 211                break;
 212        case 0x2:
 213                print_string(PRINT_ANY, "method", "%s\n", "REPLICAST");
 214                break;
 215        case 0x4:
 216                print_string(PRINT_ANY, "method", "%s", "AUTOSELECT");
 217                close_json_object();
 218                open_json_object(NULL);
 219                print_uint(PRINT_ANY, "ratio", " ratio:%u\n",
 220                           mnl_attr_get_u32(props[prop_ratio]));
 221                break;
 222        default:
 223                print_string(PRINT_ANY, NULL, "UNKNOWN\n", NULL);
 224                break;
 225        }
 226        close_json_object();
 227        delete_json_obj();
 228        return MNL_CB_OK;
 229}
 230
 231static void cmd_link_get_bcast_help(struct cmdl *cmdl)
 232{
 233        fprintf(stderr, "Usage: %s link get PPROPERTY\n\n"
 234                "PROPERTIES\n"
 235                " broadcast             - Get link broadcast\n",
 236                cmdl->argv[0]);
 237}
 238
 239static int cmd_link_get_bcast(struct nlmsghdr *nlh, const struct cmd *cmd,
 240                             struct cmdl *cmdl, void *data)
 241{
 242        int prop = TIPC_NLA_PROP_BROADCAST;
 243        struct nlattr *attrs;
 244
 245        if (help_flag) {
 246                (cmd->help)(cmdl);
 247                return -EINVAL;
 248        }
 249
 250        nlh = msg_init(TIPC_NL_LINK_GET);
 251        if (!nlh) {
 252                fprintf(stderr, "error, message initialisation failed\n");
 253                return -1;
 254        }
 255        attrs = mnl_attr_nest_start(nlh, TIPC_NLA_LINK);
 256        /* Direct to broadcast-link setting */
 257        mnl_attr_put_strz(nlh, TIPC_NLA_LINK_NAME, tipc_bclink_name);
 258        mnl_attr_nest_end(nlh, attrs);
 259        return msg_doit(nlh, cmd_link_get_bcast_cb, &prop);
 260}
 261
 262static int cmd_link_get(struct nlmsghdr *nlh, const struct cmd *cmd,
 263                        struct cmdl *cmdl, void *data)
 264{
 265        const struct cmd cmds[] = {
 266                { PRIORITY_STR, cmd_link_get_prop,      cmd_link_get_help },
 267                { TOLERANCE_STR,        cmd_link_get_prop,      cmd_link_get_help },
 268                { WINDOW_STR,   cmd_link_get_prop,      cmd_link_get_help },
 269                { BROADCAST_STR, cmd_link_get_bcast, cmd_link_get_bcast_help },
 270                { NULL }
 271        };
 272
 273        return run_cmd(nlh, cmd, cmds, cmdl, NULL);
 274}
 275
 276static void cmd_link_stat_reset_help(struct cmdl *cmdl)
 277{
 278        fprintf(stderr, "Usage: %s link stat reset link LINK\n\n", cmdl->argv[0]);
 279}
 280
 281static int cmd_link_stat_reset(struct nlmsghdr *nlh, const struct cmd *cmd,
 282                               struct cmdl *cmdl, void *data)
 283{
 284        char *link;
 285        struct opt *opt;
 286        struct nlattr *nest;
 287        struct opt opts[] = {
 288                { "link",               OPT_KEYVAL,     NULL },
 289                { NULL }
 290        };
 291
 292        if (help_flag) {
 293                (cmd->help)(cmdl);
 294                return -EINVAL;
 295        }
 296
 297        if (parse_opts(opts, cmdl) != 1) {
 298                (cmd->help)(cmdl);
 299                return -EINVAL;
 300        }
 301
 302        nlh = msg_init(TIPC_NL_LINK_RESET_STATS);
 303        if (!nlh) {
 304                fprintf(stderr, "error, message initialisation failed\n");
 305                return -1;
 306        }
 307
 308        opt = get_opt(opts, "link");
 309        if (!opt) {
 310                fprintf(stderr, "error, missing link\n");
 311                return -EINVAL;
 312        }
 313        link = opt->val;
 314
 315        nest = mnl_attr_nest_start(nlh, TIPC_NLA_LINK);
 316        mnl_attr_put_strz(nlh, TIPC_NLA_LINK_NAME, link);
 317        mnl_attr_nest_end(nlh, nest);
 318
 319        return msg_doit(nlh, NULL, NULL);
 320}
 321
 322static uint32_t perc(uint32_t count, uint32_t total)
 323{
 324        return (count * 100 + (total / 2)) / total;
 325}
 326
 327static int _show_link_stat(const char *name, struct nlattr *attrs[],
 328                           struct nlattr *prop[], struct nlattr *stats[])
 329{
 330        uint32_t proft;
 331
 332        open_json_object(NULL);
 333
 334        print_string(PRINT_ANY, "link", "Link <%s>\n", name);
 335        print_string(PRINT_JSON, "state", "", NULL);
 336        open_json_array(PRINT_JSON, NULL);
 337        if (attrs[TIPC_NLA_LINK_ACTIVE])
 338                print_string(PRINT_ANY, NULL, "  %s", "ACTIVE");
 339        else if (attrs[TIPC_NLA_LINK_UP])
 340                print_string(PRINT_ANY, NULL, "  %s", "STANDBY");
 341        else
 342                print_string(PRINT_ANY, NULL, "  %s", "DEFUNCT");
 343        close_json_array(PRINT_JSON, NULL);
 344
 345        print_uint(PRINT_ANY, "mtu", "  MTU:%u",
 346                           mnl_attr_get_u32(attrs[TIPC_NLA_LINK_MTU]));
 347        print_uint(PRINT_ANY, PRIORITY_STR, "  Priority:%u",
 348                           mnl_attr_get_u32(prop[TIPC_NLA_PROP_PRIO]));
 349        print_uint(PRINT_ANY, TOLERANCE_STR, "  Tolerance:%u ms",
 350                           mnl_attr_get_u32(prop[TIPC_NLA_PROP_TOL]));
 351        print_uint(PRINT_ANY, WINDOW_STR, "  Window:%u packets\n",
 352                           mnl_attr_get_u32(prop[TIPC_NLA_PROP_WIN]));
 353
 354        open_json_object("rx packets");
 355        print_uint(PRINT_ANY, "rx packets", "  RX packets:%u",
 356                           mnl_attr_get_u32(attrs[TIPC_NLA_LINK_RX]) -
 357                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_INFO]));
 358        print_uint(PRINT_ANY, "fragments", " fragments:%u",
 359                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTS]));
 360        print_uint(PRINT_ANY, "fragmented", "/%u",
 361                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTED]));
 362        print_uint(PRINT_ANY, "bundles", " bundles:%u",
 363                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLES]));
 364        print_uint(PRINT_ANY, "bundled", "/%u\n",
 365                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLED]));
 366        close_json_object();
 367
 368        open_json_object("tx packets");
 369        print_uint(PRINT_ANY, "tx packets", "  TX packets:%u",
 370                           mnl_attr_get_u32(attrs[TIPC_NLA_LINK_TX]) -
 371                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_INFO]));
 372        print_uint(PRINT_ANY, "fragments", " fragments:%u",
 373                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTS]));
 374        print_uint(PRINT_ANY, "fragmented", "/%u",
 375                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTED]));
 376        print_uint(PRINT_ANY, "bundles", " bundles:%u",
 377                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLES]));
 378        print_uint(PRINT_ANY, "bundled", "/%u\n",
 379                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLED]));
 380        close_json_object();
 381
 382        proft = mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT]);
 383        print_uint(PRINT_ANY, "tx profile sample", "  TX profile sample:%u",
 384                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_CNT]));
 385        print_uint(PRINT_ANY, "packets average", " packets average:%u octets\n",
 386                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_TOT]) / proft);
 387
 388        print_uint(PRINT_ANY, "0-64", "  0-64:%u%%",
 389                           perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P0]), proft));
 390        print_uint(PRINT_ANY, "-256", " -256:%u%%",
 391                           perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P1]), proft));
 392        print_uint(PRINT_ANY, "-1024", " -1024:%u%%",
 393                           perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P2]), proft));
 394        print_uint(PRINT_ANY, "-4096", " -4096:%u%%",
 395                           perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P3]), proft));
 396        print_uint(PRINT_ANY, "-16384", " -16384:%u%%",
 397                           perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P4]), proft));
 398        print_uint(PRINT_ANY, "-32768", " -32768:%u%%",
 399                           perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P5]), proft));
 400        print_uint(PRINT_ANY, "-66000", " -66000:%u%%\n",
 401                           perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P6]), proft));
 402
 403        open_json_object("rx states");
 404        print_uint(PRINT_ANY, "rx states", "  RX states:%u",
 405                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_STATES]));
 406        print_uint(PRINT_ANY, "probes", " probes:%u",
 407                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_PROBES]));
 408        print_uint(PRINT_ANY, "naks", " naks:%u",
 409                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_NACKS]));
 410        print_uint(PRINT_ANY, "defs", " defs:%u",
 411                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_DEFERRED]));
 412        print_uint(PRINT_ANY, "dups", " dups:%u\n",
 413                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_DUPLICATES]));
 414        close_json_object();
 415
 416        open_json_object("tx states");
 417        print_uint(PRINT_ANY, "tx states", "  TX states:%u",
 418                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_STATES]));
 419        print_uint(PRINT_ANY, "probes", " probes:%u",
 420                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_PROBES]));
 421        print_uint(PRINT_ANY, "naks", " naks:%u",
 422                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_NACKS]));
 423        print_uint(PRINT_ANY, "acks", " acks:%u",
 424                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_ACKS]));
 425        print_uint(PRINT_ANY, "retrans", " retrans:%u\n",
 426                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_RETRANSMITTED]));
 427        close_json_object();
 428
 429        print_uint(PRINT_ANY, "congestion link", "  Congestion link:%u",
 430                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_LINK_CONGS]));
 431        print_uint(PRINT_ANY, "send queue max", "  Send queue max:%u",
 432                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_MAX_QUEUE]));
 433        print_uint(PRINT_ANY, "avg", " avg:%u\n\n",
 434                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_AVG_QUEUE]));
 435
 436        close_json_object();
 437        return MNL_CB_OK;
 438}
 439
 440static int _show_bc_link_stat(const char *name, struct nlattr *prop[],
 441                           struct nlattr *stats[])
 442{
 443        open_json_object(NULL);
 444        print_string(PRINT_ANY, "link", "Link <%s>\n", name);
 445        print_uint(PRINT_ANY, WINDOW_STR, "  Window:%u packets\n",
 446                           mnl_attr_get_u32(prop[TIPC_NLA_PROP_WIN]));
 447
 448        open_json_object("rx packets");
 449        print_uint(PRINT_ANY, "rx packets", "  RX packets:%u",
 450                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_INFO]));
 451        print_uint(PRINT_ANY, "fragments", " fragments:%u",
 452                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTS]));
 453        print_uint(PRINT_ANY, "fragmented", "/%u",
 454                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTED]));
 455        print_uint(PRINT_ANY, "bundles", " bundles:%u",
 456                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLES]));
 457        print_uint(PRINT_ANY, "bundled", "/%u\n",
 458                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLED]));
 459        close_json_object();
 460
 461        open_json_object("tx packets");
 462        print_uint(PRINT_ANY, "tx packets", "  TX packets:%u",
 463                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_INFO]));
 464        print_uint(PRINT_ANY, "fragments", " fragments:%u",
 465                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTS]));
 466        print_uint(PRINT_ANY, "fragmented", "/%u",
 467                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTED]));
 468        print_uint(PRINT_ANY, "bundles", " bundles:%u",
 469                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLES]));
 470        print_uint(PRINT_ANY, "bundled", "/%u\n",
 471                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLED]));
 472        close_json_object();
 473
 474        open_json_object("rx naks");
 475        print_uint(PRINT_ANY, "rx naks", "  RX naks:%u",
 476                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_NACKS]));
 477        print_uint(PRINT_ANY, "defs",  " defs:%u",
 478                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_DEFERRED]));
 479        print_uint(PRINT_ANY, "dups",  " dups:%u\n",
 480                   mnl_attr_get_u32(stats[TIPC_NLA_STATS_DUPLICATES]));
 481        close_json_object();
 482
 483        open_json_object("tx naks");
 484        print_uint(PRINT_ANY, "tx naks", "  TX naks:%u",
 485                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_NACKS]));
 486        print_uint(PRINT_ANY, "acks",  " acks:%u",
 487                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_ACKS]));
 488        print_uint(PRINT_ANY, "retrans",  " retrans:%u\n",
 489                   mnl_attr_get_u32(stats[TIPC_NLA_STATS_RETRANSMITTED]));
 490        close_json_object();
 491
 492        print_uint(PRINT_ANY, "congestion link", "  Congestion link:%u",
 493                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_LINK_CONGS]));
 494        print_uint(PRINT_ANY, "send queue max", "  Send queue max:%u",
 495                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_MAX_QUEUE]));
 496        print_uint(PRINT_ANY, "avg", " avg:%u\n\n",
 497                           mnl_attr_get_u32(stats[TIPC_NLA_STATS_AVG_QUEUE]));
 498        close_json_object();
 499
 500        return MNL_CB_OK;
 501}
 502
 503static int link_stat_show_cb(const struct nlmsghdr *nlh, void *data)
 504{
 505        const char *name;
 506        const char *link = data;
 507        struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
 508        struct nlattr *info[TIPC_NLA_MAX + 1] = {};
 509        struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1] = {};
 510        struct nlattr *prop[TIPC_NLA_PROP_MAX + 1] = {};
 511        struct nlattr *stats[TIPC_NLA_STATS_MAX + 1] = {};
 512
 513        mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
 514        if (!info[TIPC_NLA_LINK])
 515                return MNL_CB_ERROR;
 516
 517        mnl_attr_parse_nested(info[TIPC_NLA_LINK], parse_attrs, attrs);
 518        if (!attrs[TIPC_NLA_LINK_NAME] || !attrs[TIPC_NLA_LINK_PROP] ||
 519            !attrs[TIPC_NLA_LINK_STATS])
 520                return MNL_CB_ERROR;
 521
 522        mnl_attr_parse_nested(attrs[TIPC_NLA_LINK_PROP], parse_attrs, prop);
 523        mnl_attr_parse_nested(attrs[TIPC_NLA_LINK_STATS], parse_attrs, stats);
 524
 525        name = mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME]);
 526
 527        /* If a link is passed, skip all but that link.
 528         * Support a substring matching as well.
 529         */
 530        if (link && !strstr(name, link))
 531                return MNL_CB_OK;
 532
 533        if (attrs[TIPC_NLA_LINK_BROADCAST]) {
 534                return _show_bc_link_stat(name, prop, stats);
 535        }
 536
 537        return _show_link_stat(name, attrs, prop, stats);
 538}
 539
 540static void cmd_link_stat_show_help(struct cmdl *cmdl)
 541{
 542        fprintf(stderr, "Usage: %s link stat show [ link { LINK | SUBSTRING | all } ]\n",
 543                cmdl->argv[0]);
 544}
 545
 546static int cmd_link_stat_show(struct nlmsghdr *nlh, const struct cmd *cmd,
 547                              struct cmdl *cmdl, void *data)
 548{
 549        char *link = NULL;
 550        struct opt *opt;
 551        struct opt opts[] = {
 552                { "link",               OPT_KEYVAL,     NULL },
 553                { NULL }
 554        };
 555        struct nlattr *attrs;
 556        int err = 0;
 557
 558        if (help_flag) {
 559                (cmd->help)(cmdl);
 560                return -EINVAL;
 561        }
 562
 563        nlh = msg_init(TIPC_NL_LINK_GET);
 564        if (!nlh) {
 565                fprintf(stderr, "error, message initialisation failed\n");
 566                return -1;
 567        }
 568
 569        if (parse_opts(opts, cmdl) < 0)
 570                return -EINVAL;
 571
 572        opt = get_opt(opts, "link");
 573        if (opt) {
 574                if (strcmp(opt->val, "all"))
 575                        link = opt->val;
 576                /* Set the flag to dump all bc links */
 577                attrs = mnl_attr_nest_start(nlh, TIPC_NLA_LINK);
 578                mnl_attr_put(nlh, TIPC_NLA_LINK_BROADCAST, 0, NULL);
 579                mnl_attr_nest_end(nlh, attrs);
 580        }
 581
 582        new_json_obj(json);
 583        err = msg_dumpit(nlh, link_stat_show_cb, link);
 584        delete_json_obj();
 585        return err;
 586}
 587
 588static void cmd_link_stat_help(struct cmdl *cmdl)
 589{
 590        fprintf(stderr, "Usage: %s link stat COMMAND [ARGS]\n\n"
 591                "COMMANDS:\n"
 592                " reset                 - Reset link statistics for link\n"
 593                " show                  - Get link priority\n",
 594                cmdl->argv[0]);
 595}
 596
 597static int cmd_link_stat(struct nlmsghdr *nlh, const struct cmd *cmd,
 598                         struct cmdl *cmdl, void *data)
 599{
 600        const struct cmd cmds[] = {
 601                { "reset",      cmd_link_stat_reset,    cmd_link_stat_reset_help },
 602                { "show",       cmd_link_stat_show,     cmd_link_stat_show_help },
 603                { NULL }
 604        };
 605
 606        return run_cmd(nlh, cmd, cmds, cmdl, NULL);
 607}
 608
 609static void cmd_link_set_help(struct cmdl *cmdl)
 610{
 611        fprintf(stderr, "Usage: %s link set PPROPERTY link LINK\n\n"
 612                "PROPERTIES\n"
 613                " tolerance TOLERANCE   - Set link tolerance\n"
 614                " priority PRIORITY     - Set link priority\n"
 615                " window WINDOW         - Set link window\n"
 616                " broadcast BROADCAST   - Set link broadcast\n",
 617                cmdl->argv[0]);
 618}
 619
 620static int cmd_link_set_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
 621                             struct cmdl *cmdl, void *data)
 622{
 623        int val;
 624        int prop;
 625        struct nlattr *props;
 626        struct nlattr *attrs;
 627        struct opt *opt;
 628        struct opt opts[] = {
 629                { "link",               OPT_KEYVAL,     NULL },
 630                { NULL }
 631        };
 632
 633        if (strcmp(cmd->cmd, PRIORITY_STR) == 0)
 634                prop = TIPC_NLA_PROP_PRIO;
 635        else if ((strcmp(cmd->cmd, TOLERANCE_STR) == 0))
 636                prop = TIPC_NLA_PROP_TOL;
 637        else if ((strcmp(cmd->cmd, WINDOW_STR) == 0))
 638                prop = TIPC_NLA_PROP_WIN;
 639        else
 640                return -EINVAL;
 641
 642        if (help_flag) {
 643                (cmd->help)(cmdl);
 644                return -EINVAL;
 645        }
 646
 647        if (cmdl->optind >= cmdl->argc) {
 648                fprintf(stderr, "error, missing value\n");
 649                return -EINVAL;
 650        }
 651        val = atoi(shift_cmdl(cmdl));
 652
 653        if (parse_opts(opts, cmdl) < 0)
 654                return -EINVAL;
 655
 656        nlh = msg_init(TIPC_NL_LINK_SET);
 657        if (!nlh) {
 658                fprintf(stderr, "error, message initialisation failed\n");
 659                return -1;
 660        }
 661        attrs = mnl_attr_nest_start(nlh, TIPC_NLA_LINK);
 662
 663        opt = get_opt(opts, "link");
 664        if (!opt) {
 665                fprintf(stderr, "error, missing link\n");
 666                return -EINVAL;
 667        }
 668        mnl_attr_put_strz(nlh, TIPC_NLA_LINK_NAME, opt->val);
 669
 670        props = mnl_attr_nest_start(nlh, TIPC_NLA_LINK_PROP);
 671        mnl_attr_put_u32(nlh, prop, val);
 672        mnl_attr_nest_end(nlh, props);
 673
 674        mnl_attr_nest_end(nlh, attrs);
 675
 676        return msg_doit(nlh, link_get_cb, &prop);
 677}
 678
 679static void cmd_link_set_bcast_help(struct cmdl *cmdl)
 680{
 681        fprintf(stderr, "Usage: %s link set broadcast PROPERTY\n\n"
 682                "PROPERTIES\n"
 683                " BROADCAST         - Forces all multicast traffic to be\n"
 684                "                     transmitted via broadcast only,\n"
 685                "                     irrespective of cluster size and number\n"
 686                "                     of destinations\n\n"
 687                " REPLICAST         - Forces all multicast traffic to be\n"
 688                "                     transmitted via replicast only,\n"
 689                "                     irrespective of cluster size and number\n"
 690                "                     of destinations\n\n"
 691                " AUTOSELECT        - Auto switching to broadcast or replicast\n"
 692                "                     depending on cluster size and destination\n"
 693                "                     node number\n\n"
 694                " ratio SIZE        - Set the AUTOSELECT criteria, percentage of\n"
 695                "                     destination nodes vs cluster size\n\n",
 696                cmdl->argv[0]);
 697}
 698
 699static int cmd_link_set_bcast(struct nlmsghdr *nlh, const struct cmd *cmd,
 700                             struct cmdl *cmdl, void *data)
 701{
 702        struct nlattr *props;
 703        struct nlattr *attrs;
 704        struct opt *opt;
 705        struct opt opts[] = {
 706                { "BROADCAST",  OPT_KEY, NULL },
 707                { "REPLICAST",  OPT_KEY, NULL },
 708                { "AUTOSELECT", OPT_KEY, NULL },
 709                { "ratio",      OPT_KEYVAL,     NULL },
 710                { NULL }
 711        };
 712        int method = 0;
 713
 714        if (help_flag) {
 715                (cmd->help)(cmdl);
 716                return -EINVAL;
 717        }
 718
 719        if (parse_opts(opts, cmdl) < 0)
 720                return -EINVAL;
 721
 722        for (opt = opts; opt->key; opt++)
 723                if (opt->val)
 724                        break;
 725
 726        if (!opt || !opt->key) {
 727                (cmd->help)(cmdl);
 728                return -EINVAL;
 729        }
 730
 731        nlh = msg_init(TIPC_NL_LINK_SET);
 732        if (!nlh) {
 733                fprintf(stderr, "error, message initialisation failed\n");
 734                return -1;
 735        }
 736
 737        attrs = mnl_attr_nest_start(nlh, TIPC_NLA_LINK);
 738        /* Direct to broadcast-link setting */
 739        mnl_attr_put_strz(nlh, TIPC_NLA_LINK_NAME, tipc_bclink_name);
 740        props = mnl_attr_nest_start(nlh, TIPC_NLA_LINK_PROP);
 741
 742        if (get_opt(opts, "BROADCAST"))
 743                method = 0x1;
 744        else if (get_opt(opts, "REPLICAST"))
 745                method = 0x2;
 746        else if (get_opt(opts, "AUTOSELECT"))
 747                method = 0x4;
 748
 749        opt = get_opt(opts, "ratio");
 750        if (!method && !opt) {
 751                (cmd->help)(cmdl);
 752                return -EINVAL;
 753        }
 754
 755        if (method)
 756                mnl_attr_put_u32(nlh, TIPC_NLA_PROP_BROADCAST, method);
 757
 758        if (opt)
 759                mnl_attr_put_u32(nlh, TIPC_NLA_PROP_BROADCAST_RATIO,
 760                                 atoi(opt->val));
 761
 762        mnl_attr_nest_end(nlh, props);
 763        mnl_attr_nest_end(nlh, attrs);
 764        return msg_doit(nlh, NULL, NULL);
 765}
 766
 767static int cmd_link_set(struct nlmsghdr *nlh, const struct cmd *cmd,
 768                        struct cmdl *cmdl, void *data)
 769{
 770        const struct cmd cmds[] = {
 771                { PRIORITY_STR, cmd_link_set_prop,      cmd_link_set_help },
 772                { TOLERANCE_STR,        cmd_link_set_prop,      cmd_link_set_help },
 773                { WINDOW_STR,   cmd_link_set_prop,      cmd_link_set_help },
 774                { BROADCAST_STR, cmd_link_set_bcast, cmd_link_set_bcast_help },
 775                { NULL }
 776        };
 777
 778        return run_cmd(nlh, cmd, cmds, cmdl, NULL);
 779}
 780
 781static int cmd_link_mon_set_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
 782                                 struct cmdl *cmdl, void *data)
 783{
 784        int size;
 785        struct nlattr *attrs;
 786
 787        if (cmdl->argc != cmdl->optind + 1) {
 788                fprintf(stderr, "error, missing value\n");
 789                return -EINVAL;
 790        }
 791        size = atoi(shift_cmdl(cmdl));
 792
 793        nlh = msg_init(TIPC_NL_MON_SET);
 794        if (!nlh) {
 795                fprintf(stderr, "error, message initialisation failed\n");
 796                return -1;
 797        }
 798        attrs = mnl_attr_nest_start(nlh, TIPC_NLA_MON);
 799
 800        mnl_attr_put_u32(nlh, TIPC_NLA_MON_ACTIVATION_THRESHOLD, size);
 801
 802        mnl_attr_nest_end(nlh, attrs);
 803
 804        return msg_doit(nlh, NULL, NULL);
 805}
 806
 807static int link_mon_summary_cb(const struct nlmsghdr *nlh, void *data)
 808{
 809        struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
 810        struct nlattr *info[TIPC_NLA_MAX + 1] = {};
 811        struct nlattr *attrs[TIPC_NLA_MON_MAX + 1] = {};
 812
 813        mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
 814        if (!info[TIPC_NLA_MON])
 815                return MNL_CB_ERROR;
 816
 817        mnl_attr_parse_nested(info[TIPC_NLA_MON], parse_attrs, attrs);
 818
 819        open_json_object(NULL);
 820        print_string(PRINT_ANY, "bearer", "\nbearer %s\n",
 821                mnl_attr_get_str(attrs[TIPC_NLA_MON_BEARER_NAME]));
 822
 823        print_uint(PRINT_ANY, "table_generation", "    table_generation %u\n",
 824               mnl_attr_get_u32(attrs[TIPC_NLA_MON_LISTGEN]));
 825        print_uint(PRINT_ANY, "cluster_size", "    cluster_size %u\n",
 826                mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEERCNT]));
 827        print_string(PRINT_ANY, "algorithm", "    algorithm %s\n",
 828                attrs[TIPC_NLA_MON_ACTIVE] ? "overlapping-ring" : "full-mesh");
 829        close_json_object();
 830
 831        return MNL_CB_OK;
 832}
 833
 834static int cmd_link_mon_summary(struct nlmsghdr *nlh, const struct cmd *cmd,
 835                                struct cmdl *cmdl, void *data)
 836{
 837        int err = 0;
 838
 839        if (help_flag) {
 840                fprintf(stderr, "Usage: %s monitor summary\n", cmdl->argv[0]);
 841                return -EINVAL;
 842        }
 843
 844        nlh = msg_init(TIPC_NL_MON_GET);
 845        if (!nlh) {
 846                fprintf(stderr, "error, message initialisation failed\n");
 847                return -1;
 848        }
 849
 850        new_json_obj(json);
 851        err = msg_dumpit(nlh, link_mon_summary_cb, NULL);
 852        delete_json_obj();
 853
 854        return err;
 855}
 856
 857#define STATUS_WIDTH 7
 858#define MAX_NODE_WIDTH 14 /* 255.4095.4095 */
 859#define MAX_DOM_GEN_WIDTH 11 /* 65535 */
 860#define DIRECTLY_MON_WIDTH 10
 861
 862#define APPL_NODE_STATUS_WIDTH 5
 863
 864static int map_get(uint64_t up_map, int i)
 865{
 866        return (up_map & (1 << i)) >> i;
 867}
 868
 869/* print the applied members, since we know the the members
 870 * are listed in ascending order, we print only the state
 871 */
 872static void link_mon_print_applied(uint16_t applied, uint64_t up_map)
 873{
 874        int i;
 875
 876        open_json_array(PRINT_JSON, "applied_node_status");
 877        for (i = 0; i < applied; i++) {
 878                char state_str[2] = {0};
 879
 880                /* print the delimiter for every -n- entry */
 881                if (i && !(i % APPL_NODE_STATUS_WIDTH))
 882                        print_string(PRINT_FP, NULL, "%s", ",");
 883
 884                sprintf(state_str, "%c", map_get(up_map, i) ? 'U' : 'D');
 885                print_string(PRINT_ANY, NULL, "%s", state_str);
 886        }
 887        close_json_array(PRINT_JSON, "applied_node_status");
 888}
 889
 890/* print the non applied members, since we don't know
 891 * the members, we print them along with the state
 892 */
 893static void link_mon_print_non_applied(uint16_t applied, uint16_t member_cnt,
 894                                       uint64_t up_map,  uint32_t *members)
 895{
 896        int i;
 897        char state;
 898
 899        open_json_array(PRINT_JSON, "[non_applied_node:status]");
 900        print_string(PRINT_FP, NULL, " %s", "[");
 901        for (i = applied; i < member_cnt; i++) {
 902                char addr_str[16];
 903                char full_state[17] = {0};
 904
 905                /* print the delimiter for every entry */
 906                if (i != applied)
 907                        print_string(PRINT_FP, NULL, "%s", ",");
 908
 909                sprintf(addr_str, "%x:", members[i]);
 910                state = map_get(up_map, i) ? 'U' : 'D';
 911                sprintf(full_state, "%s%c", addr_str, state);
 912                print_string(PRINT_ANY, NULL, "%s", full_state);
 913        }
 914        print_string(PRINT_FP, NULL, "%s", "]");
 915        close_json_array(PRINT_JSON, "[non_applied_node:status]");
 916}
 917
 918static void link_mon_print_peer_state(const uint32_t addr, const char *status,
 919                                      const char *monitored,
 920                                      const uint32_t dom_gen)
 921{
 922        char addr_str[16];
 923
 924        sprintf(addr_str, "%u.%u.%u", tipc_zone(addr), tipc_cluster(addr),
 925                tipc_node(addr));
 926        if (is_json_context()) {
 927                print_string(PRINT_JSON, "node", NULL, addr_str);
 928                print_string(PRINT_JSON, "status", NULL, status);
 929                print_string(PRINT_JSON, "monitored", NULL, monitored);
 930                print_uint(PRINT_JSON, "generation", NULL, dom_gen);
 931        } else {
 932                printf("%-*s", MAX_NODE_WIDTH, addr_str);
 933                printf("%-*s", STATUS_WIDTH, status);
 934                printf("%-*s", DIRECTLY_MON_WIDTH, monitored);
 935                printf("%-*u", MAX_DOM_GEN_WIDTH, dom_gen);
 936        }
 937}
 938
 939static int link_mon_peer_list_cb(const struct nlmsghdr *nlh, void *data)
 940{
 941        struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
 942        struct nlattr *attrs[TIPC_NLA_MON_PEER_MAX + 1] = {};
 943        struct nlattr *info[TIPC_NLA_MAX + 1] = {};
 944        uint16_t member_cnt;
 945        uint32_t applied;
 946        uint32_t dom_gen;
 947        uint64_t up_map;
 948        char status[16];
 949        char monitored[16];
 950
 951        mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
 952        if (!info[TIPC_NLA_MON_PEER])
 953                return MNL_CB_ERROR;
 954
 955        open_json_object(NULL);
 956        mnl_attr_parse_nested(info[TIPC_NLA_MON_PEER], parse_attrs, attrs);
 957
 958        (attrs[TIPC_NLA_MON_PEER_LOCAL] || attrs[TIPC_NLA_MON_PEER_HEAD]) ?
 959                strcpy(monitored, "direct") :
 960                strcpy(monitored, "indirect");
 961
 962        attrs[TIPC_NLA_MON_PEER_UP] ?
 963                strcpy(status, "up") :
 964                strcpy(status, "down");
 965
 966        dom_gen = attrs[TIPC_NLA_MON_PEER_DOMGEN] ?
 967                mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEER_DOMGEN]) : 0;
 968
 969        link_mon_print_peer_state(mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEER_ADDR]),
 970                                  status, monitored, dom_gen);
 971
 972        applied = mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEER_APPLIED]);
 973
 974        if (!applied)
 975                goto exit;
 976
 977        up_map = mnl_attr_get_u64(attrs[TIPC_NLA_MON_PEER_UPMAP]);
 978
 979        member_cnt = mnl_attr_get_payload_len(attrs[TIPC_NLA_MON_PEER_MEMBERS]);
 980
 981        /* each tipc address occupies 4 bytes of payload, hence compensate it */
 982        member_cnt /= sizeof(uint32_t);
 983
 984        link_mon_print_applied(applied, up_map);
 985
 986        link_mon_print_non_applied(applied, member_cnt, up_map,
 987                                   mnl_attr_get_payload(attrs[TIPC_NLA_MON_PEER_MEMBERS]));
 988
 989exit:
 990        print_string(PRINT_FP, NULL, "\n", "");
 991
 992        close_json_object();
 993        return MNL_CB_OK;
 994}
 995
 996static int link_mon_peer_list(uint32_t mon_ref)
 997{
 998        struct mnlu_gen_socket link_nlg;
 999        struct nlmsghdr *nlh;
1000        struct nlattr *nest;
1001        int err = 0;
1002
1003        err = mnlu_gen_socket_open(&link_nlg, TIPC_GENL_V2_NAME,
1004                                   TIPC_GENL_V2_VERSION);
1005        if (err)
1006                return -1;
1007        nlh = mnlu_gen_socket_cmd_prepare(&link_nlg, TIPC_NL_MON_PEER_GET,
1008                                          NLM_F_REQUEST | NLM_F_DUMP);
1009        if (!nlh) {
1010                fprintf(stderr, "error, message initialisation failed\n");
1011                mnlu_gen_socket_close(&link_nlg);
1012                return -1;
1013        }
1014
1015        nest = mnl_attr_nest_start(nlh, TIPC_NLA_MON);
1016        mnl_attr_put_u32(nlh, TIPC_NLA_MON_REF, mon_ref);
1017        mnl_attr_nest_end(nlh, nest);
1018
1019        err = mnlu_gen_socket_sndrcv(&link_nlg, nlh, link_mon_peer_list_cb,
1020                                     NULL);
1021        mnlu_gen_socket_close(&link_nlg);
1022        return err;
1023}
1024
1025static int link_mon_list_cb(const struct nlmsghdr *nlh, void *data)
1026{
1027        struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
1028        struct nlattr *info[TIPC_NLA_MAX + 1] = {};
1029        struct nlattr *attrs[TIPC_NLA_MON_MAX + 1] = {};
1030        char *req_bearer = data;
1031        const char *bname;
1032        const char title[] =
1033          "node          status monitored generation applied_node_status [non_applied_node:status]";
1034
1035        mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
1036        if (!info[TIPC_NLA_MON])
1037                return MNL_CB_ERROR;
1038
1039        mnl_attr_parse_nested(info[TIPC_NLA_MON], parse_attrs, attrs);
1040
1041        bname = mnl_attr_get_str(attrs[TIPC_NLA_MON_BEARER_NAME]);
1042
1043        if (*req_bearer && (strcmp(req_bearer, bname) != 0))
1044                return MNL_CB_OK;
1045
1046        open_json_object(NULL);
1047        print_string(PRINT_ANY, "bearer", "\nbearer %s\n", bname);
1048        print_string(PRINT_FP, NULL, "%s\n", title);
1049
1050        open_json_array(PRINT_JSON, bname);
1051        if (mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEERCNT]))
1052                link_mon_peer_list(mnl_attr_get_u32(attrs[TIPC_NLA_MON_REF]));
1053        close_json_array(PRINT_JSON, bname);
1054
1055        close_json_object();
1056        return MNL_CB_OK;
1057}
1058
1059static void cmd_link_mon_list_help(struct cmdl *cmdl)
1060{
1061        fprintf(stderr, "Usage: %s monitor list [ media MEDIA ARGS...]\n\n",
1062                cmdl->argv[0]);
1063        print_bearer_media();
1064}
1065
1066static void cmd_link_mon_list_l2_help(struct cmdl *cmdl, char *media)
1067{
1068        fprintf(stderr,
1069                "Usage: %s monitor list media %s device DEVICE [OPTIONS]\n",
1070                cmdl->argv[0], media);
1071}
1072
1073static void cmd_link_mon_list_udp_help(struct cmdl *cmdl, char *media)
1074{
1075        fprintf(stderr,
1076                "Usage: %s monitor list media udp name NAME\n\n",
1077                cmdl->argv[0]);
1078}
1079
1080static int cmd_link_mon_list(struct nlmsghdr *nlh, const struct cmd *cmd,
1081                             struct cmdl *cmdl, void *data)
1082{
1083        char bname[TIPC_MAX_BEARER_NAME] = {0};
1084        struct opt opts[] = {
1085                { "media",      OPT_KEYVAL,     NULL },
1086                { "device",     OPT_KEYVAL,     NULL },
1087                { "name",       OPT_KEYVAL,     NULL },
1088                { NULL }
1089        };
1090        struct tipc_sup_media sup_media[] = {
1091                { "udp",        "name",         cmd_link_mon_list_udp_help},
1092                { "eth",        "device",       cmd_link_mon_list_l2_help },
1093                { "ib",         "device",       cmd_link_mon_list_l2_help },
1094                { NULL, },
1095        };
1096
1097        int err;
1098
1099        if (parse_opts(opts, cmdl) < 0)
1100                return -EINVAL;
1101
1102        if (get_opt(opts, "media")) {
1103                err = cmd_get_unique_bearer_name(cmd, cmdl, opts, bname,
1104                                                 sup_media);
1105                if (err)
1106                        return err;
1107        }
1108
1109        if (help_flag) {
1110                cmd->help(cmdl);
1111                return -EINVAL;
1112        }
1113
1114        nlh = msg_init(TIPC_NL_MON_GET);
1115        if (!nlh) {
1116                fprintf(stderr, "error, message initialisation failed\n");
1117                return -1;
1118        }
1119
1120        new_json_obj(json);
1121        err = msg_dumpit(nlh, link_mon_list_cb, bname);
1122        delete_json_obj();
1123        return err;
1124}
1125
1126static void cmd_link_mon_set_help(struct cmdl *cmdl)
1127{
1128        fprintf(stderr, "Usage: %s monitor set PPROPERTY\n\n"
1129                "PROPERTIES\n"
1130                " threshold SIZE        - Set monitor activation threshold\n",
1131                cmdl->argv[0]);
1132}
1133
1134static int cmd_link_mon_set(struct nlmsghdr *nlh, const struct cmd *cmd,
1135                            struct cmdl *cmdl, void *data)
1136{
1137        const struct cmd cmds[] = {
1138                { "threshold",  cmd_link_mon_set_prop,  NULL },
1139                { NULL }
1140        };
1141
1142        return run_cmd(nlh, cmd, cmds, cmdl, NULL);
1143}
1144
1145static void cmd_link_mon_get_help(struct cmdl *cmdl)
1146{
1147        fprintf(stderr, "Usage: %s monitor get PPROPERTY\n\n"
1148                "PROPERTIES\n"
1149                " threshold     - Get monitor activation threshold\n",
1150                cmdl->argv[0]);
1151}
1152
1153static int link_mon_get_cb(const struct nlmsghdr *nlh, void *data)
1154{
1155        struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
1156        struct nlattr *info[TIPC_NLA_MAX + 1] = {};
1157        struct nlattr *attrs[TIPC_NLA_MON_MAX + 1] = {};
1158
1159        mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
1160        if (!info[TIPC_NLA_MON])
1161                return MNL_CB_ERROR;
1162
1163        mnl_attr_parse_nested(info[TIPC_NLA_MON], parse_attrs, attrs);
1164        if (!attrs[TIPC_NLA_MON_ACTIVATION_THRESHOLD])
1165                return MNL_CB_ERROR;
1166
1167        new_json_obj(json);
1168        print_uint(PRINT_ANY, "threshold", "%u\n",
1169                           mnl_attr_get_u32(attrs[TIPC_NLA_MON_ACTIVATION_THRESHOLD]));
1170        delete_json_obj();
1171
1172        return MNL_CB_OK;
1173}
1174
1175static int cmd_link_mon_get_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
1176                                 struct cmdl *cmdl, void *data)
1177{
1178
1179        nlh = msg_init(TIPC_NL_MON_GET);
1180        if (!nlh) {
1181                fprintf(stderr, "error, message initialisation failed\n");
1182                return -1;
1183        }
1184
1185        return msg_doit(nlh,    link_mon_get_cb,        NULL);
1186}
1187
1188static int cmd_link_mon_get(struct nlmsghdr *nlh, const struct cmd *cmd,
1189                            struct cmdl *cmdl, void *data)
1190{
1191        const struct cmd cmds[] = {
1192                { "threshold",  cmd_link_mon_get_prop,  NULL},
1193                { NULL }
1194        };
1195
1196        return run_cmd(nlh, cmd, cmds, cmdl, NULL);
1197}
1198
1199static void cmd_link_mon_help(struct cmdl *cmdl)
1200{
1201        fprintf(stderr,
1202                "Usage: %s montior COMMAND [ARGS] ...\n\n"
1203                "COMMANDS\n"
1204                " set                   - Set monitor properties\n"
1205                " get                   - Get monitor properties\n"
1206                " list                  - List all cluster members\n"
1207                " summary               - Show local node monitor summary\n",
1208                cmdl->argv[0]);
1209}
1210
1211static int cmd_link_mon(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl,
1212                        void *data)
1213{
1214        const struct cmd cmds[] = {
1215                { "set",        cmd_link_mon_set,       cmd_link_mon_set_help },
1216                { "get",        cmd_link_mon_get,       cmd_link_mon_get_help },
1217                { "list",       cmd_link_mon_list,      cmd_link_mon_list_help },
1218                { "summary",    cmd_link_mon_summary,   NULL },
1219                { NULL }
1220        };
1221
1222        return run_cmd(nlh, cmd, cmds, cmdl, NULL);
1223}
1224
1225void cmd_link_help(struct cmdl *cmdl)
1226{
1227        fprintf(stderr,
1228                "Usage: %s link COMMAND [ARGS] ...\n"
1229                "\n"
1230                "COMMANDS\n"
1231                " list                  - List links\n"
1232                " get                   - Get various link properties\n"
1233                " set                   - Set various link properties\n"
1234                " statistics            - Show or reset statistics\n"
1235                " monitor               - Show or set link supervision\n",
1236                cmdl->argv[0]);
1237}
1238
1239int cmd_link(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl,
1240             void *data)
1241{
1242        const struct cmd cmds[] = {
1243                { "get",        cmd_link_get,   cmd_link_get_help },
1244                { "list",       cmd_link_list,  NULL },
1245                { "set",        cmd_link_set,   cmd_link_set_help },
1246                { "statistics", cmd_link_stat,  cmd_link_stat_help },
1247                { "monitor",    cmd_link_mon,   cmd_link_mon_help },
1248                { NULL }
1249        };
1250
1251        return run_cmd(nlh, cmd, cmds, cmdl, NULL);
1252}
1253