rds: Changing IP address internal representation to struct in6_addr
[linux-2.6-microblaze.git] / net / rds / threads.c
index c52861d..e64f9e4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 Oracle.  All rights reserved.
+ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -82,8 +82,8 @@ void rds_connect_path_complete(struct rds_conn_path *cp, int curr)
                return;
        }
 
-       rdsdebug("conn %p for %pI4 to %pI4 complete\n",
-         cp->cp_conn, &cp->cp_conn->c_laddr, &cp->cp_conn->c_faddr);
+       rdsdebug("conn %p for %pI6c to %pI6c complete\n",
+                cp->cp_conn, &cp->cp_conn->c_laddr, &cp->cp_conn->c_faddr);
 
        cp->cp_reconnect_jiffies = 0;
        set_bit(0, &cp->cp_conn->c_map_queued);
@@ -125,13 +125,13 @@ void rds_queue_reconnect(struct rds_conn_path *cp)
        unsigned long rand;
        struct rds_connection *conn = cp->cp_conn;
 
-       rdsdebug("conn %p for %pI4 to %pI4 reconnect jiffies %lu\n",
-         conn, &conn->c_laddr, &conn->c_faddr,
-         cp->cp_reconnect_jiffies);
+       rdsdebug("conn %p for %pI6c to %pI6c reconnect jiffies %lu\n",
+                conn, &conn->c_laddr, &conn->c_faddr,
+                cp->cp_reconnect_jiffies);
 
        /* let peer with smaller addr initiate reconnect, to avoid duels */
        if (conn->c_trans->t_type == RDS_TRANS_TCP &&
-           !IS_CANONICAL(conn->c_laddr, conn->c_faddr))
+           rds_addr_cmp(&conn->c_laddr, &conn->c_faddr) >= 0)
                return;
 
        set_bit(RDS_RECONNECT_PENDING, &cp->cp_flags);
@@ -145,7 +145,7 @@ void rds_queue_reconnect(struct rds_conn_path *cp)
        }
 
        get_random_bytes(&rand, sizeof(rand));
-       rdsdebug("%lu delay %lu ceil conn %p for %pI4 -> %pI4\n",
+       rdsdebug("%lu delay %lu ceil conn %p for %pI6c -> %pI6c\n",
                 rand % cp->cp_reconnect_jiffies, cp->cp_reconnect_jiffies,
                 conn, &conn->c_laddr, &conn->c_faddr);
        rcu_read_lock();
@@ -167,14 +167,14 @@ void rds_connect_worker(struct work_struct *work)
        int ret;
 
        if (cp->cp_index > 0 &&
-           !IS_CANONICAL(cp->cp_conn->c_laddr, cp->cp_conn->c_faddr))
+           rds_addr_cmp(&cp->cp_conn->c_laddr, &cp->cp_conn->c_faddr) >= 0)
                return;
        clear_bit(RDS_RECONNECT_PENDING, &cp->cp_flags);
        ret = rds_conn_path_transition(cp, RDS_CONN_DOWN, RDS_CONN_CONNECTING);
        if (ret) {
                ret = conn->c_trans->conn_path_connect(cp);
-               rdsdebug("conn %p for %pI4 to %pI4 dispatched, ret %d\n",
-                       conn, &conn->c_laddr, &conn->c_faddr, ret);
+               rdsdebug("conn %p for %pI6c to %pI6c dispatched, ret %d\n",
+                        conn, &conn->c_laddr, &conn->c_faddr, ret);
 
                if (ret) {
                        if (rds_conn_path_transition(cp,
@@ -259,3 +259,50 @@ int rds_threads_init(void)
 
        return 0;
 }
+
+/* Compare two IPv6 addresses.  Return 0 if the two addresses are equal.
+ * Return 1 if the first is greater.  Return -1 if the second is greater.
+ */
+int rds_addr_cmp(const struct in6_addr *addr1,
+                const struct in6_addr *addr2)
+{
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
+       const __be64 *a1, *a2;
+       u64 x, y;
+
+       a1 = (__be64 *)addr1;
+       a2 = (__be64 *)addr2;
+
+       if (*a1 != *a2) {
+               if (be64_to_cpu(*a1) < be64_to_cpu(*a2))
+                       return -1;
+               else
+                       return 1;
+       } else {
+               x = be64_to_cpu(*++a1);
+               y = be64_to_cpu(*++a2);
+               if (x < y)
+                       return -1;
+               else if (x > y)
+                       return 1;
+               else
+                       return 0;
+       }
+#else
+       u32 a, b;
+       int i;
+
+       for (i = 0; i < 4; i++) {
+               if (addr1->s6_addr32[i] != addr2->s6_addr32[i]) {
+                       a = ntohl(addr1->s6_addr32[i]);
+                       b = ntohl(addr2->s6_addr32[i]);
+                       if (a < b)
+                               return -1;
+                       else if (a > b)
+                               return 1;
+               }
+       }
+       return 0;
+#endif
+}
+EXPORT_SYMBOL_GPL(rds_addr_cmp);