CS144 Lab 6 實戰記錄:構建 IP 路由器

1 實驗背景與目標

在 CS144 的 Lab 6 中,我們需要在之前實現的 NetworkInterface(Lab 5)基礎上構建一個完整的 IP 路由器。路由器的主要任務是根據路由表將接收到的 IP 數據報轉發到正確的網絡接口,并發送給正確的下一跳(next hop)。

一個路由器擁有多個網絡接口,可以在任何一個接口上接收 Internet 數據報。路由器的主要職責是根據路由表確定兩件事:

  • 應該使用哪個出站接口(interface)發送數據報
  • 數據報的下一跳(next hop)IP 地址是什么

與前幾個實驗不同,IP 路由器的實現不需要了解 TCP、ARP 或以太網的細節,只需專注于 IP 層的轉發邏輯。

2 路由器工作原理

2.1 路由器功能概述

IP 路由器主要完成兩個關鍵功能:

  1. 維護路由表:存儲一系列路由規則,每條規則包含網絡前綴、前綴長度、下一跳信息和出站接口編號
  2. 轉發數據報:根據路由表中的規則,將每個接收到的數據報轉發到正確的出站接口和下一跳地址
路由表查詢
(最長前綴匹配)
Internet數據報
路由器
轉發決策
網絡接口1
網絡接口2
網絡接口n
下一跳1
下一跳2
下一跳n

2.2 最長前綴匹配原則

路由器使用最長前綴匹配(Longest Prefix Match)算法來選擇最佳路由。這意味著當多個路由規則匹配一個目標 IP 地址時,路由器會選擇前綴長度最長的那個規則。這樣可以實現更精確的路由控制。例如,對于目標 IP 地址 172.16.10.3,可能匹配的規則有 172.16.0.0/16172.16.10.0/24,路由器會選擇前綴長度為 24 的規則,因為它提供了更精確的匹配。

接收數據報
檢查目標IP地址
在路由表中查找匹配項
有多個匹配項?
選擇前綴長度最長的匹配項
有一個匹配項?
使用該匹配項
丟棄數據報
確定出站接口和下一跳
TTL減1
TTL大于0?
通過選定接口發送到下一跳
丟棄數據報

3 路由器實現

3.1 數據結構設計

將路由表按前綴長度(1-32)分成32個組,方便從長到短進行最長前綴匹配。每個前綴長度組內使用哈希表存儲,表示匹配前綴與路由項的映射關系。

struct RouteEntry {size_t interface_num {};      // 出站接口編號std::optional<Address> next_hop {}; // 下一跳地址(如果有)
};// 路由表,按前綴長度分組(最多32個組,對應IPv4地址的32位,逆序表示。例如下標為0代表前綴長度32)
std::array<std::unordered_map<uint32_t, RouteEntry>, 32> routing_table_ {};

3.2 添加路由條目

add_route方法向路由表添加一條新的路由規則,具體處理邏輯:

  1. 前綴計算:使用右移操作獲取有效前綴位,例如:對于 192.168.1.0/24,右移 (32-24) = 8 位,保留高 24 位作為匹配前綴。需要特別處理前綴長度為 0 的默認路由,避免右移 32 位導致的未定義行為
  2. 路由條目存儲:將路由條目存入對應前綴長度的哈希表中,鍵是處理后的前綴,值是路由條目信息
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";// 截取route_prefix的前prefix_length位作為有效前綴uint32_t masked_prefix = (prefix_length == 0) ? 0 : (route_prefix >> (32 - prefix_length));// 插入到對應前綴長度的路由表中routing_table_[prefix_length][masked_prefix] = { interface_num, next_hop };
}

3.3 路由匹配查找

match 方法實現最長前綴匹配算法,為每個數據報找到最佳路由:

flowchart TDA[開始匹配] --> B[從前綴長度31開始]B --> C[計算目標IP地址的前len位]C --> D{前綴長度組中\n有匹配項?}D -->|是| E[返回匹配的路由條目]D -->|否| F[前綴長度減1]F --> G{前綴長度≥0?}G -->|是| CG -->|否| H[返回無匹配]
optional<Router::RouteEntry> Router::match(uint32_t dst_addr) const noexcept {for (int len = 31; len >= 0; --len) {uint32_t masked = (len == 0) ? 0 : (dst_addr >> (32 - len));const auto& table = routing_table_[len];auto it = table.find(masked);if (it != table.end()) {return it->second;}}return nullopt;
}

3.4 數據報轉發處理

route 方法是路由器的核心功能,負責處理所有接口收到的數據報并進行轉發。

網絡接口 路由器 最長前綴匹配 轉發邏輯 遍歷所有接口 獲取接收到的數據報隊列 檢查TTL值 丟棄數據報 TTL減1并重新計算校驗和 查找最長前綴匹配路由 返回匹配的路由條目 確定目標地址和出站接口 通過對應接口發送數據報 丟棄數據報 alt [有匹配路由] [無匹配路由] alt [TTL ≤ 1] [TTL > 1] loop [對每個數據報] 網絡接口 路由器 最長前綴匹配 轉發邏輯
void Router::route() {for (const auto& interface : interfaces_) {auto& datagrams_received = interface->datagrams_received();// 處理所有收到的數據報while (!datagrams_received.empty()) {InternetDatagram datagram = move(datagrams_received.front());datagrams_received.pop();// TTL ≤ 1表示不能再轉發,直接丟棄if (datagram.header.ttl <= 1) {continue;}// TTL減1并重新計算校驗和datagram.header.ttl -= 1;datagram.header.compute_checksum();// 使用最長前綴匹配查找路由條目auto routeEntry = match(datagram.header.dst);if (!routeEntry.has_value()) {continue;}// 如果沒有指定下一跳,則直接發送到目標IPAddress target = routeEntry->next_hop.value_or(Address::from_ipv4_numeric(datagram.header.dst));// 通過對應接口發送數據報interfaces_[routeEntry->interface_num]->send_datagram(datagram, target);}}
}

4 調試記錄

  1. 最初在計算掩碼后的前綴時,使用了按位與操作,但這種方法對于可變長度前綴處理起來比較復雜。改用右移操作后,處理變得更簡單高效。

  2. 最初的實現中,先執行路由匹配再檢查TTL,這導致一些應該被丟棄的數據報被錯誤處理。修正為先檢查TTL再進行后續處理。

  3. 處理前綴長度為0的默認路由時需要特殊處理,確保將掩碼設置為0而不是嘗試右移32位(這會導致未定義行為)。

    image-20250424213846855

5 代碼倉庫

項目代碼已上傳至GitHub:https://github.com/HeZephyr/minnow

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/902785.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/902785.shtml
英文地址,請注明出處:http://en.pswp.cn/news/902785.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【網絡安全】社會工程學策略

1. 社會工程學簡介 社會工程攻擊是威脅行為者常用的攻擊方式。這是因為&#xff0c;誘騙人們提供訪問權限、信息或金錢通常比利用軟件或網絡漏洞更容易。 您可能還記得&#xff0c;社會工程學是一種利用人為錯誤來獲取私人信息、訪問權限或貴重物品的操縱技術。它是一個涵蓋性…

【含文檔+PPT+源碼】基于SpringBoot的開放實驗管理平臺設計與實現

項目介紹 本課程演示的是一款基于SpringBoot的開放實驗管理平臺設計與實現&#xff0c;主要針對計算機相關專業的正在做畢設的學生與需要項目實戰練習的 Java 學習者。 1.包含&#xff1a;項目源碼、項目文檔、數據庫腳本、軟件工具等所有資料 2.帶你從零開始部署運行本套系統…

鴻蒙NEXT開發定位工具類 (WGS-84坐標系)(ArkTs)

import geoLocationManager from ohos.geoLocationManager; import { BusinessError, Callback } from ohos.base; import { LogUtil } from ./LogUtil; import { PermissionUtil } from ./PermissionUtil; import { map, mapCommon } from kit.MapKit; /*** 定位工具類 (WGS-8…

SSM從入門到上手-全面講解SSM框架的使用.

一、SSM框架整合 將Spring、Spring MVC和MyBatis結合在一起&#xff0c;形成一個高效且易于維護的Web應用程序架構。具體整合的方式如下&#xff1a; Spring管理Bean&#xff1a;Spring負責管理所有的Java對象&#xff0c;包括Service層、DAO層等。通過Spring的IoC容器進行依賴…

學員答題pk知識競賽小程序怎么做

制作學員答題PK知識競賽小程序&#xff0c;主要有以下步驟&#xff1a; 一、規劃設計 明確需求&#xff1a;確定小程序的使用場景是校園知識競賽、培訓機構考核還是企業內部培訓等。答題功能&#xff0c;規定答題的具體規則&#xff0c;包括題目類型&#xff08;單選、多選、…

視頻分析設備平臺EasyCVR視頻技術驅動下,監控上墻全組件解析與組網應用方案

隨著數字化進程的加速推進&#xff0c;視頻監控技術在工業、商業、社區等諸多領域得到了廣泛應用。盡管不同場景對監控功能的具體需求存在差異&#xff0c;但底層硬件架構具有顯著的共性特征。實際部署中&#xff0c;僅需依據網絡環境等實際情況&#xff0c;靈活調整設備的連接…

idea使用docker插件一鍵部署項目

一、首先保證我們電腦上已經安裝了docker docker -v查看docker版本&#xff0c;如果不能識別&#xff0c;需要先下載docker destop&#xff0c;在官網下載正常安裝即可。 安裝成功就可以使用docker 命令了 二、idea下載docker插件并配置docker參數 我是通過tcp連接docker服務…

SQL Tuning Advisor

什么是SQL Tuning Advisor STA可以用來優化那些已經被發現的高負載SQL. 默認情況下, Oracle數據庫在自動維護窗口中自動認證那些有問題的SQL并且執行優化建議&#xff0c;找尋提升高負載SQL執行計劃性能的方法. ** 如何查看自動優化維護窗口產生的報告? ** SQL> set ser…

uniapp-商城-31-shop頁面中的 我的訂單

前面的章節講了很多關于頁面 布局 的知識。 現在來看看其他欄目&#xff0c;我的訂單頁面。 1 頁面樣式圖 基本的樣式包含shop頁面 我的訂單 點擊我的訂單&#xff0c;跳轉到訂單頁面 點擊訂單的每一條訂單&#xff0c;跳轉到訂單詳情 2、創建訂單頁面 2.1 創建sub頁面文件…

深入探討JavaScript性能瓶頸與優化實戰指南

JavaScript作為現代Web開發的核心語言,其性能直接影響用戶體驗與業務指標。隨著2025年前端應用的復雜性持續增加,性能優化已成為開發者必須掌握的核心技能。本文將從性能瓶頸分析、優化策略、工具使用三個維度,結合實戰案例,系統梳理JavaScript性能優化的關鍵路徑。 一、Ja…

基于AI與drawio的圖表生成技術及其在學術研究中的應用前景分析

一、研究背景與沖突 在當今數字化時代&#xff0c;學術研究與信息傳播的方式發生了深刻變革。隨著數據量的爆炸式增長以及研究內容的日益復雜&#xff0c;高效、精準地呈現研究成果變得至關重要。圖表作為一種直觀、簡潔且信息承載量大的表達方式&#xff0c;在學術研究中扮演著…

uniapp 仿小紅書輪播圖效果

通過對小紅書的輪播圖分析&#xff0c;可得出以下總結&#xff1a; 1.單張圖片時容器根據圖片像素定高 2.多圖時輪播圖容器高度以首圖為錨點 3.比首圖長則固高左右留白 4.比首圖短則固寬上下留白 代碼如下&#xff1a; <template><view> <!--輪播--><s…

【ORACLE】記錄一些ORACLE的merge into語句的BUG

【ORACLE】記錄一些ORACLE的merge into語句的BUG 一、自相矛盾-DML重啟動行為差異,違反acid原則 發現版本&#xff1a;10g ~ 23ai 這個用例在我之前的文章里有提過&#xff0c;ORACLE和PG系關于并發事務行為有一個非常大的差異&#xff0c;就是ORACLE在某些并發沖突的場景下會…

2025上海車展:光峰科技全球首發“靈境”智能車載光學系統

當AI為光賦予思想&#xff0c;汽車將會變成什么樣&#xff1f;深圳光峰科技為您揭曉答案。 2025年4月23日&#xff0c;在剛剛開幕的“2025上海車展”上&#xff0c;全球領先的激光核心器件公司光峰科技舉辦了主題為“AI光影盛宴&#xff0c;智享未來出行”的媒體發布會&#x…

密碼學的hash函數,哈希碰撞, collision resistance, BTC用到的SHA-256簡介

密碼學中的哈希函數、哈希碰撞、抗碰撞性&#xff08;collision resistance&#xff09;以及比特幣中使用的 SHA-256 的簡明介紹&#xff1a; &#x1f9e9; 一、哈希函數&#xff08;Hash Function&#xff09; 定義&#xff1a; 哈希函數是一種將任意長度的輸入&#xff08;…

unity TEngine學習4

上一篇我們學習了UI部分&#xff0c;這一篇我們學習其他部分&#xff0c;按照老規矩還是先打開官方文檔 ResourceModule 在官方文檔里介紹了當前加載的設置&#xff0c;但是我們是小白看不懂&#xff0c;那就不管他內部怎么實現的&#xff0c;我們主要看下面的代碼給的方法&am…

【AI訓練環境搭建】在IDE(Pycharm或VSCode)上使用WSL2+Ubuntu22.04+Conda+Tensorflow+GPU進行機器學習訓練

本次實踐將在IDE&#xff08;Pycharm或VSCode&#xff09;上使用WSL2Ubuntu22.04TensorflowGPU進行機器學習訓練。基本原理是在IDE中拉起WSL2中的Python解釋器&#xff0c;并運行Python程序。要運行CondaTensorflowGPU你可能需要進行以下準備工作。 1. 此示例中將使用一個mnis…

【華為OD機試真題E卷】521、 機器人可活動的最大網格點數目 | 機試真題+思路參考+代碼解析(E卷復用)(C++)

文章目錄 一、題目題目描述輸入輸出樣例1 一、代碼與思路&#x1f9e0;C語言思路?C代碼 一、題目 參考鏈接&#xff1a;https://sars2025.blog.csdn.net/article/details/141748083 題目描述 現有一個機器人口&#xff0c;可放置于MxN的網格中任意位置&#xff0c;每個網格包…

windows端遠程控制ubuntu運行腳本程序并轉發ubuntu端腳本輸出的網頁

背景 對于一些只能在ubuntu上運行的腳本&#xff0c;并且這個腳本會在ubuntu上通過網頁展示運行結果。我們希望可以使用windows遠程操控ubuntu&#xff0c;在windows上查看網頁內容。 方法 start cmd.exe /k "sshpass -p passwd ssh namexxx.xxx.xxx.xxx "cd /hom…

Vue3集成瀏覽器API實時語音識別

效果示例 用法 <!-- 瀏覽器語音識別 --> <BrowserSpeechRecognitionModal v-if"showModal" :isOpen"showModal" close"showModal false" confirm"handleRecognitionResult" />const showModal ref(false); const input…