第12章 网络 (6)

12.8 网络层

12.8.4 分组转发

转发IP分组,根据目标地址分为:

        1. 直接和本地相连。

        2. 不直接相连,需要网关转发。

int    ip_route_input_noref(skb,   daddr,   saddr,   tos,   net_dev):

        //查找路由表。

如果 skb->_skb_refdst 成员缓存了 struct   dst_entry 信息,无需查找路由表。

ip_forward 流程:

ip_forward_options:

        处理IP选项。

最后调用 skb->dst->output,即 ip_output。

struct   sock   {

        struct   dst_entry   *sk_dst_cache;         //缓存的路由结构体。

}

如何缓存一个struct   dst_entry     dst ?

        rcu_assign_pointer(sk->sk_dst_cache,   dst);

所以若同一 socket 的所有分组的目的地址都相同,则只需在发送第一个分组时查找 struct  dst_entry。

        后续分组可使用缓存的 struct  dst_entry。

12.8.5 发送分组

ip_queue_xmit:更高层协议使用,如TCP,UDP。

举例:

tcp_transmit_skb ->

        icsk->icsk_af_ops->queue_xmit(skb,   &inet->cork.fl);

                // 即 ip_queue_xmit ()

所以 转发和本地发送的数据,都最终调用 ip_output。

1. 转移到网络访问层

int   ip_output(struct  sk_buff   *skb)

{

        struct net_device  *dev   =   skb_dst(skb)->dev;

        skb->dev   =   dev;         //将skb->dev改为路由表指示的出口设备。

        NF_HOOK_COND(NFPROTO_IPV4,   NF_INET_POST_ROUTING,   skb,   ,   dev,

 ip_finish_output,  );

}

dst->neighbour->output   =   dev_queue_xmit;

        neighbour:ARP层相关。

dev_queue_xmit

        -> dev_hard_start_xmit

                -> ops->ndo_start_xmit(skb, dev); //不同网卡的驱动自定义。

2. 分片

分片原理:

ip_fragment:实现分片,并发送。

        包括:

                设置分片偏移量。

                除最后一个分片都设置MF标志。

3. 路由

struct   dst_entry   {         // 路由查找时填充成员。

        struct   net_device         *dev;

        int         (*input)(struct sk_buff   *);           //  处理进入分组。

        int         (*output)(struct sk_buff   *);         // 处理外出分组。

};

                                本地                         转发

input指针                 ip_local_deliver        ip_forward

output指针               ip_ouput                   ip_ouput

struct   neighbour    {         //就是ARP表项,存储本地网络的IP和硬件地址。

        struct neighbour           *next;

        struct neigh_table         *tbl;

        unsigned char         ha[ALIGN(MAX_ADDR_LEN,   sizeof(unsigned long))];

                //硬件地址

        int                 (*output)(struct  neighbour   *,    struct  sk_buff   *);

                // 用于转发数据包时发送数据包到邻居设备上。

                //通常为dev_queue_xmit; ,最终调用网卡实现的 ndo_start_xmit 函数指针。

        struct   net_device         *dev;

};

12.8.6 netfilter

1. 扩展网络功能

netfilter可扩展的功能:

        1. 不同方向的包过滤。

        2. NAT。

        3. 拆分、修改包。

2. 调用钩子函数

netfilter钩子函数会中断网络层函数。

如何调用钩子函数?

        使用宏 NF_HOOK

int   NF_HOOK(uint8_t pf,   unsigned int   hook,   struct sk_buff   *skb,   struct net_device   *in, struct net_device   *out,   int   (*okfn)(struct sk_buff *))

NF_HOOK

        -> NF_HOOK_THRESH(INT_MIN)

int   NF_HOOK_THRESH(pf,   hook,   skb,   in,   out,   okfn,   INT_MIN)

        //所有钩子函数都执行,因为INT_MIN值的最小

{

        int   ret    =    nf_hook_thresh(pf,   hook,    skb,    in,   out,    okfn,   thresh);

                //nf_hook_thresh->nf_hook_slow

        if (ret    ==    1)         //ret=1 即没有注册钩子函数

                ret    =    okfn(skb);

}

宏的参数介绍:

        pf:

                调用哪个协议族的钩子函数。

        hook:钩子编号。如:

                NF_IP_FORWORD

                NF_IP_LOCAL_OUT

        okfn:

                钩子函数结构后执行。

        thresh:

                优先级高于该值的钩子函数都将执行。

                最小为:INT_MIN,此时所有钩子函数都执行。

使用举例:

int    ip_forward(struct    sk_buff    *skb)

{

        ...

        return   NF_HOOK(NFPROTO_IPV4,    NF_INET_FORWARD,   skb,   skb->dev,

  rt->dst.dev,   ip_forward_finish);

}

所以 NF_INET_FORWARD 钩子函数执行完后,就调用okfn函数,即ip_forward_finish。

如果:

        1. 内核没有开启CONFIG_NETFILTER。

                或

        2. 没有注册对应pf,hook钩子函数。

则不调用钩子函数,直接执行okfn函数,即ip_forward_finish。

ip_forward_finish:实现转发操作,包含:

        1. 递减TTL(生存时间)。

        2. 修改 IP包头。

        3. 调用dev_queue_xmit。

        4. 更新路由缓存项,以加速下一次路由。

当没有配置CONFIG_NETFILTER:

        #define    NF_HOOK(pf,    hook,    skb,    indev,    outdev,   okfn)

                (okfn)(skb)

3. 扫描挂钩表

nf_hook_slow:扫描钩子链表。

所有的钩子函数保存在:

struct list_head    nf_hooks [ NFPROTO_NUMPROTO ] [ NF_MAX_HOOKS ];

NFPROTO_NUMPROTO:

        支持的协议族数量。如IPV4,IPV6,ARP,BRIDGE。

        默认值:13。

NF_MAX_HOOKS:

        一个协议族最多的挂钩链表。

        默认值:8。

最多链表数量:13 * 8。

IPV4协议族定义 5 个链表:

        NF_INET_PRE_ROUTING

        NF_INET_LOCAL_IN

        NF_INET_FORWARD

        NF_INET_LOCAL_OUT

        NF_INET_POST_ROUTING

这 5 个链表中连接了各自钩子函数。

钩子函数用 nf_hook_ops 表示:

        struct nf_hook_ops         *arpfilter_ops;

        struct nf_hook_ops         *mangle_ops;

        struct nf_hook_ops         *filter_ops;

        struct nf_hook_ops         *ipv4_conntrack_ops;

        struct nf_hook_ops         *rawtable_ops;

        struct nf_hook_ops         *ebt_ops_filter;

struct   nf_hook_ops   {

        struct list_head    list;

        nf_hookfn            *hook;         // 钩子函数。

        u_int8_t                pf;             // 协议族。

        unsigned int         hooknum;

                // 钩子编号,如 NF_INET_POST_ROUTING

        int                         priority;

                // 钩子的优先级。按先后执行。

                //如 INT_MIN

};

nf_hook_slow

        -> nf_iterate

nf_iterate:执行指定协议族,指定钩子编号中注册的所有钩子函数。

        如:

                协议族为NFPROTO_IPV4,

                钩子编号为NF_INET_POST_ROUTING。

                (当然是,大于指定优先级的所有钩子函数。)

4. 激活钩子函数

钩子函数的返回值:

        1. NF_ACCEPT:

                包通过当前检查点,继续协议栈后续处理。

        2. NF_DROP:

                该包将被丢弃。无需其他处理。

        3. NF_QUEUE:

                包被送到用户空间的一个队列中,供用户态程序后续处理。

                不再执行其他钩子函数。

        4. NF_REPEAT

                重复执行当前hook链规则检查。

12.8.7 IPv6

1. 概述

IPv6地址长度:128位。

注:IPv5名称被STP协议使用。

IPv6 报文格式:

2. 实现

IPv6低层和IPv4低层一样。

IPv6不会分片,所以帧格式中无需分片信息。

IPv6处理流程:

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

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

相关文章

AI产品经理的35岁危机_产品经理会有35岁危机吗

01 被裁的35岁朋友 去年,一家知名公司大裁员,很多 35 岁的非高管员工被牵连,包括我的一位朋友。 我第一时间联系了他,看看有没有能够帮上忙的地方。 我:传闻XX公司要收购你们? 朋友:是的。我要…

基于element-ui 日期选择器el-date-picker, 即对日期做区间限制

需求&#xff1a; 有时候需求会让我们对日期选择器做限制&#xff0c;即控制最多可跨越多少个月份&#xff0c;其中涉及到不同年份该如何计算。 HTML&#xff1a; <el-date-pickerv-model"timePeriod"type"monthrange"value-format"yyyyMM"…

鸿蒙Harmony编程开发:HTTPS服务端证书四种校验方式

如果你还是使用HttpRequest的话&#xff0c;答案是否定的。但是&#xff0c;鸿蒙开发者很贴心的推出了远场通信服务&#xff0c;可以使用rcp模块的方法发起请求&#xff0c;并且在请求时指定服务端证书的验证方式&#xff0c;关键点就在SecurityConfiguration接口上&#xff0c…

Kafka·概述

概览 Producer 生产者发送消息给broker&#xff0c;并不是生成一条消息后立刻发送&#xff0c;而是积攒多条后&#xff0c;批量发送到broker。可以通过配置参数batch.size&#xff08;单位字节&#xff09;调整积攒多少后发送 Consumer Topic 消息的分类 当Producer发送指定…

OpenAI 重回巅峰:ChatGPT-4O 最新模型超越谷歌 Gemini 1.5,多项测试夺冠!

谷歌上周发布的Gemini 1.5 Pro模型&#xff0c;在LMSYS办的聊天机器人竞技场Chatbot Arena中获得第一名。但是&#xff0c;OpenAI迅速反应&#xff0c;推出了最新的chatgpt-4o-latest模型&#xff0c;重新夺回了冠军头衔。 chatgpt-4o-latest模型简介 OpenAI最近推出了名为gpt-…

Unity教程(十二)视差背景

Unity开发2D类银河恶魔城游戏学习笔记 Unity教程&#xff08;零&#xff09;Unity和VS的使用相关内容 Unity教程&#xff08;一&#xff09;开始学习状态机 Unity教程&#xff08;二&#xff09;角色移动的实现 Unity教程&#xff08;三&#xff09;角色跳跃的实现 Unity教程&…

C语言-从键盘输入一个字符串,将其中的小写字母全部转换成大写字母,然后输出到一个磁盘文件test中保存,输人的字符串以“!”结束

题目要求&#xff1a; 从键盘输入一个字符串,将其中的小写字母全部转换成大写字母,然后输出到一个磁盘文件test中保存,输人的字符串以"!”结束 1.实现程序&#xff1a; #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int main() {FILE* fp fopen("…

鸿蒙内核源码分析(用户态锁篇) | 如何使用快锁Futex(上)

快锁上下篇 鸿蒙内核实现了Futex&#xff0c;系列篇将用两篇来介绍快锁&#xff0c;主要两个原因: 网上介绍Futex的文章很少&#xff0c;全面深入内核介绍的就更少&#xff0c;所以来一次详细整理和挖透。涉及用户态和内核态打配合&#xff0c;共同作用&#xff0c;既要说用户…

深入理解滑动窗口算法及其经典应用

文章目录 什么是滑动窗口&#xff1f;经典题型分析与讲解**1. 长度最小的子数组****2. 无重复字符的最长子串****3. 最长重复子数组****4. 将x减到0的最小操作数**5. 水果成篮 (LeetCode 904)6. 滑动窗口最大值 (LeetCode 239)7. 字符串中的所有字母异位词 (LeetCode 剑指 Offe…

区块链基础通识(1)——分布式系统的共识问题

分布式系统 我们最初了解区块链的时候&#xff0c;很多人会形容这个区块链是一个“分布式的不可篡改账本”&#xff0c;这是一个很形象的说法&#xff0c;但是我认为更为准确的形容是“所有节点共同维护的状态机”。为什么分布式和区块链不能划等号呢&#xff1f; 两种常见的…

数字身份革命:探索Web3对个人隐私的保护

在数字化时代&#xff0c;个人隐私和数据保护成为越来越重要的话题。随着Web3的兴起&#xff0c;这一领域正在经历一场深刻的变革。Web3不仅仅是技术的演进&#xff0c;更是对个人隐私保护的一次革命性革新。本文将探讨Web3如何通过去中心化技术重新定义数字身份&#xff0c;并…

npm install报错,解决记录:11个步骤诊断和解决问题

在处理npm install报错时&#xff0c;可以遵循以下步骤来诊断和解决问题&#xff1a; 查看错误信息&#xff1a; 错误信息通常会给出问题的线索&#xff0c;例如依赖包版本冲突、网络问题、权限问题等。 更新npm和Node.js&#xff1a; 首先尝试更新npm和Node.js到最新版本&…

电子电气架构--- 智能汽车电子架构的核心诉求

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 屏蔽力是信息过载时代一个人的特殊竞争力&#xff0c;任何消耗你的人和事&#xff0c;多看一眼都是你的不…

Windows平台SDKMAN工具使用

为方便jvm生态的软件版本管理&#xff0c;可以使用sdkman工具来安装和管理诸如java、gradle等软件的当前使用版本。尤其是大多数程序员都是在windows平台开发&#xff0c;团队开发通常都需要统一的jvm相关软件的版本。这里给大家演示下windows平台如何安装和使用sdkman来实现这…

安全架构设计

目录 1安全需求分析 2安全架构原则 3安全架构方法 系统架构完整实例_系统架构设计案例-CSDN博客 1安全概述 系统安全架构设计&#xff0c;主要包含&#xff1a;物理安全&#xff0c;网络安全&#xff0c;系统安全&#xff0c;数据安全&#xff0c;应用安全。 完整性(Integ…

内存管理篇-05物理页面的迁移类型migratetype

本节内容依旧是对上节课伙伴系统的补充&#xff0c;主要介绍了新版伙伴系统的页面迁移相关的内容 为什么要引入页面迁移类型&#xff1f;新版本伙伴系统针对老版本的伙伴系统的升级改进。主要优化memory compaction内存碎片整理的过程。 页面迁移实际上就是伙伴系统中free_area…

构建高效的串行任务执行器:SerialExecutor深度解析

本文主要介绍怎么去实现一个支持串行执行任务的SerialExecutor执行器 摘要 在复杂的异步编程中&#xff0c;有时我们需要确保任务以串行的方式执行&#xff0c;以维护任务间的依赖关系或顺序。SerialExecutor 是一个自定义的执行器&#xff0c;它封装了 Java 的 Executor 接口…

leetcode 3 无重复字符的最长子串

leetcode 3 无重复字符的最长子串 正文普通解法双指针 正文 普通解法 重点观察示例 3。本题重点是创建一个动态区间&#xff0c;然后判断位于这个动态区间之外的字符是否被包含在这个动态区间范围内。并且对于 s 长度小于 1 的情况要重点进行讨论。 class Solution:def lengt…

day38.动态规划+MySql数据库复习

844.比较含退格的字符串 给定 s 和 t 两个字符串&#xff0c;当它们分别被输入到空白的文本编辑器后&#xff0c;如果两者相等&#xff0c;返回 true 。# 代表退格字符。 注意&#xff1a;如果对空文本输入退格字符&#xff0c;文本继续为空 思路:定义两个栈&#xff0c;将字符…

后端完成api顺序

contoroller层 Service层 点击getById&#xff0c;如果没有getById函数就先声明一个 然后完成函数体 db层 数据访问对象.数据库方法 //作用是提供对数据库中特定表的操作方法