add struct bsc_subscr, separating libbsc from gsm_subscriber

In a future commit, gsm_subscriber will be replaced by vlr_subscr, and it will
not make sense to use vlr_subscr in libbsc. Thus we need a dedicated BSC
subscriber: struct bsc_subscr.

Add rf_policy arg to bsc_grace_paging_request() because the bsc_subscr will no
longer have a backpointer to gsm_network (used to be via subscr->group).

Create a separate logging filter for the new BSC subscriber. The implementation
of adjusting the filter context is added in libbsc to not introduce
bsc_subscr_get/_put() dependencies to libcommon.

During Paging Response, fetch a bsc_subscr from the mobile identity, like we do
for the gsm_subscriber. It looks like a duplication now, but will make sense
for the VLR as well as for future MSC split patches.

Naming: it was requested to not name the new struct bsc_sub, because 'sub' is
too ambiguous. At the same time it would be fine to have 'bsc_sub_' as function
prefix. Instead of struct bsc_subscriber and bsc_sub_ prefix, I decided to
match both up as struct bsc_subscr and bsc_subscr_ function prefix. It's fast
to type, relatively short, unambiguous, and the naming is consistent.

Add bsc_subscr unit test.

Related: OS#1592, OS#1594
Change-Id: Ia61cc00e8bb186b976939a4fc8f7cf9ce6aa3d8e
diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am
index 30c1191..7ddf323 100644
--- a/openbsc/include/openbsc/Makefile.am
+++ b/openbsc/include/openbsc/Makefile.am
@@ -10,6 +10,7 @@
 	bsc_nat_callstats.h \
 	bsc_nat_sccp.h \
 	bsc_rll.h \
+	bsc_subscriber.h \
 	bss.h \
 	bts_ipaccess_nanobts_omlattr.h \
 	chan_alloc.h \
diff --git a/openbsc/include/openbsc/bsc_subscriber.h b/openbsc/include/openbsc/bsc_subscriber.h
new file mode 100644
index 0000000..324734f
--- /dev/null
+++ b/openbsc/include/openbsc/bsc_subscriber.h
@@ -0,0 +1,43 @@
+/* GSM subscriber details for use in BSC land */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/gsm/protocol/gsm_23_003.h>
+
+struct log_target;
+
+struct bsc_subscr {
+	struct llist_head entry;
+	int use_count;
+
+	char imsi[GSM23003_IMSI_MAX_DIGITS+1];
+	uint32_t tmsi;
+	uint16_t lac;
+};
+
+const char *bsc_subscr_name(struct bsc_subscr *bsub);
+
+struct bsc_subscr *bsc_subscr_find_or_create_by_imsi(struct llist_head *list,
+						     const char *imsi);
+struct bsc_subscr *bsc_subscr_find_or_create_by_tmsi(struct llist_head *list,
+						     uint32_t tmsi);
+
+struct bsc_subscr *bsc_subscr_find_by_imsi(struct llist_head *list,
+					   const char *imsi);
+struct bsc_subscr *bsc_subscr_find_by_tmsi(struct llist_head *list,
+					   uint32_t tmsi);
+
+void bsc_subscr_set_imsi(struct bsc_subscr *bsub, const char *imsi);
+
+struct bsc_subscr *_bsc_subscr_get(struct bsc_subscr *bsub,
+				   const char *file, int line);
+struct bsc_subscr *_bsc_subscr_put(struct bsc_subscr *bsub,
+				   const char *file, int line);
+#define bsc_subscr_get(bsub) _bsc_subscr_get(bsub, __BASE_FILE__, __LINE__)
+#define bsc_subscr_put(bsub) _bsc_subscr_put(bsub, __BASE_FILE__, __LINE__)
+
+void log_set_filter_bsc_subscr(struct log_target *target,
+			       struct bsc_subscr *bsub);
diff --git a/openbsc/include/openbsc/debug.h b/openbsc/include/openbsc/debug.h
index 6300020..74db723 100644
--- a/openbsc/include/openbsc/debug.h
+++ b/openbsc/include/openbsc/debug.h
@@ -42,6 +42,7 @@
 
 struct gsm_subscriber;
 
-void log_set_imsi_filter(struct log_target *target, struct gsm_subscriber *subscr);
+void log_set_filter_vlr_subscr(struct log_target *target,
+			       struct gsm_subscriber *vlr_subscr);
 
 extern const struct log_info log_info;
diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h
index cb632f6..bdf4ed2 100644
--- a/openbsc/include/openbsc/gsm_04_08.h
+++ b/openbsc/include/openbsc/gsm_04_08.h
@@ -15,6 +15,7 @@
 struct gsm_subscriber_connection;
 struct amr_multirate_conf;
 struct amr_mode;
+struct bsc_subscr;
 
 #define GSM48_ALLOC_SIZE	2048
 #define GSM48_ALLOC_HEADROOM	256
@@ -78,7 +79,8 @@
 int send_siemens_mrpci(struct gsm_lchan *lchan, uint8_t *classmark2_lv);
 int gsm48_extract_mi(uint8_t *classmark2, int length, char *mi_string, uint8_t *mi_type);
 int gsm48_paging_extract_mi(struct gsm48_pag_resp *pag, int length, char *mi_string, uint8_t *mi_type);
-int gsm48_handle_paging_resp(struct gsm_subscriber_connection *conn, struct msgb *msg, struct gsm_subscriber *subscr);
+int gsm48_handle_paging_resp(struct gsm_subscriber_connection *conn,
+			     struct msgb *msg, struct bsc_subscr *bsub);
 
 int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t lchan_mode);
 int gsm48_rx_rr_modif_ack(struct msgb *msg);
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 620b6e4..a36083a 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -23,6 +23,7 @@
 
 struct mncc_sock_state;
 struct gsm_subscriber_group;
+struct bsc_subscr;
 
 #define OBSC_LINKID_CB(__msgb)	(__msgb)->cb[3]
 
@@ -119,6 +120,9 @@
 	/* To whom we are allocated at the moment */
 	struct gsm_subscriber *subscr;
 
+	/* libbsc subscriber information */
+	struct bsc_subscr *bsub;
+
 	/* LU expiration handling */
 	uint8_t expire_timer_stopped;
 	/* SMS helpers for libmsc */
@@ -391,6 +395,14 @@
 	 * BTS|RNC specific timezone overrides for multi-tz networks in
 	 * OsmoMSC, this should be tied to the location area code (LAC). */
 	struct gsm_tz tz;
+
+	/* List of all struct bsc_subscr used in libbsc. This llist_head is
+	 * allocated so that the llist_head pointer itself can serve as a
+	 * talloc context (useful to not have to pass the entire gsm_network
+	 * struct to the bsc_subscr_* API, and for bsc_susbscr unit tests to
+	 * not require gsm_data.h). In an MSC-without-BSC environment, this
+	 * pointer is NULL to indicate absence of a bsc_subscribers list. */
+	struct llist_head *bsc_subscribers;
 };
 
 struct osmo_esme;
diff --git a/openbsc/include/openbsc/osmo_bsc_grace.h b/openbsc/include/openbsc/osmo_bsc_grace.h
index ea5e4e2..5a81cd1 100644
--- a/openbsc/include/openbsc/osmo_bsc_grace.h
+++ b/openbsc/include/openbsc/osmo_bsc_grace.h
@@ -22,10 +22,14 @@
 #define OSMO_BSC_GRACE_H
 
 #include <openbsc/gsm_data.h>
+#include <openbsc/signal.h>
 
 struct bsc_msc_data;
 
 int bsc_grace_allow_new_connection(struct gsm_network *net, struct gsm_bts *bts);
-int bsc_grace_paging_request(struct gsm_subscriber *sub, int type, struct bsc_msc_data *msc);
+int bsc_grace_paging_request(enum signal_rf rf_policy,
+			     struct bsc_subscr *subscr,
+			     int chan_needed,
+			     struct bsc_msc_data *msc);
 
 #endif
diff --git a/openbsc/include/openbsc/paging.h b/openbsc/include/openbsc/paging.h
index 689ff51..7dd8500 100644
--- a/openbsc/include/openbsc/paging.h
+++ b/openbsc/include/openbsc/paging.h
@@ -27,7 +27,7 @@
 #include <osmocom/core/timer.h>
 
 #include <openbsc/gsm_data.h>
-#include <openbsc/gsm_subscriber.h>
+#include <openbsc/bsc_subscriber.h>
 
 /**
  * A pending paging request
@@ -36,8 +36,8 @@
 	/* list_head for list of all paging requests */
 	struct llist_head entry;
 	/* the subscriber which we're paging. Later gsm_paging_request
-	 * should probably become a part of the gsm_subscriber struct? */
-	struct gsm_subscriber *subscr;
+	 * should probably become a part of the bsc_subsrc struct? */
+	struct bsc_subscr *bsub;
 	/* back-pointer to the BTS on which we are paging */
 	struct gsm_bts *bts;
 	/* what kind of channel type do we ask the MS to establish */
@@ -55,13 +55,14 @@
 };
 
 /* schedule paging request */
-int paging_request(struct gsm_network *network, struct gsm_subscriber *subscr,
+int paging_request(struct gsm_network *network, struct bsc_subscr *bsub,
 		   int type, gsm_cbfn *cbfn, void *data);
-int paging_request_bts(struct gsm_bts *bts, struct gsm_subscriber *subscr,
-		int type, gsm_cbfn *cbfn, void *data);
+int paging_request_bts(struct gsm_bts *bts, struct bsc_subscr *bsub,
+		       int type, gsm_cbfn *cbfn, void *data);
 
 /* stop paging requests */
-void paging_request_stop(struct gsm_bts *bts, struct gsm_subscriber *subscr,
+void paging_request_stop(struct llist_head *bts_list,
+			 struct gsm_bts *_bts, struct bsc_subscr *bsub,
 			 struct gsm_subscriber_connection *conn,
 			 struct msgb *msg);
 
@@ -71,6 +72,6 @@
 /* pending paging requests */
 unsigned int paging_pending_requests_nr(struct gsm_bts *bts);
 
-void *paging_get_data(struct gsm_bts *bts, struct gsm_subscriber *subscr);
+void *paging_get_data(struct gsm_bts *bts, struct bsc_subscr *bsub);
 
 #endif