当前位置: 首页 > news >正文

【C语言】linux内核ip_local_out函数

一、讲解

这个函数 __ip_local_out 是 Linux 内核网络子系统中的函数,部分与本地出口的 IPv4 数据包发送相关。下面讲解这段代码的每一部分:
1. 函数声明 int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb):
   - struct net *net:是指向网络命名空间(network namespace)结构的指针,用来划分和隔离不同的网络环境。
   - struct sock *sk:是一个表示网络套接字的结构体指针,可以包含该数据包的源信息(如端口号、套接字选项等)。
   - struct sk_buff *skb:指向“socket buffer”结构体的指针,代表网络层面的数据包,包含要发送的数据和相关控制信息。
2. struct iphdr *iph = ip_hdr(skb);:
   - 定义了一个指向IP头部的指针 iph,通过调用 ip_hdr(skb) 来获得指向 skb 中IP头部的指针。
3. iph->tot_len = htons(skb->len);:
   - 设置IP头部的总长度字段 tot_len。通过 htons 函数将主机字节序转换成网络字节序,并将 skb 缓冲区的长度赋给它。
4. ip_send_check(iph);:
   - 调用 ip_send_check 函数来计算IP头部的校验和。
5-7. 接下来的注释说明,如果出口设备绑定到了一个L3主设备(如VRF - Virtual Routing and Forwarding),则需要将数据包传递给对应的处理程序。
8. skb = l3mdev_ip_out(sk, skb);:
   - 调用 l3mdev_ip_out 函数处理数据包,这个处理可能涉及特定的路由选择。
9. if (unlikely(!skb)) return 0;:
   - 检查 skb 是否已被 l3mdev_ip_out 释放或处理,如果是,那么函数返回0,表示没有更多处理需要完成。
10. skb->protocol = htons(ETH_P_IP);:
    - 在发送之前,设置数据包 skb->protocol 字段为IP协议(`ETH_P_IP`),并使用 htons 进行字节序转换。
11. 最后一行是调用 Netfilter 钩子(hook):   

    return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT,net, sk, skb, NULL, skb_dst(skb)->dev,dst_output);

    - 这是用于将数据包传递给网络过滤(Netfilter)框架,进行可能的过滤或调整。
    - NFPROTO_IPV4 指明协议是 IPv4。
    - NF_INET_LOCAL_OUT 是钩子点,表示数据包在本地被发送出去之前的处理阶段。
    - net, sk, skb, NULL, skb_dst(skb)->dev 是传递给钩子的各种参数。
    - dst_output 是输出函数,如果数据包通过过滤,它将负责将数据包发送出去。
这个函数最终返回 Netfilter 钩子的返回值,其可能是一个错误码或成功指示。整体来看,这个函数是处理并发送IPV4本地出口数据包的一部分过程。

二、中文注释

这个函数是Linux内核网络栈中的一个函数,它的责任是处理IP层的本地输出。

int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
{// 获取指向sk_buff中IP报头的指针struct iphdr *iph = ip_hdr(skb);// 设置IP报头中的总长度字段为skb的长度,htons用于将主机字节顺序转换为网络字节顺序iph->tot_len = htons(skb->len);// 计算和填充IP报头的校验和ip_send_check(iph);/* 如果出口设备属于一个L3主设备,就将skb传递给它的处理函数* l3mdev_ip_out负责处理skb,可能进行一些特定于该设备的处理*/skb = l3mdev_ip_out(sk, skb);// 如果skb为空,说明处理不成功,返回0if (unlikely(!skb))return 0;// 设置skb的协议字段为IP协议,htons用于将主机字节顺序转换为网络字节顺序skb->protocol = htons(ETH_P_IP);// 调用netfilter钩子,以便进行进一步的处理(例如,过滤,NAT等)// nf_hook会根据配置决定是否处理skb或将其传递给下一个处理阶段return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT,net, sk, skb, NULL, skb_dst(skb)->dev,dst_output);
}

解释完成后,简单总结此函数的流程:
1. 函数定义有三个参数:net结构体表示网络命名空间,sock结构体表示套接字状态信息,sk_buff结构体指针skb表示要处理的网络数据包。
2. 提取IP报头,并根据skb的长度设置IP报头的总长度字段。
3. 计算IP头部校验和。
4. 如果skb是流向L3主设备的,则调用l3mdev_ip_out函数进行进一步处理。
5. 如果l3mdev_ip_out返回null(即无法处理skb),则函数直接返回0。
6. 设置skb的协议类型为ETH_P_IP,表示这是一个IP数据包。
7. 最后调用`nf_hook`函数,触发相应的Netfilter钩子进行后续处理,如过滤、NAT等,然后将数据包传递到下一步(通常是网络接口层)。这里的`dst_output`是目标输出函数,用于最终将数据包发送出去。
这个函数是网络输出路径的一部分,确保在IP层发送的每个数据包都正确处理,并通过Netfilter框架进行必要的检查和修改。

三、ip_local_out

这段代码是Linux内核网络栈的一部分,是一个用于处理本地发出的IP数据包的函数。`ip_local_out` 函数是在网络层处理完毕,准备发送数据包到链路层之前调用的。下面是详细的中文解释:

int ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)

这个函数的定义意味着它用于处理本地发出的IP数据包。它接收三个参数:
- struct net *net:指向当期网络命名空间的指针。
- struct sock *sk:与数据包相关联的socket结构体的指针。
- struct sk_buff *skb:指向"socket buffer"的指针,这是一个封装了待发送数据包内容的结构体。

{int err;

定义一个整型变量 err,用于存储操作的结果状态。

    err = __ip_local_out(net, sk, skb);

调用 __ip_local_out 函数尝试处理和发送数据包。这个函数进行一系列的校验和调整,并准备数据包被发送。它返回一个整数值来表示操作的结果。

    if (likely(err == 1))err = dst_output(net, sk, skb);

后续的代码检查 __ip_local_out 函数的返回值。使用 likely 宏是一个编译器优化,指示 err == 1 这个条件很可能是真的,这样编译器可以优化代码的分支预测。如果 __ip_local_out 成功,返回值会是1,这时会调用 dst_output 函数来发送数据包。`dst_output` 函数完成将数据包发送到目的地的最后一步工作。

    return err;
}

最后,函数返回 err 变量的值,表示了 ip_local_out 这个函数的整体执行结果。如果一切成功,应该是返回零或者在传输数据包过程中发生的任何错误码。

EXPORT_SYMBOL_GPL(ip_local_out);

最后一行代码 EXPORT_SYMBOL_GPL 是一个宏,用于导出 ip_local_out 函数的符号,使其可以被其他模块调用,同时指定导出的符号遵循GPL许可。这样,只有GPL兼容的代码才能够使用此函数。

四、dst_output

dst_output 函数是一个在网络栈中用来处理传输层发出的数据包的内联函数(inline function),其目的是将数据包传递给下一层(通常是网络层),以便最终发送到网络上。函数原型如下:

static inline int dst_output(struct net *net, struct sock *sk, struct sk_buff *skb)

参数解释:
- struct net *net: 指向当前网络命名空间的指针,用于在多个网络命名空间环境中确定数据包所属的命名空间。
- struct sock *sk: 指向套接字结构的指针,代表数据包来源的套接字。这个结构包含了一系列关于套接字状态和选项的信息。
- struct sk_buff *skb: 指向“socket buffer”结构的指针,这是内核中用以存储网络数据包的标准容器。
函数的实现只包含一行代码:

return skb_dst(skb)->output(net, sk, skb);

解释:
- skb_dst(skb): 这是一个宏,功能是从 skb(数据包)中提取目的地信息(即 dst_entry 结构)。每个数据包都有一个 dst_entry,包含了关于目的地的信息,如路由决策。
- ->output: 这是 dst_entry 结构中的一个函数指针,指向实际负责输出数据包的函数。
- net, sk, skb: 将 dst_output 函数的参数传递给 output 函数,以便正确处理数据包。
总体来说,`dst_output` 函数的职责是调用正确的输出处理函数,这个函数由路由子系统在数据包通过路由选择的过程中确定,数据包将基于路由信息被发送到正确的网络接口。该函数的返回值通常是一个错误码,指示操作成功还是发生错误。

五、skb_dst

skb_dst 几乎在所有内核版本中都是通过宏定义实现的,因此你不会在代码中找到一个名为`skb_dst`的函数。它是对`sk_buff`数据结构中的一部分内容的一个访问器,通常是这样定义的:

#define skb_dst(skb) ((skb)->dst)

这个宏简单地从`sk_buff`结构体中提取出`dst`成员。`sk_buff`通常是内核网络子系统处理数据包时使用的数据结构,其中包含了数据包的各种控制信息和数据内容。
dst成员是一个`dst_entry`类型的指针,包含了关于目的地路由信息的详细内容,如下一跳地址、路径度量、特定的路由标志等。
实际的`dst_entry`结构体和相关函数的定义可以在内核源代码的路由(routing)相关的文件中找到,例如`include/net/dst.h`和相关的`net/ipv4`或`net/ipv6`目录下的文件。
请注意,内核源代码的具体结构和定义可能会根据正在查看的Linux内核版本有所不同。如果打算对这部分代码进行修改或者深入理解,建议确认正在查看的内核源代码的版本和具体的文件路径。

相关文章:

【C语言】linux内核ip_local_out函数

一、讲解 这个函数 __ip_local_out 是 Linux 内核网络子系统中的函数,部分与本地出口的 IPv4 数据包发送相关。下面讲解这段代码的每一部分: 1. 函数声明 int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb): -…...

动态规划6,最大数组和,环形子数组最大和,乘积最大子数组

最大子数组和 思路: 1.经验题目要求 dp[i]表示:以 i 位置为结尾的所有子数组中的最大和 2.状态转移方程 按长度来划分,如果长度为1,那么dp[i] nums[i]; 如果长度大于1,那么当前位置的最大和就为 i-1 位置最大和 …...

js 清空数组的方法

1、直接赋值空数组 let array [1, 2, 3, 4, 5]; array []; 这种方法并不推荐,如下图所示: 虽然a数组确实变为了空数组,但这种方法只是修改了a的指向,把a指向一个新的空数组,然而[1,2,3,4,5]这个数组并没有被清除&a…...

QT中使用QProcess执行命令,实时获取数据,例如进度条

前言 因为之前写了一个接收和发送文件的脚本&#xff0c;然后又需要获取进度&#xff0c;同步到进度条中。 效果&#xff1a; 使用正则匹配&#xff0c;获取命令行命令中的以下数据&#xff0c;然后同步到进度条 源码demo&#xff1a; 非完整代码&#xff1a; #include <Q…...

绘图设计:用Draw.io绘制图形技巧大全(含统一建模语言UML模板)

一、常见UML模板 1.流程图 2.用例图 include是包含关系&#xff0c;extend是扩展关系 简而言之&#xff0c;include是子集指向父集&#xff1b;而extend是扩展用例指向基础用例&#xff08;基础用例可以理解为系统核心功能&#xff0c;扩展用例是可选的&#xff0c;不是必须…...

被唤醒的“第二十条”深入人心

近来张艺谋执导的电影《第二十条》&#xff0c;因为它与正在召开中的全国两会所发布的《最高人民法院工作报告》联系相当紧密&#xff0c;加之可免费收看&#xff0c;网民便相互转告&#xff0c;于是此信息条目立即冲上了网络热搜榜&#xff0c;观者如潮。因为最高人民法院工作…...

PHPInfo()信息泄漏原理以及修复方法

漏洞名称&#xff1a;PHPInfo信息泄漏、phpinfo()函数信息泄漏 漏洞描述&#xff1a; phpinfo()函数返回的信息中包含了服务器的配置信息&#xff0c;包括&#xff1a; 1&#xff09;PHP编译选项以及文件扩展名的相关信息&#xff1b; 2&#xff09;php的版本信息 3&#…...

202441读书笔记|《笠翁对韵》—— 金菡萏,玉芙蓉,酒晕微酡琼杏颊,香尘浅印玉莲双

202441读书笔记|《笠翁对韵》——金菡萏&#xff0c;玉芙蓉&#xff0c;酒晕微酡琼杏颊&#xff0c;香尘浅印玉莲双 《作家榜名著&#xff1a;笠翁对韵》作者李渔&#xff0c;霍俊明。是所有词句都有注音的一本书&#xff0c;轻松学不认识的字&#xff0c;非常朗朗上口的对偶词…...

006-v-model原理

v-model原理 简介v-model应用在输入框上v-model应用在组件上 简介 由 属性绑定(v-bind:value“searchText”) 配合 input事件监听(v-on:input“searchText event.target.value”) 实现。 应用在组件上由 props: {value: xxx } &#xff0c;this.$emit(‘input’, xxx ) 完成。…...

Ubuntu下使用DAPLink(OpenOCD)

目录 1. 下载OpenOCD源代码 2. 编译代码 2.1 运行bootstrap 2.2 安装关联库 2.3 运行./configure 2.4 运行make 2.5 运行sudo make install 3. 烧录程序 3.1 挂起MCU 3.2 写入镜像 3.3 校验镜像 通过OpenOCD实现&#xff0c;在Ubuntu18 64bit下验证。 1. 下载OpenOC…...

C# 中 Math.Round 数学函数

在 C# 中&#xff0c;Math.Round 是一个数学函数&#xff0c;用于对一个浮点数进行四舍五入操作。它接受一个浮点数作为输入&#xff0c;并返回一个最接近输入值的整数或指定小数位数的浮点数。 Math.Round 方法有多个重载&#xff0c;其中最常用的重载有以下两种形式&#xf…...

力扣---接雨水---单调队列

题目&#xff1a; 单调队列思想&#xff1a; 没有思路的小伙伴可以先把这个想清楚哦&#xff1a;力扣hot10---大根堆双端队列-CSDN博客 从上面的图就可以发现&#xff0c;如果柱子呈递减序列&#xff0c;那么不会接到雨水&#xff0c;只要有一个小凸起柱子&#xff0c;那么这个…...

微分学<4>——微分中值定理

索引 微分中值定理极值定义4.1 极大(小)值定理4.1 Fermat引理定理4.2 Rolle定理 Lagrange中值定理定理4.3 Lagrange中值定理定理4.4 Cauchy中值定理 导数对函数性质的刻画Jensen不等式 微分中值定理 极值 定义4.1 极大(小)值 若存在 x 0 x_{0} x0​的邻域 U ( x 0 , δ ) U\…...

FPGA的时钟资源

目录 简介 Clock Region详解 MRCC和SRCC的区别 BUFGs 时钟资源总结 简介 7系列FPGA的时钟结构图&#xff1a; Clock Region&#xff1a;时钟区域&#xff0c;下图中有6个时钟区域&#xff0c;用不同的颜色加以区分出来 Clock Backbone&#xff1a;从名字也能看出来&#x…...

LeetCode27: 移除元素

题目描述 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出…...

Python使用Beautiful Soup及解析html获取元素并提取内容值

Python使用Beautiful Soup及解析html获取元素并提取内容值 1. 包括解析获取标题2. 根据标签及id获取所有元素3. 根据标签及class获取所有元素4. 获取元素下的标签的值5. 获取元素下的parent及child的元素的值参考 1. 包括解析获取标题 2. 根据标签及id获取所有元素 3. 根据标…...

如何清除keep-alive缓存

在 Vue.js 中&#xff0c;使用 <keep-alive> 组件可以将组件保留在内存中&#xff0c;以避免重复渲染和销毁&#xff0c;从而提高性能。如果需要手动清除 <keep-alive> 组件的缓存&#xff0c;可以通过两种方法来实现&#xff1a; 通过 $destroy 方法销毁组件&…...

2024年新手视频剪辑软件推荐-6款视频剪辑软件测评

视频剪辑软件推荐 premiere premiere 直达地址:各大软件网站 说到底,还是得专业的来,虽然很多人觉得他是收费的,但是你懂的,想要免费总是会有办法的.别的不说,剪辑这块,我还是很认可这个软件,虽然我现在还是刚入门. 剪映 剪映 抖音官方推出的一款手机视频编辑剪辑应用,提供切割…...

无货源抖店可以做吗?那些月入上万是真的吗?分享我的成功秘籍

大家好&#xff0c;我是电商花花。 现在还是有人在不停的在问&#xff0c;抖音小店无货源还可以做吗&#xff1f;那些月入上万都是真的吗&#xff1f; 当然是真的&#xff0c;而且做抖音小店非常简单&#xff0c;前提是你真的完全掌握到核心玩法&#xff0c;且要有执行力。 …...

文献阅读:DEA-Net:基于细节增强卷积和内容引导注意的单图像去雾

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 摘要Abstract文献阅读&#xff1a;DEA-Net&#xff1a;基于细节增强卷积和内容引导注意的单图像去雾1、研究背景2、方法提出3、相关知识3.1、DEConv3.3、多重卷积的…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

C# 表达式和运算符(求值顺序)

求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如&#xff0c;已知表达式3*52&#xff0c;依照子表达式的求值顺序&#xff0c;有两种可能的结果&#xff0c;如图9-3所示。 如果乘法先执行&#xff0c;结果是17。如果5…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧

上周三&#xff0c;HubSpot宣布已构建与ChatGPT的深度集成&#xff0c;这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋&#xff0c;但同时也存在一些关于数据安全的担忧。 许多网络声音声称&#xff0c;这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

MySQL的pymysql操作

本章是MySQL的最后一章&#xff0c;MySQL到此完结&#xff0c;下一站Hadoop&#xff01;&#xff01;&#xff01; 这章很简单&#xff0c;完整代码在最后&#xff0c;详细讲解之前python课程里面也有&#xff0c;感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...

【UE5 C++】通过文件对话框获取选择文件的路径

目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 &#xff0c;这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器&#xff0c;右键点击 .uproject 文件&#xff0c;选择 "Generate Visual Studio project files"&#xff0c;重…...

PostgreSQL 与 SQL 基础:为 Fast API 打下数据基础

在构建任何动态、数据驱动的Web API时&#xff0c;一个稳定高效的数据存储方案是不可或缺的。对于使用Python FastAPI的开发者来说&#xff0c;深入理解关系型数据库的工作原理、掌握SQL这门与数据库“对话”的语言&#xff0c;以及学会如何在Python中操作数据库&#xff0c;是…...