OM2000: Route outgoing NM message depending on MO

Depending on the MO we adress, select the proper OML link
diff --git a/openbsc/include/openbsc/e1_input.h b/openbsc/include/openbsc/e1_input.h
index 95b9dd1..3c8af38 100644
--- a/openbsc/include/openbsc/e1_input.h
+++ b/openbsc/include/openbsc/e1_input.h
@@ -182,4 +182,6 @@
 int e1inp_vty_init(void);
 void e1inp_init(void);
 
+int _abis_nm_sendmsg(struct msgb *msg, int to_trx_oml);
+
 #endif /* _E1_INPUT_H */
diff --git a/openbsc/include/openbsc/misdn.h b/openbsc/include/openbsc/misdn.h
index bd97ab7..0a8b063 100644
--- a/openbsc/include/openbsc/misdn.h
+++ b/openbsc/include/openbsc/misdn.h
@@ -22,7 +22,6 @@
 #include "e1_input.h"
 
 int mi_setup(int cardnr,  struct e1inp_line *line, int release_l2);
-int _abis_nm_sendmsg(struct msgb *msg);
 int mi_e1_line_update(struct e1inp_line *line);
 
 #endif
diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c
index 6864216..f2e68aa 100644
--- a/openbsc/src/abis_nm.c
+++ b/openbsc/src/abis_nm.c
@@ -416,7 +416,7 @@
 	/* queue OML messages */
 	if (llist_empty(&bts->abis_queue) && !bts->abis_nm_pend) {
 		bts->abis_nm_pend = OBSC_NM_W_ACK_CB(msg);
-		return _abis_nm_sendmsg(msg);
+		return _abis_nm_sendmsg(msg, 0);
 	} else {
 		msgb_enqueue(&bts->abis_queue, msg);
 		return 0;
@@ -985,7 +985,7 @@
 	while (!llist_empty(&bts->abis_queue)) {
 		msg = msgb_dequeue(&bts->abis_queue);
 		wait = OBSC_NM_W_ACK_CB(msg);
-		_abis_nm_sendmsg(msg);
+		_abis_nm_sendmsg(msg, 0);
 
 		if (wait)
 			break;
diff --git a/openbsc/src/abis_om2000.c b/openbsc/src/abis_om2000.c
index bde9341..dd4416b 100644
--- a/openbsc/src/abis_om2000.c
+++ b/openbsc/src/abis_om2000.c
@@ -40,6 +40,7 @@
 #include <openbsc/abis_nm.h>
 #include <openbsc/abis_om2000.h>
 #include <openbsc/signal.h>
+#include <openbsc/e1_input.h>
 
 #define OM_ALLOC_SIZE		1024
 #define OM_HEADROOM_SIZE	128
@@ -483,11 +484,47 @@
 				   "OM2000");
 }
 
+static char *om2k_mo_name(const struct abis_om2k_mo *mo)
+{
+	static char mo_buf[64];
+
+	memset(mo_buf, 0, sizeof(mo_buf));
+	snprintf(mo_buf, sizeof(mo_buf), "%s/%02x/%02x/%02x",
+		 get_value_string(om2k_mo_class_short_vals, mo->class),
+		 mo->bts, mo->assoc_so, mo->inst);
+	return mo_buf;
+}
+
 static int abis_om2k_sendmsg(struct gsm_bts *bts, struct msgb *msg)
 {
-	msg->trx = bts->c0;
+	struct abis_om2k_hdr *o2h;
+	int to_trx_oml;
 
-	return _abis_nm_sendmsg(msg);
+	msg->l2h = msg->data;
+	o2h = (struct abis_om2k_hdr *) msg->l2h;
+
+	switch (o2h->mo.class) {
+	case OM2K_MO_CLS_TRXC:
+	case OM2K_MO_CLS_TX:
+	case OM2K_MO_CLS_RX:
+	case OM2K_MO_CLS_TS:
+		/* Route through per-TRX OML Link to the appropriate TRX */
+		to_trx_oml = 1;
+		msg->trx = gsm_bts_trx_by_nr(bts, o2h->mo.inst);
+		if (!msg->trx) {
+			LOGP(DNM, LOGL_ERROR, "MO=%s Tx Dropping msg to "
+				"non-existing TRX\n", om2k_mo_name(&o2h->mo));
+			return -ENODEV;
+		}
+		break;
+	default:
+		/* Route through the IXU/DXU OML Link */
+		msg->trx = bts->c0;
+		to_trx_oml = 0;
+		break;
+	}
+
+	return _abis_nm_sendmsg(msg, to_trx_oml);
 }
 
 static void fill_om2k_hdr(struct abis_om2k_hdr *o2h, const struct abis_om2k_mo *mo,
@@ -501,17 +538,6 @@
 	memcpy(&o2h->mo, mo, sizeof(o2h->mo));
 }
 
-static char *om2k_mo_name(const struct abis_om2k_mo *mo)
-{
-	static char mo_buf[64];
-
-	memset(mo_buf, 0, sizeof(mo_buf));
-	snprintf(mo_buf, sizeof(mo_buf), "%s/%02x/%02x/%02x",
-		 get_value_string(om2k_mo_class_short_vals, mo->class),
-		 mo->bts, mo->assoc_so, mo->inst);
-	return mo_buf;
-}
-
 const struct abis_om2k_mo om2k_mo_cf = { OM2K_MO_CLS_CF, 0, 0xFF, 0 };
 const struct abis_om2k_mo om2k_mo_is = { OM2K_MO_CLS_IS, 0, 0xFF, 0 };
 
diff --git a/openbsc/src/e1_input.c b/openbsc/src/e1_input.c
index 916bb56..e5dd11b 100644
--- a/openbsc/src/e1_input.c
+++ b/openbsc/src/e1_input.c
@@ -255,7 +255,7 @@
 	return 0;
 }
 
-int _abis_nm_sendmsg(struct msgb *msg)
+int _abis_nm_sendmsg(struct msgb *msg, int to_trx_oml)
 {
 	struct e1inp_sign_link *sign_link;
 	struct e1inp_driver *e1inp_driver;
@@ -268,12 +268,12 @@
 		return -EINVAL;
 	}
 
-#if 0
 	/* Check for TRX-specific OML link first */
-	if (msg->trx->oml_link)
+	if (to_trx_oml) {
+		if (!msg->trx->oml_link)
+			return -ENODEV;
 		sign_link = msg->trx->oml_link;
-	else
-#endif
+	} else
 		sign_link = msg->trx->bts->oml_link;
 
 	e1i_ts = sign_link->ts;
diff --git a/openbsc/src/rs232.c b/openbsc/src/rs232.c
index bb940fe..7550571 100644
--- a/openbsc/src/rs232.c
+++ b/openbsc/src/rs232.c
@@ -54,7 +54,7 @@
 static int handle_ser_write(struct bsc_fd *bfd);
 
 /* callback from abis_nm */
-int _abis_nm_sendmsg(struct msgb *msg)
+int _abis_nm_sendmsg(struct msgb *msg, int to_trx_oml)
 {
 	struct serial_handle *sh = ser_handle;
 	u_int8_t *lapd;