私は単一のイーサネットフレームを受信してから、1秒遅れ(その間にいくつかの処理を含む)後にデータを別のイーサネットフレームに送信する時間に敏感なネットワークアプリケーションを作成しています。
しかし、特に難しいのは、私ができる能力も必要だということです。キャンセルこの遅延間隔の間に異なるタイプの異なるメッセージが受信された場合、パケット送信は継続する。
正確に1秒の遅延を得るためにカーネルのソケットタイムスタンプ機能これと組み合わせる時間ベースのパケット転送。これら2つの機能を組み合わせることで、アプリケーションをユーザー空間に維持しながら、システム全体をリアルタイムプロセススケジューラで実行することなく、予測可能でかなり正確なレイテンシを作成できます。
特にソケットを作成しsocket(AF_PACKET, SOCK_RAW, TEST_ETHERTYPE)
(実際のアプリケーションはIPv4を処理しますが、今はテストに別のエーテルタイプを使用しています)、パケット到着タイムスタンプを生成し、指定された転送を許可するようにソケットオプションをSO_TIMESTAMPNS
設定します。SO_TXTIME
その後、メインループでは、アプリケーションはAPIを使用して受信したパケットデータと共に制御メッセージをrecvmsg
返しSCM_TIMESTAMPNS
、パケットをパケットとして処理して送信し、APIを使用して埋め込みタイムスタンプで使用するためにキューに入れます(これは、制御メッセージが受信されたタイムスタンプから1秒後にsendmsg
送信されます。SCM_TXTIME
しかし、キューに追加されたパケットを実際に「回収」する方法はないようです。時間ベースの送信を使用しても、パケットが長時間キューに入ることがあります。
私は自分のアプリケーションで自分自身のパケットキューを実装し、パケットが期限切れに非常に近い場合にのみカーネルを使用してパケットを予約できることを知っています。とにかく、これはカーネルキューに圧力を加えることを避けることができます。実装方法にかかわらず、遅延が終わると常にゼロ以外の間隔があり、パケットが送信される前にキャンセルされるという保証はありません。
しかし、もしそうならただ私のアプリケーションの独自のソフトウェアキューからパケットをキャンセルできる場合、最悪の場合、キャンセルウィンドウはより悲観的です。これは、締め切り前にパケットがキューに入っていることを確認する際に考慮すべきスケジュールの不一致が多いためです。一般に、複数のスレッドはソフトウェアキューの異なる端で管理する必要があり、これはより複雑になります。
簡単に言えば、パケットがカーネルキューに追加された後に時間ベースの送信のためにパケットのスケジュールをキャンセルする方法はありますか?