1 /*
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>
16
17 #include "rt_names.h"
18 #include "utils.h"
19 #include "ip_common.h"
20
print_explain(FILE * f)21 static void print_explain(FILE *f)
22 {
23 fprintf(f,
24 "Usage: ... bridge [ forward_delay FORWARD_DELAY ]\n"
25 " [ hello_time HELLO_TIME ]\n"
26 " [ max_age MAX_AGE ]\n"
27 " [ ageing_time AGEING_TIME ]\n"
28 " [ stp_state STP_STATE ]\n"
29 " [ priority PRIORITY ]\n"
30 " [ vlan_filtering VLAN_FILTERING ]\n"
31 " [ vlan_protocol VLAN_PROTOCOL ]\n"
32 "\n"
33 "Where: VLAN_PROTOCOL := { 802.1Q | 802.1ad }\n"
34 );
35 }
36
explain(void)37 static void explain(void)
38 {
39 print_explain(stderr);
40 }
41
bridge_parse_opt(struct link_util * lu,int argc,char ** argv,struct nlmsghdr * n)42 static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
43 struct nlmsghdr *n)
44 {
45 __u32 val;
46
47 while (argc > 0) {
48 if (matches(*argv, "forward_delay") == 0) {
49 NEXT_ARG();
50 if (get_u32(&val, *argv, 0))
51 invarg("invalid forward_delay", *argv);
52
53 addattr32(n, 1024, IFLA_BR_FORWARD_DELAY, val);
54 } else if (matches(*argv, "hello_time") == 0) {
55 NEXT_ARG();
56 if (get_u32(&val, *argv, 0))
57 invarg("invalid hello_time", *argv);
58
59 addattr32(n, 1024, IFLA_BR_HELLO_TIME, val);
60 } else if (matches(*argv, "max_age") == 0) {
61 NEXT_ARG();
62 if (get_u32(&val, *argv, 0))
63 invarg("invalid max_age", *argv);
64
65 addattr32(n, 1024, IFLA_BR_MAX_AGE, val);
66 } else if (matches(*argv, "ageing_time") == 0) {
67 NEXT_ARG();
68 if (get_u32(&val, *argv, 0))
69 invarg("invalid ageing_time", *argv);
70
71 addattr32(n, 1024, IFLA_BR_AGEING_TIME, val);
72 } else if (matches(*argv, "stp_state") == 0) {
73 NEXT_ARG();
74 if (get_u32(&val, *argv, 0))
75 invarg("invalid stp_state", *argv);
76
77 addattr32(n, 1024, IFLA_BR_STP_STATE, val);
78 } else if (matches(*argv, "priority") == 0) {
79 __u16 prio;
80
81 NEXT_ARG();
82 if (get_u16(&prio, *argv, 0))
83 invarg("invalid priority", *argv);
84
85 addattr16(n, 1024, IFLA_BR_PRIORITY, prio);
86 } else if (matches(*argv, "vlan_filtering") == 0) {
87 __u8 vlan_filter;
88
89 NEXT_ARG();
90 if (get_u8(&vlan_filter, *argv, 0)) {
91 invarg("invalid vlan_filtering", *argv);
92 return -1;
93 }
94 addattr8(n, 1024, IFLA_BR_VLAN_FILTERING, vlan_filter);
95 } else if (matches(*argv, "vlan_protocol") == 0) {
96 __u16 vlan_proto;
97
98 NEXT_ARG();
99 if (ll_proto_a2n(&vlan_proto, *argv)) {
100 invarg("invalid vlan_protocol", *argv);
101 return -1;
102 }
103 addattr16(n, 1024, IFLA_BR_VLAN_PROTOCOL, vlan_proto);
104 } else if (matches(*argv, "help") == 0) {
105 explain();
106 return -1;
107 } else {
108 fprintf(stderr, "bridge: unknown command \"%s\"?\n", *argv);
109 explain();
110 return -1;
111 }
112 argc--, argv++;
113 }
114
115 return 0;
116 }
117
bridge_print_opt(struct link_util * lu,FILE * f,struct rtattr * tb[])118 static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
119 {
120 if (!tb)
121 return;
122
123 if (tb[IFLA_BR_FORWARD_DELAY])
124 fprintf(f, "forward_delay %u ",
125 rta_getattr_u32(tb[IFLA_BR_FORWARD_DELAY]));
126
127 if (tb[IFLA_BR_HELLO_TIME])
128 fprintf(f, "hello_time %u ",
129 rta_getattr_u32(tb[IFLA_BR_HELLO_TIME]));
130
131 if (tb[IFLA_BR_MAX_AGE])
132 fprintf(f, "max_age %u ",
133 rta_getattr_u32(tb[IFLA_BR_MAX_AGE]));
134
135 if (tb[IFLA_BR_AGEING_TIME])
136 fprintf(f, "ageing_time %u ",
137 rta_getattr_u32(tb[IFLA_BR_AGEING_TIME]));
138
139 if (tb[IFLA_BR_STP_STATE])
140 fprintf(f, "stp_state %u ",
141 rta_getattr_u32(tb[IFLA_BR_STP_STATE]));
142
143 if (tb[IFLA_BR_PRIORITY])
144 fprintf(f, "priority %u ",
145 rta_getattr_u16(tb[IFLA_BR_PRIORITY]));
146
147 if (tb[IFLA_BR_VLAN_FILTERING])
148 fprintf(f, "vlan_filtering %u ",
149 rta_getattr_u8(tb[IFLA_BR_VLAN_FILTERING]));
150
151 if (tb[IFLA_BR_VLAN_PROTOCOL]) {
152 SPRINT_BUF(b1);
153
154 fprintf(f, "vlan_protocol %s ",
155 ll_proto_n2a(rta_getattr_u16(tb[IFLA_BR_VLAN_PROTOCOL]),
156 b1, sizeof(b1)));
157 }
158 }
159
bridge_print_help(struct link_util * lu,int argc,char ** argv,FILE * f)160 static void bridge_print_help(struct link_util *lu, int argc, char **argv,
161 FILE *f)
162 {
163 print_explain(f);
164 }
165
166 struct link_util bridge_link_util = {
167 .id = "bridge",
168 .maxattr = IFLA_BR_MAX,
169 .parse_opt = bridge_parse_opt,
170 .print_opt = bridge_print_opt,
171 .print_help = bridge_print_help,
172 };
173