gre包分片及gro、gso等offload特性的应用
图1
直接上图,再分别简单介绍各部分:
PC:笔记本电脑。
gw1:使用一台微型服务器模拟企业用户网关,同时添加静态路由使具备简单路由功能。
gw2:模拟ISP,同时添加静态路由使具备简单路由功能。
TPB:使用linux bridge桥接eth2、eth3。这里有个特殊功能,修改linux内核网络协议栈源码,使内核在不使用GRE模块情况下,具有对IP数据报的加封装和解封装GRE包头功能,同时具备GRE数据包的分片功能。
POP:模拟网络服务(如VPN服务等)提供点,这里省略了很多的网络功能,然后为了能够访问外网,对应于TPB具有加封装和解封装GRE包头功能,也是修改的linux内核网络协议栈源码。
GW3:pfsense(软防火墙和路由器),连接公司网关通往外网。
- iptables 对数据包打标记
iptables -t mangle -A FORWARD -d x.x.x.x/x -j MARK --set-mark 47
这样代码中可以识别出数据包在内核缓存中是否被标记:
if(skb->mark == 47)... ...
然后对这些被识别出的数据包添加GRE包头, 这里的GRE包头是数据包包头的最外层IP层和GRE层的总称。
- 加封装和解封装GRE包头(GRE over IPv4)
这里以内核版本版本2.6.32-431.el6.x86_64为例。
下面是ip_gre模块中从加封装GRE包头到发送的代码流程:
netif_receive_skb --> deliver_skb --> ip_rcv --> ip_rcv_finish --> dst_input --> ip_forward --> ip_forward_finish --> dst_output --> ip_output --> ip_finish_output --> ip_finish_output2 --> arp_constructor --> dev_queue_xmit --> dev_hard_start_xmit --> ipgre_xmit --> __gre_xmit --> gre_build_header --> ip_tunnel_xmit --> ip_local_out --> dst_output --> dev_queue_xmit
流程比较复杂,这里附上最简版的添加GRE包头的代码,下面代码是经过测试的,但不是在内核源码任何地方都可以用,使用前必须保证skb->data初始位置在MAC层位置上:
int TPB_xmit(struct sk_buff *skb)
{struct gre_base_hdr *greh;struct iphdr *iph, *inner_iph;int needed_headroom = 38;int tunnel_hlen = 4;unsigned char eth_addr[ETH_ALEN];unsigned char hh_data[14]; struct ethhdr *eth1, *eth2;const u8 *p1;u8 eth_daddr[ETH_ALEN];skb->encapsulation = 1;skb_reset_network_header(skb); if (skb_cow_head(skb, needed_headroom)) //扩展包头,以容得下新添加的IP层和GRE层return 0;skb_pull(skb, 14); //将skb->data向数据方向后移14个字节(即mac层长度)的位置,IP头的位置eth1 = eth_hdr(skb);memcpy(eth_addr, eth1->h_source, ETH_ALEN);memcpy(eth_daddr, eth1->h_dest, ETH_ALEN);inner_iph = (struct iphdr*)skb->data;skb_push(skb, tunnel_hlen); //将skb->data向数据方向反向移动4个字节(GRE包头长度)greh = (struct gre_base_hdr *)skb->data;greh->flags = 0;greh->protocol = skb->protocol;skb_push(skb, sizeof(struct iphdr)); //将skb->data向数据方向反向移动sizeof(struct iphdr)个字节(即IP层长度)的位置,设置为最外层IP头的位置skb_reset_network_header(skb);iph = ip_hdr(skb);iph->version = 4;iph->ihl = sizeof(struct iphdr) >> 2;iph->frag_off = 0;iph->protocol = IPPROTO_GRE;iph->tot_len = inner_iph->tot_len + htons(24);iph->tos = 0;iph->daddr = ip_array_TPB[1];iph->saddr = ip_array_TPB[0];iph->ttl = 64;iph->id = inner_iph->id;iph->check = 0;iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);eth2 = (struct ethhdr*) (((u8 *) hh_data) );eth2->h_proto = skb->protocol;memcpy(eth2->h_source, eth_addr, ETH_ALEN);memcpy(eth2->h_dest, eth_daddr, ETH_ALEN);p1= (const u8*)hh_data;skb_push(skb, 14); //将skb->data向数据方向反向移动14个字节(即MAC层长度),设置为MAC头的位置skb_reset_mac_header(skb);memcpy(skb->data, hh_data, 14);return 0;
}
接下来的解封装GRE包头介绍,以下ip_gre模块中解封装GRE包头的代码流程:
netif_receive_skb --> deliver_skb --> ip_rcv --> ip_rcv_finish --> dst_input --> ip_local_deliver --> ip_local_deliver_finish --> gre_rcv --> gre_cisco_rcv --> ipgre_rcv --> ip_tunnel_lookup --> ip_tunnel_rcv --> gro_cells_receive --> napi_schedule --> __napi_schedule --> ____napi_schedule --> netif_receive_skb --> deliver_skb --> ip_rcv --> ip_rcv_finish --> dst_input --> ip_forward --> ip_forward_finish --> dst_output --> dev_queue_xmit
同样,流程比较复杂,这里附上最简版解封装GRE包头代码:
struct sk_buff* TPB_trim_gre_header(struct sk_buff *skb)
{unsigned char hh_data[14];unsigned char* skb_data_ptr; skb->data = skb_mac_header(skb);skb_data_ptr = skb->data;memcpy(hh_data, skb_data_ptr, 14);skb_pull(skb, 24);skb_reset_mac_header(skb);memcpy(skb->data, hh_data, 14);skb_pull(skb, 14);skb_reset_network_header(skb);skb_push(skb, 14);return skb;
}
- GRE包头分片
目前硬件还不支持GRE分片,只能在代码层对GRE包头进行分片。看下整个协议栈的GSO处理逻辑:
图2
详情参考博客: https://www.cnblogs.com/lvyilong316/p/6818710.html
这里在图中tcp_tso_segment处做更改,如下:
dev_hard_start_xmit --> dev_gso_segment --> skb_gso_segment --> skb_mac_gso_segment --> inet_gso_segment
--> gre_gso_segment --> skb_mac_gso_segment --> inet_gso_segment --> tcp_tso_segment
static const struct net_offload gre_offload = {.gso_send_check = gre_gso_send_check,.gso_segment = gre_gso_segment,
};inet_add_offload(&gre_offload, IPPROTO_GRE);static int gre_gso_send_check(struct sk_buff *skb)
{if (!skb->encapsulation)return -EINVAL;return 0;
}static struct sk_buff *gre_gso_segment(struct sk_buff *skb,int features)
{... ...
}
注意:
在图1中,TPB节点和POP节点都具有加封装和解封装GRE包头功能,在POP节点接收来自TPB节点的加封装的数据包,并且进行GRE分片,如果没有关闭网卡eth3的generic-receive-offload 特性,这里分片的数据包会合并,由于数据包长超过MTU值,会被丢弃, 这里可以暂时将该特性关闭,执行命令 ethtool -K eth3 gro off。
gre包分片及gro、gso等offload特性的应用相关推荐
- linux kernel 网络协议栈之GRO(Generic receive offload)
linux kernel 网络协议栈之GRO(Generic receive offload) 2010年11月26日 Simon Liu 发表评论 阅读评论 原创文章,转载请注明: 转载自pagef ...
- linux 网卡gso,linux内核网络协议栈学习笔记:关于GRO/GSO/LRO/TSO等patch的分析和测试...
TSO,全称是TCP Segmentation Offload,我们知道通常以太网的MTU是1500,除去TCP/IP的包头,TCP的MSS (Max Segment Size)大小是1460,通常情 ...
- UDP 与 GRO, GSO
不知道是不是因为 GSO, GRO 是 Linux 新增特性的原因, 在 google 上找了半天都没有找到一篇详细的介绍如何使用 GSO/GRO 的文章, 最后从 Linux 内核中与 GSO/GR ...
- linux 网卡gso,网卡 offload 简介
网卡 offload 简介 现在,越来越多的网卡设备支持 offload 特性,来提升网络收/发性能. offload 是将本来该操作系统进行的一些数据包处理(如分片.重组等)放到网卡硬件中去做, 降 ...
- IPv6的TSO/GRO/GSO及其Linux实现的不妥
很明确的一件事是,IPv6不允许中间设备对报文分片.具体为什么这么设计,就是为了简单高效.因此,IPv6报头简洁了不少. 但TSO貌似并未违背取消IPv6分片的初衷,硬件把一些都处理的妥妥的,在路由软 ...
- DPDK2.2.0开发杂记一—— 网口抓包分片禁止及MTU配置
1. 禁止网口抓包分片 DPDK收发包是基础核心模块,网卡需要应用进程进行配置并启动,测试过程中发现DPDK驱动igb_uio抓包可能会出现mbuf串.当网络包比较大时,DPDK驱动会把包进行分片放到 ...
- IP数据包分片重叠部分的重组问题
原作者:Haboob Team 翻译:李华峰(邪灵) 介绍 本文将介绍 IDS 的工作原理和讨论 IP 数据包分片的重组过程,并研究不同操作系统在实现重组时的差异性. IDS(入侵检测系统)简介 ID ...
- mtu/mss 数据包分片详解
MTU是啥 MTU是Maximum Transmission Unit的缩写,意思是最大传输单元,这个值是作用于网卡上的,表示的是数据报文经过网卡时的最大大小,默认情况下网卡的MTU值都是1500,当 ...
- 极速前进——DPDK GRO/GSO的转发性能提升实例
通常,以太网的MTU是1500B,除去TCP/IP的协议首部,TCP的MSS(Max Segment Size)大小是1460B.一般情况下,协议栈会对超过1460B的TCP payload进行切片, ...
最新文章
- excel模糊匹配两列文字_高效便捷的Word、Excel操作技巧
- WISEGATE:SIEM的最佳实践讨论
- 云计算技术 — 容灾备份技术
- 音视频技术开发周刊 | 205
- leetcode1300. 转变数组后最接近目标值的数组和
- 学习笔记11-C语言-指针
- pythonxml库_对python 生成拼接xml报文的示例详解
- html中单选框重置,HTML表单和组件
- 美国OCC代理署长Brian Brooks将于今日离任,由首席运营官接任
- 每日一题题目26:选择排序(冒泡排序改进版)
- Linux使用命令 笔记
- Cookie的过期时间设置
- 关于Myeclipse自带JDK与本机安装JDK的的区别
- ELK filebeat和logstash使用:配置单个文件来源、配置多个文件来源
- AJAX培训第一讲:AJAX基础
- 联通光猫IPV6配置
- vue2.x和3.x中mock数据方式
- 华东师范计算机考研科目,华东师范大学计算机技术研究生考试科目和考研参考书目...
- 基础图像处理 python+opencv
- win10录屏有噪音_我的电脑是win10的,用Ev录屏有杂音,之前我调了声卡驱动,就没了,现在重装调了一下又有了...
热门文章
- pytorch apex +ddp 分布式训练+数据优化
- 优雅的使用MacBook(一些小技巧,你不会知道的)
- function() 与 $(function())
- 验证码显示不出来的问题
- MATLAB初阶绘图
- 教育教学类视频加密与安全(组图)
- 钢铁集团的混合云灾备
- 算法之克鲁斯卡尔(Kruskal)算法
- 这个小程序厉害了!一键生成花式昵称,让你的微信从此与众不同!
- python返回绝对值的函数_Python中用于返回绝对值的abs()方法