0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include <linux/module.h>
0034 #include <rdma/rdma_cm.h>
0035
0036 #include "rds_single_path.h"
0037 #include "rdma_transport.h"
0038 #include "ib.h"
0039
0040
0041 static struct rdma_cm_id *rds_rdma_listen_id;
0042 #if IS_ENABLED(CONFIG_IPV6)
0043 static struct rdma_cm_id *rds6_rdma_listen_id;
0044 #endif
0045
0046
0047 #define TOS_TO_SL(tos) ((tos) & 0xF)
0048
0049 static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
0050 struct rdma_cm_event *event,
0051 bool isv6)
0052 {
0053
0054 struct rds_connection *conn = cm_id->context;
0055 struct rds_transport *trans;
0056 int ret = 0;
0057 int *err;
0058 u8 len;
0059
0060 rdsdebug("conn %p id %p handling event %u (%s)\n", conn, cm_id,
0061 event->event, rdma_event_msg(event->event));
0062
0063 if (cm_id->device->node_type == RDMA_NODE_IB_CA)
0064 trans = &rds_ib_transport;
0065
0066
0067
0068 if (conn) {
0069 mutex_lock(&conn->c_cm_lock);
0070
0071
0072
0073
0074 if (rds_conn_state(conn) == RDS_CONN_DISCONNECTING) {
0075
0076
0077 if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST)
0078 ret = 1;
0079 goto out;
0080 }
0081 }
0082
0083 switch (event->event) {
0084 case RDMA_CM_EVENT_CONNECT_REQUEST:
0085 ret = trans->cm_handle_connect(cm_id, event, isv6);
0086 break;
0087
0088 case RDMA_CM_EVENT_ADDR_RESOLVED:
0089 rdma_set_service_type(cm_id, conn->c_tos);
0090 rdma_set_min_rnr_timer(cm_id, IB_RNR_TIMER_000_32);
0091
0092 ret = rdma_resolve_route(cm_id,
0093 RDS_RDMA_RESOLVE_TIMEOUT_MS);
0094 break;
0095
0096 case RDMA_CM_EVENT_ROUTE_RESOLVED:
0097
0098
0099
0100 if (conn) {
0101 struct rds_ib_connection *ibic;
0102
0103 ibic = conn->c_transport_data;
0104 if (ibic && ibic->i_cm_id == cm_id) {
0105 cm_id->route.path_rec[0].sl =
0106 TOS_TO_SL(conn->c_tos);
0107 ret = trans->cm_initiate_connect(cm_id, isv6);
0108 } else {
0109 rds_conn_drop(conn);
0110 }
0111 }
0112 break;
0113
0114 case RDMA_CM_EVENT_ESTABLISHED:
0115 if (conn)
0116 trans->cm_connect_complete(conn, event);
0117 break;
0118
0119 case RDMA_CM_EVENT_REJECTED:
0120 if (!conn)
0121 break;
0122 err = (int *)rdma_consumer_reject_data(cm_id, event, &len);
0123 if (!err ||
0124 (err && len >= sizeof(*err) &&
0125 ((*err) <= RDS_RDMA_REJ_INCOMPAT))) {
0126 pr_warn("RDS/RDMA: conn <%pI6c, %pI6c> rejected, dropping connection\n",
0127 &conn->c_laddr, &conn->c_faddr);
0128
0129 if (!conn->c_tos)
0130 conn->c_proposed_version = RDS_PROTOCOL_COMPAT_VERSION;
0131
0132 rds_conn_drop(conn);
0133 }
0134 rdsdebug("Connection rejected: %s\n",
0135 rdma_reject_msg(cm_id, event->status));
0136 break;
0137 case RDMA_CM_EVENT_ADDR_ERROR:
0138 case RDMA_CM_EVENT_ROUTE_ERROR:
0139 case RDMA_CM_EVENT_CONNECT_ERROR:
0140 case RDMA_CM_EVENT_UNREACHABLE:
0141 case RDMA_CM_EVENT_DEVICE_REMOVAL:
0142 case RDMA_CM_EVENT_ADDR_CHANGE:
0143 if (conn)
0144 rds_conn_drop(conn);
0145 break;
0146
0147 case RDMA_CM_EVENT_DISCONNECTED:
0148 if (!conn)
0149 break;
0150 rdsdebug("DISCONNECT event - dropping connection "
0151 "%pI6c->%pI6c\n", &conn->c_laddr,
0152 &conn->c_faddr);
0153 rds_conn_drop(conn);
0154 break;
0155
0156 case RDMA_CM_EVENT_TIMEWAIT_EXIT:
0157 if (conn) {
0158 pr_info("RDS: RDMA_CM_EVENT_TIMEWAIT_EXIT event: dropping connection %pI6c->%pI6c\n",
0159 &conn->c_laddr, &conn->c_faddr);
0160 rds_conn_drop(conn);
0161 }
0162 break;
0163
0164 default:
0165
0166 printk(KERN_ERR "RDS: unknown event %u (%s)!\n",
0167 event->event, rdma_event_msg(event->event));
0168 break;
0169 }
0170
0171 out:
0172 if (conn)
0173 mutex_unlock(&conn->c_cm_lock);
0174
0175 rdsdebug("id %p event %u (%s) handling ret %d\n", cm_id, event->event,
0176 rdma_event_msg(event->event), ret);
0177
0178 return ret;
0179 }
0180
0181 int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
0182 struct rdma_cm_event *event)
0183 {
0184 return rds_rdma_cm_event_handler_cmn(cm_id, event, false);
0185 }
0186
0187 #if IS_ENABLED(CONFIG_IPV6)
0188 int rds6_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
0189 struct rdma_cm_event *event)
0190 {
0191 return rds_rdma_cm_event_handler_cmn(cm_id, event, true);
0192 }
0193 #endif
0194
0195 static int rds_rdma_listen_init_common(rdma_cm_event_handler handler,
0196 struct sockaddr *sa,
0197 struct rdma_cm_id **ret_cm_id)
0198 {
0199 struct rdma_cm_id *cm_id;
0200 int ret;
0201
0202 cm_id = rdma_create_id(&init_net, handler, NULL,
0203 RDMA_PS_TCP, IB_QPT_RC);
0204 if (IS_ERR(cm_id)) {
0205 ret = PTR_ERR(cm_id);
0206 printk(KERN_ERR "RDS/RDMA: failed to setup listener, "
0207 "rdma_create_id() returned %d\n", ret);
0208 return ret;
0209 }
0210
0211
0212
0213
0214
0215 ret = rdma_bind_addr(cm_id, sa);
0216 if (ret) {
0217 printk(KERN_ERR "RDS/RDMA: failed to setup listener, "
0218 "rdma_bind_addr() returned %d\n", ret);
0219 goto out;
0220 }
0221
0222 ret = rdma_listen(cm_id, 128);
0223 if (ret) {
0224 printk(KERN_ERR "RDS/RDMA: failed to setup listener, "
0225 "rdma_listen() returned %d\n", ret);
0226 goto out;
0227 }
0228
0229 rdsdebug("cm %p listening on port %u\n", cm_id, RDS_PORT);
0230
0231 *ret_cm_id = cm_id;
0232 cm_id = NULL;
0233 out:
0234 if (cm_id)
0235 rdma_destroy_id(cm_id);
0236 return ret;
0237 }
0238
0239
0240
0241
0242
0243
0244
0245 static int rds_rdma_listen_init(void)
0246 {
0247 int ret;
0248 #if IS_ENABLED(CONFIG_IPV6)
0249 struct sockaddr_in6 sin6;
0250 #endif
0251 struct sockaddr_in sin;
0252
0253 sin.sin_family = PF_INET;
0254 sin.sin_addr.s_addr = htonl(INADDR_ANY);
0255 sin.sin_port = htons(RDS_PORT);
0256 ret = rds_rdma_listen_init_common(rds_rdma_cm_event_handler,
0257 (struct sockaddr *)&sin,
0258 &rds_rdma_listen_id);
0259 if (ret != 0)
0260 return ret;
0261
0262 #if IS_ENABLED(CONFIG_IPV6)
0263 sin6.sin6_family = PF_INET6;
0264 sin6.sin6_addr = in6addr_any;
0265 sin6.sin6_port = htons(RDS_CM_PORT);
0266 sin6.sin6_scope_id = 0;
0267 sin6.sin6_flowinfo = 0;
0268 ret = rds_rdma_listen_init_common(rds6_rdma_cm_event_handler,
0269 (struct sockaddr *)&sin6,
0270 &rds6_rdma_listen_id);
0271
0272 if (ret != 0)
0273 rdsdebug("Cannot set up IPv6 RDMA listener\n");
0274 #endif
0275 return 0;
0276 }
0277
0278 static void rds_rdma_listen_stop(void)
0279 {
0280 if (rds_rdma_listen_id) {
0281 rdsdebug("cm %p\n", rds_rdma_listen_id);
0282 rdma_destroy_id(rds_rdma_listen_id);
0283 rds_rdma_listen_id = NULL;
0284 }
0285 #if IS_ENABLED(CONFIG_IPV6)
0286 if (rds6_rdma_listen_id) {
0287 rdsdebug("cm %p\n", rds6_rdma_listen_id);
0288 rdma_destroy_id(rds6_rdma_listen_id);
0289 rds6_rdma_listen_id = NULL;
0290 }
0291 #endif
0292 }
0293
0294 static int rds_rdma_init(void)
0295 {
0296 int ret;
0297
0298 ret = rds_ib_init();
0299 if (ret)
0300 goto out;
0301
0302 ret = rds_rdma_listen_init();
0303 if (ret)
0304 rds_ib_exit();
0305 out:
0306 return ret;
0307 }
0308 module_init(rds_rdma_init);
0309
0310 static void rds_rdma_exit(void)
0311 {
0312
0313 rds_rdma_listen_stop();
0314 rds_ib_exit();
0315 }
0316 module_exit(rds_rdma_exit);
0317
0318 MODULE_AUTHOR("Oracle Corporation <rds-devel@oss.oracle.com>");
0319 MODULE_DESCRIPTION("RDS: IB transport");
0320 MODULE_LICENSE("Dual BSD/GPL");