Skip to content

Commit

Permalink
IB/core: Use GID table in AH creation and dmac resolution
Browse files Browse the repository at this point in the history
Previously, vlan id and source MAC were used from QP attributes. Since
the net device is now stored in the GID attributes, they could be used
instead of getting this information from the QP attributes.

IB_QP_SMAC, IB_QP_ALT_SMAC, IB_QP_VID and IB_QP_ALT_VID were removed
because there is no known libibverbs that uses them.

This commit also modifies the vendors (mlx4, ocrdma) drivers in order
to use the new approach.

ocrdma driver changes were done by Somnath Kotur <Somnath.Kotur@Avagotech.Com>

Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
  • Loading branch information
Matan Barak authored and Doug Ledford committed Oct 22, 2015
1 parent 99b27e3 commit dbf727d
Show file tree
Hide file tree
Showing 12 changed files with 193 additions and 110 deletions.
3 changes: 2 additions & 1 deletion drivers/infiniband/core/addr.c
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ static void resolve_cb(int status, struct sockaddr *src_addr,
}

int rdma_addr_find_dmac_by_grh(const union ib_gid *sgid, const union ib_gid *dgid,
u8 *dmac, u16 *vlan_id)
u8 *dmac, u16 *vlan_id, int if_index)
{
int ret = 0;
struct rdma_dev_addr dev_addr;
Expand All @@ -476,6 +476,7 @@ int rdma_addr_find_dmac_by_grh(const union ib_gid *sgid, const union ib_gid *dgi
rdma_gid2ip(&dgid_addr._sockaddr, dgid);

memset(&dev_addr, 0, sizeof(dev_addr));
dev_addr.bound_dev_if = if_index;

ctx.addr = &dev_addr;
init_completion(&ctx.comp);
Expand Down
4 changes: 2 additions & 2 deletions drivers/infiniband/core/core_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ void ib_device_unregister_sysfs(struct ib_device *device);
void ib_cache_setup(void);
void ib_cache_cleanup(void);

int ib_resolve_eth_l2_attrs(struct ib_qp *qp,
struct ib_qp_attr *qp_attr, int *qp_attr_mask);
int ib_resolve_eth_dmac(struct ib_qp *qp,
struct ib_qp_attr *qp_attr, int *qp_attr_mask);

typedef void (*roce_netdev_callback)(struct ib_device *device, u8 port,
struct net_device *idev, void *cookie);
Expand Down
2 changes: 1 addition & 1 deletion drivers/infiniband/core/uverbs_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2345,7 +2345,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
attr->alt_ah_attr.port_num = cmd.alt_dest.port_num;

if (qp->real_qp == qp) {
ret = ib_resolve_eth_l2_attrs(qp, attr, &cmd.attr_mask);
ret = ib_resolve_eth_dmac(qp, attr, &cmd.attr_mask);
if (ret)
goto release_qp;
ret = qp->device->modify_qp(qp, attr,
Expand Down
160 changes: 93 additions & 67 deletions drivers/infiniband/core/verbs.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
#include <linux/export.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <net/addrconf.h>

#include <rdma/ib_verbs.h>
#include <rdma/ib_cache.h>
Expand Down Expand Up @@ -308,6 +311,35 @@ struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
}
EXPORT_SYMBOL(ib_create_ah);

struct find_gid_index_context {
u16 vlan_id;
};

static bool find_gid_index(const union ib_gid *gid,
const struct ib_gid_attr *gid_attr,
void *context)
{
struct find_gid_index_context *ctx =
(struct find_gid_index_context *)context;

if ((!!(ctx->vlan_id != 0xffff) == !is_vlan_dev(gid_attr->ndev)) ||
(is_vlan_dev(gid_attr->ndev) &&
vlan_dev_vlan_id(gid_attr->ndev) != ctx->vlan_id))
return false;

return true;
}

static int get_sgid_index_from_eth(struct ib_device *device, u8 port_num,
u16 vlan_id, const union ib_gid *sgid,
u16 *gid_index)
{
struct find_gid_index_context context = {.vlan_id = vlan_id};

return ib_find_gid_by_filter(device, sgid, port_num, find_gid_index,
&context, gid_index);
}

int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,
const struct ib_wc *wc, const struct ib_grh *grh,
struct ib_ah_attr *ah_attr)
Expand All @@ -318,21 +350,30 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,

memset(ah_attr, 0, sizeof *ah_attr);
if (rdma_cap_eth_ah(device, port_num)) {
u16 vlan_id = wc->wc_flags & IB_WC_WITH_VLAN ?
wc->vlan_id : 0xffff;

if (!(wc->wc_flags & IB_WC_GRH))
return -EPROTOTYPE;

if (wc->wc_flags & IB_WC_WITH_SMAC &&
wc->wc_flags & IB_WC_WITH_VLAN) {
memcpy(ah_attr->dmac, wc->smac, ETH_ALEN);
ah_attr->vlan_id = wc->vlan_id;
} else {
if (!(wc->wc_flags & IB_WC_WITH_SMAC) ||
!(wc->wc_flags & IB_WC_WITH_VLAN)) {
ret = rdma_addr_find_dmac_by_grh(&grh->dgid, &grh->sgid,
ah_attr->dmac, &ah_attr->vlan_id);
ah_attr->dmac,
wc->wc_flags & IB_WC_WITH_VLAN ?
NULL : &vlan_id,
0);
if (ret)
return ret;
}
} else {
ah_attr->vlan_id = 0xffff;

ret = get_sgid_index_from_eth(device, port_num, vlan_id,
&grh->dgid, &gid_index);
if (ret)
return ret;

if (wc->wc_flags & IB_WC_WITH_SMAC)
memcpy(ah_attr->dmac, wc->smac, ETH_ALEN);
}

ah_attr->dlid = wc->slid;
Expand All @@ -344,10 +385,13 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,
ah_attr->ah_flags = IB_AH_GRH;
ah_attr->grh.dgid = grh->sgid;

ret = ib_find_cached_gid(device, &grh->dgid,
NULL, &port_num, &gid_index);
if (ret)
return ret;
if (!rdma_cap_eth_ah(device, port_num)) {
ret = ib_find_cached_gid_by_port(device, &grh->dgid,
port_num, NULL,
&gid_index);
if (ret)
return ret;
}

ah_attr->grh.sgid_index = (u8) gid_index;
flow_class = be32_to_cpu(grh->version_tclass_flow);
Expand Down Expand Up @@ -617,9 +661,7 @@ EXPORT_SYMBOL(ib_create_qp);
static const struct {
int valid;
enum ib_qp_attr_mask req_param[IB_QPT_MAX];
enum ib_qp_attr_mask req_param_add_eth[IB_QPT_MAX];
enum ib_qp_attr_mask opt_param[IB_QPT_MAX];
enum ib_qp_attr_mask opt_param_add_eth[IB_QPT_MAX];
} qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
[IB_QPS_RESET] = {
[IB_QPS_RESET] = { .valid = 1 },
Expand Down Expand Up @@ -700,12 +742,6 @@ static const struct {
IB_QP_MAX_DEST_RD_ATOMIC |
IB_QP_MIN_RNR_TIMER),
},
.req_param_add_eth = {
[IB_QPT_RC] = (IB_QP_SMAC),
[IB_QPT_UC] = (IB_QP_SMAC),
[IB_QPT_XRC_INI] = (IB_QP_SMAC),
[IB_QPT_XRC_TGT] = (IB_QP_SMAC)
},
.opt_param = {
[IB_QPT_UD] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY),
Expand All @@ -726,21 +762,7 @@ static const struct {
[IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY),
},
.opt_param_add_eth = {
[IB_QPT_RC] = (IB_QP_ALT_SMAC |
IB_QP_VID |
IB_QP_ALT_VID),
[IB_QPT_UC] = (IB_QP_ALT_SMAC |
IB_QP_VID |
IB_QP_ALT_VID),
[IB_QPT_XRC_INI] = (IB_QP_ALT_SMAC |
IB_QP_VID |
IB_QP_ALT_VID),
[IB_QPT_XRC_TGT] = (IB_QP_ALT_SMAC |
IB_QP_VID |
IB_QP_ALT_VID)
}
}
},
},
[IB_QPS_RTR] = {
[IB_QPS_RESET] = { .valid = 1 },
Expand Down Expand Up @@ -962,13 +984,6 @@ int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state,
req_param = qp_state_table[cur_state][next_state].req_param[type];
opt_param = qp_state_table[cur_state][next_state].opt_param[type];

if (ll == IB_LINK_LAYER_ETHERNET) {
req_param |= qp_state_table[cur_state][next_state].
req_param_add_eth[type];
opt_param |= qp_state_table[cur_state][next_state].
opt_param_add_eth[type];
}

if ((mask & req_param) != req_param)
return 0;

Expand All @@ -979,41 +994,52 @@ int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state,
}
EXPORT_SYMBOL(ib_modify_qp_is_ok);

int ib_resolve_eth_l2_attrs(struct ib_qp *qp,
struct ib_qp_attr *qp_attr, int *qp_attr_mask)
int ib_resolve_eth_dmac(struct ib_qp *qp,
struct ib_qp_attr *qp_attr, int *qp_attr_mask)
{
int ret = 0;
union ib_gid sgid;

if ((*qp_attr_mask & IB_QP_AV) &&
(rdma_cap_eth_ah(qp->device, qp_attr->ah_attr.port_num))) {
ret = ib_query_gid(qp->device, qp_attr->ah_attr.port_num,
qp_attr->ah_attr.grh.sgid_index, &sgid,
NULL);
if (ret)
goto out;
if (*qp_attr_mask & IB_QP_AV) {
if (qp_attr->ah_attr.port_num < rdma_start_port(qp->device) ||
qp_attr->ah_attr.port_num > rdma_end_port(qp->device))
return -EINVAL;

if (!rdma_cap_eth_ah(qp->device, qp_attr->ah_attr.port_num))
return 0;

if (rdma_link_local_addr((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw)) {
rdma_get_ll_mac((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw, qp_attr->ah_attr.dmac);
rdma_get_ll_mac((struct in6_addr *)sgid.raw, qp_attr->smac);
if (!(*qp_attr_mask & IB_QP_VID))
qp_attr->vlan_id = rdma_get_vlan_id(&sgid);
rdma_get_ll_mac((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw,
qp_attr->ah_attr.dmac);
} else {
ret = rdma_addr_find_dmac_by_grh(&sgid, &qp_attr->ah_attr.grh.dgid,
qp_attr->ah_attr.dmac, &qp_attr->vlan_id);
if (ret)
goto out;
ret = rdma_addr_find_smac_by_sgid(&sgid, qp_attr->smac, NULL);
if (ret)
union ib_gid sgid;
struct ib_gid_attr sgid_attr;
int ifindex;

ret = ib_query_gid(qp->device,
qp_attr->ah_attr.port_num,
qp_attr->ah_attr.grh.sgid_index,
&sgid, &sgid_attr);

if (ret || !sgid_attr.ndev) {
if (!ret)
ret = -ENXIO;
goto out;
}

ifindex = sgid_attr.ndev->ifindex;

ret = rdma_addr_find_dmac_by_grh(&sgid,
&qp_attr->ah_attr.grh.dgid,
qp_attr->ah_attr.dmac,
NULL, ifindex);

dev_put(sgid_attr.ndev);
}
*qp_attr_mask |= IB_QP_SMAC;
if (qp_attr->vlan_id < 0xFFFF)
*qp_attr_mask |= IB_QP_VID;
}
out:
return ret;
}
EXPORT_SYMBOL(ib_resolve_eth_l2_attrs);
EXPORT_SYMBOL(ib_resolve_eth_dmac);


int ib_modify_qp(struct ib_qp *qp,
Expand All @@ -1022,7 +1048,7 @@ int ib_modify_qp(struct ib_qp *qp,
{
int ret;

ret = ib_resolve_eth_l2_attrs(qp, qp_attr, &qp_attr_mask);
ret = ib_resolve_eth_dmac(qp, qp_attr, &qp_attr_mask);
if (ret)
return ret;

Expand Down
17 changes: 15 additions & 2 deletions drivers/infiniband/hw/mlx4/ah.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ static struct ib_ah *create_iboe_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr
struct mlx4_dev *dev = ibdev->dev;
int is_mcast = 0;
struct in6_addr in6;
u16 vlan_tag;
u16 vlan_tag = 0xffff;
union ib_gid sgid;
struct ib_gid_attr gid_attr;
int ret;

memcpy(&in6, ah_attr->grh.dgid.raw, sizeof(in6));
if (rdma_is_multicast_addr(&in6)) {
Expand All @@ -85,7 +88,17 @@ static struct ib_ah *create_iboe_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr
} else {
memcpy(ah->av.eth.mac, ah_attr->dmac, ETH_ALEN);
}
vlan_tag = ah_attr->vlan_id;
ret = ib_get_cached_gid(pd->device, ah_attr->port_num,
ah_attr->grh.sgid_index, &sgid, &gid_attr);
if (ret)
return ERR_PTR(ret);
memset(ah->av.eth.s_mac, 0, ETH_ALEN);
if (gid_attr.ndev) {
if (is_vlan_dev(gid_attr.ndev))
vlan_tag = vlan_dev_vlan_id(gid_attr.ndev);
memcpy(ah->av.eth.s_mac, gid_attr.ndev->dev_addr, ETH_ALEN);
dev_put(gid_attr.ndev);
}
if (vlan_tag < 0x1000)
vlan_tag |= (ah_attr->sl & 7) << 13;
ah->av.eth.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24));
Expand Down
12 changes: 8 additions & 4 deletions drivers/infiniband/hw/mlx4/mad.c
Original file line number Diff line number Diff line change
Expand Up @@ -1183,7 +1183,7 @@ static int is_proxy_qp0(struct mlx4_ib_dev *dev, int qpn, int slave)
int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
enum ib_qp_type dest_qpt, u16 pkey_index,
u32 remote_qpn, u32 qkey, struct ib_ah_attr *attr,
u8 *s_mac, struct ib_mad *mad)
u8 *s_mac, u16 vlan_id, struct ib_mad *mad)
{
struct ib_sge list;
struct ib_send_wr wr, *bad_wr;
Expand Down Expand Up @@ -1270,6 +1270,9 @@ int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
wr.send_flags = IB_SEND_SIGNALED;
if (s_mac)
memcpy(to_mah(ah)->av.eth.s_mac, s_mac, 6);
if (vlan_id < 0x1000)
vlan_id |= (attr->sl & 7) << 13;
to_mah(ah)->av.eth.vlan = cpu_to_be16(vlan_id);


ret = ib_post_send(send_qp, &wr, &bad_wr);
Expand Down Expand Up @@ -1306,6 +1309,7 @@ static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc
u8 *slave_id;
int slave;
int port;
u16 vlan_id;

/* Get slave that sent this packet */
if (wc->src_qp < dev->dev->phys_caps.base_proxy_sqpn ||
Expand Down Expand Up @@ -1394,18 +1398,18 @@ static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc
fill_in_real_sgid_index(dev, slave, ctx->port, &ah_attr);

memcpy(ah_attr.dmac, tunnel->hdr.mac, 6);
ah_attr.vlan_id = be16_to_cpu(tunnel->hdr.vlan);
vlan_id = be16_to_cpu(tunnel->hdr.vlan);
/* if slave have default vlan use it */
mlx4_get_slave_default_vlan(dev->dev, ctx->port, slave,
&ah_attr.vlan_id, &ah_attr.sl);
&vlan_id, &ah_attr.sl);

mlx4_ib_send_to_wire(dev, slave, ctx->port,
is_proxy_qp0(dev, wc->src_qp, slave) ?
IB_QPT_SMI : IB_QPT_GSI,
be16_to_cpu(tunnel->hdr.pkey_index),
be32_to_cpu(tunnel->hdr.remote_qpn),
be32_to_cpu(tunnel->hdr.qkey),
&ah_attr, wc->smac, &tunnel->mad);
&ah_attr, wc->smac, vlan_id, &tunnel->mad);
}

static int mlx4_ib_alloc_pv_bufs(struct mlx4_ib_demux_pv_ctx *ctx,
Expand Down
2 changes: 1 addition & 1 deletion drivers/infiniband/hw/mlx4/mcg.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ static int send_mad_to_wire(struct mlx4_ib_demux_ctx *ctx, struct ib_mad *mad)
spin_unlock_irqrestore(&dev->sm_lock, flags);
return mlx4_ib_send_to_wire(dev, mlx4_master_func_num(dev->dev),
ctx->port, IB_QPT_GSI, 0, 1, IB_QP1_QKEY,
&ah_attr, NULL, mad);
&ah_attr, NULL, 0xffff, mad);
}

static int send_mad_to_slave(int slave, struct mlx4_ib_demux_ctx *ctx,
Expand Down
2 changes: 1 addition & 1 deletion drivers/infiniband/hw/mlx4/mlx4_ib.h
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,7 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
enum ib_qp_type dest_qpt, u16 pkey_index, u32 remote_qpn,
u32 qkey, struct ib_ah_attr *attr, u8 *s_mac,
struct ib_mad *mad);
u16 vlan_id, struct ib_mad *mad);

__be64 mlx4_ib_get_new_demux_tid(struct mlx4_ib_demux_ctx *ctx);

Expand Down
Loading

0 comments on commit dbf727d

Please sign in to comment.