aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2011-01-17 11:29:07 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2011-01-17 11:29:07 +0100
commit4a3743440bd77aa0cec240e103aa2c7ce954b714 (patch)
tree1c6eb6a441fafc15bf2048441bc8ee71e29623d7
parentde56c2270268ff6e8945d5e03ec58ad52c3da64b (diff)
parentd91f94024ed9c0b9d2c674c09fe1466182002b5a (diff)
Merge branch 'on-waves/multiple-links'
-rw-r--r--include/bsc_data.h33
-rw-r--r--include/bsc_sccp.h2
-rw-r--r--include/isup_types.h4
-rw-r--r--include/mtp_data.h48
-rw-r--r--include/snmp_mtp.h4
-rw-r--r--src/Makefile.am4
-rw-r--r--src/bsc_sccp.c2
-rw-r--r--src/isup.c6
-rw-r--r--src/link_udp.c19
-rw-r--r--src/links.c177
-rw-r--r--src/main.c181
-rw-r--r--src/main_udt.c134
-rw-r--r--src/msc_conn.c45
-rw-r--r--src/mtp_layer3.c128
-rw-r--r--src/snmp_mtp.c8
-rw-r--r--src/vty_interface.c4
-rw-r--r--tests/isup/isup_parse_test.c2
17 files changed, 414 insertions, 387 deletions
diff --git a/include/bsc_data.h b/include/bsc_data.h
index d13a566..fa04c3a 100644
--- a/include/bsc_data.h
+++ b/include/bsc_data.h
@@ -1,7 +1,7 @@
/* Everything related to the BSC connection */
/*
- * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010 by On-Waves
+ * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2011 by On-Waves
* All Rights Reserved
*
* This program is free software: you can redistribute it and/or modify
@@ -42,6 +42,8 @@ struct snmp_mtp_session;
* A link to the underlying MTP2 library or such
*/
struct link_data {
+ struct llist_head entry;
+
union {
struct {
struct thread_notifier *notifier;
@@ -52,16 +54,18 @@ struct link_data {
struct write_queue write_queue;
struct sockaddr_in remote;
struct snmp_mtp_session *session;
+ int link_index;
int reset_timeout;
} udp;
};
int pcap_fd;
struct bsc_data *bsc;
- struct mtp_link *the_link;
+ struct mtp_link_set *the_link;
+
+ int available;
struct timer_list link_activate;
- int forced_down;
int (*start)(struct link_data *);
int (*write)(struct link_data *, struct msgb *msg);
@@ -95,7 +99,9 @@ struct bsc_data {
int setup;
- struct link_data link;
+ int pcap_fd;
+ int udp_reset_timeout;
+ struct mtp_link_set *link_set;
const char *token;
@@ -125,8 +131,11 @@ struct bsc_data {
/* bsc related functions */
void release_bsc_resources(struct bsc_data *bsc);
-void bsc_link_down(struct link_data *data);
-void bsc_link_up(struct link_data *data);
+void mtp_link_down(struct link_data *data);
+void mtp_link_up(struct link_data *data);
+
+void mtp_linkset_down(struct mtp_link_set *);
+void mtp_linkset_up(struct mtp_link_set *);
/* msc related functions */
int msc_init(struct bsc_data *bsc, int mgcp);
@@ -134,18 +143,18 @@ void msc_send_rlc(struct bsc_data *bsc, struct sccp_source_reference *src, struc
void msc_send_reset(struct bsc_data *bsc);
void msc_send_msg(struct bsc_data *bsc, int rc, struct sccp_parse_result *, struct msgb *msg);
void msc_send_direct(struct bsc_data *bsc, struct msgb *msg);
-void msc_clear_queue(struct bsc_data *data);
void msc_close_connection(struct bsc_data *data);
/* connection tracking and action */
-void update_con_state(struct mtp_link *link, int rc, struct sccp_parse_result *result, struct msgb *msg, int from_msc, int sls);
+void update_con_state(struct mtp_link_set *link, int rc, struct sccp_parse_result *result, struct msgb *msg, int from_msc, int sls);
unsigned int sls_for_src_ref(struct sccp_source_reference *ref);
-/* c7 init */
-int link_c7_init(struct link_data *data);
-
/* udp init */
int link_udp_init(struct link_data *data, int src_port, const char *dest_ip, int port);
+int link_init(struct bsc_data *bsc);
+int link_shutdown_all(struct mtp_link_set *);
+int link_reset_all(struct mtp_link_set *);
+int link_clear_all(struct mtp_link_set *);
/* MGCP */
void mgcp_forward(struct bsc_data *bsc, const uint8_t *data, unsigned int length);
diff --git a/include/bsc_sccp.h b/include/bsc_sccp.h
index c75bab6..8811a2b 100644
--- a/include/bsc_sccp.h
+++ b/include/bsc_sccp.h
@@ -54,7 +54,7 @@ struct active_sccp_con {
unsigned int rls_tries;
/* MTP link this was coming in */
- struct mtp_link *link;
+ struct mtp_link_set *link;
/* sls id */
int sls;
diff --git a/include/isup_types.h b/include/isup_types.h
index be7964d..5347cb4 100644
--- a/include/isup_types.h
+++ b/include/isup_types.h
@@ -25,7 +25,7 @@
#include <endian.h>
struct msgb;
-struct mtp_link;
+struct mtp_link_set;
/* This is from Table 4/Q.763 */
#define ISUP_MSG_GRS 0x17
@@ -47,7 +47,7 @@ struct isup_msg_grs {
uint8_t pointer_int;
};
-int mtp_link_forward_isup(struct mtp_link *link, struct msgb *msg, int sls);
+int mtp_link_set_forward_isup(struct mtp_link_set *link, struct msgb *msg, int sls);
int isup_parse_grs(const uint8_t *data, uint8_t length);
diff --git a/include/mtp_data.h b/include/mtp_data.h
index e98d073..349bf7a 100644
--- a/include/mtp_data.h
+++ b/include/mtp_data.h
@@ -1,6 +1,6 @@
/*
- * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010 by On-Waves
+ * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2011 by On-Waves
* All Rights Reserved
*
* This program is free software: you can redistribute it and/or modify
@@ -24,6 +24,9 @@
#include <osmocore/timer.h>
#include <osmocore/utils.h>
+struct bsc_data;
+struct link_data;
+
/* MTP Level3 timers */
/* Timers for SS7 */
@@ -34,7 +37,7 @@
/**
* The state of the mtp_link in terms of layer3 and upwards
*/
-struct mtp_link {
+struct mtp_link_set {
/* routing info.. */
int dpc, opc, sccp_opc;
int ni;
@@ -46,42 +49,47 @@ struct mtp_link {
int running;
int sccp_up;
+ int last_sls;
+
/* misc data */
uint8_t test_ptrn[14];
int sltm_pending;
- struct llist_head pending_msgs;
int sltm_once;
int was_up;
-
- /* the associated link */
- int link;
-
int slta_misses;
struct timer_list t1_timer;
struct timer_list t2_timer;
struct timer_list delay_timer;
+
+ struct llist_head links;
+ struct link_data *slc[16];
+
+ /* custom data */
+ struct bsc_data *bsc;
};
-struct mtp_link *mtp_link_alloc(void);
-void mtp_link_stop(struct mtp_link *link);
-void mtp_link_reset(struct mtp_link *link);
-int mtp_link_data(struct mtp_link *link, struct msgb *msg);
-int mtp_link_submit_sccp_data(struct mtp_link *link, int sls, const uint8_t *data, unsigned int length);
-int mtp_link_submit_isup_data(struct mtp_link *link, int sls, const uint8_t *data, unsigned int length);
+struct mtp_link_set *mtp_link_set_alloc(void);
+void mtp_link_set_stop(struct mtp_link_set *link);
+void mtp_link_set_reset(struct mtp_link_set *link);
+int mtp_link_set_data(struct mtp_link_set *link, struct msgb *msg);
+int mtp_link_set_submit_sccp_data(struct mtp_link_set *link, int sls, const uint8_t *data, unsigned int length);
+int mtp_link_set_submit_isup_data(struct mtp_link_set *link, int sls, const uint8_t *data, unsigned int length);
+
+void mtp_link_set_init_slc(struct mtp_link_set *set);
+void mtp_link_set_add_link(struct mtp_link_set *set, struct link_data *link);
/* one time init function */
-void mtp_link_init(void);
+void mtp_link_set_init(void);
/* to be implemented for MSU sending */
-void mtp_link_submit(struct mtp_link *link, struct msgb *msg);
-void mtp_link_forward_sccp(struct mtp_link *link, struct msgb *msg, int sls);
-void mtp_link_restart(struct mtp_link *link);
-void mtp_link_slta_recv(struct mtp_link *link);
-void mtp_link_sccp_down(struct mtp_link *link);
+void mtp_link_set_submit(struct link_data *link, struct msgb *msg);
+void mtp_link_set_forward_sccp(struct mtp_link_set *link, struct msgb *msg, int sls);
+void mtp_link_restart(struct link_data *link);
+void mtp_link_set_sccp_down(struct mtp_link_set *link);
#endif
diff --git a/include/snmp_mtp.h b/include/snmp_mtp.h
index fea3c66..a42b08e 100644
--- a/include/snmp_mtp.h
+++ b/include/snmp_mtp.h
@@ -32,7 +32,7 @@ void snmp_mtp_start_c7_datalink(struct snmp_mtp_session *, int link_id);
void snmp_mtp_stop_c7_datalink(struct snmp_mtp_session *, int link_id);
struct snmp_mtp_session *snmp_mtp_session_create(char *host);
-void snmp_mtp_deactivate(struct snmp_mtp_session *);
-void snmp_mtp_activate(struct snmp_mtp_session *);
+void snmp_mtp_deactivate(struct snmp_mtp_session *, int link_id);
+void snmp_mtp_activate(struct snmp_mtp_session *, int link_id);
#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 4ca99f7..83acf8d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -10,13 +10,13 @@ mgcp_mgw_LDADD = $(LAFORGE_LIBS) $(NEXUSWARE_C7_LIBS) $(NEXUSWARE_UNIPORTE_LIBS)
$(LIBOSMOVTY_LIBS) $(LIBOSMOCORE_LIBS) -lpthread
cellmgr_ng_SOURCES = main.c mtp_layer3.c thread.c input/ipaccess.c pcap.c \
- bss_patch.c bssap_sccp.c bsc_sccp.c bsc_ussd.c \
+ bss_patch.c bssap_sccp.c bsc_sccp.c bsc_ussd.c links.c \
msc_conn.c link_udp.c snmp_mtp.c debug.c vty_interface.c isup.c
cellmgr_ng_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOSCCP_LIBS) $(LIBOSMOVTY_LIBS) $(NEXUSWARE_C7_LIBS) \
-lpthread -lnetsnmp -lcrypto
udt_relay_SOURCES = main_udt.c mtp_layer3.c thread.c input/ipaccess.c pcap.c \
msc_conn.c link_udp.c snmp_mtp.c debug.c vty_interface.c \
- bss_patch.c isup.c
+ bss_patch.c isup.c links.c
udt_relay_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOSCCP_LIBS) $(LIBOSMOVTY_LIBS) $(NEXUSWARE_C7_LIBS) \
-lpthread -lnetsnmp -lcrypto
diff --git a/src/bsc_sccp.c b/src/bsc_sccp.c
index 69e2262..ea13c43 100644
--- a/src/bsc_sccp.c
+++ b/src/bsc_sccp.c
@@ -86,7 +86,7 @@ unsigned int sls_for_src_ref(struct sccp_source_reference *ref)
con = find_con_by_src_ref(ref);
if (!con)
- return 13;
+ return -1;
return con->sls;
}
diff --git a/src/isup.c b/src/isup.c
index 8af1464..340af16 100644
--- a/src/isup.c
+++ b/src/isup.c
@@ -90,7 +90,7 @@ int isup_parse_grs(const uint8_t *data, uint8_t in_length)
/* Handle incoming ISUP data */
-static int handle_circuit_reset_grs(struct mtp_link *link, int sls, int cic,
+static int handle_circuit_reset_grs(struct mtp_link_set *link, int sls, int cic,
const uint8_t *data, int size)
{
struct msgb *resp;
@@ -104,12 +104,12 @@ static int handle_circuit_reset_grs(struct mtp_link *link, int sls, int cic,
if (!resp)
return -1;
- mtp_link_submit_isup_data(link, sls, resp->l2h, msgb_l2len(resp));
+ mtp_link_set_submit_isup_data(link, sls, resp->l2h, msgb_l2len(resp));
msgb_free(resp);
return 0;
}
-int mtp_link_forward_isup(struct mtp_link *link, struct msgb *msg, int sls)
+int mtp_link_set_forward_isup(struct mtp_link_set *link, struct msgb *msg, int sls)
{
int rc = -1;
int payload_size;
diff --git a/src/link_udp.c b/src/link_udp.c
index b5da7f9..e05bd17 100644
--- a/src/link_udp.c
+++ b/src/link_udp.c
@@ -91,12 +91,12 @@ static int udp_read_cb(struct bsc_fd *fd)
if (hdr->data_type == UDP_DATA_RETR_COMPL || hdr->data_type == UDP_DATA_RETR_IMPOS) {
LOGP(DINP, LOGL_ERROR, "Link retrieval done. Restarting the link.\n");
- bsc_link_down(link);
- bsc_link_up(link);
+ mtp_link_down(link);
+ mtp_link_up(link);
goto exit;
} else if (hdr->data_type > UDP_DATA_MSU_PRIO_3) {
LOGP(DINP, LOGL_ERROR, "Link failure. retrieved message.\n");
- bsc_link_down(link);
+ mtp_link_down(link);
goto exit;
}
@@ -113,7 +113,7 @@ static int udp_read_cb(struct bsc_fd *fd)
LOGP(DINP, LOGL_DEBUG, "MSU data on: %p data %s.\n", link, hexdump(msg->data, msg->len));
if (link->pcap_fd >= 0)
mtp_pcap_write_msu(link->pcap_fd, msg->l2h, msgb_l2len(msg));
- mtp_link_data(link->the_link, msg);
+ mtp_link_set_data(link->the_link, msg);
exit:
msgb_free(msg);
@@ -130,17 +130,16 @@ static void do_start(void *_data)
{
struct link_data *link = (struct link_data *) _data;
- link->forced_down = 0;
- snmp_mtp_activate(link->udp.session);
- bsc_link_up(link);
+ snmp_mtp_activate(link->udp.session, link->udp.link_index);
+ mtp_link_up(link);
}
static int udp_link_reset(struct link_data *link)
{
LOGP(DINP, LOGL_NOTICE, "Will restart SLTM transmission in %d seconds.\n",
link->udp.reset_timeout);
- snmp_mtp_deactivate(link->udp.session);
- bsc_link_down(link);
+ snmp_mtp_deactivate(link->udp.session, link->udp.link_index);
+ mtp_link_down(link);
/* restart the link in 90 seconds... to force a timeout on the BSC */
link->link_activate.cb = do_start;
@@ -156,7 +155,7 @@ static int udp_link_write(struct link_data *link, struct msgb *msg)
hdr = (struct udp_data_hdr *) msgb_push(msg, sizeof(*hdr));
hdr->format_type = UDP_FORMAT_SIMPLE_UDP;
hdr->data_type = UDP_DATA_MSU_PRIO_0;
- hdr->data_link_index = htons(1);
+ hdr->data_link_index = htons(link->udp.link_index);
hdr->user_context = 0;
hdr->data_length = htonl(msgb_l2len(msg));
diff --git a/src/links.c b/src/links.c
new file mode 100644
index 0000000..023a7f4
--- /dev/null
+++ b/src/links.c
@@ -0,0 +1,177 @@
+/* link management code */
+/*
+ * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2011 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <bsc_data.h>
+#include <cellmgr_debug.h>
+#include <mtp_data.h>
+#include <snmp_mtp.h>
+
+#include <osmocore/talloc.h>
+
+extern struct bsc_data bsc;
+
+int is_one_up(struct mtp_link_set *set)
+{
+ struct link_data *entry;
+
+ llist_for_each_entry(entry, &set->links, entry)
+ if (entry->available)
+ return 1;
+ return 0;
+}
+
+void mtp_link_down(struct link_data *link)
+{
+ int one_up;
+ int was_up;
+
+ was_up = link->available;
+ link->available = 0;
+ one_up = is_one_up(link->the_link);
+
+ /* our linkset is now unsuable */
+ if (was_up && !one_up)
+ mtp_linkset_down(link->the_link);
+ link->clear_queue(link);
+ mtp_link_set_init_slc(link->the_link);
+}
+
+void mtp_link_up(struct link_data *link)
+{
+ int one_up;
+
+ one_up = is_one_up(link->the_link);
+ link->available = 1;
+
+ mtp_link_set_init_slc(link->the_link);
+ if (!one_up)
+ mtp_linkset_up(link->the_link);
+}
+
+void mtp_link_set_sccp_down(struct mtp_link_set *link)
+{
+}
+
+void mtp_link_set_submit(struct link_data *link, struct msgb *msg)
+{
+ link->write(link, msg);
+}
+
+void mtp_link_restart(struct link_data *link)
+{
+ LOGP(DINP, LOGL_ERROR, "Need to restart the SS7 link.\n");
+ link->reset(link);
+}
+
+static void start_rest(void *start)
+{
+ struct link_data *data;
+ bsc.setup = 1;
+
+ if (msc_init(&bsc, 1) != 0) {
+ fprintf(stderr, "Failed to init MSC part.\n");
+ exit(3);
+ }
+
+ llist_for_each_entry(data, &bsc.link_set->links, entry)
+ data->start(data);
+}
+
+int link_init(struct bsc_data *bsc)
+{
+ struct link_data *lnk;
+
+ bsc->link_set = mtp_link_set_alloc();
+ bsc->link_set->dpc = bsc->dpc;
+ bsc->link_set->opc = bsc->opc;
+ bsc->link_set->sccp_opc = bsc->sccp_opc > -1 ? bsc->sccp_opc : bsc->opc;
+ bsc->link_set->sltm_once = bsc->once;
+ bsc->link_set->ni = bsc->ni_ni;
+ bsc->link_set->spare = bsc->ni_spare;
+ bsc->link_set->bsc = bsc;
+
+ lnk = talloc_zero(bsc->link_set, struct link_data);
+ lnk->bsc = bsc;
+ lnk->udp.link_index = 1;
+ lnk->pcap_fd = bsc->pcap_fd;
+ lnk->udp.reset_timeout = bsc->udp_reset_timeout;
+ lnk->the_link = bsc->link_set;
+ mtp_link_set_add_link(bsc->link_set, lnk);
+
+ if (!bsc->src_port) {
+ LOGP(DINP, LOGL_ERROR, "You need to set a UDP address.\n");
+ return -1;
+ }
+
+ LOGP(DINP, LOGL_NOTICE, "Using UDP MTP mode.\n");
+
+ /* setup SNMP first, it is blocking */
+ lnk->udp.session = snmp_mtp_session_create(bsc->udp_ip);
+ if (!lnk->udp.session)
+ return -1;
+
+ /* now connect to the transport */
+ if (link_udp_init(lnk, bsc->src_port, bsc->udp_ip, bsc->udp_port) != 0)
+ return -1;
+
+ /*
+ * We will ask the MTP link to be taken down for two
+ * timeouts of the BSC to make sure we are missing the
+ * SLTM and it begins a reset. Then we will take it up
+ * again and do the usual business.
+ */
+ snmp_mtp_deactivate(lnk->udp.session,
+ lnk->udp.link_index);
+ bsc->start_timer.cb = start_rest;
+ bsc->start_timer.data = &bsc;
+ bsc_schedule_timer(&bsc->start_timer, lnk->udp.reset_timeout, 0);
+ LOGP(DMSC, LOGL_NOTICE, "Making sure SLTM will timeout.\n");
+
+ return 0;
+}
+
+int link_shutdown_all(struct mtp_link_set *set)
+{
+ struct link_data *lnk;
+
+ llist_for_each_entry(lnk, &set->links, entry)
+ lnk->shutdown(lnk);
+ return 0;
+}
+
+int link_reset_all(struct mtp_link_set *set)
+{
+ struct link_data *lnk;
+
+ llist_for_each_entry(lnk, &set->links, entry)
+ lnk->reset(lnk);
+ return 0;
+}
+
+int link_clear_all(struct mtp_link_set *set)
+{
+ struct link_data *lnk;
+
+ llist_for_each_entry(lnk, &set->links, entry)
+ lnk->clear_queue(lnk);
+ return 0;
+}
diff --git a/src/main.c b/src/main.c
index a977df4..3163527 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,7 +1,7 @@
/* Bloated main routine, refactor */
/*
- * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010 by On-Waves
+ * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2011 by On-Waves
* All Rights Reserved
*
* This program is free software: you can redistribute it and/or modify
@@ -26,7 +26,6 @@
#include <bss_patch.h>
#include <bssap_sccp.h>
#include <bsc_data.h>
-#include <snmp_mtp.h>
#include <cellmgr_debug.h>
#include <bsc_sccp.h>
@@ -65,18 +64,11 @@ static char *config = "cellmgr_ng.cfg";
struct bsc_data bsc;
extern void cell_vty_init(void);
-static void send_reset_ack(struct mtp_link *link, int sls);
+static void send_reset_ack(struct mtp_link_set *link, int sls);
static void bsc_resources_released(struct bsc_data *bsc);
-static void handle_local_sccp(struct mtp_link *link, struct msgb *inp, struct sccp_parse_result *res, int sls);
+static void handle_local_sccp(struct mtp_link_set *link, struct msgb *inp, struct sccp_parse_result *res, int sls);
static void clear_connections(struct bsc_data *bsc);
-static void send_local_rlsd(struct mtp_link *link, struct sccp_parse_result *res);
-
-int link_c7_init(struct link_data *data) __attribute__((__weak__));
-
-int link_c7_init(struct link_data *data)
-{
- return -1;
-}
+static void send_local_rlsd(struct mtp_link_set *link, struct sccp_parse_result *res);
/* send a RSIP to the MGCP GW */
static void mgcp_reset(struct bsc_data *bsc)
@@ -91,23 +83,7 @@ static void mgcp_reset(struct bsc_data *bsc)
/*
* methods called from the MTP Level3 part
*/
-void mtp_link_submit(struct mtp_link *link, struct msgb *msg)
-{
- bsc.link.write(&bsc.link, msg);
-}
-
-void mtp_link_restart(struct mtp_link *link)
-{
- LOGP(DINP, LOGL_ERROR, "Need to restart the SS7 link.\n");
- bsc.link.reset(&bsc.link);
-}
-
-void mtp_link_sccp_down(struct mtp_link *link)
-{
- msc_clear_queue(&bsc);
-}
-
-void mtp_link_forward_sccp(struct mtp_link *link, struct msgb *_msg, int sls)
+void mtp_link_set_forward_sccp(struct mtp_link_set *link, struct msgb *_msg, int sls)
{
int rc;
struct sccp_parse_result result;
@@ -115,7 +91,6 @@ void mtp_link_forward_sccp(struct mtp_link *link, struct msgb *_msg, int sls)
rc = bss_patch_filter_msg(_msg, &result);
if (rc == BSS_FILTER_RESET) {
LOGP(DMSC, LOGL_NOTICE, "Filtering BSS Reset from the BSC\n");
- msc_clear_queue(&bsc);
mgcp_reset(&bsc);
send_reset_ack(link, sls);
return;
@@ -155,7 +130,7 @@ void mtp_link_forward_sccp(struct mtp_link *link, struct msgb *_msg, int sls)
/*
* handle local message in close down mode
*/
-static void handle_local_sccp(struct mtp_link *link, struct msgb *inpt, struct sccp_parse_result *result, int sls)
+static void handle_local_sccp(struct mtp_link_set *link, struct msgb *inpt, struct sccp_parse_result *result, int sls)
{
/* Handle msg with a reject */
if (inpt->l2h[0] == SCCP_MSG_TYPE_CR) {
@@ -166,7 +141,7 @@ static void handle_local_sccp(struct mtp_link *link, struct msgb *inpt, struct s
cr = (struct sccp_connection_request *) inpt->l2h;
msg = create_sccp_refuse(&cr->source_local_reference);
if (msg) {
- mtp_link_submit_sccp_data(link, sls, msg->l2h, msgb_l2len(msg));
+ mtp_link_set_submit_sccp_data(link, sls, msg->l2h, msgb_l2len(msg));
msgb_free(msg);
}
return;
@@ -186,7 +161,7 @@ static void handle_local_sccp(struct mtp_link *link, struct msgb *inpt, struct s
LOGP(DINP, LOGL_DEBUG, "Sending a release request now.\n");
msg = create_sccp_rlsd(&con->dst_ref, &con->src_ref);
if (msg) {
- mtp_link_submit_sccp_data(link, con->sls, msg->l2h, msgb_l2len(msg));
+ mtp_link_set_submit_sccp_data(link, con->sls, msg->l2h, msgb_l2len(msg));
msgb_free(msg);
}
return;
@@ -219,7 +194,7 @@ static void clear_connections(struct bsc_data *bsc)
free_con(con);
}
- bsc->link.clear_queue(&bsc->link);
+ link_clear_all(bsc->link_set);
}
void bsc_resources_released(struct bsc_data *bsc)
@@ -235,9 +210,9 @@ static void bsc_reset_timeout(void *_data)
/* no reset */
if (bsc->reset_count > 0) {
LOGP(DINP, LOGL_ERROR, "The BSC did not answer the GSM08.08 reset. Restart MTP\n");
- mtp_link_stop(bsc->link.the_link);
+ mtp_link_set_stop(bsc->link_set);
clear_connections(bsc);
- bsc->link.reset(&bsc->link);
+ link_reset_all(bsc->link_set);
bsc_resources_released(bsc);
return;
}
@@ -249,7 +224,7 @@ static void bsc_reset_timeout(void *_data)
}
++bsc->reset_count;
- mtp_link_submit_sccp_data(bsc->link.the_link, 13, msg->l2h, msgb_l2len(msg));
+ mtp_link_set_submit_sccp_data(bsc->link_set, -1, msg->l2h, msgb_l2len(msg));
msgb_free(msg);
bsc_schedule_timer(&bsc->reset_timeout, 20, 0);
}
@@ -294,7 +269,7 @@ void release_bsc_resources(struct bsc_data *bsc)
continue;
/* wait for the clear commands */
- mtp_link_submit_sccp_data(bsc->link.the_link, con->sls, msg->l2h, msgb_l2len(msg));
+ mtp_link_set_submit_sccp_data(bsc->link_set, con->sls, msg->l2h, msgb_l2len(msg));
msgb_free(msg);
}
@@ -307,42 +282,30 @@ void release_bsc_resources(struct bsc_data *bsc)
bsc->reset_count = 0;
bsc_schedule_timer(&bsc->reset_timeout, 10, 0);
}
-
- /* clear pending messages from the MSC */
- msc_clear_queue(bsc);
}
-void bsc_link_down(struct link_data *data)
+void mtp_linkset_down(struct mtp_link_set *set)
{
- int was_up;
- struct mtp_link *link = data->the_link;
-
- link->available = 0;
- was_up = link->sccp_up;
- mtp_link_stop(link);
- clear_connections(data->bsc);
- mgcp_reset(data->bsc);
-
- data->clear_queue(data);
-
- /* clear pending messages from the MSC */
- msc_clear_queue(data->bsc);
+ set->available = 0;
+ mtp_link_set_stop(set);
+ clear_connections(set->bsc);
+ mgcp_reset(set->bsc);
/* If we have an A link send a reset to the MSC */
- msc_send_reset(data->bsc);
+ msc_send_reset(set->bsc);
}
-void bsc_link_up(struct link_data *data)
+void mtp_linkset_up(struct mtp_link_set *set)
{
- data->the_link->available = 1;
+ set->available = 1;
/* we have not gone through link down */
- if (data->bsc->msc_link_down) {
- clear_connections(data->bsc);
- bsc_resources_released(data->bsc);
+ if (set->bsc->msc_link_down) {
+ clear_connections(set->bsc);
+ bsc_resources_released(set->bsc);
}
- mtp_link_reset(data->the_link);
+ mtp_link_set_reset(set);
}
/**
@@ -356,7 +319,7 @@ static void send_rlc_to_bsc(unsigned int sls, struct sccp_source_reference *src,
if (!msg)
return;
- mtp_link_submit_sccp_data(bsc.link.the_link, sls, msg->l2h, msgb_l2len(msg));
+ mtp_link_set_submit_sccp_data(bsc.link_set, sls, msg->l2h, msgb_l2len(msg));
msgb_free(msg);
}
@@ -382,7 +345,7 @@ static void handle_rlsd(struct sccp_connection_released *rlsd, int from_msc)
&rlsd->source_local_reference);
}
} else {
- unsigned int sls = 13;
+ unsigned int sls = -1;
con = find_con_by_src_dest_ref(&rlsd->source_local_reference,
&rlsd->destination_local_reference);
if (con) {
@@ -417,7 +380,7 @@ static void handle_rlsd(struct sccp_connection_released *rlsd, int from_msc)
* 1.) We are destroying the connection, we might send a RLC to
* the MSC if we are waiting for one.
*/
-void update_con_state(struct mtp_link *link, int rc, struct sccp_parse_result *res, struct msgb *msg, int from_msc, int sls)
+void update_con_state(struct mtp_link_set *link, int rc, struct sccp_parse_result *res, struct msgb *msg, int from_msc, int sls)
{
struct active_sccp_con *con;
struct sccp_connection_request *cr;
@@ -537,11 +500,11 @@ static void send_local_rlsd_for_con(void *data)
++con->rls_tries;
LOGP(DINP, LOGL_DEBUG, "Sending RLSD for 0x%x the %d time.\n",
sccp_src_ref_to_int(&con->src_ref), con->rls_tries);
- mtp_link_submit_sccp_data(bsc.link.the_link, con->sls, rlsd->l2h, msgb_l2len(rlsd));
+ mtp_link_set_submit_sccp_data(bsc.link_set, con->sls, rlsd->l2h, msgb_l2len(rlsd));
msgb_free(rlsd);
}
-static void send_local_rlsd(struct mtp_link *link, struct sccp_parse_result *res)
+static void send_local_rlsd(struct mtp_link_set *link, struct sccp_parse_result *res)
{
struct active_sccp_con *con;
@@ -554,7 +517,7 @@ static void send_local_rlsd(struct mtp_link *link, struct sccp_parse_result *res
send_local_rlsd_for_con(con);
}
-static void send_reset_ack(struct mtp_link *link, int sls)
+static void send_reset_ack(struct mtp_link_set *link, int sls)
{
static const uint8_t reset_ack[] = {
0x09, 0x00, 0x03, 0x05, 0x7, 0x02, 0x42, 0xfe,
@@ -562,7 +525,7 @@ static void send_reset_ack(struct mtp_link *link, int sls)
0x00, 0x01, 0x31
};
- mtp_link_submit_sccp_data(link, sls, reset_ack, sizeof(reset_ack));
+ mtp_link_set_submit_sccp_data(link, sls, reset_ack, sizeof(reset_ack));
}
static void print_usage()
@@ -584,7 +547,7 @@ static void sigint()
printf("Terminating.\n");
handled = 1;
if (bsc.setup)
- bsc.link.shutdown(&bsc.link);
+ link_shutdown_all(bsc.link_set);
exit(0);
out:
@@ -630,14 +593,14 @@ static void handle_options(int argc, char **argv)
print_help();
exit(0);
case 'p':
- if (bsc.link.pcap_fd >= 0)
- close(bsc.link.pcap_fd);
- bsc.link.pcap_fd = open(optarg, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP| S_IROTH);
- if (bsc.link.pcap_fd < 0) {
+ if (bsc.pcap_fd >= 0)
+ close(bsc.pcap_fd);
+ bsc.pcap_fd = open(optarg, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP| S_IROTH);
+ if (bsc.pcap_fd < 0) {
fprintf(stderr, "Failed to open PCAP file.\n");
exit(0);
}
- mtp_pcap_write_header(bsc.link.pcap_fd);
+ mtp_pcap_write_header(bsc.pcap_fd);
break;
case 'c':
config = optarg;
@@ -653,19 +616,6 @@ static void handle_options(int argc, char **argv)
}
}
-static void start_rest(void *start)
-{
- bsc.setup = 1;
-
- if (msc_init(&bsc, 1) != 0) {
- fprintf(stderr, "Failed to init MSC part.\n");
- exit(3);
- }
-
- bsc.link.start(&bsc.link);
-}
-
-
int main(int argc, char **argv)
{
int rc;
@@ -680,7 +630,7 @@ int main(int argc, char **argv)
bsc.ni_ni = MTP_NI_NATION_NET;
bsc.ni_spare = 0;
- mtp_link_init();
+ mtp_link_set_init();
thread_init();
log_init(&log_info);
@@ -700,8 +650,8 @@ int main(int argc, char **argv)
bsc.setup = 0;
bsc.msc_address = "127.0.0.1";
- bsc.link.pcap_fd = -1;
- bsc.link.udp.reset_timeout = 180;
+ bsc.pcap_fd = -1;
+ bsc.udp_reset_timeout = 180;
bsc.ping_time = 20;
bsc.pong_time = 5;
bsc.msc_time = 20;
@@ -723,51 +673,8 @@ int main(int argc, char **argv)
if (rc < 0)
return rc;
- bsc.link.the_link = mtp_link_alloc();
- bsc.link.the_link->dpc = bsc.dpc;
- bsc.link.the_link->opc = bsc.opc;
- bsc.link.the_link->sccp_opc = bsc.sccp_opc > -1 ? bsc.sccp_opc : bsc.opc;
- bsc.link.the_link->link = 0;
- bsc.link.the_link->sltm_once = bsc.once;
- bsc.link.the_link->ni = bsc.ni_ni;
- bsc.link.the_link->spare = bsc.ni_spare;
- bsc.link.bsc = &bsc;
-
- if (bsc.udp_ip) {
- LOGP(DINP, LOGL_NOTICE, "Using UDP MTP mode.\n");
-
- /* setup SNMP first, it is blocking */
- bsc.link.udp.session = snmp_mtp_session_create(bsc.udp_ip);
- if (!bsc.link.udp.session)
- return -1;
-
- /* now connect to the transport */
- if (link_udp_init(&bsc.link, bsc.src_port, bsc.udp_ip, bsc.udp_port) != 0)
- return -1;
-
- /*
- * We will ask the MTP link to be taken down for two
- * timeouts of the BSC to make sure we are missing the
- * SLTM and it begins a reset. Then we will take it up
- * again and do the usual business.
- */
- snmp_mtp_deactivate(bsc.link.udp.session);
- bsc.start_timer.cb = start_rest;
- bsc.start_timer.data = &bsc;
- bsc_schedule_timer(&bsc.start_timer, bsc.link.udp.reset_timeout, 0);
- LOGP(DMSC, LOGL_NOTICE, "Making sure SLTM will timeout.\n");
- } else {
- LOGP(DINP, LOGL_NOTICE, "Using NexusWare C7 input.\n");
- if (link_c7_init(&bsc.link) != 0)
- return -1;
-
- /* give time to things to start*/
- bsc.start_timer.cb = start_rest;
- bsc.start_timer.data = &bsc;
- bsc_schedule_timer(&bsc.start_timer, 30, 0);
- LOGP(DMSC, LOGL_NOTICE, "Waiting to continue to startup.\n");
- }
-
+ if (link_init(&bsc) != 0)
+ return -1;
while (1) {
bsc_select_main(0);
diff --git a/src/main_udt.c b/src/main_udt.c
index f44be21..f13d4dd 100644
--- a/src/main_udt.c
+++ b/src/main_udt.c
@@ -1,7 +1,7 @@
/* Relay UDT/all SCCP messages */
/*
- * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010 by On-Waves
+ * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2011 by On-Waves
* All Rights Reserved
*
* This program is free software: you can redistribute it and/or modify
@@ -62,59 +62,27 @@ static char *config = "udt_relay.cfg";
struct bsc_data bsc;
extern void cell_vty_init(void);
-int link_c7_init(struct link_data *data) __attribute__((__weak__));
-
-int link_c7_init(struct link_data *data)
-{
- return -1;
-}
-
/*
* methods called from the MTP Level3 part
*/
-void mtp_link_submit(struct mtp_link *link, struct msgb *msg)
-{
- bsc.link.write(&bsc.link, msg);
-}
-
-void mtp_link_restart(struct mtp_link *link)
-{
- LOGP(DINP, LOGL_ERROR, "Need to restart the SS7 link.\n");
- bsc.link.reset(&bsc.link);
-}
-
-void mtp_link_sccp_down(struct mtp_link *link)
-{
- msc_clear_queue(&bsc);
-}
-
-void mtp_link_forward_sccp(struct mtp_link *link, struct msgb *_msg, int sls)
+void mtp_link_set_forward_sccp(struct mtp_link_set *link, struct msgb *_msg, int sls)
{
msc_send_direct(&bsc, _msg);
}
-void bsc_link_down(struct link_data *data)
+void mtp_linkset_down(struct mtp_link_set *set)
{
- int was_up;
- struct mtp_link *link = data->the_link;
-
- link->available = 0;
- was_up = link->sccp_up;
- mtp_link_stop(link);
-
- data->clear_queue(data);
-
- /* clear pending messages from the MSC */
- msc_clear_queue(data->bsc);
+ set->available = 0;
+ mtp_link_set_stop(set);
/* If we have an A link send a reset to the MSC */
- msc_send_reset(data->bsc);
+ msc_send_reset(set->bsc);
}
-void bsc_link_up(struct link_data *data)
+void mtp_linkset_up(struct mtp_link_set *set)
{
- data->the_link->available = 1;
- mtp_link_reset(data->the_link);
+ set->available = 1;
+ mtp_link_set_reset(set);
}
static void print_usage()
@@ -136,7 +104,7 @@ static void sigint()
printf("Terminating.\n");
handled = 1;
if (bsc.setup)
- bsc.link.shutdown(&bsc.link);
+ link_shutdown_all(bsc.link_set);
exit(0);
out:
@@ -182,14 +150,14 @@ static void handle_options(int argc, char **argv)
print_help();
exit(0);
case 'p':
- if (bsc.link.pcap_fd >= 0)
- close(bsc.link.pcap_fd);
- bsc.link.pcap_fd = open(optarg, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP| S_IROTH);
- if (bsc.link.pcap_fd < 0) {
+ if (bsc.pcap_fd >= 0)
+ close(bsc.pcap_fd);
+ bsc.pcap_fd = open(optarg, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP| S_IROTH);
+ if (bsc.pcap_fd < 0) {
fprintf(stderr, "Failed to open PCAP file.\n");
exit(0);
}
- mtp_pcap_write_header(bsc.link.pcap_fd);
+ mtp_pcap_write_header(bsc.pcap_fd);
break;
case 'c':
config = optarg;
@@ -205,19 +173,6 @@ static void handle_options(int argc, char **argv)
}
}
-static void start_rest(void *start)
-{
- bsc.setup = 1;
-
- if (msc_init(&bsc, 0) != 0) {
- fprintf(stderr, "Failed to init MSC part.\n");
- exit(3);
- }
-
- bsc.link.start(&bsc.link);
-}
-
-
int main(int argc, char **argv)
{
int rc;
@@ -232,7 +187,7 @@ int main(int argc, char **argv)
bsc.ni_ni = MTP_NI_NATION_NET;
bsc.ni_spare = 0;
- mtp_link_init();
+ mtp_link_set_init();
thread_init();
log_init(&log_info);
@@ -252,8 +207,8 @@ int main(int argc, char **argv)
bsc.setup = 0;
bsc.msc_address = "127.0.0.1";
- bsc.link.pcap_fd = -1;
- bsc.link.udp.reset_timeout = 180;
+ bsc.pcap_fd = -1;
+ bsc.udp_reset_timeout = 180;
bsc.ping_time = 20;
bsc.pong_time = 5;
bsc.msc_time = 20;
@@ -276,51 +231,8 @@ int main(int argc, char **argv)
if (rc < 0)
return rc;
- bsc.link.the_link = mtp_link_alloc();
- bsc.link.the_link->dpc = bsc.dpc;
- bsc.link.the_link->opc = bsc.opc;
- bsc.link.the_link->sccp_opc = bsc.sccp_opc > -1 ? bsc.sccp_opc : bsc.opc;
- bsc.link.the_link->link = 0;
- bsc.link.the_link->sltm_once = bsc.once;
- bsc.link.the_link->ni = bsc.ni_ni;
- bsc.link.the_link->spare = bsc.ni_spare;
- bsc.link.bsc = &bsc;
-
- if (bsc.udp_ip) {
- LOGP(DINP, LOGL_NOTICE, "Using UDP MTP mode.\n");
-
- /* setup SNMP first, it is blocking */
- bsc.link.udp.session = snmp_mtp_session_create(bsc.udp_ip);
- if (!bsc.link.udp.session)
- return -1;
-
- /* now connect to the transport */
- if (link_udp_init(&bsc.link, bsc.src_port, bsc.udp_ip, bsc.udp_port) != 0)
- return -1;
-
- /*
- * We will ask the MTP link to be taken down for two
- * timeouts of the BSC to make sure we are missing the
- * SLTM and it begins a reset. Then we will take it up
- * again and do the usual business.
- */
- snmp_mtp_deactivate(bsc.link.udp.session);
- bsc.start_timer.cb = start_rest;
- bsc.start_timer.data = &bsc;
- bsc_schedule_timer(&bsc.start_timer, bsc.link.udp.reset_timeout, 0);
- LOGP(DMSC, LOGL_NOTICE, "Making sure SLTM will timeout.\n");
- } else {
- LOGP(DINP, LOGL_NOTICE, "Using NexusWare C7 input.\n");
- if (link_c7_init(&bsc.link) != 0)
- return -1;
-
- /* give time to things to start*/
- bsc.start_timer.cb = start_rest;
- bsc.start_timer.data = &bsc;
- bsc_schedule_timer(&bsc.start_timer, 30, 0);
- LOGP(DMSC, LOGL_NOTICE, "Waiting to continue to startup.\n");
- }
-
+ if (link_init(&bsc) != 0)
+ return -1;
while (1) {
bsc_select_main(0);
@@ -331,8 +243,6 @@ int main(int argc, char **argv)
void release_bsc_resources(struct bsc_data *bsc)
{
- /* clear pending messages from the MSC */
- msc_clear_queue(bsc);
}
struct msgb *create_sccp_rlc(struct sccp_source_reference *src_ref,
@@ -348,7 +258,7 @@ struct msgb *create_reset()
return NULL;
}
-void update_con_state(struct mtp_link *link, int rc, struct sccp_parse_result *res, struct msgb *msg, int from_msc, int sls)
+void update_con_state(struct mtp_link_set *link, int rc, struct sccp_parse_result *res, struct msgb *msg, int from_msc, int sls)
{
LOGP(DMSC, LOGL_ERROR, "Should not be called.\n");
return;
diff --git a/src/msc_conn.c b/src/msc_conn.c
index 77c4039..bc05744 100644
--- a/src/msc_conn.c
+++ b/src/msc_conn.c
@@ -46,48 +46,13 @@ static void msc_send_id_response(struct bsc_data *bsc);
static void msc_send(struct bsc_data *bsc, struct msgb *msg, int proto);
static void msc_schedule_reconnect(struct bsc_data *bsc);
-void mtp_link_slta_recv(struct mtp_link *link)
+int send_or_queue_bsc_msg(struct mtp_link_set *link, int sls, struct msgb *msg)
{
- struct msgb *msg;
- unsigned int sls;
-
- while (!llist_empty(&link->pending_msgs)) {
- msg = msgb_dequeue(&link->pending_msgs);
- sls = (unsigned int) msg->l3h;
-
- if (mtp_link_submit_sccp_data(link, sls, msg->l2h, msgb_l2len(msg)) != 0)
- LOGP(DMSC, LOGL_ERROR, "Could not forward SCCP message.\n");
-
- msgb_free(msg);
- }
-}
-
-int send_or_queue_bsc_msg(struct mtp_link *link, int sls, struct msgb *msg)
-{
- if (link->sltm_pending) {
- LOGP(DMSC, LOGL_NOTICE, "Queueing msg for pending SLTM.\n");
- msg->l3h = (uint8_t *) sls;
- msgb_enqueue(&link->pending_msgs, msg);
- return 1;
- }
-
- if (mtp_link_submit_sccp_data(link, sls, msg->l2h, msgb_l2len(msg)) != 0)
+ if (mtp_link_set_submit_sccp_data(link, sls, msg->l2h, msgb_l2len(msg)) != 0)
LOGP(DMSC, LOGL_ERROR, "Could not forward SCCP message.\n");
return 0;
}
-
-void msc_clear_queue(struct bsc_data *data)
-{
- struct msgb *msg;
-
- LOGP(DMSC, LOGL_NOTICE, "Clearing the MSC to BSC queue.\n");
- while (!llist_empty(&data->link.the_link->pending_msgs)) {
- msg = msgb_dequeue(&data->link.the_link->pending_msgs);
- msgb_free(msg);
- }
-}
-
void msc_close_connection(struct bsc_data *bsc)
{
struct bsc_fd *bfd = &bsc->msc_connection.bfd;
@@ -157,7 +122,7 @@ static int ipaccess_a_fd_cb(struct bsc_fd *bfd)
{
int error;
struct ipaccess_head *hh;
- struct mtp_link *link;
+ struct mtp_link_set *link;
struct bsc_data *bsc;
struct msgb *msg;
@@ -181,7 +146,7 @@ static int ipaccess_a_fd_cb(struct bsc_fd *bfd)
hh = (struct ipaccess_head *) msg->data;
ipaccess_rcvmsg_base(msg, bfd);
- link = bsc->link.the_link;
+ link = bsc->link_set;
/* initialize the networking. This includes sending a GSM08.08 message */
if (hh->proto == IPAC_PROTO_IPACCESS) {
@@ -203,7 +168,7 @@ static int ipaccess_a_fd_cb(struct bsc_fd *bfd)
/* we can not forward it right now */
if (bsc->forward_only && link->sccp_up) {
- if (send_or_queue_bsc_msg(link, 13, msg) != 1)
+ if (send_or_queue_bsc_msg(link, -1, msg) != 1)
msgb_free(msg);
return 0;
}
diff --git a/src/mtp_layer3.c b/src/mtp_layer3.c
index 93a588c..531e121 100644
--- a/src/mtp_layer3.c
+++ b/src/mtp_layer3.c
@@ -20,6 +20,7 @@
*/
#include <mtp_data.h>
#include <mtp_level3.h>
+#include <bsc_data.h>
#include <cellmgr_debug.h>
#include <isup_types.h>
@@ -33,9 +34,9 @@
static void *tall_mtp_ctx = NULL;
-static int mtp_int_submit(struct mtp_link *link, int pc, int sls, int type, const uint8_t *data, unsigned int length);
+static int mtp_int_submit(struct mtp_link_set *link, int pc, int sls, int type, const uint8_t *data, unsigned int length);
-static struct msgb *mtp_msg_alloc(struct mtp_link *link)
+static struct msgb *mtp_msg_alloc(struct mtp_link_set *link)
{
struct mtp_level_3_hdr *hdr;
struct msgb *msg = msgb_alloc_headroom(4096, 128, "mtp-msg");
@@ -52,7 +53,7 @@ static struct msgb *mtp_msg_alloc(struct mtp_link *link)
return msg;
}
-static struct msgb *mtp_create_sltm(struct mtp_link *link)
+static struct msgb *mtp_create_sltm(struct mtp_link_set *link)
{
const uint8_t test_ptrn[14] = { 'G', 'S', 'M', 'M', 'M', 'S', };
struct mtp_level_3_hdr *hdr;
@@ -79,7 +80,7 @@ static struct msgb *mtp_create_sltm(struct mtp_link *link)
return msg;
}
-static struct msgb *mtp_create_slta(struct mtp_link *link, struct mtp_level_3_mng *in_mng, int l3_len)
+static struct msgb *mtp_create_slta(struct mtp_link_set *link, struct mtp_level_3_mng *in_mng, int l3_len)
{
struct mtp_level_3_hdr *hdr;
struct mtp_level_3_mng *mng;
@@ -100,7 +101,7 @@ static struct msgb *mtp_create_slta(struct mtp_link *link, struct mtp_level_3_mn
return out;
}
-static struct msgb *mtp_tfp_alloc(struct mtp_link *link, int apoc)
+static struct msgb *mtp_tfp_alloc(struct mtp_link_set *link, int apoc)
{
struct mtp_level_3_hdr *hdr;
struct mtp_level_3_prohib *prb;
@@ -118,7 +119,7 @@ static struct msgb *mtp_tfp_alloc(struct mtp_link *link, int apoc)
return out;
}
-static struct msgb *mtp_tra_alloc(struct mtp_link *link)
+static struct msgb *mtp_tra_alloc(struct mtp_link_set *link)
{
struct mtp_level_3_hdr *hdr;
struct mtp_level_3_cmn *cmn;
@@ -135,7 +136,7 @@ static struct msgb *mtp_tra_alloc(struct mtp_link *link)
return out;
}
-static struct msgb *mtp_sccp_alloc_scmg(struct mtp_link *link,
+static struct msgb *mtp_sccp_alloc_scmg(struct mtp_link_set *link,
int type, int assn, int sls)
{
struct sccp_data_unitdata *udt;
@@ -186,12 +187,12 @@ static struct msgb *mtp_sccp_alloc_scmg(struct mtp_link *link,
return out;
}
-void mtp_link_init(void)
+void mtp_link_set_init(void)
{
tall_mtp_ctx = talloc_named_const(NULL, 1, "mtp-link");
}
-static void mtp_send_sltm(struct mtp_link *link)
+static void mtp_send_sltm(struct mtp_link_set *link)
{
struct msgb *msg;
@@ -202,12 +203,12 @@ static void mtp_send_sltm(struct mtp_link *link)
return;
}
- mtp_link_submit(link, msg);
+ mtp_link_set_submit(link->slc[0], msg);
}
static void mtp_sltm_t1_timeout(void *_link)
{
- struct mtp_link *link = (struct mtp_link *) _link;
+ struct mtp_link_set *link = (struct mtp_link_set *) _link;
if (link->slta_misses == 0) {
LOGP(DINP, LOGL_ERROR, "No SLTM response. Retrying. Link: %p\n", link);
@@ -219,14 +220,14 @@ static void mtp_sltm_t1_timeout(void *_link)
link->sccp_up = 0;
link->running = 0;
bsc_del_timer(&link->t2_timer);
- mtp_link_sccp_down(link);
- mtp_link_restart(link);
+ mtp_link_set_sccp_down(link);
+ mtp_link_restart(link->slc[0]);
}
}
static void mtp_sltm_t2_timeout(void *_link)
{
- struct mtp_link *link = (struct mtp_link *) _link;
+ struct mtp_link_set *link = (struct mtp_link_set *) _link;
if (!link->running) {
LOGP(DINP, LOGL_INFO, "Not restarting SLTM timer on link: %p\n", link);
@@ -249,11 +250,11 @@ static void mtp_delayed_start(void *link)
mtp_sltm_t2_timeout(link);
}
-struct mtp_link *mtp_link_alloc(void)
+struct mtp_link_set *mtp_link_set_alloc(void)
{
- struct mtp_link *link;
+ struct mtp_link_set *link;
- link = talloc_zero(tall_mtp_ctx, struct mtp_link);
+ link = talloc_zero(tall_mtp_ctx, struct mtp_link_set);
if (!link)
return NULL;
@@ -264,11 +265,12 @@ struct mtp_link *mtp_link_alloc(void)
link->t2_timer.cb = mtp_sltm_t2_timeout;
link->delay_timer.data = link;
link->delay_timer.cb = mtp_delayed_start;
- INIT_LLIST_HEAD(&link->pending_msgs);
+ INIT_LLIST_HEAD(&link->links);
+
return link;
}
-void mtp_link_stop(struct mtp_link *link)
+void mtp_link_set_stop(struct mtp_link_set *link)
{
bsc_del_timer(&link->t1_timer);
bsc_del_timer(&link->t2_timer);
@@ -277,17 +279,17 @@ void mtp_link_stop(struct mtp_link *link)
link->running = 0;
link->sltm_pending = 0;
- mtp_link_sccp_down(link);
+ mtp_link_set_sccp_down(link);
}
-void mtp_link_reset(struct mtp_link *link)
+void mtp_link_set_reset(struct mtp_link_set *link)
{
- mtp_link_stop(link);
+ mtp_link_set_stop(link);
link->running = 1;
bsc_schedule_timer(&link->delay_timer, START_DELAY);
}
-static int mtp_link_sign_msg(struct mtp_link *link, struct mtp_level_3_hdr *hdr, int l3_len)
+static int mtp_link_sign_msg(struct mtp_link_set *link, struct mtp_level_3_hdr *hdr, int l3_len)
{
struct msgb *msg;
struct mtp_level_3_cmn *cmn;
@@ -309,18 +311,18 @@ static int mtp_link_sign_msg(struct mtp_link *link, struct mtp_level_3_hdr *hdr,
case MTP_RESTR_MSG_ALLWED:
LOGP(DINP, LOGL_INFO, "Received Restart Allowed. SST could be next: %p\n", link);
link->sccp_up = 0;
- mtp_link_sccp_down(link);
+ mtp_link_set_sccp_down(link);
msg = mtp_tfp_alloc(link, 0);
if (!msg)
return -1;
- mtp_link_submit(link, msg);
+ mtp_link_set_submit(link->slc[0], msg);
msg = mtp_tra_alloc(link);
if (!msg)
return -1;
- mtp_link_submit(link, msg);
+ mtp_link_set_submit(link->slc[0], msg);
link->sccp_up = 1;
link->was_up = 1;
LOGP(DINP, LOGL_INFO, "SCCP traffic allowed. %p\n", link);
@@ -349,7 +351,7 @@ static int mtp_link_sign_msg(struct mtp_link *link, struct mtp_level_3_hdr *hdr,
return -1;
}
-static int mtp_link_regular_msg(struct mtp_link *link, struct mtp_level_3_hdr *hdr, int l3_len)
+static int mtp_link_regular_msg(struct mtp_link_set *link, struct mtp_level_3_hdr *hdr, int l3_len)
{
struct msgb *out;
struct mtp_level_3_mng *mng;
@@ -372,7 +374,7 @@ static int mtp_link_regular_msg(struct mtp_link *link, struct mtp_level_3_hdr *h
out = mtp_create_slta(link, mng, l3_len);
if (!out)
return -1;
- mtp_link_submit(link, out);
+ mtp_link_set_submit(link->slc[0], out);
return 0;
break;
case MTP_TST_MSG_SLTA:
@@ -394,7 +396,6 @@ static int mtp_link_regular_msg(struct mtp_link *link, struct mtp_level_3_hdr *h
/* we had a matching slta */
bsc_del_timer(&link->t1_timer);
link->sltm_pending = 0;
- mtp_link_slta_recv(link);
return 0;
break;
}
@@ -404,7 +405,7 @@ static int mtp_link_regular_msg(struct mtp_link *link, struct mtp_level_3_hdr *h
return -1;
}
-static int mtp_link_sccp_data(struct mtp_link *link, struct mtp_level_3_hdr *hdr, struct msgb *msg, int l3_len)
+static int mtp_link_sccp_data(struct mtp_link_set *link, struct mtp_level_3_hdr *hdr, struct msgb *msg, int l3_len)
{
struct msgb *out;
struct sccp_con_ctrl_prt_mgt *prt;
@@ -457,15 +458,15 @@ static int mtp_link_sccp_data(struct mtp_link *link, struct mtp_level_3_hdr *hdr
if (!out)
return -1;
- mtp_link_submit(link, out);
+ mtp_link_set_submit(link->slc[MTP_LINK_SLS(hdr->addr)], out);
return 0;
}
- mtp_link_forward_sccp(link, msg, MTP_LINK_SLS(hdr->addr));
+ mtp_link_set_forward_sccp(link, msg, MTP_LINK_SLS(hdr->addr));
return 0;
}
-int mtp_link_data(struct mtp_link *link, struct msgb *msg)
+int mtp_link_set_data(struct mtp_link_set *link, struct msgb *msg)
{
int rc = -1;
struct mtp_level_3_hdr *hdr;
@@ -494,7 +495,7 @@ int mtp_link_data(struct mtp_link *link, struct msgb *msg)
break;
case MTP_SI_MNT_ISUP:
msg->l3h = &hdr->data[0];
- rc = mtp_link_forward_isup(link, msg, MTP_LINK_SLS(hdr->addr));
+ rc = mtp_link_set_forward_isup(link, msg, MTP_LINK_SLS(hdr->addr));
break;
default:
fprintf(stderr, "Unhandled: %u\n", hdr->ser_ind);
@@ -504,7 +505,7 @@ int mtp_link_data(struct mtp_link *link, struct msgb *msg)
return rc;
}
-int mtp_link_submit_sccp_data(struct mtp_link *link, int sls, const uint8_t *data, unsigned int length)
+int mtp_link_set_submit_sccp_data(struct mtp_link_set *link, int sls, const uint8_t *data, unsigned int length)
{
if (!link->sccp_up) {
@@ -512,16 +513,21 @@ int mtp_link_submit_sccp_data(struct mtp_link *link, int sls, const uint8_t *dat
return -1;
}
+ if (sls == -1) {
+ sls = link->last_sls;
+ link->last_sls = (link->last_sls + 1) % 16;
+ }
+
return mtp_int_submit(link, link->sccp_opc, sls, MTP_SI_MNT_SCCP, data, length);
}
-int mtp_link_submit_isup_data(struct mtp_link *link, int sls,
+int mtp_link_set_submit_isup_data(struct mtp_link_set *link, int sls,
const uint8_t *data, unsigned int length)
{
return mtp_int_submit(link, link->opc, sls, MTP_SI_MNT_ISUP, data, length);
}
-static int mtp_int_submit(struct mtp_link *link, int pc, int sls, int type,
+static int mtp_int_submit(struct mtp_link_set *link, int pc, int sls, int type,
const uint8_t *data, unsigned int length)
{
uint8_t *put_ptr;
@@ -541,6 +547,52 @@ static int mtp_int_submit(struct mtp_link *link, int pc, int sls, int type,
put_ptr = msgb_put(msg, length);
memcpy(put_ptr, data, length);
- mtp_link_submit(link, msg);
+ mtp_link_set_submit(link->slc[sls % 16], msg);
return 0;
}
+
+static struct link_data *find_next_link(struct mtp_link_set *set,
+ struct link_data *data)
+{
+ int found = 0;
+ struct link_data *next;
+
+ if (llist_empty(&set->links))
+ return NULL;
+
+ if (data == NULL)
+ found = 1;
+
+ /* try to find the next one */
+ llist_for_each_entry(next, &set->links, entry) {
+ if (found && next->available)
+ return next;
+ if (next == data)
+ found = 1;
+ }
+
+ /* try to find any one */
+ llist_for_each_entry(next, &set->links, entry)
+ if (next->available)
+ return next;
+
+ return NULL;
+}
+
+void mtp_link_set_init_slc(struct mtp_link_set *set)
+{
+ struct link_data *link = NULL;
+ int i;
+
+
+ for (i = 0; i < ARRAY_SIZE(set->slc); ++i) {
+ link = find_next_link(set, link);
+ set->slc[i] = link;
+ }
+}
+
+void mtp_link_set_add_link(struct mtp_link_set *set, struct link_data *lnk)
+{
+ llist_add_tail(&lnk->entry, &set->links);
+ mtp_link_set_init_slc(set);
+}
diff --git a/src/snmp_mtp.c b/src/snmp_mtp.c
index 6d85f31..ba3a219 100644
--- a/src/snmp_mtp.c
+++ b/src/snmp_mtp.c
@@ -100,12 +100,12 @@ struct snmp_mtp_session *snmp_mtp_session_create(char *host)
return session;
}
-void snmp_mtp_deactivate(struct snmp_mtp_session *session)
+void snmp_mtp_deactivate(struct snmp_mtp_session *session, int index)
{
- snmp_mtp_stop_c7_datalink(session, 1);
+ snmp_mtp_stop_c7_datalink(session, index);
}
-void snmp_mtp_activate(struct snmp_mtp_session *session)
+void snmp_mtp_activate(struct snmp_mtp_session *session, int index)
{
- snmp_mtp_start_c7_datalink(session, 1);
+ snmp_mtp_start_c7_datalink(session, index);
}
diff --git a/src/vty_interface.c b/src/vty_interface.c
index 6ddf549..0cf5929 100644
--- a/src/vty_interface.c
+++ b/src/vty_interface.c
@@ -72,7 +72,7 @@ static int config_write_cell(struct vty *vty)
vty_out(vty, " udp dest ip %s%s", bsc.udp_ip, VTY_NEWLINE);
vty_out(vty, " udp dest port %d%s", bsc.udp_port, VTY_NEWLINE);
vty_out(vty, " udp src port %d%s", bsc.src_port, VTY_NEWLINE);
- vty_out(vty, " udp reset %d%s", bsc.link.udp.reset_timeout, VTY_NEWLINE);
+ vty_out(vty, " udp reset %d%s", bsc.udp_reset_timeout, VTY_NEWLINE);
vty_out(vty, " msc ip %s%s", bsc.msc_address, VTY_NEWLINE);
vty_out(vty, " msc ip-dscp %d%s", bsc.msc_ip_dscp, VTY_NEWLINE);
vty_out(vty, " msc token %s%s", bsc.token, VTY_NEWLINE);
@@ -166,7 +166,7 @@ DEFUN(cfg_udp_reset, cfg_udp_reset_cmd,
"udp reset TIMEOUT",
"Set the timeout to take the link down")
{
- bsc.link.udp.reset_timeout = atoi(argv[0]);
+ bsc.udp_reset_timeout = atoi(argv[0]);
return CMD_SUCCESS;
}
diff --git a/tests/isup/isup_parse_test.c b/tests/isup/isup_parse_test.c
index 5b19ed0..5c3341c 100644
--- a/tests/isup/isup_parse_test.c
+++ b/tests/isup/isup_parse_test.c
@@ -62,4 +62,4 @@ int main(int argc, char **argv)
}
/* stubs */
-int mtp_link_submit_isup_data() {return -1;}
+int mtp_link_set_submit_isup_data() {return -1;}