]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
IB/ipoib: ioctl interface to manage ACL tables
authorYuval Shaia <yuval.shaia@oracle.com>
Mon, 4 Apr 2016 13:40:56 +0000 (16:40 +0300)
committerChuck Anderson <chuck.anderson@oracle.com>
Tue, 12 Jul 2016 19:48:41 +0000 (12:48 -0700)
Expose ioctl to manage ACL content by application layer.

Orabug: 23222944

Signed-off-by: Yuval Shaia <yuval.shaia@oracle.com>
Reviewed-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
merge into IOCTL code

drivers/infiniband/ulp/ipoib/Makefile
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_ioctl.c [new file with mode: 0644]
drivers/infiniband/ulp/ipoib/ipoib_main.c

index a4145f2b31d9a084c2ae1d40e7be1965d02de4e5..dab3dee987c7a342d2efb98afa3f038410ea0043 100644 (file)
@@ -6,6 +6,7 @@ ib_ipoib-y                                      := ipoib_main.o \
                                                   ipoib_verbs.o \
                                                   ipoib_vlan.o \
                                                   ipoib_ethtool.o \
+                                                  ipoib_ioctl.o \
                                                   ipoib_acl.o \
                                                   ipoib_netlink.o
 ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_CM)         += ipoib_cm.o
index bfdf3e4437b4fe04efa437838109f7bcaf111181..59f7b94e5ff48483465cf3582b8f766c91a764c4 100644 (file)
@@ -130,6 +130,19 @@ enum {
 
 #define IPOIB_QPN_MASK ((__force u32) cpu_to_be32(0xFFFFFF))
 
+/* AC ioctl commands */
+#define IPOIBACIOCTLSTART      (SIOCDEVPRIVATE)
+#define IPOIBSTATUSGET         (IPOIBACIOCTLSTART + 0)
+#define IPOIBSTATUSSET         (IPOIBACIOCTLSTART + 1)
+#define IPOIBACLINSTSZ         (IPOIBACIOCTLSTART + 2)
+#define IPOIBACLINSTGET                (IPOIBACIOCTLSTART + 3)
+#define IPOIBACLINSTADD                (IPOIBACIOCTLSTART + 4)
+#define IPOIBACLINSTDEL                (IPOIBACIOCTLSTART + 5)
+#define IPOIBACLSZ             (IPOIBACIOCTLSTART + 6)
+#define IPOIBACLGET            (IPOIBACIOCTLSTART + 7)
+#define IPOIBACLADD            (IPOIBACIOCTLSTART + 8)
+#define IPOIBACLDEL            (IPOIBACIOCTLSTART + 9)
+
 /* structs */
 
 struct ipoib_header {
@@ -481,6 +494,27 @@ struct ipoib_neigh {
        unsigned long       alive;
 };
 
+/* ACL ioctl API */
+struct ipoib_ioctl_req_data {
+       char    acl_enabled;
+       u32     sz;
+       u32     from_idx;
+       u64     *guids;
+       u64     *subnet_prefixes;
+       u32     *ips;
+       char    *uuids;
+       char    instance_name[INSTANCE_ACL_ID_SZ];
+       char    *instances_names;
+};
+
+struct ipoib_ioctl_req {
+       union {
+               char    frn_name[IFNAMSIZ];
+       } ifr_ifrn;
+
+       struct ipoib_ioctl_req_data *req_data;
+};
+
 #define IPOIB_UD_MTU(ib_mtu)           (ib_mtu - IPOIB_ENCAP_LEN)
 #define IPOIB_UD_BUF_SIZE(ib_mtu)      (ib_mtu + IB_GRH_BYTES)
 
@@ -529,6 +563,7 @@ static inline void ipoib_put_ah(struct ipoib_ah *ah)
 int ipoib_open(struct net_device *dev);
 int ipoib_add_pkey_attr(struct net_device *dev);
 int ipoib_add_umcast_attr(struct net_device *dev);
+int ipoib_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 
 void ipoib_send(struct net_device *dev, struct sk_buff *skb,
                struct ipoib_ah *address, u32 qpn);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ioctl.c b/drivers/infiniband/ulp/ipoib/ipoib_ioctl.c
new file mode 100644 (file)
index 0000000..993d990
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <net/arp.h>
+#include <linux/jhash.h>
+
+#include "ipoib.h"
+
+int ipoib_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+       struct ipoib_ioctl_req *rq = (struct ipoib_ioctl_req *)ifr;
+       struct ipoib_ioctl_req_data req_data;
+       struct ipoib_dev_priv *priv = netdev_priv(dev);
+       int rc = 0;
+       struct ib_cm_acl_elem *list;
+       ssize_t list_count, i;
+       u64 guid, subnet_prefix;
+       u32 ip;
+       char uuid[UUID_SZ];
+       struct ib_cm_acl *acl;
+       char *buf;
+
+       rc = copy_from_user(&req_data, rq->req_data,
+                           sizeof(struct ipoib_ioctl_req_data));
+       if (rc != 0) {
+               ipoib_warn(priv, "ioctl fail to copy request data\n");
+               return -EINVAL;
+       }
+
+       switch (cmd) {
+       case IPOIBSTATUSGET:
+               req_data.acl_enabled = priv->acl.enabled;
+               break;
+       case IPOIBSTATUSSET:
+               priv->acl.enabled = req_data.acl_enabled;
+               break;
+       case IPOIBACLINSTSZ:
+               req_data.sz = priv->instances_acls.list_count;
+               break;
+       case IPOIBACLINSTGET:
+               buf = kmalloc(req_data.sz, GFP_KERNEL);
+               print_acl_instances_to_buf(buf, req_data.sz, priv);
+               rc = copy_to_user(req_data.instances_names, buf, req_data.sz);
+               kfree(buf);
+               if (rc) {
+                       ipoib_warn(priv,
+                                  "ioctl fail to copy instances names to userspace\n");
+                       return -EINVAL;
+               }
+               break;
+       case IPOIBACLINSTADD:
+               rc = ipoib_create_instance_acl(req_data.instance_name, dev);
+               if (rc != 0)
+                       return -EINVAL;
+               break;
+       case IPOIBACLINSTDEL:
+               rc = ipoib_delete_instance_acl(req_data.instance_name, dev);
+               if (rc != 0)
+                       return -EINVAL;
+               break;
+       case IPOIBACLSZ:
+               if (!strcmp(req_data.instance_name, DRIVER_ACL_NAME))
+                       acl = &priv->acl;
+               else
+                       acl = ipoib_get_instance_acl(req_data.instance_name,
+                                                    dev);
+               if (!acl)
+                       return -EINVAL;
+
+               ib_cm_acl_scan(acl, &list, &list_count);
+               kfree(list);
+               req_data.sz = list_count;
+               break;
+       case IPOIBACLGET:
+               if (!strcmp(req_data.instance_name, DRIVER_ACL_NAME))
+                       acl = &priv->acl;
+               else
+                       acl = ipoib_get_instance_acl(req_data.instance_name,
+                                                    dev);
+               if (!acl)
+                       return -EINVAL;
+
+               ib_cm_acl_scan(acl, &list, &list_count);
+               for (i = req_data.from_idx; (i < list_count) &&
+                    (i < req_data.sz) ; i++) {
+                       rc = copy_to_user(&req_data.subnet_prefixes[i -
+                                         req_data.from_idx],
+                                         &(list[i].subnet_prefix),
+                                         sizeof(u64));
+                       rc |= copy_to_user(&req_data.guids[i -
+                                          req_data.from_idx], &(list[i].guid),
+                                          sizeof(u64));
+                       rc |= copy_to_user(&req_data.ips[i -
+                                          req_data.from_idx], &(list[i].ip),
+                                          sizeof(u32));
+                       rc |= copy_to_user((req_data.uuids + i * UUID_SZ),
+                                          list[i].uuid, UUID_SZ);
+                       if (rc) {
+                               ipoib_warn(priv,
+                                          "ioctl fail to copy index %ld to userspace\n",
+                                          i);
+                               kfree(list);
+                               return -EINVAL;
+                       }
+               }
+               kfree(list);
+               req_data.sz = i - req_data.from_idx;
+               break;
+       case IPOIBACLADD:
+               acl = ipoib_get_instance_acl(req_data.instance_name, dev);
+               if (!acl)
+                       return -EINVAL;
+
+               for (i = 0; i < req_data.sz; i++) {
+                       rc = copy_from_user(&subnet_prefix,
+                                           &req_data.subnet_prefixes[i],
+                                           sizeof(u64));
+                       rc |= copy_from_user(&guid, &req_data.guids[i],
+                                            sizeof(u64));
+                       rc |= copy_from_user(&ip, &req_data.ips[i],
+                                            sizeof(u32));
+                       rc |= copy_from_user(&uuid,
+                                            (req_data.uuids + i * UUID_SZ),
+                                            UUID_SZ);
+                       if (rc) {
+                               ipoib_warn(priv,
+                                          "ioctl fail to copy index %ld from userspace\n",
+                                          i);
+                               return -EINVAL;
+                       }
+                       rc = ib_cm_acl_insert(acl, subnet_prefix, guid, ip,
+                                             uuid);
+                       rc |= ib_cm_acl_insert(&priv->acl, subnet_prefix, guid,
+                                              ip, uuid);
+                       if (rc) {
+                               ipoib_warn(priv,
+                                          "ioctl fail to insert index %ld to ACL\n",
+                                          i);
+                               return -EINVAL;
+                       }
+               }
+               break;
+       case IPOIBACLDEL:
+               acl = ipoib_get_instance_acl(req_data.instance_name, dev);
+               if (!acl)
+                       return -EINVAL;
+
+               for (i = 0; i < req_data.sz; i++) {
+                       rc = copy_from_user(&subnet_prefix,
+                                           &req_data.subnet_prefixes[i],
+                                           sizeof(u64));
+                       rc |= copy_from_user(&guid, &req_data.guids[i],
+                                            sizeof(u64));
+                       if (rc) {
+                               ipoib_warn(priv,
+                                          "ioctl fail to copy index %ld from userspace\n",
+                                          i);
+                               return -EINVAL;
+                       }
+                       ib_cm_acl_delete(acl, subnet_prefix, guid);
+                       ib_cm_acl_delete(&priv->acl, subnet_prefix, guid);
+               }
+               break;
+       default:
+               ipoib_dbg(priv, "invalid ioctl opcode 0x%x\n", cmd);
+               rc = -EINVAL;
+               break;
+       }
+
+       rc = copy_to_user(rq->req_data, &req_data,
+                         sizeof(struct ipoib_ioctl_req_data));
+       if (rc != 0) {
+               ipoib_warn(priv, "ioctl fail to copy back request data\n");
+               return -EINVAL;
+       }
+
+       return rc;
+}
index 24f15841889928087947fe5063c7f5519707a82d..721a6eacad97114a81b1cff37fd9e949c9b3c001 100644 (file)
@@ -1433,6 +1433,7 @@ static const struct net_device_ops ipoib_netdev_ops = {
        .ndo_tx_timeout          = ipoib_timeout,
        .ndo_set_rx_mode         = ipoib_set_mcast_list,
        .ndo_get_iflink          = ipoib_get_iflink,
+       .ndo_do_ioctl            = ipoib_do_ioctl,
 };
 
 void ipoib_setup(struct net_device *dev)