用於 SNMP 的 Linux ifIndex 持久性
我們正在使用 OpManager 來監控遠端 linux 機器上的介面設備。這些盒子有 VLAN,我們使用這些 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 更改為動態,我們已經看到了這一點。
簡短的回答,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”等)。