Added variable to keep last received MSU sequence number.

Add link's last FSN to COO message, make it ECO if FSN is not known.
Notify the router when each link changes status, emit CBD/COO/ECO if needed.
Merged branch paulc/pstn -c 3478


git-svn-id: http://voip.null.ro/svn/yate@3489 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2010-08-21 18:21:49 +00:00
parent 6a5876435d
commit 0abe0e822a
5 changed files with 106 additions and 6 deletions

View File

@ -409,6 +409,7 @@ void SS7MTP2::timerTick(const Time& when)
if (tout) {
Debug(this,DebugInfo,"Proving period ended, link operational [%p]",this);
lock();
m_lastSeqRx = -1;
unsigned int q = m_queue.count();
if (q >= 64) {
// there shouldn't have been that many queued MSUs
@ -642,7 +643,7 @@ bool SS7MTP2::receivedPacket(const DataBlock& packet)
// just drop MSUs if not operational or out of sequence
if (!((diff == 1) && operational()))
return false;
m_bsn = fsn;
m_lastSeqRx = m_bsn = fsn;
m_fillTime = 0;
DDebug(this,DebugInfo,"New local bsn=%u/%d fsn=%u/%d [%p]",
m_bsn,m_bib,m_fsn,m_fib,this);

View File

@ -43,6 +43,16 @@ void SS7L3User::notify(SS7Layer3* network, int sls)
Debug(this,DebugStub,"Please implement SS7L3User::notify(%p,%d) [%p]",network,sls,this);
}
ObjList* SS7L3User::getNetRoutes(SS7Layer3* network, SS7PointCode::Type type)
{
return network ? network->getRoutes(type) : (ObjList*)0;
}
const ObjList* SS7L3User::getNetRoutes(const SS7Layer3* network, SS7PointCode::Type type)
{
return network ? network->getRoutes(type) : (const ObjList*)0;
}
// Constructor
SS7Layer3::SS7Layer3(SS7PointCode::Type type)
@ -565,6 +575,21 @@ bool SS7MTP3::operational(int sls) const
return false;
}
int SS7MTP3::getSequence(int sls) const
{
if (sls < 0)
return -1;
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)->getSequence();
}
return false;
}
// Attach a link in the first free SLS
void SS7MTP3::attach(SS7Layer2* link)
{
@ -828,7 +853,7 @@ bool SS7MTP3::receivedMSU(const SS7MSU& msu, SS7Layer2* link, int sls)
void SS7MTP3::notify(SS7Layer2* link)
{
Lock lock(this);
bool ok = operational();
unsigned int act = m_active;
countLinks();
#ifdef DEBUG
String tmp;
@ -836,8 +861,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 operational status changed notify upper layer
if (ok != operational()) {
// if operational status of a link changed notify upper layer
if (act != m_active) {
Debug(this,DebugNote,"Linkset is%s operational [%p]",
(operational() ? "" : " not"),this);
SS7Layer3::notify(link ? link->sls() : -1);

View File

@ -539,6 +539,32 @@ void SS7Management::notify(SS7Layer3* network, int sls)
addr << SS7PointCode::lookup(type) << "," << SS7PointCode(type,local);
Debug(this,DebugNote,"Link %s:%d is %s [%p]",addr.c_str(),sls,
(linkUp ? "up" : "down"),this);
ObjList* routes = getNetRoutes(network,type);
if (routes)
routes = routes->skipNull();
for (; routes; routes = routes->skipNext()) {
const SS7Route* r = static_cast<const SS7Route*>(routes->get());
if (r && !r->priority()) {
// found adjacent node, emit change order to it
const char* oper = linkUp ? "changeback" : "changeover";
NamedList* ctl = controlCreate(oper);
if (!ctl)
continue;
String tmp = addr;
tmp << "," << SS7PointCode(type,r->packed()) << "," << sls;
DDebug(this,DebugAll,"Sending Link %s %s [%p]",oper,tmp.c_str(),this);
ctl->setParam("address",tmp);
if (!linkUp) {
int seq = network->getSequence(sls);
if (seq >= 0)
ctl->setParam("sequence",String(seq));
else
ctl->setParam("emergency",String::boolText(true));
}
ctl->setParam("automatic",String::boolText(true));
controlExecute(ctl);
}
}
}
}
}

View File

@ -907,7 +907,8 @@ bool SS7M2PA::processMSG(unsigned char msgVersion, unsigned char msgClass,
unsigned char msgType, const DataBlock& msg, int streamId)
{
if (msgClass != M2PA) {
Debug(this,DebugWarn,"Received non M2PA message class %d",msgClass);
Debug(this,(msg.null() ? DebugInfo : DebugWarn),
"Received non M2PA message class %d",msgClass);
dumpMsg(msgVersion,msgClass,msgType,msg,streamId,false);
return false;
}
@ -1001,6 +1002,7 @@ bool SS7M2PA::decodeSeq(const DataBlock& data,u_int8_t msgType)
transmitLS();
return false;
}
m_lastSeqRx = (m_needToAck & 0x00ffffff) | 0x01000000;
return true;
}
@ -1235,6 +1237,7 @@ bool SS7M2PA::processLinkStatus(DataBlock& data,int streamId)
transmitLS();
}
setRemoteStatus(status);
m_lastSeqRx = -1;
SS7Layer2::notify();
if (m_t3.started())
m_t3.stop();

View File

@ -4773,6 +4773,13 @@ public:
inline void sls(int linkSel)
{ if ((m_sls < 0) || !m_l2user) m_sls = linkSel; }
/**
* Get the sequence number of the last MSU received
* @return Last FSN received, negative if not available
*/
virtual int getSequence() const
{ return m_lastSeqRx; }
/**
* Execute a control operation. Operations can change the link status or
* can query the aligned status.
@ -4795,7 +4802,8 @@ protected:
* Constructor
*/
inline SS7Layer2()
: m_l2userMutex(true,"SS7Layer2::l2user"), m_l2user(0), m_sls(-1)
: m_lastSeqRx(-1),
m_l2userMutex(true,"SS7Layer2::l2user"), m_l2user(0), m_sls(-1)
{ }
/**
@ -4823,6 +4831,11 @@ protected:
tmp->notify(this);
}
/**
* Last received MSU sequence number, -1 if unknown, bit 24 set if long FSN
*/
int m_lastSeqRx;
private:
Mutex m_l2userMutex;
SS7L2User* m_l2user;
@ -5006,6 +5019,22 @@ protected:
* @param sls Signalling Link that generated the notification, negative if none
*/
virtual void notify(SS7Layer3* link, int sls);
/**
* Retrieve the route table of a network for a specific Point Code type
* @param network Network layer to retrieve routes from
* @param type Point Code type of the desired table
* @return Pointer to the list of SS7Route or NULL if no such route
*/
static ObjList* getNetRoutes(SS7Layer3* network, SS7PointCode::Type type);
/**
* Retrieve the route table of a network for a specific Point Code type
* @param network Network layer to retrieve routes from
* @param type Point Code type of the desired table
* @return Pointer to the list of SS7Route or NULL if no such route
*/
static const ObjList* getNetRoutes(const SS7Layer3* network, SS7PointCode::Type type);
};
/**
@ -5015,6 +5044,7 @@ protected:
class YSIG_API SS7Layer3 : virtual public SignallingComponent
{
YCLASS(SS7Layer3,SignallingComponent)
friend class SS7L3User;
friend class SS7Router; // Access the data members to build the routing table
public:
/**
@ -5046,6 +5076,14 @@ public:
*/
virtual bool operational(int sls = -1) const = 0;
/**
* Get the sequence number of the last MSU received on a link
* @param sls Signalling Link to retrieve MSU number from
* @return Last FSN received, negative if not available
*/
virtual int getSequence(int sls) const
{ return -1; }
/**
* Initiate a MTP restart procedure if supported by the network layer
* @return True if a restart was initiated
@ -6236,6 +6274,13 @@ public:
*/
virtual bool operational(int sls = -1) const;
/**
* Get the sequence number of the last MSU received on a link
* @param sls Signalling Link to retrieve MSU number from
* @return Last FSN received, negative if not available
*/
virtual int getSequence(int sls) const;
/**
* Execute a control operation on the linkset
* @param oper Operation to execute