Quagga(含zebra,及多种其他转发协议daemon) 与 第一个Mininet(containernet)OSPF测试实验(ubuntu 22.04.3)

  1. 缘起

在学习、运行P4-utils中examples里的frrouter还有adv-net给我报一堆错,其中很大一部分就是关于zebra daemon的。因为之前没接触和配置,现在此进行。

本文仅限Quagga的成功配置与实验示例运行,前面说的那俩example还是有问题,事后搞明白了再写…

本文使用系统:ubuntu 22.04.3 + containernet(mininet也是可以的,containernet本身就是mininet的一个扩充,mininet能行的containernet也都能行。甚至mininet的程序贴过来都不用改😊)

  1. Quagga下载与配置

Caution:

1)*我是使用Snap下载的,可能还可以参考这位博主(博文网站:使用Quagga在Mininet节点上进行OSPF实验_ryu mininet ospf-CSDN博客; 官方tar资源下载网站Index of /repo/pkgs/quagga;不过很重要一点,这个博主是ubuntu 18,而我是最新的22.04!所以如果你也是新版本,非常推荐参考我的内容,可能适配度更高)的官网下载办法进行。不知道为什么我没法使用apt下载。

2) Containernet/mininet的配置不在本文覆盖范围内。Ps, 当时containernet的配置挺麻烦。有空新开贴记录

  1. Quagga资源下载

一开始找半天,硬是没找着官方资源,好多之前博客给的网站全部404了(好像说ubuntu22不再支持quagga了?我还没摸明白)。期间还尝试git clone *quagga的git网站*,但是最终多次努力,依然在make处出现两个报错而退出,安装失败;也尝试了sudo apt-install,但是报错说没找到资源,同样失败。

最后找到这个——snap,能行!

(Install quagga on Ubuntu using the Snap Store | Snapcraft)

依照这个进行就好。(apt不管用时snap可以来凑一凑…?...)

A. OSPF配置

下载完之后的quagga文件夹路径位于/snap下的quagga文件夹中。打开后有两个文件,“4”和“current”——用ls -l 看current,能发现它就是4的软连接,俩就一货。(糟糕的水印)

文件夹中能看见运行需要的动态库文件夹lib、包含多种转发协议程序的文件夹sbin,等等所需的内容都有。接下来我们需要适当配置一下。

我所使用的配置方法主要是参考此链接

Learn How to Set up Linux's Quagga Routing Suite | Engineering Education (EngEd) Program | Section很好的链接;当然,上文提到的博主的办法也应该是正确的,两者本质看着差不多,不过我没有验证。

#1 打开系统的(ipv4)默认转发:这一步在后续的py文件中也已有写入配置cmd,故可省略

echo "net.ipv4.conf.all.forwarding=1" | sudo tee -a /etc/sysctl.conf

echo "net.ipv4.conf.default.forwarding=1" | sudo tee -a /etc/sysctl.conf

sudo sysctl -p

#2 配置conf文件:复制与重命名

每次在使用quagga的daemon配置路由器时,我们都需为其编写conf配置文件。在你的quagga文件夹路径中搜一下conf,你能找到他们的位置

可以看见,里面有各种协议的.conf.default以及.conf.sample文件。我们需要后者(前者也是0 bytes空的)。使用cp指令把所有的.sample文件都复制到/etc/quagga下:

cp /snap/quagga/current/etc/quagga/*.sample /etc/quagga

接下来需要使用mv指令重命名下,删掉所有的后缀“.sample”

sudo mv ripngd.conf.sample ripngd
sudo mv ospfd.conf.sample ospfd.conf
sudo mv bgpd.conf.sample bgpd.conf
sudo mv ripd.conf.sample ripd.conf
sudo mv zebra.conf.sample zebra.conf
sudo mv vtysh.conf.sample vtysh.conf
sudo mv isisd.conf.sample isisd.conf
sudo mv babeld.conf.sample babeld.conf

注意,不同下载方式得到的quagga协议内容可能不一样,比如相比上述指令,未通过snap下载得到的内容中是没有“babeld”的,变成了“pmid”。

后续内容我就暂时先没有再参考section网站上的配置方式。(因为frrouter那个历程不报错相关zebra的错了,虽然还是运行结果错误…为了确保quagga已经配置正确,方才进行如下实验验证)。

B. Containernet(mininet) OSPF转发实验

(请允许我直接搬运博主文中的图)

  1. 实验准备(环境、程式码:.py与配置文件.conf)

#1 拷贝动态运行库:我隐隐感觉此步骤与” 999. 其他(混乱无序的)问题记录”中第5条可能重合;同时,我没有按照参考博主的"选择性cp",直接粗暴全局复制。

cp /snap/quagga/4/lib/* /lib
cp: -r not specified; omitting directory '/snap/quagga/4/lib/systemd'
cp: -r not specified; omitting directory '/snap/quagga/4/lib/x86_64-linux-gnu'

#2 启动zebra:我不清楚这在第一次运行中是否是必要的。我在第一次成功运行后,第二次重启、清除过去实验文件重新创建,没有再执行这句话,运行也能成功,不知是否是有过第一次初始运行。保险起见,现附于此处,以备有需。

sudo zebra -d

#3 r1、r2 conf文件设置:

  1. 为路由器r1、r2各复制一份zebra.conf(推荐可以新mkdir搞个实验文件夹,避免实验使用配置文件与配置文件模板搞在一起太乱)
cp zebra.conf OspfTstExp/r1zebra.conf
cp zebra.conf OspfTstExp/r2zebra.conf
  1. 为路由器r1、r2各创建一份ospfd.conf文件两份
gedit OspfTstExp/r1ospfd.conf &
gedit OspfTstExp/r2ospfd.conf &

两份文件按内容分别如下:

OspfTstExp/r1ospfd.conf

hostname r1_ospfd
password 123              
enable password 123   

router ospf                       
        ospf router-id 10.0.3.10 
        network 10.0.3.0/24 area 0          
        network 10.0.1.0/24 area 0debug ospf event
log file /etc/quagga/OspfTstExp/r1ospfd.log  

其中,密码部分可以删去。Router部分中,”router ospf”为声明路由协议为OSPF;”ospf router-id 10.0.3.10”为设定路由器标识;“network 10.0.3.0/24 area 0“及下一句为设置网络所处OSPF area。(注意,输出的log文件有个×,没法打开看——这是文件权限信息不正确导致。使用

sudo chmod 777 /etc/quagga/OspfTstExp/r1ospfd.log

 sudo chmod 777 /etc/quagga/OspfTstExp/r2ospfd.log

修改即可成功打开查看)

OspfTstExp/r2ospfd.conf

hostname r2_ospfd
password 123                  
enable password 123    

router ospf                       
        ospf router-id 10.0.3.20 
        network 10.0.3.0/24 area 0       
        network 10.0.2.0/24 area 0

debug ospf event
log file /etc/quagga/OspfTstExp/r2ospfd.log    

如假包换,r2的文件只需对r1文件修改四个地方:首行hostname、ospf的router-id标识、不与r1共享的网域、日志输出文件名。

至此,路由器r1、r2的配置均已完成。

#3 PY主程序文件:

#!/usr/bin/python3

from mininet.topo import Topo
from mininet.net import Mininet
from mininet.node import Node
from mininet.log import setLogLevel, info
from mininet.cli import CLI
import time
import os

class LinuxRouter( Node ):
    "A Node with IP forwarding enabled."

    def config( self, **params ):
        super( LinuxRouter, self).config( **params )
        # Enable forwarding on the router
        self.cmd( 'sysctl net.ipv4.ip_forward=1' )

    def terminate( self ):
        self.cmd( 'sysctl net.ipv4.ip_forward=0' )
        super( LinuxRouter, self ).terminate()


class NetworkTopo( Topo ):
    "A LinuxRouter connecting three IP subnets"

    def build( self, **_opts ):

        defaultIP1 = '10.0.3.10/24'    # IP address for r1-eth1
        defaultIP2 = '10.0.3.20/24' 
        router1 = self.addNode( 'r1', cls=LinuxRouter, ip=defaultIP1 )    # cls = class
        router2 = self.addNode( 'r2', cls=LinuxRouter, ip=defaultIP2 )
    
        h1 = self.addHost( 'h1', ip='10.0.1.100/24', defaultRoute='via 10.0.1.10')    # define gateway
        h2 = self.addHost( 'h2', ip='10.0.2.100/24', defaultRoute='via 10.0.2.20')

        self.addLink(router1,router2,intfName1='r1-eth1',intfName2='r2-eth1')    # r1-eth1 <-> r2-eth1
        self.addLink(h1,router1,intfName2='r1-eth2',params2={ 'ip' : '10.0.1.10/24' })    
    # h1-eth0 <-> r1-eth2, r1-eth2 = 10.0.1.10/24
        self.addLink(h2,router2,intfName2='r2-eth2',params2={ 'ip' : '10.0.2.20/24' })
    # h2-eth0 <-> r2-eth2, r2-eth2 = 10.0.2.20/24


def run():
    "Test linux router"
    topo = NetworkTopo()
    net = Mininet(controller = None, topo=topo )    # no controller
    net.start()
    info( '*** Routing Table on Router:\n' )

    r1=net.getNodeByName('r1')
    r2=net.getNodeByName('r2')
    info('starting zebra and ospfd service:\n')

    r1.cmd('/snap/quagga/current/sbin/zebra -f /etc/quagga/OspfTstExp/r1zebra.conf -d -z /tmp/r1zebra.api -i /tmp/r1zebra.interface')    
    # -z, -i一个都不能少,*zebra.api, *zebra.interface会在启动时自动创建,下同
    # 不过有一点要注意,*zebra.api, *zebra.interface必须创建在自动目录/tmp下
    time.sleep(1)    # time for zebra to create api socket

    r2.cmd('/snap/quagga/current/sbin/zebra -f /etc/quagga/OspfTstExp/r2zebra.conf -d -z /tmp/r2zebra.api -i /tmp/r2zebra.interface')
    time.sleep(1)    # time for zebra to create api socket
    
    r1.cmd('/snap/quagga/current/sbin/ospfd -f /etc/quagga/OspfTstExp/r1ospfd.conf -d -z /tmp/r1zebra.api -i /tmp/r1ospfd.interface')
    time.sleep(1)    # time for zebra to create api socket
    
    r2.cmd('/snap/quagga/current/sbin/ospfd -f /etc/quagga/OspfTstExp/r2ospfd.conf -d -z /tmp/r2zebra.api -i /tmp/r2ospfd.interface')
    time.sleep(1)    # time for zebra to create api socket
    
    
    CLI( net )
    net.stop()
    os.system("killall -9 ospfd zebra")        # 杀死进程
    #os.system("rm -f *api*")                # 移除.api文件
    #os.system("rm -f *interface*")            # 移除.interface文件

if __name__ == '__main__':
    setLogLevel( 'debug' ) # 一定要使用这种模式 这样有任何报错都能直接查看有迹可循
    run()

参考博主以及参考的参考博主只在第一个“r1.cmd“后面写了time.sleep(1)语句——我推荐在下面三条每个cmd语句后都加上。因为我有几次尝试过程中出现了file not found error——可能确实就是socket还没来得及产生所致。

同时,最后api与interface的移除语句可以不用加。我打成注释也可成功运行。

#4 运行:使用python3执行前面的py文件。我是等待一分十秒后,可pingall成功。

999. 其他(混乱无序的)问题记录

1) python open(“w”)指令中,虽然会自动创建不存在的文件,但如果指定路径中含有不存在的文件路径(比如新的文件夹),则不会自动创建,会报错。

2) 在运行p4-utils frrouters报错中,遇到了“invalid operation gawk”的报错。我通过使用”apt install gawk“成功安装即可。(过程中使用另一个安装指令好像报错没法装,真怪,但我现在忘记到底是哪条了,anyway我给出的这条实践表明能用)

3) 注意,对于自己安装的quagga,p4utils/mininetlib库中的node文件里的“bin_dir“变量记得换成自己的quagga sbin路径,比如我的是”/snap/quagga/current/sbin“

4) python中,函数只有在具有“return + 函数名“的时候,对象类型才是function,否则为”NoneType”类型——这在我运行frrouters过程中在类型检查语句中出现了报错,说是对象无类型,非函数。只要循迹报错位置找到相应函数手动增添返回语句“return 函数名”即可解决。

5) (还是运行frrouters过程中)报错:zebra: error while loading shared libraries: libzebra.so.0: Cannot open shared obiect file: No such file or directory

终端使用find命令:

find / -name libzebra.so.0

找到动态库路径。我的是“/snap/quagga/4/lib”

然后在/etc/ld.so.conf中加入“/snap/quagga/4/lib”这一行

保存之后,再运行: /sbin/ldconfig -v更新一下配置即可

(来自博文在ubuntu14.04 64位机上安装quagga-0.99.21-CSDN博客的参考)

6) 运行mininet/containernet时,强烈建议新手/调试过程中使用setLogLevel(‘debug’) instead of setLogLevel(‘info’)——因为前者有任何报错信息都会即时弹出,非常适合快速定位错误。这是来自上文参考的博主GoLemZ的建议,非常非常好的提醒。

7)最好别在.conf文件中使用中文注释”#注释”——不知道为什么我加上之后py执行过程中就报错不认识指令…删掉中文井号注释后全好了……

  • 17
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Quagga和Zebra是两个开源的网络路由软件套件。Zebra是一个基于BSD授权的路由软件套件,提供了OSPF、BGP、RIP、RIPng等协议的实现。而Quagga则是Zebra的一个分支,目前由社区维护,支持更多的协议,包括IS-IS、OSPFv3、PIM、RIPng等。 下面我们来简要分析一下Quagga和Zebra的源码结构: 1. Quagga Quagga的源码主要分为以下几个部分: - bgpd:BGP协议的实现。 - ospfd:OSPF协议的实现。 - ospf6d:OSPFv3协议的实现。 - ripd:RIP协议的实现。 - ripngd:RIPng协议的实现。 - isisd:ISIS协议的实现。 - pimd:PIM协议的实现。 - vtysh:用户交互界面。 其中,每个协议的实现都在对应的目录下,包括配置文件的解析、协议控制块的管理、路由表的维护等。而vtysh则是一个基于GNU Readline的交互式命令行界面,用于用户与Quagga的交互。 2. Zebra Zebra的源码主要分为以下几个部分: - zebra:路由守护进程,负责各个协议之间的协调和管理。 - lib:公共库,包括路由表、控制块、事件机制等。 - ospfOSPF协议的实现。 - ospf6:OSPFv3协议的实现。 - bgp:BGP协议的实现。 - ripd:RIP协议的实现。 - ripng:RIPng协议的实现。 在Zebra中,路由表、控制块等公共部分的实现都在lib目录下,而各个协议的实现则在对应的目录下。 总体来说,Quagga和Zebra的源码结构比较清晰,各个协议之间的代码实现相对独立,方便开发者进行二次开发和定制。同时,它们的协议实现也比较完善,可以满足不同场景下的路由需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值