Dear all,

Here in the Netherlands we have a SS7 connection with the biggest local
telco. We have 4 E1s with the following CIC usage:

Linkset one:

1-31    Incoming
33-58   Outgoing
58-63   Emergency Traffic

Linkset two:

1-31    Incoming
33-58   Outgoing
58-63   Emergency Traffic

Using the standard Dial command we cannot select on which CICs to send out traffic, since chan_ss7 will by default use all CICs:

Dial(SS7/Linkset1/number)

To overcome this problem we have written a patch that allows you to select the CICs when dialing, like follows:

Dial(SS7/Linkset1:33-58/number)

This way we can specify on which CICs to send. With the patch it's also possible to specify a single CIC like:

Dial(SS7/Linkset1:33/number)

The patch attached was written for chan_ss7 1.2.1

Best Regards,

Matthias van der Vlies
--- l4isup.c.orig	2010-04-14 13:32:30.000000000 +0200
+++ l4isup.c	2010-04-14 13:31:39.000000000 +0200
@@ -525,7 +525,7 @@
 
 /* This implements the policy: Primary hunting group odd CICs, secondary
    hunting group even CICs. Choose least recently used CIC. */
-static struct ss7_chan *cic_hunt_odd_lru(struct linkset* linkset) {
+static struct ss7_chan *cic_hunt_odd_lru(struct linkset* linkset, int first_cic, int last_cic) {
   struct ss7_chan *cur, *prev, *best, *best_prev;
   int odd;
 
@@ -537,6 +537,10 @@
       if(!cur->reset_done || (cur->blocked & (BL_LH|BL_RM|BL_RH|BL_UNEQUIPPED|BL_LINKDOWN))) {
         continue;
       }
+      /* is this cic within the selected range? */
+      if(cur->cic < first_cic || cur->cic > last_cic) {
+        continue;
+      }
       if((cur->cic % 2) == odd) {
         best = cur;
         best_prev = prev;
@@ -558,7 +562,7 @@
 
 /* This implements the policy: Primary hunting group even CICs, secondary
    hunting group odd CICs. Choose most recently used CIC. */
-static struct ss7_chan *cic_hunt_even_mru(struct linkset* linkset) {
+static struct ss7_chan *cic_hunt_even_mru(struct linkset* linkset, int first_cic, int last_cic) {
   struct ss7_chan *cur, *prev, *best, *best_prev;
 
   best = NULL;
@@ -569,6 +573,10 @@
     if(!cur->reset_done || (cur->blocked & (BL_LH|BL_RM|BL_RH|BL_UNEQUIPPED|BL_LINKDOWN))) {
       continue;
     }
+    /* is this cic within the selected range? */
+    if(cur->cic < first_cic || cur->cic > last_cic) {
+      continue;
+    }
     if((cur->cic % 2) == 0) {
       /* Choose the first idle even circuit, if any. */
       best = cur;
@@ -597,7 +605,7 @@
 }
 
 /* This implements the policy: Sequential low to high CICs */
-static struct ss7_chan *cic_hunt_seq_lth_htl(struct linkset* linkset, int lth)
+static struct ss7_chan *cic_hunt_seq_lth_htl(struct linkset* linkset, int lth, int first_cic, int last_cic)
 {
   struct ss7_chan *cur, *prev, *best = NULL, *best_prev = NULL;
 
@@ -606,6 +614,10 @@
     if(!cur->reset_done || (cur->blocked & (BL_LH|BL_RM|BL_RH|BL_UNEQUIPPED|BL_LINKDOWN))) {
       continue;
     }
+    /* is this cic within the selected range? */
+    if(cur->cic < first_cic || cur->cic > last_cic) {
+      continue;
+			          }
     if (!best) {
       best = cur;
       continue;
@@ -815,21 +827,30 @@
 }
 
 /* hunt free CIC */
-static struct ss7_chan* cic_hunt(struct linkset* linkset)
+static struct ss7_chan* cic_hunt(struct linkset* linkset, int first_cic, int last_cic)
 {
+  if(first_cic > last_cic) {
+     ast_log(LOG_ERROR, "first CIC: %d greater than last CIC: %d\n", first_cic, last_cic);
+     return NULL;
+  }
+  if(first_cic < linkset->first_cic || first_cic > linkset->last_cic || last_cic > linkset->last_cic) {
+     ast_log(LOG_ERROR, "CICs not in valid range, first: %d last: %d\n", first_cic, last_cic);
+     return NULL;
+  }
+
   struct ss7_chan* pvt;
   switch(linkset->hunt_policy) {
   case HUNT_ODD_LRU:
-    pvt = cic_hunt_odd_lru(linkset);
+    pvt = cic_hunt_odd_lru(linkset, first_cic, last_cic);
     break;
   case HUNT_EVEN_MRU:
-    pvt = cic_hunt_even_mru(linkset);
+    pvt = cic_hunt_even_mru(linkset, first_cic, last_cic);
     break;
   case HUNT_SEQ_LTH:
-    pvt = cic_hunt_seq_lth_htl(linkset, 1);
+    pvt = cic_hunt_seq_lth_htl(linkset, 1, first_cic, last_cic);
     break;
   case HUNT_SEQ_HTL:
-    pvt = cic_hunt_seq_lth_htl(linkset, 0);
+    pvt = cic_hunt_seq_lth_htl(linkset, 0, first_cic, last_cic);
     break;
   default:
     pvt = NULL;
@@ -847,6 +868,7 @@
   struct ss7_chan *pvt;
   struct linkset* linkset = this_host->default_linkset;
   char *sep = strchr(arg, '/');
+  char *cic_sep = strchr(arg, ':');
 
   ast_log(LOG_DEBUG, "SS7 request (%s/%s) format = 0x%X.\n", type, arg, format);
 
@@ -857,16 +879,58 @@
   }
   if (sep) {
     char name_buf[100];
-    strncpy(name_buf, arg, sep-arg);
-    name_buf[sep-arg] = 0;
+
+    // linkset:cics -> link1:10-21
+    if(cic_sep != NULL) {
+       strncpy(name_buf, arg, cic_sep-arg);
+       name_buf[cic_sep-arg] = 0;
+    }
+    else {
+        strncpy(name_buf, arg, sep-arg);
+        name_buf[sep-arg] = 0;
+    }
+
     linkset = lookup_linkset(name_buf);
+
     if (!linkset) {
       ast_log(LOG_ERROR, "SS7 requester: No such linkset: '%s', using default\n", name_buf);
       linkset = this_host->default_linkset;
     }
   }
   lock_global();
-  pvt = cic_hunt(linkset);
+
+  // CIC selection via dial parameter
+  // TODO check if cics extracted are numeric before calling atoi()
+  if(cic_sep != NULL) {
+      // use specific cics
+      char cics[100];
+      char first_cic[10], last_cic[10];
+
+      // copy xxx:xxx part
+      strncpy(cics, cic_sep + 1, sep-cic_sep-1);
+      cics[sep-cic_sep] = '\0';
+
+      char *cics_sep = strchr(cics, '-');
+
+      if(cics_sep != NULL) {
+     	// copy cic parts
+      	strncpy(first_cic, cics, cics_sep-cics);
+      	strncpy(last_cic, cics_sep + 1, strlen(cics) - (cics_sep-cics) - 2);
+
+	first_cic[cics_sep-cics] = '\0';
+	last_cic[strlen(cics) - (cics_sep-cics) - 2] = '\0';
+
+        pvt = cic_hunt(linkset, atoi(first_cic), atoi(last_cic));
+      }
+      else {
+	  // single CIC
+	  int cic = atoi(cics);
+          pvt = cic_hunt(linkset, cic, cic);
+      }
+  }
+  else {
+      pvt = cic_hunt(linkset, linkset->first_cic, linkset->last_cic);
+  }
 
   if(pvt == NULL) {
     unlock_global();
@@ -2789,7 +2853,9 @@
   t7_clear(pvt);
   pvt->owner = NULL;
   chan->tech_pvt = NULL;
-  newpvt = cic_hunt(pvt->link->linkset);
+  ast_log(LOG_WARNING, "Reattempt call: hunting on all cics\n");
+  // todo: use cics specified in dial parameters
+  newpvt = cic_hunt(pvt->link->linkset, pvt->link->linkset->first_cic, pvt->link->linkset->last_cic);
   if (newpvt) {
     ast_mutex_lock(&newpvt->lock);
     ast_log(LOG_DEBUG, "Reattempt call: Got cic %d\n", newpvt->cic);
-- 
_____________________________________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --

asterisk-ss7 mailing list
To UNSUBSCRIBE or update options visit:
   http://lists.digium.com/mailman/listinfo/asterisk-ss7

Reply via email to