在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

深度解析Linux網絡路徑及sk_buff struct 數據結構

454398 ? 來源:博客園 ? 作者: SammyLiu ? 2020-10-22 15:04 ? 次閱讀

理解 Linux 網絡棧(1):Linux 網絡協議棧簡單總結

本系列文章總結 Linux 網絡棧,包括:

(1)Linux 網絡協議棧總結

(2)非虛擬化Linux環境中的網絡分段卸載技術 GSO/TSO/UFO/LRO/GRO

(3)QEMU/KVM + VxLAN 環境下的 Segmentation Offloading 技術(發送端)

(4)QEMU/KVM + VxLAN 環境下的 Segmentation Offloading 技術(接收端)

1. Linux 網絡路徑

1.1 發送端

1.1.1 應用層

(1) Socket

應用層的各種網絡應用程序基本上都是通過 Linux Socket 編程接口來和內核空間的網絡協議棧通信的。Linux Socket 是從 BSD Socket 發展而來的,它是 Linux 操作系統的重要組成部分之一,它是網絡應用程序的基礎。從層次上來說,它位于應用層,是操作系統為應用程序員提供的 API,通過它,應用程序可以訪問傳輸層協議。

socket 位于傳輸層協議之上,屏蔽了不同網絡協議之間的差異

socket 是網絡編程的入口,它提供了大量的系統調用,構成了網絡程序的主體

在Linux系統中,socket 屬于文件系統的一部分,網絡通信可以被看作是對文件的讀取,使得我們對網絡的控制和對文件的控制一樣方便。

(2) 應用層處理流程

網絡應用調用Socket APIsocket (int family, int type, int protocol)創建一個 socket,該調用最終會調用 Linux system callsocket() ,并最終調用 Linux Kernel 的 sock_create() 方法。該方法返回被創建好了的那個 socket 的 file descriptor。對于每一個 userspace 網絡應用創建的 socket,在內核中都有一個對應的 struct socket和 struct sock。其中,struct sock 有三個隊列(queue),分別是rx , tx 和 err,在sock 結構被初始化的時候,這些緩沖隊列也被初始化完成;在收據收發過程中,每個 queue 中保存要發送或者接受的每個 packet 對應的 Linux 網絡棧 sk_buffer 數據結構的實例 skb。

對于 TCP socket 來說,應用調用 connect()API ,使得客戶端和服務器端通過該 socket 建立一個虛擬連接。在此過程中,TCP 協議棧通過三次握手會建立 TCP 連接。默認地,該 API 會等到 TCP 握手完成連接建立后才返回。在建立連接的過程中的一個重要步驟是,確定雙方使用的 Maxium Segemet Size (MSS)。因為 UDP 是面向無連接的協議,因此它是不需要該步驟的。

應用調用 Linux Socket 的 send 或者 write API 來發出一個 message 給接收端

sock_sendmsg 被調用,它使用 socket descriptor 獲取 sock struct,創建 message header 和 socket control message

_sock_sendmsg 被調用,根據 socket 的協議類型,調用相應協議的發送函數。

對于 TCP ,調用 tcp_sendmsg 函數。

對于 UDP 來說,userspace 應用可以調用 send()/sendto()/sendmsg() 三個 system call 中的任意一個來發送 UDP message,它們最終都會調用內核中的 udp_sendmsg() 函數。

1.1.2 傳輸層

傳輸層的最終目的是向它的用戶提供高效的、可靠的和成本有效的數據傳輸服務,主要功能包括 (1)構造 TCP segment (2)計算 checksum (3)發送回復(ACK)包 (4)滑動窗口(sliding windown)等保證可靠性的操作。TCP 協議棧的大致處理過程如下圖所示:

TCP 棧簡要過程:

tcp_sendmsg 函數會首先檢查已經建立的 TCP connection 的狀態,然后獲取該連接的 MSS,開始 segement 發送流程。

構造 TCP 段的 playload:它在內核空間中創建該 packet 的 sk_buffer 數據結構的實例 skb,從 userspace buffer 中拷貝 packet 的數據到 skb 的 buffer。

構造 TCP header。

計算 TCP 校驗和(checksum)和 順序號 (sequence number)。

TCP 校驗和是一個端到端的校驗和,由發送端計算,然后由接收端驗證。其目的是為了發現TCP首部和數據在發送端到接收端之間發生的任何改動。如果接收方檢測到校驗和有差錯,則TCP段會被直接丟棄。TCP校驗和覆蓋 TCP 首部和 TCP 數據。

TCP的校驗和是必需的

發到 IP 層處理:調用 IP handler 句柄 ip_queue_xmit,將 skb 傳入 IP 處理流程。

UDP 棧簡要過程:

UDP 將 message 封裝成 UDP 數據報

調用 ip_append_data() 方法將 packet 送到 IP 層進行處理。

1.1.3 IP 網絡層 - 添加header 和 checksum,路由處理,IP fragmentation

網絡層的任務就是選擇合適的網間路由和交換結點, 確保數據及時傳送。網絡層將數據鏈路層提供的幀組成數據包,包中封裝有網絡層包頭,其中含有邏輯地址信息- -源站點和目的站點地址的網絡地址。其主要任務包括 (1)路由處理,即選擇下一跳 (2)添加 IP header(3)計算 IP header checksum,用于檢測 IP 報文頭部在傳播過程中是否出錯 (4)可能的話,進行 IP 分片(5)處理完畢,獲取下一跳的 MAC 地址,設置鏈路層報文頭,然后轉入鏈路層處理。

IP 頭:

IP 棧基本處理過程如下圖所示:

首先,ip_queue_xmit(skb)會檢查skb->dst路由信息。如果沒有,比如套接字的第一個包,就使用ip_route_output()選擇一個路由。

接著,填充IP包的各個字段,比如版本、包頭長度、TOS等。

中間的一些分片等,可參閱相關文檔。基本思想是,當報文的長度大于mtu,gso的長度不為0就會調用 ip_fragment 進行分片,否則就會調用ip_finish_output2把數據發送出去。ip_fragment 函數中,會檢查 IP_DF 標志位,如果待分片IP數據包禁止分片,則調用icmp_send()向發送方發送一個原因為需要分片而設置了不分片標志的目的不可達ICMP報文,并丟棄報文,即設置IP狀態為分片失敗,釋放skb,返回消息過長錯誤碼。

接下來就用 ip_finish_ouput2 設置鏈路層報文頭了。如果,鏈路層報頭緩存有(即hh不為空),那就拷貝到skb里。如果沒,那么就調用neigh_resolve_output,使用 ARP 獲取。

1.1.4 數據鏈路層

功能上,在物理層提供比特流服務的基礎上,建立相鄰結點之間的數據鏈路,通過差錯控制提供數據幀(Frame)在信道上無差錯的傳輸,并進行各電路上的動作系列。數據鏈路層在不可靠的物理介質上提供可靠的傳輸。該層的作用包括:物理地址尋址、數據的成幀、流量控制、數據的檢錯、重發等。在這一層,數據的單位稱為幀(frame)。數據鏈路層協議的代表包括:SDLC、HDLC、PPP、STP、幀中繼等。

實現上,Linux 提供了一個 Network device 的抽象層,其實現在 linux/net/core/dev.c。具體的物理網絡設備在設備驅動中(driver.c)需要實現其中的虛函數。Network Device 抽象層調用具體網絡設備的函數。

1.1.5 物理層 - 物理層封裝和發送

物理層在收到發送請求之后,通過 DMA 將該主存中的數據拷貝至內部RAM(buffer)之中。在數據拷貝中,同時加入符合以太網協議的相關header,IFG、前導符和CRC。對于以太網網絡,物理層發送采用CSMA/CD,即在發送過程中偵聽鏈路沖突。

一旦網卡完成報文發送,將產生中斷通知CPU,然后驅動層中的中斷處理程序就可以刪除保存的 skb 了。

1.1.6 簡單總結

(來源)

1.2 接收端

1.2.1 物理層和數據鏈路層

簡要過程:

一個 package 到達機器的物理網絡適配器,當它接收到數據幀時,就會觸發一個中斷,并將通過 DMA 傳送到位于 linux kernel 內存中的 rx_ring。

網卡發出中斷,通知 CPU 有個 package 需要它處理。中斷處理程序主要進行以下一些操作,包括分配 skb_buff 數據結構,并將接收到的數據幀從網絡適配器I/O端口拷貝到skb_buff 緩沖區中;從數據幀中提取出一些信息,并設置 skb_buff 相應的參數,這些參數將被上層的網絡協議使用,例如skb->protocol;

終端處理程序經過簡單處理后,發出一個軟中斷(NET_RX_SOFTIRQ),通知內核接收到新的數據幀。

內核 2.5 中引入一組新的 API 來處理接收的數據幀,即 NAPI。所以,驅動有兩種方式通知內核:(1) 通過以前的函數netif_rx;(2)通過NAPI機制。該中斷處理程序調用 Network device的 netif_rx_schedule 函數,進入軟中斷處理流程,再調用 net_rx_action 函數。

該函數關閉中斷,獲取每個 Network device 的 rx_ring 中的所有 package,最終 pacakage 從 rx_ring 中被刪除,進入 netif _receive_skb 處理流程。

netif_receive_skb 是鏈路層接收數據報的最后一站。它根據注冊在全局數組 ptype_all 和 ptype_base 里的網絡層數據報類型,把數據報遞交給不同的網絡層協議的接收函數(INET域中主要是ip_rcv和arp_rcv)。該函數主要就是調用第三層協議的接收函數處理該skb包,進入第三層網絡層處理。

1.2.2 網絡層

IP 層的入口函數在 ip_rcv 函數。該函數首先會做包括 package checksum 在內的各種檢查,如果需要的話會做 IP defragment(將多個分片合并),然后 packet 調用已經注冊的 Pre-routing netfilter hook ,完成后最終到達 ip_rcv_finish 函數。

ip_rcv_finish 函數會調用 ip_router_input 函數,進入路由處理環節。它首先會調用 ip_route_input 來更新路由,然后查找 route,決定該 package 將會被發到本機還是會被轉發還是丟棄:

如果是發到本機的話,調用 ip_local_deliver 函數,可能會做 de-fragment(合并多個 IP packet),然后調用 ip_local_deliver 函數。該函數根據 package 的下一個處理層的 protocal number,調用下一層接口,包括 tcp_v4_rcv (TCP), udp_rcv (UDP),icmp_rcv (ICMP),igmp_rcv(IGMP)。對于 TCP 來說,函數 tcp_v4_rcv 函數會被調用,從而處理流程進入 TCP 棧。

如果需要轉發 (forward),則進入轉發流程。該流程需要處理 TTL,再調用 dst_input 函數。該函數會 (1)處理 Netfilter Hook (2)執行 IP fragmentation (3)調用dev_queue_xmit,進入鏈路層處理流程。

1.2.3 傳輸層 (TCP/UDP)

傳輸層 TCP 處理入口在 tcp_v4_rcv 函數(位于 linux/net/ipv4/tcp ipv4.c 文件中),它會做 TCP header 檢查等處理。

調用 _tcp_v4_lookup,查找該 package 的 open socket。如果找不到,該 package 會被丟棄。接下來檢查 socket 和 connection 的狀態。

如果socket 和 connection 一切正常,調用 tcp_prequeue 使 package 從內核進入 user space,放進 socket 的 receive queue。然后 socket 會被喚醒,調用 system call,并最終調用 tcp_recvmsg 函數去從 socket recieve queue 中獲取 segment。

1.2.4 接收端 - 應用層

每當用戶應用調用 read 或者 recvfrom 時,該調用會被映射為/net/socket.c 中的 sys_recv 系統調用,并被轉化為 sys_recvfrom 調用,然后調用 sock_recgmsg 函數。

對于 INET 類型的 socket,/net/ipv4/af inet.c 中的inet_recvmsg 方法會被調用,它會調用相關協議的數據接收方法。

對 TCP 來說,調用 tcp_recvmsg。該函數從 socket buffer 中拷貝數據到 user buffer。

對 UDP 來說,從 user space 中可以調用三個 system call recv()/recvfrom()/recvmsg() 中的任意一個來接收 UDP package,這些系統調用最終都會調用內核中的 udp_recvmsg 方法。

1.2.5 報文接收過程簡單總結

2. Linux sk_buff struct 數據結構和隊列(Queue)

2.1 sk_buff

(本章節摘選自http://amsekharkernel.blogspot.com/2014/08/what-is-skb-in-linux-kernel-what-are.html)

2.1.1 sk_buff 是什么

當網絡包被內核處理時,底層協議的數據被傳送更高層,當數據傳送時過程反過來。由不同協議產生的數據(包括頭和負載)不斷往下層傳遞直到它們最終被發送。因為這些操作的速度對于網絡層的表現至關重要,內核使用一個特定的結構叫 sk_buff,其定義文件在skbuffer.h。Socket buffer被用來在網絡實現層交換數據而不用拷貝來或去數據包 –這顯著獲得速度收益。

sk_buff 是 Linux 網絡的一個核心數據結構,其定義文件在skbuffer.h。

socket kernel buffer (skb) 是 Linux 內核網絡棧(L2 到 L4)處理網絡包(packets)所使用的 buffer,它的類型是 sk_buffer。簡單來說,一個 skb 表示 Linux 網絡棧中的一個 packet;TCP 分段和 IP 分組生產的多個 skb 被一個 skb list 形式來保存。

struct sock 有三個 skb 隊列(sk_buffer queue),分別是rx , tx 和 err。

它的主要結構成員:

struct sk_buff {
    /* These two members must be first. */ # packet 可以存在于 list 或者 queue 中,這兩個成員用于鏈表處理
    struct sk_buff        *next;
    struct sk_buff        *prev;
    struct sk_buff_head    *list; #該 packet 所在的 list
 ...
    struct sock        *sk;      #跟該 skb 相關聯的 socket
    struct timeval        stamp; # packet 發送或者接收的時間,主要用于 packet sniffers
    struct net_device    *dev;  #這三個成員跟蹤該 packet 相關的 devices,比如接收它的設備等
    struct net_device    *input_dev;
    struct net_device    *real_dev;

    union {                  #指向各協議層 header 結構
        struct tcphdr    *th;
        struct udphdr    *uh;
        struct icmphdr    *icmph;
        struct igmphdr    *igmph;
        struct iphdr    *ipiph;
        struct ipv6hdr    *ipv6h;
        unsigned char    *raw;
    } h;

    union {
        struct iphdr    *iph;
        struct ipv6hdr    *ipv6h;
        struct arphdr    *arph;
        unsigned char    *raw;
    } nh;

    union {
        unsigned char    *raw;
    } mac;

    struct  dst_entry    *dst; #指向該 packet 的路由目的結構,告訴我們它會被如何路由到目的地
    char            cb[40];    # SKB control block,用于各協議層保存私有信息,比如 TCP 的順序號和幀的重發狀態
    unsigned int        len, #packet 的長度
                data_len,
                mac_len,       # MAC header 長度
                csum;          # packet 的 checksum,用于計算保存在 protocol header 中的校驗和。發送時,當 checksum offloading 時,不設置;接收時,可以由device計算

    unsigned char        local_df, #用于 IPV4 在已經做了分片的情況下的再分片,比如 IPSEC 情況下。
                cloned:1, #在 skb 被 cloned 時設置,此時,skb 各成員是自己的,但是數據是shared的
                nohdr:1,  #用于支持 TSO
                pkt_type, #packet 類型
                ip_summed; # 網卡能支持的校驗和計算的類型,NONE 表示不支持,HW 表示支持,

    __u32            priority; #用于 QoS
    unsigned short        protocol, # 接收 packet 的協議
                security;

2.1.2 skb 的主要操作

(1)分配skb = alloc_skb(len, GFP_KERNEL)

(2)添加 payload(skb_put(skb, user_data_len))

(3)使用skb->push 添加 protocol header,或者 skb->pull 刪除 header

2.2 Linux 網絡棧使用的驅動隊列 (driver queue)

(本章節摘選自Queueing in the Linux Network StackbyDan Siemon)

2.2.1 隊列

在 IP 棧和 NIC 驅動之間,存在一個 driver queue (驅動隊列)。典型地,它被實現為 FIFO ring buffer,簡單地可以認為它是固定大小的。這個隊列不包含 packet data,相反,它只是保存 socket kernel buffer (skb)的指針,而 skb 的使用如上節所述是貫穿內核網絡棧處理過程的始終的。

該隊列的輸入時 IP 棧處理完畢的 packets。這些packets 要么是本機的應用產生的,要么是進入本機又要被路由出去的。被 IP 棧加入隊列的 packets 會被網絡設備驅動(hardware driver)取出并且通過一個數據通道(data bus)發到 NIC 硬件設備并傳輸出去。

在不使用 TSO/GSO 的情況下,IP 棧發到該隊列的 packets 的長度必須小于 MTU。

2.2.2 skb 大小 - 默認最大大小為 NIC MTU

絕大多數的網卡都有一個固定的最大傳輸單元(maximum transmission unit, MTU)屬性,它是該網絡設備能夠傳輸的最大幀(frame)的大小。對以太網來說,默認值為 1500 bytes,但是有些以太網絡可以支持巨幀(jumbo frame),最大能到 9000 bytes。在 IP 網絡棧內,MTU 表示能發給 NIC 的最大 packet 的大小。比如,如果一個應用向一個 TCP socket 寫入了 2000 bytes 數據,那么 IP 棧需要創建兩個 IP packets 來保持每個 packet 的大小等于或者小于 1500 bytes。可見,對于大數據傳輸,相對較小的 MTU 會導致產生大量的小網絡包(small packets)并被傳入 driver queue。這成為 IP 分片 (IP fragmentation)。

下圖表示 payload 為 1500 bytes 的 IP 包,在 MTU 為 1000 和 600 時候的分片情況:

備注:

以上資料是從網絡上獲取的各種資料整理而來

這一塊本身就比較復雜,而且不同的 linux 內核的版本之間也有差異,文中的內容還需要進一步加工,錯誤在所難免。

編輯:hfy

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11479

    瀏覽量

    213067
  • Socket
    +關注

    關注

    1

    文章

    212

    瀏覽量

    35661
  • 網絡協議
    +關注

    關注

    3

    文章

    273

    瀏覽量

    22030
  • 數據結構
    +關注

    關注

    3

    文章

    573

    瀏覽量

    40644
收藏 人收藏

    評論

    相關推薦
    熱點推薦

    Linux sk_buff四大指針與相關操作

     在以上文章中,沒有分析過Linux內核網絡關鍵的數據結構-套接字數據緩存struct sk_buff
    發表于 10-13 17:23 ?5196次閱讀
    <b class='flag-5'>Linux</b> <b class='flag-5'>sk_buff</b>四大指針與相關操作

    深度數據結構的疑問

    你好,我對深度數據結構(STDepthTableControl)有一些疑問:typedef結構{ uint32_t depthUnits; int32_t depthClampMin
    發表于 11-08 11:09

    嵌入式linux TCP/IP協議棧概述

    包包頭。3. 數據傳輸數據的傳輸使用了一個非常重要的結構sk_buff,該結構體用來實現數據
    發表于 12-07 10:05

    Linux內核中的數據結構的一點認識

    大家都知道linux內核是世界上優秀的軟件之一,作為一款優秀的軟件,其中的許多的設計都精妙之處,十分值得學習和借鑒。今天我們就帶大家看一下內核中的數據結構中一點設計。打開內核源碼中的 include
    發表于 04-20 16:42

    LINUX 進程源代碼分析

    LINUX 進程源代碼分析 task_struct 數據結構表示進程的數據結構struct task_
    發表于 02-09 15:13 ?16次下載

    Linux網絡設備驅動程序

    當要發送數據包的時候,內核必須建立一個包含傳輸數據sk_buff,然后將sk_buff交給下層,各層在sk_buff遞交給下一層,各層在
    發表于 05-10 11:15 ?1920次閱讀

    Linux發送HTTP網絡包圖像 sk_buff數據結構解析

    如果你對Linux是如何實現 對用戶原始的網絡包進行協議頭封裝與解析,為什么會粘包拆包,期間網絡包經歷了哪些緩沖區、經歷了幾次拷貝(CPU、DMA),TCP又是如何實現滑動/擁塞窗口
    的頭像 發表于 05-10 12:14 ?2571次閱讀

    網卡的Ring Buffer詳解

    DMA 將 NIC 接收的數據包逐個寫入 sk_buff ,一個數據包可能占用多個 sk_buff , sk_buff 讀寫順序遵循FIFO
    的頭像 發表于 03-17 14:25 ?1911次閱讀

    Linux內核的鏈表數據結構

    Linux內核實現了自己的鏈表數據結構,它的設計與傳統的方式不同,非常巧妙也很通用。
    的頭像 發表于 03-24 11:34 ?1039次閱讀
    <b class='flag-5'>Linux</b>內核的鏈表<b class='flag-5'>數據結構</b>

    網卡的Ring Buffer詳解

    DMA 將 NIC 接收的數據包逐個寫入 sk_buff ,一個數據包可能占用多個 sk_buff , sk_buff 讀寫順序遵循FIFO
    的頭像 發表于 04-04 09:15 ?1499次閱讀

    sk_buff內存空間布局情況與相關操作(一)

    套接字數據緩存(socket buffer)在Linux內核中表示為:struct sk_buff,是Linux內核中
    的頭像 發表于 07-30 16:43 ?1560次閱讀
    <b class='flag-5'>sk_buff</b>內存空間布局情況與相關操作(一)

    sk_buff內存空間布局情況與相關操作(二)

    操作tailroom中用戶數據塊區域:skb_put用于修改指向數據區末尾的指針tail: void *skb_put( struct sk_buff *skb, unsigned i
    的頭像 發表于 07-30 16:47 ?993次閱讀
    <b class='flag-5'>sk_buff</b>內存空間布局情況與相關操作(二)

    sk_buff內存空間布局情況與相關操作(三)

    2、非線性區域 在1、中,可以看到每張sk_buff的圖: 在end指針緊挨著一個非線性區域 ; 在struct sk_buff中沒有指向skb_shared_info結構的指針,利用
    的頭像 發表于 07-30 16:48 ?1629次閱讀
    <b class='flag-5'>sk_buff</b>內存空間布局情況與相關操作(三)

    linux設備模型數據結構分析

    數據結構 2.1 kobject kobject 代表內核對象,結構體本身不單獨使用,而是嵌套在其他高層結構中,用于組織成拓撲關系; sysfs 文件系統中一個目錄對應一個 kobject ; 看看
    的頭像 發表于 09-28 14:44 ?723次閱讀
    <b class='flag-5'>linux</b>設備模型<b class='flag-5'>數據結構</b>分析

    Linux GIC驅動數據結構分析

    數據結構分析 先來張圖: GIC驅動中,使用 struct gic_chip_data 結構體來描述GIC控制器的信息,整個驅動都是圍繞著該結構體的初始化,驅動中將函數指針都初始化好,
    的頭像 發表于 09-28 15:18 ?781次閱讀
    <b class='flag-5'>Linux</b> GIC驅動<b class='flag-5'>數據結構</b>分析
    主站蜘蛛池模板: 亚洲阿v天堂2018在线观看 | 国产成视频 | 日韩一级片免费看 | 全国最大色成免费网站 | 在线精品视频成人网 | 天天做天天爱夜夜大爽完整 | 女人色网 | 国产精品网址你懂的 | 4388x17亚洲最大成人网 | 国产乱码精品一区二区三区四川人 | 天天操天天做 | 国产精品情人露脸在线观看 | 特黄特黄特色大片免费观看 | 97视频人人 | 四虎永久在线观看免费网站网址 | 日韩成人毛片高清视频免费看 | 女bbbbxxxx视频| 亚洲成人在线网站 | 国产福利小视频在线观看 | 久久天天躁综合夜夜黑人鲁色 | 欧洲成品大片在线播放 | 色婷婷综合久久久久中文一区二区 | 成在线人视频免费视频 | 中文字幕 视频一区 | 小说区v天堂网 | chinese国产videoxx实拍 | 中文天堂网 | 四虎www.| 手机福利视频 | 天天在线看片 | aaa在线观看视频高清视频 | 天天躁夜夜躁狠狠躁2021a | 国产精品久久久久久久久kt | 日本簧片在线观看 | 国产v精品成人免费视频400条 | 天堂网视频 | 久久看精品 | 免费一级牲交毛片 | 高清视频 一区二区三区四区 | 男人都懂的网址在线看片 | 草草影院私人免费入口 |