Japan QualNet Community Forums Japan QualNet Community Forums
Welcome Guest 
ログイン
ユーザ名:

パスワード:


パスワード紛失

新規登録
検索
メインメニュー
アクセスカウンター
2025/04/30:4/5
2025/04/29:19/24

2025/03/07より260/1286
人気モジュール
No.1: フォーラム 47
No.2: QualNet概要 3
日曜日からの合計
人気Browser&OS
No.1:巡回ロボット35
No.2:Linux3
No.3:Macintosh2

No.1:どっかの巡回ロボット31
No.2:Safari6
No.3:Google巡回ロボット4

日曜日からの合計
メイン
   Link (MAC) Layer Settings
     MAC層でセグメントのシーケンス番号を出力させる方法について
投稿するにはまず登録を

スレッド表示 | 新しいものから 前のトピック | 次のトピック | 下へ
投稿者 スレッド
musen
投稿日時: 2007/6/24 20:29
新米
登録日: 2006/10/5
居住地:
投稿: 19
MAC層でセグメントのシーケンス番号を出力させる方法について
中継端末を含め全端末でMAC層での送信時におけるセグメントのシーケンス番号を出力させたいのですが、中継端末はトランスポート層までパケットを上げないため、MAC層でti->ti_seqを出力させても0しか出力されません。mac層でセグメントのシーケンス番号を出力される方法をご存知でしょうか?
よろしくお願いいたします。
hiro
投稿日時: 2007/6/24 21:05
長老
登録日: 2005/7/16
居住地:
投稿: 452
Re: MAC層でセグメントのシーケンス番号を出力させる方法について
情報が少ないので、全くの想像ですが。
シーケンス番号というのは、TCPのシーケンス番号のことですか?
一般的にはMAC層ではデータ部(ペイロード部)のことは関知しないので、MAC層のヘッダ情報しか使いません。
というか、MAC層ではTCPのシーケンス番号については関与しないので、
中継端末でシーケンス番号か変化することはないと思います。

どうしても見たければ、MAC層からトランスポート層へデータを受け渡す箇所のソースコードを参考にして、
MAC層におけるデータ部からトランスポート層のヘッダ情報(TCPシーケンス番号)を参照している部分を、
MAC層のソースコードに無理やり入れるしかないと思います。
musen
投稿日時: 2007/6/24 22:44
新米
登録日: 2006/10/5
居住地:
投稿: 19
Re: MAC層でセグメントのシーケンス番号を出力させる方法について
情報が少なくて申し訳なかったです。
TCPのシーケンス番号のことです。
中継端末でシーケンス番号が変化することはたしかにないです。
私が見たいのは中継端末がフレームを送信しロスしたときにフレームを再送信すると思うのですがMAC層レベルではどのTCPのシーケンス番号のセグメントを再送しているかがわかりません。MAC層での再送信時におけるTCPのシーケンス番号を出力させたいと思っています。
よろしくお願いいたします。
mast
投稿日時: 2007/6/25 12:14
一人前
登録日: 2005/4/7
居住地:
投稿: 93
Re: MAC層でセグメントのシーケンス番号を出力させる方法について
私ならこんな風にやるかなー、という程度ですが、以下、参考までに…
(改造を加えて動かしたわけではないのでちゃんと動作するかどうかは知りません)

クロスレイヤ的な処理をする(他のレイヤの情報を使って特定レイヤの処理をする)には、まずはMessage構造体にレイヤ毎のヘッダ位置を保持するフィールドを持たせるのが一番手っ取り早いのではないかと思います。Linuxのパケットデータ構造であるソケットバッファ(struct sk_buff@include/linux/skbuff.h)がそんな感じになってるので、本気で実装する場合には参考になるかもしれません。例えば以下のような感じで出来そうな気がしないでもないです…

■1 message.hで、
Message構造体に各レイヤのプロトコルタイプ/ヘッダポインタを格納するフィールドを追加
struct message_str
{
    Message*  next; // For kernel use only.
    ...
    // Users should not modify anything above this line.
    int mac_protocol_type       // Newly added
    void *mac_hdr               // Newly added
    int network_protocol_type   // Newly added
    void *network_hdr           // Newly added
    int transport_protocol_type // Newly added
    void *transport_hdr         // Newly added
};



■2 message.h/message.cppに以下の関数宣言/定義を追加
// Retrun the ProtocolType of a specific layer
int MESSAGE_GetMacProtocolType(Node* node, Message* msg)
{
	return msg->mac_protocol_type;
}

int MESSAGE_GetNetworkProtocolType(Node* node, Message* msg)
{
	return msg->network_protocol_type;
}

int MESSAGE_GetTransportProtocolType(Node* node, Message* msg)
{
	return msg->transport_protocol_type;
}

// Retrun the pointer to the ProtocolHeader for a specific layer of this packet
void* MESSAGE_GetMacHeader(Node* node, Message* msg)
{
	return msg->mac_hdr;
}

void* MESSAGE_GetNetworkHeader(Node* node, Message* msg)
{
	return msg->network_hdr;
}

void* MESSAGE_GetTransportHeader(Node* node, Message* msg)
{
	return msg->transport_hdr;
}


■3 各プロトコルが自身のヘッダをパケットに追加する(MESSAGE_AddHeader()等を呼び出す)箇所で、上記で新たにMessage構造体に追加したプロトコルタイプ/ヘッダポインタフィールドを設定
(以下はTCPの場合の例:TCPはMESSAGE_AddHeader()の呼び出しでヘッダを付けるのではないので注意)
void tcp_output(
    Node *node,
    struct tcpcb *tp,
    UInt32 tcp_now,
    struct tcpstat *tcp_stat)
{
    ...
    // Send the packet to the IP model.
    // Remove the ipovly pseudo-header beforehand.
    {
        ...
        anEcnCapablePacket = TransportTcpSetEcnCapablePacket(node, tp, ti);
        TransportTcpSetEcnEchoAndCWR(node, tp, ti);

        TransportTcpTrace(node, tp, ti, "output");
        if (anEcnCapablePacket) {
            TransportTcpTrace(node, 0, 0, "ECT");
        }
        TransportTcpTrace(node, tp, ti, "variables");

        MESSAGE_RemoveHeader(node, msg, sizeof(struct ipovly), TRACE_TCP);

        memcpy(
            MESSAGE_ReturnPacket(msg),
            &ti->ti_t,
            sizeof (struct tcphdr));

        memcpy(
            MESSAGE_ReturnPacket(msg) + sizeof (struct tcphdr),
            (ti + 1), optlen);

        msg->transport_protocol_type = TransportProtocol_TCP; // Newly added
        msg->transport_hdr = MESSAGE_ReturnPacket(msg);       // Newly added

        // Hack solution for TCP trace.
        msg->headerSizes[msg->numberOfHeaders] -= sizeof(struct ipovly);
        msg->numberOfHeaders++;
        ...
    }
    ...
}


■4 クロスレイヤ処理したい箇所で以下のようにして他レイヤのプロトコルヘッダを取得
    ...
    switch (MESSAGE_GetTransportProtocolType(node, msg))
    {
        case TransportProtocol_UDP:
        {
            TransportUdpHeader* udphdr = (TransportUdpHeader *) MESSAGE_GetTransportHeader(node, msg);
             ...
        }
        case TransportProtocol_TCP:
        {
            struct tcphdr* tcphdr = (struct tcphdr *) MESSAGE_GetTransportHeader(node, msg);
            ...
        }
        case TransportProtocol_RSVP:
        default:
        {
            // NOOP
            break;
        }
    }
    ...

musen
投稿日時: 2007/6/27 10:35
新米
登録日: 2006/10/5
居住地:
投稿: 19
Re: MAC層でセグメントのシーケンス番号を出力させる方法について
mastさん
返信ありがとうございました。返信遅くなりまして申し訳なかったです。非常に参考になりました。
mastさんがご教授して下さった方式でできると思い試してみました。
mastさんが書いてくださった1〜3を指定の場所に挿入し
4.クロスレイヤ処理したい箇所で以下のようにして他レイヤのプロトコルヘッダを取得をmac_dot11.cppの以下の場所に挿入しました。
switch (dot11->state) {
        case DOT11_S_WF_DIFS_OR_EIFS: {
            if (dot11->BO == 0) {
                if (MacDot11StationHasFrameToSend(dot11)) {

                    MacDot11StationTransmitFrame(node, dot11);
printf("MacDot11StationTransmitFrame(node, dot11)を通過\n");
	switch(MESSAGE_GetTransportProtocolType(node,msg))
{
printf("MESSAGE_GetTransportProtocolType(node,msg)通過\n");
					
case TransportProtocol_TCP:
{
printf("TransportProtocol_TCP\n");
			
struct tcphdr* tcphdr=(struct tcphdr *MESSAGE_GetTransportHeader(node,msg);

}

default:
{
 break;
}


qualnetをはしらせた所
printf("MacDot11StationTransmitFrame(node, dot11)を通過\n")は出力されるのですが、("MESSAGE_GetTransportProtocolType(node,msg)通過\n")は出力されません。つまりbreakの方を通っています。
case TransportProtocol_TCP:の方を通ってくれません。
使用しているアプリケーションはFTP/GENERICでTCPはrenoを使用しています。
もし原因がわかるのであればご教授していただきたいです。
よろしくお願いいたします。


mast
投稿日時: 2007/6/27 10:58
一人前
登録日: 2005/4/7
居住地:
投稿: 93
Re: MAC層でセグメントのシーケンス番号を出力させる方法について
なぜでしょうね?
うまくいきそうに見えるのですが…
私にも原因の見当がつきません。

・MESSAGE_GetTransportProtocolType(node,msg)が何を返しているか?
printf("%d = MESSAGE_GetTransportProtocolType()\n", MESSAGE_GetTransportProtocolType(node,msg))

・tcp_output()でちゃんとmsg->transport_protocol_typeにTransportProtocol_TCP(=1?)がセットされているか?
・そもそもtcp_output()でセットしている箇所を通っているか?

といったあたりからまず調べていくのがよいかと思います。
musen
投稿日時: 2007/6/27 13:07
新米
登録日: 2006/10/5
居住地:
投稿: 19
Re: MAC層でセグメントのシーケンス番号を出力させる方法について
mastさん、返信ありがとうございます。
mastさんに指摘していただいたところを調べていきたいと思っています。
4 クロスレイヤ処理したい箇所で以下のようにして他レイヤのプロトコルヘッダを取得を教えていただいた部分をmac_dot11.cppに追加する際に

void MacDot11HandleTimeout(
    Node* node,
    MacDataDot11* dot11)


void MacDot11HandleTimeout(
    Node* node,
    MacDataDot11* dot11,
	Message* msg)  //追加
{
	

    if (dot11->beaconIsDue
        && MacDot11StationCanHandleDueBeacon(node, dot11))
    {
        return;
    }

    if (dot11->useDvcs) {
        //
        // A Packet sequence could possibly have failed,
        // go back to sending/receiving omnidirectionally if not already
        // doing so.
        //
        PHY_UnlockAntennaDirection(
            node, dot11->myMacData->phyNumber);
    }

    switch (dot11->state) {
        case DOT11_S_WF_DIFS_OR_EIFS: {
            if (dot11->BO == 0) {
                if (MacDot11StationHasFrameToSend(dot11)) {

                    MacDot11StationTransmitFrame(node, dot11);
					printf("MacDot11StationTransmitFrame(node, dot11)を通過\n");
switch(MESSAGE_GetTransportProtocolType(node,msg))
{
printf("MESSAGE_GetTransportProtocolType(node,msg)通過\n");
 case TransportProtocol_TCP:
{
 printf("TransportProtocol_TCP\n");
struct tcphdr* tcphdr=(struct tcphdr *MESSAGE_GetTransportHeader(node,msg);

に変更しました。
void MacDot11HandleTimeout(
Node* node,
MacDataDot11* dot11)
を使用する箇所は全て以下のように変更しました。
void MacDot11HandleTimeout(
Node* node,
MacDataDot11* dot11,
Message* msg)
変更すると何か悪影響を及ぼすでしょうか?
よろしくお願いいたします。
mast
投稿日時: 2007/6/27 18:52
一人前
登録日: 2005/4/7
居住地:
投稿: 93
Re: MAC層でセグメントのシーケンス番号を出力させる方法について
他への悪影響はありません。
が、うまくいかない原因が恐らく分かりました。

そのmsgが指し示している先は、パケットデータのほうではなく、タイマーイベント通知のために使われてるMessageインスタンスです。
パケットデータは、dot11->currentMessageが指し示しています。

ですので、MacDot11HandleTimeout()関数の引数にmsgを追加する必要はないと思います。
musen
投稿日時: 2007/6/28 1:30
新米
登録日: 2006/10/5
居住地:
投稿: 19
Re: MAC層でセグメントのシーケンス番号を出力させる方法について
mastさん、何度も返信ありがとうございます。
mastさんの仰られた通りに
void MacDot11HandleTimeout内にstruct message_str *msgを宣言し、
msg=dot11->currentMessageとし、MacDot11Handle Timeout()関数に追加したmsgを削除するとコンパイルは通りました。
しかし、qualnetを起動し走らせるとすぐにシミュレーションがとまってしまいます。
コンパイルが通っているためどこでエラーが起こっているのかわからない状況です。
アドバイス等よろしくお願いいたします。
mast
投稿日時: 2007/6/29 10:44
一人前
登録日: 2005/4/7
居住地:
投稿: 93
Re: MAC層でセグメントのシーケンス番号を出力させる方法について
musenさんの書かれた情報からだけではさすがになんとも…

「シミュレーションがとまる」というのは、
1.エラーダイアログが出て止まる
という意味ではなく、
2.シミュレーションが進まなくなる(シミュレーション時間が一向に進まなくなる)
という意味でしょうか?

1であれば、そのエラー出力の情報からどの辺で止まっているかの目星がつけられる可能性はあります。
2であれば、どこかで無限ループに陥っているということになります。
その場合、コンソールへの出力が皆無かそうでないかによって、ある程度原因箇所の特定は可能です。
コンソールに全く何も表示されていない状態で止まっているのであれば、それは少なくとも初期化フェーズ(configファイル読み込み時点)で無限ループに陥っていることになります。「Initialization completed in XXX sec」という内容が出力されていれば、少なくとも初期化フェーズは通過しています。(さらに「Current Sim Time[s] = ...」という内容がいくつか出力されていれば、少なくともその時刻までは無限ループに陥ることなくシミュレーションが進んでいたことになります)。この場合、あとはパケット送信処理ルーチンをTCPから順に下位レイヤに向かって順に追っていきどの辺りで無限ループが発生しているかを見極めていくのが最短アプローチかと思います。(デバッガを使ってブレークポイントを張りながら試してみたり、適当にprintf文を突っ込んで試してみたりしてみてください。)

それなりに骨の折れる作業にはなりますが、がんばってみてください・・・
(1) 2 »
スレッド表示 | 新しいものから 前のトピック | 次のトピック | トップ
Copyright c KOZO KEIKAKU ENGINEERING Inc. All Rights Reserved.
XOOPS Cube PROJECT