Phase 2 of image generation prep
[ric-app/ts.git] / src / ts_xapp / ts_xapp.cpp
1 // vi: ts=4 sw=4 noet:
2 /*
3 ==================================================================================
4         Copyright (c) 2020 Nokia
5         Copyright (c) 2020 AT&T Intellectual Property.
6
7    Licensed under the Apache License, Version 2.0 (the "License");
8    you may not use this file except in compliance with the License.
9    You may obtain a copy of the License at
10
11        http://www.apache.org/licenses/LICENSE-2.0
12
13    Unless required by applicable law or agreed to in writing, software
14    distributed under the License is distributed on an "AS IS" BASIS,
15    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16    See the License for the specific language governing permissions and
17    limitations under the License.
18 ==================================================================================
19 */
20
21 /*
22         Mnemonic:       ts_xapp.cpp
23         Abstract:       Traffic Steering xApp;
24                                1. Receives A1 Policy
25                                2. Queries SDL to decide which UE to attempt Traffic Steering for
26                                3. Requests prediction for UE throughput on current and neighbor cells
27                                4. Receives prediction
28                                5. Optionally exercises Traffic Steering action over E2
29
30         Date:           22 April 2020
31         Author:         Ron Shacham
32                 
33 */
34
35 #include <stdio.h>
36 #include <string.h>
37 #include <unistd.h>
38
39 #include <iostream>
40 #include <memory>
41
42 #include <sdl/syncstorage.hpp>
43 #include <set>
44 #include <map>
45 #include <vector>
46 #include <string>
47
48 #include "ricxfcpp/xapp.hpp"
49
50 using Namespace = std::string;
51 using Key = std::string;
52 using Data = std::vector<uint8_t>;
53 using DataMap = std::map<Key, Data>;
54 using Keys = std::set<Key>;
55
56
57 // ----------------------------------------------------------
58
59 std::unique_ptr<Xapp> xfw;
60
61
62 void policy_callback( Message& mbuf, int mtype, int subid, int len, Msg_component payload,  void* data ) {
63
64   long now;
65   long total_count;
66
67   int sz;
68   int i;
69
70   int response_to = 0;   // max timeout wating for a response
71
72   int send_mtype = 0;
73   int rmtype;                                                   // received message type
74   int delay = 1000000;                          // mu-sec delay; default 1s
75
76   std::unique_ptr<Message> msg;
77   Msg_component send_payload;                           // special type of unique pointer to the payload
78   
79   fprintf( stderr, "Policy Callback got a message, type=%d , length=%d\n" , mtype, len);
80   fprintf(stderr, "payload is %s\n", payload.get());
81   
82   //fprintf( stderr, "callback 1 got a message type = %d len = %d\n", mtype, len );
83   mbuf.Send_response( 101, -1, 5, (unsigned char *) "OK1\n" );  // validate that we can use the same buffer for 2 rts calls
84   mbuf.Send_response( 101, -1, 5, (unsigned char *) "OK2\n" );
85
86   mtype = 0;
87
88   fprintf(stderr, "cb 1\n");
89
90   msg = xfw->Alloc_msg( 2048 );
91   
92   sz = msg->Get_available_size();  // we'll reuse a message if we received one back; ensure it's big enough
93   if( sz < 2048 ) {
94     fprintf( stderr, "<SNDR> fail: message returned did not have enough size: %d [%d]\n", sz, i );
95     exit( 1 );
96   }
97
98   fprintf(stderr, "cb 2");
99   
100   send_payload = msg->Get_payload(); // direct access to payload
101   snprintf( (char *) send_payload.get(), 2048, "{\"UEPredictionSet\" : [\"222\", \"333\", \"444\"]}" ); 
102
103   fprintf(stderr, "cb 3");    
104   
105   // payload updated in place, nothing to copy from, so payload parm is nil
106   if ( ! msg->Send_msg( mtype, Message::NO_SUBID, strlen( (char *) send_payload.get() )+1, NULL )) {
107     fprintf( stderr, "<SNDR> send failed: %d\n", msg->Get_state() );
108   }
109
110   fprintf(stderr, "cb 4");    
111
112   /*
113   msg = xfw->Receive( response_to );
114   if( msg != NULL ) {
115     rmtype = msg->Get_mtype();
116     send_payload = msg->Get_payload();
117     fprintf( stderr, "got: mtype=%d payload=(%s)\n", rmtype, (char *) send_payload.get() );
118   } 
119   */  
120   
121 }
122
123
124 void prediction_callback( Message& mbuf, int mtype, int subid, int len, Msg_component payload,  void* data ) {
125
126   long now;
127   long total_count;
128
129   int sz;
130   int i;
131
132   int response_to = 0;   // max timeout wating for a response
133
134   int send_mtype = 0;
135   int rmtype;                                                   // received message type
136   int delay = 1000000;                          // mu-sec delay; default 1s
137
138   std::unique_ptr<Message> msg;
139   Msg_component send_payload;                           // special type of unique pointer to the payload
140   
141   fprintf( stderr, "Prediction Callback got a message, type=%d , length=%d\n" , mtype, len);
142   fprintf(stderr, "payload is %s\n", payload.get());
143   
144   mbuf.Send_response( 101, -1, 5, (unsigned char *) "OK1\n" );  // validate that we can use the same buffer for 2 rts calls
145   mbuf.Send_response( 101, -1, 5, (unsigned char *) "OK2\n" );
146
147   mtype = 0;
148
149   fprintf(stderr, "cb 1\n");
150   
151 }
152
153
154
155 extern int main( int argc, char** argv ) {
156
157   std::unique_ptr<Message> msg;
158   Msg_component payload;                                // special type of unique pointer to the payload
159
160   int nthreads = 1;
161
162   int response_to = 0;   // max timeout wating for a response  
163
164   int delay = 1000000;                          // mu-sec delay; default 1s  
165
166   char* port = (char *) "4560";
167
168   int ai;  
169   
170   ai = 1;
171   while( ai < argc ) {                          // very simple flag processing (no bounds/error checking)
172     if( argv[ai][0] != '-' )  {
173       break;
174     }
175     
176     switch( argv[ai][1] ) {                     // we only support -x so -xy must be -x -y
177     case 'd':                                   // delay between messages (mu-sec)
178       delay = atoi( argv[ai+1] );
179       ai++;
180       break;
181       
182     case 'p': 
183       port = argv[ai+1];        
184       ai++;
185       break;
186       
187     case 't':                                   // timeout in seconds; we need to convert to ms for rmr calls
188       response_to = atoi( argv[ai+1] ) * 1000;
189       ai++;
190       break;
191     }
192     ai++;
193   }
194   
195   fprintf( stderr, "<XAPP> response timeout set to: %d\n", response_to );
196   fprintf( stderr, "<XAPP> listening on port: %s\n", port );
197   
198   xfw = std::unique_ptr<Xapp>( new Xapp( port, true ) ); // new xAPP thing; wait for a route table
199
200   fprintf(stderr, "code1\n");
201   
202   xfw->Add_msg_cb( 20010, policy_callback, NULL );
203   xfw->Add_msg_cb( 30002, prediction_callback, NULL );
204
205   fprintf(stderr, "code2\n");
206
207   std::string sdl_namespace_u = "TS-UE-metrics";
208   std::string sdl_namespace_c = "TS-cell-metrics";
209
210   fprintf(stderr, "code5\n");
211   
212   std::unique_ptr<shareddatalayer::SyncStorage> sdl(shareddatalayer::SyncStorage::create());
213
214   Namespace nsu(sdl_namespace_u);
215   Namespace nsc(sdl_namespace_c);
216
217     /*
218
219   fprintf(stderr, "before sdl set\n");
220   
221   try{
222     //connecting to the Redis and generating a random key for namespace "hwxapp"
223     fprintf(stderr, "IN SDL Set Data");
224     //    std::string data_string = "{\"rsrp\" : -110}";
225
226
227     std::string data_string = "{\"CellID\": \"310-680-200-555001\", \"MeasTimestampPDCPBytes\": \"2020-03-18 02:23:18.220\", \"MeasPeriodPDCPBytes\": 20, \"PDCPBytesDL\": 2000000, \"PDCPBytesUL\": 1200000, \"MeasTimestampAvailPRB\": \"2020-03-18 02:23:18.220\", \"MeasPeriodAvailPRB\": 20, \"AvailPRBDL\": 30, \"AvailPRBUL\": 50  }";
228       
229     DataMap dmap;
230     //    char key[4]="abc";
231     char key[] = "310-680-200-555001";
232     std::cout << "KEY: "<< key << std::endl;
233     Key k = key;
234     Data d;
235     //    uint8_t num = 101;
236     d.assign(data_string.begin(), data_string.end());
237     //    d.push_back(num);
238     dmap.insert({k,d});
239
240     sdl->set(nsc, dmap);
241
242     data_string = "{ \"CellID\": \"310-680-200-555002\", \"MeasTimestampPDCPBytes\": \"2020-03-18 02:23:18.220\", \"MeasPeriodPDCPBytes\": 20, \"PDCPBytesDL\": 800000, \"PDCPBytesUL\": 400000, \"MeasTimestampAvailPRB\": \"2020-03-18 02:23:18.220\", \"MeasPeriodAvailPRB\": 20, \"AvailPRBDL\": 30, \"AvailPRBUL\": 45  }";
243
244     Data d2;
245     DataMap dmap2;    
246     char key2[] = "310-680-200-555002";
247     std::cout << "KEY: "<< key2 << std::endl;
248     Key k2 = key2;
249     d2.assign(data_string.begin(), data_string.end());
250     //    d.push_back(num);
251     dmap2.insert({k2,d});
252
253     sdl->set(nsc, dmap2);
254
255
256
257     std::string data_string = "{ \"CellID\": \"310-680-200-555003\", \"MeasTimestampPDCPBytes\": \"2020-03-18 02:23:18.220\", \"MeasPeriodPDCPBytes\": 20, \"PDCPBytesDL\": 800000, \"PDCPBytesUL\": 400000, \"MeasTimestampAvailPRB\": \"2020-03-18 02:23:18.220\", \"MeasPeriodAvailPRB\": 20, \"AvailPRBDL\": 30, \"AvailPRBUL\": 45  }";
258
259     Data d3;
260     DataMap dmap3;
261     char key3[] = "310-680-200-555003";
262     std::cout << "KEY: "<< key3 << std::endl;
263     Key k3 = key3;
264     d3.assign(data_string.begin(), data_string.end());
265     //    d.push_back(num);
266     dmap3.insert({k3,d3});
267
268     sdl->set(nsc, dmap3);
269
270
271
272     data_string = "{ \"UEID\": 12345, \"ServingCellID\": \"310-680-200-555002\", \"MeasTimestampUEPDCPBytes\": \"2020-03-18 02:23:18.220\", \"MeasPeriodUEPDCPBytes\": 20,\"UEPDCPBytesDL\": 250000,\"UEPDCPBytesUL\": 100000, \"MeasTimestampUEPRBUsage\": \"2020-03-18 02:23:18.220\", \"MeasPeriodUEPRBUsage\": 20, \"UEPRBUsageDL\": 10, \"UEPRBUsageUL\": 30, \"MeasTimestampRF\": \"2020-03-18 02:23:18.210\",\"MeasPeriodRF\": 40, \"ServingCellRF\": [-115,-16,-5], \"NeighborCellRF\": [  {\"CID\": \"310-680-200-555001\",\"Cell-RF\": [-90,-13,-2.5 ] }, {\"CID\": \"310-680-200-555003\",   \"Cell-RF\": [-140,-17,-6 ] } ] }";
273       
274     Data d4;
275     DataMap dmap4;
276     char key4[] = "12345";
277     std::cout << "KEY: "<< key << std::endl;
278     d4.assign(data_string.begin(), data_string.end());
279     Key k4 = key4;
280     //    d.push_back(num);
281     dmap4.insert({k4,d4});
282
283     sdl->set(nsu, dmap4);
284
285     
286   }
287   catch(...){
288     fprintf(stderr,"SDL Error in Set Data for Namespace");
289     return false;
290   }
291   
292   fprintf(stderr, "after sdl set\n");
293
294     */
295
296   fprintf(stderr, "before sdl get\n");
297
298
299   std::string prefix2="310";
300   Keys K = sdl->findKeys(nsc, prefix2);     // just the prefix
301   DataMap Dk = sdl->get(nsc, K);
302
303   std::cout << "K contains " << K.size() << " elements.\n";  
304
305   fprintf(stderr, "before forloop\n");
306
307   for(auto si=K.begin();si!=K.end();++si){
308     std::vector<uint8_t> val_v = Dk[(*si)]; // 4 lines to unpack a string
309     char val[val_v.size()+1];                               // from Data
310     int i;
311     for(i=0;i<val_v.size();++i) val[i] = (char)(val_v[i]);
312     val[i]='\0';
313     fprintf(stderr, "KEYS and Values %s = %s\n",(*si).c_str(), val);
314   }
315
316
317   std::string prefix3="12";
318   Keys K2 = sdl->findKeys(nsu, prefix3);     // just the prefix
319   DataMap Dk2 = sdl->get(nsu, K2);
320
321   std::cout << "K contains " << K2.size() << " elements.\n";  
322
323   fprintf(stderr, "before forloop\n");
324
325   for(auto si=K2.begin();si!=K2.end();++si){
326     std::vector<uint8_t> val_v = Dk2[(*si)]; // 4 lines to unpack a string
327     char val[val_v.size()+1];                               // from Data
328     int i;
329     for(i=0;i<val_v.size();++i) val[i] = (char)(val_v[i]);
330     val[i]='\0';
331     fprintf(stderr, "KEYS and Values %s = %s\n",(*si).c_str(), val);
332   }  
333   
334
335   fprintf(stderr, "after sdl get\n");
336
337   xfw->Run( nthreads );
338
339   fprintf(stderr, "code3\n");  
340   
341   msg = xfw->Alloc_msg( 2048 );
342
343   fprintf(stderr, "code4\n");    
344
345   
346 }