docs: enhance EvoBGP architecture plan with new risk mitigation strategies, testing matrix for BIRD2, and CI/CD workflow details. Updated section titles for clarity and added completed todos for deployment practices.
This commit is contained in:
@@ -26,6 +26,15 @@ todos:
|
||||
- id: replica-bundle
|
||||
content: Подписанный бандл ревизии, API, evobgp-node
|
||||
status: pending
|
||||
- id: risk-hardening
|
||||
content: Двухфазный deploy, LKG, pin BIRD, политика миграций, обязательная подпись бандла на ноде
|
||||
status: completed
|
||||
- id: test-bird-matrix
|
||||
content: Матрица сценариев BIRD + golden-тесты birdfmt + bird -p в CI
|
||||
status: completed
|
||||
- id: ci-gitea
|
||||
content: .gitea/workflows/ci.yaml, документация для act runner
|
||||
status: completed
|
||||
isProject: false
|
||||
---
|
||||
|
||||
@@ -50,7 +59,10 @@ Control-plane на **Go**, анонс префиксов через **BIRD**, п
|
||||
10. [Реплика evobgp-node](#10-реплика-evobgp-node)
|
||||
11. [Выбор СУБД](#11-выбор-субд)
|
||||
12. [Профиль microVPS — детализация](#12-профиль-microvps-детализация)
|
||||
13. [Риски и этапы](#13-риски-и-этапы-внедрения)
|
||||
13. [Снижение рисков (меры и процессы)](#13-снижение-рисков-меры-и-процессы)
|
||||
14. [Тестирование BIRD2 и матрица сценариев](#14-тестирование-bird2-и-матрица-сценариев)
|
||||
15. [CI/CD (Gitea Actions)](#15-cicd-gitea-actions)
|
||||
16. [Риски и этапы внедрения](#16-риски-и-этапы-внедрения)
|
||||
|
||||
---
|
||||
|
||||
@@ -576,7 +588,75 @@ Raft, HTTP/`gorqlite`; для HA control-plane; не замена дефолтн
|
||||
|
||||
---
|
||||
|
||||
## 13. Риски и этапы внедрения
|
||||
## 13. Снижение рисков (меры и процессы)
|
||||
|
||||
Дополняет [§9](#9-эксплуатация-и-масштаб) и [§10](#10-реплика-evobgp-node) конкретными обязательными практиками.
|
||||
|
||||
### Конфигурация BIRD: безопасное применение
|
||||
|
||||
- **Двухфазный deploy:** (1) запись новой ревизии во **временный** каталог на общем volume и проверка `**bird -c <path> -p`** (парсинг без запуска демона; см. `bird(8)`); (2) только при нулевом коде выхода — **атомарная** подмена активных файлов (rename) и `**birdc configure`**. Опционально перед фазой (2) — `preview`/diff в control-plane (REST).
|
||||
- **Last-known-good (LKG):** хранить на volume **предыдущую** применённую ревизию; при неуспехе `configure` или ненулевом exit **автоматически** восстановить файлы LKG, зафиксировать событие в логах/метриках и **не** оставлять BIRD в полусобранном состоянии.
|
||||
- **Canary в production:** перед полным apply — отдельный `bgp_speaker` или подмножество `bgp_peer` (см. [§9](#9-эксплуатация-и-масштаб)); полный выкат только после проверки сессий/префиксов на канареечном спикере.
|
||||
|
||||
### Данные, очередь, microVPS
|
||||
|
||||
- **Миграции:** в основной ветке — только **вперёд**; откат схемы — явные down-миграции (если приняты в процессе) или восстановление БД из бэкапа; политика фиксируется в операторской документации.
|
||||
- **Jobs:** обязательные `**idempotency_key`** и уникальность в `job_audit` там, где это предотвращает двойной apply/reload.
|
||||
- **microVPS:** пороги мониторинга на рост таблиц ревизий/артефактов, **retention** старых ревизий, лимиты ротации логов Docker (см. [§12](#12-профиль-microvps-детализация)) — с **алертами** при приближении к лимиту диска и OOM.
|
||||
|
||||
### Безопасность
|
||||
|
||||
- **evobgp-node:** в production **обязательна** проверка **подписи** бандла (отдельно от TLS транспорта); ключ подписи не смешивать с другими ролями.
|
||||
- Секреты BGP (пароли, ключи) — только secret store / Docker secrets; **не** логировать полные конфиги с секретами.
|
||||
|
||||
### Поставка и совместимость
|
||||
|
||||
- В **Dockerfile** / Compose зафиксировать **версию образа BIRD 2** (тег minor или digest), совпадающую с образом, в котором выполняется `**bird -p`** в CI ([§15](#15-cicd-gitea-actions)).
|
||||
- **Статический каркас** (router id, локальные интерфейсы, операторские правки) — в файлах **вне** автогенерируемых фрагментов; сгенерированное — только в согласованных путях `bird.d/` (см. [§8](#8-генерация-bird-и-ревизии), [§10](#10-реплика-evobgp-node)).
|
||||
|
||||
### Порядок внедрения (уточнение)
|
||||
|
||||
Перед полным набором микросервисов целесообразен параллельный этап: **контракт OpenAPI + каркас `internal/birdfmt` + golden-тесты + проверка `bird -p` в CI** ([§14](#14-тестирование-bird2-и-матрица-сценариев), [§15](#15-cicd-gitea-actions)), затем миграции PG и один вертикальный сценарий (например `IP_RANGES`).
|
||||
|
||||
---
|
||||
|
||||
## 14. Тестирование BIRD2 и матрица сценариев
|
||||
|
||||
Цель — покрыть **поверхность генератора** EvoBGP, а не весь язык BIRD. Комбинации фиксируются **матрицей** и каталогом сценариев в репозитории (`internal/birdfmt/testdata/scenarios/`).
|
||||
|
||||
### Матрица покрытия (ориентир)
|
||||
|
||||
|
||||
| Измерение | Варианты для покрытия |
|
||||
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Роль спикера | master (полный набор фрагментов); реплика / **бандл** для `evobgp-node` (manifest + подмножество includes + локальный `local.conf`) |
|
||||
| Типы модулей (выход render) | `AS_PREFIXES`, `CDN_CIDRS`, `DOMAINS` (материализованные префиксы), `IP_RANGES` — минимум по одному сценарию; комбинация **2+ типов** в одной ревизии |
|
||||
| Пиры | при поддержке каркасом — только static; **1× IPv4**, **1× IPv6**, несколько пиров, смешанный v4/v6 |
|
||||
| Community | каждый поддерживаемый `kind` в справочнике + вариант без community (default) |
|
||||
| Фильтры | экспорт «разрешить анонс»; при генерации — отрицательные кейсы (reject) |
|
||||
| Граничные данные | пустой префикс-лист; один префикс; большой список (нагрузка на размер файла) |
|
||||
| Шаблоны include | каждый именуемый фрагмент из `internal/birdfmt` участвует хотя бы в одном интеграционном сценарии |
|
||||
|
||||
|
||||
По мере расширения генератора матрица **дополняется**; регрессия — новыми строками в таблице тестов и при необходимости новыми подкаталогами сценариев.
|
||||
|
||||
### Виды тестов
|
||||
|
||||
1. **Unit / snapshot (Go):** пакет `internal/birdfmt` — вход из фикстур, выход сравнивается с `*.golden` или `txtar`.
|
||||
2. **Синтаксис BIRD в CI:** для каждого сценария с `bird.conf` выполняется `**bird -c … -p`** в контейнере с **той же major/minor версией BIRD 2**, что в production ([§13](#13-снижение-рисков-меры-и-процессы)).
|
||||
3. **Позже:** контрактные тесты HTTP по `docs/openapi.yaml` после реализации `internal/httpapi`.
|
||||
|
||||
---
|
||||
|
||||
## 15. CI/CD (Gitea Actions)
|
||||
|
||||
- Workflows: каталог `**.gitea/workflows/`** в корне репозитория; синтаксис совместим с GitHub Actions ([документация Gitea Actions](https://docs.gitea.com/usage/actions/quickstart/)).
|
||||
- Нужен зарегистрированный **act runner** с меткой `ubuntu-latest` (или согласованной с инсталляцией) и при job с Docker — доступ **Docker** на runner.
|
||||
- Рекомендуемый pipeline: **lint OpenAPI** (`npx @redocly/cli lint docs/openapi.yaml`), `**go vet` / `go test` / `go build ./...`**, **проверка всех `testdata/scenarios/*/bird.conf` через `bird -p`** (см. workflow в репозитории).
|
||||
|
||||
---
|
||||
|
||||
## 16. Риски и этапы внедрения
|
||||
|
||||
### Риски
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# Gitea Actions
|
||||
|
||||
В репозитории включён workflow [workflows/ci.yaml](workflows/ci.yaml).
|
||||
|
||||
Требования к runner:
|
||||
|
||||
- Метка `ubuntu-latest` (или измените `runs-on` под свои labels).
|
||||
- Для job `bird2` на runner должен быть доступен **Docker** (проверка `bird -c … -p` в контейнере `debian:bookworm-slim` с пакетом `bird2`).
|
||||
|
||||
Секреты не обязательны для базового CI; для публикации образов добавьте свои шаги и credentials в отдельный workflow.
|
||||
@@ -0,0 +1,56 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, master]
|
||||
pull_request:
|
||||
branches: [main, master]
|
||||
|
||||
jobs:
|
||||
openapi:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
- name: Lint OpenAPI (Redocly)
|
||||
run: npx --yes @redocly/cli@1 lint docs/openapi.yaml
|
||||
|
||||
go:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.22"
|
||||
- name: Vet
|
||||
run: go vet ./...
|
||||
- name: Test
|
||||
run: go test ./... -race -count=1
|
||||
- name: Build all commands
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
out="${RUNNER_TEMP}/evobgp-bin"
|
||||
mkdir -p "$out"
|
||||
for d in cmd/*/; do
|
||||
name="$(basename "$d")"
|
||||
go build -o "$out/$name" "./$d"
|
||||
done
|
||||
|
||||
bird2:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [go]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: bird -p on all scenario bird.conf files
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
for conf in internal/birdfmt/testdata/scenarios/*/bird.conf; do
|
||||
echo "==> $conf"
|
||||
docker run --rm \
|
||||
-e "BIRD_CONF=/work/${conf}" \
|
||||
-v "$PWD:/work:ro" \
|
||||
debian:bookworm-slim \
|
||||
bash -ceu 'apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -y -qq bird2 >/dev/null && bird -c "$BIRD_CONF" -p'
|
||||
done
|
||||
@@ -0,0 +1,3 @@
|
||||
package main
|
||||
|
||||
func main() {}
|
||||
@@ -0,0 +1,3 @@
|
||||
package main
|
||||
|
||||
func main() {}
|
||||
@@ -0,0 +1,3 @@
|
||||
package main
|
||||
|
||||
func main() {}
|
||||
@@ -0,0 +1,3 @@
|
||||
package main
|
||||
|
||||
func main() {}
|
||||
@@ -0,0 +1,3 @@
|
||||
package main
|
||||
|
||||
func main() {}
|
||||
@@ -0,0 +1,3 @@
|
||||
package main
|
||||
|
||||
func main() {}
|
||||
@@ -0,0 +1,3 @@
|
||||
package main
|
||||
|
||||
func main() {}
|
||||
@@ -0,0 +1,3 @@
|
||||
package main
|
||||
|
||||
func main() {}
|
||||
@@ -0,0 +1,64 @@
|
||||
package birdfmt
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"io/fs"
|
||||
"path"
|
||||
"sort"
|
||||
)
|
||||
|
||||
//go:embed testdata/scenarios
|
||||
var scenariosFS embed.FS
|
||||
|
||||
// BirdScenarioPaths returns POSIX-style directory paths (under testdata/scenarios)
|
||||
// that contain a bird.conf file, sorted for stable iteration.
|
||||
func BirdScenarioPaths() ([]string, error) {
|
||||
var dirs []string
|
||||
err := fs.WalkDir(scenariosFS, "testdata/scenarios", func(p string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.IsDir() || d.Name() != "bird.conf" {
|
||||
return nil
|
||||
}
|
||||
dir := path.Dir(p)
|
||||
if dir == "testdata/scenarios" {
|
||||
return nil
|
||||
}
|
||||
dirs = append(dirs, dir)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sort.Strings(dirs)
|
||||
return dirs, nil
|
||||
}
|
||||
|
||||
// ScenarioBirdConfRel returns the path relative to module root internal/birdfmt/ for bird.conf.
|
||||
func ScenarioBirdConfRel(scenarioDir string) string {
|
||||
return path.Join(scenarioDir, "bird.conf")
|
||||
}
|
||||
|
||||
// ReadScenarioBirdConf returns the contents of bird.conf for a scenario directory from embed.
|
||||
func ReadScenarioBirdConf(scenarioDir string) ([]byte, error) {
|
||||
return scenariosFS.ReadFile(path.Join(scenarioDir, "bird.conf"))
|
||||
}
|
||||
|
||||
// RepoRelativeBirdConf is the path from the repository root (for CI / docker bind mounts).
|
||||
func RepoRelativeBirdConf(scenarioDir string) string {
|
||||
return path.Join("internal/birdfmt", scenarioDir, "bird.conf")
|
||||
}
|
||||
|
||||
// AllScenarioNames returns leaf scenario names (last path segment) for tables / docs.
|
||||
func AllScenarioNames() ([]string, error) {
|
||||
paths, err := BirdScenarioPaths()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
names := make([]string, len(paths))
|
||||
for i, p := range paths {
|
||||
names[i] = path.Base(p)
|
||||
}
|
||||
return names, nil
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package birdfmt
|
||||
|
||||
import (
|
||||
"path"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBirdScenarioPaths_Table(t *testing.T) {
|
||||
paths, err := BirdScenarioPaths()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Expected scenario leaf names — extend when adding directories under testdata/scenarios.
|
||||
wantNames := []string{
|
||||
"bgp_dual_peer",
|
||||
"bgp_ipv4_peer",
|
||||
"bgp_ipv6_peer",
|
||||
"domains_resolved",
|
||||
"empty_static",
|
||||
"filter_export",
|
||||
"large_prefix_list",
|
||||
"mixed_static_bgp",
|
||||
"minimal",
|
||||
"static_ipv4",
|
||||
"with_include",
|
||||
}
|
||||
var gotNames []string
|
||||
for _, p := range paths {
|
||||
gotNames = append(gotNames, path.Base(p))
|
||||
}
|
||||
slices.Sort(gotNames)
|
||||
if !slices.Equal(gotNames, wantNames) {
|
||||
t.Fatalf("scenario set drift: got %v want %v", gotNames, wantNames)
|
||||
}
|
||||
|
||||
for _, p := range paths {
|
||||
t.Run(path.Base(p), func(t *testing.T) {
|
||||
b, err := ReadScenarioBirdConf(p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(b) == 0 {
|
||||
t.Fatal("empty bird.conf")
|
||||
}
|
||||
if !strings.Contains(string(b), "router id") {
|
||||
t.Fatal("expected router id in scenario")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepoRelativeBirdConf_Table(t *testing.T) {
|
||||
paths, err := BirdScenarioPaths()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, p := range paths {
|
||||
rel := RepoRelativeBirdConf(p)
|
||||
if !strings.HasPrefix(rel, "internal/birdfmt/") {
|
||||
t.Fatalf("%s: bad prefix %q", p, rel)
|
||||
}
|
||||
if !strings.HasSuffix(rel, "/bird.conf") {
|
||||
t.Fatalf("%s: expected .../bird.conf, got %q", p, rel)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package birdfmt
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// RenderStaticIPv4Protocol renders a BIRD 2 `protocol static` block for IPv4 prefixes.
|
||||
// Prefixes are sorted for stable output (golden tests, reproducible rev).
|
||||
func RenderStaticIPv4Protocol(protocolName string, prefixes []netip.Prefix) string {
|
||||
if protocolName == "" {
|
||||
protocolName = "evobgp_static_v4"
|
||||
}
|
||||
uniq := make(map[string]netip.Prefix)
|
||||
for _, p := range prefixes {
|
||||
if !p.Addr().Is4() {
|
||||
continue
|
||||
}
|
||||
uniq[p.String()] = p.Masked()
|
||||
}
|
||||
keys := make([]string, 0, len(uniq))
|
||||
for k := range uniq {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
var b strings.Builder
|
||||
b.WriteString("protocol static ")
|
||||
b.WriteString(protocolName)
|
||||
b.WriteString(" {\n ipv4;\n")
|
||||
for _, k := range keys {
|
||||
b.WriteString(" route ")
|
||||
b.WriteString(k)
|
||||
b.WriteString(" unreachable;\n")
|
||||
}
|
||||
b.WriteString("}\n")
|
||||
return b.String()
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package birdfmt
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"net/netip"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
//go:embed testdata/golden/static_ipv4_small.golden
|
||||
var goldenStaticIPv4Small string
|
||||
|
||||
func TestRenderStaticIPv4Protocol_Golden(t *testing.T) {
|
||||
p1 := netip.MustParsePrefix("203.0.113.0/24")
|
||||
p2 := netip.MustParsePrefix("198.51.100.0/24")
|
||||
// duplicate to assert dedup
|
||||
got := RenderStaticIPv4Protocol("evobgp_test", []netip.Prefix{p1, p2, p1})
|
||||
|
||||
want := strings.TrimSuffix(goldenStaticIPv4Small, "\n")
|
||||
got = strings.TrimSuffix(got, "\n")
|
||||
if got != want {
|
||||
t.Fatalf("golden mismatch\n--- got ---\n%s\n--- want ---\n%s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderStaticIPv4Protocol_Empty(t *testing.T) {
|
||||
got := RenderStaticIPv4Protocol("evobgp_empty", nil)
|
||||
if !strings.Contains(got, "protocol static evobgp_empty") {
|
||||
t.Fatal(got)
|
||||
}
|
||||
if !strings.Contains(got, "ipv4") {
|
||||
t.Fatal(got)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
protocol static evobgp_test {
|
||||
ipv4;
|
||||
route 198.51.100.0/24 unreachable;
|
||||
route 203.0.113.0/24 unreachable;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
# tags: peer, ipv4, ipv6, mixed
|
||||
router id 192.0.2.1;
|
||||
|
||||
protocol device {
|
||||
}
|
||||
|
||||
protocol direct {
|
||||
ipv4;
|
||||
ipv6;
|
||||
}
|
||||
|
||||
protocol bgp peer_a {
|
||||
local 192.0.2.1 as 65001;
|
||||
neighbor 192.0.2.2 as 65002;
|
||||
ipv4 {
|
||||
import all;
|
||||
export all;
|
||||
};
|
||||
}
|
||||
|
||||
protocol bgp peer_b {
|
||||
local fd00:ebgp::1 as 65001;
|
||||
neighbor fd00:ebgp::3 as 65003;
|
||||
ipv6 {
|
||||
import all;
|
||||
export all;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# tags: peer, ipv4, AS_PREFIXES
|
||||
router id 192.0.2.1;
|
||||
|
||||
protocol device {
|
||||
}
|
||||
|
||||
protocol direct {
|
||||
ipv4;
|
||||
ipv6;
|
||||
}
|
||||
|
||||
protocol bgp peer_v4 {
|
||||
local 192.0.2.1 as 65001;
|
||||
neighbor 192.0.2.2 as 65002;
|
||||
ipv4 {
|
||||
import all;
|
||||
export all;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# tags: peer, ipv6, AS_PREFIXES
|
||||
router id 192.0.2.1;
|
||||
|
||||
protocol device {
|
||||
}
|
||||
|
||||
protocol direct {
|
||||
ipv4;
|
||||
ipv6;
|
||||
}
|
||||
|
||||
protocol bgp peer_v6 {
|
||||
local fd00:ebgp::1 as 65001;
|
||||
neighbor fd00:ebgp::2 as 65002;
|
||||
ipv6 {
|
||||
import all;
|
||||
export all;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
# tags: DOMAINS, module_output
|
||||
# DOMAINS modules materialize to prefixes before render; same shape as static IPv4.
|
||||
|
||||
router id 192.0.2.1;
|
||||
|
||||
protocol device {
|
||||
}
|
||||
|
||||
protocol direct {
|
||||
ipv4;
|
||||
ipv6;
|
||||
}
|
||||
|
||||
protocol static evobgp_from_domains {
|
||||
ipv4;
|
||||
route 192.0.2.10/32 unreachable;
|
||||
route 192.0.2.11/32 unreachable;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# tags: edge, IP_RANGES
|
||||
# Empty static IPv4 table (generator must emit valid empty protocol).
|
||||
|
||||
router id 192.0.2.1;
|
||||
|
||||
protocol device {
|
||||
}
|
||||
|
||||
protocol direct {
|
||||
ipv4;
|
||||
ipv6;
|
||||
}
|
||||
|
||||
protocol static evobgp_empty {
|
||||
ipv4;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
# tags: community, filter, peer
|
||||
# Export filter (placeholder for community-aware export).
|
||||
|
||||
router id 192.0.2.1;
|
||||
|
||||
protocol device {
|
||||
}
|
||||
|
||||
protocol direct {
|
||||
ipv4;
|
||||
ipv6;
|
||||
}
|
||||
|
||||
filter evobgp_export_v4 {
|
||||
if net ~ [ 203.0.113.0/24 ] then accept;
|
||||
reject;
|
||||
}
|
||||
|
||||
protocol bgp peer_filtered {
|
||||
local 192.0.2.1 as 65001;
|
||||
neighbor 192.0.2.2 as 65002;
|
||||
ipv4 {
|
||||
import all;
|
||||
export filter evobgp_export_v4;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
# tags: stress, CDN_CIDRS
|
||||
router id 192.0.2.1;
|
||||
|
||||
include "bird.d/bulk_static.conf";
|
||||
|
||||
protocol device {
|
||||
}
|
||||
|
||||
protocol direct {
|
||||
ipv4;
|
||||
ipv6;
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
protocol static evobgp_bulk {
|
||||
ipv4;
|
||||
route 10.200.0.0/24 unreachable;
|
||||
route 10.200.1.0/24 unreachable;
|
||||
route 10.200.2.0/24 unreachable;
|
||||
route 10.200.3.0/24 unreachable;
|
||||
route 10.200.4.0/24 unreachable;
|
||||
route 10.200.5.0/24 unreachable;
|
||||
route 10.200.6.0/24 unreachable;
|
||||
route 10.200.7.0/24 unreachable;
|
||||
route 10.200.8.0/24 unreachable;
|
||||
route 10.200.9.0/24 unreachable;
|
||||
route 10.200.10.0/24 unreachable;
|
||||
route 10.200.11.0/24 unreachable;
|
||||
route 10.200.12.0/24 unreachable;
|
||||
route 10.200.13.0/24 unreachable;
|
||||
route 10.200.14.0/24 unreachable;
|
||||
route 10.200.15.0/24 unreachable;
|
||||
route 10.200.16.0/24 unreachable;
|
||||
route 10.200.17.0/24 unreachable;
|
||||
route 10.200.18.0/24 unreachable;
|
||||
route 10.200.19.0/24 unreachable;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
# tags: baseline, master
|
||||
# Minimal BIRD 2 skeleton (device + direct), no EvoBGP-generated fragments yet.
|
||||
|
||||
router id 192.0.2.1;
|
||||
|
||||
protocol device {
|
||||
}
|
||||
|
||||
protocol direct {
|
||||
ipv4;
|
||||
ipv6;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
# tags: IP_RANGES, CDN_CIDRS, peer, combined
|
||||
# Combined static materialization + BGP session (multi-module revision sketch).
|
||||
|
||||
router id 192.0.2.1;
|
||||
|
||||
protocol device {
|
||||
}
|
||||
|
||||
protocol direct {
|
||||
ipv4;
|
||||
ipv6;
|
||||
}
|
||||
|
||||
protocol static evobgp_prefixes {
|
||||
ipv4;
|
||||
route 203.0.113.0/24 unreachable;
|
||||
route 203.0.114.0/24 unreachable;
|
||||
}
|
||||
|
||||
protocol bgp uplink {
|
||||
local 192.0.2.1 as 65001;
|
||||
neighbor 192.0.2.2 as 65002;
|
||||
ipv4 {
|
||||
import all;
|
||||
export all;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
# tags: IP_RANGES, module_output
|
||||
# Static IPv4 routes only (materialized prefix list style).
|
||||
|
||||
router id 192.0.2.1;
|
||||
|
||||
protocol device {
|
||||
}
|
||||
|
||||
protocol direct {
|
||||
ipv4;
|
||||
ipv6;
|
||||
}
|
||||
|
||||
protocol static evobgp_v4 {
|
||||
ipv4;
|
||||
route 198.51.100.0/24 unreachable;
|
||||
route 203.0.113.0/24 unreachable;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
# tags: baseline, include
|
||||
# Operator shell includes generated fragments from bird.d/
|
||||
|
||||
router id 192.0.2.1;
|
||||
|
||||
include "bird.d/static.conf";
|
||||
|
||||
protocol device {
|
||||
}
|
||||
|
||||
protocol direct {
|
||||
ipv4;
|
||||
ipv6;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
protocol static evobgp_inc {
|
||||
ipv4;
|
||||
route 203.0.113.0/24 unreachable;
|
||||
}
|
||||
Reference in New Issue
Block a user