aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2011-01-23 23:31:26 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2011-01-24 15:35:08 +0100
commitea5ce23d72cbb6571862a4356ca21890aae5ecc9 (patch)
treef21942c09ed14873540e8b96d3e551fa08e50d36
parent8ade9b7bc235b644a1ce63ba0db9e855b118d267 (diff)
mtp: Make it possible to block a link.
The semantic of a block is to take the physical link down, call mtp_link_down and to make sure that the link remains down and no packets are forwarded there. The unblock call will reset the link and this should get it back into operation again.
-rw-r--r--include/mtp_data.h5
-rw-r--r--src/link_udp.c26
-rw-r--r--src/mtp_link.c14
-rw-r--r--src/sctp_m2ua.c14
4 files changed, 49 insertions, 10 deletions
diff --git a/include/mtp_data.h b/include/mtp_data.h
index b991f46..1d93f20 100644
--- a/include/mtp_data.h
+++ b/include/mtp_data.h
@@ -90,6 +90,8 @@ struct mtp_link {
/* link test routine */
uint8_t test_ptrn[14];
+ int blocked;
+
int link_no;
int sltm_pending;
int was_up;
@@ -120,6 +122,9 @@ int mtp_link_set_submit_isup_data(struct mtp_link_set *link, int sls, const uint
void mtp_link_set_init_slc(struct mtp_link_set *set);
int mtp_link_set_add_link(struct mtp_link_set *set, struct mtp_link *link);
+void mtp_link_block(struct mtp_link *link);
+void mtp_link_unblock(struct mtp_link *link);
+
/* one time init function */
void mtp_link_set_init(void);
diff --git a/src/link_udp.c b/src/link_udp.c
index 1e24faf..2dfc34b 100644
--- a/src/link_udp.c
+++ b/src/link_udp.c
@@ -107,6 +107,11 @@ static int udp_read_cb(struct bsc_fd *fd)
goto exit;
}
+ if (link->blocked) {
+ LOGP(DINP, LOGL_ERROR, "The link is blocked.\n");
+ rc = 0;
+ goto exit;
+ }
/* throw away data as the link is down */
if (link->set->available == 0) {
@@ -167,6 +172,11 @@ static int udp_link_reset(struct mtp_link *link)
return 0;
}
+static int udp_link_shutdown(struct mtp_link *link)
+{
+ return udp_link_reset(link);
+}
+
static int udp_link_write(struct mtp_link *link, struct msgb *msg)
{
struct mtp_udp_link *ulnk;
@@ -202,7 +212,7 @@ static int udp_link_start(struct mtp_link *link)
int link_udp_init(struct mtp_udp_link *link, const char *remote, int port)
{
/* function table */
- link->base.shutdown = udp_link_dummy;
+ link->base.shutdown = udp_link_shutdown;
link->base.clear_queue = udp_link_dummy;
link->base.reset = udp_link_reset;
@@ -296,7 +306,7 @@ void snmp_mtp_callback(struct snmp_mtp_session *session,
link = &ulink->base;
- if (res == SNMP_STATUS_TIMEOUT) {
+ if (res == SNMP_STATUS_TIMEOUT && !link->blocked) {
LOGP(DINP, LOGL_ERROR, "Failed to restart link: %d\n", link_id);
udp_link_reset(link);
return;
@@ -313,11 +323,13 @@ void snmp_mtp_callback(struct snmp_mtp_session *session,
* restart the link in 90 seconds...
* to force a timeout on the BSC
*/
- link->link_activate.cb = do_start;
- link->link_activate.data = link;
- bsc_schedule_timer(&link->link_activate, ulink->reset_timeout, 0);
- LOGP(DINP, LOGL_NOTICE,
- "Will restart SLTM transmission in %d seconds.\n", ulink->reset_timeout);
+ if (!link->blocked) {
+ link->link_activate.cb = do_start;
+ link->link_activate.data = link;
+ bsc_schedule_timer(&link->link_activate, ulink->reset_timeout, 0);
+ LOGP(DINP, LOGL_NOTICE,
+ "Will restart SLTM transmission in %d seconds.\n", ulink->reset_timeout);
+ }
break;
default:
LOGP(DINP, LOGL_ERROR, "Unknown event %d\n", area);
diff --git a/src/mtp_link.c b/src/mtp_link.c
index d885738..8a55aae 100644
--- a/src/mtp_link.c
+++ b/src/mtp_link.c
@@ -167,3 +167,17 @@ void mtp_link_failure(struct mtp_link *link)
rate_ctr_inc(&link->ctrg->ctr[MTP_LNK_ERROR]);
link->reset(link);
}
+
+void mtp_link_block(struct mtp_link *link)
+{
+ link->blocked = 1;
+ link->shutdown(link);
+}
+
+void mtp_link_unblock(struct mtp_link *link)
+{
+ if (!link->blocked)
+ return;
+ link->blocked = 0;
+ link->reset(link);
+}
diff --git a/src/sctp_m2ua.c b/src/sctp_m2ua.c
index 65fde0b..d0e88da 100644
--- a/src/sctp_m2ua.c
+++ b/src/sctp_m2ua.c
@@ -327,8 +327,10 @@ static int m2ua_handle_data(struct sctp_m2ua_conn *conn,
memcpy(msg->l2h, data->dat, data->len);
link = &conn->trans->base;
- mtp_handle_pcap(link, NET_IN, msg->l2h, msgb_l2len(msg));
- mtp_link_set_data(link, msg);
+ if (!link->blocked) {
+ mtp_handle_pcap(link, NET_IN, msg->l2h, msgb_l2len(msg));
+ mtp_link_set_data(link, msg);
+ }
msgb_free(msg);
return 0;
@@ -526,6 +528,12 @@ static int sctp_trans_accept(struct bsc_fd *fd, unsigned int what)
return -1;
}
+ if (!trans->base.blocked) {
+ LOGP(DINP, LOGL_NOTICE, "The link is blocked.\n");
+ close(s);
+ return -1;
+ }
+
LOGP(DINP, LOGL_NOTICE, "Got a new SCTP connection.\n");
conn = talloc_zero(fd->data, struct sctp_m2ua_conn);
if (!conn) {
@@ -621,7 +629,7 @@ struct mtp_m2ua_link *sctp_m2ua_transp_create(const char *ip, int port)
return NULL;
}
- trans->base.shutdown = sctp_m2ua_dummy;
+ trans->base.shutdown = sctp_m2ua_reset;
trans->base.clear_queue = sctp_m2ua_dummy;
trans->base.reset = sctp_m2ua_reset;
trans->base.start = sctp_m2ua_start;