aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/bsc_data.h4
-rw-r--r--include/sctp_m2ua.h19
-rw-r--r--src/main_stp.c8
-rw-r--r--src/sctp_m2ua.c171
4 files changed, 141 insertions, 61 deletions
diff --git a/include/bsc_data.h b/include/bsc_data.h
index df62493..6fb5b26 100644
--- a/include/bsc_data.h
+++ b/include/bsc_data.h
@@ -39,6 +39,7 @@
struct bsc_data;
struct snmp_mtp_session;
+struct mtp_m2ua_transport;
/**
* Struct holding the BSC to MSC forwarding state.
@@ -155,6 +156,9 @@ struct bsc_data {
/* MSC related data... currently only one is supported */
struct bsc_msc_forward msc_forward;
+
+ /* m2ua code */
+ struct sctp_m2ua_transport *m2ua_trans;
};
/* bsc related functions */
diff --git a/include/sctp_m2ua.h b/include/sctp_m2ua.h
index 2627d7d..dcb6269 100644
--- a/include/sctp_m2ua.h
+++ b/include/sctp_m2ua.h
@@ -33,12 +33,20 @@ struct mtp_link;
* Drive M2UA over a SCTP link. Right now we have no
* real concept for failover and such for the link.
*/
-struct mtp_m2ua_link {
- struct mtp_link base;
-
+struct sctp_m2ua_transport {
int started;
struct llist_head conns;
struct bsc_fd bsc;
+
+ struct llist_head links;
+};
+
+struct mtp_m2ua_link {
+ struct mtp_link base;
+
+ int link_index;
+ struct llist_head entry;
+ struct sctp_m2ua_transport *transport;
};
/*
@@ -52,9 +60,10 @@ struct sctp_m2ua_conn {
int established;
struct write_queue queue;
- struct mtp_m2ua_link *trans;
+ struct sctp_m2ua_transport *trans;
};
-struct mtp_m2ua_link *sctp_m2ua_transp_create(const char *ip, int port);
+struct sctp_m2ua_transport *sctp_m2ua_transp_create(const char *ip, int port);
+struct mtp_m2ua_link *mtp_m2ua_link_create(struct mtp_link_set *);
#endif
diff --git a/src/main_stp.c b/src/main_stp.c
index a26823d..203ce12 100644
--- a/src/main_stp.c
+++ b/src/main_stp.c
@@ -356,6 +356,12 @@ int main(int argc, char **argv)
if (!set)
return -1;
+ bsc->m2ua_trans = sctp_m2ua_transp_create("0.0.0.0", 2904);
+ if (!bsc->m2ua_trans) {
+ LOGP(DINP, LOGL_ERROR, "Failed to create SCTP transport.\n");
+ return -1;
+ }
+
m2ua_set = mtp_link_set_alloc(bsc);
m2ua_set->dpc = 92;
m2ua_set->opc = 9;
@@ -372,7 +378,7 @@ int main(int argc, char **argv)
m2ua_set->pass_all_isup = bsc->isup_pass;
m2ua_set->forward = set;
- lnk = sctp_m2ua_transp_create("0.0.0.0", 2904);
+ lnk = mtp_m2ua_link_create(m2ua_set);
lnk->base.pcap_fd = -1;
mtp_link_set_add_link(m2ua_set, (struct mtp_link *) lnk);
diff --git a/src/sctp_m2ua.c b/src/sctp_m2ua.c
index 2b8ac07..0e0c083 100644
--- a/src/sctp_m2ua.c
+++ b/src/sctp_m2ua.c
@@ -30,6 +30,19 @@
#include <string.h>
#include <unistd.h>
+static struct mtp_m2ua_link *find_m2ua_link(struct sctp_m2ua_transport *trans, int link_index)
+{
+ struct mtp_m2ua_link *link;
+ link_index = link_index;
+
+ llist_for_each_entry(link, &trans->links, entry) {
+ if (link->link_index == link_index)
+ return link;
+ }
+
+ return NULL;
+}
+
static void link_down(struct mtp_link *link)
{
rate_ctr_inc(&link->ctrg->ctr[MTP_LNK_ERROR]);
@@ -38,13 +51,17 @@ static void link_down(struct mtp_link *link)
static void m2ua_conn_destroy(struct sctp_m2ua_conn *conn)
{
+ struct mtp_m2ua_link *link;
+
close(conn->queue.bfd.fd);
bsc_unregister_fd(&conn->queue.bfd);
write_queue_clear(&conn->queue);
llist_del(&conn->entry);
- if (conn->asp_up && conn->asp_active && conn->established)
- link_down(&conn->trans->base);
+ /* TODO: hardcoded link index */
+ link = find_m2ua_link(conn->trans, 0);
+ if (link && conn->asp_up && conn->asp_active && conn->established)
+ link_down(&link->base);
talloc_free(conn);
#warning "Notify any other AS(P) for failover scenario"
@@ -73,7 +90,8 @@ static int m2ua_conn_send(struct sctp_m2ua_conn *conn,
return 0;
}
-static int m2ua_conn_send_ntfy(struct sctp_m2ua_conn *conn,
+static int m2ua_conn_send_ntfy(struct mtp_m2ua_link *link,
+ struct sctp_m2ua_conn *conn,
struct sctp_sndrcvinfo *info)
{
struct m2ua_msg *msg;
@@ -94,6 +112,8 @@ static int m2ua_conn_send_ntfy(struct sctp_m2ua_conn *conn,
else
state[1] = ntohs(M2UA_STP_AS_INACTIVE);
+ /* TODO: embed the interface identifier */
+
m2ua_msg_add_data(msg, MUA_TAG_STATUS, 4, (uint8_t *) state);
m2ua_msg_add_data(msg, MUA_TAG_ASP_IDENT, 4, conn->asp_ident);
rc = m2ua_conn_send(conn, msg, info);
@@ -136,7 +156,6 @@ static int m2ua_handle_asp_ack(struct sctp_m2ua_conn *conn,
memcpy(conn->asp_ident, asp_ident->dat, 4);
conn->asp_up = 1;
- m2ua_conn_send_ntfy(conn, info);
m2ua_msg_free(ack);
return 0;
}
@@ -157,7 +176,8 @@ static int m2ua_handle_asp(struct sctp_m2ua_conn *conn,
return 0;
}
-static int m2ua_handle_asptm_act(struct sctp_m2ua_conn *conn,
+static int m2ua_handle_asptm_act(struct mtp_m2ua_link *link,
+ struct sctp_m2ua_conn *conn,
struct m2ua_msg *m2ua,
struct sctp_sndrcvinfo *info)
{
@@ -177,18 +197,24 @@ static int m2ua_handle_asptm_act(struct sctp_m2ua_conn *conn,
}
conn->asp_active = 1;
- m2ua_conn_send_ntfy(conn, info);
+ m2ua_conn_send_ntfy(link, conn, info);
m2ua_msg_free(ack);
return 0;
}
-static int m2ua_handle_asptm(struct sctp_m2ua_conn *conn,
+static int m2ua_handle_asptm(struct mtp_m2ua_link *link,
+ struct sctp_m2ua_conn *conn,
struct m2ua_msg *m2ua,
struct sctp_sndrcvinfo *info)
{
+ if (!link) {
+ LOGP(DINP, LOGL_ERROR, "Link is required.\n");
+ return -1;
+ }
+
switch (m2ua->hdr.msg_type) {
case M2UA_ASPTM_ACTIV:
- m2ua_handle_asptm_act(conn, m2ua, info);
+ m2ua_handle_asptm_act(link, conn, m2ua, info);
break;
default:
LOGP(DINP, LOGL_ERROR, "Unhandled msg_type %d\n",
@@ -199,13 +225,14 @@ static int m2ua_handle_asptm(struct sctp_m2ua_conn *conn,
return 0;
}
-static int m2ua_handle_state_req(struct sctp_m2ua_conn *conn,
+static int m2ua_handle_state_req(struct mtp_m2ua_link *link,
+ struct sctp_m2ua_conn *conn,
struct m2ua_msg *m2ua,
struct sctp_sndrcvinfo *info)
{
- struct m2ua_msg_part *ident, *state;
+ struct m2ua_msg_part *state;
struct m2ua_msg *conf;
- int interface = 0, req;
+ int req;
state = m2ua_msg_find_tag(m2ua, M2UA_TAG_STATE_REQ);
if (!state || state->len != 4) {
@@ -213,12 +240,6 @@ static int m2ua_handle_state_req(struct sctp_m2ua_conn *conn,
return -1;
}
- ident = m2ua_msg_find_tag(m2ua, MUA_TAG_IDENT_INT);
- if (ident && ident->len == 4) {
- memcpy(&interface, ident->dat, 4);
- interface = ntohl(interface);
- }
-
memcpy(&req, state->dat, 4);
req = ntohl(req);
@@ -230,7 +251,7 @@ static int m2ua_handle_state_req(struct sctp_m2ua_conn *conn,
conf->hdr.msg_class = M2UA_CLS_MAUP;
conf->hdr.msg_type = M2UA_MAUP_STATE_CON;
- m2ua_msg_add_data(conf, MUA_TAG_IDENT_INT, 4, (uint8_t *) &interface);
+ m2ua_msg_add_data(conf, MUA_TAG_IDENT_INT, 4, (uint8_t *) &link->link_index);
m2ua_msg_add_data(conf, M2UA_TAG_STATE_REQ, 4, (uint8_t *) &req);
if (m2ua_conn_send(conn, conf, info) != 0) {
m2ua_msg_free(conf);
@@ -246,7 +267,8 @@ static int m2ua_handle_state_req(struct sctp_m2ua_conn *conn,
return 0;
}
-static int m2ua_handle_est_req(struct sctp_m2ua_conn *conn,
+static int m2ua_handle_est_req(struct mtp_m2ua_link *link,
+ struct sctp_m2ua_conn *conn,
struct m2ua_msg *m2ua,
struct sctp_sndrcvinfo *info)
{
@@ -266,12 +288,13 @@ static int m2ua_handle_est_req(struct sctp_m2ua_conn *conn,
conn->established = 1;
LOGP(DINP, LOGL_NOTICE, "M2UA/Link is established.\n");
- mtp_link_up(&conn->trans->base);
+ mtp_link_up(&link->base);
m2ua_msg_free(conf);
return 0;
}
-static int m2ua_handle_rel_req(struct sctp_m2ua_conn *conn,
+static int m2ua_handle_rel_req(struct mtp_m2ua_link *link,
+ struct sctp_m2ua_conn *conn,
struct m2ua_msg *m2ua,
struct sctp_sndrcvinfo *info)
{
@@ -291,12 +314,13 @@ static int m2ua_handle_rel_req(struct sctp_m2ua_conn *conn,
conn->established = 0;
LOGP(DINP, LOGL_NOTICE, "M2UA/Link is released.\n");
- link_down(&conn->trans->base);
+ link_down(&link->base);
m2ua_msg_free(conf);
return 0;
}
-static int m2ua_handle_data(struct sctp_m2ua_conn *conn,
+static int m2ua_handle_data(struct mtp_m2ua_link *_link,
+ struct sctp_m2ua_conn *conn,
struct m2ua_msg *m2ua,
struct sctp_sndrcvinfo *info)
{
@@ -324,7 +348,7 @@ static int m2ua_handle_data(struct sctp_m2ua_conn *conn,
msg->l2h = msgb_put(msg, data->len);
memcpy(msg->l2h, data->dat, data->len);
- link = &conn->trans->base;
+ link = &_link->base;
if (!link->blocked) {
mtp_handle_pcap(link, NET_IN, msg->l2h, msgb_l2len(msg));
mtp_link_set_data(link, msg);
@@ -334,22 +358,28 @@ static int m2ua_handle_data(struct sctp_m2ua_conn *conn,
return 0;
}
-static int m2ua_handle_maup(struct sctp_m2ua_conn *conn,
+static int m2ua_handle_maup(struct mtp_m2ua_link *link,
+ struct sctp_m2ua_conn *conn,
struct m2ua_msg *m2ua,
struct sctp_sndrcvinfo *info)
{
+ if (!link) {
+ LOGP(DINP, LOGL_ERROR, "Link is required.\n");
+ return -1;
+ }
+
switch (m2ua->hdr.msg_type) {
case M2UA_MAUP_STATE_REQ:
- m2ua_handle_state_req(conn, m2ua, info);
+ m2ua_handle_state_req(link, conn, m2ua, info);
break;
case M2UA_MAUP_EST_REQ:
- m2ua_handle_est_req(conn, m2ua, info);
+ m2ua_handle_est_req(link, conn, m2ua, info);
break;
case M2UA_MAUP_REL_REQ:
- m2ua_handle_rel_req(conn, m2ua, info);
+ m2ua_handle_rel_req(link, conn, m2ua, info);
break;
case M2UA_MAUP_DATA:
- m2ua_handle_data(conn, m2ua, info);
+ m2ua_handle_data(link, conn, m2ua, info);
break;
default:
LOGP(DINP, LOGL_ERROR, "Unhandled msg_type %d\n",
@@ -375,9 +405,23 @@ static int m2ua_handle_mgmt(struct sctp_m2ua_conn *conn,
return 0;
}
+static int m2ua_find_interface(struct m2ua_msg *m2ua, int def)
+{
+ struct m2ua_msg_part *ident;
+
+ ident = m2ua_msg_find_tag(m2ua, MUA_TAG_IDENT_INT);
+ if (ident && ident->len == 4) {
+ memcpy(&def, ident->dat, 4);
+ def = ntohl(def);
+ }
+
+ return def;
+}
+
static int m2ua_conn_handle(struct sctp_m2ua_conn *conn,
struct msgb *msg, struct sctp_sndrcvinfo *info)
{
+ struct mtp_m2ua_link *link;
struct m2ua_msg *m2ua;
m2ua = m2ua_from_msg(msg->len, msg->data);
if (!m2ua) {
@@ -385,6 +429,8 @@ static int m2ua_conn_handle(struct sctp_m2ua_conn *conn,
return -1;
}
+ link = find_m2ua_link(conn->trans, m2ua_find_interface(m2ua, 0));
+
switch (m2ua->hdr.msg_class) {
case M2UA_CLS_MGMT:
m2ua_handle_mgmt(conn, m2ua, info);
@@ -393,10 +439,10 @@ static int m2ua_conn_handle(struct sctp_m2ua_conn *conn,
m2ua_handle_asp(conn, m2ua, info);
break;
case M2UA_CLS_ASPTM:
- m2ua_handle_asptm(conn, m2ua, info);
+ m2ua_handle_asptm(link, conn, m2ua, info);
break;
case M2UA_CLS_MAUP:
- m2ua_handle_maup(conn, m2ua, info);
+ m2ua_handle_maup(link, conn, m2ua, info);
break;
default:
LOGP(DINP, LOGL_ERROR, "Unhandled msg_class %d\n",
@@ -443,13 +489,15 @@ static int m2ua_conn_read(struct bsc_fd *fd)
static int sctp_m2ua_write(struct mtp_link *link, struct msgb *msg)
{
- struct mtp_m2ua_link *trans;
+ struct mtp_m2ua_link *mlink;
+ struct sctp_m2ua_transport *trans;
struct sctp_m2ua_conn *conn = NULL, *tmp;
struct sctp_sndrcvinfo info;
struct m2ua_msg *m2ua;
uint32_t interface;
- trans = (struct mtp_m2ua_link *) link;
+ mlink = (struct mtp_m2ua_link *) link;
+ trans = mlink->transport;
if (llist_empty(&trans->conns))
goto clean;
@@ -509,7 +557,7 @@ static int m2ua_conn_write(struct bsc_fd *fd, struct msgb *msg)
static int sctp_trans_accept(struct bsc_fd *fd, unsigned int what)
{
struct sctp_event_subscribe events;
- struct mtp_m2ua_link *trans;
+ struct sctp_m2ua_transport *trans;
struct sctp_m2ua_conn *conn;
struct sockaddr_in addr;
socklen_t len;
@@ -529,12 +577,6 @@ 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) {
@@ -572,30 +614,31 @@ static int sctp_m2ua_dummy(struct mtp_link *link)
return 0;
}
-static int sctp_m2ua_start(struct mtp_link *link)
+static int sctp_m2ua_start(struct mtp_link *_link)
{
- struct mtp_m2ua_link *trans = (struct mtp_m2ua_link *) link;
+ struct mtp_m2ua_link *link = (struct mtp_m2ua_link *) _link;
- trans->started = 1;
+ link->transport->started = 1;
return 0;
}
-static int sctp_m2ua_reset(struct mtp_link *link)
+static int sctp_m2ua_reset(struct mtp_link *_link)
{
struct sctp_m2ua_conn *conn, *tmp;
- struct mtp_m2ua_link *transp = (struct mtp_m2ua_link *) link;
+ struct mtp_m2ua_link *link = (struct mtp_m2ua_link *) _link;
- llist_for_each_entry_safe(conn, tmp, &transp->conns, entry)
+ /* TODO: only connection that use the current link index! */
+ llist_for_each_entry_safe(conn, tmp, &link->transport->conns, entry)
m2ua_conn_destroy(conn);
return 0;
}
-struct mtp_m2ua_link *sctp_m2ua_transp_create(const char *ip, int port)
+struct sctp_m2ua_transport *sctp_m2ua_transp_create(const char *ip, int port)
{
int sctp;
struct sockaddr_in addr;
- struct mtp_m2ua_link *trans;
+ struct sctp_m2ua_transport *trans;
sctp = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
if (!sctp) {
@@ -623,19 +666,13 @@ struct mtp_m2ua_link *sctp_m2ua_transp_create(const char *ip, int port)
int on = 1;
setsockopt(sctp, SOL_SCTP, 112, &on, sizeof(on));
- trans = talloc_zero(NULL, struct mtp_m2ua_link);
+ trans = talloc_zero(NULL, struct sctp_m2ua_transport);
if (!trans) {
LOGP(DINP, LOGL_ERROR, "Remove the talloc.\n");
close(sctp);
return NULL;
}
- 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;
- trans->base.write = sctp_m2ua_write;
-
trans->bsc.fd = sctp;
trans->bsc.data = trans;
trans->bsc.cb = sctp_trans_accept;
@@ -649,6 +686,30 @@ struct mtp_m2ua_link *sctp_m2ua_transp_create(const char *ip, int port)
}
INIT_LLIST_HEAD(&trans->conns);
+ INIT_LLIST_HEAD(&trans->links);
+
return trans;
}
+struct mtp_m2ua_link *mtp_m2ua_link_create(struct mtp_link_set *set)
+{
+ struct mtp_m2ua_link *lnk;
+
+ lnk = talloc_zero(set, struct mtp_m2ua_link);
+ if (!lnk) {
+ LOGP(DINP, LOGL_ERROR, "Failed to allocate.\n");
+ return NULL;
+ }
+
+ /* remember we have a link here */
+ llist_add(&lnk->entry, &set->bsc->m2ua_trans->links);
+
+ lnk->base.shutdown = sctp_m2ua_reset;
+ lnk->base.clear_queue = sctp_m2ua_dummy;
+ lnk->base.reset = sctp_m2ua_reset;
+ lnk->base.start = sctp_m2ua_start;
+ lnk->base.write = sctp_m2ua_write;
+
+ lnk->transport = set->bsc->m2ua_trans;
+ return lnk;
+}