initial working osmo-smlc implementation

The lower level Lb/SCCP interface conn handling is essentially a copy of
OsmoMSC's A/SCCP infrastructure (OsmoMSC also connects to multiple BSCs).

The smlc_subscr is mostly a copy of OsmoBSC's bsc_subscr.

smlc_loc_req FSM is the SMLC side of OsmoBSC's new lcs_loc_req FSM.

cell_locations configures geographic coordinates of individual cells.

Change-Id: I917ba8fc51a1f1150be77ae01e12a7b16a853052
diff --git a/include/osmocom/smlc/lb_peer.h b/include/osmocom/smlc/lb_peer.h
new file mode 100644
index 0000000..b5ac6d6
--- /dev/null
+++ b/include/osmocom/smlc/lb_peer.h
@@ -0,0 +1,67 @@
+#pragma once
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/gsm/gsm0808.h>
+#include <osmocom/sigtran/sccp_sap.h>
+
+#include <osmocom/smlc/debug.h>
+#include <osmocom/smlc/lb_conn.h>
+
+struct vlr_subscr;
+struct lb_conn;
+struct neighbor_ident_entry;
+
+#define LOG_LB_PEER_CAT(LB_PEER, subsys, loglevel, fmt, args ...) \
+	LOGPFSMSL((LB_PEER)? (LB_PEER)->fi : NULL, subsys, loglevel, fmt, ## args)
+
+#define LOG_LB_PEER(LB_PEER, loglevel, fmt, args ...) \
+	LOG_LB_PEER_CAT(LB_PEER, DLB, loglevel, fmt, ## args)
+
+struct lb_peer {
+	struct llist_head entry;
+	struct osmo_fsm_inst *fi;
+
+	struct sccp_lb_inst *sli;
+	struct osmo_sccp_addr peer_addr;
+};
+
+#define lb_peer_for_each_lb_conn(LB_CONN, LB_PEER) \
+	llist_for_each_entry(LB_CONN, &(LB_PEER)->sli->lb_conns, entry) \
+		if ((LB_CONN)->lb_peer == (LB_PEER))
+
+#define lb_peer_for_each_lb_conn_safe(LB_CONN, LB_CONN_NEXT, LB_PEER) \
+	llist_for_each_entry_safe(LB_CONN, LB_CONN_NEXT, &(LB_PEER)->sli->lb_conns, entry) \
+		if ((LB_CONN)->lb_peer == (LB_PEER))
+
+enum lb_peer_state {
+	LB_PEER_ST_WAIT_RX_RESET = 0,
+	LB_PEER_ST_WAIT_RX_RESET_ACK,
+	LB_PEER_ST_READY,
+	LB_PEER_ST_DISCARDING,
+};
+
+enum lb_peer_event {
+	LB_PEER_EV_MSG_UP_CL = 0,
+	LB_PEER_EV_MSG_UP_CO_INITIAL,
+	LB_PEER_EV_MSG_UP_CO,
+	LB_PEER_EV_MSG_DOWN_CL,
+	LB_PEER_EV_MSG_DOWN_CO_INITIAL,
+	LB_PEER_EV_MSG_DOWN_CO,
+	LB_PEER_EV_RX_RESET,
+	LB_PEER_EV_RX_RESET_ACK,
+	LB_PEER_EV_CONNECTION_SUCCESS,
+	LB_PEER_EV_CONNECTION_TIMEOUT,
+};
+
+struct lb_peer_ev_ctx {
+	uint32_t conn_id;
+	struct lb_conn *lb_conn;
+	struct msgb *msg;
+};
+
+struct lb_peer *lb_peer_find_or_create(struct sccp_lb_inst *sli, const struct osmo_sccp_addr *peer_addr);
+struct lb_peer *lb_peer_find(struct sccp_lb_inst *sli, const struct osmo_sccp_addr *peer_addr);
+
+int lb_peer_up_l2(struct sccp_lb_inst *sli, const struct osmo_sccp_addr *calling_addr, bool co, uint32_t conn_id,
+		  struct msgb *l2);
+void lb_peer_disconnect(struct sccp_lb_inst *sli, uint32_t conn_id);