#include <linux/jhash.h>
#include "ipoib.h"
-int extract_guid_and_subnet(const char *buf, char *name, u64 *subnet_prefix,
- u64 *guid)
-{
- u64 gid[8];
- int i, shift;
-
- memset(&gid, 0, sizeof(gid));
-
- if (name) {
- if (sscanf(buf,
- "%s %4llx:%4llx:%4llx:%4llx:%4llx:%4llx:%4llx:%4llx",
- name, &gid[0], &gid[1], &gid[2], &gid[3], &gid[4],
- &gid[5], &gid[6], &gid[7]) != 9)
- return -EINVAL;
- } else
- if (sscanf(buf,
- "%4llx:%4llx:%4llx:%4llx:%4llx:%4llx:%4llx:%4llx",
- &gid[0], &gid[1], &gid[2], &gid[3], &gid[4], &gid[5],
- &gid[6], &gid[7]) != 8)
- return -EINVAL;
-
- *guid = 0;
- *subnet_prefix = 0;
- for (i = 0; i < 4; i++) {
- shift = ((3 - i) * 16);
- *subnet_prefix |= gid[i] << shift;
- *guid |= gid[i + 4] << shift;
- }
-
- return 0;
-}
-
-int extract_guid_subnet_and_ip(const char *buf, char *name, u64 *subnet_prefix,
- u64 *guid, u32 *src_ip, char *uuid)
-{
- u64 gid[8];
- u32 ip[4];
- int rc, i, shift;
-
- memset(&gid, 0, sizeof(gid));
- memset(&ip, 0, sizeof(ip));
- memset(uuid, 0, UUID_SZ);
-
- rc = sscanf(buf,
- "%s %4llx:%4llx:%4llx:%4llx:%4llx:%4llx:%4llx:%4llx %s %d.%d.%d.%d",
- name, &gid[0], &gid[1], &gid[2], &gid[3], &gid[4], &gid[5],
- &gid[6], &gid[7], uuid, &ip[0], &ip[1], &ip[2], &ip[3]);
- if (rc != 14)
- return -EINVAL;
-
- *guid = 0;
- *subnet_prefix = 0;
- for (i = 0; i < 4; i++) {
- shift = ((3 - i) * 16);
- *subnet_prefix |= gid[i] << shift;
- *guid |= gid[i + 4] << shift;
- }
-
- *src_ip = 0;
- for (i = 0; i < 4; i++) {
- shift = ((3 - i) * 8);
- *src_ip |= ip[i] << shift;
- }
-
- return 0;
-}
-
static ssize_t show_acl_enabled(struct device *d,
struct device_attribute *attr, char *buf)
{
static DEVICE_ATTR(acl_enabled, S_IWUSR | S_IRUGO, show_acl_enabled,
set_acl_enabled);
-static ssize_t add_acl(struct device *d, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(d));
- int rc;
- u64 guid, subnet_prefix;
- u32 ip;
- char uuid[UUID_SZ];
- struct ib_cm_acl *instance_acl;
- char name[INSTANCE_ACL_ID_SZ];
-
- rc = extract_guid_subnet_and_ip(buf, name, &subnet_prefix, &guid, &ip,
- uuid);
- if (rc != 0)
- return rc;
-
- instance_acl = ipoib_get_instance_acl(name, to_net_dev(d));
- if (!instance_acl)
- return -EINVAL;
-
- rc = ib_cm_acl_insert(instance_acl, subnet_prefix, guid, ip, uuid);
- rc |= ib_cm_acl_insert(&priv->acl, subnet_prefix, guid, ip, uuid);
- if (rc != 0)
- return rc;
-
- return count;
-}
-
-static DEVICE_ATTR(add_acl, S_IWUSR, NULL, add_acl);
-
-static ssize_t delete_acl(struct device *d, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(d));
- u64 guid, subnet_prefix;
- int rc;
- struct ib_cm_acl *instance_acl;
- char name[INSTANCE_ACL_ID_SZ];
-
- rc = extract_guid_and_subnet(buf, name, &subnet_prefix, &guid);
- if (rc != 0)
- return rc;
-
- instance_acl = ipoib_get_instance_acl(name, to_net_dev(d));
- if (!instance_acl)
- return -EINVAL;
-
- ib_cm_acl_delete(instance_acl, subnet_prefix, guid);
- ib_cm_acl_delete(&priv->acl, subnet_prefix, guid);
-
- return count;
-}
-
-static DEVICE_ATTR(delete_acl, S_IWUSR, NULL, delete_acl);
-
-void print_acl_to_buf(char *buf, const char *name, struct ib_cm_acl *acl)
-{
- struct ib_cm_acl_elem *list;
- ssize_t list_count, i;
- u8 *subnet_prefix, *guid;
- u8 *ip;
-
- ib_cm_acl_scan(acl, &list, &list_count);
- for (i = 0; i < list_count; i++) {
- subnet_prefix = (u8 *)&(list[i].subnet_prefix);
- guid = (u8 *)&(list[i].guid);
- ip = (u8 *)&(list[i].ip);
- sprintf(buf,
- "%s%s\t%d\t%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\t%s\t%d.%d.%d.%d\n",
- buf, name, list[i].ref_count, subnet_prefix[7],
- subnet_prefix[6], subnet_prefix[5], subnet_prefix[4],
- subnet_prefix[3], subnet_prefix[2], subnet_prefix[1],
- subnet_prefix[0], guid[7], guid[6], guid[5], guid[4],
- guid[3], guid[2], guid[1], guid[0], list[i].uuid,
- ip[3], ip[2], ip[1], ip[0]);
- }
- kfree(list);
-}
-
-static ssize_t show_acl(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(d));
- struct ipoib_instance_acl *results[ACL_BATCH_SZ];
- unsigned int count, i;
- unsigned long idx = 0;
-
- strcpy(buf, "");
-
- print_acl_to_buf(buf, DRIVER_ACL_NAME, &priv->acl);
-
- count = 0;
- do {
- count = radix_tree_gang_lookup(&priv->instances_acls.instances,
- (void **)results, idx,
- ACL_BATCH_SZ);
- for (i = 0; i < count; i++)
- print_acl_to_buf(buf, results[i]->name,
- &results[i]->acl);
- if (count)
- idx = jhash(results[i - 1]->name,
- strlen(results[i - 1]->name), 0) + 1;
- } while (count);
-
- return strlen(buf);
-}
-
-static DEVICE_ATTR(acl, S_IRUGO, show_acl, NULL);
-
void print_acl_instances_to_buf(char *buf, size_t sz,
struct ipoib_dev_priv *priv)
{
} while (count);
}
-static ssize_t show_acl_instances(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(d));
-
- /* Assumption here is that buf has enoght place to hold entire list */
- print_acl_instances_to_buf(buf, priv->instances_acls.list_count *
- INSTANCE_ACL_ID_SZ + 1, priv);
-
- return strlen(buf);
-}
-
-static DEVICE_ATTR(acl_instances, S_IRUGO, show_acl_instances, NULL);
-
-static ssize_t add_acl_instance(struct device *d, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- char name[INSTANCE_ACL_ID_SZ];
- char *crlf_pos = strchr(buf, '\n');
-
- strncpy(name, buf, INSTANCE_ACL_ID_SZ);
- if (crlf_pos)
- name[crlf_pos - buf] = 0;
- ipoib_create_instance_acl(name, to_net_dev(d));
-
- return count;
-}
-
-static DEVICE_ATTR(add_acl_instance, S_IWUSR, NULL, add_acl_instance);
-
-static ssize_t delete_acl_instance(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- char name[INSTANCE_ACL_ID_SZ];
- char *crlf_pos = strchr(buf, '\n');
-
- strncpy(name, buf, INSTANCE_ACL_ID_SZ);
- if (crlf_pos)
- name[crlf_pos - buf] = 0;
- ipoib_delete_instance_acl(name, to_net_dev(d));
-
- return count;
-}
-
-static DEVICE_ATTR(delete_acl_instance, S_IWUSR, NULL, delete_acl_instance);
-
int ipoib_create_acl_sysfs(struct net_device *dev)
{
- int rc = 0;
-
if (!ipoib_debug_level)
dev_attr_acl_enabled.attr.mode = 0444;
- rc = device_create_file(&dev->dev, &dev_attr_acl_enabled);
- if (rc)
- return rc;
-
- if (!ipoib_debug_level)
- return 0;
-
- rc = device_create_file(&dev->dev, &dev_attr_add_acl);
- if (rc)
- return rc;
- rc = device_create_file(&dev->dev, &dev_attr_delete_acl);
- if (rc)
- return rc;
- rc = device_create_file(&dev->dev, &dev_attr_acl);
- if (rc)
- return rc;
- rc = device_create_file(&dev->dev, &dev_attr_add_acl_instance);
- if (rc)
- return rc;
- rc = device_create_file(&dev->dev, &dev_attr_delete_acl_instance);
- if (rc)
- return rc;
- rc = device_create_file(&dev->dev, &dev_attr_acl_instances);
- if (rc)
- return rc;
-
- return 0;
+ return device_create_file(&dev->dev, &dev_attr_acl_enabled);
}
void delete_instance_acls(struct net_device *dev)