IPv4 受信処理
Rev.4を表示中。最新版はこちら。
1. 概要
IPv4の受信処理と中継処理のメモ。
2. 処理の流れ
IPパケットを受信した時の処理の流れを図1に示す。

図1 受信時の流れ
3. 受信処理
3.1 受信開始
受信したIPv4パケットはip_rcv()に渡される。ip_rcv()ではIPヘッダの内容をチェックした後、NF_IP_PRE_ROUTINGフック処理を行った後、ip_rcv_finish()を呼び出す。
ip_rcv_finish()では、IPパケットのDstIPでルーティングテーブルを検索を行なう。ルーティングテーブルにエントリがあった場合は、最後にdst_input()を呼ぶ。
dst_input()はヒットしたルーティングエントリに登録されている受信ハンドラを呼び出して、自システム宛の受信か中継処理を行なう。自システム 宛の経路にはip_local_deliver()、その他の経路にはip_forward()が設定されている。
ip_rcv_finish()の処理概要
if (likely(skb->dst == NULL)) {
/* ルーティングテーブルを検索 */
int err = ip_route_input()
if (unlikely(err)) {
/* 経路がないなどの理由でエラーが返った場合は廃棄 */
goto drop;
}
}
/* IPヘッダにオプションがあれば処理をする
* ここではSourceRoutingオプションを処理する
*/
if (iph->ihl > 5 && ip_rcv_options(skb))
goto drop;
/* ヒットしたルーティングエントリに対応するハンドラへ
* 自システム宛ならip_local_deliver()
* 中継ならip_forward()
*/
return dst_input(skb);
drop:
kfree_skb(skb);
return NET_RX_DROP;
3.2 自システム宛のケース - ip_local_deliver()
受信したパケットが自システム宛だった場合は、dst_input()からip_local_deliver()が呼び出される。
ip_local_deliver()では、パケットがフラグメントされていた場合はリアセンブル処理を行ない、ip_local_deliver_finish()を呼び出す。ip_local_deliver_finish()ではIPパケットの上位プロトコルに応じて、上位プロトコル(TCP,UDP,...)の受信ルーチ ンを呼び出す。また、この際RAWソケットが使用されているのであれば、RAWソケットにも受信データを渡す。
{
resubmit:
/* Rawソケットが使用されていた場合、
* Rawソケットの受信ルーチンを呼ぶ */
if (raw_sk && !raw_v4_input(skb, skb->nh.iph, hash))
raw_sk = NULL;
if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) {
/*
* 上位層の受信ルーチンを呼び出し
* TCP tcp_v4_rcv()
* UDP udp_rcv()
* ICMP icmp_rcv()
*/
ret = ipprot->handler(skb);
} else {
/* 該当プロトコルが登録されていない */
if (!raw_sk) {
/* ICMPエラーを返す(DstUnreachable,ProtocolUnReachable) */
} else
IP_INC_STATS_BH(IPSTATS_MIB_INDELIVERS);
kfree_skb(skb);
}
}
