aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2011-02-23 11:25:45 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2011-02-23 15:27:09 +0100
commit47c9faac3b86f14a1dda0592d5bcf297f72c823f (patch)
treec35326369961d0f8752edbc779abf590b58d94ea
parent8d7027846fbb00f35eb1e19e74970c8771c811e5 (diff)
mtp: Attempt to implement the MTP Restart properly
For the SSP functionatilty we will need to have the timers T18 and T20. In the period of T18 we will collect TFP/TFR/TFA for the reachable nodes of the system. Each of this node will send us a TRA when it is finished. Right now we assume to only have one node and stop the T18 after the TRA of this node. Then we would need to send the TFP/TFR we have collected. On the expiry of the T20 timer we will need to send our TRA and notify local users. For more complex routing we will need to have a shared routing cache and remember which SSNs and OPCs are reachable and have inter linkset notifications.
-rw-r--r--include/mtp_data.h6
-rw-r--r--src/mtp_layer3.c95
-rw-r--r--src/vty_interface.c24
3 files changed, 105 insertions, 20 deletions
diff --git a/include/mtp_data.h b/include/mtp_data.h
index bbd013e..b9fbfb6 100644
--- a/include/mtp_data.h
+++ b/include/mtp_data.h
@@ -83,6 +83,12 @@ struct mtp_link_set {
/* statistics */
struct rate_ctr_group *ctrg;
+ /* statistics for routing */
+ int timeout_t18;
+ int timeout_t20;
+ struct timer_list T18;
+ struct timer_list T20;
+
/* custom data */
struct bsc_data *bsc;
struct ss7_application *app;
diff --git a/src/mtp_layer3.c b/src/mtp_layer3.c
index 0ceb7b0..4740281 100644
--- a/src/mtp_layer3.c
+++ b/src/mtp_layer3.c
@@ -189,6 +189,9 @@ void mtp_link_set_stop(struct mtp_link_set *link)
llist_for_each_entry(lnk, &link->links, entry)
mtp_link_stop_link_test(lnk);
+ bsc_del_timer(&link->T18);
+ bsc_del_timer(&link->T20);
+
link->sccp_up = 0;
link->running = 0;
link->linkset_up = 0;
@@ -204,7 +207,8 @@ void mtp_link_set_reset(struct mtp_link_set *link)
mtp_link_start_link_test(lnk);
}
-static int send_tfp(struct mtp_link *link, int apoc)
+/* unused right now but we want to use it again */
+int send_tfp(struct mtp_link *link, int apoc)
{
struct msgb *msg;
msg = mtp_tfp_alloc(link, apoc);
@@ -243,31 +247,63 @@ static int linkset_up(struct mtp_link *link)
if (set->linkset_up)
return 0;
- if (send_tfp(link, 0) != 0)
- return -1;
- if (send_tfp(link, set->opc) != 0)
- return -1;
+ set->linkset_up = 1;
+ bsc_schedule_timer(&set->T18, set->timeout_t18, 0);
+ bsc_schedule_timer(&set->T20, set->timeout_t20, 0);
+
+ /* More the functionality of a SSP here... */
if (set->sccp_opc != set->opc &&
- send_tfp(link, set->sccp_opc) != 0)
- return -1;
+ send_tfa(link, set->sccp_opc) != 0) {
+ LOGP(DINP, LOGL_ERROR,
+ "Failed to send TFA for OPC %d on linkset %d.\n", set->sccp_opc, set->nr);
+ }
+
if (set->isup_opc != set->opc &&
- send_tfp(link, set->isup_opc) != 0)
- return -1;
+ send_tfa(link, set->isup_opc) != 0) {
+ LOGP(DINP, LOGL_ERROR,
+ "Failed to send TFA for OPC %d on linkset %d.\n", set->sccp_opc, set->nr);
+ }
+
+ return 0;
+}
+
+static void linkset_t18_cb(void *_set)
+{
+ struct mtp_link_set *set = _set;
+ struct mtp_link *link = set->slc[0];
+
+ if (!link) {
+ LOGP(DINP, LOGL_ERROR,
+ "Linkset restart but no link available on linkset %d\n", set->nr);
+ bsc_del_timer(&set->T20);
+ set->linkset_up = 0;
+ return;
+ }
+
+ /* TODO: now send out routing states */
+ LOGP(DINP, LOGL_NOTICE, "The linkset %d has collected routing data.\n", set->nr);
+}
+
+static void linkset_t20_cb(void *_set)
+{
+ struct mtp_link_set *set = _set;
+ struct mtp_link *link = set->slc[0];
+
+ if (!link) {
+ LOGP(DINP, LOGL_ERROR,
+ "Linkset restart but no link available on linkset %d\n", set->nr);
+ bsc_del_timer(&set->T20);
+ set->linkset_up = 0;
+ return;
+ }
/* Send the TRA for all PCs */
if (send_tra(link, set->opc) != 0)
- return -1;
- if (set->sccp_opc != set->opc &&
- send_tfa(link, set->sccp_opc) != 0)
- return -1;
- if (set->isup_opc != set->opc &&
- send_tfa(link, set->isup_opc) != 0)
- return -1;
+ return;
- set->linkset_up = 1;
LOGP(DINP, LOGL_NOTICE,
"The linkset %d/%s is considered running.\n", set->nr, set->name);
- return 0;
+ return;
}
static int mtp_link_sign_msg(struct mtp_link_set *link, struct mtp_level_3_hdr *hdr, int l3_len)
@@ -289,9 +325,18 @@ static int mtp_link_sign_msg(struct mtp_link_set *link, struct mtp_level_3_hdr *
case MTP_TRF_RESTR_MSG_GRP:
switch (cmn->h1) {
case MTP_RESTR_MSG_ALLWED:
- LOGP(DINP, LOGL_INFO, "Received Restart Allowed. SST could be next on %d/%s.\n", link->nr, link->name);
+ LOGP(DINP, LOGL_INFO,
+ "Received TRA on linkset %d/%s.\n", link->nr, link->name);
+ /*
+ * TODO: routing should be done on a higher level. This should not
+ * arrive after we expired the timer but we are friendly here and
+ * respond with a TFA and TRA...
+ */
+ bsc_del_timer(&link->T18);
+ bsc_del_timer(&link->T20);
+ linkset_t18_cb(link);
+ linkset_t20_cb(link);
link->sccp_up = 1;
- LOGP(DINP, LOGL_INFO, "SCCP traffic allowed on %d/%s.\n", link->nr, link->name);
return 0;
break;
}
@@ -612,6 +657,16 @@ struct mtp_link_set *mtp_link_set_alloc(struct bsc_data *bsc)
link->sccp_opc = link->isup_opc = -1;
link->pcap_fd = bsc->pcap_fd;
link->bsc = bsc;
+
+ /* timeout code */
+ link->timeout_t18 = 15;
+ link->timeout_t20 = 16;
+
+ link->T18.cb = linkset_t18_cb;
+ link->T18.data = link;
+ link->T20.cb = linkset_t20_cb;
+ link->T20.data = link;
+
llist_add_tail(&link->entry, &bsc->linksets);
return link;
diff --git a/src/vty_interface.c b/src/vty_interface.c
index 36cdfbb..0f67fc7 100644
--- a/src/vty_interface.c
+++ b/src/vty_interface.c
@@ -202,6 +202,10 @@ static void write_linkset(struct vty *vty, struct mtp_link_set *set)
vty_out(vty, " mtp3 ni %d%s", set->ni, VTY_NEWLINE);
vty_out(vty, " mtp3 spare %d%s", set->spare, VTY_NEWLINE);
vty_out(vty, " mtp3 sltm-once %d%s", set->sltm_once, VTY_NEWLINE);
+ vty_out(vty, " mtp3 timeout t18 %d%s",
+ set->timeout_t18, VTY_NEWLINE);
+ vty_out(vty, " mtp3 timeout t20 %d%s",
+ set->timeout_t20, VTY_NEWLINE);
for (i = 0; i < ARRAY_SIZE(set->supported_ssn); ++i) {
if (!set->supported_ssn[i])
@@ -425,6 +429,24 @@ DEFUN(cfg_linkset_sltm_once, cfg_linkset_sltm_once_cmd,
return CMD_SUCCESS;
}
+DEFUN(cfg_linkset_t18, cfg_linkset_t18_cmd,
+ "mtp3 timeout t18 <0-1000>",
+ "MTP Level3\n" "Timeouts\n" "T18 link restart timeout\n" "Seconds\n")
+{
+ struct mtp_link_set *set = vty->index;
+ set->timeout_t18 = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_linkset_t20, cfg_linkset_t20_cmd,
+ "mtp3 timeout t20 <0-1000>",
+ "MTP Level3\n" "Timeouts\n" "T20 link restart timeout\n" "Seconds\n")
+{
+ struct mtp_link_set *set = vty->index;
+ set->timeout_t20 = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
DEFUN(cfg_linkset_link, cfg_linkset_link_cmd,
"link <0-100>",
"Link\n" "Link number\n")
@@ -876,6 +898,8 @@ void cell_vty_init(void)
install_element(LINKSETS_NODE, &cfg_linkset_mtp3_ssn_cmd);
install_element(LINKSETS_NODE, &cfg_linkset_no_mtp3_ssn_cmd);
install_element(LINKSETS_NODE, &cfg_linkset_sltm_once_cmd);
+ install_element(LINKSETS_NODE, &cfg_linkset_t18_cmd);
+ install_element(LINKSETS_NODE, &cfg_linkset_t20_cmd);
install_element(LINKSETS_NODE, &cfg_linkset_link_cmd);
install_node(&link_node, dummy_write);