TIM:Traffic Indication Map,流量指示图。
在80211协议节能模式中,AP会缓存下行数据,AP就是通过beacon帧中TIM来告知休眠中的STA有数据需要接收。
DTIM:Delivery Traffic Indication Map,是一种特殊的TIM,其除了缓存的单播信息,也同时指示AP缓存的组播信息。
TIM IE包含了四个域:DTIM Count, DTIM Period, Bitmap Control, and Partial Virtual
Bitmap。
Length:1byte,表示TIM的长度。
DTIM Count:1byte,表示下次DTIM之前还有多少个beacon帧(包括当前的beacon帧),如果DTIM Count为0表示当前的TIM就是DTIM。
DTIM Period:1byte,表示两个DTIM之间有多少个beacon帧。1表示所有的TIM都是DTIM。
Bitmap Control:1byte,bit0表示是否有组播/广播数据包缓存,1表示有组播/广播数据包缓存,0表示没有。bit1-7表示bitmap的偏移情况,即Partial Virtual Bitmap起始值是多少。
Partial virtual Bitmap:1-251byte,以Bitmap Control的起始值开始的bitmap。可以表示的范围0~2007。
第一个例子,AP没有缓存组播/广播的下行数据,只缓存了STA AID 2和AID 7的数据。其中Bitmap Control为0x00,Partial Virtual Bitmap为0x84。
运行结果:
第二个例子,AP缓存了组播/广播的下行数据,还缓存了STA AID 2, AID 7, AID 22和AID 24的数据。
运行结果:
第三个例子,AP缓存了组播/广播的下行数据,还缓存了STA AID 24的数据。
运行结果:
#include
#define ADD_TIM_BIT 0
#define REMOVE_TIM_BIT 1
#define TIM_ELEMENT_ID 5
#define TIM_BASE_SIZE 3 /* size of TIM fields */
#define AID_SIZE 2008 /* valid AIDs are 1 thru 2007 */
#define VBM_SIZE 251 /* size of VBM array = 2008/8 = 251 */
typedef unsigned char UINT8;
typedef unsigned short int UINT16;
struct _tim
{
UINT8 Element_id;
UINT8 IELength;
UINT8 DtimCount;
UINT8 DtimPeriod;
UINT8 BitMapControl;
UINT8 PartialVirtualBitMap[VBM_SIZE];
};
UINT8 virtualBitMap[VBM_SIZE];
UINT8 mcast_pending = 0;
UINT8 dtimCount = 0;
UINT8 dtimPeriod = 5;
void Build_TIM(struct _tim * Tim)
{
UINT8 octetIndex;
UINT8 offset = 0;
UINT8 lengthOfPartialVirtualBitMap = 0;
/* Find first nonzero octet in the virtual bit map */
for (octetIndex = 0; ((virtualBitMap[octetIndex] == 0) && (octetIndex < VBM_SIZE)); octetIndex++)
/* empty */;
if (octetIndex < VBM_SIZE)
/* Clear the lsb as it is reserved for the broadcast/ multicast indication bit */
offset = octetIndex & 0xFE;
/* Find last nonzero octet in the virtual bit map */
for (octetIndex = (VBM_SIZE - 1); ((virtualBitMap[octetIndex] == 0) && (octetIndex > 0)); octetIndex--)
/* empty */;
lengthOfPartialVirtualBitMap = octetIndex - offset + 1;
Tim->Element_id = TIM_ELEMENT_ID;
Tim->IELength = lengthOfPartialVirtualBitMap + TIM_BASE_SIZE;
Tim->DtimCount = dtimCount;
Tim->DtimPeriod = dtimPeriod;
Tim->BitMapControl = offset;
/* Update broadcast/ multicast indication bit if necessary */
if ((Tim->DtimCount == 0) && mcast_pending)
Tim->BitMapControl |= 0x01;
/* Copy the virtual bit map octets that are nonzero */
/* Note: A NULL virtualBitMap will still add a single octet of zero */
for (octetIndex = 0; octetIndex < lengthOfPartialVirtualBitMap; octetIndex++)
Tim->PartialVirtualBitMap[octetIndex] = virtualBitMap[offset + octetIndex];
}
void Update_VirtualBitMap(UINT16 station_id, UINT8 Action)
{
UINT16 aid = station_id;
UINT8 aid_octet;
UINT8 aid_bit;
if ((aid > 0) && (aid < AID_SIZE))
{
/* Get aid position in Virtual Bit Map. */
aid_octet = (UINT8)(aid >> 3);
aid_bit = (UINT8)(0x01 << (aid & 0x07));
if (Action == REMOVE_TIM_BIT)
virtualBitMap[aid_octet] &= ~aid_bit;
else
virtualBitMap[aid_octet] |= aid_bit;
}
}
void main(void)
{
struct _tim Tim;
UINT8 ExampleCase;
ExampleCase = 3;
switch (ExampleCase)
{
case 1:
mcast_pending = 0;
Update_VirtualBitMap(2, ADD_TIM_BIT);
Update_VirtualBitMap(7, ADD_TIM_BIT);
break;
case 2:
mcast_pending = 1;
Update_VirtualBitMap(2, ADD_TIM_BIT);
Update_VirtualBitMap(7, ADD_TIM_BIT);
Update_VirtualBitMap(22, ADD_TIM_BIT);
Update_VirtualBitMap(24, ADD_TIM_BIT);
break;
case 3:
mcast_pending = 1;
Update_VirtualBitMap(24, ADD_TIM_BIT);
break;
case 4:
mcast_pending = 0;
Update_VirtualBitMap(3, ADD_TIM_BIT);
Update_VirtualBitMap(37, ADD_TIM_BIT);
Update_VirtualBitMap(43, ADD_TIM_BIT);
break;
case 5:
mcast_pending = 0;
Update_VirtualBitMap(35, ADD_TIM_BIT);
break;
case 6:
mcast_pending = 0;
Update_VirtualBitMap(43, ADD_TIM_BIT);
break;
case 7:
mcast_pending = 0;
Update_VirtualBitMap(35, ADD_TIM_BIT);
Update_VirtualBitMap(35, REMOVE_TIM_BIT);
break;
case 8:
mcast_pending = 1;
Update_VirtualBitMap(13, ADD_TIM_BIT);
Update_VirtualBitMap(43, ADD_TIM_BIT);
Update_VirtualBitMap(63, ADD_TIM_BIT);
Update_VirtualBitMap(73, ADD_TIM_BIT);
break;
case 9:
mcast_pending = 1;
Update_VirtualBitMap(2007, ADD_TIM_BIT);
break;
default:
break;
}
Build_TIM(&Tim);
printf("Element_id = %d.\n", Tim.Element_id);
printf("IELength = %d.\n", Tim.IELength);
printf("DtimCount = %d.\n", Tim.DtimCount);
printf("DtimPeriod = %d.\n", Tim.DtimPeriod);
printf("BitMapControl = 0x%02X\n", Tim.BitMapControl);
if (Tim.IELength - TIM_BASE_SIZE > 0)
{
int octetIndex;
for (octetIndex = 0; octetIndex < Tim.IELength - TIM_BASE_SIZE; octetIndex++)
printf("PartialVirtualBitMap [%d] = 0x%02X\n", octetIndex, Tim.PartialVirtualBitMap
[octetIndex]);
}
}
802.11-2007.pdf Annex L