History

net/8021q: Implement Multiple VLAN Registration Protocol (MVRP)

Initial implementation of the Multiple VLAN Registration Protocol (MVRP) from IEEE 802.1Q-2011, based on the existing implementation of the GARP VLAN Registration Protocol (GVRP).

David Ward committed 13 years ago

Commit 86fbe9b1 parent febf0189 files · +136 −7Browse files

Unified · Split

9 files
  1. include/uapi/linux/if_ether.h +1 −0
  2. include/uapi/linux/if_vlan.h +1 −0
  3. net/8021q/Kconfig +11 −0
  4. net/8021q/Makefile +1 −0
  5. net/8021q/vlan.c +22 −5
  6. net/8021q/vlan.h +16 −0
  7. net/8021q/vlan_dev.c +11 −1
  8. net/8021q/vlan_mvrp.c +72 −0
  9. net/8021q/vlan_netlink.c +1 −1
include/uapi/linux/if_ether.h+1−0
@@ -83,6 +83,7 @@ · 82 unmodified lines
8383 #define ETH_P_802_EX1 0x88B5 /* 802.1 Local Experimental 1. */
8484 #define ETH_P_TIPC 0x88CA /* TIPC */
8585 #define ETH_P_8021AH 0x88E7 /* 802.1ah Backbone Service Tag */
86+#define ETH_P_MVRP 0x88F5 /* 802.1Q MVRP */
8687 #define ETH_P_1588 0x88F7 /* IEEE 1588 Timesync */
8788 #define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */
8889 #define ETH_P_TDLS 0x890D /* TDLS */
include/uapi/linux/if_vlan.h+1−0
@@ -34,6 +34,7 @@ enum vlan_flags { · 33 unmodified lines
3434 VLAN_FLAG_REORDER_HDR = 0x1,
3535 VLAN_FLAG_GVRP = 0x2,
3636 VLAN_FLAG_LOOSE_BINDING = 0x4,
37+ VLAN_FLAG_MVRP = 0x8,
3738 };
3839
3940 enum vlan_name_types {
net/8021q/Kconfig+11−0
@@ -27,3 +27,14 @@ config VLAN_8021Q_GVRP · 26 unmodified lines
2727 automatic propagation of registered VLANs to switches.
2828
2929 If unsure, say N.
30+
31+config VLAN_8021Q_MVRP
32+ bool "MVRP (Multiple VLAN Registration Protocol) support"
33+ depends on VLAN_8021Q
34+ select MRP
35+ help
36+ Select this to enable MVRP end-system support. MVRP is used for
37+ automatic propagation of registered VLANs to switches; it
38+ supersedes GVRP and is not backwards-compatible.
39+
40+ If unsure, say N.
net/8021q/Makefile+1−0
@@ -6,5 +6,6 @@ obj-$(CONFIG_VLAN_8021Q) += 8021q.o · 5 unmodified lines
66
77 8021q-y := vlan.o vlan_dev.o vlan_netlink.o
88 8021q-$(CONFIG_VLAN_8021Q_GVRP) += vlan_gvrp.o
9+8021q-$(CONFIG_VLAN_8021Q_MVRP) += vlan_mvrp.o
910 8021q-$(CONFIG_PROC_FS) += vlanproc.o
1011
net/8021q/vlan.c+22−5
@@ -95,6 +95,8 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) · 94 unmodified lines
9595
9696 grp->nr_vlan_devs--;
9797
98+ if (vlan->flags & VLAN_FLAG_MVRP)
99+ vlan_mvrp_request_leave(dev);
98100 if (vlan->flags & VLAN_FLAG_GVRP)
99101 vlan_gvrp_request_leave(dev);
100102
@@ -107,8 +109,10 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) · 6 unmodified lines
107109
108110 netdev_upper_dev_unlink(real_dev, dev);
109111
110− if (grp->nr_vlan_devs == 0)
112+ if (grp->nr_vlan_devs == 0) {
113+ vlan_mvrp_uninit_applicant(real_dev);
111114 vlan_gvrp_uninit_applicant(real_dev);
115+ }
112116
113117 /* Get rid of the vlan's reference to real_dev */
114118 dev_put(real_dev);
@@ -151,15 +155,18 @@ int register_vlan_dev(struct net_device *dev) · 36 unmodified lines
151155 err = vlan_gvrp_init_applicant(real_dev);
152156 if (err < 0)
153157 goto out_vid_del;
158+ err = vlan_mvrp_init_applicant(real_dev);
159+ if (err < 0)
160+ goto out_uninit_gvrp;
154161 }
155162
156163 err = vlan_group_prealloc_vid(grp, vlan_id);
157164 if (err < 0)
158− goto out_uninit_applicant;
165+ goto out_uninit_mvrp;
159166
160167 err = netdev_upper_dev_link(real_dev, dev);
161168 if (err)
162− goto out_uninit_applicant;
169+ goto out_uninit_mvrp;
163170
164171 err = register_netdevice(dev);
165172 if (err < 0)
@@ -181,7 +188,10 @@ int register_vlan_dev(struct net_device *dev) · 15 unmodified lines
181188
182189 out_upper_dev_unlink:
183190 netdev_upper_dev_unlink(real_dev, dev);
184−out_uninit_applicant:
191+out_uninit_mvrp:
192+ if (grp->nr_vlan_devs == 0)
193+ vlan_mvrp_uninit_applicant(real_dev);
194+out_uninit_gvrp:
185195 if (grp->nr_vlan_devs == 0)
186196 vlan_gvrp_uninit_applicant(real_dev);
187197 out_vid_del:
@@ -655,13 +665,19 @@ static int __init vlan_proto_init(void) · 467 unmodified lines
655665 if (err < 0)
656666 goto err3;
657667
658− err = vlan_netlink_init();
668+ err = vlan_mvrp_init();
659669 if (err < 0)
660670 goto err4;
661671
672+ err = vlan_netlink_init();
673+ if (err < 0)
674+ goto err5;
675+
662676 vlan_ioctl_set(vlan_ioctl_handler);
663677 return 0;
664678
679+err5:
680+ vlan_mvrp_uninit();
665681 err4:
666682 vlan_gvrp_uninit();
667683 err3:
@@ -682,6 +698,7 @@ static void __exit vlan_cleanup_module(void) · 14 unmodified lines
682698 unregister_pernet_subsys(&vlan_net_ops);
683699 rcu_barrier(); /* Wait for completion of call_rcu()'s */
684700
701+ vlan_mvrp_uninit();
685702 vlan_gvrp_uninit();
686703 }
687704
net/8021q/vlan.h+16−0
@@ -171,6 +171,22 @@ static inline int vlan_gvrp_init(void) { return 0; } · 170 unmodified lines
171171 static inline void vlan_gvrp_uninit(void) {}
172172 #endif
173173
174+#ifdef CONFIG_VLAN_8021Q_MVRP
175+extern int vlan_mvrp_request_join(const struct net_device *dev);
176+extern void vlan_mvrp_request_leave(const struct net_device *dev);
177+extern int vlan_mvrp_init_applicant(struct net_device *dev);
178+extern void vlan_mvrp_uninit_applicant(struct net_device *dev);
179+extern int vlan_mvrp_init(void);
180+extern void vlan_mvrp_uninit(void);
181+#else
182+static inline int vlan_mvrp_request_join(const struct net_device *dev) { return 0; }
183+static inline void vlan_mvrp_request_leave(const struct net_device *dev) {}
184+static inline int vlan_mvrp_init_applicant(struct net_device *dev) { return 0; }
185+static inline void vlan_mvrp_uninit_applicant(struct net_device *dev) {}
186+static inline int vlan_mvrp_init(void) { return 0; }
187+static inline void vlan_mvrp_uninit(void) {}
188+#endif
189+
174190 extern const char vlan_fullname[];
175191 extern const char vlan_version[];
176192 extern int vlan_netlink_init(void);
net/8021q/vlan_dev.c+11−1
@@ -261,7 +261,7 @@ int vlan_dev_change_flags(const struct net_device *dev, u32 flags, u32 mask) · 260 unmodified lines
261261 u32 old_flags = vlan->flags;
262262
263263 if (mask & ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP |
264− VLAN_FLAG_LOOSE_BINDING))
264+ VLAN_FLAG_LOOSE_BINDING | VLAN_FLAG_MVRP))
265265 return -EINVAL;
266266
267267 vlan->flags = (old_flags & ~mask) | (flags & mask);
@@ -272,6 +272,13 @@ int vlan_dev_change_flags(const struct net_device *dev, u32 flags, u32 mask) · 4 unmodified lines
272272 else
273273 vlan_gvrp_request_leave(dev);
274274 }
275+
276+ if (netif_running(dev) && (vlan->flags ^ old_flags) & VLAN_FLAG_MVRP) {
277+ if (vlan->flags & VLAN_FLAG_MVRP)
278+ vlan_mvrp_request_join(dev);
279+ else
280+ vlan_mvrp_request_leave(dev);
281+ }
275282 return 0;
276283 }
277284
@@ -312,6 +319,9 @@ static int vlan_dev_open(struct net_device *dev) · 34 unmodified lines
312319 if (vlan->flags & VLAN_FLAG_GVRP)
313320 vlan_gvrp_request_join(dev);
314321
322+ if (vlan->flags & VLAN_FLAG_MVRP)
323+ vlan_mvrp_request_join(dev);
324+
315325 if (netif_carrier_ok(real_dev))
316326 netif_carrier_on(dev);
317327 return 0;
net/8021q/vlan_mvrp.c+72−0
@@ -0,0 +1,72 @@
1+/*
2+ * IEEE 802.1Q Multiple VLAN Registration Protocol (MVRP)
3+ *
4+ * Copyright (c) 2012 Massachusetts Institute of Technology
5+ *
6+ * Adapted from code in net/8021q/vlan_gvrp.c
7+ * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
8+ *
9+ * This program is free software; you can redistribute it and/or
10+ * modify it under the terms of the GNU General Public License
11+ * version 2 as published by the Free Software Foundation.
12+ */
13+#include <linux/types.h>
14+#include <linux/if_ether.h>
15+#include <linux/if_vlan.h>
16+#include <net/mrp.h>
17+#include "vlan.h"
18+
19+#define MRP_MVRP_ADDRESS { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x21 }
20+
21+enum mvrp_attributes {
22+ MVRP_ATTR_INVALID,
23+ MVRP_ATTR_VID,
24+ __MVRP_ATTR_MAX
25+};
26+#define MVRP_ATTR_MAX (__MVRP_ATTR_MAX - 1)
27+
28+static struct mrp_application vlan_mrp_app __read_mostly = {
29+ .type = MRP_APPLICATION_MVRP,
30+ .maxattr = MVRP_ATTR_MAX,
31+ .pkttype.type = htons(ETH_P_MVRP),
32+ .group_address = MRP_MVRP_ADDRESS,
33+ .version = 0,
34+};
35+
36+int vlan_mvrp_request_join(const struct net_device *dev)
37+{
38+ const struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
39+ __be16 vlan_id = htons(vlan->vlan_id);
40+
41+ return mrp_request_join(vlan->real_dev, &vlan_mrp_app,
42+ &vlan_id, sizeof(vlan_id), MVRP_ATTR_VID);
43+}
44+
45+void vlan_mvrp_request_leave(const struct net_device *dev)
46+{
47+ const struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
48+ __be16 vlan_id = htons(vlan->vlan_id);
49+
50+ mrp_request_leave(vlan->real_dev, &vlan_mrp_app,
51+ &vlan_id, sizeof(vlan_id), MVRP_ATTR_VID);
52+}
53+
54+int vlan_mvrp_init_applicant(struct net_device *dev)
55+{
56+ return mrp_init_applicant(dev, &vlan_mrp_app);
57+}
58+
59+void vlan_mvrp_uninit_applicant(struct net_device *dev)
60+{
61+ mrp_uninit_applicant(dev, &vlan_mrp_app);
62+}
63+
64+int __init vlan_mvrp_init(void)
65+{
66+ return mrp_register_application(&vlan_mrp_app);
67+}
68+
69+void vlan_mvrp_uninit(void)
70+{
71+ mrp_unregister_application(&vlan_mrp_app);
72+}
net/8021q/vlan_netlink.c+1−1
@@ -62,7 +62,7 @@ static int vlan_validate(struct nlattr *tb[], struct nlattr *data[]) · 61 unmodified lines
6262 flags = nla_data(data[IFLA_VLAN_FLAGS]);
6363 if ((flags->flags & flags->mask) &
6464 ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP |
65− VLAN_FLAG_LOOSE_BINDING))
65+ VLAN_FLAG_LOOSE_BINDING | VLAN_FLAG_MVRP))
6666 return -EINVAL;
6767 }
6868

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t