// 网桥设备驱动程序的hard_start_xmit函数
// 函数主要任务:
// 1.广播或多播地址,在所有端口上扩散
// 2.存在转发项,在指定端口上发送
// 3.没有找到转发项,在所有端口上扩散
1.1 int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct net_bridge *br = netdev_priv(dev);
const unsigned char *dest = skb->data;
struct net_bridge_fdb_entry *dst;
//更新网桥设备的统计信息
br->statistics.tx_packets++;
br->statistics.tx_bytes += skb->len;
//更新l2头位置
skb->mac.raw = skb->data;
skb_pull(skb, ETH_HLEN);
rcu_read_lock();
if (dest[0] & 1)//l2地址的第一个字节的第一位为1,则为多播地址
br_flood_deliver(br, skb, 0);//在所有端口上发送此报文
else if ((dst = __br_fdb_get(br, dest)) != NULL)//如果转发数据中存在目标地址的记录
br_deliver(dst->dst, skb);//通过与目标地址相关的端口发送
else
br_flood_deliver(br, skb, 0);
rcu_read_unlock();
return 0;
}
// 在所有端口扩散skb
// 参数:__packet_hook, __br_deliver
// 调用路径:br_dev_xmit->br_flood_deliver->br_flood
1.3 static void br_flood(struct net_bridge *br, struct sk_buff *skb, int clone,
void (*__packet_hook)(const struct net_bridge_port *p,
struct sk_buff *skb))
{
struct net_bridge_port *p;
struct net_bridge_port *prev;
//指示是否复制一份skb,br_dev_xmit->br_flood_deliver->br_flood此调用路径clone=0
if (clone) {
struct sk_buff *skb2;
if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
br->statistics.tx_dropped++;
return;
}
skb = skb2;
}
prev = NULL;
//遍历所有的端口
list_for_each_entry_rcu(p, &br->port_list, list) {
if (should_deliver(p, skb)) {//skb的输出设备非此
网络子系统34_网桥设备的传输与接收
最新推荐文章于 2023-09-07 14:58:15 发布
本文深入探讨了Linux内核中网桥设备的传输过程,包括hard_start_xmit函数的角色、多播与单播数据帧的处理、br_dev_queue_push_xmit中的MTU检查以及br_handle_frame系列函数如何决定数据帧的路由和桥接。内容涵盖了从接收到转发数据帧的完整流程,展示了网桥如何维护转发数据库并处理BPDU数据。
摘要由CSDN通过智能技术生成