乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      ip_queue_xmit簡單注釋

       enchen008 2013-09-11

      在ULNI上圖中寫的清楚,此函數(shù)一般由tcp或sctp調(diào)用
      上層工作都已經(jīng)做好了,只差ip頭及以下部分的填充
      tcp可以做到這一點(diǎn),因為有mss的限制以及自己的一些控制包大小的算法

      而udp不一樣,它的數(shù)據(jù)包分段沒有完成需要下層幫忙,
      因此udp使用的ip_append_data函數(shù)要復(fù)雜得多。
      下面簡單注釋ip_queue_xmit函數(shù)

       
      1. int ip_queue_xmit(struct sk_buff *skb, int ipfragok)  
      2. {  
      3.     struct sock *sk = skb->sk;  
      4.     struct inet_sock *inet = inet_sk(sk);  
      5.     struct ip_options *opt = inet->opt;  
      6.     struct rtable *rt;  
      7.     struct iphdr *iph;  
      8.     /* Skip all of this if the packet is already routed, 
      9.      * f.e. by something like SCTP. 
      10.      */  
      11.     //首先檢測skb->rtable是否為空,不為空說明已經(jīng)指定了路由,跳到packet_routed繼續(xù)執(zhí)行   
      12.     //根據(jù)上面注釋,似乎sctp可能提前指定路由   
      13.     rt = skb->rtable;  
      14.     if (rt != NULL)  
      15.         goto packet_routed;  
      16.     /* Make sure we can route this packet. */  
      17.     //檢測socket路由合法性,如果不合法也需要重新查找路由   
      18.     rt = (struct rtable *)__sk_dst_check(sk, 0);  
      19.     if (rt == NULL) {  
      20.         __be32 daddr;  
      21.         /* Use correct destination address if we have options. */  
      22.         daddr = inet->daddr;  
      23.         if(opt && opt->srr)  
      24.             daddr = opt->faddr;  
      25.         {  
      26.             struct flowi fl = { .oif = sk->sk_bound_dev_if,  
      27.                         .nl_u = { .ip4_u =  
      28.                               { .daddr = daddr,  
      29.                             .saddr = inet->saddr,  
      30.                             .tos = RT_CONN_FLAGS(sk) } },  
      31.                         .proto = sk->sk_protocol,  
      32.                         .flags = inet_sk_flowi_flags(sk),  
      33.                         .uli_u = { .ports =  
      34.                                { .sport = inet->sport,  
      35.                              .dport = inet->dport } } };  
      36.             /* If this fails, retransmit mechanism of transport layer will 
      37.              * keep trying until route appears or the connection times 
      38.              * itself out. 
      39.              */  
      40.             security_sk_classify_flow(sk, &fl);  
      41.             //下面是主要的出口路由查找函數(shù),等看完路由這一章再回來補(bǔ)充   
      42.             if (ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 0))  
      43.                 goto no_route;  
      44.         }  
      45.         //下面函數(shù)做的其中一件事是sk->sk_dst_cache = dst;并釋放舊的dst緩存   
      46.         sk_setup_caps(sk, &rt->u.dst);  
      47.     }  
      48.     //增加路由緩存引用計數(shù)   
      49.     skb->dst = dst_clone(&rt->u.dst);  
      50. packet_routed:  
      51.     //如果sk_buff指向的sock的opt中包含嚴(yán)格源站路由選項,   
      52.     //而剛剛查找到的路由項目標(biāo)地址又不等于網(wǎng)關(guān)地址的話前往no_route   
      53.     //說明嚴(yán)格源站路由無法滿足   
      54.     if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway)  
      55.         goto no_route;  
      56.     /* OK, we know where to send it, allocate and build IP header. */  
      57.     //在skb的數(shù)據(jù)中預(yù)留出ip首部包括選項的空間給ip報頭,并將   
      58.     //skb->network_header指向它   
      59.     skb_push(skb, sizeof(struct iphdr) + (opt ? opt->optlen : 0));  
      60.     skb_reset_network_header(skb);  
      61.     iph = ip_hdr(skb);  
      62.     //在ip首部填入版本號4,ip首部長度5(20字節(jié),這個值在后面要根據(jù)選項   
      63.     //的長度增加),以及服務(wù)類型   
      64.     *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff));  
      65.     //如果socket要求ip不分片(這是通過檢測sock->pmtudisc做到的,   
      66.     //如果使用路徑mtu發(fā)現(xiàn)則說明要求不分片,否則允許分片)并且參數(shù)ipfragok等于0,   
      67.     //那么將DF標(biāo)志置1,否則清0   
      68.     if (ip_dont_fragment(sk, &rt->u.dst) && !ipfragok)  
      69.         iph->frag_off = htons(IP_DF);  
      70.     else  
      71.         iph->frag_off = 0;  
      72.     //設(shè)置ip首部的ttl(從sock的uc_ttl獲得,如果小于0則從路由項的metrics獲得),   
      73.     //protocol(從sock->sk_protocol),源地址,目標(biāo)地址(兩者都從路由項獲得)   
      74.     iph->ttl      = ip_select_ttl(inet, &rt->u.dst);  
      75.     iph->protocol = sk->sk_protocol;  
      76.     iph->saddr    = rt->rt_src;  
      77.     iph->daddr    = rt->rt_dst;  
      78.     /* Transport layer set skb->h.foo itself. */  
      79.     //若opt不為NULL,則在ip首部長度中加上選項長度,   
      80.     //并且調(diào)用ip_options_build向IP首部中寫入ip選項   
      81.     if (opt && opt->optlen) {  
      82.         iph->ihl += opt->optlen >> 2;  
      83.         //這個函數(shù)值得一看,opt是從inet_sock中獲得的   
      84.         ip_options_build(skb, opt, inet->daddr, rt, 0);  
      85.     }  
      86.     //調(diào)用ip_select_ident_more填入IP首部的id字段   
      87.     //關(guān)于ip的id在ULNI上講得很清楚,Linux為了防止id回繞采取的策略是對于每一個ip   
      88.     //分配一個inet_peer結(jié)構(gòu),在這個inet_peer中記錄針對這個ip的id號,   
      89.     //這樣可以很大程度上減緩id回繞的速度,但是仍不能完全避免   
      90.     ip_select_ident_more(iph, &rt->u.dst, sk,  
      91.                  (skb_shinfo(skb)->gso_segs ?: 1) - 1);  
      92.     skb->priority = sk->sk_priority;  
      93.     skb->mark = sk->sk_mark;  
      94.     return ip_local_out(skb);  
      95. no_route:  
      96.     IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);  
      97.     kfree_skb(skb);  
      98.     return -EHOSTUNREACH;  
      99. }  

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多