Update TS to enforce A1 policy on throughput predictions

TS xApp does not enforce the A1 Policy "threshold" to send CONTROL
messages. This feature was disabled in previous changes to allow
interoperability with other xApps in the TS use case.

This change re-enables the "threshold" policy in TS xApp.
If one of the cells has a higher throughput prediction above
a given "threshold" percentage than the current serving cell,
then TS sends a CONTROL request to hanfoff the UE to the cell
with the higher throughput.

Issue-ID: RICAPP-188

Signed-off-by: Alexandre Huff <alexandrehuff@utfpr.edu.br>
Change-Id: I1bdaa80407aee6873107ea4c70e1781df6bbb7af
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f55aa94..faf843b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -34,7 +34,7 @@
 
 set( major_version "1" )		# until CI supports auto tagging; must hard set
 set( minor_version "2" )
-set( patch_level "2" )
+set( patch_level "3" )
 
 set( install_root "${CMAKE_INSTALL_PREFIX}" )
 set( install_inc "/usr/local/include" )
diff --git a/container-tag.yaml b/container-tag.yaml
index f020aa4..74c7376 100644
--- a/container-tag.yaml
+++ b/container-tag.yaml
@@ -1,3 +1,3 @@
 # this is used by CI jobs to apply a tag when it builds the image
 ---
-tag: '1.2.2'
+tag: '1.2.3'
diff --git a/docs/rel-notes.rst b/docs/rel-notes.rst
index 4bece11..f529d07 100644
--- a/docs/rel-notes.rst
+++ b/docs/rel-notes.rst
@@ -9,6 +9,10 @@
 Traffic Steering xAPP
 =====================
 
+2022 May 10 Version 1.2.3
+--------------------------
+        Update TS to enforce A1 policy on throughput predictions
+
 2022 Mar 26 Version 1.2.2
 --------------------------
         Fix dummy values in gRPC message sent to RC xApp
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index d25c714..72525cf 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -63,8 +63,6 @@
         }
     ]
 
-.. ``[{"du-id": 1010, "ue-id": "Train passenger 2", "measTimeStampRf": 1620835470108, "Degradation": "RSRP RSSINR"}]``
-
 Sending QoE Prediction Request
 ==============================
 
@@ -73,8 +71,6 @@
 The RMR Message Type is 30000.
 The following is an example message body:
 
-.. {"UEPredictionSet" : ["12345"]}
-
 .. code-block::
 
     { "UEPredictionSet": ["Train passenger 2"] }
@@ -82,9 +78,7 @@
 Receiving QoE Prediction
 ========================
 
-Traffic Steering xApp defines a callback for QoE Prediction received from QP xApp.  The RMR message type is 30002.  The following is an example message body:
-
-.. {"12345" : { "310-680-200-555001" : [ 2000000 , 1200000 ] , "310-680-200-555002" : [ 800000 , 400000 ] , "310-680-200-555003" : [ 800000 , 400000 ]  } }
+Traffic Steering xApp defines a callback for QoE Prediction received from QP xApp. The RMR message type is 30002. The following is an example message body:
 
 .. code-block::
 
@@ -96,11 +90,12 @@
         }
     }
 
-This message provides predictions for UE ID "Train passenger 2".  For its service cell and neighbor cells, it lists an array containing two elements: DL Throughput and UL Throughput predictions.
+This message provides throughput predictions of three cells for the UE ID "Train passenger 2". For each service cell, it lists an array containing two elements: DL Throughput and UL Throughput predictions.
 
-Traffic Steering xApp checks for the Service Cell ID for UE ID, and determines whether the predicted throughput is higher in a neighbor cell.
+Traffic Steering xApp checks for the Service Cell ID for UE ID, and determines if the predicted throughput is higher in a neighbor cell.
 The first cell in this prediction message is assumed to be the serving cell.
 
+If predicted throughput is higher than the A1 policy "*threshold*" in a given neighbor cell, Traffic Steering sends the CONTROL message to a given endpoint.
 Since RC xApp is not mandatory for the Traffic Steering use case, TS xApp sends CONTROL messages using either REST or gRPC calls.
 The CONTROL endpoint is set up in the xApp descriptor file called "config-file.json". Please, check out the "schema.json" file for configuration examples.
 
@@ -144,5 +139,5 @@
     }
 
 TS xApp also requires to fetch additional RAN information from the E2 Manager to communicate with RC xApp.
-By default, TS xApp requests information to the default endpoint of E2 Manager in the Kubernetes cluster.
-Still, the default E2 Manager endpoint from TS can be changed using the env variable "SERVICE_E2MGR_HTTP_BASE_URL".
+By default, TS xApp requests information to the default endpoint of E2 Manager in the Kubernetes cluster. Currently, this is done once on startup.
+Finally, the default E2 Manager endpoint from TS can be changed using the env variable "SERVICE_E2MGR_HTTP_BASE_URL".
diff --git a/src/ts_xapp/ts_xapp.cpp b/src/ts_xapp/ts_xapp.cpp
index 6bb05b7..e4a06e7 100644
--- a/src/ts_xapp/ts_xapp.cpp
+++ b/src/ts_xapp/ts_xapp.cpp
@@ -92,7 +92,7 @@
 std::unique_ptr<Xapp> xfw;
 std::unique_ptr<api::MsgComm::Stub> rc_stub;
 
-int rsrp_threshold = 0;
+int downlink_threshold = 0;  // A1 policy type 20008 (in percentage)
 
 // scoped enum to identify which API is used to send control messages
 enum class TsControlApi { REST, gRPC };
@@ -115,6 +115,10 @@
 }; */
 
 struct PolicyHandler : public BaseReaderHandler<UTF8<>, PolicyHandler> {
+  /*
+    Assuming we receive the following payload from A1 Mediator
+    {"operation": "CREATE", "policy_type_id": 20008, "policy_instance_id": "tsapolicy145", "payload": {"threshold": 5}}
+  */
   unordered_map<string, string> cell_pred;
   std::string ue_id;
   bool ue_id_found = false;
@@ -426,13 +430,9 @@
 } */
 
 void policy_callback( Message& mbuf, int mtype, int subid, int len, Msg_component payload,  void* data ) {
-
-  int response_to = 0;	 // max timeout wating for a response
-  int rmtype;		// received message type
-
   string arg ((const char*)payload.get(), len); // RMR payload might not have a nil terminanted char
 
-  cout << "[INFO] Policy Callback got a message, type=" << mtype << ", length="<< len << "\n";
+  cout << "[INFO] Policy Callback got a message, type=" << mtype << ", length=" << len << "\n";
   cout << "[INFO] Payload is " << arg << endl;
 
   PolicyHandler handler;
@@ -442,8 +442,8 @@
 
   //Set the threshold value
   if (handler.found_threshold) {
-    cout << "[INFO] Setting RSRP Threshold to A1-P value: " << handler.threshold << endl;
-    rsrp_threshold = handler.threshold;
+    cout << "[INFO] Setting Threshold for A1-P value: " << handler.threshold << "%\n";
+    downlink_threshold = handler.threshold;
   }
 
 }
@@ -614,7 +614,12 @@
 
   }
 
-  if ( highest_throughput > serving_cell_throughput ) {
+  float thresh = 0;
+  if( downlink_threshold > 0 ) {  // we also take into account the threshold in A1 policy type 20008
+    thresh = serving_cell_throughput * (downlink_threshold / 100.0);
+  }
+
+  if ( highest_throughput > ( serving_cell_throughput + thresh ) ) {
 
     // sending a control request message
     if ( ts_control_api == TsControlApi::REST ) {
diff --git a/xapp-descriptor/config-file.json b/xapp-descriptor/config-file.json
index e38cecf..76561c2 100644
--- a/xapp-descriptor/config-file.json
+++ b/xapp-descriptor/config-file.json
@@ -1,57 +1,57 @@
 {
-        "xapp_name": "trafficxapp",
-        "version": "1.2.2",
-        "containers": [
-            {
-                "name": "trafficxapp",
-                "image": {
-                    "registry": "nexus3.o-ran-sc.org:10002",
-                    "name": "o-ran-sc/ric-app-ts",
-                    "tag": "1.2.2"
-                }
+    "xapp_name": "trafficxapp",
+    "version": "1.2.3",
+    "containers": [
+        {
+            "name": "trafficxapp",
+            "image": {
+                "registry": "nexus3.o-ran-sc.org:10002",
+                "name": "o-ran-sc/ric-app-ts",
+                "tag": "1.2.3"
             }
-        ],
-        "messaging": {
-            "ports": [
-                {
-                    "name": "rmr-data",
-                    "container": "trafficxapp",
-                    "port": 4560,
-                    "rxMessages": [
-                        "TS_QOE_PREDICTION",
-                        "A1_POLICY_REQ",
-                        "TS_ANOMALY_UPDATE"
-                    ],
-                    "txMessages": [ "TS_UE_LIST", "TS_ANOMALY_ACK" ],
-                    "policies": [20008],
-                    "description": "rmr receive data port for trafficxapp"
-                },
-                {
-                    "name": "rmr-route",
-                    "container": "trafficxapp",
-                    "port": 4561,
-                    "description": "rmr route port for trafficxapp"
-                }
-            ]
-        },
-        "rmr": {
-            "protPort": "tcp:4560",
-            "maxSize": 2072,
-            "numWorkers": 1,
-            "txMessages": [
-                "TS_UE_LIST",
-                "TS_ANOMALY_ACK"
-            ],
-            "rxMessages": [
-                "TS_QOE_PREDICTION",
-                "A1_POLICY_REQ",
-                "TS_ANOMALY_UPDATE"
-            ],
-            "policies": [20008]
-        },
-        "controls": {
-            "ts_control_api": "grpc",
-            "ts_control_ep": "localhost:50051"
         }
-
+    ],
+    "messaging": {
+        "ports": [
+            {
+                "name": "rmr-data",
+                "container": "trafficxapp",
+                "port": 4560,
+                "rxMessages": [
+                    "TS_QOE_PREDICTION",
+                    "A1_POLICY_REQ",
+                    "TS_ANOMALY_UPDATE"
+                ],
+                "txMessages": [ "TS_UE_LIST", "TS_ANOMALY_ACK" ],
+                "policies": [20008],
+                "description": "rmr receive data port for trafficxapp"
+            },
+            {
+                "name": "rmr-route",
+                "container": "trafficxapp",
+                "port": 4561,
+                "description": "rmr route port for trafficxapp"
+            }
+        ]
+    },
+    "rmr": {
+        "protPort": "tcp:4560",
+        "maxSize": 2072,
+        "numWorkers": 1,
+        "txMessages": [
+            "TS_UE_LIST",
+            "TS_ANOMALY_ACK"
+        ],
+        "rxMessages": [
+            "TS_QOE_PREDICTION",
+            "A1_POLICY_REQ",
+            "TS_ANOMALY_UPDATE"
+        ],
+        "policies": [20008]
+    },
+    "controls": {
+        "ts_control_api": "rest",
+        "ts_control_ep": "http://127.0.0.1:5000/api/echo"
     }
+
+}