iproute2/bridge/link.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2
   3#include <stdio.h>
   4#include <stdlib.h>
   5#include <unistd.h>
   6#include <time.h>
   7#include <sys/socket.h>
   8#include <sys/time.h>
   9#include <netinet/in.h>
  10#include <linux/if.h>
  11#include <linux/if_bridge.h>
  12#include <string.h>
  13#include <stdbool.h>
  14
  15#include "json_print.h"
  16#include "libnetlink.h"
  17#include "utils.h"
  18#include "br_common.h"
  19
  20static unsigned int filter_dev_index;
  21static unsigned int filter_master_index;
  22
  23static const char *stp_states[] = {
  24        [BR_STATE_DISABLED] = "disabled",
  25        [BR_STATE_LISTENING] = "listening",
  26        [BR_STATE_LEARNING] = "learning",
  27        [BR_STATE_FORWARDING] = "forwarding",
  28        [BR_STATE_BLOCKING] = "blocking",
  29};
  30
  31static const char *hw_mode[] = {
  32        "VEB", "VEPA"
  33};
  34
  35static void print_link_flags(FILE *fp, unsigned int flags, unsigned int mdown)
  36{
  37        open_json_array(PRINT_ANY, is_json_context() ? "flags" : "<");
  38        if (flags & IFF_UP && !(flags & IFF_RUNNING))
  39                print_string(PRINT_ANY, NULL,
  40                             flags ? "%s," : "%s", "NO-CARRIER");
  41        flags &= ~IFF_RUNNING;
  42
  43#define _PF(f) if (flags&IFF_##f) {                                     \
  44                flags &= ~IFF_##f ;                                     \
  45                print_string(PRINT_ANY, NULL, flags ? "%s," : "%s", #f); }
  46        _PF(LOOPBACK);
  47        _PF(BROADCAST);
  48        _PF(POINTOPOINT);
  49        _PF(MULTICAST);
  50        _PF(NOARP);
  51        _PF(ALLMULTI);
  52        _PF(PROMISC);
  53        _PF(MASTER);
  54        _PF(SLAVE);
  55        _PF(DEBUG);
  56        _PF(DYNAMIC);
  57        _PF(AUTOMEDIA);
  58        _PF(PORTSEL);
  59        _PF(NOTRAILERS);
  60        _PF(UP);
  61        _PF(LOWER_UP);
  62        _PF(DORMANT);
  63        _PF(ECHO);
  64#undef _PF
  65        if (flags)
  66                print_hex(PRINT_ANY, NULL, "%x", flags);
  67        if (mdown)
  68                print_string(PRINT_ANY, NULL, ",%s", "M-DOWN");
  69        close_json_array(PRINT_ANY, "> ");
  70}
  71
  72void print_stp_state(__u8 state)
  73{
  74        if (state <= BR_STATE_BLOCKING)
  75                print_string(PRINT_ANY, "state",
  76                             "state %s ", stp_states[state]);
  77        else
  78                print_uint(PRINT_ANY, "state",
  79                             "state (%d) ", state);
  80}
  81
  82int parse_stp_state(const char *arg)
  83{
  84        size_t nstates = ARRAY_SIZE(stp_states);
  85        int state;
  86
  87        for (state = 0; state < nstates; state++)
  88                if (strcmp(stp_states[state], arg) == 0)
  89                        break;
  90
  91        if (state == nstates)
  92                state = -1;
  93
  94        return state;
  95}
  96
  97static void print_hwmode(__u16 mode)
  98{
  99        if (mode >= ARRAY_SIZE(hw_mode))
 100                print_0xhex(PRINT_ANY, "hwmode",
 101                            "hwmode %#llx ", mode);
 102        else
 103                print_string(PRINT_ANY, "hwmode",
 104                             "hwmode %s ", hw_mode[mode]);
 105}
 106
 107static void print_protinfo(FILE *fp, struct rtattr *attr)
 108{
 109        if (attr->rta_type & NLA_F_NESTED) {
 110                struct rtattr *prtb[IFLA_BRPORT_MAX + 1];
 111
 112                parse_rtattr_nested(prtb, IFLA_BRPORT_MAX, attr);
 113
 114                if (prtb[IFLA_BRPORT_STATE])
 115                        print_stp_state(rta_getattr_u8(prtb[IFLA_BRPORT_STATE]));
 116
 117                if (prtb[IFLA_BRPORT_PRIORITY])
 118                        print_uint(PRINT_ANY, "priority",
 119                                   "priority %u ",
 120                                   rta_getattr_u16(prtb[IFLA_BRPORT_PRIORITY]));
 121
 122                if (prtb[IFLA_BRPORT_COST])
 123                        print_uint(PRINT_ANY, "cost",
 124                                   "cost %u ",
 125                                   rta_getattr_u32(prtb[IFLA_BRPORT_COST]));
 126
 127                if (!show_details)
 128                        return;
 129
 130                if (!is_json_context())
 131                        fprintf(fp, "%s    ", _SL_);
 132
 133                if (prtb[IFLA_BRPORT_MODE])
 134                        print_on_off(PRINT_ANY, "hairpin", "hairpin %s ",
 135                                     rta_getattr_u8(prtb[IFLA_BRPORT_MODE]));
 136                if (prtb[IFLA_BRPORT_GUARD])
 137                        print_on_off(PRINT_ANY, "guard", "guard %s ",
 138                                     rta_getattr_u8(prtb[IFLA_BRPORT_GUARD]));
 139                if (prtb[IFLA_BRPORT_PROTECT])
 140                        print_on_off(PRINT_ANY, "root_block", "root_block %s ",
 141                                     rta_getattr_u8(prtb[IFLA_BRPORT_PROTECT]));
 142                if (prtb[IFLA_BRPORT_FAST_LEAVE])
 143                        print_on_off(PRINT_ANY, "fastleave", "fastleave %s ",
 144                                     rta_getattr_u8(prtb[IFLA_BRPORT_FAST_LEAVE]));
 145                if (prtb[IFLA_BRPORT_LEARNING])
 146                        print_on_off(PRINT_ANY, "learning", "learning %s ",
 147                                     rta_getattr_u8(prtb[IFLA_BRPORT_LEARNING]));
 148                if (prtb[IFLA_BRPORT_LEARNING_SYNC])
 149                        print_on_off(PRINT_ANY, "learning_sync", "learning_sync %s ",
 150                                     rta_getattr_u8(prtb[IFLA_BRPORT_LEARNING_SYNC]));
 151                if (prtb[IFLA_BRPORT_UNICAST_FLOOD])
 152                        print_on_off(PRINT_ANY, "flood", "flood %s ",
 153                                     rta_getattr_u8(prtb[IFLA_BRPORT_UNICAST_FLOOD]));
 154                if (prtb[IFLA_BRPORT_MCAST_FLOOD])
 155                        print_on_off(PRINT_ANY, "mcast_flood", "mcast_flood %s ",
 156                                     rta_getattr_u8(prtb[IFLA_BRPORT_MCAST_FLOOD]));
 157                if (prtb[IFLA_BRPORT_BCAST_FLOOD])
 158                        print_on_off(PRINT_ANY, "bcast_flood", "bcast_flood %s ",
 159                                     rta_getattr_u8(prtb[IFLA_BRPORT_BCAST_FLOOD]));
 160                if (prtb[IFLA_BRPORT_MULTICAST_ROUTER])
 161                        print_uint(PRINT_ANY, "mcast_router", "mcast_router %u ",
 162                                   rta_getattr_u8(prtb[IFLA_BRPORT_MULTICAST_ROUTER]));
 163                if (prtb[IFLA_BRPORT_MCAST_TO_UCAST])
 164                        print_on_off(PRINT_ANY, "mcast_to_unicast", "mcast_to_unicast %s ",
 165                                     rta_getattr_u8(prtb[IFLA_BRPORT_MCAST_TO_UCAST]));
 166                if (prtb[IFLA_BRPORT_NEIGH_SUPPRESS])
 167                        print_on_off(PRINT_ANY, "neigh_suppress", "neigh_suppress %s ",
 168                                     rta_getattr_u8(prtb[IFLA_BRPORT_NEIGH_SUPPRESS]));
 169                if (prtb[IFLA_BRPORT_NEIGH_VLAN_SUPPRESS]) {
 170                        struct rtattr *at;
 171
 172                        at = prtb[IFLA_BRPORT_NEIGH_VLAN_SUPPRESS];
 173                        print_on_off(PRINT_ANY, "neigh_vlan_suppress",
 174                                     "neigh_vlan_suppress %s ",
 175                                     rta_getattr_u8(at));
 176                }
 177                if (prtb[IFLA_BRPORT_VLAN_TUNNEL])
 178                        print_on_off(PRINT_ANY, "vlan_tunnel", "vlan_tunnel %s ",
 179                                     rta_getattr_u8(prtb[IFLA_BRPORT_VLAN_TUNNEL]));
 180
 181                if (prtb[IFLA_BRPORT_BACKUP_PORT]) {
 182                        int ifidx;
 183
 184                        ifidx = rta_getattr_u32(prtb[IFLA_BRPORT_BACKUP_PORT]);
 185                        print_string(PRINT_ANY,
 186                                     "backup_port", "backup_port %s ",
 187                                     ll_index_to_name(ifidx));
 188                }
 189
 190                if (prtb[IFLA_BRPORT_BACKUP_NHID])
 191                        print_uint(PRINT_ANY, "backup_nhid", "backup_nhid %u ",
 192                                   rta_getattr_u32(prtb[IFLA_BRPORT_BACKUP_NHID]));
 193
 194                if (prtb[IFLA_BRPORT_ISOLATED])
 195                        print_on_off(PRINT_ANY, "isolated", "isolated %s ",
 196                                     rta_getattr_u8(prtb[IFLA_BRPORT_ISOLATED]));
 197                if (prtb[IFLA_BRPORT_LOCKED])
 198                        print_on_off(PRINT_ANY, "locked", "locked %s ",
 199                                     rta_getattr_u8(prtb[IFLA_BRPORT_LOCKED]));
 200                if (prtb[IFLA_BRPORT_MAB])
 201                        print_on_off(PRINT_ANY, "mab", "mab %s ",
 202                                     rta_getattr_u8(prtb[IFLA_BRPORT_MAB]));
 203                if (prtb[IFLA_BRPORT_MCAST_N_GROUPS]) {
 204                        struct rtattr *at = prtb[IFLA_BRPORT_MCAST_N_GROUPS];
 205
 206                        print_uint(PRINT_ANY, "mcast_n_groups",
 207                                   "mcast_n_groups %u ", rta_getattr_u32(at));
 208                }
 209                if (prtb[IFLA_BRPORT_MCAST_MAX_GROUPS]) {
 210                        struct rtattr *at = prtb[IFLA_BRPORT_MCAST_MAX_GROUPS];
 211
 212                        print_uint(PRINT_ANY, "mcast_max_groups",
 213                                   "mcast_max_groups %u ", rta_getattr_u32(at));
 214                }
 215        } else
 216                print_stp_state(rta_getattr_u8(attr));
 217}
 218
 219
 220/*
 221 * This is reported by HW devices that have some bridging
 222 * capabilities.
 223 */
 224static void print_af_spec(struct rtattr *attr, int ifindex)
 225{
 226        struct rtattr *aftb[IFLA_BRIDGE_MAX+1];
 227
 228        parse_rtattr_nested(aftb, IFLA_BRIDGE_MAX, attr);
 229
 230        if (aftb[IFLA_BRIDGE_MODE])
 231                print_hwmode(rta_getattr_u16(aftb[IFLA_BRIDGE_MODE]));
 232}
 233
 234int print_linkinfo(struct nlmsghdr *n, void *arg)
 235{
 236        FILE *fp = arg;
 237        struct ifinfomsg *ifi = NLMSG_DATA(n);
 238        struct rtattr *tb[IFLA_MAX+1];
 239        unsigned int m_flag = 0;
 240        int len = n->nlmsg_len;
 241        const char *name;
 242
 243        len -= NLMSG_LENGTH(sizeof(*ifi));
 244        if (len < 0) {
 245                fprintf(stderr, "Message too short!\n");
 246                return -1;
 247        }
 248
 249        if (!(ifi->ifi_family == AF_BRIDGE || ifi->ifi_family == AF_UNSPEC))
 250                return 0;
 251
 252        if (filter_dev_index && filter_dev_index != ifi->ifi_index)
 253                return 0;
 254
 255        parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(ifi), len, NLA_F_NESTED);
 256
 257        if (filter_master_index && tb[IFLA_MASTER] &&
 258            filter_master_index != rta_getattr_u32(tb[IFLA_MASTER]))
 259                return 0;
 260
 261        name = get_ifname_rta(ifi->ifi_index, tb[IFLA_IFNAME]);
 262        if (!name)
 263                return -1;
 264
 265        print_headers(fp, "[LINK]");
 266
 267        open_json_object(NULL);
 268        if (n->nlmsg_type == RTM_DELLINK)
 269                print_bool(PRINT_ANY, "deleted", "Deleted ", true);
 270
 271        print_int(PRINT_ANY, "ifindex", "%d: ", ifi->ifi_index);
 272        m_flag = print_name_and_link("%s: ", name, tb);
 273        print_link_flags(fp, ifi->ifi_flags, m_flag);
 274
 275        if (tb[IFLA_MTU])
 276                print_int(PRINT_ANY,
 277                          "mtu", "mtu %u ",
 278                          rta_getattr_u32(tb[IFLA_MTU]));
 279
 280        if (tb[IFLA_MASTER]) {
 281                int master = rta_getattr_u32(tb[IFLA_MASTER]);
 282
 283                print_string(PRINT_ANY, "master", "master %s ",
 284                             ll_index_to_name(master));
 285        }
 286
 287        if (tb[IFLA_PROTINFO])
 288                print_protinfo(fp, tb[IFLA_PROTINFO]);
 289
 290        if (tb[IFLA_AF_SPEC])
 291                print_af_spec(tb[IFLA_AF_SPEC], ifi->ifi_index);
 292
 293        print_string(PRINT_FP, NULL, "%s", "\n");
 294        close_json_object();
 295        fflush(fp);
 296        return 0;
 297}
 298
 299static void usage(void)
 300{
 301        fprintf(stderr,
 302                "Usage: bridge link set dev DEV [ cost COST ] [ priority PRIO ] [ state STATE ]\n"
 303                "                               [ guard {on | off} ]\n"
 304                "                               [ hairpin {on | off} ]\n"
 305                "                               [ fastleave {on | off} ]\n"
 306                "                               [ root_block {on | off} ]\n"
 307                "                               [ learning {on | off} ]\n"
 308                "                               [ learning_sync {on | off} ]\n"
 309                "                               [ flood {on | off} ]\n"
 310                "                               [ mcast_router MULTICAST_ROUTER ]\n"
 311                "                               [ mcast_flood {on | off} ]\n"
 312                "                               [ bcast_flood {on | off} ]\n"
 313                "                               [ mcast_to_unicast {on | off} ]\n"
 314                "                               [ mcast_max_groups MAX_GROUPS ]\n"
 315                "                               [ neigh_suppress {on | off} ]\n"
 316                "                               [ neigh_vlan_suppress {on | off} ]\n"
 317                "                               [ vlan_tunnel {on | off} ]\n"
 318                "                               [ isolated {on | off} ]\n"
 319                "                               [ locked {on | off} ]\n"
 320                "                               [ mab {on | off} ]\n"
 321                "                               [ hwmode {vepa | veb} ]\n"
 322                "                               [ backup_port DEVICE ] [ nobackup_port ]\n"
 323                "                               [ backup_nhid NHID ]\n"
 324                "                               [ self ] [ master ]\n"
 325                "       bridge link show [dev DEV] [master DEVICE]\n");
 326        exit(-1);
 327}
 328
 329static int brlink_modify(int argc, char **argv)
 330{
 331        struct {
 332                struct nlmsghdr  n;
 333                struct ifinfomsg ifm;
 334                char             buf[512];
 335        } req = {
 336                .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
 337                .n.nlmsg_flags = NLM_F_REQUEST,
 338                .n.nlmsg_type = RTM_SETLINK,
 339                .ifm.ifi_family = PF_BRIDGE,
 340        };
 341        char *d = NULL;
 342        bool backup_nhid_set = false;
 343        __u32 backup_nhid;
 344        int backup_port_idx = -1;
 345        __s8 neigh_suppress = -1;
 346        __s8 neigh_vlan_suppress = -1;
 347        __s8 learning = -1;
 348        __s8 learning_sync = -1;
 349        __s8 flood = -1;
 350        __s8 vlan_tunnel = -1;
 351        __s8 mcast_router = -1;
 352        __s8 mcast_flood = -1;
 353        __s8 bcast_flood = -1;
 354        __s8 mcast_to_unicast = -1;
 355        __s32 max_groups = -1;
 356        __s8 locked = -1;
 357        __s8 macauth = -1;
 358        __s8 isolated = -1;
 359        __s8 hairpin = -1;
 360        __s8 bpdu_guard = -1;
 361        __s8 fast_leave = -1;
 362        __s8 root_block = -1;
 363        __u32 cost = 0;
 364        __s16 priority = -1;
 365        __s8 state = -1;
 366        __s16 mode = -1;
 367        __u16 flags = 0;
 368        struct rtattr *nest;
 369        int ret;
 370
 371        while (argc > 0) {
 372                if (strcmp(*argv, "dev") == 0) {
 373                        NEXT_ARG();
 374                        d = *argv;
 375                } else if (strcmp(*argv, "guard") == 0) {
 376                        NEXT_ARG();
 377                        bpdu_guard = parse_on_off("guard", *argv, &ret);
 378                        if (ret)
 379                                return ret;
 380                } else if (strcmp(*argv, "hairpin") == 0) {
 381                        NEXT_ARG();
 382                        hairpin = parse_on_off("hairpin", *argv, &ret);
 383                        if (ret)
 384                                return ret;
 385                } else if (strcmp(*argv, "fastleave") == 0) {
 386                        NEXT_ARG();
 387                        fast_leave = parse_on_off("fastleave", *argv, &ret);
 388                        if (ret)
 389                                return ret;
 390                } else if (strcmp(*argv, "root_block") == 0) {
 391                        NEXT_ARG();
 392                        root_block = parse_on_off("root_block", *argv, &ret);
 393                        if (ret)
 394                                return ret;
 395                } else if (strcmp(*argv, "learning") == 0) {
 396                        NEXT_ARG();
 397                        learning = parse_on_off("learning", *argv, &ret);
 398                        if (ret)
 399                                return ret;
 400                } else if (strcmp(*argv, "learning_sync") == 0) {
 401                        NEXT_ARG();
 402                        learning_sync = parse_on_off("learning_sync", *argv, &ret);
 403                        if (ret)
 404                                return ret;
 405                } else if (strcmp(*argv, "flood") == 0) {
 406                        NEXT_ARG();
 407                        flood = parse_on_off("flood", *argv, &ret);
 408                        if (ret)
 409                                return ret;
 410                } else if (strcmp(*argv, "mcast_router") == 0) {
 411                        NEXT_ARG();
 412                        mcast_router = atoi(*argv);
 413                } else if (strcmp(*argv, "mcast_flood") == 0) {
 414                        NEXT_ARG();
 415                        mcast_flood = parse_on_off("mcast_flood", *argv, &ret);
 416                        if (ret)
 417                                return ret;
 418                } else if (strcmp(*argv, "bcast_flood") == 0) {
 419                        NEXT_ARG();
 420                        bcast_flood = parse_on_off("bcast_flood", *argv, &ret);
 421                        if (ret)
 422                                return ret;
 423                } else if (strcmp(*argv, "mcast_to_unicast") == 0) {
 424                        NEXT_ARG();
 425                        mcast_to_unicast = parse_on_off("mcast_to_unicast", *argv, &ret);
 426                        if (ret)
 427                                return ret;
 428                } else if (strcmp(*argv, "mcast_max_groups") == 0) {
 429                        NEXT_ARG();
 430                        if (get_s32(&max_groups, *argv, 0))
 431                                invarg("invalid mcast_max_groups", *argv);
 432                } else if (strcmp(*argv, "cost") == 0) {
 433                        NEXT_ARG();
 434                        cost = atoi(*argv);
 435                } else if (strcmp(*argv, "priority") == 0) {
 436                        NEXT_ARG();
 437                        priority = atoi(*argv);
 438                } else if (strcmp(*argv, "state") == 0) {
 439                        NEXT_ARG();
 440                        char *endptr;
 441
 442                        state = strtol(*argv, &endptr, 10);
 443                        if (!(**argv != '\0' && *endptr == '\0')) {
 444                                state = parse_stp_state(*argv);
 445                                if (state == -1) {
 446                                        fprintf(stderr,
 447                                                "Error: invalid STP port state\n");
 448                                        return -1;
 449                                }
 450                        }
 451                } else if (strcmp(*argv, "hwmode") == 0) {
 452                        NEXT_ARG();
 453                        flags = BRIDGE_FLAGS_SELF;
 454                        if (strcmp(*argv, "vepa") == 0)
 455                                mode = BRIDGE_MODE_VEPA;
 456                        else if (strcmp(*argv, "veb") == 0)
 457                                mode = BRIDGE_MODE_VEB;
 458                        else {
 459                                fprintf(stderr,
 460                                        "Mode argument must be \"vepa\" or \"veb\".\n");
 461                                return -1;
 462                        }
 463                } else if (strcmp(*argv, "self") == 0) {
 464                        flags |= BRIDGE_FLAGS_SELF;
 465                } else if (strcmp(*argv, "master") == 0) {
 466                        flags |= BRIDGE_FLAGS_MASTER;
 467                } else if (strcmp(*argv, "neigh_suppress") == 0) {
 468                        NEXT_ARG();
 469                        neigh_suppress = parse_on_off("neigh_suppress", *argv, &ret);
 470                        if (ret)
 471                                return ret;
 472                } else if (strcmp(*argv, "neigh_vlan_suppress") == 0) {
 473                        NEXT_ARG();
 474                        neigh_vlan_suppress = parse_on_off("neigh_vlan_suppress",
 475                                                           *argv, &ret);
 476                        if (ret)
 477                                return ret;
 478                } else if (strcmp(*argv, "vlan_tunnel") == 0) {
 479                        NEXT_ARG();
 480                        vlan_tunnel = parse_on_off("vlan_tunnel", *argv, &ret);
 481                        if (ret)
 482                                return ret;
 483                } else if (strcmp(*argv, "isolated") == 0) {
 484                        NEXT_ARG();
 485                        isolated = parse_on_off("isolated", *argv, &ret);
 486                        if (ret)
 487                                return ret;
 488                } else if (strcmp(*argv, "locked") == 0) {
 489                        NEXT_ARG();
 490                        locked = parse_on_off("locked", *argv, &ret);
 491                        if (ret)
 492                                return ret;
 493                } else if (strcmp(*argv, "mab") == 0) {
 494                        NEXT_ARG();
 495                        macauth = parse_on_off("mab", *argv, &ret);
 496                        if (ret)
 497                                return ret;
 498                } else if (strcmp(*argv, "backup_port") == 0) {
 499                        NEXT_ARG();
 500                        backup_port_idx = ll_name_to_index(*argv);
 501                        if (!backup_port_idx) {
 502                                fprintf(stderr, "Error: device %s does not exist\n",
 503                                        *argv);
 504                                return -1;
 505                        }
 506                } else if (strcmp(*argv, "nobackup_port") == 0) {
 507                        backup_port_idx = 0;
 508                } else if (strcmp(*argv, "backup_nhid") == 0) {
 509                        NEXT_ARG();
 510                        if (get_u32(&backup_nhid, *argv, 0))
 511                                invarg("invalid backup_nhid", *argv);
 512                        backup_nhid_set = true;
 513                } else {
 514                        usage();
 515                }
 516                argc--; argv++;
 517        }
 518        if (d == NULL) {
 519                fprintf(stderr, "Device is a required argument.\n");
 520                return -1;
 521        }
 522
 523
 524        req.ifm.ifi_index = ll_name_to_index(d);
 525        if (req.ifm.ifi_index == 0) {
 526                fprintf(stderr, "Cannot find bridge device \"%s\"\n", d);
 527                return -1;
 528        }
 529
 530        /* Nested PROTINFO attribute.  Contains: port flags, cost, priority and
 531         * state.
 532         */
 533        nest = addattr_nest(&req.n, sizeof(req),
 534                            IFLA_PROTINFO | NLA_F_NESTED);
 535        /* Flags first */
 536        if (bpdu_guard >= 0)
 537                addattr8(&req.n, sizeof(req), IFLA_BRPORT_GUARD, bpdu_guard);
 538        if (hairpin >= 0)
 539                addattr8(&req.n, sizeof(req), IFLA_BRPORT_MODE, hairpin);
 540        if (fast_leave >= 0)
 541                addattr8(&req.n, sizeof(req), IFLA_BRPORT_FAST_LEAVE,
 542                         fast_leave);
 543        if (root_block >= 0)
 544                addattr8(&req.n, sizeof(req), IFLA_BRPORT_PROTECT, root_block);
 545        if (flood >= 0)
 546                addattr8(&req.n, sizeof(req), IFLA_BRPORT_UNICAST_FLOOD, flood);
 547        if (mcast_router >= 0)
 548                addattr8(&req.n, sizeof(req), IFLA_BRPORT_MULTICAST_ROUTER,
 549                         mcast_router);
 550        if (mcast_flood >= 0)
 551                addattr8(&req.n, sizeof(req), IFLA_BRPORT_MCAST_FLOOD,
 552                         mcast_flood);
 553        if (bcast_flood >= 0)
 554                addattr8(&req.n, sizeof(req), IFLA_BRPORT_BCAST_FLOOD,
 555                         bcast_flood);
 556        if (mcast_to_unicast >= 0)
 557                addattr8(&req.n, sizeof(req), IFLA_BRPORT_MCAST_TO_UCAST,
 558                         mcast_to_unicast);
 559        if (max_groups >= 0)
 560                addattr32(&req.n, sizeof(req), IFLA_BRPORT_MCAST_MAX_GROUPS,
 561                          max_groups);
 562        if (learning >= 0)
 563                addattr8(&req.n, sizeof(req), IFLA_BRPORT_LEARNING, learning);
 564        if (learning_sync >= 0)
 565                addattr8(&req.n, sizeof(req), IFLA_BRPORT_LEARNING_SYNC,
 566                         learning_sync);
 567
 568        if (cost > 0)
 569                addattr32(&req.n, sizeof(req), IFLA_BRPORT_COST, cost);
 570
 571        if (priority >= 0)
 572                addattr16(&req.n, sizeof(req), IFLA_BRPORT_PRIORITY, priority);
 573
 574        if (state >= 0)
 575                addattr8(&req.n, sizeof(req), IFLA_BRPORT_STATE, state);
 576
 577        if (neigh_suppress != -1)
 578                addattr8(&req.n, sizeof(req), IFLA_BRPORT_NEIGH_SUPPRESS,
 579                         neigh_suppress);
 580        if (neigh_vlan_suppress != -1)
 581                addattr8(&req.n, sizeof(req), IFLA_BRPORT_NEIGH_VLAN_SUPPRESS,
 582                         neigh_vlan_suppress);
 583        if (vlan_tunnel != -1)
 584                addattr8(&req.n, sizeof(req), IFLA_BRPORT_VLAN_TUNNEL,
 585                         vlan_tunnel);
 586        if (isolated != -1)
 587                addattr8(&req.n, sizeof(req), IFLA_BRPORT_ISOLATED, isolated);
 588
 589        if (locked >= 0)
 590                addattr8(&req.n, sizeof(req), IFLA_BRPORT_LOCKED, locked);
 591
 592        if (macauth >= 0)
 593                addattr8(&req.n, sizeof(req), IFLA_BRPORT_MAB, macauth);
 594
 595        if (backup_port_idx != -1)
 596                addattr32(&req.n, sizeof(req), IFLA_BRPORT_BACKUP_PORT,
 597                          backup_port_idx);
 598
 599        if (backup_nhid_set)
 600                addattr32(&req.n, sizeof(req), IFLA_BRPORT_BACKUP_NHID,
 601                          backup_nhid);
 602
 603        addattr_nest_end(&req.n, nest);
 604
 605        /* IFLA_AF_SPEC nested attribute. Contains IFLA_BRIDGE_FLAGS that
 606         * designates master or self operation and IFLA_BRIDGE_MODE
 607         * for hw 'vepa' or 'veb' operation modes. The hwmodes are
 608         * only valid in 'self' mode on some devices so far.
 609         */
 610        if (mode >= 0 || flags > 0) {
 611                nest = addattr_nest(&req.n, sizeof(req), IFLA_AF_SPEC);
 612
 613                if (flags > 0)
 614                        addattr16(&req.n, sizeof(req), IFLA_BRIDGE_FLAGS, flags);
 615
 616                if (mode >= 0)
 617                        addattr16(&req.n, sizeof(req), IFLA_BRIDGE_MODE, mode);
 618
 619                addattr_nest_end(&req.n, nest);
 620        }
 621
 622        if (rtnl_talk(&rth, &req.n, NULL) < 0)
 623                return -1;
 624
 625        return 0;
 626}
 627
 628static int brlink_show(int argc, char **argv)
 629{
 630        char *filter_dev = NULL;
 631        char *filter_master = NULL;
 632
 633        while (argc > 0) {
 634                if (strcmp(*argv, "dev") == 0) {
 635                        NEXT_ARG();
 636                        if (filter_dev)
 637                                duparg("dev", *argv);
 638                        filter_dev = *argv;
 639                }
 640                if (strcmp(*argv, "master") == 0) {
 641                        NEXT_ARG();
 642                        if (filter_master)
 643                                duparg("master", *argv);
 644                        filter_master = *argv;
 645                }
 646                argc--; argv++;
 647        }
 648
 649        if (filter_dev) {
 650                filter_dev_index = ll_name_to_index(filter_dev);
 651                if (!filter_dev_index)
 652                        return nodev(filter_dev);
 653        }
 654        if (filter_master) {
 655                filter_master_index = ll_name_to_index(filter_master);
 656                if (!filter_master_index)
 657                        return nodev(filter_master);
 658        }
 659
 660        if (rtnl_linkdump_req(&rth, PF_BRIDGE) < 0) {
 661                perror("Cannot send dump request");
 662                exit(1);
 663        }
 664
 665        new_json_obj(json);
 666        if (rtnl_dump_filter(&rth, print_linkinfo, stdout) < 0) {
 667                fprintf(stderr, "Dump terminated\n");
 668                exit(1);
 669        }
 670
 671        delete_json_obj();
 672        fflush(stdout);
 673        return 0;
 674}
 675
 676int do_link(int argc, char **argv)
 677{
 678        ll_init_map(&rth);
 679        timestamp = 0;
 680
 681        if (argc > 0) {
 682                if (matches(*argv, "set") == 0 ||
 683                    matches(*argv, "change") == 0)
 684                        return brlink_modify(argc-1, argv+1);
 685                if (matches(*argv, "show") == 0 ||
 686                    matches(*argv, "lst") == 0 ||
 687                    matches(*argv, "list") == 0)
 688                        return brlink_show(argc-1, argv+1);
 689                if (matches(*argv, "help") == 0)
 690                        usage();
 691        } else
 692                return brlink_show(0, NULL);
 693
 694        fprintf(stderr, "Command \"%s\" is unknown, try \"bridge link help\".\n", *argv);
 695        exit(-1);
 696}
 697