Commit c3acdc06 authored by Doug Ledford's avatar Doug Ledford

IB/ipoib: Clean up send-only multicast joins

Even though we don't expect the group to be created by the SM we
sill need to provide all the parameters to force the SM to validate
they are correct.
Signed-off-by: default avatarJason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 7fbc67df
...@@ -448,8 +448,7 @@ static int ipoib_mcast_join_complete(int status, ...@@ -448,8 +448,7 @@ static int ipoib_mcast_join_complete(int status,
return status; return status;
} }
static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast, static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast)
int create)
{ {
struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ib_sa_multicast *multicast; struct ib_sa_multicast *multicast;
...@@ -471,7 +470,14 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast, ...@@ -471,7 +470,14 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
IB_SA_MCMEMBER_REC_PKEY | IB_SA_MCMEMBER_REC_PKEY |
IB_SA_MCMEMBER_REC_JOIN_STATE; IB_SA_MCMEMBER_REC_JOIN_STATE;
if (create) { if (mcast != priv->broadcast) {
/*
* RFC 4391:
* The MGID MUST use the same P_Key, Q_Key, SL, MTU,
* and HopLimit as those used in the broadcast-GID. The rest
* of attributes SHOULD follow the values used in the
* broadcast-GID as well.
*/
comp_mask |= comp_mask |=
IB_SA_MCMEMBER_REC_QKEY | IB_SA_MCMEMBER_REC_QKEY |
IB_SA_MCMEMBER_REC_MTU_SELECTOR | IB_SA_MCMEMBER_REC_MTU_SELECTOR |
...@@ -492,6 +498,22 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast, ...@@ -492,6 +498,22 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
rec.sl = priv->broadcast->mcmember.sl; rec.sl = priv->broadcast->mcmember.sl;
rec.flow_label = priv->broadcast->mcmember.flow_label; rec.flow_label = priv->broadcast->mcmember.flow_label;
rec.hop_limit = priv->broadcast->mcmember.hop_limit; rec.hop_limit = priv->broadcast->mcmember.hop_limit;
/*
* Historically Linux IPoIB has never properly supported SEND
* ONLY join. It emulated it by not providing all the required
* attributes, which is enough to prevent group creation and
* detect if there are full members or not. A major problem
* with supporting SEND ONLY is detecting when the group is
* auto-destroyed as IPoIB will cache the MLID..
*/
#if 1
if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags))
comp_mask &= ~IB_SA_MCMEMBER_REC_TRAFFIC_CLASS;
#else
if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags))
rec.join_state = 4;
#endif
} }
multicast = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port, multicast = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port,
...@@ -517,7 +539,6 @@ void ipoib_mcast_join_task(struct work_struct *work) ...@@ -517,7 +539,6 @@ void ipoib_mcast_join_task(struct work_struct *work)
struct ib_port_attr port_attr; struct ib_port_attr port_attr;
unsigned long delay_until = 0; unsigned long delay_until = 0;
struct ipoib_mcast *mcast = NULL; struct ipoib_mcast *mcast = NULL;
int create = 1;
if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
return; return;
...@@ -566,7 +587,6 @@ void ipoib_mcast_join_task(struct work_struct *work) ...@@ -566,7 +587,6 @@ void ipoib_mcast_join_task(struct work_struct *work)
if (IS_ERR_OR_NULL(priv->broadcast->mc) && if (IS_ERR_OR_NULL(priv->broadcast->mc) &&
!test_bit(IPOIB_MCAST_FLAG_BUSY, &priv->broadcast->flags)) { !test_bit(IPOIB_MCAST_FLAG_BUSY, &priv->broadcast->flags)) {
mcast = priv->broadcast; mcast = priv->broadcast;
create = 0;
if (mcast->backoff > 1 && if (mcast->backoff > 1 &&
time_before(jiffies, mcast->delay_until)) { time_before(jiffies, mcast->delay_until)) {
delay_until = mcast->delay_until; delay_until = mcast->delay_until;
...@@ -590,12 +610,8 @@ void ipoib_mcast_join_task(struct work_struct *work) ...@@ -590,12 +610,8 @@ void ipoib_mcast_join_task(struct work_struct *work)
/* Found the next unjoined group */ /* Found the next unjoined group */
init_completion(&mcast->done); init_completion(&mcast->done);
set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags))
create = 0;
else
create = 1;
spin_unlock_irq(&priv->lock); spin_unlock_irq(&priv->lock);
ipoib_mcast_join(dev, mcast, create); ipoib_mcast_join(dev, mcast);
spin_lock_irq(&priv->lock); spin_lock_irq(&priv->lock);
} else if (!delay_until || } else if (!delay_until ||
time_before(mcast->delay_until, delay_until)) time_before(mcast->delay_until, delay_until))
...@@ -618,7 +634,7 @@ void ipoib_mcast_join_task(struct work_struct *work) ...@@ -618,7 +634,7 @@ void ipoib_mcast_join_task(struct work_struct *work)
} }
spin_unlock_irq(&priv->lock); spin_unlock_irq(&priv->lock);
if (mcast) if (mcast)
ipoib_mcast_join(dev, mcast, create); ipoib_mcast_join(dev, mcast);
} }
int ipoib_mcast_start_thread(struct net_device *dev) int ipoib_mcast_start_thread(struct net_device *dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment