gprs: Implement PURGE_MS GSUP messages

This commit implements the encoding and decoding of the messages

  - Purge MS Request
  - Purge MS Error
  - Purge MS Result

and adds corresponding tests.

Sponsored-by: On-Waves ehf
diff --git a/openbsc/include/openbsc/gprs_gsup_messages.h b/openbsc/include/openbsc/gprs_gsup_messages.h
index f1a9978..b63f74b 100644
--- a/openbsc/include/openbsc/gprs_gsup_messages.h
+++ b/openbsc/include/openbsc/gprs_gsup_messages.h
@@ -39,6 +39,7 @@
 	GPRS_GSUP_PDP_INFO_COMPL_IE		= 0x04,
 	GPRS_GSUP_PDP_INFO_IE			= 0x05,
 	GPRS_GSUP_CANCEL_TYPE_IE		= 0x06,
+	GPRS_GSUP_FREEZE_PTMSI_IE		= 0x07,
 	GPRS_GSUP_PDP_CONTEXT_ID_IE		= 0x10,
 	GPRS_GSUP_PDP_TYPE_IE			= 0x11,
 	GPRS_GSUP_ACCESS_POINT_NAME_IE		= 0x12,
@@ -92,6 +93,7 @@
 	enum gsm48_gmm_cause		cause;
 	enum gprs_gsup_cancel_type	cancel_type;
 	int				pdp_info_compl;
+	int				freeze_ptmsi;
 	struct gsm_auth_tuple		auth_tuples[GPRS_GSUP_MAX_NUM_AUTH_INFO];
 	size_t				num_auth_tuples;
 	struct gprs_gsup_pdp_info	pdp_infos[GPRS_GSUP_MAX_NUM_PDP_INFO];
diff --git a/openbsc/src/gprs/gprs_gsup_messages.c b/openbsc/src/gprs/gprs_gsup_messages.c
index 1dad74f..8996fe2 100644
--- a/openbsc/src/gprs/gprs_gsup_messages.c
+++ b/openbsc/src/gprs/gprs_gsup_messages.c
@@ -237,6 +237,10 @@
 			gsup_msg->pdp_info_compl = 1;
 			break;
 
+		case GPRS_GSUP_FREEZE_PTMSI_IE:
+			gsup_msg->freeze_ptmsi = 1;
+			break;
+
 		case GPRS_GSUP_PDP_CONTEXT_ID_IE:
 			/* When these IE appear in the top-level part of the
 			 * message, they are used by Delete Subscr Info to delete
@@ -381,6 +385,9 @@
 	if (gsup_msg->pdp_info_compl)
 		msgb_tlv_put(msg, GPRS_GSUP_PDP_INFO_COMPL_IE, 0, &u8);
 
+	if (gsup_msg->freeze_ptmsi)
+		msgb_tlv_put(msg, GPRS_GSUP_FREEZE_PTMSI_IE, 0, &u8);
+
 	for (idx = 0; idx < gsup_msg->num_pdp_infos; idx++) {
 		const struct gprs_gsup_pdp_info *pdp_info;
 
diff --git a/openbsc/tests/gprs/gprs_test.c b/openbsc/tests/gprs/gprs_test.c
index b8e9cbe..37dc832 100644
--- a/openbsc/tests/gprs/gprs_test.c
+++ b/openbsc/tests/gprs/gprs_test.c
@@ -471,6 +471,23 @@
 		TEST_IMSI_IE,
 	};
 
+	static const uint8_t purge_ms_req[] = {
+		0x0c,
+		TEST_IMSI_IE,
+	};
+
+	static const uint8_t purge_ms_err[] = {
+		0x0c,
+		TEST_IMSI_IE,
+		0x02, 0x01, 0x03, /* Illegal MS */
+	};
+
+	static const uint8_t purge_ms_res[] = {
+		0x0c,
+		TEST_IMSI_IE,
+		0x07, 0x00,
+	};
+
 	static const struct test {
 		char *name;
 		const uint8_t *data;
@@ -494,6 +511,12 @@
 			location_cancellation_err, sizeof(location_cancellation_err)},
 		{"Location Cancellation Result",
 			location_cancellation_res, sizeof(location_cancellation_res)},
+		{"Purge MS Request",
+			purge_ms_req, sizeof(purge_ms_req)},
+		{"Purge MS Error",
+			purge_ms_err, sizeof(purge_ms_err)},
+		{"Purge MS Result",
+			purge_ms_res, sizeof(purge_ms_res)},
 	};
 
 	printf("Test GSUP message decoding/encoding\n");
diff --git a/openbsc/tests/gprs/gprs_test.ok b/openbsc/tests/gprs/gprs_test.ok
index eda1f36..4825b67 100644
--- a/openbsc/tests/gprs/gprs_test.ok
+++ b/openbsc/tests/gprs/gprs_test.ok
@@ -24,4 +24,7 @@
   Testing Location Cancellation Request
   Testing Location Cancellation Error
   Testing Location Cancellation Result
+  Testing Purge MS Request
+  Testing Purge MS Error
+  Testing Purge MS Result
 Done.