【ArchSummit架构师峰会】探讨数据与人工智能相互驱动的关系>>> 了解详情
写点什么

OpenFlow(OVS) 下的“路由技术”

  • 2019-11-11
  • 本文字数:3074 字

    阅读完需:约 10 分钟

OpenFlow(OVS)下的“路由技术”

熟悉这款设备的同学,应该也快到不惑之年了吧!这应该是 Cisco 最古老的路由器了。上个世纪 80 年代至今,路由交换技术不断发展,但是在这波澜壮阔的变化之中,总有一些东西在嘈杂的机房内闪闪发光,像极了工程师的头顶,充满了智慧!



Cisco“古董”路由器


本文主要描述了一种将三层路由变成二层交换转发(以及二层转发变成三层路由)的实现方式,以应对 OVS(OpenFlow)跨网段路由复杂的问题;当然技术本身是客观的,具体应用还要看场景。


随着 SDN 技术不断“发展”,玩路由器交换机的变成了“传统网工”,搞控制器、转发器的才算是正常工作,当然任何新技术的掌握都离开对“历史”了解或者反刍;也许几年以后当有人听到一条一条的配置 ACL、配置路由表是一件很不可思议的事情,因为那时所有的配置都是控制器做好模型生成配置自动下发的,点点鼠标或者写个 py 脚本就可以了。

传统的路由交换机

OK,言归正传,我们先来了解一下传统路由、交换的区别:



交换: 一般指的是同网段内分组包的转发,转发依据:MAC 地址。


  • PC 视角:当两台主机在同一个网段,PC1 需要访问 PC2 时,PC1 首先会发送 arp 请求报文,请求 PC2 的的 MAC 地址;收到响应后,PC1 会把 PC2 的 MAC 地址封装在分组包的目的 MAC 的位置,然后将分组报文扔给交换机;PC2 也会做类似的动作。

  • 交换机视角:交换机会接收网段上的所有数据帧;利用接收数据帧中的源 MAC 地址来建立 MAC 地址表(源地址自学习),使用地址老化机制进行地址表维护。MAC 地址表中查找数据帧中的目的 MAC 地址,如果找到就将该数据帧发送到相应的端口,如果找不到,就向除入端口以外的所有的端口发送;向所有端口转发广播帧和多播帧。


路由:一般指不同网段的数据包的转发,转发依据:IP 路由。


  • PC 视角:当两台主机在不同的网段,PC1 需要访问 PC2 时,PC1 首先会在自己的路由表内查询 PC2 的 IP 地址对应的下一跳(一般默认是网关)地址,然后再去发送 ARP 报文,请求该下一跳对应的 MAC 地址;收到响应后,PC1 会把该 MAC 地址封装在数据包的目的 MAC 的位置(注意此时的目的 IP 仍是 PC2 的 IP 地址,而不是下一跳 IP),然后将数据报文扔给路由器;PC2 也会做类似的动作。

  • 路由器视角:当路由器收到一个 IP 数据包,路由器就会找出数据包的三层包头中的目的 IP 地址,然后拿着目的 IP 地址到自己的路由表中进行查询,找到“最匹配”的路由条目后,将数据包根据路由条目所指示的出接口或者下一跳 IP 转发出去,这就是 IP 路由(当然路由器还会做一些额外的工作:将数据包的三层包头的 TTL 减一,修改数据包的二层源 MAC 地址为自己出接口的 MAC,修改数据包的二层目的 MAC 地址为下一跳的 MAC);而每一台路由器都会在本地维护一个路由表(Routing Table),路由表中装在着路由器获知的路由条目,路由条目由路由前缀(路由所关联的目的地址)、路由信息的来源、出接口或者下一跳 IP 等元素构成;路由器通过静态配置或者动态的方式获取路由条目并维护自己的路由表。

OpenFlow 的出现

当 OpenFlow 出现以后,路由器、交换机统一变成了转发器,转发依据:流表。


OK,我们先看一下流表长啥样:


root@ubuntu:~# ovs-ofctl dump-flows br2NXST_FLOW reply (xid=0x4):cookie=0x0, duration=16080.313s, table=0, n_packets=1, n_bytes=42, idle_age=15691, priority=200,arp,arp_tpa=2.2.2.0/24 actions=output:100cookie=0x0, duration=15964.186s, table=0, n_packets=1, n_bytes=42, idle_age=15691, priority=100,arp,arp_tpa=1.1.1.0/24 actions=output:1cookie=0x0, duration=15985.113s, table=0, n_packets=5, n_bytes=490, idle_age=15692, priority=200,icmp,nw_dst=2.2.2.0/24 actions=output:100cookie=0x0, duration=15802.910s, table=0, n_packets=5, n_bytes=490, idle_age=15692, priority=100,icmp,nw_dst=1.1.1.0/24 actions=output:1
复制代码


当然有人称流表为 ACL,这也可以理解,都有着强大的匹配域以及 Action,流表的 Pipeline 可以算是其特色(性能暂时先不 care);到此为止,MAC 表、路由表在转发器上面已经统统看不到了,你能看到只有上面的流表。


就 OVS 来说,如果把 Bridge 配置成 Secure 模式,默认是没有什么流表的;如果现在我们把 OVS 配置成一台普通的传统二层交换机,只需要增加几条关于 ARP、ICMP 的流表,就可以 Ping 通了(可以参考以上示例),这还是比较简单的。


当然可能有些人说还有更简单的:只需把 Bridge 配置 Standalone 模式或者增加一条默认 action=NORMAL 的流表就可以了。但是如果这样的话,所有的流量又回到传统的二层三层转发去了,作为新时代的 OVS,这符合我的个性啊,如果这样的话,这活还是交给 Linux Bridge 来干吧。


但是问题来了,如果把 OVS 配置成一台有路由器功能的转发器,这就比较困难了;因为通过上文分析路由转发过程相对来说还是比较复杂的,需要做的工作如下:


  • 需要一个类似网关的设备(Device),来响应 ARP 请求:当然可以在新增 OVS 时自动生成的设备上配置网关地址,也可以增加单独的设备专门作为网关。

  • 需要修改数据包的二层源目 MAC 地址以及三层包头的 TTL:因为路由是逐跳转发的,每一跳都需要做这些工作,即使是现在通过流表转发,中间的转发器直接转发报文,到达倒数第一跳的时候还是需要把数据包的目的 MAC 地址修改为接受端的 MAC 地址。

一切皆交换的世界

在 OpenFlow 的世界所有的网络设备都是转发器或者称为交换机,执行简单的转发转发动作; OK,那我们能不能将跨网段访问的路由转发变换成普通的二层转发呢?答案是 YES!


下面我们通过一个示例来实现这个想法:首先我们要解决的第一个问题就是网关的问题:如何取消对网关的 ARP 请求?这个在 Linux 平台下并不是一件难事,只需一条命令:


root@ubuntu:~# ip route add 0.0.0.0/0 dev eth0 scope link
复制代码


(同时注意 arp_ignore 需要是 0 或 1)


Link 路由是可以直接 arp 目标地址的,而不是 arp 下一跳地址。意思就是说,目标地址是属于跟本地直连的二层链路上,不跨三层。既然是不跨三层的链路,arp 就可以畅行无阻,而标准中又没有规定 arp 协议包的请求源和请求目标必须是同一个网段的地址(甚至都没有掩码约束),所以说,一个以下的 arp 请求是有效的:



验证得到了响应:



细心的童鞋可以发现上面的命令实际上解决了我们的两个问题,网关的问题解决了,另外由于源主机直接请求目的主机的 MAC 地址,所以封装的时候也直接封装了目的主机的 MAC,省去了我们在倒数第一跳修改数据包的目的 MAC 为目的主机的工作。


最后剩下一个问题就是防环的 TTL 的问题,这个处理起来也比较简单一些,我们可以在流表中加入 actions=dec_ttl(1), output:100,在每一跳中自动减小 TTL。


然后在接收端的 PC 上面做类似的操作,中间的 OVS 添加相关 ARP 以及业务流的流表,就实现了跨网段的“交换”。

Little Tips

通过以上描述,已经实现了跨网段的路由向交换的转换,另外也可以实现所谓二层交换向路由的转换,比如 10.0.0.100/24 访问 10.0.0.200/24,按照我们的想当然是应该走二层转发的,也就是直接请求目的主机的 MAC 地址,然后封装、发送。


但是由于种种原因,目的主机 10.0.0.200/24 可能跟源主机是跨三层网络的,那现在怎么办呢?OK,可以在源主机上面增加一条明细路由把 10.0.0.200/24 指向默认网关,在目的主机上面增加一条明细路由把 10.0.0.100/24 指向默认网关,然后再 ping 一下,有木有看到自己的嘴角上扬呢!


交换机本就应该做二层转发的事情,其他的分布式出去吧!


本文转载自公众号 UCloud 技术(ID:ucloud_tech)。


原文链接:


https://mp.weixin.qq.com/s/xTmseMTJdBJ3TB93elxsHA


2019-11-11 17:371204

评论

发布
暂无评论
发现更多内容

数据质量提升

奔向架构师

数据质量 7月月更

JAVA编程规范之服务器

源字节1号

软件开发 后端开发

(WebFlux)001、如何自定义注解实现功能

编号94530

spring springmvc WebFlux 拦截器 @WebFilter

3 分钟掌握 Node.js 版本的区别

pingan8787

JavaScript node.js Vue 前端开发

听说学Python字体反爬的人,都打开过这篇博客,自如字体反爬,图片字体反爬

梦想橡皮擦

Python 爬虫 7月月更

消息队列存储消息数据的MySQL表设计

intelamd

编写Prometheus HTTP 服务发现有什么要求

耳东@Erdong

Prometheus 服务注册与发现 7月月更

深入浅出边缘云 | 3. 资源配置

俞凡

架构 边缘计算 网络 深入浅出边缘云

Java避坑指南:涉及金钱计算时使用BigDecimal如何避坑

Beaver

数据中台建设(六):数据体系建设

Lansonli

数据中台 7月月更

jQuery 遍历-后代深入解析分析【前端jQuery框架】

恒山其若陋兮

7月月更

leetcode 406. Queue Reconstruction by Height 根据身高重建队列(中等)

okokabcd

LeetCode 数据结构与算法 贪心算法

设备树的引入与体验

贾献华

7月月更

好的plm软件有哪些?plm软件排行榜

PingCode

模块八

Geek_2ce415

Snowflake vs. Redshift的2022战报:两个数据平台谁更适合你?

雨果

类似 MS Project 的项目管理工具有哪些

PingCode

openim支持十万超级大群

Geek_1ef48b

透过开发抽奖小程序,体会创新与迭代

小院里的霍大侠

创业 前端开发 创新 淘宝小程序 签约计划第三季

你了解SpringBoot启动时API相关信息是用什么数据结构存储的吗?

宁在春

Java 源码 springboot 7月月更

vue2升级vue3: TSX Vue 3 Composition API Refs

zhoulujun

Vue3 Ref JSX tsx 子组件

走进Redis,让你重新认识redis。绝不是表面

派大星

签约计划第三季

一文详解:SRv6 Policy模型、算路及引流

穿过生命散发芬芳

7月月更 SRv6

大家都在用的plm项目管理软件有哪些

PingCode

项目管理

Python中关于函数的那点事

Java学术趴

7月月更

设计消息队列存储消息数据的 MySQL 表格

爱晒太阳的大白

使用 Solidity 和 Node.js 构建简单的区块链预言机

devpoint

区块链 Node 预言机 7月月更

小心你的字典和样板代码

白日梦想家

总结 编码 反思 编程、 编码风格

Spark 在 Yarn 上运行 Spark 应用程序

xiaosi

spark YARN

最新发布!阿里巴巴专家亲自撰写,Dubbo 3.0 分布式实战(彩印版)

冉然学Java

Java 分布式 dubbo 框架 RPC 协议实现原理

SpringBoot日志收集-Aop方式-存进数据库

宁在春

aop springboot 7月月更

OpenFlow(OVS)下的“路由技术”_文化 & 方法_UCloud技术_InfoQ精选文章