跳转至

第一阶段:编程作业

编程作业

实验的第一阶段是编程作业。在仓库的 Homework 目录下有四个编程作业,每个作业中有评分脚本,通过数据测试你的路由器中核心功能的实现。你需要在被标记 TODO 的函数中补全它的功能,通过测试后,就可以更容易地完成后续的路由器实现。

实验的第一阶段实现了路由器中几个比较独立的子功能,它们容易实现和测试,并且采用了同学们在编程课中比较熟悉的评测模式,还提供了所有的输入和输出。在分别实现和测试以后,就可以比较放心地把这些功能集成到最终的路由器中。

教学目的

锻炼同学对于 RFC 全英文文档的阅读能力,这个能力对于未来的学习和研究是很有必要的,因此在本文档中,不会很细致地用中文把要实现的内容复述一遍,目的是让同学去阅读 RFC 文档进行自学。如果实在不想自学,或者因为时间问题,可以在网上搜索中文博客,但这样做也缺少了一次很重要的锻炼机会。相比论文,RFC 的文字比较详细和朴实,是比较好的英文技术类阅读资料。

例如在研究生阶段,需要阅读很多英文论文,并且尝试编写代码对论文进行复现,这个过程实际上和这里的编程作业是十分类似的:阅读英文,把自然语言转化为代码,再把代码正确地跑起来。

作业内容

四个编程作业需要实现的功能:

  • eui64:用 MAC 地址生成 IPv6 Link Local 地址
  • internet-checksum:计算 Internet 校验和
  • lookup:路由表查询和更新
  • protocol(protocol-ospf):RIPng(OSPF)协议解析和封装,其中 protocol 作业对应的是 RIPng 协议,protocol-ospf 作业对应的是 OSPF 协议,二选一即可,建议和第二、三阶段采用同样的协议

其中 eui64 比较容易,主要是熟悉实验框架和平台的使用。internet-checksum 可能是编程作业里最难的一个,涉及到比较复杂的逻辑,需要仔细思考。lookup 题目可易可难,取决于你实现的方法。protocol/protocol-ospf 也不复杂,需要一定的细心。要编写的代码行数:eui64 < lookup < protocol(protocol-ospf) < internet-checksum。

每个题目都有类似的结构(以 internet-checksum 为例):

  • data:数据所在的目录
  • checksum.h:头文件,记录了函数的输入输出和功能
  • checksum.cpp:你需要修改的地方
  • grade.py:一个简单的评分脚本,它会编译并运行你的代码,进行评测
  • main.cpp:用于评测的交互库,你不需要修改它
  • Makefile:用于编译并链接 HAL、交互库和你实现的代码
  • README.md:题目的要求

首先阅读 README.md 和头文件,理解要如何实现功能。接着,在本地运行下面的命令进行测试(在 Homework/internet-checksum 目录下执行):

pip3 install pyshark # 仅第一次
# 修改 checksum.cpp
make # 编译,得到可以执行的 checksum
./checksum < data/checksum_input1.pcap # 你可以手动运行来看效果
make grade # 也可以运行评分脚本,实际上就是运行 python3 grade.py

上述命令会对每组数据运行你的程序,然后比对输出。如果输出与预期不一致,它会用 diff 工具把你的输出和答案输出的不同显示出来。diff 工具会使用 unified diff 格式输出两个文件的不同,对于只出现在第一个文件,而不出现在第二个文件的行,它会在开头标注减号;反过来,对于只出现在第二个文件,而不出现在第一个文件的行,它会在开头标注加号。在 make grade 中,它用 diff 工具比较的第一个文件是你的程序实际的输出,第二个文件是正确答案,因此减号代表不应该出现的输出,加号表示应该出现但还没有出现的正确输出。

其中部分作业的输入数据的格式是 PCAP,它是一种常见的保存网络流量的格式,它可以用 Wireshark 软件打开来查看它的内容,也可以自己按照这个格式造新的数据。需要注意的是,为了区分一个以太网帧到底来自哪个虚拟的网口,所有的 PCAP 输入都有一个额外的 VLAN 头,VLAN 0-3 分别对应虚拟的 0-3 号网口,虽然实际情况下不应该用 VLAN 0,但简单起见就直接映射了。

macOS 网络相关结构体定义与 Linux 不同

macOS 系统下部分网络相关的结构体实现与 Linux 有区别,可能会导致云端编译错误。为了解决兼容性的问题,macOS 平台使用宏定义实现了与 Linux 通用的写法,请使用通用的写法避免编译错误。 具体体现为: 按照字节访问 MAC 地址 (结构体 ether_addr),请使用 mac->ether_addr_octet,而不是 mac->octet。 按照字节访问 IPv6 地址 (结构体 in6_addr),请使用 ip6->s6_addr,而不是ip6->__u6_addr8、ip6->__u6_addr16、ip6->__u6_addr32

HONOR CODE

在每个作业目录中,都有一个 HONOR-CODE.md 文件,你需要在这个文件中以 Markdown 格式记录你完成这个作业时参考网上的文章或者代码、与同学的交流情况。

HONOR CODE 可以在截止日期之后再提交到仓库中。

评测流程

同学在 TANLabs 上创建好自己的作业仓库后,就可以往自己的仓库提交自己的代码更新。对于每次 git push,GitLab CI 都会进行评测,然后把评测结果推送到 TANLabs 上,然后你就可以在 TANLabs 上看到最新的评测信息。GitLab CI 会进行和本地一样的测试(有兴趣可以查看项目根目录中的 .gitlab-ci.yml),数据也完全一致。你提交的代码会用于判断你掌握的程度和代码查重。一般来说,你只需要修改每个编程作业题的源文件,其他文件不需要编辑。如果你有编辑的需求,为了防止影响评测的结果,请找助教确认。需要注意的是,master 分支是受保护的,你不能进行 Force Push,并且最终成绩的评测也必须是 master 分支上的。

DDL

截止时间是针对 GitLab 上 CI 评测时间来说的,其中评测的时间很短,评测的时间约等于你 Push 提交代码的时间。所以请勿在 DDL 前修改代码而不 Push,只有在 DDL 之前 Push 到 GitLab 的代码的才有效。如果出现了因为 GitLab 自身问题导致超过 DDL 的,请联系助教。

GitLab CI 评测

当你用 Git 把代码提交到 GitLab 上的时候,GitLab 会按照仓库内的 .gitlab-ci.yml 设置的脚本进行编译和评测,它会调用上面提到的本地评测脚本。如果出现了本地评测成功,在线评测失败的情况,请先阅读 FAQ 排查常见问题,排查无果请联系助教。但请不要擅自修改 .gitlab-ci.yml,严禁 攻击 评测系统。

对于同学提交的作业,利用 GitLab CI,在仓库中设置了 .gitlab-ci.yml 文件,评测的流程:

  1. 同学修改代码,通过 GitLab CI 编译和评测
  2. 评测结果保留在 GitLab 的 Artifacts 中
  3. 评测完成时,通过 WebHook 通知 TANLabs,TANLabs 从 GitLab 取回评测结果
  4. 同学在 TANLabs 上浏览评测信息,选择作为最终成绩的评测结果

第一阶段实验是怎么设计出来的?

第一阶段实验包括了四个路由器所要实现的功能,它们比较重要,也比较容易实现错误,因此单独抽出来变成一个给定输入和输出进行代码实现的编程作业,这样可以在保证这部分代码一定的正确性。诚然,这一部分的测试可能检测不出所有可能出现的错误,只能为后面的实验提供一些帮助。为何选取这四个部分作为编程作业,是参考了往年同学在实现路由器阶段遇到的常见问题。


最后更新: 2023年12月24日
作者:Jiajie Chen (97.56%), Wende Tan (1.22%), Haixuan Tong (1.22%)

评论