rds: rdma: add consumer reject
authorSantosh Shilimkar <santosh.shilimkar@oracle.com>
Wed, 24 Oct 2018 03:09:00 +0000 (23:09 -0400)
committerSantosh Shilimkar <santosh.shilimkar@oracle.com>
Mon, 4 Feb 2019 22:59:11 +0000 (14:59 -0800)
For legacy protocol version incompatibility with non linux RDS,
consumer reject reason being used to convey it to peer. But the
choice of reject reason value as '1' was really poor.

Anyway for interoperability reasons with shipping products,
it needs to be supported. For any future versions, properly
encoded reject reason should to be used.

Reviewed-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
[yanjun.zhu@oracle.com: Adapted original patch with ipv6 changes]
Signed-off-by: Zhu Yanjun <yanjun.zhu@oracle.com>
net/rds/ib_cm.c
net/rds/rdma_transport.c
net/rds/rdma_transport.h

index 0eeae0910f06ff55afe2dc305b48b416d15a8992..a1c3ad380ec81fb43b9900dc4dbd9fff7e37cad1 100644 (file)
@@ -734,8 +734,10 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
 
        /* Check whether the remote protocol version matches ours. */
        version = rds_ib_protocol_compatible(event, isv6);
-       if (!version)
+       if (!version) {
+               err = RDS_RDMA_REJ_INCOMPAT;
                goto out;
+       }
 
        dp = event->param.conn.private_data;
        if (isv6) {
@@ -851,7 +853,7 @@ out:
        if (conn)
                mutex_unlock(&conn->c_cm_lock);
        if (err)
-               rdma_reject(cm_id, NULL, 0);
+               rdma_reject(cm_id, &err, sizeof(int));
        return destroy;
 }
 
index 6b0f57c83a2ada30112fb89b56e6035aac29224e..63cbc6b8560ca1efcc9e639c745f0f6761197fb2 100644 (file)
@@ -51,6 +51,8 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
        struct rds_connection *conn = cm_id->context;
        struct rds_transport *trans;
        int ret = 0;
+       int *err;
+       u8 len;
 
        rdsdebug("conn %p id %p handling event %u (%s)\n", conn, cm_id,
                 event->event, rdma_event_msg(event->event));
@@ -106,8 +108,18 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
                break;
 
        case RDMA_CM_EVENT_REJECTED:
+               if (!conn)
+                       break;
+               err = (int *)rdma_consumer_reject_data(cm_id, event, &len);
+               if (!err || (err && ((*err) == RDS_RDMA_REJ_INCOMPAT))) {
+                       pr_warn("RDS/RDMA: conn <%pI6c, %pI6c> rejected, dropping connection\n",
+                               &conn->c_laddr, &conn->c_faddr);
+                       conn->c_proposed_version = RDS_PROTOCOL_COMPAT_VERSION;
+                       rds_conn_drop(conn);
+               }
                rdsdebug("Connection rejected: %s\n",
                         rdma_reject_msg(cm_id, event->status));
+               break;
                /* FALLTHROUGH */
        case RDMA_CM_EVENT_ADDR_ERROR:
        case RDMA_CM_EVENT_ROUTE_ERROR:
index 200d3134aaae18f5e3c06f66aaf64f5918699236..bfafd4a6d8271008997de9dbef33d5bf3dd193a4 100644 (file)
 
 #define RDS_RDMA_RESOLVE_TIMEOUT_MS     5000
 
+/* Below reject reason is for legacy interoperability issue with non-linux
+ * RDS endpoints where older version incompatibility is conveyed via value 1.
+ * For future version(s), proper encoded reject reason should be be used.
+ */
+#define RDS_RDMA_REJ_INCOMPAT          1
+
 int rds_rdma_conn_connect(struct rds_connection *conn);
 int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
                              struct rdma_cm_event *event);