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>
This commit is contained in:
David S. Miller 2018-02-21 17:51:04 -05:00
commit 0ea5f58ebc
3 changed files with 86 additions and 37 deletions

View File

@ -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)

View File

@ -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))
hlist_for_each_entry_rcu(addr, &port->hlhead[hash], hlnode)
if (addr_equal(is_v6, addr, iaddr))
return addr;
else if (!is_v6 && addr->atype == IPVL_IPV4 &&
addr->ip4addr.s_addr ==
((struct in_addr *)iaddr)->s_addr)
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;
}

View File

@ -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);