【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内核版本有所不同。如果打算对这部分代码进行修改或者深入理解,建议确认正在查看的内核源代码的版本和具体的文件路径。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

react实战——react旅游网

慕课网react实战 搭建项目问题1.按照官网在index.tsx中引入antd出错?2.typescript中如何使用react-router3.react-router3.1 V63.2 V53.3V6实现私有路由 4.函数式组件接收props参数时定义数据接口?5.使用TypeScript开发react项目:6.要使一个组…

SQLite3中的callback回调函数注意的细节

调用 sqlite3_exec(sqlite3*, const char *sql, sqlite_callback, void *data, char **errmsg)该例程提供了一个执行 SQL 命令的快捷方式, SQL 命令由 sql 参数提供,可以由多个 SQL 命令组成。 在这里, 第一个参数 sqlite3 是打开的数据库对…

代码随想录算法训练营第day41|背包理论基础、416. 分割等和子集

目录 a.背包理论基础——01背包 1.二维数组的01背包表示 2.一维滚动数组表示 b. 416. 分割等和子集 - 力扣(LeetCode) a.背包理论基础——01背包 背包问题分类: 对于面试的话,其实掌握01背包,和完全背包&#xff…

Excel F4键的作用

目录 一. 单元格相对/绝对引用转换二. 重复上一步操作 一. 单元格相对/绝对引用转换 ⏹ 使用F4键 如下图所示,B1单元格引用了A1单元格的内容。此时是使用相对引用,可以按下键盘上的F4键进行相对引用和绝对引用的转换。 二. 重复上一步操作 ⏹添加或删除…

SSM框架,MyBatis-Plus的学习(下)

条件构造器 使用MyBatis-Plus的条件构造器,可以构建灵活高效的查询条件,可以通过链式调用来组合多个条件。 条件构造器的继承结构 Wrapper : 条件构造抽象类,最顶端父类 AbstractWrapper : 用于查询条件封装&#xf…

首屏性能优化:提升用户体验的秘籍

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

复盘-excel

excel-选列没有用,选小标题才可以 将簇状柱形图放置在一个新表上##### excel: 添加数据模型时,要通过套用表格格式与外部断开连接 透视分析2010年人数未解决(第四套) 通过日期显示星期几 判断星期几 因为前面已经通过星期六&#xff0c…

03_Tomcat

文章目录 Tomcat概念自制简易的服务器JavaEE规范Tomcat安装Tomcat启动Tomcat的资源部署直接部署虚拟映射 Tomcat的设置 Tomcat 概念 服务器:两层含义。 软件层面:软件,可以将本地的资源发布到网络中,供网络上面的其他用户来访问…

grafana table合并查询

注:本文基于Grafana v9.2.8编写 1 问题 默认情况下table展示的是一个查询返回的多个field,但是我想要的数据在不同的metric上,比如我需要显示某个pod的读写IO,但是读和写这两个指标存在于两个不同的metirc,需要分别查…

多种方法求解数组排序

𝙉𝙞𝙘𝙚!!👏🏻‧✧̣̥̇‧✦👏🏻‧✧̣̥̇‧✦ 👏🏻‧✧̣̥̇:Solitary_walk ⸝⋆ ━━━┓ - 个性标签 - :来于“云”的“羽球人”。…

C++——string模拟实现

前言:上篇文章我们对string类及其常用的接口方法的使用进行了分享,这篇文章将着重进行对这些常用的接口方法的内部细节进行分享和模拟实现。 目录 一.基础框架 二.遍历字符串 1.[]运算符重载 2.迭代器 3.范围for 三.常用方法 1.增加 2.删除 3.调…

数据库-第十一章 并发控制【期末复习|考研复习】

前言 总结整理不易,希望大家点赞收藏。 给大家整理了一下数据库系统概论中的重点概念,以供大家期末复习和考研复习的时候使用。 参考资料是王珊老师和萨师煊老师的数据库系统概论(第五版)。 数据库系统概论系列文章传送门: 第一章 绪论 第二/…

数据分析-Pandas数据画箱线图

数据分析-Pandas数据画箱线图 数据分析和处理中,难免会遇到各种数据,那么数据呈现怎样的规律呢?不管金融数据,风控数据,营销数据等等,莫不如此。如何通过图示展示数据的规律? 数据表&#xff…

【重新定义matlab强大系列十七】Matlab深入浅出长短期记忆神经网络LSTM

🔗 运行环境:Matlab 🚩 撰写作者:左手の明天 🥇 精选专栏:《python》 🔥 推荐专栏:《算法研究》 #### 防伪水印——左手の明天 #### 💗 大家好🤗&#x1f91…

音视频学习笔记——c++多线程(二)

✊✊✊🌈大家好!本篇文章是多线程系列第二篇文章😇。首先讲解了利用mutex解决多线程数据共享问题,举例更好理解lock和unlock的使用方法,以及错误操作造成的死锁问题,最后讲解了lock_guard与unique_lock使用…

Django模型层(附带test环境)

Django模型层(附带test环境) 目录 Django模型层(附带test环境)连接数据库Django ORM在models.py中建表允许为空指定默认值数据库迁移命令 开启测试环境建表语句补充(更改默认表名)数据的增加时间数据的时区 多表数据的增加一对多多对多 数据的删除修改数据查询数据查询所有数据…

鸿蒙OpenHarmony HDF 驱动开发

目录 序一、概述二、HDF驱动框架三、驱动程序四、驱动配置坚持就有收获 序 最近忙于适配OpenHarmonyOS LiteOS-M 平台,已经成功实践适配平台GD32F407、STM32F407、STM32G474板卡,LiteOS适配已经算是有实际经验了。 但是,鸿蒙代码学习进度慢下…

【AcWing】蓝桥杯集训每日一题Day1|二分|差分|503.借教室(C++)

503. 借教室 503. 借教室 - AcWing题库难度:简单时/空限制:1s / 128MB总通过数:8052总尝试数:26311来源:NOIP2012提高组算法标签二分差分 题目内容 在大学期间,经常需要租借教室。 大到院系举办活动&…

基于机器学习的网络入侵检测二元分类模型构建与性能评估(NSL-KDD数据集)

简介 该项目是一个基于NSL-KDD数据集的网络入侵检测系统,主要采用机器学习方法对网络流量数据进行使用了多种机器学习模型,如逻辑回归、线性SVM、多项式核SVM、高斯核SVM、决策树、随机森林、朴素贝叶斯和K近邻算法训练二元分类(正常/异常&a…

bug总结(1)--变量取错

a c t i v i t y [ ′ t a g n a m e ′ ] 应为 activity[tag_name]应为 activity[′tagn​ame′]应为couponActivitList[0][‘name’] .隐藏的bug,在测试中竟然测不出来,而且上线了好久。为啥会出现这种低级错误呢?第一是写的时候不够仔细认…