Постоянство Linux ifIndex для SNMP
Мы используем OpManager для мониторинга интерфейсных устройств на удаленных Linux-блоках. В этих блоках есть сети VLAN, которые мы используем для сбора информации о сетях, соединяемых с блоками. Например, у нас есть eth0.2, eth0.3, eth0.12, eth0.13, eth0.22, eth0.23 (соответствующие vlans 2,3,12,13,22,23 соответственно).
Мы используем SNMP на управляющем IP-адресе, чтобы проверить и убедиться, что интерфейсы работают. Однако мы сталкиваемся с проблемой изменения индексов интерфейса, если нам нужно перезапустить сетевой сервис. Мы получим сообщения об ошибках, такие как:
Интерфейс 'eth0.23 - eth0.23' отключен. Описание интерфейса - "eth0.23", индекс - 11. Идентификатор канала не настроен.
Хотя интерфейс работает и работает.
Как мы можем изменить значения индекса, чтобы быть постоянными через перезагрузки. Мы видели это, если мы изменили интерфейс со статического IP-адреса на динамический.
2 ответа
Короткий ответ: для RFC SNMP не требуется постоянство 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 для получения значения SIOCGIFINDEX из ядра Linux.
Когда я столкнулся с такой проблемой в системе мониторинга на основе SNMP, я использовал альтернативные средства для ссылки на сетевые интерфейсы. В частности, я использовал имя интерфейса вместо номера индекса интерфейса (например, "eth0", "eth1", "vlan150" и т. Д.).
Вы можете подумать об использовании if_indextoname(index_val, index_name). Где index_val имеет тип unsigned int, а index_name имеет тип char *.
Передайте index_val, и ядро linux отобразит его на правильное имя index_name, которое вы можете использовать в своем коде, так как index_name одинаково при перезагрузках.