linux网桥处理函数学习-----br_handle_frame
来源:互联网 发布:邮轮上有网络吗 编辑:程序博客网 时间:2024/06/05 02:41
/* * 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;}
阅读全文
0 0
- linux网桥处理函数学习-----br_handle_frame
- br_handle_frame()函数
- linux网桥处理函数学习------br_handle_frame_finish
- 桥数据包接收----br_handle_frame(六)
- linux网络地址处理函数
- linux处理字符串函数
- linux 出错处理函数
- linux信号处理函数
- Linux信号处理函数
- Linux学习 循环处理
- Linux学习 处理输出
- Linux信号处理机制及处理函数
- Linux 信号signal处理函数
- linux进程终止处理函数
- Linux 信号signal处理函数
- Linux 信号signal处理函数
- Linux 信号signal处理函数
- Linux 信号signal处理函数
- bzoj 2004: [Hnoi2010]Bus 公交线路 状压dp+矩阵乘法
- 声明与定义的区别
- neo4j 大量数据的批量导入
- FPGA流水线技术原理与实例
- 侧边框
- linux网桥处理函数学习-----br_handle_frame
- js 改变运行上下文
- 前端_购物车选择多选少选
- 86标准SQL与92标准SQL用法区别
- 5.Struts2_Action 概述
- C语言基础知识学习(变量的储存类型)
- 【bzoj 2431】逆序对数列(DP)
- angularjs指令之间的数据交互
- Spark由浅到深(1)--安装,测试,问题排错