classRouter { //! The router's collection of network interfaces std::vector<AsyncNetworkInterface> _interfaces{};
std::vector<RouteEntry> _routing_table{};
//! Send a single datagram from the appropriate outbound interface to the next hop, //! as specified by the route with the longest prefix_length that matches the //! datagram's destination address. voidroute_one_datagram(InternetDatagram &dgram);
public: //! Add an interface to the router //! \param[in] interface an already-constructed network interface //! \returns The index of the interface after it has been added to the router size_tadd_interface(AsyncNetworkInterface &&interface){ _interfaces.push_back(std::move(interface)); return _interfaces.size() - 1; }
//! Access an interface by index AsyncNetworkInterface &interface(constsize_t N){ return _interfaces.at(N); }
//! Add a route (a forwarding rule) voidadd_route(constuint32_t route_prefix, constuint8_t prefix_length, const std::optional<Address> next_hop, constsize_t interface_num);
//! Route packets between the interfaces voidroute(); };
具体实现如下:
//! \param[in] route_prefix The "up-to-32-bit" IPv4 address prefix to match the datagram's destination address against //! \param[in] prefix_length For this route to be applicable, how many high-order (most-significant) bits of the route_prefix will need to match the corresponding bits of the datagram's destination address? //! \param[in] next_hop The IP address of the next hop. Will be empty if the network is directly attached to the router (in which case, the next hop address should be the datagram's final destination). //! \param[in] interface_num The index of the interface to send the datagram out on. voidRouter::add_route(constuint32_t route_prefix, constuint8_t prefix_length, const optional<Address> next_hop, constsize_t interface_num){ _routing_table.push_back(RouteEntry( route_prefix, prefix_length, next_hop, interface_num, // 另一种计算方法 // prefix_length == 0 ? 0 : numeric_limits<int>::min() >> (prefix_length - 1) (prefix_length == 0) ? 0 : (0xFFFFFFFF << (32 - prefix_length)) )); }
//! \param[in] dgram The datagram to be routed voidRouter::route_one_datagram(InternetDatagram &dgram){ // check TTL // TTL 为 1 时,数据包在此结束生命周期 if(dgram.header().ttl <= 1) { return; } // 最长前缀匹配 uint32_t dest = dgram.header().dst; int match_idx = -1; int max_match_len = -1; for(size_t i = 0; i < _routing_table.size(); i++) { auto mask = _routing_table[i]._prefix_mask; if((dest & mask) == _routing_table[i]._route_prefix && max_match_len < _routing_table[i]._prefix_length) { match_idx = i; max_match_len = _routing_table[i]._prefix_length; } } if(match_idx == -1) { return; } // 不要忘记给 TTL 减1 dgram.header().ttl -= 1; // send dgram auto next_hop = _routing_table[match_idx]._next_hop; auto interface_num = _routing_table[match_idx]._interface_num; if(next_hop.has_value()) { _interfaces[interface_num].send_datagram(dgram, next_hop.value()); } else { _interfaces[interface_num].send_datagram(dgram, Address::from_ipv4_numeric(dest)); } }