1. 程式人生 > >Linux 網路協議棧開發(六)—— 二層橋轉發藍圖(下)

Linux 網路協議棧開發(六)—— 二層橋轉發藍圖(下)

  1. struct sk_buff *br_handle_vlan(struct net_bridge *br,  
  2.                    struct net_bridge_vlan_group *vg,  
  3.                    struct sk_buff *skb)  
  4. {  
  5.     struct br_vlan_stats *stats;  
  6.     struct net_bridge_vlan *v;  
  7.     u16 vid;  
  8.     /* If this packet was not filtered at input, let it pass */
  9.     if (!BR_INPUT_SKB_CB(skb)->vlan_filtered)  
  10.         goto out;  
  11.     /* At this point, we know that the frame was filtered and contains 
  12.      * a valid vlan id.  If the vlan id has untagged flag set, 
  13.      * send untagged; otherwise, send tagged. 
  14.      */
  15.     br_vlan_get_tag(skb, &vid);  
  16.     /*find vid from vlan group*/
  17.     v = br_vlan_find(vg, vid);  
  18.     /* Vlan entry must be configured at this point.  The 
  19.      * only exception is the bridge is set in promisc mode and the 
  20.      * packet is destined for the bridge device.  In this case 
  21.      * pass the packet as is. 
  22.      */
  23.     if
     (!v || !br_vlan_should_use(v)) {  
  24.         if ((br->dev->flags & IFF_PROMISC) && skb->dev == br->dev) {  
  25.             goto out;  
  26.         } else {  
  27.             kfree_skb(skb);  
  28.             return NULL;  
  29.         }  
  30.     }  
  31.     /*statistacs the vlan if flow and if the vlan_stats_enabled is true */
  32.     if (br->vlan_stats_enabled) {  
  33.         stats = this_cpu_ptr(v->stats);  
  34.         u64_stats_update_begin(&stats->syncp);  
  35.         stats->tx_bytes += skb->len;  
  36.         stats->tx_packets++;  
  37.         u64_stats_update_end(&stats->syncp);  
  38.     }  
  39.     if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED)  
  40.         skb->vlan_tci = 0;  
  41. out:  
  42.     return skb;  
  43. }  

這個函式的作用很簡單就是,資料包是否要帶tag,過程:
在傳遞進來的vlan group中查詢自己所處的vlan
如果該vlan不存在則判斷當前模式是否是混雜模式和資料包的裝置是否是橋下的裝置,選擇發包或者丟棄。
如果存在,且vlan是開啟的,則統計vlan介面上的資料流量,最後根據vlan出口的標記位進行位運算判斷是否要帶tag.

然後我們來看一下上節提到的發往本地資料包的處理函式

  1. staticint br_pass_frame_up(struct sk_buff *skb)  
  2. {  
  3.     struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;  
  4.     struct net_bridge *br = netdev_priv(brdev);  
  5.     struct net_bridge_vlan_group *vg;  
  6.     struct pcpu_sw_netstats *brstats = this_cpu_ptr(br->stats);  
  7.     /*統計該橋上的流量*/
  8.     u64_stats_update_begin(&brstats->syncp);  
  9.     brstats->rx_packets++;  
  10.     brstats->rx_bytes += skb->len;  
  11.     u64_stats_update_end(&brstats->syncp);  
  12.     /*獲取該橋上的vlan組*/
  13.     vg = br_vlan_group_rcu(br);  
  14.     /* Bridge is just like any other port.  Make sure the 
  15.      * packet is allowed except in promisc modue when someone 
  16.      * may be running packet capture. 
  17.      */
  18.     if (!(brdev->flags & IFF_PROMISC) &&  
  19.         !br_allowed_egress(vg, skb)) {  
  20.         kfree_skb(skb);  
  21.         return NET_RX_DROP;  
  22.     }  
  23.     /*替換掉資料包中的裝置資訊改為橋裝置*/
  24.     indev = skb->dev;  
  25.     skb->dev = brdev;  
  26.     /*配置資料包vlan的相關資訊*/
  27.     skb = br_handle_vlan(br, vg, skb);  
  28.     if (!skb)  
  29.         return NET_RX_DROP;  
  30.     /*進入NF_BR_LOCAL_IN*/
  31.     return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN,  
  32.                dev_net(indev), NULL, skb, indev, NULL,  
  33.                br_netif_receive_skb);  
  34. }  

這個函式所做的事情很簡單,就是配置vlan的相關資訊後,然後發往本地的netfilter鉤子函式中
最後重新回到netif_recive_skb.如下函式:

  1. staticint
  2. br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb)  
  3. {  
  4. <span>  </span>return netif_receive_skb(skb);  
  5. }  
再來看看資料包轉發的函式
  1. staticvoid __br_forward(conststruct net_bridge_port *to, struct sk_buff *skb)  
  2. {  
  3.     struct net_bridge_vlan_group *vg;  
  4.     struct net_device *indev;  
  5.     if (skb_warn_if_lro(skb)) {  
  6.         kfree_skb(skb);  
  7.         return;  
  8.     }  
  9.     /*獲取vlan組,這個組中有許多的vlanid,br_handle_vlan函式就是要在這個組中查詢自己的vid*/
  10.     vg = nbp_vlan_group_rcu(to);  
  11.     /*新增vlan的相關配置*/
  12.     skb = br_handle_vlan(to->br, vg, skb);  
  13.     if (!skb)  
  14.         return;  
  15.     indev = skb->dev;  
  16.     skb->dev = to->dev;  
  17.     skb_forward_csum(skb);  
  18.     NF_HOOK(NFPROTO_BRIDGE, NF_BR_FORWARD,  
  19.         dev_net(indev), NULL, skb, indev, skb->dev,  
  20.         br_forward_finish);  
  21. 相關推薦

    Linux 網路協議開發—— 轉發藍圖

    struct sk_buff *br_handle_vlan(struct net_bridge *br,                      struct net_bridge_vlan_group *vg,                      struct sk_b

    Linux 網路協議開發番外篇—— Windows路由表詳解

    一、檢視Windows路由表  路由表是Windows的TCP/IP協議棧的一個重要的部分。但是,路由表不是Windows作業系統向普通使用者顯示的東西。如果你要看到這個路由表,你必須要開啟一個命令提示符對話方塊,然後輸入“ROUTE PRINT”命令。結果如下: 路由

    Linux 網路協議開發—— 網路協議核心分析

    1.1 傳送端 1.1.1 應用層 (1) Socket 應用層的各種網路應用程式基本上都是通過 Linux Socket 程式設計介面來和核心空間的網路協議棧通訊的。Linux Socket 是從 BSD Socket 發展而來的,它是 Linux 作業系統的重要組成部分之一,它是網路應用程式

    Linux 網路協議開發基礎篇—— 使用wireshark分析TCP/IP協議中TCP包頭的格式

    摘要: 本文簡單介紹了TCP面向連線理論知識,詳細講述了TCP報文各個欄位含義,並從Wireshark俘獲分組中選取TCP連線建立相關報文段進行分析。 一、概述 TCP是面向連線的可靠傳輸協議,兩個程序互發資料之前需要建立連線,這裡的連線只不過是端系統中分配的一些快

    Linux 網路協議開發程式碼分析篇之VLAN—— VLAN收發處理

            以一個例子來說明,當主機收到報文,交由vlan協議模組處理後(vlan_rcv),此時需要更換skb->dev所指向的裝置,以使上層協議認為報文是來自於虛擬網絡卡(比如eth1.1),而不知道網絡卡eth1的存在。更換裝置就需要知道skb->dev更換的目標。這由兩個因素決定:sk

    Linux 網路協議開發基礎篇—— VID與PVID

    一、PVID的作用及和VID的區別        PVID和VID經常出現於二、三層交換機裡,由於PVID和VID的設定不合理,造成VLAN劃分變得混亂。        PVID是交換機上的概念,說的是進入該埠的報文如果沒有打vlan id就按PVID的值打上,VID是報文

    Linux 網路協議之核心鎖—— 程序上下文與中斷上下文的理解

    一.什麼是核心態和使用者態 核心態:在核心空間執行,通常是驅動程式,中斷相關程式,核心排程程式,記憶體管理及其操作程式。 使用者態:使用者程式執行空間。 二.什麼是程序上下文與中斷上下文 1.程序上下文: (1)程序上文:其是指程序由使用者態切換到核心態是需

    linux網路協議(五)網路 (1)L2與L3

    5.1、L2與L3: 網路的目的是使可以訪問不同主機的資源,僅以最簡單的使用如訪問我們軟體四部閘道器技術組的伺服器,是通過訪問192.168.36.XXX的IP地址達到訪問那臺主機的目的,而我們自己的主機IP都是192.168.10.XXX,我們的主機和閘道器技術組的主機不

    linux網路協議(四)鏈路 (5)vlan處理

    4.6、VLAN處理: 4.6.1、vlan原理 對於帶vlan的乙太網報文,其乙太網型別為0x8100,所以鏈路層中對於帶vlan報文的處理就是對於乙太網型別為0x8100的報文的處理; vlan,用於在鏈路層劃分廣播域,實現資料在鏈路層分流,在二層交換機中,vlan實際

    linux網路協議分析筆記14-路由4-FIB3

    看完fib的查詢,弄清了一些資料結構的組織,我們再來看看路由表是如何建立的 從ip_fib_init註冊的兩個通知鏈來看,在IP地址傳送變動時會觸發通知鏈的處理函式,都會呼叫fib_add_ifaddr()來新增地址到路由中 這個裡面由呼叫了fib_magic來進行路由地址的操作。 static void

    Linux網路協議之資料包處理過程(非技術人員勿看)

    1.中斷處理函式中:    網絡卡收到一幀------------------------〉   引發中斷-------------------〉   cpu呼叫相應的中斷處理函式(指向此網絡卡驅動中的相應的處理函式)(把此packet讀到ram中)--------------------〉   呼叫neti

    Linux網路協議()——套接字快取(socket buffer)

    Linux網路核心資料結構是套接字快取(socket buffer),簡稱skb。它代表一個要傳送或處理的報文,並貫穿於整個協議棧。 1、    套接字快取 skb由兩部分組成: (1)    報文資料:它儲存了實際在網路中傳輸的資料; (2)    管理資料:供核心處理報

    linux網路協議(四)鏈路 (1)鏈路原理

    四:鏈路層: 4.1、鏈路層原理: 4.1.1、鏈路層在幹什麼: 在報文接收方向上,網絡卡驅動把接收到的資料按照其對應的鏈路層協議(如乙太網)組裝成報文,然後把它上交給鏈路層,介面是netif_receive_skb,至此網絡卡驅動的任務就結束了,報文交給鏈路層處理; 在報

    Linux 網路協議收訊息過程-Ring Buffer

    想看能不能完整梳理一下收訊息過程。從 NIC 收資料開始,到觸發軟中斷,交付資料包到 IP 層再經由路由機制到 TCP 層,最終交

    ZigBee協議開發

    1、在一開始的學習中藉助官方模板,新增簡單的程式碼,做出基本通訊試驗,建立感性的認識,然後在官方程式碼基本試驗基礎上,瞭解相關的概念,掌握通訊過程原理,結合自己的理解,自己動手做一個個性化試驗,驗證理解。 2、各種通訊方式: (1)單播:在ZigBee網路中,模組之間要進行通訊,發射模組需要非常

    學習Linux-4.12核心網路協議1.6——協議的初始化(inet_init實現過程)

    這篇文章主要分析inet_init()函式的實現過程: 1796 static int __init inet_init(void) 1797 { 1798 struct inet_protosw *q; 1799 struct list_head *r;

    學習Linux-4.12核心網路協議1.7——網路裝置的初始化struct net_device

    在linux的網路裝置裡,其中一個最關鍵的結構體應該要算net_device了,它由對應的網路裝置驅動進行建立和初始化,服務於核心網路子系統。 1. struct net_device 註釋分析 struct net_device這個結構體比較大,在瞭解它之前,我們先看一下

    學習Linux-4.12核心網路協議2.1——介面加快傳輸速率的特性

    前面花了好多篇幅,終於將網路協議棧的初始化相關的內容介紹完了,也就是說完成前面的那些步驟以後,網路協議棧具備了資料包的收發功能。在網路介面層,它只負責資料包的接收與傳送,而不關注資料包在網路層的型別是什麼,所以傳輸速率的快慢往往與介面層的處理有著密切的關係,下面我們來了解一下在提供傳輸速率上面,現在的核心都

    學習Linux-4.12核心網路協議2.2——介面資料包的接收上半部

    前面寫了這麼多,終於可以開始分析資料報的傳輸過程了,那我們就愉快的開始吧! 我們知道,一箇中斷處理函式主要分兩個部分,上半部和下半部,這篇文章主要介紹上半部分。 當一個數據包到達的時候,網絡卡驅動會完成接收並且觸發中斷,我們就從這個中斷處理函式開始: 當一箇中斷產生併發送

    學習Linux-4.12核心網路協議1.5——協議的初始化(inet_init主要資料結構)

    前面瞭解到網路初始化申請了兩塊skb快取記憶體和建立了一個/proc/net/protocols檔案,現在開始重頭戲,網路協議棧的初始化。這篇文章主要介紹網路棧中使用到的主要資料結構。 網路協議棧的核心實現和理論上的分層有些不一樣,在程式碼裡面的分層如下圖: 開始前,