DPDK(二):準備知識8 --- netfilter

1、簡介
Netfilter是Linux 2.4.x引入的一個子系統,它做爲一個通用的、抽象的框架,提供一整套的hook函數的管理機制,使得諸如數據包過濾、網絡地址轉換(NAT)和基於協議類型的鏈接跟蹤成爲了可能。Netfilter在內核中位置以下圖所示:linux

Netfilter在netfilter_ipv4.h中命名5個節點,這5個節點是netfilter發揮做用的地方。網絡

在數據包流經內核協議棧的整個過程當中,在一些已預約義的關鍵點上PRE_ROUTING、LOCAL_IN、FORWARD、LOCAL_OUT和POST_ROUTING會根據數據包的協議簇PF_INET到這些關鍵點去查找是否註冊有鉤子函數。若是沒有,則直接返回okfn函數指針所指向的函數繼續走協議棧;若是有,則調用nf_hook_slow函數,從而進入到Netfilter框架中去進一步調用已註冊在該過濾點下的鉤子函數,再根據其返回值來肯定是否繼續執行由函數指針okfn所指向的函數。
2、鉤子介紹
Netfilter使用NF_HOOK(include/linux/netfilter.h)宏在協議棧內部切入到Netfilter框架中。
一、鉤子函數
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
         NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, INT_MIN)
關於宏NF_HOOK各個參數的解釋說明:
1)         pf:協議族名,Netfilter架構一樣能夠用於IP層以外,所以這個變量還能夠有諸如PF_INET6,PF_DECnet等名字。
2)         hook:HOOK點的名字,對於IP層,就是取上面的五個值;
3)         skb:不解釋;
4)         indev:數據包進來的設備,以struct net_device結構表示;
5)         outdev:數據包出去的設備,以struct net_device結構表示;
(後面能夠看到,以上五個參數將傳遞給nf_register_hook中註冊的處理函數。)
6)         okfn:是個函數指針,當全部的該HOOK點的全部登記函數調用完後,轉而走此流程
#define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh)                \
({int __ret;                                                                                \
if ((__ret=nf_hook_thresh(pf, hook, &(skb), indev, outdev, okfn, thresh, 1)) == 1)\
         __ret = (okfn)(skb);                                                       \
__ret;})
NF_HOOK_THRESH宏增長的最後一個參數thresh用來指定經過該宏去遍歷鉤子函數時的優先級。
static inline int nf_hook_thresh(int pf, unsigned int hook,
                            struct sk_buff **pskb,
                            struct net_device *indev,
                            struct net_device *outdev,
                            int (*okfn)(struct sk_buff *), int thresh,
                            int cond)
{
if (!cond) 
return 1;
#ifndef CONFIG_NETFILTER_DEBUG
if (list_empty(&nf_hooks[pf][hook]))
         return 1;
#endif
return nf_hook_slow(pf, hook, pskb, indev, outdev, okfn, thresh);
}
這個函數又只增長了一個參數cond,該參數爲0則放棄遍歷,而且也不執行okfn函數;爲1則執行nf_hook_slow去完成鉤子函數okfn的順序遍歷(優先級從小到大依次執行)。其核心就是nf_hook_slow()函數。該函數本質上作的事情很簡單,根據優先級查找雙向鏈表nf_hooks[][],找到對應的回調函數來處理數據包,而後根據其返回值判斷是否須要執行okfn函數。
二、HOOK點介紹
從協議棧正常的流程切入到Netfilter框架中,而後順序、依次去調用每一個HOOK點全部的鉤子函數的相關操做有以下幾處:
1)net/ipv4/ip_input.c裏的ip_rcv函數。該函數主要用來處理網絡層的IP報文的入口函數,它到Netfilter框架的切入點爲:
NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,ip_rcv_finish)
2)net/ipv4/ip_forward.c中的ip_forward函數,它的切入點爲:
NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, rt->u.dst.dev,ip_forward_finish);
3)net/ipv4/ip_output.c中的ip_output函數,它切入Netfilter框架的形式爲:
NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,ip_finish_output, !(IPCB(skb)->flags & IPSKB_REROUTED));
這裏咱們看到切入點從無條件宏NF_HOOK改爲了有條件宏NF_HOOK_COND,調用該宏的條件是:若是協議棧當前所處理的數據包skb中沒有從新路由的標記,數據包纔會進入Netfilter框架。不然直接調用ip_finish_output函數走協議棧去處理。除此以外,有條件宏和無條件宏再無其餘任何差別。
4)仍是在net/ipv4/ip_input.c中的ip_local_deliver函數。該函數處理全部目的地址是本機的數據包,其切入函數爲:
NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,ip_local_deliver_finish);
5)net/ipv4/ip_output.c中的ip_push_pending_frames函數。該函數是將IP分片重組成完整的IP報文,而後發送出去。進入Netfilter框架的切入點爲:
NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output);架構

相關文章
相關標籤/搜索