9
0
Fork 0

mtp: Move the link testing into a new file for mtp_link

The link testing should work under the linkset and if the
SLTM is failing the link should be taken down and it should
be restarted.
This commit is contained in:
Holger Hans Peter Freyther 2011-01-20 16:30:24 +01:00
parent 2d845fca0c
commit a8ce061d86
6 changed files with 214 additions and 139 deletions

View File

@ -112,8 +112,6 @@ struct bsc_data {
/* bsc related functions */
void release_bsc_resources(struct bsc_data *bsc);
void mtp_link_down(struct mtp_link *data);
void mtp_link_up(struct mtp_link *data);
void mtp_linkset_down(struct mtp_link_set *);
void mtp_linkset_up(struct mtp_link_set *);

View File

@ -26,6 +26,7 @@
struct bsc_data;
struct mtp_link;
struct mtp_level_3_mng *mng;
/* MTP Level3 timers */
@ -52,19 +53,9 @@ struct mtp_link_set {
int last_sls;
/* misc data */
uint8_t test_ptrn[14];
int sltm_pending;
int sltm_once;
int was_up;
int slta_misses;
struct timer_list t1_timer;
struct timer_list t2_timer;
struct llist_head links;
struct mtp_link *slc[16];
int sltm_once;
/* special handling */
int pass_all_isup;
@ -89,6 +80,17 @@ struct mtp_link {
struct timer_list link_activate;
/* link test routine */
uint8_t test_ptrn[14];
int sltm_pending;
int was_up;
int slta_misses;
struct timer_list t1_timer;
struct timer_list t2_timer;
/* callback's to implement */
int (*start)(struct mtp_link *);
int (*write)(struct mtp_link *, struct msgb *msg);
int (*shutdown)(struct mtp_link *);
@ -118,4 +120,17 @@ void mtp_link_set_forward_isup(struct mtp_link_set *link, struct msgb *msg, int
void mtp_link_restart(struct mtp_link *link);
void mtp_link_set_sccp_down(struct mtp_link_set *link);
/* link related routines */
void mtp_link_down(struct mtp_link *data);
void mtp_link_up(struct mtp_link *data);
void mtp_link_init(struct mtp_link *link);
void mtp_link_start_link_test(struct mtp_link *link);
void mtp_link_stop_link_test(struct mtp_link *link);
int mtp_link_slta(struct mtp_link *link, uint16_t l3_len, struct mtp_level_3_mng *mng);
/* internal routines */
struct msgb *mtp_msg_alloc(struct mtp_link_set *link);
void mtp_link_set_trasmit(struct mtp_link *link, int sls, struct msgb *msg);
#endif

View File

@ -11,17 +11,19 @@ mgcp_mgw_LDADD = $(LAFORGE_LIBS) $(NEXUSWARE_C7_LIBS) $(NEXUSWARE_UNIPORTE_LIBS)
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 links.c \
msc_conn.c link_udp.c snmp_mtp.c debug.c vty_interface.c isup.c
msc_conn.c link_udp.c snmp_mtp.c debug.c vty_interface.c isup.c \
mtp_link.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 links.c sctp_m2ua.c
bss_patch.c isup.c links.c sctp_m2ua.c mtp_link.c
udt_relay_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOSCCP_LIBS) $(LIBOSMOVTY_LIBS) $(NEXUSWARE_C7_LIBS) \
-lpthread -lnetsnmp -lcrypto -lm2ua -lsctp
osmo_stp_SOURCES = main_stp.c mtp_layer3.c thread.c pcap.c link_udp.c snmp_mtp.c \
debug.c vty_interface.c links.c isup.c sctp_m2ua.c
debug.c vty_interface.c links.c isup.c sctp_m2ua.c \
mtp_link.c
osmo_stp_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOSCCP_LIBS) $(LIBOSMOVTY_LIBS) $(NEXUSWARE_C7_LIBS) \
-lpthread -lnetsnmp -lcrypto -lm2ua -lsctp

View File

@ -46,12 +46,14 @@ void mtp_link_down(struct mtp_link *link)
was_up = link->available;
link->available = 0;
link->was_up = 0;
one_up = is_one_up(link->set);
/* our linkset is now unsuable */
if (was_up && !one_up)
mtp_linkset_down(link->set);
link->clear_queue(link);
mtp_link_stop_link_test(link);
mtp_link_set_init_slc(link->set);
}
@ -61,10 +63,13 @@ void mtp_link_up(struct mtp_link *link)
one_up = is_one_up(link->set);
link->available = 1;
link->was_up = 0;
mtp_link_set_init_slc(link->set);
if (!one_up)
mtp_linkset_up(link->set);
else
mtp_link_start_link_test(link);
}
void mtp_link_set_sccp_down(struct mtp_link_set *link)

View File

@ -36,7 +36,7 @@ static void *tall_mtp_ctx = NULL;
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_set *link)
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");
@ -53,33 +53,6 @@ static struct msgb *mtp_msg_alloc(struct mtp_link_set *link)
return msg;
}
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;
struct mtp_level_3_mng *mng;
struct msgb *msg = mtp_msg_alloc(link);
uint8_t *data;
if (!msg)
return NULL;
hdr = (struct mtp_level_3_hdr *) msg->l2h;
hdr->ser_ind = MTP_SI_MNT_REG_MSG;
mng = (struct mtp_level_3_mng *) msgb_put(msg, sizeof(*mng));
mng->cmn.h0 = MTP_TST_MSG_GRP;
mng->cmn.h1 = MTP_TST_MSG_SLTM;
mng->length = ARRAY_SIZE(test_ptrn);
data = msgb_put(msg, ARRAY_SIZE(test_ptrn));
memcpy(data, test_ptrn, ARRAY_SIZE(test_ptrn));
/* remember the last tst ptrn... once we have some */
memcpy(link->test_ptrn, test_ptrn, ARRAY_SIZE(test_ptrn));
return msg;
}
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;
@ -101,6 +74,7 @@ static struct msgb *mtp_create_slta(struct mtp_link_set *link, struct mtp_level_
return out;
}
static struct msgb *mtp_base_alloc(struct mtp_link_set *link, int msg, int apoc)
{
struct mtp_level_3_hdr *hdr;
@ -203,60 +177,6 @@ void mtp_link_set_init(void)
tall_mtp_ctx = talloc_named_const(NULL, 1, "mtp-link");
}
static void mtp_send_sltm(struct mtp_link_set *link)
{
struct msgb *msg;
link->sltm_pending = 1;
msg = mtp_create_sltm(link);
if (!msg) {
LOGP(DINP, LOGL_ERROR, "Failed to allocate SLTM.\n");
return;
}
mtp_link_set_submit(link->slc[0], msg);
}
static void mtp_sltm_t1_timeout(void *_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);
++link->slta_misses;
mtp_send_sltm(link);
bsc_schedule_timer(&link->t1_timer, MTP_T1);
} else {
LOGP(DINP, LOGL_ERROR, "Two missing SLTAs. Restart link: %p\n", link);
link->sccp_up = 0;
link->running = 0;
link->linkset_up = 0;
bsc_del_timer(&link->t2_timer);
mtp_link_set_sccp_down(link);
mtp_link_restart(link->slc[0]);
}
}
static void mtp_sltm_t2_timeout(void *_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);
return;
}
link->slta_misses = 0;
mtp_send_sltm(link);
bsc_schedule_timer(&link->t1_timer, MTP_T1);
if (link->sltm_once && link->was_up)
LOGP(DINP, LOGL_INFO, "Not sending SLTM again as configured.\n");
else
bsc_schedule_timer(&link->t2_timer, MTP_T2);
}
struct mtp_link_set *mtp_link_set_alloc(void)
{
struct mtp_link_set *link;
@ -266,10 +186,6 @@ struct mtp_link_set *mtp_link_set_alloc(void)
return NULL;
link->ni = MTP_NI_NATION_NET;
link->t1_timer.data = link;
link->t1_timer.cb = mtp_sltm_t1_timeout;
link->t2_timer.data = link;
link->t2_timer.cb = mtp_sltm_t2_timeout;
INIT_LLIST_HEAD(&link->links);
return link;
@ -277,21 +193,24 @@ struct mtp_link_set *mtp_link_set_alloc(void)
void mtp_link_set_stop(struct mtp_link_set *link)
{
bsc_del_timer(&link->t1_timer);
bsc_del_timer(&link->t2_timer);
struct mtp_link *lnk;
llist_for_each_entry(lnk, &link->links, entry)
mtp_link_stop_link_test(lnk);
link->sccp_up = 0;
link->running = 0;
link->linkset_up = 0;
link->sltm_pending = 0;
mtp_link_set_sccp_down(link);
}
void mtp_link_set_reset(struct mtp_link_set *link)
{
struct mtp_link *lnk;
mtp_link_set_stop(link);
link->running = 1;
mtp_sltm_t2_timeout(link);
llist_for_each_entry(lnk, &link->links, entry)
mtp_link_start_link_test(lnk);
}
static int send_tfp(struct mtp_link_set *link, int apoc)
@ -382,7 +301,6 @@ static int mtp_link_sign_msg(struct mtp_link_set *link, struct mtp_level_3_hdr *
mtp_link_set_sccp_down(link);
link->sccp_up = 1;
link->was_up = 1;
LOGP(DINP, LOGL_INFO, "SCCP traffic allowed. %p\n", link);
return 0;
break;
@ -409,20 +327,20 @@ static int mtp_link_sign_msg(struct mtp_link_set *link, struct mtp_level_3_hdr *
return -1;
}
static int mtp_link_regular_msg(struct mtp_link_set *link, struct mtp_level_3_hdr *hdr, int l3_len)
static int mtp_link_regular_msg(struct mtp_link *link, struct mtp_level_3_hdr *hdr, int l3_len)
{
struct msgb *out;
struct mtp_level_3_mng *mng;
if (hdr->ni != link->ni || l3_len < 1) {
if (hdr->ni != link->set->ni || l3_len < 1) {
LOGP(DINP, LOGL_ERROR, "Unhandled data (ni: %d len: %d)\n",
hdr->ni, l3_len);
return -1;
}
if (MTP_ADDR_DPC(hdr->addr) != link->opc) {
if (MTP_ADDR_DPC(hdr->addr) != link->set->opc) {
LOGP(DINP, LOGL_ERROR, "MSG for 0x%x not handled by 0x%x\n",
MTP_ADDR_DPC(hdr->addr), link->opc);
MTP_ADDR_DPC(hdr->addr), link->set->opc);
return -1;
}
@ -435,36 +353,16 @@ static int mtp_link_regular_msg(struct mtp_link_set *link, struct mtp_level_3_hd
switch (mng->cmn.h1) {
case MTP_TST_MSG_SLTM:
/* simply respond to the request... */
out = mtp_create_slta(link, mng, l3_len);
out = mtp_create_slta(link->set, mng, l3_len);
if (!out)
return -1;
mtp_link_set_submit(link->slc[0], out);
mtp_link_set_submit(link->set->slc[0], out);
return 0;
break;
case MTP_TST_MSG_SLTA:
if (mng->length != 14) {
LOGP(DINP, LOGL_ERROR, "Wrongly sized SLTA: %u\n", mng->length);
return -1;
}
if (l3_len != 16) {
LOGP(DINP, LOGL_ERROR, "Wrongly sized SLTA: %u\n", mng->length);
return -1;
}
if (memcmp(mng->data, link->test_ptrn, sizeof(link->test_ptrn)) != 0) {
LOGP(DINP, LOGL_ERROR, "Wrong test pattern SLTA\n");
return -1;
}
/* we had a matching slta */
bsc_del_timer(&link->t1_timer);
link->sltm_pending = 0;
/* This link of the linkset is now proven */
linkset_up(link);
return 0;
/* If this link is proven set it up */
if (mtp_link_slta(link, l3_len, mng) == 0)
linkset_up(link->set);
break;
}
break;
@ -556,7 +454,7 @@ int mtp_link_set_data(struct mtp_link *link, struct msgb *msg)
rc = mtp_link_sign_msg(link->set, hdr, l3_len);
break;
case MTP_SI_MNT_REG_MSG:
rc = mtp_link_regular_msg(link->set, hdr, l3_len);
rc = mtp_link_regular_msg(link, hdr, l3_len);
break;
case MTP_SI_MNT_SCCP:
rc = mtp_link_sccp_data(link->set, hdr, msg, l3_len);
@ -622,6 +520,11 @@ static int mtp_int_submit(struct mtp_link_set *link, int pc, int sls, int type,
return 0;
}
void mtp_link_set_trasmit(struct mtp_link *link, int sls, struct msgb *msg)
{
return mtp_link_set_submit(link->set->slc[sls % 16], msg);
}
static struct mtp_link *find_next_link(struct mtp_link_set *set,
struct mtp_link *data)
{
@ -664,7 +567,9 @@ void mtp_link_set_init_slc(struct mtp_link_set *set)
void mtp_link_set_add_link(struct mtp_link_set *set, struct mtp_link *lnk)
{
llist_add_tail(&lnk->entry, &set->links);
lnk->set = set;
mtp_link_init(lnk);
llist_add_tail(&lnk->entry, &set->links);
mtp_link_set_init_slc(set);
}

150
src/mtp_link.c Normal file
View File

@ -0,0 +1,150 @@
/* MTP level3 link */
/*
* (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2010 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 Affero General Public License as published by
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <mtp_data.h>
#include <mtp_level3.h>
#include <cellmgr_debug.h>
#include <string.h>
static struct msgb *mtp_create_sltm(struct mtp_link *link)
{
const uint8_t test_ptrn[14] = { 'G', 'S', 'M', 'M', 'M', 'S', };
struct mtp_level_3_hdr *hdr;
struct mtp_level_3_mng *mng;
struct msgb *msg = mtp_msg_alloc(link->set);
uint8_t *data;
if (!msg)
return NULL;
hdr = (struct mtp_level_3_hdr *) msg->l2h;
hdr->ser_ind = MTP_SI_MNT_REG_MSG;
mng = (struct mtp_level_3_mng *) msgb_put(msg, sizeof(*mng));
mng->cmn.h0 = MTP_TST_MSG_GRP;
mng->cmn.h1 = MTP_TST_MSG_SLTM;
mng->length = ARRAY_SIZE(test_ptrn);
data = msgb_put(msg, ARRAY_SIZE(test_ptrn));
memcpy(data, test_ptrn, ARRAY_SIZE(test_ptrn));
/* remember the last tst ptrn... once we have some */
memcpy(link->test_ptrn, test_ptrn, ARRAY_SIZE(test_ptrn));
return msg;
}
static void mtp_send_sltm(struct mtp_link *link)
{
struct msgb *msg;
link->sltm_pending = 1;
msg = mtp_create_sltm(link);
if (!msg) {
LOGP(DINP, LOGL_ERROR, "Failed to allocate SLTM.\n");
return;
}
mtp_link_set_trasmit(link, 0, msg);
}
static void mtp_sltm_t1_timeout(void *_link)
{
struct mtp_link *link = (struct mtp_link *) _link;
if (link->slta_misses == 0) {
LOGP(DINP, LOGL_ERROR, "No SLTM response. Retrying. Link: %p\n", link);
++link->slta_misses;
mtp_send_sltm(link);
bsc_schedule_timer(&link->t1_timer, MTP_T1);
} else {
LOGP(DINP, LOGL_ERROR, "Two missing SLTAs. Restart link: %p\n", link);
bsc_del_timer(&link->t2_timer);
mtp_link_down(link);
}
}
static void mtp_sltm_t2_timeout(void *_link)
{
struct mtp_link *link = (struct mtp_link *) _link;
if (!link->set->running) {
LOGP(DINP, LOGL_INFO, "The linkset is not active. Stopping SLTM now. %p\n", link);
return;
}
link->slta_misses = 0;
mtp_send_sltm(link);
bsc_schedule_timer(&link->t1_timer, MTP_T1);
if (link->set->sltm_once && link->was_up)
LOGP(DINP, LOGL_INFO, "Not sending SLTM again as configured.\n");
else
bsc_schedule_timer(&link->t2_timer, MTP_T2);
}
void mtp_link_init(struct mtp_link *link)
{
link->t1_timer.data = link;
link->t1_timer.cb = mtp_sltm_t1_timeout;
link->t2_timer.data = link;
link->t2_timer.cb = mtp_sltm_t2_timeout;
}
void mtp_link_stop_link_test(struct mtp_link *link)
{
bsc_del_timer(&link->t1_timer);
bsc_del_timer(&link->t2_timer);
link->sltm_pending = 0;
}
void mtp_link_start_link_test(struct mtp_link *link)
{
mtp_sltm_t2_timeout(link);
}
int mtp_link_slta(struct mtp_link *link, uint16_t l3_len,
struct mtp_level_3_mng *mng)
{
if (mng->length != 14) {
LOGP(DINP, LOGL_ERROR, "Wrongly sized SLTA: %u\n", mng->length);
return -1;
}
if (l3_len != 16) {
LOGP(DINP, LOGL_ERROR, "Wrongly sized SLTA: %u\n", mng->length);
return -1;
}
if (memcmp(mng->data, link->test_ptrn, sizeof(link->test_ptrn)) != 0) {
LOGP(DINP, LOGL_ERROR, "Wrong test pattern SLTA\n");
return -1;
}
/* we had a matching slta */
bsc_del_timer(&link->t1_timer);
link->sltm_pending = 0;
link->was_up = 1;
return 0;
}