# OSPF Unnumbered with ECMP

> Интерфейсы OSPF unnumbered с балансировкой ECMP для топологий spine-leaf в ЦОД и облачных развертываний Yandex Cloud и VK Cloud.

Source: https://opennix.org/docs/vyos/examples/ospf-unnumbered-ecmp/


OSPF unnumbered позволяет использовать интерфейсы без назначения IP subnet, упрощая конфигурацию point-to-point линков. ECMP (Equal-Cost Multipath) обеспечивает load balancing между несколькими путями с одинаковой метрикой.

## Сценарий использования

### Применимость

- **Datacenter Spine-Leaf**: L3 underlay с минимальной адресацией
- **Cloud Networking**: Multi-AZ топологии в Yandex Cloud / VK Cloud
- **Campus Networks**: L3 core с ECMP между зданиями
- **Service Provider**: Carrier network с load balancing

### Преимущества

1. **Simplified Address Planning**: Не требуется /30 или /31 для каждого линка
2. **ECMP Load Balancing**: Автоматическое распределение трафика
3. **Fast Convergence**: Sub-second failover с правильными timers
4. **Scalability**: Легко добавлять новые линки
5. **Resource Efficiency**: Экономия IP адресов

## Топология сети

### Базовая топология (2 роутера, 2 линка)

```
                    ┌─────────────────┐
                    │   Router A      │
                    │   Area 0.0.0.0  │
                    │   RID: 192.168.0.1
                    │                 │
                    │ lo: 192.168.0.1 │
                    │ eth1: /32       │
                    │ eth2: /32       │
                    └────┬───────┬────┘
                         │       │
                    eth1 │       │ eth2
                   /32 IP│       │/32 IP
                    eth1 │       │ eth2
                    ┌────┴───────┴────┐
                    │   Router B      │
                    │   Area 0.0.0.0  │
                    │   RID: 192.168.0.2
                    │                 │
                    │ lo: 192.168.0.2 │
                    │ eth1: /32       │
                    │ eth2: /32       │
                    └─────────────────┘
```

### Datacenter Spine-Leaf с ECMP

```
     ┌─────────┐           ┌─────────┐
     │ Spine 1 │           │ Spine 2 │
     │Area 0   │═══════════│Area 0   │
     └─┬─┬─┬─┬─┘           └─┬─┬─┬─┬─┘
       │ │ │ │               │ │ │ │
    ┌──┘ │ │ └──┐         ┌──┘ │ │ └──┐
    │    │ │    │         │    │ │    │
 ┌──┴┐ ┌─┴┐ ┌──┴┐     ┌──┴┐ ┌─┴┐ ┌──┴┐
 │L1 │ │L2│ │L3 │ ... │L4 │ │L5│ │L6 │
 │A0 │ │A0│ │A0 │     │A0 │ │A0│ │A0 │
 └───┘ └──┘ └───┘     └───┘ └──┘ └───┘

ECMP: Каждый Leaf имеет 2+ пути к другим Leaf через Spines
```

## Требования

### Минимальные требования

- VyOS 1.4 (Sagitta) или новее
- OSPF support (FRRouting)
- Unique Router ID для каждого роутера
- Loopback interfaces

### Сетевые параметры (пример)

| Параметр | Router A | Router B |
|----------|----------|----------|
| Router ID | 192.168.0.1 | 192.168.0.2 |
| Loopback | 192.168.0.1/32 | 192.168.0.2/32 |
| eth1 | 192.168.0.1/32 | 192.168.0.2/32 |
| eth2 | 192.168.0.1/32 | 192.168.0.2/32 |
| OSPF Area | 0.0.0.0 | 0.0.0.0 |

## Конфигурация Router A

### Интерфейсы

```bash
configure

# Loopback для Router ID
set interfaces loopback lo address '192.168.0.1/32'
set interfaces loopback lo description 'Router ID + OSPF announce'

# eth1 - Unnumbered (использует адрес loopback)
set interfaces ethernet eth1 address '192.168.0.1/32'
set interfaces ethernet eth1 description 'OSPF link to Router B eth1'
set interfaces ethernet eth1 ip ospf authentication md5 key-id 1 md5-key 'SecureOSPFPassword123'
set interfaces ethernet eth1 ip ospf network 'point-to-point'

# eth2 - Unnumbered (тот же IP, что и loopback)
set interfaces ethernet eth2 address '192.168.0.1/32'
set interfaces ethernet eth2 description 'OSPF link to Router B eth2'
set interfaces ethernet eth2 ip ospf authentication md5 key-id 1 md5-key 'SecureOSPFPassword123'
set interfaces ethernet eth2 ip ospf network 'point-to-point'

commit
```

### OSPF Configuration

```bash
configure

# OSPF основные параметры
set protocols ospf parameters router-id '192.168.0.1'
set protocols ospf parameters abr-type 'cisco'

# Area 0 (backbone)
set protocols ospf area 0.0.0.0 network '192.168.0.1/32'

# OSPF log adjacency changes
set protocols ospf log-adjacency-changes detail

# Timers для быстрой конвергенции
set protocols ospf timers throttle spf delay '50'
set protocols ospf timers throttle spf initial-holdtime '100'
set protocols ospf timers throttle spf max-holdtime '1000'

commit
save
```

### Объяснение ключевых параметров

- **`/32` на интерфейсе**: Unnumbered - интерфейс использует адрес loopback
- **`network point-to-point`**: OSPF не ждет DR/BDR election, быстрее конвергенция
- **`authentication md5`**: Безопасность OSPF adjacency
- **`throttle spf`**: Быстрый пересчет SPF при изменениях (50ms delay)

## Конфигурация Router B

```bash
configure

# Loopback
set interfaces loopback lo address '192.168.0.2/32'
set interfaces loopback lo description 'Router ID + OSPF announce'

# Интерфейсы
set interfaces ethernet eth1 address '192.168.0.2/32'
set interfaces ethernet eth1 description 'OSPF link to Router A eth1'
set interfaces ethernet eth1 ip ospf authentication md5 key-id 1 md5-key 'SecureOSPFPassword123'
set interfaces ethernet eth1 ip ospf network 'point-to-point'

set interfaces ethernet eth2 address '192.168.0.2/32'
set interfaces ethernet eth2 description 'OSPF link to Router A eth2'
set interfaces ethernet eth2 ip ospf authentication md5 key-id 1 md5-key 'SecureOSPFPassword123'
set interfaces ethernet eth2 ip ospf network 'point-to-point'

# OSPF
set protocols ospf parameters router-id '192.168.0.2'
set protocols ospf parameters abr-type 'cisco'
set protocols ospf area 0.0.0.0 network '192.168.0.2/32'
set protocols ospf log-adjacency-changes detail
set protocols ospf timers throttle spf delay '50'
set protocols ospf timers throttle spf initial-holdtime '100'
set protocols ospf timers throttle spf max-holdtime '1000'

commit
save
```

## Интеграция с Yandex Cloud

### Сценарий: Multi-AZ Spine-Leaf в Yandex Cloud

```
┌─────────────────────────────────────────────┐
│         Yandex Cloud VPC                    │
│                                             │
│  ┌──────────────┐       ┌──────────────┐   │
│  │  Zone A      │       │  Zone B      │   │
│  │              │       │              │   │
│  │ ┌─────────┐  │       │ ┌─────────┐  │   │
│  │ │ Spine-A │  │═══════│═│ Spine-B │  │   │
│  │ │ VyOS    │◄─┼───────┼─┤ VyOS    │  │   │
│  │ └────┬────┘  │       │ └────┬────┘  │   │
│  │      ║       │       │      ║       │   │
│  │  ┌───╩───┐   │       │  ┌───╩───┐   │   │
│  │  │ Leaf  │   │       │  │ Leaf  │   │   │
│  │  │ VMs   │   │       │  │ VMs   │   │   │
│  │  └───────┘   │       │  └───────┘   │   │
│  └──────────────┘       └──────────────┘   │
└─────────────────────────────────────────────┘
```

### Конфигурация Spine (Yandex Cloud)

```bash
configure

# Management интерфейс (DHCP от Yandex Cloud)
set interfaces ethernet eth0 address dhcp
set interfaces ethernet eth0 description 'Yandex Cloud VPC management'

# Loopback
set interfaces loopback lo address '10.255.0.1/32'
set interfaces loopback lo description 'Spine-A Router ID'

# Unnumbered интерфейсы к Leaf роутерам
set interfaces ethernet eth1 address '10.255.0.1/32'
set interfaces ethernet eth1 description 'Link to Leaf-1'
set interfaces ethernet eth1 ip ospf network 'point-to-point'
set interfaces ethernet eth1 ip ospf authentication md5 key-id 1 md5-key 'YandexCloudOSPF2025'

set interfaces ethernet eth2 address '10.255.0.1/32'
set interfaces ethernet eth2 description 'Link to Leaf-2'
set interfaces ethernet eth2 ip ospf network 'point-to-point'
set interfaces ethernet eth2 ip ospf authentication md5 key-id 1 md5-key 'YandexCloudOSPF2025'

set interfaces ethernet eth3 address '10.255.0.1/32'
set interfaces ethernet eth3 description 'Link to Leaf-3'
set interfaces ethernet eth3 ip ospf network 'point-to-point'
set interfaces ethernet eth3 ip ospf authentication md5 key-id 1 md5-key 'YandexCloudOSPF2025'

# OSPF
set protocols ospf parameters router-id '10.255.0.1'
set protocols ospf parameters abr-type 'cisco'
set protocols ospf area 0.0.0.0 network '10.255.0.1/32'
set protocols ospf log-adjacency-changes detail

# Fast convergence timers
set protocols ospf timers throttle spf delay '50'
set protocols ospf timers throttle spf initial-holdtime '100'
set protocols ospf timers throttle spf max-holdtime '1000'

# ECMP configuration (FRR)
# Будет настроено через vtysh ниже

commit
save

# FRR ECMP configuration
vtysh
conf t
router ospf
maximum-paths 16
exit
exit
exit
```

### Конфигурация Leaf (Yandex Cloud)

```bash
configure

# Loopback
set interfaces loopback lo address '10.255.1.1/32'
set interfaces loopback lo description 'Leaf-1 Router ID'

# Unnumbered интерфейсы к Spine роутерам (ECMP)
set interfaces ethernet eth1 address '10.255.1.1/32'
set interfaces ethernet eth1 description 'Link to Spine-A'
set interfaces ethernet eth1 ip ospf network 'point-to-point'
set interfaces ethernet eth1 ip ospf authentication md5 key-id 1 md5-key 'YandexCloudOSPF2025'

set interfaces ethernet eth2 address '10.255.1.1/32'
set interfaces ethernet eth2 description 'Link to Spine-B'
set interfaces ethernet eth2 ip ospf network 'point-to-point'
set interfaces ethernet eth2 ip ospf authentication md5 key-id 1 md5-key 'YandexCloudOSPF2025'

# LAN интерфейс для VM подключения
set interfaces ethernet eth3 address '10.10.1.1/24'
set interfaces ethernet eth3 description 'VMs subnet'

# OSPF
set protocols ospf parameters router-id '10.255.1.1'
set protocols ospf parameters abr-type 'cisco'
set protocols ospf area 0.0.0.0 network '10.255.1.1/32'
set protocols ospf area 0.0.0.0 network '10.10.1.0/24'
set protocols ospf log-adjacency-changes detail
set protocols ospf timers throttle spf delay '50'
set protocols ospf timers throttle spf initial-holdtime '100'
set protocols ospf timers throttle spf max-holdtime '1000'

commit
save

# ECMP
vtysh
conf t
router ospf
maximum-paths 16
exit
exit
exit
```

### Мониторинг через Yandex Monitoring

```bash
# Экспорт метрик OSPF neighbors
show ip ospf neighbor | grep -c "Full" > /tmp/ospf_neighbors_full.txt

# Yandex Monitoring custom metrics (через агент)
# /etc/yandex/unified_agent/config.yml
```

## Интеграция с VK Cloud

### Конфигурация с учетом VK Cloud Networking

```bash
configure

# VK Cloud management (OpenStack Neutron)
set interfaces ethernet eth0 address dhcp
set interfaces ethernet eth0 description 'VK Cloud management'

# Остальная конфигурация аналогична Yandex Cloud

# Особенности VK Cloud:
# 1. Security Groups - разрешить OSPF (IP protocol 89)
# 2. Floating IP - только для management, не для OSPF
# 3. MTU 1450 для overlay networks

set interfaces ethernet eth1 mtu '1450'
set interfaces ethernet eth2 mtu '1450'

commit
save
```

### Security Groups (VK Cloud)

В VK Cloud Console создать Security Group:
- **Rule 1**: OSPF (IP Protocol 89) from VPC CIDR
- **Rule 2**: ICMP from VPC CIDR
- **Rule 3**: SSH (TCP 22) from trusted IPs

## Проверка конфигурации

### Проверка OSPF neighbors

```bash
# OSPF neighbors
show ip ospf neighbor

# Ожидаемый вывод:
# Neighbor ID     Pri State           Up Time         Dead Time Address         Interface
# 192.168.0.2       1 Full/Point-to-Point  00:05:30        00:00:35  192.168.0.2     eth1:192.168.0.1
# 192.168.0.2       1 Full/Point-to-Point  00:05:25        00:00:38  192.168.0.2     eth2:192.168.0.1

# State должен быть "Full"
```

### Проверка OSPF database

```bash
# OSPF LSDB
show ip ospf database

# Router LSAs
show ip ospf database router

# Детали конкретного LSA
show ip ospf database router 192.168.0.1
```

### Проверка маршрутов ECMP

```bash
# Routing table
show ip route ospf

# Ожидаемый вывод с ECMP:
# O   192.168.0.2/32 [110/10] via 192.168.0.2, eth1, weight 1, 00:05:30
#                            via 192.168.0.2, eth2, weight 1, 00:05:25

# Два пути к одному destination = ECMP работает
```

### Проверка интерфейсов OSPF

```bash
# OSPF интерфейсы
show ip ospf interface

# Детали конкретного интерфейса
show ip ospf interface eth1

# Важные параметры:
# - Network type: POINTOPOINT
# - Timer intervals: Hello 10s, Dead 40s
# - State: Point-to-Point
```

### Тест связности и ECMP

```bash
# Ping до loopback соседа
ping 192.168.0.2 count 10

# Traceroute
traceroute 192.168.0.2

# Проверка load balancing (iperf3)
# На Router B:
iperf3 -s

# На Router A (несколько parallel streams для ECMP):
iperf3 -c 192.168.0.2 -P 4 -t 30

# Мониторинг утилизации интерфейсов
watch -n 1 'show interfaces ethernet eth1 ; show interfaces ethernet eth2'
```

## Troubleshooting

### Проблема 1: OSPF neighbors не устанавливаются

**Симптомы**:
```bash
show ip ospf neighbor
# Пусто или State = "Init" / "2-Way"
```

**Причины и решения**:

1. **MD5 authentication mismatch**:
   ```bash
   # Проверить конфигурацию
   show configuration commands | grep "ospf authentication"

   # Убедиться что key-id и md5-key одинаковые на обоих концах
   ```

2. **Network type mismatch**:
   ```bash
   # Должно быть point-to-point на обоих
   show ip ospf interface eth1 | grep "Network Type"

   # Исправить
   set interfaces ethernet eth1 ip ospf network 'point-to-point'
   commit
   ```

3. **Firewall блокирует OSPF (protocol 89)**:
   ```bash
   # Разрешить OSPF
   set firewall ipv4-name WAN_LOCAL rule 100 action 'accept'
   set firewall ipv4-name WAN_LOCAL rule 100 protocol 'ospf'
   commit
   ```

### Проблема 2: ECMP не работает

**Симптомы**:
```bash
show ip route 192.168.0.2/32
# Показывает только один путь, хотя должно быть два
```

**Решение**:
```bash
# Проверить FRR ECMP configuration
vtysh
show running-config | grep maximum-paths

# Если не установлено:
conf t
router ospf
maximum-paths 16
exit
exit
write memory
exit

# Также проверить kernel ECMP support
sysctl net.ipv4.fib_multipath_hash_policy
# Должно быть 1 (layer 3+4 hash)

# Установить если нужно
sysctl -w net.ipv4.fib_multipath_hash_policy=1

# Сделать permanent
echo "net.ipv4.fib_multipath_hash_policy=1" >> /etc/sysctl.conf
```

### Проблема 3: Медленная конвергенция

**Симптомы**:
При падении линка switchover занимает > 10 секунд

**Решение**:

1. **Уменьшить OSPF timers**:
   ```bash
   configure
   set interfaces ethernet eth1 ip ospf dead-interval '12'
   set interfaces ethernet eth1 ip ospf hello-interval '3'
   set interfaces ethernet eth2 ip ospf dead-interval '12'
   set interfaces ethernet eth2 ip ospf hello-interval '3'
   commit
   ```

2. **Включить BFD**:
   ```bash
   # BFD на интерфейсах
   set interfaces ethernet eth1 ip enable-bfd
   set interfaces ethernet eth2 ip enable-bfd

   # BFD для OSPF
   vtysh
   conf t
   router ospf
   bfd
   exit
   interface eth1
   ip ospf bfd
   exit
   interface eth2
   ip ospf bfd
   exit
   exit
   write memory
   exit
   ```

   **Результат**: Sub-second failover (< 1 секунда)

### Проблема 4: Routing loops

**Симптомы**:
Traceroute показывает циклы, пакеты ходят по кругу

**Причины**:
- Неправильная OSPF area конфигурация
- Redistribution loops

**Решение**:
```bash
# Проверить area assignment
show ip ospf interface

# Все unnumbered интерфейсы должны быть в одной area
# Проверить redistribution
show configuration commands | grep redistribute

# Использовать route-map для фильтрации
set policy route-map OSPF-REDIST rule 10 action 'deny'
set policy route-map OSPF-REDIST rule 10 match interface 'eth0'
set policy route-map OSPF-REDIST rule 20 action 'permit'

set protocols ospf redistribute connected route-map 'OSPF-REDIST'
commit
```

## Best Practices

### 1. Router ID Planning

- Используйте loopback адреса как Router ID
- Назначайте из единого /16 блока (например, 10.255.0.0/16)
- Spine: 10.255.0.x, Leaf: 10.255.1.x, 10.255.2.x, ...

### 2. OSPF Timers

**Production (default)**:
- Hello: 10 seconds
- Dead: 40 seconds
- Convergence: ~40 seconds

**Fast Convergence**:
```bash
set interfaces ethernet ethX ip ospf dead-interval '12'
set interfaces ethernet ethX ip ospf hello-interval '3'
```
- Convergence: ~12 seconds

**BFD (best)**:
- Convergence: < 1 second

### 3. ECMP Configuration

```bash
# FRR
vtysh
conf t
router ospf
maximum-paths 16
exit
exit
write memory

# Kernel
sysctl -w net.ipv4.fib_multipath_hash_policy=1
sysctl -w net.ipv4.fib_multipath_use_neigh=1
```

### 4. Security

```bash
# MD5 authentication на всех OSPF интерфейсах
set interfaces ethernet ethX ip ospf authentication md5 key-id 1 md5-key 'StrongPassword'

# Пассивные интерфейсы (не отправлять OSPF Hello)
set protocols ospf passive-interface 'eth0'
set protocols ospf passive-interface 'eth3'
```

### 5. Logging

```bash
# OSPF adjacency changes
set protocols ospf log-adjacency-changes detail

# Syslog
set system syslog global facility protocols level 'info'

# Мониторинг
watch -n 5 'show ip ospf neighbor'
```

## Advanced Configuration

### Stub Area для экономии ресурсов

```bash
# Leaf роутеры в stub area (меньше LSA, меньше CPU/memory)
set protocols ospf area 0.0.0.1 area-type stub
set protocols ospf area 0.0.0.1 network '10.255.1.0/24'
```

### OSPF Cost Tuning

```bash
# Изменить cost для приоритизации путей
set interfaces ethernet eth1 ip ospf cost '10'
set interfaces ethernet eth2 ip ospf cost '20'

# eth1 будет preferred path
```

### BFD для sub-second failover

```bash
# Подробная BFD конфигурация
set protocols bfd peer 192.168.0.2 multihop local-address '192.168.0.1'
set protocols bfd peer 192.168.0.2 interval transmit '300'
set protocols bfd peer 192.168.0.2 interval receive '300'
set protocols bfd peer 192.168.0.2 interval multiplier '3'

# 300ms * 3 = 900ms максимальное время обнаружения отказа
```

## Ссылки

- [VyOS OSPF Configuration](https://docs.vyos.io/en/latest/configuration/protocols/ospf.html)
- [RFC 2328 - OSPF Version 2](https://datatracker.ietf.org/doc/html/rfc2328)
- [RFC 3137 - OSPF Stub Router Advertisement](https://datatracker.ietf.org/doc/html/rfc3137)
- [FRRouting OSPF Documentation](http://docs.frrouting.org/en/latest/ospfd.html)
- [Yandex Cloud VPC](https://cloud.yandex.ru/docs/vpc/)
- [VK Cloud Networks](https://mcs.mail.ru/docs/networks)

