Neels Hofmeyr | c4628a3 | 2018-12-07 14:47:34 +0100 | [diff] [blame] | 1 | #pragma once |
| 2 | |
| 3 | #include <osmocom/core/linuxlist.h> |
| 4 | #include <osmocom/gsm/gsm0808.h> |
| 5 | #include <osmocom/sigtran/sccp_sap.h> |
| 6 | |
| 7 | #include <osmocom/msc/debug.h> |
| 8 | #include <osmocom/msc/paging.h> |
| 9 | |
| 10 | struct vlr_subscr; |
| 11 | struct ran_conn; |
| 12 | struct neighbor_ident_entry; |
| 13 | |
| 14 | #define LOG_RAN_PEER_CAT(RAN_PEER, subsys, loglevel, fmt, args ...) \ |
| 15 | LOGPFSMSL((RAN_PEER)? (RAN_PEER)->fi : NULL, subsys, loglevel, fmt, ## args) |
| 16 | |
| 17 | #define LOG_RAN_PEER(RAN_PEER, loglevel, fmt, args ...) \ |
| 18 | LOG_RAN_PEER_CAT(RAN_PEER, \ |
| 19 | (RAN_PEER) && (RAN_PEER)->sri? (RAN_PEER)->sri->ran->log_subsys : DMSC, \ |
| 20 | loglevel, fmt, ## args) |
| 21 | |
| 22 | /* A BSC or RNC with activity on a local SCCP connection. |
| 23 | * Here we collect those BSC and RNC peers that are actually connected to the MSC and manage their connection Reset |
| 24 | * status. |
| 25 | * |
| 26 | * Before we had explicit neighbor configuration for inter-BSC and inter-MSC handover, the only way to know which peer |
| 27 | * address corresponds to which LAC (for paging a specific LAC) was to collect the LAC from L3 messages coming in on a |
| 28 | * subscriber connection. We still continue that practice to support unconfigured operation. |
| 29 | * |
| 30 | * The neighbor list config extends this by possibly naming LAC and CI that have not seen explicit activity yet, and |
| 31 | * allows us to page towards the correct peer's SCCP address from the start. |
| 32 | * |
| 33 | * So, for paging, the idea is to look for a LAC that is recorded here, and if not found, query the neighbor |
| 34 | * configuration for a peer's SCCP address matching that LAC. If found, look for active connections on that SCCP address |
| 35 | * here. |
| 36 | * |
| 37 | * Any valid RAN peer will contact us and initiate a RESET procedure. In turn, on osmo-msc start, we may choose to |
| 38 | * initiate a RESET procedure towards every known RAN peer. |
| 39 | * |
| 40 | * Semantically, it would make sense to keep the list of ran_conn instances in each struct ran_peer, but since |
| 41 | * non-Initial Connection-Oriented messages indicate only the conn by id (and identify the ran_peer from that), the conn |
| 42 | * list is kept in sccp_ran_inst. For convenience, see ran_peer_for_each_ran_conn(). |
| 43 | */ |
| 44 | struct ran_peer { |
| 45 | /* Entry in sccp_ran_inst->ran_conns */ |
| 46 | struct llist_head entry; |
| 47 | |
| 48 | struct sccp_ran_inst *sri; |
| 49 | struct osmo_sccp_addr peer_addr; |
| 50 | struct osmo_fsm_inst *fi; |
| 51 | |
| 52 | /* See cell_id_list.h */ |
| 53 | struct llist_head cells_seen; |
Pau Espin Pedrol | f9f38b5 | 2019-05-07 11:48:16 +0200 | [diff] [blame] | 54 | |
| 55 | /* Whether we detected the BSC supports Osmux (during BSSMAP_RESET) */ |
| 56 | bool remote_supports_osmux; |
Neels Hofmeyr | c4628a3 | 2018-12-07 14:47:34 +0100 | [diff] [blame] | 57 | }; |
| 58 | |
| 59 | #define ran_peer_for_each_ran_conn(RAN_CONN, RAN_PEER) \ |
| 60 | llist_for_each_entry(RAN_CONN, &(RAN_PEER)->sri->ran_conns, entry) \ |
| 61 | if ((RAN_CONN)->ran_peer == (RAN_PEER)) |
| 62 | |
| 63 | #define ran_peer_for_each_ran_conn_safe(RAN_CONN, RAN_CONN_NEXT, RAN_PEER) \ |
| 64 | llist_for_each_entry_safe(RAN_CONN, RAN_CONN_NEXT, &(RAN_PEER)->sri->ran_conns, entry) \ |
| 65 | if ((RAN_CONN)->ran_peer == (RAN_PEER)) |
| 66 | |
| 67 | enum ran_peer_state { |
| 68 | RAN_PEER_ST_WAIT_RX_RESET = 0, |
| 69 | RAN_PEER_ST_WAIT_RX_RESET_ACK, |
| 70 | RAN_PEER_ST_READY, |
| 71 | RAN_PEER_ST_DISCARDING, |
| 72 | }; |
| 73 | |
| 74 | enum ran_peer_event { |
| 75 | RAN_PEER_EV_MSG_UP_CL = 0, |
| 76 | RAN_PEER_EV_MSG_UP_CO_INITIAL, |
| 77 | RAN_PEER_EV_MSG_UP_CO, |
| 78 | RAN_PEER_EV_MSG_DOWN_CL, |
| 79 | RAN_PEER_EV_MSG_DOWN_CO_INITIAL, |
| 80 | RAN_PEER_EV_MSG_DOWN_CO, |
| 81 | RAN_PEER_EV_RX_RESET, |
| 82 | RAN_PEER_EV_RX_RESET_ACK, |
| 83 | RAN_PEER_EV_CONNECTION_SUCCESS, |
| 84 | RAN_PEER_EV_CONNECTION_TIMEOUT, |
| 85 | }; |
| 86 | |
| 87 | struct ran_peer_ev_ctx { |
| 88 | uint32_t conn_id; |
| 89 | struct ran_conn *conn; |
| 90 | struct msgb *msg; |
| 91 | }; |
| 92 | |
| 93 | struct ran_peer *ran_peer_find_or_create(struct sccp_ran_inst *sri, const struct osmo_sccp_addr *peer_addr); |
| 94 | struct ran_peer *ran_peer_find(struct sccp_ran_inst *sri, const struct osmo_sccp_addr *peer_addr); |
| 95 | |
| 96 | void ran_peer_cells_seen_add(struct ran_peer *ran_peer, const struct gsm0808_cell_id *id); |
| 97 | |
| 98 | int ran_peer_up_l2(struct sccp_ran_inst *sri, const struct osmo_sccp_addr *calling_addr, bool co, uint32_t conn_id, |
| 99 | struct msgb *l2); |
| 100 | void ran_peer_disconnect(struct sccp_ran_inst *sri, uint32_t conn_id); |
| 101 | |
| 102 | int ran_peers_down_paging(struct sccp_ran_inst *sri, enum CELL_IDENT page_where, struct vlr_subscr *vsub, |
| 103 | enum paging_cause cause); |
| 104 | int ran_peer_down_paging(struct ran_peer *rp, const struct gsm0808_cell_id *page_id, struct vlr_subscr *vsub, |
| 105 | enum paging_cause cause); |
| 106 | |
| 107 | struct ran_peer *ran_peer_find_by_cell_id(struct sccp_ran_inst *sri, const struct gsm0808_cell_id *cid, |
| 108 | bool expecting_single_match); |
| 109 | struct ran_peer *ran_peer_find_by_addr(struct sccp_ran_inst *sri, const struct osmo_sccp_addr *addr); |