這來主要看看ovs從網路介面收到packet後的一系列操作。
在核心模組啟動的時候會初始化vport子系統(ovs_vport_init),各種vport型別,那麼什麼時候會呼叫相應的函式與實際網路裝置建立聯絡?其實當我們在為網橋增設埠的時候,就會進入ovs_netdev_vport_ops中的create方法,進而 註冊網路裝置。
看ovs-vsctl add-port br0 eth1 實際做了什麼?
struct netdev_vport
;const
struct vport_ops ovs_netdev_vport_ops =
;--datapath/vport-netdev.c
static
struct vport *
netdev_create
(const
struct vport_parms *parms)
//不是環迴介面;而且底層鏈路層是乙太網;netdev->netdev_ops == &internal_dev_netdev_ops 顯然為false
err =
netdev_rx_handler_register
(netdev_vport->dev, netdev_frame_hook, vport);[
//核心,收到packet後會呼叫]() netdev_frame_hook處理;
dev_set_promiscuity
(netdev_vport->dev,1)
;//設定為混雜模式;
netdev_vport->dev->priv_flags |
= iff_ovs_datapath;
//設定netdevice私有區域的標識;
return vport;
}--datapath/vport.h 建立vport所需要的引數結構
struct vport_parms
;
函式netdev_rx_handler_register(struct net_device *dev,rx_handler_func_t *rx_handler, void *rx_handler_data)定義在 linux/netdevice.h 實現在 net/core/dev.c 中,為網路裝置dev註冊乙個receive handler,rx_handler_data指向的是這個receive handler是用的記憶體區域(這裡存的是vport,裡面有datapath的相關資訊)。這個handler 以後會被 __netif_receive_skb() 呼叫,實際就是更新netdevice中的兩個指標域,rcu_assign_pointer(dev->rx_handler_data, rx_handler_data), rcu_assign_pointer(dev->rx_handler, rx_handler) 。
netif_receive_skb(struct sk_buff *skb)從網路中接收資料,它是主要的接收資料處理函式,總是成功,這個buffer在擁塞處理或協議層的時候可能被丟棄。這個函式只能從軟中斷環境(softirq context)中呼叫,並且中斷允許。返回值 net_rx_success表示沒有擁塞,net_rx_drop包丟棄。(實現細節暫時沒看)
接下來進入我們的鉤子函式 netdev_frame_hook(datapath/vport-netdev.c)這裡主要看核心版本》=2.6.39的實現。
static rx_handler_result_t netdev_frame_hook
(struct sk_buff *
*pskb)
函式 netdev_port_receive 首先得到乙個packet的拷貝,否則會損壞先於我們而來的packet使用者 (e.g. tcpdump via af_packet),我們之後沒有這種情況,因為會告知handle_bridge()我們獲得了那個packet 。
skb_push是將skb的資料區向後移動*_hlen長度,為了存入幀頭;而skb_put是擴充套件資料區後面為存資料memcpy做準備。
static
void
netdev_port_receive
(struct vport *vport,
struct sk_buff *skb)
接下來將收到的packet傳給datapath處理(datapath/vport.c),引數vport是收到這個包的vport(表徵物理介面和datapath),skb是收到的資料。讀的時候要用rcu_read_lock,這個包不能被共享而且skb->data 應該指向乙太網頭域,而且呼叫者要確保已經執行過 compute_ip_summed() 初始化那些校驗和域。
void
ovs_vport_receive
(struct vport *vport,
struct sk_buff *skb)
接下來我們的datapath模組來處理傳上來的packet(datapath/datapath.c),首先我們要判斷如果存在skb->cb域中的ovs data sw_flow 是空的話,就要從packet中提攜構造;函式 ovs_flow_extract 從乙太網幀中構造 sw_flow_key,為接下來的流表查詢做準備;流表結構struct flow_table定義在flow.h中,流表實在ovs_flow_init的時候初始化的?? 如果沒有match成功,就會upcall遞交給使用者空間處理(見vswitchd模組分析),匹配成功的話執行flow action(接下來就是openflow相關)。
void
ovs_dp_process_received_packet
(struct vport *p,
struct sk_buff *skb)
ovs_cb
(skb)
->flow = flow;
}
stats_counter =
&stats->n_hit;
ovs_flow_used
(ovs_cb
(skb)
->flow, skb)
;ovs_execute_actions
(dp, skb)
;
out:
/* update datapath statistics. */
u64_stats_update_begin
(&stats->sync);(
*stats_counter)++;
u64_stats_update_end
(&stats->sync)
;}
springmvc三十 異常處理流程
handlerexceptionresolvers 異常解析也是springmvc的9大元件之一。org.springframework.web.servlet.handlerexceptionresolver org.springframework.web.servlet.mvc.method.a...
IRP 處理流程
本文通過開啟乙個檔案物件為例子,描述了乙個帶有兩個i o stack location的irp的詳細處理過程。當然乙個irp可以有多個i o stack location,具體個數取決於將要處理該請求的驅動的層數。下圖詳細描述了驅動程式是如何通過使用i o支援例程 io routines 來處理ir...
異常處理流程
異常類結構 來觀察兩個異常類的繼承關係 可以發現所有的異常型別最高的繼承類是throwable,並且通過doc文件可以發現在throwable下有兩個子類 error 指的是jvm錯誤,這個時候的程式並沒有執行,無法處理 exception 指的是程式執行中產生的異常,使用者可以使用異常處理格式處理...