| .. | .. |
|---|
| 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: |
|---|
| 89 | + rdma_set_service_type(cm_id, conn->c_tos); |
|---|
| 84 | 90 | /* XXX do we need to clean up if this fails? */ |
|---|
| 85 | 91 | ret = rdma_resolve_route(cm_id, |
|---|
| 86 | 92 | RDS_RDMA_RESOLVE_TIMEOUT_MS); |
|---|
| .. | .. |
|---|
| 94 | 100 | struct rds_ib_connection *ibic; |
|---|
| 95 | 101 | |
|---|
| 96 | 102 | ibic = conn->c_transport_data; |
|---|
| 97 | | - if (ibic && ibic->i_cm_id == cm_id) |
|---|
| 103 | + if (ibic && ibic->i_cm_id == cm_id) { |
|---|
| 104 | + cm_id->route.path_rec[0].sl = |
|---|
| 105 | + TOS_TO_SL(conn->c_tos); |
|---|
| 98 | 106 | ret = trans->cm_initiate_connect(cm_id, isv6); |
|---|
| 99 | | - else |
|---|
| 107 | + } else { |
|---|
| 100 | 108 | rds_conn_drop(conn); |
|---|
| 109 | + } |
|---|
| 101 | 110 | } |
|---|
| 102 | 111 | break; |
|---|
| 103 | 112 | |
|---|
| 104 | 113 | case RDMA_CM_EVENT_ESTABLISHED: |
|---|
| 105 | | - trans->cm_connect_complete(conn, event); |
|---|
| 114 | + if (conn) |
|---|
| 115 | + trans->cm_connect_complete(conn, event); |
|---|
| 106 | 116 | break; |
|---|
| 107 | 117 | |
|---|
| 108 | 118 | case RDMA_CM_EVENT_REJECTED: |
|---|
| 119 | + if (!conn) |
|---|
| 120 | + break; |
|---|
| 121 | + err = (int *)rdma_consumer_reject_data(cm_id, event, &len); |
|---|
| 122 | + if (!err || |
|---|
| 123 | + (err && len >= sizeof(*err) && |
|---|
| 124 | + ((*err) <= RDS_RDMA_REJ_INCOMPAT))) { |
|---|
| 125 | + pr_warn("RDS/RDMA: conn <%pI6c, %pI6c> rejected, dropping connection\n", |
|---|
| 126 | + &conn->c_laddr, &conn->c_faddr); |
|---|
| 127 | + |
|---|
| 128 | + if (!conn->c_tos) |
|---|
| 129 | + conn->c_proposed_version = RDS_PROTOCOL_COMPAT_VERSION; |
|---|
| 130 | + |
|---|
| 131 | + rds_conn_drop(conn); |
|---|
| 132 | + } |
|---|
| 109 | 133 | rdsdebug("Connection rejected: %s\n", |
|---|
| 110 | 134 | rdma_reject_msg(cm_id, event->status)); |
|---|
| 111 | | - /* FALLTHROUGH */ |
|---|
| 135 | + break; |
|---|
| 112 | 136 | case RDMA_CM_EVENT_ADDR_ERROR: |
|---|
| 113 | 137 | case RDMA_CM_EVENT_ROUTE_ERROR: |
|---|
| 114 | 138 | case RDMA_CM_EVENT_CONNECT_ERROR: |
|---|
| .. | .. |
|---|
| 120 | 144 | break; |
|---|
| 121 | 145 | |
|---|
| 122 | 146 | case RDMA_CM_EVENT_DISCONNECTED: |
|---|
| 147 | + if (!conn) |
|---|
| 148 | + break; |
|---|
| 123 | 149 | rdsdebug("DISCONNECT event - dropping connection " |
|---|
| 124 | 150 | "%pI6c->%pI6c\n", &conn->c_laddr, |
|---|
| 125 | 151 | &conn->c_faddr); |
|---|