+7 (495) 788 99 99
Публикация  |  6 Августа 2024

Нагрузочное тестирование EVPN-MPLS на маршрутизаторах MR-381 от B4COM. Методика, результаты и выводы

Нагрузочное тестирование EVPN-MPLS на маршрутизаторах MR-381 от B4COM. Методика, результаты и выводы

Наш эксперт, Сергей Бочарников, опубликовал на Хабре практическую статью, в которой поделился опытом проведения нагрузочного тестирования EVPN-MPLS на маршрутизаторах MR-381 от B4COM.

В конце 2023 года отечественный вендор B4com Tech анонсировал выпуск маршрутизаторов для провайдерского сегмента IP/MPLS. Среди новых моделей наше внимание привлекли те, которые поддерживают интерфейсы 100G, поскольку они стали стандартом подключения в современных центрах обработки данных (ЦОД).

В модельный ряд входят устройства MR-381 и MR-382, различающиеся интерфейсами, но построенные на одном чипе — Broadcom Qumran2C. Этот чип активно используется в таких маршрутизаторах, как Cisco NCS 5500/5700, Juniper ACX7000 и Edge-Core AGR400.

 

Программное обеспечение

На текущий момент используется B4comOS. Это операционная система, построенная изначально на OcNOS от IP Infusion, но с 2022 года полностью отделившаяся и развивающаяся самостоятельно.

Ниже — схема с описанием основных модулей, которые используются в ОС.

 

За время, пока я работаю с оборудованием этого вендора, не раз возникала потребность в подобной картинке. Например, периодически приходится обращаться к модулю HSL, который занимается программированием ASIC'а и, соответственно, может показывать информацию о FIB. Ещё интерес представляет модуль NSM, который отвечает за control-plane. Бывает так, что нужно и в него заглянуть. Поэтому хочется всё-таки не просто вводить какие-то команды и смотреть результаты вывода, а ещё и понимать, что происходит.

Первое наше знакомство с MR

С чипом мы уже знакомы и знаем его возможности. Но вопрос в том, как вендор смог адаптировать ASIC и насколько софт, скажем так, "сырой". В общем, в конце 2023 года мы взяли 2 коробки на тесты. Провели достаточно ограниченное тестирование на предмет использования этих маршрутизаторов в сети одного из наших заказчиков. Смотрели на базовый функционал: IS-IS, LDP, L3VPN (средствами MP-BGP VPNv4). Нагружали до 90 Gbps. Нашли мелкие нюансы, о которых знали заранее по работе с коммутаторами, и быстро их сами поправили. В целом, всё было нормально и без каких-либо подводных камней.

Однако следует понимать, что эти тесты были однобокими и удовлетворяли потребности только одного заказчика. А поскольку у нас их несколько, весной этого года возникла необходимость повторить тесты, но уже с более интересным и комплексным дизайном.

Речь идёт про EVPN-MPLS с Active-Active IRB и Anycast Gateway.

Тесты EVPN-MPLS

Топология

Наша тестовая среда включает два сегмента: EVPN-VXLAN и EVPN-MPLS.

 

Включения между сегментами выполнены для «проброса» двух сервисов: L3 и L2.

Для L3 используется стандартный Option-A, который с обоих сторон передаётся как type-5 EVPN, но на «стыке» разрывается и передаётся как чистый IPv4.

Пример конфигурации Option-A на PE и BL

Border-leaf

router bgp 300
!
address-family ipv4 vrf VRF-A
max-paths ebgp 2
neighbor 1.1.1.0 remote-as 500
neighbor 1.1.1.0 activate
no neighbor 1.1.1.0 send-community both
neighbor 1.1.1.2 remote-as 500
neighbor 1.1.1.2 activate
no neighbor 1.1.1.2 send-community both
neighbor 1.1.1.0 upd ate-source 1.1.1.1
neighbor 1.1.1.2 upd ate-source 1.1.1.3
exit-address-family
!
address-family ipv4 vrf VRF-B
max-paths ebgp 2
neighbor 2.2.2.0 remote-as 500
neighbor 2.2.2.0 activate
no neighbor 2.2.2.0 send-community both
neighbor 2.2.2.2 remote-as 500
neighbor 2.2.2.2 activate
no neighbor 2.2.2.2 send-community both
neighbor 2.2.2.0 update-source 2.2.2.1
neighbor 2.2.2.2 update-source 2.2.2.3
exit-address-family
!

PE

router bgp 500
!
address-family ipv4 vrf VRF-A
max-paths ebgp 2
neighbor 1.1.1.1 remote-as 300
neighbor 1.1.1.1 activate
neighbor 1.1.1.5 remote-as 301
neighbor 1.1.1.5 activate
neighbor 1.1.1.1 update-source 1.1.1.0
neighbor 1.1.1.5 update-source 1.1.1.4
exit-address-family
!
address-family ipv4 vrf VRF-B
max-paths ebgp 2
neighbor 2.2.2.1 remote-as 300
neighbor 2.2.2.1 activate
neighbor 2.2.2.5 remote-as 301
neighbor 2.2.2.5 activate
neighbor 2.2.2.1 update-source 2.2.2.0
neighbor 2.2.2.5 update-source 2.2.2.4
exit-address-family
!
exit
!

L2 включает более сложные сценарии. Оба сегмента используют EVPN-MH (EVPN Multi-Homing), можно назвать back-to-back evpn-mh (аналогично back-to-back vpc). Объединение выполнено в один общий LAG на 4 физических интерфейсах с разными ESI на парах.

Пример конфигурации L2 на PE и BL

Border-leaf

interface ce2
channel-group 1 mode active
lldp-agent
se t lldp port-id-tlv if-name
exit
!
interface po1
switchport
load-interval 30
mtu 9216
evpn multi-homed system-mac 0000.1111.bbbb
port-channel load-balance rtag7

PE

interface ce22 
channel‑group 1 mode active
lldp‑agent
se t lldp port‑id‑tlv if‑name
exit
!
interface po1 
switchport
load‑interval 30 
mtu 9216 
evpn multi‑homed system‑mac 0000.1111.aaaa
!

В стенде у нас 2500 таких растянутых L2-сетей, соответственно, такое же количество IRB-интерфейсов на обоих PE, всё это в режиме Active-Active с Anycast Gateway.

Пример конфигурации сервиса на PE

указываем MAC для AGW

evpn irb-forwarding anycast-gateway-mac 0011.2233.4455

создаём 2500 L2 сервисов

mac vrf vni_1000
rd 20.0.0.1:1000
route-target both 500:1000
...
mac vrf vni_3499
rd 20.0.0.1:3499
route-target both 500:3499

создаём 2500 интерфейсов

interface irb1000
ip vrf forwarding VRF-A
evpn irb-if-forwarding anycast-gateway-mac
ip address 30.0.0.1/24
...
interface irb3499
ip vrf forwarding VRF-A
evpn irb-if-forwarding anycast-gateway-mac
ip address 30.9.195.1/24

создаём 2500 evpn-id

evpn mpls id 1000
host-reachability-protocol evpn-bgp vni_1000
evpn irb irb1000
...
evpn mpls id 3499
host-reachability-protocol evpn-bgp vni_3499
evpn irb irb3499

создаём 2500 l2-subinterface

interface po1.1000 switchport
encapsulation dot1q 1000
rewrite pop
mtu 9216
access-if-evpn
map vpn-id 1000
...
interface po1.3499 switchport
encapsulation dot1q 3499
rewrite pop
mtu 9216
access-if-evpn
map vpn-id 3499

На BL настройка чуть проще, так как не требуется использовать IRB и L2-subinterface, растягиваем чистый L2 по EVPN-VXLAN домену.

Пример конфигурации сервиса на BL

создаём 2500 L2 сервисов

nvo vxlan id 11000 ingress-replication inner-vid-disabled
vxlan host-reachability-protocol evpn-bgp vni_11000
vni-name vni_11000
...
nvo vxlan id 13499 ingress-replication inner-vid-disabled
vxlan host-reachability-protocol evpn-bgp vni_13499
vni-name vni_13499

привязываем 2500 сервисов к целевому порту

nvo vxlan access-if port-vlan po1 1000
map vni-name vni_11000
...
nvo vxlan access-if port-vlan po1 3499
map vni-name vni_13499


Методика тестирования

Для генерации трафика использовался TRex.

В тесте запускались 2500 потоков, каждый с уникальным source IP и dot1q тегом, но общим destination IP. Это обеспечивает достаточную энтропию для балансировки и тестирует все 2500 IRB-интерфейсов, через которые маршрутизируется трафик.

Пример скрипта для генерации трафика

from trex_stl_lib.api import *
import argparse
import os

class STLS1(object):
def __init__(self):
self.mac_counter = 0 # Initialize a counter for generating MAC addresses

def generate_mac(self):
base_mac = [0x10, 0x70, 0x00, 0x00, 0x00, 0x00]
mac_suffix = self.mac_counter * 4096 # Increment by 4096 for each new MAC
for i in range(5, 1, -1):
base_mac[i] = mac_suffix & 0xFF
mac_suffix >>= 8
self.mac_counter += 1
return ':'.join('{:02x}'.format(b) for b in base_mac)

def create_stream(self, vlan_id, src_ip, src_mac, pkt_size=1400):
# Calculate the payload size needed to reach the desired packet size
header_size = len(Ether() / Dot1Q() / IP() / UDP())
payload_size = pkt_size - header_size
payload = 'x' * payload_size

return STLStream(
packet=STLPktBuilder(pkt=Ether(src=src_mac, dst="00:11:22:33:44:55") /
Dot1Q(prio=1, vlan=vlan_id) /
IP(src=src_ip, dst="10.200.0.5") /
UDP(dport=12, sport=1025) / payload),
mode=STLTXCont(pps=10),
# mac_dst_override_mode=STLStreamDstMAC_PKT # another way to explicitly take it
)

def get_streams(self, direction, tunables, **kwargs):
parser = argparse.ArgumentParser(description='Argparser for {}'.format(os.path.basename(__file__)),
formatter_class=argparse.ArgumentDefaultsHelpFormatter)

args = parser.parse_args(tunables)
streams = []
# Loop to generate streams for varying VLAN IDs and source IP addresses
vlan_id = 1000
for i in range(0, 10): # second octet range
for j in range(0, 256): # third octet range
src_ip = f"30.{i}.{j}.10"
src_mac = self.generate_mac()
streams.append(self.create_stream(vlan_id, src_ip, src_mac))
vlan_id += 1 # Increment VLAN ID for each stream
if vlan_id > 1010:
break
if vlan_id > 1010:
break
return streams

# dynamic load - used for trex console or simulator
def register():
return STLS1()


Сервис L2 растянут до хоста, а на PE (Provider Edge) этот сервис терминируется через IRB-интерфейсы. Конфигурации этих интерфейсов были описаны ранее.

Как видно из вышеописанного, мы предполагаем нагрузочное тестирование и пускаем трафик через большой объем сервисов, в данном случае 2500 штук. Это позволяет заранее выявить узкие места и создать качественную архитектуру.

Что касается полосы пропускания, то мы используем сценарий постепенного набора с шагом в 1% от максимума на порту, то есть 1 Gbps. Вначале запускаем трафик на 1 Gbps, который приблизительно равномерно распределяется по всем созданным сервисам, и затем начинаем наращивать объем.

Мы отслеживаем состояние как control plane, так и data plane. С контрольной плоскостью все понятно: достаточно включить логи и наблюдать за активностью используемых протоколов. Они должны быть стабильными и не должны флапать или перестраиваться. В отношении data plane сначала анализируем счетчики на дашборде TRex, и если необходимо, смотрим аналогичную информацию на самих узлах.

Результат тестов

При базовой нагрузке (1 Gbps) проблем не возникает.

DF/Non-DF выбираются корректно. Принцип выбора соответствует RFC7432 и подробно разобран в статьях, которые я приложил выше.

PE1-MR381#sh evpn mpls 
EVPN-MPLS Information
=================
Codes: NW - Network Port
AC - Access Port
(u) - Untagged

VPN-ID EVI-Name EVI-Type Type Interface ESI VLAN DF-Status Src-Addr Dst-Addr
_______________________________________________________________________________________________________________________________
1000 ---- L2 NW ---- ---- ---- ---- 20.0.0.1 20.0.0.3
1000 ---- -- AC po1.1000 00:00:00:11:11:aa:aa:00:00:00 ---- DF ---- ----
1001 ---- L2 NW ---- ---- ---- ---- 20.0.0.1 20.0.0.3
1001 ---- -- AC po1.1001 00:00:00:11:11:aa:aa:00:00:00 ---- NON-DF ---- ----
1002 ---- L2 NW ---- ---- ---- ---- 20.0.0.1 20.0.0.3
1002 ---- -- AC po1.1002 00:00:00:11:11:aa:aa:00:00:00 ---- DF ---- ----

.....

3497 ---- L2 NW ---- ---- ---- ---- 20.0.0.1 20.0.0.3
3497 ---- -- AC po1.3497 00:00:00:11:11:aa:aa:00:00:00 ---- NON-DF ---- ----
3498 ---- L2 NW ---- ---- ---- ---- 20.0.0.1 20.0.0.3
3498 ---- -- AC po1.3498 00:00:00:11:11:aa:aa:00:00:00 ---- DF ---- ----
3499 ---- L2 NW ---- ---- ---- ---- 20.0.0.1 20.0.0.3
3499 ---- -- AC po1.3499 00:00:00:11:11:aa:aa:00:00:00 ---- NON-DF ---- ----

Аналогичная история с Aliasing и ESI label.

PE1-MR381#sh evpn mpls label alias 
S - Self
R - Remote
ESI PE-IP-ADDRESS TENANT ALIAS-LABEL
=============================================================================================
00:00:00:11:11:aa:aa:00:00:00 20.0.0.1(S) 1000 30
00:00:00:11:11:aa:aa:00:00:00 20.0.0.1(S) 1001 29
00:00:00:11:11:aa:aa:00:00:00 20.0.0.1(S) 1002 28

....

00:00:00:11:11:aa:aa:00:00:00 20.0.0.3(R) 3497 31959
00:00:00:11:11:aa:aa:00:00:00 20.0.0.3(R) 3498 31958
00:00:00:11:11:aa:aa:00:00:00 20.0.0.3(R) 3499 31961 PE1-MR381#sh evpn mpls label esi
S - Self
R - Remote
ESI PE-IP-ADDRESS ESI-LABEL
================================================================
00:00:00:11:11:aa:aa:00:00:00 20.0.0.1(S) 18
00:00:00:11:11:aa:aa:00:00:00 20.0.0.3(R) 18

Продолжая увеличивать нагрузку, мы заметили, что при использовании UDP в качестве заголовков трафик на PE неверно классифицируется и попадает в другую очередь, где в дальнейшем отбрасывается.

 

При использовании TCP подобной проблемы не возникает, и весь трафик классифицируется корректно.

После общения с вендором и корректировки данного поведения для UDP потоков с помощью патча, мы повторили тесты и успешно достигли целевой нагрузки.

 
Также счетчики на очередях показывают корректные значения.
 

Выводы

Этот опыт показал важность комплексного тестирования. Без нагрузочных тестов мы могли бы перейти к следующей фазе и не обратить внимание на особенности реализации, что могло бы привести к проблемам на этапе ПНР или, что еще хуже, на ПСИ. В такой ситуации времени на разбор полетов уже не будет, и придется действовать быстро и решительно. Также мы проверили готовность вендора к быстрому реагированию на выявленные недостатки, что является важным фактором для дальнейшего взаимодействия.

Наш эксперт, Сергей Бочарников, опубликовал на Хабре практическую статью, в которой поделился опытом проведения нагрузочного тестирования EVPN-MPLS на маршрутизаторах MR-381 от B4COM.

Сергей Бочарников

Ведущий инженер по направлению ЦОД