437 lines
27 KiB
YAML
437 lines
27 KiB
YAML
- name: osd_network
|
||
type: string or array of strings
|
||
type_ru: строка или массив строк
|
||
info: |
|
||
Network mask of public OSD network(s) (IPv4 or IPv6). Each OSD listens to all
|
||
addresses of UP + RUNNING interfaces matching one of these networks, on the
|
||
same port. Port is auto-selected except if [bind_port](osd.en.md#bind_port) is
|
||
explicitly specified. Bind address(es) may also be overridden manually by
|
||
specifying [bind_address](osd.en.md#bind_address). If OSD networks are not specified
|
||
at all, OSD just listens to a wildcard address (0.0.0.0).
|
||
info_ru: |
|
||
Маски подсетей (IPv4 или IPv6) публичной сети или сетей OSD. Каждый OSD слушает
|
||
один и тот же порт на всех адресах поднятых (UP + RUNNING) сетевых интерфейсов,
|
||
соответствующих одной из указанных сетей. Порт выбирается автоматически, если
|
||
только [bind_port](osd.ru.md#bind_port) не задан явно. Адреса для подключений можно
|
||
также переопределить явно, задав [bind_address](osd.ru.md#bind_address). Если сети OSD
|
||
не заданы вообще, OSD слушает все адреса (0.0.0.0).
|
||
- name: osd_cluster_network
|
||
type: string or array of strings
|
||
type_ru: строка или массив строк
|
||
info: |
|
||
Network mask of separate network(s) (IPv4 or IPv6) to use for OSD
|
||
cluster connections. I.e. OSDs will always attempt to use these networks
|
||
to connect to other OSDs, while clients will attempt to use networks from
|
||
[osd_network](#osd_network).
|
||
info_ru: |
|
||
Маски подсетей (IPv4 или IPv6) отдельной кластерной сети или сетей OSD.
|
||
То есть, OSD будут всегда стараться использовать эти сети для соединений
|
||
с другими OSD, а клиенты будут стараться использовать сети из [osd_network](#osd_network).
|
||
- name: use_rdma
|
||
type: bool
|
||
default: true
|
||
info: |
|
||
Try to use RDMA through libibverbs for communication if it's available.
|
||
Disable if you don't want Vitastor to use RDMA. TCP-only clients can also
|
||
talk to an RDMA-enabled cluster, so disabling RDMA may be needed if clients
|
||
have RDMA devices, but they are not connected to the cluster.
|
||
|
||
`use_rdma` works with RoCEv1/RoCEv2 networks, but not with iWARP and,
|
||
maybe, with some Infiniband configurations which require RDMA-CM.
|
||
Consider `use_rdmacm` for such networks.
|
||
info_ru: |
|
||
Попробовать использовать RDMA через libibverbs для связи при наличии
|
||
доступных устройств. Отключите, если вы не хотите, чтобы Vitastor
|
||
использовал RDMA. TCP-клиенты также могут работать с RDMA-кластером,
|
||
так что отключать RDMA может быть нужно, только если у клиентов есть
|
||
RDMA-устройства, но они не имеют соединения с кластером Vitastor.
|
||
|
||
`use_rdma` работает с RoCEv1/RoCEv2 сетями, но не работает с iWARP и
|
||
может не работать с частью конфигураций Infiniband, требующих RDMA-CM.
|
||
Рассмотрите включение `use_rdmacm` для таких сетей.
|
||
- name: use_rdmacm
|
||
type: bool
|
||
default: true
|
||
info: |
|
||
Use an alternative implementation of RDMA through RDMA-CM (Connection
|
||
Manager). Works with all RDMA networks: Infiniband, iWARP and
|
||
RoCEv1/RoCEv2, and even allows to disable TCP and run only with RDMA.
|
||
OSDs always use random port numbers for RDMA-CM listeners, different
|
||
from their TCP ports. `use_rdma` is automatically disabled when
|
||
`use_rdmacm` is enabled.
|
||
info_ru: |
|
||
Использовать альтернативную реализацию RDMA на основе RDMA-CM (Connection
|
||
Manager). Работает со всеми типами RDMA-сетей: Infiniband, iWARP и
|
||
RoCEv1/RoCEv2, и даже позволяет полностью отключить TCP и работать
|
||
только на RDMA. OSD используют случайные номера портов для ожидания
|
||
соединений через RDMA-CM, отличающиеся от их TCP-портов. Также при
|
||
включении `use_rdmacm` автоматически отключается опция `use_rdma`.
|
||
- name: disable_tcp
|
||
type: bool
|
||
default: true
|
||
info: |
|
||
Fully disable TCP and only use RDMA-CM for OSD communication.
|
||
info_ru: |
|
||
Полностью отключить TCP и использовать только RDMA-CM для соединений с OSD.
|
||
- name: rdma_device
|
||
type: string
|
||
info: |
|
||
RDMA device name to use for Vitastor OSD communications (for example,
|
||
"rocep5s0f0"). If not specified, Vitastor will try to find an RoCE
|
||
device matching [osd_network](osd.en.md#osd_network), preferring RoCEv2,
|
||
or choose the first available RDMA device if no RoCE devices are
|
||
found or if `osd_network` is not specified. Auto-selection is also
|
||
unsupported with old libibverbs < v32, like in Debian 10 Buster or
|
||
CentOS 7.
|
||
|
||
Vitastor supports all adapters, even ones without ODP support, like
|
||
Mellanox ConnectX-3 and non-Mellanox cards. Versions up to Vitastor
|
||
1.2.0 required ODP which is only present in Mellanox ConnectX >= 4.
|
||
See also [rdma_odp](#rdma_odp).
|
||
|
||
Run `ibv_devinfo -v` as root to list available RDMA devices and their
|
||
features.
|
||
|
||
Remember that you also have to configure your network switches if you use
|
||
RoCE/RoCEv2, otherwise you may experience unstable performance. Refer to
|
||
the manual of your network vendor for details about setting up the switch
|
||
for RoCEv2 correctly. Usually it means setting up Lossless Ethernet with
|
||
PFC (Priority Flow Control) and ECN (Explicit Congestion Notification).
|
||
info_ru: |
|
||
Название RDMA-устройства для связи с Vitastor OSD (например, "rocep5s0f0").
|
||
Если не указано, Vitastor попробует найти RoCE-устройство, соответствующее
|
||
[osd_network](osd.en.md#osd_network), предпочитая RoCEv2, или выбрать первое
|
||
попавшееся RDMA-устройство, если RoCE-устройств нет или если сеть `osd_network`
|
||
не задана. Также автовыбор не поддерживается со старыми версиями библиотеки
|
||
libibverbs < v32, например в Debian 10 Buster или CentOS 7.
|
||
|
||
Vitastor поддерживает все модели адаптеров, включая те, у которых
|
||
нет поддержки ODP, то есть вы можете использовать RDMA с ConnectX-3 и
|
||
картами производства не Mellanox. Версии Vitastor до 1.2.0 включительно
|
||
требовали ODP, который есть только на Mellanox ConnectX 4 и более новых.
|
||
См. также [rdma_odp](#rdma_odp).
|
||
|
||
Запустите `ibv_devinfo -v` от имени суперпользователя, чтобы посмотреть
|
||
список доступных RDMA-устройств, их параметры и возможности.
|
||
|
||
Обратите внимание, что если вы используете RoCE/RoCEv2, вам также необходимо
|
||
правильно настроить для него коммутаторы, иначе вы можете столкнуться с
|
||
нестабильной производительностью. Подробную информацию о настройке
|
||
коммутатора для RoCEv2 ищите в документации производителя. Обычно это
|
||
подразумевает настройку сети без потерь на основе PFC (Priority Flow
|
||
Control) и ECN (Explicit Congestion Notification).
|
||
- name: rdma_port_num
|
||
type: int
|
||
info: |
|
||
RDMA device port number to use. Only for devices that have more than 1 port.
|
||
See `phys_port_cnt` in `ibv_devinfo -v` output to determine how many ports
|
||
your device has.
|
||
|
||
Not relevant for RDMA-CM (use_rdmacm).
|
||
info_ru: |
|
||
Номер порта RDMA-устройства, который следует использовать. Имеет смысл
|
||
только для устройств, у которых более 1 порта. Чтобы узнать, сколько портов
|
||
у вашего адаптера, посмотрите `phys_port_cnt` в выводе команды
|
||
`ibv_devinfo -v`.
|
||
|
||
Опция неприменима к RDMA-CM (use_rdmacm).
|
||
- name: rdma_gid_index
|
||
type: int
|
||
info: |
|
||
Global address identifier index of the RDMA device to use. Different GID
|
||
indexes may correspond to different protocols like RoCEv1, RoCEv2 and iWARP.
|
||
Search for "GID" in `ibv_devinfo -v` output to determine which GID index
|
||
you need.
|
||
|
||
If not specified, Vitastor will try to auto-select a RoCEv2 IPv4 GID, then
|
||
RoCEv2 IPv6 GID, then RoCEv1 IPv4 GID, then RoCEv1 IPv6 GID, then IB GID.
|
||
GID auto-selection is unsupported with libibverbs < v32.
|
||
|
||
A correct rdma_gid_index for RoCEv2 is usually 1 (IPv6) or 3 (IPv4).
|
||
|
||
Not relevant for RDMA-CM (use_rdmacm).
|
||
info_ru: |
|
||
Номер глобального идентификатора адреса RDMA-устройства, который следует
|
||
использовать. Разным gid_index могут соответствовать разные протоколы связи:
|
||
RoCEv1, RoCEv2, iWARP. Чтобы понять, какой нужен вам - смотрите строчки со
|
||
словом "GID" в выводе команды `ibv_devinfo -v`.
|
||
|
||
Если не указан, Vitastor попробует автоматически выбрать сначала GID,
|
||
соответствующий RoCEv2 IPv4, потом RoCEv2 IPv6, потом RoCEv1 IPv4, потом
|
||
RoCEv1 IPv6, потом IB. Авто-выбор GID не поддерживается со старыми версиями
|
||
libibverbs < v32.
|
||
|
||
Правильный rdma_gid_index для RoCEv2, как правило, 1 (IPv6) или 3 (IPv4).
|
||
|
||
Опция неприменима к RDMA-CM (use_rdmacm).
|
||
- name: rdma_mtu
|
||
type: int
|
||
info: |
|
||
RDMA Path MTU to use. Must be 1024, 2048 or 4096. Default is to use the
|
||
RDMA device's MTU.
|
||
info_ru: |
|
||
Максимальная единица передачи (Path MTU) для RDMA. Должно быть равно 1024,
|
||
2048 или 4096. По умолчанию используется значение MTU RDMA-устройства.
|
||
- name: rdma_max_sge
|
||
type: int
|
||
default: 128
|
||
info: |
|
||
Maximum number of scatter/gather entries to use for RDMA. OSDs negotiate
|
||
the actual value when establishing connection anyway, so it's usually not
|
||
required to change this parameter.
|
||
info_ru: |
|
||
Максимальное число записей разделения/сборки (scatter/gather) для RDMA.
|
||
OSD в любом случае согласовывают реальное значение при установке соединения,
|
||
так что менять этот параметр обычно не нужно.
|
||
- name: rdma_max_msg
|
||
type: int
|
||
default: 132096
|
||
info: Maximum size of a single RDMA send or receive operation in bytes.
|
||
info_ru: Максимальный размер одной RDMA-операции отправки или приёма.
|
||
- name: rdma_max_recv
|
||
type: int
|
||
default: 16
|
||
info: |
|
||
Maximum number of RDMA receive buffers per connection (RDMA requires
|
||
preallocated buffers to receive data). Each buffer is `rdma_max_msg` bytes
|
||
in size. So this setting directly affects memory usage: a single Vitastor
|
||
RDMA client uses `rdma_max_recv * rdma_max_msg * OSD_COUNT` bytes of memory.
|
||
Default is roughly 2 MB * number of OSDs.
|
||
info_ru: |
|
||
Максимальное число буферов для RDMA-приёма данных на одно соединение
|
||
(RDMA требует заранее выделенных буферов для приёма данных). Каждый буфер
|
||
имеет размер `rdma_max_msg` байт. Таким образом, настройка прямо влияет на
|
||
потребление памяти - один Vitastor-клиент с RDMA использует
|
||
`rdma_max_recv * rdma_max_msg * ЧИСЛО_OSD` байт памяти, по умолчанию -
|
||
примерно 2 МБ * число OSD.
|
||
- name: rdma_max_send
|
||
type: int
|
||
default: 8
|
||
info: |
|
||
Maximum number of outstanding RDMA send operations per connection. Should be
|
||
less than `rdma_max_recv` so the receiving side doesn't run out of buffers.
|
||
Doesn't affect memory usage - additional memory isn't allocated for send
|
||
operations.
|
||
info_ru: |
|
||
Максимальное число RDMA-операций отправки, отправляемых в очередь одного
|
||
соединения. Желательно, чтобы оно было меньше `rdma_max_recv`, чтобы
|
||
у принимающей стороны в процессе работы не заканчивались буферы на приём.
|
||
Не влияет на потребление памяти - дополнительная память на операции отправки
|
||
не выделяется.
|
||
- name: rdma_odp
|
||
type: bool
|
||
default: false
|
||
online: false
|
||
info: |
|
||
Use RDMA with On-Demand Paging. ODP is currently only available on Mellanox
|
||
ConnectX-4 and newer adapters. ODP allows to not register memory explicitly
|
||
for RDMA adapter to be able to use it. This, in turn, allows to skip memory
|
||
copying during sending. One would think this should improve performance, but
|
||
**in reality** RDMA performance with ODP is **drastically** worse. Example
|
||
3-node cluster with 8 NVMe in each node and 2*25 GBit/s ConnectX-6 RDMA network
|
||
without ODP pushes 3950000 read iops, but only 239000 iops with ODP...
|
||
|
||
This happens because Mellanox ODP implementation seems to be based on
|
||
message retransmissions when the adapter doesn't know about the buffer yet -
|
||
it likely uses standard "RNR retransmissions" (RNR = receiver not ready)
|
||
which is generally slow in RDMA/RoCE networks. Here's a presentation about
|
||
it from ISPASS-2021 conference: https://tkygtr6.github.io/pub/ISPASS21_slides.pdf
|
||
|
||
ODP support is retained in the code just in case a good ODP implementation
|
||
appears one day.
|
||
info_ru: |
|
||
Использовать RDMA с On-Demand Paging. ODP - функция, доступная пока что
|
||
исключительно на адаптерах Mellanox ConnectX-4 и более новых. ODP позволяет
|
||
не регистрировать память для её использования RDMA-картой. Благодаря этому
|
||
можно не копировать данные при отправке их в сеть и, казалось бы, это должно
|
||
улучшать производительность - но **по факту** получается так, что
|
||
производительность только ухудшается, причём сильно. Пример - на 3-узловом
|
||
кластере с 8 NVMe в каждом узле и сетью 2*25 Гбит/с на чтение с RDMA без ODP
|
||
удаётся снять 3950000 iops, а с ODP - всего 239000 iops...
|
||
|
||
Это происходит из-за того, что реализация ODP у Mellanox неоптимальная и
|
||
основана на повторной передаче сообщений, когда карте не известен буфер -
|
||
вероятно, на стандартных "RNR retransmission" (RNR = receiver not ready).
|
||
А данные повторные передачи в RDMA/RoCE - всегда очень медленная штука.
|
||
Презентация на эту тему с конференции ISPASS-2021: https://tkygtr6.github.io/pub/ISPASS21_slides.pdf
|
||
|
||
Возможность использования ODP сохранена в коде на случай, если вдруг в один
|
||
прекрасный день появится хорошая реализация ODP.
|
||
- name: peer_connect_interval
|
||
type: sec
|
||
min: 1
|
||
default: 5
|
||
online: true
|
||
info: Interval before attempting to reconnect to an unavailable OSD.
|
||
info_ru: Время ожидания перед повторной попыткой соединиться с недоступным OSD.
|
||
- name: peer_connect_timeout
|
||
type: sec
|
||
min: 1
|
||
default: 5
|
||
online: true
|
||
info: Timeout for OSD connection attempts.
|
||
info_ru: Максимальное время ожидания попытки соединения с OSD.
|
||
- name: osd_idle_timeout
|
||
type: sec
|
||
min: 1
|
||
default: 5
|
||
online: true
|
||
info: |
|
||
OSD connection inactivity time after which clients and other OSDs send
|
||
keepalive requests to check state of the connection.
|
||
info_ru: |
|
||
Время неактивности соединения с OSD, после которого клиенты или другие OSD
|
||
посылают запрос проверки состояния соединения.
|
||
- name: osd_ping_timeout
|
||
type: sec
|
||
min: 1
|
||
default: 5
|
||
online: true
|
||
info: |
|
||
Maximum time to wait for OSD keepalive responses. If an OSD doesn't respond
|
||
within this time, the connection to it is dropped and a reconnection attempt
|
||
is scheduled.
|
||
info_ru: |
|
||
Максимальное время ожидания ответа на запрос проверки состояния соединения.
|
||
Если OSD не отвечает за это время, соединение отключается и производится
|
||
повторная попытка соединения.
|
||
- name: max_etcd_attempts
|
||
type: int
|
||
default: 5
|
||
online: true
|
||
info: |
|
||
Maximum number of attempts for etcd requests which can't be retried
|
||
indefinitely.
|
||
info_ru: |
|
||
Максимальное число попыток выполнения запросов к etcd для тех запросов,
|
||
которые нельзя повторять бесконечно.
|
||
- name: etcd_quick_timeout
|
||
type: ms
|
||
default: 1000
|
||
online: true
|
||
info: |
|
||
Timeout for etcd requests which should complete quickly, like lease refresh.
|
||
info_ru: |
|
||
Максимальное время выполнения запросов к etcd, которые должны завершаться
|
||
быстро, таких, как обновление резервации (lease).
|
||
- name: etcd_slow_timeout
|
||
type: ms
|
||
default: 5000
|
||
online: true
|
||
info: Timeout for etcd requests which are allowed to wait for some time.
|
||
info_ru: |
|
||
Максимальное время выполнения запросов к etcd, для которых не обязательно
|
||
гарантировать быстрое выполнение.
|
||
- name: etcd_keepalive_timeout
|
||
type: sec
|
||
default: max(30, etcd_report_interval*2)
|
||
online: true
|
||
info: |
|
||
Timeout for etcd connection HTTP Keep-Alive. Should be higher than
|
||
etcd_report_interval to guarantee that keepalive actually works.
|
||
info_ru: |
|
||
Таймаут для HTTP Keep-Alive в соединениях к etcd. Должен быть больше, чем
|
||
etcd_report_interval, чтобы keepalive гарантированно работал.
|
||
- name: etcd_ws_keepalive_interval
|
||
type: sec
|
||
default: 5
|
||
online: true
|
||
info: |
|
||
etcd websocket ping interval required to keep the connection alive and
|
||
detect disconnections quickly.
|
||
info_ru: |
|
||
Интервал проверки живости вебсокет-подключений к etcd.
|
||
- name: etcd_min_reload_interval
|
||
type: ms
|
||
default: 1000
|
||
online: true
|
||
info: |
|
||
Minimum interval for full etcd state reload. Introduced to prevent
|
||
excessive load on etcd during outages when etcd can't keep up with event
|
||
streams and cancels them.
|
||
info_ru: |
|
||
Минимальный интервал полной перезагрузки состояния из etcd. Добавлено для
|
||
предотвращения избыточной нагрузки на etcd во время отказов, когда etcd не
|
||
успевает рассылать потоки событий и отменяет их.
|
||
- name: tcp_header_buffer_size
|
||
type: int
|
||
default: 65536
|
||
info: |
|
||
Size of the buffer used to read data using an additional copy. Vitastor
|
||
packet headers are 128 bytes, payload is always at least 4 KB, so it is
|
||
usually beneficial to try to read multiple packets at once even though
|
||
it requires to copy the data an additional time. The rest of each packet
|
||
is received without an additional copy. You can try to play with this
|
||
parameter and see how it affects random iops and linear bandwidth if you
|
||
want.
|
||
info_ru: |
|
||
Размер буфера для чтения данных с дополнительным копированием. Пакеты
|
||
Vitastor содержат 128-байтные заголовки, за которыми следуют данные размером
|
||
от 4 КБ и для мелких операций ввода-вывода обычно выгодно за 1 вызов читать
|
||
сразу несколько пакетов, даже не смотря на то, что это требует лишний раз
|
||
скопировать данные. Часть каждого пакета за пределами значения данного
|
||
параметра читается без дополнительного копирования. Вы можете попробовать
|
||
поменять этот параметр и посмотреть, как он влияет на производительность
|
||
случайного и линейного доступа.
|
||
- name: min_zerocopy_send_size
|
||
type: int
|
||
default: 32768
|
||
info: |
|
||
OSDs and clients will attempt to use io_uring-based zero-copy TCP send
|
||
for buffers larger than this number of bytes. Zero-copy send with io_uring is
|
||
supported since Linux kernel version 6.1. Support is auto-detected and disabled
|
||
automatically when not available. It can also be disabled explicitly by setting
|
||
this parameter to a negative value.
|
||
|
||
⚠️ Warning! Zero-copy send performance may vary greatly from CPU to CPU and from
|
||
one kernel version to another. Generally, it tends to only make benefit with larger
|
||
messages. With smaller messages (say, 4 KB), it may actually be slower. 32 KB is
|
||
enough for almost all CPUs, but even smaller values are optimal for some of them.
|
||
For example, 4 KB is OK for EPYC Milan/Genoa and 12 KB is OK for Xeon Ice Lake
|
||
(but verify it yourself please).
|
||
|
||
Verification instructions:
|
||
1. Add `iommu=pt` into your Linux kernel command line and reboot.
|
||
2. Upgrade your kernel. For example, it's very important to use 6.11+ with recent AMD EPYCs.
|
||
3. Run some tests with the [send-zerocopy liburing example](https://github.com/axboe/liburing/blob/master/examples/send-zerocopy.c)
|
||
to find the minimal message size for which zero-copy is optimal.
|
||
Use `./send-zerocopy tcp -4 -R` at the server side and
|
||
`time ./send-zerocopy tcp -4 -b 0 -s BUFFER_SIZE -D SERVER_IP` at the client side with
|
||
`-z 0` (no zero-copy) and `-z 1` (zero-copy), and compare MB/s and used CPU time
|
||
(user+system).
|
||
info_ru: |
|
||
OSD и клиенты будут пробовать использовать TCP-отправку без копирования (zero-copy) на
|
||
основе io_uring для буферов, больших, чем это число байт. Отправка без копирования
|
||
поддерживается в io_uring, начиная с версии ядра Linux 6.1. Наличие поддержки
|
||
проверяется автоматически и zero-copy отключается, когда поддержки нет. Также
|
||
её можно отключить явно, установив данный параметр в отрицательное значение.
|
||
|
||
⚠️ Внимание! Производительность данной функции может сильно отличаться на разных
|
||
процессорах и на разных версиях ядра Linux. В целом, zero-copy обычно быстрее с
|
||
большими сообщениями, а с мелкими (например, 4 КБ) zero-copy может быть даже
|
||
медленнее. 32 КБ достаточно почти для всех процессоров, но для каких-то можно
|
||
использовать даже меньшие значения. Например, для EPYC Milan/Genoa подходит 4 КБ,
|
||
а для Xeon Ice Lake - 12 КБ (но, пожалуйста, перепроверьте это сами).
|
||
|
||
Инструкция по проверке:
|
||
1. Добавьте `iommu=pt` в командную строку загрузки вашего ядра Linux и перезагрузитесь.
|
||
2. Обновите ядро. Например, для AMD EPYC очень важно использовать версию 6.11+.
|
||
3. Позапускайте тесты с помощью [send-zerocopy из примеров liburing](https://github.com/axboe/liburing/blob/master/examples/send-zerocopy.c),
|
||
чтобы найти минимальный размер сообщения, для которого zero-copy отправка оптимальна.
|
||
Запускайте `./send-zerocopy tcp -4 -R` на стороне сервера и
|
||
`time ./send-zerocopy tcp -4 -b 0 -s РАЗМЕР_БУФЕРА -D АДРЕС_СЕРВЕРА` на стороне клиента
|
||
с опцией `-z 0` (обычная отправка) и `-z 1` (отправка без копирования), и сравнивайте
|
||
скорость в МБ/с и занятое процессорное время (user+system).
|
||
- name: use_sync_send_recv
|
||
type: bool
|
||
default: false
|
||
info: |
|
||
If true, synchronous send/recv syscalls are used instead of io_uring for
|
||
socket communication. Useless for OSDs because they require io_uring anyway,
|
||
but may be required for clients with old kernel versions.
|
||
info_ru: |
|
||
Если установлено в истину, то вместо io_uring для передачи данных по сети
|
||
будут использоваться обычные синхронные системные вызовы send/recv. Для OSD
|
||
это бессмысленно, так как OSD в любом случае нуждается в io_uring, но, в
|
||
принципе, это может применяться для клиентов со старыми версиями ядра.
|