| .. | .. |
|---|
| 43 | 43 | static struct rdma_cm_id *rds6_rdma_listen_id; |
|---|
| 44 | 44 | #endif |
|---|
| 45 | 45 | |
|---|
| 46 | +/* Per IB specification 7.7.3, service level is a 4-bit field. */ |
|---|
| 47 | +#define TOS_TO_SL(tos) ((tos) & 0xF) |
|---|
| 48 | + |
|---|
| 46 | 49 | static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id, |
|---|
| 47 | 50 | struct rdma_cm_event *event, |
|---|
| 48 | 51 | bool isv6) |
|---|
| .. | .. |
|---|
| 51 | 54 | struct rds_connection *conn = cm_id->context; |
|---|
| 52 | 55 | struct rds_transport *trans; |
|---|
| 53 | 56 | int ret = 0; |
|---|
| 57 | + int *err; |
|---|
| 58 | + u8 len; |
|---|
| 54 | 59 | |
|---|
| 55 | 60 | rdsdebug("conn %p id %p handling event %u (%s)\n", conn, cm_id, |
|---|
| 56 | 61 | event->event, rdma_event_msg(event->event)); |
|---|
| .. | .. |
|---|
| 81 | 86 | break; |
|---|
| 82 | 87 | |
|---|
| 83 | 88 | case RDMA_CM_EVENT_ADDR_RESOLVED: |
|---|
| 84 | | - /* XXX do we need to clean up if this fails? */ |
|---|
| 85 | | - ret = rdma_resolve_route(cm_id, |
|---|
| 89 | + if (conn) { |
|---|
| 90 | + rdma_set_service_type(cm_id, conn->c_tos); |
|---|
| 91 | + /* XXX do we need to clean up if this fails? */ |
|---|
| 92 | + ret = rdma_resolve_route(cm_id, |
|---|
| 86 | 93 | RDS_RDMA_RESOLVE_TIMEOUT_MS); |
|---|
| 94 | + } |
|---|
| 87 | 95 | break; |
|---|
| 88 | 96 | |
|---|
| 89 | 97 | case RDMA_CM_EVENT_ROUTE_RESOLVED: |
|---|
| .. | .. |
|---|
| 94 | 102 | struct rds_ib_connection *ibic; |
|---|
| 95 | 103 | |
|---|
| 96 | 104 | ibic = conn->c_transport_data; |
|---|
| 97 | | - if (ibic && ibic->i_cm_id == cm_id) |
|---|
| 105 | + if (ibic && ibic->i_cm_id == cm_id) { |
|---|
| 106 | + cm_id->route.path_rec[0].sl = |
|---|
| 107 | + TOS_TO_SL(conn->c_tos); |
|---|
| 98 | 108 | ret = trans->cm_initiate_connect(cm_id, isv6); |
|---|
| 99 | | - else |
|---|
| 109 | + } else { |
|---|
| 100 | 110 | rds_conn_drop(conn); |
|---|
| 111 | + } |
|---|
| 101 | 112 | } |
|---|
| 102 | 113 | break; |
|---|
| 103 | 114 | |
|---|
| 104 | 115 | case RDMA_CM_EVENT_ESTABLISHED: |
|---|
| 105 | | - trans->cm_connect_complete(conn, event); |
|---|
| 116 | + if (conn) |
|---|
| 117 | + trans->cm_connect_complete(conn, event); |
|---|
| 106 | 118 | break; |
|---|
| 107 | 119 | |
|---|
| 108 | 120 | case RDMA_CM_EVENT_REJECTED: |
|---|
| 121 | + if (!conn) |
|---|
| 122 | + break; |
|---|
| 123 | + err = (int *)rdma_consumer_reject_data(cm_id, event, &len); |
|---|
| 124 | + if (!err || |
|---|
| 125 | + (err && len >= sizeof(*err) && |
|---|
| 126 | + ((*err) <= RDS_RDMA_REJ_INCOMPAT))) { |
|---|
| 127 | + pr_warn("RDS/RDMA: conn <%pI6c, %pI6c> rejected, dropping connection\n", |
|---|
| 128 | + &conn->c_laddr, &conn->c_faddr); |
|---|
| 129 | + |
|---|
| 130 | + if (!conn->c_tos) |
|---|
| 131 | + conn->c_proposed_version = RDS_PROTOCOL_COMPAT_VERSION; |
|---|
| 132 | + |
|---|
| 133 | + rds_conn_drop(conn); |
|---|
| 134 | + } |
|---|
| 109 | 135 | rdsdebug("Connection rejected: %s\n", |
|---|
| 110 | 136 | rdma_reject_msg(cm_id, event->status)); |
|---|
| 111 | | - /* FALLTHROUGH */ |
|---|
| 137 | + break; |
|---|
| 112 | 138 | case RDMA_CM_EVENT_ADDR_ERROR: |
|---|
| 113 | 139 | case RDMA_CM_EVENT_ROUTE_ERROR: |
|---|
| 114 | 140 | case RDMA_CM_EVENT_CONNECT_ERROR: |
|---|
| .. | .. |
|---|
| 120 | 146 | break; |
|---|
| 121 | 147 | |
|---|
| 122 | 148 | case RDMA_CM_EVENT_DISCONNECTED: |
|---|
| 149 | + if (!conn) |
|---|
| 150 | + break; |
|---|
| 123 | 151 | rdsdebug("DISCONNECT event - dropping connection " |
|---|
| 124 | 152 | "%pI6c->%pI6c\n", &conn->c_laddr, |
|---|
| 125 | 153 | &conn->c_faddr); |
|---|