#include <asm-generic/sizes.h>
#include <rdma/rdma_cm_ib.h>
#include <rdma/ib_cache.h>
+#include <rdma/ib_cm.h>
#include "rds.h"
#include "ib.h"
ic->i_frag_sz = ib_init_frag_size;
}
+/*
+* 0 - all good copy uuid to the connection context
+* 1 - acl is not enabled, ignore uuid
+* -1 - acl match failed
+*/
+static int rds_ib_match_acl(struct rdma_cm_id *cm_id, u32 saddr, char* uuid)
+{
+ struct ib_cm_acl *acl = 0;
+ struct ib_cm_acl_elem *acl_elem = 0;
+ __be64 fguid = cm_id->route.path_rec->dgid.global.interface_id;
+ __be64 fsubnet = cm_id->route.path_rec->dgid.global.subnet_prefix;
+ struct ib_cm_dpp dpp;
+
+ ib_cm_dpp_init(&dpp, cm_id->device, cm_id->port_num,
+ ntohs(cm_id->route.path_rec->pkey));
+ acl = ib_cm_dpp_acl_lookup(&dpp);
+ if (!acl)
+ goto out;
+
+ if (!acl->enabled)
+ return 0;
+
+ acl_elem = ib_cm_acl_lookup(acl, be64_to_cpu(fsubnet),
+ be64_to_cpu(fguid));
+ if (!acl_elem)
+ goto out;
+
+ saddr = be32_to_cpu(saddr);
+ if (!saddr)
+ goto out;
+
+ acl_elem = ib_cm_acl_lookup_uuid_ip(acl, acl_elem->uuid, saddr);
+ if (!acl_elem)
+ goto out;
+
+ memcpy(uuid, acl_elem->uuid, UUID_SZ);
+ return 1;
+out:
+ pr_err("RDS/IB: %s failed due to ACL mismatch. Check ACLs\n", __func__);
+ return -1;
+}
+
/*
* Connection established.
* We get here for both outgoing and incoming connection.
}
}
- printk(KERN_NOTICE "RDS/IB: %s conn %p i_cm_id %p, frag %dKB, connected <%pI4,%pI4,%d> version %u.%u%s\n",
+ printk(KERN_NOTICE "RDS/IB: %s conn %p i_cm_id %p, frag %dKB, connected <%pI4,%pI4,%d> version %u.%u%s%s\n",
ic->i_active_side ? "Active " : "Passive",
conn, ic->i_cm_id, ic->i_frag_sz / SZ_1K,
&conn->c_laddr, &conn->c_faddr, conn->c_tos,
RDS_PROTOCOL_MAJOR(conn->c_version),
RDS_PROTOCOL_MINOR(conn->c_version),
- ic->i_flowctl ? ", flow control" : "");
+ ic->i_flowctl ? ", flow control" : "",
+ conn->c_acl_en ? ", ACL Enabled" : "");
/* The connection might have been dropped under us*/
if (!ic->i_cm_id) {
struct rdma_conn_param conn_param;
u32 version;
int err = 1, destroy = 1;
+ char uuid[UUID_SZ];
+ int acl_ret = 0;
/* Check whether the remote protocol version matches ours. */
version = rds_ib_protocol_compatible(event);
(unsigned long long)be64_to_cpu(fguid),
dp->dp_tos);
+ acl_ret = rds_ib_match_acl(cm_id, dp->dp_saddr, uuid);
+ if (acl_ret < 0) {
+ rdma_reject(cm_id, &acl_ret, sizeof(int));
+ rdsdebug("RDS: IB: rds_ib_match_acl failed\n");
+ goto out;
+ }
+
/* RDS/IB is not currently netns aware, thus init_net */
conn = rds_conn_create(&init_net, dp->dp_daddr, dp->dp_saddr,
&rds_ib_transport, dp->dp_tos, GFP_KERNEL);
rds_ib_set_protocol(conn, version);
rds_ib_set_frag_size(conn, be16_to_cpu(dp->dp_frag_sz));
+ memcpy(conn->c_uuid, uuid, RDS_UUID_MAXLEN);
+ conn->c_acl_en = acl_ret;
+ conn->c_acl_init = 1;
+
if (dp->dp_tos && !conn->c_base_conn) {
conn->c_base_conn = rds_conn_create(&init_net,
dp->dp_daddr, dp->dp_saddr,
struct rdma_conn_param conn_param;
struct rds_ib_connect_private dp;
int ret;
+ char uuid[UUID_SZ];
+
+ ret = rds_ib_match_acl(ic->i_cm_id, conn->c_faddr, uuid);
+ if (ret < 0) {
+ pr_err("RDS: IB: active conn=%p, <%u.%u.%u.%u,%u.%u.%u.%u,%d> destroyed due ACL violation\n",
+ conn, NIPQUAD(conn->c_laddr), NIPQUAD(conn->c_faddr),
+ conn->c_tos);
+ rds_ib_conn_destroy_init(conn);
+ return 0;
+ }
+
+ memcpy(conn->c_uuid, uuid, RDS_UUID_MAXLEN);
+ conn->c_acl_en = ret;
+ conn->c_acl_init = 1;
rds_ib_set_protocol(conn, RDS_PROTOCOL_4_1);
ic->i_flowctl = rds_ib_sysctl_flow_control; /* advertise flow control */