[ofa-general] Re: [PATCH v3 for 2.6.24] IB/ipoib: enable IGMP for userpsace multicast IB apps

Roland Dreier rdreier at cisco.com
Wed Oct 10 14:43:28 PDT 2007


OK, at long last I merged the following.  I rewrote the changelog to
(I think) be more understandable, and also cleaned up a few things in
the patch (including whitespace damage...).

commit 335a64a5a958002bc238c90de695e120c3c8c120
Author: Or Gerlitz <ogerlitz at voltaire.com>
Date:   Mon Oct 8 10:13:00 2007 +0200

    IPoIB: Allow setting policy to ignore multicast groups
    
    The kernel IB stack allows (through the RDMA CM) userspace
    applications to join and use multicast groups from the IPoIB MGID
    range.  This allows multicast traffic to be handled directly from
    userspace QPs, without going through the kernel stack, which gives
    better performance for some applications.
    
    However, to fully interoperate with IP multicast, such userspace
    applications need to participate in IGMP reports and queries, or else
    routers may not forward the multicast traffic to the system where the
    application is running.  The simplest way to do this is to share the
    kernel IGMP implementation by using the IP_ADD_MEMBERSHIP option to
    join multicast groups that are being handled directly in userspace.
    
    However, in such cases, the actual multicast traffic should not also
    be handled by the IPoIB interface, because that would burn resources
    handling multicast packets that will just be discarded in the kernel.
    
    To handle this, this patch adds lookup on the database used for IB
    multicast group reference counting when IPoIB is joining multicast
    groups, and if a multicast group is already handled by user space,
    then the IPoIB kernel driver ignores the group.  This is controlled by
    a per-interface policy flag.  When the flag is set, IPoIB will not
    join and attach its QP to a multicast group which already has an entry
    in the database; when the flag is cleared, IPoIB will behave as before
    this change.
    
    For each IPoIB interface, the /sys/class/net/$intf/umcast attribute
    controls the policy flag.  The default value is off/0.
    
    Signed-off-by: Or Gerlitz <ogerlitz at voltaire.com>
    Signed-off-by: Roland Dreier <rolandd at cisco.com>

diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index fc16bce..a198ce8 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -86,6 +86,7 @@ enum {
 	IPOIB_MCAST_STARTED       = 8,
 	IPOIB_FLAG_NETIF_STOPPED  = 9,
 	IPOIB_FLAG_ADMIN_CM 	  = 10,
+	IPOIB_FLAG_UMCAST	  = 11,
 
 	IPOIB_MAX_BACKOFF_SECONDS = 16,
 
@@ -384,6 +385,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);
 
 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_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 900335a..ff17fe3 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1019,6 +1019,37 @@ static ssize_t show_pkey(struct device *dev,
 }
 static DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL);
 
+static ssize_t show_umcast(struct device *dev,
+			   struct device_attribute *attr, char *buf)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(dev));
+
+	return sprintf(buf, "%d\n", test_bit(IPOIB_FLAG_UMCAST, &priv->flags));
+}
+
+static ssize_t set_umcast(struct device *dev,
+			  struct device_attribute *attr,
+			  const char *buf, size_t count)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(dev));
+	unsigned long umcast_val = simple_strtoul(buf, NULL, 0);
+
+	if (umcast_val > 0) {
+		set_bit(IPOIB_FLAG_UMCAST, &priv->flags);
+		ipoib_warn(priv, "ignoring multicast groups joined directly "
+				"by userspace\n");
+	} else
+		clear_bit(IPOIB_FLAG_UMCAST, &priv->flags);
+
+	return count;
+}
+static DEVICE_ATTR(umcast, S_IWUSR | S_IRUGO, show_umcast, set_umcast);
+
+int ipoib_add_umcast_attr(struct net_device *dev)
+{
+	return device_create_file(&dev->dev, &dev_attr_umcast);
+}
+
 static ssize_t create_child(struct device *dev,
 			    struct device_attribute *attr,
 			    const char *buf, size_t count)
@@ -1136,6 +1167,8 @@ static struct net_device *ipoib_add_port(const char *format,
 		goto sysfs_failed;
 	if (ipoib_add_pkey_attr(priv->dev))
 		goto sysfs_failed;
+	if (ipoib_add_umcast_attr(priv->dev))
+		goto sysfs_failed;
 	if (device_create_file(&priv->dev->dev, &dev_attr_create_child))
 		goto sysfs_failed;
 	if (device_create_file(&priv->dev->dev, &dev_attr_delete_child))
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 94a5709..62abfb6 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -761,6 +761,7 @@ void ipoib_mcast_restart_task(struct work_struct *work)
 	struct ipoib_mcast *mcast, *tmcast;
 	LIST_HEAD(remove_list);
 	unsigned long flags;
+	struct ib_sa_mcmember_rec rec;
 
 	ipoib_dbg_mcast(priv, "restarting multicast task\n");
 
@@ -794,6 +795,14 @@ void ipoib_mcast_restart_task(struct work_struct *work)
 		if (!mcast || test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {
 			struct ipoib_mcast *nmcast;
 
+			/* ignore group which is directly joined by userspace */
+			if (test_bit(IPOIB_FLAG_UMCAST, &priv->flags) &&
+			    !ib_sa_get_mcmember_rec(priv->ca, priv->port, &mgid, &rec)) {
+				ipoib_dbg_mcast(priv, "ignoring multicast entry for mgid "
+						IPOIB_GID_FMT "\n", IPOIB_GID_ARG(mgid));
+				continue;
+			}
+
 			/* Not found or send-only group, let's add a new entry */
 			ipoib_dbg_mcast(priv, "adding multicast entry for mgid "
 					IPOIB_GID_FMT "\n", IPOIB_GID_ARG(mgid));
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index 6762988..293f5b8 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -119,6 +119,8 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
 		goto sysfs_failed;
 	if (ipoib_add_pkey_attr(priv->dev))
 		goto sysfs_failed;
+	if (ipoib_add_umcast_attr(priv->dev))
+		goto sysfs_failed;
 
 	if (device_create_file(&priv->dev->dev, &dev_attr_parent))
 		goto sysfs_failed;



More information about the general mailing list