OpenBTS-UMTS/SGSNGGSN/SgsnExport.h

200 lines
8.2 KiB
C++

/*
* OpenBTS provides an open source alternative to legacy telco protocols and
* traditionally complex, proprietary hardware systems.
*
* Copyright 2011, 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero General
* Public License version 3. See the COPYING and NOTICE files in the main
* directory for licensing information.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
*/
#ifndef SGSNEXPORT_H
#define SGSNEXPORT_H
#include <string>
#include <Defines.h> // For RN_UMTS
#include "ByteVector.h"
#include "SgsnBase.h" // For SmCause
#include "LinkedLists.h"
#include "MemoryLeak.h"
namespace SGSN {
class GmmInfo;
class SgsnInfo;
// Printing option flags.
enum PrintOptions {
printVerbose = 1,
printCaps = 2,
printDebug = 4,
printNoMsId = 8
};
// 24.008 4.1.3 GMM state machine picture and description.
class GmmState
{ public:
enum state {
//GmmNotOurTlli, // This tlli was not assigned by us.
GmmDeregistered, // Tlli was assigned by us, but not registered yet.
GmmRegistrationPending,
GmmRegisteredNormal, // aka "GPRS Attached"
GmmRegisteredSuspsended
};
static const char *GmmState2Name(state);
};
// A class for downlink messages from the SGSN to GPRS/UMTS.
struct SgsnDownlinkMsg
{
//enum { } msgType;
ByteVector mDlData; // The PDU itself.
std::string mDescr; // Description of this pdu.
SgsnDownlinkMsg(ByteVector a, std::string wDescr) : mDlData(a), mDescr(wDescr) { RN_MEMCHKNEW(SgsnDownlinkMsg) }
// The virtual keyword on a destructor indicates that both the base destructor (this one)
virtual ~SgsnDownlinkMsg() { RN_MEMCHKDEL(SgsnDownlinkMsg) }
//SgsnDownlinkPdu(SgsnDownlinkPdu&other) { *this = other; }
};
struct GprsSgsnDownlinkPdu : public SingleLinkListNode, public SgsnDownlinkMsg
{
uint32_t mTlli; // For gprs: the TLLI of the MS to receive the message.
// (In gprs NSAPI is encoded in the LLC message in the data.)
uint32_t mAliasTlli;// Another TLLI that the SGSN knows refers to the same MS as the above.
Timeval mDlTime;
bool isKeepAlive() { return false; } // Is this is a dummy message?
unsigned size() { return mDlData.size(); } // Decl must exactly match SingleLinkListNode
GprsSgsnDownlinkPdu(ByteVector a, uint32_t wTlli, uint32_t wAliasTlli, std::string descr) :
SgsnDownlinkMsg(a,descr), mTlli(wTlli), mAliasTlli(wAliasTlli)
{}
};
struct UmtsSgsnDownlinkPdu : public SgsnDownlinkMsg
{
int mRbid; // For UMTS, the rbid (if 3..4) or NSAPI if (5..15).
UmtsSgsnDownlinkPdu(ByteVector a, int wRbid, std::string descr) :
SgsnDownlinkMsg(a,descr), mRbid(wRbid)
{}
};
// This class is inherited by the MSInfo struct in GPRS and the UEInfo struct in UMTS
// to provide the necessary Sgsn linkage.
// The SgsnInfo class has the L3 information for the MS/UE and corresponds
// one-to-one with MSInfo or UEInfo classes (and their corresponding inherited MSUEAdapter)
// but the creation and destruction of SgsnInfo and UE or MSInfo are decoupled:
// the SgsnInfo is manufactured upon need (GPRS Attach Request) from the MSInfo or UEInfo,
// and either struct can be deleted without informing the other.
// They are identified by TLLI (in GPRS) or U-RNTI (in UMTS) which is the same in both.
// The MSInfo is very ephemeral, and is normally destroyed shortly after the
// MS ceases communication (sending TBFs); it could be as soon as the MS has certainly
// dropped back to GPRS Packet-Idle mode, because the MS will call back in if necessary
// to create a new MSInfo structure, although we keep it around a little longer than that.
// However, if the MS calls back in it will do so with the same TLLI,
// which will correspond to the SgsnInfo it used previously.
// According to the spec, the GPRS registration information, which is saved in GmmInfo
// should last about an hour.
class MSUEAdapter {
// Methods that begin with 'sgsn' are implemented by the SGSN side.
// Methods that begin with 'ms' are implemented by the UMTS RRC or GPRS L2 side.
public:
// The rbid is used only by UMTS.
void sgsnWriteLowSide(ByteVector &payload,uint32_t handle, unsigned rbid=0);
GmmState::state sgsnGetRegistrationState(uint32_t mshandle);
void sgsnPrint(uint32_t mshandle, int options, std::ostream &os);
void sgsnFreePdpAll(uint32_t mshandle);
//MSUEAdapter() {}
//virtual ~MSUEAdapter() {}
virtual std::string msid() const = 0; // A human readable name for the MS or UE.
#if RN_UMTS
// This is the old interface to GPRS/UMTS; see saWriteHighSide()
// This sends a pdu from the sgsn (or anywhere) to the ms.
// For UMTS the rbid is the rbid; For GPRS the rbid is the TLLI.
// This is the previous interface:
virtual void msWriteHighSide(ByteVector &dlpdu, uint32_t rbidOrTlli, const char *descr) = 0;
// This is called when the RRC SecurityModeComplete or SecurityModeFailure is received.
void sgsnHandleSecurityModeComplete(bool success);
// When allocating Pdp Contexts, the Ggsn allocates RABs in the middle
// of the procedure, and waits for RRC to respond with this function:
void sgsnHandleRabSetupResponse(unsigned RabId,bool success);
// Deactivate all the rabs specified by rabMask.
virtual void msDeactivateRabs(unsigned rabMask) = 0;
// This is only externally visible for UMTS because in GPRS we have
// to send messages through LLC first, so this call is made by LLC to the SGSN.
void sgsnHandleL3Msg(uint32_t handle, ByteVector &msgFrame);
// For UMTS only, get the SgsnInfo that goes with this UE.
// Only used when called indirectly from RRC so we know the UEInfo still exists.
SGSN::SgsnInfo *sgsnGetSgsnInfo(); // Return SgsnInfo for this UE or NULL.
#else
// This sends a pdu from the MS/UE to the sgsn.
void sgsnSendKeepAlive();
int sgsnGetMultislotClass(uint32_t mshandle);
bool sgsnGetGeranFeaturePackI(uint32_t mshandle);
#endif
private:
virtual uint32_t msGetHandle() = 0; // return URNTI or TLLI
friend std::ostream& operator<<(std::ostream&os,const SgsnInfo*);
};
// This is our information about the allocated channel passed from GPRS or UMTS back to GGSN.
// In a normal system, the whole QoS would be passed back and forth, but we
// are letting the GGSN module handle the QoS.
struct RabStatus {
enum Status { RabIdle, RabFailure, RabPending, RabAllocated, RabDeactPending } mStatus;
//Timeval mDeactivateTime; // If RabFreePending, when to kill it.
SmCauseType mFailCode;
unsigned mRateDownlink; // peak KByte/sec downlink of allocated channel
unsigned mRateUplink; // peak KByte/sec uplink of allocated channel
RabStatus(): mStatus(RabIdle), mFailCode((SmCauseType)0) {}
RabStatus(SmCauseType wFailCode): mStatus(RabFailure), mFailCode(wFailCode) {}
RabStatus(Status wStatus,SmCauseType wFailCode): mStatus(wStatus), mFailCode(wFailCode) {}
//void scheduleDeactivation() {
// mStatus = RabDeactPending;
// mDeactivationTime.future(gConfig.getNum("UMTS.Rab.DeactivationDelay",5000));
//}
void text(std::ostream &os) const;
};
// This class is just a container to hold the callbacks from the SGSN to the external world.
// No objects of this class are created.
struct SgsnAdapter {
// Find the MS by TLLI or UE by U-RNTI.
// Return NULL if it no longer exists.
static MSUEAdapter *findMs(uint32_t);
static bool isUmts();
// Send a PDU to GPRS/UMTS [not implemented for UMTS yet.]
static void saWriteHighSide(GprsSgsnDownlinkPdu *dlpdu);
#if RN_UMTS
// Return 0 on success or SmCause value on error.
static RabStatus allocateRabForPdp(uint32_t urnti, int rbid, ByteVector &qos);
static void startIntegrityProtection(uint32_t urnti, std::string Kcs);
#endif
};
// This is the external interface to the SGSN.
struct Sgsn {
public:
static bool isUmts() { return SgsnAdapter::isUmts(); }
// Find the UE/MS in the SGSN database and return the handle, which is
// either TLLI for GPRS or URNTI for UMTS. GPRS or UMTS can then look up
// its MSInfo or UEInfo structure by the handle.
// Return 0 if not found.
static uint32_t findHandleByPTmsi(uint32_t ptmsi);
static uint32_t findHandleByImsi(ByteVector &imsi);
static bool handleGprsSuspensionRequest(uint32_t wTlli, const ByteVector &wRaId);
static void notifyGsmActivity(const char *imsi);
//#if RN_UMTS
// FIXME: make this work like gprs
//static void sgsnWriteLowSide(ByteVector &payload,SgsnInfo *si, unsigned rbid); // UMTS only
//#endif
};
}; // namespace SGSN
#endif