unix linux tecn,linux bridge 解析

linux内核学习,有不足之处欢迎大家一起探讨

1.网桥创建

br_init   注册ioctrl操作函数  br_ioctl_deviceless_stub ,在br_ioctl_deviceless_stub函数中可以创建一个新的虚拟网桥设备,并绑定另一个ioctrl操作函数 br_dev_ioctl ,br_dev_ioctl 函数可以增加或者删除一个'接口' (add_del_if) ,在br_add_if中注册报文处理函数br_handle_frame

2.网桥处理报文

__netif_receive_skb_core 调用br_handle_frame

3.注册及收包如图:

811b63936bb19eaacc179dfb6b74e182.png

4.部分函数

4.1staticint__init br_init(void)

点击(此处)折叠或打开

static int __init br_init(void)

{

int err;

BUILD_BUG_ON(sizeof(struct br_input_skb_cb) > FIELD_SIZEOF(struct sk_buff, cb));

err = stp_proto_register(&br_stp_proto);

if (err 

pr_err("bridge: can't register sap for STP\n");

return err;

}

err = br_fdb_init();

if (err)

goto err_out;

err = register_pernet_subsys(&br_net_ops);

if (err)

goto err_out1;

err = br_nf_core_init();

if (err)

goto err_out2;

err = register_netdevice_notifier(&br_device_notifier);

if (err)

goto err_out3;

err = register_switchdev_notifier(&br_switchdev_notifier);

if (err)

goto err_out4;

err = br_netlink_init();

if (err)

goto err_out5;

brioctl_set(br_ioctl_deviceless_stub);

#if IS_ENABLED(CONFIG_ATM_LANE)

br_fdb_test_addr_hook = br_fdb_test_addr;

#endif

#if IS_MODULE(CONFIG_BRIDGE_NETFILTER)

pr_info("bridge: filtering via arp/ip/ip6tables is no longer available "

"by default. Update your scripts to load br_netfilter if you "

"need this.\n");

#endif

return 0;

err_out5:

unregister_switchdev_notifier(&br_switchdev_notifier);

err_out4:

unregister_netdevice_notifier(&br_device_notifier);

err_out3:

br_nf_core_fini();

err_out2:

unregister_pernet_subsys(&br_net_ops);

err_out1:

br_fdb_fini();

err_out:

stp_proto_unregister(&br_stp_proto);

return err;

}

module_init(br_init)

4.2intbr_ioctl_deviceless_stub(struct net*net,unsignedintcmd,void __user*uarg)

点击(此处)折叠或打开

int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uarg)

{

switch (cmd) {

case SIOCGIFBR:

case SIOCSIFBR:

return old_deviceless(net, uarg);

case SIOCBRADDBR:

case SIOCBRDELBR:

{

char buf[IFNAMSIZ];

if (!ns_capable(net->user_ns, CAP_NET_ADMIN))

return -EPERM;

if (copy_from_user(buf, uarg, IFNAMSIZ))

return -EFAULT;

buf[IFNAMSIZ-1] = 0;

if (cmd == SIOCBRADDBR)

return br_add_bridge(net, buf);

return br_del_bridge(net, buf);

}

}

return -EOPNOTSUPP;

}

4.3intbr_add_bridge(struct net*net,constchar*name)

点击(此处)折叠或打开

int br_add_bridge(struct net *net, const char *name)

{

struct net_device *dev;

int res;

dev = alloc_netdev(sizeof(struct net_bridge), name, NET_NAME_UNKNOWN,

br_dev_setup);

if (!dev)

return -ENOMEM;

dev_net_set(dev, net);

dev->rtnl_link_ops = &br_link_ops;

res = register_netdev(dev);

if (res)

free_netdev(dev);

return res;

}

4.4void br_dev_setup(struct net_device*dev)

点击(此处)折叠或打开

void br_dev_setup(struct net_device *dev)

{

struct net_bridge *br = netdev_priv(dev);

eth_hw_addr_random(dev);

ether_setup(dev);

dev->netdev_ops = &br_netdev_ops;

dev->needs_free_netdev = true;

dev->ethtool_ops = &br_ethtool_ops;

SET_NETDEV_DEVTYPE(dev, &br_type);

dev->priv_flags = IFF_EBRIDGE | IFF_NO_QUEUE;

dev->features = COMMON_FEATURES | NETIF_F_LLTX | NETIF_F_NETNS_LOCAL |

NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX;

dev->hw_features = COMMON_FEATURES | NETIF_F_HW_VLAN_CTAG_TX |

NETIF_F_HW_VLAN_STAG_TX;

dev->vlan_features = COMMON_FEATURES;

br->dev = dev;

spin_lock_init(&br->lock);

INIT_LIST_HEAD(&br->port_list);

INIT_HLIST_HEAD(&br->fdb_list);

spin_lock_init(&br->hash_lock);

br->bridge_id.prio[0] = 0x80;

br->bridge_id.prio[1] = 0x00;

ether_addr_copy(br->group_addr, eth_stp_addr);

br->stp_enabled = BR_NO_STP;

br->group_fwd_mask = BR_GROUPFWD_DEFAULT;

br->group_fwd_mask_required = BR_GROUPFWD_DEFAULT;

br->designated_root = br->bridge_id;

br->bridge_max_age = br->max_age = 20 * HZ;

br->bridge_hello_time = br->hello_time = 2 * HZ;

br->bridge_forward_delay = br->forward_delay = 15 * HZ;

br->bridge_ageing_time = br->ageing_time = BR_DEFAULT_AGEING_TIME;

dev->max_mtu = ETH_MAX_MTU;

br_netfilter_rtable_init(br);

br_stp_timer_init(br);

br_multicast_init(br);

INIT_DELAYED_WORK(&br->gc_work, br_fdb_cleanup);

}

4.5staticconststruct net_device_ops br_netdev_ops

点击(此处)折叠或打开

static const struct net_device_ops br_netdev_ops = {

.ndo_open         = br_dev_open,

.ndo_stop         = br_dev_stop,

.ndo_init         = br_dev_init,

.ndo_uninit         = br_dev_uninit,

.ndo_start_xmit         = br_dev_xmit,

.ndo_get_stats64     = br_get_stats64,

.ndo_set_mac_address     = br_set_mac_address,

.ndo_set_rx_mode     = br_dev_set_multicast_list,

.ndo_change_rx_flags     = br_dev_change_rx_flags,

.ndo_change_mtu         = br_change_mtu,

.ndo_do_ioctl         = br_dev_ioctl,

#ifdef CONFIG_NET_POLL_CONTROLLER

.ndo_netpoll_setup     = br_netpoll_setup,

.ndo_netpoll_cleanup     = br_netpoll_cleanup,

.ndo_poll_controller     = br_poll_controller,

#endif

.ndo_add_slave         = br_add_slave,

.ndo_del_slave         = br_del_slave,

.ndo_fix_features = br_fix_features,

.ndo_fdb_add         = br_fdb_add,

.ndo_fdb_del         = br_fdb_delete,

.ndo_fdb_dump         = br_fdb_dump,

.ndo_bridge_getlink     = br_getlink,

.ndo_bridge_setlink     = br_setlink,

.ndo_bridge_dellink     = br_dellink,

.ndo_features_check     = passthru_features_check,

};

4.6static int br_add_slave(struct net_device *dev, struct net_device *slave_dev,struct netlink_ext_ack*extack)

点击(此处)折叠或打开

static int br_add_slave(struct net_device *dev, struct net_device *slave_dev,

struct netlink_ext_ack *extack)

{

struct net_bridge *br = netdev_priv(dev);

return br_add_if(br, slave_dev, extack);

}

4.7intbr_add_if(struct net_bridge*br,struct net_device*dev,struct netlink_ext_ack*extack)

点击(此处)折叠或打开

int br_add_if(struct net_bridge *br, struct net_device *dev,

struct netlink_ext_ack *extack)

{

struct net_bridge_port *p;

int err = 0;

unsigned br_hr, dev_hr;

bool changed_addr;

/* Don't allow bridging non-ethernet like devices, or DSA-enabled

* master network devices since the bridge layer rx_handler prevents

* the DSA fake ethertype handler to be invoked, so we do not strip off

* the DSA switch tag protocol header and the bridge layer just return

* RX_HANDLER_CONSUMED, stopping RX processing for these frames.

*/

if ((dev->flags & IFF_LOOPBACK) ||

dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN ||

!is_valid_ether_addr(dev->dev_addr) ||

netdev_uses_dsa(dev))

return -EINVAL;

/* No bridging of bridges */

if (dev->netdev_ops->ndo_start_xmit == br_dev_xmit) {

NL_SET_ERR_MSG(extack,

"Can not enslave a bridge to a bridge");

return -ELOOP;

}

/* Device has master upper dev */

if (netdev_master_upper_dev_get(dev))

return -EBUSY;

/* No bridging devices that dislike that (e.g. wireless) */

if (dev->priv_flags & IFF_DONT_BRIDGE) {

NL_SET_ERR_MSG(extack,

"Device does not allow enslaving to a bridge");

return -EOPNOTSUPP;

}

p = new_nbp(br, dev);

if (IS_ERR(p))

return PTR_ERR(p);

call_netdevice_notifiers(NETDEV_JOIN, dev);

err = dev_set_allmulti(dev, 1);

if (err)

goto put_back;

err = kobject_init_and_add(&p->kobj, &brport_ktype, &(dev->dev.kobj),

SYSFS_BRIDGE_PORT_ATTR);

if (err)

goto err1;

err = br_sysfs_addif(p);

if (err)

goto err2;

err = br_netpoll_enable(p);

if (err)

goto err3;

err = netdev_rx_handler_register(dev, br_handle_frame, p);

if (err)

goto err4;

dev->priv_flags |= IFF_BRIDGE_PORT;

err = netdev_master_upper_dev_link(dev, br->dev, NULL, NULL, extack);

if (err)

goto err5;

err = nbp_switchdev_mark_set(p);

if (err)

goto err6;

dev_disable_lro(dev);

list_add_rcu(&p->list, &br->port_list);

nbp_update_port_count(br);

netdev_update_features(br->dev);

br_hr = br->dev->needed_headroom;

dev_hr = netdev_get_fwd_headroom(dev);

if (br_hr 

update_headroom(br, dev_hr);

else

netdev_set_rx_headroom(dev, br_hr);

if (br_fdb_insert(br, p, dev->dev_addr, 0))

netdev_err(dev, "failed insert local address bridge forwarding table\n");

err = nbp_vlan_init(p);

if (err) {

netdev_err(dev, "failed to initialize vlan filtering on this port\n");

goto err7;

}

spin_lock_bh(&br->lock);

changed_addr = br_stp_recalculate_bridge_id(br);

if (netif_running(dev) && netif_oper_up(dev) &&

(br->dev->flags & IFF_UP))

br_stp_enable_port(p);

spin_unlock_bh(&br->lock);

br_ifinfo_notify(RTM_NEWLINK, NULL, p);

if (changed_addr)

call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev);

br_mtu_auto_adjust(br);

br_set_gso_limits(br);

kobject_uevent(&p->kobj, KOBJ_ADD);

return 0;

err7:

list_del_rcu(&p->list);

br_fdb_delete_by_port(br, p, 0, 1);

nbp_update_port_count(br);

err6:

netdev_upper_dev_unlink(dev, br->dev);

err5:

dev->priv_flags &= ~IFF_BRIDGE_PORT;

netdev_rx_handler_unregister(dev);

err4:

br_netpoll_disable(p);

err3:

sysfs_remove_link(br->ifobj, p->dev->name);

err2:

kobject_put(&p->kobj);

p = NULL; /* kobject_put frees */

err1:

dev_set_allmulti(dev, -1);

put_back:

dev_put(dev);

kfree(p);

return err;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值