用于 SNMP 的 Linux ifIndex 持久性

jin*_*wow 5 networking linux snmp

我们正在使用 OpManager 来监控远程 linux 机器上的接口设备。这些盒子有 VLAN,我们用它来收集有关正在中继到盒子的网络的信息。例如我们有 eth0.2, eth0.3, eth0.12, eth0.13, eth0.22, eth0.23(分别对应于 vlan 2、3、12、13、22、23)。

我们在管理 IP 地址上使用 SNMP 来检查并确保接口已启动。但是,如果我们必须重新启动网络服务,我们会遇到接口索引更改的问题。我们会收到如下错误信息:

接口“eth0.23 - eth0.23”已关闭。接口描述为“eth0.23”,索引为 11。未配置电路 ID。

即使界面已启动并正在运行。

我们如何通过重新启动将索引值更改为持久性。如果我们也将接口从静态 IP 更改为动态,我们已经看到了这一点。

chu*_*ckx 6

简而言之,SNMP RFC 不需要网络管理器重新初始化之间的 ifIndex 持久性。net-snmp 不提供任何特殊工具来提供此功能。

来自 RFC 2863:

接口的 ifIndex 值的恒定性(在重新初始化之间)的要求是通过要求在一个接口被动态删除后,它的 ifIndex 值不会被另一个动态添加的接口重新使用,直到在以下重新初始化之后网络管理系统。

要点是当系统重新初始化(即重新启动)时,明确允许 ifIndex 条目用于任何接口。

从 Linux 内核 (net/core/dev.c):

static int dev_new_index(struct net *net)
{
    static int ifindex;
    for (;;) {
        if (++ifindex <= 0)
            ifindex = 1;
        if (!__dev_get_by_index(net, ifindex))
            return ifindex;
    }
}
Run Code Online (Sandbox Code Playgroud)

内核中的 ifindex 分配使用简单的增量算法。这是相关的,因为在 net-snmp (agent/mibgroup/if-mib/data_access/interface_ioctl.c) 中:

oid
netsnmp_access_interface_ioctl_ifindex_get(int fd, const char *name)
{
#ifndef SIOCGIFINDEX
    return 0;
#else
    struct ifreq    ifrq;
    int rc = 0;

    DEBUGMSGTL(("access:interface:ioctl", "ifindex_get\n"));

    rc = _ioctl_get(fd, SIOCGIFINDEX, &ifrq, name);
    if (rc < 0) {
        DEBUGMSGTL(("access:interface:ioctl",
                   "ifindex_get error on inerface '%s'\n", name));
        return 0;
    }

    return ifrq.ifr_ifindex;
#endif /* SIOCGIFINDEX */
}
Run Code Online (Sandbox Code Playgroud)

这个函数最终被调用来填充 ifindex,它只是使用 IOCTL 接口从 Linux 内核检索 SIOCGIFINDEX 值。

当我使用基于 SNMP 的监控系统遇到这种性质的问题时,我最终使用了另一种方法来引用网络接口。特别是,我使用了接口名称而不是接口索引号(即“eth0”、“eth1”、“vlan150”等)。