anjana_sreekumar@infosys.com | 991c206 | 2020-01-08 11:42:57 +0530 | [diff] [blame^] | 1 | #include <iostream> |
| 2 | #include <memory> |
| 3 | #include <string> |
| 4 | #include <sstream> |
| 5 | #include <time.h> |
| 6 | #include <grpcpp/grpcpp.h> |
| 7 | |
| 8 | #include "mmeGrpc.grpc.pb.h" |
| 9 | |
| 10 | #include <controlBlock.h> |
| 11 | #include <contextManager/dataBlocks.h> |
| 12 | #include <contextManager/subsDataGroupManager.h> |
| 13 | #include <procedureStats.h> |
| 14 | |
| 15 | using grpc::Server; |
| 16 | using grpc::ServerBuilder; |
| 17 | using grpc::ServerContext; |
| 18 | using grpc::ServerReader; |
| 19 | using grpc::ServerReaderWriter; |
| 20 | using grpc::ServerWriter; |
| 21 | using grpc::Status; |
| 22 | using mmeGrpc::UeContextReqBuf; |
| 23 | using mmeGrpc::UeContextRespBuf; |
| 24 | using mmeGrpc::UeContextRespBuf_SessionContextRespBuf; |
| 25 | using mmeGrpc::MmeGrpcCli; |
| 26 | using mmeGrpc::Empty; |
| 27 | using mmeGrpc::ProcedureStatsRespBuf; |
| 28 | using mmeGrpc::EventInfoRespBuf; |
| 29 | using mmeGrpc::EventInfoRespBuf_EventInfoBuf; |
| 30 | |
| 31 | using namespace mme; |
| 32 | |
| 33 | const string UEStates[4]={ "NoState", "EpsAttached", "Detached", "Idle" }; |
| 34 | // Logic and data behind the server's behavior. |
| 35 | class MmeGrpcCliServiceImpl final : public MmeGrpcCli::Service { |
| 36 | Status GetUeContextInfo(SM::ControlBlock* controlBlk_p, UeContextRespBuf* reply) { |
| 37 | //time_t my_time = time(NULL); |
| 38 | // SM::ControlBlock* controlBlk_p = mme::SubsDataGroupManager::Instance()->findControlBlock((uint32_t)request->id()); |
| 39 | if (controlBlk_p) |
| 40 | { |
| 41 | UEContext* uecontext_p=dynamic_cast<UEContext*>(controlBlk_p->getPermDataBlock()); |
| 42 | if (uecontext_p != NULL) |
| 43 | { |
| 44 | //cout << "MY TIME " << ctime(&my_time); |
| 45 | |
| 46 | // Display IMSI |
| 47 | stringstream ss; |
| 48 | ss << uecontext_p->getImsi(); |
| 49 | reply->set_imsi(ss.str()); |
| 50 | |
| 51 | // MSISDN |
| 52 | ss.str(""); |
| 53 | ss << uecontext_p->getMsisdn(); |
| 54 | string ms(ss.str()); |
| 55 | ms.resize(10); |
| 56 | ms.shrink_to_fit(); |
| 57 | reply->set_msisdn(ms); |
| 58 | |
| 59 | // TAI |
| 60 | ss.str(""); |
| 61 | const TAI& tai = uecontext_p->getTai().tai_m; |
| 62 | ss << "MCC : "; |
| 63 | ss << (unsigned char)((tai.plmn_id.idx[0] & 0x0f) + 0x30); |
| 64 | ss << (unsigned char)((tai.plmn_id.idx[0] >> 4) + 0x30); |
| 65 | ss << (unsigned char)((tai.plmn_id.idx[1] & 0x0f) + 0x30); |
| 66 | ss << " MNC : "; |
| 67 | ss << (unsigned char)((tai.plmn_id.idx[2] & 0x0f) + 0x30); |
| 68 | ss << (unsigned char)((tai.plmn_id.idx[2] >> 4) + 0x30); |
| 69 | ss << " TAC : " << tai.tac ; |
| 70 | reply->set_tai(ss.str()); |
| 71 | |
| 72 | // Cell Identity |
| 73 | ss.str(""); |
| 74 | const CGI& cgi = uecontext_p->getUtranCgi().cgi_m; |
| 75 | ss << "0x" << std::hex << cgi.cell_id; |
| 76 | reply->set_eutran_cgi(ss.str()); |
| 77 | |
| 78 | reply->set_context_id(uecontext_p->getContextID()); |
| 79 | |
| 80 | reply->set_enb_ue_s1ap_id(uecontext_p->getS1apEnbUeId()); |
| 81 | |
| 82 | MmContext* mmCtxt = uecontext_p->getMmContext(); |
| 83 | UE_State_e uestate = mmCtxt->getMmState(); |
| 84 | |
| 85 | reply->set_ue_state(UEStates[uestate]); |
| 86 | |
| 87 | SessionContext* sessioncontext_p = uecontext_p->getSessionContext(); |
| 88 | if (sessioncontext_p != NULL) |
| 89 | { |
| 90 | UeContextRespBuf_SessionContextRespBuf* session_ctxt = reply->add_sessioncontext(); |
| 91 | if (session_ctxt) |
| 92 | { |
| 93 | // APN |
| 94 | const apn_name& apn = sessioncontext_p->getAccessPtName().apnname_m; |
| 95 | string apnStr((const char*)(apn.val), apn.len); |
| 96 | session_ctxt->set_apn(apnStr); |
| 97 | |
| 98 | // PDN address |
| 99 | const PAA& PdnAddr = sessioncontext_p->getPdnAddr().paa_m; |
| 100 | char ipStr[INET_ADDRSTRLEN]; |
| 101 | inet_ntop(AF_INET, &(PdnAddr.ip_type.ipv4), ipStr, INET_ADDRSTRLEN); |
| 102 | session_ctxt->set_pdn_address(ipStr); |
| 103 | |
| 104 | // Bearer ID |
| 105 | session_ctxt->set_bearer_id(5); |
| 106 | |
| 107 | // S11 SGW GTP-C TEID |
| 108 | const fteid& s11SgwCTeid = sessioncontext_p->getS11SgwCtrlFteid().fteid_m; |
| 109 | |
| 110 | ss.str(""); |
| 111 | memset(ipStr, 0, INET_ADDRSTRLEN); |
| 112 | uint32_t ip = ntohl(s11SgwCTeid.ip.ipv4.s_addr); |
| 113 | |
| 114 | inet_ntop(AF_INET, &(ip), ipStr, INET_ADDRSTRLEN); |
| 115 | ss << "IP " << ipStr << " TEID " << s11SgwCTeid.header.teid_gre; |
| 116 | session_ctxt->set_s11_sgw_gtpc_teid(ss.str()); |
| 117 | |
| 118 | // S5S8 PGW GTP-C TEID |
| 119 | const fteid& s5s8PgwCTeid = sessioncontext_p->getS5S8PgwCtrlFteid().fteid_m; |
| 120 | |
| 121 | ss.str(""); |
| 122 | memset(ipStr, 0, INET_ADDRSTRLEN); |
| 123 | ip = ntohl(s5s8PgwCTeid.ip.ipv4.s_addr); |
| 124 | |
| 125 | inet_ntop(AF_INET, &(ip), ipStr, INET_ADDRSTRLEN); |
| 126 | ss << "IP " << ipStr << " TEID " << s5s8PgwCTeid.header.teid_gre; |
| 127 | session_ctxt->set_s5_pgw_gtpc_teid(ss.str()); |
| 128 | |
| 129 | BearerContext* bearerCtxt = sessioncontext_p->getBearerContext(); |
| 130 | // S1U ENB TEID |
| 131 | const fteid& s1uEnbTeid = bearerCtxt->getS1uEnbUserFteid().fteid_m; |
| 132 | |
| 133 | ss.str(""); |
| 134 | memset(ipStr, 0, INET_ADDRSTRLEN); |
| 135 | ip = ntohl(s1uEnbTeid.ip.ipv4.s_addr); |
| 136 | |
| 137 | inet_ntop(AF_INET, &(ip), ipStr, INET_ADDRSTRLEN); |
| 138 | ss << "IP " << ipStr << " TEID " << s1uEnbTeid.header.teid_gre; |
| 139 | session_ctxt->set_s1u_enb_teid(ss.str()); |
| 140 | |
| 141 | // S1U SGW TEID |
| 142 | const fteid& s1uSgwTeid = bearerCtxt->getS1uSgwUserFteid().fteid_m; |
| 143 | ss.str(""); |
| 144 | memset(ipStr, 0, INET_ADDRSTRLEN); |
| 145 | ip = ntohl(s1uSgwTeid.ip.ipv4.s_addr); |
| 146 | |
| 147 | inet_ntop(AF_INET, &(ip), ipStr, INET_ADDRSTRLEN); |
| 148 | ss << "IP " << ipStr << " TEID " << s1uSgwTeid.header.teid_gre; |
| 149 | session_ctxt->set_s1u_sgw_teid(ss.str()); |
| 150 | |
| 151 | // S5-U PGW TEID |
| 152 | const fteid& s5uPgwTeid = bearerCtxt->getS5S8PgwUserFteid().fteid_m; |
| 153 | ss.str(""); |
| 154 | memset(ipStr, 0, INET_ADDRSTRLEN); |
| 155 | ip = ntohl(s5uPgwTeid.ip.ipv4.s_addr); |
| 156 | |
| 157 | inet_ntop(AF_INET, &(ip), ipStr, INET_ADDRSTRLEN); |
| 158 | ss << "IP " << ipStr << " TEID " << s5uPgwTeid.header.teid_gre; |
| 159 | session_ctxt->set_s5u_pgw_teid(ss.str()); |
| 160 | |
| 161 | } |
| 162 | } |
| 163 | } |
| 164 | } |
| 165 | return Status::OK; |
| 166 | |
| 167 | } |
| 168 | |
| 169 | Status GetUeContext(ServerContext* context, const UeContextReqBuf* request, |
| 170 | UeContextRespBuf* reply) override |
| 171 | { |
| 172 | SM::ControlBlock* controlBlk_p = mme::SubsDataGroupManager::Instance()->findControlBlock((uint32_t)request->id()); |
| 173 | GetUeContextInfo(controlBlk_p, reply); |
| 174 | |
| 175 | return Status::OK; |
| 176 | } |
| 177 | |
| 178 | Status ShowAllMobileContexts(ServerContext* context, const Empty* request, |
| 179 | ServerWriter<UeContextRespBuf>* writer) override |
| 180 | { |
| 181 | for (uint32_t i = 1; i <= 8000; i++) |
| 182 | { |
| 183 | SM::ControlBlock* controlBlk_p = mme::SubsDataGroupManager::Instance()->findControlBlock(i); |
| 184 | if (controlBlk_p != NULL && controlBlk_p->getPermDataBlock() != NULL) |
| 185 | { |
| 186 | UeContextRespBuf reply; |
| 187 | GetUeContextInfo(controlBlk_p, &reply); |
| 188 | writer->Write(reply); |
| 189 | } |
| 190 | } |
| 191 | return Status::OK; |
| 192 | } |
| 193 | |
| 194 | Status GetDebugUeContext(ServerContext* context, const UeContextReqBuf* request, |
| 195 | EventInfoRespBuf* reply) override { |
| 196 | SM::ControlBlock* controlBlk_p = mme::SubsDataGroupManager::Instance()->findControlBlock((uint32_t)request->id()); |
| 197 | if( controlBlk_p ) |
| 198 | { |
| 199 | UEContext* uecontext_p=dynamic_cast<UEContext*>(controlBlk_p->getPermDataBlock()); |
| 200 | if( uecontext_p ) |
| 201 | { |
| 202 | MmContext* mmCtxt = uecontext_p->getMmContext(); |
| 203 | UE_State_e uestate = mmCtxt->getMmState(); |
| 204 | reply->set_ue_state(UEStates[static_cast<int>(uestate)]); |
| 205 | } |
| 206 | deque<SM::debugEventInfo> evtQ = controlBlk_p->getDebugInfoQueue(); |
| 207 | for(auto it=evtQ.begin();it!=evtQ.end();it++) |
| 208 | { |
| 209 | EventInfoRespBuf_EventInfoBuf* EvtInfo = reply->add_eventinfo(); |
| 210 | string strEvent = Events[it->event]; |
| 211 | EvtInfo->set_event(strEvent); |
| 212 | string strState = States[it->state]; |
| 213 | EvtInfo->set_state(strState); |
| 214 | EvtInfo->set_time(ctime(&(it->evt_time))); |
| 215 | } |
| 216 | } |
| 217 | return Status::OK; |
| 218 | } |
| 219 | |
| 220 | Status GetProcStats(ServerContext* context,const Empty* request, |
| 221 | ProcedureStatsRespBuf* reply) override { |
| 222 | /*time_t my_time = time(NULL); |
| 223 | my_time = time(NULL); |
| 224 | cout << "Req recieved at server" << ctime(&my_time);*/ |
| 225 | reply->set_num_of_air_sent(ProcedureStats::num_of_air_sent); |
| 226 | reply->set_num_of_ulr_sent(ProcedureStats::num_of_ulr_sent); |
| 227 | reply->set_num_of_processed_aia(ProcedureStats::num_of_processed_aia); |
| 228 | reply->set_num_of_processed_ula(ProcedureStats::num_of_processed_ula); |
| 229 | reply->set_num_of_auth_req_to_ue_sent(ProcedureStats::num_of_auth_req_to_ue_sent); |
| 230 | reply->set_num_of_processed_auth_response(ProcedureStats::num_of_processed_auth_response); |
| 231 | reply->set_num_of_sec_mode_cmd_to_ue_sent(ProcedureStats::num_of_sec_mode_cmd_to_ue_sent); |
| 232 | reply->set_num_of_processed_sec_mode_resp(ProcedureStats::num_of_processed_sec_mode_resp); |
| 233 | reply->set_num_of_esm_info_req_to_ue_sent(ProcedureStats::num_of_esm_info_req_to_ue_sent); |
| 234 | reply->set_num_of_handled_esm_info_resp(ProcedureStats::num_of_handled_esm_info_resp); |
| 235 | reply->set_num_of_cs_req_to_sgw_sent(ProcedureStats::num_of_cs_req_to_sgw_sent); |
| 236 | reply->set_num_of_processed_cs_resp(ProcedureStats::num_of_processed_cs_resp); |
| 237 | reply->set_num_of_init_ctxt_req_to_ue_sent(ProcedureStats::num_of_init_ctxt_req_to_ue_sent); |
| 238 | reply->set_num_of_processed_init_ctxt_resp(ProcedureStats::num_of_processed_init_ctxt_resp); |
| 239 | reply->set_num_of_mb_req_to_sgw_sent(ProcedureStats::num_of_mb_req_to_sgw_sent); |
| 240 | reply->set_num_of_processed_attach_cmp_from_ue(ProcedureStats::num_of_processed_attach_cmp_from_ue); |
| 241 | reply->set_num_of_processed_mb_resp(ProcedureStats::num_of_processed_mb_resp); |
| 242 | reply->set_num_of_attach_done(ProcedureStats::num_of_attach_done); |
| 243 | reply->set_num_of_del_session_req_sent(ProcedureStats::num_of_del_session_req_sent); |
| 244 | reply->set_num_of_purge_req_sent(ProcedureStats::num_of_purge_req_sent); |
| 245 | reply->set_num_of_processed_del_session_resp(ProcedureStats::num_of_processed_del_session_resp); |
| 246 | reply->set_num_of_processed_pur_resp(ProcedureStats::num_of_processed_pur_resp); |
| 247 | reply->set_num_of_detach_accept_to_ue_sent(ProcedureStats::num_of_detach_accept_to_ue_sent); |
| 248 | reply->set_num_of_processed_detach_accept(ProcedureStats::num_of_processed_detach_accept); |
| 249 | reply->set_num_of_ue_ctxt_release(ProcedureStats::num_of_ue_ctxt_release); |
| 250 | reply->set_num_of_processed_ctxt_rel_resp(ProcedureStats::num_of_processed_ctxt_rel_resp); |
| 251 | reply->set_num_of_subscribers_attached(ProcedureStats::num_of_subscribers_attached); |
| 252 | reply->set_num_of_rel_access_bearer_req_sent(ProcedureStats::num_of_rel_access_bearer_req_sent); |
| 253 | reply->set_num_of_rel_access_bearer_resp_received(ProcedureStats::num_of_rel_access_bearer_resp_received); |
| 254 | reply->set_num_of_s1_rel_req_received(ProcedureStats::num_of_s1_rel_req_received); |
| 255 | reply->set_num_of_s1_rel_cmd_sent(ProcedureStats::num_of_s1_rel_cmd_sent); |
| 256 | reply->set_num_of_s1_rel_comp_received(ProcedureStats::num_of_s1_rel_comp_received); |
| 257 | reply->set_num_of_clr_received(ProcedureStats::num_of_clr_received); |
| 258 | reply->set_num_of_cla_sent(ProcedureStats::num_of_cla_sent); |
| 259 | reply->set_num_of_detach_req_to_ue_sent(ProcedureStats::num_of_detach_req_to_ue_sent); |
| 260 | reply->set_num_of_detach_accept_from_ue(ProcedureStats::num_of_detach_accept_from_ue); |
| 261 | reply->set_total_num_of_subscribers(ProcedureStats::total_num_of_subscribers); |
| 262 | reply->set_num_of_subscribers_detached(ProcedureStats::num_of_subscribers_detached); |
| 263 | reply->set_num_of_tau_response_to_ue_sent(ProcedureStats::num_of_tau_response_to_ue_sent); |
| 264 | |
| 265 | //reply->set_num_of_ddn_received(ProcedureStats::num_of_ddn_received); |
| 266 | return Status::OK; |
| 267 | } |
| 268 | |
| 269 | }; |
| 270 | |
| 271 | void * RunServer(void* data) { |
| 272 | std::string server_address("0.0.0.0:50051"); |
| 273 | MmeGrpcCliServiceImpl service; |
| 274 | |
| 275 | ServerBuilder builder; |
| 276 | // Listen on the given address without any authentication mechanism. |
| 277 | builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); |
| 278 | // Register "service" as the instance through which we'll communicate with |
| 279 | // clients. In this case it corresponds to an *synchronous* service. |
| 280 | builder.RegisterService(&service); |
| 281 | // Finally assemble the server. |
| 282 | std::unique_ptr<Server> server(builder.BuildAndStart()); |
| 283 | std::cout << "Server listening on " << server_address << std::endl; |
| 284 | |
| 285 | // Wait for the server to shutdown. Note that some other thread must be |
| 286 | // responsible for shutting down the server for this call to ever return. |
| 287 | server->Wait(); |
| 288 | |
| 289 | return NULL; |
| 290 | } |