TECHNOLOGY LINUX KERNEL

【第16回】元東大教員から学ぶLinuxカーネル「ソケット通信(TCP/UDP/IP)」

2022年10月19日

本記事の信頼性

  • リアルタイムシステムの研究歴12年.
  • 東大教員の時に,英語でOS(Linuxカーネル)の授業.
  • 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校(UNC)コンピュータサイエンス学部で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発.
  • プログラミング歴15年以上,習得している言語: C/C++PythonSolidity/Vyper,Java,Ruby,Go,Rust,D,HTML/CSS/JS/PHP,MATLAB,Assembler (x64,ARM).
  • 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」GitHubにオープンソースとして公開
  • 2020年1月~現在はアメリカのノースカロライナ州チャペルヒルにあるGuarantee Happiness LLCのCTOとしてECサイト開発やWeb/SNSマーケティングの業務.2022年6月~現在はアメリカのノースカロライナ州チャペルヒルにあるJapanese Tar Heel, Inc.のCEO兼CTO.
  • 最近は自然言語処理AIイーサリアムに関する有益な情報発信に従事.
    • (AI全般を含む)自然言語処理AIの論文の日本語訳や,AIチャットボット(ChatGPT,Auto-GPT,Gemini(旧Bard)など)の記事を50本以上執筆.アメリカのサンフランシスコ(広義のシリコンバレー)の会社でプロンプトエンジニア・マネージャー・Quality Assurance(QA)の業務委託の経験あり.
    • (スマートコントラクトのプログラミングを含む)イーサリアムや仮想通貨全般の記事を200本以上執筆.イギリスのロンドンの会社で仮想通貨の英語の記事を日本語に翻訳する業務委託の経験あり.

こういった私から学べます.

前回を読んでいない方はこちらからどうぞ.

Linuxカーネルの記事一覧はこちらからどうぞ.

LinuxカーネルはC言語で書かれています.

私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.

私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!

友だち追加

独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!

今回のテーマはソケット通信(TCP/UDP/IP)です.

本記事では,以下を習得できます.

  • Linuxカーネルのネットワークアーキテクチャ
  • パケットフィルタやファイアウォールを用いたIPパケット管理の実践的な技術
  • カーネル空間でのソケットの使用方法
  • TCPアクセラレーション(TCP高速化機能)
  • UDPアクセラレーション(UDP高速化機能)

本記事は,以下のユーザ空間でソケット通信によるネットワークプログラミングを理解していることを前提とします.

ソケット通信

インターネットの発展により,ネットワークアプリケーションは飛躍的に増加しています.

結果として,OSのネットワークサブシステムに求められる速度や生産性も向上しています.

ネットワーキングサブシステムは,OSカーネルの必須コンポーネントではありません(Linuxカーネルはネットワーキングのコンフィグなしでコンパイルできます).

しかし,クラウドやIoTの普及に伴い,コンピュータシステム(あるいは組込みシステム)における接続性の必要性から,ネットワークに対応しているOSの搭載はほぼ必須です.

最近のOSは,TCP/IPスタックを使用しています.

そのカーネルはトランスポート層までのプロトコルを実装し,アプリケーション層のプロトコルは通常ユーザ空間で実装されます(HTTP,FTP,SSH等).

ユーザ空間では,ネットワーク通信を抽象化したものがソケットです.

ソケットは通信チャネルを抽象化したもので,カーネルベースのTCP/IPスタックのインタラクションインタフェースです.

IPソケットは,IPアドレス,使用するトランスポート層プロトコル(TCP,UDP等),ポートに関連付けられます.

ソケットを使用する一般的な関数呼び出しは,作成(socket関数),初期化(bind関数),接続(connect関数),接続待ち(listen/accept関数),ソケットの終了(close関数)です.

ネットワーク通信は,TCPソケットの場合はread/write関数またはrecv/send関数,UDPソケットの場合はrecvfrom/sendto関数の呼び出しで実現されます.

送受信の操作はアプリケーションに対して透過的であり,カプセル化やネットワーク上での送信はカーネルの判断に委ねられます.

ただし,rawソケットを用いたユーザ空間でのTCP/IPスタックの実装(ソケット作成時のPF_PACKETオプション)や,カーネルでのアプリケーション層プロトコルの実装(TUX Webサーバ)は可能です.

ソケットを使ったユーザ空間プログラミングの詳細については,「Beej's Guide to Network Programming Using Internet Sockets」を参照してください.

Linuxカーネルのソケット通信

Linuxカーネルは,ネットワークパケットを扱うための3つの基本構造体,struct socket,struct sock,struct sk_buffを提供します.

struct socket構造体とstruct sock構造体は,ソケットを抽象化したものです.

struct socket構造体はユーザ空間に近い抽象化であり,例えばBSDのソケットはネットワークアプリケーションのプログラミングに使用されます.

struct sock構造体(Linux用語ではINET socket)は,ソケットをネットワークで表現したものです.

これらの2つの構造体は関連しており,struct socket構造体はINETソケットフィールドを持ち,struct sock構造体はそれを保持するBSDソケットを持っています.

struct sk_buff構造体は,ネットワークパケットとそのステータスを表現するもので,ユーザ空間またはネットワークインタフェースからカーネルパケットを受信したときに作成されます.

ソケット通信を管理する構造体

ソケット通信を管理する構造体を紹介します.

socket構造体

linux/include/linux/net.hにあるsocket構造体は一般的なBSDソケットのことです.

重要なメンバ変数は以下になります.

  • ops:プロトコル固有のソケット操作
  • sk:内部ネットワークプロトコルに依存しないソケット表現

proto_ops構造体

linux/include/linux/net.hにあるproto_ops構造体では,特定のプロトコルを実装するための関数ポインタを管理します.

具体的には,ソケット構造体を介して汎用関数から呼び出される(sock_release,sock_sendmsg等)の関数ポインタです.

sock構造体

linux/include/net/sock.hのsock構造体は,ソケットのネットワーク層(INETソケット)を表現します.

sock構造体は,ユーザ空間のソケットと暗黙のうちにsocket 構造体と関連付けられます.

sock構造体は,接続の状態に関する情報を格納するために使用されます.

構造体のメンバ変数と関連する操作は,通常,sk_という文字列で始まります.

sock構造体の重要なメンバ変数は以下になります.

  • sk_protocol:ソケットが使用するプロトコルのタイプ
  • sk_type:ソケットのタイプ(SOCK_STREAM,SOCK_DGRAM等)
  • sk_socket:socket構造体を保持するBSDソケット
  • sk_send_head:送信用のsk_buff構造体のリスト

※末尾の関数ポインタは,様々な状況に対応するためのコールバックです.

INETソケットを作成するinet_create関数でsock構造体を利用しています.

sk_buff構造体

linux/include/linux/skbuff.hのsk_buff構造体は,ソケットのバッファ(ネットワークパケット)を管理する構造体です.

構造体のメンバ変数には,ヘッダとパケットの内容,使用されたプロトコル,使用されたネットワークデバイス,他の構造体 sk_buffへのポインタに関する情報が含まれます.

重要なメンバ変数は以下になります.

  • next,prev:バッファリスト中の次と前の要素へのポインタ
  • dev:バッファを送信または受信するデバイス
  • sk:バッファに関連付けられたソケット
  • destructor:バッファの割り当てを解除するコールバック
  • transport_header,network_header,mac_header:パケットの先頭とパケット内の様々なヘッダの先頭の間のオフセットである.これらは,パケットが通過する様々な処理層によって内部的に維持されています.ヘッダへのポインタを得るには,tcp_hdr/udp_hdr/ip_hdr等の関数のいずれかを使用します.原則として,各プロトコルは受信したパケット内のそのプロトコルのヘッダへの参照を取得する関数を提供します.network_headerメンバ変数はパケットがネットワーク層に到達するまで設定されず,transport_headerメンバ変数はパケットがトランスポート層に到達するまで設定されないことに注意してください.

tcphdr/udphdr/iphdr構造体

linux/include/uapi/linux/tcp.hのtcphdr構造体はTCPヘッダを管理します.

tcphdr構造体の主なメンバ変数は以下になります.

  • source:送信元ポート
  • dest:宛先ポート
  • ack,syn,fin:使用するTCPフラグ

linux/include/uapi/linux/udp.hのudphdr構造体はUDPヘッダを管理します.

udphdr構造体の主なメンバ変数は以下になります.

  • source:送信元ポート
  • dest:宛先ポート

linux/include/uapi/linux/ip.hのiphdr構造体はIPヘッダを管理します.

iphdr構造体の主なメンバ変数は以下になります.

  • protocol:使用されるトランスポート層プロトコル
  • saddr:送信元IPアドレス
  • daddr:宛先IPアドレス

ソケットの作成

ソケットの作成は,ユーザ空間でsocket関数を呼び出すのと似ていますが,作成されたstruct socket構造体はresパラメータに格納されます.

linux/include/linux/net.hに以下のソケットの作成関数があります.

これらの呼び出しのパラメータは以下の通りです.

  • net:もし存在する場合,使用するネットワーク名前空間への参照として使用され,通常init_netで初期化する.
  • family:情報転送に使用するプロトコルファミリーを表す.通常,PF_(Protocol Family)という文字列で始まる.使用するプロトコルファミリーを表す定数はlinux/include/linux/socket.hにあり,TCP/IPプロトコルではPF_INETが最もよく使用される.
  • type:ソケットのタイプを表し,このパラメータに使用される定数(enum sock_type列挙型)はlinux/include/linux/net.hにある.最もよく使われるのは,コネクションベースの送信元と送信先間通信のためのSOCK_STREAM とコネクションレス型通信のためのSOCK_DGRAMである.
  • proto:使用するプロトコルを表し,typeパラメータと密接な関係がある.このパラメータに使用される定数(enum列挙型)はlinux/include/uapi/linux/in.hにあり,最も使用されるのはTCPのIPPROTO_TCPとUDPのIPPROTO_UDPである.

socketシステムコールはlinux/net/socket.cにあるsys_socket関数(28行目の「SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)」)を呼び出します.

sys_socket関数は,__sys_socket関数(1行目)を呼び出します.

__sys_socket関数では,21行目でsock_create関数を呼び出していることがわかります.

ソケットの終了

ソケットを終了する場合(コネクションを使用するソケットの場合),および関連リソースを解放する場合は,以下のlinux/net/socket.cのsock_release関数(34行目)を呼び出します.

sock_release関数は__sock_release関数(1行目)を呼び出します.

__sock_release関数は,ソケット構造体のopsメンバ変数にあるrelease関数ポインタを呼び出します.

ソケット通信によるメッセージの送受信

ソケット通信によるメッセージの送受信は以下の関数で行います.

メッセージの送受信関数は,ソケットのopsメンバ変数にあるsendmsg/recvmsg関数を呼び出します.

kernel_をプレフィックスに持つ関数は,ソケットがカーネルで使用される場合に使用されます.

  • msg:msghdr構造体であり,送受信するメッセージを格納しています.msghdr構造体の重要な構成要素はmsg_nameとmsg_namelenで,UDPソケットの場合はメッセージの送信先アドレス(sockaddr_in構造体)を記入する必要があります.
  • vec:そのデータとサイズを含むバッファへのポインタを含むstruct kvec構造体です.iovec構造体と同様の構造を持っています(iovec構造体はユーザ空間のデータに対応し,kvec構造体はカーネル空間のデータに対応します).

linux/net/socket.cのsys_sendtoシステムコールハンドラ関数(45行目)は,__sys_sendto関数(1行目)を呼び出しています.

__sys_sendto関数では,sock_sendmsg関数(37行目)を利用しています.

バイトオーダーの変換

異なるシステムにおいて,ワード内のバイトオーダー(エンディアン)には,ビッグエンディアン(最上位バイトが先),リトルエンディアン(最下位バイトが先)などがあります.

ネットワークは異なるプラットフォームのシステムを相互接続するため,インターネットではネットワークバイトオーダーと呼ばれる数値データの格納順序の標準が定められています.

これに対して,ホストコンピュータ上で数値データを表現するためのバイト列をホストバイトオーダーと呼びます.

ネットワークから送受信されるデータはネットワークバイトオーダーの形式であり,この形式とホストバイトオーダーとの間で変換する必要があります.

変換には以下のマクロを使用します.

  • u16 htons(u16 x)マクロ(host to network short):16ビット整数をホストバイトオーダーからネットワークバイトオーダーに変換します.
  • u32 htonl(u32 x)マクロ(host to network long):32ビット整数をホストバイトオーダーからネットワークバイトオーダーへ変換します.
  • u16 ntohs(u16 x)マクロ(network to host short):16ビット整数をネットワークバイトオーダーからホストバイトオーダーに変換します.
  • u32 ntohl(u32 x)マクロ(network to host long):32ビット整数をネットワークバイトオーダーからホストバイトオーダーに変換します.

netfilter

netfilterは,ネットワークパケットをキャプチャして変更・分析(フィルタリング,NAT等)するためのカーネルインターフェースの名前です.

ユーザ空間ではiptablesがnetfilterのインタフェースを使用します.

Linuxカーネルでは,netfilterを使ったパケットキャプチャは,フックを付けることによって行われます.

フックは,カーネルのネットワークパケットがたどる経路のさまざまな場所に,必要に応じて指定することができます.

パッケージがたどる経路とフックに指定可能な場所の構成図はこちらです.

netfilterはLinuxカーネル固有の機能ですが,様々なOSでnetfilterと同様の機能を実行できるC言語で開発されたネットワークアナライザ「Wireshark」を知りたいあなたはこちらからどうぞ.

netfilterで利用する構造体と関数

linux/include/linux/netfilter.hのstruct nf_hook_ops構造体でフックを定義します.

  • pf:パッケージの種類(PF_INET等)
  • priority:優先度

priorityは,linux/include/uapi/linux/netfilter_ipv4.hのenum nf_ip_hook_prioritiesで定義されています.

  • dev:キャプチャの対象となるデバイス(ネットワークインタフェース)
  • hooknum:使用されるフックのタイプ.パケットがキャプチャされるとき,処理モードはhooknumとhookメンバ変数によって定義される.

hooknumは,IPの場合,フックの種類はlinux/include/uapi/linux/netfilter.hのenum nf_inet_hooksで定義されています.

  • hook:ネットワークパケット(パケットはsk_buff構造体として送られる)をキャプチャする際に呼び出されるハンドラ関数である.
  • priv:ハンドラ関数に渡されるプライベートな情報である.

hookキャプチャハンドラ関数のプロトタイプはlinux/include/linux/netfilter.hのnf_hookfn関数型で定義される.

nf_hookfn関数型では,privパラメータはnf_hook_ops構造体を初期化したプライベート情報,skbはキャプチャしたネットワークパケットへのポインタです.

skbの情報に基づいて,パケットフィルタリングの判断が行われます.

この関数のstateパラメータは,入力インタフェース,出力インタフェース,優先度,フック番号など,パケットキャプチャに関連する状態情報です.

優先度とフック番号は,同じ関数を複数のフックから呼び出せるようにするために有用です.

キャプチャハンドラ関数は,linux/include/uapi/linux/netfilter.hで定義されている定数NF_*のいずれかを返すことができます.

NF_DROPはパケットをフィルタリング(無視)するために使用し,NF_ACCEPTはパケットを受理して転送するために使用します.

フックの登録・解除関数は以下になります.

  • nf_register_net_hook関数:netfilterを利用したフックを登録する.
  • nf_unregister_net_hook関数:netfilterを利用したフックを解除する.
  • nf_register_net_hooks関数:n個のnetfilterを利用したフックを登録する.
  • nf_unregister_net_hooks関数:n個のnetfilterを利用したフックを解除する.

netfilterフックのパラメータとして設定されたsk_buff構造体からのヘッダ抽出関数の使用に関して,いくつかの制約があります.

IPヘッダはip_hdr関数でその都度取得できますが,TCP/UDPヘッダはtcp_hdr/udp_hdr関数で取得できるのは,システム外から受信したパッケージではなく,システム内部から受信したパッケージに対してだけです.

システム外から受信したパッケージの場合,以下のようにパッケージのヘッダオフセットを手動で計算する必要があります.

上記のコードは,すべてのフィルタリングの状況で動作するので,ヘッダアクセス関数の代わりに使用することをおすすめします!

netfilterでパケットの送受信を制御するカーネルモジュール

netfilterでパケットの送受信を制御するカーネルモジュールのコード一式はこちらからダウンロードして下さい.

netfilterのコードnetfilter_kernel_module.cは以下になります.

netfilter_hook_func関数で宛先のIPアドレスが1.1.1.1,通信プロトコルがICMP(いわゆるpingで利用する通信プロトコル)をフィルタリングします.

まずは「ping 1.1.1.1」を実行して正常に動作するか確認しましょう.

次に,ビルドしてカーネルモジュールをロードしましょう.

「ping 1.1.1.1」を実行するとnetfilterによるパケットフィルタリングにより正常に動作しないことがわかります.

カーネルモジュールをアンロードすると「ping 1.1.1.1」は正常に動作します.

参考:netcat

netcatは,ネットワークコードを含むアプリケーションを開発する時によく利用されるツールです.

また,netcatは,「Swiss-Army Knife for TCP/IP」(TCP/IP用スイス軍用ナイフ)というニックネームも持っています.

※netcatはスイス軍用ナイフのように便利という意味です.

netcatでできることは以下になります.

  • TCP接続を開始する.
  • TCP接続を待つ.
  • UDPパケットを送受信する.
  • トラフィックをhexdumpフォーマットで表示する.
  • 接続を確立した後のプログラムを実行する(例:シェル).
  • 送信パッケージの特別なオプションを設定する.

netcatの使い方を知りたいあなたは,以下の記事がおすすめです!

TCPアクセラレーション(TCP高速化機能)

TCPアクセラレーション(TCP高速化機能)は,TCPにおいてアプリケーションに手を加えることなく,ネットワーク接続において標準的なTCPよりも優れたスループットを実現する一連の技術のことです.

本記事では,LinuxカーネルにマージされているTCPアクセラレーションを紹介します.

基本的には,TCPアクセラレーションは,Bufferbloat(バッファブロート)と呼ばれるパケット交換型ネットワークにおける送信パケットの過剰なバッファリングにより生じる大きな遅延に関する課題を解決するために開発されています.

※後述するUDPアクセラレーションも含みます.

Bufferbloatの解説動画は以下がわかりやすいです.

TCP Small Queues(TSQ),CoDel,Byte Queue Limits(BQL)

TCP Small Queues(TSQ)は,データがどこにキューイングされているかに関係なく,任意のソケットによって送信のためにキューイングされるデータの量を制限することです.

TSQの目的は,伝送キューに入るTCPパケットを減らし,ラウンドトリップタイム(RTT)や輻輳ウインドウサイズ(cwnd)の偏り,bufferbloatの一部を減らすことです.

TSQの開発の動機にはCoDelと呼ばれるキュー管理アルゴリズムが挙げられます.

CoDelは,パケットが時間とともにルータのキューに蓄積されるのを防ぐために動作します.

より低いレベルでは,バイトキュー制限は,特定のネットワークインターフェースに出力されるのを待つことができるデータ量に上限を設定します.

しかし,バイトキュー制限はデバイスキューのレベルでしか機能しません.

一方,ネットワーキングスタックは,キューイング規則(Queueing Discipline)レベルなど,他の場所でバッファリングを行うことができます.

※キューイング規則はキューを取り出す方法のことでFirst In First Out(FIFO)等のことを表します.

また,Byte Queue Limits(BQL)と呼ばれる適正な上限値を設定することで,NICの不要なキューイングを削減する手法もあります.

TSQの特徴は,デバイスキューより上のレベルでバッファリングを制限できることです.

TSQは,データがどこにキューイングされているかに関係なく,任意のソケットによって送信のためにキューイングされるデータの量を制限します.

つまり,TSQは,キューイング,トラフィック制御,またはネットフィルタのコードに潜むバッファに惑わされません.

TSQによるIPv4のTCPの伝送制限は,/proc/sys/net/ipv4/tcp_limit_output_bytesで設定できます.

私のLinux環境では,1MB(= 1,024KB = 1,048,576Bytes)に設定されています.

TSQのIPv4のコードは,linux/net/ipv4/tcp_output.cにあります.

  • tsq_tasklet構造体:TSQを管理する.
  • tcp_tsq_write関数:TCPのパケットをTSQで伝送する.
  • tcp_tsq_handler関数:TSQ用のハンドラ関数.

TCP Fast Open(TFO)

TCP Fast Open(TFO)は,2つのエンドポイント間の連続したTCPコネクションのオープンを高速化する拡張機能です.

TFO cookie(TCPオプション)は,クライアント側に保存され,サーバとの最初の接続時に設定される暗号化cookieです.

クライアントが後で再接続するとき,最初のSYNパケットとTFO cookieデータを送信し,自身を認証します.

成功すれば,サーバは3ウェイハンドシェイクの最終ACKパケットを受信する前にクライアントへのデータ送信を開始できるため,ラウンドトリップ遅延をスキップしてデータ送信開始の待ち時間を短縮することができます.

TFOのIPv4サポートは,Linuxカーネルのバージョン3.6(クライアントのサポート)と3.7(2012年12月)(サーバのサポート)でLinuxカーネルのメインラインにマージされました.

2014年1月のLinuxカーネルのバージョン3.13でデフォルトで有効になりました.

IPv6サーバのTFOサポートはLinuxカーネルのバージョン3.16でマージされました.

TFOのIPv4のコードは,linux/net/ipv4/tcp_fastopen.cにあるので興味があるあなたは是非読みましょう!

TCP Fast Openの解説動画はこちらです.

TCPの輻輳制御

TCPでは,インターネットにアクセスが集中することで輻輳が発生し,性能が低下する主な原因になっています.

輻輳を回避するために,多くのTCPの輻輳制御アルゴリズムが提案されました.

TCPの輻輳制御アルゴリズムのタイプは以下になります.

  • ロスベース(Loss-based)輻輳制御
  • 遅延ベース(Delay-based)輻輳制御
  • Hybrid輻輳制御

本記事では代表的なTCPの輻輳制御アルゴリズムである以下を紹介します.

まずはTCPの輻輳制御を学びたいあなたは「基本から学ぶ TCPと輻輳制御 ……押さえておきたい輻輳制御アルゴリズム 記事一覧」を読みましょう!

以下の動画もおすすめです!

CUBIC

CUBICは,Loss-based輻輳回避アルゴリズムです.

CUBICの特徴は,従来のアルゴリズムに比べて,高遅延に直面しても,より迅速かつ確実にネットワーク上の広帯域接続を達成することができることです.

CUBICは,長距離ネットワークを最適化するのに有用です.

2006年に最初のCUBIC実装がLinuxカーネルのバージョン2.6.13でリリースされたました.

Linuxカーネルのバージョン2.6.19以降,CUBICはLinuxカーネルのデフォルトTCP輻輳制御アルゴリズムになりました.

LinuxでCUBICを利用しているかどうかは,sysctlコマンドで確認できます.

私のLinuxカーネルのバージョン5.15ではCUBICであることがわかります.

CUBICのIPv4のコードは,linux/net/ipv4/tcp_cubic.cにあるので興味があるあなたは是非読みましょう!

CUBICの解説動画はこちらです.

BBR

BBRは,2016年にGoogleで開発されたDelay-based輻輳制御アルゴリズムです.

※BBRはBottleneck Bandwidth and Round-trip propagation timeの略です.

ほとんどのTCPの輻輳制御アルゴリズムは,パケットロスに依存して輻輳や送信率の低下を検出するという意味でLoss-basedです.

BBRは,ネットワークが送信データパケットの直近のフライトを配信した際の最大帯域幅と往復時間を使用して,ネットワークのモデルを構築します.

パケット配信の累積的または選択的な確認応答ごとに,データパケットの送信とそのパケットの確認応答との間の時間間隔にわたって配信されたデータ量を記録するレートサンプルが生成されます.

ネットワーク・インターフェース・コントローラがMbit/sからGbit/sの性能に進化するにつれ,パケットロスではなくBufferbloatに関連する遅延が最大スループットの実現に対して支配的になっています.

そこで,BBRなどの高スループットと低遅延を実現するDelay-based輻輳制御アルゴリズムが,CUBIC等の一般的なLoss-based輻輳制御アルゴリズムより優れてきています.

BBRはLinuxカーネルのバージョン4.9にマージされました.

また,後述するQUICでも利用可能です.

BBRのIPv4のコードは,linux/net/ipv4/tcp_bbr.cにあるので興味があるあなたは是非読みましょう!

BBRの解説動画はこちらです.

参考:TCP Protective Load Balancing(PLB),Data Center TCP(DCTCP)

TCP Protective Load Balancing(PLB)は,グーグルが開発したLinuxカーネルのTCPの輻輳制御「Data Center TCP(DCTCP)」のコードにフックしてロードバランシングする手法です.

PLBは,Linuxカーネルのバージョン6.2でマージ予定です.

PLBの論文は「PLB: Congestion Signals are Simple and Effective for Network Load Balancing」ですので,興味があるあなたは是非読みましょう!

UDPアクセラレーション(UDP高速化機能)

UDPアクセラレーション(UDP高速化機能)は,UDPにおいてアプリケーションに手を加えることなく,ネットワーク接続において標準的なUDPよりも優れたスループットを実現する一連の技術のことです.

つまり,TCPアクセラレーションのUDP版です.

本記事では,LinuxカーネルにマージされているUDPアクセラレーションを紹介します.

UDP-Lite

UDP-Liteは,コネクションレス型のプロトコルで,破損の可能性があるデータペイロードを受信側で破棄せず,アプリケーションに配信することを可能にします.

従来のUDPパケットでは1ビットでもデータが損傷すれば破棄されるのに対して,UDP-Liteはそのまま伝送されます.

UDP-Liteにより,データの完全性に関する決定をアプリケーション層(アプリケーションまたはコーデック)で行えるため,音声や動画の伝送に有用です.

UDP-LiteのIPv4のコードは,linux/net/ipv4/udplite.cにあるので興味があるあなたは是非読みましょう!

UDP-LiteはLinuxカーネルでは必要最低限の処理で,ほとんど何もしないことが高速化に貢献しているということです!

UDP-Liteの解説動画はこちらです.

参考:Quick UDP Internet Connections(QUIC)

Quick UDP Internet Connections(QUIC)は,グーグルが開発したUDPにコネクション指向を追加したトランスポート層の通信プロトコルです.

QUICはLinuxカーネルのメインラインにはマージされていませんので注意して下さい.

QUICはユーザ空間のライブラリとして実装されています.

QUICの詳細を知りたいあなたはこちらからどうぞ.

まとめ

今回はソケット通信(TCP/UDP/IP)を紹介しました.

Linuxカーネルでソケット通信がどのように実装されているかがわかりました.

ソケット通信(TCP/UDP/IP)を深掘りしたいあなたは,以下を読みましょう!

以下の動画もおすすめです!

LinuxカーネルはC言語で書かれています.

私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.

私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!

友だち追加

独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!

-TECHNOLOGY, LINUX KERNEL
-, , , , , , , , , ,