Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
181 changes: 181 additions & 0 deletions DEMO_README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# MILCOM Demo — Running the Jammer Attacks

Step-by-step guide for running the software-defined USRP jammer during the
MILCOM demo. Covers the two attack modes used in the demo (**barrage** and
**random**) and the **clean** baseline (jammer off).

> **Safety / legal:** This jammer transmits real RF. Only run it over the air
> inside a shielded lab or on frequencies you are authorized to use. Keep the
> jammer co-channel with the victim gNB and nothing else.

---

## 1. What each attack does

| Mode | `attack_type` | RF behavior | Config file |
|------|---------------|-------------|-------------|
| **Clean** | *(jammer off)* | No interference — baseline traffic | *(none — do not start the jammer)* |
| **Barrage** | `barrage` | Wideband noise, transmitted **continuously** across the band | `configs/barrage.yaml` |
| **Random** | `random` | Same wideband noise, gated **50 ms ON / 50 ms OFF** (bursty) | `configs/random.yaml` |

The demo classifier is trained on **clean / barrage / random**.

---

## 2. Requirements

- Linux host with a **USRP B210** connected (attack radio)
- **UHD** drivers installed and the device visible (`uhd_find_devices`)
- Build tools: `cmake`, `make`, a C++ compiler

```bash
sudo apt update
sudo apt install build-essential cmake libuhd-dev uhd-host
```

---

## 3. Build the jammer (one time)

From the `jammer/` directory of the repo:

```bash
mkdir -p build && cd build
cmake ..
make -j
```

This produces the `jammer` binary in `jammer/build/`.

> Rebuild (`make -j`) only if you change C++ source. Editing a YAML config does
> **not** require a rebuild.

---

## 4. Confirm the USRP is detected

```bash
uhd_find_devices
```

You should see your B210 listed. If not, replug the USRP and re-run before
starting the demo.

---

## 5. Run each attack

All commands are run from `jammer/build/`. Stop any attack with **Ctrl+C**.

### 5.1 Clean (baseline)

Do **not** start the jammer. Keep the gNB + UE link running with traffic so the
detector sees a clean KPI baseline.

### 5.2 Barrage jamming

```bash
./jammer --config ../configs/barrage.yaml
```

You will see repeating `Transmitting (barrage, fresh buffer)....` lines while it
runs. This transmits continuous wideband noise.

### 5.3 Random (bursty) jamming

```bash
./jammer --config ../configs/random.yaml
```

Output alternates between `Transmitting (random) ON ...` and
`Transmitting (random) IDLE ...` every 50 ms, producing the bursty signature.

---

## 6. Key config parameters

Edit these in the YAML files under `configs/` before the demo to match your
lab. Defaults below are from the checked-in configs.

| Field | Meaning | Barrage / Random default |
|-------|---------|--------------------------|
| `attack_type` | `barrage` or `random` | per file |
| `center_frequency` | Victim carrier center, Hz | `1842050000` (Band 3) |
| `bandwidth` | Jam bandwidth, Hz | `40e6` |
| `sampling_freq` | USRP TX sample rate | `23.04e6` |
| `tx_gain` | USRP TX gain, dB — **controls jamming strength** | `50` |
| `amplitude` | Waveform amplitude (0–1) | `0.7` |
| `num_samples` | Samples per TX buffer | `20000` |
| `burst_duration_ms` | (random only) ON time | `50` |
| `idle_duration_ms` | (random only) OFF time | `50` |
| `device_args` | UHD device selector | `type=b200` |

> **Match `center_frequency` and `sampling_freq` to your gNB.** The jammer must
> sit on the same carrier as the victim gNB for the attack to register in the
> KPIs.

---

## 7. Command-line overrides (no rebuild needed)

Any config field can be overridden on the command line, which is handy for
tuning gain live during the demo without editing files:

```bash
# Raise barrage power on the fly
./jammer --config ../configs/barrage.yaml --tx_gain 55

# Retune to a different carrier
./jammer --config ../configs/barrage.yaml --center_frequency 3619200000

# Switch mode without editing YAML
./jammer --config ../configs/barrage.yaml --attack_type random

# Change the random duty cycle
./jammer --config ../configs/random.yaml --burst_duration_ms 100 --idle_duration_ms 100
```

Supported override flags: `--attack_type`, `--tx_gain`, `--center_frequency`,
`--bandwidth`, `--sampling_freq`, `--amplitude`, `--amplitude_width`,
`--num_samples`, `--initial_phase`, `--burst_duration_ms`, `--idle_duration_ms`,
`--device_args`, `--write_iq`, `--write_csv`.

If KPIs still look clean when jamming, raise `--tx_gain` in ~2 dB steps.

---

## 8. Suggested demo sequence

Run the detector alongside so the audience sees the label change as you toggle
the jammer:

```text
1. Clean — jammer OFF → detector shows "clean"
2. Barrage — ./jammer --config ../configs/barrage.yaml
(Ctrl+C to stop) → detector shows "barrage"
3. Clean — jammer OFF again → detector returns to "clean"
4. Random — ./jammer --config ../configs/random.yaml
(Ctrl+C to stop) → detector shows "random"
```

The detector needs ~30 s of KPI history (its sliding window) before the label
settles after each toggle.

**Live detector (separate terminal, from the `ml/` directory of the repo):**

```bash
source .venv/bin/activate
python detect_live_gnb.py --config config_gnb.yaml --run-id 20260702_190948
```

---

## 9. Troubleshooting

| Symptom | Fix |
|---------|-----|
| `Error: center_frequency, sampling_freq, and tx_gain must be set` | Fill those fields in the YAML (or pass via CLI). |
| No USRP found / UHD error | Run `uhd_find_devices`; replug the B210; check `device_args`. |
| KPIs stay "clean" under jamming | Increase `tx_gain`; confirm `center_frequency` matches the gNB. |
| `Unknown attack_type` | Use exactly `barrage` or `random`. |
| Old behavior after editing `.cc` | Rebuild with `make -j` in `build/`. |
14 changes: 14 additions & 0 deletions configs/barrage.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
attack_type: barrage
amplitude: 0.7
amplitude_width: 0.05
center_frequency: 1842050000
bandwidth: 40e6
initial_phase: 0
sampling_freq: 23.04e6
num_samples: 20000
output_iq_file: "output.fc32"
output_csv_file: "output.csv"
write_iq: false
write_csv: true
device_args: "type=b200"
tx_gain: 50
1 change: 1 addition & 0 deletions configs/basic_jammer.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
attack_type: barrage
amplitude: 0.7
amplitude_width: 0.05
center_frequency: 3.619200e9
Expand Down
42 changes: 42 additions & 0 deletions configs/constant.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
attack_type: constant

# Narrowband Gaussian-noise jammer (v3).
#
# Tuned per published 5G NR jamming experiments at 23.04 MS/s:
# STORM (CEUR 2025) used 1.92 MHz of white noise at ±1.92 MHz offset
# from the SSB center with tx_gain in the 60–80 dB range on a B210.
# Antosik (IEEE 2024) measured ~25 dB power-efficiency gain for
# narrowband over barrage jamming when the waveform is true noise.

amplitude: 0.6
amplitude_width: 0.05

# Baseband offset from LO. 0 = auto-shift to +1.92 MHz to avoid the NR DC
# subcarrier and the B-series DC-offset cancellation null. Try ±1.92 MHz,
# ±3.84 MHz, or any value within ±10 MHz to target different PRB regions.
tone_offset_hz: 0

# Width of the noise band in Hz. 1.92 MHz matches the STORM SSB-attack
# bandwidth; up to ~5 MHz is reasonable. Narrower = more power per
# subcarrier and more "narrowband gain".
jam_bandwidth_hz: 1.92e6

# Legacy fields used by older constant generators; ignored by v3 but kept
# for YAML compatibility.
num_tones: 64

center_frequency: 1842050000
bandwidth: 40e6
initial_phase: 0
sampling_freq: 23.04e6
num_samples: 23040 # 1 ms of waveform at 23.04 MS/s; buffer is re-streamed
output_iq_file: "output.fc32"
output_csv_file: "output.csv"
write_iq: false
write_csv: true
device_args: "type=b200"

# Recommended starting point. Barrage works well around 50; narrowband
# noise with the correct waveform should produce moderate degradation
# at 45–55. If KPIs still look clean, raise in steps of 2 dB.
tx_gain: 50
16 changes: 16 additions & 0 deletions configs/random.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
attack_type: random
burst_duration_ms: 50
idle_duration_ms: 50
amplitude: 0.7
amplitude_width: 0.05
center_frequency: 1842050000
bandwidth: 40e6
initial_phase: 0
sampling_freq: 23.04e6
num_samples: 20000
output_iq_file: "output.fc32"
output_csv_file: "output.csv"
write_iq: false
write_csv: true
device_args: "type=b200"
tx_gain: 50
38 changes: 38 additions & 0 deletions configs/test_constant.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
attack_type: constant

# Narrowband Gaussian-noise constant jammer (v3).
# See configs/constant.yaml and jammer/src/constant.cc for the literature
# references that motivated this design.

amplitude: 0.6
amplitude_width: 0.05

# 0 = auto-shift to +1.92 MHz off LO (avoids the NR DC subcarrier + the
# B-series DC-offset null). Try ±1.92 MHz to target the alternate SSB
# halves, or larger offsets like ±5 MHz to land in the data PRBs.
tone_offset_hz: 0

# 1.92 MHz matches the STORM SSB-attack recipe. Wider (e.g. 3.84e6) hits
# more subcarriers but loses some narrowband gain. Narrower (e.g. 1.0e6)
# concentrates power further.
jam_bandwidth_hz: 1.92e6

num_tones: 64

center_frequency: 1842050000
bandwidth: 40e6
initial_phase: 0
sampling_freq: 23.04e6
num_samples: 23040
output_iq_file: "output.fc32"
output_csv_file: "output.csv"
write_iq: false
write_csv: true
device_args: "type=b200"

# Tuning ladder if results are too weak / too strong:
# gain 45 — first test
# gain 48 — usual sweet spot for moderate degradation
# gain 50 — strong but should not release RRC with this waveform
# gain 52+ — risk of disconnect; back off and try wider jam_bandwidth_hz
tx_gain: 48
16 changes: 16 additions & 0 deletions hdr/args.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ typedef struct db_args_s {
std::string data_id = "";
} db_args_t;

enum class attack_type_t { BARRAGE, CONSTANT, RANDOM };

attack_type_t parseAttackType(const std::string &type);
const char *attackTypeToString(attack_type_t type);

typedef struct all_args_s {
float amplitude;
float amplitude_width;
Expand All @@ -37,6 +42,15 @@ typedef struct all_args_s {
bool write_csv;
rf_args_t rf;

attack_type_t attack_type = attack_type_t::BARRAGE;
float tone_offset_hz = 0.0f;
float burst_duration_ms = 50.0f;
float idle_duration_ms = 50.0f;

// Constant (partial-band noise) jamming controls
float jam_bandwidth_hz = 5.0e6f; // width of narrowband noise around tone_offset_hz
int num_tones = 64; // tones used to synthesize the noise comb

//autoconfig control
bool enable_autoconfigure = false;
db_args_t db;
Expand All @@ -46,4 +60,6 @@ all_args_t parseConfig(const std::string &filename);

void overrideConfig(all_args_t &args, int argc, char *argv[]);

void validateAttackArgs(const all_args_t &args);

#endif // !ARGS_H
14 changes: 14 additions & 0 deletions hdr/attack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef ATTACK_H
#define ATTACK_H

#include "args.h"

#include <complex>
#include <uhd/usrp/multi_usrp.hpp>
#include <vector>

std::vector<std::complex<float>> generate_samples(const all_args_t &args);

void transmission(uhd::usrp::multi_usrp::sptr usrp, const all_args_t &args);

#endif
13 changes: 13 additions & 0 deletions hdr/barrage.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef BARRAGE_H
#define BARRAGE_H

#include "args.h"

#include <complex>
#include <vector>

// Wideband barrage jamming: random frequency and amplitude per sample
// across [center_frequency ± bandwidth/2].
std::vector<std::complex<float>> generate_barrage(const all_args_t &args);

#endif
17 changes: 17 additions & 0 deletions hdr/constant.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef CONSTANT_H
#define CONSTANT_H

#include "args.h"

#include <complex>
#include <vector>

// Constant (narrowband Gaussian noise) jamming: true complex Gaussian
// noise band-limited to jam_bandwidth_hz and centered at tone_offset_hz
// off LO. Method matches published 5G NR jamming experiments on USRP
// B-series at 23.04 MS/s (STORM CEUR 2025; Antosik IEEE 2024) which
// found Gaussian noise raises the UE noise floor instead of being
// rejected by AGC the way discrete CW tones are.
std::vector<std::complex<float>> generate_constant(const all_args_t &args);

#endif
Loading