void Clock::clockSet(const Time& when) { ScopedLock lock(mLock); mBaseTime = Timeval(0); mBaseFN = when.FN(); isValid = true; }
void Clock::set(const Time& when) { mLock.lock(); mBaseTime = Timeval(0); mBaseFN = when.FN(); mLock.unlock(); }
void PDCHL1Downlink::bugFixIdleFrame() { // DEBUG: We are only using this function to fix this problem for now. if (gFixIdleFrame) { // For this debug purpose, the mssage is sent on the next frame // TODO: debug purpose only! This only works for one channel! //Time tnext(gBSNNext.FN()); //gBTS.clock().wait(tnext); } // Did we make it in time? { Time tnow = gBTS.time(); int fn = tnow.FN(); int mfn = (fn / 13); // how many 13-multiframes int rem = (fn - (mfn*13)); // how many blocks within the last multiframe. int tbsn = mfn * 3 + ((rem==12) ? 2 : (rem/4)); GPRSLOG(2) <<"idleframe"<<LOGVAR(fn)<<LOGVAR(tbsn)<<LOGVAR(rem); } /*** if (mchIdleFrame.size() == 0) { RLCMsgPacketDownlinkDummyControlBlock *dummymsg = new RLCMsgPacketDownlinkDummyControlBlock(); mchIdleFrame.set(BitVector(RLCBlockSizeInBits[ChannelCodingCS1])); dummymsg->write(mchIdleFrame); delete dummymsg; } send1Frame(mchIdleFrame,ChannelCodingCS1,true); ***/ }
void Clock::wait(const Time& when) const { int32_t now = FN(); int32_t target = when.FN(); int32_t delta = FNDelta(target,now); if (delta<1) return; static const int32_t maxSleep = 51*26; if (delta>maxSleep) delta=maxSleep; sleepFrames(delta); }
// Return true if the CCCH frame was used. bool CCCHLogicalChannel::processRaches() { while (RachInfo *rach = gRachq.readNoBlock()) { Time now = gBTS.time(); int age = now - rach->mWhen; // The result is number of frames and could be negative. if (age>sMaxAge) { LOG(WARNING) << "ignoring RACH burst with age " << age; if (rach->mChan) { LOG(INFO) << "BTS congestion: unable to process RACH for pre-allocated channel within expiration time"; rach->mChan->l2sendp(L3_HARDRELEASE_REQUEST); // (pat) added 9-6-2013 } delete rach; continue; // Did not use the CCCH frame yet. } ChannelType chtype = decodeChannelNeeded(rach->mRA); LOG(DEBUG) <<LOGVAR(*rach) <<LOGVAR(chtype) <<LOGVAR(mCcchGroup); if (chtype == PSingleBlock1PhaseType || chtype == PSingleBlock2PhaseType) { assert(rach->mChan == NULL); if (0 == gConfig.getNum("GPRS.Enable")) { // GPRS service request when the beacon advertises no beacon support. // This was a spurious RACH message or a stupid handset. Ignore it. assert(rach->mChan == NULL); delete rach; continue; } // Regardless of the type of GPRS request, we will send a single-block uplink, // which the MS will (most likely) use to send us a PacketResourceRequest. // First request a single-block reservation from GPRS. If GPRS resources are busy, // this will return NULL and we will send reject the RACH. L3ImmediateAssignment *iap = GPRS::makeSingleBlockImmediateAssign(rach, mCcchNextWriteTime.FN() + 4); if (iap) { L2LogicalChannelBase::l2sendm(*iap,L3_UNIT_DATA); delete iap; delete rach; } else { } return true; // We processed this rach and used the CCCH, one way or another. } // L2LogicalChannel *LCH; // if (chtype == TCHFType) { // // FIXME: This blocks at L2LAPDm::sendIdle! // LCH = gBTS.getTCH(); // } else if (chtype == SDCCHType) { // // We may reserve some SDCCH for CC and SMS. // if (requestingLUR(rach->mRA)) { // int SDCCHAvailable = gBTS.SDCCHAvailable(); // int SDCCHReserve = gConfig.getNum("GSM.Channels.SDCCHReserve"); // if (requestingLUR(rach->mRA) && SDCCHAvailable <= SDCCHReserve) { // // (pat 2-2014) Changed this message and downgraded from CRIT. // LOG(CRIT) << "LUR [Location Update Request] congestion, insufficient "<<LOGVAR(SDCCHAvailable) << " <= " <<LOGVAR(SDCCHReserve); // goto failure; // } // } // // LCH = gBTS.getSDCCH(); // } else { // LOG(NOTICE) << "RACH burst for unsupported service RA=" << rach->mRA; // LCH = gBTS.getSDCCH(); // Try anyway. // } // // // // Nothing available? // if (!LCH) { // failure: #if 0 // return false; #endif // } if (! rach->mChan) { delete rach; continue; } // Success. Send an ImmediateAssignment. int initialTA = rach->initialTA(); assert(initialTA >= 0 && initialTA <= 62); // enforced by AccessGrantResponder. //LCH->l1InitPhy(rach->RSSI(),initialTA,gBTS.clock().systime(rach->mWhen.FN())); gReports.incr("OpenBTS.GSM.RR.RACH.TA.Accepted",(int)(initialTA)); L2LogicalChannel *LCH = rach->mChan; // TODO: Update T3101. L3ImmediateAssignment assign( L3RequestReference(rach->mRA,rach->mWhen), LCH->channelDescription(), L3TimingAdvance(initialTA) ); //assign.setStartFrame(rach->mReadyTime.FN() + 104); if (0) { // This was for debugging. Adding this delay made the layer1 connection reliable. // Delay the channel assignment until the SACCH is known to be transmitting... Time sacchStart = LCH->getSACCH()->getNextWriteTime(); now = gBTS.time(); // Must update this because getTCH blocked. int msecsDelay = ((sacchStart - now.FN()).FN() * gFrameMicroseconds) / 1000; // Add an extra gratuitous 250ms delay for testing. // msecsDelay += 250; if (msecsDelay < 0) { msecsDelay = 0; } if (msecsDelay) { LCH->addT3101(msecsDelay); //assign.setStartFrame(now.FN() + (1000 * msecsDelay) / gFrameMicroseconds); usleep(msecsDelay * 1000); } LOG(INFO) << "sending L3ImmediateAssignment " << LCH->descriptiveString() <<LOGVAR(msecsDelay) <<" " <<assign; } L2LogicalChannelBase::l2sendm(assign,L3_UNIT_DATA); delete rach; return true; // We used this CCCH. } return false; // CCCH frame not used. }