Rust的eBFP框架Aya(一) - Linux內核網絡基礎

前言

在我的Rust入門及實戰系列文章中已經說明, Rust是一門內存安全的高性能編程語言,從它的這些優秀特性來看,就是一門專為系統開發而誕生的語言。至于很多使用Rust來進行web開發的行為,不能說它們不好,只能說是殺雞焉用牛刀耳。

本系列的文章旨在為大家介紹一個新的專用于開發eBPF程序的Rust框架:Aya。Aya 是 Rust 中的一個 eBPF(Extended Berkeley Packet Filter)庫,提供了用 Rust 語言編寫、加載和運行 eBPF 程序的能力。eBPF 是一種強大的技術,用于在 Linux 內核中安全地運行沙盒程序,常用于網絡編程、性能監控和安全增強。我們在后面的文章中將對eBPF進行更加詳細和深入的介紹。

Linux內核網絡基礎

如果你還不了解什么是eBPF, 那么其實從它的名稱中便可見一斑,從Packet Filter可以看出,這顯然是用于包的處理的一門技術。它通過在Linux的內核中的不同掛載點,加入一個隔離可控的二進制程序,來達到我們想要為內核增加功能處理網絡包的目的。既然是在內核的網絡處理流程中動手腳,那么在開始之前,我們有必要對Linux內核原本的網絡處理流程有基本的認知, 否則,如果直接開始eBPF的編寫,那么我們很可能會變成狗拿刺猬,無從下手。

網絡模型概覽

眾所周知,網絡模型的的劃分有不同的方法, 最流行的莫過于經典的OSI七層網絡模型, TCP/IP四層網絡模型,還有綜合兩者而成的五層網絡模型。從理解內核網絡工作原理的角度出發,我們選擇五層網絡模型進行接下來的探究:
請添加圖片描述

注: 在Linux系統中,內核源碼的位置位于/usr/src/目錄下的對應內核命名的目錄下,例如我使用的azure虛擬機上,內核代碼的目錄為/usr/src/linux-headers-5.15.0-1052-azure。 后文提到的內核代碼相關的目錄都是以此為根的相對路徑。

Linux內核在收到一個網絡數據包后,首先會由網卡驅動程序(相關內核代碼位于drivers/net/ethernet中)先進行處理, 然后回交由內核中處理協議棧相關的代碼進行處理(相關內核代碼位于kernel/net/中),處理完成后的結果,再由socket提供接口,供用戶空間的應用層程序訪問。

網絡中斷處理原理

那么從網卡收到數據包,是怎么傳遞給內核進行處理的呢,這里就要談到中斷處理了。 從硬件的角度來看,當一個網卡收到數據包時, 它會進行以下兩件事情:

  • 將數據包以DMA(Direct Memory Access)的方式, 將收到的數據幀存放到內存的環形緩沖區中(Buffer Ring);
  • 向CPU的引腳施加一個電壓變化,向CPU表明現在有一個數據來了,需要處理。

上述這種通過向CPU引腳施加電壓的硬件操作,被稱為硬中斷。那么CPU此時就會對收到的數據包進行處理,那么如何處理呢?網絡包如果一直不停的到來,而對網絡包的處理往往又是復雜和耗時的,如果CPU每收到一個數據包都對它進行處理完成后再干別的工作,就會導致CPU的占用率過高,而無法對其他的硬中斷進行響應了,比如鼠標鍵盤等設備發起的硬中斷請求。

軟中斷注冊

因此,當CPU收到一個網卡發來的硬中斷時,它會告訴網卡驅動程序: “你先去內存登記一下待辦事項吧”,于是網卡驅動程序會在內存中標記一個變量,表示這里有一個網絡包需要人手來處理了。這個在內存中設置標志的操作,就被稱為軟中斷。

上述過程的圖示如下:
請添加圖片描述

軟中斷處理

內核驅動程序處理

在我們的Linux啟動后,內核中會運行一個進程ksoftirqd, 它的職責就是檢測內存中是否有軟中斷需要處理, 一旦檢測到這是一個網絡驅動注冊的軟中斷,就會調用網卡驅動中的poll函數,從內存的環形緩沖區中將網絡數據包收下來并進行處理, 這個過程的圖示如下:
請添加圖片描述
其中, 網卡驅動程序中的igb_poll()函數會從內存的環形緩沖區中將完整的網絡數據包取出來,然后調用igb_clean_rx_irq()函數進行處理,這些處理包括:

  • 校驗收到的數據格式是否是一個合法的網絡包;
  • 將收到的數據包格式化成skb,解析timestamp, VLAN id, protocol等字段信息
內核協議棧處理

在驅動程序對數據包進行處理后,處理完的數據將被發送到內核的協議棧進行處理,在進入協議棧之前,內核中存在一個GRO引擎,它的作用是把一些小的網絡包合成一個大的網絡包,一次性發給協議棧進行處理,目的是減少傳送給協議棧的包數量,這有助于減少 CPU 的使用量。
請添加圖片描述
如上圖所示,在數據包進入協議棧后:

  • 首先會調用netif_receive_skb()函數,其中會辨別數據包的網絡層協議,根據網絡層協議調用不同的函數;
  • 例如判斷得到這個數據包是個IP包,則會接下來調用ip_rcv()函數,在其中又會判斷它的傳輸層協議,根據其是TCP還是UDP而調用不同的函數;
  • 例如判斷得到這是一個TCP包,那么將繼續調用tcp_rcv()函數對數據進行處理;
  • 處理完成后的數據可以供用戶通過socket訪問;

小結

網絡模塊在Linux內核中及其復雜,上面的介紹以盡可能簡單明了的方式描述了一個數據包從網卡收到它開始,如何被內核進行處理的整個過程。其中包含了CPU硬中斷,ksoftiqrd線程,軟中斷處理,網卡驅動對數據包的處理,skb的創建, 網絡協議棧對數據包的處理等過程。

本文沒有涉及用戶空間應用程序從socket取包的過程,這涉及到recvfrom系統調用,也是一個比較復雜的話題。本系列文章旨在介紹Rust開發eBPF程序,只關注內核對網絡包的處理流程,因此用戶空間取包不在我們的關注范圍內。在了解了網絡包在內核中的處理流程之后,對于后需eBPF程序的掛載點,我們應當會有更清晰的認識。

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

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

相關文章

2017下半年軟工(橋接模式)

題目——橋接模式(抽象調用實現部分) package org.example.橋接模式;/*** 橋接模式的核心思想是將抽象部分與它的實現部分分離,使它們可以獨立變化,就是說你在實現部分:WinImp、LinuxImp基礎上還能加上RedHatImp&#…

03-微服務架構構建之微服務拆分

文章目錄 前言一、微服務拆分的原則二、微服務拆分的時機三、微服務拆分的方法總結 前言 微服務架構是將一個單體應用程序拆分為一個個獨立且保持松耦合的服務的一種架構方式,每個服務有著獨立的數據庫并且能獨立運行部署。微服務架構的構建過程中,第一…

偷竊別人的密碼

在工作中都用到virtual machine吧,同事之間還互相借用機器,或者不借用但憑借自己的域賬號能登錄任意機器,而且每個域賬號都有sudo權限? 那你要小心了! 因為我可以輕易記錄下每個ssh登錄到我機器,或者我在…

uniapp 輸入框輸入時,會將內容頂上去的解決方案

// 設置頁面最小高度 export const setPageMinHeight () > {return {position: relative,min-height: uni.getSystemInfoSync().windowHeight px} }頁面使用: import {setPageMinHeight} from "/utils/uniUtil";data() {return {minHeight: setPag…

Unity 狀態系統

狀態系統 原理食用方法Demo 原理 #mermaid-svg-lUbxJ8eMP3KqrEhY {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-lUbxJ8eMP3KqrEhY .error-icon{fill:#552222;}#mermaid-svg-lUbxJ8eMP3KqrEhY .error-text{fill:#55…

官方officevisio在線安裝包

在線安裝包,在線就是要有網絡環境,你能搜到這篇博客,就初步具備網絡環境 visio在線安裝包.zip官方版下載丨最新版下載丨綠色版下載丨APP下載-123云盤 在線安裝包如下,雙擊執行安裝即可,可供選擇的64/32位 軟件的激活與…

netty使用

支持協議 TCP/UDPHTTP/HTTPSWebSocketSPDY/HTTP2MQTT/CoAP 服務端 常用類 ServerBootstrap 服務端配置類 //設置線程組、parentGroup處理連接、childGroup處理I/O group(EventLoopGroup parentGroup, EventLoopGroup childGroup) //Channel通過何種方式獲取新的連接(NioSe…

【擴散模型】ControlNet從原理到實戰

ControlNet從原理到實戰 ControlNet原理ControlNet應用于大型預訓練擴散模型ControlNet訓練過程ControlNet示例1 ControlNet與Canny Edge2. ControlNet與Depth3. ControlNet與M-LSD Lines4. ControlNet與HED Boundary ControlNet實戰Canny Edge實戰Open Pose 小結參考資料 Cont…

Linux系統上RabbitMQ安裝教程

一、安裝前環境準備 Linux:CentOS 7.9 RabbitMQ Erlang 1、系統內須有C等基本工具 yum install build-essential openssl openssl-devel unixODBC unixODBC-devel make gcc gcc-c kernel-devel m4 ncurses-devel tk tc xz socat2、下載安裝包 1)首先&a…

[linux] kaggle 數據集用linux下載

你可以通過以下步驟獲取Kaggle的下載鏈接并在Linux中進行下載: 首先,確保你已經安裝了Python和Kaggle API。如果沒有安裝,你可以通過以下命令安裝: pip install kaggle 接著,你需要在Kaggle網站上獲取API Token。登錄…

時間相關類

內容 JDK7時間相關類JDK8時間相關類 第一章 Date類 1.1 Date概述 java.util.Date類 表示特定的瞬間,精確到毫秒。 繼續查閱Date類的描述,發現Date擁有多個構造函數,只是部分已經過時,我們重點看以下兩個構造函數 public Dat…

【PyTorch】 暫退法(dropout)

文章目錄 1. 理論介紹2. 實例解析2.1. 實例描述2.2. 代碼實現2.2.1. 主要代碼2.2.2. 完整代碼2.2.3. 輸出結果 1. 理論介紹 線性模型泛化的可靠性是有代價的,因為線性模型沒有考慮到特征之間的交互作用,由此模型靈活性受限。泛化性和靈活性之間的基本權…

Docker構建自定義鏡像

創建一個docker-demo的文件夾,放入需要構建的文件 主要是配置Dockerfile文件 第一種配置方法 # 指定基礎鏡像 FROM ubuntu:16.04 # 配置環境變量,JDK的安裝目錄 ENV JAVA_DIR/usr/local# 拷貝jdk和java項目的包 COPY ./jdk8.tar.gz $JAVA_DIR/ COPY ./docker-demo…

Java基礎50題: 21.實現一個方法printArray, 以數組為參數,循環訪問數組中的每個元素,打印每個元素的值.

概述 實現一個方法printArray, 以數組為參數,循環訪問數組中的每個元素,打印每個元素的值. 代碼 public static void printArray(int[] array) {for (int i 0; i < array.length; i) {System.out.println(array[i] " ");}System.out.println();}public static…

【數據結構c實現】順序表實現

文章目錄 線性表線性表的順序實現結點結構結點初始化增配空間Inc打印順序表show_list線性表長度length尾部插入push_back頭部插入push_front尾部刪除pop_back頭部刪除pop_front按位置插入insert_pos按值查找find按位置刪除delete_pos按值刪除delete_val排序sort(冒泡&#xff1…

云上業務DDoS與CC攻擊防護實踐

案例背景&#xff1a;DDoS攻擊來勢洶洶&#xff0c;云上業務面臨威脅 某網絡科技有限公司&#xff0c;SaaS化創業公司&#xff0c;業務基于云上開展。其業務主要為各大網站提供安全驗證服務&#xff0c;且市場占有率較高&#xff0c;服務客戶遍布金融、直播、教育、電商等多個領…

【日常總結】mybatis-plus WHERE BINARY 中文查不出來

目錄 一、場景 二、問題 三、原因 四、解決方案 五、拓展&#xff08;全表全字段修改字符集一鍵更改&#xff09; 準備工作&#xff1a;做好整個庫備份 1. 全表一鍵修改 Stage 1&#xff1a;運行如下查詢 Stage 2&#xff1a;復制sql語句 Stage 3&#xff1a;執行即可…

100. 相同的樹(Java)

目錄 解法&#xff1a; 官方解法&#xff1a; 方法一&#xff1a;深度優先搜索 復雜度分析 時間復雜度&#xff1a; 空間復雜度&#xff1a; 方法二&#xff1a;廣度優先搜索 復雜度分析 時間復雜度&#xff1a; 空間復雜度&#xff1a; 給你兩棵二叉樹的根節點 p 和…

L1-028:判斷素數

題目描述 本題的目標很簡單&#xff0c;就是判斷一個給定的正整數是否素數。 輸入格式&#xff1a; 輸入在第一行給出一個正整數N&#xff08;≤ 10&#xff09;&#xff0c;隨后N行&#xff0c;每行給出一個小于231的需要判斷的正整數。 輸出格式&#xff1a; 對每個需要判斷的…

Kotlin(十五) 高階函數詳解

高階函數的定義 高階函數和Lambda的關系是密不可分的。在之前的文章中&#xff0c;我們熟悉了Lambda編程的基礎知識&#xff0c;并且掌握了一些與集合相關的函數式API的用法&#xff0c;如map、filter函數等。另外&#xff0c;我們也了解了Kotlin的標準函數&#xff0c;如run、…