网络层具体就是IP协议层,处理发送和接收数据外,还需要进行转发和路由分组。在查找最佳路由并选择适当网卡的时候也会涉及对底层地址族的处理,例如MAC地址。

ip头数据结构定义在:include/uapi/linux/ip.h。

struct iphdr {

#if defined(__LITTLE_ENDIAN_BITFIELD)

__u8    ihl:4,

version:4;

#elif defined (__BIG_ENDIAN_BITFIELD)

__u8    version:4,

ihl:4;

#else

#error  "Please fix <asm/byteorder.h>"

#endif

__u8    tos;

__be16  tot_len;

__be16  id;

__be16  frag_off;

__u8    ttl;

__u8    protocol;

__sum16 check;

__be32  saddr;

__be32  daddr;

/*The options start here. */

};

1.1.1.1  接收

ipv4数据包的主接收方法是ip_rcv()函数,会检测报到类似如果是PACKET_OTHERHOST(定义在include/uapi/linux/if_packet.h文件中)则直接丢弃。检查是否是共享的包,如果是分享的包则克隆它。获取ip头数据结构,来操作相关协议事务。然后调用NK_HOOK,NF_HOOK定义在include/linux/netfilter.h文件中。

static inline int

NF_HOOK(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, struct sk_buff *skb,

struct net_device *in, struct net_device *out,

int (*okfn)(struct net *, struct sock *, struct sk_buff *))

它是netfilter钩子函数,如果允许包传递则返回1。如果返回其他值说明这个包被hook给消耗掉了。

其中hook为NF_INET_PRE_ROUTING(定义在

include/uapi/linux/netfilter.h

okfn指向ip_rcv_finish()函数。ip_rcv_finish()也定义在:net/ipv4/ip_input.c

在ip网络层中需要分段、重组的实现。须在路由选在子系统中查找,确定是发给当前主机还是转发。

如果是当前主机则依次调用方法ip_local_deliver()和ip_local_deliver_finish()函数。如果需要转发则调用ip_forward()函数。

1.1.1.1.1          分片合并

IP分组可能是分片的,可以通过ip_defrag重新组合分片分组的各个部分。代码流程如下图(图摘自《深入linux内核架构》):

内核在独立的缓存中管理原本属于一个分组的各个分片,该缓存称为分片缓存(fragment cache)。属于同一个分组的各个分片保存在一个独立的等待队列中,直至该分组的所有分片到达。

ip_frag_reasm将各个分片重新组合起来。

1.1.1.1.2          交付到传输层

如果数据是给本机的,那么返回到ip_local_deliver。调用netfilter挂钩NF_IP_LOCAL_IN恢复在ip_local_deliver_finish函数中的处理。

分组的协议标识符确定一个传输层的函数,分组将传递给该函数。每个协议都有一个net_protocol结构的实例。定义在:

include/net/protocol.h文件中

struct net_protocol {

int                     (*early_demux)(struct sk_buff *skb);

int                     (*early_demux_handler)(struct sk_buff *skb);

int                     (*handler)(struct sk_buff *skb);

void                    (*err_handler)(struct sk_buff *skb, u32 info);

unsigned int            no_policy:1,

netns_ok:1,

/* does the protocol do more stringent

* icmp tag validation than simple

* socket lookup?

*/

icmp_strict_tag_validation:1;

};

1.1.1.1.3          分组转发

ip分组也可能转发到另一台计算机。这就需要调用ip_forward函数。

ip_forward使用NF_HOOK挂钩函数,挂钩编号为NF_INET_FORWARD,回调函数为ip_forward_finish。

1.1.1.2  发送

由ip_queue_xmit函数将数据包从L4移到L3

  网络层要选择合适的网间路由和交换结点,确保数据及时传送。其主要任务包括 (1)路由处理,即选择下一跳 (2)添加 IP header(3)计算 IP header checksum,用于检测 IP 报文头部在传播过程中是否出错 (4)可能的话,进行 IP 分片(5)处理完毕,获取下一跳的 MAC 地址,设置链路层报文头,然后转入链路层处理。

发送和接收操作的流程并不总是分离的,如果分组只通过当前计算机转发,那么发送和接收操作是交织的。

Linux协议栈(7)——网络层实现相关推荐

  1. linux Netfilter在网络层的实现详细分析(iptables)

    我在之前已经写过两篇关于netfilter的文章: Linux netfilter hook源码分析(基于内核代码版本4.18.0-80)_yg@hunter的博客-CSDN博客 Linux下使用Ne ...

  2. Linux协议栈(1)——协议介绍

    Linux协议栈(1)--协议介绍 本系列材料是关于Linux网络内核协议栈的,总体上将其分10个文章,主要目的是简明扼要的描述Linux协议栈在内核中的实现,从总体上掌握linux网络协议栈.因为操 ...

  3. linux协议栈学习 第七节 GRO的实现

    linux协议栈学习 第七节 GRO的实现 GRO (generic receive offload) 概述: GRO是在协议栈接收报文时进行减负的一种处理方式,该方式在设计上考虑了多种协议报文.主要 ...

  4. 《探寻linux协议栈》之二:源于skb的一场大联欢

    写在前面 skb是什么 skb长什么样 skb中和网络协议有关的指针 skb的储存 skb如何到linux内核协议栈中 内核接收驱动skb的入口函数netif_receive_skb 总结 写在前面 ...

  5. linux 协议栈之socket,Linux TCP/IP 协议栈之 Socket 的实现分析(一)

    内核版本:2.6.37 参考[作者:kendo的文章(基于内涵版本2.6.12)] 第一部份 Socket套接字的创建 socket 并不是 TCP/IP协议的一部份. 从广义上来讲,socket 是 ...

  6. [置顶] Linux协议栈代码阅读笔记(一)

    Linux协议栈代码阅读笔记(一) (基于linux-2.6.21.7) (一)用户态通过诸如下面的C库函数访问协议栈服务 int socket(int domain, int type, int p ...

  7. linux 协议栈 位置,[置顶] Linux协议栈代码阅读笔记(一)

    Linux协议栈代码阅读笔记(一) (基于linux-2.6.21.7) (一)用户态通过诸如下面的C库函数访问协议栈服务 int socket(int domain, int type, int p ...

  8. Linux协议栈--NAPI机制

    Linux内核中的NAPI机制介绍 本文将介绍Linux内核中的NAPI:Linux网络设备驱动程序中的一种支持新一代网络适配器的架构. New API(NAPI)用于支持高速网卡处理网络数据包的一种 ...

  9. linux 协议栈学习 第八节 链路层GRO的处理

    linux 协议栈学习 第八节 链路层GRO的处理 链路层的接收匹配函数__napi_gro_receive(napi, skb): 该函数对报文进行匹配,并不合并报文. 匹配规则必须同时满足以下两个 ...

最新文章

  1. linux 下面安装 .sh 格式的软件
  2. BZOJ3277 串 【广义后缀自动机】
  3. JZOJ 5439. 【NOIP2017提高A组集训10.31】Calculate
  4. 2017《面向对象程序设计》作业四
  5. 曼哈顿距离与切比雪夫距离的转化及prufer序列
  6. 你为什么要关心equals和hashcode
  7. linux不识别xfs,51CTO博客-专业IT技术博客创作平台-技术成就梦想
  8. paip.函数式编程方法概述以及总结
  9. 用Java实现向Cassandra数据库中插入和查询数据
  10. Final Scrum
  11. Java Web目前主流的框架以及正在兴起的框架
  12. pdfbox、icepdf工具实现pdf转图片
  13. 硬禾课堂 - 一分钟焊接小技巧
  14. 如何使用 JS 实现带字母的导航城市列表,以及城市搜索
  15. 测试用例设计——错误猜测法
  16. 编程之类的文案_精选50句文案,个个都是让你灵感喷涌的句子!
  17. mysql异常Incorrect string value: ‘\xE6\xB5\x8B\xE8\xAF\x95‘ for column ‘region_name‘
  18. 腾讯游戏与网易游戏Q3财报对比:前者营收同比降4%
  19. C#获取本机局域网ip和公网ip
  20. FFmpeg源码分析-直播延迟-内存泄漏

热门文章

  1. maven中把依赖的JAR包一起打包(转)
  2. POJ 2299 Ultra-QuickSort(树状数组+离散化)
  3. linux下递归修改目录/文件权限命令
  4. Everyday English
  5. Matlab Robotic Toolbox V9.10工具箱(二):正/逆运动学
  6. Canvas实用库Fabric.js使用手册
  7. Linux环境软RAID 5 搭建
  8. 20155229实验三 《Java面向对象程序设计实验三 敏捷开发与XP实践 》实验报告
  9. Linux磁盘配额应用
  10. 关于TXT转CHM的完整解决方式