IP 层收发报文简要剖析6--ip_forward 报文转发
//在函数ip_route_input_slow->ip_mkroute_input注册,
/*
* IP数据包的转发是由ip_forward()处理,该函数在ip_rcv_finish()
* 通过输入路由缓存被调用。
*/
int ip_forward(struct sk_buff *skb)
{
u32 mtu;
struct iphdr *iph; /* Our header */
struct rtable *rt; /* Route we use */
struct ip_options *opt = &(IPCB(skb)->opt);
struct net *net; /* that should never happen */
if (skb->pkt_type != PACKET_HOST)
goto drop; if (unlikely(skb->sk))
goto drop; if (skb_warn_if_lro(skb))
goto drop; if (!xfrm4_policy_check(NULL, XFRM_POLICY_FWD, skb))/*查找ipsec 策略路由*/
goto drop; if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb))//存在路由警告选项
return NET_RX_SUCCESS; skb_forward_csum(skb);
net = dev_net(skb->dev); /*
* According to the RFC, we must first decrease the TTL field. If
* that reaches zero, we must reply an ICMP control message telling
* that the packet's lifetime expired.
*/
if (ip_hdr(skb)->ttl <= 1)//ttl 减少了
goto too_many_hops; if (!xfrm4_route_forward(skb))//ipsec 策略路由转发处理
goto drop; rt = skb_rtable(skb); if (opt->is_strictroute && rt->rt_uses_gateway)//如果数据包启用了严格路由处理,且下一跳不是网关
goto sr_failed;//发送ICMP_SR_FAILED icmp IPCB(skb)->flags |= IPSKB_FORWARDED;
mtu = ip_dst_mtu_maybe_forward(&rt->dst, true);
if (ip_exceeds_mtu(skb, mtu)) {
IP_INC_STATS(net, IPSTATS_MIB_FRAGFAILS);
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
htonl(mtu));
goto drop;
} /* We are about to mangle packet. Copy it! 确保空间足够*/
if (skb_cow(skb, LL_RESERVED_SPACE(rt->dst.dev)+rt->dst.header_len))
goto drop;
iph = ip_hdr(skb); /* Decrease ttl after skb cow done */
ip_decrease_ttl(iph); /*
* We now generate an ICMP HOST REDIRECT giving the route
* we calculated.
*/
if (IPCB(skb)->flags & IPSKB_DOREDIRECT && !opt->srr &&
!skb_sec_path(skb))
ip_rt_send_redirect(skb);//数据报文输出路由存在重定向标志,且该数据报中不存在源路由选项,就发送重定向icmp报文 skb->priority = rt_tos2priority(iph->tos); return NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD,
net, NULL, skb, skb->dev, rt->dst.dev,
ip_forward_finish); sr_failed:
/*
* Strict routing permits no gatewaying
*/
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0);
goto drop; too_many_hops:
/* Tell the sender its packet died... */
__IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS);
icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
drop:
kfree_skb(skb);
return NET_RX_DROP;
}
static int ip_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct ip_options *opt = &(IPCB(skb)->opt); __IP_INC_STATS(net, IPSTATS_MIB_OUTFORWDATAGRAMS);
__IP_ADD_STATS(net, IPSTATS_MIB_OUTOCTETS, skb->len); if (unlikely(opt->optlen))
ip_forward_options(skb);//IP数据报文选项 记录路由选项 时间戳等 return dst_output(net, sk, skb);//指向ip_output ip_mc_output
}
ip_forward
IP 层收发报文简要剖析6--ip_forward 报文转发的更多相关文章
- IP 层收发报文简要剖析3--ip输入报文分片重组
在ip_local_deliver中,如果检测到是分片包,则需要将报文进行重组.其所有的分片被重新组合后才能提交到上层协议,每一个被重新组合的数据包文用ipq结构实例来表示 struct ipq { ...
- IP 层收发报文简要剖析2--ip报文的输入ip_local_deliver
ip报文根据路由结果:如果发往本地则调用ip_local_deliver处理报文:如果是转发出去,则调用ip_forward 处理报文. 一.ip报文转发到本地: /* * Deliver IP Pa ...
- IP 层收发报文简要剖析1-ip报文的输入
ip层数据包处理场景如下: 网络层处理数据包文时需要和路由表以及邻居系统打交道.输入数据时,提供输入接口给链路层调用,并调用传输层的输入接口将数据输入到传输层. 在输出数据时,提供输出接口给传输层,并 ...
- IP 层收发报文简要剖析6--ip报文输出3 ip_push_pending_frames
L4层的协议会把数据通过ip_append_data或ip_append_page把数据线放在缓冲区,然后再显示调用ip_push_pending_frames传送数据. 把数据放在缓冲区有两个优点, ...
- IP 层收发报文简要剖析5--ip报文发送2
udp 发送ip段报文接口ip_append_data ip_append_data 函数主要用来udp 套接字以及raw套接字发送报文的接口.在tcp中发送ack 以及rest段的ip_send_u ...
- IP 层收发报文简要剖析4--ip 报文发送
无论是从本地输出的数据还是转发的数据报文,经过路由后都要输出到网络设备,而输出到网络设备的接口就是dst_output(output)函数 路由的时候,dst_output函数设置为ip_output ...
- TCP层的分段和IP层的分片之间的关系 & MTU和MSS之间的关系 (转载)
首先说明:数据报的分段和分片确实发生,分段发生在传输层,分片发生在网络层.但是对于分段来说,这是经常发生在UDP传输层协议上的情况,对于传输层使用TCP协议的通道来说,这种事情很少发生. 1,MTU( ...
- 原 TCP层的分段和IP层的分片之间的关系 & MTU和MSS之间的关系
首先说明:数据报的分段和分片确实发生,分段发生在传输层,分片发生在网络层.但是对于分段来说,这是经常发生在UDP传输层协议上的情况,对于传输层使用TCP协议的通道来说,这种事情很少发生. 1,MTU( ...
- Linux内核IP层的报文处理流程(一)
本文主要讲解了Linux内核IP层的整体架构和对从网卡接受的报文处理流程,使用的内核的版本是2.6.32.27 为了方便理解,本文采用整体流程图加伪代码的方式对Linxu内核中IP整体实现架构和对网卡 ...
随机推荐
- golang常用库:字段参数验证库-validator
背景 在平常开发中,特别是在web应用开发中,为了验证输入字段的合法性,都会做一些验证操作.比如对用户提交的表单字段进行验证,或者对请求的API接口字段进行验证,验证字段的合法性,保证输入字段值的安全 ...
- 带权二分图最大匹配KM算法
二分图的判定 如果一个图是连通的,可以用如下的染色法判定是否二分图: 我们把X部的结点颜色设为0,Y部的颜色设为1. 从某个未染色的结点u开始,做BFS或者DFS .把u染为0,枚举u的儿子v.如果v ...
- Privileged Permission开机授权时序图 SourceCode android-10.0.0_r36
Privileged Permission开机授权时序图 | SourceCode:android-10.0.0_r36 | Author:秋城 | v1.1SystemServerSystemSer ...
- 如何制作一个vagrant box
因为要用的窗口应用,基于服务器的各种box不能使用(曾经尝试安装桌面,没有成功).所以试着基于Ubuntu的虚拟机创建自己的box. 过程中主要参考了这篇文章:http://www.360do ...
- css选择器 兄弟选择器 相邻兄弟选择器 子元素选择器
1.兄弟选择器: ~ 该选择器会选择当前元素之后的所有相邻指定元素(具有相同父元素的兄弟元素): .p ~ li{ color: blue; } <div> <p class=&qu ...
- Linux运维学习第五周记
休惊岁岁年年貌 且对朝朝暮暮人 细雨晴时一百六 画船鼍鼓莫违民 雨生百谷,春雨贵如油 第五周学记 这周主要学习了九三级磁盘.存储相关知识和Linux文件系统以及计算机网络的内容 磁盘和文件系统 磁盘结 ...
- springboot入门系列(二):SpringBoot整合Swagger
上一篇<简单搭建SpringBoot项目>讲了简单的搭建SpringBoot 项目,而 SpringBoot 和 Swagger-ui 搭配在持续交付的前后端开发中意义重大,Swagger ...
- JS实现将二维数组生成到页面上
前言 之前没说过数组,现在来写一下数组 CSS span { border:2px solid skyblue; width:30px; height: 30px; display: inline-b ...
- MySQL设置慢查询
MySQL的慢查询日志是用来记录在MySQL中响应时间超过阀值的语句,则会被记录到慢查询日志中(运行时间超过long_query_time值的SQL语句): 慢查询相关参数: slow_query ...
- 分区表的表进行update操作
今天对一张创建了分区表的表进行update操作,正好需要修改的是创建分区的那一列,由于是要修改在分区表范围内的数据,所以无法修改. 然后搜了一下,需要修改row movement这个属性:alter ...