小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

ip_queue_xmit簡(jiǎn)單注釋

 enchen008 2013-09-11

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

而udp不一樣,它的數(shù)據(jù)包分段沒(méi)有完成需要下層幫忙,
因此udp使用的ip_append_data函數(shù)要復(fù)雜得多。
下面簡(jiǎn)單注釋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.     //首先檢測(cè)skb->rtable是否為空,不為空說(shuō)明已經(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.     //檢測(cè)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ù),等看完路由這一章再回來(lái)補(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.     //增加路由緩存引用計(jì)數(shù)   
  49.     skb->dst = dst_clone(&rt->u.dst);  
  50. packet_routed:  
  51.     //如果sk_buff指向的sock的opt中包含嚴(yán)格源站路由選項(xiàng),   
  52.     //而剛剛查找到的路由項(xiàng)目標(biāo)地址又不等于網(wǎng)關(guān)地址的話前往no_route   
  53.     //說(shuō)明嚴(yán)格源站路由無(wú)法滿足   
  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首部包括選項(xiàng)的空間給ip報(bào)頭,并將   
  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首部填入版本號(hào)4,ip首部長(zhǎng)度5(20字節(jié),這個(gè)值在后面要根據(jù)選項(xiàng)   
  63.     //的長(zhǎng)度增加),以及服務(wù)類型   
  64.     *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff));  
  65.     //如果socket要求ip不分片(這是通過(guò)檢測(cè)sock->pmtudisc做到的,   
  66.     //如果使用路徑mtu發(fā)現(xiàn)則說(shuō)明要求不分片,否則允許分片)并且參數(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則從路由項(xiàng)的metrics獲得),   
  73.     //protocol(從sock->sk_protocol),源地址,目標(biāo)地址(兩者都從路由項(xiàng)獲得)   
  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首部長(zhǎng)度中加上選項(xiàng)長(zhǎng)度,   
  80.     //并且調(diào)用ip_options_build向IP首部中寫入ip選項(xiàng)   
  81.     if (opt && opt->optlen) {  
  82.         iph->ihl += opt->optlen >> 2;  
  83.         //這個(gè)函數(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回繞采取的策略是對(duì)于每一個(gè)ip   
  88.     //分配一個(gè)inet_peer結(jié)構(gòu),在這個(gè)inet_peer中記錄針對(duì)這個(gè)ip的id號(hào),   
  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. }  

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

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多