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/sccp_lb_inst.h b/include/osmocom/smlc/sccp_lb_inst.h
new file mode 100644
index 0000000..525eac0
--- /dev/null
+++ b/include/osmocom/smlc/sccp_lb_inst.h
@@ -0,0 +1,63 @@
+/* Lb: BSSAP-LE/SCCP */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <osmocom/core/tdef.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/gsm/gsm0808_utils.h>
+#include <osmocom/sigtran/sccp_sap.h>
+
+struct msgb;
+struct sccp_lb_inst;
+
+#define LOG_SCCP_LB_CO(sli, peer_addr, conn_id, level, fmt, args...) \
+	LOGP(DLB, level, "(Lb-%u%s%s) " fmt, \
+	     conn_id, peer_addr ? " from " : "", \
+	     peer_addr ? osmo_sccp_inst_addr_name((sli)->sccp, peer_addr) : "", \
+	     ## args)
+
+#define LOG_SCCP_LB_CL_CAT(sli, peer_addr, subsys, level, fmt, args...) \
+	LOGP(subsys, level, "(Lb%s%s) " fmt, \
+	     peer_addr ? " from " : "", \
+	     peer_addr ? osmo_sccp_inst_addr_name((sli)->sccp, peer_addr) : "", \
+	     ## args)
+
+#define LOG_SCCP_LB_CL(sli, peer_addr, level, fmt, args...) \
+	LOG_SCCP_LB_CL_CAT(sli, peer_addr, DLB, level, fmt, ##args)
+
+#define LOG_SCCP_LB_CAT(sli, subsys, level, fmt, args...) \
+	LOG_SCCP_LB_CL_CAT(sli, NULL, subsys, level, fmt, ##args)
+
+#define LOG_SCCP_LB(sli, level, fmt, args...) \
+	LOG_SCCP_LB_CL(sli, NULL, level, fmt, ##args)
+
+enum reset_msg_type {
+	SCCP_LB_MSG_NON_RESET = 0,
+	SCCP_LB_MSG_RESET,
+	SCCP_LB_MSG_RESET_ACK,
+};
+
+struct sccp_lb_inst {
+	struct osmo_sccp_instance *sccp;
+	struct osmo_sccp_user *scu;
+	struct osmo_sccp_addr local_sccp_addr;
+
+	struct llist_head lb_peers;
+	struct llist_head lb_conns;
+
+	void *user_data;
+};
+
+struct sccp_lb_inst *sccp_lb_init(void *talloc_ctx, struct osmo_sccp_instance *sccp, enum osmo_sccp_ssn ssn,
+				  const char *sccp_user_name);
+int sccp_lb_inst_next_conn_id();
+
+int sccp_lb_down_l2_co_initial(struct sccp_lb_inst *sli,
+			       const struct osmo_sccp_addr *called_addr,
+			       uint32_t conn_id, struct msgb *l2);
+int sccp_lb_down_l2_co(struct sccp_lb_inst *sli, uint32_t conn_id, struct msgb *l2);
+int sccp_lb_down_l2_cl(struct sccp_lb_inst *sli, const struct osmo_sccp_addr *called_addr, struct msgb *l2);
+
+int sccp_lb_disconnect(struct sccp_lb_inst *sli, uint32_t conn_id, uint32_t cause);