]> git.proxmox.com Git - mirror_iproute2.git/blame - ip/iplink_bridge_slave.c
iplink: add missing link type
[mirror_iproute2.git] / ip / iplink_bridge_slave.c
CommitLineData
8c39db39
JP
1/*
2 * iplink_bridge_slave.c Bridge slave 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 <sys/socket.h>
14#include <netinet/in.h>
15#include <linux/if_link.h>
16#include <linux/if_bridge.h>
17
18#include "rt_names.h"
19#include "utils.h"
20#include "ip_common.h"
21
22static void explain(void)
23{
24 fprintf(stderr,
25 "Usage: ... bridge_slave [ state STATE ] [ priority PRIO ] [cost COST ]\n"
26 " [ guard {on | off} ]\n"
27 " [ hairpin {on | off} ] \n"
28 " [ fastleave {on | off} ]\n"
29 " [ root_block {on | off} ]\n"
30 " [ learning {on | off} ]\n"
31 " [ flood {on | off} ]\n"
32 );
33}
34
35static const char *port_states[] = {
36 [BR_STATE_DISABLED] = "disabled",
37 [BR_STATE_LISTENING] = "listening",
38 [BR_STATE_LEARNING] = "learning",
39 [BR_STATE_FORWARDING] = "forwarding",
40 [BR_STATE_BLOCKING] = "blocking",
41};
42
43static void print_portstate(FILE *f, __u8 state)
44{
45 if (state <= BR_STATE_BLOCKING)
46 fprintf(f, "state %s ", port_states[state]);
47 else
48 fprintf(f, "state (%d) ", state);
49}
50
51static void print_onoff(FILE *f, char *flag, __u8 val)
52{
53 fprintf(f, "%s %s ", flag, val ? "on" : "off");
54}
55
56static void bridge_slave_print_opt(struct link_util *lu, FILE *f,
57 struct rtattr *tb[])
58{
59 if (!tb)
60 return;
61
62 if (tb[IFLA_BRPORT_STATE])
63 print_portstate(f, rta_getattr_u8(tb[IFLA_BRPORT_STATE]));
64
65 if (tb[IFLA_BRPORT_PRIORITY])
66 fprintf(f, "priority %d ",
67 rta_getattr_u16(tb[IFLA_BRPORT_PRIORITY]));
68
69 if (tb[IFLA_BRPORT_COST])
70 fprintf(f, "cost %d ",
71 rta_getattr_u32(tb[IFLA_BRPORT_COST]));
72
73 if (tb[IFLA_BRPORT_MODE])
74 print_onoff(f, "hairpin",
75 rta_getattr_u8(tb[IFLA_BRPORT_MODE]));
76
77 if (tb[IFLA_BRPORT_GUARD])
78 print_onoff(f, "guard",
79 rta_getattr_u8(tb[IFLA_BRPORT_GUARD]));
80
81 if (tb[IFLA_BRPORT_PROTECT])
82 print_onoff(f, "root_block",
83 rta_getattr_u8(tb[IFLA_BRPORT_PROTECT]));
84
85 if (tb[IFLA_BRPORT_FAST_LEAVE])
86 print_onoff(f, "fastleave",
87 rta_getattr_u8(tb[IFLA_BRPORT_FAST_LEAVE]));
88
89 if (tb[IFLA_BRPORT_LEARNING])
90 print_onoff(f, "learning",
91 rta_getattr_u8(tb[IFLA_BRPORT_LEARNING]));
92
93 if (tb[IFLA_BRPORT_UNICAST_FLOOD])
94 print_onoff(f, "flood",
95 rta_getattr_u8(tb[IFLA_BRPORT_UNICAST_FLOOD]));
96}
97
98static void bridge_slave_parse_on_off(char *arg_name, char *arg_val,
99 struct nlmsghdr *n, int type)
100{
101 __u8 val;
102
103 if (strcmp(arg_val, "on") == 0)
104 val = 1;
105 else if (strcmp(arg_val, "off") == 0)
106 val = 0;
107 else
108 invarg("should be \"on\" or \"off\"", arg_name);
109
110 addattr8(n, 1024, type, val);
111}
112
113static int bridge_slave_parse_opt(struct link_util *lu, int argc, char **argv,
114 struct nlmsghdr *n)
115{
116 __u8 state;
117 __u16 priority;
118 __u32 cost;
119
120 while (argc > 0) {
121 if (matches(*argv, "state") == 0) {
122 NEXT_ARG();
123 if (get_u8(&state, *argv, 0))
124 invarg("state is invalid", *argv);
125 addattr8(n, 1024, IFLA_BRPORT_STATE, state);
126 } else if (matches(*argv, "priority") == 0) {
127 NEXT_ARG();
128 if (get_u16(&priority, *argv, 0))
129 invarg("priority is invalid", *argv);
130 addattr16(n, 1024, IFLA_BRPORT_PRIORITY, priority);
131 } else if (matches(*argv, "cost") == 0) {
132 NEXT_ARG();
133 if (get_u32(&cost, *argv, 0))
134 invarg("cost is invalid", *argv);
135 addattr32(n, 1024, IFLA_BRPORT_COST, cost);
136 } else if (matches(*argv, "hairpin") == 0) {
137 NEXT_ARG();
138 bridge_slave_parse_on_off("hairpin", *argv, n,
139 IFLA_BRPORT_MODE);
140 } else if (matches(*argv, "guard") == 0) {
141 NEXT_ARG();
142 bridge_slave_parse_on_off("guard", *argv, n,
143 IFLA_BRPORT_GUARD);
144 } else if (matches(*argv, "root_block") == 0) {
145 NEXT_ARG();
146 bridge_slave_parse_on_off("root_block", *argv, n,
147 IFLA_BRPORT_PROTECT);
148 } else if (matches(*argv, "fastleave") == 0) {
149 NEXT_ARG();
150 bridge_slave_parse_on_off("fastleave", *argv, n,
151 IFLA_BRPORT_FAST_LEAVE);
152 } else if (matches(*argv, "learning") == 0) {
153 NEXT_ARG();
154 bridge_slave_parse_on_off("learning", *argv, n,
155 IFLA_BRPORT_LEARNING);
156 } else if (matches(*argv, "flood") == 0) {
157 NEXT_ARG();
158 bridge_slave_parse_on_off("flood", *argv, n,
159 IFLA_BRPORT_UNICAST_FLOOD);
160 } else if (matches(*argv, "help") == 0) {
161 explain();
162 return -1;
163 } else {
164 fprintf(stderr, "bridge_slave: unknown option \"%s\"?\n",
165 *argv);
166 explain();
167 return -1;
168 }
169 argc--, argv++;
170 }
171
172 return 0;
173}
174
175struct link_util bridge_slave_link_util = {
176 .id = "bridge",
177 .maxattr = IFLA_BRPORT_MAX,
178 .print_opt = bridge_slave_print_opt,
179 .parse_opt = bridge_slave_parse_opt,
180 .slave = true,
181};