All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V3 1/2] bonding support for IPv6 transmit hashing
@ 2012-06-30  6:17 John
  2012-06-30  8:05 ` David Miller
  0 siblings, 1 reply; 3+ messages in thread
From: John @ 2012-06-30  6:17 UTC (permalink / raw)
  To: netdev

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index f5a40b9..b138d84 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3345,56 +3345,93 @@ static struct notifier_block bond_netdev_notifier = {
  /*---------------------------- Hashing Policies -----------------------------*/

  /*
+ * Hash for the output device based upon layer 2 data
+ */
+static int bond_xmit_hash_policy_l2(struct sk_buff *skb, int count)
+{
+	struct ethhdr *data = (struct ethhdr *)skb->data;
+
+	if (skb_headlen(skb) >= offsetof(struct ethhdr, h_proto))
+		return (data->h_dest[5] ^ data->h_source[5]) % count;
+
+	return 0;
+}
+
+/*
   * Hash for the output device based upon layer 2 and layer 3 data. If
- * the packet is not IP mimic bond_xmit_hash_policy_l2()
+ * the packet is not IP, fall back on bond_xmit_hash_policy_l2()
   */
  static int bond_xmit_hash_policy_l23(struct sk_buff *skb, int count)
  {
  	struct ethhdr *data = (struct ethhdr *)skb->data;
-	struct iphdr *iph = ip_hdr(skb);
+	struct iphdr *iph;
+	struct ipv6hdr *ipv6h;
+	u32 v6hash;

-	if (skb->protocol == htons(ETH_P_IP)) {
+	if (skb->protocol == htons(ETH_P_IP) &&
+		skb_network_header_len(skb) >= sizeof(struct iphdr)) {
+		iph = ip_hdr(skb);
  		return ((ntohl(iph->saddr ^ iph->daddr) & 0xffff) ^
  			(data->h_dest[5] ^ data->h_source[5])) % count;
-	}
-
-	return (data->h_dest[5] ^ data->h_source[5]) % count;
+	} else if (skb->protocol == htons(ETH_P_IPV6) &&
+		skb_network_header_len(skb) >= sizeof(struct ipv6hdr)) {
+		ipv6h = ipv6_hdr(skb);
+		v6hash =
+			(ipv6h->saddr.s6_addr32[1] ^ ipv6h->daddr.s6_addr32[1]) ^
+			(ipv6h->saddr.s6_addr32[2] ^ ipv6h->daddr.s6_addr32[2]) ^
+			(ipv6h->saddr.s6_addr32[3] ^ ipv6h->daddr.s6_addr32[3]);
+		v6hash = (v6hash >> 16) ^ (v6hash >> 8) ^ v6hash;
+		return (v6hash ^ data->h_dest[5] ^ data->h_source[5]) % count;
+	}
+
+	return bond_xmit_hash_policy_l2(skb, count);
  }

  /*
   * Hash for the output device based upon layer 3 and layer 4 data. If
   * the packet is a frag or not TCP or UDP, just use layer 3 data.  If it is
- * altogether not IP, mimic bond_xmit_hash_policy_l2()
+ * altogether not IP, fall back on bond_xmit_hash_policy_l2()
   */
  static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count)
  {
-	struct ethhdr *data = (struct ethhdr *)skb->data;
-	struct iphdr *iph = ip_hdr(skb);
-	__be16 *layer4hdr = (__be16 *)((u32 *)iph + iph->ihl);
-	int layer4_xor = 0;
+	u32 layer4_xor = 0;
+	struct iphdr *iph;
+	struct ipv6hdr *ipv6h;

  	if (skb->protocol == htons(ETH_P_IP)) {
+		iph = ip_hdr(skb);
  		if (!ip_is_fragment(iph) &&
-		    (iph->protocol == IPPROTO_TCP ||
-		     iph->protocol == IPPROTO_UDP)) {
+			(iph->protocol == IPPROTO_TCP ||
+			iph->protocol == IPPROTO_UDP)) {
+			__be16 *layer4hdr = (__be16 *)((u32 *)iph + iph->ihl);
+			if (iph->ihl * sizeof(u32) + sizeof(__be16) * 2 >
+				skb_headlen(skb) - skb_network_offset(skb))
+				goto short_header;
  			layer4_xor = ntohs((*layer4hdr ^ *(layer4hdr + 1)));
+		} else if (skb_network_header_len(skb) < sizeof(struct iphdr)) {
+			goto short_header;
  		}
-		return (layer4_xor ^
-			((ntohl(iph->saddr ^ iph->daddr)) & 0xffff)) % count;
-
+		return (layer4_xor ^ ((ntohl(iph->saddr ^ iph->daddr)) & 0xffff)) % count;
+	} else if (skb->protocol == htons(ETH_P_IPV6)) {
+		ipv6h = ipv6_hdr(skb);
+		if (ipv6h->nexthdr == IPPROTO_TCP || ipv6h->nexthdr == IPPROTO_UDP) {
+			__be16 *layer4hdrv6 = (__be16 *)((u8 *)ipv6h + sizeof(struct ipv6hdr));
+			if (sizeof(struct ipv6hdr) + sizeof(__be16) * 2 >
+				skb_headlen(skb) - skb_network_offset(skb))
+				goto short_header;
+			layer4_xor = (*layer4hdrv6 ^ *(layer4hdrv6 + 1));
+		} else if (skb_network_header_len(skb) < sizeof(struct ipv6hdr)) {
+			goto short_header;
+		}
+		layer4_xor ^=
+			(ipv6h->saddr.s6_addr32[1] ^ ipv6h->daddr.s6_addr32[1]) ^
+			(ipv6h->saddr.s6_addr32[2] ^ ipv6h->daddr.s6_addr32[2]) ^
+			(ipv6h->saddr.s6_addr32[3] ^ ipv6h->daddr.s6_addr32[3]);
+		return ((layer4_xor >> 16) ^ (layer4_xor >> 8) ^ layer4_xor) % count;
  	}

-	return (data->h_dest[5] ^ data->h_source[5]) % count;
-}
-
-/*
- * Hash for the output device based upon layer 2 data
- */
-static int bond_xmit_hash_policy_l2(struct sk_buff *skb, int count)
-{
-	struct ethhdr *data = (struct ethhdr *)skb->data;
-
-	return (data->h_dest[5] ^ data->h_source[5]) % count;
+short_header:
+	return bond_xmit_hash_policy_l2(skb, count);
  }

  /*-------------------------- Device entry points ----------------------------*/

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH V3 1/2] bonding support for IPv6 transmit hashing
  2012-06-30  6:17 [PATCH V3 1/2] bonding support for IPv6 transmit hashing John
@ 2012-06-30  8:05 ` David Miller
  2012-06-30 19:50   ` John Eaglesham
  0 siblings, 1 reply; 3+ messages in thread
From: David Miller @ 2012-06-30  8:05 UTC (permalink / raw)
  To: linux; +Cc: netdev


If you're going to post multiple patches, give them unique
subject line texts describing what each change does uniquely.
Do not use identical subject lines ever, that is very unhelpful
for the people reading your changes.

From: John <linux@8192.net>
Date: Fri, 29 Jun 2012 23:17:11 -0700

> + skb_network_header_len(skb) >= sizeof(struct ipv6hdr)) {
> +		ipv6h = ipv6_hdr(skb);
> +		v6hash =
> + (ipv6h->saddr.s6_addr32[1] ^ ipv6h->daddr.s6_addr32[1]) ^
> + (ipv6h->saddr.s6_addr32[2] ^ ipv6h->daddr.s6_addr32[2]) ^
> + (ipv6h->saddr.s6_addr32[3] ^ ipv6h->daddr.s6_addr32[3]);
> +		v6hash = (v6hash >> 16) ^ (v6hash >> 8) ^ v6hash;
> + return (v6hash ^ data->h_dest[5] ^ data->h_source[5]) % count;

Either you formatted this terribly, or your email client corrupted
your patches.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH V3 1/2] bonding support for IPv6 transmit hashing
  2012-06-30  8:05 ` David Miller
@ 2012-06-30 19:50   ` John Eaglesham
  0 siblings, 0 replies; 3+ messages in thread
From: John Eaglesham @ 2012-06-30 19:50 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

On 6/30/2012 1:05 AM, David Miller wrote:
>
> If you're going to post multiple patches, give them unique
> subject line texts describing what each change does uniquely.
> Do not use identical subject lines ever, that is very unhelpful
> for the people reading your changes.
>
> From: John <linux@8192.net>
> Date: Fri, 29 Jun 2012 23:17:11 -0700
>
>> + skb_network_header_len(skb) >= sizeof(struct ipv6hdr)) {
>> +		ipv6h = ipv6_hdr(skb);
>> +		v6hash =
>> + (ipv6h->saddr.s6_addr32[1] ^ ipv6h->daddr.s6_addr32[1]) ^
>> + (ipv6h->saddr.s6_addr32[2] ^ ipv6h->daddr.s6_addr32[2]) ^
>> + (ipv6h->saddr.s6_addr32[3] ^ ipv6h->daddr.s6_addr32[3]);
>> +		v6hash = (v6hash >> 16) ^ (v6hash >> 8) ^ v6hash;
>> + return (v6hash ^ data->h_dest[5] ^ data->h_source[5]) % count;
>
> Either you formatted this terribly, or your email client corrupted
> your patches.
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

Thanks for the feedback. It must have been my mail client formatting 
that incorrectly. I will re-submit with useful subject lines in a method 
that preserves the intended indentation.

John

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2012-06-30 19:50 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-30  6:17 [PATCH V3 1/2] bonding support for IPv6 transmit hashing John
2012-06-30  8:05 ` David Miller
2012-06-30 19:50   ` John Eaglesham

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.