Fixed MTP management, included test timers and inhibit flag in SS7Layer2.
git-svn-id: http://voip.null.ro/svn/yate@3500 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
d11940f0ed
commit
9870e16a4c
|
@ -443,9 +443,19 @@
|
||||||
; If no router is attached only a single User Part can be connected
|
; If no router is attached only a single User Part can be connected
|
||||||
;router=ss7router
|
;router=ss7router
|
||||||
|
|
||||||
|
; link: string: Name of a SS7 Layer 2 link to create in the linkset
|
||||||
|
; This parameter can be repeated to add more links to the linkset
|
||||||
|
; An explicit SLS can be provided after a comma
|
||||||
|
; Example: link=mtp2_to_hq,3
|
||||||
|
;link=
|
||||||
|
|
||||||
; autostart: bool: Automatically enable the linkset at startup
|
; autostart: bool: Automatically enable the linkset at startup
|
||||||
;autostart=yes
|
;autostart=yes
|
||||||
|
|
||||||
|
; maintenance: integer: Interval in msec for sending SLTM messages (Q.707 T2)
|
||||||
|
; A value of zero disables sending SLTM else it is clamped to range 5s - 10m
|
||||||
|
;maintenance=60000
|
||||||
|
|
||||||
; layer3dump: string: Filename to dump MTP3 packets to
|
; layer3dump: string: Filename to dump MTP3 packets to
|
||||||
;layer3dump=
|
;layer3dump=
|
||||||
|
|
||||||
|
|
|
@ -490,7 +490,7 @@ SS7MTP3::SS7MTP3(const NamedList& params)
|
||||||
: SignallingComponent(params.safe("SS7MTP3"),¶ms),
|
: SignallingComponent(params.safe("SS7MTP3"),¶ms),
|
||||||
SignallingDumpable(SignallingDumper::Mtp3),
|
SignallingDumpable(SignallingDumper::Mtp3),
|
||||||
Mutex(true,"SS7MTP3"),
|
Mutex(true,"SS7MTP3"),
|
||||||
m_total(0), m_active(0), m_inhibit(false)
|
m_total(0), m_active(0), m_inhibit(false), m_check(0)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (debugAt(DebugAll)) {
|
if (debugAt(DebugAll)) {
|
||||||
|
@ -531,6 +531,14 @@ SS7MTP3::SS7MTP3(const NamedList& params)
|
||||||
Debug(this,level,"Point code types are '%s' [%p]",stype.safe(),this);
|
Debug(this,level,"Point code types are '%s' [%p]",stype.safe(),this);
|
||||||
|
|
||||||
m_inhibit = !params.getBoolValue("autostart",true);
|
m_inhibit = !params.getBoolValue("autostart",true);
|
||||||
|
int check = params.getIntValue("maintenance",60000);
|
||||||
|
if (check > 0) {
|
||||||
|
if (check < 5000)
|
||||||
|
check = 5000;
|
||||||
|
else if (check > 600000)
|
||||||
|
check = 600000;
|
||||||
|
m_check = 1000 * check;
|
||||||
|
}
|
||||||
buildRoutes(params);
|
buildRoutes(params);
|
||||||
setDumper(params.getValue("layer3dump"));
|
setDumper(params.getValue("layer3dump"));
|
||||||
}
|
}
|
||||||
|
@ -569,12 +577,31 @@ bool SS7MTP3::operational(int sls) const
|
||||||
L2Pointer* p = static_cast<L2Pointer*>(l->get());
|
L2Pointer* p = static_cast<L2Pointer*>(l->get());
|
||||||
if (!(p && *p))
|
if (!(p && *p))
|
||||||
continue;
|
continue;
|
||||||
if ((*p)->sls() == sls)
|
if (sls < 0) {
|
||||||
|
if ((*p)->operational() && !(*p)->inhibited())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ((*p)->sls() == sls)
|
||||||
return (*p)->operational();
|
return (*p)->operational();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SS7MTP3::inhibited(int sls) const
|
||||||
|
{
|
||||||
|
if (sls < 0)
|
||||||
|
return true;
|
||||||
|
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)->inhibited();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int SS7MTP3::getSequence(int sls) const
|
int SS7MTP3::getSequence(int sls) const
|
||||||
{
|
{
|
||||||
if (sls < 0)
|
if (sls < 0)
|
||||||
|
@ -605,18 +632,36 @@ void SS7MTP3::attach(SS7Layer2* link)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Attach in the first free SLS
|
ObjList* before = 0;
|
||||||
int sls = 0;
|
int sls = link->sls();
|
||||||
ObjList* before = m_links.skipNull();
|
if (sls >= 0) {
|
||||||
for (; before; before = before->skipNext()) {
|
before = m_links.skipNull();
|
||||||
L2Pointer* p = static_cast<L2Pointer*>(before->get());
|
for (; before; before = before->skipNext()) {
|
||||||
if (!*p)
|
L2Pointer* p = static_cast<L2Pointer*>(before->get());
|
||||||
continue;
|
if (!*p)
|
||||||
if (sls < (*p)->sls())
|
continue;
|
||||||
break;
|
if (sls < (*p)->sls())
|
||||||
sls++;
|
break;
|
||||||
|
if (sls == (*p)->sls()) {
|
||||||
|
sls = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sls < 0) {
|
||||||
|
// Attach in the first free SLS
|
||||||
|
sls = 0;
|
||||||
|
before = m_links.skipNull();
|
||||||
|
for (; before; before = before->skipNext()) {
|
||||||
|
L2Pointer* p = static_cast<L2Pointer*>(before->get());
|
||||||
|
if (!*p)
|
||||||
|
continue;
|
||||||
|
if (sls < (*p)->sls())
|
||||||
|
break;
|
||||||
|
sls++;
|
||||||
|
}
|
||||||
|
link->sls(sls);
|
||||||
}
|
}
|
||||||
link->sls(sls);
|
|
||||||
if (!before)
|
if (!before)
|
||||||
m_links.append(new L2Pointer(link));
|
m_links.append(new L2Pointer(link));
|
||||||
else
|
else
|
||||||
|
@ -670,6 +715,18 @@ bool SS7MTP3::control(Operation oper, NamedList* params)
|
||||||
if (ok != operational())
|
if (ok != operational())
|
||||||
SS7Layer3::notify(-1);
|
SS7Layer3::notify(-1);
|
||||||
}
|
}
|
||||||
|
if (params && params->getBoolValue("emergency")) {
|
||||||
|
unsigned int cnt = 0;
|
||||||
|
const ObjList* l = &m_links;
|
||||||
|
for (; l; l = l->next()) {
|
||||||
|
L2Pointer* p = static_cast<L2Pointer*>(l->get());
|
||||||
|
if (!(p && *p))
|
||||||
|
continue;
|
||||||
|
cnt++;
|
||||||
|
(*p)->control(SS7Layer2::Resume,params);
|
||||||
|
}
|
||||||
|
Debug(this,DebugNote,"Emergency resume attempt on %u links [%p]",cnt,this);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
case Status:
|
case Status:
|
||||||
return ok;
|
return ok;
|
||||||
|
@ -724,8 +781,15 @@ bool SS7MTP3::initialize(const NamedList* config)
|
||||||
continue;
|
continue;
|
||||||
NamedPointer* ptr = YOBJECT(NamedPointer,param);
|
NamedPointer* ptr = YOBJECT(NamedPointer,param);
|
||||||
NamedList* linkConfig = ptr ? YOBJECT(NamedList,ptr->userData()) : 0;
|
NamedList* linkConfig = ptr ? YOBJECT(NamedList,ptr->userData()) : 0;
|
||||||
NamedList params(param->c_str());
|
String linkName(*param);
|
||||||
params.addParam("basename",*param);
|
int linkSls = -1;
|
||||||
|
int sep = linkName.find(',');
|
||||||
|
if (sep >= 0) {
|
||||||
|
linkSls = linkName.substr(sep + 1).toInteger(-1);
|
||||||
|
linkName = linkName.substr(0,sep);
|
||||||
|
}
|
||||||
|
NamedList params(linkName);
|
||||||
|
params.addParam("basename",linkName);
|
||||||
if (linkConfig)
|
if (linkConfig)
|
||||||
params.copyParams(*linkConfig);
|
params.copyParams(*linkConfig);
|
||||||
else {
|
else {
|
||||||
|
@ -735,6 +799,8 @@ bool SS7MTP3::initialize(const NamedList* config)
|
||||||
SS7Layer2* link = YSIGCREATE(SS7Layer2,¶ms);
|
SS7Layer2* link = YSIGCREATE(SS7Layer2,¶ms);
|
||||||
if (!link)
|
if (!link)
|
||||||
continue;
|
continue;
|
||||||
|
if (linkSls >= 0)
|
||||||
|
link->sls(linkSls);
|
||||||
attach(link);
|
attach(link);
|
||||||
if (!link->initialize(linkConfig)) {
|
if (!link->initialize(linkConfig)) {
|
||||||
detach(link);
|
detach(link);
|
||||||
|
@ -779,7 +845,7 @@ int SS7MTP3::transmitMSU(const SS7MSU& msu, const SS7Label& label, int sls)
|
||||||
SS7Layer2* link = *p;
|
SS7Layer2* link = *p;
|
||||||
if (link->sls() == sls) {
|
if (link->sls() == sls) {
|
||||||
XDebug(this,DebugAll,"Found link %p for SLS=%d [%p]",link,sls,this);
|
XDebug(this,DebugAll,"Found link %p for SLS=%d [%p]",link,sls,this);
|
||||||
if (link->operational()) {
|
if (link->operational() && !link->inhibited()) {
|
||||||
if (link->transmitMSU(msu)) {
|
if (link->transmitMSU(msu)) {
|
||||||
DDebug(this,DebugAll,"Sent MSU over link '%s' %p with SLS=%d%s [%p]",
|
DDebug(this,DebugAll,"Sent MSU over link '%s' %p with SLS=%d%s [%p]",
|
||||||
link->toString().c_str(),link,sls,
|
link->toString().c_str(),link,sls,
|
||||||
|
@ -801,7 +867,7 @@ int SS7MTP3::transmitMSU(const SS7MSU& msu, const SS7Label& label, int sls)
|
||||||
if (!*p)
|
if (!*p)
|
||||||
continue;
|
continue;
|
||||||
SS7Layer2* link = *p;
|
SS7Layer2* link = *p;
|
||||||
if (link->operational() && link->transmitMSU(msu)) {
|
if (link->operational() && !link->inhibited() && link->transmitMSU(msu)) {
|
||||||
sls = link->sls();
|
sls = link->sls();
|
||||||
DDebug(this,DebugAll,"Sent MSU over link '%s' %p with SLS=%d%s [%p]",
|
DDebug(this,DebugAll,"Sent MSU over link '%s' %p with SLS=%d%s [%p]",
|
||||||
link->toString().c_str(),link,sls,
|
link->toString().c_str(),link,sls,
|
||||||
|
@ -861,6 +927,8 @@ void SS7MTP3::notify(SS7Layer2* link)
|
||||||
tmp << "Link '" << link->toString() << "' is " << (link->operational()?"":"not ") << "operational. ";
|
tmp << "Link '" << link->toString() << "' is " << (link->operational()?"":"not ") << "operational. ";
|
||||||
Debug(this,DebugInfo,"%sLinkset has %u/%u active links [%p]",tmp.null()?"":tmp.c_str(),m_active,m_total,this);
|
Debug(this,DebugInfo,"%sLinkset has %u/%u active links [%p]",tmp.null()?"":tmp.c_str(),m_active,m_total,this);
|
||||||
#endif
|
#endif
|
||||||
|
if (link && link->operational())
|
||||||
|
link->m_check = Time::now() + 50000 + (::random() % 200000);
|
||||||
// if operational status of a link changed notify upper layer
|
// if operational status of a link changed notify upper layer
|
||||||
if (act != m_active) {
|
if (act != m_active) {
|
||||||
Debug(this,DebugNote,"Linkset is%s operational [%p]",
|
Debug(this,DebugNote,"Linkset is%s operational [%p]",
|
||||||
|
@ -869,4 +937,48 @@ void SS7MTP3::notify(SS7Layer2* link)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SS7MTP3::timerTick(const Time& when)
|
||||||
|
{
|
||||||
|
Lock lock(this);
|
||||||
|
if (!m_check)
|
||||||
|
return;
|
||||||
|
for (ObjList* o = m_links.skipNull(); o; o = o->skipNext()) {
|
||||||
|
L2Pointer* p = static_cast<L2Pointer*>(o->get());
|
||||||
|
if (!(p && *p && (*p)->m_check && (*p)->operational()))
|
||||||
|
continue;
|
||||||
|
if ((*p)->m_check < when) {
|
||||||
|
(*p)->m_check = when + m_check;
|
||||||
|
for (unsigned int i = 0; i < YSS7_PCTYPE_COUNT; i++) {
|
||||||
|
SS7PointCode::Type type = (SS7PointCode::Type)(i + 1);
|
||||||
|
unsigned int local = getLocal(type);
|
||||||
|
if (!local)
|
||||||
|
continue;
|
||||||
|
ObjList* o = getRoutes(type);
|
||||||
|
if (!o)
|
||||||
|
continue;
|
||||||
|
unsigned char sio = getNI(type) | SS7MSU::MTN;
|
||||||
|
for (o = o->skipNull(); o; o = o->skipNext()) {
|
||||||
|
const SS7Route* r = static_cast<const SS7Route*>(o->get());
|
||||||
|
if (r->priority())
|
||||||
|
continue;
|
||||||
|
// build and send a SLTM to the adjacent node
|
||||||
|
unsigned int len = 4;
|
||||||
|
SS7Label lbl(type,r->packed(),local,(*p)->sls());
|
||||||
|
SS7MSU sltm(sio,lbl,0,len+2);
|
||||||
|
unsigned char* d = sltm.getData(lbl.length()+1,len+2);
|
||||||
|
if (!d)
|
||||||
|
continue;
|
||||||
|
*d++ = SS7MsgMTN::SLTM;
|
||||||
|
*d++ = len << 4;
|
||||||
|
unsigned char patt = (*p)->sls();
|
||||||
|
patt = (patt << 4) | (patt & 0x0f);
|
||||||
|
while (len--)
|
||||||
|
*d++ = patt++;
|
||||||
|
(*p)->transmitMSU(sltm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* vi: set ts=8 sw=4 sts=4 noet: */
|
/* vi: set ts=8 sw=4 sts=4 noet: */
|
||||||
|
|
|
@ -4826,6 +4826,7 @@ protected:
|
||||||
class YSIG_API SS7Layer2 : virtual public SignallingComponent
|
class YSIG_API SS7Layer2 : virtual public SignallingComponent
|
||||||
{
|
{
|
||||||
YCLASS(SS7Layer2,SignallingComponent)
|
YCLASS(SS7Layer2,SignallingComponent)
|
||||||
|
friend class SS7MTP3;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* LSSU Status Indications
|
* LSSU Status Indications
|
||||||
|
@ -4928,6 +4929,13 @@ public:
|
||||||
inline void sls(int linkSel)
|
inline void sls(int linkSel)
|
||||||
{ if ((m_sls < 0) || !m_l2user) m_sls = linkSel; }
|
{ if ((m_sls < 0) || !m_l2user) m_sls = linkSel; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the link is inhibited by MTP3 Management
|
||||||
|
* @return True if the link is inhibited and should not be used
|
||||||
|
*/
|
||||||
|
inline bool inhibited() const
|
||||||
|
{ return m_inhibited; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the sequence number of the last MSU received
|
* Get the sequence number of the last MSU received
|
||||||
* @return Last FSN received, negative if not available
|
* @return Last FSN received, negative if not available
|
||||||
|
@ -4958,7 +4966,8 @@ protected:
|
||||||
*/
|
*/
|
||||||
inline SS7Layer2()
|
inline SS7Layer2()
|
||||||
: m_lastSeqRx(-1),
|
: m_lastSeqRx(-1),
|
||||||
m_l2userMutex(true,"SS7Layer2::l2user"), m_l2user(0), m_sls(-1)
|
m_l2userMutex(true,"SS7Layer2::l2user"), m_l2user(0), m_sls(-1),
|
||||||
|
m_check(0), m_inhibited(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4995,6 +5004,8 @@ private:
|
||||||
Mutex m_l2userMutex;
|
Mutex m_l2userMutex;
|
||||||
SS7L2User* m_l2user;
|
SS7L2User* m_l2user;
|
||||||
int m_sls;
|
int m_sls;
|
||||||
|
u_int64_t m_check;
|
||||||
|
bool m_inhibited;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5231,6 +5242,14 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual bool operational(int sls = -1) const = 0;
|
virtual bool operational(int sls = -1) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a specific link is inhibited
|
||||||
|
* @param sls Signalling Link to check
|
||||||
|
* @return True if the specified link is inhibited and should not be used
|
||||||
|
*/
|
||||||
|
virtual bool inhibited(int sls) const
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the sequence number of the last MSU received on a link
|
* Get the sequence number of the last MSU received on a link
|
||||||
* @param sls Signalling Link to retrieve MSU number from
|
* @param sls Signalling Link to retrieve MSU number from
|
||||||
|
@ -6429,6 +6448,13 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual bool operational(int sls = -1) const;
|
virtual bool operational(int sls = -1) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a specific link is inhibited
|
||||||
|
* @param sls Signalling Link to check
|
||||||
|
* @return True if the specified link is inhibited and should not be used
|
||||||
|
*/
|
||||||
|
virtual bool inhibited(int sls) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the sequence number of the last MSU received on a link
|
* Get the sequence number of the last MSU received on a link
|
||||||
* @param sls Signalling Link to retrieve MSU number from
|
* @param sls Signalling Link to retrieve MSU number from
|
||||||
|
@ -6484,6 +6510,12 @@ protected:
|
||||||
*/
|
*/
|
||||||
virtual void destroyed();
|
virtual void destroyed();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Periodical timer tick used to perform housekeeping and link checking
|
||||||
|
* @param when Time to use as computing base for events and timeouts
|
||||||
|
*/
|
||||||
|
virtual void timerTick(const Time& when);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process a MSU received from the Layer 2 component
|
* Process a MSU received from the Layer 2 component
|
||||||
* @param msu Message data, starting with Service Indicator Octet
|
* @param msu Message data, starting with Service Indicator Octet
|
||||||
|
@ -6514,6 +6546,8 @@ private:
|
||||||
unsigned int m_active;
|
unsigned int m_active;
|
||||||
// inhibited flag
|
// inhibited flag
|
||||||
bool m_inhibit;
|
bool m_inhibit;
|
||||||
|
// maintenance check interval
|
||||||
|
u_int64_t m_check;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue