本文主要描述了一种将三层路由变成二层交换转发(以及二层转发变成三层路由)的实现方式,以应对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,我们先看一下流表长啥样:

 
 
 
 
 

Java

 
1
2
3
4
5
6
root@ubuntu:~# ovs-ofctl dump-flows br2
NXST_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:100
cookie=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:1
cookie=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:100
cookie=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平台下并不是一件难事,只需一条命令:

 
 
 
 
 

Java

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

本质都是一样的,改变ARP的请求方式!

传统路由和OVS区别的更多相关文章

  1. springboot rabbitmq direct exchange和topic exchange 写法上关于路由键的区别

    这是direct exchange写法中消息发送写法,可见下图红色框中路由键是queue队列中定义的路由键 这是topic exchange写法中消息发送写法,可见下图红色框中路由键是exchange ...

  2. MongoDB与传统数据库的使用区别——批量插入与批量查询

    我在百X知道上回答问题时经常遇到类似与这样的问题:MongoDB有没有像MySQL一样的ODBC驱动?MongoDB能不能像MySQL一样获取字段名称或类型. 我的回答是:不行,因为MongoDB不是 ...

  3. Ajax与传统Web开发的区别

    基本概念 1.1,Ajax AJAX:即“Asynchronous Javascript And XML”(异步的JavaScript和XML),是指一种创建交互式网页应用的网页开发技术,尤其是在一种 ...

  4. 【Ajax 1】Ajax与传统Web开发的区别

    导读:从用户体验度的角度来说,利用Ajax进行开发的网站,其体验度高于利用传统Web开发技术,那么,是什么因素导致了这一现象呢?难道说Ajax开发,就一定优于传统Web技术吗?本篇文章,将主要介绍Aj ...

  5. ThingJS和传统3D开发的区别

    物联网3D可视化开发已经辐射到各行各业,无论车间还是消防,城市还是粮仓,亦或是地铁.科技园,物联网可视化是科技的进步,也是行业的进步.而传统的3D可视化开发实施起来并不那么乐观.如果使用ThingJS ...

  6. Restful API和传统的API的区别

    一.功能区别 Restful API是当作资源的唯一标识符,而传统是实现某某功能 如:/api/getList/1 and /api/getList?page=1 二.methods多样性 Restf ...

  7. 传统IO与NIO区别二

    nio是new io的简称,从jdk1.4就被引入了.现在的jdk已经到了1.6了,可以说不是什么新东西了.但其中的一些思想值得我来研究.这两天,我研究了下其中的套接字部分,有一些心得,在此分享.  ...

  8. OE1、OE2、ON1、ON2路由有什么区别?

    OSPF的路由类型: 1 .O    域内路由 2 .O/A  域间路由 3 .OE1  域外路由,会累加METRIC值(默认20) 4 .OE2  域外路由,不累加METRIC值(默认20),由外部 ...

  9. Redis,传统数据库,HBase,Hive区别联系

    首先介绍各个数据库: Redis: 传统数据库: HBase: Hive:

随机推荐

  1. Sublime Text 3 调用cmd运行c、java、python、batch file

    一.调用cmd运行c(首先复制MinGW到C盘根目录,并添加环境变量) Tools --> Build System --> New Build System 删除所有内容 复制如下代码进 ...

  2. windows server 2016 无法联网问题

    首先,联网分解为两个问题,一.WLAN(无线网).二.以太网(有线网) 一 .WLAN问题解决方案 1.打开服务器管理器 2.添加角色和功能 3.一直点下一步到“功能”,勾选 DirectPlay 和 ...

  3. sqlserver 一个字段分成两个字段 截取,保存

      Ma,LeiTo(Ma,lT) 分割后为 姓       名 Ma,LeiTo  Ma,lT SELECT LEFT(作者, CHARINDEX('(', 作者) - 1) AS 姓 , repl ...

  4. python第十四课--排序及自定义函数

    1.排序 特点: 1).升序:从小到大 2).降序:从大到小 课堂实现选择排序:参看老郭选择排序.py文件 2.函数:(方法/method) 自定义函数: 概念:它表示一段作用范围(作用域),当中封装 ...

  5. javascript花式理解闭包

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...

  6. [BJWC2011]最小三角形

    嘟嘟嘟 这一看就是平面分治的题,所以就想办法往这上面去靠. 关键就是到\(mid\)点的限制距离是什么.就是对于当前区间,所有小于这个距离的点都选出来,参与更新最优解. 假设从左右区间中得到的最优解是 ...

  7. redis 使用案例

    1.使用redis消息列队发布信息 在一些用户创造用户的应用中(如SNS,微博),可能出现1秒有上千万个用户同时发布消息的情况,此时如果使用mysql可能出现‘too many connections ...

  8. Day18 (一)类的加载器

    一个运行时的Java虚拟机(JVM)负责运行一个Java程序. 当启动一个Java程序时,一个虚拟机实例诞生:当程序关闭退出,这个虚拟机实例也就随之消亡. 如果在同一台计算机上同时运行多个Java程序 ...

  9. 【Agile123】Automated Test in Agile

    https://www.infoq.com/articles/thoughts-on-test-automation-in-agile Start Small Balance the cost vs. ...

  10. 《信息安全技术》实验二 Windows口令破解

    <信息安全技术>实验二 Windows口令破解 实验目的 了解Windows口令破解原理 对信息安全有直观感性认识 能够运用工具实现口令破解 实验环境 实验机Windows Server ...