Linux 3.10 kernel bridge转发逻辑

2026/1/14 20:56:11

http://www.lampbrother.net

NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,br_handle_frame_finish); break; default: drop:

kfree_skb(skb); }

return RX_HANDLER_CONSUMED; }

经过NF_BR_LOCAL_IN hook点会执行br_handle_local_finish函数。 l br_handle_local_finish

点击(此处)折叠或打开

static int br_handle_local_finish(struct sk_buff *skb) {

struct net_bridge_port *p = br_port_get_rcu(skb->dev); u16 vid = 0;

/*获取skb的vlan id(3.10的bridge支持vlan)*/ br_vlan_get_tag(skb, &vid);

/*更新bridge的mac表,注意vlan id也是参数,说明每个vlan有一个独立的mac表*/

br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid); return 0; /* process further */ }

经过NF_BR_PRE_ROUTING hook点会执行br_handle_frame_finish函数。 l br_handle_frame_finish

点击(此处)折叠或打开

int br_handle_frame_finish(struct sk_buff *skb)

http://www.lampbrother.net

{

const unsigned char *dest = eth_hdr(skb)->h_dest; struct net_bridge_port *p = br_port_get_rcu(skb->dev); struct net_bridge *br;

struct net_bridge_fdb_entry *dst; struct net_bridge_mdb_entry *mdst; struct sk_buff *skb2; u16 vid = 0;

if (!p || p->state == BR_STATE_DISABLED) goto drop;

/*这个判断主要是vlan的相关检查,如是否和接收接口配置的vlan相同*/ if (!br_allowed_ingress(p->br, nbp_get_vlan_info(p), skb, &vid)) goto out;

/* insert into forwarding database after filtering to avoid spoofing */ br = p->br; /*更新转发数据库*/

br_fdb_update(br, p, eth_hdr(skb)->h_source, vid); /*多播mac的处理*/

if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) && br_multicast_rcv(br, p, skb)) goto drop;

if (p->state == BR_STATE_LEARNING) goto drop;

BR_INPUT_SKB_CB(skb)->brdev = br->dev;

/* The packet skb2 goes to the local host (NULL to skip). */ skb2 = NULL;

/*如果网桥被设置为混杂模式*/ if (br->dev->flags & IFF_PROMISC) skb2 = skb; dst = NULL;

http://www.lampbrother.net

/*如果skb的目的mac是广播*/ if (is_broadcast_ether_addr(dest)) skb2 = skb;

else if (is_multicast_ether_addr(dest)) { /*多播*/ mdst = br_mdb_get(br, skb, vid);

if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) { if ((mdst && mdst->mglist) || br_multicast_is_router(br)) skb2 = skb;

br_multicast_forward(mdst, skb, skb2); skb = NULL; if (!skb2) goto out; } else

skb2 = skb;

br->dev->stats.multicast++;

} else if ((dst = __br_fdb_get(br, dest, vid)) && dst->is_local) {/*目的地址是本机mac,则发往本机协议栈*/ skb2 = skb;

/* Do not forward the packet since it's local. */ skb = NULL; }

if (skb) { if (dst) {

dst->used = jiffies;

br_forward(dst->dst, skb, skb2); //转发给目的接口 } else

br_flood_forward(br, skb, skb2); //找不到目的接口则广播 } if (skb2)

http://www.lampbrother.net

return br_pass_frame_up(skb2); //发往本机协议栈 out:

return 0; drop:

kfree_skb(skb); goto out; }

我们先看发往本机协议栈的函数br_pass_frame_up。 l br_pass_frame_up 点击(此处)折叠或打开

static int br_pass_frame_up(struct sk_buff *skb) {

struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev; struct net_bridge *br = netdev_priv(brdev); //更新统计计数(略)

/* Bridge is just like any other port. Make sure the * packet is allowed except in promisc modue when someone * may be running packet capture. */

if (!(brdev->flags & IFF_PROMISC) && !br_allowed_egress(br, br_get_vlan_info(br), skb)) {

kfree_skb(skb); //如果不是混杂模式且vlan处理不合要求则丢弃 return NET_RX_DROP; }

//vlan处理逻辑

skb = br_handle_vlan(br, br_get_vlan_info(br), skb); if (!skb)

return NET_RX_DROP; indev = skb->dev;


Linux 3.10 kernel bridge转发逻辑.doc 将本文的Word文档下载到电脑
搜索更多关于: Linux 3.10 kernel bridge转发逻辑 的文档
相关推荐
相关阅读
× 游客快捷下载通道(下载后可以自由复制和排版)

下载本文档需要支付 10

支付方式:

开通VIP包月会员 特价:29元/月

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:xuecool-com QQ:370150219