1. 程式人生 > >linux網橋處理函式學習-----br_handle_frame

linux網橋處理函式學習-----br_handle_frame

/*
 * Return NULL if skb is handled
 * note: already called with rcu_read_lock
 */
rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
{
    struct net_bridge_port *p;
    struct sk_buff *skb = *pskb;
    const unsigned char *dest = eth_hdr(skb)->h_dest;
    br_should_route_hook_t *rhook;

    if
(unlikely(skb->pkt_type == PACKET_LOOPBACK)) return RX_HANDLER_PASS; /*檢測源mac地址的合法性:組播(包括廣播)和全0的源mac地址是非法的*/ if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) goto drop; /*檢測skb是否共享,如果是共享的,clone出一份新的skb,老的skb計數減1*/ skb = skb_share_check(skb, GFP_ATOMIC); if (!skb)
return RX_HANDLER_CONSUMED; p = br_port_get_rcu(skb->dev); #if defined(CONFIG_BCM_KF_WANDEV) if (!p) { kfree_skb(skb); return RX_HANDLER_CONSUMED; } #endif /*目的mac是01:80:c2:00:00:0xlinklocal地址*/ if (unlikely(is_link_local_ether_addr(dest)))
{ u16 fwd_mask = p->
br->group_fwd_mask_required; /* * See IEEE 802.1D Table 7-10 Reserved addresses * * Assignment Value * Bridge Group Address 01-80-C2-00-00-00 (STP的目的mac地址) * (MAC Control) 802.3 01-80-C2-00-00-01 * (Link Aggregation) 802.3 01-80-C2-00-00-02 * 802.1X PAE address 01-80-C2-00-00-03 * * 802.1AB LLDP 01-80-C2-00-00-0E * * Others reserved for future standardization */ switch (dest[5]) { case 0x00: /* Bridge Group Address */ /* If STP is turned off, then must forward to keep loop detection */ /* 如果是STP的目的MAC地址,但是stp沒有使能或者有轉發標記,那麼轉發該報文,不然上送自身(STP報文的上送)*/ if (p->br->stp_enabled == BR_NO_STP || fwd_mask & (1u << dest[5])) goto forward; break; case 0x01: /* IEEE MAC (Pause) */ goto drop; default: /* Allow selective forwarding for most other protocols */ fwd_mask |= p->br->group_fwd_mask; if (fwd_mask & (1u << dest[5])) goto forward; } /*如果是linklocal地址,並且不是上面幾種情況,則上送到自身*/ /* Deliver packet to local host only */ if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, NULL, skb, skb->dev, NULL, br_handle_local_finish)) { return RX_HANDLER_CONSUMED; /* consumed by filter */ } else { *pskb = skb; return RX_HANDLER_PASS; /* continue processing */ } } forward: #if defined(CONFIG_BCM_KF_IEEE1905) && defined(CONFIG_BCM_IEEE1905) /* allow broute to forward packets to the stack in any STP state */ rhook = rcu_dereference(br_should_route_hook); if (rhook) { if ((*rhook)(skb)) { *pskb = skb; if ((skb->protocol == htons(0x893a)) || (skb->protocol == htons(0x8912)) || (skb->protocol == htons(0x88e1))) #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) br_handle_local_finish(NULL, skb); #else br_handle_local_finish(skb); #endif return RX_HANDLER_PASS; } else if (skb->protocol == htons(0x893a) && (skb->pkt_type == PACKET_MULTICAST)) /* do not bridge multicast 1905 packets when 1905 is compiled */ goto drop; dest = eth_hdr(skb)->h_dest; } #endif #if defined(CONFIG_BCM_KF_WL) if (( (skb->protocol == htons(0x886c) /*ETHER_TYPE_BRCM*/) || (skb->protocol == htons(0x888e) /*ETHER_TYPE_802_1X*/) || (skb->protocol == htons(0x88c7) /*ETHER_TYPE_802_1X_PREAUTH*/) ) && (p->state != BR_STATE_FORWARDING) && (p->state != BR_STATE_DISABLED)) { /* force to forward brcm_type event packet */ NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, NULL, skb, skb->dev, NULL, br_handle_frame_finish); return RX_HANDLER_CONSUMED; } #endif switch (p->state) { #if defined(CONFIG_BCM_KF_FBOND) && (defined(CONFIG_BCM_FBOND) || defined(CONFIG_BCM_FBOND_MODULE)) case BR_STATE_BLOCKING: /* if this is unicast let it through even if the port is blocked it will be dropped later if a destination is not found to prevent flooding unicast from a blocked port */ if (is_multicast_ether_addr(dest)) goto drop; #endif case BR_STATE_FORWARDING: #if !defined(CONFIG_BCM_KF_IEEE1905) || !defined(CONFIG_BCM_IEEE1905) rhook = rcu_dereference(br_should_route_hook); if (rhook) { if ((*rhook)(skb)) { *pskb = skb; return RX_HANDLER_PASS; } dest = eth_hdr(skb)->h_dest; } #endif /* fall through */ case BR_STATE_LEARNING: /*如果目的mac地址與本地介面地址相等,標記報文型別為PACKET_HOST*/ if (ether_addr_equal(p->br->dev->dev_addr, dest)) skb->pkt_type = PACKET_HOST; /*對於網橋埠是forward和learning狀態的,則先呼叫防火牆處理函式處理NF_BR_PRE_ROUTING的ebtables(類似於ip層iptables,這個是網橋層面上的防火牆)相關規則*/ /*最終呼叫br_handle_frame_finish*/ NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, NULL, skb, skb->dev, NULL, br_handle_frame_finish); break; default: drop: kfree_skb(skb); } return RX_HANDLER_CONSUMED; }