CS144-lab5

发布时间 2023-10-11 23:09:57作者: cerwang

Checkpoint 5 Writeup

该lab较简单,没什么好说的
有两点是route函数for循环时必须用引用,还是ttl递减后要重新计算checksum,写的时候被坑到了。
至于找到最长前缀匹配,遍历路由表即可,注意prefix为0时要特判;为了方便判断是否在路由表中找到符合项,max_prefix设置为int8_t。

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() << "/"
       << static_cast<int>( prefix_length ) << " => " << ( next_hop.has_value() ? next_hop->ip() : "(direct)" )
       << " on interface " << interface_num << "\n";

  (void)route_prefix;
  (void)prefix_length;
  (void)next_hop;
  (void)interface_num;

  if ( next_hop.has_value() ) {
    router_table.push_back( { route_prefix, prefix_length, next_hop.value().ipv4_numeric(), interface_num } );
  } else {
    router_table.push_back( { route_prefix, prefix_length, std::nullopt, interface_num } );
  }
}

void Router::route()
{
  // !!! &
  for ( auto& inter : interfaces_ ) {
    std::optional<InternetDatagram> maybe_dgram = inter.maybe_receive();
    if ( maybe_dgram.has_value() ) {
      InternetDatagram dgram = maybe_dgram.value();
      if ( dgram.header.ttl <= 1 ) {
        continue;
      }
      dgram.header.ttl--;
      // !!!!
      dgram.header.compute_checksum();
      uint32_t dst_ip = dgram.header.dst;
      int8_t max_prefix = -1;
      size_t max_prefix_index = 0;
      for ( size_t i = 0; i < router_table.size(); i++ ) {
          if ( !router_table[i].prefix_length || (( dst_ip >> ( 32 - router_table[i].prefix_length ) )
               == ( router_table[i].route_prefix >> ( 32 - router_table[i].prefix_length ) )) ) {
            if(router_table[i].prefix_length > max_prefix)
            {
              max_prefix = router_table[i].prefix_length;
              max_prefix_index = i;
            }
        }
      }
      if(max_prefix == -1)
        continue;
      interfaces_[router_table[max_prefix_index].interface_num].send_datagram(
        dgram, Address::from_ipv4_numeric( router_table[max_prefix_index].next_hop.value_or( dst_ip ) ) );
    }
  }