跳转至

调试

本地测试

在编写 OSPF 协议的路由器的时候,可以在本机搭建一个虚拟的和评测环境一样的网络拓扑,这样就可以在虚拟网络中按照评测流程一步一步进行,同时观察程序的行为,可以大大地加快代码的调试。

本地测试主要分为两个部分:首先,搭建网络拓扑,将网络中各个设备连接好;其次,在各个设备上,运行相应的软件(比如 R2 运行自己编写的路由器,R1 和 R3 运行标准的路由器实现),并配置好网络(比如 IPv6 地址和路由等)。

搭建网络拓扑的具体过程见附录中的拓扑搭建文档

快捷脚本

实验仓库中,在 Setup/ospf 目录下提供了 netns 配置脚本、BIRD 配置文件以及评测脚本,你可以参考里面的内容进行配置。

具体来说,可以按照下列顺序在本地进行评测:

  1. Homework/ospf/r2/ 目录下用 make 命令构建你编写的 OSPF 路由器,确认系统内没有正在运行的 OSPF 路由器(进程名为 router)以及 BIRD 程序(进程名为 bird);
  2. 打开一个命令行窗口,进入 Setup/ospf/setup 目录,执行 sudo ./setup-netns.sh 配置 netns 环境,然后执行 sudo ./start-r2.sh 在 R2 上启动路由器,不要退出;
  3. 再打开一个命令行窗口,进入 Setup/ospf/setup/bird-v2 目录,执行 sudo ./bird-r1-v2.sh 在 R1 上启动 BIRD,不要退出;
  4. 再打开一个命令行窗口,进入 Setup/ospf/setup/bird-v2 目录,执行 sudo ./bird-r3-v2.sh 在 R3 上启动 BIRD,不要退出;
  5. 再打开一个命令行窗口,进入 Setup/ospf/test 目录,依次执行 sudo ./test3-bird-v2.shsudo ./test4.sh 直到 sudo ./test7.sh,每个脚本对应评测中的一项;
  6. 所有项目评测完毕后,可以退出 R1 和 R3 上的 BIRD 和 R2 上的路由器。

在评测过程中,如果发现某一步结果不对,可以使用 tcpdump 或者 Wireshark 来进行抓包。具体地,如果要在某个 netns 中抓包(例如 PC1),需要用如下命令来运行 tcpdump 或者 Wireshark:

sudo ip netns exec PC1 tcpdump [some arguments]
sudo ip netns exec PC1 wireshark

软件配置

你实现的路由器实际上包括两部分功能:IPv6 分组转发以及 OSPF 路由协议。在第二阶段中,自己写的路由器运行在 R2 上,而 R1 和 R3 都需要运行标准的路由器。那么,在 Linux 环境中,为了实现路由器的功能,需要配置下面两个部分:分组转发和路由协议。

分组转发

为了打开 Linux 的转发功能(例如 R1 和 R3),需要用 root 身份运行下面的命令(重启后失效):

# enable forwarding for all interfaces
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding

如果你需要在 netns 中用 Linux 自带的功能做转发,则需要运行如下命令:

# enable forwarding for all interfaces in netns R1
ip netns exec R1 sh -c "echo 1 > /proc/sys/net/ipv6/conf/all/forwarding"

路由协议

为了实现路由协议,需要运行 BIRD。下面提供一个 BIRD(BIRD Internet Routing Daemon,安装方法 apt install bird2)的参考配置,以 Debian 为例,按如下方式修改文件 /etc/bird.conf 即可。

BIRD v2.x 配置

BIRD v2.x 官方配置文档

# log "bird.log" all;  # 可以将 log 输出到文件中
# debug protocols all;  # 如果要更详细的信息,可以打开这个

router id 网口IP地址;  # 随便写一个,保证唯一性即可

protocol device {
}

protocol kernel {
    # 表示 BIRD 会把系统的路由表通过 OSPF 发出去,也会把收到的 OSPF 信息写入系统路由表
    # 你可以用 `ip -6 route` 或 `ip -6 r` 命令查看系统的 IPv6 路由表
    # 退出 BIRD 后从系统中删除路由
    persist off;
    # 从系统学习路由
    learn;
    ipv6 {
        # 导出路由到系统,可以用 `ip -6 r` 看到
        # 也可以用 `export none` 表示不导出,用 `birdc show route` 查看路由
        export all;
    };
}

protocol static {
    ipv6 { };
    route a:b:c:d::/64 via "网口名称";  # 可以手动添加一个静态路由方便调试,只有在这个网口存在并且为 UP 时才生效
}

# BIRD 的 OSPF 协议中会自动引入直连路由,故不需要 protocol direct

protocol ospf v3 {
    ipv6 {
        import all;
        export all;
    };
    debug all;
    area 0 {  # 本实验中只有一个区域 0
        interface "网口名称" {  # 网口名称必须存在,否则 BIRD 会直接退出
            hello 5;  # 5 秒发送一次 OSPF Hello
            type pointopoint;  # 本实验中假设路由器间链路为点对点链路
            link lsa suppression yes;  # 不发送本实验中不需要的 Link LSA
        };
        interface "连接 PC 的网口名称" {
            stub on;  # 将和 PC 直连的网口设置为 stub,不发送 Hello,不洪泛 LSA
            link lsa suppression yes;
        };
    };
}
配置使用

这里的网口名称对应你连接到路由器的网口,需要配置一个固定的 IP 地址,应当和路由器对应网口的 IP 地址在同一个网段内。配置固定 IP 地址的命令格式为 ip a add IP地址/前缀长度 dev 网口名称,你可以用 ip a 命令查看所有网口的信息。

以下以 BIRD v2.x 为例:启动服务(如 systemctl start bird)后,你就可以开始抓包,同时查看 BIRD 输出的信息(journalctl -f -u bird),这对调试你的路由器实现很有帮助。

你也可以直接运行 BIRD(bird -c /etc/bird.conf),可在命令选项中加上 -d 把程序放到前台,方便直接退出进程。若想同时开多个 BIRD,则需要给每个进程指定单独的 PID 文件和 socket,如 bird -d -c bird1.conf -P bird1.pid -s bird1.socket

在安装 BIRD(sudo apt install bird2)之后,它默认是已经启动并且开机自启动。如果要启动 BIRD,运行 sudo systemctl start bird;停止 BIRD:sudo systemctl stop bird;重启 BIRD:sudo systemctl restart bird;打开开机自启动:sudo systemctl enable bird;关闭开机自启动:sudo systemctl disable bird

配合 BIRD 使用的还有它的客户端程序 birdc,它可以连接到 BIRD 服务并且控制 BIRD 的行为。默认情况下 birdc 会连接系统服务(systemctl 启动)的 BIRD,如果启动 BIRD 时采用了 -s 参数,那么 birdc 也要用 -s 指定同样的 socket 路径。

对于一条静态路由(如 route a:b:c:d::/64 via "abcd"),它只有在 abcd 处于 UP 状态时才会生效。如果你只是想让 BIRD 向外宣告这一条路由,可以用 lo(本地环回)代替 abcd 并且运行 ip l set lo up。你可以用 birdc show route 来确认这件事情。


最后更新: 2024年2月22日
作者:Jiajie Chen (5.04%), Haixuan Tong (94.96%)

评论