Skip to content

Commit 214220e

Browse files
metze-sambasmfrench
authored andcommitted
smb: server: make use of rdma_restrict_node_type()
For smbdirect it required to use different ports depending on the RDMA protocol. E.g. for iWarp 5445 is needed (as tcp port 445 already used by the raw tcp transport for SMB), while InfiniBand, RoCEv1 and RoCEv2 use port 445, as they use an independent port range (even for RoCEv2, which uses udp port 4791 itself). Currently ksmbd is not able to function correctly at all if the system has iWarp (RDMA_NODE_RNIC) interface(s) and any InfiniBand, RoCEv1 and/or RoCEv2 interface(s) at the same time. Now we do a wildcard listen on port 5445 only for iWarp devices and another wildcard listen on port 445 of any InfiniBand, RoCEv1 and/or RoCEv2 devices. The wildcard listeners also work if there is no device of the requested node_type, this is the same logic as we had before, but before we had to decide between port 5445 or 445 and now both are possible at the same time. Cc: Jason Gunthorpe <jgg@ziepe.ca> Cc: Leon Romanovsky <leon@kernel.org> Cc: Steve French <smfrench@gmail.com> Cc: Tom Talpey <tom@talpey.com> Cc: Long Li <longli@microsoft.com> Acked-by: Namjae Jeon <linkinjeon@kernel.org> Cc: linux-rdma@vger.kernel.org Cc: linux-cifs@vger.kernel.org Cc: samba-technical@lists.samba.org Signed-off-by: Stefan Metzmacher <metze@samba.org> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent 07e0b72 commit 214220e

1 file changed

Lines changed: 80 additions & 28 deletions

File tree

fs/smb/server/transport_rdma.c

Lines changed: 80 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,6 @@
6161
* Those may change after a SMB_DIRECT negotiation
6262
*/
6363

64-
/* Set 445 port to SMB Direct port by default */
65-
static int smb_direct_port = SMB_DIRECT_PORT_INFINIBAND;
66-
6764
/* The local peer's maximum number of credits to grant to the peer */
6865
static int smb_direct_receive_credit_max = 255;
6966

@@ -90,8 +87,9 @@ struct smb_direct_device {
9087
};
9188

9289
static struct smb_direct_listener {
90+
int port;
9391
struct rdma_cm_id *cm_id;
94-
} smb_direct_listener;
92+
} smb_direct_ib_listener, smb_direct_iw_listener;
9593

9694
static struct workqueue_struct *smb_direct_wq;
9795

@@ -2620,6 +2618,7 @@ static bool rdma_frwr_is_supported(struct ib_device_attr *attrs)
26202618
static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id,
26212619
struct rdma_cm_event *event)
26222620
{
2621+
struct smb_direct_listener *listener = new_cm_id->context;
26232622
struct smb_direct_transport *t;
26242623
struct smbdirect_socket *sc;
26252624
struct smbdirect_socket_parameters *sp;
@@ -2708,7 +2707,7 @@ static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id,
27082707

27092708
handler = kthread_run(ksmbd_conn_handler_loop,
27102709
KSMBD_TRANS(t)->conn, "ksmbd:r%u",
2711-
smb_direct_port);
2710+
listener->port);
27122711
if (IS_ERR(handler)) {
27132712
ret = PTR_ERR(handler);
27142713
pr_err("Can't start thread\n");
@@ -2745,39 +2744,73 @@ static int smb_direct_listen_handler(struct rdma_cm_id *cm_id,
27452744
return 0;
27462745
}
27472746

2748-
static int smb_direct_listen(int port)
2747+
static int smb_direct_listen(struct smb_direct_listener *listener,
2748+
int port)
27492749
{
27502750
int ret;
27512751
struct rdma_cm_id *cm_id;
2752+
u8 node_type = RDMA_NODE_UNSPECIFIED;
27522753
struct sockaddr_in sin = {
27532754
.sin_family = AF_INET,
27542755
.sin_addr.s_addr = htonl(INADDR_ANY),
27552756
.sin_port = htons(port),
27562757
};
27572758

2759+
switch (port) {
2760+
case SMB_DIRECT_PORT_IWARP:
2761+
/*
2762+
* only allow iWarp devices
2763+
* for port 5445.
2764+
*/
2765+
node_type = RDMA_NODE_RNIC;
2766+
break;
2767+
case SMB_DIRECT_PORT_INFINIBAND:
2768+
/*
2769+
* only allow InfiniBand, RoCEv1 or RoCEv2
2770+
* devices for port 445.
2771+
*
2772+
* (Basically don't allow iWarp devices)
2773+
*/
2774+
node_type = RDMA_NODE_IB_CA;
2775+
break;
2776+
default:
2777+
pr_err("unsupported smbdirect port=%d!\n", port);
2778+
return -ENODEV;
2779+
}
2780+
27582781
cm_id = rdma_create_id(&init_net, smb_direct_listen_handler,
2759-
&smb_direct_listener, RDMA_PS_TCP, IB_QPT_RC);
2782+
listener, RDMA_PS_TCP, IB_QPT_RC);
27602783
if (IS_ERR(cm_id)) {
27612784
pr_err("Can't create cm id: %ld\n", PTR_ERR(cm_id));
27622785
return PTR_ERR(cm_id);
27632786
}
27642787

2788+
ret = rdma_restrict_node_type(cm_id, node_type);
2789+
if (ret) {
2790+
pr_err("rdma_restrict_node_type(%u) failed %d\n",
2791+
node_type, ret);
2792+
goto err;
2793+
}
2794+
27652795
ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
27662796
if (ret) {
27672797
pr_err("Can't bind: %d\n", ret);
27682798
goto err;
27692799
}
27702800

2771-
smb_direct_listener.cm_id = cm_id;
2772-
27732801
ret = rdma_listen(cm_id, 10);
27742802
if (ret) {
27752803
pr_err("Can't listen: %d\n", ret);
27762804
goto err;
27772805
}
2806+
2807+
listener->port = port;
2808+
listener->cm_id = cm_id;
2809+
27782810
return 0;
27792811
err:
2780-
smb_direct_listener.cm_id = NULL;
2812+
listener->port = 0;
2813+
listener->cm_id = NULL;
27812814
rdma_destroy_id(cm_id);
27822815
return ret;
27832816
}
@@ -2786,10 +2819,6 @@ static int smb_direct_ib_client_add(struct ib_device *ib_dev)
27862819
{
27872820
struct smb_direct_device *smb_dev;
27882821

2789-
/* Set 5445 port if device type is iWARP(No IB) */
2790-
if (ib_dev->node_type != RDMA_NODE_IB_CA)
2791-
smb_direct_port = SMB_DIRECT_PORT_IWARP;
2792-
27932822
if (!rdma_frwr_is_supported(&ib_dev->attrs))
27942823
return 0;
27952824

@@ -2832,8 +2861,9 @@ int ksmbd_rdma_init(void)
28322861
{
28332862
int ret;
28342863

2835-
smb_direct_port = SMB_DIRECT_PORT_INFINIBAND;
2836-
smb_direct_listener.cm_id = NULL;
2864+
smb_direct_ib_listener = smb_direct_iw_listener = (struct smb_direct_listener) {
2865+
.cm_id = NULL,
2866+
};
28372867

28382868
ret = ib_register_client(&smb_direct_ib_client);
28392869
if (ret) {
@@ -2849,31 +2879,53 @@ int ksmbd_rdma_init(void)
28492879
smb_direct_wq = alloc_workqueue("ksmbd-smb_direct-wq",
28502880
WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_PERCPU,
28512881
0);
2852-
if (!smb_direct_wq)
2853-
return -ENOMEM;
2882+
if (!smb_direct_wq) {
2883+
ret = -ENOMEM;
2884+
goto err;
2885+
}
28542886

2855-
ret = smb_direct_listen(smb_direct_port);
2887+
ret = smb_direct_listen(&smb_direct_ib_listener,
2888+
SMB_DIRECT_PORT_INFINIBAND);
28562889
if (ret) {
2857-
destroy_workqueue(smb_direct_wq);
2858-
smb_direct_wq = NULL;
2859-
pr_err("Can't listen: %d\n", ret);
2860-
return ret;
2890+
pr_err("Can't listen on InfiniBand/RoCEv1/RoCEv2: %d\n", ret);
2891+
goto err;
28612892
}
28622893

2863-
ksmbd_debug(RDMA, "init RDMA listener. cm_id=%p\n",
2864-
smb_direct_listener.cm_id);
2894+
ksmbd_debug(RDMA, "InfiniBand/RoCEv1/RoCEv2 RDMA listener. cm_id=%p\n",
2895+
smb_direct_ib_listener.cm_id);
2896+
2897+
ret = smb_direct_listen(&smb_direct_iw_listener,
2898+
SMB_DIRECT_PORT_IWARP);
2899+
if (ret) {
2900+
pr_err("Can't listen on iWarp: %d\n", ret);
2901+
goto err;
2902+
}
2903+
2904+
ksmbd_debug(RDMA, "iWarp RDMA listener. cm_id=%p\n",
2905+
smb_direct_iw_listener.cm_id);
2906+
28652907
return 0;
2908+
err:
2909+
ksmbd_rdma_stop_listening();
2910+
ksmbd_rdma_destroy();
2911+
return ret;
28662912
}
28672913

28682914
void ksmbd_rdma_stop_listening(void)
28692915
{
2870-
if (!smb_direct_listener.cm_id)
2916+
if (!smb_direct_ib_listener.cm_id && !smb_direct_iw_listener.cm_id)
28712917
return;
28722918

28732919
ib_unregister_client(&smb_direct_ib_client);
2874-
rdma_destroy_id(smb_direct_listener.cm_id);
28752920

2876-
smb_direct_listener.cm_id = NULL;
2921+
if (smb_direct_ib_listener.cm_id)
2922+
rdma_destroy_id(smb_direct_ib_listener.cm_id);
2923+
if (smb_direct_iw_listener.cm_id)
2924+
rdma_destroy_id(smb_direct_iw_listener.cm_id);
2925+
2926+
smb_direct_ib_listener = smb_direct_iw_listener = (struct smb_direct_listener) {
2927+
.cm_id = NULL,
2928+
};
28772929
}
28782930

28792931
void ksmbd_rdma_destroy(void)

0 commit comments

Comments
 (0)