精华内容
下载资源
问答
  • Linux TCP/IP 协议栈调优

    千次阅读 2014-12-04 16:00:11
    有些性能瓶颈和Linux的TCP/IP协议栈的设置有关,所以特别google了一下Linux TCP/IP协议栈的参数意义和配置,记录一下。 如果想永久的保存参数的设置, 可以将参数加入到/etc/sysctl.conf中。如果想临时的更改...

    本文转载至:http://colobu.com/2014/09/18/linux-tcpip-tuning

    最近忙于系统性能的DEBUG和调优。 有些性能瓶颈和Linux的TCP/IP的协议栈的设置有关,所以特别google了一下Linux TCP/IP的协议栈的参数意义和配置,记录一下。
    如果想永久的保存参数的设置, 可以将参数加入到/etc/sysctl.conf中。如果想临时的更改参数的配置, 可以修改/proc/sys/net/ipv4/下的参数, 机器重启后更改失效。


    杨云1028整理的参数的说明:
    参考文章:
    linux内核TCP相关参数解释
    http://os.chinaunix.net/a2008/0918/985/000000985483.shtml

    linux内核参数优化
    http://blog.chinaunix.net/uid-29081804-id-3830203.html

    linux内核参数注释

    根据参数文件所处目录不同而进行分表整理
    下列文件所在目录:/proc/sys/net/ipv4/

    名称

    默认值

    建议值

    描述

    tcpsyn_retries

    5

    1

    对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃。不应该大于255,默认值是5,对应于180秒左右时间。。(对于大负载而物理通信良好的网络而言,这个值偏高,可修改为2.这个值仅仅是针对对外的连接,对进来的连接,是由tcp_retries1决定的)

    tcp_synack_retries

    5

    1

    对于远端的连接请求SYN,内核会发送SYN + ACK数据报,以确认收到上一个 SYN连接请求包。这是所谓的三次握手( threeway handshake)机制的第二个步骤。这里决定内核在放弃连接之前所送出的 SYN+ACK 数目。不应该大于255,默认值是5,对应于180秒左右时间。

    tcp_keepalive_time

    7200

    600

    TCP发送keepalive探测消息的间隔时间(秒),用于确认TCP连接是否有效。

    防止两边建立连接但不发送数据的攻击。

    tcp_keepalive_probes

    9

    3

    TCP发送keepalive探测消息的间隔时间(秒),用于确认TCP连接是否有效。

    tcp_keepalive_intvl

    75

    15

    探测消息未获得响应时,重发该消息的间隔时间(秒)。默认值为75秒。 (对于普通应用来说,这个值有一些偏大,可以根据需要改小.特别是web类服务器需要改小该值,15是个比较合适的值)

    tcp_retries1

    3

    3

    放弃回应一个TCP连接请求前﹐需要进行多少次重试。RFC 规定最低的数值是3

    tcp_retries2

    15

    5

    在丢弃激活(已建立通讯状况)的TCP连接之前﹐需要进行多少次重试。默认值为15,根据RTO的值来决定,相当于13-30分钟(RFC1122规定,必须大于100秒).(这个值根据目前的网络设置,可以适当地改小,我的网络内修改为了5)

    tcp_orphan_retries

    7

    3

    在近端丢弃TCP连接之前﹐要进行多少次重试。默认值是7个﹐相当于 50秒 - 16分钟﹐视 RTO 而定。如果您的系统是负载很大的web服务器﹐那么也许需要降低该值﹐这类 sockets 可能会耗费大量的资源。另外参的考tcp_max_orphans。(事实上做NAT的时候,降低该值也是好处显著的,我本人的网络环境中降低该值为3)

    tcp_fin_timeout

    60

    2

    对于本端断开的socket连接,TCP保持在FIN-WAIT-2状态的时间。对方可能会断开连接或一直不结束连接或不可预料的进程死亡。默认值为 60 秒。

    tcp_max_tw_buckets

    180000

    36000

    系统在同时所处理的最大 timewait sockets 数目。如果超过此数的话﹐time-wait socket 会被立即砍除并且显示警告信息。之所以要设定这个限制﹐纯粹为了抵御那些简单的 DoS 攻击﹐不过﹐如果网络条件需要比默认值更多﹐则可以提高它(或许还要增加内存)。(事实上做NAT的时候最好可以适当地增加该值)

    tcp_tw_recycle

    0

    1

    打开快速 TIME-WAIT sockets 回收。除非得到技术专家的建议或要求﹐请不要随意修改这个值。(做NAT的时候,建议打开它)

    tcp_tw_reuse

    0

    1

    表示是否允许重新应用处于TIME-WAIT状态的socket用于新的TCP连接(这个对快速重启动某些服务,而启动后提示端口已经被使用的情形非常有帮助)

    tcp_max_orphans

    8192

    32768

    系统所能处理不属于任何进程的TCP sockets最大数量。假如超过这个数量﹐那么不属于任何进程的连接会被立即reset,并同时显示警告信息。之所以要设定这个限制﹐纯粹为了抵御那些简单的 DoS 攻击﹐千万不要依赖这个或是人为的降低这个限制。如果内存大更应该增加这个值。(这个值Redhat AS版本中设置为32768,但是很多防火墙修改的时候,建议该值修改为2000)

    tcp_abort_on_overflow

    0

    0

    当守护进程太忙而不能接受新的连接,就象对方发送reset消息,默认值是false。这意味着当溢出的原因是因为一个偶然的猝发,那么连接将恢复状态。只有在你确信守护进程真的不能完成连接请求时才打开该选项,该选项会影响客户的使用。(对待已经满载的sendmail,apache这类服务的时候,这个可以很快让客户端终止连接,可以给予服务程序处理已有连接的缓冲机会,所以很多防火墙上推荐打开它)

    tcp_syncookies

    0

    1

    只有在内核编译时选择了CONFIG_SYNCOOKIES时才会发生作用。当出现syn等候队列出现溢出时象对方发送syncookies。目的是为了防止syn flood攻击。

    tcp_stdurg

    0

    0

    使用 TCP urg pointer 字段中的主机请求解释功能。大部份的主机都使用老旧的 BSD解释,因此如果您在 Linux 打开它﹐或会导致不能和它们正确沟通。

    tcp_max_syn_backlog

    1024

    16384

    对于那些依然还未获得客户端确认的连接请求﹐需要保存在队列中最大数目。对于超过 128Mb 内存的系统﹐默认值是 1024 ﹐低于 128Mb 的则为 128。如果服务器经常出现过载﹐可以尝试增加这个数字。警告﹗假如您将此值设为大于 1024﹐最好修改include/net/tcp.h里面的TCP_SYNQ_HSIZE﹐以保持TCP_SYNQ_HSIZE*16(SYN Flood攻击利用TCP协议散布握手的缺陷,伪造虚假源IP地址发送大量TCP-SYN半打开连接到目标系统,最终导致目标系统Socket队列资源耗尽而无法接受新的连接。为了应付这种攻击,现代Unix系统中普遍采用多连接队列处理的方式来缓冲(而不是解决)这种攻击,是用一个基本队列处理正常的完全连接应用(Connect()Accept() ),是用另一个队列单独存放半打开连接。这种双队列处理方式和其他一些系统内核措施(例如Syn-Cookies/Caches)联合应用时,能够比较有效的缓解小规模的SYN Flood攻击(事实证明)

    tcp_window_scaling

    1

    1

    该文件表示设置tcp/ip会话的滑动窗口大小是否可变。参数值为布尔值,为1时表示可变,为0时表示不可变。tcp/ip通常使用的窗口最大可达到 65535 字节,对于高速网络,该值可能太小,这时候如果启用了该功能,可以使tcp/ip滑动窗口大小增大数个数量级,从而提高数据传输的能力(RFC 1323)。(对普通地百M网络而言,关闭会降低开销,所以如果不是高速网络,可以考虑设置为0)

    tcp_timestamps

    1

    1

    Timestamps 用在其它一些东西中﹐可以防范那些伪造的 sequence 号码。一条1G的宽带线路或许会重遇到带 out-of-line数值的旧sequence 号码(假如它是由于上次产生的)。Timestamp 会让它知道这是个 ‘旧封包‘。(该文件表示是否启用以一种比超时重发更精确的方法(RFC 1323)来启用对 RTT 的计算;为了实现更好的性能应该启用这个选项。)

    tcp_sack

    1

    1

    使用 Selective ACK﹐它可以用来查找特定的遗失的数据报—- 因此有助于快速恢复状态。该文件表示是否启用有选择的应答(Selective Acknowledgment),这可以通过有选择地应答乱序接收到的报文来提高性能(这样可以让发送者只发送丢失的报文段)。(对于广域网通信来说这个选项应该启用,但是这会增加对 CPU 的占用。)

    tcp_fack

    1

    1

    打开FACK拥塞避免和快速重传功能。(注意,当tcp_sack设置为0的时候,这个值即使设置为1也无效)[这个是TCP连接靠谱的核心功能]

    tcp_dsack

    1

    1

    允许TCP发送“两个完全相同“的SACK。

    tcp_ecn

    0

    0

    TCP的直接拥塞通告功能。

    tcp_reordering

    3

    6

    TCP流中重排序的数据报最大数量。 (一般有看到推荐把这个数值略微调整大一些,比如5)

    tcp_retrans_collapse

    1

    0

    对于某些有bug的打印机提供针对其bug的兼容性。(一般不需要这个支持,可以关闭它)

    tcp_wmemmindefaultmax

    4096

    16384

    131072

    8192

    131072

    16777216

    发送缓存设置

    min:为TCP socket预留用于发送缓冲的内存最小值。每个tcp socket都可以在建议以后都可以使用它。默认值为4096(4K)。

    default:为TCP socket预留用于发送缓冲的内存数量,默认情况下该值会影响其它协议使用的net.core.wmem_default 值,一般要低于net.core.wmem_default的值。默认值为16384(16K)。

    max: 用于TCP socket发送缓冲的内存最大值。该值不会影响net.core.wmem_max,”静态”选择参数SO_SNDBUF则不受该值影响。默认值为131072(128K)。(对于服务器而言,增加这个参数的值对于发送数据很有帮助,在我的网络环境中,修改为了51200 131072 204800)

    tcprmemmindefaultmax

    4096

    87380

    174760

    32768

    131072

    16777216

    接收缓存设置

    同tcp_wmem

    tcp_memmindefaultmax

    根据内存计算

    786432

    1048576 1572864

    low:当TCP使用了低于该值的内存页面数时,TCP不会考虑释放内存。即低于此值没有内存压力。(理想情况下,这个值应与指定给 tcp_wmem 的第 2 个值相匹配 - 这第 2 个值表明,最大页面大小乘以最大并发请求数除以页大小 (131072 300 / 4096)。 )

    pressure:当TCP使用了超过该值的内存页面数量时,TCP试图稳定其内存使用,进入pressure模式,当内存消耗低于low值时则退出pressure状态。(理想情况下这个值应该是 TCP 可以使用的总缓冲区大小的最大值 (204800 300 / 4096)。 )

    high:允许所有tcp sockets用于排队缓冲数据报的页面量。(如果超过这个值,TCP 连接将被拒绝,这就是为什么不要令其过于保守 (512000 * 300 / 4096) 的原因了。 在这种情况下,提供的价值很大,它能处理很多连接,是所预期的 2.5 倍;或者使现有连接能够传输 2.5 倍的数据。 我的网络里为192000 300000 732000)

    一般情况下这些值是在系统启动时根据系统内存数量计算得到的。

    tcp_app_win

    31

    31

    保留max(window/2^tcp_app_win, mss)数量的窗口由于应用缓冲。当为0时表示不需要缓冲。

    tcp_adv_win_scale

    2

    2

    计算缓冲开销bytes/2^tcp_adv_win_scale(如果tcp_adv_win_scale > 0)或者bytes-bytes/2^(-tcp_adv_win_scale)(如果tcp_adv_win_scale BOOLEAN>0)

    tcp_low_latency

    0

    0

    允许 TCP/IP 栈适应在高吞吐量情况下低延时的情况;这个选项一般情形是的禁用。(但在构建Beowulf 集群的时候,打开它很有帮助)

    tcp_westwood

    0

    0

    启用发送者端的拥塞控制算法,它可以维护对吞吐量的评估,并试图对带宽的整体利用情况进行优化;对于 WAN 通信来说应该启用这个选项。

    tcp_bic

    0

    0

    为快速长距离网络启用 Binary Increase Congestion;这样可以更好地利用以 GB 速度进行操作的链接;对于 WAN 通信应该启用这个选项。

    ip_forward

    0

    NAT必须开启IP转发支持,把该值写1

    ip_local_port_range:minmax

    32768

    61000

    1024

    65000

    表示用于向外连接的端口范围,默认比较小,这个范围同样会间接用于NAT表规模。

    ip_conntrack_max

    65535

    65535

    系统支持的最大ipv4连接数,默认65536(事实上这也是理论最大值),同时这个值和你的内存大小有关,如果内存128M,这个值最大8192,1G以上内存这个值都是默认65536

    所处目录/proc/sys/net/ipv4/netfilter/
    文件需要打开防火墙才会存在

    名称

    默认值

    建议值

    描述

    ip_conntrack_max

    65536

    65536

    系统支持的最大ipv4连接数,默认65536(事实上这也是理论最大值),同时这个值和你的内存大小有关,如果内存128M,这个值最大8192,1G以上内存这个值都是默认65536,这个值受/proc/sys/net/ipv4/ip_conntrack_max限制


    ip_conntrack_tcp_timeout_established

    432000

    180

    已建立的tcp连接的超时时间,默认432000,也就是5天。影响:这个值过大将导致一些可能已经不用的连接常驻于内存中,占用大量链接资源,从而可能导致NAT ip_conntrack: table full的问题建议:对于NAT负载相对本机的 NAT表大小很紧张的时候,可能需要考虑缩小这个值,以尽早清除连接,保证有可用的连接资源;如果不紧张,不必修改

    ip_conntrack_tcp_timeout_time_wait

    120

    120

    time_wait状态超时时间,超过该时间就清除该连接

    ip_conntrack_tcp_timeout_close_wait

    60

    60

    close_wait状态超时时间,超过该时间就清除该连接

    ip_conntrack_tcp_timeout_fin_wait

    120

    120

    fin_wait状态超时时间,超过该时间就清除该连接

    文件所处目录/proc/sys/net/core/

    名称

    默认值

    建议值

    描述

    netdev_max_backlog


    1024

    16384

    每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目,对重负载服务器而言,该值需要调高一点。

    somaxconn


    128

    16384

    用来限制监听(LISTEN)队列最大数据包的数量,超过这个数量就会导致链接超时或者触发重传机制。

    web应用中listen函数的backlog默认会给我们内核参数的net.core.somaxconn限制到128,而nginx定义的NGX_LISTEN_BACKLOG默认为511,所以有必要调整这个值。对繁忙的服务器,增加该值有助于网络性能

    wmem_default


    129024

    129024

    默认的发送窗口大小(以字节为单位)

    rmem_default


    129024

    129024

    默认的接收窗口大小(以字节为单位)

    rmem_max


    129024

    873200

    最大的TCP数据接收缓冲

    wmem_max

    129024

    873200

    最大的TCP数据发送缓冲

    两种修改内核参数方法

    1. 使用echo value方式直接追加到文件里如echo “1” >/proc/sys/net/ipv4/tcp_syn_retries,但这种方法设备重启后又会恢复为默认值

    2. 把参数添加到/etc/sysctl.conf中,然后执行sysctl -p使参数生效,永久生效

    内核生产环境优化参数

    生产中常用的参数:

         
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
         
    net .ipv4 .tcp_syn_retries = 1
    net .ipv4 .tcp_synack_retries = 1
    net .ipv4 .tcp_keepalive_time = 600
    net .ipv4 .tcp_keepalive_probes = 3
    net .ipv4 .tcp_keepalive_intvl = 15
    net .ipv4 .tcp_retries2 = 5
    net .ipv4 .tcp_fin_timeout = 2
    net .ipv4 .tcp_max_tw_buckets = 36000
    net .ipv4 .tcp_tw_recycle = 1
    net .ipv4 .tcp_tw_reuse = 1
    net .ipv4 .tcp_max_orphans = 32768
    net .ipv4 .tcp_syncookies = 1
    net .ipv4 .tcp_max_syn_backlog = 16384
    net .ipv4 .tcp_wmem = 8192 131072 16777216
    net .ipv4 .tcp_rmem = 32768 131072 16777216
    net .ipv4 .tcp_mem = 786432 1048576 1572864
    net .ipv4 .ip_local_port_range = 1024 65000
    net .ipv4 .ip_conntrack_max = 65536
    net .ipv4 .netfilter .ip_conntrack_max= 65536
    net .ipv4 .netfilter .ip_conntrack_tcp_timeout_established= 180
    net .core .somaxconn = 16384
    net .core .netdev_max_backlog = 16384

    不同的生产环境需要优化的参数基本差不多,只是值有相应的变化。具体优化值要参考应用场景,这儿所列只是常用优化参数,是否适合,可在上面查看该参数描述,理解后,再根据自己生产环境而设。

    其它相关linux内核参数调整文章:
    Linux内核参数优化
    http://flandycheng.blog.51cto.com/855176/476769

    优化linux的内核参数来提高服务器并发处理能力
    http://www.ha97.com/4396.html

    nginx做web服务器linux内核参数优化
    http://blog.csdn.net/force_eagle/article/details/6725243


    sudops网站提供的优化例子:
    Linux下TCP/IP及内核参数优化有多种方式,参数配置得当可以大大提高系统的性能,也可以根据特定场景进行专门的优化,如TIME_WAIT过高,DDOS攻击等等。
    如下配置是写在sysctl.conf中,可使用sysctl -p生效,文中附带了一些默认值和中文解释(从网上收集和翻译而来),确有些辛苦,转载请保留链接,谢谢~。
    相关参数仅供参考,具体数值还需要根据机器性能,应用场景等实际情况来做更细微调整。

         
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
         
    net.core.netdev_max_backlog = 400000
    #该参数决定了,网络设备接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。
    net.core.optmem_max = 10000000
    #该参数指定了每个套接字所允许的最大缓冲区的大小
    net.core.rmem_default = 10000000
    #指定了接收套接字缓冲区大小的缺省值(以字节为单位)。
    net.core.rmem_max = 10000000
    #指定了接收套接字缓冲区大小的最大值(以字节为单位)。
    net.core.somaxconn = 100000
    #Linux kernel参数,表示socket监听的backlog(监听队列)上限
    net.core.wmem_default = 11059200
    #定义默认的发送窗口大小;对于更大的 BDP 来说,这个大小也应该更大。
    net.core.wmem_max = 11059200
    #定义发送窗口的最大大小;对于更大的 BDP 来说,这个大小也应该更大。
    net.ipv4.conf.all.rp_filter = 1
    net.ipv4.conf. default.rp_filter = 1
    #严谨模式 1 (推荐)
    #松散模式 0
    net.ipv4.tcp_congestion_control = bic
    #默认推荐设置是 htcp
    net.ipv4.tcp_window_scaling = 0
    #关闭tcp_window_scaling
    #启用 RFC 1323 定义的 window scaling;要支持超过 64KB 的窗口,必须启用该值。
    net.ipv4.tcp_ecn = 0
    #把TCP的直接拥塞通告(tcp_ecn)关掉
    net.ipv4.tcp_sack = 1
    #关闭tcp_sack
    #启用有选择的应答(Selective Acknowledgment),
    #这可以通过有选择地应答乱序接收到的报文来提高性能(这样可以让发送者只发送丢失的报文段);
    #(对于广域网通信来说)这个选项应该启用,但是这会增加对 CPU 的占用。
    net.ipv4.tcp_max_tw_buckets = 10000
    #表示系统同时保持TIME_WAIT套接字的最大数量
    net.ipv4.tcp_max_syn_backlog = 8192
    #表示SYN队列长度,默认1024,改成8192,可以容纳更多等待连接的网络连接数。
    net.ipv4.tcp_syncookies = 1
    #表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
    net.ipv4.tcp_timestamps = 1
    #开启TCP时间戳
    #以一种比重发超时更精确的方法(请参阅 RFC 1323)来启用对 RTT 的计算;为了实现更好的性能应该启用这个选项。
    net.ipv4.tcp_tw_reuse = 1
    #表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
    net.ipv4.tcp_tw_recycle = 1
    #表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
    net.ipv4.tcp_fin_timeout = 10
    #表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。
    net.ipv4.tcp_keepalive_time = 1800
    #表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为30分钟。
    net.ipv4.tcp_keepalive_probes = 3
    #如果对方不予应答,探测包的发送次数
    net.ipv4.tcp_keepalive_intvl = 15
    #keepalive探测包的发送间隔
    net.ipv4.tcp_mem
    #确定 TCP 栈应该如何反映内存使用;每个值的单位都是内存页(通常是 4KB)。
    #第一个值是内存使用的下限。
    #第二个值是内存压力模式开始对缓冲区使用应用压力的上限。
    #第三个值是内存上限。在这个层次上可以将报文丢弃,从而减少对内存的使用。对于较大的 BDP 可以增大这些值(但是要记住,其单位是内存页,而不是字节)。
    net.ipv4.tcp_rmem
    #与 tcp_wmem 类似,不过它表示的是为自动调优所使用的接收缓冲区的值。
    net.ipv4.tcp_wmem = 30000000 30000000 30000000
    #为自动调优定义每个 socket 使用的内存。
    #第一个值是为 socket 的发送缓冲区分配的最少字节数。
    #第二个值是默认值(该值会被 wmem_default 覆盖),缓冲区在系统负载不重的情况下可以增长到这个值。
    #第三个值是发送缓冲区空间的最大字节数(该值会被 wmem_max 覆盖)。
    net.ipv4.ip_local_port_range = 1024 65000
    #表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。
    net.ipv4.netfilter.ip_conntrack_max= 204800
    #设置系统对最大跟踪的TCP连接数的限制
    net.ipv4.tcp_slow_start_after_idle = 0
    #关闭tcp的连接传输的慢启动,即先休止一段时间,再初始化拥塞窗口。
    net.ipv4.route.gc_timeout = 100
    #路由缓存刷新频率,当一个路由失败后多长时间跳到另一个路由,默认是300。
    net.ipv4.tcp_syn_retries = 1
    #在内核放弃建立连接之前发送SYN包的数量。
    net.ipv4.icmp_echo_ignore_broadcasts = 1
    # 避免放大攻击
    net.ipv4.icmp_ignore_bogus_error_responses = 1
    # 开启恶意icmp错误消息保护
    net.inet.udp.checksum= 1
    #防止不正确的udp包的攻击
    net.ipv4.conf. default.accept_source_route = 0
    #是否接受含有源路由信息的ip包。参数值为布尔值,1表示接受,0表示不接受。
    #在充当网关的linux主机上缺省值为1,在一般的linux主机上缺省值为0。
    #从安全性角度出发,建议你关闭该功能。

    最初的幸福ever也提供了一些参数的说明。

    /proc/sys/net目录
    所有的TCP/IP参数都位于/proc/sys/net目录下(请注意,对/proc/sys/net目录下内容的修改都是临时的,任何修改在系统重启后都会丢失),例如下面这些重要的参数:

    参数(路径+文件)

    描述

    默认值

    优化值

    /proc/sys/net/core/rmem_default

    默认的TCP数据接收窗口大小(字节)。

    229376

    256960

    /proc/sys/net/core/rmem_max

    最大的TCP数据接收窗口(字节)。

    131071

    513920

    /proc/sys/net/core/wmem_default

    默认的TCP数据发送窗口大小(字节)。

    229376

    256960

    /proc/sys/net/core/wmem_max

    最大的TCP数据发送窗口(字节)。

    131071

    513920

    /proc/sys/net/core/netdev_max_backlog

    在每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。

    1000

    2000

    /proc/sys/net/core/somaxconn

    定义了系统中每一个端口最大的监听队列的长度,这是个全局的参数。

    128

    2048

    /proc/sys/net/core/optmem_max

    表示每个套接字所允许的最大缓冲区的大小。

    20480

    81920

    /proc/sys/net/ipv4/tcp_mem

    确定TCP栈应该如何反映内存使用,每个值的单位都是内存页(通常是4KB)。第一个值是内存使用的下限;第二个值是内存压力模式开始对缓冲区使用应用压力的上限;第三个值是内存使用的上限。在这个层次上可以将报文丢弃,从而减少对内存的使用。对于较大的BDP可以增大这些值(注意,其单位是内存页而不是字节)。

    94011  125351  188022

    131072  262144  524288

    /proc/sys/net/ipv4/tcp_rmem

    为自动调优定义socket使用的内存。第一个值是为socket接收缓冲区分配的最少字节数;第二个值是默认值(该值会被rmem_default覆盖),缓冲区在系统负载不重的情况下可以增长到这个值;第三个值是接收缓冲区空间的最大字节数(该值会被rmem_max覆盖)。

    4096  87380  4011232

    8760  256960  4088000

    /proc/sys/net/ipv4/tcp_wmem

    为自动调优定义socket使用的内存。第一个值是为socket发送缓冲区分配的最少字节数;第二个值是默认值(该值会被wmem_default覆盖),缓冲区在系统负载不重的情况下可以增长到这个值;第三个值是发送缓冲区空间的最大字节数(该值会被wmem_max覆盖)。

    4096  16384  4011232

    8760  256960  4088000

    /proc/sys/net/ipv4/tcp_keepalive_time

    TCP发送keepalive探测消息的间隔时间(秒),用于确认TCP连接是否有效。

    7200

    1800

    /proc/sys/net/ipv4/tcp_keepalive_intvl

    探测消息未获得响应时,重发该消息的间隔时间(秒)。

    75

    30

    /proc/sys/net/ipv4/tcp_keepalive_probes

    在认定TCP连接失效之前,最多发送多少个keepalive探测消息。

    9

    3

    /proc/sys/net/ipv4/tcp_sack

    启用有选择的应答(1表示启用),通过有选择地应答乱序接收到的报文来提高性能,让发送者只发送丢失的报文段,(对于广域网通信来说)这个选项应该启用,但是会增加对CPU的占用。

    1

    1

    /proc/sys/net/ipv4/tcp_fack

    启用转发应答,可以进行有选择应答(SACK)从而减少拥塞情况的发生,这个选项也应该启用。

    1

    1

    /proc/sys/net/ipv4/tcp_timestamps

    TCP时间戳(会在TCP包头增加12个字节),以一种比重发超时更精确的方法(参考RFC 1323)来启用对RTT 的计算,为实现更好的性能应该启用这个选项。

    1

    1

    /proc/sys/net/ipv4/tcp_window_scaling

    启用RFC 1323定义的window scaling,要支持超过64KB的TCP窗口,必须启用该值(1表示启用),TCP窗口最大至1GB,TCP连接双方都启用时才生效。

    1

    1

    /proc/sys/net/ipv4/tcp_syncookies

    表示是否打开TCP同步标签(syncookie),内核必须打开了CONFIG_SYN_COOKIES项进行编译,同步标签可以防止一个套接字在有过多试图连接到达时引起过载。

    1

    1

    /proc/sys/net/ipv4/tcp_tw_reuse

    表示是否允许将处于TIME-WAIT状态的socket(TIME-WAIT的端口)用于新的TCP连接 。

    0

    1

    /proc/sys/net/ipv4/tcp_tw_recycle

    能够更快地回收TIME-WAIT套接字。

    0

    1

    /proc/sys/net/ipv4/tcp_fin_timeout

    对于本端断开的socket连接,TCP保持在FIN-WAIT-2状态的时间(秒)。对方可能会断开连接或一直不结束连接或不可预料的进程死亡。

    60

    30

    /proc/sys/net/ipv4/ip_local_port_range

    表示TCP/UDP协议允许使用的本地端口号

    32768  61000

    1024  65000

    /proc/sys/net/ipv4/tcp_max_syn_backlog

    对于还未获得对方确认的连接请求,可保存在队列中的最大数目。如果服务器经常出现过载,可以尝试增加这个数字。

    2048

    2048

    /proc/sys/net/ipv4/tcp_low_latency

    允许TCP/IP栈适应在高吞吐量情况下低延时的情况,这个选项应该禁用。

    0

     

    /proc/sys/net/ipv4/tcp_westwood

    启用发送者端的拥塞控制算法,它可以维护对吞吐量的评估,并试图对带宽的整体利用情况进行优化,对于WAN 通信来说应该启用这个选项。

    0

     

    /proc/sys/net/ipv4/tcp_bic

    为快速长距离网络启用Binary Increase Congestion,这样可以更好地利用以GB速度进行操作的链接,对于WAN通信应该启用这个选项。

    1


    展开全文
  • Linux TCP/IP 协议栈源码分析

    千次阅读 2017-01-12 10:09:09
    [转载]Linux TCP/IP 协议栈源码分析 一.linux内核网络栈代码的准备知识 1. linux内核ipv4网络部分分层结构: BSD socket层: 这一部分处理BSD socket相关操作,每个socket在内核中以struct socket结构体现。这一...

    一.linux内核网络栈代码的准备知识

    1. linux内核ipv4网络部分分层结构

    BSD socket层: 这一部分处理BSD socket相关操作,每个socket在内核中以struct socket结构体现。这一部分的文件

    主要有:/net/socket.c /net/protocols.c etc
    INET socket层:BSD socket是个可以用于各种网络协议的接口,而当用于tcp/ip,即建立了AF_INET形式的socket时,

    还需要保留些额外的参数,于是就有了struct sock结构。文件主要

    有:/net/ipv4/protocol.c /net/ipv4/af_inet.c /net/core/sock.c etc
    TCP/UDP层:处理传输层的操作,传输层用struct inet_protocol和struct proto两个结构表示。文件主要

    有:/net/ipv4/udp.c /net/ipv4/datagram.c /net/ipv4/tcp.c /net/ipv4/tcp_input.c /net/ipv4//tcp_output.c /net/ipv4/tcp_minisocks.c /net/ipv4/tcp_output.c /net/ipv4/tcp_timer.c

    etc  
    IP层:处理网络层的操作,网络层用struct packet_type结构表示。文件主要有:/net/ipv4/ip_forward.c

    ip_fragment.c ip_input.c ip_output.c etc.
    数据链路层和驱动程序:每个网络设备以struct net_device表示,通用的处理在dev.c中,驱动程序都在/driver/net目

    录下。

    2. 两台主机建立udp通信所走过的函数列表

     

    ^
    |       sys_read                fs/read_write.c
    |       sock_read               net/socket.c
    |       sock_recvmsg            net/socket.c
    |       inet_recvmsg            net/ipv4/af_inet.c
    |       udp_recvmsg             net/ipv4/udp.c
    |       skb_recv_datagram       net/core/datagram.c
    |       -------------------------------------------
    |       sock_queue_rcv_skb      include/net/sock.h
    |       udp_queue_rcv_skb       net/ipv4/udp.c
    |       udp_rcv                 net/ipv4/udp.c
    |       ip_local_deliver_finish net/ipv4/ip_input.c
    |       ip_local_deliver        net/ipv4/ip_input.c
    |       ip_recv                 net/ipv4/ip_input.c
    |       net_rx_action           net/dev.c
    |       -------------------------------------------
    |       netif_rx                net/dev.c
    |       el3_rx                  driver/net/3c309.c
    |       el3_interrupt           driver/net/3c309.c
    ==========================
    |       sys_write               fs/read_write.c
    |       sock_writev             net/socket.c                    
    |       sock_sendmsg            net/socket.c
    |       inet_sendmsg            net/ipv4/af_inet.c
    |       udp_sendmsg             net/ipv4/udp.c
    |       ip_build_xmit           net/ipv4/ip_output.c
    |       output_maybe_reroute    net/ipv4/ip_output.c
    |       ip_output               net/ipv4/ip_output.c
    |       ip_finish_output        net/ipv4/ip_output.c
    |       dev_queue_xmit          net/dev.c
    |       --------------------------------------------
    |       el3_start_xmit          driver/net/3c309.c
    V

    3. 网络路径图、重要数据结构sk_buffer及路由介绍

     

    linux-net.pdf 第2.1章 第2.3章 第2.4章

    4. 从连接、发送、到接收数据包的过程

     

        linux-net.pdf 第4、5、6章详细阐述

    二.linux的tcp-ip栈代码的详细分析

     

    1.数据结构(msghdr,sk_buff,socket,sock,proto_ops,proto)

     

    bsd套接字层,操作的对象是socket,数据存放在msghdr这样的数据结构:

    创建socket需要传递family,type,protocol三个参数,创建socket其实就是创建一个socket实例,然后创建一个文件描述符结构,并且互相建立一些关联,即建立互相连接的指针,并且初始化这些对文件的写读操作映射到socket的read,write函数上来。

    同时初始化socket的操作函数(proto_ops结构),如果传入的type参数是STREAM类型,那么就初始化为SOCKET->ops为inet_stream_ops,如果是DGRAM类型,则SOCKET-ops为inet_dgram_ops。对于inet_stream_ops其实是一个结构体,包含了stream类型的socket操作的一些入口函数,在这些函数里主要做的是对socket进行相关的操作,同时通过调用下面提到的sock中的相关操作完成socket到sock层的传递。比如在inet_stream_ops里有个inet_release的操作,这个操作除了释放socket的类型空间操作外,还通过调用socket连接的sock的close操作,对于stream类型来说,即tcp_close来关闭sock

    释放sock。

    创建socket同时还创建sock数据空间,初始化sock,初始化过程主要做的事情是初始化三个队列,receive_queue(接收到的数据包sk_buff链表队列),send_queue(需要发送数据包的sk_buff链表队列),backlog_queue(主要用于tcp中三次握手成功的那些数据包,自己猜的),根据family、type参数,初始化sock的操作,比如对于family为inet类型的,type为stream类型的,sock->proto初始化为tcp_prot.其中包括stream类型的协议sock操作对应的入口函数。

    在一端对socket进行write的过程中,首先会把要write的字符串缓冲区整理成msghdr的数据结构形式(参见linux内核2.4版源代码分析大全),然后调用sock_sendmsg把msghdr的数据传送至inet层,对于msghdr结构中数据区中的每个数据包,创建sk_buff结构,填充数据,挂至发送队列。一层层往下层协议传递。一下每层协议不再对数据进行拷贝。而是对sk_buff结构进行操作。

    inet套接字及以下层 数据存放在sk_buff这样的数据结构里:

    路由:

        在linux的路由系统主要保存了三种与路由相关的数据,第一种是在物理上和本机相连接的主机地址信息表,第二种是保存了在网络访问中判断一个网络地址应该走什么路由的数据表;第三种是最新使用过的查询路由地址的缓存地址数据表。

        1.neighbour结构  neighbour_table{ }是一个包含和本机所连接的所有邻元素的信息的数据结构。该结构中有个元素是neighbour结构的数组,数组的每一个元素都是一个对应于邻机的neighbour结构,系统中由于协议的不同,会有不同的判断邻居的方式,每种都有neighbour_table{}类型的实例,这些实例是通过neighbour_table{}中的指针next串联起来的。在neighbour结构中,包含有与该邻居相连的网络接口设备net_device的指针,网络接口的硬件地址,邻居的硬件地址,包含有neigh_ops{}指针,这些函数指针是直接用来连接传输数据的,包含有queue_xmit(struct * sk_buff)函数入口地址,这个函数可能会调用硬件驱动程序的发送函数。

        2.FIB结构 在FIB中保存的是最重要的路由规则,通过对FIB数据的查找和换算,一定能够获得路由一个地址的方法。系统中路由一般采取的手段是:先到路由缓存中查找表项,如果能够找到,直接对应的一项作为路由的规则;如果不能找到,那么就到FIB中根据规则换算传算出来,并且增加一项新的,在路由缓存中将项目添加进去。

        3.route结构(即路由缓存中的结构)

    数据链路层:

       net_device{}结构,对应于每一个网络接口设备。这个结构中包含很多可以直接获取网卡信息的函数和变量,同时包含很多对于网卡操作的函数,这些直接指向该网卡驱动程序的许多函数入口,包括发送接收数据帧到缓冲区等。当这些完成后,比如数据接收到缓冲区后便由netif_rx(在net/core/dev.c各种设备驱动程序的上层框架程序)把它们组成sk_buff形式挂到系统接收的backlog队列然后交由上层网络协议处理。同样,对于上层协议处理下来的那些sk_buff。便由dev_queue_xmit函数放入网络缓冲区,交给网卡驱动程序的发送程序处理。

       在系统中存在一张链表dev_base将系统中所有的net_device{}结构连在一起。对应于内核初始化而言,系统启动时便为每个所有可能支持的网络接口设备申请了一个net_device{}空间并串连起来,然后对每个接点运行检测过程,如果检测成功,则在dev_base链表中保留这个接点,否则删除。对应于模块加载来说,则是调用register_netdev()注册net_device,在这个函数中运行检测过程,如果成功,则加到dev_base链表。否则就返回检测不到信息。删除同理,调用

    unregister_netdev。

    2.启动分析

     

        2.1 初始化进程 :start-kernel(main.c)---->do_basic_setup(main.c)---->sock_init(/net/socket.c)---->do_initcalls(main.c)

    void __init sock_init(void)
    {
    int i;

    printk(KERN_INFO "Linux NET4.0 for Linux 2.4/n");
    printk(KERN_INFO "Based upon Swansea University Computer Society NET3.039/n");

    /*
      * Initialize all address (protocol) families. 每一项表示的是针对一个地址族的操作集合,例如对于ipv4来说,在net/ipv4/af_inet.c文件中的函数inet_proto_init()就调用sock_register()函数将inet_families_ops初始化到属于IPV4的net_families数组中的一项。
      */
    for (i = 0; i < NPROTO; i++)
      net_families[i] = NULL; 

    /*
      * Initialize sock SLAB cache.初始化对于sock结构预留的内存的slab缓存。
      */
    sk_init();

    #ifdef SLAB_SKB
    /*
      * Initialize skbuff SLAB cache 初始化对于skbuff结构的slab缓存。以后对于skbuff的申请可以通过函数kmem_cache_alloc()在这个缓存中申请空间。
      */
    skb_init();
    #endif

    /*
      * Wan router layer.
      */

    #ifdef CONFIG_WAN_ROUTER 
    wanrouter_init();
    #endif

    /*
      * Initialize the protocols module. 向系统登记sock文件系统,并且将其安装到系统上来。
      */

    register_filesystem(&sock_fs_type);
    sock_mnt = kern_mount(&sock_fs_type);
    /* The real protocol initialization is performed when
      *  do_initcalls is run. 
      */

    /*
      * The netlink device handler may be needed early.
      */

    #ifdef CONFIG_NET
    rtnetlink_init();
    #endif
    #ifdef CONFIG_NETLINK_DEV
    init_netlink();
    #endif
    #ifdef CONFIG_NETFILTER
    netfilter_init();
    #endif

    #ifdef CONFIG_BLUEZ
    bluez_init();
    #endif

    /*yfhuang ipsec*/
    #ifdef CONFIG_IPSEC            
    pfkey_init();
    #endif
    /*yfhuang ipsec*/
    }

     

     

        2.2 do_initcalls() 中做了其它的初始化,其中包括

                    协议初始化,路由初始化,网络接口设备初始化

    (例如inet_init函数以_init开头表示是系统初始化时做,函数结束后跟module_init(inet_init),这是一个宏,在include/linux/init.c中定义,展开为_initcall(inet_init),表示这个函数在do_initcalls被调用了)

        2.3 协议初始化

    此处主要列举inet协议的初始化过程。

     

    static int __init inet_init(void)
    {
    struct sk_buff *dummy_skb;
    struct inet_protocol *p;
    struct inet_protosw *q;
    struct list_head *r;

    printk(KERN_INFO "NET4: Linux TCP/IP 1.0 for NET4.0/n");

    if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)) {
      printk(KERN_CRIT "inet_proto_init: panic/n");
      return -EINVAL;
    }

    /*
      * Tell SOCKET that we are alive... 注册socket,告诉socket inet类型的地址族已经准备好了
      */
       (void) sock_register(&inet_family_ops);

    /*
      * Add all the protocols. 包括arp,ip、ICMP、UPD、tcp_v4、tcp、igmp的初始化,主要初始化各种协议对应的inode和socket变量。

    其中arp_init完成系统中路由部分neighbour表的初始化

    ip_init完成ip协议的初始化。在这两个函数中,都通过定义一个packet_type结构的变量将这种数据包对应的协议发送数据、允许发送设备都做初始化。

      */

    printk(KERN_INFO "IP Protocols: ");
    for (p = inet_protocol_base; p != NULL;) {
      struct inet_protocol *tmp = (struct inet_protocol *) p->next;
      inet_add_protocol(p);
      printk("%s%s",p->name,tmp?", ":"/n");
      p = tmp;
    }

    /* Register the socket-side information for inet_create. */
    for(r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r)
      INIT_LIST_HEAD(r);

    for(q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q)
      inet_register_protosw(q);

    /*
      * Set the ARP module up 
      */

    arp_init();

       /*
        * Set the IP module up
        */

    ip_init();

    tcp_v4_init(&inet_family_ops);

    /* Setup TCP slab cache for open requests. */
    tcp_init();

    /*
      * Set the ICMP layer up
      */

    icmp_init(&inet_family_ops);

    /* I wish inet_add_protocol had no constructor hook...
        I had to move IPIP from net/ipv4/protocol.c :-( --ANK
      */
    #ifdef CONFIG_NET_IPIP
    ipip_init();
    #endif
    #ifdef CONFIG_NET_IPGRE
    ipgre_init();
    #endif

    /*
      * Initialise the multicast router
      */
    #if defined(CONFIG_IP_MROUTE)
    ip_mr_init();
    #endif

    /*
      * Create all the /proc entries.
      */
    #ifdef CONFIG_PROC_FS
    proc_net_create ("raw", 0, raw_get_info);
    proc_net_create ("netstat", 0, netstat_get_info);
    proc_net_create ("snmp", 0, snmp_get_info);
    proc_net_create ("sockstat", 0, afinet_get_info);
    proc_net_create ("tcp", 0, tcp_get_info);
    proc_net_create ("udp", 0, udp_get_info);
    #endif  /* CONFIG_PROC_FS */

    ipfrag_init();

    return 0;
    }  

    module_init(inet_init);

    2.4 路由初始化(包括neighbour表、FIB表、和路由缓存表的初始化工作)

     

    2.4.1 rtcache表 ip_rt_init()函数 在net/ipv4/ip_output中调用,net/ipv4/route.c中定义

     

    2.4.2 FIB初始化 在ip_rt_init()中调用 在net/ipv4/fib_front.c中定义

     

               2.4.3 neigbour表初始化  arp_init()函数中定义

     

         2.5 网络接口设备初始化

                 在系统中网络接口都是由一个dev_base链表进行管理的。通过内核的启动方式也是通过这个链表进行操作的。在系统启动之初,将所有内核能够支持的网络接口都初始化成这个链表中的一个节点,并且每个节点都需要初始化出init函数指针,用来检测网络接口设备。然后,系统遍历整个dev_base链表,对每个节点分别调用init函数指针,如果成功,证明网络接口设备可用,那么这个节点就可以进一步初始化,如果返回失败,那么证明该网络设备不存在或是不可用,只能将该节点删除。启动结束之后,在dev_base中剩下的都是可以用的网络接口设备。

                2.5.1 do_initcalls---->net_dev_init()(net/core/dev.c)------>ethif_probe()(drivers/net/Space.c,在netdevice{}结构的init中调用,这边ethif_probe是以太网卡针对的调用)

     

     

    3.网络设备驱动程序(略)

     

     

    4.网络连接

     

         4.1 连接的建立和关闭

     

                tcp连接建立的代码如下:

                        server=gethostbyname(SERVER_NAME);

                        sockfd=socket(AF_INET,SOCK_STREAM,0);

                        address.sin_family=AF_INET;

                        address.sin_port=htons(PORT_NUM);

                        memcpy(&address.sin_addr,server->h_addr,server->h_length);

                        connect(sockfd,&address,sizeof(address));

           连接的初始化与建立期间主要发生的事情如下:

           1)sys_socket调用:调用socket_creat(),创建出一个满足传入参数family、type、和protocol的socket,调用sock_map_fd()获取一个未被使用的文件描述符,并且申请并初始化对应的file{}结构。

           2)sock_creat():创建socket结构,针对每种不同的family的socket结构的初始化,就需要调用不同的create函数来完成。对应于inet类型的地址来说,在网络协议初始化时调用sock_register()函数中完成注册的定义如下:

            struct net_proto_family inet_family_ops={

                    PF_INET;

                    inet_create

            };所以inet协议最后会调用inet_create函数。

           3)inet_create: 初始化sock的状态设置为SS_UNCONNECTED,申请一个新的sock结构,并且初始化socket的成员ops初始化为inet_stream_ops,而sock的成员prot初始化为tcp_prot。然后调用sock_init_data,将该socket结构的变量sock和sock类型的变量关联起来。

           4)在系统初始化完毕后便是进行connect的工作,系统调用connect将一个和socket结构关联的文件描述符和一个sockaddr{}结构的地址对应的远程机器相关联,并且调用各个协议自己对应的connect连接函数。对应于tcp类型,则sock->ops->connect便为inet_stream_connect。

           5)inet_stream_connect: 得到sk,sk=sock->sk,锁定sk,对自动获取sk的端口号存放在sk->num中,并且用htons()函数转换存放在sk->sport中。然后调用sk->prot->connect()函数指针,对tcp协议来说就是tcp_v4_connect()函数。然后将sock->state状态字设置为SS_CONNECTING,等待后面一系列的处理完成之后,就将状态改成SS_CONNECTTED。

           6) tcp_v4_connect():调用函数ip_route_connect(),寻找合适的路由存放在rt中。ip_route_connect找两次,第一次找到下一跳的ip地址,在路由缓存或fib中找到,然后第二次找到下一跳的具体邻居,到neigh_table中找到。然后申请出tcp头的空间存放在buff中。将sk中相关地址数据做一些针对路由的变动,并且初始化一个tcp连接的序列号,调用函数tcp_connect(),初始化tcp头,并设置tcp处理需要的定时器。一次connect()建立的过程就结束了。

           连接的关闭主要如下:

            1)close: 一个socket文件描述符对应的file{}结构中,有一个file_operations{}结构的成员f_ops,它的初始化关闭函数为sock_close函数。

            2)sock_close:调用函数sock_release(),参数为一个socket{}结构的指针。

            3)sock_release:调用inet_release,并释放socket的指针和文件空间

            4)inet_release: 调用和该socket对应协议的关闭函数inet_release,如果是tcp协议,那么调用的是tcp_close;最后释放sk。

            4.2 数据发送流程图

     

     

    各层主要函数以及位置功能说明:

            1)sock_write:初始化msghdr{}结构 net/socket.c

            2)sock_sendmsg:net/socket.c

            3)inet_sendmsg:net/ipv4/af_net.c

            4)tcp_sendmsg:申请sk_buff{}结构的空间,把msghdr{}结构中的数据填入sk_buff空间。net/ipv4/tcp.c

            5)tcp_send_skb:net/ipv4/tcp_output.c

            6)tcp_transmit_skb:net/ipv4/tcp_output.c

            7)ip_queue_xmit:net/ipv4/ip_output.c

            8)ip_queue_xmit2:net/ipv4/ip_output.c

            9)ip_output:net/ipv4/ip_output.c

            10)ip_finish_output:net/ipv4/ip_output.c

            11)ip_finish_output2:net/ipv4/ip_output.c

            12)neigh_resolve_output:net/core/neighbour.c

            13)dev_queue_xmit:net/core/dev.c

            4.3 数据接收流程图

     

    各层主要函数以及位置功能说明:

            1)sock_read:初始化msghdr{}的结构类型变量msg,并且将需要接收的数据存放的地址传给msg.msg_iov->iov_base.      net/socket.c

            2)sock_recvmsg: 调用函数指针sock->ops->recvmsg()完成在INET Socket层的数据接收过程.其中sock->ops被初始化为inet_stream_ops,其成员recvmsg对应的函数实现为inet_recvmsg()函数. net/socket.c

            3)sys_recv()/sys_recvfrom():分别对应着面向连接和面向无连接的协议两种情况. net/socket.c

            4)inet_recvmsg:调用sk->prot->recvmsg函数完成数据接收,这个函数对于tcp协议便是tcp_recvmsg net/ipv4/af_net.c

            5)tcp_recvmsg:从网络协议栈接收数据的动作,自上而下的触发动作一直到这个函数为止,出现了一次等待的过程.函数tcp_recvmsg可能会被动地等待在sk的接收数据队列上,也就是说,系统中肯定有其他地方会去修改这个队列使得tcp_recvmsg可以进行下去.入口参数sk是这个网络连接对应的sock{}指针,msg用于存放接收到的数据.接收数据的时候会去遍历接收队列中的数据,找到序列号合适的.

            但读取队列为空时tcp_recvmsg就会调用tcp_v4_do_rcv使用backlog队列填充接收队列.

            6)tcp_v4_rcv:tcp_v4_rcv被ip_local_deliver函数调用,是从IP层协议向INET Socket层提交的"数据到"请求,入口参数skb存放接收到的数据,len是接收的数据的长度,这个函数首先移动skb->data指针,让它指向tcp头,然后更新tcp层的一些数据统计,然后进行tcp的一些值的校验.再从INET Socket层中已经建立的sock{}结构变量中查找正在等待当前到达数据的哪一项.可能这个sock{}结构已经建立,或者还处于监听端口、等待数据连接的状态。返回的sock结构指针存放在sk中。然后根据其他进程对sk的操作情况,将skb发送到合适的位置.调用如下:

            TCP包接收器(tcp_v4_rcv)将TCP包投递到目的套接字进行接收处理. 当套接字正被用户锁定,TCP包将暂时排入该套接字的后备队列(sk_add_backlog).这时如果某一用户线程企图锁定该套接字(lock_sock),该线程被排入套接字的后备处理等待队列(sk->lock.wq).当用户释放上锁的套接字时(release_sock,在tcp_recvmsg中调用),后备队列中的TCP包被立即注入TCP包处理器(tcp_v4_do_rcv)进行处理,然后唤醒等待队列中最先的一个用户来获得其锁定权. 如果套接字未被上锁,当用户正在读取该套接字时, TCP包将被排入套接字的预备队列(tcp_prequeue),将其传递到该用户线程上下文中进行处理.如果添加到sk->prequeue不成功,便可以添加到 sk->receive_queue队列中(用户线程可以登记到预备队列,当预备队列中出现第一个包时就唤醒等待线程.)   /net/tcp_ipv4.c

            7)ip_rcv、ip_rcv_finish:从以太网接收数据,放到skb里,作ip层的一些数据及选项检查,调用ip_route_input()做路由处理,判断是进行ip转发还是将数据传递到高一层的协议.调用skb->dst->input函数指针,这个指针的实现可能有多种情况,如果路由得到的结果说明这个数据包应该转发到其他主机,这里的input便是ip_forward;如果数据包是给本机的,那么input指针初始化为ip_local_deliver函数./net/ipv4/ip_input.c

            8)ip_local_deliver、ip_local_deliver_finish:入口参数skb存放需要传送到上层协议的数据,从ip头中获取是否已经分拆的信息,如果已经分拆,则调用函数ip_defrag将数据包重组。然后通过调用ip_prot->handler指针调用tcp_v4_rcv(tcp)。ip_prot是inet_protocol结构指针,是用来ip层登记协议的,比如由udp,tcp,icmp等协议。 /net/ipv4/ip_input.c

     

     

    Linux通过同时对多种通信协议的支持来提供通用的底层基础服务。它的第一个网络模型的版本是4.3 BSD,也称为Net/1,今天的Linux已经使用Net/4 (Linux 2.2),其中大多数代码已经完全和BSD的版本不同,但是它依然支持UINX平台之间程序的移植。

    Linux网络套接字实现的模式是UNIX下的普遍标准。同时,Net/4的网络层是完全另起炉灶重写的。首先,新的网络层尽可能地实行并行处理, 因此其伸缩性比起以前的版本,不可同日而语。其次,它包括了许多的优化,以便绕过不少流行操作系统网络实现中的不合理处(例如Windows)。到目前为止,Linux 是唯一与IPv4和IPv6协议标准完全保持兼容的操作系统,而Linux2.4的IPv4伸缩性又大有提高。

    Linux支持的六种不同通信协议族:

    1) TCP/IP (使用TCP/IP的Internet 协议族),本文讨论的重点。

    2) UNIX域协议 (一种进程间通信的协议)

    3) X25协议

    4) AX25协议 (业余无线X25)

    5)IPX协议 (Novell IPX)

    6) APPLETALK协议 (AppleTalk DDP)

    1.1 内核源代码的组织

    表1是本文要使用的Linux Net/4网络源代码的,其中大部分位于目录/usr/src/linux-2.2.x/net,列表如下,

    插口层
    BSD Socket
    /net/socket.c
    /net/protocols.c
    INET Socket
    /ipv4/protocol.c
    /ipv4/af_inet.c
    /net/ipv4/core/sock.c
    协议层
    TCP/UDP
    /net/ipv4/udp.c
    /net/ipv4/datagram.c
    /net/ipv4/tcp_input.c
    /net/ipv4//tcp_output.c
    /net/ipv4/tcp.c
    /net/ipv4/tcp_minisocks.c
    /net/ipv4/tcp_timer.c etc...
    IP
    /net/ipv4/ip_forward.c
    /net/ipv4/ip_fragment.c
    /net/ipv4/ip_input.c
    /net/ipv4/ip_output.c
    接口层
    Ethernet
    ......

    1.2  Linux中TCP/IP网络层次结构与实现
    Linux通过一组相邻的软件层实现了TCP/IP模型,它由BSD Socket层、INET

    Socket层、传输层、网络层,和链路层构成。应用程序使用系统调用向内核函数传递参数和数据从而进入内核空间,由内核中注册的内核函数对相应的数据结构进行处理。Linux的TCP/IP层次结构和实现方式如图 1 所示。

    协议栈图片

    展开全文
  • linux tcp ip协议栈学习路线图(1)

    千次阅读 2018-06-17 16:06:02
    即将开启tcp/ip协议栈的学习,本篇博客主要是针对接下来即将分析的协议栈目录。1. tcp/ip协议栈的数据结构:详见2. inet_init()初始化,详见:点击打开链接3. socket()通信流程基于TCP(面向连接)的socket编程,...

    即将开启tcp/ip协议栈的学习,本篇博客主要是提供接下来即将分析的协议栈相应的文章目录。

    1. tcp/ip协议栈的数据结构,详见:点击打开链接

    2. inet_init()初始化,详见:点击打开链接

    3. socket()通信流程

    基于TCP(面向连接)的socket编程,分为客户端和服务器端。

    客户端的流程如下:
    (1)创建套接字(socket)详见:点击打开链接
    (2)向服务器发出连接请求(connect)
    (3)和服务器端进行通信(send/recv)
    (4)关闭套接字
    服务器端的流程如下:
    (1)创建套接字(socket)详见:点击打开链接
    (2)将套接字绑定到一个本地地址和端口上(bind)详见:点击打开链接
    (3)将套接字设为监听模式,准备接收客户端请求(listen)详见:点击打开链接
    (4)等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)
    (5)用返回的套接字和客户端进行通信(send/recv)
    (6)返回,等待另一个客户请求。
    (7)关闭套接字。


    展开全文
  • Linux关闭防火墙命令

    万次阅读 多人点赞 2019-05-27 14:59:55
    一、下面是red hat/CentOs7关闭防火墙的命令! 1:查看防火状态 systemctl status firewalld service iptablesstatus 2:暂时关闭防火墙 systemctl stop firewalld service iptablesstop 3:永久关闭防火墙 ...

    一、下面是red hat/CentOs7关闭防火墙的命令!

    1:查看防火状态

    systemctl status firewalld

    service  iptables status

    2:暂时关闭防火墙

    systemctl stop firewalld

    service  iptables stop

    3:永久关闭防火墙

    systemctl disable firewalld

    chkconfig iptables off

    4:重启防火墙

    systemctl enable firewalld

    service iptables restart  

    5:永久关闭后重启

    //暂时还没有试过

    chkconfig iptables on

     

    二、firewalld

    Centos7默认安装了firewalld,如果没有安装的话,可以使用 yum install firewalld firewalld-config进行安装。

    1.启动防火墙

    systemctl start firewalld 

    2.禁用防火墙

    systemctl stop firewalld

    3.设置开机启动

    systemctl enable firewalld

    4.停止并禁用开机启动

    sytemctl disable firewalld

    5.重启防火墙

     

    firewall-cmd --reload
    

    6.查看状态

    systemctl status firewalld或者 firewall-cmd --state

    7.查看版本

    firewall-cmd --version

    8.查看帮助

    firewall-cmd --help

    9.查看区域信息

    firewall-cmd --get-active-zones

    10.查看指定接口所属区域信息

    firewall-cmd --get-zone-of-interface=eth0

    11.拒绝所有包

    firewall-cmd --panic-on

    12.取消拒绝状态

    firewall-cmd --panic-off

    13.查看是否拒绝

    firewall-cmd --query-panic

    14.将接口添加到区域(默认接口都在public)

    firewall-cmd --zone=public --add-interface=eth0(永久生效再加上 --permanent 然后reload防火墙)

    15.设置默认接口区域

    firewall-cmd --set-default-zone=public(立即生效,无需重启)

    16.更新防火墙规则

    firewall-cmd --reload或firewall-cmd --complete-reload(两者的区别就是第一个无需断开连接,就是firewalld特性之一动态
    添加规则,第二个需要断开连接,类似重启服务)

    17.查看指定区域所有打开的端口

     

    firewall-cmd --zone=public --list-ports

    18.在指定区域打开端口(记得重启防火墙)

     

    firewall-cmd --zone=public --add-port=80/tcp(永久生效再加上 --permanent)
    

    说明:
    –zone 作用域
    –add-port=8080/tcp 添加端口,格式为:端口/通讯协议
    –permanent #永久生效,没有此参数重启后失效

    补充:

    CentOS 7 下使用 Firewall 

    在 CentOS 7 中,引入了一个新的服务,Firewalld,下面一张图,让大家明确的了解 Firewall 与 iptables 之间的关系与区别。

    firewall stack

    安装它,只需

    # yum install firewalld
    

    如果需要图形界面的话,则再安装

    # yum install firewall-config
    

    一、介绍

    防火墙守护 firewalld 服务引入了一个信任级别的概念来管理与之相关联的连接与接口。它支持 ipv4 与 ipv6,并支持网桥,采用 firewall-cmd (command) 或 firewall-config (gui) 来动态的管理 kernel netfilter 的临时或永久的接口规则,并实时生效而无需重启服务。

    zone

    Firewall 能将不同的网络连接归类到不同的信任级别,Zone 提供了以下几个级别

    • drop: 丢弃所有进入的包,而不给出任何响应
    • block: 拒绝所有外部发起的连接,允许内部发起的连接
    • public: 允许指定的进入连接
    • external: 同上,对伪装的进入连接,一般用于路由转发
    • dmz: 允许受限制的进入连接
    • work: 允许受信任的计算机被限制的进入连接,类似 workgroup
    • home: 同上,类似 homegroup
    • internal: 同上,范围针对所有互联网用户
    • trusted: 信任所有连接

    过滤规则

    • source: 根据源地址过滤
    • interface: 根据网卡过滤
    • service: 根据服务名过滤
    • port: 根据端口过滤
    • icmp-block: icmp 报文过滤,按照 icmp 类型配置
    • masquerade: ip 地址伪装
    • forward-port: 端口转发
    • rule: 自定义规则

    其中,过滤规则的优先级遵循如下顺序

    1. source
    2. interface
    3. firewalld.conf

    二、使用方法

    # systemctl start firewalld         # 启动,
    # systemctl enable firewalld        # 开机启动
    # systemctl stop firewalld          # 关闭
    # systemctl disable firewalld       # 取消开机启动
    

    具体的规则管理,可以使用 firewall-cmd,具体的使用方法可以

    $ firewall-cmd --help
    
    --zone=NAME                         # 指定 zone
    --permanent                         # 永久修改,--reload 后生效
    --timeout=seconds                   # 持续效果,到期后自动移除,用于调试,不能与 --permanent 同时使用
    

    1. 查看规则

    查看运行状态

    $ firewall-cmd --state
    

    查看已被激活的 Zone 信息

    $ firewall-cmd --get-active-zones
    public
      interfaces: eth0 eth1
    

    查看指定接口的 Zone 信息

    $ firewall-cmd --get-zone-of-interface=eth0
    public
    

    查看指定级别的接口

    $ firewall-cmd --zone=public --list-interfaces
    eth0
    

    查看指定级别的所有信息,譬如 public

    $ firewall-cmd --zone=public --list-all
    public (default, active)
      interfaces: eth0
      sources:
      services: dhcpv6-client http ssh
      ports:
      masquerade: no
      forward-ports:
      icmp-blocks:
      rich rules:
    

    查看所有级别被允许的信息

    $ firewall-cmd --get-service
    

    查看重启后所有 Zones 级别中被允许的服务,即永久放行的服务

    $ firewall-cmd --get-service --permanent
    

    2. 管理规则

    # firewall-cmd --panic-on           # 丢弃
    # firewall-cmd --panic-off          # 取消丢弃
    # firewall-cmd --query-panic        # 查看丢弃状态
    # firewall-cmd --reload             # 更新规则,不重启服务
    # firewall-cmd --complete-reload    # 更新规则,重启服务
    

    添加某接口至某信任等级,譬如添加 eth0 至 public,永久修改

    # firewall-cmd --zone=public --add-interface=eth0 --permanent
    

    设置 public 为默认的信任级别

    # firewall-cmd --set-default-zone=public
    

    a. 管理端口

    列出 dmz 级别的被允许的进入端口

    # firewall-cmd --zone=dmz --list-ports
    

    允许 tcp 端口 8080 至 dmz 级别

    # firewall-cmd --zone=dmz --add-port=8080/tcp
    

    允许某范围的 udp 端口至 public 级别,并永久生效

    # firewall-cmd --zone=public --add-port=5060-5059/udp --permanent
    

    b. 网卡接口

    列出 public zone 所有网卡

    # firewall-cmd --zone=public --list-interfaces
    

    将 eth0 添加至 public zone,永久

    # firewall-cmd --zone=public --permanent --add-interface=eth0
    

    eth0 存在与 public zone,将该网卡添加至 work zone,并将之从 public zone 中删除

    # firewall-cmd --zone=work --permanent --change-interface=eth0
    

    删除 public zone 中的 eth0,永久

    # firewall-cmd --zone=public --permanent --remove-interface=eth0
    

    c. 管理服务

    添加 smtp 服务至 work zone

    # firewall-cmd --zone=work --add-service=smtp
    

    移除 work zone 中的 smtp 服务

    # firewall-cmd --zone=work --remove-service=smtp
    

    d. 配置 external zone 中的 ip 地址伪装

    查看

    # firewall-cmd --zone=external --query-masquerade
    

    打开伪装

    # firewall-cmd --zone=external --add-masquerade
    

    关闭伪装

    # firewall-cmd --zone=external --remove-masquerade
    

    e. 配置 public zone 的端口转发

    要打开端口转发,则需要先

    # firewall-cmd --zone=public --add-masquerade
    

    然后转发 tcp 22 端口至 3753

    # firewall-cmd --zone=public --add-forward-port=port=22:proto=tcp:toport=3753
    

    转发 22 端口数据至另一个 ip 的相同端口上

    # firewall-cmd --zone=public --add-forward-port=port=22:proto=tcp:toaddr=192.168.1.100
    

    转发 22 端口数据至另一 ip 的 2055 端口上

    # firewall-cmd --zone=public --add-forward-port=port=22:proto=tcp:toport=2055:toaddr=192.168.1.100
    

    f. 配置 public zone 的 icmp

    查看所有支持的 icmp 类型

    # firewall-cmd --get-icmptypes
    destination-unreachable echo-reply echo-request parameter-problem redirect router-advertisement router-solicitation source-quench time-exceeded
    

    列出

    # firewall-cmd --zone=public --list-icmp-blocks
    

    添加 echo-request 屏蔽

    # firewall-cmd --zone=public --add-icmp-block=echo-request [--timeout=seconds]
    

    移除 echo-reply 屏蔽

    # firewall-cmd --zone=public --remove-icmp-block=echo-reply
    

    g. IP 封禁

    # firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='222.222.222.222' reject"
    

    当然,我们仍然可以通过 ipset 来封禁 ip

    封禁 ip

    # firewall-cmd --permanent --zone=public --new-ipset=blacklist --type=hash:ip
    # firewall-cmd --permanent --zone=public --ipset=blacklist --add-entry=222.222.222.222
    

    封禁网段

    # firewall-cmd --permanent --zone=public --new-ipset=blacklist --type=hash:net
    # firewall-cmd --permanent --zone=public --ipset=blacklist --add-entry=222.222.222.0/24
    

    导入 ipset 的 blacklist 规则

    # firewall-cmd --permanent --zone=public --new-ipset-from-file=/path/blacklist.xml
    

    如果已经存 blacklist,则需要先删除

    # firewall-cmd --get-ipsets
    blacklist
    # firewall-cmd --permanent --zone=public --delete-ipset=blacklist
    

    然后封禁 blacklist

    # firewall-cmd --permanent --zone=public --add-rich-rule='rule source ipset=blacklist drop'
    

    重新载入以生效

    # firewall-cmd --reload
    

    查看 blacklist

    # firewall-cmd --ipset=blacklist --get-entries
    

    以上都是一些常用方法,更多高级方法,请参考:

    展开全文
  • Linux TCP/IP 协议栈源码分析 - 数据 发送/接收 流程图
  • linux TCP/IP协议端口分配规则与分类

    千次阅读 2017-12-30 22:38:34
    TCP/IP 协议中的端口在报头中占2个字节即16位,范围是从0-65535。端口号用来表示和区别网络中的不同应用程序 端口分类 (1)公认端口(Well Known Ports):0-1023之间的端口号,也叫Well Known ports。这些端口由...
  • linux-Tcp IP协议栈源码阅读笔记

    千次阅读 2013-11-16 15:08:06
    一.linux内核网络栈代码的准备知识   1. linux内核ipv4网络部分分层结构:   BSD socket层: 这一部分处理BSD socket相关操作,每个socket在内核中以struct socket结构体现。这一部分的文件   主要有:/...
  • Linux下TCP/IP协议栈的简单脉络分析

    千次阅读 2015-08-11 22:13:17
    由于之前有简单的看过一些TCP/IP详解的一些东西,所以索性就找了本《追踪LinuxTCP/IP代码运行》的书看了一上午,结果发现初次接触这些内核方面的东西,收获甚微。于是又在网上找相关类的大神博客,拿来拜读,虽然...
  • 1、IP协议首部格式(IP协议处余网络层) IP数据报首部图片格式: 最高位在左边,记为0 bit;最低位在右边,记为31 bit 头部代码结构如下 //定义IP首部 typedef struct _iphdr{ unsigned char h_lenv
  • Linux关闭防火墙 / 开放端口

    千次阅读 2020-07-05 13:05:43
    Linux常用的JDK / Tomcat / Nginx软件安装已经安装后无法访问的问题,是由于Linux防火墙开启禁用了端口,那么需要解决的问题就是端口开放或者关闭防火墙。本问题将介绍CentOS 6 以及CentOS 7的解决方案。
  • Linux iptables IP映射 跨网段访问

    千次阅读 2019-03-11 15:17:09
    Linux iptables IP映射 跨网段访问 19.1 前言 开发中,遇到一个跨多个网段访问设备内部局域网的问题。刚开始对这个跨网段的问题无从下手,但后面想了又想,难道不能让一个网口直接桥接到另外一个网口吗?顺着这个...
  • Linux网络协议栈--IP

    千次阅读 2012-08-01 21:49:53
    IP是什么就不介绍了,不清楚的请自行百度。 这篇文章的定位 (1)说明下网络层中IPV4协议收发数据的流程 (2)不涉及太多细节 (3)一些关键数据结构 (4)一部分关于路由系统 (5)为更清晰看清楚中间的流程...
  • 假如是IP数据报,IP协议再根据IP首部中的“上层协议”字段确定该数据报的有效载荷是TCP、UDP、ICMP还是IGMP,然后交给相应的协议处理。假如是TCP段或UDP段,TCP或UDP协议再根据TCP首部或UDP首部的“ 端口号 ”字段...
  • Linux 修改IP

    千次阅读 2012-05-24 10:24:38
    即时生效: ifconfig eth0 192.168.1.102 netmask 255.255.255.0 启动生效: vim /etc/sysconfig/network-scripts/...IPADDR=192.168.1.102 NETMASK=255.255.255.0 修改default gateway 即时生效: route add d
  • Linux修改ip配置文件

    千次阅读 2020-10-12 21:18:59
    通过修改配置文件是IP地址永久生效 第一步进入配置文件所在目录: cd /etc/sysconfig/network-scripts/ #进入配置文件ifcfg-ens33所在位置 第二步写入配置信息并保存退出: vi ifcfg-ens33 #编辑配置文件ifcfg-ens33...
  • linuxip 命令 和 ifconfig 命令

    万次阅读 多人点赞 2017-04-01 00:14:15
    net-tools起源于BSD的TCP/IP工具箱,后来成为老版本Linux内核中配置网络功能的工具。但自2001年起,Linux社区已经对其停止维护。同时,一些Linux发行版比如Arch Linux和CentOS/RHEL 7则已经完全抛弃了net-tools,只...
  • linux iptables IP限制访问 指定IP访问

    万次阅读 2017-09-11 10:47:30
    只允许指定的一个IP访问服务器 vi /etc/sysconfig/iptables *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -s 165.232.121.17 -j ACCEPT -A INPUT -j DROP COMMIT ...
  • linux ping IP地址与telnet 测试IP端口

    万次阅读 2018-07-27 09:53:13
    格式:ping IP地址或主机名 [-t] [-a] [-n count] [-l size] 参数含义:-t不停地向目标主机发送数据; -a 以IP地址格式来显示目标主机的网络地址 ; -n count 指定要Ping多少次,具体次数由count来指定 ; -l ...
  • TCP/IP协议四层模型

    万次阅读 多人点赞 2017-10-28 17:18:26
      TCP/IP协议族是一个四层协议系统:1. 数据链路层  1.1 作用   (1) 实现网卡接口的网络驱动,以处理数据在以太网线等物理媒介上的传输   (2) 网络驱动程序隐藏了不同物理网络的不同电气特性,为上层协议...
  • 1、TCP/IP简介 1.1 协议简介 ... 两台计算机通过TCP/IP协议通讯的过程如上图右所示。传输层及其以下的机制由内核提供,应用层由用户进程提供(后面将介绍如何使用socket API编 写应用程序),应用程序对
  • 嵌入式linux的网络编程(1)--TCP/IP协议概述1.OSI参考模型及TCP/IP参考模型 通信协议用于协调不同网络设备之间的信息交换,它们建立了设备之间互相识别的信息机制.大家一定都听说过著名的OSI协议参考模型,它是基于国际...
  • 一.linux内核网络栈代码的准备知识 1. linux内核ipv4网络部分分层结构: BSD socket层: 这一部分处理BSD socket相关操作,每个socket在内核...INET socket层:BSD socket是个可以用于各种网络协议的接口,而当...
  • iproute是Linux下一个网络管理工具包合集,用于取代先前的如ifconfig,route,ifup,ifdown,netstat等历史网络管理工具。该工具包功能强大,它通过网络链路套接字接口与内核进行联系。iproute的用户界面比net-tools...
  • Linux系统中网络协议和网络配置文件的介绍

    千次阅读 多人点赞 2020-07-08 11:29:10
    网络协议介绍1.1 网络协议的概念1.2 TCP/IP协议1.3 常见的网络应用协议1.3.1 HTTP协议1.3.2 DNS协议1.3.3 FTP协议1.3.4 Telnet协议二.网络配置文件介绍2.1 配置文件介绍2.2 网络接口配置文件介绍2.3 主机名称配置...
  • linux常用命令:ip 命令

    千次阅读 2019-07-07 10:46:33
    ip命令用来显示或操纵Linux主机的路由、网络设备、策略路由和隧道,是Linux下较新的功能强大的网络配置工具。ip命令完全可以替代ifconfig命令,而且功能还比ifconfig命令强大 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 131,379
精华内容 52,551
关键字:

linux关闭ip6协议

linux 订阅