Skip to content

Commit

Permalink
IB/core: Implement a limit on UMAD receive List
Browse files Browse the repository at this point in the history
The existing behavior of ib_umad, which maintains received MAD
packets in an unbounded list, poses a risk of uncontrolled growth.
As user-space applications extract packets from this list, the rate
of extraction may not match the rate of incoming packets, leading
to potential list overflow.

To address this, we introduce a limit to the size of the list. After
considering typical scenarios, such as OpenSM processing, which can
handle approximately 100k packets per second, and the 1-second retry
timeout for most packets, we set the list size limit to 200k. Packets
received beyond this limit are dropped, assuming they are likely timed
out by the time they are handled by user-space.

Notably, packets queued on the receive list due to reasons like
timed-out sends are preserved even when the list is full.

Signed-off-by: Michael Guralnik <[email protected]>
Reviewed-by: Mark Zhang <[email protected]>
Link: https://lore.kernel.org/r/7197cb58a7d9e78399008f25036205ceab07fbd5.1713268818.git.leon@kernel.org
Signed-off-by: Leon Romanovsky <[email protected]>
  • Loading branch information
mikijoy authored and rleon committed Apr 21, 2024
1 parent 349e859 commit ca0b44e
Showing 1 changed file with 15 additions and 6 deletions.
21 changes: 15 additions & 6 deletions drivers/infiniband/core/user_mad.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ MODULE_AUTHOR("Roland Dreier");
MODULE_DESCRIPTION("InfiniBand userspace MAD packet access");
MODULE_LICENSE("Dual BSD/GPL");

#define MAX_UMAD_RECV_LIST_SIZE 200000

enum {
IB_UMAD_MAX_PORTS = RDMA_MAX_PORTS,
IB_UMAD_MAX_AGENTS = 32,
Expand Down Expand Up @@ -113,6 +115,7 @@ struct ib_umad_file {
struct mutex mutex;
struct ib_umad_port *port;
struct list_head recv_list;
atomic_t recv_list_size;
struct list_head send_list;
struct list_head port_list;
spinlock_t send_lock;
Expand Down Expand Up @@ -180,24 +183,28 @@ static struct ib_mad_agent *__get_agent(struct ib_umad_file *file, int id)
return file->agents_dead ? NULL : file->agent[id];
}

static int queue_packet(struct ib_umad_file *file,
struct ib_mad_agent *agent,
struct ib_umad_packet *packet)
static int queue_packet(struct ib_umad_file *file, struct ib_mad_agent *agent,
struct ib_umad_packet *packet, bool is_recv_mad)
{
int ret = 1;

mutex_lock(&file->mutex);

if (is_recv_mad &&
atomic_read(&file->recv_list_size) > MAX_UMAD_RECV_LIST_SIZE)
goto unlock;

for (packet->mad.hdr.id = 0;
packet->mad.hdr.id < IB_UMAD_MAX_AGENTS;
packet->mad.hdr.id++)
if (agent == __get_agent(file, packet->mad.hdr.id)) {
list_add_tail(&packet->list, &file->recv_list);
atomic_inc(&file->recv_list_size);
wake_up_interruptible(&file->recv_wait);
ret = 0;
break;
}

unlock:
mutex_unlock(&file->mutex);

return ret;
Expand All @@ -224,7 +231,7 @@ static void send_handler(struct ib_mad_agent *agent,
if (send_wc->status == IB_WC_RESP_TIMEOUT_ERR) {
packet->length = IB_MGMT_MAD_HDR;
packet->mad.hdr.status = ETIMEDOUT;
if (!queue_packet(file, agent, packet))
if (!queue_packet(file, agent, packet, false))
return;
}
kfree(packet);
Expand Down Expand Up @@ -284,7 +291,7 @@ static void recv_handler(struct ib_mad_agent *agent,
rdma_destroy_ah_attr(&ah_attr);
}

if (queue_packet(file, agent, packet))
if (queue_packet(file, agent, packet, true))
goto err2;
return;

Expand Down Expand Up @@ -409,6 +416,7 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,

packet = list_entry(file->recv_list.next, struct ib_umad_packet, list);
list_del(&packet->list);
atomic_dec(&file->recv_list_size);

mutex_unlock(&file->mutex);

Expand All @@ -421,6 +429,7 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
/* Requeue packet */
mutex_lock(&file->mutex);
list_add(&packet->list, &file->recv_list);
atomic_inc(&file->recv_list_size);
mutex_unlock(&file->mutex);
} else {
if (packet->recv_wc)
Expand Down

0 comments on commit ca0b44e

Please sign in to comment.