RoCE多网卡时,报文可以过去,但是回不来
摘要:虽然网卡是接入RoCE网络,但其实问题本身是单纯路由相关的,所以看的时候,不用关注RoCE,只当做一个独立子网就行了
本文分享自华为云社区《<跟唐老师学习云网络> - RoCE多网卡时,报文可以过去,但是回不来》,作者: tsjsdbd 。
一、网络概要
一台机子,接入2个子网,一个普通通信的,一个高速通信的。并且接入高速通信子网,有8张网卡。如下图:
本文描述的问题,只关注高速子网这一部分。为帮助理解问题,网络可以简化为:
每个网卡,都有分配该子网的一个IP。如下:
二、问题现象
A只能通B里面的一个IP,其余7个IP都不通。下图为A--->B 的结果:
图示:只有1个IP能通
反过来也一样,后面只讲一个方向的(A-->B)。
三、问题定位
1.先看报文有没有到达B。
如果都不能到B,说明网络接的有问题。如果到了B,但是不回来,说明路由配置可能有问题。
Ping不通的ip(228)时,在主机B上面进行抓包分析(228对应的网卡名是enp80s0f0,所以这里监听这个网卡):
tcpdump -i enp80s0f0 -n arp listening on enp80s0f0, link-type EN10MB (Ethernet), capture size 262144 bytes 17:02:23.720556 ARP, Request who-has 29.28.195.228 tell 29.28.204.80, length 46 17:02:24.758954 ARP, Request who-has 29.28.195.228 tell 29.28.204.80, length 46 17:02:25.782954 ARP, Request who-has 29.28.195.228 tell 29.28.204.80, length 46 17:02:26.807063 ARP, Request who-has 29.28.195.228 tell 29.28.204.80, length 46 ^C
可以看到,报文能到B。
2.但是为什么B不给A回消息呢?
于是我们来看看,当B要给A回消息时,路由怎么走的?
查看路由表:
ip route default via 192.168.0.1 dev enp218s0 proto dhcp metric 104 29.28.192.0/20 dev enp137s0f1 proto kernel scope link src 29.28.201.211 metric 105 29.28.192.0/20 dev enp137s0f0 proto kernel scope link src 29.28.193.28 metric 106 29.28.192.0/20 dev enp80s0f1 proto kernel scope link src 29.28.204.230 metric 107 29.28.192.0/20 dev enp106s0f0 proto kernel scope link src 29.28.194.199 metric 108 29.28.192.0/20 dev enp106s0f1 proto kernel scope link src 29.28.195.31 metric 109 29.28.192.0/20 dev enp80s0f0 proto kernel scope link src 29.28.195.228 metric 110 29.28.192.0/20 dev enp234s0f1 proto kernel scope link src 29.28.197.165 metric 111 29.28.192.0/20 dev enp234s0f0 proto kernel scope link src 29.28.195.75 metric 112
根据以前学的router知识,可以看到,(排除default路由外)应该是会匹配到 第1条(标红)规则。
注:metric表示路由代价,目的子网都匹配的情况下,会选代价最低的那一条。
即 B-->A给A回消息时,报文要从 网卡enp137s0f1 发出去,并且发出去的报文源地址要设为29.28.201.211。
难怪不通,因为答非所问了嘛(回arp报文,内容对不上)。
再看为什么211这个ip能通?
因为 211 是该子网路由选择,所对应的IP,所以刚好能通。
这就解释了为什么刚好1个IP能通,另外7个不通。
3.如何让报文从哪个口收到,就从哪个口回去?
往外发报文,根据源地址来选择网卡(注意这里的源是指 主机B,因为回报文是往外发),这种场景可以称之为「源地址路由」,而要实现源地址路由,就需要用到「ip rule 路由策略」这种高级路由配置。
四、ip rule 路由策略
在配置「源地址路由」规则前,我们需要先补充一点基础知识。
1. 路由表“副本”
以前我们学的 route -n 路由表,其实属于“新手村”,即系统默认使用这张路由规则表。但就像《剑来》里面说的那样,在新手村外还有很多其他“境界”。Linux新版本(2.x之后)为实现更复杂的路由能力,将原来的“新手村”,复制了很多的“副本”。
Ps:这种增加“副本”的思路,在咱们IT领域非常常见,比如我们之前学到的各种namespace。
当前系统总的“副本”数量,在 /etc/iproute2/rt_tables 这个文件中。
255 local 254 main 253 default 0 unspec
我们之前学的 route -n 新手村表,就是其中的 254 这个副本号,名字叫做 main。
要增加副本,可以如下这么操作:
echo "$id $table" >> /etc/iproute2/rt_tables
就行了。
2. 如何决定使用哪个“副本”
为了确认使用哪个“副本”,在前面补了一个 rule 规则。
条件基本就是:源IP,目的地址,收到网口这些。
具体见:https://www.computerhope.com/unix/ip.htm
所以现在流程变成了:
- 新增一个副本
- 设置rule规则,指向这个新增的副本
- 往副本里面增加以前学会的route记录
比如,我们希望某个源IP为 29.28.201.211 的报文,走独立的“路由副本”策略:
- 新建“路由副本”
echo "200 table0" >> /etc/iproute2/rt_tables
- 增加规则,使这种报文,走该独立副本。(from表示源ip)
ip rule add from 29.28.201.211 table table0
- 然后我们往这个“路由表副本”里面,放入以前学到的普通的路由规则:
ip route add 29.28.192.0/20 dev eth0 table table0
- 可以确认下副本中路由是否正确
ip route show table table0 29.28.192.0/20 dev eth0 scope link
这样,我们就可以控制更复杂的路由规则了。
3. 再看“新手村”路由表
在知道路由表可以有很多“副本”之后,我们再回头看看原来那个“新手村”。
从 /etc/iproute2/rt_tables 文件内容可以知道,咱们“新手村”对应的那个路标表名字叫做main。
所以查询这个表的内容:
root@tsjsdbd:/# ip route show table main default via 172.17.0.1 dev eth0 172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.2
这个和我们平时看到的路由,是一样的:
root@tsjsdbd:/# ip route default via 172.17.0.1 dev eth0 172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.2
也就是,我们平时敲的 route -n 看到的列表,其实就是 main 这张表里面的内容。
其余表(0-local,253-default,255-local)的内容,一般不用关注。
4. rule规则匹配优先级
在rule规则表里面,很多记录的时候,匹配优先级是怎么定的?答案是每一条记录,它有个优先级的字段。如下:
[root@tsjsdbd]# ip rule 0: from all lookup local 32766: from all lookup main 32767: from all lookup default
最前面的数字,就是优先级。数字越小,优先级越高,也就是会先进行匹配,同时也代表这条规则可以排的更靠前。
在 rule add 添加规则的时候,是可以指定“优先级的”。如:
ip rule add from 192.168.1.0/24 table table0 pri 333
就可以指定
在不指定优先级的情况下,会默认加到当前最小值前面(即,不指定优先值时,会加一条优先级较高的rule)。
如下:
[root@tsjsdbd]# ip rule add from 192.168.1.0/24 table table0 pri 333
上面这条会加一条333优先级的rule
[root@tsjsdbd]# ip rule add from 192.168.2.0/24 table table0
这条没指定优先级,就会加一条优先级332的(因为当前rule里面最小的是333)。
可以查询确认:
[root@tsjsdbd]# ip rule 0: from all lookup local 332: from 192.168.2.0/24 lookup table0 333: from 192.168.1.0/24 lookup table0 32766: from all lookup main 32767: from all lookup default
删除rule的话,有几种便捷的指定方式:(优先级、条件、table)
ip rule del pri 333 ip rule del from 192.168.2.0/24 ip rule del table table0
最后注意,添加或修改了rule规则后,不会立即生效,需要 ip route flush cache 后才生效(官方文档是这么说的,自己验证的时候注意下就行)。
五、源地址路由
再回到问题上来,8个网卡,哪个口收到,要求使用该口的ip回去。可以通过8个路由table实现(因为大家的目标网段是一样的,所以在同一个table表里面话,不好写规则)。
于是,可以把8个路由规则,分散到8个“世界”中,然后通过 rule 分散后,各自进行匹配。
事实上,「源地址路由」的实现,一般都是这种套路:
- 添加一条“源地址”的rule
ip rule add from 192.168.1.2 table 100
- 在目标table里面,设置路由规则
ip route add 172.25.2.0/24 via 192.168.1.5 table 100
最终解决8个RoCE网卡可以互通的路由设置如下:
- table表(8个)
/root # cat /etc/iproute2/rt_tables 200 table0 201 table1 202 table2 203 table3 204 table4 205 table5 206 table6 207 table7
- rule表(8个)
/root # ip rule 0: from all lookup local 32758: from 29.28.197.165 lookup table7 32759: from 29.28.195.75 lookup table6 32760: from 29.28.201.211 lookup table5 32761: from 29.28.193.28 lookup table4 32762: from 29.28.195.31 lookup table3 32763: from 29.28.194.199 lookup table2 32764: from 29.28.204.230 lookup table1 32765: from 29.28.195.228 lookup table0 32766: from all lookup main 32767: from all lookup default
- 每个table表里面,1条路由规则
/root # ip route show table table5 29.28.192.0/20 dev enp137s0f1 scope link src 29.28.201.211
以上3步行为,通过一个脚本来完成。
六、最后
最后我们来看看,网络有问题的时候,与设置完「源地址路由」后的区别:
查询“以xx为源ip,以yy为目的ip,路由选择结果是什么”方式,
可以使用ip route get 命令。
设置前:
# ip route get 29.28.204.80 from 29.28.201.211 29.28.204.80 from 29.28.201.211 dev enp137s0f0 uid 0
设置后:
# ip route get 29.28.204.80 from 29.28.201.211 29.28.204.80 from 29.28.201.211 dev enp137s0f1 table table5 uid 0
可以看到,是按照我们的目标“哪个口来,哪个口回去”的方式运行的。
注:虽然网卡是接入RoCE网络,但其实问题本身是单纯路由相关的,所以看的时候,不用关注RoCE,只当做一个独立子网就行了。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
7个工程应用中数据库性能优化经验分享
摘要:此篇文章分别从sql执行过程、执行计划、索引数据结构、索引查询提速原理、聚焦索引、左前缀优化原则、自增主键索引这些角度谈一谈我们对数据库优化的理解。 本文分享自华为云社区《工程应用中数据库性能优化经验小结》,作者: 叶工 。 1、前言 现阶段交付的算法产品,绝大多数涉及到数据库的使用。它承载的内容包括:用户权限管理、数据集信息、异步推论的结果、个性化配置等等。 在OCR场景下,数据集体量通常较大(一个数据集几十万张图片),而数据库往往部署在客户共享数据库中(同时运行大量其他业务),甚至只能和算法镜像共享同一台服务器,因此在后台研发中尤其要关心数据库性能瓶颈。 此篇文章分别从 sql执行过程、执行计划、索引数据结构、索引查询提速原理、聚焦索引、左前缀优化原则、自增主键索引这些角度谈一谈我们对数据库优化的理解。 2、ORM场景下如何获得完整SQL语句 1. 线上环境可以通过连接池进行慢SQL拦截,并发出告警通知 2. 测试阶段,因为使用预编译语句或ORM框架,无法获取完整SQL时可以使用数据库日志方式获取 set global general_log=on; show variab...
- 下一篇
如何通过Python将JSON格式文件导入redis?
摘要:如果希望将 JSON 文件导入到 Redis 中,首先要做的就是连接到 redis 服务。 本文分享自华为云社区《Python将JSON格式文件导入 redis,多种方法》,作者: 梦想橡皮擦 。 在导入前需要先确定你已经安装 Redis,并且可以启动相关服务。 windows 上启动 redis 的命令是 redis-server.exe redis.windows.conf,效果图如下: 使用 Python 连接 redis 如果希望将 JSON 文件导入到 Redis 中,首先要做的就是连接到 redis 服务,实现步骤如下所示。 安装 redis 与 导入 安装 redis 库 pip install redis 导入 redis 库 import redis 使用代码连接 Redis 通过 redis 库的 Redis 类连接 Redis 服务器。 import redis r = redis.Redis(host='localhost', port=6379, db=0) print(r) 连接到本地 Redis 服务器,并使用默认端口 6379,连接到数据库 0...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS8编译安装MySQL8.0.19
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Red5直播服务器,属于Java语言的直播服务器
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7