blob: 3bbbcaa120cf0a1cb83586e9356bd0337e882ec2 [file] [log] [blame]
Jiri Pirko28d84b42014-09-28 16:33:29 -07001/*
2 * iplink_bridge.c Bridge device support
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: Jiri Pirko <jiri@resnulli.us>
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <linux/if_link.h>
Nikolay Aleksandrov70dfb0b2016-02-09 00:14:19 +010016#include <netinet/ether.h>
Jiri Pirko28d84b42014-09-28 16:33:29 -070017
Toshiaki Makita1eea5c42015-08-31 18:48:46 +090018#include "rt_names.h"
Jiri Pirko28d84b42014-09-28 16:33:29 -070019#include "utils.h"
20#include "ip_common.h"
21
Zhang Shengju43367ef2015-08-12 06:03:23 +000022static void print_explain(FILE *f)
Jiri Pirko28d84b42014-09-28 16:33:29 -070023{
Zhang Shengju43367ef2015-08-12 06:03:23 +000024 fprintf(f,
Jiri Pirko28d84b42014-09-28 16:33:29 -070025 "Usage: ... bridge [ forward_delay FORWARD_DELAY ]\n"
26 " [ hello_time HELLO_TIME ]\n"
27 " [ max_age MAX_AGE ]\n"
Nikolay Aleksandrov6c99fb62015-06-16 13:38:47 +030028 " [ ageing_time AGEING_TIME ]\n"
Nikolay Aleksandrovdab04962015-06-16 13:38:48 +030029 " [ stp_state STP_STATE ]\n"
Nikolay Aleksandrovb0197a02015-06-16 13:38:49 +030030 " [ priority PRIORITY ]\n"
Nikolay Aleksandrove4d456f2015-08-12 09:19:06 -070031 " [ vlan_filtering VLAN_FILTERING ]\n"
Toshiaki Makita1eea5c42015-08-31 18:48:46 +090032 " [ vlan_protocol VLAN_PROTOCOL ]\n"
33 "\n"
34 "Where: VLAN_PROTOCOL := { 802.1Q | 802.1ad }\n"
Jiri Pirko28d84b42014-09-28 16:33:29 -070035 );
36}
37
Zhang Shengju43367ef2015-08-12 06:03:23 +000038static void explain(void)
39{
40 print_explain(stderr);
41}
42
Nikolay Aleksandrov70dfb0b2016-02-09 00:14:19 +010043static void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf,
44 size_t len)
45{
46 char eaddr[32];
47
48 ether_ntoa_r((const struct ether_addr *)id->addr, eaddr);
49 snprintf(buf, len, "%.2x%.2x.%s", id->prio[0], id->prio[1], eaddr);
50}
51
Jiri Pirko28d84b42014-09-28 16:33:29 -070052static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
53 struct nlmsghdr *n)
54{
55 __u32 val;
56
57 while (argc > 0) {
58 if (matches(*argv, "forward_delay") == 0) {
59 NEXT_ARG();
Zhang Shengju6a9ce302015-08-13 07:48:15 +000060 if (get_u32(&val, *argv, 0))
Jiri Pirko28d84b42014-09-28 16:33:29 -070061 invarg("invalid forward_delay", *argv);
Zhang Shengju6a9ce302015-08-13 07:48:15 +000062
Jiri Pirko28d84b42014-09-28 16:33:29 -070063 addattr32(n, 1024, IFLA_BR_FORWARD_DELAY, val);
64 } else if (matches(*argv, "hello_time") == 0) {
65 NEXT_ARG();
Zhang Shengju6a9ce302015-08-13 07:48:15 +000066 if (get_u32(&val, *argv, 0))
Jiri Pirko28d84b42014-09-28 16:33:29 -070067 invarg("invalid hello_time", *argv);
Zhang Shengju6a9ce302015-08-13 07:48:15 +000068
Jiri Pirko28d84b42014-09-28 16:33:29 -070069 addattr32(n, 1024, IFLA_BR_HELLO_TIME, val);
70 } else if (matches(*argv, "max_age") == 0) {
71 NEXT_ARG();
Zhang Shengju6a9ce302015-08-13 07:48:15 +000072 if (get_u32(&val, *argv, 0))
Jiri Pirko28d84b42014-09-28 16:33:29 -070073 invarg("invalid max_age", *argv);
Zhang Shengju6a9ce302015-08-13 07:48:15 +000074
Jiri Pirko28d84b42014-09-28 16:33:29 -070075 addattr32(n, 1024, IFLA_BR_MAX_AGE, val);
Nikolay Aleksandrov6c99fb62015-06-16 13:38:47 +030076 } else if (matches(*argv, "ageing_time") == 0) {
77 NEXT_ARG();
Zhang Shengju6a9ce302015-08-13 07:48:15 +000078 if (get_u32(&val, *argv, 0))
Nikolay Aleksandrov6c99fb62015-06-16 13:38:47 +030079 invarg("invalid ageing_time", *argv);
Zhang Shengju6a9ce302015-08-13 07:48:15 +000080
Nikolay Aleksandrov6c99fb62015-06-16 13:38:47 +030081 addattr32(n, 1024, IFLA_BR_AGEING_TIME, val);
Nikolay Aleksandrovdab04962015-06-16 13:38:48 +030082 } else if (matches(*argv, "stp_state") == 0) {
83 NEXT_ARG();
Zhang Shengju6a9ce302015-08-13 07:48:15 +000084 if (get_u32(&val, *argv, 0))
Nikolay Aleksandrovdab04962015-06-16 13:38:48 +030085 invarg("invalid stp_state", *argv);
Zhang Shengju6a9ce302015-08-13 07:48:15 +000086
Nikolay Aleksandrovdab04962015-06-16 13:38:48 +030087 addattr32(n, 1024, IFLA_BR_STP_STATE, val);
Nikolay Aleksandrovb0197a02015-06-16 13:38:49 +030088 } else if (matches(*argv, "priority") == 0) {
89 __u16 prio;
90
91 NEXT_ARG();
Zhang Shengju6a9ce302015-08-13 07:48:15 +000092 if (get_u16(&prio, *argv, 0))
Nikolay Aleksandrovb0197a02015-06-16 13:38:49 +030093 invarg("invalid priority", *argv);
Zhang Shengju6a9ce302015-08-13 07:48:15 +000094
Nikolay Aleksandrovb0197a02015-06-16 13:38:49 +030095 addattr16(n, 1024, IFLA_BR_PRIORITY, prio);
Nikolay Aleksandrove4d456f2015-08-12 09:19:06 -070096 } else if (matches(*argv, "vlan_filtering") == 0) {
97 __u8 vlan_filter;
98
99 NEXT_ARG();
100 if (get_u8(&vlan_filter, *argv, 0)) {
101 invarg("invalid vlan_filtering", *argv);
102 return -1;
103 }
104 addattr8(n, 1024, IFLA_BR_VLAN_FILTERING, vlan_filter);
Toshiaki Makita1eea5c42015-08-31 18:48:46 +0900105 } else if (matches(*argv, "vlan_protocol") == 0) {
106 __u16 vlan_proto;
107
108 NEXT_ARG();
109 if (ll_proto_a2n(&vlan_proto, *argv)) {
110 invarg("invalid vlan_protocol", *argv);
111 return -1;
112 }
113 addattr16(n, 1024, IFLA_BR_VLAN_PROTOCOL, vlan_proto);
Jiri Pirko28d84b42014-09-28 16:33:29 -0700114 } else if (matches(*argv, "help") == 0) {
115 explain();
116 return -1;
117 } else {
118 fprintf(stderr, "bridge: unknown command \"%s\"?\n", *argv);
119 explain();
120 return -1;
121 }
122 argc--, argv++;
123 }
124
125 return 0;
126}
127
128static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
129{
130 if (!tb)
131 return;
132
133 if (tb[IFLA_BR_FORWARD_DELAY])
134 fprintf(f, "forward_delay %u ",
135 rta_getattr_u32(tb[IFLA_BR_FORWARD_DELAY]));
136
137 if (tb[IFLA_BR_HELLO_TIME])
138 fprintf(f, "hello_time %u ",
139 rta_getattr_u32(tb[IFLA_BR_HELLO_TIME]));
140
141 if (tb[IFLA_BR_MAX_AGE])
142 fprintf(f, "max_age %u ",
143 rta_getattr_u32(tb[IFLA_BR_MAX_AGE]));
Nikolay Aleksandrovfdba0512015-08-12 09:11:30 -0700144
145 if (tb[IFLA_BR_AGEING_TIME])
146 fprintf(f, "ageing_time %u ",
147 rta_getattr_u32(tb[IFLA_BR_AGEING_TIME]));
148
149 if (tb[IFLA_BR_STP_STATE])
150 fprintf(f, "stp_state %u ",
151 rta_getattr_u32(tb[IFLA_BR_STP_STATE]));
152
153 if (tb[IFLA_BR_PRIORITY])
154 fprintf(f, "priority %u ",
155 rta_getattr_u16(tb[IFLA_BR_PRIORITY]));
Nikolay Aleksandrove4d456f2015-08-12 09:19:06 -0700156
157 if (tb[IFLA_BR_VLAN_FILTERING])
158 fprintf(f, "vlan_filtering %u ",
159 rta_getattr_u8(tb[IFLA_BR_VLAN_FILTERING]));
Toshiaki Makita1eea5c42015-08-31 18:48:46 +0900160
161 if (tb[IFLA_BR_VLAN_PROTOCOL]) {
162 SPRINT_BUF(b1);
163
164 fprintf(f, "vlan_protocol %s ",
165 ll_proto_n2a(rta_getattr_u16(tb[IFLA_BR_VLAN_PROTOCOL]),
166 b1, sizeof(b1)));
167 }
Nikolay Aleksandrov70dfb0b2016-02-09 00:14:19 +0100168
169 if (tb[IFLA_BR_BRIDGE_ID]) {
170 char bridge_id[32];
171
172 br_dump_bridge_id(RTA_DATA(tb[IFLA_BR_BRIDGE_ID]), bridge_id,
173 sizeof(bridge_id));
174 fprintf(f, "bridge_id %s ", bridge_id);
175 }
176
177 if (tb[IFLA_BR_ROOT_ID]) {
178 char root_id[32];
179
180 br_dump_bridge_id(RTA_DATA(tb[IFLA_BR_BRIDGE_ID]), root_id,
181 sizeof(root_id));
182 fprintf(f, "designated_root %s ", root_id);
183 }
Jiri Pirko28d84b42014-09-28 16:33:29 -0700184}
185
Zhang Shengju43367ef2015-08-12 06:03:23 +0000186static void bridge_print_help(struct link_util *lu, int argc, char **argv,
187 FILE *f)
188{
189 print_explain(f);
190}
191
Jiri Pirko28d84b42014-09-28 16:33:29 -0700192struct link_util bridge_link_util = {
193 .id = "bridge",
194 .maxattr = IFLA_BR_MAX,
195 .parse_opt = bridge_parse_opt,
196 .print_opt = bridge_print_opt,
Zhang Shengju43367ef2015-08-12 06:03:23 +0000197 .print_help = bridge_print_help,
Jiri Pirko28d84b42014-09-28 16:33:29 -0700198};