⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 2_4网络代码阅读笔记(5) - china linux forum.htm

📁 包括较少的一些linux下的网络代码阅读笔记
💻 HTM
📖 第 1 页 / 共 3 页
字号:
            EALREADY. <BR>*/ <BR>err = -EINPROGRESS; <BR>break; <BR>} 
            <BR>&gt;&gt;&gt;&gt;return flags&amp;O_NONBLOCK ? 0 : 
            sk-&gt;sndtimeo; 
            <BR>&gt;&gt;&gt;&gt;sk-&gt;sndtimeo在创建socket的时候,在函数sock_init_data里赋值 
            <BR>&gt;&gt;&gt;&gt;sk-&gt;sndtimeo=MAX_SCHEDULE_TIMEOUT;可以通过setsockopt修改 
            <BR>timeo = sock_sndtimeo(sk, flags&amp;O_NONBLOCK); 
            <BR>&gt;&gt;&gt;&gt;判断TCP状态机是不是TCPF_SYN_SENT或者TCPF_SYN_RECV <BR>if 
            ((1&lt;<SK->state)&amp;(TCPF_SYN_SENT|TCPF_SYN_RECV)) { <BR>/* Error 
            code is set above */ 
            <BR>&gt;&gt;&gt;&gt;如果为非阻塞,或者(inet_wait_for_connect好象不会返回0,除非time0=0. 
            <BR>&gt;&gt;&gt;&gt;看看后面的代码) <BR>if (!timeo || 
            !inet_wait_for_connect(sk, timeo)) <BR>goto out; <BR>err = 
            sock_intr_errno(timeo); <BR>if (signal_pending(current)) <BR>goto 
            out; <BR>} <BR>/* Connection was closed by RST, timeout, ICMP error 
            <BR>* or another process disconnected us. <BR>*/ <BR>if 
            (sk-&gt;state == TCP_CLOSE) <BR>goto sock_error; <BR>/* sk-&gt;err 
            may be not zero now, if RECVERR was ordered by user <BR>* and error 
            was received after socket entered established state. <BR>* Hence, it 
            is handled normally after connect() return successfully. <BR>*/ 
            <BR>&gt;&gt;&gt;&gt;将socket的状态置为SS_CONNECTED <BR>sock-&gt;state = 
            SS_CONNECTED; <BR>err = 0; <BR>out: <BR>release_sock(sk); <BR>return 
            err; <BR>sock_error: <BR>err = sock_error(sk) ? : -ECONNABORTED; 
            <BR>sock-&gt;state = SS_UNCONNECTED; <BR>if 
            (sk-&gt;prot-&gt;disconnect(sk, flags)) <BR>sock-&gt;state = 
            SS_DISCONNECTING; <BR>goto out; <BR>} 
            <BR><BR><BR>&gt;&gt;&gt;&gt;当syn数据报发送出去后,等待连接建立 <BR>static long 
            inet_wait_for_connect(struct sock *sk, long timeo) <BR>{ 
            <BR>DECLARE_WAITQUEUE(wait, current); <BR>&gt;&gt;&gt;&gt;当前进程为可中断 
            <BR>__set_current_state(TASK_INTERRUPTIBLE); 
            <BR>add_wait_queue(sk-&gt;sleep, &amp;wait); <BR>/* Basic 
            assumption: if someone sets sk-&gt;err, he _must_ <BR>* change state 
            of the socket from TCP_SYN_*. <BR>* Connect() does not allow to get 
            error notifications <BR>* without closing the socket. <BR>*/ 
            <BR>&gt;&gt;&gt;&gt;如果状态机仍为TCP_SYN_SEND或者TCP_SYN_RECV,则睡眠等待状态变化 
            <BR>while ((1&lt;<SK->state)&amp;(TCPF_SYN_SENT|TCPF_SYN_RECV)) { 
            <BR>release_sock(sk); <BR>timeo = schedule_timeout(timeo); 
            <BR>lock_sock(sk); <BR>if (signal_pending(current) || !timeo) 
            <BR>break; <BR>set_current_state(TASK_INTERRUPTIBLE); <BR>} 
            <BR>__set_current_state(TASK_RUNNING); 
            <BR>remove_wait_queue(sk-&gt;sleep, &amp;wait); <BR>return timeo; 
            <BR>} <BR><BR>下面是tcp_v4_connect: <BR><BR>/* This will initiate an 
            outgoing connection. */ <BR>int tcp_v4_connect(struct sock *sk, 
            struct sockaddr *uaddr, int addr_len) <BR>{ <BR>struct tcp_opt *tp = 
            &amp;(sk-&gt;tp_pinfo.af_tcp); <BR>struct sockaddr_in *usin = 
            (struct sockaddr_in *) uaddr; <BR>struct sk_buff *buff; <BR>struct 
            rtable *rt; <BR>u32 daddr, nexthop; <BR>int tmp; <BR>int err; 
            <BR>................... <BR>&gt;&gt;&gt;&gt;uaddr是用户传入的服务器的地址 
            <BR>nexthop = daddr = usin-&gt;sin_addr.s_addr; <BR>if 
            (sk-&gt;protinfo.af_inet.opt &amp;&amp; 
            sk-&gt;protinfo.af_inet.opt-&gt;srr) { <BR>if (daddr == 0) 
            <BR>return -EINVAL; <BR>nexthop = 
            sk-&gt;protinfo.af_inet.opt-&gt;faddr; <BR>} 
            <BR>&gt;&gt;&gt;&gt;根据源地址、目的地址、TOS以及出口网络设备选择一条路由 <BR>tmp = 
            ip_route_connect(&amp;rt, nexthop, sk-&gt;saddr, 
            <BR>RT_TOS(sk-&gt;protinfo.af_inet.tos)|RTO_CONN|sk-&gt;localroute, 
            sk-&gt;bound_d <BR>ev_if); <BR>if (tmp &lt; 0) <BR>return tmp; 
            <BR>if (rt-&gt;rt_flags&amp;(RTCF_MULTICAST|RTCF_BROADCAST)) { 
            <BR>ip_rt_put(rt); <BR>return -ENETUNREACH; <BR>} 
            <BR>&gt;&gt;&gt;&gt;old_dst = sk-&gt;dst_cache; 
            <BR>&gt;&gt;&gt;&gt;sk-&gt;dst_cache = dst; 
            <BR>&gt;&gt;&gt;&gt;dst_release(old_dst); <BR>__sk_dst_set(sk, 
            &amp;rt-&gt;u.dst); <BR>sk-&gt;route_caps = 
            rt-&gt;u.dst.dev-&gt;features; <BR>if (!sk-&gt;protinfo.af_inet.opt 
            || !sk-&gt;protinfo.af_inet.opt-&gt;srr) <BR>daddr = rt-&gt;rt_dst; 
            <BR>err = -ENOBUFS; <BR>&gt;&gt;&gt;&gt;分配syn数据报文sk_buff <BR>buff = 
            alloc_skb(MAX_TCP_HEADER + 15, GFP_KERNEL); <BR>if (buff == NULL) 
            <BR>goto failure; <BR>&gt;&gt;&gt;&gt;源地址 <BR>if (!sk-&gt;saddr) 
            <BR>sk-&gt;saddr = rt-&gt;rt_src; <BR>sk-&gt;rcv_saddr = 
            sk-&gt;saddr; <BR>if (tp-&gt;ts_recent_stamp &amp;&amp; sk-&gt;daddr 
            != daddr) { <BR>/* Reset inherited state */ <BR>tp-&gt;ts_recent = 
            0; <BR>tp-&gt;ts_recent_stamp = 0; <BR>tp-&gt;write_seq = 0; <BR>} 
            <BR>if (sysctl_tcp_tw_recycle &amp;&amp; <BR>!tp-&gt;ts_recent_stamp 
            &amp;&amp; <BR>rt-&gt;rt_dst == daddr) { <BR>struct inet_peer *peer 
            = rt_get_peer(rt); <BR>/* VJ's idea. We save last timestamp seen 
            from <BR>* the destination in peer table, when entering state 
            TIME-WAIT <BR>* and initialize ts_recent from it, when trying new 
            connection. <BR>*/ <BR>if (peer &amp;&amp; peer-&gt;tcp_ts_stamp + 
            TCP_PAWS_MSL &gt;= xtime.tv_sec) { <BR>tp-&gt;ts_recent_stamp = 
            peer-&gt;tcp_ts_stamp; <BR>tp-&gt;ts_recent = peer-&gt;tcp_ts; <BR>} 
            <BR>} <BR>sk-&gt;dport = usin-&gt;sin_port; <BR>sk-&gt;daddr = 
            daddr; <BR>if (!tp-&gt;write_seq) <BR>&gt;&gt;&gt;&gt;获取初始序列号 
            <BR>tp-&gt;write_seq = secure_tcp_sequence_number(sk-&gt;saddr, 
            sk-&gt;daddr, <BR>sk-&gt;sport, usin-&gt;sin_port); 
            <BR>tp-&gt;ext_header_len = 0; <BR>if (sk-&gt;protinfo.af_inet.opt) 
            <BR>tp-&gt;ext_header_len = sk-&gt;protinfo.af_inet.opt-&gt;optlen; 
            <BR>sk-&gt;protinfo.af_inet.id = tp-&gt;write_seq^jiffies; 
            <BR>&gt;&gt;&gt;&gt;初始MSS=536 <BR>tp-&gt;mss_clamp = 536; 
            <BR>&gt;&gt;&gt;&gt;发送syn数据报文 <BR>err = tcp_connect(sk, buff); 
            <BR>if (err == 0) <BR>return 0; <BR>failure: <BR>__sk_dst_reset(sk); 
            <BR>sk-&gt;route_caps = 0; <BR>sk-&gt;dport = 0; <BR>return err; 
            <BR>} 
            <BR><BR>ip_route_connect调用ip_route_output,它先在路由高速缓冲(由rt_hash_table哈希 
            <BR>链表表示)中查找,如果没有找到,则调用ip_route_output_slow,它调用fib_lookup 
            <BR>到转发信息表fib_tables(结构structfib_table)中去查找,此时找到正确的的路由 <BR>后: 
            <BR>rth = dst_alloc(&amp;ipv4_dst_ops); 
            <BR>atomic_set(&amp;rth-&gt;u.dst.__refcnt, 1); 
            <BR>rth-&gt;u.dst.flags= DST_HOST; <BR>rth-&gt;key.dst = 
            oldkey-&gt;dst; <BR>rth-&gt;key.tos = tos; <BR>rth-&gt;key.src = 
            oldkey-&gt;src; <BR>rth-&gt;key.iif = 0; <BR>rth-&gt;key.oif = 
            oldkey-&gt;oif; <BR>rth-&gt;rt_dst = key.dst; <BR>rth-&gt;rt_src = 
            key.src; <BR>rth-&gt;rt_iif = oldkey-&gt;oif ? : 
            dev_out-&gt;ifindex; <BR>rth-&gt;u.dst.dev = dev_out; 
            <BR>dev_hold(dev_out); <BR>rth-&gt;rt_gateway = key.dst; 
            <BR>rth-&gt;rt_spec_dst= key.src; <BR>&gt;&gt;&gt;&gt;发包例程 
            <BR>rth-&gt;u.dst.output=ip_output; <BR>if (flags&amp;RTCF_LOCAL) { 
            <BR>&gt;&gt;&gt;&gt;收包例程 <BR>rth-&gt;u.dst.input = ip_local_deliver; 
            <BR>rth-&gt;rt_spec_dst = key.dst; <BR>} <BR>if 
            (flags&amp;(RTCF_BROADCAST|RTCF_MULTICAST)) { 
            <BR>rth-&gt;rt_spec_dst = key.src; <BR>if (flags&amp;RTCF_LOCAL 
            &amp;&amp; !(dev_out-&gt;flags&amp;IFF_LOOPBACK)) 
            <BR>rth-&gt;u.dst.output = ip_mc_output; 
            <BR>................................................... <BR>} 
            <BR>rt_set_nexthop(rth, &amp;res, 0); <BR>rth-&gt;rt_flags = flags; 
            <BR>hash = rt_hash_code(oldkey-&gt;dst, 
            oldkey-&gt;src^(oldkey-&gt;oif&lt;&lt;5), tos); 
            <BR><BR>&gt;&gt;&gt;&gt;对可能的arp做准备,并将得到的路由信息添加到路由高速缓冲中。 <BR>err = 
            rt_intern_hash(hash, rth, rp); <BR><BR><BR><BR>下面就是tcp_connect: 
            <BR>int tcp_connect(struct sock *sk, struct sk_buff *buff) <BR>{ 
            <BR>&gt;&gt;&gt;&gt;路由信息 <BR>struct dst_entry *dst = 
            __sk_dst_get(sk); <BR>struct tcp_opt *tp = 
            &amp;(sk-&gt;tp_pinfo.af_tcp); <BR>/* Reserve space for headers. */ 
            <BR>skb_reserve(buff, MAX_TCP_HEADER); <BR>/* We'll fix this up when 
            we get a response from the other end. <BR>* See 
            tcp_input.c:tcp_rcv_state_process case TCP_SYN_SENT. <BR>*/ 
            <BR>&gt;&gt;&gt;&gt;tcp报头长度 <BR>tp-&gt;tcp_header_len = 
            sizeof(struct tcphdr) + <BR>(sysctl_tcp_timestamps ? 
            TCPOLEN_TSTAMP_ALIGNED : 0); <BR>/* If user gave his TCP_MAXSEG, 
            record it to clamp */ <BR>&gt;&gt;&gt;&gt;将用户给定的mss赋给mss_clamp 
            <BR>if (tp-&gt;user_mss) <BR>tp-&gt;mss_clamp = tp-&gt;user_mss; 
            <BR>tp-&gt;max_window = 0; <BR>&gt;&gt;&gt;&gt;计算几个TCB的几个与mss相关的域 
            <BR>&gt;&gt;&gt;&gt; tp-&gt;user_mss is mss set by user by 
            TCP_MAXSEG. It does NOT counts <BR>&gt;&gt;&gt;&gt; for TCP options, 
            but includes only bare TCP header. <BR>&gt;&gt;&gt;&gt; 
            tp-&gt;mss_clamp is mss negotiated at connection setup. 
            <BR>&gt;&gt;&gt;&gt; It is minumum of user_mss and mss received with 
            SYN. <BR>&gt;&gt;&gt;&gt; It also does not include TCP options. 
            <BR>&gt;&gt;&gt;&gt; tp-&gt;pmtu_cookie is last pmtu, seen by this 
            function. <BR>&gt;&gt;&gt;&gt; tp-&gt;mss_cache is current effective 
            sending mss, including <BR>&gt;&gt;&gt;&gt; all tcp options except 
            for SACKs. It is evaluated, <BR>&gt;&gt;&gt;&gt; taking into account 
            current pmtu, but never exceeds <BR>&gt;&gt;&gt;&gt; 
            tp-&gt;mss_clamp. <BR>tcp_sync_mss(sk, dst-&gt;pmtu); <BR>if 
            (!tp-&gt;window_clamp) <BR>tp-&gt;window_clamp = dst-&gt;window; 
            <BR>tp-&gt;advmss = dst-&gt;advmss; 
            <BR>&gt;&gt;&gt;&gt;计算tp-&gt;ack.rcv_mss的值 <BR>&gt;&gt;&gt;&gt; 
            RCV_MSS is an our guess about MSS used by the peer. 
            <BR>&gt;&gt;&gt;&gt; We haven't any direct information about the 
            MSS. <BR>&gt;&gt;&gt;&gt; It's better to underestimate the RCV_MSS 
            rather than overestimate. <BR>&gt;&gt;&gt;&gt; Overestimations make 
            us ACKing less frequently than needed. <BR>&gt;&gt;&gt;&gt; 
            Underestimations are more easy to detect and fix by 
            tcp_measure_rcv_ms <BR>&gt;&gt;&gt;&gt; s(). 
            <BR>tcp_initialize_rcv_mss(sk); 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -