/*
* 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:0x是linklocal地址*/
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;
}
linux网桥处理函数学习-----br_handle_frame
最新推荐文章于 2023-08-10 14:30:48 发布