__be32 random_id_operand;
struct list_head timewait_list;
struct workqueue_struct *wq;
- struct list_head dpp_acl_map;
} cm;
/* Counter indexes ordered by attribute ID */
kfree(work);
}
-void ib_cm_acl_init(struct ib_cm_acl *acl)
-{
- acl->enabled = 0;
- acl->allowed_list = RB_ROOT;
- acl->list_count = 0;
- spin_lock_init(&acl->lock);
-}
-EXPORT_SYMBOL(ib_cm_acl_init);
-
-int ib_cm_acl_insert(struct ib_cm_acl *acl, u64 subnet_prefix, u64 guid, u32 ip,
- const char *uuid)
-{
- struct ib_cm_acl_elem *elem;
- struct rb_node **new, *parent = NULL;
- int rc = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&acl->lock, flags);
-
- new = &(acl->allowed_list.rb_node);
-
- while (*new) {
- elem = rb_entry(*new, struct ib_cm_acl_elem, node);
-
- parent = *new;
- if ((guid == elem->guid) &&
- (subnet_prefix == elem->subnet_prefix)) {
- elem->ref_count++;
- goto exist;
- }
-
- if (subnet_prefix == elem->subnet_prefix)
- if (guid > elem->guid)
- new = &((*new)->rb_right);
- else
- new = &((*new)->rb_left);
- else if (subnet_prefix > elem->subnet_prefix)
- new = &((*new)->rb_right);
- else
- new = &((*new)->rb_left);
- }
-
- elem = kmalloc(sizeof(struct ib_cm_acl_elem), GFP_ATOMIC);
- if (!elem)
- goto err_nomem;
- elem->guid = guid;
- elem->subnet_prefix = subnet_prefix;
- elem->ip = ip;
- memcpy(elem->uuid, uuid, UUID_SZ);
- elem->ref_count = 1;
- rb_link_node(&elem->node, parent, new);
- rb_insert_color(&elem->node, &acl->allowed_list);
- acl->list_count++;
-
- goto out;
-
-err_nomem:;
- rc = -ENOMEM;
-
-exist:
-
-out:
- spin_unlock_irqrestore(&acl->lock, flags);
- return rc;
-}
-EXPORT_SYMBOL(ib_cm_acl_insert);
-
-struct ib_cm_acl_elem *_ib_cm_acl_lookup(struct ib_cm_acl *acl,
- u64 subnet_prefix, u64 guid)
-{
- struct rb_node *node;
- struct ib_cm_acl_elem *elem;
-
- node = acl->allowed_list.rb_node;
-
- while (node) {
- elem = rb_entry(node, struct ib_cm_acl_elem, node);
- if ((guid == elem->guid) &&
- (subnet_prefix == elem->subnet_prefix))
- return elem;
-
- if (subnet_prefix == elem->subnet_prefix)
- if (guid > elem->guid)
- node = node->rb_right;
- else
- node = node->rb_left;
- else if (subnet_prefix > elem->subnet_prefix)
- node = node->rb_right;
- else
- node = node->rb_left;
- }
-
- return NULL;
-}
-
-struct ib_cm_acl_elem *ib_cm_acl_lookup(struct ib_cm_acl *acl,
- u64 subnet_prefix, u64 guid)
-{
- struct ib_cm_acl_elem *elem;
- unsigned long flags;
-
- spin_lock_irqsave(&acl->lock, flags);
- elem = _ib_cm_acl_lookup(acl, subnet_prefix, guid);
- spin_unlock_irqrestore(&acl->lock, flags);
-
- return elem;
-}
-EXPORT_SYMBOL(ib_cm_acl_lookup);
-
-struct ib_cm_acl_elem *ib_cm_acl_lookup_uuid_ip(struct ib_cm_acl *acl,
- char *uuid, u32 ip)
-{
- struct ib_cm_acl_elem *elem, *ret = NULL;
- struct rb_node *node;
- unsigned long flags;
-
- spin_lock_irqsave(&acl->lock, flags);
- node = rb_first(&acl->allowed_list);
- while (node) {
- elem = container_of(node, struct ib_cm_acl_elem, node);
- if ((ip == elem->ip) && (!memcmp(uuid, elem->uuid, UUID_SZ))) {
- ret = elem;
- goto out;
- }
- node = rb_next(node);
- }
-
-out:
- spin_unlock_irqrestore(&acl->lock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL(ib_cm_acl_lookup_uuid_ip);
-
-int ib_cm_acl_delete(struct ib_cm_acl *acl, u64 subnet_prefix, u64 guid)
-{
- struct ib_cm_acl_elem *elem;
- int ref_count = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&acl->lock, flags);
- elem = _ib_cm_acl_lookup(acl, subnet_prefix, guid);
- if (elem) {
- elem->ref_count--;
- ref_count = elem->ref_count;
- if (elem->ref_count == 0) {
- rb_erase(&elem->node, &acl->allowed_list);
- kfree(elem);
- acl->list_count--;
- }
- }
- spin_unlock_irqrestore(&acl->lock, flags);
- return ref_count;
-}
-EXPORT_SYMBOL(ib_cm_acl_delete);
-
-void ib_cm_acl_scan(struct ib_cm_acl *acl, struct ib_cm_acl_elem **list,
- ssize_t *list_count)
-{
- struct ib_cm_acl_elem *elem, *list_elem;
- struct rb_node *node;
- unsigned long flags;
-
- spin_lock_irqsave(&acl->lock, flags);
- *list = kmalloc_array(acl->list_count, sizeof(struct ib_cm_acl_elem),
- GFP_ATOMIC);
- if (!*list) {
- *list_count = 0;
- spin_unlock_irqrestore(&acl->lock, flags);
- pr_crit("Fail to allocate memory for acl_scan\n");
- return;
- }
- list_elem = *list;
- node = rb_first(&acl->allowed_list);
- while (node) {
- elem = container_of(node, struct ib_cm_acl_elem, node);
- list_elem->guid = elem->guid;
- list_elem->subnet_prefix = elem->subnet_prefix;
- list_elem->ip = elem->ip;
- memcpy(list_elem->uuid, elem->uuid, UUID_SZ);
- list_elem->ref_count = elem->ref_count;
- list_elem++;
- node = rb_next(node);
- }
-
- *list_count = acl->list_count;
- spin_unlock_irqrestore(&acl->lock, flags);
-}
-EXPORT_SYMBOL(ib_cm_acl_scan);
-
-void ib_cm_acl_clean(struct ib_cm_acl *acl)
-{
- struct ib_cm_acl_elem *elem;
- struct rb_node *node, *curr;
- unsigned long flags;
-
- spin_lock_irqsave(&acl->lock, flags);
- node = rb_first(&acl->allowed_list);
- while (node) {
- curr = node;
- node = rb_next(node);
- elem = container_of(curr, struct ib_cm_acl_elem, node);
- rb_erase(curr, &acl->allowed_list);
- kfree(elem);
- }
-
- acl->list_count = 0;
- spin_unlock_irqrestore(&acl->lock, flags);
-}
-EXPORT_SYMBOL(ib_cm_acl_clean);
-
-int ib_cm_register_acl(struct ib_cm_acl *acl, struct ib_cm_dpp *dpp)
-{
- struct ib_cm_dpp_acl *dpp_acl;
-
- dpp_acl = kzalloc(sizeof(struct ib_cm_dpp_acl), GFP_KERNEL);
- if (unlikely(!dpp_acl))
- return -ENOMEM;
-
- ib_cm_dpp_dbg("Registering ACL", dpp);
-
- ib_cm_dpp_copy(&dpp_acl->dpp, dpp);
- dpp_acl->acl = acl;
- list_add(&dpp_acl->list, &cm.dpp_acl_map);
-
- return 0;
-}
-EXPORT_SYMBOL(ib_cm_register_acl);
-
-struct ib_cm_acl *ib_cm_dpp_acl_lookup(struct ib_cm_dpp *dpp)
-{
- struct ib_cm_dpp_acl *dpp_acl;
-
- list_for_each_entry(dpp_acl, &cm.dpp_acl_map, list) {
- if (ib_cm_dpp_compare(&dpp_acl->dpp, dpp))
- return dpp_acl->acl;
- }
-
- return NULL;
-}
-EXPORT_SYMBOL(ib_cm_dpp_acl_lookup);
-
-void ib_cm_unregister_acl(struct ib_cm_acl *acl)
-{
- struct ib_cm_dpp_acl *dpp_acl, *tmp;
-
- list_for_each_entry_safe(dpp_acl, tmp, &cm.dpp_acl_map, list) {
- if (dpp_acl->acl == acl) {
- ib_cm_dpp_dbg("Unregistering ACL", &dpp_acl->dpp);
- list_del(&dpp_acl->list);
- kfree(dpp_acl);
- }
- }
-}
-EXPORT_SYMBOL(ib_cm_unregister_acl);
-
-static void ib_cm_dpp_acl_cleanup(void)
-{
- struct ib_cm_dpp_acl *dpp_acl;
-
- list_for_each_entry(dpp_acl, &cm.dpp_acl_map, list) {
- kfree(dpp_acl);
- }
-}
-
static inline int cm_convert_to_ms(int iba_time)
{
/* approximate conversion to ms from 4.096us x 2^iba_time */
}
}
-static char const cm_drop_reason_desc[4][32] = {
- "N/A",
- "No GRH",
- "grh.guid != mad.guid",
- "acl drop"
-};
-
-enum cm_drop_reason {
- CM_DROP_ACCEPT,
- CM_DROP_NO_GRH,
- CM_DROP_INV_MAD_GUID,
- CM_DROP_ACL
-};
-
-static enum cm_drop_reason cm_acl_filter(struct cm_work *work)
-{
- struct cm_req_msg *req_msg;
- struct ib_grh *grh;
- struct ib_cm_dpp dpp;
- struct ib_cm_acl *acl;
- u64 subnet_prefix = 0, guid = 0;
- struct ib_wc *wc;
- enum cm_drop_reason drop = CM_DROP_ACCEPT;
-
- req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
- grh = (struct ib_grh *)work->mad_recv_wc->recv_buf.grh;
- wc = (struct ib_wc *)work->mad_recv_wc->wc;
-
- ib_cm_dpp_init(&dpp, work->port->cm_dev->ib_device,
- work->port->port_num, be16_to_cpu(req_msg->pkey));
- ib_cm_dpp_dbg("CM Request from interface", &dpp);
- acl = ib_cm_dpp_acl_lookup(&dpp);
- if (acl && acl->enabled) {
- if (!(wc->wc_flags & IB_WC_GRH))
- drop = CM_DROP_NO_GRH;
- else if (grh->sgid.global.interface_id !=
- req_msg->primary_local_gid.global.interface_id)
- drop = CM_DROP_INV_MAD_GUID;
- else {
- subnet_prefix = be64_to_cpu(req_msg->
- primary_local_gid.global.
- subnet_prefix);
- guid = be64_to_cpu(req_msg->primary_local_gid.global.
- interface_id);
- if (!ib_cm_acl_lookup(acl, subnet_prefix, guid))
- drop = CM_DROP_ACL;
- }
-
- if (drop) {
- pr_debug("Blocked CM request, reason=%s\n",
- cm_drop_reason_desc[drop]);
- pr_debug("\tgrh.sgid=(0x%llx,0x%llx), grh.dgid=(0x%llx,0x%llx)\n",
- be64_to_cpu(grh->sgid.global.subnet_prefix),
- be64_to_cpu(grh->sgid.global.interface_id),
- be64_to_cpu(grh->dgid.global.subnet_prefix),
- be64_to_cpu(grh->dgid.global.interface_id));
- pr_debug("\tlocal=(0x%llx,0x%llx), remote=(0x%llx,0x%llx)\n",
- be64_to_cpu(req_msg->primary_local_gid.global.
- subnet_prefix),
- be64_to_cpu(req_msg->primary_local_gid.global.
- interface_id),
- be64_to_cpu(req_msg->primary_remote_gid.global.
- subnet_prefix),
- be64_to_cpu(req_msg->primary_remote_gid.global.
- interface_id));
- }
- }
-
- return drop;
-}
-
static int cm_req_handler(struct cm_work *work)
{
struct ib_cm_id *cm_id;
struct cm_id_private *cm_id_priv, *listen_cm_id_priv;
struct cm_req_msg *req_msg;
- int ret = 0;
-
- ret = cm_acl_filter(work);
- if (ret)
- return -EINVAL;
+ int ret;
req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
idr_init(&cm.local_id_table);
get_random_bytes(&cm.random_id_operand, sizeof cm.random_id_operand);
INIT_LIST_HEAD(&cm.timewait_list);
- INIT_LIST_HEAD(&cm.dpp_acl_map);
ret = class_register(&cm_class);
if (ret) {
{
struct cm_timewait_info *timewait_info, *tmp;
- ib_cm_dpp_acl_cleanup();
-
spin_lock_irq(&cm.lock);
list_for_each_entry(timewait_info, &cm.timewait_list, list)
cancel_delayed_work(&timewait_info->work.work);
static int get_low_record_time_index(struct mlx4_ib_dev *dev, u8 port,
int *resched_delay_sec);
-/*
- * Generate GUID by changing the fourth byte to be the GUID index in the
- * port GUID table.
- *
- * For example:
- * 00:02:C9:03:YY:XX:XX:XX
- * Where:
- * 00:02:C9:03 - Mellanox prefix GUID
- * YY - is the GUID index in the GUID table
- * XX:XX:XX - rest of the original GUID
- */
-__be64 generate_guid(struct mlx4_ib_dev *dev, int port_num, int record_index)
-{
- static union ib_gid gid = {.raw={0}};
- __be64 gen_guid = 0;
- static int queried_port = 1;
-
- /* If the gid of this port was not already queried -
- query and act accordingly */
- if ((!gid.global.interface_id || (queried_port != port_num)) &&
- dev->ib_dev.query_gid(&dev->ib_dev, port_num, 0, &gid))
- goto exit;
-
- if (mlx4_ib_guid_gen_magic < 0x64)
- goto exit;
-
- queried_port = port_num;
- gen_guid = gid.global.interface_id;
- ((u8 *)(&gen_guid))[4] = mlx4_ib_guid_gen_magic +
- (record_index % NUM_ALIAS_GUID_IN_REC);
-
- pr_debug("record: %d, port_guid: 0x%llx generated: 0x%llx",
- record_index, be64_to_cpu(gid.global.interface_id),
- be64_to_cpu(gen_guid));
-
-exit:
- return gen_guid;
-}
-
void mlx4_ib_update_cache_on_guid_change(struct mlx4_ib_dev *dev, int block_num,
u8 port_num, u8 *p_data)
{
int ret = 0;
int i, j;
union ib_gid gid;
- __be64 gen_guid;
if (!mlx4_is_master(dev->dev))
return 0;
if (mlx4_ib_sm_guid_assign)
for (j = 1; j < NUM_ALIAS_GUID_PER_PORT; j++)
mlx4_set_admin_guid(dev->dev, 0, j, i + 1);
- else {
- for (j = 0; j < NUM_ALIAS_GUID_PER_PORT; j++) {
- gen_guid = generate_guid(dev, i + 1, j);
- if (!gen_guid)
- continue;
- mlx4_set_admin_guid(dev->dev, gen_guid, j,
- i + 1);
- *(__be64 *)&dev->sriov.alias_guid.ports_guid[i].
- all_rec_per_port[j].
- all_recs[(j % 8) * GUID_REC_SIZE] =
- gen_guid;
- }
- }
for (j = 0 ; j < NUM_ALIAS_GUID_REC_IN_PORT; j++)
invalidate_guid_record(dev, i + 1, j);
module_param_named(sm_guid_assign, mlx4_ib_sm_guid_assign, int, 0444);
MODULE_PARM_DESC(sm_guid_assign, "Enable SM alias_GUID assignment if sm_guid_assign > 0 (Default: 0)");
-int mlx4_ib_guid_gen_magic = 90;
-module_param_named(guid_gen_magic, mlx4_ib_guid_gen_magic, int, 0444);
-MODULE_PARM_DESC(guid_gen_magic,
- "Magic num to add to the generated guid, default is 100.");
-
static const char mlx4_ib_version[] =
DRV_NAME ": Mellanox ConnectX InfiniBand driver v"
DRV_VERSION " (" DRV_RELDATE ")\n";
/*module param to indicate if SM assigns the alias_GUID*/
extern int mlx4_ib_sm_guid_assign;
-/*module param for generating even GUIDs, Oracle only*/
-extern int mlx4_ib_guid_gen_magic;
-
#define MLX4_IB_UC_STEER_QPN_ALIGN 1
#define MLX4_IB_UC_MAX_NUM_QPS (256 * 1024)
struct mlx4_ib_ucontext {
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
ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_DEBUG) += ipoib_fs.o
#include <linux/kref.h>
#include <linux/if_infiniband.h>
#include <linux/mutex.h>
-#include <linux/radix-tree.h>
#include <net/neighbour.h>
#include <net/sch_generic.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_pack.h>
#include <rdma/ib_sa.h>
-#include <rdma/ib_cm.h>
#include <linux/sched.h>
/* constants */
IPOIB_NON_CHILD = 0,
IPOIB_LEGACY_CHILD = 1,
IPOIB_RTNL_CHILD = 2,
-
- ACL_BATCH_SZ = 100,
};
#define IPOIB_OP_RECV (1ul << 31)
#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 {
struct ipoib_dev_priv *priv;
};
-#define DRIVER_ACL_NAME "_main_"
-#define INSTANCE_ACL_ID_SZ 80
-struct ipoib_instance_acl {
- char name[INSTANCE_ACL_ID_SZ];
- struct ib_cm_acl acl;
-};
-
-struct ipoib_instances_acls {
- struct radix_tree_root instances; /* list of ipoib_instance_acl */
- size_t list_count;
- struct mutex lock;
-};
-
/*
* Device private locking: network stack tx_lock protects members used
* in TX fast path, lock protects everything else. lock nests inside
unsigned max_send_sge;
/* Device specific; obtained from query_device */
unsigned max_sge;
- struct ib_cm_acl acl;
- /* Used to diaplay instance ACLs, no actual use in driver */
- struct ipoib_instances_acls instances_acls;
- int arp_blocked;
- int arp_accepted;
- int ud_blocked;
};
struct ipoib_ah {
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)
-void print_acl_instances_to_buf(char *buf, size_t sz,
- struct ipoib_dev_priv *priv);
-
void ipoib_neigh_dtor(struct ipoib_neigh *neigh);
static inline void ipoib_neigh_put(struct ipoib_neigh *neigh)
{
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);
/* We don't support UC connections at the moment */
#define IPOIB_CM_SUPPORTED(ha) (ha[0] & (IPOIB_FLAGS_RC))
-int ipoib_create_acl_sysfs(struct net_device *dev);
-void ipoib_init_acl(struct net_device *dev);
-void ipoib_clean_acl(struct net_device *dev);
-int ipoib_create_instance_acl(const char *name, struct net_device *dev);
-int ipoib_delete_instance_acl(const char *name, struct net_device *dev);
-struct ib_cm_acl *ipoib_get_instance_acl(const char *name,
- struct net_device *dev);
-
#ifdef CONFIG_INFINIBAND_IPOIB_CM
extern int ipoib_max_conn_qp;
printk(level "%s: " format, ipoib_dev_name(priv), ## arg)
#define ipoib_warn(priv, format, arg...) \
ipoib_printk(KERN_WARNING, priv, format , ## arg)
-#define ipoib_err(priv, format, arg...) \
- ipoib_printk(KERN_ERR, priv, format, ## arg)
#define ipoib_warn_ratelimited(priv, format, arg...) \
pr_warn_ratelimited("%s: " format, ipoib_dev_name(priv), ## arg)
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#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)
-{
- struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(d));
-
- if (priv->acl.enabled)
- return sprintf(buf, "1\n");
- else
- return sprintf(buf, "0\n");
-}
-
-static ssize_t set_acl_enabled(struct device *d, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(d));
-
- priv->acl.enabled = strcmp(buf, "0\n");
- return count;
-}
-
-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)
-{
- struct ipoib_instance_acl *results[ACL_BATCH_SZ];
- unsigned int count, i;
- unsigned long idx = 0;
-
- if (sz == 0)
- return;
-
- strcpy(buf, "");
-
- count = 0;
- do {
- count = radix_tree_gang_lookup(&priv->instances_acls.instances,
- (void **)results, idx,
- ACL_BATCH_SZ);
- for (i = 0; i < count; i++) {
- if (sz &&
- (strlen(buf) + strlen(results[i]->name) + 1) > sz)
- return;
- sprintf(buf, "%s%s\n", buf, results[i]->name);
- }
-
- if (count)
- idx = jhash(results[i - 1]->name,
- strlen(results[i - 1]->name), 0) + 1;
- } 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;
-
- rc = device_create_file(&dev->dev, &dev_attr_acl_enabled);
- if (rc)
- return rc;
- 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;
-}
-
-void delete_instance_acls(struct net_device *dev)
-{
- struct ipoib_dev_priv *priv = netdev_priv(dev);
- struct ipoib_instance_acl *results[ACL_BATCH_SZ];
- unsigned int count, i;
- unsigned long idx = 0;
-
- count = 0;
- do {
- count = radix_tree_gang_lookup(&priv->instances_acls.instances,
- (void **)results, idx,
- ACL_BATCH_SZ);
- for (i = 0; i < count; i++) {
- ipoib_dbg(priv, "Clean instance ACL %s\n",
- results[i]->name);
- ipoib_delete_instance_acl(results[i]->name, dev);
- }
- if (count)
- idx = jhash(results[i - 1]->name,
- strlen(results[i - 1]->name), 0) + 1;
- } while (count);
-}
-
-int ipoib_create_instance_acl(const char *name, struct net_device *dev)
-{
- u32 inst_name_hash;
- struct ipoib_instance_acl *instance_acl;
- struct ipoib_dev_priv *priv = netdev_priv(dev);
- int rc = 0;
-
- if (strlen(name) > INSTANCE_ACL_ID_SZ)
- return -EINVAL;
-
- inst_name_hash = jhash(name, strlen(name), 0);
- mutex_lock(&priv->instances_acls.lock);
- if (radix_tree_lookup(&priv->instances_acls.instances, inst_name_hash))
- goto err_exist;
-
- instance_acl = (struct ipoib_instance_acl *)
- kmalloc(sizeof(struct ipoib_instance_acl), GFP_KERNEL);
- if (!instance_acl)
- goto err_nomem;
-
- strcpy(instance_acl->name, name);
- ib_cm_acl_init(&instance_acl->acl);
-
- rc = radix_tree_insert(&priv->instances_acls.instances, inst_name_hash,
- instance_acl);
- if (rc != 0)
- goto err_radix;
-
- priv->instances_acls.list_count++;
-
- __module_get(THIS_MODULE);
-
- goto out;
-
-err_exist:
- ipoib_err(priv, "Instance ACL %s already exist\n", name);
- rc = -EEXIST;
- goto out;
-
-err_nomem:
- ipoib_err(priv, "No memory to create Instance ACL %s\n", name);
- rc = -ENOMEM;
- goto out;
-
-err_radix:
- ipoib_err(priv, "Error %d while trying to add %s\n", rc, name);
- kfree(instance_acl);
-
-out:
- mutex_unlock(&priv->instances_acls.lock);
- return rc;
-}
-
-int ipoib_delete_instance_acl(const char *name, struct net_device *dev)
-{
- u32 inst_name_hash;
- struct ipoib_instance_acl *instance_acl;
- struct ipoib_dev_priv *priv = netdev_priv(dev);
- struct ib_cm_acl_elem *list;
- ssize_t list_count, i;
- int rc = 0;
-
- inst_name_hash = jhash(name, strlen(name), 0);
- mutex_lock(&priv->instances_acls.lock);
- instance_acl = (struct ipoib_instance_acl *)
- radix_tree_delete(&priv->instances_acls.instances,
- inst_name_hash);
- if (!instance_acl)
- goto err_notexist;
-
- /* Decrease reference count in main ACL */
- ib_cm_acl_scan(&instance_acl->acl, &list, &list_count);
- for (i = 0; i < list_count; i++) {
- /* Clean all referrence */
- do
- ib_cm_acl_delete(&priv->acl, list[i].subnet_prefix,
- list[i].guid);
- while (ib_cm_acl_delete(&(instance_acl->acl),
- list[i].subnet_prefix, list[i].guid));
- }
- kfree(list);
-
- ib_cm_acl_clean(&(instance_acl->acl));
-
- kfree(instance_acl);
-
- priv->instances_acls.list_count--;
-
- module_put(THIS_MODULE);
-
- goto out;
-
-err_notexist:
- ipoib_err(priv, "Instance ACL %s is not exist\n", name);
- rc = -EINVAL;
- goto out;
-
-out:
- mutex_unlock(&priv->instances_acls.lock);
- return rc;
-}
-
-struct ib_cm_acl *ipoib_get_instance_acl(const char *name,
- struct net_device *dev)
-{
- u32 inst_name_hash;
- struct ipoib_instance_acl *instance_acl;
- struct ipoib_dev_priv *priv = netdev_priv(dev);
-
- inst_name_hash = jhash(name, strlen(name), 0);
- mutex_lock(&priv->instances_acls.lock);
- instance_acl = (struct ipoib_instance_acl *)
- radix_tree_lookup(&priv->instances_acls.instances,
- inst_name_hash);
- mutex_unlock(&priv->instances_acls.lock);
- if (!instance_acl) {
- ipoib_err(priv, "Instance ACL %s is not exist\n", name);
- return 0;
- }
-
- return &(instance_acl->acl);
-}
-
-void ipoib_init_acl(struct net_device *dev)
-{
- struct ib_cm_dpp dpp;
- struct ipoib_dev_priv *priv = netdev_priv(dev);
-
- ipoib_dbg(priv, "Initializing ACL for device %s\n", dev->name);
- ib_cm_acl_init(&priv->acl);
- ib_cm_dpp_init(&dpp, priv->ca, priv->port, priv->pkey);
- ib_cm_register_acl(&priv->acl, &dpp);
-}
-
-void ipoib_clean_acl(struct net_device *dev)
-{
- struct ipoib_dev_priv *priv = netdev_priv(dev);
-
- delete_instance_acls(dev);
-
- ipoib_dbg(priv, "Clean ACL for device %s\n", dev->name);
- ib_cm_unregister_acl(&priv->acl);
- ib_cm_acl_clean(&priv->acl);
-}
goto err_cm;
}
- INIT_RADIX_TREE(&priv->instances_acls.instances, GFP_KERNEL);
- priv->instances_acls.list_count = 0;
- mutex_init(&priv->instances_acls.lock);
-
ret = ib_cm_listen(priv->cm.id, cpu_to_be64(IPOIB_CM_IETF_ID | priv->qp->qp_num),
0, NULL);
if (ret) {
#include <linux/ip.h>
#include <linux/tcp.h>
-#include <net/arp.h>
#include "ipoib.h"
return 0;
}
-static inline int ipoib_is_valid_arp_address(struct net_device *dev,
- struct sk_buff *skb,
- __be64 interface_id)
-{
- struct ipoib_dev_priv *priv = netdev_priv(dev);
- union ib_gid *sgid;
-
- sgid = (union ib_gid *)(skb->data + sizeof(struct arphdr) + 4);
-
- if (sgid->global.interface_id != interface_id) {
- ipoib_dbg(priv, "Invalid ARP: sguid=0x%llx, arp.sguid=0x%llx\n",
- be64_to_cpu(interface_id),
- be64_to_cpu(sgid->global.interface_id));
- return 0;
- }
-
- return 1;
-}
-
-static char const ipoib_drop_reason_desc[5][32] = {
- "N/A",
- "No GRH",
- "grh.guid != arp.guid",
- "acl",
- "non CM packet"
-};
-
-enum ipoib_drop_reason {
- IPOIB_DROP_ACCEPT,
- IPOIB_DROP_NO_GRH,
- IPOIB_DROP_INV_ARP_GUID,
- IPOIB_DROP_ACL,
- IPOIB_DROP_NON_CM_PACKRT
-};
-
static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
unsigned int wr_id = wc->wr_id & ~IPOIB_OP_RECV;
struct sk_buff *skb;
u64 mapping[IPOIB_UD_RX_SG];
- union ib_gid *dgid, *sgid;
- enum ipoib_drop_reason drop = IPOIB_DROP_ACCEPT;
- u64 subnet_prefix = 0, guid = 0;
+ union ib_gid *dgid;
ipoib_dbg_data(priv, "recv completion: id %d, status: %d\n",
wr_id, wc->status);
return;
}
- skb = priv->rx_ring[wr_id].skb;
+ skb = priv->rx_ring[wr_id].skb;
if (unlikely(wc->status != IB_WC_SUCCESS)) {
if (wc->status != IB_WC_WR_FLUSH_ERR)
/* First byte of dgid signals multicast when 0xff */
dgid = &((struct ib_grh *)skb->data)->dgid;
- sgid = &((struct ib_grh *)skb->data)->sgid;
if (!(wc->wc_flags & IB_WC_GRH) || dgid->raw[0] != 0xff)
skb->pkt_type = PACKET_HOST;
++dev->stats.rx_packets;
dev->stats.rx_bytes += skb->len;
- if (unlikely(be16_to_cpu(skb->protocol) == ETH_P_ARP)) {
- if (priv->acl.enabled) {
- subnet_prefix = be64_to_cpu(sgid->global.subnet_prefix);
- guid = be64_to_cpu(sgid->global.interface_id);
- if (!(wc->wc_flags & IB_WC_GRH))
- drop = IPOIB_DROP_NO_GRH;
- else if (!ipoib_is_valid_arp_address(dev, skb,
- sgid->global.interface_id))
- drop = IPOIB_DROP_INV_ARP_GUID;
- else if (!ib_cm_acl_lookup(&priv->acl, subnet_prefix,
- guid))
- drop = IPOIB_DROP_ACL;
- if (drop) {
- goto drop;
- priv->arp_blocked++;
- }
- }
- priv->arp_accepted++;
- } else
- if (priv->acl.enabled) {
- priv->ud_blocked++;
- drop = IPOIB_DROP_NON_CM_PACKRT;
- goto drop;
- }
-
skb->dev = dev;
if ((dev->features & NETIF_F_RXCSUM) &&
likely(wc->wc_flags & IB_WC_IP_CSUM_OK))
napi_gro_receive(&priv->napi, skb);
- goto repost;
-
-drop:
- ipoib_dbg(priv, "Blocking packet (%s) from 0x%llx 0x%llx\n",
- ipoib_drop_reason_desc[drop], subnet_prefix, guid);
- dev_kfree_skb_any(skb);
- ++dev->stats.rx_dropped;
- goto repost;
-
repost:
if (unlikely(ipoib_ib_post_receive(dev, wr_id)))
ipoib_warn(priv, "ipoib_ib_post_receive failed "
+++ /dev/null
-/*
- * 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_warn(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;
-}
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- ipoib_dbg(priv, "bringing up interface %s\n", dev->name);
+ ipoib_dbg(priv, "bringing up interface\n");
netif_carrier_off(dev);
/* Delete any child interfaces first */
list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list) {
- ipoib_clean_acl(cpriv->dev);
/* Stop GC on child */
set_bit(IPOIB_STOP_NEIGH_GC, &cpriv->flags);
cancel_delayed_work(&cpriv->neigh_reap_task);
*/
ipoib_neigh_hash_uninit(dev);
- ipoib_clean_acl(priv->dev);
-
ipoib_ib_dev_cleanup(dev);
kfree(priv->rx_ring);
.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)
goto event_failed;
}
- ipoib_init_acl(priv->dev);
-
result = register_netdev(priv->dev);
if (result) {
printk(KERN_WARNING "%s: couldn't register ipoib port %d; error %d\n",
goto sysfs_failed;
if (device_create_file(&priv->dev->dev, &dev_attr_delete_named_child))
goto sysfs_failed;
- if (ipoib_debug_level)
- if (ipoib_create_acl_sysfs(priv->dev))
- goto sysfs_failed;
+
return priv->dev;
goto err;
}
- ipoib_init_acl(priv->dev);
-
result = register_netdevice(priv->dev);
if (result) {
ipoib_warn(priv, "failed to initialize; error %i", result);
if (device_create_file(&priv->dev->dev, &dev_attr_parent))
goto sysfs_failed;
-
- if (ipoib_debug_level)
- if (ipoib_create_acl_sysfs(priv->dev))
- goto sysfs_failed;
}
priv->child_type = type;
#if !defined(IB_CM_H)
#define IB_CM_H
-#include <linux/spinlock.h>
-
#include <rdma/ib_mad.h>
#include <rdma/ib_sa.h>
#define CM_LAP_ATTR_ID cpu_to_be16(0x0019)
#define CM_APR_ATTR_ID cpu_to_be16(0x001A)
-/**
- * This struct is used to hold unique IB interface identifiers
- */
-struct ib_cm_dpp {
- struct ib_device *device;
- u8 port;
- u16 pkey;
-};
-
-static inline void ib_cm_dpp_init(struct ib_cm_dpp *dpp,
- struct ib_device *device, u8 port, u16 pkey)
-{
- dpp->device = device;
- dpp->port = port;
- dpp->pkey = pkey;
-}
-
-static inline void ib_cm_dpp_copy(struct ib_cm_dpp *ddpp,
- struct ib_cm_dpp *sdpp)
-{
- ddpp->device = sdpp->device;
- ddpp->port = sdpp->port;
- ddpp->pkey = sdpp->pkey;
-}
-
-static inline bool ib_cm_dpp_compare(struct ib_cm_dpp *dpp1,
- struct ib_cm_dpp *dpp2)
-{
- return ((dpp1->device == dpp2->device) && (dpp1->port == dpp2->port) &&
- (dpp1->pkey == dpp2->pkey));
-}
-
-static inline void ib_cm_dpp_dbg(char *msg, struct ib_cm_dpp *dpp)
-{
- pr_debug("%s: %s, %d, 0x%x\n", msg, dpp->device->name, dpp->port,
- dpp->pkey);
-}
-
-#define UUID_SZ 64
-struct ib_cm_acl_elem {
- struct rb_node node;
- u64 guid;
- u64 subnet_prefix;
- u32 ip;
- char uuid[UUID_SZ];
- int ref_count;
-};
-
-struct ib_cm_acl {
- bool enabled;
- struct rb_root allowed_list;
- ssize_t list_count;
- spinlock_t lock;
-};
-
-void ib_cm_acl_init(struct ib_cm_acl *acl);
-int ib_cm_acl_insert(struct ib_cm_acl *acl, u64 subnet_prefix, u64 guid, u32 ip,
- const char *uuid);
-struct ib_cm_acl_elem *ib_cm_acl_lookup(struct ib_cm_acl *acl,
- u64 subnet_prefix, u64 guid);
-struct ib_cm_acl_elem *ib_cm_acl_lookup_uuid_ip(struct ib_cm_acl *acl,
- char *uuid, u32 ip);
-int ib_cm_acl_delete(struct ib_cm_acl *acl, u64 subnet_prefix, u64 guid);
-void ib_cm_acl_scan(struct ib_cm_acl *acl, struct ib_cm_acl_elem **list,
- ssize_t *list_count);
-void ib_cm_acl_clean(struct ib_cm_acl *acl);
-
-/**
- * This table map dpp to acl
- */
-struct ib_cm_dpp_acl {
- struct list_head list;
- struct ib_cm_dpp dpp;
- struct ib_cm_acl *acl;
-};
-
-int ib_cm_register_acl(struct ib_cm_acl *acl, struct ib_cm_dpp *dpp);
-struct ib_cm_acl *ib_cm_dpp_acl_lookup(struct ib_cm_dpp *dpp);
-void ib_cm_unregister_acl(struct ib_cm_acl *acl);
-
/**
* ib_cm_handler - User-defined callback to process communication events.
* @cm_id: Communication identifier associated with the reported event.
IB_MTU_4096 = 5
};
-static inline int ib_gid_cmp(union ib_gid *gid1, union ib_gid *gid2)
-{
- return (gid1->global.subnet_prefix == gid2->global.subnet_prefix) &&
- (gid1->global.interface_id == gid2->global.interface_id);
-}
-
static inline int ib_mtu_enum_to_int(enum ib_mtu mtu)
{
switch (mtu) {
#define RDS_GET_MR_FOR_DEST 7
#define RDS_CONN_RESET 8
#define SO_RDS_TRANSPORT 9
-#define RDS_CONFIG_UUID 11
/* supported values for SO_RDS_TRANSPORT */
#define RDS_TRANS_IB 0
#define RDS_CMSG_MASKED_ATOMIC_CSWP 9
#define RDS_CMSG_ASYNC_SEND 10
#define RDS_CMSG_RXPATH_LATENCY 11
-#define RDS_CMSG_UUID 12
#define RDS_INFO_FIRST 10000
#define RDS_INFO_COUNTERS 10000
int32_t status;
};
-#define RDS_UUID_MAXLEN 64
-struct rds_uuid_args {
- u_int8_t uuid[RDS_UUID_MAXLEN];
- unsigned int uuid_en;
- unsigned int acl_en;
- unsigned int drop_cnt;
-};
-
#define RDS_RDMA_SEND_SUCCESS 0
#define RDS_RDMA_REMOTE_ERROR 1
#define RDS_RDMA_SEND_CANCELED 2
#define RDS_RDMA_SEND_DROPPED 3
#define RDS_RDMA_SEND_OTHER_ERROR 4
-#define RDS_RDMA_SEND_ACCVIO 5
/*
* Common set of flags for all RDMA related structs
{
struct rds_reset reset;
struct rds_connection *conn;
- LIST_HEAD(s_addr_conns);
if (optlen != sizeof(struct rds_reset))
return -EINVAL;
sizeof(struct rds_reset)))
return -EFAULT;
- /* Reset all conns associated with source addr */
- if (reset.dst.s_addr == 0) {
- pr_info("RDS: Reset ALL conns for Source %pI4\n",
- &reset.src.s_addr);
-
- rds_conn_laddr_list(reset.src.s_addr, &s_addr_conns);
- if (list_empty(&s_addr_conns))
- goto done;
-
- list_for_each_entry(conn, &s_addr_conns, c_laddr_node)
- if (conn) {
- conn->c_drop_source = 1;
- rds_conn_drop(conn);
- }
- goto done;
- }
-
conn = rds_conn_find(sock_net(rds_rs_to_sk(rs)),
reset.src.s_addr, reset.dst.s_addr,
rs->rs_transport, reset.tos);
conn->c_drop_source = DR_USER_RESET;
rds_conn_drop(conn);
}
-done:
+
return 0;
}
}
-static int rds_set_config_uuid(struct rds_sock *rs, char __user *optval,
- int optlen)
-{
- return rds_set_bool_option(&rs->rs_uuid_en, optval, optlen);
-}
-
-static int rds_get_config_uuid(struct rds_sock *rs, char __user *optval,
- int *optlen)
-{
- struct rds_uuid_args args;
-
- memset(&args, 0, sizeof(args));
- args.uuid_en = rs->rs_uuid_en;
- args.drop_cnt = rs->rs_uuid_drop_cnt;
- if (rs->rs_conn) {
- args.acl_en = rs->rs_conn->c_acl_en;
- memcpy(args.uuid, rs->rs_conn->c_uuid, sizeof(args.uuid));
- }
-
- if (copy_to_user(optval, &args, sizeof(args)))
- return -EFAULT;
-
- if (put_user(sizeof(args), optlen))
- return -EFAULT;
-
- return 0;
-}
-
static int rds_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, unsigned int optlen)
{
case SO_RDS_MSG_RXPATH_LATENCY:
ret = rds_recv_track_latency(rs, optval, optlen);
break;
- case RDS_CONFIG_UUID:
- ret = rds_set_config_uuid(rs, optval, optlen);
- break;
default:
ret = -ENOPROTOOPT;
}
else
ret = 0;
break;
- case RDS_CONFIG_UUID:
- ret = rds_get_config_uuid(rs, optval, optlen);
- break;
default:
break;
}
return ret;
}
-void rds_conn_laddr_list(__be32 laddr, struct list_head *laddr_conns)
-{
- struct rds_connection *conn;
- struct hlist_head *head;
- int i;
-
- rcu_read_lock();
-
- for (i = 0, head = rds_conn_hash; i < ARRAY_SIZE(rds_conn_hash);
- i++, head++) {
- hlist_for_each_entry_rcu(conn, head, c_hash_node)
- if (conn->c_laddr == laddr)
- list_add(&conn->c_laddr_node, laddr_conns);
- }
-
- rcu_read_unlock();
-}
-
/*
* This is called by transports as they're bringing down a connection.
* It clears partial message state so that the transport can start sending
* the conn has been shutdown that no one else is referencing the connection.
* We can only ensure this in the rmmod path in the current code.
*/
-void rds_conn_destroy(struct rds_connection *conn, int shutdown)
+void rds_conn_destroy(struct rds_connection *conn)
{
struct rds_message *rm, *rtmp;
unsigned long flags;
- LIST_HEAD(to_be_dropped);
rds_rtd(RDS_RTD_CM, "freeing conn %p <%u.%u.%u.%u,%u.%u.%u.%u,%d>\n",
conn, NIPQUAD(conn->c_laddr), NIPQUAD(conn->c_faddr),
conn->c_tos);
- set_bit(RDS_DESTROY_PENDING, &conn->c_flags);
-
/* Ensure conn will not be scheduled for reconnect */
spin_lock_irq(&rds_conn_lock);
hlist_del_init_rcu(&conn->c_hash_node);
list_for_each_entry_safe(rm, rtmp,
&conn->c_send_queue,
m_conn_item) {
- if (shutdown) {
- list_del_init(&rm->m_conn_item);
- BUG_ON(!list_empty(&rm->m_sock_item));
- rds_message_put(rm);
- } else {
- list_move_tail(&rm->m_conn_item, &to_be_dropped);
- }
+ list_del_init(&rm->m_conn_item);
+ BUG_ON(!list_empty(&rm->m_sock_item));
+ rds_message_put(rm);
}
-
- if (!list_empty(&to_be_dropped))
- rds_send_remove_from_sock(&to_be_dropped, RDS_RDMA_SEND_ACCVIO);
-
if (conn->c_xmit_rm)
rds_message_put(conn->c_xmit_rm);
struct rds_connection *conn;
};
-struct rds_ib_conn_destroy_work {
- struct delayed_work work;
- struct rds_connection *conn;
-};
-
struct rds_ib_addr_change_work {
struct delayed_work work;
__be32 addr;
void rds_ib_cm_connect_complete(struct rds_connection *conn,
struct rdma_cm_event *event);
void rds_ib_init_frag(unsigned int version);
-void rds_ib_conn_destroy_init(struct rds_connection *conn);
#define rds_ib_conn_error(conn, fmt...) \
__rds_ib_conn_error(conn, KERN_WARNING "RDS/IB: " fmt)
#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.
if (conn->c_version < RDS_PROTOCOL_VERSION) {
if (conn->c_version != RDS_PROTOCOL_COMPAT_VERSION) {
+ /*
+ * BUG: destroying connection here can deadlock with
+ * the CM event handler on the c_cm_lock.
+ */
printk(KERN_NOTICE "RDS/IB: Connection to"
" %u.%u.%u.%u version %u.%u failed,"
" no longer supported\n",
NIPQUAD(conn->c_faddr),
RDS_PROTOCOL_MAJOR(conn->c_version),
RDS_PROTOCOL_MINOR(conn->c_version));
- rds_ib_conn_destroy_init(conn);
+ rds_conn_destroy(conn);
return;
}
}
- printk(KERN_NOTICE "RDS/IB: %s conn %p i_cm_id %p, frag %dKB, connected <%pI4,%pI4,%d> version %u.%u%s%s\n",
+ printk(KERN_NOTICE "RDS/IB: %s conn %p i_cm_id %p, frag %dKB, connected <%pI4,%pI4,%d> version %u.%u%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" : "",
- conn->c_acl_en ? ", ACL Enabled" : "");
+ ic->i_flowctl ? ", flow control" : "");
/* 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) {
- int reject_reason = RDS_ACL_FAILURE;
-
- rdma_reject(cm_id, &reject_reason, sizeof(int));
- rdsdebug("RDS: IB: passive: 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,
return destroy;
}
-void rds_ib_conn_destroy_worker(struct work_struct *_work)
-{
- struct rds_ib_conn_destroy_work *work =
- container_of(_work, struct rds_ib_conn_destroy_work, work.work);
- struct rds_connection *conn = work->conn;
-
- rds_conn_destroy(conn, 0);
-
- kfree(work);
-}
-
-void rds_ib_conn_destroy_init(struct rds_connection *conn)
-{
- struct rds_ib_conn_destroy_work *work;
-
- work = kzalloc(sizeof *work, GFP_ATOMIC);
- if (!work) {
- pr_err("RDS/IB: failed to allocate connection destroy work\n");
- return;
- }
-
- work->conn = conn;
- INIT_DELAYED_WORK(&work->work, rds_ib_conn_destroy_worker);
- queue_delayed_work(rds_aux_wq, &work->work, 0);
-}
int rds_ib_cm_initiate_connect(struct rdma_cm_id *cm_id)
{
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 */
spin_unlock_irq(&ib_nodev_conns_lock);
list_for_each_entry_safe(ic, _ic, &tmp_list, ib_node)
- rds_conn_destroy(ic->conn, 1);
+ rds_conn_destroy(ic->conn);
}
static unsigned int get_unmap_fmr_cpu(struct rds_ib_device *rds_ibdev,
list_for_each_entry_safe(lc, _lc, &tmp_list, loop_node) {
WARN_ON(lc->conn->c_passive);
- rds_conn_destroy(lc->conn, 1);
+ rds_conn_destroy(lc->conn);
}
}
&conn->c_reject_w,
msecs_to_jiffies(10));
}
- } else if (event->status == RDS_REJ_CONSUMER_DEFINED &&
- (*err) == RDS_ACL_FAILURE) {
- /* Rejection due to ACL violation */
- pr_err("RDS: IB: conn=%p, <%u.%u.%u.%u,%u.%u.%u.%u,%d> destroyed due to ACL violation\n",
- conn, NIPQUAD(conn->c_laddr),
- NIPQUAD(conn->c_faddr),
- conn->c_tos);
- rds_ib_conn_destroy_init(conn);
} else {
rds_rtd(RDS_RTD_ERR,
"Rejected: *err %d status %d calling rds_conn_drop <%u.%u.%u.%u,%u.%u.%u.%u,%d>\n",
#define RDS_PROTOCOL_MINOR(v) ((v) & 255)
#define RDS_PROTOCOL(maj, min) (((maj) << 8) | min)
-/* Reject reason codes.
- * 0401 below indicates 4.1 version.
- * 0020 indicates type of reject.
- * Reserving earlier ones for version mismatch or other reasons.
- */
-#define RDS_ACL_FAILURE 0x04010020
-
/*
* XXX randomly chosen, but at least seems to be unused:
* # 18464-18768 Unassigned
#define RDS_RECONNECT_PENDING 1
#define RDS_IN_XMIT 2
#define RDS_RECV_REFILL 3
-#define RDS_DESTROY_PENDING 4
#define RDS_RDMA_RESOLVE_TO_MAX_INDEX 5
#define RDS_ADDR_RES_TM_INDEX_MAX 5
unsigned int c_route_resolved;
enum rds_conn_drop_src c_drop_source;
- struct list_head c_laddr_node;
-
- unsigned char c_acl_init;
- unsigned char c_acl_en;
- u_int8_t c_uuid[RDS_UUID_MAXLEN];
};
static inline
u64 m_ack_seq;
__be32 m_daddr;
unsigned long m_flags;
- unsigned int m_status;
/* Never access m_rs without holding m_rs_lock.
* Lock nesting is
unsigned int op_dmaoff;
struct scatterlist *op_sg;
} data;
- struct rm_uuid_op {
- u_int8_t value[RDS_UUID_MAXLEN];
- u_int8_t enable;
- } uuid;
};
};
/* Socket receive path trace points*/
u8 rs_rx_traces;
u8 rs_rx_trace[RDS_MSG_RX_DGRAM_TRACE_MAX];
-
- /* UUID specific fields */
- unsigned char rs_uuid_en;
- unsigned int rs_uuid_drop_cnt;
- unsigned int rs_uuid_sent_cnt;
- unsigned int rs_uuid_recv_cnt;
};
static inline struct rds_sock *rds_sk_to_rs(const struct sock *sk)
__be32 faddr,
struct rds_transport *trans, u8 tos);
void rds_conn_shutdown(struct rds_connection *conn, int restart);
-void rds_conn_destroy(struct rds_connection *conn, int shutdown);
+void rds_conn_destroy(struct rds_connection *conn);
void rds_conn_reset(struct rds_connection *conn);
void rds_conn_drop(struct rds_connection *conn);
-void rds_conn_laddr_list(__be32 laddr, struct list_head *laddr_conns);
void rds_conn_connect_if_down(struct rds_connection *conn);
void rds_for_each_conn_info(struct socket *sock, unsigned int len,
struct rds_info_iterator *iter,
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);
return ret;
}
-static int rds_cmsg_uuid(struct rds_sock *rs, struct rds_incoming *inc,
- struct msghdr *msghdr)
-{
- struct rds_uuid_args args;
-
- if (!inc->i_conn->c_acl_en || !rs->rs_uuid_en)
- return 0;
-
- memcpy(args.uuid, inc->i_conn->c_uuid, sizeof(inc->i_conn->c_uuid));
- args.acl_en = inc->i_conn->c_acl_en;
- args.uuid_en = rs->rs_uuid_en;
-
- return put_cmsg(msghdr, SOL_RDS, RDS_CMSG_UUID, sizeof(args), &args);
-}
-
int rds_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
int msg_flags)
{
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;
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.
}
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;
}
&rm->m_flags))) {
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_DROPPED;
+ &rm->m_flags))
list_move_tail(&rm->m_conn_item,
&to_be_dropped);
- }
spin_unlock_irqrestore(&conn->c_lock, flags);
continue;
}
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;
rds_message_unmapped(rm);
rds_message_put(rm);
}
- rds_send_remove_from_sock(&to_be_dropped, rm->m_status);
+ rds_send_remove_from_sock(&to_be_dropped, RDS_RDMA_SEND_DROPPED);
}
/*
size += sizeof(struct scatterlist);
break;
- case RDS_CMSG_UUID:
- cmsg_groups |= 1;
- size += sizeof(struct scatterlist);
- break;
-
default:
return -EINVAL;
}
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)
{
ret = rds_cmsg_asend(rs, rm, cmsg);
break;
- case RDS_CMSG_UUID:
- ret = rds_cmsg_uuid(rs, rm, cmsg);
- break;
-
default:
return -EINVAL;
}
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.
goto out;
}
- if (conn->c_acl_init && rds_match_uuid(conn, rm)) {
- ret = -EFAULT;
- goto out;
- }
-
- if (test_bit(RDS_DESTROY_PENDING, &conn->c_flags)) {
- ret = -EAGAIN;
- 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;
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);
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);
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.
.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,
- },
{ }
};
list_for_each_entry_safe(tc, _tc, &tmp_list, t_tcp_node) {
if (tc->conn->c_passive)
- rds_conn_destroy(tc->conn->c_passive, 1);
- rds_conn_destroy(tc->conn, 1);
+ rds_conn_destroy(tc->conn->c_passive);
+ rds_conn_destroy(tc->conn);
}
}
sk->sk_prot->disconnect(sk, 0);
tcp_done(sk);
if (tc->conn->c_passive)
- rds_conn_destroy(tc->conn->c_passive, 1);
- rds_conn_destroy(tc->conn, 1);
+ rds_conn_destroy(tc->conn->c_passive);
+ rds_conn_destroy(tc->conn);
}
}