开发板须要有双网卡,并能进行正常通讯。网络
若选择中断机制实现,硬件PHY上需具备中断引脚且能正常输出。函数
双网卡冗余备份方案采用"主-备份"网卡策略将多块物理网卡进行绑定,绑定后两个网卡只有一个物理地址和IP地址,同一时刻只有一个网卡进行工做,当主网卡或线路出现故障时能自动切换到备份网卡。测试
双网卡冗余备份方案采用轮询机制检测,即每隔一段时间进行一次PHY链接状态检测,当检测到主网卡链接断开且备份网卡链接正常时,切换至备份网卡。spa
双网卡冗余备份方案采用中断机制检测,即PHY链接状态改变产生中断信号,当即进行检测,当检测到主网卡链接断开且备份网卡链接正常时,切换至备份网卡。code
中断机制检测相比轮询机制,反应时间更快,但须要硬件支持。ip
调用ifconfig命令查看当前网卡信息,获取须要进行绑定的两个网卡名,如图 4.1所示。开发
图 4.1获取网卡信息cmd
跳转到/etc/目录下,添加一个绑定双网卡的配置文件bonding.ini,内容示例如程序清单 4.1所示。it
程序清单 4.1 bonding.ini配置文件io
[bonding] ipaddr=192.168.2.220 netmask=255.255.255.0 gateway=192.168.2.1 mac=80:46:38:78:28:39 en1name=en1 en2name=en2 mode=1 ****** mode=0 (若不配置默认100ms)********* miimon=100 ****** mode=1 (若不配置默认降低沿触发)********* gpiotype=1 gpiolevel=0
本次配置采用了主从策略,具体说明以下:
ipaddr:配置绑定后的IP地址;
netmask:配置绑定后的子网掩码;
gateway:配置绑定后的默认网关;
mac:配置绑定后的物理地址;
en1name:配置须要绑定的主网卡名;
en2name:配置须要绑定的备份网卡名;
mode:配置工做模式(0:轮询机制,1:中断机制),若选择轮询机制,需配置miimon项;若选择中断机制,需配置en1gpio、en2gpio、gpiotype、gpiolevel项;
miimon:配置轮询检测时间(毫秒),一般设置为100毫秒;
gpiotype:配置触发方式(0:电平触发,1:边沿触发);
gpiolevel:配置触发条件(若是为电平触发, 1 表示高电平触发, 0 表示低电平触发;若是为边沿触发, 1 表示上升沿触发, 0 表示降低沿触发, 2 表示双边沿触发)。
双网卡冗余备份模块须要调用网卡驱动中的ioctl函数,并设置物理网卡硬件地址,要求底层网卡驱动具备如表格 4.1功能:
表格 4.1 ioctl函数cmd命令
cmd命令 |
参数类型 |
功能 |
SIOCSIFHWADDR |
struct ifreq |
设置硬件地址 |
GET_LINK_STATE |
struct ifreq |
获取PHY状态 |
SET_PHY_MICR |
NULL |
设置PHY中断 |
CLEAR_PHY_MISR |
NULL |
清除PHY中断状态 |
GET_MAC_IRQ |
ULONG |
获取网卡中断号 |
GET_PHY_GPIO |
UINT8 |
获取PHY中断输出GPIO管脚号 |
若网卡驱动中ioctl函数未实现,需修改网卡驱动,具体细节为:
网卡驱动函数中添加ioctl函数,如程序清单 4.2所示。
程序清单 4.2网卡驱动函数修改
static struct netdev_funcs net0_drv = { ioctl = __enetCoreIoctl, };
编写ioctl函数,如程序清单 4.3所示。
程序清单 4.3添加ioctl函数
static INT __enetCoreIoctl (struct netdev *pNetDev, int iCmd, void *pArg) { struct ifreq *pifreq; switch (iCmd) { case XXX: break; default: break; } return (ERROR_NONE); }
ioctl函数中,添加SIOCSIFHWADDR命令,如程序清单 4.4所示。
程序清单 4.4添加SIOCSIFHWADDR命令
#define SIOCSIFHWADDR _IOW('i', 55, struct ifreq) case GET_LINK_STATE: pifreq = (struct ifreq *)pArg; /* TODO:设置 MAC 地址 */ break;
ioctl函数中,添加GET_MAC_IRQ命令,如程序清单 4.5所示。
程序清单 4.5添加GET_MAC_IRQ命令
#define GET_MAC_IRQ _IOWR('i', 260, struct ifreq) case GET_MAC_IRQ: /* TODO:获取 MAC 中断号 */ break;
轮询机制须要调用网卡驱动中的ioctl函数,并读取硬件设备PHY的链接状态,须要修改网卡驱动ioctl函数,具体细节为:
ioctl函数中,添加GET_LINK_STATE命令,如程序清单 4.6所示。
程序清单 4.6添加GET_LINK_STATE命令
#define GET_LINK_STATE _IOWR('i', 257, struct ifreq) case GET_LINK_STATE: pifreq = (struct ifreq *)pArg; /* TODO: 读取硬件设备PHY的链接状态 */ /* 若链接:pifreq->ifr_flags |= IFF_RUNNING; */ /* 未链接:pifreq->ifr_flags &= ~IFF_RUNNING; */ break;
中断机制须要调用网卡驱动中的ioctl函数,并清除PHY的中断状态寄存器,须要修改网卡驱动ioctl函数,具体细节为:
添加SET_PHY_MICR命令,如程序清单 4.7所示。
程序清单 4.7添加SET_PHY_MICR命令
#define SET_PHY_MICR _IOWR('i', 258, struct ifreq) case SET_PHY_MICR: /* TODO:设置 PHY 中断控制寄存器,使能连接状态改变中断 */ /* 将硬件 PHY 上的中断引脚设置为输出 */ break;
添加CLEAR_PHY_MISR命令,如程序清单 4.8所示。
程序清单 4.8添加CLEAR_PHY_MISR命令
#define CLEAR_PHY_MISR _IOWR('i', 259, struct ifreq) case CLEAR_PHY_MISR: /* TODO:清除 PHY 中断状态 */ break;
注意:申请GPIO管脚号须要在开发板 BSP 适配文件中添加对应的GPIO配置。
添加GET_PHY_GPIO命令,如程序清单 4.9 所示。
程序清单 4.9添加GET_PHY_GPIO命令
#define GET_PHY_GPIO _IOWR('i', 261, struct ifreq) case GET_PHY_GPIO: /* TODO:获取 PHY GPIO 管脚号 */ break;
模块加载,开启双网卡冗余备份。
模块卸载,关闭双网卡冗余备份。
主机ping开发板,手动拔掉一根网线,观察是否自动切换到另外一个网卡上去,网络是否仍是连通状态;等会拔掉另外一根网线再次观察网络连通性。