SNMP 的 Linux ifIndex 持久性

SNMP 的 Linux ifIndex 持久性

我们使用 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 更改为动态 IP,我们也看到了这一点。

答案1

简而言之,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;
    }
}

内核中的 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 */
}

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

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

答案2

您可以考虑使用 if_indextoname(index_val, index_name)。其中 index_val 为 unsigned int 类型,index_name 为 char * 类型。

传递 index_val 并且 Linux 内核会将其映射到正确的 index_name,您可以在代码中使用它,因为 index_name 在重启后是相同的。

相关内容