一、ipoib_intf_init函数定义
int ipoib_intf_init(struct ib_device *hca, u8 port, const char *name,
struct net_device *dev, struct ipoib_dev_priv *priv)
{
struct rdma_netdev *rn = netdev_priv(dev);
int rc;
priv->ca = hca;
priv->port = port;
rc = rdma_init_netdev(hca, port, RDMA_NETDEV_IPOIB, name,
NET_NAME_UNKNOWN, ipoib_setup_common, dev,
!ipoib_enhanced_enabled);
if (rc) {
if (rc != -EOPNOTSUPP)
goto out;
if (priv->num_tx_queues > 1) {
netif_set_real_num_tx_queues(dev, priv->num_tx_queues);
netif_set_real_num_rx_queues(dev, priv->num_rx_queues);
rn->attach_mcast = ipoib_mcast_attach_rss;
rn->send = ipoib_send_rss;
/* Override ethtool_ops to ethtool_ops_rss */
ipoib_set_ethtool_ops_rss(dev);
} else {
rn->attach_mcast = ipoib_mcast_attach;
rn->send = ipoib_send;
}
dev->netdev_ops = ipoib_get_rn_ops(priv);
rn->detach_mcast = ipoib_mcast_detach;
rn->hca = hca;
}
priv->rn_ops = dev->netdev_ops;
dev->netdev_ops = ipoib_get_netdev_ops(priv);
rn->clnt_priv = priv;
/*
* Only the child register_netdev flows can handle priv_destructor
* being set, so we force it to NULL here and handle manually until it
* is safe to turn on.
*/
priv->next_priv_destructor = dev->priv_destructor;
dev->priv_destructor = NULL;
ipoib_build_priv(dev);
return 0;
out:
return rc;
}
二、函数解读
是的,这个函数`ipoib_intf_init`在初始化一个IP over InfiniBand (IPoIB) 网络接口时注册了回调函数 ipoib_send_rss 和 ipoib_send。让我们用中文逐步解读这个函数的作用和它做了什么:
1. 函数 ipoib_intf_init 接收了几个参数:
- *hca:指向InfiniBand设备 (ib_device) 的指针。
- port:表示InfiniBand端口的号码。
- *name:网络接口的名字。
- *dev:指向网络设备 (net_device) 的指针。
- *priv:指向IPoIB私有数据结构 (ipoib_dev_priv) 的指针。
2. 函数开始时,将 hca 和 port 存储在 priv 结构中,这样就能在后面使用这些IB设备和端口信息。
3. 调用 rdma_init_netdev 来初始化网络设备。这个过程会设置一些基础的网络设备操作,并且可以通过参数 ipoib_setup_common 来定制一些IPoIB的特定设置。
4. 如果 rdma_init_netdev 返回的 rc 不为零,表示初始化失败,除非错误代码是 -EOPNOTSUPP,否则会直接跳到函数最后,并返回错误码。
5. 如果初始化成功,函数将会根据 priv->num_tx_queues 的值来决定使用哪一套回调函数:
- 如果 priv->num_tx_queues 大于1,表示启用了多个发送队列(可能是为了RSS)。这时,函数会设置真正的发送(netif_set_real_num_tx_queues)和接收(netif_set_real_num_rx_queues)队列数量,并注册多队列版本的回调函数 ipoib_mcast_attach_rss 和 ipoib_send_rss。
- 如果只有一个发送队列,就会注册单队列版本的回调函数 ipoib_mcast_attach 和 ipoib_send。
6. 还有其他一些回调函数被设置,例如 ipoib_mcast_detach 用于处理组播的分离操作。
7. ipoib_get_rn_ops 和 ipoib_get_netdev_ops 函数被用于获取和设置适当的网络操作结构(netdev_ops),其中可能还包含了更多回调函数。
8. 函数设置了 rn->clnt_priv 为 priv,将私有结构关联到设备上下文中。
9. 有一个特别的代码块处理了网络设备的 priv_destructor。原来的析构器被存储在 priv->next_priv_destructor 中,而 dev->priv_destructor 被设置为 NULL。这表明在特定情况下,设备的内存或资源会在后续过程手动释放而不是自动释放。
10. 调用 ipoib_build_priv 函数来对IPoIB私有结构进行进一步初始和构建。
11. 在成功完成所有操作之后,函数返回0,表示成功。如果有步骤失败,则跳转至 out 标签,并返回相应的错误码。
总之,这个函数负责根据InfiniBand设备和端口对IPoIB网络接口进行初始化,注册了网络操作回调函数以及其他相关职能的函数,以便正确处理网络数据包的发送和接收。