Назад | Перейти на главную страницу

Постоянство ifIndex в Linux для 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-адреса на динамический.

Короткий ответ: 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 имеет тип int без знака, а index_name имеет тип char *.

Передайте index_val, и ядро ​​linux сопоставит его с правильным index_name, которое вы можете использовать в своем коде, поскольку index_name одинаково при перезагрузках.