ネットワーク・コーナ ご購入はこちら ダウンロード・データあります パケットづくりではじめる ネットワーク入門 第 16 回 インターフェースの種別を知る 本連載はネットワーク上を流れるパケットを直接扱 うようなツールを自作しつつ,ネットワークの仕組み を勉強していきます.テーマは「自作」,「現物ベー ス」 , 「動く感動」の三つです.ネットワークにはイー サネットと IP を想定しています. ● 前回までの自作ルータ・プログラムで目を つぶっていたこと…IPヘッダ取得時のムダ処理 前回までは自作の簡易ルータに NAT 機能を追加し ていきました.具体的には NAPT や複数プロトコル (TCP/UDP/ICMP)の対応,ポート・フォワーディン グなどの機能を追加しました.これにより,一般的な ブロードバンド・ルータに実装されている機能がどの ような動作をするのか,実装を通して知ることができ ました. しかし前回までのプログラムには,実は問題点があ ります.ヘッダのアラインメントを考慮しなくて済む ようにヘッダ情報を毎回コピーして処理しているた め,無駄が多いという点です.これを防ぐためには, L2 ネットワークの種別に応じたオフセット位置から パケットを格納し,IP ヘッダの先頭がアラインメン トにそろうようにする必要があります. ● 今回やること 今回はルータから離れて,L2 ネットワークの種別 リスト 1 TCP ヘッダの解析処理(ip-analyzer.c) static void proc_tcp(pktbuf_t pktbuf) { struct tcphdr tcphdr; char *p = pktbuf_get_header(pktbuf); /* オプション領域からヘッダ位置を取得 */ memcpy(&tcphdr, p, sizeof(tcphdr)); printf("TCP¥tsrc port: %d¥n", ntohs(tcphdr.th_sport)); printf("¥tdst port: %d¥n", ntohs(tcphdr.th_dport)); printf("¥tseq number: %u¥n", ntohl(tcphdr.th_seq)); printf("¥tack number: %u¥n", ntohl(tcphdr.th_ack)); printf("¥tflags: 0x%02x¥n", tcphdr.th_flags); } 2016 年 11 月号 坂井 弘亮 を知る方法と,それを利用して受信バッファの先頭を 調整する方法について説明します. プログラミングの課題…IP ヘッダを 効率良く取得するのは難しい ● ホントは避けたい…memcpy による非効率な IP ヘッダ操作 リスト 1 は,連載の第 3 回で作成した簡易アナライ ザ(ネットワーク・パケットのアナライザ)のソース コード(ip-analyzer.c)中にある TCP ヘッダの 解析部分です.今回問題にするのは,関数内の 3 行目 にある memcpy() の呼び出しです. リスト 1 では関数内でローカルに定義した構造体に パケットのヘッダ部分を一時的にコピーした上で,コ ピー先からヘッダ情報を取得しています. これはヘッダのアラインメント問題を回避するため の 対 策 で す. し か し memcpy() に よ る メ モ リ・ コ ピーが行われてしまうため無駄があり,処理速度の観 点からも非常に不利だと言えます. そして前回までに作成してきたツール類のソース コードには,実はこのようなコピー処理が多くありま す.つまり全体的に,無駄な処理が多く残っているわ けです. ● CPU/OS に依存するメモリ・アクセスの問題 …4 バイト・アラインメントずれ そもそもアラインメント問題とは,どのようなもの でしょうか? 通常,リスト 2 のように整数型の変数を定義した場 合,その変数が配置されているメモリ上のアドレス (&val)は,変数のサイズ(sizeof(val))の倍数 の値になっています.つまりリスト 2 の例では,if 文の条件は真になります. リスト 2 整数型の変数を定義した場合 int val; if ((((int)&val) % sizeof(val)) == 0) printf("alignment OK.¥n"); 本連載のプログラムのソースコードは以下の筆者のホームページからダウンロードでき ます.ライセンスは KL-01 というもので,組み込み機器などでも自由に利用できます. http://kozos.jp/books/interface/ethernet2/ 107
© Copyright 2024 ExpyDoc