/* * Copyright (c) 2005 Voltaire Inc. All rights reserved. * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved. * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved. * Copyright (c) 2005 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE.
*/
spin_lock_bh(&lock);
list_for_each_entry(req, &req_list, list) { if (nlh->nlmsg_seq != req->seq) continue; /* We set the DGID part, the rest was set earlier */
rdma_addr_set_dgid(req->addr, &gid);
req->status = 0;
found = 1; break;
}
spin_unlock_bh(&lock);
if (!found)
pr_info("Couldn't find request waiting for DGID: %pI6\n",
&gid);
}
int ib_nl_handle_ip_res_resp(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack)
{ if ((nlh->nlmsg_flags & NLM_F_REQUEST) ||
!(NETLINK_CB(skb).sk)) return -EPERM;
if (ib_nl_is_good_ip_resp(nlh))
ib_nl_process_good_ip_rsep(nlh);
/* If we have a gateway in IB mode then it must be an IB network */ if (has_gateway(dst, family) && dev_addr->network == RDMA_NETWORK_IB) return ib_nl_fetch_ha(dev_addr, daddr, seq, family); else return dst_fetch_ha(dst, dev_addr, daddr);
}
staticint addr_resolve_neigh(conststruct dst_entry *dst, conststruct sockaddr *dst_in, struct rdma_dev_addr *addr, unsignedint ndev_flags,
u32 seq)
{ int ret = 0;
if (ndev_flags & IFF_LOOPBACK)
memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN); else
ret = fetch_ha(dst, addr, dst_in, seq); return ret;
}
staticint copy_src_l2_addr(struct rdma_dev_addr *dev_addr, conststruct sockaddr *dst_in, conststruct dst_entry *dst, conststruct net_device *ndev)
{ int ret = 0;
if (dst->dev->flags & IFF_LOOPBACK)
ret = rdma_translate_ip(dst_in, dev_addr); else
rdma_copy_src_l2_addr(dev_addr, dst->dev);
/* * If there's a gateway and type of device not ARPHRD_INFINIBAND, * we're definitely in RoCE v2 (as RoCE v1 isn't routable) set the * network type accordingly.
*/ if (has_gateway(dst, dst_in->sa_family) &&
ndev->type != ARPHRD_INFINIBAND)
dev_addr->network = dst_in->sa_family == AF_INET ?
RDMA_NETWORK_IPV4 :
RDMA_NETWORK_IPV6; else
dev_addr->network = RDMA_NETWORK_IB;
*ndev_flags = ndev->flags; /* A physical device must be the RDMA device to use */ if (ndev->flags & IFF_LOOPBACK) { /* * RDMA (IB/RoCE, iWarp) doesn't run on lo interface or * loopback IP address. So if route is resolved to loopback * interface, translate that to a real ndev based on non * loopback IP address.
*/
ndev = rdma_find_ndev_for_src_ip_rcu(dev_net(ndev), dst_in); if (IS_ERR(ndev)) return -ENODEV;
}
ndev = rdma_read_gid_attr_ndev_rcu(addr->sgid_attr); if (IS_ERR(ndev)) return PTR_ERR(ndev);
/* * Since we are holding the rcu, reading net and ifindex * are safe without any additional reference; because * change_net_namespace() in net/core/dev.c does rcu sync * after it changes the state to IFF_DOWN and before * updating netdev fields {net, ifindex}.
*/
addr->net = dev_net(ndev);
addr->bound_dev_if = ndev->ifindex; return 0;
}
if (!addr->net) {
pr_warn_ratelimited("%s: missing namespace\n", __func__); return -EINVAL;
}
rcu_read_lock(); if (resolve_by_gid_attr) { if (!addr->sgid_attr) {
rcu_read_unlock();
pr_warn_ratelimited("%s: missing gid_attr\n", __func__); return -EINVAL;
} /* * If the request is for a specific gid attribute of the * rdma_dev_addr, derive net from the netdevice of the * GID attribute.
*/
ret = set_addr_netns_by_gid_rcu(addr); if (ret) {
rcu_read_unlock(); return ret;
}
} if (src_in->sa_family == AF_INET) {
ret = addr4_resolve(src_in, dst_in, addr, &rt);
dst = &rt->dst;
} else {
ret = addr6_resolve(src_in, dst_in, addr, &dst);
} if (ret) {
rcu_read_unlock(); goto done;
}
ret = rdma_set_src_addr_rcu(addr, &ndev_flags, dst_in, dst);
rcu_read_unlock();
/* * Resolve neighbor destination address if requested and * only if src addr translation didn't fail.
*/ if (!ret && resolve_neigh)
ret = addr_resolve_neigh(dst, dst_in, addr, ndev_flags, seq);
if (src_in->sa_family == AF_INET)
ip_rt_put(rt); else
dst_release(dst);
done: /* * Clear the addr net to go back to its original state, only if it was * derived from GID attribute in this context.
*/ if (resolve_by_gid_attr)
rdma_addr_set_net_defaults(addr); return ret;
}
spin_lock_bh(&lock); /* * Although the work will normally have been canceled by the workqueue, * it can still be requeued as long as it is on the req_list.
*/
cancel_delayed_work(&req->work); if (!list_empty(&req->list)) {
list_del_init(&req->list);
kfree(req);
}
spin_unlock_bh(&lock);
}
/** * rdma_addr_cancel - Cancel resolve ip request * @addr: Pointer to address structure given previously * during rdma_resolve_ip(). * rdma_addr_cancel() is synchronous function which cancels any pending * request if there is any.
*/ void rdma_addr_cancel(struct rdma_dev_addr *addr)
{ struct addr_req *req, *temp_req; struct addr_req *found = NULL;
spin_lock_bh(&lock);
list_for_each_entry_safe(req, temp_req, &req_list, list) { if (req->addr == addr) { /* * Removing from the list means we take ownership of * the req
*/
list_del_init(&req->list);
found = req; break;
}
}
spin_unlock_bh(&lock);
if (!found) return;
/* * sync canceling the work after removing it from the req_list * guarentees no work is running and none will be started.
*/
cancel_delayed_work_sync(&found->work);
kfree(found);
}
EXPORT_SYMBOL(rdma_addr_cancel);
struct resolve_cb_context { struct completion comp; int status;
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.