Skip to content

Commit 19b752a

Browse files
monis410dledford
authored andcommitted
IB/cma: Allow port reuse for rdma_id
When allocating a port number for binding to a rdma_id, assuming the allocation is not for a specific port, the rule is to allow only ports that were not in use before by any other rdma_id. This condition is too strong to achieve the goal of a unique 5 tuple rdma_id. Instead, we can compare current rdma_id with other rdma_id for difference in one of destination port, source address and destination address to allow port reuse. Signed-off-by: Moni Shoua <[email protected]> Signed-off-by: Leon Romanovsky <[email protected]> Acked-by: Sean Hefty <[email protected]> Signed-off-by: Doug Ledford <[email protected]>
1 parent 498683c commit 19b752a

File tree

1 file changed

+60
-7
lines changed
  • drivers/infiniband/core

1 file changed

+60
-7
lines changed

drivers/infiniband/core/cma.c

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2847,20 +2847,26 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
28472847
int ret;
28482848

28492849
id_priv = container_of(id, struct rdma_id_private, id);
2850+
memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr));
28502851
if (id_priv->state == RDMA_CM_IDLE) {
28512852
ret = cma_bind_addr(id, src_addr, dst_addr);
2852-
if (ret)
2853+
if (ret) {
2854+
memset(cma_dst_addr(id_priv), 0, rdma_addr_size(dst_addr));
28532855
return ret;
2856+
}
28542857
}
28552858

2856-
if (cma_family(id_priv) != dst_addr->sa_family)
2859+
if (cma_family(id_priv) != dst_addr->sa_family) {
2860+
memset(cma_dst_addr(id_priv), 0, rdma_addr_size(dst_addr));
28572861
return -EINVAL;
2862+
}
28582863

2859-
if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_ADDR_QUERY))
2864+
if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_ADDR_QUERY)) {
2865+
memset(cma_dst_addr(id_priv), 0, rdma_addr_size(dst_addr));
28602866
return -EINVAL;
2867+
}
28612868

28622869
atomic_inc(&id_priv->refcount);
2863-
memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr));
28642870
if (cma_any_addr(dst_addr)) {
28652871
ret = cma_resolve_loopback(id_priv);
28662872
} else {
@@ -2976,6 +2982,43 @@ static int cma_alloc_port(enum rdma_port_space ps,
29762982
return ret == -ENOSPC ? -EADDRNOTAVAIL : ret;
29772983
}
29782984

2985+
static int cma_port_is_unique(struct rdma_bind_list *bind_list,
2986+
struct rdma_id_private *id_priv)
2987+
{
2988+
struct rdma_id_private *cur_id;
2989+
struct sockaddr *daddr = cma_dst_addr(id_priv);
2990+
struct sockaddr *saddr = cma_src_addr(id_priv);
2991+
__be16 dport = cma_port(daddr);
2992+
2993+
hlist_for_each_entry(cur_id, &bind_list->owners, node) {
2994+
struct sockaddr *cur_daddr = cma_dst_addr(cur_id);
2995+
struct sockaddr *cur_saddr = cma_src_addr(cur_id);
2996+
__be16 cur_dport = cma_port(cur_daddr);
2997+
2998+
if (id_priv == cur_id)
2999+
continue;
3000+
3001+
/* different dest port -> unique */
3002+
if (!cma_any_port(cur_daddr) &&
3003+
(dport != cur_dport))
3004+
continue;
3005+
3006+
/* different src address -> unique */
3007+
if (!cma_any_addr(saddr) &&
3008+
!cma_any_addr(cur_saddr) &&
3009+
cma_addr_cmp(saddr, cur_saddr))
3010+
continue;
3011+
3012+
/* different dst address -> unique */
3013+
if (!cma_any_addr(cur_daddr) &&
3014+
cma_addr_cmp(daddr, cur_daddr))
3015+
continue;
3016+
3017+
return -EADDRNOTAVAIL;
3018+
}
3019+
return 0;
3020+
}
3021+
29793022
static int cma_alloc_any_port(enum rdma_port_space ps,
29803023
struct rdma_id_private *id_priv)
29813024
{
@@ -2988,9 +3031,19 @@ static int cma_alloc_any_port(enum rdma_port_space ps,
29883031
remaining = (high - low) + 1;
29893032
rover = prandom_u32() % remaining + low;
29903033
retry:
2991-
if (last_used_port != rover &&
2992-
!cma_ps_find(net, ps, (unsigned short)rover)) {
2993-
int ret = cma_alloc_port(ps, id_priv, rover);
3034+
if (last_used_port != rover) {
3035+
struct rdma_bind_list *bind_list;
3036+
int ret;
3037+
3038+
bind_list = cma_ps_find(net, ps, (unsigned short)rover);
3039+
3040+
if (!bind_list) {
3041+
ret = cma_alloc_port(ps, id_priv, rover);
3042+
} else {
3043+
ret = cma_port_is_unique(bind_list, id_priv);
3044+
if (!ret)
3045+
cma_bind_port(bind_list, id_priv);
3046+
}
29943047
/*
29953048
* Remember previously used port number in order to avoid
29963049
* re-using same port immediately after it is closed.

0 commit comments

Comments
 (0)