`
hulianwang2014
  • 浏览: 725932 次
文章分类
社区版块
存档分类
最新评论
  • bcworld: 排版成这样,一点看的欲望都没有了
    jfinal

Linux bonding的初始状态问题以及解决

 
阅读更多

问题:

启动一个bonding网卡,往其里面添加两个根本就没有插着网线的网卡,拉起该bonding后,ifconfig发现其有RUNNING标志,然后将其一个slave插上网线再拔掉,ifconfig就没有RUNNING标志了。

分析:

这个问题实际上无伤大雅,只是在第一次欺骗一下OS而已,然而却会影响到keepalived的track_interfaces配置,进而影响基于VRRP的热备切换,导致拥有没有插着网线的机器的热备组中的若干台机器一旦重启,其热备状态就会混乱。没有插线的机器无论如何也不能是MASTER,可是keepalived看到了bonding网卡的RUNNING标志,误认为其已经可以使用,进而可能成为MASTER状态。

解析与修正:

如果仅仅为了短平快的解决当下问题,那么最简单不过的就是将keepalived中基于RUNNING的判断换成基于LOWER_UP的判断,LOWER_UP就是标识网卡有没有插线的(但不绝对,还可能受别的因素影响,但是大多数情况-显然并非全部情况下可以这么认为),事实证明这是完全可以的,问题解决了。但是却违反了track_interfaces的初衷,因此这种改法不好!
在彻底修正这个问题之前还是需要了解网卡的各种状态以及层次。总体来讲,网卡state分为管理state和操作state。
管理state:这个状态是自上而下配置的,表示管理员的意愿
操作state:这个state是网卡自身现状,表示网卡目前是否已经准备好并且有能力为用户服务。

现在看看Linux系统中网卡的各种state:
IFF_LOWER_UP-线缆已经接好且上电
IFF_RUNNING-操作state是UP(那么什么时候操作state会是DOWN呢?1.在管理state为DOWN的时候,即管理员用命令down了网卡;2.网卡没有插线

理解了这些状态之后,即使没有keepalived,状态也不会,这就不是热备切换的问题了,keepalived并没有错,即便是修正了keepalived,那么bonding还是会影响到其它使用它的程序的...正是bonding驱动的bug导致了状态判断错误。
bond_open的返回值是0,因此bonding网卡默认就是START状态的,因为在物理网卡enslave进bonding网卡的时候需要bonding网卡是IF_UP状态的。可以在bond_enslave的最后看到一个频繁调用的函数:bond_set_carrier。该函数判断bonding网卡的所有slave的状态,如果全部为DOWN,则将bonding本身也设置成DOWN。这应该是一个周期调用的函数,调用周期取决于bonding的miimon参数,另外在几个关键点也会调用bond_set_carrier,比如在新的slave被bongding的时候,即调用bond_enslave的时候。基本上bond_set_carrier的逻辑是这样的:
static int bond_set_carrier(struct bonding *bond)
{
    struct slave *slave;
    int i;

    if (bond->slave_cnt == 0)
        goto down;

    if (bond->params.mode == BOND_MODE_8023AD)
        return bond_3ad_set_carrier(bond);
//遍历所有的slave,只要有一个UP,那么bonding就UP
    bond_for_each_slave(bond, slave, i) {
        if (slave->link == BOND_LINK_UP) {
            if (!netif_carrier_ok(bond->dev)) {
                netif_carrier_on(bond->dev);
                return 1;
            }
            return 0;
        }
    }

down:
    if (netif_carrier_ok(bond->dev)) {
        netif_carrier_off(bond->dev);
        return 1;
    }
    return 0;
}

没有任何问题。在周期性检测中,会设置所有slave的状态:
bond_for_each_slave(bond, slave, i) {
        slave->new_link = BOND_LINK_NOCHANGE;

        link_state = bond_check_dev_link(bond, slave->dev, 0);

        switch (slave->link) {
        case BOND_LINK_UP:
            if (link_state)
                continue;
             //将状态设置为FAIL,此后再调用bond_set_carrier时可能会off掉bonding网卡
            slave->link = BOND_LINK_FAIL;
...

到底哪里出了问题??为何一块物理网卡明明是没有插线的,却没有调到bond_set_carrier最后面的netif_carrier_off,原因很显然了,因为netif_carrier_ok判断没有通过,为何没有通过,原因在于bonding自创建之日,其state根本就没有涉及__LINK_STATE_NOCARRIER这个bit的初始化!什么?这等错误竟然在内核里面出现!改了它便是,在bond_open的最后,return 0之前,加上一句:
netif_carrier_on(bond->dev);

即可修正这个错误。另外要修改的是bond_set_carrier函数:
if (bond->slave_cnt == 0)
        goto down;
如果slave_cnt为0,那么就要调用netif_carrier_on将bonding拉起来,以便于后面往其加入新的slave,那么上述语句改为:
if (bond->slave_cnt == 0) {
        netif_carrier_on(bond->dev)
        goto down;
}

关于这个修改,我只是为了保险起见,实质上并无必要,到底有没有必要进行这个修改,我并没有实测过,话说只要初始状态正确,后面的只是按照既有的逻辑来过,不可能有任何问题,话虽如此,可我还是不信任kernel社区的这帮人,要不然怎么会忘记初始化carrier状态呢?

插曲:

这个问题是我项目中遇到的,因为要赶工期,领导决定先把这个问题放一下,抓紧主要问题解决,我因此也和领导有了一次冲突,因为我觉得做一个产品,真的就需要完美无缺,不能有遗留问题等到用户真的需要的时候再解决,宁可延期也要完美,这是我的逻辑,至于说我为何没有把这事情分发下去,是因为到了产品发布的最后关头,正如领导说的,谁熟悉什么谁做什么,我自认为在项目组对网络,对kernel比较熟悉,因此这个问题只有我能快速解决,如果说我因为解决这个问题而耽误了项目进度,那是我的错,因此我选择在工作时间外加班解决它,这是我回到家里搞定的,也只能这样才能保证产品的按期发布。关键问题是,到底应该以产品发布的时间点为准呢还是应该以产品的完美程度为准。我选择后者,你们呢?


分享到:
评论

相关推荐

    linux双网卡绑定

    在Linux系统中,双网卡绑定(Bonding)是一种网络冗余和负载均衡技术,它允许将多个物理网络接口(NICs,Network Interface Controllers)组合为一个逻辑接口,以提高网络连接的可靠性或带宽。这通常应用于服务器...

    linux文档收集综合班(基础命令+常见应用).docx

    本文档主要涵盖了Linux网络配置、内核参数调整、端口管理以及远程访问等多个方面,以下是对这些知识点的详细说明: 1. **网卡子接口配置**: Linux系统允许在一个物理网卡上创建多个逻辑接口,即子接口,以实现...

    HeartBeat在 Linux的配置

    HeartBeat是Linux环境中的一种高可用性(High Availability, HA)解决方案,主要用于监控系统服务和网络资源,当检测到节点故障时,它能自动将服务从失效节点转移至其他正常节点,确保服务的连续性和可靠性。在Linux上...

    Linu运维工程师道面试题完整版.docx

    Linux运维工程师面试题涵盖了...这些面试题展示了Linux运维工程师应具备的基本技能,包括对系统操作、网络配置、文件管理、命令行工具的熟悉程度,以及问题解决和调试能力。熟悉这些知识点对于Linux运维工作至关重要。

    全用户态服务开发套件F-Stack.pdf

    Stack是一款全面的用户态服务开发套件,旨在解决数据服务快速增长带来的挑战,特别是针对CDN(内容分发网络)和RTMP(实时传输协议)等服务流量以及DDoS(分布式拒绝服务)和CC(Challenge Collapsar)攻击的问题。...

    Linu运维工程师道面试题完整版.pdf

    可以使用`who -r`或`runlevel`命令来查看Linux服务器当前的运行级别,这反映了系统的运行状态,如单用户模式、多用户无图形界面模式(运行级别3)和多用户带图形界面模式(运行级别5)。 2. **查看默认网关**: ...

    team_mode_random.rar_random_random.c

    在Linux内核驱动程序开发中,`team`模块是一个用于网络接口聚合(NIC bonding)的工具,它允许多个网络接口组合在一起,以提高网络连接的可靠性和带宽。标题中的"team_mode_random.rar_random_random.c"暗示我们关注...

    Newstartha 配置技巧

    随着信息技术的飞速发展以及企业对于业务连续性和服务质量的要求日益提升,高可用性(High Availability, HA)产品的需求也在不断增长。Newstart HA作为一款优秀的高可用性解决方案,在业界的应用变得越来越广泛。...

    基于RHEL5.4或者5.10的11gRAC(11.2.0.4)安装.docx

    在本文中,我们将深入探讨如何在Red Hat Enterprise Linux (RHEL) 5.4或5.10上安装Oracle 11g Real Application Clusters (RAC) 11.2.0.4。Oracle RAC是一种高可用性解决方案,它允许多台服务器共享同一数据库实例,...

    MySQL数据库双机热备服务器配置.docx

    这种配置通常涉及到两台服务器,它们共享同一份数据库,并通过心跳机制监控彼此的状态,以实现故障切换。以下是对整个配置过程的详细说明: 1. **平台整体拓扑结构**: - 两台Linux服务器通过以太网卡连接到网络,...

    openvswitch用户层处理详解流程

    例如,在 `dpif_linux.c` 中定义的 `dpif_linux_execute()` 函数创建一个 OVS_PACKET_CMD_EXECUTE 类型的 nlmsg,并调用 `nl_sock_transact()` 发送给数据平面。 ##### 3.3 配置更新 - **bridge_init()**:初始化 ...

    bt蓝牙hid协议.zip

    4. **HID控制通道**:HID协议支持一个控制通道,用于初始化设备、获取设备状态、配置设备参数等操作。例如,主机可以通过控制通道发送 HID 控制命令来唤醒或休眠设备。 5. **中断数据通道**:中断通道用于传输HID...

    超聚变试题(2).docx

    在Redhat 7.X系统中,可以通过命令`cat /etc/net/bonding/bondX`来查看主备端口的配置以及当前端口的状态。这对于网络管理员来说是非常有用的工具,可以帮助他们更好地管理和配置网络连接。 ### 15. 服务器风扇的...

    Bond网卡配置

    在Linux环境下,Bond配置主要通过编辑`/etc/modprobe.conf`和`/etc/sysconfig/network-scripts/`目录下的相关配置文件来实现。 ##### 1. `/etc/modprobe.conf` 此文件用于定义Bond驱动的基本参数: ```bash alias...

    Android_bluetooth

    - **简介**:Linux操作系统下的蓝牙协议栈,为Android蓝牙功能提供了底层支持。 - **功能**: - 管理蓝牙设备的连接。 - 提供蓝牙协议栈的实现。 - 支持蓝牙配置文件如HSP/HFP。 ##### 7. AIDL (Android ...

Global site tag (gtag.js) - Google Analytics