summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-02-21 17:51:04 -0500
committerDavid S. Miller <davem@davemloft.net>2018-02-21 17:51:04 -0500
commit0ea5f58ebc83edfd13b0b254fbbc4ac191351c18 (patch)
tree1205e2f0a7b0deb369e661f8c942d7f0850865bc
parentcac56209a66ea3b0be67aa2966b2c628b944da1e (diff)
parent218798f407875e8a1ce9164f5e0c50f02105dc64 (diff)
downloadlinux-stable-0ea5f58ebc83edfd13b0b254fbbc4ac191351c18.tar.gz
linux-stable-0ea5f58ebc83edfd13b0b254fbbc4ac191351c18.tar.bz2
linux-stable-0ea5f58ebc83edfd13b0b254fbbc4ac191351c18.zip
Merge branch 'ipvlan-deps'
Matteo Croce says: ==================== Remove IPVlan module dependencies on IPv6 and L3 Master dev The IPVlan module currently depends on IPv6 and L3 Master dev. Refactor the code to allow building IPVlan module regardless of the value of CONFIG_IPV6 as done in other drivers like VxLAN or GENEVE. Also change the CONFIG_NET_L3_MASTER_DEV dependency into a select, since compiling L3 Master device alone has little sense. $ grep -wE 'CONFIG_(IPV6|IPVLAN)' .config CONFIG_IPV6=y CONFIG_IPVLAN=m $ ll drivers/net/ipvlan/ipvlan.ko 48K drivers/net/ipvlan/ipvlan.ko $ grep -wE 'CONFIG_(IPV6|IPVLAN)' .config CONFIG_IPVLAN=m $ ll drivers/net/ipvlan/ipvlan.ko 44K drivers/net/ipvlan/ipvlan.ko ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/Kconfig3
-rw-r--r--drivers/net/ipvlan/ipvlan_core.c72
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c48
3 files changed, 86 insertions, 37 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 944ec3c9282c..d88b78a17440 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -149,9 +149,8 @@ config MACVTAP
config IPVLAN
tristate "IP-VLAN support"
depends on INET
- depends on IPV6
depends on NETFILTER
- depends on NET_L3_MASTER_DEV
+ select 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/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index c1f008fe4e1d..1b5dc200b573 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -35,6 +35,7 @@ void ipvlan_count_rx(const struct ipvl_dev *ipvlan,
}
EXPORT_SYMBOL_GPL(ipvlan_count_rx);
+#if IS_ENABLED(CONFIG_IPV6)
static u8 ipvlan_get_v6_hash(const void *iaddr)
{
const struct in6_addr *ip6_addr = iaddr;
@@ -42,6 +43,12 @@ static u8 ipvlan_get_v6_hash(const void *iaddr)
return __ipv6_addr_jhash(ip6_addr, ipvlan_jhash_secret) &
IPVLAN_HASH_MASK;
}
+#else
+static u8 ipvlan_get_v6_hash(const void *iaddr)
+{
+ return 0;
+}
+#endif
static u8 ipvlan_get_v4_hash(const void *iaddr)
{
@@ -51,6 +58,23 @@ static u8 ipvlan_get_v4_hash(const void *iaddr)
IPVLAN_HASH_MASK;
}
+static bool addr_equal(bool is_v6, struct ipvl_addr *addr, const void *iaddr)
+{
+ if (!is_v6 && addr->atype == IPVL_IPV4) {
+ struct in_addr *i4addr = (struct in_addr *)iaddr;
+
+ return addr->ip4addr.s_addr == i4addr->s_addr;
+#if IS_ENABLED(CONFIG_IPV6)
+ } else if (is_v6 && addr->atype == IPVL_IPV6) {
+ struct in6_addr *i6addr = (struct in6_addr *)iaddr;
+
+ return ipv6_addr_equal(&addr->ip6addr, i6addr);
+#endif
+ }
+
+ return false;
+}
+
static struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port,
const void *iaddr, bool is_v6)
{
@@ -59,15 +83,9 @@ static struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port,
hash = is_v6 ? ipvlan_get_v6_hash(iaddr) :
ipvlan_get_v4_hash(iaddr);
- hlist_for_each_entry_rcu(addr, &port->hlhead[hash], hlnode) {
- if (is_v6 && addr->atype == IPVL_IPV6 &&
- ipv6_addr_equal(&addr->ip6addr, iaddr))
- return addr;
- else if (!is_v6 && addr->atype == IPVL_IPV4 &&
- addr->ip4addr.s_addr ==
- ((struct in_addr *)iaddr)->s_addr)
+ hlist_for_each_entry_rcu(addr, &port->hlhead[hash], hlnode)
+ if (addr_equal(is_v6, addr, iaddr))
return addr;
- }
return NULL;
}
@@ -93,13 +111,9 @@ struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan,
{
struct ipvl_addr *addr;
- list_for_each_entry(addr, &ipvlan->addrs, anode) {
- if ((is_v6 && addr->atype == IPVL_IPV6 &&
- ipv6_addr_equal(&addr->ip6addr, iaddr)) ||
- (!is_v6 && addr->atype == IPVL_IPV4 &&
- addr->ip4addr.s_addr == ((struct in_addr *)iaddr)->s_addr))
+ list_for_each_entry(addr, &ipvlan->addrs, anode)
+ if (addr_equal(is_v6, addr, iaddr))
return addr;
- }
return NULL;
}
@@ -150,6 +164,7 @@ static void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int
lyr3h = ip4h;
break;
}
+#if IS_ENABLED(CONFIG_IPV6)
case htons(ETH_P_IPV6): {
struct ipv6hdr *ip6h;
@@ -188,6 +203,7 @@ static void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int
}
break;
}
+#endif
default:
return NULL;
}
@@ -337,14 +353,18 @@ static struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port,
{
struct ipvl_addr *addr = NULL;
- if (addr_type == IPVL_IPV6) {
+ switch (addr_type) {
+#if IS_ENABLED(CONFIG_IPV6)
+ case IPVL_IPV6: {
struct ipv6hdr *ip6h;
struct in6_addr *i6addr;
ip6h = (struct ipv6hdr *)lyr3h;
i6addr = use_dest ? &ip6h->daddr : &ip6h->saddr;
addr = ipvlan_ht_addr_lookup(port, i6addr, true);
- } else if (addr_type == IPVL_ICMPV6) {
+ break;
+ }
+ case IPVL_ICMPV6: {
struct nd_msg *ndmh;
struct in6_addr *i6addr;
@@ -356,14 +376,19 @@ static struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port,
i6addr = &ndmh->target;
addr = ipvlan_ht_addr_lookup(port, i6addr, true);
}
- } else if (addr_type == IPVL_IPV4) {
+ break;
+ }
+#endif
+ case IPVL_IPV4: {
struct iphdr *ip4h;
__be32 *i4addr;
ip4h = (struct iphdr *)lyr3h;
i4addr = use_dest ? &ip4h->daddr : &ip4h->saddr;
addr = ipvlan_ht_addr_lookup(port, i4addr, false);
- } else if (addr_type == IPVL_ARP) {
+ break;
+ }
+ case IPVL_ARP: {
struct arphdr *arph;
unsigned char *arp_ptr;
__be32 dip;
@@ -377,6 +402,8 @@ static struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port,
memcpy(&dip, arp_ptr, 4);
addr = ipvlan_ht_addr_lookup(port, &dip, false);
+ break;
+ }
}
return addr;
@@ -420,6 +447,7 @@ out:
return ret;
}
+#if IS_ENABLED(CONFIG_IPV6)
static int ipvlan_process_v6_outbound(struct sk_buff *skb)
{
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
@@ -456,6 +484,12 @@ err:
out:
return ret;
}
+#else
+static int ipvlan_process_v6_outbound(struct sk_buff *skb)
+{
+ return NET_XMIT_DROP;
+}
+#endif
static int ipvlan_process_outbound(struct sk_buff *skb)
{
@@ -759,6 +793,7 @@ struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, struct sk_buff *skb,
goto out;
break;
}
+#if IS_ENABLED(CONFIG_IPV6)
case AF_INET6:
{
struct dst_entry *dst;
@@ -778,6 +813,7 @@ struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, struct sk_buff *skb,
skb_dst_set(skb, dst);
break;
}
+#endif
default:
break;
}
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 2469df118fbf..67c91ceda979 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -22,12 +22,14 @@ static const struct nf_hook_ops ipvl_nfops[] = {
.hooknum = NF_INET_LOCAL_IN,
.priority = INT_MAX,
},
+#if IS_ENABLED(CONFIG_IPV6)
{
.hook = ipvlan_nf_input,
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_LOCAL_IN,
.priority = INT_MAX,
},
+#endif
};
static const struct l3mdev_ops ipvl_l3mdev_ops = {
@@ -800,12 +802,14 @@ static int ipvlan_add_addr(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6)
return -ENOMEM;
addr->master = ipvlan;
- if (is_v6) {
- memcpy(&addr->ip6addr, iaddr, sizeof(struct in6_addr));
- addr->atype = IPVL_IPV6;
- } else {
+ if (!is_v6) {
memcpy(&addr->ip4addr, iaddr, sizeof(struct in_addr));
addr->atype = IPVL_IPV4;
+#if IS_ENABLED(CONFIG_IPV6)
+ } else {
+ memcpy(&addr->ip6addr, iaddr, sizeof(struct in6_addr));
+ addr->atype = IPVL_IPV6;
+#endif
}
list_add_tail(&addr->anode, &ipvlan->addrs);
@@ -833,6 +837,20 @@ static void ipvlan_del_addr(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6)
return;
}
+static bool ipvlan_is_valid_dev(const struct net_device *dev)
+{
+ struct ipvl_dev *ipvlan = netdev_priv(dev);
+
+ if (!netif_is_ipvlan(dev))
+ return false;
+
+ if (!ipvlan || !ipvlan->port)
+ return false;
+
+ return true;
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
static int ipvlan_add_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr)
{
if (ipvlan_addr_busy(ipvlan->port, ip6_addr, true)) {
@@ -850,19 +868,6 @@ static void ipvlan_del_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr)
return ipvlan_del_addr(ipvlan, ip6_addr, true);
}
-static bool ipvlan_is_valid_dev(const struct net_device *dev)
-{
- struct ipvl_dev *ipvlan = netdev_priv(dev);
-
- if (!netif_is_ipvlan(dev))
- return false;
-
- if (!ipvlan || !ipvlan->port)
- return false;
-
- return true;
-}
-
static int ipvlan_addr6_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
@@ -913,6 +918,7 @@ static int ipvlan_addr6_validator_event(struct notifier_block *unused,
return NOTIFY_OK;
}
+#endif
static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr)
{
@@ -993,6 +999,7 @@ static struct notifier_block ipvlan_notifier_block __read_mostly = {
.notifier_call = ipvlan_device_event,
};
+#if IS_ENABLED(CONFIG_IPV6)
static struct notifier_block ipvlan_addr6_notifier_block __read_mostly = {
.notifier_call = ipvlan_addr6_event,
};
@@ -1000,6 +1007,7 @@ static struct notifier_block ipvlan_addr6_notifier_block __read_mostly = {
static struct notifier_block ipvlan_addr6_vtor_notifier_block __read_mostly = {
.notifier_call = ipvlan_addr6_validator_event,
};
+#endif
static void ipvlan_ns_exit(struct net *net)
{
@@ -1024,9 +1032,11 @@ static int __init ipvlan_init_module(void)
ipvlan_init_secret();
register_netdevice_notifier(&ipvlan_notifier_block);
+#if IS_ENABLED(CONFIG_IPV6)
register_inet6addr_notifier(&ipvlan_addr6_notifier_block);
register_inet6addr_validator_notifier(
&ipvlan_addr6_vtor_notifier_block);
+#endif
register_inetaddr_notifier(&ipvlan_addr4_notifier_block);
register_inetaddr_validator_notifier(&ipvlan_addr4_vtor_notifier_block);
@@ -1045,9 +1055,11 @@ error:
unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block);
unregister_inetaddr_validator_notifier(
&ipvlan_addr4_vtor_notifier_block);
+#if IS_ENABLED(CONFIG_IPV6)
unregister_inet6addr_notifier(&ipvlan_addr6_notifier_block);
unregister_inet6addr_validator_notifier(
&ipvlan_addr6_vtor_notifier_block);
+#endif
unregister_netdevice_notifier(&ipvlan_notifier_block);
return err;
}
@@ -1060,9 +1072,11 @@ static void __exit ipvlan_cleanup_module(void)
unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block);
unregister_inetaddr_validator_notifier(
&ipvlan_addr4_vtor_notifier_block);
+#if IS_ENABLED(CONFIG_IPV6)
unregister_inet6addr_notifier(&ipvlan_addr6_notifier_block);
unregister_inet6addr_validator_notifier(
&ipvlan_addr6_vtor_notifier_block);
+#endif
}
module_init(ipvlan_init_module);