From 94333fac44d1da19ebdf41704780c1af3cabea61 Mon Sep 17 00:00:00 2001 From: Matteo Croce Date: Wed, 21 Feb 2018 01:31:13 +0100 Subject: [PATCH] ipvlan: drop ipv6 dependency IPVlan has an hard dependency on IPv6, refactor the ipvlan code to allow compiling it with IPv6 disabled, move duplicate code into addr_equal() and refactor series of if-else into a switch. Signed-off-by: Matteo Croce Signed-off-by: David S. Miller --- drivers/net/Kconfig | 1 - drivers/net/ipvlan/ipvlan_core.c | 72 ++++++++++++++++++++++++-------- drivers/net/ipvlan/ipvlan_main.c | 48 +++++++++++++-------- 3 files changed, 85 insertions(+), 36 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 944ec3c9282c..3234c6618d75 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -149,7 +149,6 @@ config MACVTAP config IPVLAN tristate "IP-VLAN support" depends on INET - depends on IPV6 depends on NETFILTER depends on NET_L3_MASTER_DEV ---help--- 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)) + 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; } 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);