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