Added a reroute buffer used to implement T3 and T6 (missequencing avoidance).

Changed debug messages and levels to be easier to interpret the typical output.


git-svn-id: http://voip.null.ro/svn/yate@3725 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2010-10-19 11:17:12 +00:00
parent bede083f28
commit 1959fa4adc
3 changed files with 165 additions and 12 deletions

View File

@ -877,8 +877,9 @@ int SS7MTP3::transmitMSU(const SS7MSU& msu, const SS7Label& label, int sls)
bool mgmt = (msu.getSIF() == SS7MSU::SNM);
Lock lock(this);
if (!(maint || m_active || (mgmt && m_checked))) {
Debug(this,DebugMild,"Could not transmit MSU, %s [%p]",
m_total ? "all links are down" : "no data links attached",this);
Debug(this,DebugMild,"Could not transmit %s MSU, %s",
msu.getServiceName(),
m_total ? "all links are down" : "no data links attached");
return -1;
}
@ -910,7 +911,8 @@ int SS7MTP3::transmitMSU(const SS7MSU& msu, const SS7Label& label, int sls)
return -1;
}
// found link but is down - reroute
Debug(this,DebugMild,"Rerouting MSU for SLS=%d, link is down",sls);
Debug(this,DebugAll,"Rerouting %s MSU for SLS=%d, link is down",
msu.getServiceName(),sls);
break;
}
}
@ -936,7 +938,7 @@ int SS7MTP3::transmitMSU(const SS7MSU& msu, const SS7Label& label, int sls)
}
Debug(this,((sls == -2) ? DebugWarn : DebugMild),
"Could not find any link to send %s MSU [%p]",msu.getServiceName(),this);
"Could not find any link to send %s MSU",msu.getServiceName());
return -1;
}
@ -974,8 +976,8 @@ bool SS7MTP3::receivedMSU(const SS7MSU& msu, SS7Layer2* link, int sls)
}
if (!maint && (msu.getSIF() != SS7MSU::SNM) &&
link->inhibited(SS7Layer2::Unchecked|SS7Layer2::Inactive|SS7Layer2::Local)) {
Debug(this,DebugMild,"Received MSU on inhibited 0x%02X link %d '%s' [%p]",
link->inhibited(),sls,link->toString().c_str(),this);
Debug(this,DebugMild,"Received MSU on inhibited 0x%02X link %d '%s'",
link->inhibited(),sls,link->toString().c_str());
return false;
}
}

View File

@ -44,6 +44,24 @@ private:
ObjList m_views[YSS7_PCTYPE_COUNT];
};
class HeldMSU : public SS7MSU
{
friend class TelEngine::SS7Route;
private:
inline HeldMSU(const SS7Router* router, const SS7MSU& msu,
const SS7Label& label, int sls, SS7Route::State states, const SS7Layer3* source)
: SS7MSU(msu),
m_router(router), m_label(label), m_sls(sls),
m_states(states), m_source(source)
{ }
const SS7Router* m_router;
const SS7Label m_label;
int m_sls;
SS7Route::State m_states;
const SS7Layer3* m_source;
};
}; // anonymous namespace
// Control operations
@ -201,6 +219,27 @@ int SS7Route::transmitMSU(const SS7Router* router, const SS7MSU& msu,
const SS7Label& label, int sls, State states, const SS7Layer3* source)
{
lock();
if (msu.getSIF() > SS7MSU::MTNS && m_buffering) {
if (m_state & states) {
// Store User Part messages in the controlled rerouting buffer
DDebug(router,DebugInfo,"Storing %s MSU in reroute buffer of %u",
msu.getServiceName(),packed());
m_reroute.append(new HeldMSU(router,msu,label,sls,states,source));
sls = 0;
}
else
sls = -1;
}
else
sls = transmitInternal(router,msu,label,sls,states,source);
unlock();
return sls;
}
// Transmit the MSU, called with the route locked
int SS7Route::transmitInternal(const SS7Router* router, const SS7MSU& msu,
const SS7Label& label, int sls, State states, const SS7Layer3* source)
{
int offs = 0;
if (msu.getSIF() > SS7MSU::MTNS)
offs = sls >> shift();
@ -214,6 +253,7 @@ 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);
lock();
if (res != -1) {
unsigned int cong = l3->congestion(res);
if (cong) {
@ -229,10 +269,48 @@ int SS7Route::transmitMSU(const SS7Router* router, const SS7MSU& msu,
#endif
return res;
}
lock();
}
return -1;
}
void SS7Route::rerouteCheck(u_int64_t when)
{
lock();
if (m_buffering && m_buffering <= when) {
if (m_state & Prohibited)
rerouteFlush();
unsigned int c = 0;
while (HeldMSU* msu = static_cast<HeldMSU*>(m_reroute.remove(false))) {
transmitInternal(msu->m_router,*msu,msu->m_label,msu->m_sls,
msu->m_states,msu->m_source);
c++;
}
if (c)
Debug(DebugNote,"Released %u MSUs from reroute buffer of %u",c,packed());
m_buffering = 0;
}
unlock();
return -1;
}
void SS7Route::rerouteFlush()
{
if (!m_buffering)
return;
lock();
unsigned int c = m_reroute.count();
if (c)
Debug(DebugMild,"Flushed %u MSUs from reroute buffer of %u",c,packed());
m_reroute.clear();
m_buffering = 0;
unlock();
}
void SS7Route::reroute()
{
XDebug(DebugAll,"Initiating controlled rerouting to %u",packed());
lock();
m_buffering = Time::now() + 800000;
unlock();
}
@ -395,7 +473,7 @@ bool SS7Router::restart()
{
Debug(this,DebugNote,"Restart of %s initiated [%p]",
(m_transfer ? "STP" : "SN"),this);
Lock mylock(this);
lock();
m_phase2 = false;
m_started = false;
m_isolate.stop();
@ -411,19 +489,23 @@ bool SS7Router::restart()
checkRoutes();
m_checkRoutes = true;
m_restart.start();
unlock();
rerouteFlush();
return true;
}
void SS7Router::disable()
{
Debug(this,DebugNote,"MTP operation is disabled [%p]",this);
Lock mylock(this);
lock();
m_phase2 = false;
m_started = false;
m_checkRoutes = false;
m_isolate.stop();
m_restart.stop();
m_routeTest.stop();
unlock();
rerouteFlush();
}
// Attach a SS7 Layer 3 (network) to the router
@ -578,6 +660,8 @@ void SS7Router::timerTick(const Time& when)
m_started = false;
m_isolate.stop();
m_restart.stop();
mylock.drop();
rerouteFlush();
return;
}
if (m_started) {
@ -590,6 +674,7 @@ void SS7Router::timerTick(const Time& when)
m_trafficOk.stop();
silentAllow();
}
rerouteCheck(when);
return;
}
// MTP restart actions
@ -694,6 +779,10 @@ int SS7Router::transmitMSU(const SS7MSU& msu, const SS7Label& label, int sls)
case SS7MSU::MTNS:
// Management and Maintenance can be sent even on prohibited routes
states = SS7Route::AnyState;
break;
default:
if (!m_started)
return -1;
}
return routeMSU(msu,label,0,sls,states);
}
@ -716,6 +805,8 @@ HandledMSU SS7Router::receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7L
notifyRoutes(SS7Route::KnownState,src);
}
}
if ((msu.getSIF() > SS7MSU::MTNS) && !m_started)
return HandledMSU::Failure;
lock();
m_rxMsu++;
ObjList* l;
@ -1302,6 +1393,51 @@ void SS7Router::clearRoutes(SS7Layer3* network, bool ok)
}
}
// Initiate controlled rerouting on all routes including a linkset
void SS7Router::reroute(const SS7Layer3* network)
{
Lock lock(m_routeMutex);
for (unsigned int i = 0; i < YSS7_PCTYPE_COUNT; i++) {
SS7PointCode::Type type = static_cast<SS7PointCode::Type>(i+1);
const ObjList* l = getRoutes(type);
if (l)
l = l->skipNull();
for (; l; l = l->skipNext()) {
SS7Route* r = static_cast<SS7Route*>(l->get());
if (r->hasNetwork(network))
r->reroute();
}
}
}
// Check if routes have finished controlled rerouting
void SS7Router::rerouteCheck(const Time& when)
{
Lock lock(m_routeMutex);
for (unsigned int i = 0; i < YSS7_PCTYPE_COUNT; i++) {
SS7PointCode::Type type = static_cast<SS7PointCode::Type>(i+1);
const ObjList* l = getRoutes(type);
if (l)
l = l->skipNull();
for (; l; l = l->skipNext())
static_cast<SS7Route*>(l->get())->rerouteCheck(when);
}
}
// Flush the controlled rerouting buffer of all routes
void SS7Router::rerouteFlush()
{
Lock lock(m_routeMutex);
for (unsigned int i = 0; i < YSS7_PCTYPE_COUNT; i++) {
SS7PointCode::Type type = static_cast<SS7PointCode::Type>(i+1);
const ObjList* l = getRoutes(type);
if (l)
l = l->skipNull();
for (; l; l = l->skipNext())
static_cast<SS7Route*>(l->get())->rerouteFlush();
}
}
bool SS7Router::uninhibit(SS7Layer3* network, int sls, bool remote)
{
if (!(network && m_mngmt))
@ -1476,6 +1612,7 @@ void SS7Router::notify(SS7Layer3* network, int sls)
clearRoutes(network,oper);
checkRoutes(network);
}
reroute(network);
}
// iterate and notify all user parts
ObjList* l = &m_layer4;

View File

@ -5253,7 +5253,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_congCount(0), m_congBytes(0)
m_state(Unknown), m_buffering(0), m_congCount(0), m_congBytes(0)
{ m_networks.setDelete(false); }
/**
@ -5264,7 +5264,7 @@ public:
: Mutex(true,"SS7Route"),
m_packed(original.packed()), m_priority(original.priority()),
m_shift(original.shift()), m_state(original.state()),
m_congCount(0), m_congBytes(0)
m_buffering(0), m_congCount(0), m_congBytes(0)
{ m_networks.setDelete(false); }
/**
@ -5379,12 +5379,23 @@ public:
*/
bool congested();
/**
* Initiate controlled rerouting procedure, buffer user part messages for T6
*/
void reroute();
private:
int transmitInternal(const SS7Router* router, const SS7MSU& msu,
const SS7Label& label, int sls, State states, const SS7Layer3* source);
void rerouteCheck(u_int64_t when);
void rerouteFlush();
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
u_int64_t m_buffering; // Time when controlled rerouting ends
ObjList m_reroute; // Controlled rerouting buffer
unsigned int m_congCount; // Congestion event count
unsigned int m_congBytes; // Congestion MSU bytes count
};
@ -6279,6 +6290,9 @@ private:
void silentAllow(const SS7Layer3* network = 0);
void checkRoutes(const SS7Layer3* noResume = 0);
void clearRoutes(SS7Layer3* network, bool ok);
void reroute(const SS7Layer3* network);
void rerouteCheck(const Time& when);
void rerouteFlush();
bool setRouteSpecificState(SS7PointCode::Type type, unsigned int packedPC,
unsigned int srcPC, SS7Route::State state, const SS7Layer3* changer = 0);
inline bool setRouteSpecificState(SS7PointCode::Type type, const SS7PointCode& dest,