@@ -99,7 +99,9 @@ void agent_send_response(struct ib_mad *mad, struct ib_grh *grh,
}
agent = port_priv->agent[qpn];
- ah = ib_create_ah_from_wc(agent->qp->pd, wc, grh, port_num);
+ /* Physical devices (and their MAD replies) always reside in the host
+ * network namespace */
+ ah = ib_create_ah_from_wc(agent->qp->pd, wc, grh, port_num, &init_net);
if (IS_ERR(ah)) {
dev_err(&device->dev, "ib_create_ah_from_wc error %ld\n",
PTR_ERR(ah));
@@ -290,8 +290,13 @@ static int cm_alloc_response_msg(struct cm_port *port,
struct ib_mad_send_buf *m;
struct ib_ah *ah;
+ /* For IB, the network namespace doesn't affect the created address
+ * handle, so we use &init_net. In the future, RoCE support will
+ * require finding a specific network namespace to send the response
+ * from. */
ah = ib_create_ah_from_wc(port->mad_agent->qp->pd, mad_recv_wc->wc,
- mad_recv_wc->recv_buf.grh, port->port_num);
+ mad_recv_wc->recv_buf.grh, port->port_num,
+ &init_net);
if (IS_ERR(ah))
return PTR_ERR(ah);
@@ -346,7 +351,7 @@ static void cm_init_av_for_response(struct cm_port *port, struct ib_wc *wc,
av->port = port;
av->pkey_index = wc->pkey_index;
ib_init_ah_from_wc(port->cm_dev->ib_device, port->port_num, wc,
- grh, &av->ah_attr);
+ grh, &av->ah_attr, &init_net);
}
static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
@@ -157,8 +157,11 @@ static struct ib_mad_send_buf *alloc_response_msg(struct ib_mad_agent *agent,
struct ib_ah *ah;
int hdr_len;
+ /* Physical devices (and their MAD replies) always reside in the host
+ * network namespace */
ah = ib_create_ah_from_wc(agent->qp->pd, recv_wc->wc,
- recv_wc->recv_buf.grh, agent->port_num);
+ recv_wc->recv_buf.grh, agent->port_num,
+ &init_net);
if (IS_ERR(ah))
return (void *) ah;
@@ -287,10 +290,13 @@ create_rmpp_recv(struct ib_mad_agent_private *agent,
if (!rmpp_recv)
return NULL;
+ /* Physical devices (and their MAD replies) always reside in the host
+ * network namespace */
rmpp_recv->ah = ib_create_ah_from_wc(agent->agent.qp->pd,
mad_recv_wc->wc,
mad_recv_wc->recv_buf.grh,
- agent->agent.port_num);
+ agent->agent.port_num,
+ &init_net);
if (IS_ERR(rmpp_recv->ah))
goto error;
@@ -239,7 +239,9 @@ static void recv_handler(struct ib_mad_agent *agent,
ib_init_ah_from_wc(agent->device, agent->port_num,
mad_recv_wc->wc, mad_recv_wc->recv_buf.grh,
- &ah_attr);
+ &ah_attr, &init_net);
+ /* Note that network namespace seperation isn't supported on
+ * umad yet. */
packet->mad.hdr.gid_index = ah_attr.grh.sgid_index;
packet->mad.hdr.hop_limit = ah_attr.grh.hop_limit;
@@ -193,7 +193,8 @@ struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
EXPORT_SYMBOL(ib_create_ah);
int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc,
- struct ib_grh *grh, struct ib_ah_attr *ah_attr)
+ struct ib_grh *grh, struct ib_ah_attr *ah_attr,
+ struct net *net)
{
u32 flow_class;
u16 gid_index;
@@ -214,7 +215,7 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc,
ret = rdma_addr_find_dmac_by_grh(&grh->dgid, &grh->sgid,
ah_attr->dmac,
&ah_attr->vlan_id,
- &init_net);
+ net);
if (ret)
return ret;
}
@@ -247,12 +248,13 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc,
EXPORT_SYMBOL(ib_init_ah_from_wc);
struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc,
- struct ib_grh *grh, u8 port_num)
+ struct ib_grh *grh, u8 port_num,
+ struct net *net)
{
struct ib_ah_attr ah_attr;
int ret;
- ret = ib_init_ah_from_wc(pd->device, port_num, wc, grh, &ah_attr);
+ ret = ib_init_ah_from_wc(pd->device, port_num, wc, grh, &ah_attr, net);
if (ret)
return ERR_PTR(ret);
@@ -468,7 +468,8 @@ static void srpt_mad_recv_handler(struct ib_mad_agent *mad_agent,
return;
ah = ib_create_ah_from_wc(mad_agent->qp->pd, mad_wc->wc,
- mad_wc->recv_buf.grh, mad_agent->port_num);
+ mad_wc->recv_buf.grh, mad_agent->port_num,
+ &init_net);
if (IS_ERR(ah))
goto err;
@@ -48,6 +48,7 @@
#include <linux/rwsem.h>
#include <linux/scatterlist.h>
#include <linux/workqueue.h>
+#include <net/net_namespace.h>
#include <uapi/linux/if_ether.h>
#include <linux/atomic.h>
@@ -1798,9 +1799,14 @@ struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr);
* ignored unless the work completion indicates that the GRH is valid.
* @ah_attr: Returned attributes that can be used when creating an address
* handle for replying to the message.
+ * @net: The network namespace to use for address resolution.
+ *
+ * It is the caller's responsibility to make sure the network namespace is
+ * alive until the function returns.
*/
int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc,
- struct ib_grh *grh, struct ib_ah_attr *ah_attr);
+ struct ib_grh *grh, struct ib_ah_attr *ah_attr,
+ struct net *net);
/**
* ib_create_ah_from_wc - Creates an address handle associated with the
@@ -1810,12 +1816,17 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc,
* @grh: References the received global route header. This parameter is
* ignored unless the work completion indicates that the GRH is valid.
* @port_num: The outbound port number to associate with the address.
+ * @net: The network namespace to use for address resolution.
*
* The address handle is used to reference a local or global destination
* in all UD QP post sends.
+ *
+ * It is the caller's responsibility to make sure the network namespace is
+ * alive until the function returns.
*/
struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc,
- struct ib_grh *grh, u8 port_num);
+ struct ib_grh *grh, u8 port_num,
+ struct net *net);
/**
* ib_modify_ah - Modifies the address vector associated with an address