aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Yasevich <vyasevic@redhat.com>2013-02-13 07:00:12 -0500
committerDavid S. Miller <davem@davemloft.net>2013-02-13 19:41:46 -0500
commit407af3299ef1ac7e87ce3fb530e32a009d1a9efd (patch)
tree9572e0b02eb9f6c2952b490f3a79f4b790fcea3c
parent85f46c6baef1486ce20e13dd7cdea5dd15be2a90 (diff)
bridge: Add netlink interface to configure vlans on bridge ports
Add a netlink interface to add and remove vlan configuration on bridge port. The interface uses the RTM_SETLINK message and encodes the vlan configuration inside the IFLA_AF_SPEC. It is possble to include multiple vlans to either add or remove in a single message. Signed-off-by: Vlad Yasevich <vyasevic@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netdevice.h2
-rw-r--r--include/uapi/linux/if_bridge.h9
-rw-r--r--net/bridge/br_device.c1
-rw-r--r--net/bridge/br_if.c1
-rw-r--r--net/bridge/br_netlink.c139
-rw-r--r--net/bridge/br_private.h1
-rw-r--r--net/core/rtnetlink.c72
7 files changed, 207 insertions, 18 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 25bd46f52877..1b90f9401000 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1020,6 +1020,8 @@ struct net_device_ops {
1020 int (*ndo_bridge_getlink)(struct sk_buff *skb, 1020 int (*ndo_bridge_getlink)(struct sk_buff *skb,
1021 u32 pid, u32 seq, 1021 u32 pid, u32 seq,
1022 struct net_device *dev); 1022 struct net_device *dev);
1023 int (*ndo_bridge_dellink)(struct net_device *dev,
1024 struct nlmsghdr *nlh);
1023 int (*ndo_change_carrier)(struct net_device *dev, 1025 int (*ndo_change_carrier)(struct net_device *dev,
1024 bool new_carrier); 1026 bool new_carrier);
1025}; 1027};
diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h
index 5db297514aec..3ca9817ca7e8 100644
--- a/include/uapi/linux/if_bridge.h
+++ b/include/uapi/linux/if_bridge.h
@@ -108,15 +108,24 @@ struct __fdb_entry {
108 * [IFLA_AF_SPEC] = { 108 * [IFLA_AF_SPEC] = {
109 * [IFLA_BRIDGE_FLAGS] 109 * [IFLA_BRIDGE_FLAGS]
110 * [IFLA_BRIDGE_MODE] 110 * [IFLA_BRIDGE_MODE]
111 * [IFLA_BRIDGE_VLAN_INFO]
111 * } 112 * }
112 */ 113 */
113enum { 114enum {
114 IFLA_BRIDGE_FLAGS, 115 IFLA_BRIDGE_FLAGS,
115 IFLA_BRIDGE_MODE, 116 IFLA_BRIDGE_MODE,
117 IFLA_BRIDGE_VLAN_INFO,
116 __IFLA_BRIDGE_MAX, 118 __IFLA_BRIDGE_MAX,
117}; 119};
118#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1) 120#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1)
119 121
122#define BRIDGE_VLAN_INFO_MASTER (1<<0) /* Operate on Bridge device as well */
123
124struct bridge_vlan_info {
125 u16 flags;
126 u16 vid;
127};
128
120/* Bridge multicast database attributes 129/* Bridge multicast database attributes
121 * [MDBA_MDB] = { 130 * [MDBA_MDB] = {
122 * [MDBA_MDB_ENTRY] = { 131 * [MDBA_MDB_ENTRY] = {
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 35a2c2c84f33..091bedf266a0 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -316,6 +316,7 @@ static const struct net_device_ops br_netdev_ops = {
316 .ndo_fdb_dump = br_fdb_dump, 316 .ndo_fdb_dump = br_fdb_dump,
317 .ndo_bridge_getlink = br_getlink, 317 .ndo_bridge_getlink = br_getlink,
318 .ndo_bridge_setlink = br_setlink, 318 .ndo_bridge_setlink = br_setlink,
319 .ndo_bridge_dellink = br_dellink,
319}; 320};
320 321
321static void br_dev_free(struct net_device *dev) 322static void br_dev_free(struct net_device *dev)
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index af9d65ab4001..335c60cebfd1 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -23,6 +23,7 @@
23#include <linux/if_ether.h> 23#include <linux/if_ether.h>
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <net/sock.h> 25#include <net/sock.h>
26#include <linux/if_vlan.h>
26 27
27#include "br_private.h" 28#include "br_private.h"
28 29
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 39ca9796f3f7..534a9f4587a9 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -16,6 +16,7 @@
16#include <net/rtnetlink.h> 16#include <net/rtnetlink.h>
17#include <net/net_namespace.h> 17#include <net/net_namespace.h>
18#include <net/sock.h> 18#include <net/sock.h>
19#include <uapi/linux/if_bridge.h>
19 20
20#include "br_private.h" 21#include "br_private.h"
21#include "br_private_stp.h" 22#include "br_private_stp.h"
@@ -119,10 +120,14 @@ nla_put_failure:
119 */ 120 */
120void br_ifinfo_notify(int event, struct net_bridge_port *port) 121void br_ifinfo_notify(int event, struct net_bridge_port *port)
121{ 122{
122 struct net *net = dev_net(port->dev); 123 struct net *net;
123 struct sk_buff *skb; 124 struct sk_buff *skb;
124 int err = -ENOBUFS; 125 int err = -ENOBUFS;
125 126
127 if (!port)
128 return;
129
130 net = dev_net(port->dev);
126 br_debug(port->br, "port %u(%s) event %d\n", 131 br_debug(port->br, "port %u(%s) event %d\n",
127 (unsigned int)port->port_no, port->dev->name, event); 132 (unsigned int)port->port_no, port->dev->name, event);
128 133
@@ -144,6 +149,7 @@ errout:
144 rtnl_set_sk_err(net, RTNLGRP_LINK, err); 149 rtnl_set_sk_err(net, RTNLGRP_LINK, err);
145} 150}
146 151
152
147/* 153/*
148 * Dump information about all ports, in response to GETLINK 154 * Dump information about all ports, in response to GETLINK
149 */ 155 */
@@ -162,6 +168,64 @@ out:
162 return err; 168 return err;
163} 169}
164 170
171const struct nla_policy ifla_br_policy[IFLA_MAX+1] = {
172 [IFLA_BRIDGE_FLAGS] = { .type = NLA_U16 },
173 [IFLA_BRIDGE_MODE] = { .type = NLA_U16 },
174 [IFLA_BRIDGE_VLAN_INFO] = { .type = NLA_BINARY,
175 .len = sizeof(struct bridge_vlan_info), },
176};
177
178static int br_afspec(struct net_bridge *br,
179 struct net_bridge_port *p,
180 struct nlattr *af_spec,
181 int cmd)
182{
183 struct nlattr *tb[IFLA_BRIDGE_MAX+1];
184 int err = 0;
185
186 err = nla_parse_nested(tb, IFLA_BRIDGE_MAX, af_spec, ifla_br_policy);
187 if (err)
188 return err;
189
190 if (tb[IFLA_BRIDGE_VLAN_INFO]) {
191 struct bridge_vlan_info *vinfo;
192
193 vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
194
195 if (vinfo->vid >= VLAN_N_VID)
196 return -EINVAL;
197
198 switch (cmd) {
199 case RTM_SETLINK:
200 if (p) {
201 err = nbp_vlan_add(p, vinfo->vid);
202 if (err)
203 break;
204
205 if (vinfo->flags & BRIDGE_VLAN_INFO_MASTER)
206 err = br_vlan_add(p->br, vinfo->vid);
207 } else
208 err = br_vlan_add(br, vinfo->vid);
209
210 if (err)
211 break;
212
213 break;
214
215 case RTM_DELLINK:
216 if (p) {
217 nbp_vlan_delete(p, vinfo->vid);
218 if (vinfo->flags & BRIDGE_VLAN_INFO_MASTER)
219 br_vlan_delete(p->br, vinfo->vid);
220 } else
221 br_vlan_delete(br, vinfo->vid);
222 break;
223 }
224 }
225
226 return err;
227}
228
165static const struct nla_policy ifla_brport_policy[IFLA_BRPORT_MAX + 1] = { 229static const struct nla_policy ifla_brport_policy[IFLA_BRPORT_MAX + 1] = {
166 [IFLA_BRPORT_STATE] = { .type = NLA_U8 }, 230 [IFLA_BRPORT_STATE] = { .type = NLA_U8 },
167 [IFLA_BRPORT_COST] = { .type = NLA_U32 }, 231 [IFLA_BRPORT_COST] = { .type = NLA_U32 },
@@ -241,6 +305,7 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlh)
241{ 305{
242 struct ifinfomsg *ifm; 306 struct ifinfomsg *ifm;
243 struct nlattr *protinfo; 307 struct nlattr *protinfo;
308 struct nlattr *afspec;
244 struct net_br