Added support for reporting route congestion.

Detection is currently implemented only on SIGTRAN M2UA.


git-svn-id: http://yate.null.ro/svn/yate/trunk@3619 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2010-09-01 12:05:55 +00:00
parent 68e38ecffc
commit 1c176bb1cc
5 changed files with 122 additions and 8 deletions

View File

@ -705,6 +705,25 @@ bool SS7MTP3::inhibit(int sls, int setFlags, int clrFlags)
return false;
}
unsigned int SS7MTP3::congestion(int sls)
{
unsigned int level = 0;
const ObjList* l = &m_links;
for (; l; l = l->next()) {
L2Pointer* p = static_cast<L2Pointer*>(l->get());
if (!(p && *p))
continue;
if ((*p)->sls() == sls)
return (*p)->congestion();
else if (sls >= 0) {
unsigned int cong = (*p)->congestion();;
if (level < cong)
level = cong;
}
}
return level;
}
int SS7MTP3::getSequence(int sls) const
{
if (sls < 0)

View File

@ -171,7 +171,7 @@ SS7MsgSNM* SS7MsgSNM::parse(SS7Management* receiver, unsigned char type,
do {
// TFP,TFR,TFA: Q.704 15.7, RST,RSR: Q.704 15.10
// There must be at least 2 bytes in buffer
if (type == TFP || type == TFR || type == TFA ||
if (type == TFP || type == TFR || type == TFA || type == TFC ||
type == RST || type == RSR) {
// 2 bytes destination
SS7PointCode pc;
@ -390,6 +390,7 @@ HandledMSU SS7Management::receivedMSU(const SS7MSU& msu, const SS7Label& label,
if (msg->type() == SS7MsgSNM::TFP ||
msg->type() == SS7MsgSNM::TFR ||
msg->type() == SS7MsgSNM::TFA ||
msg->type() == SS7MsgSNM::TFC ||
msg->type() == SS7MsgSNM::RST ||
msg->type() == SS7MsgSNM::RSR) {
String dest = msg->params().getValue("destination");

View File

@ -168,6 +168,17 @@ bool SS7Route::operational(int sls)
return false;
}
// Check and reset congestion status
bool SS7Route::congested()
{
if (m_congCount >= 8 || m_congBytes >= 256) {
m_congCount = 0;
m_congBytes = 0;
return true;
}
return false;
}
// Try to transmit a MSU through one of the attached networks
int SS7Route::transmitMSU(const SS7Router* router, const SS7MSU& msu,
const SS7Label& label, int sls, const SS7Layer3* source)
@ -182,8 +193,14 @@ int SS7Route::transmitMSU(const SS7Router* router, const SS7MSU& msu,
XDebug(router,DebugAll,"Attempting transmitMSU on L3=%p '%s' [%p]",
(void*)l3,l3->toString().c_str(),router);
int res = l3->transmitMSU(msu,label,sls);
if (res != -1)
if (res != -1) {
unsigned int cong = l3->congestion(res);
if (cong) {
m_congCount++;
m_congBytes += msu.length();
}
return res;
}
lock();
}
unlock();
@ -200,7 +217,7 @@ SS7Router::SS7Router(const NamedList& params)
m_changes(0), m_transfer(false), m_phase2(false), m_started(false),
m_restart(0), m_isolate(0), m_routeTest(0), m_testRestricted(false),
m_checkRoutes(false), m_sendUnavail(true), m_sendProhibited(true),
m_rxMsu(0), m_txMsu(0), m_fwdMsu(0),
m_rxMsu(0), m_txMsu(0), m_fwdMsu(0), m_congestions(0),
m_mngmt(0)
{
#ifdef DEBUG
@ -223,8 +240,8 @@ SS7Router::SS7Router(const NamedList& params)
SS7Router::~SS7Router()
{
Debug(this,DebugInfo,"SS7Router destroyed, rx=%lu, tx=%lu, fwd=%lu",
m_rxMsu,m_txMsu,m_fwdMsu);
Debug(this,DebugInfo,"SS7Router destroyed, rx=%lu, tx=%lu, fwd=%lu, cong=%lu",
m_rxMsu,m_txMsu,m_fwdMsu,m_congestions);
}
bool SS7Router::initialize(const NamedList* config)
@ -538,10 +555,34 @@ int SS7Router::routeMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* net
unlock();
int slsTx = route ? route->transmitMSU(this,msu,label,sls,network) : -1;
if (slsTx >= 0) {
bool cong = route->congested();
if (cong) {
Debug(this,DebugMild,"Route to %u reports congestion",route->packed());
while (m_mngmt) {
unsigned int local = getLocal(label.type());
if (!local)
break;
NamedList* ctl = m_mngmt->controlCreate("congest");
if (!ctl)
break;
String addr;
addr << SS7PointCode::lookup(label.type()) << ",";
addr << SS7PointCode(label.type(),local) << "," << label.opc();
String dest;
dest << SS7PointCode(label.type(),route->packed());
ctl->addParam("address",addr);
ctl->addParam("destination",dest);
ctl->setParam("automatic",String::boolText(true));
m_mngmt->controlExecute(ctl);
break;
}
}
lock();
m_txMsu++;
if (network)
m_fwdMsu++;
if (cong)
m_congestions++;
unlock();
}
return slsTx;

View File

@ -1669,6 +1669,7 @@ bool SS7M2UA::processMAUP(unsigned char msgType, const DataBlock& msg, int strea
case 3: // Establish Confirm
m_lastSeqRx = -1;
m_linkState = LinkUp;
m_congestion = 0;
m_rpo = false;
SS7Layer2::notify();
return true;
@ -1751,6 +1752,20 @@ bool SS7M2UA::processMAUP(unsigned char msgType, const DataBlock& msg, int strea
return recoveredMSU(data);
}
break;
case 14: // Congestion Indication
{
u_int32_t cong = 0;
if (!SIGAdaptation::getTag(msg,0x0304,cong)) {
err = "Missing congestion state";
break;
}
u_int32_t disc = 0;
SIGAdaptation::getTag(msg,0x0305,disc);
int level = disc ? DebugWarn : (cong ? DebugMild : DebugNote);
Debug(this,level,"Congestion level %u, discard level %u",cong,disc);
m_congestion = cong;
}
return true;
}
Debug(this,DebugStub,"%s M2UA MAUP message type %u",err,msgType);
return false;
@ -1760,6 +1775,7 @@ void SS7M2UA::activeChange(bool active)
{
if (!active) {
getSequence();
m_congestion = 0;
m_rpo = false;
switch (m_linkState) {
case LinkUpEmg:

View File

@ -5089,6 +5089,13 @@ public:
inline bool inhibited(int flags) const
{ return (m_inhibited & flags) != 0; }
/**
* Get the current congestion level of the link
* @return Congestion level, 0 if not congested, 3 if maximum congestion
*/
virtual unsigned int congestion()
{ return m_congestion; }
/**
* Get the sequence number of the last MSU received
* @return Last FSN received, negative if not available
@ -5118,7 +5125,7 @@ protected:
* Constructor
*/
inline SS7Layer2()
: m_autoEmergency(true), m_lastSeqRx(-1),
: m_autoEmergency(true), m_lastSeqRx(-1), m_congestion(0),
m_l2userMutex(true,"SS7Layer2::l2user"), m_l2user(0), m_sls(-1),
m_checkTime(0), m_checkFail(false), m_inhibited(Unchecked)
{ }
@ -5187,6 +5194,11 @@ protected:
*/
int m_lastSeqRx;
/**
* Current congestion level
*/
unsigned int m_congestion;
private:
Mutex m_l2userMutex;
SS7L2User* m_l2user;
@ -5234,7 +5246,7 @@ public:
inline SS7Route(unsigned int packed, unsigned int priority = 0, unsigned int shift = 0)
: Mutex(true,"SS7Route"),
m_packed(packed), m_priority(priority), m_shift(shift),
m_state(Unknown)
m_state(Unknown), m_congCount(0), m_congBytes(0)
{ m_networks.setDelete(false); }
/**
@ -5244,7 +5256,8 @@ public:
inline SS7Route(const SS7Route& original)
: Mutex(true,"SS7Route"),
m_packed(original.packed()), m_priority(original.priority()),
m_shift(original.shift()), m_state(original.state())
m_shift(original.shift()), m_state(original.state()),
m_congCount(0), m_congBytes(0)
{ m_networks.setDelete(false); }
/**
@ -5343,12 +5356,20 @@ public:
int transmitMSU(const SS7Router* router, const SS7MSU& msu,
const SS7Label& label, int sls, const SS7Layer3* source = 0);
/**
* Check the current congestion status according to Q.704 11.2.3.1
* @return True if a TFC should be sent
*/
bool congested();
private:
unsigned int m_packed; // Packed destination point code
unsigned int m_priority; // Network priority for the given destination (used by SS7Layer3)
unsigned int m_shift; // SLS right shift when selecting linkset
ObjList m_networks; // List of networks used to route to the given destination (used by SS7Router)
State m_state; // State of the route
unsigned int m_congCount; // Congestion event count
unsigned int m_congBytes; // Congestion MSU bytes count
};
/**
@ -5491,6 +5512,14 @@ public:
virtual bool inhibit(int sls, int setFlags, int clrFlags = 0)
{ return false; }
/**
* Get the current congestion level of a link
* @param sls Signalling Link to check for congestion, -1 for maximum
* @return Congestion level, 0 if not congested, 3 if maximum congestion
*/
virtual unsigned int congestion(int sls)
{ return 0; }
/**
* Get the sequence number of the last MSU received on a link
* @param sls Signalling Link to retrieve MSU number from
@ -6206,6 +6235,7 @@ private:
unsigned long m_rxMsu;
unsigned long m_txMsu;
unsigned long m_fwdMsu;
unsigned long m_congestions;
SS7Management* m_mngmt;
};
@ -6828,6 +6858,13 @@ public:
*/
virtual bool inhibit(int sls, int setFlags, int clrFlags = 0);
/**
* Get the current congestion level of a link
* @param sls Signalling Link to check for congestion, -1 for maximum
* @return Congestion level, 0 if not congested, 3 if maximum congestion
*/
virtual unsigned int congestion(int sls);
/**
* Get the sequence number of the last MSU received on a link
* @param sls Signalling Link to retrieve MSU number from