News:

On Tuesday September 6th the forum will be down for maintenance from 9:30 PM to 11:59 PM PDT

Main Menu

Technical : DigitMaps and the OutboundCallRoute

Started by RonR, March 27, 2011, 01:44:38 PM

Previous topic - Next topic

RonR

I hope the following isn't intimidating and/or totally boring.  I thought some might find it interesting to see how the default OBi DigitMaps and OutboundCallRoute work together from a more technical standpoint.


At first glance, it appears each outbound port (ITSPA, ITSPB, LINE, and OBiTALK) has its own DigitMap, each controlling the individual port it's associated with.  However, appearances can be deceiving.  When you place a call from the OBi's PHONE Port, the PHONE Port DigitMap is the only DigitMap the OBi firmware directly accesses.  In reality, the ITSPA, ITSPB, LINE, and OBiTALK DigitMaps only come into play because they're actually part of the PHONE Port DigitMap through indirect references: (Msp1), (Msp2), (Mli), (Mpp), and (Mpli).  The OutboundCallRoute also uses these indirect references to the very same DigitMaps.

Internally, the OBi expands these indirect references into single entities.  In an OBi set to factory defaults, here's what the OBi actually sees when it processes the PHONE Port DigitMap and OutboundCallRoute to place your call:


PHONE Port DigitMap:

([1-9]x?*xxxxxxxS4|[1-9]x?*1xxxxxxxxxx|[1-9]x?*xx.|[1-9]|[1-9][0-9]|911|**0|***|#|**11xxxxxxxxxx|**1<1>[2-9]xxxxxxxxx|**1011xx.|**1xx.|**1xx.<*:@>xx?x?<*:.>xx?x?<*:.>xx?x?<*:.>xx?x?|**1xx.<*:@>xx?x?<*:.>xx?x?<*:.>xx?x?<*:.>xx?x?<*::>xx?x?x?x?|**1[^*]@@.|**21xxxxxxxxxx|**2<1>[2-9]xxxxxxxxx|**2011xx.|**2xx.|**2xx.<*:@>xx?x?<*:.>xx?x?<*:.>xx?x?<*:.>xx?x?|**2xx.<*:@>xx?x?<*:.>xx?x?<*:.>xx?x?<*:.>xx?x?<*::>xx?x?x?x?|**2[^*]@@.|**8xxxxxxxS4|**81xxxxxxxxxx|**8xx.|**9<ob>xxxxxxxxx|**9obxxxxxxxxx|xxxxxxxS4|1xxxxxxxxxx|xx.)


PHONE Port OutboundCallRoute:

{([1-9]x?*xxxxxxxS4|[1-9]x?*1xxxxxxxxxx|[1-9]x?*xx.):pp},{(<#:>|911):li},{**0:aa},{***:aa2},{(<**1:>1xxxxxxxxxx|<**1:1>[2-9]xxxxxxxxx|<**1:>011xx.|<**1:>xx.|<**1:>xx.<*:@>xx?x?<*:.>xx?x?<*:.>xx?x?<*:.>xx?x?|<**1:>xx.<*:@>xx?x?<*:.>xx?x?<*:.>xx?x?<*:.>xx?x?<*::>xx?x?x?x?|<**1:>[^*]@@.):sp1},{(<**2:>1xxxxxxxxxx|<**2:1>[2-9]xxxxxxxxx|<**2:>011xx.|<**2:>xx.|<**2:>xx.<*:@>xx?x?<*:.>xx?x?<*:.>xx?x?<*:.>xx?x?|<**2:>xx.<*:@>xx?x?<*:.>xx?x?<*:.>xx?x?<*:.>xx?x?<*::>xx?x?x?x?|<**2:>[^*]@@.):sp2},{(<**8:>xxxxxxxS4|<**8:>1xxxxxxxxxx|<**8:>xx.):li},{(<**9:ob>xxxxxxxxx|<**9:>obxxxxxxxxx):pp},{(xxxxxxxS4|1xxxxxxxxxx|xx.):pli}


By using indirect references to individual groups of rules relating to a particular port, and locating those groups on the page associated with the port they refer to, the PHONE Port DigitMap is infinitely more manageable.  Just keep in mind, however, that from the OBi's point of view, it's all part of one PHONE Port DigitMap and one OutboundCallRoute.

If you study the PHONE Port DigitMap and OutboundCallRoute, you'll see there is basically a one-to-one relationship between them.  This isn't by accident and it's why it's generally a good idea to leave them both unmodified unless you fully understand the ramifications of changing them.  Any alterations you make here are likely to have a profound effect on any indirectly referenced DigitMap that's part of your modification.

When you place a call from the OBi's PHONE Port, the OBi first looks at the expanded PHONE Port DigitMap and locates the single rule that best matches the number you dialed.  The resulting number from this process may be different because DigitMaps can transform as well as match.  This resulting number is then processed through each element of the expanded OutboundCallRoute, one at a time, left to right, until a matching rule is found.  The first match found is the one that dictates which port is to be used for the outbound call.

What's important to take away from all this is that when you make a change to a DigitMap, you must be looking at the whole picture, not just the small fragment on the page you're staring at.  With a little effort, it's not difficult to follow the exact path a particular number will take through the PHONE Port DigitMap and OutboundCallRoute.

plugger2

Quote from: RonR on March 27, 2011, 01:44:38 PM
At first glance, it appears each outbound port (ITSPA, ITSPB, LINE, and OBiTALK) has its own DigitMap, each controlling the individual port it's associated with.  However, appearances can be deceiving.  When you place a call from the OBi's PHONE Port, the PHONE Port DigitMap is the only DigitMap the OBi firmware directly accesses.  In reality, the ITSPA, ITSPB, LINE, and OBiTALK DigitMaps only come into play because they're actually part of the PHONE Port DigitMap through indirect references: (Msp1), (Msp2), (Mli), (Mpp), and (Mpli).  The OutboundCallRoute also uses these indirect references to the very same DigitMaps.

RonR,

Your "one step processing" model isn't entirely accurate. For example, if you send a call to a trunk group (say tg1) via the PHONE port OutboundCallRoute, and the trunk group list is (for example):

sp1,sp2,li

then the DigitMaps associated with each of sp1,sp2,li will be evaluated in turn looking for a fit. So it's not accurate to say

"When you place a call from the OBi's PHONE Port, the PHONE Port DigitMap is the only DigitMap the OBi firmware directly accesses."

Of course, unless you are using trunk groups, it is unlikely you will even notice this second-stage checking is even occurring, or encounter problems with it. But if you do run afoul of this (as I did when I started with trunk groups -- very useful feature, BTW), it's good to understand that what's happening under the hood with DigitMap checking is not a one-shot deal.



RonR

#2
plugger2,

I think you'll find that what I described is accurate.  Normally, to introduce Trunk Group 1, you would do so by setting PrimaryLine to 'Trunk Group 1'.  Then (Mpli) would point to TG1 and whatever it references (and whatever they reference, and ...) would be expanded into the PHONE Port DigitMap that's actually evaluated.  No change to the OutboundCallRoute is necessary.  The same would be true if you manually splice TGx or anything else anywhere in any DigitMap.

I'm confident the processing I described doesn't change regardless of what or where you add things.  The end result is one huge PHONE Port DigitMap and and one huge OutboundCallRoute, both of which are evaluated as I described.

[I confess I don't know if the expansion of indirect references happens in the literal sense (i.e into a separate linear buffer for processing) or if the parser is written to do it on-the-fly, but the net result is the same either way.]

I hadn't thought about it until now, but it's pretty clear the OutboundCallRoute processing also takes into account whether the port a matching rule would normally select is available.  If not, the evaluation process no doubt continues, which would take care of having multiple candidates when a Trunk Group is present.  If you run off the end of the OutboundCallRoute without finding a matching rule on a port that's available, you get the error message that there are no routes available for your call.

plugger2

#3
RonR,

I understand what you are saying, but just so we are on the same page with respect to the actual behaviour, perhaps you can try this experiment:

Create a rule in your OutboundCallRoute that maps a test phone # to say, sp2. Something like

{XXXXXXX:sp2}

where XXXXXXX is your test number.

Now, create a trunk group (say trunk group 2) that has just sp2 in it's list (a rather boring trunk group, but to illustrate the point).

Finally, amend the digitMap for sp2 so that it blocks your test #.

(!XXXXXXX|[whatever else was here])

OK, now you can test what happens when you dial your test number when the OutgoingCallRoute clause is set to

{XXXXXXX:sp2}

as compared to

{XXXXXXX:tg2}

What you will see is that in the first example, the call is accepted by sp2 (the sp2 digitMap blocking of the call is ignored), but in the second instance, the digitMap of sp2 blocks the call.

Leaving aside for one moment the question of whether this inconsistency in behaviour of how and when to treat the sp2 digitMap is a bug or a feature, it does suggest (at least to me) that the processing of the routing is more dynamic than a single stage macro expansion, as you are suggesting above.

Having said that, if indeed the the result of trunk group "hunt" _was_ evaluated as a part of a one-shot macro expansion, as you are suggesting, it would strike me as a rather odd design decision to do it that way.

It would be odd because it would be unduly limiting to how the "hunt" could be conducted -- only information at hand on the availability of service on each port at one point in time could be used, which is at odds with the essential time sequential nature of the search.

Dynamic processing, more in the style of an interpreter, rather than in the static style of a macro processor, would be much more natural, and extensible. For example, using a  dynamic processing model, it would be possible to do "deep" trunk group hunting (which is actually one of my fond hopes for the future as requested in the Feature Requests subforum http://www.obitalk.com/forum/index.php?topic=420.0), whereas using a static macro expansion model, it wouldn't.

But, odd or not, I suppose it is possible.

Perhaps an OBi engineer can chime in to clarify the nature of these deep philosophical questions. :-)



RonR

#4
Quote from: plugger2 on March 27, 2011, 09:18:23 PMCreate a rule in your OutboundCallRoute that maps a test phone # to say, sp2. Something like

{XXXXXXX:sp2}

where XXXXXXX is your test number.
Where in the OutboundCallRoute are you placing this?  Placement is critical in the OutboundCallRoute as evaluation occurs left to right and stops on the first match.  If all the rules prior to this one fail, then this one will unconditionally send XXXXXXX out the SP2 port.

Quote from: plugger2 on March 27, 2011, 09:18:23 PMNow, create a trunk group (say trunk group 2) that has just sp2 in it's list (a rather boring trunk group, but to illustrate the point).
Where are you referencing TG2 from?  A trunk group has to be referenced in another digit map or call routing rule in order to be used.  Just putting something in TG2's TrunkList and DigitMap doesn't make TG2 magically spring to life.  (Your later example of {XXXXXXX:tg2} isn't valid syntax, so it doesn't count.)

Quote from: plugger2 on March 27, 2011, 09:18:23 PMFinally, amend the digitMap for sp2 so that it blocks your test #.

(!XXXXXXX|[whatever else was here])
That rule is only interesting if PrimaryLine is SP2 or you're dialing the number as **2XXXXXXX.  Otherwise, none of the rules in the SP2 DigitMap will be evaluated.

Quote from: plugger2 on March 27, 2011, 09:18:23 PMOK, now you can test what happens when you dial your test number when the OutgoingCallRoute clause is set to

{XXXXXXX:sp2}

as compared to

{XXXXXXX:tg2}

What you will see is that in the first example, the call is accepted by sp2 (the sp2 digitMap blocking of the call is ignored), but in the second instance, the digitMap of sp2 blocks the call.
Your first example simply sends XXXXXXX out the SP2 port.  No DigitMaps anywhere are evaluated.  Of course it's accepted.  The second example isn't valid.  The terminal specifier has to be PH, AA, LI, SPx, or PP.  It can't be a trunk group.  I'm guessing the OBi simply ignored it.

Quote from: plugger2 on March 27, 2011, 09:18:23 PMHaving said that, if indeed the the result of trunk group "hunt" _was_ evaluated as a part of a one-shot macro expansion, as you are suggesting, it would strike me as a rather odd design decision to do it that way.

It would be odd because it would be unduly limiting to how the "hunt" could be conducted -- only information at hand on the availability of service on each port at one point in time could be used, which is at odds with the essential time sequential nature of the search.

Dynamic processing, more in the style of an interpreter, rather than in the static style of a macro processor, would be much more natural, and extensible. For example, using a  dynamic processing model, it would be possible to do "deep" trunk group hunting (which is actually one of my fond hopes for the future as requested in the Feature Requests subforum), whereas using a static macro expansion model, it wouldn't.
I can't figure out what kind of dynamic processing and "deep" trunk group hunting you're hoping for.  The evaluation of the OutboundCallRoute is virtually instantaneous and the OBi always knows which of its ports are in use and which are available.  How is anything limited, unduly or otherwise?  With the current implementation, the OBi will use the first available port that's not in use from a trunk group list whose rule matches (and even in the order specified) and the call will be on its way.  What else are you wanting to happen?

The PHONE Port DigitMap + OutboundCallRoute scheme currently implemented in the OBi is actually pretty elegant.  Maybe my explanation of how it works isn't as clear as I'd hoped it would be.

plugger2

Quote from: RonR on March 27, 2011, 10:57:34 PM
Your first example simply sends XXXXXXX out the SP2 port.  No DigitMaps anywhere are evaluated.  Of course it's accepted.  The second example isn't valid.  The terminal specifier has to be PH, AA, LI, SPx, or PP.  It can't be a trunk group.  I'm guessing the OBi simply ignored it.

OK, we are clearly not on the same page. The syntax above is valid, and it works as you would expect. OBi certainly does not ignore it. The call is directed to the trunk group, which is evaluated in order, looking for an available physical trunk, according to trunk group rules.

Try it and get back to me.

RonR

plugger2,

You might want to do some reading on page 115 of the OBi Device Administration Guide (Version 23.03.11: 23 March 2011) under the heading of 'Outbound Call Route Configuration':


The general format is:
OutboundCallRoute := rule OR {rule},{rule},....

Note that the curly braces may be omitted if there is only one rule in the route. The OR operator is NOT part of the parameter syntax; it is used here to separate alternative values only.


A rule has the following format:
rule := callee-list : terminal
where
callee-list := callee|callee|callee| ... (vertical bar separated list of 0 or more callee object)
callee := number OR embedded-digit-map OR @ (@ = any number)
terminal := PHx OR AAx OR LIx(arg) OR SPx(arg) OR PPx(arg) (arg object is optional)


The OutboundCallRoute sends calls to a terminal (port), not to another DigitMap or Trunk Group.

plugger2

#7
LOL. And you might want to do some reading on trunk groups, p76, paragraph 2 (my emphasis):

"Up to 4 trunk groups can be configured on an OBi device. Each trunk group is conceptually another trunk with its own DigitMap. A trunk group and its associated DigitMap are referenced using the short name TGn and (Mtgn) respectively, where n = 1, 2, 3, 4. They can be referenced in other digit maps and call routing rules so that calls may be routed to a particular trunk group."

Looks like OBi have to update the info on p115 to bring it up to date. :-)


RonR

I think you're going to find that the syntax they're referring to is:


{(Mtg1):sp2}


although at this hour, I can't think of what this could possibly be good for (but it fits the syntax rules).   :)

plugger2

#9
Quote from: RonR on March 28, 2011, 12:33:31 AM
I think you're going to find that the syntax they're referring to is:


{(Mtg1):sp2}


although at this hour, I can't think of what this could possibly be good for (but it fits the syntax rules).   :)

Nope. It's just what it says -- you can put tg1, tg2 in a routing rule, and it's treated just like any other trunk for routing purposes (except of course it will resolve ultimately to a physical trunk according to the rules as described -- unless of course there is no available physical trunk in the list with a "legal" digitMap for the call.)

The syntax above will work, as you say, but I can't figure out what it would be useful for, either. So we agree on something! ;-)

I suggest you try it out for yourself, and you'll see there is nothing ambiguous or mysterious about the paragraph on p76.

Edit: Oh, and BTW, the description of the list of acceptable terminals on p115 is also not up-to-date regarding voice gateways (vg1, vg2, ...). These can now also be used as terminals in routing rules. So there's two bugs in the p115 documentation we've uncovered in this thread alone. :-)






RonR

Quote from: plugger2 on March 28, 2011, 12:47:13 AMSo we agree on something! ;-)
I think we're going to agree on more, but I'm not sure if it's going to be everything.   :)

There are a number of omissions in the OBi documentation regarding not only syntax but also operation of the OutboundCallRoute:

1. Terminal can be VGx.  This is non-controversial and appears to work as expected.

2. It appears that terminal can be a comma separated list of trunks or endpoints. For example:

{(xxxxxxxS4|1xxxxxxxxxx|xx.):sp1,sp2}

3. Terminal can be TGx.  But here's where the water gets a little murky.  I would think that
{(...):tg1} would simply be replaced by {(...):sp1,sp2}.  If it is, this actually works due to item 2 above and no special TGx handler is needed.  The only problem is the order isn't preserved.  SP2 is always tried first, followed by SP1 if SP2 is unavailable.  Since the order is preserved when using a real TGx but not when a simulated TGx is tested, there's still a missing link somewhere.  It's possible there's a special TGx handler that's used to avoid this problem.

Here's where we'll probably part company.  None of this discussion about trunk groups causes me to want to change a single word in my original post.  I'm still convinced it holds true, whether trunk groups are implemented via a simple substitution or a more sophisticated 'trunk/endpoint emulator' routine.

What does need to be corrected (and I will add the necessary strike-outs shortly) is my speculation in the third post of this thread that OutboundCallRoute processing doesn't stop when a port with a matching rule is found but the port is not available.  Processing stops when a matching rule is found, period.  If that port is not available, you get an error message.

While it's a little unclear exactly how trunk group processing is implemented at the lowest level, I don't believe the details are germane to the overall discussion of how DigitMaps and the OutboundCallRoute play together in the OBi.

It would be nice, however, if obi-support2 chimed in with a detailed description of exactly how trunk group processing is, in fact, implemented.

obi-support2

Just to confirm your observation/interpretation...

1. PHONE Port - DigitMap is the first gate that processes the digits dialed from the PHONE Port. Once the digits are accepted (and properly transformed by the digitmap, if applicable), the resulting number is used to determine the route to place the call, using the OutboundCallRoute.
The Digitmap on each trunk does not come into play, unless they are explicitly referenced in
PhonePort's digitmap

2. OutboundCallRoute may transform the number again based on the digit-map used in the matching routing rule. Note that OutboundCallRoute does not allow forking at present; so only 1 trunk can be selected to place the call. Again the digitmap on each trunk does not play a role here, unless they are explicitly referenced in the PhonePort's OutboundCallRoute.
(Only inboundCallRoute allows forking to up to 4 destinations)

3. If the resulting trunk from #2 is NOT a trunk group, then the number from #2 will be used to call out on that trunk. That would be the end of it.

4. If the resulting trunk from #2 is a trunk group, OBi indeed will apply each member trunk's digit map to select a usable trunk member to place the call. It's a valid point that this may not be quite consistent with the non-trunk-group case, in the sense that the digitmap on each trunk now plays a role in the trunk-selection; but it makes trunk group more useful w/o introducing new syntax.





OBIHAI Support Staff

RonR

#12
Quote from: obi-support2 on March 28, 2011, 04:41:11 PMNote that OutboundCallRoute does not allow forking at present; so only 1 trunk can be selected to place the call.
Multiple terminal specifiers in an OutboundCallRoute rule currently behave more like a single target 'hunt' than a multiple target 'fork'.

Whether intended or not, with (xx.) as the only PHONE Port DigitMap rule and {(xx.):sp1,sp2} as the only OutboundCallRoute rule, the call goes out SP2 if SP2 is available or SP1 if it's not.

I state this only as an observation, not to make any particular point.