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: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;} 
原创粉丝点击