From: Bang Nguyen Date: Wed, 3 Feb 2016 16:13:25 +0000 (-0800) Subject: RDS: message filtering based on UUID X-Git-Tag: v4.1.12-92~148^2~5 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=c4ff58ed47bb15774c230f9e25f0eaf46f5d7388;p=users%2Fjedix%2Flinux-maple.git RDS: message filtering based on UUID Egress message is filtered based on UUID and for ingress, the unique UUID is CMS'ed to application to take further action. SYSCTL 'uuid_tx_no_drop' to override UUID based packet filtering Orabug: 23222944 Signed-off-by: Bang Nguyen Signed-off-by: Yuval Shaia Signed-off-by: Santosh Shilimkar --- diff --git a/net/rds/rds.h b/net/rds/rds.h index 5499e15aaf3ca..dfc1781d7457a 100644 --- a/net/rds/rds.h +++ b/net/rds/rds.h @@ -1035,6 +1035,7 @@ extern unsigned long rds_sysctl_trace_flags; extern unsigned int rds_sysctl_trace_level; extern unsigned int rds_sysctl_shutdown_trace_start_time; extern unsigned int rds_sysctl_shutdown_trace_end_time; +extern unsigned int rds_sysctl_uuid_tx_no_drop; /* threads.c */ int rds_threads_init(void); diff --git a/net/rds/recv.c b/net/rds/recv.c index 90b665be6d4a1..0fc42f3119db7 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c @@ -875,6 +875,11 @@ int rds_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, goto out; } + if (rds_cmsg_uuid(rs, inc, msg)) { + ret = -EFAULT; + goto out; + } + rds_stats_inc(s_recv_delivered); sin = (struct sockaddr_in *)msg->msg_name; diff --git a/net/rds/send.c b/net/rds/send.c index 5bc6400ae3687..268dd727aa870 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -167,6 +167,27 @@ static void release_in_xmit(struct rds_connection *conn) wake_up_all(&conn->c_waitq); } +static int rds_match_uuid(struct rds_connection *conn, struct rds_message *rm) +{ + int ret = 0; + + if (!conn->c_acl_en || !rm->uuid.enable) { + rdsdebug("uuid is not enabled acl_en=%d uuid_en=%d val=%s\n", + conn->c_acl_en, rm->uuid.enable, rm->uuid.value); + return 0; + } + + ret = memcmp(conn->c_uuid, rm->uuid.value, sizeof(conn->c_uuid)); + + if (!ret && rm->m_rs) + rm->m_rs->rs_uuid_sent_cnt++; + + if (ret && rds_sysctl_uuid_tx_no_drop) + return 0; + + return ret; +} + /* * We're making the concious trade-off here to only send one message * down the connection at a time. @@ -265,6 +286,12 @@ restart: } rm->data.op_active = 1; + if (conn->c_acl_en) { + memcpy(rm->uuid.value, conn->c_uuid, + RDS_UUID_MAXLEN); + rm->uuid.enable = 1; + } + conn->c_xmit_rm = rm; } @@ -322,9 +349,11 @@ restart: &rm->m_flags))) { spin_lock_irqsave(&conn->c_lock, flags); if (test_and_clear_bit(RDS_MSG_ON_CONN, - &rm->m_flags)) + &rm->m_flags)) { + rm->m_status = RDS_RDMA_SEND_DROPPED; list_move_tail(&rm->m_conn_item, &to_be_dropped); + } spin_unlock_irqrestore(&conn->c_lock, flags); continue; } @@ -346,6 +375,20 @@ restart: conn->c_xmit_rm = rm; } + /* If fail uuid match, drop the message */ + if (rds_match_uuid(conn, rm)) { + spin_lock_irqsave(&conn->c_lock, flags); + if (test_and_clear_bit(RDS_MSG_ON_CONN, &rm->m_flags)) { + rm->m_status = RDS_RDMA_SEND_ACCVIO; + list_move_tail(&rm->m_conn_item, + &to_be_dropped); + } + spin_unlock_irqrestore(&conn->c_lock, flags); + conn->c_xmit_rm = 0; + rm->m_rs->rs_uuid_drop_cnt++; + continue; + } + /* The transport either sends the whole rdma or none of it */ if (rm->rdma.op_active && !conn->c_xmit_rdma_sent) { rm->m_final_op = &rm->rdma; @@ -468,7 +511,7 @@ over_batch: rds_message_unmapped(rm); rds_message_put(rm); } - rds_send_remove_from_sock(&to_be_dropped, RDS_RDMA_SEND_DROPPED); + rds_send_remove_from_sock(&to_be_dropped, rm->m_status); } /* @@ -1065,6 +1108,11 @@ static int rds_rm_size(struct msghdr *msg, int data_len) size += sizeof(struct scatterlist); break; + case RDS_CMSG_UUID: + cmsg_groups |= 1; + size += sizeof(struct scatterlist); + break; + default: return -EINVAL; } @@ -1104,6 +1152,17 @@ static int rds_cmsg_asend(struct rds_sock *rs, struct rds_message *rm, return 0; } +static int rds_cmsg_uuid(struct rds_sock *rs, struct rds_message *rm, + struct cmsghdr *cmsg) +{ + struct rds_uuid_args *args = CMSG_DATA(cmsg); + + /* Copy uuid to rm */ + memcpy(rm->uuid.value, args->uuid, RDS_UUID_MAXLEN); + + return 0; +} + static int rds_cmsg_send(struct rds_sock *rs, struct rds_message *rm, struct msghdr *msg, int *allocated_mr) { @@ -1148,6 +1207,10 @@ static int rds_cmsg_send(struct rds_sock *rs, struct rds_message *rm, ret = rds_cmsg_asend(rs, rm, cmsg); break; + case RDS_CMSG_UUID: + ret = rds_cmsg_uuid(rs, rm, cmsg); + break; + default: return -EINVAL; } @@ -1248,6 +1311,7 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len) rm->data.op_active = 1; rm->m_daddr = daddr; + rm->uuid.enable = rs->rs_uuid_en; /* For RDMA operation(s), add up rmda bytes to payload to make * sure its within system QoS threshold limits. @@ -1317,6 +1381,11 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len) goto out; } + if (conn->c_acl_init && rds_match_uuid(conn, rm)) { + ret = -EFAULT; + goto out; + } + /* Not accepting new sends until all the failed ops have been reaped */ if (rds_async_send_enabled && conn->c_pending_flush) { ret = -EAGAIN; @@ -1584,6 +1653,11 @@ rds_send_pong(struct rds_connection *conn, __be16 dport) conn->c_next_tx_seq++; spin_unlock_irqrestore(&conn->c_lock, flags); + if (conn->c_acl_en) { + memcpy(rm->uuid.value, conn->c_uuid, RDS_UUID_MAXLEN); + rm->uuid.enable = 1; + } + rds_stats_inc(s_send_queued); rds_stats_inc(s_send_pong); @@ -1635,6 +1709,11 @@ rds_send_hb(struct rds_connection *conn, int response) conn->c_next_tx_seq++; spin_unlock_irqrestore(&conn->c_lock, flags); + if (conn->c_acl_en) { + memcpy(rm->uuid.value, conn->c_uuid, RDS_UUID_MAXLEN); + rm->uuid.enable = 1; + } + ret = rds_send_xmit(conn); if (ret == -ENOMEM || ret == -EAGAIN) queue_delayed_work(rds_wq, &conn->c_send_w, 1); diff --git a/net/rds/sysctl.c b/net/rds/sysctl.c index b22e8b8b6b89d..e26122c706a67 100644 --- a/net/rds/sysctl.c +++ b/net/rds/sysctl.c @@ -52,6 +52,9 @@ unsigned int rds_sysctl_ping_enable = 1; unsigned int rds_sysctl_shutdown_trace_start_time; unsigned int rds_sysctl_shutdown_trace_end_time; +/* Do not drop packets on transmit */ +unsigned int rds_sysctl_uuid_tx_no_drop = 1; + /* * We have official values, but must maintain the sysctl interface for existing * software that expects to find these values here. @@ -127,6 +130,13 @@ static struct ctl_table rds_sysctl_rds_table[] = { .mode = 0644, .proc_handler = &proc_dointvec, }, + { + .procname = "uuid_tx_no_drop", + .data = &rds_sysctl_uuid_tx_no_drop, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, { } };