TCP実装のつづき。
TCP通信中にパケットモニタを起動して、相互のデータの内容をログしてみました。
これはかなり強力なデバッグ方法でプログラム内で変数モニタしなくても良くわかります。
ボードから送り出されるパケットのデータをよくよく見てみるといろいろ問題がわかってきました。
(1)数値のバイト並びが逆
イーサネットのフレーム内では数値は上位バイトから転送される。
なのでインテルフォーマットの16ビットや32ビットの数値はバイト並びを
入れ替えてからメモリにセットしなければならない。
(2)シーケンス番号(SEQ)、確認応答番号(ACK)の値が変
TCPパケット受信で生成されるソケット構造体と受信バッファのフォーマットが
違っていた。ソケットではunsigned long、バッファは char[]の配列なのにそのまま
代入していたのでむちゃくちゃな数値になっていた
socket.seq_no = rxtcp.seq_no; ではダメで
socket.seq_no = cnvendian32(*(unsigned long *)rxtcp.seq_no);
という具合に配列を4バイト変数と見た上でさらにバイト並び替え。
パケットを生成するときは逆に
*(unsigned long *)txtcp.seq_no = cnvendian32(socket.seq_no); となる
あとは代入する構造体やサムの計算方法を間違えていたりで、
これらは後からもってきたTCP処理部分を移植した時のバグでした。
修正後、クライアントから接続要求、切断要求を出すとボード内のTCP状態が
LISTEN→SYN_RCVD→ESTABLISHED→CLOSE と正しく遷移しているようです。