IEEE 802.1Q中的数据读取

前天还为一下的代码耿耿于怀,因为不明白为什么地址+偏移量,然后再来或、与运算。

 if(pEthHeader->EthType == TESTPROV_ETH_TYPE_802_1Q)
    {
      if(NET_BUFFER_LIST_INFO(pNetBufferList, Ieee8021QNetBufferListInfo) == 0)// no tag info present in OOB
	{
	  // Count of unstripped packets
	  pFilter->RecdUnStrippedPackets++; 
	  
        }
      else
        {
	  //should only reach here if vlanid  > 0
	  VLanId =  ((*(PUSHORT)((PUCHAR)pEthHeader + 14)) & 0x0FFF);
	  if(VLanId == 0)
	    pFilter->RecdUnStrippedPackets++;  
        }
      
      pEthHeader->EthType = (USHORT)*((PUCHAR)pEthHeader + 16);
      bytesParsed = ETH_HEADER_SIZE + ETH_802_1Q_TAG_SIZE;
      
    }
  else
    bytesParsed = ETH_HEADER_SIZE;

 pEthHeader是一个缓冲区的,指向Ethernet Header,这是它的定义:

typedef struct _TESTPROV_ETH_HEADER
{
    UCHAR       DstAddr[TESTPROV_MAC_ADDR_LEN];
    UCHAR       SrcAddr[TESTPROV_MAC_ADDR_LEN];
    USHORT      EthType;

} TESTPROV_ETH_HEADER;

 这里有一个EthType指明某种协议类型。可以参考:EtherType

这里代码考虑了两种情况,分别是包头中是否包含了IEEE 802.1Q的信息。数据结构如图:



 可以看到IEEE 802.1Q Header是4个Byte的。位置在Ethernet Type之前。根据EtherType的值:

0x8100      VLAN-tagged frame (IEEE 802.1Q) 

 如果包含了IEEE 802.1Q Header,这个type值就定于0x0081(代码中是这样的,跟前面定义倒叙了??)

所以要拿到Vid:VLAN Identifier (VID) : a 12-bit field specifying the VLAN to which the frame belongs. 所以对于 802.1Q Header中的后两个Byte中的后面前4个bit为:(PCP和CFI)。 所以要拿到vlanID,自然packetBuffer+14bytes,然后再从后面两个bytes中取出后12-bit.

 VLanId =  ((*(PUSHORT)((PUCHAR)pEthHeader + 14)) & 0x0FFF);

 

这样的话,要拿到VlanID自然要petherhead+12+4了,才能得到了。这样就全部解释清楚了.

--------------------------------现在看看如何拿到AddressFamily----------------------------------

我一直对前面的pEtherhead->EthType的获得方式没有弄清。现在看看这段代码:

 //
  // Start parsing the data
  //
    
  parserState = ParsingIPHeaders;
  
  switch (parserState) 
    {
    case ParsingIPHeaders:
      
      // Determine the address family (IPv4 / IPv6)
      if (bytesCopied < bytesParsed + IP_ADDRESS_FAMILY_LEN)
	{
	  goto Exit;
	}
      AddressFamily = IP_ADDRESS_FAMILY(packetBuffer + bytesParsed);
      
      if (IP_ADDRESS_FAMILY_IP4 == AddressFamily){..}

 跳过前面的bytesParsed = ETH_HEADER_SIZE;的Ethernet Header,就到了IP Header了。

000000: 00 A0 CC 63 08 1B 00 40 : 95 49 03 5F 08 00 45 00 [email protected]._..E. 
000010: 00 3C 82 47 00 00 20 01 : 94 C9 C0 A8 01 20 C0 A8 .<.G.. ...... .. 
000020: 01 40 08 00 48 5C 01 00 : 04 00 61 62 63 64 65 66 [email protected]\....abcdef 
000030: 67 68 69 6A 6B 6C 6D 6E : 6F 70 71 72 73 74 75 76 ghijklmnopqrstuv 
000040: 77 61 62 63 64 65 66 67 : 68 69                   wabcdefghi......

packetBuffer 指向的是上面的45的位置。至于数据格式参考 Sample Ping Packet Decode

其中高位表示IP version, 低位表示IP header 长度=5个32bits的word.其中((PUCHAR)(buffer))=45.
然后右移4为,对于16进制来说就是4为就是除以16,就剩下一个位,ox45就只剩下 ox4,转换为10进制=4.

可以参考论坛 http://topic.csdn.net/u/20091128/18/2b41c174-e24c-4b0d-8b30-55ff6131db01.html?34775   以及 http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/9234a3cb-eca5-440c-839e-7d45e54fd38b

 

 

参考: IEEE802.1q: http://en.wikipedia.org/wiki/IEEE_802.1Q

         Ethernet header : http://en.wikipedia.org/wiki/EtherType

         IPv4 Header: http://www.networksorcery.com/enp/protocol/ip.htm

         IPv6 header :http://www.networksorcery.com/enp/protocol/ipv6.htm

         Mobility Header: http://www.networksorcery.com/enp/protocol/mobilityheader.htm

 

你可能感兴趣的:(thread,数据结构,.net,Microsoft,Social)