Created
February 12, 2019 13:47
-
-
Save brb/819bd7803941d5c4a2ad426ec095c80a to your computer and use it in GitHub Desktop.
ipvlan-no-netfilter.patch applied to v4.15.18
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig | |
index 0936da592..589d7f3a5 100644 | |
--- a/drivers/net/Kconfig | |
+++ b/drivers/net/Kconfig | |
@@ -145,13 +145,15 @@ config MACVTAP | |
To compile this driver as a module, choose M here: the module | |
will be called macvtap. | |
+config IPVLAN_L3S | |
+ depends on NETFILTER | |
+ def_bool y | |
+ select NET_L3_MASTER_DEV | |
config IPVLAN | |
tristate "IP-VLAN support" | |
depends on INET | |
depends on IPV6 | |
- depends on NETFILTER | |
- depends on NET_L3_MASTER_DEV | |
---help--- | |
This allows one to create virtual devices off of a main interface | |
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 8a2c64dc9..3ee95367a 100644 | |
--- a/drivers/net/ipvlan/Makefile | |
+++ b/drivers/net/ipvlan/Makefile | |
@@ -5,4 +5,5 @@ | |
obj-$(CONFIG_IPVLAN) += ipvlan.o | |
obj-$(CONFIG_IPVTAP) += ipvtap.o | |
-ipvlan-objs := ipvlan_core.o ipvlan_main.o | |
+ipvlan-objs-$(CONFIG_IPVLAN_L3S) += ipvlan_l3s.o | |
+ipvlan-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 5166575a1..48d14d8c5 100644 | |
--- a/drivers/net/ipvlan/ipvlan.h | |
+++ b/drivers/net/ipvlan/ipvlan.h | |
@@ -164,10 +164,9 @@ struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan, | |
const void *iaddr, bool is_v6); | |
bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6); | |
void ipvlan_ht_addr_del(struct ipvl_addr *addr); | |
-struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, struct sk_buff *skb, | |
- u16 proto); | |
-unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb, | |
- const struct nf_hook_state *state); | |
+struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h, | |
+ int addr_type, bool use_dest); | |
+void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type); | |
void ipvlan_count_rx(const struct ipvl_dev *ipvlan, | |
unsigned int len, bool success, bool mcast); | |
int ipvlan_link_new(struct net *src_net, struct net_device *dev, | |
@@ -176,4 +175,35 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev, | |
void ipvlan_link_delete(struct net_device *dev, struct list_head *head); | |
void ipvlan_link_setup(struct net_device *dev); | |
int ipvlan_link_register(struct rtnl_link_ops *ops); | |
+#ifdef CONFIG_IPVLAN_L3S | |
+int ipvlan_l3s_register(struct ipvl_port *port); | |
+void ipvlan_l3s_unregister(struct ipvl_port *port); | |
+void ipvlan_migrate_l3s_hook(struct net *oldnet, struct net *newnet); | |
+int ipvlan_l3s_init(void); | |
+void ipvlan_l3s_cleanup(void); | |
+#else | |
+static inline int ipvlan_l3s_register(struct ipvl_port *port) | |
+{ | |
+ return -ENOTSUPP; | |
+} | |
+ | |
+static inline void ipvlan_l3s_unregister(struct ipvl_port *port) | |
+{ | |
+} | |
+ | |
+static inline void ipvlan_migrate_l3s_hook(struct net *oldnet, | |
+ struct net *newnet) | |
+{ | |
+} | |
+ | |
+static inline int ipvlan_l3s_init(void) | |
+{ | |
+ return 0; | |
+} | |
+ | |
+static inline void ipvlan_l3s_cleanup(void) | |
+{ | |
+} | |
+#endif /* CONFIG_IPVLAN_L3S */ | |
+ | |
#endif /* __IPVLAN_H */ | |
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c | |
index e92f31a53..bb82c9fb3 100644 | |
--- a/drivers/net/ipvlan/ipvlan_core.c | |
+++ b/drivers/net/ipvlan/ipvlan_core.c | |
@@ -116,7 +116,7 @@ bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6) | |
return false; | |
} | |
-static void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type) | |
+void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type) | |
{ | |
void *lyr3h = NULL; | |
@@ -335,9 +335,8 @@ static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff **pskb, | |
return ret; | |
} | |
-static struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, | |
- void *lyr3h, int addr_type, | |
- bool use_dest) | |
+struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h, | |
+ int addr_type, bool use_dest) | |
{ | |
struct ipvl_addr *addr = NULL; | |
@@ -609,7 +608,9 @@ int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev) | |
case IPVLAN_MODE_L2: | |
return ipvlan_xmit_mode_l2(skb, dev); | |
case IPVLAN_MODE_L3: | |
+#ifdef CONFIG_IPVLAN_L3S | |
case IPVLAN_MODE_L3S: | |
+#endif | |
return ipvlan_xmit_mode_l3(skb, dev); | |
} | |
@@ -714,8 +715,10 @@ rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb) | |
return ipvlan_handle_mode_l2(pskb, port); | |
case IPVLAN_MODE_L3: | |
return ipvlan_handle_mode_l3(pskb, port); | |
+#ifdef CONFIG_IPVLAN_L3S | |
case IPVLAN_MODE_L3S: | |
return RX_HANDLER_PASS; | |
+#endif | |
} | |
/* Should not reach here */ | |
@@ -724,94 +727,3 @@ rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb) | |
kfree_skb(skb); | |
return RX_HANDLER_CONSUMED; | |
} | |
- | |
-static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb, | |
- struct net_device *dev) | |
-{ | |
- struct ipvl_addr *addr = NULL; | |
- struct ipvl_port *port; | |
- void *lyr3h; | |
- int addr_type; | |
- | |
- if (!dev || !netif_is_ipvlan_port(dev)) | |
- goto out; | |
- | |
- port = ipvlan_port_get_rcu(dev); | |
- if (!port || port->mode != IPVLAN_MODE_L3S) | |
- goto out; | |
- | |
- lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type); | |
- if (!lyr3h) | |
- goto out; | |
- | |
- addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true); | |
-out: | |
- return addr; | |
-} | |
- | |
-struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, struct sk_buff *skb, | |
- u16 proto) | |
-{ | |
- struct ipvl_addr *addr; | |
- struct net_device *sdev; | |
- | |
- addr = ipvlan_skb_to_addr(skb, dev); | |
- if (!addr) | |
- goto out; | |
- | |
- sdev = addr->master->dev; | |
- switch (proto) { | |
- case AF_INET: | |
- { | |
- int err; | |
- struct iphdr *ip4h = ip_hdr(skb); | |
- | |
- err = ip_route_input_noref(skb, ip4h->daddr, ip4h->saddr, | |
- ip4h->tos, sdev); | |
- if (unlikely(err)) | |
- goto out; | |
- break; | |
- } | |
- case AF_INET6: | |
- { | |
- struct dst_entry *dst; | |
- struct ipv6hdr *ip6h = ipv6_hdr(skb); | |
- int flags = RT6_LOOKUP_F_HAS_SADDR; | |
- struct flowi6 fl6 = { | |
- .flowi6_iif = sdev->ifindex, | |
- .daddr = ip6h->daddr, | |
- .saddr = ip6h->saddr, | |
- .flowlabel = ip6_flowinfo(ip6h), | |
- .flowi6_mark = skb->mark, | |
- .flowi6_proto = ip6h->nexthdr, | |
- }; | |
- | |
- skb_dst_drop(skb); | |
- dst = ip6_route_input_lookup(dev_net(sdev), sdev, &fl6, flags); | |
- skb_dst_set(skb, dst); | |
- break; | |
- } | |
- default: | |
- break; | |
- } | |
- | |
-out: | |
- return skb; | |
-} | |
- | |
-unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb, | |
- const struct nf_hook_state *state) | |
-{ | |
- struct ipvl_addr *addr; | |
- unsigned int len; | |
- | |
- addr = ipvlan_skb_to_addr(skb, skb->dev); | |
- if (!addr) | |
- goto out; | |
- | |
- skb->dev = addr->master->dev; | |
- len = skb->len + ETH_HLEN; | |
- ipvlan_count_rx(addr->master, len, true, false); | |
-out: | |
- return NF_ACCEPT; | |
-} | |
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c | |
index 30cb803e2..66ff90694 100644 | |
--- a/drivers/net/ipvlan/ipvlan_main.c | |
+++ b/drivers/net/ipvlan/ipvlan_main.c | |
@@ -9,87 +9,21 @@ | |
#include "ipvlan.h" | |
-static unsigned int ipvlan_netid __read_mostly; | |
- | |
-struct ipvlan_netns { | |
- unsigned int ipvl_nf_hook_refcnt; | |
-}; | |
- | |
-static const struct nf_hook_ops ipvl_nfops[] = { | |
- { | |
- .hook = ipvlan_nf_input, | |
- .pf = NFPROTO_IPV4, | |
- .hooknum = NF_INET_LOCAL_IN, | |
- .priority = INT_MAX, | |
- }, | |
- { | |
- .hook = ipvlan_nf_input, | |
- .pf = NFPROTO_IPV6, | |
- .hooknum = NF_INET_LOCAL_IN, | |
- .priority = INT_MAX, | |
- }, | |
-}; | |
- | |
-static const struct l3mdev_ops ipvl_l3mdev_ops = { | |
- .l3mdev_l3_rcv = ipvlan_l3_rcv, | |
-}; | |
- | |
-static void ipvlan_adjust_mtu(struct ipvl_dev *ipvlan, struct net_device *dev) | |
-{ | |
- ipvlan->dev->mtu = dev->mtu; | |
-} | |
- | |
-static int ipvlan_register_nf_hook(struct net *net) | |
-{ | |
- struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid); | |
- int err = 0; | |
- | |
- if (!vnet->ipvl_nf_hook_refcnt) { | |
- err = nf_register_net_hooks(net, ipvl_nfops, | |
- ARRAY_SIZE(ipvl_nfops)); | |
- if (!err) | |
- vnet->ipvl_nf_hook_refcnt = 1; | |
- } else { | |
- vnet->ipvl_nf_hook_refcnt++; | |
- } | |
- | |
- return err; | |
-} | |
- | |
-static void ipvlan_unregister_nf_hook(struct net *net) | |
-{ | |
- struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid); | |
- | |
- if (WARN_ON(!vnet->ipvl_nf_hook_refcnt)) | |
- return; | |
- | |
- vnet->ipvl_nf_hook_refcnt--; | |
- if (!vnet->ipvl_nf_hook_refcnt) | |
- nf_unregister_net_hooks(net, ipvl_nfops, | |
- ARRAY_SIZE(ipvl_nfops)); | |
-} | |
- | |
static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval) | |
{ | |
struct ipvl_dev *ipvlan; | |
- struct net_device *mdev = port->dev; | |
int err = 0; | |
ASSERT_RTNL(); | |
if (port->mode != nval) { | |
if (nval == IPVLAN_MODE_L3S) { | |
/* New mode is L3S */ | |
- err = ipvlan_register_nf_hook(read_pnet(&port->pnet)); | |
- if (!err) { | |
- mdev->l3mdev_ops = &ipvl_l3mdev_ops; | |
- mdev->priv_flags |= IFF_L3MDEV_MASTER; | |
- } else | |
+ err = ipvlan_l3s_register(port); | |
+ if (err) | |
return err; | |
} else if (port->mode == IPVLAN_MODE_L3S) { | |
/* Old mode was L3S */ | |
- mdev->priv_flags &= ~IFF_L3MDEV_MASTER; | |
- ipvlan_unregister_nf_hook(read_pnet(&port->pnet)); | |
- mdev->l3mdev_ops = NULL; | |
+ ipvlan_l3s_unregister(port); | |
} | |
list_for_each_entry(ipvlan, &port->ipvlans, pnode) { | |
if (nval == IPVLAN_MODE_L3 || nval == IPVLAN_MODE_L3S) | |
@@ -142,9 +76,7 @@ static void ipvlan_port_destroy(struct net_device *dev) | |
dev->priv_flags &= ~IFF_IPVLAN_MASTER; | |
if (port->mode == IPVLAN_MODE_L3S) { | |
- dev->priv_flags &= ~IFF_L3MDEV_MASTER; | |
- ipvlan_unregister_nf_hook(dev_net(dev)); | |
- dev->l3mdev_ops = NULL; | |
+ ipvlan_l3s_unregister(port); | |
} | |
netdev_rx_handler_unregister(dev); | |
cancel_work_sync(&port->wq); | |
@@ -545,6 +477,11 @@ static int ipvlan_nl_fillinfo(struct sk_buff *skb, | |
return ret; | |
} | |
+static void ipvlan_adjust_mtu(struct ipvl_dev *ipvlan, struct net_device *dev) | |
+{ | |
+ ipvlan->dev->mtu = dev->mtu; | |
+} | |
+ | |
int ipvlan_link_new(struct net *src_net, struct net_device *dev, | |
struct nlattr *tb[], struct nlattr *data[], | |
struct netlink_ext_ack *extack) | |
@@ -738,7 +675,6 @@ static int ipvlan_device_event(struct notifier_block *unused, | |
case NETDEV_REGISTER: { | |
struct net *oldnet, *newnet = dev_net(dev); | |
- struct ipvlan_netns *old_vnet; | |
oldnet = read_pnet(&port->pnet); | |
if (net_eq(newnet, oldnet)) | |
@@ -746,12 +682,7 @@ static int ipvlan_device_event(struct notifier_block *unused, | |
write_pnet(&port->pnet, newnet); | |
- old_vnet = net_generic(oldnet, ipvlan_netid); | |
- if (!old_vnet->ipvl_nf_hook_refcnt) | |
- break; | |
- | |
- ipvlan_register_nf_hook(newnet); | |
- ipvlan_unregister_nf_hook(oldnet); | |
+ ipvlan_migrate_l3s_hook(oldnet, newnet); | |
break; | |
} | |
case NETDEV_UNREGISTER: | |
@@ -1000,23 +931,6 @@ static struct notifier_block ipvlan_addr6_vtor_notifier_block __read_mostly = { | |
.notifier_call = ipvlan_addr6_validator_event, | |
}; | |
-static void ipvlan_ns_exit(struct net *net) | |
-{ | |
- struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid); | |
- | |
- if (WARN_ON_ONCE(vnet->ipvl_nf_hook_refcnt)) { | |
- vnet->ipvl_nf_hook_refcnt = 0; | |
- nf_unregister_net_hooks(net, ipvl_nfops, | |
- ARRAY_SIZE(ipvl_nfops)); | |
- } | |
-} | |
- | |
-static struct pernet_operations ipvlan_net_ops = { | |
- .id = &ipvlan_netid, | |
- .size = sizeof(struct ipvlan_netns), | |
- .exit = ipvlan_ns_exit, | |
-}; | |
- | |
static int __init ipvlan_init_module(void) | |
{ | |
int err; | |
@@ -1029,13 +943,13 @@ static int __init ipvlan_init_module(void) | |
register_inetaddr_notifier(&ipvlan_addr4_notifier_block); | |
register_inetaddr_validator_notifier(&ipvlan_addr4_vtor_notifier_block); | |
- err = register_pernet_subsys(&ipvlan_net_ops); | |
+ err = ipvlan_l3s_init(); | |
if (err < 0) | |
goto error; | |
err = ipvlan_link_register(&ipvlan_link_ops); | |
if (err < 0) { | |
- unregister_pernet_subsys(&ipvlan_net_ops); | |
+ ipvlan_l3s_cleanup(); | |
goto error; | |
} | |
@@ -1054,7 +968,7 @@ static int __init ipvlan_init_module(void) | |
static void __exit ipvlan_cleanup_module(void) | |
{ | |
rtnl_link_unregister(&ipvlan_link_ops); | |
- unregister_pernet_subsys(&ipvlan_net_ops); | |
+ ipvlan_l3s_cleanup(); | |
unregister_netdevice_notifier(&ipvlan_notifier_block); | |
unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block); | |
unregister_inetaddr_validator_notifier( |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment