]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
ipvlan: drop ipv6 dependency
authorMatteo Croce <mcroce@redhat.com>
Fri, 22 Jun 2018 17:26:00 +0000 (19:26 +0200)
committerStefan Bader <stefan.bader@canonical.com>
Tue, 14 Aug 2018 10:30:43 +0000 (12:30 +0200)
BugLink: http://bugs.launchpad.net/bugs/1776927
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 <mcroce@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
(cherry picked from commit 94333fac44d1da19ebdf41704780c1af3cabea61)
Signed-off-by: Joseph Salisbury <joseph.salisbury@canonical.com>
Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
drivers/net/Kconfig
drivers/net/ipvlan/ipvlan_core.c
drivers/net/ipvlan/ipvlan_main.c

index 0936da592e12af4b7ed84b57c867e0555f56978c..6ee6f0bb90664ff1d13e7bd1d4facb866d015459 100644 (file)
@@ -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---
index e92f31a53339a9d13893f29758d86da6735f696c..6c8d28cfe8c3a2908d56f46d8a76c0c9be50781e 100644 (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))
-                       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;
        }
@@ -341,14 +357,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;
 
@@ -360,14 +380,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;
@@ -381,6 +406,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;
@@ -424,6 +451,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);
@@ -460,6 +488,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)
 {
@@ -772,6 +806,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;
@@ -791,6 +826,7 @@ struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, struct sk_buff *skb,
                skb_dst_set(skb, dst);
                break;
        }
+#endif
        default:
                break;
        }
index 30cb803e2fe5b31d8fc056b88754e7996eee4955..28cf28fabb97bbd7619a1661c918ac5faa114379 100644 (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)) {
@@ -906,6 +924,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)
 {
@@ -992,6 +1011,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,
 };
@@ -999,6 +1019,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)
 {
@@ -1023,9 +1044,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);
 
@@ -1044,9 +1067,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;
 }
@@ -1059,9 +1084,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);