2016-02-12 17 views
11

私はサーバーから1ミリ秒ごとに生のイーサネットパケット(TCP/UDPなし)を受信するコードを書いています。受信したすべてのパケットについて、私のアプリケーションは14個の生のパケットで返答しなければなりません。 1ミリ秒ごとにスケジュールされたパケットを送信する前にサーバーが14パケットを受信しない場合、サーバーはアラームを発生させ、アプリケーションは中断しなければなりません。サーバーとクライアントの通信は、1対1のリンクです。マイクロ秒レベルの精度でRAWソケットパケットを受信

サーバは、正確な1ms間隔でパケットを生成するハードウェア(FPGA)です。クライアントアプリケーションは、10G SolarFlare NICを搭載したLinux(RHEL/Centos 7)マシンで動作します。コードの

私の最初のバージョンは、それの後に、私はこれらのタイムスタンプと印刷の時間差を印刷この

while(1) 
{ 
    while(1) 
    { 
    numbytes = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL); 
    if(numbytes > 0) 
    { 
     //Some more lines here, to read packet number 
     break; 
    } 
    } 
    for (i=0;i<14;i++) 
    { 
    if (sendto(sockfd,(void *)(sym) , sizeof(sym), 0, NULL, NULL) < 0) 
      perror("Send failed\n"); 
    } 
} 
私は recvfrom呼び出しの前に( clock_gettimeを使用して)タイムスタンプを取ることによって、受信時間測定

と1のようなものです時間差が900-1100 usの許容範囲を超えたときはいつでも、

私が直面しています問題は、パケットが、時間が

Decode Time : 1234 
Decode Time : 762 
Decode Time : 1593 
Decode Time : 406 
Decode Time : 1703 
Decode Time : 257 
Decode Time : 1493 
Decode Time : 514 
and so on.. 

(プリントがマイクロ秒である)このようfluctuating.Somethingされるそして、時にはデコード時間が2000usを超え、アプリケーションが壊れる受けるということです。

この状況では、アプリケーションは2秒から数分の間にどこかに壊れます。

オプションは今まで私が試しました。

  1. 特定の単離されたコアに対する親和性を設定する。 SCHED_FIFO
  2. 増加ソケットバッファと最大スケジューリング優先順位を設定
  3. 設定ネットワークインタフェースのサイズアプリケーション
  4. poll(),select()コールを使用recvfrom上に紡糸処理同じコアに親和性を中断します。

これらのオプションはすべて、初期バージョンのコードよりも大幅に改善されています。これで、アプリケーションは約1〜2時間実行されます。しかしこれではまだ十分ではありません。

いくつかの観察:アプリケーションが実行されている間、私は私が他の1Gイーサネットインタフェースを介してネットワーク通信を思わせるその(LinuxマシンにSSHセッションを取るたび

  1. 私は、これらのデコード時間プリントのAA巨大なダンプを取得します10Gイーサネットインターフェイスに干渉を引き起こしています)。
  2. アプリケーションはCentOS(約30分〜1.5時間の実行時間)よりもRHEL(約2〜3時間の実行時間)でパフォーマンスが向上します
  3. 同じハードウェア構成のLinuxマシンでも実行時間は異なりますOS。

アプリケーションの実行時間を改善する他の方法があるかどうかをご提案ください。

ありがとうございます。

+2

処理時間のほかに、現実世界ではネットワークがパケット配信時間を大幅に変えることを理解する必要があります。完全なQoSポリシーが適切に設定されていて、このトラフィックのプライオリティキューを定義している場合、これがネットワーク上にある(インターネット上を移動しない)場合は、これをある程度緩和することができます。さもなければ、私はネットワーク上でそのような近いタイミングで何かを使用しようと試みることさえしないでしょう。 –

+0

可能であれば、PREEMPT_RTコンパイル済みのLinuxカーネルを使うことをお勧めします。 – LPs

+1

この精度でパケットを送信することは、certanilyとして、達成したいことは、イーサネット上では実現できません。私はあなたのPCとあなたのデータとインターフェイスを処理する別のFPGAを持つことをお勧めします。 – Koshinae

答えて

1

まず、タイムスタンプ方法の精度を確認する必要があります。 clock_gettime。分解能はナノ秒ですが、精度と精度に問題があります。それはあなたの問題に対する答えではありませんが、進行する前にタイムスタンプがどれだけ信頼できるかを知らせます。アプリケーションでCLOCK_MONOTONICを使用する理由については、Difference between CLOCK_REALTIME and CLOCK_MONOTONIC?を参照してください。

デコード時間の変動の大部分は、デコードごとの可変操作数、オペレーティングシステムのコンテキスト切り替え、またはIRQによるものと思われます。

デコードごとの操作投稿内でコードが簡略化されているため、私はコメントできません。この問題は、プロファイリングして検査することもできます。プロセスごと

コンテキスト切り替えを容易に検査及びRonが述べたようにhttps://unix.stackexchange.com/a/84345

を監視することができ、これらは、ネットワークのための非常に厳密なタイミング要件があります。それは孤立したネットワークでなければならず、単一の目的でなければなりません。 ssh'ingが他のすべてのトラフィックを防止する必要があることを示しているときのデコードオーバータイムに関するあなたの観察。別のNICがあれば、これは邪魔になります。したがって、私はIRQが問題だと思っています。/proc/interruptsを参照してください。

長い間隔(時間 - >日)で一貫したデコード時間を達成するには、OSを大幅に簡素化する必要があります。不要なプロセスやサービス、ハードウェアを削除し、おそらく独自のカーネルを構築します。コンテキスト切り替えと割り込みを減らすことを目標にしています。その時点でリアルタイムOSを考慮する必要があります。これは、一貫性のあるデコード時間の確率を向上させるだけであり、保証するものではありません。

私の研究は、FPGA ADC、PC、およびイーサネットの組み合わせであるデータ集録システムを開発しています。必然的に、多目的PCの不一致は、特定の機能を専用のハードウェアに移動する必要があることを意味します。 PC用アプリケーションの開発とハードウェアへの移行の長所/短所を考えてみましょう。

+0

タイムスタンプの取得に 'CLOCK_MONOTONIC'を使用しています。そして、計算された時間は観察された結果と一致する。 – Vikram

+0

私は 'isolcpus'カーネルコマンドを使っていくつかのCPUコアを分離しました。 'ps -eF'を使って実行中のプロセスをチェックすると、migration、ksoftirqd、kworkerを除いて、それらの独立したコアでプロセスが実行されないことがわかります。私はこれらが避けられないことを知っています。 – Vikram

関連する問題