aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);