日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

1.1 linux網絡

  • Linux 是因特網的產物, 這是無可爭議的. 首先, 得感謝因特網通信, Linux的開發過程證明了一個很多人曾持有的觀點是荒謬的 : 對分散在世界各地的一組程序員進行項目管理是不可能的. 第一個內核源代碼版本是在十多年前通過FTP服務器提供的, 此后網絡便成了數據交換的支柱, 無論是概念和代碼的開發, 還是內核錯誤的消除, 都是如此.
  • 內核郵件列表是個活生生的例子, 它幾乎沒有改變過. 每個人都能夠看到最新貢獻的代碼, 并為促進Linux的開發提出自己的意見, 當然, 得假定所表達的意見是合理的. Linux對各種網絡適應得都很好, 這是可以理解的, 因為它是與因特網共同成長的.
  • 在構成因特網的服務器中, 大部分是運行Linux的計算機. 不出所料, 網絡實現是Linux內核中一個關鍵的部分, 正在獲得越來越多的關注. 實際上, Linux不支持的網絡方案很少.
  • 網絡功能的實現是內核最復雜、牽涉最廣的一部分. 除了經典的因特網協議(如TCP、UDP)和相關的IP傳輸機制之外, Linux還支持許多其他的互聯方案,使得所有想得到的計算機/操作系統能夠互操作.
  • Linux也支持大量用于數據傳輸的硬件, 如以太網卡和令牌環網適配器及ISDN卡和調制解調器, 但這并沒有使內核的工作變得簡單.
  • 盡管如此, Linux開發人員提出了一種結構良好得令人驚訝的模型, 統一了各種不同的方法. 雖然本章是本書最長的章之一, 但并沒有涵蓋網絡實現的每個細節. 即使概述一下所有的驅動程序和協議, 也超出了一本書的范圍, 由于信息量巨大, 實際上可能需要許多本書. 不算網卡驅動程序, 網絡子系統的C語言實現在內核源代碼中就占了15MB, 如果將相應的代碼打印到紙上要有6000多頁. 與網絡相關的頭文件的數目巨大, 使得內核開發者將這些頭文件存儲到一個專門的目錄include/net中, 而不是存儲到標準位置include/linux. 網絡相關的代碼中包含了許多概念, 這些形成了網絡子系統的邏輯支柱, 我們在本章中最感興趣的就是這些概念. 我們的討論主要限于TCP/IP實現, 因為它是目前使用最廣泛的網絡協議.
  • 當然, 網絡子系統的開發, 并不是從頭開始的. 在計算機之間交換數據的標準和慣例都已經存在數十年之久, 這些都為大家所熟知且沿用已久. Linux也實現了這些標準, 以連接到其他計算機.

1.2 網絡實現的分層模型

  • 內核網絡子系統的實現與本章開頭介紹的TCP/IP參考模型非常相似
  • 相關的C語言代碼劃分為不同層次,各層次都有明確定義的任務,各個層次只能通過明確定義的接口與上下緊鄰的層次通信。這種做法的好處在于,可以組合使用各種設備、傳輸機制和協議。例如,通常的以太網卡不僅可用于建立因特網(IP)連接,還可以在其上傳輸其他類型的協議,如Appletalk或IPX,而無須對網卡的設備驅動程序做任何類型的修改。
  • 圖12-3說明了內核對這個分層模型的實現

 

一文讀懂Linux網絡命名空間

內核對這個分層模型的實現

 

 

  • 網絡子系統是內核中涉及面最廣、要求最高的部分之一。為什么是這樣呢?答案是,該子系統處理了大量特定于協議的細節和微妙之處,穿越各層的代碼路徑中有大量的函數指針,而沒有直接的函數調用。這是不可避免的,因為各個層次有多種組合方式,這顯然不會使代碼路徑變得更清楚或更易于跟蹤。此外,其中涉及的數據結構通常彼此緊密關聯。為降低描述上復雜性,下文的內容主要講述 因特網協議。
  • 分層模型不僅反映在網絡子系統的設計上,而且也反映在數據傳輸的方式上(或更精確地說,對各層產生和傳輸的數據進行封裝的方式)。通常,各層的數據都由首部和數據兩部分組成, 如圖12-4所示。

 

一文讀懂Linux網絡命名空間

各層的數據都由首部和數據兩部分組成

  • 首部部分包含了與數據部分有關的元數據(目標地址、長度、傳輸協議類型等),數據部分包含有用數據(或凈荷)。
  • 傳輸的基本單位是(以太網)幀,網卡以幀為單位發送數據。幀首部部分的主數據項是目標系統的硬件地址,這是數據傳輸的目的地,通過電纜傳輸數據時也需要該數據項。
  • 高層協議的數據在封裝到以太網幀時,將協議產生的首部和數據二元組封裝到幀的數據部分。在因特網網絡上,這是互聯網絡層數據。
  • 因為通過以太網不僅可以傳輸IP分組,還可以傳輸其他協議的分組,如Appletalk或IPX分組,接收系統必須能夠區分不同的協議類型,以便將數據轉發到正確的例程進一步處理。分析數據并查明使用的傳輸協議是非常耗時的。因此,以太網幀的首部(和所有其他現代網絡協議的首部部分)包含了一個標識符,唯一地標識了幀數據部分中的協議類型。這些標識符(用于以太網傳輸)由一個國際組織(IEEE)分配。
  • 協議棧中的所有協議都有這種劃分。為此,傳輸的每個幀開始都是一系列協議首部,而后才是應用層的數據,如圖12-5所示
一文讀懂Linux網絡命名空間

在以太網幀中通過TCP/IP傳輸HTTP數據

  • 圖12-5清楚地說明了為容納控制信息所犧牲的部分帶寬.

 

更多linux內核視頻教程文檔資料免費領取后臺私信【內核】自行獲取.

一文讀懂Linux網絡命名空間

 

Linux內核源碼/內存調優/文件系統/進程管理/設備驅動/網絡協議棧-學習視頻教程-騰訊課堂

 

2、網絡命名空間net

  • pid的命名空間, 我們知道內核的許多部分包含在命名空間中. 這可以建立系統的多個虛擬視圖, 并彼此分隔開來. 每個實例看起來像是一臺運行Linux的獨立機器,但在一臺物理機器上,可以同時運行許多這樣的實例。在內核版本2.6.24開發期間,內核也開始對網絡子系統采用命名空間. 這對該子系統增加了一些額外的復雜性,因為該子系統的所有屬性在此前的版本中都是"全局"的,而現在需要按命名空間來管理, 例如, 可用網卡的數量. 對特定的網絡設備來說,如果它在一個命名空間中可見,在另一個命名空間中就不一定是可見的.

2.1 網絡命令空間net

  • 照例需要一個中樞結構來跟蹤所有可用的命名空間, 即struct net, 其定義如下:
struct net {
    atomic_t        passive;    /* To decided when the network
                                 * namespace should be freed.
                                 */
    atomic_t        count;      /* To decided when the network
                                 *  namespace should be shut down.
                                 */
    spinlock_t      rules_mod_lock;
    atomic64_t      cookie_gen;

    struct list_head        list;         /* list of network namespaces */
    struct list_head        cleanup_list; /* namespaces on death row */
    struct list_head        exit_list;    /* Use only net_mutex */
    struct user_namespace   *user_ns;     /* Owning user namespace */
    spinlock_t               nsid_lock;
    struct idr               netns_ids;

    struct ns_common         ns;

    struct proc_dir_entry   *proc_net;
    struct proc_dir_entry   *proc_net_stat;

#ifdef CONFIG_SYSCTL
    struct ctl_table_set    sysctls;
#endif

    struct sock             *rtnl;          /* rtnetlink socket */
    struct sock             *genl_sock;

    struct list_head         dev_base_head;
    struct hlist_head       *dev_name_head;
    struct hlist_head       *dev_index_head;
    unsigned int             dev_base_seq; /* protected by rtnl_mutex */
    int                      ifindex;
    unsigned int             dev_unreg_count;

    /* core fib_rules */
    struct list_head         rules_ops;


    struct net_device       *loopback_dev;      /* The loopback */
    struct netns_core       core;
    struct netns_mib        mib;
    struct netns_packet     packet;
    struct netns_unix       unx;
    struct netns_ipv4       ipv4;
#if IS_ENABLED(CONFIG_IPV6)
    struct netns_ipv6       ipv6;
#endif
#if IS_ENABLED(CONFIG_IEEE802154_6LOWPAN)
    struct netns_ieee802154_lowpan  ieee802154_lowpan;
#endif
#if defined(CONFIG_IP_SCTP) || defined(CONFIG_IP_SCTP_MODULE)
    struct netns_sctp       sctp;
#endif
#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
    struct netns_dccp       dccp;
#endif
#ifdef CONFIG_NETFILTER
    struct netns_nf     nf;
    struct netns_xt     xt;
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
    struct netns_ct     ct;
#endif
#if defined(CONFIG_NF_TABLES) || defined(CONFIG_NF_TABLES_MODULE)
    struct netns_nftables   nft;
#endif
#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
    struct netns_nf_frag    nf_frag;
#endif
    struct sock         *nfnl;
    struct sock         *nfnl_stash;
#if IS_ENABLED(CONFIG_NETFILTER_NETLINK_ACCT)
    struct list_head    nfnl_acct_list;
#endif
#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
    struct list_head    nfct_timeout_list;
#endif
#endif
#ifdef CONFIG_WEXT_CORE
    struct sk_buff_head     wext_nlevents;
#endif
    struct net_generic __rcu    *gen;

    /* Note : following structs are cache line aligned */
#ifdef CONFIG_XFRM
    struct netns_xfrm       xfrm;
#endif
#if IS_ENABLED(CONFIG_IP_VS)
    struct netns_ipvs       *ipvs;
#endif
#if IS_ENABLED(CONFIG_MPLS)
    struct netns_mpls       mpls;
#endif
    struct sock            *diag_nlsk;
    atomic_t                fnhe_genid;
};

  • 使網絡子系統完全感知命名空間的工作才剛剛開始。讀者現在看到的情況,即內核版本2.6.24中的情況,仍然處于開發的早期階段。因此,隨著網絡子系統中越來越多的組件從全局管理轉換為可感知命名空間的實現,struct net 的長度在未來會不斷增長。現在,基本的基礎設施已經轉換完畢。
  • 對網絡設備的跟蹤已經考慮到命名空間的效應,對最重要的一些協議的命名空間支持也是可用的。由于本書中尚未討論網絡實現的任何具體內容,struct net 中引用的結構當然還是未知的(但在本章行文過程中,這一點會逐漸改變)。現在,只需要簡要地概述一下,哪些概念是以可感知命名空間的方式進行處理的即可.
  1. count是一個標準的使用計數器,在使用特定的net實例前后,需要分別調用輔助函數get_net和put_net. 在count降低到0時,將釋放該命名空間,并將其從系統中刪除.
  2. 所有可用的命名空間都保存在一個雙鏈表上,表頭是net_namespace_list。list用作鏈表元素. copy_net_ns函數向該鏈表添加一個新的命名空間。在用create_new_namespace創建一組新的命名空間時,會自動調用該函數。
  3. 由于每個命名空間都包含不同的網絡設備,這必然會反映到procfs的內容上(參見10.1節)。各命名空間的處理需要三個數據項:/proc/net由proc_net表示,而/proc/net/stats由proc_net_stats表示,proc_net_root指向當前命名空間的procfs實例的根結點,即/proc
  4. 每個命名空間都可以有一個不同的環回設備,而loopback_dev指向履行該職責的(虛擬)網絡設備.
  5. 網絡設備由struct net_device表示。與特定命名空間關聯的所有設備都保存在一個雙鏈表上,表頭為dev_base_head。各個設備還通過另外兩個雙鏈表維護:一個將設備名用作散列鍵(dev_name_head),另一個將接口索引用作散列鍵(dev_index_head)。
  • 請注意,術語“設備”和“接口”有細微的差別。設備表示提供物理傳輸能力的硬件設備,而接口可以是純虛擬的實體,可能在真正的設備上實現。例如,一個網卡可以提供兩個接口。對我們來說,兩個術語的區別不那么重要,在下文中將交替使用這兩個術語。網絡子系統的許多組件仍然需要做很多工作才能正確處理命名空間,要使網絡子系統能夠完全感知命名空間,還有相當長的路要走。例如,內核版本2.6.25(在撰寫本章時,仍處于開發中)將開始一些最初的準備工作,以便使特定的協議能夠感知到命名空間:
struct net
{
 /*  ......  */
    struct net_device       *loopback_dev;      /* The loopback */
    struct netns_core       core;
    struct netns_mib        mib;
    struct netns_packet     packet;
    struct netns_unix       unx;
    struct netns_ipv4       ipv4;
#if IS_ENABLED(CONFIG_IPV6)
    struct netns_ipv6       ipv6;
#endif
 /*  ......  */
}

  • ipv4用于存儲協議參數(此前是全局的), 為此引入了特定于協議的結構. 這個方 法是逐步進行的:首先設置好基本框架,后續的各個步驟,將全局屬性遷移到各命名空間的表示,這些結構最初都是空的。在未來的內核版本中,還將引入更多此類代碼
  • linux系統包括默認的命名空間 : "init_net"和用戶自定義的net
  • 我們通常說的namespace 一般是默認的命名空間 : "init_net", 也就是所有的"網絡通信協議"+"網絡設備"都是屬于默認的命名空間.
  • 大多數計算機通常都只需要一個網絡命名空間. 即只有默認命名空間init_net(該變量實際上是全局的,并未包含在另一個命名空間中,其定義如下:
//  http://lxr.free-electrons.com/source/net/core/net_namespace.c?v=4.7#L35
struct net init_net = {
    .dev_base_head = LIST_HEAD_INIT(init_net.dev_base_head),
};
EXPORT_SYMBOL(init_net);

  • init_net會被鏈接到net_namespace_list這個雙向鏈表上, 定義如下所示:
  • net_namespace_list就包含了所有的網絡命令空間, 其以init_net為表頭
LIST_HEAD(net_namespace_list);
EXPORT_SYMBOL_GPL(net_namespace_list);

2.2 初始化 & 清理元組 pernet_operations(創建命名空間)

初始化 & 清理元組pernet_operations

  • 每個網絡命名空間由幾個部分組成, 例如, 在procfs中的表示. 每當創建一個新的網絡命名空間時, 必須初始化這些部分. 在刪除命名空間時, 也同樣需要一些清理工作. 內核采用下列結構來跟蹤所有必需的初始化/清理元組.
//  http://lxr.free-electrons.com/source/include/net/net_namespace.h?v=4.7#L288
struct pernet_operations {
    struct list_head list;
    int (*init)(struct net *net);
    void (*exit)(struct net *net);
    void (*exit_batch)(struct list_head *net_exit_list);
    int *id;
    size_t size;
};

//  http://lxr.free-electrons.com/source/include/net/net_namespace.h?v=4.7#L316
int register_pernet_subsys(struct pernet_operations *);
void unregister_pernet_subsys(struct pernet_operations *);
int register_pernet_device(struct pernet_operations *);
void unregister_pernet_device(struct pernet_operations *);

  • 這個結構沒什么特別之處 :
一文讀懂Linux網絡命名空間

 

?

 

  • 內核pernet_operations結構將被鏈接到pernet_list這個雙向鏈表上, 定義:
static LIST_HEAD(pernet_list);
static struct list_head *first_device = &pernet_list;
DEFINE_MUTEX(net_mutex);

  • 輔助函數register_pernet_subsys和unregister_pernet_subsys分別向該鏈表添加和刪除數據元素. 每當創建一個新的網絡命名空間時, 內核將遍歷pernet_operations的鏈表, 用表示新命名空間的net實例作為參數來調用初始化函數。在刪除網絡命名空間時,清理工作的處理是類似的

網絡命令空間的創建

  • 每個network namespace包換許多元件, 所以當一個新的network namespace被創建, 這些元件必須被初始化. 同樣, 當它被刪除時,需要做必要的清理工作.
  • Kernel引入了如下結構pernet_operations來維護所有需要做的 initialization/cleanup工作
  • 當一個新的network namespace被創建, kernel遍歷pernet_operations 的list, 即遍歷pernet_list, 并調用其init函數.
  • 在linux內核中默認情況下, 會有一個"默認的網絡命名空間", 其名為init_net, 并也將其導出, 作為全局變量.
  • kernel2.4、2.6:通過copy_net_ns和net_create函數向內核中添加一個網絡命名空間, 其中copy_net_ns函數
//   http://lxr.free-electrons.com/source/net/core/net_namespace.c?v=2.6.32#L120

//  這個函數用于向內核中添加一個網絡命名空間
// struct net *net_create(void);
// 這個函數主要做了三件事 :
// 1.  通過struct net*net_alloc(void)函數分配了一個structnet結構體
// 2.  通過setup_net(struct net*ns)函數對分配的struct net結構體進行了相應的設置;
// 3.  將分配的struct net結構體加入到 net_namespace_list的雙鏈表尾部

//  http://lxr.free-electrons.com/source/net/core/net_namespace.c?v=2.6.32#L143
struct net *copy_net_ns(unsigned long flags, struct net *old_net)
{
    if (!(flags & CLONE_NEWNET))
        return get_net(old_net);
    return net_create();
}

// 1. 如果設置了CLONE_NEWNET, 就通過net_create創建一個新的net網絡命令空間
// 2. 否則的話, 返回舊的網絡命令空間

  • kernel 3.10之后刪除了 net_create 函數, 而通過copy_net_ns函數添加一個網絡命名空間。

釋放一個網絡命名空間

  • 內核可以通過net_free和net_drop_ns函數來釋放掉指定的網絡命名空間.
  • 定義:
static void net_free(struct net *net)
{
    kfree(rcu_access_pointer(net->gen));
    kmem_cache_free(net_cachep, net);
}

void net_drop_ns(void *p)
{
    struct net *ns = p;
    if (ns && atomic_dec_and_test(&ns->passive))
        net_free(ns);
}

2.3 總結

  • 記住下列事實就足夠了
  1. 網絡子系統實現的所有全局函數,都需要一個網絡命名空間作為參數,而網絡子系統的所有全局屬性,只能通過所述命名空間迂回訪問.
  2. linux系統包括默認的命名空間 : init_net和用戶自定義的net namespace一般是默認的命名空間:init_net, 也就是所有的"網絡通信協議"+"網絡設備"都是屬于默認的命名空間.
  3. 網絡命名空間定義了2個鏈表, pernet_list和net_namespace_list init_net會被鏈接到net_namespace_list這個雙向鏈表上 pernet_operations結構將被鏈接到first_device = pernet_list這個雙向鏈表上
  4. 如果沒自定義網絡命名空間的話,所有想用網絡命名空間時都將利用默認的init_net

3、網絡命令空間設備

命名空間設備指的是那些?

  • 就是網絡設備. 通過register_pernet_device注冊:就是"注冊一個網絡設備"到"所有的網絡命名空間net", 網絡設備包括兩類:虛擬的網絡設備和物理網絡設備 :

3.1 虛擬網絡設備

  • 虛擬網絡設備的協議根據自身設計特點對skb數據進行處理, 并通過全局變量xx_net_id和各個協議私有的特殊數據結構xx_net, 尋找到該數據包對應的應用層socket插口, 并將其放在該socket插口的接收隊列中; 最后應用層在某個時刻會通過read系統調用讀取該數據
一文讀懂Linux網絡命名空間

 

?

 

3.2 物理網絡設備

  • 比如網卡驅動、無線網卡驅動

3.3 namespace與socket, 網絡設備的關系

  • 上述的socket索引方法有個繞彎的地方:就是每個協議私有的xx_net結構可以直接由協議模塊本身分配,索引起來也方便,不要用到全局的net_generic。而目前內核所用的方法,其實是為了另外的目的,那就是命名空間namespace。也就是虛擬多用戶的一套機制,具體的也沒細看,好像目前內核整個namespace還沒有全部完成。
  • network的命名空間問題主要在于,每個協議模塊的xx_net私有結構不僅是一個,而是由內核全局決定的,即每注冊一個新的用戶(有點像虛擬機機制),就分配一個新的xx_net結構,這樣多用戶間可以用參數相同的socket連接,但卻指向不同的socket, 可以看到socket的操作,都會有個net參數,就是為了這個作用,主要實現函數在namespace.c中
  • 在Linux協議棧中引入網絡命名空間,是為了支持網絡協議棧的多個實例,而這些協議棧的隔離就是由命名空間來實現的(有點像進程的線性地址空間,協議棧不能訪問其他協議棧的私有數據)。需要納入命名空間的元素包括進程,套接字,網絡設備。進程創建的套接字必須屬于某個命名空間,套接字的操作也必須在命名空間內進行,網絡設備也必須屬于某個命名空間,但可能會改變,因為網絡設備屬于公共資源<~/include/net.h>
  • 在內核中引入命名空間工作量非常大. 為了保持與向后兼容,網絡系統在初始化的時候只初始化了一個命名空間,即init_net命名空間。所有的命名空間通過list項組織起來。每個網絡設備都對應有一個命名空間。命名空間下的所有網絡設備通過dev_base_head組織在一起

分享到:
標簽:網絡 Linux
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定