.. | .. |
---|
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); |
---|