aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2019-02-08 07:55:31 -0500
committerDavid S. Miller <davem@davemloft.net>2019-02-08 14:16:48 -0500
commitc675e06a98a474f7ad0af32ce467613da818da52 (patch)
tree89d60212e3566eb1d81de4ba55b78c9264ae9403
parent998a8a8387ff5f65da456d1fc448dbb926fb5d78 (diff)
ipvlan: decouple l3s mode dependencies from other modes
Right now ipvlan has a hard dependency on CONFIG_NETFILTER and otherwise it cannot be built. However, the only ipvlan operation mode that actually depends on netfilter is l3s, everything else is independent of it. Break this hard dependency such that users are able to use ipvlan l3 mode on systems where netfilter is not compiled in. Therefore, this adds a hidden CONFIG_IPVLAN_L3S bool which is defaulting to y when CONFIG_NETFILTER is set in order to retain existing behavior for l3s. All l3s related code is refactored into ipvlan_l3s.c that is compiled in when enabled. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Cc: Mahesh Bandewar <maheshb@google.com> Cc: Florian Westphal <fw@strlen.de> Cc: Martynas Pumputis <m@lambda.lt> Acked-by: Florian Westphal <fw@strlen.de> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/Kconfig6
-rw-r--r--drivers/net/ipvlan/Makefile3
-rw-r--r--drivers/net/ipvlan/ipvlan.h37
-rw-r--r--drivers/net/ipvlan/ipvlan_core.c105
-rw-r--r--drivers/net/ipvlan/ipvlan_l3s.c227
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c117
6 files changed, 287 insertions, 208 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index edb1c023a753..7f9727f64f55 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -145,13 +145,15 @@ config MACVTAP
145 To compile this driver as a module, choose M here: the module 145 To compile this driver as a module, choose M here: the module
146 will be called macvtap. 146 will be called macvtap.
147 147
148config IPVLAN_L3S
149 depends on NETFILTER
150 def_bool y
151 select NET_L3_MASTER_DEV
148 152
149config IPVLAN 153config IPVLAN
150 tristate "IP-VLAN support" 154 tristate "IP-VLAN support"
151 depends on INET 155 depends on INET
152 depends on IPV6 || !IPV6 156 depends on IPV6 || !IPV6
153 depends on NETFILTER
154 select NET_L3_MASTER_DEV
155 ---help--- 157 ---help---
156 This allows one to create virtual devices off of a main interface 158 This allows one to create virtual devices off of a main interface
157 and packets will be delivered based on the dest L3 (IPv6/IPv4 addr) 159 and packets will be delivered based on the dest L3 (IPv6/IPv4 addr)
diff --git a/drivers/net/ipvlan/Makefile b/drivers/net/ipvlan/Makefile
index 8a2c64dc9641..3ee95367a994 100644
--- a/drivers/net/ipvlan/Makefile
+++ b/drivers/net/ipvlan/Makefile
@@ -5,4 +5,5 @@
5obj-$(CONFIG_IPVLAN) += ipvlan.o 5obj-$(CONFIG_IPVLAN) += ipvlan.o
6obj-$(CONFIG_IPVTAP) += ipvtap.o 6obj-$(CONFIG_IPVTAP) += ipvtap.o
7 7
8ipvlan-objs := ipvlan_core.o ipvlan_main.o 8ipvlan-objs-$(CONFIG_IPVLAN_L3S) += ipvlan_l3s.o
9ipvlan-objs := ipvlan_core.o ipvlan_main.o $(ipvlan-objs-y)
diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h
index adb826f55e60..b906d2f6bd04 100644
--- a/drivers/net/ipvlan/ipvlan.h
+++ b/drivers/net/ipvlan/ipvlan.h
@@ -165,10 +165,9 @@ struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan,
165 const void *iaddr, bool is_v6); 165 const void *iaddr, bool is_v6);
166bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6); 166bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6);
167void ipvlan_ht_addr_del(struct ipvl_addr *addr); 167void ipvlan_ht_addr_del(struct ipvl_addr *addr);
168struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, struct sk_buff *skb, 168struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h,
169 u16 proto); 169 int addr_type, bool use_dest);
170unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb, 170void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type);
171 const struct nf_hook_state *state);
172void ipvlan_count_rx(const struct ipvl_dev *ipvlan, 171void ipvlan_count_rx(const struct ipvl_dev *ipvlan,
173 unsigned int len, bool success, bool mcast); 172 unsigned int len, bool success, bool mcast);
174int ipvlan_link_new(struct net *src_net, struct net_device *dev, 173int ipvlan_link_new(struct net *src_net, struct net_device *dev,
@@ -177,6 +176,36 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev,
177void ipvlan_link_delete(struct net_device *dev, struct list_head *head); 176void ipvlan_link_delete(struct net_device *dev, struct list_head *head);
178void ipvlan_link_setup(struct net_device *dev); 177void ipvlan_link_setup(struct net_device *dev);
179int ipvlan_link_register(struct rtnl_link_ops *ops); 178int ipvlan_link_register(struct rtnl_link_ops *ops);
179#ifdef CONFIG_IPVLAN_L3S
180int ipvlan_l3s_register(struct ipvl_port *port);
181void ipvlan_l3s_unregister(struct ipvl_port *port);
182void ipvlan_migrate_l3s_hook(struct net *oldnet, struct net *newnet);
183int ipvlan_l3s_init(void);
184void ipvlan_l3s_cleanup(void);
185#else
186static inline int ipvlan_l3s_register(struct ipvl_port *port)
187{
188 return -ENOTSUPP;
189}
190
191static inline void ipvlan_l3s_unregister(struct ipvl_port *port)
192{
193}
194
195static inline void ipvlan_migrate_l3s_hook(struct net *oldnet,
196 struct net *newnet)
197{
198}
199
200static inline int ipvlan_l3s_init(void)
201{
202 return 0;
203}
204
205static inline void ipvlan_l3s_cleanup(void)
206{
207}
208#endif /* CONFIG_IPVLAN_L3S */
180 209
181static inline bool netif_is_ipvlan_port(const struct net_device *dev) 210static inline bool netif_is_ipvlan_port(const struct net_device *dev)
182{ 211{
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index 1a8132eb2a3e..e0f5bc82b10c 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -138,7 +138,7 @@ bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6)
138 return ret; 138 return ret;
139} 139}
140 140
141static void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type) 141void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type)
142{ 142{
143 void *lyr3h = NULL; 143 void *lyr3h = NULL;
144 144
@@ -355,9 +355,8 @@ out:
355 return ret; 355 return ret;
356} 356}
357 357
358static struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, 358struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h,
359 void *lyr3h, int addr_type, 359 int addr_type, bool use_dest)
360 bool use_dest)
361{ 360{
362 struct ipvl_addr *addr = NULL; 361 struct ipvl_addr *addr = NULL;
363 362
@@ -647,7 +646,9 @@ int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
647 case IPVLAN_MODE_L2: 646 case IPVLAN_MODE_L2:
648 return ipvlan_xmit_mode_l2(skb, dev); 647 return ipvlan_xmit_mode_l2(skb, dev);
649 case IPVLAN_MODE_L3: 648 case IPVLAN_MODE_L3:
649#ifdef CONFIG_IPVLAN_L3S
650 case IPVLAN_MODE_L3S: 650 case IPVLAN_MODE_L3S:
651#endif
651 return ipvlan_xmit_mode_l3(skb, dev); 652 return ipvlan_xmit_mode_l3(skb, dev);
652 } 653 }
653 654
@@ -743,8 +744,10 @@ rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb)
743 return ipvlan_handle_mode_l2(pskb, port); 744 return ipvlan_handle_mode_l2(pskb, port);
744 case IPVLAN_MODE_L3: 745 case IPVLAN_MODE_L3:
745 return ipvlan_handle_mode_l3(pskb, port); 746 return ipvlan_handle_mode_l3(pskb, port);
747#ifdef CONFIG_IPVLAN_L3S
746 case IPVLAN_MODE_L3S: 748 case IPVLAN_MODE_L3S:
747 return RX_HANDLER_PASS; 749 return RX_HANDLER_PASS;
750#endif
748 } 751 }
749 752
750 /* Should not reach here */ 753 /* Should not reach here */
@@ -753,97 +756,3 @@ rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb)
753 kfree_skb(skb); 756 kfree_skb(skb);
754 return RX_HANDLER_CONSUMED; 757 return RX_HANDLER_CONSUMED;
755} 758}
756
757static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb,
758 struct net_device *dev)
759{
760 struct ipvl_addr *addr = NULL;
761 struct ipvl_port *port;
762 void *lyr3h;
763 int addr_type;
764
765 if (!dev || !netif_is_ipvlan_port(dev))
766 goto out;
767
768 port = ipvlan_port_get_rcu(dev);
769 if (!port || port->mode != IPVLAN_MODE_L3S)
770 goto out;
771
772 lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type);
773 if (!lyr3h)
774 goto out;
775
776 addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
777out:
778 return addr;
779}
780
781struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, struct sk_buff *skb,
782 u16 proto)
783{
784 struct ipvl_addr *addr;
785 struct net_device *sdev;
786
787 addr = ipvlan_skb_to_addr(skb, dev);
788 if (!addr)
789 goto out;
790
791 sdev = addr->master->dev;
792 switch (proto) {
793 case AF_INET:
794 {
795 int err;
796 struct iphdr *ip4h = ip_hdr(skb);
797
798 err = ip_route_input_noref(skb, ip4h->daddr, ip4h->saddr,
799 ip4h->tos, sdev);
800 if (unlikely(err))
801 goto out;
802 break;
803 }
804#if IS_ENABLED(CONFIG_IPV6)
805 case AF_INET6:
806 {
807 struct dst_entry *dst;
808 struct ipv6hdr *ip6h = ipv6_hdr(skb);
809 int flags = RT6_LOOKUP_F_HAS_SADDR;
810 struct flowi6 fl6 = {
811 .flowi6_iif = sdev->ifindex,
812 .daddr = ip6h->daddr,
813 .saddr = ip6h->saddr,
814 .flowlabel = ip6_flowinfo(ip6h),
815 .flowi6_mark = skb->mark,
816 .flowi6_proto = ip6h->nexthdr,
817 };
818
819 skb_dst_drop(skb);
820 dst = ip6_route_input_lookup(dev_net(sdev), sdev, &fl6,
821 skb, flags);
822 skb_dst_set(skb, dst);
823 break;
824 }
825#endif
826 default:
827 break;
828 }
829
830out:
831 return skb;
832}
833
834unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb,
835 const struct nf_hook_state *state)
836{
837 struct ipvl_addr *addr;
838 unsigned int len;
839
840 addr = ipvlan_skb_to_addr(skb, skb->dev);
841 if (!addr)
842 goto out;
843
844 skb->dev = addr->master->dev;
845 len = skb->len + ETH_HLEN;
846 ipvlan_count_rx(addr->master, len, true, false);
847out:
848 return NF_ACCEPT;
849}
diff --git a/drivers/net/ipvlan/ipvlan_l3s.c b/drivers/net/ipvlan/ipvlan_l3s.c
new file mode 100644
index 000000000000..9a2f24078a54
--- /dev/null
+++ b/drivers/net/ipvlan/ipvlan_l3s.c
@@ -0,0 +1,227 @@
1/* Copyright (c) 2014 Mahesh Bandewar <maheshb@google.com>
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License as
5 * published by the Free Software Foundation; either version 2 of
6 * the License, or (at your option) any later version.
7 */
8
9#include "ipvlan.h"
10
11static unsigned int ipvlan_netid __read_mostly;
12
13struct ipvlan_netns {
14 unsigned int ipvl_nf_hook_refcnt;
15};
16
17static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb,
18 struct net_device *dev)
19{
20 struct ipvl_addr *addr = NULL;
21 struct ipvl_port *port;
22 int addr_type;
23 void *lyr3h;
24
25 if (!dev || !netif_is_ipvlan_port(dev))
26 goto out;
27
28 port = ipvlan_port_get_rcu(dev);
29 if (!port || port->mode != IPVLAN_MODE_L3S)
30 goto out;
31
32 lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type);
33 if (!lyr3h)
34 goto out;
35
36 addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
37out:
38 return addr;
39}
40
41static struct sk_buff *ipvlan_l3_rcv(struct net_device *dev,
42 struct sk_buff *skb, u16 proto)
43{
44 struct ipvl_addr *addr;
45 struct net_device *sdev;
46
47 addr = ipvlan_skb_to_addr(skb, dev);
48 if (!addr)
49 goto out;
50
51 sdev = addr->master->dev;
52 switch (proto) {
53 case AF_INET:
54 {
55 struct iphdr *ip4h = ip_hdr(skb);
56 int err;
57
58 err = ip_route_input_noref(skb, ip4h->daddr, ip4h->saddr,
59 ip4h->tos, sdev);
60 if (unlikely(err))
61 goto out;
62 break;
63 }
64#if IS_ENABLED(CONFIG_IPV6)
65 case AF_INET6:
66 {
67 struct dst_entry *dst;
68 struct ipv6hdr *ip6h = ipv6_hdr(skb);
69 int flags = RT6_LOOKUP_F_HAS_SADDR;
70 struct flowi6 fl6 = {
71 .flowi6_iif = sdev->ifindex,
72 .daddr = ip6h->daddr,
73 .saddr = ip6h->saddr,
74 .flowlabel = ip6_flowinfo(ip6h),
75 .flowi6_mark = skb->mark,
76 .flowi6_proto = ip6h->nexthdr,
77 };
78
79 skb_dst_drop(skb);
80 dst = ip6_route_input_lookup(dev_net(sdev), sdev, &fl6,
81 skb, flags);
82 skb_dst_set(skb, dst);
83 break;
84 }
85#endif
86 default:
87 break;
88 }
89out:
90 return skb;
91}
92
93static const struct l3mdev_ops ipvl_l3mdev_ops = {
94 .l3mdev_l3_rcv = ipvlan_l3_rcv,
95};
96
97static unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb,
98 const struct nf_hook_state *state)
99{
100 struct ipvl_addr *addr;
101 unsigned int len;
102
103 addr = ipvlan_skb_to_addr(skb, skb->dev);
104 if (!addr)
105 goto out;
106
107 skb->dev = addr->master->dev;
108 len = skb->len + ETH_HLEN;
109 ipvlan_count_rx(addr->master, len, true, false);
110out:
111 return NF_ACCEPT;
112}
113
114static const struct nf_hook_ops ipvl_nfops[] = {
115 {
116 .hook = ipvlan_nf_input,
117 .pf = NFPROTO_IPV4,
118 .hooknum = NF_INET_LOCAL_IN,
119 .priority = INT_MAX,
120 },
121#if IS_ENABLED(CONFIG_IPV6)
122 {
123 .hook = ipvlan_nf_input,
124 .pf = NFPROTO_IPV6,
125 .hooknum = NF_INET_LOCAL_IN,
126 .priority = INT_MAX,
127 },
128#endif
129};
130
131static int ipvlan_register_nf_hook(struct net *net)
132{
133 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
134 int err = 0;
135
136 if (!vnet->ipvl_nf_hook_refcnt) {
137 err = nf_register_net_hooks(net, ipvl_nfops,
138 ARRAY_SIZE(ipvl_nfops));
139 if (!err)
140 vnet->ipvl_nf_hook_refcnt = 1;
141 } else {
142 vnet->ipvl_nf_hook_refcnt++;
143 }
144
145 return err;
146}
147
148static void ipvlan_unregister_nf_hook(struct net *net)
149{
150 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
151
152 if (WARN_ON(!vnet->ipvl_nf_hook_refcnt))
153 return;
154
155 vnet->ipvl_nf_hook_refcnt--;
156 if (!vnet->ipvl_nf_hook_refcnt)
157 nf_unregister_net_hooks(net, ipvl_nfops,
158 ARRAY_SIZE(ipvl_nfops));
159}
160
161void ipvlan_migrate_l3s_hook(struct net *oldnet, struct net *newnet)
162{
163 struct ipvlan_netns *old_vnet;
164
165 ASSERT_RTNL();
166
167 old_vnet = net_generic(oldnet, ipvlan_netid);
168 if (!old_vnet->ipvl_nf_hook_refcnt)
169 return;
170
171 ipvlan_register_nf_hook(newnet);
172 ipvlan_unregister_nf_hook(oldnet);
173}
174
175static void ipvlan_ns_exit(struct net *net)
176{
177 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
178
179 if (WARN_ON_ONCE(vnet->ipvl_nf_hook_refcnt)) {
180 vnet->ipvl_nf_hook_refcnt = 0;
181 nf_unregister_net_hooks(net, ipvl_nfops,
182 ARRAY_SIZE(ipvl_nfops));
183 }
184}
185
186static struct pernet_operations ipvlan_net_ops = {
187 .id = &ipvlan_netid,
188 .size = sizeof(struct ipvlan_netns),
189 .exit = ipvlan_ns_exit,
190};
191
192int ipvlan_l3s_init(void)
193{
194 return register_pernet_subsys(&ipvlan_net_ops);
195}
196
197void ipvlan_l3s_cleanup(void)
198{
199 unregister_pernet_subsys(&ipvlan_net_ops);
200}
201
202int ipvlan_l3s_register(struct ipvl_port *port)
203{
204 struct net_device *dev = port->dev;
205 int ret;
206
207 ASSERT_RTNL();
208
209 ret = ipvlan_register_nf_hook(read_pnet(&port->pnet));
210 if (!ret) {
211 dev->l3mdev_ops = &ipvl_l3mdev_ops;
212 dev->priv_flags |= IFF_L3MDEV_MASTER;
213 }
214
215 return ret;
216}
217
218void ipvlan_l3s_unregister(struct ipvl_port *port)
219{
220 struct net_device *dev = port->dev;
221
222 ASSERT_RTNL();
223
224 dev->priv_flags &= ~IFF_L3MDEV_MASTER;
225 ipvlan_unregister_nf_hook(read_pnet(&port->pnet));
226 dev->l3mdev_ops = NULL;
227}
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 19bdde60680c..8ec73d973079 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -9,73 +9,10 @@
9 9
10#include "ipvlan.h" 10#include "ipvlan.h"
11 11
12static unsigned int ipvlan_netid __read_mostly;
13
14struct ipvlan_netns {
15 unsigned int ipvl_nf_hook_refcnt;
16};
17
18static const struct nf_hook_ops ipvl_nfops[] = {
19 {
20 .hook = ipvlan_nf_input,
21 .pf = NFPROTO_IPV4,
22 .hooknum = NF_INET_LOCAL_IN,
23 .priority = INT_MAX,
24 },
25#if IS_ENABLED(CONFIG_IPV6)
26 {
27 .hook = ipvlan_nf_input,
28 .pf = NFPROTO_IPV6,
29 .hooknum = NF_INET_LOCAL_IN,
30 .priority = INT_MAX,
31 },
32#endif
33};
34
35static const struct l3mdev_ops ipvl_l3mdev_ops = {
36 .l3mdev_l3_rcv = ipvlan_l3_rcv,
37};
38
39static void ipvlan_adjust_mtu(struct ipvl_dev *ipvlan, struct net_device *dev)
40{
41 ipvlan->dev->mtu = dev->mtu;
42}
43
44static int ipvlan_register_nf_hook(struct net *net)
45{
46 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
47 int err = 0;
48
49 if (!vnet->ipvl_nf_hook_refcnt) {
50 err = nf_register_net_hooks(net, ipvl_nfops,
51 ARRAY_SIZE(ipvl_nfops));
52 if (!err)
53 vnet->ipvl_nf_hook_refcnt = 1;
54 } else {
55 vnet->ipvl_nf_hook_refcnt++;
56 }
57
58 return err;
59}
60
61static void ipvlan_unregister_nf_hook(struct net *net)
62{
63 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
64
65 if (WARN_ON(!vnet->ipvl_nf_hook_refcnt))
66 return;
67
68 vnet->ipvl_nf_hook_refcnt--;
69 if (!vnet->ipvl_nf_hook_refcnt)
70 nf_unregister_net_hooks(net, ipvl_nfops,
71 ARRAY_SIZE(ipvl_nfops));
72}
73
74static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval, 12static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval,
75 struct netlink_ext_ack *extack) 13 struct netlink_ext_ack *extack)
76{ 14{
77 struct ipvl_dev *ipvlan; 15 struct ipvl_dev *ipvlan;
78 struct net_device *mdev = port->dev;
79 unsigned int flags; 16 unsigned int flags;
80 int err; 17 int err;
81 18
@@ -97,17 +34,12 @@ static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval,
97 } 34 }
98 if (nval == IPVLAN_MODE_L3S) { 35 if (nval == IPVLAN_MODE_L3S) {
99 /* New mode is L3S */ 36 /* New mode is L3S */
100 err = ipvlan_register_nf_hook(read_pnet(&port->pnet)); 37 err = ipvlan_l3s_register(port);
101 if (!err) { 38 if (err)
102 mdev->l3mdev_ops = &ipvl_l3mdev_ops;
103 mdev->priv_flags |= IFF_L3MDEV_MASTER;
104 } else
105 goto fail; 39 goto fail;
106 } else if (port->mode == IPVLAN_MODE_L3S) { 40 } else if (port->mode == IPVLAN_MODE_L3S) {
107 /* Old mode was L3S */ 41 /* Old mode was L3S */
108 mdev->priv_flags &= ~IFF_L3MDEV_MASTER; 42 ipvlan_l3s_unregister(port);
109 ipvlan_unregister_nf_hook(read_pnet(&port->pnet));
110 mdev->l3mdev_ops = NULL;
111 } 43 }
112 port->mode = nval; 44 port->mode = nval;
113 } 45 }
@@ -166,11 +98,8 @@ static void ipvlan_port_destroy(struct net_device *dev)
166 struct ipvl_port *port = ipvlan_port_get_rtnl(dev); 98 struct ipvl_port *port = ipvlan_port_get_rtnl(dev);
167 struct sk_buff *skb; 99 struct sk_buff *skb;
168 100
169 if (port->mode == IPVLAN_MODE_L3S) { 101 if (port->mode == IPVLAN_MODE_L3S)
170 dev->priv_flags &= ~IFF_L3MDEV_MASTER; 102 ipvlan_l3s_unregister(port);
171 ipvlan_unregister_nf_hook(dev_net(dev));
172 dev->l3mdev_ops = NULL;
173 }
174 netdev_rx_handler_unregister(dev); 103 netdev_rx_handler_unregister(dev);
175 cancel_work_sync(&port->wq); 104 cancel_work_sync(&port->wq);
176 while ((skb = __skb_dequeue(&port->backlog)) != NULL) { 105 while ((skb = __skb_dequeue(&port->backlog)) != NULL) {
@@ -446,6 +375,11 @@ static const struct header_ops ipvlan_header_ops = {
446 .cache_update = eth_header_cache_update, 375 .cache_update = eth_header_cache_update,
447}; 376};
448 377
378static void ipvlan_adjust_mtu(struct ipvl_dev *ipvlan, struct net_device *dev)
379{
380 ipvlan->dev->mtu = dev->mtu;
381}
382
449static bool netif_is_ipvlan(const struct net_device *dev) 383static bool netif_is_ipvlan(const struct net_device *dev)
450{ 384{
451 /* both ipvlan and ipvtap devices use the same netdev_ops */ 385 /* both ipvlan and ipvtap devices use the same netdev_ops */
@@ -781,7 +715,6 @@ static int ipvlan_device_event(struct notifier_block *unused,
781 715
782 case NETDEV_REGISTER: { 716 case NETDEV_REGISTER: {
783 struct net *oldnet, *newnet = dev_net(dev); 717 struct net *oldnet, *newnet = dev_net(dev);
784 struct ipvlan_netns *old_vnet;
785 718
786 oldnet = read_pnet(&port->pnet); 719 oldnet = read_pnet(&port->pnet);
787 if (net_eq(newnet, oldnet)) 720 if (net_eq(newnet, oldnet))
@@ -789,12 +722,7 @@ static int ipvlan_device_event(struct notifier_block *unused,
789 722
790 write_pnet(&port->pnet, newnet); 723 write_pnet(&port->pnet, newnet);
791 724
792 old_vnet = net_generic(oldnet, ipvlan_netid); 725 ipvlan_migrate_l3s_hook(oldnet, newnet);
793 if (!old_vnet->ipvl_nf_hook_refcnt)
794 break;
795
796 ipvlan_register_nf_hook(newnet);
797 ipvlan_unregister_nf_hook(oldnet);
798 break; 726 break;
799 } 727 }
800 case NETDEV_UNREGISTER: 728 case NETDEV_UNREGISTER:
@@ -1068,23 +996,6 @@ static struct notifier_block ipvlan_addr6_vtor_notifier_block __read_mostly = {
1068}; 996};
1069#endif 997#endif
1070 998
1071static void ipvlan_ns_exit(struct net *net)
1072{
1073 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
1074
1075 if (WARN_ON_ONCE(vnet->ipvl_nf_hook_refcnt)) {
1076 vnet->ipvl_nf_hook_refcnt = 0;
1077 nf_unregister_net_hooks(net, ipvl_nfops,
1078 ARRAY_SIZE(ipvl_nfops));
1079 }
1080}
1081
1082static struct pernet_operations ipvlan_net_ops = {
1083 .id = &ipvlan_netid,
1084 .size = sizeof(struct ipvlan_netns),
1085 .exit = ipvlan_ns_exit,
1086};
1087
1088static int __init ipvlan_init_module(void) 999static int __init ipvlan_init_module(void)
1089{ 1000{
1090 int err; 1001 int err;
@@ -1099,13 +1010,13 @@ static int __init ipvlan_init_module(void)
1099 register_inetaddr_notifier(&ipvlan_addr4_notifier_block); 1010 register_inetaddr_notifier(&ipvlan_addr4_notifier_block);
1100 register_inetaddr_validator_notifier(&ipvlan_addr4_vtor_notifier_block); 1011 register_inetaddr_validator_notifier(&ipvlan_addr4_vtor_notifier_block);
1101 1012
1102 err = register_pernet_subsys(&ipvlan_net_ops); 1013 err = ipvlan_l3s_init();
1103 if (err < 0) 1014 if (err < 0)
1104 goto error; 1015 goto error;
1105 1016
1106 err = ipvlan_link_register(&ipvlan_link_ops); 1017 err = ipvlan_link_register(&ipvlan_link_ops);
1107 if (err < 0) { 1018 if (err < 0) {
1108 unregister_pernet_subsys(&ipvlan_net_ops); 1019 ipvlan_l3s_cleanup();
1109 goto error; 1020 goto error;
1110 } 1021 }
1111 1022
@@ -1126,7 +1037,7 @@ error:
1126static void __exit ipvlan_cleanup_module(void) 1037static void __exit ipvlan_cleanup_module(void)
1127{ 1038{
1128 rtnl_link_unregister(&ipvlan_link_ops); 1039 rtnl_link_unregister(&ipvlan_link_ops);
1129 unregister_pernet_subsys(&ipvlan_net_ops); 1040 ipvlan_l3s_cleanup();
1130 unregister_netdevice_notifier(&ipvlan_notifier_block); 1041 unregister_netdevice_notifier(&ipvlan_notifier_block);
1131 unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block); 1042 unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block);
1132 unregister_inetaddr_validator_notifier( 1043 unregister_inetaddr_validator_notifier(