Skip to content

Commit

Permalink
IB/mlx4: Handle IPv4 header when demultiplexing MAD
Browse files Browse the repository at this point in the history
When MAD arrives to the hypervisor, we need to identify which slave it
should be sent by destination GID. When L3 protocol is IPv4 the
GRH is replaced by an IPv4 header. This patch detects when IPv4 header
needs to be parsed instead of GRH.

Fixes: b6ffaef ('mlx4: In RoCE allow guests to have multiple GIDS')
Signed-off-by: Moni Shoua <[email protected]>
Signed-off-by: Daniel Jurgens <[email protected]>
Reviewed-by: Mark Bloch <[email protected]>
Signed-off-by: Leon Romanovsky <[email protected]>
Signed-off-by: Doug Ledford <[email protected]>
  • Loading branch information
monis410 authored and dledford committed Nov 17, 2016
1 parent af4295c commit 850d8fd
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 10 deletions.
16 changes: 9 additions & 7 deletions drivers/infiniband/core/verbs.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
}
EXPORT_SYMBOL(ib_create_ah);

static int ib_get_header_version(const union rdma_network_hdr *hdr)
int ib_get_rdma_header_version(const union rdma_network_hdr *hdr)
{
const struct iphdr *ip4h = (struct iphdr *)&hdr->roce4grh;
struct iphdr ip4h_checked;
Expand Down Expand Up @@ -359,6 +359,7 @@ static int ib_get_header_version(const union rdma_network_hdr *hdr)
return 4;
return 6;
}
EXPORT_SYMBOL(ib_get_rdma_header_version);

static enum rdma_network_type ib_get_net_type_by_grh(struct ib_device *device,
u8 port_num,
Expand All @@ -369,7 +370,7 @@ static enum rdma_network_type ib_get_net_type_by_grh(struct ib_device *device,
if (rdma_protocol_ib(device, port_num))
return RDMA_NETWORK_IB;

grh_version = ib_get_header_version((union rdma_network_hdr *)grh);
grh_version = ib_get_rdma_header_version((union rdma_network_hdr *)grh);

if (grh_version == 4)
return RDMA_NETWORK_IPV4;
Expand Down Expand Up @@ -415,9 +416,9 @@ static int get_sgid_index_from_eth(struct ib_device *device, u8 port_num,
&context, gid_index);
}

static int get_gids_from_rdma_hdr(union rdma_network_hdr *hdr,
enum rdma_network_type net_type,
union ib_gid *sgid, union ib_gid *dgid)
int ib_get_gids_from_rdma_hdr(const union rdma_network_hdr *hdr,
enum rdma_network_type net_type,
union ib_gid *sgid, union ib_gid *dgid)
{
struct sockaddr_in src_in;
struct sockaddr_in dst_in;
Expand Down Expand Up @@ -447,6 +448,7 @@ static int get_gids_from_rdma_hdr(union rdma_network_hdr *hdr,
return -EINVAL;
}
}
EXPORT_SYMBOL(ib_get_gids_from_rdma_hdr);

int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,
const struct ib_wc *wc, const struct ib_grh *grh,
Expand All @@ -469,8 +471,8 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,
net_type = ib_get_net_type_by_grh(device, port_num, grh);
gid_type = ib_network_to_gid_type(net_type);
}
ret = get_gids_from_rdma_hdr((union rdma_network_hdr *)grh, net_type,
&sgid, &dgid);
ret = ib_get_gids_from_rdma_hdr((union rdma_network_hdr *)grh, net_type,
&sgid, &dgid);
if (ret)
return ret;

Expand Down
33 changes: 30 additions & 3 deletions drivers/infiniband/hw/mlx4/mad.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
#include <linux/mlx4/cmd.h>
#include <linux/gfp.h>
#include <rdma/ib_pma.h>
#include <linux/ip.h>
#include <net/ipv6.h>

#include <linux/mlx4/driver.h>
#include "mlx4_ib.h"
Expand Down Expand Up @@ -480,6 +482,23 @@ static int find_slave_port_pkey_ix(struct mlx4_ib_dev *dev, int slave,
return -EINVAL;
}

static int get_gids_from_l3_hdr(struct ib_grh *grh, union ib_gid *sgid,
union ib_gid *dgid)
{
int version = ib_get_rdma_header_version((const union rdma_network_hdr *)grh);
enum rdma_network_type net_type;

if (version == 4)
net_type = RDMA_NETWORK_IPV4;
else if (version == 6)
net_type = RDMA_NETWORK_IPV6;
else
return -EINVAL;

return ib_get_gids_from_rdma_hdr((union rdma_network_hdr *)grh, net_type,
sgid, dgid);
}

int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
enum ib_qp_type dest_qpt, struct ib_wc *wc,
struct ib_grh *grh, struct ib_mad *mad)
Expand Down Expand Up @@ -538,7 +557,10 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
memset(&attr, 0, sizeof attr);
attr.port_num = port;
if (is_eth) {
memcpy(&attr.grh.dgid.raw[0], &grh->dgid.raw[0], 16);
union ib_gid sgid;

if (get_gids_from_l3_hdr(grh, &sgid, &attr.grh.dgid))
return -EINVAL;
attr.ah_flags = IB_AH_GRH;
}
ah = ib_create_ah(tun_ctx->pd, &attr);
Expand Down Expand Up @@ -651,6 +673,11 @@ static int mlx4_ib_demux_mad(struct ib_device *ibdev, u8 port,
is_eth = 1;

if (is_eth) {
union ib_gid dgid;
union ib_gid sgid;

if (get_gids_from_l3_hdr(grh, &sgid, &dgid))
return -EINVAL;
if (!(wc->wc_flags & IB_WC_GRH)) {
mlx4_ib_warn(ibdev, "RoCE grh not present.\n");
return -EINVAL;
Expand All @@ -659,10 +686,10 @@ static int mlx4_ib_demux_mad(struct ib_device *ibdev, u8 port,
mlx4_ib_warn(ibdev, "RoCE mgmt class is not CM\n");
return -EINVAL;
}
err = mlx4_get_slave_from_roce_gid(dev->dev, port, grh->dgid.raw, &slave);
err = mlx4_get_slave_from_roce_gid(dev->dev, port, dgid.raw, &slave);
if (err && mlx4_is_mf_bonded(dev->dev)) {
other_port = (port == 1) ? 2 : 1;
err = mlx4_get_slave_from_roce_gid(dev->dev, other_port, grh->dgid.raw, &slave);
err = mlx4_get_slave_from_roce_gid(dev->dev, other_port, dgid.raw, &slave);
if (!err) {
port = other_port;
pr_debug("resolved slave %d from gid %pI6 wire port %d other %d\n",
Expand Down
19 changes: 19 additions & 0 deletions include/rdma/ib_verbs.h
Original file line number Diff line number Diff line change
Expand Up @@ -2580,6 +2580,24 @@ void ib_dealloc_pd(struct ib_pd *pd);
*/
struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr);

/**
* ib_get_gids_from_rdma_hdr - Get sgid and dgid from GRH or IPv4 header
* work completion.
* @hdr: the L3 header to parse
* @net_type: type of header to parse
* @sgid: place to store source gid
* @dgid: place to store destination gid
*/
int ib_get_gids_from_rdma_hdr(const union rdma_network_hdr *hdr,
enum rdma_network_type net_type,
union ib_gid *sgid, union ib_gid *dgid);

/**
* ib_get_rdma_header_version - Get the header version
* @hdr: the L3 header to parse
*/
int ib_get_rdma_header_version(const union rdma_network_hdr *hdr);

/**
* ib_init_ah_from_wc - Initializes address handle attributes from a
* work completion.
Expand Down Expand Up @@ -3357,4 +3375,5 @@ int ib_sg_to_pages(struct ib_mr *mr, struct scatterlist *sgl, int sg_nents,
void ib_drain_rq(struct ib_qp *qp);
void ib_drain_sq(struct ib_qp *qp);
void ib_drain_qp(struct ib_qp *qp);

#endif /* IB_VERBS_H */

0 comments on commit 850d8fd

Please sign in to comment.