gtphub: prepare: keep tunnel ref in gtp_packet_desc.

Rather than passing a tunnel pointer as function arguments, keep it in the
gtp_packet_desc struct passed around anyway.

Reason: in the next commit (will add sgsn_use_sender), I need the tunnel to be
passed back out to gtphub_handle_buf(), and besides simplifying existing code,
this also makes passing the tunnel back out trivial.

Sponsored-by: On-Waves ehi
diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c
index 6428c60..e96088c 100644
--- a/openbsc/src/gprs/gtphub.c
+++ b/openbsc/src/gprs/gtphub.c
@@ -91,6 +91,7 @@
 	int rc; /* enum gtp_rc */
 	unsigned int plane_idx;
 	unsigned int side_idx;
+	struct gtphub_tunnel *tun;
 	time_t timestamp;
 	union gtpie_member *ie[GTPIE_SIZE];
 };
@@ -1416,7 +1417,7 @@
 	osmo_static_assert((GTPH_PLANE_CTRL == 0) && (GTPH_PLANE_USER == 1),
 			   plane_nrs_match_GSN_addr_IE_indices);
 
-	struct gtphub_tunnel *tun = NULL;
+	struct gtphub_tunnel *tun = p->tun;
 
 	if (p->type == GTP_CREATE_PDP_REQ) {
 		if (p->side_idx != GTPH_SIDE_SGSN) {
@@ -1426,8 +1427,18 @@
 			return -1;
 		}
 
+		if (tun) {
+			LOG(LOGL_ERROR, "Not implemented: Received"
+			    " Create PDP Context Request for an already"
+			    " established tunnel:"
+			    " from %s, tunnel %s\n",
+			    gtphub_port_str(from_ctrl),
+			    gtphub_tunnel_str(p->tun));
+			return -1;
+		}
+
 		/* A new tunnel. */
-		tun = gtphub_tunnel_new();
+		p->tun = tun = gtphub_tunnel_new();
 		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
@@ -1457,14 +1468,15 @@
 
 	for (plane_idx = 0; plane_idx < 2; plane_idx++) {
 		int rc;
-		struct gsn_addr addr_from_ie;
+		struct gsn_addr use_addr;
+		uint16_t use_port;
 		uint32_t tei_from_ie;
 		int ie_idx;
 
 		/* Fetch GSN Address and TEI from IEs. As ensured by above
 		 * static asserts, plane_idx corresponds to the GSN Address IE
 		 * index (the first one = 0 = ctrl, second one = 1 = user). */
-		rc = gsn_addr_get(&addr_from_ie, p, plane_idx);
+		rc = gsn_addr_get(&use_addr, p, plane_idx);
 		if (rc) {
 			LOG(LOGL_ERROR, "Cannot read %s GSN Address IE\n",
 			    gtphub_plane_idx_names[plane_idx]);
@@ -1472,8 +1484,8 @@
 		}
 		LOG(LOGL_DEBUG, "Read %s GSN addr %s (%d)\n",
 		    gtphub_plane_idx_names[plane_idx],
-		    gsn_addr_to_str(&addr_from_ie),
-		    addr_from_ie.len);
+		    gsn_addr_to_str(&use_addr),
+		    use_addr.len);
 
 		ie_idx = gtpie_getie(p->ie, ie_type[plane_idx], 0);
 		if (ie_idx < 0) {
@@ -1490,11 +1502,12 @@
 			tei_from_ie = ntoh32(p->ie[ie_idx]->tv4.v);
 
 		/* Make sure an entry for this peer address with default port
-		 * exists */
-		struct gtphub_peer_port *peer_from_ie =
-			gtphub_port_have(hub, &hub->to_gsns[side_idx][plane_idx],
-					 &addr_from_ie,
-					 gtphub_plane_idx_default_port[plane_idx]);
+		 * exists. */
+		struct gtphub_peer_port *peer_from_ie;
+		use_port = gtphub_plane_idx_default_port[plane_idx];
+		peer_from_ie = gtphub_port_have(hub,
+						&hub->to_gsns[side_idx][plane_idx],
+						&use_addr, use_port);
 
 		gtphub_tunnel_endpoint_set_peer(&tun->endpoint[side_idx][plane_idx],
 						peer_from_ie);
@@ -1575,10 +1588,11 @@
 
 static int gtphub_handle_delete_pdp_ctx(struct gtphub *hub,
 					struct gtp_packet_desc *p,
-					struct gtphub_tunnel *known_tun,
 					struct gtphub_peer_port *from_ctrl,
 					struct gtphub_peer_port *to_ctrl)
 {
+	struct gtphub_tunnel *known_tun = p->tun;
+
 	if (p->type == GTP_DELETE_PDP_REQ) {
 		if (!known_tun) {
 			LOG(LOGL_ERROR, "Cannot find tunnel for Delete PDP Context Request.\n");
@@ -1673,6 +1687,7 @@
 
 		LOG(LOGL_DEBUG, "Delete PDP Context: removing tunnel %s\n",
 		    gtphub_tunnel_str(known_tun));
+		p->tun = NULL;
 		expiring_item_del(&known_tun->expiry_entry);
 	}
 
@@ -1694,7 +1709,6 @@
  * the packet p. */
 static int gtphub_handle_pdp_ctx(struct gtphub *hub,
 				 struct gtp_packet_desc *p,
-				 struct gtphub_tunnel *known_tun,
 				 struct gtphub_peer_port *from_ctrl,
 				 struct gtphub_peer_port *to_ctrl)
 {
@@ -1708,7 +1722,7 @@
 
 	case GTP_DELETE_PDP_REQ:
 	case GTP_DELETE_PDP_RSP:
-		return gtphub_handle_delete_pdp_ctx(hub, p, known_tun,
+		return gtphub_handle_delete_pdp_ctx(hub, p,
 						    from_ctrl, to_ctrl);
 
 	case GTP_UPDATE_PDP_REQ:
@@ -1912,8 +1926,7 @@
 			struct gtphub_peer_port *from,
 			struct gtphub_peer_port *to_proxy,
 			struct gtphub_peer_port **final_unmapped,
-			struct gtphub_peer_port **unmapped_from_seq,
-			struct gtphub_tunnel **unmapped_from_tun)
+			struct gtphub_peer_port **unmapped_from_seq)
 {
 	/* Always (try to) unmap sequence and TEI numbers, which need to be
 	 * replaced in the packet. Either way, give precedence to the proxy, if
@@ -1921,19 +1934,17 @@
 
 	if (unmapped_from_seq)
 		*unmapped_from_seq = NULL;
-	if (unmapped_from_tun)
-		*unmapped_from_tun = NULL;
 	if (final_unmapped)
 		*final_unmapped = NULL;
+	p->tun = NULL;
 
 	struct gtphub_peer_port *from_seq = NULL;
 	struct gtphub_peer_port *from_tei = NULL;
 	struct gtphub_peer_port *unmapped = NULL;
-	struct gtphub_tunnel *tun = NULL;
 
 	from_seq = gtphub_unmap_seq(p, from);
 
-	if (gtphub_unmap_header_tei(&from_tei, &tun, hub, p, from) < 0)
+	if (gtphub_unmap_header_tei(&from_tei, &p->tun, hub, p, from) < 0)
 		return -1;
 
 	struct gtphub_peer *from_peer = from->peer_addr->peer;
@@ -1970,8 +1981,6 @@
 
 	if (unmapped_from_seq)
 		*unmapped_from_seq = from_seq;
-	if (unmapped_from_tun)
-		*unmapped_from_tun = tun;
 	if (final_unmapped)
 		*final_unmapped = unmapped;
 	return 0;
@@ -2146,10 +2155,9 @@
 
 	struct gtphub_peer_port *to_peer_from_seq;
 	struct gtphub_peer_port *to_peer;
-	struct gtphub_tunnel *tun;
 	if (gtphub_unmap(hub, &p, from_peer,
 			 hub->proxy[other_side_idx(side_idx)][plane_idx],
-			 &to_peer, &to_peer_from_seq, &tun)
+			 &to_peer, &to_peer_from_seq)
 	    != 0) {
 		return -1;
 	}
@@ -2169,10 +2177,15 @@
 		/* This may be a Create PDP Context response. If it is, there
 		 * are other addresses in the GTP message to set up apart from
 		 * the sender. */
-		if (gtphub_handle_pdp_ctx(hub, &p, tun, from_peer, to_peer)
+		if (gtphub_handle_pdp_ctx(hub, &p, from_peer, to_peer)
 		    != 0)
 			return -1;
 	}
+	
+	/* Either to_peer was resolved from an existing tunnel,
+	 * or a PDP Ctx and thus a tunnel has just been created,
+	 * or the tunnel has been deleted due to this message. */
+	OSMO_ASSERT(p.tun || (p.type == GTP_DELETE_PDP_RSP));
 
 	gtphub_check_restart_counter(hub, &p, from_peer);
 	gtphub_map_restart_counter(hub, &p);