rds サブルーチン

目的

高信頼性データグラム・ソケット (RDS) は、さまざまなネットワーク・トランスポートを介してソケット間の信頼性の高い順次データグラム配信を提供します。

ライブラリー

#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/bypass.h>
#include <net/rds_rdma.h>

説明

RDS は、 RDS アプリケーション・プログラミング・インターフェース (API) の実装です。 RDS は、 InfiniBand およびループバックを介して転送できます。 TCP 経由の RDS は使用不可です。 RDS は、標準の AF_INET アドレスを使用してエンドポイントを識別します。

ソケット作成

RDS ソケットは、以下のように作成されます。
rds_socket = socket(AF_BYPASS, SOCK_SEQPACKET, BYPASSPROTO_RDS);

ソケットのオプション

RDS は、 setsockopt および getsockopt 呼び出しを介して複数のソケット・オプションをサポートします。 SOL_SOCKET ソケット・レベルでは、以下のオプションが重要です。
SO_RCVBUF
受信バッファーのサイズを指定します。 輻輳制御 (輻輳制御) を参照。
SO_SNDBUF
送信バッファーのサイズを指定します。 メッセージ伝送 (Message Transmission) を参照。
SO_SNDTIMEO
ブロッキング・モードで満杯のキューを持つソケットにメッセージをエンキューするときのソケットの送信タイムアウトを指定します。
RDS は、 SOL_RDS ソケット・レベルで複数のプロトコル固有のオプションもサポートします。

バインディング

新しい RDS は、 socket 呼び出しから最初に戻されるときには、ローカル・アドレスを持ちません。 メッセージを送受信する前に、 bind システム・コールを実行して、ソケットをローカル・アドレスにバインドする必要があります。 bind 呼び出しは、ローカル・アドレスが接続されているインターフェースのタイプに基づいて、特定のネットワーク・トランスポートにソケットを接続します。 呼び出しがソケットに接続された時点から、ソケットは、このネットワーク・トランスポートを介して使用可能な宛先に到達することができます。

例えば、 ib0などの InfiniBand インターフェースのアドレスにバインドする場合、ソケットは InfiniBand トランスポート・システムを使用します。 RDS は、トランスポート・システムを特定のアドレスに関連付けることができない場合、 EADDRNOTAVAIL 値を返します。

RDS ソケットは 1 つのアドレスにのみバインドでき、特定のアドレスまたはポートのペアにバインドできるのは 1 つのソケットのみです。 バインディング・アドレスにポートが指定されていない場合は、アンバインドされたポートがランダムに選択されます。

RDS は、アプリケーションが以前にバインドされたソケットを別のアドレスにバインドすることを許可しません。 INADDR_ANY ワイルドカード・アドレスへのバインディングは許可されません。

接続中

操作のデフォルト・モードでは、 RDS は接続されていないソケットを使用し、 sendmsg サブルーチンに対する引数として宛先アドレスを指定します。 ただし、 RDS では、 connect サブルーチンを使用してソケットをリモート・エンドポイントに接続することができます。 ソケットが接続されている場合、宛先アドレスを指定せずに sendmsg サブルーチンを呼び出すことができ、サブルーチンは以前に提供されたリモート・アドレスを使用します。

輻輳制御

RDS には、TCP などの一般的なストリーミング・プロトコルのような明示的な輻輳制御メカニズムはありません。 ソケットには、 send queue sizereceive queue sizeの 2 つのキュー制限があります。 メッセージは、ペイロードのバイト数に基づいて計算されます。

send queue size は、ローカル・プロセスがローカル・ソケットでキューに入れることができるデータを制限します。 この制限を超えると、カーネルは、キューが解放され、リモート・ホストによってメッセージが配信されて確認されるまで、メッセージを受け入れません。

receive queue size は、ソケットに 輻輳のマークを付ける前に、 RDS がソケットの受信キューに保管するデータを制限します。 ソケットが輻輳状態になると、 RDS は 輻輳マップ 更新を他の参加ホストに送信します。これらのホストは、このポートへの追加メッセージの送信を停止することが予期されます。

リモート・ホストが輻輳したポートにメッセージを送信し続けることができるタイミング・ウィンドウがあります。 RDS は、ソケットの受信キューが制限を超えた場合でもメッセージを受け入れることにより、タイミング・ウィンドウを解決します。

アプリケーションが recvmsg システム・コールを使用して受信キューから着信メッセージを受信すると、受信キューのバイト数が受信キューのサイズより少なくなり、ポートに uncongestedのマークが付けられます。 輻輳更新がすべての参加ホストに送信されます。

送信バッファー・サイズおよび受信バッファー・サイズの値は、 SO_SNDBUF および SO_RCVBUF ソケット・オプションを介してアプリケーションによって調整できます。

ブロッキング動作

sendmsg 呼び出しと recvmsg 呼び出しは、さまざまな状況でブロックされる可能性があります。 ファイル記述子の非ブロッキング設定および MSG_DONTWAIT メッセージ・フラグによっては、呼び出しがブロックされたり、エラーで戻されたりすることがあります。 ファイル記述子がブロッキング・モード (デフォルト) に設定されていて、 MSG_DONTWAIT フラグが指定されていない場合、呼び出しはブロックされます。

SO_SNDTIMEO および SO_RCVTIMEO ソケット・オプションは、呼び出しが終了してエラーを返すまでのタイムアウト (秒単位) を指定するために使用されます。 デフォルトのタイムアウトは 0 で、これは RDS が無期限にブロックすることを許可します。

メッセージ伝送

RDS ソケットがバインドされた後、 sendmsg 呼び出しを使用してメッセージを送信できます。 ワイヤー・プロトコルはメッセージ長を表すために符号なし 32 ビット整数を使用するため、メッセージ長は 4 GB を超えることはできません。

RDS は、アウト・オブ・バンドのデータをサポートしません。 アプリケーションは、ブロードキャストまたはマルチキャストがサポートされていないユニキャスト・アドレスにのみデータを送信できます。

sendmsg 呼び出しが成功すると、メッセージがネットワーク内に存在しなくなったことを宛先が確認するまで、またはアプリケーションがメッセージを送信キューから削除するまで、メッセージはソケットの送信キューに置かれます。

RDS_CANCEL_SENT_TO ソケット・オプションを使用して、メッセージを送信キューから除去することができます。

メッセージが送信キューにある場合は、そのペイロード・バイトが考慮されます。 伝送キューが解放されていないときにメッセージを送信しようとすると、呼び出しは EAGAIN 値をブロックするか、または戻します。

輻輳 (ふくそう) のマークが付けられた宛先にメッセージが送信されると、呼び出しがブロックされるか、ENOBUFS 値が返されます。

ペイロード・バイトなしで送信されるメッセージは、宛先の送信バッファーにスペースを必要としませんが、メッセージ受信は宛先に送信されます。 受信側はペイロード・データを取得できませんが、送信側のアドレスは表示できます。

ソケットがバインドされていないポートに送信されたメッセージは、宛先ホストによって破棄されます。 エラー・メッセージは送信側に報告されません。

メッセージ受信

ソース・アドレスにバインドされた後、 RDS で recvmsg 呼び出しを使用してメッセージを受信できます。 RDS は、送信側がメッセージを送信したのと同じ順序でメッセージを返します。

フィールドが設定されている場合、送信側のアドレスは、 メッセージ名 フィールドが指す Sockaddr_in 構造体に戻されます。

MSG_PEEK (メッセージ・ EEK) フラグが設定されている場合、受信キュー上の最初のメッセージは、キューからメッセージを除去せずに戻されます。

配信を待機しているメッセージによって使用されるメモリーは、受信のためにキューに入れることができるメッセージの数を制限しません。 RDS は輻輳の制御を試みます。

メッセージの長さが recvmsg 呼び出しに提供されたバッファーのサイズを超える場合、メッセージ内の残りのバイトは破棄され、 msg_flags フィールドに MSG_TRUNC フラグが設定されます。 この場合、 recvmsg 呼び出しは、コピーされたバイト数を戻します。 メッセージ全体の長さは返されません。 フラグ引数で MSG_TRUNCrecvmsgに設定されている場合、メッセージ全体のバイト数を返します。 長さゼロのバッファーを提供したり、フラグ引数に MSG_PEEK および MSG_TRUNC オプションを設定したりすることなく、受信キュー内の次のメッセージのサイズを表示できます。

長さがゼロのメッセージの送信アドレスは、 メッセージ名 フィールドで提供されます。

制御メッセージ

RDS は、 sendmsg および recvmsg 呼び出しの msg_control および msg_controllen フィールドを使用することによって補助データである制御メッセージを使用します。 RDS によって生成される制御メッセージの cmsg_level 値は sol_rdsです。 ほとんどの制御メッセージは、 RDS バージョン 3 で追加された zerocopy インターフェースに関連しており、 rds-rdma サブルーチンで説明されています。

唯一の例外は RDS_CMSG_CONG_UPDATE メッセージです。

ポーリング

poll インターフェースのサポートは制限されています。 POLLIN は、 RDS メッセージがある場合、またはソケットの受信キューで待機中の制御メッセージがある場合に返されます。 POLLOUT は、ソケットの送信キューにスペースがある場合に返されます。

輻輳ポートにメッセージを送信するには、特別な処理メカニズムが必要です。 アプリケーションが輻輳した宛先にメッセージを送信しようとすると、システム・コールは エノブFS 値を返します。 RDS は POLLOUT をポーリングできません。これは、送信キューが引き続きメッセージを収容でき、 poll インターフェースへの呼び出しが、宛先が輻輳していても即時に戻る可能性があるためです。

以下のいずれかの方法で輻輳を処理できます。
  • POLLIN オプションをポーリングします。 デフォルトでは、輻輳マップが更新されると、 poll インターフェースでスリープ中のプロセスがアクティブ化されます。 アプリケーションは、以前に輻輳した送信操作を再試行できます。
  • 明示的な輻輳をモニターします。これにより、アプリケーションの制御が強化されます。
明示的モニターを使用すると、アプリケーションは以前と同様に POLLIN オプションをポーリングし、さらに RDS_CONG_MONITOR ソケット・オプションを使用して、64 ビット・マスク値をソケットにインストールします。ここで、各ビットはポートのグループに対応します。 輻輳更新を受信すると、 RDS ソケットは、ソケットにインストールされているビット・マスクに対して、 uncongested になったポートのセットを検査します。 オーバーラップすると、制御メッセージがソケットにエンキューされ、アプリケーションが活動化されます。 recvmsg 呼び出しが呼び出されると、 RDS はソケット上のビットマップを含む制御メッセージを渡します。

輻輳モニター・ビット・マスク は、 RDS_CONG_MONITOR オプションを指定した setsockopt 呼び出し、および 64 ビット・マスク変数へのポインターを使用して設定および照会できます。

輻輳更新は、 RDS_CMSG_CONG_UPDATE 制御メッセージを介してアプリケーションに配信されます。 制御メッセージは個別に配信されますが、 RDS データ・メッセージと一緒に配信されることはありません。 制御メッセージの cmsg_data フィールドは、64 ビット・マスク値を含む 8 バイトのデータです。

アプリケーションは、以下のマクロを使用して、ビット・マスク内のビットをテストし、設定することができます。
#define RDS_CONG_MONITOR_SIZE   64
#define RDS_CONG_MONITOR_BIT(port)  (((unsigned int) port) % RDS_CONG_MONITOR_SIZE)
#define RDS_CONG_MONITOR_MASK(port) (1 << RDS_CONG_MONITOR_BIT(port))

メッセージの取り消し

アプリケーションは、 setsockopt 呼び出しで RDS_CANCEL_SENT_TO ソケット・オプションを使用することにより、送信キューからメッセージを取り消すことができます。 setsockopt 呼び出しは、引数としてオプションの sockaddr_in アドレス構造体を使用します。 sockaddr_in アドレスで指定された宛先アドレスへのメッセージのみが廃棄されます。 アドレスが指定されていない場合は、すべての保留メッセージが廃棄されます。
注: この呼び出しは、送信されないメッセージ、および送信されるが確認応答をリモート・ホストから受信しないメッセージに影響します。

信頼性

sendmsg が成功すると、 RDS は、宛先ソケットが開いている限り、宛先アドレスにバインドされているソケット上の recvmsg にメッセージが表示されることを保証します。

宛先にソケットがバインドされていない場合、メッセージは除去されます。 メッセージを送信している RDS が、ソケットがバインドされていることを確認できない場合は、メッセージが確実に送信されるか、送信されたメッセージが取り消されるまで、メッセージの送信を無期限に試行します。

ソケットがクローズされると、ソケット上の保留中の送信済みメッセージは取り消され、受信側が見ることができるか、または見ることができません。

RDS_CANCEL_SENT_TO ソケット・オプションを使用すると、特定の宛先へのすべての保留メッセージを取り消すことができます。

受信ソケットがクローズされ、メッセージが保留されている場合、送信側はそれらのメッセージをネットワークを離れたものと見なし、再送しません。

メッセージは、 MSG_PEEK が指定されていない限り、 recvmsg 呼び出しによって表示されます。 メッセージが送信されると、送信ソケットの送信キューから除去されます。

同じソケットから同じ宛先に送信されるすべてのメッセージは、送信された順序で配信されます。 異なるソケットから、または異なる宛先に送信されたメッセージは、ランダムに配信されます。