同一个交换机下接收不同类型的goose报文

缘由

同一个交换机下无法连接多个设备进行goose通信。

实践

以下实践均在同一个交换机上做出,不同交换机上还没有这个问题:单片机网卡同时可以接收带TPID、TCI和不带TPID、TCI都能够接收,使用wireshark抓包看不到TPID、TCI,被抓包软件过滤掉了,goose发布端口能够正常发送,订阅端口也能够正常接收,被抓包软件带偏了,导致无法正常解析带TPID、TCI的报文数据,在enc624j600网卡接收goose报文时,会判断报文类别,也就是ethhdr->type,根据相应的ethhdr->type进入不同的回调函数。在接收到不带TPID、TCI的goose报文时,那么报文的第12个字节和第13个字节是0x88、0xb8,也就是ETH_P_GOOSE类型。当报文中带TPID、TCI(假设TPID设置为0x81、0x00),报文的第12个字节和第13个字节会变成0x81和0x00,但是接收中没有对这个类型进行处理,导致无法正常接收到带TPID、TCI的goose报文。

/** GOOSE**/
  ETH_P_GOOSE       = 0x88B8U,
  /** VLAN **/
  ETH_P_GOOSE_VLAN   = 0x8100U 
switch (htons(ethhdr->type)) {
		/* IP or ARP packet? */
		case ETHTYPE_IP:
		case ETHTYPE_IPV6:
		case ETHTYPE_ARP:
			/* full packet send to tcpip_thread to process */
			ok = netif->input(p, netif);
			if (ok != ERR_OK) {
				LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
				pbuf_free(p);
				p = NULL;
			}
			break;
        case ETH_VLAN:
        case ETH_P_GOOSE:
			 ......
            GooseReceiver_handleMessage(receiver, p->payload, p->len);
            pbuf_free(p);
            p = NULL;
            break;
       ......
            
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,需要了解Goose报文的结构。Goose报文是基于IEC 61850标准的一种通信协议,主要用于在电力系统中进行广域保护和控制。它采用了Ethernet II帧的格式,但添加了一些特殊的字段,用于传输IEC 61850数据。 以下是Goose报文的基本结构: ![Goose报文结构](https://i.imgur.com/gJ7Vd3b.png) 其中,各字段的含义如下: - Destination MAC Address:目的MAC地址,通常为组播地址。 - Source MAC Address:源MAC地址。 - EtherType:以太网类型,固定为0x88B8。 - VLAN Tag:可选的VLAN标签,如果存在则占4个字节。 - APPID:应用程序标识符,用于标识Goose报文。 - Length:数据长度,包括APPID、数据集和GOOSE Control Block。 - Goose Control Block:Goose控制块,包括时间戳、状态变量和数据变量。 - Dataset:数据集,包括状态变量和数据变量。 下面是一个用Verilog实现的Goose报文解析代码示例: ```verilog module goose_parser ( input wire [7:0] rx_data, input wire rx_clk, input wire rx_valid, input wire rst_n, output reg [7:0] appid, output reg [15:0] length, output reg [31:0] time, output reg [47:0] mac_dest, output reg [47:0] mac_src, output reg [15:0] ethertype, output reg [15:0] vlan_tag, output reg [15:0] goose_appid, output reg [15:0] goose_length, output reg [15:0] goose_protocol, output reg [7:0] goose_pdu[], output reg [7:0] goose_mac[], output reg [15:0] goose_mac_length ); reg [7:0] rx_data_reg [63:0]; reg [5:0] rx_data_count; reg [7:0] appid_reg [1:0]; reg [15:0] length_reg [1:0]; reg [31:0] time_reg [1:0]; reg [47:0] mac_dest_reg [1:0]; reg [47:0] mac_src_reg [1:0]; reg [15:0] ethertype_reg [1:0]; reg [15:0] vlan_tag_reg [1:0]; reg [15:0] goose_appid_reg [1:0]; reg [15:0] goose_length_reg [1:0]; reg [15:0] goose_protocol_reg [1:0]; reg [7:0] goose_pdu_reg [255:0]; reg [7:0] goose_mac_reg [5:0]; reg [15:0] goose_mac_length_reg; reg [1:0] state; parameter IDLE = 2'b00; parameter RX_HEADER = 2'b01; parameter RX_GOOSE_PDU = 2'b10; always @(posedge rx_clk) begin if (!rst_n) begin state <= IDLE; rx_data_count <= 0; appid_reg[0] <= 8'h00; appid_reg[1] <= 8'h00; length_reg[0] <= 16'h0000; length_reg[1] <= 16'h0000; time_reg[0] <= 32'h00000000; time_reg[1] <= 32'h00000000; mac_dest_reg[0] <= 48'h000000000000; mac_dest_reg[1] <= 48'h000000000000; mac_src_reg[0] <= 48'h000000000000; mac_src_reg[1] <= 48'h000000000000; ethertype_reg[0] <= 16'h0000; ethertype_reg[1] <= 16'h0000; vlan_tag_reg[0] <= 16'h0000; vlan_tag_reg[1] <= 16'h0000; goose_appid_reg[0] <= 16'h0000; goose_appid_reg[1] <= 16'h0000; goose_length_reg[0] <= 16'h0000; goose_length_reg[1] <= 16'h0000; goose_protocol_reg[0] <= 16'h0000; goose_protocol_reg[1] <= 16'h0000; goose_mac_length_reg <= 16'h0000; state <= IDLE; end else begin case (state) IDLE: begin if (rx_valid) begin rx_data_reg[rx_data_count] <= rx_data; rx_data_count <= rx_data_count + 1; if (rx_data_count == 6) begin mac_dest_reg[1] <= {rx_data_reg[0], rx_data_reg[1], rx_data_reg[2], rx_data_reg[3], rx_data_reg[4], rx_data_reg[5]}; mac_src_reg[0] <= {rx_data_reg[0], rx_data_reg[1], rx_data_reg[2], rx_data_reg[3], rx_data_reg[4], rx_data_reg[5]}; state <= RX_HEADER; rx_data_count <= 0; end end end RX_HEADER: begin if (rx_valid) begin rx_data_reg[rx_data_count] <= rx_data; rx_data_count <= rx_data_count + 1; if (rx_data_count == 2) begin ethertype_reg[1] <= rx_data_reg[0]; ethertype_reg[0] <= rx_data_reg[1]; state <= RX_GOOSE_PDU; rx_data_count <= 0; end end end RX_GOOSE_PDU: begin if (rx_valid) begin rx_data_reg[rx_data_count] <= rx_data; rx_data_count <= rx_data_count + 1; if (rx_data_count == 8) begin appid_reg[1] <= rx_data_reg[0]; appid_reg[0] <= rx_data_reg[1]; length_reg[1] <= rx_data_reg[2]; length_reg[0] <= rx_data_reg[3]; time_reg[3] <= rx_data_reg[4]; time_reg[2] <= rx_data_reg[5]; time_reg[1] <= rx_data_reg[6]; time_reg[0] <= rx_data_reg[7]; state <= RX_GOOSE_PDU; rx_data_count <= 0; end else if (rx_data_count > 8 && rx_data_count <= 8 + length_reg[1] + length_reg[0]) begin goose_pdu_reg[rx_data_count-9] <= rx_data; if (rx_data_count == 8 + length_reg[1] + length_reg[0]) begin goose_protocol_reg[1] <= goose_pdu_reg[0]; goose_protocol_reg[0] <= goose_pdu_reg[1]; goose_appid_reg[1] <= goose_pdu_reg[2]; goose_appid_reg[0] <= goose_pdu_reg[3]; goose_length_reg[1] <= goose_pdu_reg[4]; goose_length_reg[0] <= goose_pdu_reg[5]; goose_mac_length_reg <= goose_pdu_reg[6] * 256 + goose_pdu_reg[7]; for (int i=0; i<goose_mac_length_reg; i=i+1) begin goose_mac_reg[i] <= goose_pdu_reg[i+8]; end end rx_data_count <= rx_data_count + 1; end end end endcase end end assign appid = appid_reg[1:0]; assign length = length_reg[1:0]; assign time = time_reg[3:0]; assign mac_dest = mac_dest_reg[1:0]; assign mac_src = mac_src_reg[1:0]; assign ethertype = ethertype_reg[1:0]; assign vlan_tag = vlan_tag_reg[1:0]; assign goose_appid = goose_appid_reg[1:0]; assign goose_length = goose_length_reg[1:0]; assign goose_protocol = goose_protocol_reg[1:0]; assign goose_pdu = goose_pdu_reg[255:0]; assign goose_mac = goose_mac_reg[5:0]; assign goose_mac_length = goose_mac_length_reg; endmodule ``` 这个模块将输入的Goose报文解析为各个字段,包括目的MAC地址、源MAC地址、应用程序标识符、数据长度、时间戳、数据集等。它通过有限状态机实现了报文解析的逻辑,一步一步地读取报文中的数据,并将其存储到对应的寄存器中。最后,通过输出端口将各个字段输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值