summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2005-11-08 09:37:56 -0800
committerDavid S. Miller <davem@davemloft.net>2005-11-08 09:37:56 -0800
commit971f359ddcb2e7a0d577479c7561bda407febe1b (patch)
tree9bca1b66b368bd1f6aa7d3a2e58f3cbd2658306c /include
parentf093182d313edde9b1f86dbdaf40ba4da2dbd0e7 (diff)
[IPV6]: Put addr_diff() into common header for future use.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r--include/net/ipv6.h48
1 files changed, 48 insertions, 0 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 65ec86678a0..98661fa4fc7 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -341,6 +341,54 @@ static inline int ipv6_addr_any(const struct in6_addr *a)
}
/*
+ * find the first different bit between two addresses
+ * length of address must be a multiple of 32bits
+ */
+static inline int __ipv6_addr_diff(const void *token1, const void *token2, int addrlen)
+{
+ const __u32 *a1 = token1, *a2 = token2;
+ int i;
+
+ addrlen >>= 2;
+
+ for (i = 0; i < addrlen; i++) {
+ __u32 xb = a1[i] ^ a2[i];
+ if (xb) {
+ int j = 31;
+
+ xb = ntohl(xb);
+ while ((xb & (1 << j)) == 0)
+ j--;
+
+ return (i * 32 + 31 - j);
+ }
+ }
+
+ /*
+ * we should *never* get to this point since that
+ * would mean the addrs are equal
+ *
+ * However, we do get to it 8) And exacly, when
+ * addresses are equal 8)
+ *
+ * ip route add 1111::/128 via ...
+ * ip route add 1111::/64 via ...
+ * and we are here.
+ *
+ * Ideally, this function should stop comparison
+ * at prefix length. It does not, but it is still OK,
+ * if returned value is greater than prefix length.
+ * --ANK (980803)
+ */
+ return (addrlen << 5);
+}
+
+static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_addr *a2)
+{
+ return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
+}
+
+/*
* Prototypes exported by ipv6
*/