Linux Audio

Check our new training course

Linux kernel drivers training

Mar 31-Apr 9, 2025, special US time zones
Register
Loading...
v4.6
  1/*
  2 * Copyright (c) 2009 Oracle.  All rights reserved.
  3 *
  4 * This software is available to you under a choice of one of two
  5 * licenses.  You may choose to be licensed under the terms of the GNU
  6 * General Public License (GPL) Version 2, available from the file
  7 * COPYING in the main directory of this source tree, or the
  8 * OpenIB.org BSD license below:
  9 *
 10 *     Redistribution and use in source and binary forms, with or
 11 *     without modification, are permitted provided that the following
 12 *     conditions are met:
 13 *
 14 *      - Redistributions of source code must retain the above
 15 *        copyright notice, this list of conditions and the following
 16 *        disclaimer.
 17 *
 18 *      - Redistributions in binary form must reproduce the above
 19 *        copyright notice, this list of conditions and the following
 20 *        disclaimer in the documentation and/or other materials
 21 *        provided with the distribution.
 22 *
 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 30 * SOFTWARE.
 31 *
 32 */
 33#include <linux/module.h>
 34#include <rdma/rdma_cm.h>
 35
 
 36#include "rdma_transport.h"
 37#include "ib.h"
 38
 39static struct rdma_cm_id *rds_rdma_listen_id;
 40
 41int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
 42			      struct rdma_cm_event *event)
 43{
 44	/* this can be null in the listening path */
 45	struct rds_connection *conn = cm_id->context;
 46	struct rds_transport *trans;
 47	int ret = 0;
 48
 49	rdsdebug("conn %p id %p handling event %u (%s)\n", conn, cm_id,
 50		 event->event, rdma_event_msg(event->event));
 51
 52	if (cm_id->device->node_type == RDMA_NODE_IB_CA)
 53		trans = &rds_ib_transport;
 54
 55	/* Prevent shutdown from tearing down the connection
 56	 * while we're executing. */
 57	if (conn) {
 58		mutex_lock(&conn->c_cm_lock);
 59
 60		/* If the connection is being shut down, bail out
 61		 * right away. We return 0 so cm_id doesn't get
 62		 * destroyed prematurely */
 63		if (rds_conn_state(conn) == RDS_CONN_DISCONNECTING) {
 64			/* Reject incoming connections while we're tearing
 65			 * down an existing one. */
 66			if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST)
 67				ret = 1;
 68			goto out;
 69		}
 70	}
 71
 72	switch (event->event) {
 73	case RDMA_CM_EVENT_CONNECT_REQUEST:
 74		ret = trans->cm_handle_connect(cm_id, event);
 75		break;
 76
 77	case RDMA_CM_EVENT_ADDR_RESOLVED:
 78		/* XXX do we need to clean up if this fails? */
 79		ret = rdma_resolve_route(cm_id,
 80					 RDS_RDMA_RESOLVE_TIMEOUT_MS);
 81		break;
 82
 83	case RDMA_CM_EVENT_ROUTE_RESOLVED:
 84		/* Connection could have been dropped so make sure the
 85		 * cm_id is valid before proceeding
 86		 */
 87		if (conn) {
 88			struct rds_ib_connection *ibic;
 89
 90			ibic = conn->c_transport_data;
 91			if (ibic && ibic->i_cm_id == cm_id)
 92				ret = trans->cm_initiate_connect(cm_id);
 93			else
 94				rds_conn_drop(conn);
 95		}
 96		break;
 97
 98	case RDMA_CM_EVENT_ESTABLISHED:
 99		trans->cm_connect_complete(conn, event);
100		break;
101
 
 
 
 
102	case RDMA_CM_EVENT_ADDR_ERROR:
103	case RDMA_CM_EVENT_ROUTE_ERROR:
104	case RDMA_CM_EVENT_CONNECT_ERROR:
105	case RDMA_CM_EVENT_UNREACHABLE:
106	case RDMA_CM_EVENT_REJECTED:
107	case RDMA_CM_EVENT_DEVICE_REMOVAL:
108	case RDMA_CM_EVENT_ADDR_CHANGE:
109		if (conn)
110			rds_conn_drop(conn);
111		break;
112
113	case RDMA_CM_EVENT_DISCONNECTED:
114		rdsdebug("DISCONNECT event - dropping connection "
115			"%pI4->%pI4\n", &conn->c_laddr,
116			 &conn->c_faddr);
117		rds_conn_drop(conn);
118		break;
119
120	case RDMA_CM_EVENT_TIMEWAIT_EXIT:
121		if (conn) {
122			pr_info("RDS: RDMA_CM_EVENT_TIMEWAIT_EXIT event: dropping connection %pI4->%pI4\n",
123				&conn->c_laddr, &conn->c_faddr);
124			rds_conn_drop(conn);
125		}
126		break;
127
128	default:
129		/* things like device disconnect? */
130		printk(KERN_ERR "RDS: unknown event %u (%s)!\n",
131		       event->event, rdma_event_msg(event->event));
132		break;
133	}
134
135out:
136	if (conn)
137		mutex_unlock(&conn->c_cm_lock);
138
139	rdsdebug("id %p event %u (%s) handling ret %d\n", cm_id, event->event,
140		 rdma_event_msg(event->event), ret);
141
142	return ret;
143}
144
145static int rds_rdma_listen_init(void)
146{
147	struct sockaddr_in sin;
148	struct rdma_cm_id *cm_id;
149	int ret;
150
151	cm_id = rdma_create_id(&init_net, rds_rdma_cm_event_handler, NULL,
152			       RDMA_PS_TCP, IB_QPT_RC);
153	if (IS_ERR(cm_id)) {
154		ret = PTR_ERR(cm_id);
155		printk(KERN_ERR "RDS/RDMA: failed to setup listener, "
156		       "rdma_create_id() returned %d\n", ret);
157		return ret;
158	}
159
160	sin.sin_family = AF_INET;
161	sin.sin_addr.s_addr = (__force u32)htonl(INADDR_ANY);
162	sin.sin_port = (__force u16)htons(RDS_PORT);
163
164	/*
165	 * XXX I bet this binds the cm_id to a device.  If we want to support
166	 * fail-over we'll have to take this into consideration.
167	 */
168	ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
169	if (ret) {
170		printk(KERN_ERR "RDS/RDMA: failed to setup listener, "
171		       "rdma_bind_addr() returned %d\n", ret);
172		goto out;
173	}
174
175	ret = rdma_listen(cm_id, 128);
176	if (ret) {
177		printk(KERN_ERR "RDS/RDMA: failed to setup listener, "
178		       "rdma_listen() returned %d\n", ret);
179		goto out;
180	}
181
182	rdsdebug("cm %p listening on port %u\n", cm_id, RDS_PORT);
183
184	rds_rdma_listen_id = cm_id;
185	cm_id = NULL;
186out:
187	if (cm_id)
188		rdma_destroy_id(cm_id);
189	return ret;
190}
191
192static void rds_rdma_listen_stop(void)
193{
194	if (rds_rdma_listen_id) {
195		rdsdebug("cm %p\n", rds_rdma_listen_id);
196		rdma_destroy_id(rds_rdma_listen_id);
197		rds_rdma_listen_id = NULL;
198	}
199}
200
201static int rds_rdma_init(void)
202{
203	int ret;
204
205	ret = rds_rdma_listen_init();
206	if (ret)
207		goto out;
208
209	ret = rds_ib_init();
210	if (ret)
211		goto err_ib_init;
212
213	goto out;
214
215err_ib_init:
216	rds_rdma_listen_stop();
217out:
218	return ret;
219}
220module_init(rds_rdma_init);
221
222static void rds_rdma_exit(void)
223{
224	/* stop listening first to ensure no new connections are attempted */
225	rds_rdma_listen_stop();
226	rds_ib_exit();
227}
228module_exit(rds_rdma_exit);
229
230MODULE_AUTHOR("Oracle Corporation <rds-devel@oss.oracle.com>");
231MODULE_DESCRIPTION("RDS: IB transport");
232MODULE_LICENSE("Dual BSD/GPL");
233
v4.10.11
  1/*
  2 * Copyright (c) 2009 Oracle.  All rights reserved.
  3 *
  4 * This software is available to you under a choice of one of two
  5 * licenses.  You may choose to be licensed under the terms of the GNU
  6 * General Public License (GPL) Version 2, available from the file
  7 * COPYING in the main directory of this source tree, or the
  8 * OpenIB.org BSD license below:
  9 *
 10 *     Redistribution and use in source and binary forms, with or
 11 *     without modification, are permitted provided that the following
 12 *     conditions are met:
 13 *
 14 *      - Redistributions of source code must retain the above
 15 *        copyright notice, this list of conditions and the following
 16 *        disclaimer.
 17 *
 18 *      - Redistributions in binary form must reproduce the above
 19 *        copyright notice, this list of conditions and the following
 20 *        disclaimer in the documentation and/or other materials
 21 *        provided with the distribution.
 22 *
 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 30 * SOFTWARE.
 31 *
 32 */
 33#include <linux/module.h>
 34#include <rdma/rdma_cm.h>
 35
 36#include "rds_single_path.h"
 37#include "rdma_transport.h"
 38#include "ib.h"
 39
 40static struct rdma_cm_id *rds_rdma_listen_id;
 41
 42int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
 43			      struct rdma_cm_event *event)
 44{
 45	/* this can be null in the listening path */
 46	struct rds_connection *conn = cm_id->context;
 47	struct rds_transport *trans;
 48	int ret = 0;
 49
 50	rdsdebug("conn %p id %p handling event %u (%s)\n", conn, cm_id,
 51		 event->event, rdma_event_msg(event->event));
 52
 53	if (cm_id->device->node_type == RDMA_NODE_IB_CA)
 54		trans = &rds_ib_transport;
 55
 56	/* Prevent shutdown from tearing down the connection
 57	 * while we're executing. */
 58	if (conn) {
 59		mutex_lock(&conn->c_cm_lock);
 60
 61		/* If the connection is being shut down, bail out
 62		 * right away. We return 0 so cm_id doesn't get
 63		 * destroyed prematurely */
 64		if (rds_conn_state(conn) == RDS_CONN_DISCONNECTING) {
 65			/* Reject incoming connections while we're tearing
 66			 * down an existing one. */
 67			if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST)
 68				ret = 1;
 69			goto out;
 70		}
 71	}
 72
 73	switch (event->event) {
 74	case RDMA_CM_EVENT_CONNECT_REQUEST:
 75		ret = trans->cm_handle_connect(cm_id, event);
 76		break;
 77
 78	case RDMA_CM_EVENT_ADDR_RESOLVED:
 79		/* XXX do we need to clean up if this fails? */
 80		ret = rdma_resolve_route(cm_id,
 81					 RDS_RDMA_RESOLVE_TIMEOUT_MS);
 82		break;
 83
 84	case RDMA_CM_EVENT_ROUTE_RESOLVED:
 85		/* Connection could have been dropped so make sure the
 86		 * cm_id is valid before proceeding
 87		 */
 88		if (conn) {
 89			struct rds_ib_connection *ibic;
 90
 91			ibic = conn->c_transport_data;
 92			if (ibic && ibic->i_cm_id == cm_id)
 93				ret = trans->cm_initiate_connect(cm_id);
 94			else
 95				rds_conn_drop(conn);
 96		}
 97		break;
 98
 99	case RDMA_CM_EVENT_ESTABLISHED:
100		trans->cm_connect_complete(conn, event);
101		break;
102
103	case RDMA_CM_EVENT_REJECTED:
104		rdsdebug("Connection rejected: %s\n",
105			 rdma_reject_msg(cm_id, event->status));
106		/* FALLTHROUGH */
107	case RDMA_CM_EVENT_ADDR_ERROR:
108	case RDMA_CM_EVENT_ROUTE_ERROR:
109	case RDMA_CM_EVENT_CONNECT_ERROR:
110	case RDMA_CM_EVENT_UNREACHABLE:
 
111	case RDMA_CM_EVENT_DEVICE_REMOVAL:
112	case RDMA_CM_EVENT_ADDR_CHANGE:
113		if (conn)
114			rds_conn_drop(conn);
115		break;
116
117	case RDMA_CM_EVENT_DISCONNECTED:
118		rdsdebug("DISCONNECT event - dropping connection "
119			"%pI4->%pI4\n", &conn->c_laddr,
120			 &conn->c_faddr);
121		rds_conn_drop(conn);
122		break;
123
124	case RDMA_CM_EVENT_TIMEWAIT_EXIT:
125		if (conn) {
126			pr_info("RDS: RDMA_CM_EVENT_TIMEWAIT_EXIT event: dropping connection %pI4->%pI4\n",
127				&conn->c_laddr, &conn->c_faddr);
128			rds_conn_drop(conn);
129		}
130		break;
131
132	default:
133		/* things like device disconnect? */
134		printk(KERN_ERR "RDS: unknown event %u (%s)!\n",
135		       event->event, rdma_event_msg(event->event));
136		break;
137	}
138
139out:
140	if (conn)
141		mutex_unlock(&conn->c_cm_lock);
142
143	rdsdebug("id %p event %u (%s) handling ret %d\n", cm_id, event->event,
144		 rdma_event_msg(event->event), ret);
145
146	return ret;
147}
148
149static int rds_rdma_listen_init(void)
150{
151	struct sockaddr_in sin;
152	struct rdma_cm_id *cm_id;
153	int ret;
154
155	cm_id = rdma_create_id(&init_net, rds_rdma_cm_event_handler, NULL,
156			       RDMA_PS_TCP, IB_QPT_RC);
157	if (IS_ERR(cm_id)) {
158		ret = PTR_ERR(cm_id);
159		printk(KERN_ERR "RDS/RDMA: failed to setup listener, "
160		       "rdma_create_id() returned %d\n", ret);
161		return ret;
162	}
163
164	sin.sin_family = AF_INET;
165	sin.sin_addr.s_addr = (__force u32)htonl(INADDR_ANY);
166	sin.sin_port = (__force u16)htons(RDS_PORT);
167
168	/*
169	 * XXX I bet this binds the cm_id to a device.  If we want to support
170	 * fail-over we'll have to take this into consideration.
171	 */
172	ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
173	if (ret) {
174		printk(KERN_ERR "RDS/RDMA: failed to setup listener, "
175		       "rdma_bind_addr() returned %d\n", ret);
176		goto out;
177	}
178
179	ret = rdma_listen(cm_id, 128);
180	if (ret) {
181		printk(KERN_ERR "RDS/RDMA: failed to setup listener, "
182		       "rdma_listen() returned %d\n", ret);
183		goto out;
184	}
185
186	rdsdebug("cm %p listening on port %u\n", cm_id, RDS_PORT);
187
188	rds_rdma_listen_id = cm_id;
189	cm_id = NULL;
190out:
191	if (cm_id)
192		rdma_destroy_id(cm_id);
193	return ret;
194}
195
196static void rds_rdma_listen_stop(void)
197{
198	if (rds_rdma_listen_id) {
199		rdsdebug("cm %p\n", rds_rdma_listen_id);
200		rdma_destroy_id(rds_rdma_listen_id);
201		rds_rdma_listen_id = NULL;
202	}
203}
204
205static int rds_rdma_init(void)
206{
207	int ret;
208
209	ret = rds_rdma_listen_init();
210	if (ret)
211		goto out;
212
213	ret = rds_ib_init();
214	if (ret)
215		goto err_ib_init;
216
217	goto out;
218
219err_ib_init:
220	rds_rdma_listen_stop();
221out:
222	return ret;
223}
224module_init(rds_rdma_init);
225
226static void rds_rdma_exit(void)
227{
228	/* stop listening first to ensure no new connections are attempted */
229	rds_rdma_listen_stop();
230	rds_ib_exit();
231}
232module_exit(rds_rdma_exit);
233
234MODULE_AUTHOR("Oracle Corporation <rds-devel@oss.oracle.com>");
235MODULE_DESCRIPTION("RDS: IB transport");
236MODULE_LICENSE("Dual BSD/GPL");
237