【C语言】ipoib模块 - ipoib_send_rss函数

一、ipoib_send_rss函数定义

int ipoib_send_rss(struct net_device *dev, struct sk_buff *skb,
           struct ib_ah *address, u32 dqpn)
{
    struct ipoib_dev_priv *priv = ipoib_priv(dev);
    struct ipoib_tx_buf *tx_req;
    struct ipoib_send_ring *send_ring;
    u16 queue_index;
    int hlen, rc;
    void *phead;
    int req_index;
    unsigned usable_sge = priv->max_send_sge - !!skb_headlen(skb);
    /* Find the correct QP to submit the IO to */
    queue_index = skb_get_queue_mapping(skb);
    send_ring = priv->send_ring + queue_index;
    if (skb_is_gso(skb)) {
        hlen = skb_transport_offset(skb) + tcp_hdrlen(skb);
        phead = skb->data;
        if (unlikely(!skb_pull(skb, hlen))) {
            ipoib_warn(priv, "linear data too small\n");
            ++send_ring->stats.tx_dropped;
            ++send_ring->stats.tx_errors;
            dev_kfree_skb_any(skb);
            return -1;
        }
    } else {
        if (unlikely(skb->len > priv->mcast_mtu + IPOIB_ENCAP_LEN)) {
            ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n",
                   skb->len, priv->mcast_mtu + IPOIB_ENCAP_LEN);
            ++send_ring->stats.tx_dropped;
            ++send_ring->stats.tx_errors;
            ipoib_cm_skb_too_long(dev, skb, priv->mcast_mtu);
            return -1;
        }
        phead = NULL;
        hlen  = 0;
    }
    if (skb_shinfo(skb)->nr_frags > usable_sge) {
        if (skb_linearize(skb) < 0) {
            ipoib_warn(priv, "skb could not be linearized\n");
            ++send_ring->stats.tx_dropped;
            ++send_ring->stats.tx_errors;
            dev_kfree_skb_any(skb);
            return -1;
        }
        /* Does skb_linearize return ok without reducing nr_frags? */
        if (skb_shinfo(skb)->nr_frags > usable_sge) {
            ipoib_warn(priv, "too many frags after skb linearize\n");
            ++send_ring->stats.tx_dropped;
            ++send_ring->stats.tx_errors;
            dev_kfree_skb_any(skb);
            return -1;
        }
    }
    ipoib_dbg_data(priv, "sending packet, length=%d address=%p qpn=0x%06x\n",
               skb->len, address, dqpn);
    /*
     * We put the skb into the tx_ring _before_ we call post_send_rss()
     * because it's entirely possible that the completion handler will
     * run before we execute anything after the post_send_rss().  That
     * means we have to make sure everything is properly recorded and
     * our state is consistent before we call post_send_rss().
     */
    req_index = send_ring->tx_head & (priv->sendq_size - 1);
    tx_req = &send_ring->tx_ring[req_index];
    tx_req->skb = skb;
    if (skb->len < ipoib_inline_thold &&
        !skb_shinfo(skb)->nr_frags) {
        tx_req->is_inline = 1;
        send_ring->tx_wr.wr.send_flags |= IB_SEND_INLINE;
    } else {
        if (unlikely(ipoib_dma_map_tx(priv->ca, tx_req))) {
            ++send_ring->stats.tx_errors;
            dev_kfree_skb_any(skb);
            return -1;
        }
        tx_req->is_inline = 0;
        send_ring->tx_wr.wr.send_flags &= ~IB_SEND_INLINE;
    }
    if (skb->ip_summed == CHECKSUM_PARTIAL)
        send_ring->tx_wr.wr.send_flags |= IB_SEND_IP_CSUM;
    else
        send_ring->tx_wr.wr.send_flags &= ~IB_SEND_IP_CSUM;
    /* increase the tx_head after send success, but use it for queue state */
    if (atomic_read(&send_ring->tx_outstanding) == priv->sendq_size - 1) {
        ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n");
        netif_stop_subqueue(dev, queue_index);
    }
    skb_orphan(skb);
    skb_dst_drop(skb);
    if (__netif_subqueue_stopped(dev, queue_index))
        if (ib_req_notify_cq(send_ring->send_cq, IB_CQ_NEXT_COMP |
                     IB_CQ_REPORT_MISSED_EVENTS))
            ipoib_warn(priv, "request notify on send CQ failed\n");
    rc = post_send_rss(send_ring, req_index,
               address, dqpn, tx_req, phead, hlen);
    if (unlikely(rc)) {
        ipoib_warn(priv, "post_send_rss failed, error %d\n", rc);
        ++send_ring->stats.tx_errors;
        if (!tx_req->is_inline)
            ipoib_dma_unmap_tx(priv, tx_req);
        dev_kfree_skb_any(skb);
        if (__netif_subqueue_stopped(dev, queue_index))
            netif_wake_subqueue(dev, queue_index);
        rc = 0;
    } else {
        netdev_get_tx_queue(dev, queue_index)->trans_start = jiffies;
        rc = send_ring->tx_head;
        ++send_ring->tx_head;
        atomic_inc(&send_ring->tx_outstanding);
    }
    return rc;
}

二、函数解读

函数`ipoib_send_rss` 是一个用于IPoIB(IP over InfiniBand)的Linux内核网络模块中针对发送数据包的函数。该函数使用Receive-Side Scaling(RSS)技术来支持多核处理,意味着它可以将数据包的发送操作分配给不同的CPU核心。以下是对该函数的逐行解读:
1. 函数接收四个参数:
   - *dev:指向`net_device`结构的指针,表示关联的InfiniBand网络设备。
   - *skb:指向`sk_buff`结构的指针,表示要发送的数据包。
   - *address:指向`ib_ah`结构的指针,表示Address Handle,用于标识目的地的地址信息。
   - dqpn:一个无符号32位整数,表示目的地的队列对编号(Destination Queue Pair Number)。
2. 函数首先通过`ipoib_priv(dev)`获取到设备的私有结构体指针`ipoib_dev_priv`。
3. 接着定义了一些本地变量,包括发送缓冲区请求指针`tx_req`、发送环指针 send_ring、队列索引`queue_index`和其他与发送操作相关的辅助变量。
4. 函数中首先计算出要使用的发送环的索引,通过调用`skb_get_queue_mapping(skb)`获取`skb`数据包的队列映射并存储于`queue_index`中。然后使用该索引从设备的私有结构体中获得对应的发送环 send_ring。
5. 对于分段的传输(skb_is_gso),函数将执行必要的操作来调整skb的头部指向传输数据,并更新数据包头长度。如果skb的头部数据太小无法进行这个操作,打印警告信息,丢弃skb,并返回错误代码。
6. 如果数据包长度超过了多播的最大传输单元加上IPoIB的封装长度,也会打印警告信息,递增丢包统计,并调用`ipoib_cm_skb_too_long`处理过长的数据包,然后返回错误代码。
7. 如果数据包包含的片段数(nr_frags)超出了最大支持的Scatter/Gather条目数量(usable_sge),函数尝试通过调用`skb_linearize`将数据包线性化。如果线性化失败或者仍然有太多片段,打印警告信息,丢弃skb,并返回错误代码。
8. 准备发送的数据包。如果skb的长度少于内联阈值并且没有片段,将数据包标记为内联发送;否则,将数据通过DMA映射到设备,并根据校验和需求设置IB的发送标志。
9. 在尝试发送数据包前,需要确保如果发送完成处理程序先于`post_send_rss`调用完成执行,所有的状态记录都已更新。
10. 如果发送队列满了,会停止网络队列来防止更多的发送操作。数据包被孤立(断开与套接字的联系),并且其路由缓存项被删除。
11. 如果子网络队列被停止了,请求发送完成队列的通知。如果请求通知失败,打印警告信息。
12. 通过调用`post_send_rss`函数发送数据包。如果发送失败,打印警告信息,解除DMA映射(如果使用的是DMA),释放skb,并唤醒网络子队列(如果它被停止了)。如果发送成功,更新发送环的状态记录,递增发送缓冲区标头索引,增加未完成的发送操作的计数,并返回成功。
综上所述,这个函数的作用是对于使用RSS的IPoIB进行数据包的准备和发送工作,涉及到网络队列的管理、数据包的内存管理和DMA,还包括对InfiniBand传输和其完成事件的处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/334475.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Backtrader 文档学习-Indicators混合时间框架

Backtrader 文档学习-Indicators混合时间周期 1.不同时间周期 如果数据源在Cerebro引擎中具有不同的时间范围和不同的长度&#xff0c;指示器将会终止。 比如&#xff1a;data0是日线&#xff0c;data1是月线 。 pivotpoint btind.PivotPoint(self.data1) sellsignal self…

第11章 GUI Page500~504 步骤三十二:打开画板文件02

各个图元类新增GetTypeName_Static()&#xff0c;并将原来的GetTypeName()改为调用静态方法实现&#xff1a; 直线&#xff1a; 圆&#xff1a; 十字&#xff1a; 矩形&#xff1a; 文字&#xff1a; tool_4_save_load.hpp添加两行 tool_4_save_load.cpp增加&#xff1a; 增加…

利用python进行有限元分析(一)

【利用Python进行有限元分析】 https://www.bilibili.com/video/BV1VE411s7Yy/?share_sourcecopy_web&vd_source3c57d167735998da175fa3c99f9d0e20离散了位移场&#xff0c;使用能量原理&#xff0c;用动能和应变能和虚功原理来寻找一致的质量、刚度和节点力向量。 一致是…

机器人强化学习-双机械臂

概要 基于 robosuite 库&#xff0c;进行双臂机器人学习训练 环境测试 下面展示下分别控制两个机械手随机运动的画面&#xff1a; 双臂显示场景如下&#xff1a;双臂调用代码如下&#xff1a; import numpy as np import robosuite as suite import robomimic import rob…

集成腾讯Bugly使用步骤以及字符串的上传(IOS手把手)

一、集成Bugly 1.通过CocoaPods集成&#xff0c;在工程的Podfile里面添加以下代码&#xff1a; pod Bugly 保存并在终端cd进入你的项目路径&#xff0c;执行pod install,然后用后缀为.xcworkspace的文件打开工程。 2.在工程的AppDelegate.m文件导入头文件 #import "A…

MacMaster:一款功能强大的高级网络接口管理与监控工具

关于MacMaster MacMaster是一款功能强大的高级网络接口管理与监控工具&#xff0c;该工具专为网络安全研究人员打造&#xff0c;支持对各种不同系统网络接口的MAC地址进行管理。 MacMaster本质上是一个全面的命令行工具&#xff0c;该工具在设计之初就考虑到的简单性和功能性…

树形结构下拉框组件vue-treeselect的使用(安装、模糊匹配、单选、多选、延迟加载、异步搜索等)

一、基本使用流程 首先npm安装依赖 npm install riophae/vue-treeselect --save然后在需要使用的组件中引入 import Treeselect from riophae/vue-treeselect import riophae/vue-treeselect/dist/vue-treeselect.css声明组件 components: { Treeselect }使用 <treesele…

智能驾驶新浪潮:SSD与UFS存储技术如何破浪前行?- SSD篇

随着汽车行业的不断发展&#xff0c;对存储的需求也在不断的变化中。早期阶段的汽车对存储的需求主要是收音机、播放器、导航仪等&#xff0c;有些还可以支持光盘和U盘的外接播放。中期阶段&#xff0c;也是当前主流的燃油车行车记录、多媒体、车联网的需求&#xff0c;对存储性…

【网站项目】基于ssm的青大校园预点餐系统

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

三层架构——工业控制领域简单理解

前言闲话 工业领域对好滴软件架构的需求不高&#xff0c;但不意味着可以用纯面向过程式编程解决问题&#xff0c;这样后期维护必将大乱。 曾经和一位从业30年的老电气工程师交流工业控制编程&#xff1a; 我问&#xff1a;为啥富士康这些大厂以前的机器都不联网&#xff1f;&…

自养买家号测评(补单)在亚马逊、lazada、速卖通等平台上需要注意什么?

在当今的电商环境中&#xff0c;许多卖家选择自己养号进行测评。然而&#xff0c;这种做法并非毫无风险。亚马逊、Lazada、eBay、Shopee、Wish、速卖通、沃尔玛、阿里国际、Mercari和Tik Tok等平台都存在封号的风险。特别是在每年的风险控制期内&#xff0c;新号被封的情况尤为…

Rectangle:圆角矩形、渐变矩形、随机颜色矩形

import QtQuickWindow {width: 640height: 480visible: truetitle: qsTr("Rectangle")//圆角Rectangle {id: rect1x: 120; y: 10width: 100; height: 200;border.color: "black"border.width: 3radius: 10}//渐变Rectangle {id: rect2x: 230; y: 10width: …

西门子WINCC常用C脚本1

1.置位&#xff0c;复位&#xff0c;取反 获取变量值&#xff1a;GetTagBit(可以是位也可以是字节&#xff0c;字&#xff0c;双字等具体字母不同) 设置变量值&#xff1a;SetTagBit 置位&#xff1a;SetTagBit&#xff08;"变量名",1&#xff09; 复位&#xff…

rbash环境变量提权

rbash为一个受限制的bash shell变体&#xff0c;限制用户在交互式环境中可使用的操作&#xff0c;以此提升系统安全性 可通过环境变量提权方式&#xff0c;越过此限制 export -p //查看环境变量 BASH_CMDS[a]/bin/sh;a //把/bin/sh给a /bin/bash export PATH$…

StackOverflow的架构

我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版&#xff0c;欢迎购买。点击进入详情 ​Stack Overflow 工程主管Roberta Arcoverde在最近接受 ​Scott Hanselman采访时透露了 Stack Overflow 架构的故事。他们每秒处理超过 6000 个请求&#xff0c…

如何利用在线网络靶场将安全提升至新水平

在 Standoff 365 的在线网络靶场中&#xff0c;任何公司都可以试验信息安全手段和企业网络设置&#xff0c;优化攻击检测、响应和事件调查的技能。 2023 年&#xff0c;我们不仅准许攻击者使用&#xff0c;也准许防御者使用。我们可以根据客户要求轻松部署 10 个细分行业中的任…

大创项目推荐 深度学习驾驶行为状态检测系统(疲劳 抽烟 喝水 玩手机) - opencv python

文章目录 1 前言1 课题背景2 相关技术2.1 Dlib人脸识别库2.2 疲劳检测算法2.3 YOLOV5算法 3 效果展示3.1 眨眼3.2 打哈欠3.3 使用手机检测3.4 抽烟检测3.5 喝水检测 4 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于深度学习的驾…

【不用找素材】ECS 游戏Demo制作教程(3) 1.17

一、生成墓碑 新建脚本如下&#xff1a; using Unity.Entities; using Unity.Mathematics;namespace ECSdemo {public struct GraveyardRandom : IComponentData{public Random Value;}}扩充GraveyardMono如下&#xff1a; using Unity.Entities; using Unity.Mathematics; …

代码随想录算法训练营day13|239.滑动窗口最大值、347.前K个高频元素

239. 滑动窗口最大值 347.前 K 个高频元素 239. 滑动窗口最大值 &#xff08;一刷至少需要理解思路&#xff09; 之前讲的都是栈的应用&#xff0c;这次该是队列的应用了。 本题算比较有难度的&#xff0c;需要自己去构造单调队列&#xff0c;建议先看视频来理解。 题目链接/文…

linux磁盘,分区,挂载等等

1. 修改磁盘分区的标签 例如&#xff1a;733be18b-7baf-d84c-879d-ca3db465f179太长了&#xff0c;修改一下。 linuxchenxiao:/media/linux/733be18b-7baf-d84c-879d-ca3db465f179$ 先 sudo blkid sudo blkid 找到你想修改的UUID(唯一标识符) /dev/sda1: UUID"733be…