本文主要讲解使用quagga、Docker和quagga搭建简单的BGP网络。使用OVS+Docker+quagga搭建BUG网络首先对本次使用的技术进行一个简单的介绍，接着说明一下本次试验的环境，最后进行BGP简单网络的搭建。1. 简单介绍1.1 BGP网络介绍[collapse title="BGP网络介绍" status="false"]BGP(边界网关协议)主要用于互联网AS(自治系统)之间的互联，BGP的最主要功能在于控制路由的传播和选择最好的路由。中国联通 、中国电信、中国移动、教育网和一些大的民营IDC运营商都具有AS号，全国各大网络运营商多数都是通过BGP协议与自身的AS号来实现多线互联的。使用BGP协议互联后，网络运营商的所有骨干路由设备将会判断到IDC机房IP段的最佳路由，以保证不同网络运营商用户的高速访问。[/collapse]1.2 Docker介绍[collapse title="Docker介绍" status="false"]Docker 是一个开源的应用容器引擎，让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中，然后发布到任何流行的 Linux或Windows 机器上，也可以实现虚拟化。容器是完全使用沙箱机制，相互之间不会有任何接口。[/collapse]1.3 quagga介绍[collapse title="quagga介绍" status="false"]quagga软件原名是Zebra是由一个日本开发团队编写的一个以GNU版权方式发布的软件。它将linux机器打造成一台功能完备的路由器。Quagga支持的路由协议 Quagga能够同时支持RIPv1、RIPv2、RIPng、OSPFv2、OSPFv3、BGP-4和 BGP-4+等诸多TCP/IP协议。其中： RIPv1、RIPv2、OSPFv2适用于Ipv4的自治域系统内部网络路由协议。 BGP-4是用于Ipv4的自治域系统之间的外部网络路由协议。 RIPng、OSPFv3、BGP-4+主要扩展对Ipv6的支持。Quagga的特性 模块化设计：Quagga基于模块化方案的设计，即对每一个路由协议使用单独的守护进程。 运行速度快：因为使用了模块化的设计，使得Quagga的运行速度比一般的路由选择程序要快。 可靠性高：在所有软件模块都失败的情况下，路由器可以继续保持连接并且daemons也会继续运行。故障诊断不必离线的状态下被诊断和更正 支持Ipv6：Quagga不仅支持Ipv4，还支持Ipv6。Quagga的运行机制 由于Quagga采用模块化的设计，因此Quagga运行时要运行多个守护进程，包括ripd ripngd ospfd ospf6d bgpd 和Zebra。 其中，Zebra守护进程用来更新内核的路由表，而其他的守护进程负责进行相应路由选择协议的路由更新。Quagga的好处[/collapse]1.4 OpenVSwitch介绍[collapse title="OpenVSwitch介绍" status="false"]OpenvSwitch，简称OVS是一个虚拟交换软件，主要用于虚拟机VM环境，作为一个虚拟交换机，支持Xen/XenServer, KVM, and VirtualBox多种虚拟化技术。虽然是虚拟交换机，但是其工作原理与物理交换机类似。在虚拟交换机的实现中，其两端分别连接着物理网卡和多块虚拟网卡，同时虚拟交换机内部会维护一张映射表，根据MAC地址寻找对应的虚拟机链路进而完成数据转发。 OpenvSwitch是实现虚拟化网络的重要基础组件，在OpenStack中利用OpenvSwitch作为底层部件来完成虚拟网络提供和租户网络管理。OpenvSwitch可以实现访问控制功能，通过转发规则，可以实现简单的安全行为，包括通过、禁止等。[/collapse]2. 本次运行的环境2.1 系统环境Centos 7.6.18102.2 软件环境Docker 17.06【docker镜像为centos7】OpenVSwitch 2.5.8版本3. BGP网络搭建[scode type="blue"]3.1为首先准备BGP的一些基础环境，[/scode]3.1 BGP环境准备准备Docker和OVS3.1.1 安装Docker和OVS[root@localhost ~]#yum install docker-ce.x86_64 openvswitch.x86_64 -y #安装docker和OVS [root@localhost ~]#systemctl start docker [root@localhost ~]#systemctl start openvswitch #启动docker和OVS3.1.2 Docker下载centos镜像[root@localhost ~]#docker pull centos:latest #下载centos镜像 [root@localhost ~]#docker run -itd --privileged=true --name temp centos:latest /bin/bash #运行centos镜像 [root@localhost ~]#docker exec -i temp yum update -y #更新docker镜像系统 [root@localhost ~]#docker exec -i temp yum install quagga net-tools vim screen -y #在docker镜像里安装quagga等基础环境 [root@localhost ~]#docker commit temp quagga #保存为quagga镜像3.1.3 部署OVS[scode type="blue"]增加OVS网桥[/scode][root@localhost ~]#ovs-vsctl add-br br1 #增加OVS网桥 [root@localhost ~]#ovs-vsctl show 15f3e9bd-93d4-44d5-aba9-752bea391fce Bridge "br1" Port "br1" Interface "br1" type: internal ovs_version: "2.5.8" #查看是否添加成功3.1.4 部署BGP网络[scode type="blue"]网络拓扑图如下所示：[/scode]运行Docker[root@localhost ~]# docker run -itd --privileged=true --network none --name BGP1 quagga:latest /bin/bash #运行docker A [root@localhost ~]# ovs-docker add-port br1 eth1 BGP1 --ipaddress=192.168.2.1/24 [root@localhost ~]# ovs-docker add-port br1 eth2 BGP1 --ipaddress=100.100.0.1/30 #添加容器A网络 [root@localhost ~]# docker run -itd --privileged=true --network none --name BGP2 quagga:latest /bin/bash #运行docker B [root@localhost ~]# ovs-docker add-port br1 eth1 BGP2 --ipaddress=10.10.2.1/24 [root@localhost ~]# ovs-docker add-port br1 eth2 BGP2 --ipaddress=100.100.0.2/30 #添加容器B网络容器BGP1-运行quagga程序这里使用screen放在后台运行[root@localhost ~]# docker attach BGP1 [root@a6a0fd30b609 ~]# echo 'hostname 55dea2659df3'>/etc/quagga/zebra.conf #写入zebra配置文件 [root@a6a0fd30b609 ~]# nohup zebra & #放后台 [root@a6a0fd30b609 ~]# echo '! -*- bgp -*- ! ! BGPd sample configuratin file ! ! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $ ! hostname bgpd password zebra !enable password please-set-at-here ! !bgp mulitple-instance ! router bgp 7675 ! bgp router-id 10.0.0.1 ! network 10.0.0.0/8 ! neighbor 10.0.0.2 remote-as 7675 ! neighbor 10.0.0.2 route-map set-nexthop out ! neighbor 10.0.0.2 ebgp-multihop ! neighbor 10.0.0.2 next-hop-self ! ! access-list all permit any ! !route-map set-nexthop permit 10 ! match ip address all ! set ip next-hop 10.0.0.1 ! !log file bgpd.log ! log stdout'> /etc/quagga/bgpd.conf # 写入BGP配置文件 [root@a6a0fd30b609 ~]# nohup bgpd & # 放入后台 [root@a6a0fd30b609 ~]# echo '! -*- ospf -*- ! ! OSPFd sample configuration file ! ! hostname ospfd password zebra !enable password please-set-at-here ! !router ospf ! network 192.168.1.0/24 area 0 ! log stdout'>/etc/quagga/ospfd.conf #写入ospf配置文件 [root@a6a0fd30b609 ~]# nohup ospfd & [root@a6a0fd30b609 ~]# netstat -tunlp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:2601 0.0.0.0:* LISTEN 61/zebra tcp 0 0 0.0.0.0:2604 0.0.0.0:* LISTEN 101/ospfd tcp 0 0 0.0.0.0:2605 0.0.0.0:* LISTEN 95/bgpd tcp 0 0 0.0.0.0:179 0.0.0.0:* LISTEN 95/bgpd tcp6 0 0 :::2601 :::* LISTEN 61/zebra tcp6 0 0 :::2604 :::* LISTEN 101/ospfd tcp6 0 0 :::2605 :::* LISTEN 95/bgpd tcp6 0 0 :::179 :::* LISTEN 95/bgpd #检测端口容器BGP2-运行quagga程序[scode type="blue"]配置内容同上[/scode]配置BGP网络[scode type="yellow"]对容器BGP1进行配置[/scode][scode type="blue"]我们要确认当前没有已经配置的BGP会话。在一些版本，我们可能会发现一个AS号为7675的BGP会话。由于我们不需要这个会话，所以把它移除。[/scode][root@a6a0fd30b609 ~]# vtysh #进入quagga路由器 bgpd# configure terminal bgpd(config)# no router bgp 7675 bgpd(config)# router bgp 100 bgpd(config-router)# no auto-summary bgpd(config-router)# no synchronization bgpd(config-router)# neighbor 100.100.0.2 remote-as 200 bgpd(config-router)# neighbor 100.100.0.2 description "provider B" bgpd(config-router)# exit bgpd(config)# exit bgpd# write # 对BGP进行设置[scode type="yellow"]对容器BGP2进行配置[/scode][root@ea07e44ee83b ~]# vtysh Router-B# configure terminal Router-B(config)#no router bgp 7675 Router-B(config)# router bgp 200 Router-B(config)#no auto-summary Router-B(config)#no synchronizaiton Router-B(config-router)# neighbor 100.100.0.1 remote-as 100 Router-B(config-router)# neighbor 100.100.0.1 description "provider A" Router-B(config-router)#exit Router-B(config)#exit Router-B# write[scode type="yellow"]检测此步骤是否搭建成功,如果显示如下，说明此步骤没问题。[/scode]ea07e44ee83b# show ip bgp summary BGP router identifier 100.100.0.2, local AS number 200 RIB entries 0, using 0 bytes of memory Peers 1, using 4560 bytes of memory Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd 100.100.0.1 4 100 3 4 0 0 0 00:01:12 0 Total number of neighbors 1 配置BGP前缀通告AS 100将以192.168.2.1/24作为通告，在我们的例子中AS 200将同样以10.10.2.1/24作为通告。这些前缀需要被添加到BGP配置如下。#在路由器-A中： bgpd# configure terminal bgpd(config)# router bgp 100 bgpd(config-router)# network 192.168.2.1/24 bgpd(config-router)# exit bgpd(config)# exit bgpd# write #在路由器-B中： ea07e44ee83b# configure terminal ea07e44ee83b(config)# router bgp 200 ea07e44ee83b(config-router)# network 10.10.2.1/24 ea07e44ee83b(config-router)# exit ea07e44ee83b(config)# exit ea07e44ee83b# write #两个路由器会根据需要开始通告前缀。测试前缀通告[scode type="blue"]首先，确认前缀的数量是否被改变了,输入“show ip bgp summary”查看：[/scode]ea07e44ee83b# show ip bgp summary BGP router identifier 100.100.0.2, local AS number 200 RIB entries 3, using 336 bytes of memory Peers 1, using 4560 bytes of memory Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd 100.100.0.1 4 100 11 12 0 0 0 00:08:15 1 Total number of neighbors 1[scode type="blue"]查看所接收的更多前缀细节，我们可以使用以下命令，“show ip bgp neighbors 邻居IP advertised-routes”这个命令用于显示邻居所接收到的前缀总数。[/scode]ea07e44ee83b# show ip bgp neighbors 100.100.0.1 advertised-routes BGP table version is 0, local router ID is 100.100.0.2 Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, r RIB-failure, S Stale, R Removed Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path *> 10.10.2.0/24 100.100.0.2 0 32768 i Total number of prefixes 1 [scode type="blue"]查看哪一个前缀是我们从邻居接收到的,可以使用如下命令：“show ip bgp neighbors 邻居IP routes”[/scode]ea07e44ee83b# show ip bgp neighbors 100.100.0.1 routes BGP table version is 0, local router ID is 100.100.0.2 Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, r RIB-failure, S Stale, R Removed Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path *> 192.168.2.0 100.100.0.1 0 0 100 i Total number of prefixes 1 [scode type="blue"]也可以查看所有的BGP路由器：“show ip bgp”[/scode]ea07e44ee83b# show ip bgp BGP table version is 0, local router ID is 100.100.0.2 Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, r RIB-failure, S Stale, R Removed Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path *> 10.10.2.0/24 0.0.0.0 0 32768 i *> 192.168.2.0 100.100.0.1 0 0 100 i Total number of prefixes 23.1.5 测试BGP网络[scode type="blue"]在BGP1中ping BGP2中的192.168.2.1和10.10.2.1都可以ping通[/scode]测试方法1ea07e44ee83b# ping 192.168.2.1 PING 192.168.2.1 (192.168.2.1) 56(84) bytes of data. 64 bytes from 192.168.2.1: icmp_seq=1 ttl=64 time=0.947 ms 64 bytes from 192.168.2.1: icmp_seq=2 ttl=64 time=0.095 ms 64 bytes from 192.168.2.1: icmp_seq=3 ttl=64 time=0.101 ms 64 bytes from 192.168.2.1: icmp_seq=4 ttl=64 time=0.120 ms ^C --- 192.168.2.1 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3001ms rtt min/avg/max/mdev = 0.095/0.315/0.947/0.365 ms ea07e44ee83b# ping 10.10.2.1 PING 10.10.2.1 (10.10.2.1) 56(84) bytes of data. 64 bytes from 10.10.2.1: icmp_seq=1 ttl=64 time=0.240 ms 64 bytes from 10.10.2.1: icmp_seq=2 ttl=64 time=0.072 ms 64 bytes from 10.10.2.1: icmp_seq=3 ttl=64 time=0.080 ms 64 bytes from 10.10.2.1: icmp_seq=4 ttl=64 time=0.092 ms ^C --- 10.10.2.1 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 2999ms rtt min/avg/max/mdev = 0.072/0.121/0.240/0.069 ms #ping测试测试方法2[root@localhost ~]# docker run -itd --privileged=true --network none --name test quagga:latest /bin/bash [root@localhost ~]# ovs-docker add-port br1 eth1 test --ipaddress=192.168.2.100/24 [root@localhost ~]# docker exec -i test ip route add default via 192.168.2.1 [root@localhost ~]# docker exec -i test ping 10.10.2.1 -c 4 PING 10.10.2.1 (10.10.2.1) 56(84) bytes of data. 64 bytes from 10.10.2.1: icmp_seq=1 ttl=63 time=1.07 ms 64 bytes from 10.10.2.1: icmp_seq=2 ttl=63 time=0.228 ms 64 bytes from 10.10.2.1: icmp_seq=3 ttl=63 time=0.235 ms 64 bytes from 10.10.2.1: icmp_seq=4 ttl=63 time=0.117 ms --- 10.10.2.1 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3001ms rtt min/avg/max/mdev = 0.117/0.414/1.078/0.386 ms # 如果可以通，说明配置成功
本章讲解了使用OpenVSwitch的openflow协议的一些记录。初体验：OVS的openflow协议全文概括本章讲解了使用OpenVSwitch的openflow协议的一些命令，以后可能会用到，因此，在博客里做个记录。openflow介绍[collapse title="OpenVSwitch介绍" status="true"]软件定义网络（Software Defined Network，SDN）是由美国斯坦福大学CLean State课题研究组提出的一种新型网络创新架构，是网络虚拟化的一种实现方式。其核心技术OpenFlow通过将网络设备的控制面与数据面分离开来，从而实现了网络流量的灵活控制，使网络作为管道变得更加智能，为核心网络及应用的创新提供了良好的平台。OpenFlow，一种网络通信协议，属于数据链路层，能够控制网上交换器或路由器的转发平面（forwarding plane），借此改变网络数据包所走的网络路径。[/collapse][scode type="blue"]如果想要看openvswitch的介绍或者ovs的编译步骤，请看以下文章：[/scode][post cid="44" /]命令汇总列出br1网桥的接口[root@localhost ~]# ovs-ofctl -O OpenFlow13 show br1 #列出br4网桥的接口 OFPT_FEATURES_REPLY (OF1.3) (xid=0x2): dpid:0000227f47f14b45 n_tables:254, n_buffers:256 capabilities: FLOW_STATS TABLE_STATS PORT_STATS GROUP_STATS QUEUE_STATS OFPST_PORT_DESC reply (OF1.3) (xid=0x3): 1(ca5ab26545b04_l): addr:da:ed:cd:c6:bf:0a config: 0 state: 0 current: 10GB-FD COPPER speed: 10000 Mbps now, 0 Mbps max 2(619496038daf4_l): addr:3a:0b:d6:59:99:4f config: 0 state: 0 current: 10GB-FD COPPER speed: 10000 Mbps now, 0 Mbps max LOCAL(br1): addr:22:7f:47:f1:4b:45 config: PORT_DOWN state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max OFPT_GET_CONFIG_REPLY (OF1.3) (xid=0x5): frags=normal miss_send_len=0列出br1网桥的接口[root@localhost ~]# ovs-ofctl dump-ports -O OpenFlow13 br1 #列出br1网桥的接口 OFPST_PORT reply (OF1.3) (xid=0x2): 3 ports port LOCAL: rx pkts=0, bytes=0, drop=1, errs=0, frame=0, over=0, crc=0 tx pkts=0, bytes=0, drop=0, errs=0, coll=0 duration=6401.851s port 1: rx pkts=551, bytes=1043382, drop=0, errs=0, frame=0, over=0, crc=0 tx pkts=391, bytes=29298, drop=0, errs=0, coll=0 duration=6392.311s port 2: rx pkts=383, bytes=28650, drop=0, errs=0, frame=0, over=0, crc=0 tx pkts=394, bytes=702996, drop=0, errs=0, coll=0 duration=6390.151s列出br1网桥的某个接口的详细信息[root@localhost ~]# ovs-ofctl dump-ports -O OpenFlow13 br1 OFPST_PORT reply (OF1.3) (xid=0x2): 3 ports port LOCAL: rx pkts=0, bytes=0, drop=1, errs=0, frame=0, over=0, crc=0 tx pkts=0, bytes=0, drop=0, errs=0, coll=0 duration=6401.851s port 1: rx pkts=551, bytes=1043382, drop=0, errs=0, frame=0, over=0, crc=0 tx pkts=391, bytes=29298, drop=0, errs=0, coll=0 duration=6392.311s port 2: rx pkts=383, bytes=28650, drop=0, errs=0, frame=0, over=0, crc=0 tx pkts=394, bytes=702996, drop=0, errs=0, coll=0 duration=6390.151s [root@localhost ~]# ovs-ofctl dump-ports -O OpenFlow13 br1 OFPST_PORT reply (OF1.3) (xid=0x2): 3 ports port LOCAL: rx pkts=0, bytes=0, drop=1, errs=0, frame=0, over=0, crc=0 tx pkts=0, bytes=0, drop=0, errs=0, coll=0 duration=6434.883s port 1: rx pkts=551, bytes=1043382, drop=0, errs=0, frame=0, over=0, crc=0 tx pkts=391, bytes=29298, drop=0, errs=0, coll=0 duration=6425.343s port 2: rx pkts=383, bytes=28650, drop=0, errs=0, frame=0, over=0, crc=0 tx pkts=394, bytes=702996, drop=0, errs=0, coll=0 duration=6423.183s 查看 Open vSwitch 中的端口信息[root@localhost ~]# ovs-ofctl show -O OpenFlow13 br1 OFPT_FEATURES_REPLY (OF1.3) (xid=0x2): dpid:0000227f47f14b45 n_tables:254, n_buffers:256 capabilities: FLOW_STATS TABLE_STATS PORT_STATS GROUP_STATS QUEUE_STATS OFPST_PORT_DESC reply (OF1.3) (xid=0x3): 1(ca5ab26545b04_l): addr:da:ed:cd:c6:bf:0a config: 0 state: 0 current: 10GB-FD COPPER speed: 10000 Mbps now, 0 Mbps max 2(619496038daf4_l): addr:3a:0b:d6:59:99:4f config: 0 state: 0 current: 10GB-FD COPPER speed: 10000 Mbps now, 0 Mbps max LOCAL(br1): addr:22:7f:47:f1:4b:45 config: PORT_DOWN state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max OFPT_GET_CONFIG_REPLY (OF1.3) (xid=0x5): frags=normal miss_send_len=0 获得网络接口的 OpenFlow 编号[root@localhost ~]# ovs-vsctl get Interface 619496038daf4_l ofport #获得网络接口的 OpenFlow 编号 2 查看网桥下的流表[root@localhost ~]# ovs-ofctl dump-flows -O OpenFlow13 br1 #查看网桥下的流表 OFPST_FLOW reply (OF1.3) (xid=0x2): cookie=0x0, duration=6575.901s, table=0, n_packets=769, n_bytes=730998, priority=0 actions=NORMAL添加流表ovs-ofctl add-flow br1 in_port=1,actions=output:2删除网桥中所有的流表ovs-ofctl del-flows br1删除根据匹配项删除网桥中的流表ovs-ofctl del-flows br0 "in_port=1"让端口发来的数据包全部丢弃ovs-ofctl add-flow br1 priority=12,in_port=2,actions=drop
本文主要内容是编译OpenVSwitch，当做自己的一个编译记录。OVS源码编译OpenVSwitch介绍[collapse title="OpenVSwitch介绍" status="true"]Open vSwitch是在开源的Apache2.0许可下的产品级质量的多层虚拟交换标准！它旨在通过编程扩展，使庞大的网络自动化（配置、管理、维护），同时还支持标准的管理接口和协议（如NetFlow， sFlow， SPAN， RSPAN， CLI， LACP， 802.1ag）。[/collapse]OVS编译[scode type="blue"]下载OVS源代码[/scode]wget http://openvswitch.org/releases/openvswitch-版本.tar.gz[scode type="blue"]具体的可以去OVS官网查看版本[/scode][scode type="blue"]解压并生成配置文件[/scode]tar -xvzf openvswitch-版本.tar.gz cd openvswitch-版本 ./configure --with-linux=/lib/modules/$(uname -r)/build[scode type="blue"]直接编译安装可以使用make -j $number[/scode]make # 或者make -j 16 make install make modules_install[scode type="blue"]加载模块[/scode]modprobe openvswitch #不要使用insmod openvswitch[scode type="blue"]因为openvswitch模块与linux的bridge模块冲突，所以如果发生冲突，不能加载ovs的内核模块时，先卸载掉bridge模块。[/scode]rmmod bridge modprobe openvswitch[scode type="blue"]使用lsmod查看已加载的所有模块，验证是否加载ovs的内核模块成功。 使用dmesg查看模块加载报错信息[/scode]lsmod | grep openvswitch[scode type="blue"]如果一直加载模块不成功，可以用命令modinfo openvswitch查看该模块的信息，内核版本以及依赖关系等。或者用dmesg | tail查看kernel的日志信息。[/scode]OVS编译成功