Загрузка данных


Привет, Саша! Ты проделал огромную работу, собрав все эти фрагменты из разных документаций. Ты абсолютно прав, что разрозненные инструкции часто сбивают с толку — в них не хватает связующих звеньев (например, как именно "подружить" капризный OAI gNB с Open5GS, как настроить сетевые интерфейсы и что именно вводить в телефон).

Как человек, который изучает системное программирование и понимает, как работают низкоуровневые процессы (ты же разбираешься в event loops и C!), ты легко поймешь архитектуру. Но чтобы всё заработало **с первого раза**, нужно учесть множество нюансов. OAI (OpenAirInterface) очень требователен к параметрам 3GPP, а USRP B200 чувствителен к USB-шине.

Ниже — **максимально подробное, исчерпывающее руководство (Master Guide)**, которое объединяет всё, что ты нашел, и добавляет недостающие шаги. Мы будем использовать тестовый PLMN **999/70** (как в твоих конфигах).

---

### ЭТАП 0: Требования и подготовка "железа"

1. **ПК/Сервер:** Ubuntu 22.04 LTS (это критично, на 24.04 OAI и Open5GS могут иметь конфликты зависимостей). Минимум 16 ГБ ОЗУ, 4 ядра CPU.
2. **USRP B200:** Подключается **строго в USB 3.0** (синий порт). Желательно использовать кабель длиной не более 1-1.5 метров.
3. **SIM-карта:** Программируемая (например, sysmoISIM-SJA2).
4. **Телефон (COTS UE):** Android с модемом Snapdragon (Samsung S22/S23, Xiaomi 12/13 и новее). **iPhone не рекомендуется** — Apple жестко режет функционал для приватных сетей.

---

### ЭТАП 1: Программирование SIM-карты (pySim)

Ты уже нашел правильные инструкции. Давай их зафиксируем.
*Предполагаем, что у тебя есть программатор (например, Omnikey) и Python 3.9+.*

1. Установи зависимости и pySim (как в твоем тексте).
2. Вставь SIM в программатор, проверь, что она видна:
   ```bash
   pcsc_scan
   ```
3. Запиши данные. **Важно:** Ключи `Ki` и `OPc` должны быть записаны на SIM и **точно так же** введены в Open5GS WebUI позже.
   ```bash
   ./pySim-prog.py -n "Test5G" -p 0 -x 999 -y 70 -t sysmoISIM-SJA2 -i 999700000000001 -o <твой_OPc> -k <твой_Ki> -s 8900000000000000001 -a 00000000
   ```
   *(Замени `<твой_OPc>` и `<твой_Ki>` на реальные hex-значения. ADM поставь `00000000` или `12345678`, но **запомни его**, чтобы не заблокировать SIM!)*

---

### ЭТАП 2: Установка и настройка Open5GS (Ядро сети)

Open5GS хранит данные абонентов в MongoDB. Его нужно установить первым.

#### 2.1. Установка MongoDB
```bash
sudo apt update
sudo apt install -y gnupg
curl -fsSL https://pgp.mongodb.com/server-8.0.asc | sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg --dearmor
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/8.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list
sudo apt update
sudo apt install -y mongodb-org
sudo systemctl start mongod
sudo systemctl enable mongod
```

#### 2.2. Установка Open5GS и WebUI
```bash
sudo add-apt-repository ppa:open5gs/latest
sudo apt update
sudo apt install -y open5gs

# Установка Node.js для WebUI
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

# Установка самого WebUI
curl -fsSL https://open5gs.org/open5gs/assets/webui/install | sudo -E bash -
```

#### 2.3. Создание виртуального сетевого интерфейса (ogstun)
Ядро должно куда-то маршрутизировать трафик телефона в интернет.
```bash
sudo ip tuntap add name ogstun mode tun
sudo ip addr add 10.45.0.1/16 dev ogstun
sudo ip link set ogstun mtu 1400 # Важно для избежания фрагментации
sudo ip link set ogstun up
```
*Чтобы интерфейс создавался после перезагрузки, добавь эти команды в `/etc/rc.local` или создай systemd-сервис.*

#### 2.4. Настройка NAT (чтобы телефон вышел в Интернет)
```bash
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -A POSTROUTING -s 10.45.0.0/16 ! -o ogstun -j MASQUERADE
```

#### 2.5. Конфигурация Open5GS (Самое важное для связки с OAI!)
OAI gNB очень капризен. Он ожидает четкого соответствия параметрам. Открываем файлы и редактируем.

**Файл `/etc/open5gs/amf.yaml`** (Убедись, что выглядит так):
```yaml
amf:
  sbi:
    server:
      - address: 127.0.0.5
        port: 7777
  ngap:
    server:
      - address: 127.0.0.5
  guami:
    - plmn_id:
        mcc: 999
        mnc: 70
      amf_id:
        region: 2
        set: 1
  tai:
    - plmn_id:
        mcc: 999
        mnc: 70
      tac: 1
  plmn_support:
    - plmn_id:
        mcc: 999
        mnc: 70
      s_nssai:
        - sst: 1
          sd: ffffff # OAI часто требует явного указания SD
  security:
    integrity_order : [ NIA2, NIA1, NIA0 ]
    ciphering_order : [ NEA0, NEA1, NEA2 ]
```

**Файл `/etc/open5gs/smf.yaml`** (Проверь DNN):
```yaml
smf:
  sbi:
    server:
      - address: 127.0.0.4
        port: 7777
  pfcp:
    server:
      - address: 127.0.0.4
  session:
    - subnet: 10.45.0.0/16
      dnn: internet
```

**Файл `/etc/open5gs/upf.yaml`**:
```yaml
upf:
  pfcp:
    server:
      - address: 127.0.0.7
  gtpu:
    server:
      - address: 127.0.0.7
  session:
    - subnet: 10.45.0.0/16
```

Перезапускаем ядро:
```bash
sudo systemctl restart open5gs-amfd open5gs-smfd open5gs-upfd open5gs-nrfd open5gs-ausfd open5gs-udmd open5gs-pcfd open5gs-nssfd open5gs-bsfd open5gs-udrd
```

#### 2.6. Регистрация абонента в WebUI
1. Открой браузер: `http://localhost:9999` (admin / 1423).
2. Перейди в **Subscriber** -> нажми **(+)**.
3. Заполни:
   * **IMSI:** `999700000000001`
   * **K и OPc:** Впиши ровно те же hex-значения, что зашил в SIM на Этапе 1!
   * **APN/DNN:** `internet`
   * **Slice (S-NSSAI):** SST: `1`, SD: `ffffff`
4. Нажми **SAVE**.

---

### ЭТАП 3: Сборка OpenAirInterface (gNB)

#### 3.1. Установка UHD (Драйвер для USRP)
Не собирай UHD из исходников, если не хочешь тратить 2 часа. В Ubuntu 22.04 есть готовые пакеты, которых хватит для B200.
```bash
sudo apt install -y software-properties-common
sudo add-apt-repository -y ppa:ettusresearch/uhd
sudo apt update
sudo apt install -y libuhd-dev uhd-host

# Обязательно скачай прошивки для USRP (займет время)!
sudo uhd_images_downloader
```
*Проверь, что USRP виден:* Подключи B200 и выполни `uhd_find_devices`. Ты должен увидеть строку с `name=B200...`.

#### 3.2. Сборка OAI gNB
```bash
sudo apt install -y git cmake build-essential ninja-build python3-pip libboost-all-dev libusb-1.0-0-dev libssl-dev libxml2-dev libxslt1-dev

git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/openairinterface5g
cd ~/openairinterface5g
git checkout develop

cd cmake_targets
./build_oai -I --install-optional-packages -w USRP -C  # Установка зависимостей
./build_oai --gNB -w USRP -C                           # Компиляция RAN
```

#### 3.3. Конфигурация gNB (Магия связки с Open5GS)
Создай файл конфига `~/openairinterface5g/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.51prb.usrpb200.conf`.
**Внимание:** OAI использует старый синтаксис `.conf`, а не `.yaml`. Скопируй этот конфиг целиком, он уже настроен на работу с твоим Open5GS на локальной машине:

```conf
Active_gNBs = ( "gNB-open5gs");
Asn1_verbosity = "none";

gNBs =
(
 {
    ////////// Identification parameters:
    gNB_ID    =  0xe00;
    gNB_name  =  "gNB-open5gs";

    tracking_area_code  =  1;
    plmn_list = ({ mcc = 999; mnc = 70; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) });
    nr_cellid = 12345678L;

    ////////// Physical parameters:
    servingCellConfigCommon = (
    {
      physCellId = 0;
      absoluteFrequencySSB = 640704;
      dl_frequencyBand = 78;
      dl_absoluteFrequencyPointA = 639996;
      dl_offstToCarrier = 0;
      dl_subcarrierSpacing = 1; # 30 kHz
      dl_carrierBandwidth = 51;
      initialDLBWPlocationAndBandwidth = 13750;
      initialDLBWPsubcarrierSpacing = 1;
      initialDLBWPcontrolResourceSetZero = 12;
      initialDLBWPsearchSpaceZero = 0;

      ul_frequencyBand = 78;
      ul_offstToCarrier = 0;
      ul_subcarrierSpacing = 1;
      ul_carrierBandwidth = 51;
      pMax = 20;
      initialULBWPlocationAndBandwidth = 13750;
      initialULBWPsubcarrierSpacing = 1;

      prach_ConfigurationIndex = 98;
      prach_msg1_FDM = 0;
      prach_msg1_FrequencyStart = 0;
      zeroCorrelationZoneConfig = 13;
      preambleReceivedTargetPower = -96;
      preambleTransMax = 6;
      powerRampingStep = 1;
      ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
      ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14;
      ra_ContentionResolutionTimer = 7;
      rsrp_ThresholdSSB = 19;
      prach_RootSequenceIndex_PR = 2;
      prach_RootSequenceIndex = 1;
      msg1_SubcarrierSpacing = 1;
      restrictedSetConfig = 0;
      msg3_DeltaPreamble = 1;
      p0_NominalWithGrant = -90;

      pucchGroupHopping = 0;
      hoppingId = 40;
      p0_nominal = -90;

      ssb_PositionsInBurst_Bitmap = 1;
      ssb_periodicityServingCell = 2;
      dmrs_TypeA_Position = 0;
      subcarrierSpacing = 1;

      dl_UL_TransmissionPeriodicity = 6;
      nrofDownlinkSlots = 7;
      nrofDownlinkSymbols = 6;
      nrofUplinkSlots = 2;
      nrofUplinkSymbols = 4;

      ssPBCH_BlockPower = -25;
    });

    SCTP : { SCTP_INSTREAMS = 2; SCTP_OUTSTREAMS = 2; };

    ////////// AMF parameters:
    amf_ip_address = ({ ipv4 = "127.0.0.5"; });

    NETWORK_INTERFACES :
    {
        GNB_IPV4_ADDRESS_FOR_NG_AMF = "127.0.0.1";
        GNB_IPV4_ADDRESS_FOR_NGU    = "127.0.0.1";
        GNB_PORT_FOR_S1U            = 2152;
    };
  }
);

MACRLCs = ( { num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; pusch_TargetSNRx10 = 200; pucch_TargetSNRx10 = 200; } );
L1s = ( { num_cc = 1; tr_n_preference = "local_mac"; prach_dtx_threshold = 120; pucch0_dtx_threshold = 100; } );

RUs = (
{
  local_rf       = "yes"
  nb_tx          = 1
  nb_rx          = 1
  att_tx         = 10;
  att_rx         = 10;
  bands          = [78];
  max_pdschReferenceSignalPower = -27;
  max_rxgain                    = 114;
  eNB_instances  = [0];
  clock_src = "internal";
}
);

security = {
  ciphering_algorithms = ( "nea0" );
  integrity_algorithms = ( "nia2", "nia0" );
  drb_ciphering = "yes";
  drb_integrity = "no";
};

log_config : {
  global_log_level = "info";
  hw_log_level     = "info";
  phy_log_level    = "info";
  mac_log_level    = "info";
  rlc_log_level    = "info";
  pdcp_log_level   = "info";
  rrc_log_level    = "info";
  ngap_log_level   = "debug";
};
```
*Обрати внимание на `NETWORK_INTERFACES`: мы жестко задали `127.0.0.1`, так как ядро и RAN на одной машине. Это избавит от проблем с маршрутизацией.*

---

### ЭТАП 4: Запуск сети (Порядок критичен!)

Открой **три терминала**.

**Терминал 1: Логи ядра (чтобы видеть, что происходит)**
```bash
sudo journalctl -u open5gs-amfd -f
```

**Терминал 2: Запуск gNB (OAI)**
```bash
cd ~/openairinterface5g/cmake_targets/ran_build/build
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.51prb.usrpb200.conf --sa -E --continuous-tx
```
*Жди, пока в логах не появится строка:* `[NR_RRC] eNB connected to AMF` или `NGAP: Connection established`. Это значит, что RAN "постучалась" в ядро.

---

### ЭТАП 5: Подключение COTS UE (Телефона)

Это этап, на котором 90% людей сдаются. Телефон не хочет подключаться, потому что думает, что это "чужая" сеть.

1. **Вставь SIM-карту** в телефон.
2. **Настройки мобильной сети:**
   * **Точка доступа (APN):** Создай новую. Имя: `internet`, APN: `internet`. Остальное оставь пустым. Сохрани и выбери её.
   * **Роуминг:** **ОБЯЗАТЕЛЬНО включи "Роуминг данных" (Data Roaming)**. Так как PLMN 999/70 не является домашним для телефона, без роуминга ядро отвергнет регистрацию.
   * **Тип сети:** Выбери "Только 5G" (или 5G SA). Отключи 4G/LTE.
3. **Инженерное меню (Если телефон не видит сеть):**
   * На Samsung: `*#0011#` (просмотр) или `*#2263#` (настройка). Тебе нужно принудительно выбрать Band 78 (n78).
   * На Xiaomi/Android: `*#*#4636#*#*` -> Phone Information -> Set Preferred Network Type -> **5G NR Only**.
4. **Отключи VoLTE и VoNR** в настройках телефона (если есть такая галочка). Голосовые сервисы в приватных сетях часто вызывают сбой регистрации.
5. **Включи и выключи Авиарежим**, чтобы заставить модем пересканировать эфир.

---

### ЭТАП 6: Диагностика и решение проблем

Поднеси телефон вплотную к антеннам USRP. Смотри в **Терминал 1** (логи AMF).

**Сценарий А: Телефон видит сеть, но не регистрируется (ошибка Authentication Failure)**
* **Причина:** Не совпадают ключи.
* **Решение:** Зайди в WebUI Open5GS (`localhost:9999`) и перепроверь, что `Ki` и `OPc` побуквенно совпадают с тем, что ты зашил в SIM через pySim.

**Сценарий Б: В логах AMF видно `Registration Reject`, причина `#11` (PLMN not allowed) или `#13` (Roaming not allowed)**
* **Причина:** Телефон не пускает в сеть из-за политик роуминга.
* **Решение:** Убедись, что в настройках телефона включен **Роуминг данных**. В конфиге `amf.yaml` убедись, что нет секции `access_control`, которая блокирует PLMN 999/70.

**Сценарий В: В логах OAI gNB сыплются ошибки `O` (Overflows) или `U` (Underflows)**
* **Причина:** USRP B200 не успевает передавать данные по USB 3.0.
* **Решение:**
  1. Убедись, что USRP воткнут напрямую в порт USB 3.0 на материнской плате (не через хаб, не через переднюю панель корпуса).
  2. В конфиге OAI уменьши количество PRB с 51 до 25 или 11 (измени `dl_carrierBandwidth` и `ul_carrierBandwidth`, а также `initialDLBWPlocationAndBandwidth`).
  3. Увеличь буфер USB: `sudo sysctl -w net.core.rmem_max=62500000` и `sudo sysctl -w net.core.wmem_max=62500000`.

**Сценарий Г: Телефон зарегистрировался (в логах AMF: `Registration Accept`), но интернет не работает (пинг не идет)**
* **Причина:** Проблема с NAT или UPF.
* **Решение:** Проверь, что интерфейс `ogstun` поднят (`ip a s ogstun`). Проверь, что в `upf.yaml` указан правильный `subnet: 10.45.0.0/16`. Убедись, что на хосте включен `ip_forward=1`.

---

### Финальная проверка
Если всё прошло успешно:
1. В терминале OAI ты увидишь: `[RRC] UE rnti=xxxx has entered RRC_CONNECTED`.
2. В терминале AMF: `UE SUPI[999700000000001] Registration complete`.
3. На экране телефона появится иконка **5G** (без стрелочек вверх-вниз, если нет трафика, или со стрелочками, если пингуешь).
4. Попробуй пинг с телефона: `ping -i 1 8.8.8.8`.

Саша, эта сборка — классический "hello world" в мире телекома, и она требует внимательности к деталям. Если на каком-то шаге что-то пойдет не так, не расстраивайся. В 99% случаев проблема кроется либо в опечатке в `Ki/OPc`, либо в том, что телефон не переключился в режим "5G Only" / "Роуминг".

Смотри в логи, анализируй их (твой бэкграунд в системном программировании тебе в этом очень поможет — ты понимаешь, как работают сокеты и события). У тебя всё получится! Если застрянешь на конкретной ошибке в логах — пиши, разберем её побайтно.