Linux 内核源码阅读——ipv4

[复制链接]
发表于 2025-10-10 05:51:45 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
Linux 内核源码阅读——ipv4

综述

在 Linux 内核中,IPv4 协议的实现重要分布在 net/ipv4/ 目次下。以下是一些关键的源文件及其作用:
1. 协议栈焦点


  • net/ipv4/ip_input.c:处置惩罚吸收到的 IPv4 数据包(输入路径)。
  • net/ipv4/ip_output.c:处置惩罚 IPv4 数据包的发送(输出路径)。
  • net/ipv4/ip_forward.c:实现 IP 数据包的转发逻辑。
2. 所在管理


  • net/ipv4/devinet.c:管理 IPv4 所在,包罗添加、删除和查询接口所在。
  • net/ipv4/af_inet.c:实现 IPv4 协议族的 socket 利用,如 socket()、bind()、connect() 等。
3. 路由子体系


  • net/ipv4/route.c:焦点的路由查找和管理逻辑。
  • net/ipv4/fib_frontend.c、fib_trie.c:实现基于前缀树(Trie)的 FIB(Forwarding Information Base)路由表。
4. 传输层交互


  • net/ipv4/tcp_ipv4.c:IPv4 版本的 TCP 处置惩罚。
  • net/ipv4/udp.c:IPv4 版本的 UDP 处置惩罚。
  • net/ipv4/raw.c:处置惩罚 IPv4 原始套接字(Raw Sockets)。
5. 其他紧张模块


  • net/ipv4/ip_fragment.c:处置惩罚 IP 数据包的分片和重组。
  • net/ipv4/icmp.c:实现 ICMP(Internet Control Message Protocol)。
  • net/ipv4/igmp.c:实现 IGMP(Internet Group Management Protocol)。
  • net/ipv4/netfilter/ 目次:Linux 内核 Netfilter(防火墙和 NAT)干系代码。
收发包

关键数据布局

iphdr
  1. struct iphdr {
  2. #if defined(__LITTLE_ENDIAN_BITFIELD)
  3.         __u8        ihl:4,      // IP头长度 (单位:4字节)
  4.                 version:4;       // IP版本(例如 IPv4)
  5. #elif defined (__BIG_ENDIAN_BITFIELD)
  6.         __u8        version:4,   // IP版本(例如 IPv4)
  7.                   ihl:4;          // IP头长度 (单位:4字节)
  8. #else
  9. #error        "Please fix <asm/byteorder.h>"  // 如果没有定义大小端模式,编译时会报错
  10. #endif
  11.         __u8        tos;          // 服务类型(Type of Service,TOS),用于指定数据包的优先级和路由
  12.         __u16        tot_len;      // 总长度(包括头部和数据部分),单位字节
  13.         __u16        id;           // 标识符,用于标识分片的所有部分
  14.         __u16        frag_off;     // 分片偏移和标志,指示是否是分片,以及分片的位置
  15.         __u8        ttl;          // 生存时间(Time To Live),指定数据包能在网络上生存的最大跳数
  16.         __u8        protocol;     // 上层协议类型(例如 ICMP、TCP、UDP 等)
  17.         __u16        check;        // 校验和,用于错误检查
  18.         __u32        saddr;        // 源 IP 地址
  19.         __u32        daddr;        // 目标 IP 地址
  20.         /*The options start here. */
  21. };
复制代码
收包重要接口ip_rcv
  1. /**
  2. * ip_rcv - 处理接收到的 IPv4 数据包
  3. * @skb: 指向 socket buffer 的指针,包含接收到的数据包
  4. * @dev: 指向接收到数据包的网络设备的指针
  5. * @pt: 指向 packet_type 结构体的指针,描述数据包类型
  6. *
  7. * 该函数用于接收并处理从网络设备接收到的 IPv4 数据包。它解析 IP 头部,
  8. * 检查数据包的有效性,并根据协议类型(如 TCP、UDP 或 ICMP)将数据包
  9. * 传递给相应的协议栈进行处理。如果数据包不可达或格式无效,返回错误。
  10. * 如果数据包处理成功,返回 0。
  11. *
  12. * 返回值:
  13. *   - 0:表示数据包处理成功,已传递给适当的协议处理函数
  14. *   - 负值:表示错误,例如数据包格式无效或目标不可达
  15. */
  16. int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt);
复制代码
  1. @startuml
  2. start
  3. :网络数据包到达;
  4. :调用 ip_rcv 函数;
  5. :调用 ip_rcv_finish 完成处理;
  6. :调用 ip_route_input 查找路由;
  7. if (路由(缓存)查找成功?) then (是)
  8.   if (是本地包?) then (是)
  9.     :调用 ip_local_deliver 处理本地包;
  10.     :将数据包交给本地协议栈处理;
  11.   else (否)
  12.     if (是多播包?) then (是)
  13.       :调用 ip_route_input_mc 处理多播包;
  14.       :处理多播包;
  15.     else (否)
  16.       :调用 ip_route_input_slow 进行慢路径处理;
  17.       :处理路由查找未命中的情况;
  18.         note right
  19.           插入缓存表rt_hash_table
  20.       end note
  21.     endif
  22.   endif
  23. else (否)
  24.   :调用 ip_route_input_slow 进行慢路径处理;
  25.   :处理路由查找未命中的情况;
  26.   note right
  27.         插入缓存表rt_hash_table
  28.   end note
  29. endif
  30. stop
  31. @enduml
复制代码

本机包:ip_local_deliver
其他包,举行转发:ip_forward
发包重要接口ip_output

该函数的重要任务是:

  • 处置惩罚 IP 头部(如查抄和更新校验和)
  • 实验 IP 选项 处置惩罚
  • 大概必要举行 分片
  • 终极调用 底层链路层接口 举行发送
  1. int ip_output(struct sk_buff *skb)
复制代码
重要流程
  1. @startuml
  2. start
  3. :调用 ip_output(skb);
  4. if (需要分片?) then (是)
  5.     :调用 ip_fragment(skb);
  6.     :对每个分片调用 ip_finish_output(skb);
  7. else (否)
  8.     :调用 ip_finish_output(skb);
  9. endif
  10. :进入 ip_finish_output2;
  11. :添加链路层头部(如以太网头部);
  12. if (存在 hh 缓存?) then (否)
  13.     :发送 ARP 请求;
  14.     :等待 ARP 响应;
  15.     :缓存邻居信息;
  16. endif
  17. :调用 hh->hh_output(skb);
  18. stop
  19. @enduml
复制代码

装备管理

变乱关照处置惩罚函数——inetdev_event

处置惩罚什么变乱?
NETDEV_REGISTER ——注册接口
NETDEV_UP —— 接口UP
NETDEV_DOWN —— 接口DOWN
NETDEV_CHANGEMTU —— 改变MTU
NETDEV_UNREGISTER ——注销接口
NETDEV_CHANGENAME —— 更改接口名
接口UP处置惩罚

分为平凡接口和环回口处置惩罚

  • MTU 查抄
  • 环回装备的特别处置惩罚
  • 启动多播(Multicast)功能
RTNetlink 消息

RTNetlink 是 Linux 内核用于网络设置和管理的接口,它通过 Netlink sockets 向用户空间通报网络干系的信息。
关键布局
  1. static struct rtnetlink_link inet_rtnetlink_table[RTM_MAX - RTM_BASE + 1] = {
  2.          [4] = { .doit         = inet_rtm_newaddr,  }, /* 处理新的 IP 地址添加消息 */
  3.          [5] = { .doit         = inet_rtm_deladdr,  }, /* 处理删除 IP 地址的消息 */
  4.          [6] = { .dumpit = inet_dump_ifaddr,  }, /* 处理获取 IP 地址的消息 */
  5.          [8] = { .doit         = inet_rtm_newroute, }, /* 处理新的路由添加消息 */
  6.          [9] = { .doit         = inet_rtm_delroute, }, /* 处理删除路由的消息*/
  7.         [10] = { .doit         = inet_rtm_getroute, .dumpit = inet_dump_fib, },
  8. #ifdef CONFIG_IP_MULTIPLE_TABLES /* 多个路由表支持 */
  9.         [16] = { .doit         = inet_rtm_newrule, },
  10.         [17] = { .doit         = inet_rtm_delrule, },
  11.         [18] = { .dumpit = inet_dump_rules,  },
  12. #endif
  13. };
复制代码
重要流程

  1. @startuml
  2. start
  3. :module_init(inet_init);
  4. floating note left:  module_init内核模块的初始化入口点
  5. :inet_init;
  6. note right
  7. 初始化网络协议栈中与 IP 协议相关
  8. end note
  9. :ip_init;
  10. note right
  11. 初始化 IPv4 协议栈
  12. end note
  13. :ip_rt_init;
  14. :devinet_init;
  15. note right
  16. 初始化与设备相关的网络功能
  17. end note
  18. :rtnetlink_links[PF_INET] = inet_rtnetlink_table;
  19. note left
  20. 注册 IPv4 相关的 Netlink 消息处理表
  21. end note
  22. stop
  23. @enduml
复制代码
  1. /**
  2. * module_init() - driver initialization entry point
  3. * @x: function to be run at kernel boot time or module insertion
  4. *
  5. * module_init() will either be called during do_initcalls (if
  6. * builtin) or at module insertion time (if a module).  There can only
  7. * be one per module.
  8. */
  9. #define module_init(x)        __initcall(x);
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表