/* * Copyright (c) 2015, Mellanox Technologies inc. 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.
*/
#include"core_priv.h"
#include <linux/in.h> #include <linux/in6.h>
/* For in6_dev_get/in6_dev_put */ #include <net/addrconf.h> #include <net/bonding.h>
if (!rdma_protocol_roce(ib_dev, port)) return 1UL << IB_GID_TYPE_IB;
for (i = 0; i < CAP_TO_GID_TABLE_SIZE; i++) if (PORT_CAP_TO_GID_TYPE[i].is_supported(ib_dev, port))
ret_flags |= 1UL << PORT_CAP_TO_GID_TYPE[i].gid_type;
/** * is_ndev_for_default_gid_filter - Check if a given netdevice * can be considered for default GIDs or not. * @ib_dev: IB device to check * @port: Port to consider for adding default GID * @rdma_ndev: rdma netdevice pointer * @cookie: Netdevice to consider to form a default GID * * is_ndev_for_default_gid_filter() returns true if a given netdevice can be * considered for deriving default RoCE GID, returns false otherwise.
*/ staticbool
is_ndev_for_default_gid_filter(struct ib_device *ib_dev, u32 port, struct net_device *rdma_ndev, void *cookie)
{ struct net_device *cookie_ndev = cookie; bool res;
if (!rdma_ndev) returnfalse;
rcu_read_lock();
/* * When rdma netdevice is used in bonding, bonding master netdevice * should be considered for default GIDs. Therefore, ignore slave rdma * netdevices when bonding is considered. * Additionally when event(cookie) netdevice is bond master device, * make sure that it the upper netdevice of rdma netdevice.
*/
res = ((cookie_ndev == rdma_ndev && !netif_is_bond_slave(rdma_ndev)) ||
(netif_is_bond_master(cookie_ndev) &&
rdma_is_upper_dev_rcu(rdma_ndev, cookie_ndev)));
rcu_read_lock();
res = rdma_is_upper_dev_rcu(rdma_ndev, cookie);
rcu_read_unlock();
return res;
}
/** * is_upper_ndev_bond_master_filter - Check if a given netdevice * is bond master device of netdevice of the RDMA device of port. * @ib_dev: IB device to check * @port: Port to consider for adding default GID * @rdma_ndev: Pointer to rdma netdevice * @cookie: Netdevice to consider to form a default GID * * is_upper_ndev_bond_master_filter() returns true if a cookie_netdev * is bond master device and rdma_ndev is its lower netdevice. It might * not have been established as slave device yet.
*/ staticbool
is_upper_ndev_bond_master_filter(struct ib_device *ib_dev, u32 port, struct net_device *rdma_ndev, void *cookie)
{ struct net_device *cookie_ndev = cookie; bool match = false;
if (!rdma_ndev) returnfalse;
rcu_read_lock(); if (netif_is_bond_master(cookie_ndev) &&
rdma_is_upper_dev_rcu(rdma_ndev, cookie_ndev))
match = true;
rcu_read_unlock(); return match;
}
/* Lock the rtnl to make sure the netdevs does not move under * our feet
*/
rtnl_lock();
down_read(&net_rwsem);
for_each_net(net)
for_each_netdev(net, ndev) { /* * Filter and add default GIDs of the primary netdevice * when not in bonding mode, or add default GIDs * of bond master device, when in bonding mode.
*/ if (is_ndev_for_default_gid_filter(ib_dev, port,
rdma_ndev, ndev))
add_default_gids(ib_dev, port, rdma_ndev, ndev);
/** * rdma_roce_rescan_device - Rescan all of the network devices in the system * and add their gids, as needed, to the relevant RoCE devices. * * @ib_dev: the rdma device
*/ void rdma_roce_rescan_device(struct ib_device *ib_dev)
{
ib_enum_roce_netdev(ib_dev, pass_all_filter, NULL,
enum_all_gids_of_dev_cb, NULL);
}
EXPORT_SYMBOL(rdma_roce_rescan_device);
/** * rdma_roce_rescan_port - Rescan all of the network devices in the system * and add their gids if relevant to the port of the RoCE device. * * @ib_dev: IB device * @port: Port number
*/ void rdma_roce_rescan_port(struct ib_device *ib_dev, u32 port)
{ struct net_device *ndev = NULL;
if (rdma_protocol_roce(ib_dev, port)) {
ndev = ib_device_get_netdev(ib_dev, port); if (!ndev) return;
enum_all_gids_of_dev_cb(ib_dev, port, ndev, ndev);
dev_put(ndev);
}
}
EXPORT_SYMBOL(rdma_roce_rescan_port);
if (master_ndev) {
bond_delete_netdev_default_gids(ib_dev, port, rdma_ndev,
master_ndev);
dev_put(master_ndev);
}
}
/* The following functions operate on all IB devices. netdevice_event and * addr_event execute ib_enum_all_roce_netdevs through a work. * ib_enum_all_roce_netdevs iterates through all IB devices.
*/
if (ndev->type != ARPHRD_ETHER) return NOTIFY_DONE;
switch (event) { case NETDEV_REGISTER: case NETDEV_UP:
cmds[0] = bonding_default_del_cmd_join;
cmds[1] = add_default_gid_cmd;
cmds[2] = add_cmd; break;
case NETDEV_UNREGISTER: if (ndev->reg_state < NETREG_UNREGISTERED)
cmds[0] = del_cmd; else return NOTIFY_DONE; break;
case NETDEV_CHANGEADDR:
cmds[0] = netdev_del_cmd; if (ndev->reg_state == NETREG_REGISTERED) {
cmds[1] = add_default_gid_cmd;
cmds[2] = add_cmd;
} break;
case NETDEV_CHANGEUPPER:
netdevice_event_changeupper(ndev,
container_of(ptr, struct netdev_notifier_changeupper_info, info),
cmds); break;
case NETDEV_BONDING_FAILOVER:
cmds[0] = bonding_event_ips_del_cmd; /* Add default GIDs of the bond device */
cmds[1] = bonding_default_add_cmd; /* Add IP based GIDs of the bond device */
cmds[2] = add_cmd_upper_ips; break;
int __init roce_gid_mgmt_init(void)
{
gid_cache_wq = alloc_ordered_workqueue("gid-cache-wq", 0); if (!gid_cache_wq) return -ENOMEM;
register_inetaddr_notifier(&nb_inetaddr); if (IS_ENABLED(CONFIG_IPV6))
register_inet6addr_notifier(&nb_inet6addr); /* We relay on the netdevice notifier to enumerate all * existing devices in the system. Register to this notifier * last to make sure we will not miss any IP add/del * callbacks.
*/
register_netdevice_notifier(&nb_netdevice);
return 0;
}
void __exit roce_gid_mgmt_cleanup(void)
{ if (IS_ENABLED(CONFIG_IPV6))
unregister_inet6addr_notifier(&nb_inet6addr);
unregister_inetaddr_notifier(&nb_inetaddr);
unregister_netdevice_notifier(&nb_netdevice); /* Ensure all gid deletion tasks complete before we go down, * to avoid any reference to free'd memory. By the time * ib-core is removed, all physical devices have been removed, * so no issue with remaining hardware contexts.
*/
destroy_workqueue(gid_cache_wq);
}
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.