Chinaunix首页
|
论坛
|
博客
博文
博主
v.t
4月28日14:30-20:30机房服务器迁移,暂停博客使用
9/30日 14:00 -10/4日 08:00暂时无法发布内容!
9/30日 14:00 -10/4日 08:00暂时无法发布内容!
首页
|
博文目录
|
关于我
vir_tec
博客访问: 17468
博文数量: 1
博客积分: 0
博客等级: 民兵
技术积分: 16
用 户 组: 普通用户
注册时间: 2019-04-05 15:39
文章分类
全部博文
(1)
kernel-4.17.2
(1)
net-bridge
(1)
未分配的博文
(0)
推荐博文
·
ORACLE SQL overlap时间段重...
·
Rust入门到精通(三)—— 不...
·
Oracle 1582-10-07问题
·
1:Python开发:初识Python...
·
ORACLE物理结构
相关博文
·
倒计时1天!龙蜥社区开源软件...
·
探索OS升级迭代的兼容性和安...
·
开放原子校源行(天津大学站...
·
时间单位的选择会如何影响价...
·
Jtti:盘点Linux云服务器的监...
·
在Linux中如何查看日志?...
·
百度搜索:蓝易云 - SSH远程U...
·
使用OpManager Plus提升应用...
·
如何保证六西格玛激励机制的...
·
华纳云:Ubuntu系统清理日志...
linux bridge 解析
分类:
LINUX
2019-04-05 21:37:09
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.注册及收包如图:
4.部分函数
4.1
static
int
__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
<
0
)
{
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.2
int
br_ioctl_deviceless_stub
(
struct net
*
net
,
unsigned
int
cmd
,
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.3
int
br_add_bridge
(
struct net
*
net
,
const
char
*
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.4
void 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.5
static
const
struct 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.6
static
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.7
int
br_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
<
dev_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
;
}
阅读(10709) | 评论(0) | 转发(0) |
0
上一篇:没有了
下一篇:没有了
给主人留下些什么吧!~~
评论热议
请登录后评论。
登录
注册