C语言linux内核ipoib模块 – ipoib_intf_init

一、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网络接口进行初始化,注册了网络操作回调函数以及其他相关职能的函数,以便正确处理网络数据包的发送和接收。