1. 程式人生 > >Linux核心Bridge程式碼

Linux核心Bridge程式碼

註冊

module_init(br_init)

static int __init br_init(void)
{
	...
	err = br_netfilter_init();
	...
	br_handle_frame_hook = br_handle_frame; // 設定br_handle_frame_hook為br_handle_frame
	...
}

int __init br_netfilter_init(void)
{
	...
	ret = nf_register_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
	...
}

static
struct nf_hook_ops br_nf_ops[] __read_mostly = { { .hook = br_nf_pre_routing, .owner = THIS_MODULE, .pf = PF_BRIDGE, .hooknum = NF_BR_PRE_ROUTING, .priority = NF_BR_PRI_BRNF, }, { .hook = br_nf_local_in, .owner = THIS_MODULE, .pf = PF_BRIDGE, .hooknum = NF_BR_LOCAL_IN, .priority =
NF_BR_PRI_BRNF, }, { .hook = br_nf_forward_ip, .owner = THIS_MODULE, .pf = PF_BRIDGE, .hooknum = NF_BR_FORWARD, .priority = NF_BR_PRI_BRNF - 1, }, { .hook = br_nf_forward_arp, .owner = THIS_MODULE, .pf = PF_BRIDGE, .hooknum = NF_BR_FORWARD, .priority = NF_BR_PRI_BRNF, }, {
.hook = br_nf_local_out, .owner = THIS_MODULE, .pf = PF_BRIDGE, .hooknum = NF_BR_LOCAL_OUT, .priority = NF_BR_PRI_FIRST, }, { .hook = br_nf_post_routing, .owner = THIS_MODULE, .pf = PF_BRIDGE, .hooknum = NF_BR_POST_ROUTING, .priority = NF_BR_PRI_LAST, }, { .hook = ip_sabotage_in, .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_FIRST, }, { .hook = ip_sabotage_in, .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP6_PRI_FIRST, }, };

資料流

以rx為例,eth0收到skb後通過netif_receive_skb()上送協議棧,netif_receive_skb()呼叫handle_bridge(),handle_bridge()判斷skb->dev->br_port是否非空(eth0是否橋接),若是,呼叫br_handle_frame_hook()即br_handle_frame(),經過ebtables的NF_BR_PRE_ROUTING鏈時呼叫br_nf_pre_routing(),經過iptables的NF_INET_PRE_ROUTING鏈後呼叫br_nf_pre_routing_finish(),再次經過ebtables的NF_BR_PRE_ROUTING鏈,由於NF_BR_PRI_BRNF = 0 < 1,因此不呼叫br_nf_pre_routing(),直接呼叫br_handle_frame_finish() 在br_handle_frame_finish()中分兩種情況: 1、skb的dmac地址是本機地址:在br_pass_frame_up()中修改skb->dev為網橋,重新交給netif_receive_skb(),此時skb->dev->br_port為空,不走橋接邏輯,直接上送ip_rcv() 2、其它:在br_forward()中轉發

int netif_receive_skb(struct sk_buff *skb)
{
    ...
    skb = handle_bridge(skb, &pt_prev, &ret, orig_dev);
    ...
}

static inline struct sk_buff *handle_bridge(struct sk_buff *skb,
                                            struct packet_type **pt_prev, int *ret,
                                            struct net_device *orig_dev)
{
    ...
    return br_handle_frame_hook(port, skb);
}

struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
{
    ...
    NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
            br_handle_frame_finish);
    ...
}

static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb,
                                        const struct net_device *in,
                                        const struct net_device *out,
                                        int (*okfn)(struct sk_buff *))
{
    ...
    if (!setup_pre_routing(skb)) // 標記BRNF_NF_BRIDGE_PREROUTING
        return NF_DROP;
    ...
    NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, skb->dev, NULL,
            br_nf_pre_routing_finish);

    return NF_STOLEN;
    ...
}

static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff *skb,
                                    const struct net_device *in,
                                    const struct net_device *out,
                                    int (*okfn)(struct sk_buff *))
{
    if (skb->nf_bridge &&
	    !(skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) { // 檢查標記NF_BR_PRE_ROUTING
	    return NF_STOP;  
	}

    return NF_ACCEPT;
}

static int br_nf_pre_routing_finish(struct sk_buff *skb)
{
    ...
    nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; // 取消標記NF_BR_PRE_ROUTING
    ...
    NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
                    br_handle_frame_finish, 1);
    ...
}

int br_handle_frame_finish(struct sk_buff *skb)
{
    ...
    br_pass_frame_up(br, skb2); // 本地
    ...
    br_forward(dst->dst, skb); // 轉發
    ...
}

static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
{
    ...
    // 修改skb->dev為網橋
    skb->dev = brdev;
    ...
    // 重新交給netif_receive_skb()
    NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,
            netif_receive_skb);
}

void br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
{
    ...
    __br_forward(to, skb);
    ...
}

static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
{
    ...
    // 修改skb->dev為出裝置
    skb->dev = to->dev;
    ...
    NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev,
            br_forward_finish);
}