Linux核心分析

來源:互聯網
上載者:User

核心版本:2.6.34

ICMP模組比較簡單,要注意的是icmp的速率限制策略,向IP層傳輸資料ip_append_data()和 ip_push_pending_frames()。

在net/ipv4/af_inet.c中的inet_init()註冊icmp協議,從這裡也可以看出,ICMP模組是綁 定在IP模組之上的。inet_add_protocol()會將icmp_protocol加入到全域量inet_protos中。

if (inet_add_protocol(&icmp_protocol, IPPROTO_ICMP) < 0)      printk(KERN_CRIT "inet_init: Cannot add ICMP protocol\n");     icmp_protocol定義如下:     static const struct net_protocol icmp_protocol = {      .handler = icmp_rcv,      .no_policy = 1,      .netns_ok = 1,     };

除了註冊icmp協議,還要對icmp模組初始化,這部分由icmp_init()完成。

if (icmp_init() < 0)      panic("Failed to create the ICMP control socket.\n");

icmp_init()函數做的事很簡單,register_pernet_subsys(&icmp_sk_ops),而註冊icmp網路子系統過程中會調用 icmp_sk_ops.init(即icmp_sk_init函數)來完成它的初始化,下面具體看icmp_sk_init()函數。

首先為net為配CPU數目 (nr_cpu_ids)個struct sock結構體空間,這裡的net是全域的網路名稱,一般是init_inet。
net->ipv4.icmp_sk = kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL);

每個CPU i,它的sock結構體位於net中的icmp_sk[i]。於每 個CPU i,初始化剛剛分配的icmp_sk[i]:

 -第一步,inet_ctl_sock_create()建立sk,並在net->ipv4.icmp_sk[i] = sk中將其賦值給icmp_sk[i]。

 -第二步:ICMP發送緩衝區大小sk_sndbuf設定為128K

for_each_possible_cpu(i) {      struct sock *sk;      err = inet_ctl_sock_create(&sk, PF_INET,         SOCK_RAW, IPPROTO_ICMP, net);      if (err < 0)       goto fail;               net->ipv4.icmp_sk[i] = sk;      sk->sk_sndbuf =       (2 * ((64 * 1024) + sizeof(struct sk_buff)));      sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);      inet_sk(sk)->pmtudisc = IP_PMTUDISC_DONT;     }

忽略發往廣播位址的icmp echo報文;忽略發往廣播位址的錯誤的響應報文;

net->ipv4.sysctl_icmp_echo_ignore_all = 0;     net->ipv4.sysctl_icmp_echo_ignore_broadcasts = 1;     net->ipv4.sysctl_icmp_ignore_bogus_error_responses = 1;

設定icmp處理速率,這裡的ratelimit和ratemask參 數在後面限速處理時會具體用到。

net->ipv4.sysctl_icmp_ratelimit = 1 * HZ;     net->ipv4.sysctl_icmp_ratemask = 0x1818;     net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr = 0;

初始化工作完成後,還是從icmp的接收開始,icmp_rcv 完成icmp報文的處理。
取得icmp前序,此時skb->transport_header是在IP模組處理中的ip_local_deliver_finish() 將其設定為了指向icmp前序的位置。

icmph = icmp_hdr(skb);

根據icmp的類型type交由不同的處理函數去完成。

icmp_pointers[icmph->type].handler(skb);

icmp_pointers是在icmp.c中定義的全域量,部分如下:

static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = {      [ICMP_ECHOREPLY] = {       .handler = icmp_discard,      },      [1] = {       .handler = icmp_discard,       .error = 1,      },     ……     }

比如對於收到的icmp報文type為0或1(響應回覆或目的不可達),協議棧要做的就是丟棄掉它 – icmp_discard()。下 面以icmp echo和icmp timestamp為例說明。

收到icmp echo報文執行icmp_echo()

icmp_param是回複時資訊,它直接 拷貝了echo的ICMP前序icmp_hdr(skb),僅僅改變了前序的type = ICMP_ECHO_REPLY,然後調用icmp_reply()處理髮送。

struct icmp_bxm icmp_param;     icmp_param.data.icmph    = *icmp_hdr(skb);     icmp_param.data.icmph.type = ICMP_ECHOREPLY;     icmp_param.skb     = skb;     icmp_param.offset    = 0;     icmp_param.data_len    = skb->len;     icmp_param.head_len    = sizeof(struct icmphdr);     icmp_reply(&icmp_param, skb);

收到icmp timestamp報文後執行icmp_timestamp()

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.