Commit 816e5984 authored by Eugenia Emantayev's avatar Eugenia Emantayev Committed by David S. Miller

net/mlx4_core: In SR-IOV mode host should add promisc QP to default entry only

In current situation host is adding the promiscuous QP to all steering
entries and the default entry as well. In this case when having PV
and SR-IOV on the same setup bridge will receive all traffic that is
targeted to the other VMs. This is bad.
Solution: In SR-IOV mode host can add promiscuous QP to default entry only.
The above problem and fix are relevant for B0 steering mode only.
Signed-off-by: default avatarEugenia Emantayev <eugenia@mellanox.com>
Signed-off-by: default avatarAmir Vadai <amirv@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 75908376
...@@ -433,43 +433,58 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port, ...@@ -433,43 +433,58 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port,
} }
mgm = mailbox->buf; mgm = mailbox->buf;
/* the promisc qp needs to be added for each one of the steering if (!(mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER)) {
* entries, if it already exists, needs to be added as a duplicate /* The promisc QP needs to be added for each one of the steering
* for this entry */ * entries. If it already exists, needs to be added as
list_for_each_entry(entry, &s_steer->steer_entries[steer], list) { * a duplicate for this entry.
err = mlx4_READ_ENTRY(dev, entry->index, mailbox); */
if (err) list_for_each_entry(entry,
goto out_mailbox; &s_steer->steer_entries[steer],
list) {
err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
if (err)
goto out_mailbox;
members_count = be32_to_cpu(mgm->members_count) & 0xffffff; members_count = be32_to_cpu(mgm->members_count) &
prot = be32_to_cpu(mgm->members_count) >> 30; 0xffffff;
found = false; prot = be32_to_cpu(mgm->members_count) >> 30;
for (i = 0; i < members_count; i++) { found = false;
if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) { for (i = 0; i < members_count; i++) {
/* Entry already exists, add to duplicates */ if ((be32_to_cpu(mgm->qp[i]) &
dqp = kmalloc(sizeof *dqp, GFP_KERNEL); MGM_QPN_MASK) == qpn) {
if (!dqp) { /* Entry already exists.
* Add to duplicates.
*/
dqp = kmalloc(sizeof(*dqp), GFP_KERNEL);
if (!dqp) {
err = -ENOMEM;
goto out_mailbox;
}
dqp->qpn = qpn;
list_add_tail(&dqp->list,
&entry->duplicates);
found = true;
}
}
if (!found) {
/* Need to add the qpn to mgm */
if (members_count ==
dev->caps.num_qp_per_mgm) {
/* entry is full */
err = -ENOMEM; err = -ENOMEM;
goto out_mailbox; goto out_mailbox;
} }
dqp->qpn = qpn; mgm->qp[members_count++] =
list_add_tail(&dqp->list, &entry->duplicates); cpu_to_be32(qpn & MGM_QPN_MASK);
found = true; mgm->members_count =
cpu_to_be32(members_count |
(prot << 30));
err = mlx4_WRITE_ENTRY(dev, entry->index,
mailbox);
if (err)
goto out_mailbox;
} }
} }
if (!found) {
/* Need to add the qpn to mgm */
if (members_count == dev->caps.num_qp_per_mgm) {
/* entry is full */
err = -ENOMEM;
goto out_mailbox;
}
mgm->qp[members_count++] = cpu_to_be32(qpn & MGM_QPN_MASK);
mgm->members_count = cpu_to_be32(members_count | (prot << 30));
err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
if (err)
goto out_mailbox;
}
} }
/* add the new qpn to list of promisc qps */ /* add the new qpn to list of promisc qps */
...@@ -556,51 +571,65 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port, ...@@ -556,51 +571,65 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,
if (err) if (err)
goto out_mailbox; goto out_mailbox;
/* remove the qp from all the steering entries*/ if (!(mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER)) {
list_for_each_entry(entry, &s_steer->steer_entries[steer], list) { /* remove the qp from all the steering entries*/
found = false; list_for_each_entry(entry,
list_for_each_entry(dqp, &entry->duplicates, list) { &s_steer->steer_entries[steer],
if (dqp->qpn == qpn) { list) {
found = true; found = false;
break; list_for_each_entry(dqp, &entry->duplicates, list) {
if (dqp->qpn == qpn) {
found = true;
break;
}
} }
} if (found) {
if (found) { /* A duplicate, no need to change the MGM,
/* a duplicate, no need to change the mgm, * only update the duplicates list
* only update the duplicates list */ */
list_del(&dqp->list); list_del(&dqp->list);
kfree(dqp); kfree(dqp);
} else { } else {
int loc = -1; int loc = -1;
err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
if (err) err = mlx4_READ_ENTRY(dev,
entry->index,
mailbox);
if (err)
goto out_mailbox;
members_count =
be32_to_cpu(mgm->members_count) &
0xffffff;
for (i = 0; i < members_count; ++i)
if ((be32_to_cpu(mgm->qp[i]) &
MGM_QPN_MASK) == qpn) {
loc = i;
break;
}
if (loc < 0) {
mlx4_err(dev, "QP %06x wasn't found in entry %d\n",
qpn, entry->index);
err = -EINVAL;
goto out_mailbox; goto out_mailbox;
members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
for (i = 0; i < members_count; ++i)
if ((be32_to_cpu(mgm->qp[i]) &
MGM_QPN_MASK) == qpn) {
loc = i;
break;
} }
if (loc < 0) { /* copy the last QP in this MGM
mlx4_err(dev, "QP %06x wasn't found in entry %d\n", * over removed QP
qpn, entry->index); */
err = -EINVAL; mgm->qp[loc] = mgm->qp[members_count - 1];
goto out_mailbox; mgm->qp[members_count - 1] = 0;
mgm->members_count =
cpu_to_be32(--members_count |
(MLX4_PROT_ETH << 30));
err = mlx4_WRITE_ENTRY(dev,
entry->index,
mailbox);
if (err)
goto out_mailbox;
} }
/* copy the last QP in this MGM over removed QP */
mgm->qp[loc] = mgm->qp[members_count - 1];
mgm->qp[members_count - 1] = 0;
mgm->members_count = cpu_to_be32(--members_count |
(MLX4_PROT_ETH << 30));
err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
if (err)
goto out_mailbox;
} }
} }
out_mailbox: out_mailbox:
......
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