diff options
-rw-r--r-- | include/sctp_m2ua.h | 11 | ||||
-rw-r--r-- | src/sctp_m2ua.c | 122 |
2 files changed, 97 insertions, 36 deletions
diff --git a/include/sctp_m2ua.h b/include/sctp_m2ua.h index 9f4d5c7..99af46e 100644 --- a/include/sctp_m2ua.h +++ b/include/sctp_m2ua.h @@ -44,6 +44,15 @@ struct sctp_m2ua_transport { struct mtp_m2ua_link { struct mtp_link *base; + /* + * The state of the link, who is using it and + * what will happen to it. For load-sharing we + * will need to turn this into a list. + */ + int asp_active; + int established; + struct sctp_m2ua_conn *conn; + int link_index; struct llist_head entry; struct sctp_m2ua_transport *transport; @@ -56,8 +65,6 @@ struct sctp_m2ua_conn { struct llist_head entry; uint8_t asp_ident[4]; int asp_up; - int asp_active; - int established; struct write_queue queue; struct sctp_m2ua_transport *trans; diff --git a/src/sctp_m2ua.c b/src/sctp_m2ua.c index 26d6be0..89bfb70 100644 --- a/src/sctp_m2ua.c +++ b/src/sctp_m2ua.c @@ -58,10 +58,17 @@ static void m2ua_conn_destroy(struct sctp_m2ua_conn *conn) write_queue_clear(&conn->queue); llist_del(&conn->entry); - /* 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); + llist_for_each_entry(link, &conn->trans->links, entry) { + if (link->conn != conn) + continue; + + if (link->established) + link_down(link->base); + link->established = 0; + link->asp_active = 0; + link->conn = NULL; + } + talloc_free(conn); #warning "Notify any other AS(P) for failover scenario" @@ -108,7 +115,7 @@ static int m2ua_conn_send_ntfy(struct mtp_m2ua_link *link, /* state change */ state[0] = ntohs(M2UA_STP_AS_STATE_CHG); - if (conn->asp_active) + if (link->asp_active) state[1] = ntohs(M2UA_STP_AS_ACTIVE); else state[1] = ntohs(M2UA_STP_AS_INACTIVE); @@ -179,14 +186,13 @@ static int m2ua_handle_asp(struct sctp_m2ua_conn *conn, return 0; } -static int m2ua_handle_asptm_act(struct mtp_m2ua_link *link, - struct sctp_m2ua_conn *conn, +static int m2ua_handle_asptm_act(struct sctp_m2ua_conn *conn, struct m2ua_msg *m2ua, struct sctp_sndrcvinfo *info) { + struct m2ua_msg_part *part; struct m2ua_msg *ack; - /* TODO: parse the interface identifiers. This is plural */ ack = m2ua_msg_alloc(); if (!ack) return -1; @@ -194,30 +200,67 @@ static int m2ua_handle_asptm_act(struct mtp_m2ua_link *link, ack->hdr.msg_class = M2UA_CLS_ASPTM; ack->hdr.msg_type = M2UA_ASPTM_ACTIV_ACK; + /* + * Move things over to this connection now. + */ + llist_for_each_entry(part, &m2ua->headers, entry) { + struct mtp_m2ua_link *link; + uint32_t interf; + + + if (part->tag != MUA_TAG_IDENT_INT) + continue; + if (part->len != 4) + continue; + + memcpy(&interf, part->dat, 4); + link = find_m2ua_link(conn->trans, ntohl(interf)); + if (!link) { + LOGP(DINP, LOGL_ERROR, + "M2UA Link index %d is not configured.\n", ntohl(interf)); + continue; + } + + link->conn = conn; + link->asp_active = 1; + m2ua_msg_add_data(ack, MUA_TAG_IDENT_INT, 4, (uint8_t *) &interf); + } + + if (m2ua_conn_send(conn, ack, info) != 0) { m2ua_msg_free(ack); return -1; } - conn->asp_active = 1; - m2ua_conn_send_ntfy(link, conn, info); + /* now again send NTFY on all these links */ + llist_for_each_entry(part, &m2ua->headers, entry) { + struct mtp_m2ua_link *link; + uint32_t interf; + + + if (part->tag != MUA_TAG_IDENT_INT) + continue; + if (part->len != 4) + continue; + + memcpy(&interf, part->dat, 4); + link = find_m2ua_link(conn->trans, ntohl(interf)); + if (!link) + continue; + m2ua_conn_send_ntfy(link, conn, info); + } + m2ua_msg_free(ack); return 0; } -static int m2ua_handle_asptm(struct mtp_m2ua_link *link, - struct sctp_m2ua_conn *conn, +static int m2ua_handle_asptm(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(link, conn, m2ua, info); + m2ua_handle_asptm_act(conn, m2ua, info); break; default: LOGP(DINP, LOGL_ERROR, "Unhandled msg_type %d\n", @@ -237,6 +280,13 @@ static int m2ua_handle_state_req(struct mtp_m2ua_link *link, struct m2ua_msg *conf; int req; + if (link->conn != conn) { + LOGP(DINP, LOGL_ERROR, + "Someone forgot the ASP Activate on link-index %d\n", + link->link_index); + return -1; + } + state = m2ua_msg_find_tag(m2ua, M2UA_TAG_STATE_REQ); if (!state || state->len != 4) { LOGP(DINP, LOGL_ERROR, "Mandantory state request not present.\n"); @@ -285,11 +335,12 @@ static int m2ua_handle_est_req(struct mtp_m2ua_link *link, conf->hdr.msg_type = M2UA_MAUP_EST_CON; if (m2ua_conn_send(conn, conf, info) != 0) { + link->established = 0; m2ua_msg_free(conf); return -1; } - conn->established = 1; + link->established = 1; LOGP(DINP, LOGL_NOTICE, "M2UA/Link is established.\n"); mtp_link_up(link->base); m2ua_msg_free(conf); @@ -315,7 +366,7 @@ static int m2ua_handle_rel_req(struct mtp_m2ua_link *link, return -1; } - conn->established = 0; + link->established = 0; LOGP(DINP, LOGL_NOTICE, "M2UA/Link is released.\n"); link_down(link->base); m2ua_msg_free(conf); @@ -371,6 +422,13 @@ static int m2ua_handle_maup(struct mtp_m2ua_link *link, return -1; } + if (link->conn != conn) { + LOGP(DINP, LOGL_ERROR, + "Someone forgot the ASP Activate on link-index %d\n", + link->link_index); + return -1; + } + switch (m2ua->hdr.msg_type) { case M2UA_MAUP_STATE_REQ: m2ua_handle_state_req(link, conn, m2ua, info); @@ -442,7 +500,7 @@ static int m2ua_conn_handle(struct sctp_m2ua_conn *conn, m2ua_handle_asp(conn, m2ua, info); break; case M2UA_CLS_ASPTM: - m2ua_handle_asptm(link, conn, m2ua, info); + m2ua_handle_asptm(conn, m2ua, info); break; case M2UA_CLS_MAUP: m2ua_handle_maup(link, conn, m2ua, info); @@ -493,26 +551,22 @@ 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 *mlink; - struct sctp_m2ua_transport *trans; - struct sctp_m2ua_conn *conn = NULL, *tmp; struct sctp_sndrcvinfo info; struct m2ua_msg *m2ua; uint32_t interface; mlink = (struct mtp_m2ua_link *) link->data; - trans = mlink->transport; - if (llist_empty(&trans->conns)) - goto clean; - llist_for_each_entry(tmp, &trans->conns, entry) - if (tmp->established && tmp->asp_active && tmp->asp_up) { - conn = tmp; - break; - } + if (!mlink->conn) { + LOGP(DINP, LOGL_ERROR, "M2UA write with no ASP for %d/%s of %d/%s.\n", + link->nr, link->name, link->set->nr, link->set->name); + goto clean; + } - if (!conn) { - LOGP(DINP, LOGL_ERROR, "No active ASP?\n"); + if (!mlink->asp_active || !mlink->established) { + LOGP(DINP, LOGL_ERROR, "ASP not ready for %d/%s of %d/%s.\n", + link->nr, link->name, link->set->nr, link->set->name); goto clean; } @@ -534,7 +588,7 @@ static int sctp_m2ua_write(struct mtp_link *link, struct msgb *msg) info.sinfo_assoc_id = 1; info.sinfo_ppid = htonl(2); - m2ua_conn_send(conn, m2ua, &info); + m2ua_conn_send(mlink->conn, m2ua, &info); m2ua_msg_free(m2ua); clean: |