我是靠谱客的博主 受伤板凳,最近开发中收集的这篇文章主要介绍linux通过端口发送,三、Linux上桥的实现,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

69075335167d2dda96e42aaff68a4a46.png

如图,这里就不对每个处理函数就行讲解了。

上送网络层进行处理

static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)

{

struct net_device *indev, *brdev = br->dev;

skb->dev = brdev; //把报文的接收dev修改为bridge dev

NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,

netif_receive_skb);

}

泛洪发送

static void br_flood(struct net_bridge *br, struct sk_buff *skb,

void (*__packet_hook)(const struct net_bridge_port *p,

struct sk_buff *skb))

{

struct net_bridge_port *p;

struct net_bridge_port *prev;

prev = NULL;

/*遍历bridge下加入的二层端口,从每个二层端口发送一份出去*/

list_for_each_entry_rcu(p, &br->port_list, list)

{

if (should_deliver(p, skb))

{

if (prev != NULL)

{

struct sk_buff *skb2;

/*把报文拷贝一份后从二层端口发送出去*/

if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL)

{

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

kfree_skb(skb);

return;

}

__packet_hook(prev, skb2);

}

prev = p;

}

}

if (prev != NULL) {

__packet_hook(prev, skb);

return;

}

kfree_skb(skb);

}

六、MAC地址的学习

bridge每收到一个报文,就会根据报文的源MAC来更新FDB表项。

int br_handle_frame_finish(struct sk_buff *skb)

{

const unsigned char *dest = eth_hdr(skb)->h_dest;

struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);

struct net_bridge *br;

struct net_bridge_fdb_entry *dst;

struct sk_buff *skb2;

br = p->br;

br_fdb_update(br, p, eth_hdr(skb)->h_source);

}

void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,

const unsigned char *addr)

{

struct hlist_head *head = &br->hash[br_mac_hash(addr)];

struct net_bridge_fdb_entry *fdb;

fdb = fdb_find(head, addr);

/*如果FDB表项已经存在,则更新*/

if (likely(fdb))

{

/* attempt to update an entry for a local interface */

/*如果是本机FDB,表示接收错误*/

if (unlikely(fdb->is_local))

{

if (net_ratelimit())

printk(KERN_WARNING "%s: received packet with "

"own address as source addressn",

source->dev->name);

}

else{/*更新FDB表项,同时更新FDB的老化时间戳*/

fdb->dst = source;

fdb->ageing_timer = jiffies;

}

}

/*如果FDB表项不存在,就新建一个FDB*/else{spin_lock(&br->hash_lock);

if (!fdb_find(head, addr))

fdb_create(head, source, addr, 0);

spin_unlock(&br->hash_lock);

}

}

七、MAC地址的老化

每次FDB表项被命中更新时,会更新FDB表项的老化时间戳。Bridge起了一个定时器,来定期的清理长时间不用的FDB表项。

初始化定时器

void br_stp_timer_init(struct net_bridge *br)

{

。。。。。。

setup_timer(&br->gc_timer, br_fdb_cleanup, (unsigned long) br);

}

void br_fdb_cleanup(unsigned long _data)

{

struct net_bridge *br = (struct net_bridge *)_data;

unsigned long delay = hold_time(br);

unsigned long next_timer = jiffies + br->forward_delay;

int i;

/*加锁进行保护*/

spin_lock_bh(&br->hash_lock);

/*遍历FDB hash表中的每一项,判断FDB表项是否过期,如果过期,就删除*/

for (i = 0; i

{

struct net_bridge_fdb_entry *f;

struct hlist_node *h, *n;

hlist_for_each_entry_safe(f, h, n, &br->hash[i], hlist)

{

unsigned long this_timer;

/*跳过静态的FDB表项*/

if (f->is_static)

continue;

this_timer = f->ageing_timer + delay;

/*如果FDB表项过期,就删除该FDB表项*/

if (time_before_eq(this_timer, jiffies))

fdb_delete(f);

else if (time_before(this_timer, next_timer))

next_timer = this_timer;

}

}

spin_unlock_bh(&br->hash_lock);

/*遍历完后重新设置老化定时器*/

mod_timer(&br->gc_timer, round_jiffies(next_timer + HZ/4));

}

最后

以上就是受伤板凳为你收集整理的linux通过端口发送,三、Linux上桥的实现的全部内容,希望文章能够帮你解决linux通过端口发送,三、Linux上桥的实现所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(72)

评论列表共有 0 条评论

立即
投稿
返回
顶部