CS144--Lab6笔记

CS144——Lab6笔记

Getting started

首先是版本控制操作,从lab5分支创建用于lab6开发的分支,我是在Clion的Git图形操作界面设定的。然后按照文档,从远程仓库拉取lab6的实验内容

//在新分支dev-lab6下
git fetch
git merge origin/lab6-startercode
make -j4

会弹出一个询问界面,让你提交此次合并到你本地仓库分支的说明commit,可以不管,直接ctrl+X键。

简易路由实现

本次实验是让你实现一个简易路由,其功能是对于接收到的任何数据包:

  1. 确认发送接口
  2. 下一跳的IP地址

无需处理任何复杂的路由协议,例如:RIP,OSPF,BGP······记住,此次代码不依赖Lab0~4的TCP栈,不要去修改webget.cc的内容,整个代码量推荐 25~30行
下图就是lab6的抽象:
在这里插入图片描述

实现

根据 router.hh 中已经给出的代码和注释可知,只需要在Router类中再添加一个成员变量routetable用来记录路由,每一个路由都有路由前缀、前缀长度、下一跳IP地址、网络接口等数据构成,所以需要单独构造一个数据类型来表示:

    //! 路有条目
    struct RouteEntry{
        uint32_t route_prefix;
        uint8_t prefix_length;
        std::optional<Address> next_hop;
        size_t interface_num;
        RouteEntry() = default;
        RouteEntry(const uint32_t _route_prefix, const uint8_t _prefix_length,\
                   const std::optional<Address> &_next_hop, const size_t _interface_num)\
        :
            route_prefix(_route_prefix),
            prefix_length(_prefix_length),
            next_hop(_next_hop),
            interface_num(_interface_num)
        {}
    };

然后添加一个成员变量,_route_table:

    //! 路有表
    std::vector<RouteEntry> _route_table{};

文档指明,对于每一个数据报,路由的时间复杂度为 O(N) 是可以接受的。

注意: 在转发数据报时候,如果路由直接连接当前网络,下一跳将是一个空的可选项,即下一跳就是数据报的目的地址,如果路由器是通过其他路由器连接到当前网络,则下一跳将包含沿路径的下一个路由器的IP地址

** 路由仅需要知道IP地址和路由表,通过 ==最长前缀匹配匹配(longest-prefix match)来决定下一跳的 NetworkInterface**
源代码:

void Router::add_route(const uint32_t route_prefix,
                       const uint8_t prefix_length,
                       const optional<Address> next_hop,
                       const size_t interface_num) {
    cerr << "DEBUG: adding route " << Address::from_ipv4_numeric(route_prefix).ip() << "/" << int(prefix_length)
         << " => " << (next_hop.has_value() ? next_hop->ip() : "(direct)") << " on interface " << interface_num << "\n";

//    DUMMY_CODE(route_prefix, prefix_length, next_hop, interface_num);
    // Your code here.
    //在路有表末尾构造新的列表项
    _route_table.emplace_back(route_prefix,prefix_length,next_hop,interface_num);
}

//! \param[in] dgram The datagram to be routed
void Router::route_one_datagram(InternetDatagram &dgram) {
//    DUMMY_CODE(dgram);
    // Your code here.
    //进行最长前缀匹配
    //先得到IP字段
    uint32_t ip = dgram.header().dst;
    auto max_match_iter = _route_table.end();
    for(auto route_iter = _route_table.begin(); \
         route_iter != _route_table.end(); route_iter =std::next(route_iter)){
        //如果前缀匹配相同,或者前缀匹配长度为0
        //! NOTE: 根据CSAPP,32位整数,右移量只取最低5位,即 mod 32,因此直接右移32位
        //! 等价右移0位,需要特殊判断
        if(route_iter->prefix_length == 0 || (route_iter->route_prefix ^ ip) >> \
                                                  (32 - route_iter->prefix_length) == 0){
            //成立则需要更新最佳匹配
            if(max_match_iter == _route_table.end() || \
                route_iter->prefix_length > max_match_iter->prefix_length){
                max_match_iter = route_iter;
            }
        }
    }
    //匹配了路有规则还需要看TTL>1
    if(max_match_iter != _route_table.end() && dgram.header().ttl > 1){
        --dgram.header().ttl;
        AsyncNetworkInterface &next_interface = interface(max_match_iter->interface_num);
        //如果路由器直接连接的相关网络,下一跳为目的地IP地址,否则为下一跳路有的IP地址
        if(max_match_iter->next_hop.has_value()){
            next_interface.send_datagram(dgram,max_match_iter->next_hop.value());
        }
        else{
            next_interface.send_datagram(dgram,Address::from_ipv4_numeric(ip));
        }
    }
    //对于TTL为1和0,直接丢弃,在本实验中不做ICMP回复
}

注意: 在CSAPP中,32位整数,右移32位等价于右移0位
然后可以进行测试了,打开terminal,进入build目录:

make -j4
make check_lab6

测试结果:
在这里插入图片描述

也可以直接做另外的测试,同样是在build目录下执行:

sudo ./apps/network_simulator

结果如下:
在这里插入图片描述
这就是一个非常简易的路由实现呀~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值