用户态代码
package/network/config/swconfig
内核代码:
drivers/net/phy/swconfig.c
初始化脚本
/lib/network/switch.sh
switch.sh的内容如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #!/bin/sh # Copyright (C) 2009 OpenWrt.org setup_switch_dev() { config_get name "$1" name name="${name:-$1}" [ -d "/sys/class/net/$name" ] && ifconfig "$name" up swconfig dev "$name" load network } setup_switch() { config_load network config_foreach setup_switch_dev switch } |
/etc/init.d/network包含初始化接口,在start/reload的时候调用
1 2 3 4 5 | init_switch() { setup_switch() { return 0; } include /lib/network setup_switch |
setup_switch会遍历network配置中的switch,执行swconfig dev switchX load network
swconfig dev <dev> [port <port>|vlan <vlan>] (help|set <key> <value>|get <key>|load <config>|show)
使用help命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # swconfig dev switch0 help switch0: QCA MP(QCA MP), ports: 2 (cpu @ 0), vlans: 128 --switch Attribute 1 (int): enable_vlan (Enable 8021q VLAN) Attribute 2 (int): max_frame_size (Set Max frame Size Of Mac) Attribute 3 (none): reset_mibs (Reset All MIB Counters) Attribute 4 (none): flush_arl (Flush All ARL table) Attribute 5 (string): dump_arl (Dump All ARL table) Attribute 6 (unknown): switch_ext (Switch extended configuration) Attribute 7 (none): apply (Activate changes in the hardware) Attribute 8 (none): reset (Reset the switch) --vlan Attribute 1 (int): vid (Configure Vlan Id) Attribute 2 (ports): ports (VLAN port mapping) --port Attribute 1 (none): reset_mib (Reset Mib Counters) Attribute 2 (string): mib (Get Mib Counters) Attribute 3 (int): enable_eee (Enable EEE) Attribute 4 (int): pvid (Primary VLAN ID) Attribute 5 (string): link (Get port link information) |
如初始化流程所示,使用load命令:
# swconfig dev switch0 load network
使用help命令可以列出全局属性,如--switch所示,查看要设置属性的名字。
比如查看enable_vlan的值。
# swconfig dev switch0 get enable_vlan
1
比如,重置switch
# swconfig dev switch0 set reset
显示全局、port、vlan属性
# swconfig dev switch0 show
显示port属性
# swconfig dev switch1 port 6 show
显示vlan属性
# swconfig dev switch1 vlan 0 show
VLAN 0:
vid: 0
ports:
需要指定port
比如读取port的link
# swconfig dev switch1 port 1 get link
port:1 link:down
比如设置pvid
# swconfig dev switch1 port 1 set pvid 1
注意,属性设置后,需要设置apply属性才能生效到硬件
swconfig dev switch1 set apply
需要指定VLAN的序号,注意序号和vid不同。
通过netlink和内核swconfig模块通信,netlink的family为switch。
switch有3种属性,全局属性,port属性,vlan属性。
这里重点讲一下load的机制,比如 swconfig dev switch1 load network
首先遍历network的switch类型的setction,如果name这个option或者section名匹配switch1,则确定是这个section。比如:
config switch 'switch1'
option name 'switch1'
option enable_vlan '1'
name匹配,就匹配上了,如果没有name,switch section的名字switch1匹配也可以,所以上述name是可以省略的。然后global属性,在switch section指定,支持两个属性,reset和enable_vlan。
port属性,通过switch_port section指定,device选项指定switch1,port选项指定哪个port。其它选项指定port属性,比如:
config switch_port
option device 'switch1'
option port '1'
option pvid '5'
vlan属性,通过switch_vlan section指定。和switch_port类似
config switch_vlan
option device 'switch1'
option vlan '1'
option ports '1 2 3 6'
在swlib_set_attr_setting()函数中,对uci配置中的字符串进行解析,生成switch_val。特别的对于SWITCH_TYPE_PORTS类型,即switch_vlan.ports配置项,解析成多个switch_port结构体,带上id和flags。
flags可以带上SWLIB_PORT_FLAG_TAGGED。
另外还支持switch_ext section。设置所有属性后,还额外设置apply属性,来生效。
另外load还有一个early_settings:
struct swlib_setting early_settings[] = {
{ .name = "reset", .val = "1" },
{ .name = "enable_vlan", .val = "1" },
};
上述两个会先设置下去,如果switch setion有对应的值,则使用对应的值,没有就使用默认值。
所以uci里面没有reset,也会默认reset。而uci设置enable_vlan 为1相当于没设置。
初始化的时候,注册了generic netlink,来实现和swconfig用户态通信。
提供register_switch()接口给交换机驱动来注册交换机。unregister_switch来删除注册的交换机。
注册的交换机的名字是 switch%d,按照注册的顺序来。
注册的交换机的ops,结构体为struct switch_dev_ops。它的定义如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | struct switch_dev_ops { struct switch_attrlist attr_global, attr_port, attr_vlan; struct switch_attrlist attr_reg; int (*get_reg_val)(struct switch_dev *dev, int reg, int *val); int (*set_reg_val)(struct switch_dev *dev, int reg, int val); int (*get_vlan_ports)(struct switch_dev *dev, struct switch_val *val); int (*set_vlan_ports)(struct switch_dev *dev, struct switch_val *val); int (*get_port_pvid)(struct switch_dev *dev, int port, int *val); int (*set_port_pvid)(struct switch_dev *dev, int port, int val); int (*apply_config)(struct switch_dev *dev); int (*reset_switch)(struct switch_dev *dev); int (*get_port_link)(struct switch_dev *dev, int port, struct switch_port_link *link); int (*get_port_stats)(struct switch_dev *dev, int port, struct switch_port_stats *stats); }; |
首先是3个属性列表attr_global, attr_port, attr_vlan,是驱动提供的3种属性的数组。
属性有名字、描述、类型、读取接口、设置接口等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | struct switch_attrlist { int n_attr; const struct switch_attr *attr; }; struct switch_attr { int disabled; int type; const char *name; const char *description; int (*set)(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val); int (*get)(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val); /* for driver internal use */ int id; int ofs; int max; }; |
支持的netlink命令
1 SWITCH_CMD_GET_SWITCH
枚举出所有的switch,dumpit接口为swconfig_dump_switches()。
2 SWITCH_CMD_LIST_GLOBAL/SWITCH_CMD_LIST_VLAN/SWITCH_CMD_LIST_PORT
列出global,port, vlan属性。doit接口为swconfig_list_attrs。
它会合并驱动提供的属性,以及默认属性。
比如vlan提供了默认属性:
static struct switch_attr default_vlan[] = {
[VLAN_PORTS] = {
.type = SWITCH_TYPE_PORTS,
.name = "ports",
.description = "VLAN port mapping",
.set = swconfig_set_vlan_ports,
.get = swconfig_get_vlan_ports,
},
};
如果驱动提供了,get_vlan_ports或set_vlan_ports接口。那么默认属性ports就是激活的,否则不激活。