Roland,
Can you please comment on this?

Thanks,
Yossi

Yossi Etigin wrote:

Would it work to have a more naive approach, and just keep track of the
last time each send-only membership was used, and set up a timer that
runs, say every minute, and garbage collect send-only memberships that
are more than 2 minutes old, or something like that?


How about this one:

diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index ca126fc..7a5998f 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -88,6 +88,7 @@ enum {
    IPOIB_FLAG_ADMIN_CM      = 9,
    IPOIB_FLAG_UMCAST      = 10,
    IPOIB_FLAG_CSUM          = 11,
+    IPOIB_MCAST_RUN_GC      = 12,

    IPOIB_MAX_BACKOFF_SECONDS = 16,

@@ -127,6 +128,7 @@ struct ipoib_mcast {
    struct list_head  list;

    unsigned long created;
+    unsigned long used;
    unsigned long backoff;

    unsigned long flags;
@@ -275,7 +277,8 @@ struct ipoib_dev_priv {
    struct rb_root multicast_tree;

    struct delayed_work pkey_poll_task;
-    struct delayed_work mcast_task;
+    struct delayed_work mcast_join_task;
+    struct delayed_work mcast_leave_task;
    struct work_struct flush_task;
    struct work_struct restart_task;
    struct delayed_work ah_reap_task;
@@ -440,6 +443,7 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port);
void ipoib_dev_cleanup(struct net_device *dev);

void ipoib_mcast_join_task(struct work_struct *work);
+void ipoib_mcast_leave_task(struct work_struct *work);
void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb);

void ipoib_mcast_restart_task(struct work_struct *work);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 2442090..b7f4b2b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -990,7 +990,8 @@ static void ipoib_setup(struct net_device *dev)

    INIT_DELAYED_WORK(&priv->pkey_poll_task, ipoib_pkey_poll);
    INIT_WORK(&priv->pkey_event_task, ipoib_pkey_event);
-    INIT_DELAYED_WORK(&priv->mcast_task,   ipoib_mcast_join_task);
+    INIT_DELAYED_WORK(&priv->mcast_join_task,   ipoib_mcast_join_task);
+    INIT_DELAYED_WORK(&priv->mcast_leave_task, ipoib_mcast_leave_task);
    INIT_WORK(&priv->flush_task,   ipoib_ib_dev_flush);
    INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task);
    INIT_DELAYED_WORK(&priv->ah_reap_task, ipoib_reap_ah);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 3f663fb..1957e93 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -120,6 +120,7 @@ static struct ipoib_mcast *ipoib_mcast_alloc(struct net_device *dev,

    mcast->dev = dev;
    mcast->created = jiffies;
+    mcast->used = jiffies;
    mcast->backoff = 1;

    INIT_LIST_HEAD(&mcast->list);
@@ -389,7 +390,7 @@ static int ipoib_mcast_join_complete(int status,
        mutex_lock(&mcast_mutex);
        if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
            queue_delayed_work(ipoib_workqueue,
-                       &priv->mcast_task, 0);
+                       &priv->mcast_join_task, 0);
        mutex_unlock(&mcast_mutex);

        if (mcast == priv->broadcast)
@@ -422,7 +423,7 @@ static int ipoib_mcast_join_complete(int status,
    mutex_lock(&mcast_mutex);
    spin_lock_irq(&priv->lock);
    if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
-        queue_delayed_work(ipoib_workqueue, &priv->mcast_task,
+        queue_delayed_work(ipoib_workqueue, &priv->mcast_join_task,
                   mcast->backoff * HZ);
    spin_unlock_irq(&priv->lock);
    mutex_unlock(&mcast_mutex);
@@ -492,7 +493,7 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
        mutex_lock(&mcast_mutex);
        if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
            queue_delayed_work(ipoib_workqueue,
-                       &priv->mcast_task,
+                       &priv->mcast_join_task,
                       mcast->backoff * HZ);
        mutex_unlock(&mcast_mutex);
    }
@@ -501,7 +502,7 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
void ipoib_mcast_join_task(struct work_struct *work)
{
    struct ipoib_dev_priv *priv =
-        container_of(work, struct ipoib_dev_priv, mcast_task.work);
+        container_of(work, struct ipoib_dev_priv, mcast_join_task.work);
    struct net_device *dev = priv->dev;

    if (!test_bit(IPOIB_MCAST_RUN, &priv->flags))
@@ -530,7 +531,7 @@ void ipoib_mcast_join_task(struct work_struct *work)
            mutex_lock(&mcast_mutex);
            if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
                queue_delayed_work(ipoib_workqueue,
-                           &priv->mcast_task, HZ);
+                           &priv->mcast_join_task, HZ);
            mutex_unlock(&mcast_mutex);
            return;
        }
@@ -591,7 +592,9 @@ int ipoib_mcast_start_thread(struct net_device *dev)

    mutex_lock(&mcast_mutex);
    if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags))
-        queue_delayed_work(ipoib_workqueue, &priv->mcast_task, 0);
+        queue_delayed_work(ipoib_workqueue, &priv->mcast_join_task, 0);
+    if (!test_and_set_bit(IPOIB_MCAST_RUN_GC, &priv->flags))
+        queue_delayed_work(ipoib_workqueue, &priv->mcast_leave_task, 0);
    mutex_unlock(&mcast_mutex);

    spin_lock_irq(&priv->lock);
@@ -613,7 +616,9 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush)

    mutex_lock(&mcast_mutex);
    clear_bit(IPOIB_MCAST_RUN, &priv->flags);
-    cancel_delayed_work(&priv->mcast_task);
+    clear_bit(IPOIB_MCAST_RUN_GC, &priv->flags);
+    cancel_delayed_work(&priv->mcast_join_task);
+    cancel_delayed_work(&priv->mcast_leave_task);
    mutex_unlock(&mcast_mutex);

    if (flush)
@@ -720,6 +725,7 @@ out:
            }
        }

+        mcast->used = jiffies;
        ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
    }

@@ -864,6 +870,33 @@ void ipoib_mcast_restart_task(struct work_struct *work)
        ipoib_mcast_start_thread(dev);
}

+void ipoib_mcast_leave_task(struct work_struct *work)
+{
+    struct ipoib_dev_priv *priv =
+        container_of(work, struct ipoib_dev_priv, mcast_leave_task.work);
+    struct net_device *dev = priv->dev;
+    struct ipoib_mcast *mcast, *tmcast;
+    LIST_HEAD(remove_list);
+ + if (!test_bit(IPOIB_MCAST_RUN_GC, &priv->flags))
+        return;
+ + list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) {
+        if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) &&
+            time_before(mcast->used, jiffies - 120 * HZ)) {
+            rb_erase(&mcast->rb_node, &priv->multicast_tree);
+            list_move_tail(&mcast->list, &remove_list);
+        }
+    }
+
+    list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
+        ipoib_mcast_leave(dev, mcast);
+        ipoib_mcast_free(mcast);
+    }
+ + queue_delayed_work(ipoib_workqueue, &priv->mcast_leave_task, 60 * HZ);
+}
+
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG

struct ipoib_mcast_iter *ipoib_mcast_iter_init(struct net_device *dev)
_______________________________________________
general mailing list
[email protected]
http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

_______________________________________________
general mailing list
[email protected]
http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to