[OML] parse attributes depending on BTS type

Some NM attributes are defined differently depending on
the BTS type.  Having one big nm_att_tlvdef[] table for
all BTS types is no longer sufficient.  This patch

* introduces 'struct gsm_bts_model' to describe a BTS model
* adds definitions of gsm_bts_model for BS-11 and nanoBTS
* changes the abis_nm_tlv_parse() function: include a bts pointer
diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c
index d2676db..694ae06 100644
--- a/openbsc/src/gsm_data.c
+++ b/openbsc/src/gsm_data.c
@@ -32,6 +32,8 @@
 
 void *tall_bsc_ctx;
 
+static LLIST_HEAD(bts_models);
+
 void set_ts_e1link(struct gsm_bts_trx_ts *ts, u_int8_t e1_nr,
 		   u_int8_t e1_ts, u_int8_t e1_ts_ss)
 {
@@ -118,6 +120,29 @@
 	return chreq_names[c];
 }
 
+static struct gsm_bts_model *bts_model_find(enum gsm_bts_type type)
+{
+	struct gsm_bts_model *model;
+
+	llist_for_each_entry(model, &bts_models, list) {
+		if (model->type == type)
+			return model;
+	}
+
+	return NULL;
+}
+
+int gsm_bts_model_register(struct gsm_bts_model *model)
+{
+	if (bts_model_find(model->type))
+		return -EEXIST;
+
+	tlv_def_patch(&model->nm_att_tlvdef, &nm_att_tlvdef);
+	llist_add_tail(&model->list, &bts_models);
+	return 0;
+}
+
+
 struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
 {
 	struct gsm_bts_trx *trx = talloc_zero(bts, struct gsm_bts_trx);
@@ -160,14 +185,21 @@
 			      u_int8_t tsc, u_int8_t bsic)
 {
 	struct gsm_bts *bts = talloc_zero(net, struct gsm_bts);
+	struct gsm_bts_model *model = bts_model_find(type);
 	int i;
 
 	if (!bts)
 		return NULL;
 
+	if (!model) {
+		talloc_free(bts);
+		return NULL;
+	}
+
 	bts->network = net;
 	bts->nr = net->num_bts++;
 	bts->type = type;
+	bts->model = model;
 	bts->tsc = tsc;
 	bts->bsic = bsic;
 	bts->num_trx = 0;
@@ -504,9 +536,16 @@
 	return meas_rep;
 }
 
-void gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type)
+int gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type)
 {
+	struct gsm_bts_model *model;
+
+	model = bts_model_find(type);
+	if (!model)
+		return -EINVAL;
+
 	bts->type = type;
+	bts->model = model;
 
 	switch (bts->type) {
 	case GSM_BTS_TYPE_NANOBTS:
@@ -517,4 +556,6 @@
 	case GSM_BTS_TYPE_BS11:
 		break;
 	}
+
+	return 0;
 }