//======================================================= // FUNCTION: Set_Nav // PURPOSE: Update the NAV process. //======================================================= void Set_Nav(MobileNode *node, unsigned int duration_ns) { WGNTime now; WGNTime new_nav; unsigned int time_dif; WGNflag flag; now = GetTime(); new_nav = LocalTimeAdd(now, duration_ns); // if there is already a exiting NAV process, update the NAV ending time. if (Timer_SwitchSign(node, NAV_TIMER) == ON) { time_dif = LocalTimeMinus(new_nav, node->nodeMac->nodeTimer->nav_timer->end_time); //if the new NAV last longer than the current one if(time_dif > 0) { NAVTimer_Stop(node); flag = EventDestroy(node->Id, NAVTimeOut); if (flag == FALSE) { printf("[Set_Nav]:: Error, Can not find the entry which will be destroyed!\n"); exit(1); } NAVTimer_Start(node, duration_ns); } } //else create a new NAV process. else NAVTimer_Start(node, duration_ns); //The change of the NAV state can impact on the backoff process. CheckBFTimer(node); }
void recvACK(MobileNode *node) { WGNflag idle; WGNflag flag; if (GetTxStatus(node) != MAC_SEND) { return; } TXTimer_Stop(node); flag = EventDestroy(node->Id, TXTimeOut); if (flag == FALSE) { printf("[recvACK]:: Error, Can not find the entry which will be destroyed!\n"); exit(1); } // The successful reception of the ACK frame implies // the successful DATA transmission. Hence, Short/Long // Retry Counter and the CW should be reset. if (IsOverRTSThreshold(node->nodeMac->pktTx) == FALSE) { RstSRCounter(node); } else RstLRCounter(node); Reset_cw(node); Dot11FrameFree(node->nodeMac->pktTx); node->nodeMac->pktTx = NULL; // Backoff before accessing the medium to transmit again. idle = CheckIfChannelIdle(node); BFTimer_Start(node,idle); tx_resume(node); }
/*----------------------------------------------------------------------------* * NAME * SchedDeinit * * DESCRIPTION * Deinitialise the scheduler. * * RETURNS * void * *----------------------------------------------------------------------------*/ void SchedDeinit(void *data) { SchedulerInstanceType *inst; inst = (SchedulerInstanceType *) data; if (instance != inst) { return; } if (inst != NULL) { uint8 i; for (i = 0; i < _SCHED_MAX_SEGMENTS; i ++) { if (inst->thread[i].inUse) { MessageQueueEntryType *msg, *msgNext; for (msg = inst->thread[i].messageFreeList; msg; msg = msgNext) { msgNext = msg->next; MemFree(msg); msg = NULL; } MemFree(inst->thread[i].tasks); inst->thread[i].tasks = NULL; MutexDestroy(&inst->thread[i].qMutex); EventDestroy(&inst->thread[i].eventHandle); } } MutexDestroy(&inst->bgMutex); EventDestroy(&inst->eventHandle); instance = NULL; MemFree(inst); inst = NULL; } }
static void readLog(EventProc proc) { while (TRUE) { Event event; Res res; res = EventRead(&event, proc); if (res == ResFAIL) break; /* eof */ if (res != ResOK) error("Truncated log"); eventTime = event->any.clock; EventRecord(proc, event, eventTime); EventReplay(event, eventTime); EventDestroy(proc, event); } }
//======================================================= // FUNCTION: CheckBFTimer // PURPOSE: Manage the state convert of the backoff timer //======================================================= void CheckBFTimer(MobileNode *node) { WGNflag flag; //Resume to the back off process once the channel becomes free. if ((CheckIfChannelIdle(node) == TRUE) && (Timer_PauseSign(node,BF_TIMER) == TRUE)) { BFTimer_Resume(node); } //Stop the back off process once the channel becomes busy. if ((CheckIfChannelIdle(node) == FALSE) && (Timer_SwitchSign(node,BF_TIMER) == ON) && (Timer_PauseSign(node,BF_TIMER) == FALSE)) { BFTimer_Pause(node); flag = EventDestroy(node->Id, BFTimeOut); if (flag == FALSE) { printf("[CheckBFTimer]:: Error, Can not find the entry which will be destroyed!\n"); exit(1); } } }
void recvCTS(MobileNode *node) { WGNflag flag; if(GetTxStatus(node) != MAC_RTS) { return; } Dot11FrameFree(node->nodeMac->pktRts); node->nodeMac->pktRts = NULL; TXTimer_Stop(node); flag = EventDestroy(node->Id, TXTimeOut); if (flag == FALSE) { printf("[recvCTS]:: Error, Can not find the entry which will be destroyed!\n") ; exit(1); } //According to the IEEE spec 9.2.4, The successful reception //of the CTS packet can lead to the reset of the short retry counter //but not the contension window size. RstSRCounter(node); tx_resume(node); }
//======================================================= // FUNCTIONS: recv@ // PURPOSE: Process the frame based on its type //======================================================= void recvRTS(MobileNode *node) { WGNflag flag; if( GetTxStatus(node) != MAC_IDLE) { return; } //If the node is responding with someone else and ignores this RTS. if (PktRspIsEmpty(node) == FALSE) { return; } SendCTS(node, node->nodeMac->pktRx); //Stop deferral process that invoked by the frame which is ready to sent. if (Timer_SwitchSign(node, DF_TIMER) == ON) { DFTimer_Stop(node); flag = EventDestroy(node->Id, DFTimeOut); if (flag == FALSE) { printf("[recvRTS]:: Error, Can not find the entry which will be destroyed!\n"); exit(1); } } tx_resume(node); }
void recvDATA(MobileNode *node) { WGN_802_11_Mac_Frame *frame; unsigned int *temp; unsigned int seq_no; unsigned int srcid; WGNflag found; WGNflag flag; int i; if (CheckIfIsBroadCastPkt(node->nodeMac->pktRx) == FALSE) { if (IsOverRTSThreshold(node->nodeMac->pktRx) == TRUE) { if (GetTxStatus(node) == MAC_CTS) { Dot11FrameFree(node->nodeMac->pktRsp); node->nodeMac->pktRsp = NULL; TXTimer_Stop(node); flag = EventDestroy(node->Id, TXTimeOut); if (flag == FALSE) { printf("[recvDATA]:: Error, Can not find the entry which will be destroyed!\n"); exit(1); } //RstSRCounter(node); //Reset_cw(node); } else { return; } SendACK(node, node->nodeMac->pktRx); tx_resume(node); } else { //if the node is in the corresponsing with others it will simply //drop the incoming packet. if(PktRspIsEmpty(node) == FALSE) { return; } SendACK(node, node->nodeMac->pktRx); if(Timer_SwitchSign(node, TX_TIMER) == OFF) { tx_resume(node); } else { //seems ok, but be carefull when debug!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! } } } //Frame duplication checking procedure. srcid = node->nodeMac->pktRx->pseudo_header->srcid; seq_no = node->nodeMac->pktRx->pseudo_header->sc.sc_sequence; temp = node->nodeMac->mac_buffer; temp = &(temp[(srcid-1) * MAC_DUP_CHK_BUF_SIZE]); found = FALSE; // If the packet is a retried one, check whether it is a duplicated one or not. if (node->nodeMac->pktRx->pseudo_header->fc.fc_retry == 1) { for(i=0;(i<MAC_DUP_CHK_BUF_SIZE)&&(found==FALSE);i++) { if(temp[i] == seq_no) { found = TRUE; return; } } } //if the incoming packet is a new one, insert it to the buffer if (found == FALSE) { temp[node->nodeMac->mac_buf_index[srcid-1]]= seq_no; //update the index. the index should always point to the position of the //eariest incoming packet node->nodeMac->mac_buf_index[srcid-1] = (node->nodeMac->mac_buf_index[srcid-1] + 1) % MAC_DUP_CHK_BUF_SIZE; } frame = node->nodeMac->pktRx; node->nodeMac->pktRx = NULL; //ship the frame to the uplayer (Logic Link Layer) MacUpPortSend(node, frame); }
//======================================================= // FUNCTION: Collision // PURPOSE: Handle the collisions //======================================================= void Collision(MobileNode *node, WGN_802_11_Mac_Frame *frame) { WGNflag flag; switch(GetRxStatus(node)) { case MAC_RECV: SetRxStatus(node, MAC_COLL); // NOTE: NO BREAK here!!! case MAC_COLL: // Update the RXTimeout time if(SecToNsec(Frame_Time(node, frame)) > RXTimer_Remain(node)) { RXTimer_Stop(node); flag = EventDestroy(node->Id, RXTimeOut); if (flag == FALSE) { printf("[Collision]:: Error, Can not find the entry which will be destroyed!\n"); exit(1); } switch(GetFcSubtype(node->nodeMac->pktRx)) { case MAC_SUBTYPE_RTS: node->nodeStats->RtsDropForCollision += 1; break; case MAC_SUBTYPE_CTS: node->nodeStats->CtsDropForCollision += 1; break; case MAC_SUBTYPE_ACK: node->nodeStats->AckDropForCollision += 1; break; case MAC_SUBTYPE_DATA: node->nodeStats->DataDropForCollision += 1; break; default: printf("[Collision]:: Error, Invalid subtype!\n"); exit(1); } Dot11FrameFree(node->nodeMac->pktRx); node->nodeMac->pktRx = NULL; node->nodeMac->pktRx = frame; frame = NULL; RXTimer_Start(node, SecToNsec(RX_Time(node))); //here we need not mark the frame with collision error, it will be drop after //reception for the MAC rx state of MAC_COLL } else { switch(GetFcSubtype(frame)) { case MAC_SUBTYPE_RTS: node->nodeStats->RtsDropForCollision += 1; break; case MAC_SUBTYPE_CTS: node->nodeStats->CtsDropForCollision += 1; break; case MAC_SUBTYPE_ACK: node->nodeStats->AckDropForCollision += 1; break; case MAC_SUBTYPE_DATA: node->nodeStats->DataDropForCollision += 1; break; default: printf("[Collision]:: Error, Invalid frame subtype!\n"); exit(1); } Dot11FrameFree(frame); } break; default: printf("[Collision]:: Error, unpredictable rx status comes out!\n"); } }
static void readLog(EventProc proc) { EventCode c; Word bucketLimit = bucketSize; char *styleConv = NULL; /* suppress uninit warning */ /* Print event count header. */ if (reportEvents) { if (style == '\0') { printf(" bucket:"); for(c = 0; c <= EventCodeMAX; ++c) if (eventEnabled[c]) printf(" %04X", (unsigned)c); printf(" all\n"); } } /* Init event counts. */ for(c = 0; c <= EventCodeMAX; ++c) totalEventCount[c] = 0; clearBucket(); /* Init style. */ switch (style) { case '\0': styleConv = " %8lX"; break; case 'C': styleConv = ", %lu"; break; case 'L': styleConv = " %lX"; break; default: error("Unknown style code '%c'", style); } while (TRUE) { /* loop for each event */ char *eventFormat; int argCount, i; Event event; EventCode code; Res res; /* Read and parse event. */ res = EventRead(&event, proc); if (res == ResFAIL) break; /* eof */ if (res != ResOK) error("Truncated log"); eventTime = event->any.clock; code = EventGetCode(event); /* Output bucket, if necessary, and update counters */ if (bucketSize != 0 && eventTime >= bucketLimit) { reportBucketResults(bucketLimit-1); clearBucket(); do { bucketLimit += bucketSize; } while (eventTime >= bucketLimit); } if (reportEvents) { ++bucketEventCount[code]; ++totalEventCount[code]; } /* Output event. */ if (verbose) { eventFormat = EventCode2Format(code); argCount = strlen(eventFormat); if (eventFormat[0] == '0') argCount = 0; if (style == 'L') putchar('('); switch (style) { case '\0': case 'L': { printf("%-19s", EventCode2Name(code)); } break; case 'C': printf("%u", (unsigned)code); break; } switch (style) { case '\0': printf(" %8lu", (ulong)eventTime); break; case 'C': printf(", %lu", (ulong)eventTime); break; case 'L': printf(" %lX", (ulong)eventTime); break; } switch (event->any.code) { case EventLabel: { switch (style) { case '\0': case 'C': { EventString sym = LabelText(proc, event->aw.w1); printf((style == '\0') ? " %08lX " : ", %lu, ", (ulong)event->aw.a0); if (sym != NULL) { printStr(sym, (style == 'C')); } else { printf((style == '\0') ? "sym %05lX" : "sym %lX\"", (ulong)event->aw.w1); } } break; case 'L': { printf(" %lX %lX", (ulong)event->aw.a0, (ulong)event->aw.w1); } break; } } break; case EventMeterValues: { switch (style) { case '\0': { if (event->pddwww.w3 == 0) { printf(" %08lX 0 N/A N/A N/A N/A", (ulong)event->pddwww.p0); } else { double mean = event->pddwww.d1 / (double)event->pddwww.w3; /* .stddev: stddev = sqrt(meanSquared - mean^2), but see */ /* <code/meter.c#limitation.variance>. */ double stddev = sqrt(fabs(event->pddwww.d2 - (mean * mean))); printf(" %08lX %8u %8u %8u %#8.3g %#8.3g", (ulong)event->pddwww.p0, (uint)event->pddwww.w3, (uint)event->pddwww.w4, (uint)event->pddwww.w5, mean, stddev); } printAddr(proc, (Addr)event->pddwww.p0); } break; case 'C': { putchar(','); printAddr(proc, (Addr)event->pddwww.p0); printf(", %.10G, %.10G, %u, %u, %u", event->pddwww.d1, event->pddwww.d2, (uint)event->pddwww.w3, (uint)event->pddwww.w4, (uint)event->pddwww.w5); } break; case 'L': { printf(" %lX %#.10G %#.10G %X %X %X", (ulong)event->pddwww.p0, event->pddwww.d1, event->pddwww.d2, (uint)event->pddwww.w3, (uint)event->pddwww.w4, (uint)event->pddwww.w5); } break; } } break; case EventPoolInit: { /* pool, arena, class */ printf(styleConv, (ulong)event->ppp.p0); printf(styleConv, (ulong)event->ppp.p1); /* class is a Pointer, but we label them, so call printAddr */ if (style != 'L') { if (style == 'C') putchar(','); printAddr(proc, (Addr)event->ppp.p2); } else printf(styleConv, (ulong)event->ppp.p2); } break; default: for (i = 0; i < argCount; ++i) { switch(code) { #include "eventdef.h" #undef RELATION } } } if (style == 'L') putchar(')'); putchar('\n'); fflush(stdout); } processEvent(proc, event, eventTime); EventDestroy(proc, event); } /* while(!feof(input)) */ /* report last bucket (partial) */ if (bucketSize != 0) { reportBucketResults(eventTime); } if (reportEvents) { /* report totals */ switch (style) { case '\0': { printf("\n run:"); } break; case 'L': { printf("(t"); } break; case 'C': { printf("%lu", eventTime+1); } break; } reportEventResults(totalEventCount); /* explain event codes */ if (style == '\0') { printf("\n"); for(c = 0; c <= EventCodeMAX; ++c) if (eventEnabled[c]) printf(" %04X %s\n", (unsigned)c, EventCode2Name(c)); if (bucketSize == 0) printf("\nevent clock stopped at %lu\n", (ulong)eventTime); } } }