LOADING

加载过慢请开启缓存 浏览器默认开启

无线电安全基础-从PDU开始理解通信协议是如何构成的(发送篇/未完)

PDU 是什么?

简单理解就是数据块。GNUradio 传统上是流式数据。比如麦克风录音或者天线接收 IQ 数据,这些都是不停的流。但是在现代通信协议当中比如说 WIFI、蓝牙它们都是一包一包数据的进行传输。比如 WIFI 一帧一帧的发。所以每一包数据要整体处理,要知道包头,时间戳,长度等信息

示例

一、在 gnuradio 当中如何生成一个 PDU

通过 RandomPDU Generator 生成 PDU

其四个参数分别影响:PDU 长度范围最少为 15,最大为 150 字节,mask 与 pdu 每一字节做 AND 操作,总长度必须是 Length Modulo 的倍数。

二、PDU +CRC32 校验

在上一个示例的基础上加了 CRC32 校验

先生成一个随机 pdu 包 然后在其尾部补充 4 个 CRC32 校验值

三、一个数据帧的完整实现

在示例二的基础之上我们再加上了 protocol formatter。这个模块的作用是可以根据 Header Format Object 的内容将输入的 PDU 格式化后生成一个符合协议要求的 header 并且再和原先的 payload 组合成新的 PDU

再来看Header Format Object 的内容是如何定义的

参数 内容
Access Code '101010101111101010101'
Threshold 3
Payload Bits per Symbol 1

我们来分别解析这些参数的含义:

  1. Access Code 是一个 “帧同步字”(syncword)。通常发射端会在每个数据包前加上这段固定的比特序列,用来帮助接收端找到包的起始位置
  2. Threshold:在检测 Access Code 时,允许最多3位bit错误(适应噪声)。
  3. Payload Bits per Symbol:1bit对应1个符号(典型的二进制系统,比如 BPSK调制)

来说总结:**Header Format 定义了如何构造前导同步字、以及头部要携带的内容。 **

那么最终的数据包格式为

[Access Code] + [Header] + [Payload]

但是 Access Code不是在PDU本体里,而是更像一个附加前缀。Access Code并不会直接出现在PDU里面,因为PDU属于逻辑层封装,Access Code是物理层同步信号。

这个过程是这样的

[ Access Code ] + [ PDU(Header + Payload + CRC) ]
    ↓
进入物理层调制
    ↓
发送

在这里出现的 PDU 只有Header + Payload + CRC 部分 不含Access Code

四、合并输出

在上面三个例子我们从 GNUradio 是如何输出 PDU 开始到生成一个完整的数据帧。那么现在我们来开始将其合并起来。可能初看这个流程图会觉得很复杂 但是其实它只是将我们前面所学的内容增加了流的输出部分。

这里是我们示例三当中的内容,用于生成 PDU。然后分别输出 header 和 payload 到 PDU to Tagged Stream 块当中。该块顾名思义就是将 PDU 转成流

可以来看一下是如何转化为流的,首先会打包比特。将 8 比特输入的信息转化为 1 比特输出。紧接着进行一个 Map 运算。这个操作比较简单仅仅是将输入改为输出的值。其实就是数据类型的转化( bit 0 -> byte 0; bit 1 -> byte 1 )

然后就到了比较复杂的地方了 Chunks to Symbols 这个块会将我们传输的 byte 转化成对应的 symbol 以便后续传输

那 symbol 是什么呢? 在数字通信中,“符号”是用来表示一个或多个比特的最小传输单位。它不再是简单的 0 或 1,而是一个具有特定数值的信号单元,通常是复数(在这个流程图中是实数,因为是 BPSK)。这些符号就是我们说的“星座图”

这又涉及到一个概念,什么是星座图?

简单来说星座图就是一个字典,它的定义在 Constellation Object中

可以来解析一下该星座图:

  • ID 是星座图名称
  • Constellation Type: Variable Constellation: 表示这是一个可变星座图对象。
  • Symbol Map: digital.psk_2(1): 这是关键。它不直接写出 0, 1 这个列表,而是调用了一个函数 digital.psk_2(1) 来生成符号映射表。
    • digital.psk_2 在 GNU Radio 中特指 BPSK (Binary Phase Shift Keying) 调制。
    • 参数 (1) 通常表示 每符号的比特数 (bits per symbol)。所以 digital.psk_2(1) 就是获取 1 比特/符号 BPSK 的符号映射表。
    • 对于 BPSK (1 bit/symbol),标准的符号映射表通常是:输入比特 0 对应第一个星座点,输入比特 1 对应第二个星座点。这个函数调用会生成这个 [0, 1] 的映射列表。
  • Constellation Points: digital.psk_2(0): 同样,这里调用了函数 digital.psk_2(0) 来生成星座点的列表。
    • 参数 (0) 通常表示获取这个调制方案的星座点本身
    • 对于标准的 BPSK,星座点是位于实数轴上的 -1 和 1。这个函数调用会生成这个 [-1, 1] 的星座点列表(这里的截图显示是 [complex_vector],但对于 BPSK,虚部是 0,所以实际上是 [-1+0j, 1+0j],也就是实数 -1 和 1)。

剩下的一些参数不影响我们的内容。简单来说 这个 Constellation Object 块的作用不仅仅是简单地存贮 -1, 10, 1 这两个列表,它通过调用 digital.psk_2 这个函数,明确地声明了它定义的是一个 BPSK (1比特/符号) 调制方案的星座图

回到我们的解析当中。那么Chunks to Symbols 具体是如何工作的呢?首先从星座图我们可以知道符号分别被定义为了-1,1. 其对应的比特内容为 0,1.这里可以理解为经过Chunks to Symbols 处理后:

  • 原始信息是 0 的时候,就用符号 -1
  • 原始信息是 1 的时候,就用符号 1

.这里是个符号上的对应关系.不是实际的数学意义上的值。这个过程其实就是 Chunks to Symbol 去星座图当中去查询对应的 Symbols,然后将输入的内容翻译成星座图当中对应的符号再输出。(实际上这是个数学的过程,但是在这里我们也没必要深入研究)

输入原始比特 (0 或 1)
↓
根据“星座图(Constellation Object 定义的规则)查找对应的“symbol”
↓
输出查找到的“symbol” (-1 或 1)

那么经过 Chunks to Symbol 处理后就输出到一个 Vitrual Sink 的块当中。这个块的作用是可以用来传输流。这里可以看到我们将处理好的 payload 流和 header 流混合再一起后进行输出。最后显示再外面时域和邻域图上

这样我们完成了一个 PDU 从十六进制转换为比特的操作