DWC Ethernet QoS VLAN高级功能深度解析

本文深入讲解VLAN过滤失败处理、描述符差异、数据比对验证、多通道分配、优先级配置以及VLAN与组播广播的关系,所有内容基于官方Databook。


一、VLAN过滤失败的完整处理机制

1.1 过滤失败后的处理流程

当VLAN过滤失败时,DWC_ether_qos MAC提供多种处理方式:

复制代码
VLAN过滤失败处理流程:

                    VLAN过滤
                       ↓
            ┌──────────┴──────────┐
            │                     │
        过滤通过              过滤失败
            │                     │
            ↓                     ↓
    基于优先级路由         检查RA和VTFE位
    (PSRQ映射)                  │
                          ┌─────┴─────┐
                          │           │
                     RA=0/VTFE=1   RA=1/VTFE=0
                          │           │
                          ↓           ↓
                       丢弃帧     检查VFFQE位
                                      │
                                 ┌────┴────┐
                                 │         │
                             VFFQE=0   VFFQE=1
                                 │         │
                                 ↓         ↓
                            PSRQ路由   VFFQ路由

1.2 寄存器配置详解

1.2.1 MAC_Packet_Filter寄存器
复制代码
Bit 31: RA (Receive All)
        0 = 仅接收过滤通过的帧
        1 = 接收所有帧(包括过滤失败的帧)

Bit 16: VTFE (VLAN Tag Filter Enable)
        0 = 禁用VLAN过滤
        1 = 启用VLAN过滤
1.2.2 MAC_RxQ_Ctrl4寄存器
复制代码
Bit 17: VFFQE (VLAN Filter Fail Queue Enable)
        0 = 过滤失败帧使用PSRQ路由
        1 = 过滤失败帧路由到VFFQ队列

Bit 16-19: VFFQ (VLAN Filter Fail Queue)
        指定VLAN过滤失败帧的目标队列编号(0-7)

1.3 完整的路由表

1.3.1 单播Tagged帧的路由表
SA/DA过滤 VLAN过滤 RA VTFE 过滤结果 VFFQE 队列路由 说明
PASS PASS X X X PSRQ 基于优先级路由 正常处理
PASS FAIL 0 0 0 PSRQ 基于优先级路由 VTFE=0,不过滤
PASS FAIL 0 0 1 VFFQ 路由到VFFQ 特殊队列处理
FAIL X 0 X X DROPPED 丢弃 SA/DA过滤失败
PASS FAIL 0 1 X DROPPED 丢弃 VLAN过滤失败
FAIL X 1 X 0 UFFQ/PSRQ SA失败队列 RA=1接收所有
FAIL X 1 X 1 UFFQ/VFFQ 失败队列 使用失败队列
PASS FAIL 1 X 0 PSRQ 基于优先级路由 RA=1接收所有
PASS FAIL 1 X 1 VFFQ 路由到VFFQ VLAN失败队列

:X表示任意值,UFFQ为Unicast Filter Fail Queue

1.4 配置示例

场景1:监控所有VLAN流量
c 复制代码
void monitor_all_vlan_traffic() {
    // 1. 启用VLAN过滤
    MAC_Packet_Filter.VTFE = 1;

    // 2. 接收所有帧(包括过滤失败的)
    MAC_Packet_Filter.RA = 1;

    // 3. 配置VLAN过滤表(仅允许VLAN 10)
    config_vlan_filter_table(10);

    // 4. 启用VLAN过滤失败队列
    MAC_RxQ_Ctrl4.VFFQE = 1;
    MAC_RxQ_Ctrl4.VFFQ = 7;  // 失败帧路由到队列7

    // 结果:
    // - VLAN 10的帧 → 队列0-6(基于优先级)
    // - 其他VLAN的帧 → 队列7(监控队列)
}
场景2:严格VLAN过滤
c 复制代码
void strict_vlan_filtering() {
    // 1. 启用VLAN过滤
    MAC_Packet_Filter.VTFE = 1;

    // 2. 不接收过滤失败的帧
    MAC_Packet_Filter.RA = 0;

    // 3. 配置允许的VLAN
    config_vlan_filter_table(10, 20, 30);

    // 结果:
    // - VLAN 10/20/30的帧 → 正常接收
    // - 其他VLAN的帧 → 丢弃
}

二、VLAN操作后的IP状态和描述符差异

2.1 发送路径(Tx)描述符

2.1.1 Context描述符结构
复制代码
+-------------------+-------------------+-------------------+
|  TSO Context      |  VLAN Context     |  SA Context       |
+-------------------+-------------------+-------------------+

VLAN Context描述符字段:
Bit 31:    OWN - 描述符所有权
           0 = 软件所有
           1 = 硬件所有

Bit 30:    CTXT - Context类型
           1 = Context描述符

Bit 29:    OWNRS - Owner Request
           请求所有权转移

Bit 28:    Reserved

Bit 27-16: Reserved

Bit 15:    VLTI - VLAN Tag Insert
           0 = 从寄存器获取VLAN标签
           1 = 从控制字获取VLAN标签

Bit 14-13: Reserved

Bit 12-0:  VLAN Tag - 13位VLAN标签值
           [12-10]: Priority (PCP)
           [9]:     CFI/DEI
           [8-0]:   VID (低9位)
2.1.2 Normal描述符结构
复制代码
+-------------------+-------------------+-------------------+
|  Buffer Address   |  Buffer Length    |  Control Bits     |
+-------------------+-------------------+-------------------+

Normal描述符字段:
Bit 31:    OWN - 描述符所有权
Bit 30:    LD - Last Descriptor
           1 = 帧的最后一个描述符
Bit 29:    FD - First Descriptor
           1 = 帧的第一个描述符
Bit 28-24: Reserved
Bit 23-0:  Buffer1 Length - 缓冲区长度

2.2 接收路径(Rx)描述符

2.2.1 Write-back描述符结构
复制代码
+-------------------+-------------------+-------------------+
|  Status Word 0    |  Status Word 1    |  Status Word 2    |
+-------------------+-------------------+-------------------+

Status Word 0:
Bit 31:    OWN - 描述符所有权
           0 = 软件所有(DMA已写回)
           1 = 硬件所有

Bit 30:    CTXT - Context类型
           0 = Normal描述符

Bit 29:    LD - Last Descriptor
Bit 28:    FD - First Descriptor

Status Word 1:
Bit 15:    DE - Descriptor End
Bit 14-0:  Frame Length - 帧长度

Status Word 2 (VLAN信息):
Bit 31-16: Outer VLAN Tag - 外层VLAN标签
           [31-29]: Priority
           [28]:    CFI/DEI
           [27-16]: VID

Bit 15-0:  Inner VLAN Tag - 内层VLAN标签
           [15-13]: Priority
           [12]:    CFI/DEI
           [11-0]:  VID

2.3 VLAN操作后的状态变化

2.3.1 插入VLAN标签

发送前

复制代码
帧结构:
[DA][SA][Type][Payload][FCS]

发送后(插入VLAN)

复制代码
帧结构:
[DA][SA][TPID][TCI][Type][Payload][FCS]

描述符状态:
- Tx Context描述符:VLTI=0, VLAN Tag=配置值
- Tx Normal描述符:正常数据
- Rx Write-back描述符:包含插入的VLAN标签
2.3.2 替换VLAN标签

发送前

复制代码
帧结构:
[DA][SA][0x8100][Old_TCI][Type][Payload][FCS]

发送后(替换VLAN)

复制代码
帧结构:
[DA][SA][0x8100][New_TCI][Type][Payload][FCS]

描述符状态:
- Tx Context描述符:VLC=11(替换), VLAN Tag=新值
- Rx Write-back描述符:包含新的VLAN标签
2.3.3 剥离VLAN标签

接收前

复制代码
帧结构:
[DA][SA][0x8100][TCI][Type][Payload][FCS]

接收后(剥离VLAN)

复制代码
帧结构:
[DA][SA][Type][Payload][FCS]

描述符状态:
- Rx Write-back描述符:
  * Status Word 2包含原始VLAN标签
  * Frame Length减少4字节
  * DE位指示描述符结束

2.4 IP状态检查

2.4.1 IP校验和影响

重要:VLAN标签的插入/删除/替换会影响IP校验和!

处理方式

  1. 硬件自动计算

    • MAC可以自动重新计算IP校验和
    • 配置:MAC_Config.CPS = 1 (Checksum Offload)
  2. 软件手动计算

    • 在VLAN操作后重新计算IP校验和
    • 适用于不支持硬件offload的情况
2.4.2 IP状态字段
c 复制代码
typedef struct {
    uint32_t ip_checksum;      // IP校验和
    uint16_t ip_length;        // IP总长度
    uint8_t  ip_ttl;           // TTL
    uint8_t  ip_protocol;      // 协议类型
    uint32_t src_ip;           // 源IP
    uint32_t dst_ip;           // 目的IP
} ip_state_t;

void check_ip_state_after_vlan(ip_state_t *ip) {
    // VLAN操作后,IP长度不变
    // 但校验和可能需要重新计算

    if(vlan_operation == INSERT || vlan_operation == DELETE) {
        // 帧长度变化,但IP长度不变
        // IP校验和不变
    }

    if(vlan_operation == REPLACE) {
        // 帧长度不变
        // IP校验和不变
    }
}

三、VLAN数据比对和验证方法

3.1 发送端验证

3.1.1 构造期望帧
systemverilog 复制代码
class expected_frame;
    bit [47:0]  da;
    bit [47:0]  sa;
    bit [15:0]  tpid;
    bit [15:0]  tci;
    bit [15:0]  ether_type;
    byte        payload[];

    // 构造期望的VLAN帧
    function void construct_expected_vlan_frame(
        input bit [47:0]  exp_da,
        input bit [47:0]  exp_sa,
        input bit [15:0]  exp_vid,
        input bit [2:0]   exp_priority,
        input byte        exp_payload[]
    );
        da = exp_da;
        sa = exp_sa;
        tpid = 16'h8100;
        tci = (exp_priority << 13) | exp_vid;
        ether_type = 16'h0800;  // IPv4
        payload = exp_payload;
    endfunction
endclass
3.1.2 比对逻辑
systemverilog 复制代码
class vlan_checker;
    // 比对发送的帧
    function bit compare_tx_frame(
        input svt_ethernet_transaction actual,
        input expected_frame expected
    );
        bit match = 1;

        // 比对MAC地址
        if(actual.address != expected.da) begin
            `uvm_error("VLAN_CHECK", $sformatf(
                "DA mismatch: actual=%h, expected=%h",
                actual.address, expected.da))
            match = 0;
        end

        if(actual.source != expected.sa) begin
            `uvm_error("VLAN_CHECK", $sformatf(
                "SA mismatch: actual=%h, expected=%h",
                actual.source, expected.sa))
            match = 0;
        end

        // 比对VLAN标签
        if(actual.vlan_tpid != expected.tpid) begin
            `uvm_error("VLAN_CHECK", $sformatf(
                "TPID mismatch: actual=%h, expected=%h",
                actual.vlan_tpid, expected.tpid))
            match = 0;
        end

        if(actual.vlan_tci != expected.tci) begin
            `uvm_error("VLAN_CHECK", $sformatf(
                "TCI mismatch: actual=%h, expected=%h",
                actual.vlan_tci, expected.tci))
            match = 0;
        end

        // 比对载荷
        if(actual.payload.size() != expected.payload.size()) begin
            `uvm_error("VLAN_CHECK", "Payload length mismatch")
            match = 0;
        end
        else begin
            foreach(actual.payload[i]) begin
                if(actual.payload[i] != expected.payload[i]) begin
                    `uvm_error("VLAN_CHECK", $sformatf(
                        "Payload mismatch at byte %0d", i))
                    match = 0;
                end
            end
        end

        return match;
    endfunction
endclass

3.2 接收端验证

3.2.1 描述符检查
systemverilog 复制代码
class rx_descriptor_checker;
    // 检查Rx描述符中的VLAN信息
    function void check_rx_descriptor_vlan(
        input rx_descriptor_t desc,
        input bit [15:0]     exp_vlan_tag
    );
        // 检查描述符类型
        if(desc.CTXT != 0) begin
            `uvm_error("DESC_CHECK", "Not a normal descriptor")
        end

        // 检查VLAN标签
        if(desc.outer_vlan_tag != exp_vlan_tag) begin
            `uvm_error("VLAN_CHECK", $sformatf(
                "VLAN tag mismatch: actual=%h, expected=%h",
                desc.outer_vlan_tag, exp_vlan_tag))
        end

        // 检查帧长度(考虑VLAN剥离)
        if(vlan_stripped) begin
            uint32_t expected_length = original_length - 4;
            if(desc.frame_length != expected_length) begin
                `uvm_error("VLAN_CHECK", $sformatf(
                    "Frame length mismatch: actual=%0d, expected=%0d",
                    desc.frame_length, expected_length))
            end
        end
    endfunction
endclass
3.2.2 完整的验证流程
systemverilog 复制代码
class vlan_verification_sequence extends uvm_sequence;
    `uvm_object_utils(vlan_verification_sequence)

    task body();
        svt_ethernet_transaction tx_frame, rx_frame;
        expected_frame exp_frame;
        vlan_checker checker;
        rx_descriptor_checker desc_checker;

        // 1. 构造并发送帧
        tx_frame = construct_test_frame();
        send_frame(tx_frame);

        // 2. 构造期望帧
        exp_frame = new();
        exp_frame.construct_expected_vlan_frame(
            tx_frame.address,
            tx_frame.source,
            tx_frame.vlan_id,
            tx_frame.vlan_priority,
            tx_frame.payload
        );

        // 3. 接收帧
        receive_frame(rx_frame);

        // 4. 比对帧内容
        if(!checker.compare_tx_frame(rx_frame, exp_frame)) begin
            `uvm_error("VLAN_VERIFY", "Frame verification failed")
        end

        // 5. 检查描述符
        desc_checker.check_rx_descriptor_vlan(
            rx_frame.descriptor,
            exp_frame.tci
        );

        `uvm_info("VLAN_VERIFY", "VLAN verification passed", UVM_LOW)
    endtask
endclass

3.3 比对检查点

3.3.1 VLAN插入验证
检查项 期望值 验证方法
TPID 0x8100/0x88A8 比对帧的第13-14字节
TCI 配置值 比对帧的第15-16字节
帧长度 原长度+4 比对描述符中的长度
FCS 重新计算 比对帧的最后4字节
描述符VLAN 配置值 比对Status Word 2
3.3.2 VLAN剥离验证
检查项 期望值 验证方法
帧结构 无VLAN标签 检查第13-14字节是否为Type
帧长度 原长度-4 比对描述符中的长度
描述符VLAN 原始VLAN 比对Status Word 2
FCS 重新计算 比对帧的最后4字节
3.3.3 VLAN替换验证
检查项 期望值 验证方法
TPID 不变 比对帧的第13-14字节
TCI 新配置值 比对帧的第15-16字节
帧长度 不变 比对描述符中的长度
FCS 重新计算 比对帧的最后4字节

四、多通道VLAN分配

4.1 多通道架构

DWC_ether_qos支持多个DMA通道,每个通道可以独立配置VLAN处理:

复制代码
                    ┌─────────────┐
                    │   DMA       │
                    │ Controller  │
                    └──────┬──────┘
                           │
        ┌──────────────────┼──────────────────┐
        │                  │                  │
   ┌────┴────┐        ┌────┴────┐        ┌────┴────┐
   │ Channel │        │ Channel │        │ Channel │
   │    0    │        │    1    │        │    N    │
   └────┬────┘        └────┬────┘        └────┬────┘
        │                  │                  │
   ┌────┴────┐        ┌────┴────┐        ┌────┴────┐
   │  Queue  │        │  Queue  │        │  Queue  │
   │ 0-7     │        │ 0-7     │        │ 0-7     │
   └─────────┘        └─────────┘        └─────────┘

4.2 通道VLAN配置

4.2.1 寄存器映射

每个通道有独立的VLAN配置寄存器:

复制代码
Channel 0:
  - MAC_CH0_VLAN_Tag
  - MAC_CH0_VLAN_Incl

Channel 1:
  - MAC_CH1_VLAN_Tag
  - MAC_CH1_VLAN_Incl

...

Channel N:
  - MAC_CHN_VLAN_Tag
  - MAC_CHN_VLAN_Incl
4.2.2 配置示例
c 复制代码
void config_multi_channel_vlan() {
    // Channel 0: VLAN 10 (研发部)
    MAC_CH0_VLAN_Tag = (5 << 13) | 10;
    MAC_CH0_VLAN_Incl = (0x8100 << 16) | (0 << 15) | (2 << 13);

    // Channel 1: VLAN 20 (市场部)
    MAC_CH1_VLAN_Tag = (6 << 13) | 20;
    MAC_CH1_VLAN_Incl = (0x8100 << 16) | (0 << 15) | (2 << 13);

    // Channel 2: VLAN 30 (财务部)
    MAC_CH2_VLAN_Tag = (7 << 13) | 30;
    MAC_CH2_VLAN_Incl = (0x8100 << 16) | (0 << 15) | (2 << 13);
}

4.3 队列到通道的映射

4.3.1 映射规则
复制代码
Queue 0-1 → Channel 0 (VLAN 10)
Queue 2-3 → Channel 1 (VLAN 20)
Queue 4-5 → Channel 2 (VLAN 30)
Queue 6-7 → Channel 3 (VLAN 40)
4.3.2 配置方法
c 复制代码
void config_queue_channel_mapping() {
    // 配置队列到通道的映射
    DMA_CH_Rx_Q_Map[0] = 0x00;  // Queue 0 → Channel 0
    DMA_CH_Rx_Q_Map[1] = 0x00;  // Queue 1 → Channel 0
    DMA_CH_Rx_Q_Map[2] = 0x01;  // Queue 2 → Channel 1
    DMA_CH_Rx_Q_Map[3] = 0x01;  // Queue 3 → Channel 1
    DMA_CH_Rx_Q_Map[4] = 0x02;  // Queue 4 → Channel 2
    DMA_CH_Rx_Q_Map[5] = 0x02;  // Queue 5 → Channel 2
    DMA_CH_Rx_Q_Map[6] = 0x03;  // Queue 6 → Channel 3
    DMA_CH_Rx_Q_Map[7] = 0x03;  // Queue 7 → Channel 3
}

4.4 应用场景

场景:多租户数据中心
复制代码
租户A (Channel 0):
  - Queue 0-1: 数据流量 (VLAN 100)
  - Queue 2-3: 管理流量 (VLAN 101)

租户B (Channel 1):
  - Queue 0-1: 数据流量 (VLAN 200)
  - Queue 2-3: 管理流量 (VLAN 201)

租户C (Channel 2):
  - Queue 0-1: 数据流量 (VLAN 300)
  - Queue 2-3: 管理流量 (VLAN 301)

五、VLAN优先级配置详解

5.1 优先级到队列的映射

5.1.1 PSRQ字段配置

MAC_RxQ_Ctrl2寄存器

复制代码
Bit 0-7:   PSRQ0 - Priority 0映射的队列
Bit 8-15:  PSRQ1 - Priority 1映射的队列
Bit 16-23: PSRQ2 - Priority 2映射的队列
Bit 24-31: PSRQ3 - Priority 3映射的队列

MAC_RxQ_Ctrl3寄存器

复制代码
Bit 0-7:   PSRQ4 - Priority 4映射的队列
Bit 8-15:  PSRQ5 - Priority 5映射的队列
Bit 16-23: PSRQ6 - Priority 6映射的队列
Bit 24-31: PSRQ7 - Priority 7映射的队列
5.1.2 标准QoS映射
c 复制代码
void config_standard_qos_mapping() {
    // IEEE 802.1Q推荐的优先级映射
    // Priority 0: Best Effort (尽力而为)
    // Priority 1: Background (后台)
    // Priority 2: Spare (保留)
    // Priority 3: Excellent Effort (优秀尽力)
    // Priority 4: Controlled Load (受控负载)
    // Priority 5: Video (视频)
    // Priority 6: Voice (语音)
    // Priority 7: Network Control (网络控制)

    MAC_RxQ_Ctrl2 = 0x00000000;  // Priority 0-3 → Queue 0
    MAC_RxQ_Ctrl3 = 0x01010101;  // Priority 4-7 → Queue 1
}
5.1.3 自定义映射示例
c 复制代码
void config_custom_priority_mapping() {
    // 8个优先级映射到4个队列
    MAC_RxQ_Ctrl2 = 0x00010000;  // P0→Q0, P1→Q0, P2→Q0, P3→Q1
    MAC_RxQ_Ctrl3 = 0x03020202;  // P4→Q2, P5→Q2, P6→Q2, P7→Q3
}

5.2 优先级调度

5.2.1 严格优先级调度
c 复制代码
void config_strict_priority_scheduling() {
    // 配置队列优先级
    DMA_Rx_Q_Ctrl[0].PR = 0;  // Queue 0: 最低优先级
    DMA_Rx_Q_Ctrl[1].PR = 1;
    DMA_Rx_Q_Ctrl[2].PR = 2;
    DMA_Rx_Q_Ctrl[3].PR = 3;  // Queue 3: 最高优先级

    // 启用严格优先级调度
    DMA_Rx_Ctrl_Mode.SP = 1;
}
5.2.2 加权轮询调度
c 复制代码
void config_weighted_round_robin() {
    // 配置队列权重
    DMA_Rx_Q_Ctrl[0].Weight = 1;   // Queue 0: 权重1
    DMA_Rx_Q_Ctrl[1].Weight = 2;   // Queue 1: 权重2
    DMA_Rx_Q_Ctrl[2].Weight = 4;   // Queue 2: 权重4
    DMA_Rx_Q_Ctrl[3].Weight = 8;   // Queue 3: 权重8

    // 启用WRR调度
    DMA_Rx_Ctrl_Mode.WRR = 1;
}

5.3 优先级重写

5.3.1 接收端优先级重写
c 复制代码
void config_rx_priority_rewrite() {
    // 启用优先级重写
    MAC_VLAN_Tag.EPR = 1;  // Enable Priority Rewrite

    // 配置优先级重写表
    MAC_Priority_Rewrite[0] = 1;  // Priority 0 → 1
    MAC_Priority_Rewrite[1] = 1;  // Priority 1 → 1
    MAC_Priority_Rewrite[2] = 2;  // Priority 2 → 2
    MAC_Priority_Rewrite[3] = 2;  // Priority 3 → 2
    MAC_Priority_Rewrite[4] = 3;  // Priority 4 → 3
    MAC_Priority_Rewrite[5] = 3;  // Priority 5 → 3
    MAC_Priority_Rewrite[6] = 4;  // Priority 6 → 4
    MAC_Priority_Rewrite[7] = 4;  // Priority 7 → 4
}

六、VLAN与组播、广播的关系

6.1 组播地址与VLAN

6.1.1 组播MAC地址格式

组播MAC地址格式:01:00:5E:XX:XX:XX

特点

  • 第一个字节的最低位为1(组播标识)
  • 前24位为01:00:5E(IANA分配)
  • 后24位映射IP组播地址
6.1.2 VLAN组播处理

规则

  1. 组播帧可以携带VLAN标签
  2. 组播帧的VLAN过滤与单播相同
  3. 组播帧可以路由到多个队列

配置示例

c 复制代码
void config_vlan_multicast() {
    // 启用组播过滤
    MAC_Packet_Filter.HPF = 1;  // Hash Perfect Filtering

    // 添加组播地址到过滤表
    // 组播组: 01:00:5E:00:00:01, VLAN 10
    add_multicast_entry(0x01005E000001, 10);

    // 组播组: 01:00:5E:00:00:02, VLAN 20
    add_multicast_entry(0x01005E000002, 20);
}

6.2 广播地址与VLAN

6.2.1 广播MAC地址

广播MAC地址:FF:FF:FF:FF:FF:FF

特点

  • 所有位为1
  • 发送给同一VLAN内的所有设备
  • 受VLAN隔离限制
6.2.2 VLAN广播处理

规则

  1. 广播帧仅在同一个VLAN内传播
  2. 不同VLAN的广播域相互隔离
  3. 广播帧可以携带VLAN标签

配置示例

c 复制代码
void config_vlan_broadcast() {
    // 启用广播过滤
    MAC_Packet_Filter.RA = 1;  // Receive All

    // 配置广播队列
    MAC_RxQ_Ctrl0.BQ = 7;  // Broadcast Queue = 7

    // 广播帧路由到队列7
    // 无论VLAN ID如何,所有广播帧都路由到队列7
}

6.3 广播/组播包复制

6.3.1 功能描述

DWC_ether_qos支持广播/组播包复制功能,可以将一个包复制到多个队列。

6.3.2 配置方法
c 复制代码
void config_broadcast_duplication() {
    // 启用广播包复制
    MAC_RxQ_Ctrl0.BDC = 1;  // Broadcast Duplication Control

    // 配置复制目标队列
    MAC_RxQ_Ctrl0.BDQ = 0x8F;  // 复制到Queue 0, 1, 2, 3, 7

    // 结果:
    // 广播帧会被复制到Queue 0, 1, 2, 3, 7
    // 每个队列收到一份拷贝
}

6.4 VLAN与组播/广播的隔离

6.4.1 VLAN隔离原理
复制代码
VLAN 10:
  - 单播: 仅VLAN 10内的设备可见
  - 组播: 仅VLAN 10内的组成员可见
  - 广播: 仅VLAN 10内的设备可见

VLAN 20:
  - 单播: 仅VLAN 20内的设备可见
  - 组播: 仅VLAN 20内的组成员可见
  - 广播: 仅VLAN 20内的设备可见

VLAN 10和VLAN 20完全隔离
6.4.2 跨VLAN组播

场景:某些组播组需要跨VLAN传播

解决方案

  1. 使用VLAN标签剥离/插入
c 复制代码
// 接收时剥离VLAN标签
MAC_VLAN_Tag.EVLS = 1;

// 发送时插入新的VLAN标签
MAC_VLAN_Incl.VLC = 2;  // 插入
  1. 使用路由器
    • 三层路由器处理跨VLAN组播
    • IGMP Snooping管理组播组

6.5 组播/组播过滤与VLAN

6.5.1 组播VLAN过滤表
c 复制代码
typedef struct {
    bit [47:0]  mac_address;  // 组播MAC地址
    bit [11:0]  vlan_id;      // VLAN ID
    bit         valid;        // 有效位
    bit [2:0]   queue;        // 目标队列
} multicast_vlan_entry_t;

void config_multicast_vlan_filter() {
    multicast_vlan_entry_t entries[4];

    // 组播组1: 01:00:5E:00:00:01, VLAN 10 → Queue 0
    entries[0] = '{0x01005E000001, 10, 1, 0};

    // 组播组2: 01:00:5E:00:00:02, VLAN 10 → Queue 1
    entries[1] = '{0x01005E000002, 10, 1, 1};

    // 组播组3: 01:00:5E:00:00:01, VLAN 20 → Queue 2
    entries[2] = '{0x01005E000001, 20, 1, 2};

    // 组播组4: 01:00:5E:00:00:02, VLAN 20 → Queue 3
    entries[3] = '{0x01005E000002, 20, 1, 3};

    // 写入过滤表
    for(int i = 0; i < 4; i++) {
        write_multicast_table(i, entries[i]);
    }
}

七、完整验证示例

7.1 综合测试场景

systemverilog 复制代码
class comprehensive_vlan_test extends uvm_test;
    `uvm_component_utils(comprehensive_vlan_test)

    task run_phase(uvm_phase phase);
        phase.raise_objection(this);

        // 测试1: VLAN插入验证
        test_vlan_insertion();

        // 测试2: VLAN剥离验证
        test_vlan_stripping();

        // 测试3: VLAN替换验证
        test_vlan_replacement();

        // 测试4: VLAN过滤失败处理
        test_vlan_filter_fail();

        // 测试5: 多通道VLAN
        test_multi_channel_vlan();

        // 测试6: 优先级映射
        test_priority_mapping();

        // 测试7: 组播VLAN
        test_multicast_vlan();

        // 测试8: 广播VLAN
        test_broadcast_vlan();

        phase.drop_objection(this);
    endtask

    task test_vlan_insertion();
        `uvm_info("TEST", "Testing VLAN insertion...", UVM_LOW)

        // 配置VLAN插入
        config_vlan_insert(10, 5);

        // 发送无VLAN的帧
        send_frame_without_vlan();

        // 接收并验证
        receive_and_verify_vlan(10, 5);
    endtask

    task test_vlan_filter_fail();
        `uvm_info("TEST", "Testing VLAN filter fail...", UVM_LOW)

        // 配置VLAN过滤(仅允许VLAN 10)
        config_vlan_filter(10);

        // 启用过滤失败队列
        enable_filter_fail_queue(7);

        // 发送VLAN 20的帧
        send_vlan_frame(20);

        // 验证帧路由到队列7
        verify_frame_in_queue(7);
    endtask
endclass

八、总结

核心要点

  1. 过滤失败处理:可路由到特定队列或丢弃,灵活配置
  2. 描述符差异:Tx Context描述符配置VLAN操作,Rx Write-back描述符包含VLAN信息
  3. 数据比对:比对帧内容、描述符状态、长度变化
  4. 多通道分配:每个通道独立配置VLAN,支持多租户
  5. 优先级配置:PSRQ映射、严格优先级/WRR调度
  6. 组播广播:VLAN隔离组播/广播域,支持包复制

最佳实践

  1. 验证方法:构造期望帧,比对所有字段
  2. 调试技巧:使用过滤失败队列捕获异常帧
  3. 性能优化:合理配置多通道和队列映射
  4. 安全考虑:严格VLAN过滤,防止VLAN跳跃

参考资料

  1. Synopsys DesignWare Cores Ethernet Quality-of-Service Databook
  2. IEEE 802.1Q - VLAN Standard
  3. IEEE 802.1p - Priority Classification
  4. IANA IPv4 Multicast Address Registry

关键词:VLAN过滤失败、描述符、数据比对、多通道、优先级、组播、广播

相关推荐
Hello.Reader2 小时前
双卡 A100 + Ollama 最终落地手册一键部署脚本、配置文件、预热脚本与 Python 客户端完整打包
开发语言·网络·python
计算机安禾2 小时前
【数据结构与算法】第30篇:哈希表(Hash Table)
数据结构·学习·算法·哈希算法·散列表·visual studio
yangyanping201082 小时前
Go语言学习之配置管理库Viper
开发语言·学习·golang
onlooker66662 小时前
Claude code 源码学习
学习·ai编程·claude code
sinat_255487812 小时前
泛型:超级、扩展、列表·学习笔记
java·windows·学习·算法
世人万千丶2 小时前
Flutter 框架跨平台鸿蒙开发 - 鸿蒙护眼版本2048操作式游戏应用
学习·flutter·游戏·华为·harmonyos·鸿蒙
派大星酷2 小时前
Java 网络编程全解:TCP、UDP、HTTP、WebSocket
java·网络·tcp/ip
jinanwuhuaguo2 小时前
OpenClaw、Agent、Skill、MCP 深度解读与区分分析
网络·人工智能·网络协议·rpc·openclaw
TorrieLeung3 小时前
碎片学习|外贸报价-FOB
学习·tob·外贸销售