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
|
||||
;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=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=
|
||||
|
||||
|
|
|
@ -490,7 +490,7 @@ SS7MTP3::SS7MTP3(const NamedList& params)
|
|||
: SignallingComponent(params.safe("SS7MTP3"),¶ms),
|
||||
SignallingDumpable(SignallingDumper::Mtp3),
|
||||
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
|
||||
if (debugAt(DebugAll)) {
|
||||
|
@ -531,6 +531,14 @@ SS7MTP3::SS7MTP3(const NamedList& params)
|
|||
Debug(this,level,"Point code types are '%s' [%p]",stype.safe(),this);
|
||||
|
||||
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);
|
||||
setDumper(params.getValue("layer3dump"));
|
||||
}
|
||||
|
@ -569,12 +577,31 @@ bool SS7MTP3::operational(int sls) const
|
|||
L2Pointer* p = static_cast<L2Pointer*>(l->get());
|
||||
if (!(p && *p))
|
||||
continue;
|
||||
if ((*p)->sls() == sls)
|
||||
if (sls < 0) {
|
||||
if ((*p)->operational() && !(*p)->inhibited())
|
||||
return true;
|
||||
}
|
||||
else if ((*p)->sls() == sls)
|
||||
return (*p)->operational();
|
||||
}
|
||||
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
|
||||
{
|
||||
if (sls < 0)
|
||||
|
@ -605,18 +632,36 @@ void SS7MTP3::attach(SS7Layer2* link)
|
|||
return;
|
||||
}
|
||||
}
|
||||
// Attach in the first free SLS
|
||||
int sls = 0;
|
||||
ObjList* 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++;
|
||||
ObjList* before = 0;
|
||||
int sls = link->sls();
|
||||
if (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;
|
||||
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)
|
||||
m_links.append(new L2Pointer(link));
|
||||
else
|
||||
|
@ -670,6 +715,18 @@ bool SS7MTP3::control(Operation oper, NamedList* params)
|
|||
if (ok != operational())
|
||||
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;
|
||||
case Status:
|
||||
return ok;
|
||||
|
@ -724,8 +781,15 @@ bool SS7MTP3::initialize(const NamedList* config)
|
|||
continue;
|
||||
NamedPointer* ptr = YOBJECT(NamedPointer,param);
|
||||
NamedList* linkConfig = ptr ? YOBJECT(NamedList,ptr->userData()) : 0;
|
||||
NamedList params(param->c_str());
|
||||
params.addParam("basename",*param);
|
||||
String linkName(*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)
|
||||
params.copyParams(*linkConfig);
|
||||
else {
|
||||
|
@ -735,6 +799,8 @@ bool SS7MTP3::initialize(const NamedList* config)
|
|||
SS7Layer2* link = YSIGCREATE(SS7Layer2,¶ms);
|
||||
if (!link)
|
||||
continue;
|
||||
if (linkSls >= 0)
|
||||
link->sls(linkSls);
|
||||
attach(link);
|
||||
if (!link->initialize(linkConfig)) {
|
||||
detach(link);
|
||||
|
@ -779,7 +845,7 @@ int SS7MTP3::transmitMSU(const SS7MSU& msu, const SS7Label& label, int sls)
|
|||
SS7Layer2* link = *p;
|
||||
if (link->sls() == sls) {
|
||||
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)) {
|
||||
DDebug(this,DebugAll,"Sent MSU over link '%s' %p with SLS=%d%s [%p]",
|
||||
link->toString().c_str(),link,sls,
|
||||
|
@ -801,7 +867,7 @@ int SS7MTP3::transmitMSU(const SS7MSU& msu, const SS7Label& label, int sls)
|
|||
if (!*p)
|
||||
continue;
|
||||
SS7Layer2* link = *p;
|
||||
if (link->operational() && link->transmitMSU(msu)) {
|
||||
if (link->operational() && !link->inhibited() && link->transmitMSU(msu)) {
|
||||
sls = link->sls();
|
||||
DDebug(this,DebugAll,"Sent MSU over link '%s' %p with SLS=%d%s [%p]",
|
||||
link->toString().c_str(),link,sls,
|
||||
|
@ -861,6 +927,8 @@ void SS7MTP3::notify(SS7Layer2* link)
|
|||
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);
|
||||
#endif
|
||||
if (link && link->operational())
|
||||
link->m_check = Time::now() + 50000 + (::random() % 200000);
|
||||
// if operational status of a link changed notify upper layer
|
||||
if (act != m_active) {
|
||||
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: */
|
||||
|
|
|
@ -4826,6 +4826,7 @@ protected:
|
|||
class YSIG_API SS7Layer2 : virtual public SignallingComponent
|
||||
{
|
||||
YCLASS(SS7Layer2,SignallingComponent)
|
||||
friend class SS7MTP3;
|
||||
public:
|
||||
/**
|
||||
* LSSU Status Indications
|
||||
|
@ -4928,6 +4929,13 @@ public:
|
|||
inline void sls(int 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
|
||||
* @return Last FSN received, negative if not available
|
||||
|
@ -4958,7 +4966,8 @@ protected:
|
|||
*/
|
||||
inline SS7Layer2()
|
||||
: 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;
|
||||
SS7L2User* m_l2user;
|
||||
int m_sls;
|
||||
u_int64_t m_check;
|
||||
bool m_inhibited;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -5231,6 +5242,14 @@ public:
|
|||
*/
|
||||
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
|
||||
* @param sls Signalling Link to retrieve MSU number from
|
||||
|
@ -6429,6 +6448,13 @@ public:
|
|||
*/
|
||||
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
|
||||
* @param sls Signalling Link to retrieve MSU number from
|
||||
|
@ -6484,6 +6510,12 @@ protected:
|
|||
*/
|
||||
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
|
||||
* @param msu Message data, starting with Service Indicator Octet
|
||||
|
@ -6514,6 +6546,8 @@ private:
|
|||
unsigned int m_active;
|
||||
// inhibited flag
|
||||
bool m_inhibit;
|
||||
// maintenance check interval
|
||||
u_int64_t m_check;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue