gtphub: simplify/fix: one TEI mapping per tunnel.

Because the sender is known, one unique TEI per tunnel suffices to map the TEIs
that the peers are sending to gtphub, instead of previously 4 (SGSN<->GGSN
interaction on User and Ctrl plane, where each had an own unique TEI).

Also, previously, a tunnel's endpoints should also have been checked against
each other for TEI reuse, not only against the endpoints of other tunnels. This
simplification fixes that problem for free.

Thus simplify TEI reuse detection and improve VTY show readability and
debugging.

Adjust log and VTY output for tunnels.
Adjust tests accordingly.

Suggested-by: Holger Hans Peter Freyther <holger@moiji-mobile.com>
Sponsored-by: On-Waves ehi
diff --git a/openbsc/include/openbsc/gtphub.h b/openbsc/include/openbsc/gtphub.h
index 97cfc60..9cb7605 100644
--- a/openbsc/include/openbsc/gtphub.h
+++ b/openbsc/include/openbsc/gtphub.h
@@ -398,7 +398,6 @@
 struct gtphub_tunnel_endpoint {
 	struct gtphub_peer_port *peer;
 	uint32_t tei_orig; /* from/to peer */
-	uint32_t tei_repl; /* from/to the other tunnel endpoint */
 
 	struct rate_ctr_group *counters_io;
 };
@@ -407,6 +406,7 @@
 	struct llist_head entry;
 	struct expiring_item expiry_entry;
 
+	uint32_t tei_repl; /* unique TEI to replace peers' TEIs */
 	struct gtphub_tunnel_endpoint endpoint[GTPH_SIDE_N][GTPH_PLANE_N];
 };
 
diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c
index 24d0c58..0218924 100644
--- a/openbsc/src/gprs/gtphub.c
+++ b/openbsc/src/gprs/gtphub.c
@@ -995,9 +995,9 @@
 		APPEND("/%s", gsn_addr_to_str(&u->peer->peer_addr->addr));
 	}
 
-	APPEND(" (TEI C %x=%x/U %x=%x)",
-	       c->tei_orig, c->tei_repl,
-	       u->tei_orig, u->tei_repl);
+	APPEND(" (TEI C=%x U=%x)",
+	       c->tei_orig,
+	       u->tei_orig);
 	return buf;
 }
 
@@ -1008,6 +1008,7 @@
 	int left = sizeof(buf);
 	int l;
 
+	APPEND("TEI=%x: ", tun->tei_repl);
 	APPEND("%s", gtphub_tunnel_side_str(tun, GTPH_SIDE_SGSN));
 	APPEND(" <-> %s", gtphub_tunnel_side_str(tun, GTPH_SIDE_GGSN));
 
@@ -1030,12 +1031,14 @@
 {
 	if (!tun)
 		return 0;
+	if (!tun->tei_repl)
+		return 0;
 	int side_idx;
 	int plane_idx;
 	for_each_side_and_plane(side_idx, plane_idx) {
 		struct gtphub_tunnel_endpoint *te =
 			&tun->endpoint[side_idx][plane_idx];
-		if (!(te->peer && te->tei_orig && te->tei_repl))
+		if (!(te->peer && te->tei_orig))
 			return 0;
 	}
 	return 1;
@@ -1212,29 +1215,33 @@
 	return nrm->origin;
 }
 
-static int gtphub_check_mapped_tei(struct gtphub_tunnel_endpoint *new_te,
-				   struct gtphub_tunnel_endpoint *iterated_te,
+static int gtphub_check_mapped_tei(struct gtphub_tunnel *new_tun,
+				   struct gtphub_tunnel *iterated_tun,
 				   uint32_t *tei_min,
 				   uint32_t *tei_max)
 {
-	if (!new_te->tei_repl)
-		return 1;
-	if (new_te->tei_repl != iterated_te->tei_repl)
+	if (!new_tun->tei_repl || !iterated_tun->tei_repl)
 		return 1;
 
-	/* new_te->tei_repl is already taken. Try to find one out of the known
+	*tei_min = (*tei_min < iterated_tun->tei_repl)? *tei_min : iterated_tun->tei_repl;
+	*tei_max = (*tei_max > iterated_tun->tei_repl)? *tei_max : iterated_tun->tei_repl;
+
+	if (new_tun->tei_repl != iterated_tun->tei_repl)
+		return 1;
+
+	/* new_tun->tei_repl is already taken. Try to find one out of the known
 	 * range. */
-	LOG(LOGL_DEBUG, "TEI replacement %d already taken.\n", new_te->tei_repl);
+	LOG(LOGL_DEBUG, "TEI replacement %d already taken.\n", new_tun->tei_repl);
 
 	if ((*tei_max) < 0xffffffff) {
 		(*tei_max)++;
-		new_te->tei_repl = *tei_max;
-		LOG(LOGL_DEBUG, "Using TEI %d instead.\n", new_te->tei_repl);
+		new_tun->tei_repl = *tei_max;
+		LOG(LOGL_DEBUG, "Using TEI %d instead.\n", new_tun->tei_repl);
 		return 1;
 	} else if ((*tei_min) > 1) {
 		(*tei_min)--;
-		new_te->tei_repl = *tei_min;
-		LOG(LOGL_DEBUG, "Using TEI %d instead.\n", new_te->tei_repl);
+		new_tun->tei_repl = *tei_min;
+		LOG(LOGL_DEBUG, "Using TEI %d instead.\n", new_tun->tei_repl);
 		return 1;
 	}
 
@@ -1249,8 +1256,6 @@
 	uint32_t tei_max = 0;
 	int side_idx;
 	int plane_idx;
-	int side_idx2;
-	int plane_idx2;
 	struct gtphub_tunnel_endpoint *te;
 	struct gtphub_tunnel_endpoint *te2;
 
@@ -1303,23 +1308,14 @@
 		if (tun_continue)
 			continue;
 
-		/* Check whether the mapped TEIs assigned to the endpoints are
-		 * used anywhere else. */
-		for_each_side_and_plane(side_idx, plane_idx) {
-			te = &tun->endpoint[side_idx][plane_idx];
-			tei_min = (tei_min < te->tei_repl)? tei_min : te->tei_repl;
-			tei_max = (tei_max > te->tei_repl)? tei_max : te->tei_repl;
-
-			for_each_side_and_plane(side_idx2, plane_idx2) {
-				te2 = &new_tun->endpoint[side_idx2][plane_idx2];
-				if (!gtphub_check_mapped_tei(te2, te, &tei_min, &tei_max)) {
-					LOG(LOGL_ERROR,
-					    "No mapped TEI is readily available."
-					    " Searching for holes between occupied"
-					    " TEIs not implemented.");
-					return 0;
-				}
-			}
+		/* Check whether the mapped TEI is already used by another
+		 * tunnel. */
+		if (!gtphub_check_mapped_tei(new_tun, tun, &tei_min, &tei_max)) {
+			LOG(LOGL_ERROR,
+			    "No mapped TEI is readily available."
+			    " Searching for holes between occupied"
+			    " TEIs not implemented.");
+			return 0;
 		}
 
 	}
@@ -1350,7 +1346,7 @@
 			&tun->endpoint[p->side_idx][p->plane_idx];
 		struct gtphub_tunnel_endpoint *te_to =
 			&tun->endpoint[other_side][p->plane_idx];
-		if ((te_to->tei_repl == p->header_tei_rx)
+		if ((tun->tei_repl == p->header_tei_rx)
 		    && te_from->peer
 		    && gsn_addr_same(&te_from->peer->peer_addr->addr,
 				     &from->peer_addr->addr)) {
@@ -1453,6 +1449,10 @@
 
 		/* A new tunnel. */
 		p->tun = tun = gtphub_tunnel_new();
+
+		/* Create TEI mapping */
+		tun->tei_repl = nr_pool_next(&hub->tei_pool);
+
 		llist_add(&tun->entry, &hub->tunnels);
 		gtphub_tunnel_refresh(hub, tun, p->timestamp);
 		/* The endpoint peers on this side (SGSN) will be set from IEs
@@ -1471,8 +1471,7 @@
 		 * TEI and be available in tun (== p->tun). Just fill in the
 		 * GSN Addresses below.*/
 		OSMO_ASSERT(tun);
-		OSMO_ASSERT(tun->endpoint[other_side_idx(p->side_idx)][GTPH_PLANE_CTRL].tei_repl
-			    == p->header_tei_rx);
+		OSMO_ASSERT(tun->tei_repl == p->header_tei_rx);
 		OSMO_ASSERT(to_ctrl);
 	}
 
@@ -1555,12 +1554,9 @@
 		}
 
 		if (tei_from_ie) {
-			/* Create TEI mapping and replace in GTP packet IE */
-			uint32_t mapped_tei = nr_pool_next(&hub->tei_pool);
-
+			/* Replace TEI in GTP packet IE */
 			tun->endpoint[side_idx][plane_idx].tei_orig = tei_from_ie;
-			tun->endpoint[side_idx][plane_idx].tei_repl = mapped_tei;
-			p->ie[ie_idx]->tv4.v = hton32(mapped_tei);
+			p->ie[ie_idx]->tv4.v = hton32(tun->tei_repl);
 
 			if (!gtphub_check_reused_teis(hub, tun)) {
 				/* It's highly unlikely that all TEIs are
diff --git a/openbsc/src/gprs/gtphub_vty.c b/openbsc/src/gprs/gtphub_vty.c
index 5b9fc79..9e3c5e0 100644
--- a/openbsc/src/gprs/gtphub_vty.c
+++ b/openbsc/src/gprs/gtphub_vty.c
@@ -398,8 +398,8 @@
 	time_t now = gtphub_now();
 
 	vty_out(vty, "All tunnels%s:%s"
-		"Legend: (expiry in minutes) SGSN <-> GGSN, with each:%s"
-		"        <IP-Ctrl>[/<IP-User>] (<TEI-Ctrl>=<mapped>/<TEI-User>=<mapped>)%s",
+		"Legend: TEI=<hex>: SGSN <-> GGSN (expiry in minutes), with each:%s"
+		"        <IP-Ctrl>[/<IP-User>] (TEI C=<TEI-Ctrl-hex> U=<TEI-User-hex>)%s",
 		with_io_stats? "with I/O stats" : "",
 		VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
 
@@ -408,9 +408,9 @@
 	struct gtphub_tunnel *tun;
 	llist_for_each_entry(tun, &g_hub->tunnels, entry) {
 		vty_out(vty,
-			"(%4dm) %s%s",
-			(int)((tun->expiry_entry.expiry - now) / 60),
+			"%s (expiry in %dm)%s",
 			gtphub_tunnel_str(tun),
+			(int)((tun->expiry_entry.expiry - now) / 60),
 			VTY_NEWLINE);
 		count ++;
 		if (!gtphub_tunnel_complete(tun))
diff --git a/openbsc/tests/gtphub/gtphub_test.c b/openbsc/tests/gtphub/gtphub_test.c
index 0980278..fa9ad8b 100644
--- a/openbsc/tests/gtphub/gtphub_test.c
+++ b/openbsc/tests/gtphub/gtphub_test.c
@@ -929,8 +929,8 @@
 				"6d31",	/* mapped seq ("abcd") */
 				"23",
 				"42000121436587f9",
-				"00000002", /* mapped TEI Data I ("123") */
-				"00000001", /* mapped TEI Control ("321") */
+				"00000001", /* Data I: tunnel's TEI */
+				"00000001", /* Control: tunnel's TEI */
 				"0009""08696e7465726e6574",
 				"0004""7f000201", /* replaced with gtphub's ggsn ctrl */
 				"0004""7f000202" /* replaced with gtphub's ggsn user */
@@ -943,8 +943,9 @@
 	LVL2_ASSERT(was_resolved_for("240010123456789", "internet"));
 
 	LVL2_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C 321=1/U 123=2)"
-		" <-> 192.168.43.34/(uninitialized) (TEI C 0=0/U 0=0)"
+		"TEI=1:"
+		" 192.168.42.23 (TEI C=321 U=123)"
+		" <-> 192.168.43.34/(uninitialized) (TEI C=0 U=0)"
 		" @21945\n"));
 
 	const char *gtp_resp_from_ggsn =
@@ -962,8 +963,8 @@
 				"00000321", /* unmapped TEI ("001") */
 				"abcd", /* unmapped seq ("6d31") */
 				"23",
-				"00000004", /* mapped TEI from GGSN ("567") */
-				"00000003", /* mapped TEI from GGSN ("765") */
+				"00000001", /* mapped TEI from GGSN ("567") */
+				"00000001", /* mapped TEI from GGSN ("765") */
 				"0004""7f000101", /* gtphub's address towards SGSNs (Ctrl) */
 				"0004""7f000102" /* gtphub's address towards SGSNs (User) */
 			       );
@@ -1007,12 +1008,13 @@
 	gtphub_gc(hub, now);
 
 	LVL2_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C 321=1/U 123=2)"
-		" <-> 192.168.43.34 (TEI C 765=3/U 567=4)"
+		"TEI=1:"
+		" 192.168.42.23 (TEI C=321 U=123)"
+		" <-> 192.168.43.34 (TEI C=765 U=567)"
 		" @21945\n"));
 
 	/* TEI Ctrl from above and next sequence after abcd. */
-	const char *gtp_req_from_sgsn = MSG_DEL_PDP_CTX_REQ("00000003", "abce");
+	const char *gtp_req_from_sgsn = MSG_DEL_PDP_CTX_REQ("00000001", "abce");
 	const char *gtp_req_to_ggsn = MSG_DEL_PDP_CTX_REQ("00000765", "6d32");
 
 	LVL2_ASSERT(msg_from_sgsn_c(&sgsn_sender,
@@ -1022,8 +1024,9 @@
 
 	/* 21945 + 31 = 21976 */
 	LVL2_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C 321=1/U 123=2)"
-		" <-> 192.168.43.34 (TEI C 765=3/U 567=4)"
+		"TEI=1:"
+		" 192.168.42.23 (TEI C=321 U=123)"
+		" <-> 192.168.43.34 (TEI C=765 U=567)"
 		" @21976\n"));
 
 	const char *gtp_resp_from_ggsn =
@@ -1049,8 +1052,9 @@
 	gtphub_gc(hub, now);
 
 	LVL2_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C 321=1/U 123=2)"
-		" <-> 192.168.43.34 (TEI C 765=3/U 567=4)"
+		"TEI=1:"
+		" 192.168.42.23 (TEI C=321 U=123)"
+		" <-> 192.168.43.34 (TEI C=765 U=567)"
 		" @21945\n"));
 
 	/* TEI Ctrl from above and next sequence after abcd. */
@@ -1064,12 +1068,13 @@
 
 	/* 21945 + 31 = 21976 */
 	LVL2_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C 321=1/U 123=2)"
-		" <-> 192.168.43.34 (TEI C 765=3/U 567=4)"
+		"TEI=1:"
+		" 192.168.42.23 (TEI C=321 U=123)"
+		" <-> 192.168.43.34 (TEI C=765 U=567)"
 		" @21976\n"));
 
 	const char *gtp_resp_from_sgsn =
-		MSG_DEL_PDP_CTX_RSP("00000003", "6d31");
+		MSG_DEL_PDP_CTX_RSP("00000001", "6d31");
 	const char *gtp_resp_to_ggsn =
 		MSG_DEL_PDP_CTX_RSP("00000765", "5432");
 
@@ -1112,8 +1117,9 @@
 	 * 0x00000567 == 1383 (TEI from GGSN User)
 	 * Mapped TEIs should be 1 and 2. */
 	OSMO_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C 321=1/U 123=2)"
-		" <-> 192.168.43.34 (TEI C 765=3/U 567=4)"
+		"TEI=1:"
+		" 192.168.42.23 (TEI C=321 U=123)"
+		" <-> 192.168.43.34 (TEI C=765 U=567)"
 		" @21945\n"));
 
 	if (del_from_side == GTPH_SIDE_SGSN) {
@@ -1136,8 +1142,9 @@
 
 	/* now == 345; now + (6 * 60 * 60) == 21600 + 345 == 21945. */
 	OSMO_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C 321=1/U 123=2)"
-		" <-> 192.168.43.34 (TEI C 765=3/U 567=4)"
+		"TEI=1:"
+		" 192.168.42.23 (TEI C=321 U=123)"
+		" <-> 192.168.43.34 (TEI C=765 U=567)"
 		" @21945\n"));
 
 	LOG("- user data starts");
@@ -1152,7 +1159,7 @@
 		"32" 	/* 0b001'1 0010: version 1, protocol GTP, with seq nr */
 		"ff"	/* type 255: G-PDU */
 		"0058"	/* length: 88 + 8 octets == 96 */
-		"00000002" /* mapped User TEI for SGSN from create_pdp_ctx() */
+		"00000001" /* mapped TEI for SGSN from create_pdp_ctx() */
 		"0070"	/* seq */
 		"0000"	/* No extensions */
 		/* User data (ICMP packet), 96 - 12 = 84 octets  */
@@ -1182,15 +1189,16 @@
 	/* Make sure the user plane messages have refreshed the TEI mapping
 	 * timeouts: 21945 + 600 == 22545. */
 	OSMO_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C 321=1/U 123=2)"
-		" <-> 192.168.43.34 (TEI C 765=3/U 567=4)"
+		"TEI=1:"
+		" 192.168.42.23 (TEI C=321 U=123)"
+		" <-> 192.168.43.34 (TEI C=765 U=567)"
 		" @22545\n"));
 
 	const char *u_from_sgsn =
 		"32" 	/* 0b001'1 0010: version 1, protocol GTP, with seq nr */
 		"ff"	/* type 255: G-PDU */
 		"0058"	/* length: 88 + 8 octets == 96 */
-		"00000004" /* mapped User TEI for GGSN from create_pdp_ctx() */
+		"00000001" /* mapped User TEI for GGSN from create_pdp_ctx() */
 		"1234"	/* unknown seq */
 		"0000"	/* No extensions */
 		/* User data (ICMP packet), 96 - 12 = 84 octets  */
@@ -1218,8 +1226,9 @@
 	/* Make sure the user plane messages have refreshed the TEI mapping
 	 * timeouts: 21945 + 600 == 22545. Both timeouts refreshed: */
 	OSMO_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C 321=1/U 123=2)"
-		" <-> 192.168.43.34 (TEI C 765=3/U 567=4)"
+		"TEI=1:"
+		" 192.168.42.23 (TEI C=321 U=123)"
+		" <-> 192.168.43.34 (TEI C=765 U=567)"
 		" @22545\n"));
 
 	OSMO_ASSERT(clear_test_hub());
@@ -1249,8 +1258,8 @@
 				"6d32",	/* mapped seq ("abce") */
 				"23",
 				"42000121436587f9",
-				"00000006", /* mapped TEI Data I ("123") */
-				"00000005", /* mapped TEI Control ("321") */
+				"00000002", /* mapped TEI Data I ("123") */
+				"00000002", /* mapped TEI Control ("321") */
 				"0009""08696e7465726e6574",
 				"0004""7f000201", /* replaced with gtphub's ggsn ctrl */
 				"0004""7f000202" /* replaced with gtphub's ggsn user */
@@ -1263,13 +1272,14 @@
 	OSMO_ASSERT(was_resolved_for("240010123456789", "internet"));
 
 	OSMO_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C 321=5/U 123=6)"
-		" <-> 192.168.43.34/(uninitialized) (TEI C 0=0/U 0=0)"
+		"TEI=2:"
+		" 192.168.42.23 (TEI C=321 U=123)"
+		" <-> 192.168.43.34/(uninitialized) (TEI C=0 U=0)"
 		" @21945\n"));
 
 	const char *gtp_resp_from_ggsn =
 		MSG_PDP_CTX_RSP("004e",
-				"00000005", /* destination TEI (sent in req above) */
+				"00000002", /* destination TEI (sent in req above) */
 				"6d32", /* mapped seq */
 				"01", /* restart */
 				"00000567", /* TEI U */
@@ -1282,8 +1292,8 @@
 				"00000321", /* unmapped TEI ("001") */
 				"abce", /* unmapped seq ("6d32") */
 				"23",
-				"00000008", /* mapped TEI from GGSN ("567") */
-				"00000007", /* mapped TEI from GGSN ("765") */
+				"00000002", /* mapped TEI from GGSN ("567") */
+				"00000002", /* mapped TEI from GGSN ("765") */
 				"0004""7f000101", /* gtphub's address towards SGSNs (Ctrl) */
 				"0004""7f000102" /* gtphub's address towards SGSNs (User) */
 			       );
@@ -1323,8 +1333,8 @@
 				"6d33",	/* mapped seq ("1234") */
 				"23",
 				"42000121436587f9",
-				"00000006", /* mapped TEI Data I ("123") */
-				"00000005", /* mapped TEI Control ("321") */
+				"00000002", /* mapped TEI Data I ("123") */
+				"00000002", /* mapped TEI Control ("321") */
 				"0009""08696e7465726e6574",
 				"0004""7f000201", /* replaced with gtphub's ggsn ctrl */
 				"0004""7f000202" /* replaced with gtphub's ggsn user */
@@ -1337,17 +1347,19 @@
 	OSMO_ASSERT(was_resolved_for("240010123456789", "internet"));
 
 	OSMO_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C cba=5/U abc=6)"
-		" <-> 192.168.43.34/(uninitialized) (TEI C 0=0/U 0=0)"
+		"TEI=2:"
+		" 192.168.42.23 (TEI C=cba U=abc)"
+		" <-> 192.168.43.34/(uninitialized) (TEI C=0 U=0)"
 		" @21955\n"
-		"(uninitialized) (TEI C 321=1/U 123=2)"
-		" <-> 192.168.43.34 (TEI C 765=3/U 567=4)"
+		"TEI=1:"
+		" (uninitialized) (TEI C=321 U=123)"
+		" <-> 192.168.43.34 (TEI C=765 U=567)"
 		" @21945\n"
 		));
 
 	const char *gtp_resp_from_ggsn =
 		MSG_PDP_CTX_RSP("004e",
-				"00000005", /* destination TEI (sent in req above) */
+				"00000002", /* destination TEI (sent in req above) */
 				"6d33", /* mapped seq */
 				"01", /* restart */
 				"00000def", /* TEI U */
@@ -1360,8 +1372,8 @@
 				"00000cba", /* unmapped TEI ("005") */
 				"1234", /* unmapped seq ("6d32") */
 				"23",
-				"00000008", /* mapped TEI from GGSN ("567") */
-				"00000007", /* mapped TEI from GGSN ("765") */
+				"00000002", /* mapped TEI from GGSN ("567") */
+				"00000002", /* mapped TEI from GGSN ("765") */
 				"0004""7f000101", /* gtphub's address towards SGSNs (Ctrl) */
 				"0004""7f000102" /* gtphub's address towards SGSNs (User) */
 			       );
@@ -1401,8 +1413,8 @@
 				"6d32",	/* mapped seq ("1234") */
 				"23",
 				"42000121436587f9",
-				"00000006", /* mapped TEI Data I ("123") */
-				"00000005", /* mapped TEI Control ("321") */
+				"00000002", /* mapped TEI Data I ("123") */
+				"00000002", /* mapped TEI Control ("321") */
 				"0009""08696e7465726e6574",
 				"0004""7f000201", /* replaced with gtphub's ggsn ctrl */
 				"0004""7f000202" /* replaced with gtphub's ggsn user */
@@ -1415,14 +1427,15 @@
 	OSMO_ASSERT(was_resolved_for("240010123456789", "internet"));
 
 	OSMO_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C 321=5/U 123=6)"
-		" <-> 192.168.43.34/(uninitialized) (TEI C 0=0/U 0=0)"
+		"TEI=2:"
+		" 192.168.42.23 (TEI C=321 U=123)"
+		" <-> 192.168.43.34/(uninitialized) (TEI C=0 U=0)"
 		" @21955\n"
 		));
 
 	const char *gtp_resp_from_ggsn =
 		MSG_PDP_CTX_RSP("004e",
-				"00000005", /* destination TEI (sent in req above) */
+				"00000002", /* destination TEI (sent in req above) */
 				"6d32", /* mapped seq */
 				"01", /* restart */
 				"00000def", /* TEI U */
@@ -1435,8 +1448,8 @@
 				"00000321", /* unmapped TEI ("005") */
 				"1234", /* unmapped seq ("6d32") */
 				"23",
-				"00000008", /* mapped TEI from GGSN ("567") */
-				"00000007", /* mapped TEI from GGSN ("765") */
+				"00000002", /* mapped TEI from GGSN ("567") */
+				"00000002", /* mapped TEI from GGSN ("765") */
 				"0004""7f000101", /* gtphub's address towards SGSNs (Ctrl) */
 				"0004""7f000102" /* gtphub's address towards SGSNs (User) */
 			       );
@@ -1462,8 +1475,9 @@
 
 	/* now == 345; now + (6 * 60 * 60) == 21600 + 345 == 21945. */
 	OSMO_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C 321=1/U 123=2)"
-		" <-> 192.168.43.34 (TEI C 765=3/U 567=4)"
+		"TEI=1:"
+		" 192.168.42.23 (TEI C=321 U=123)"
+		" <-> 192.168.43.34 (TEI C=765 U=567)"
 		" @21945\n"));
 
 	LOG("- user data starts");
@@ -1477,7 +1491,7 @@
 		"32" 	/* 0b001'1 0010: version 1, protocol GTP, with seq nr */
 		"ff"	/* type 255: G-PDU */
 		"0058"	/* length: 88 + 8 octets == 96 */
-		"00000002" /* mapped User TEI for SGSN from create_pdp_ctx() */
+		"00000001" /* mapped User TEI for SGSN from create_pdp_ctx() */
 		"0070"	/* seq */
 		"0000"	/* No extensions */
 		/* User data (ICMP packet), 96 - 12 = 84 octets  */
@@ -1507,15 +1521,16 @@
 	/* Make sure the user plane messages have refreshed the TEI mapping
 	 * timeouts: 21945 + 600 == 22545. */
 	OSMO_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C 321=1/U 123=2)"
-		" <-> 192.168.43.34 (TEI C 765=3/U 567=4)"
+		"TEI=1:"
+		" 192.168.42.23 (TEI C=321 U=123)"
+		" <-> 192.168.43.34 (TEI C=765 U=567)"
 		" @22545\n"));
 
 	const char *u_from_sgsn =
 		"32" 	/* 0b001'1 0010: version 1, protocol GTP, with seq nr */
 		"ff"	/* type 255: G-PDU */
 		"0058"	/* length: 88 + 8 octets == 96 */
-		"00000004" /* mapped User TEI for GGSN from create_pdp_ctx() */
+		"00000001" /* mapped User TEI for GGSN from create_pdp_ctx() */
 		"1234"	/* unknown seq */
 		"0000"	/* No extensions */
 		/* User data (ICMP packet), 96 - 12 = 84 octets  */
@@ -1543,8 +1558,9 @@
 	/* Make sure the user plane messages have refreshed the TEI mapping
 	 * timeouts: 21945 + 600 == 22545. Both timeouts refreshed: */
 	OSMO_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C 321=1/U 123=2)"
-		" <-> 192.168.43.34 (TEI C 765=3/U 567=4)"
+		"TEI=1:"
+		" 192.168.42.23 (TEI C=321 U=123)"
+		" <-> 192.168.43.34 (TEI C=765 U=567)"
 		" @22545\n"));
 
 	OSMO_ASSERT(clear_test_hub());
@@ -1572,7 +1588,7 @@
 				"6d31",	/* mapped seq ("abcd") */
 				"23",
 				"42000121436587f9",
-				"00000002", /* mapped TEI Data I ("123") */
+				"00000001", /* mapped TEI Data I ("123") */
 				"00000001", /* mapped TEI Control ("321") */
 				"0009""08696e7465726e6574",
 				"0004""7f000201", /* replaced with gtphub's ggsn ctrl */
@@ -1585,8 +1601,9 @@
 				    gtp_req_to_ggsn1));
 
 	OSMO_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C 321=1/U 123=2)"
-		" <-> 192.168.43.34/(uninitialized) (TEI C 0=0/U 0=0)"
+		"TEI=1:"
+		" 192.168.42.23 (TEI C=321 U=123)"
+		" <-> 192.168.43.34/(uninitialized) (TEI C=0 U=0)"
 		" @21945\n"));
 
 	now ++;
@@ -1607,8 +1624,8 @@
 				"6d32",	/* mapped seq ("abce") */
 				"23",
 				"42000121436588f9",
-				"00000004", /* mapped TEI Data I ("124") */
-				"00000003", /* mapped TEI Control ("322") */
+				"00000002", /* mapped TEI Data I ("124") */
+				"00000002", /* mapped TEI Control ("322") */
 				"0009""08696e7465726e6574",
 				"0004""7f000201", /* replaced with gtphub's ggsn ctrl */
 				"0004""7f000202" /* replaced with gtphub's ggsn user */
@@ -1620,11 +1637,13 @@
 				    gtp_req_to_ggsn2));
 
 	OSMO_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C 322=3/U 124=4)"
-		" <-> 192.168.43.34/(uninitialized) (TEI C 0=0/U 0=0)"
+		"TEI=2:"
+		" 192.168.42.23 (TEI C=322 U=124)"
+		" <-> 192.168.43.34/(uninitialized) (TEI C=0 U=0)"
 		" @21946\n"
-		"192.168.42.23 (TEI C 321=1/U 123=2)"
-		" <-> 192.168.43.34/(uninitialized) (TEI C 0=0/U 0=0)"
+		"TEI=1:"
+		" 192.168.42.23 (TEI C=321 U=123)"
+		" <-> 192.168.43.34/(uninitialized) (TEI C=0 U=0)"
 		" @21945\n"
 		));
 
@@ -1645,8 +1664,8 @@
 				"00000321", /* unmapped TEI ("001") */
 				"abcd", /* unmapped seq ("6d31") */
 				"23",
-				"00000006", /* mapped TEI from GGSN ("567") */
-				"00000005", /* mapped TEI from GGSN ("765") */
+				"00000001", /* mapped TEI from GGSN ("567") */
+				"00000001", /* mapped TEI from GGSN ("765") */
 				"0004""7f000101", /* gtphub's address towards SGSNs (Ctrl) */
 				"0004""7f000102" /* gtphub's address towards SGSNs (User) */
 			       );
@@ -1657,11 +1676,13 @@
 				    gtp_resp_to_sgsn1));
 
 	OSMO_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C 322=3/U 124=4)"
-		" <-> 192.168.43.34/(uninitialized) (TEI C 0=0/U 0=0)"
+		"TEI=2:"
+		" 192.168.42.23 (TEI C=322 U=124)"
+		" <-> 192.168.43.34/(uninitialized) (TEI C=0 U=0)"
 		" @21946\n"
-		"192.168.42.23 (TEI C 321=1/U 123=2)"
-		" <-> 192.168.43.34 (TEI C 765=5/U 567=6)"
+		"TEI=1:"
+		" 192.168.42.23 (TEI C=321 U=123)"
+		" <-> 192.168.43.34 (TEI C=765 U=567)"
 		" @21947\n"
 		));
 
@@ -1669,7 +1690,7 @@
 
 	const char *gtp_resp_from_ggsn2 =
 		MSG_PDP_CTX_RSP("004e",
-				"00000003", /* destination TEI (sent in req above) */
+				"00000002", /* destination TEI (sent in req above) */
 				"6d32", /* mapped seq */
 				"01", /* restart */
 				"00000568", /* TEI U */
@@ -1682,8 +1703,8 @@
 				"00000322", /* unmapped TEI ("001") */
 				"abce", /* unmapped seq ("6d31") */
 				"23",
-				"00000008", /* mapped TEI from GGSN ("567") */
-				"00000007", /* mapped TEI from GGSN ("765") */
+				"00000002", /* mapped TEI from GGSN ("567") */
+				"00000002", /* mapped TEI from GGSN ("765") */
 				"0004""7f000101", /* gtphub's address towards SGSNs (Ctrl) */
 				"0004""7f000102" /* gtphub's address towards SGSNs (User) */
 			       );
@@ -1694,11 +1715,13 @@
 				    gtp_resp_to_sgsn2));
 
 	OSMO_ASSERT(tunnels_are(
-		"192.168.42.23 (TEI C 322=3/U 124=4)"
-		" <-> 192.168.43.34 (TEI C 766=7/U 568=8)"
+		"TEI=2:"
+		" 192.168.42.23 (TEI C=322 U=124)"
+		" <-> 192.168.43.34 (TEI C=766 U=568)"
 		" @21948\n"
-		"192.168.42.23 (TEI C 321=1/U 123=2)"
-		" <-> 192.168.43.34 (TEI C 765=5/U 567=6)"
+		"TEI=1:"
+		" 192.168.42.23 (TEI C=321 U=123)"
+		" <-> 192.168.43.34 (TEI C=765 U=567)"
 		" @21947\n"
 		));