/* * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The OpenAirInterface Software Alliance licenses this file to You under * the OAI Public License, Version 1.1 (the "License"); you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://www.openairinterface.org/?page_id=698 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ #include <string.h> #include <math.h> #include <execinfo.h> #include <signal.h> #include <unistd.h> #include <getopt.h> //#include "SIMULATION/TOOLS/defs.h" #include "PHY/types.h" #include "PHY/defs.h" #include "PHY/vars.h" #include "MAC_INTERFACE/vars.h" #include "ARCH/CBMIMO1/DEVICE_DRIVER/vars.h" #include "SCHED/defs.h" #include "SCHED/vars.h" #include "LAYER2/MAC/defs.h" #include "LAYER2/MAC/vars.h" #include "RRC/LITE/vars.h" #include "PHY_INTERFACE/vars.h" #include "UTIL/LOG/log.h" #include "OCG_vars.h" #include "UTIL/OTG/otg_tx.h" #include "UTIL/OTG/otg.h" #include "UTIL/OTG/otg_vars.h" char binary_table[16][5] = {{"0000\0"},{"0001\0"},{"0010\0"},{"0011\0"},{"0100\0"},{"0101\0"},{"0110\0"},{"0111\0"},{"1000\0"},{"1001\0"},{"1010\0"},{"1011\0"},{"1100\0"},{"1101\0"},{"1110\0"},{"1111\0"}}; typedef enum { RRCConnectionRequest=0, RRCConnectionSetup, RRCConnectionSetupComplete, RRCConnectionReconfiguration, RRCConnectionReconfigurationComplete, RRCSIB1, RRCSIB2_3 } RRC_MESSAGES_t; typedef enum { eNB_RRC=0, eNB_S1U, eNB_PDCP, eNB_RLC_UM, eNB_RLC_AM, eNB_RLC_TM, eNB_MAC, UE_RRC, UE_S1U, UE_PDCP, UE_RLC_UM, UE_RLC_AM, UE_RLC_TM, eNB_SI } SDUsource_t; typedef struct { int verbose; int RRCmessage; int lcid; int rbid; int SDUsize; int TBsize; SDUsource_t SDUsource; char input1_file[128]; char input2_file[128]; char output_file[128]; unsigned char input1_sdu[1024]; unsigned char input2_sdu[1024]; int input1_sdu_flag; unsigned short input1_sdu_len; int input2_sdu_flag; unsigned short input2_sdu_len; int frame; int input_sib; int input_eNB_MAC; } args_t; int input_text(char *file,char *sdu) { FILE *fd; int i,b_ind=0; char c,c0,c1; unsigned char byte; fd = fopen(file,"r"); while (!feof(fd)) { c0 = fgetc(fd); if (!feof(fd)) c1 = fgetc(fd); else return(-1); byte = 0; for (i=0,c=c0; i<2; i++,c=c1) switch(c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': byte += (c-'0')<<(4*(1-i)); break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': byte += (10+c-'A')<<(4*(1-i)); break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': byte += (10+c-'a')<<(4*(1-i)); break; case '\n': case '\0': return(b_ind); break; default: printf("Unknown hex character %c in file\n",c); return(-1); break; } sdu[b_ind]=byte; printf("byte %d: %x (%s%s)\n",b_ind,byte,binary_table[byte>>4],binary_table[byte&0xf]); b_ind++; } return(b_ind); } int parse_args(int argc, char** argv, args_t* args) { int c; int k; const struct option long_options[] = { {"lcid", required_argument, NULL, 256}, {"rbid", required_argument, NULL, 257}, {"TBsize", required_argument, NULL, 258}, {"SDUsize", required_argument, NULL, 259}, {"eNB_RRC", no_argument, NULL, 260}, {"eNB_S1U", no_argument, NULL, 261}, {"eNB_PDCP", no_argument, NULL, 262}, {"eNB_RLC_UM", no_argument, NULL, 263}, {"eNB_RLC_AM", no_argument, NULL, 264}, {"eNB_RLC_TM", no_argument, NULL, 265}, {"eNB_MAC" , no_argument, NULL, 266}, {"UE_RRC", no_argument, NULL, 267}, {"UE_S1U", no_argument, NULL, 268}, {"UE_PDCP", no_argument, NULL, 269}, {"UE_RLC_UM", no_argument, NULL, 270}, {"UE_RLC_AM", no_argument, NULL, 271}, {"UE_RLC_TM", no_argument, NULL, 272}, {"RRCConnectionRequest", no_argument, NULL, 273}, {"RRCConnectionSetup", no_argument, NULL, 274}, {"RRCConnectionSetupComplete", no_argument, NULL, 275}, {"RRCConnectionReconfiguration", no_argument, NULL, 276}, {"RRCConnectionReconfigurationComplete", no_argument, NULL, 277}, {"RRCSIB1", no_argument, NULL, 278}, {"RRCSIB2_3", no_argument, NULL, 279}, {NULL, 0, NULL, 0} }; args->frame = 0; while((c = getopt_long(argc, argv, "ho:I:J:v", long_options, NULL)) != -1) { switch(c) { case 'h': return 1; case 'o': strcpy(args->output_file,optarg); break; case 'f': args->frame = atoi(optarg); break; case 'I': strcpy(args->input1_file,optarg); args->input1_sdu_len = input_text(args->input1_file,args->input1_sdu); printf("Got sdu1 of length %d bytes\n",args->input1_sdu_len); args->input1_sdu_flag=1; break; case 'J': strcpy(args->input2_file,optarg); args->input2_sdu_len = input_text(args->input2_file,args->input2_sdu); printf("Got sdu2 of length %d bytes\n",args->input2_sdu_len); args->input2_sdu_flag=1; break; case 'v': args->verbose++; break; case 256: // lchan args->lcid = atoi(optarg); break; case 257: // args->rbid = atoi(optarg); break; case 258: args->TBsize = atoi(optarg); break; case 259: args->SDUsize = atoi(optarg); break; case 260: //eNB_RRC case 261: //eNB_S1U case 262: //eNB_PDCP case 263: //eNB_RLC_UM case 264: //eNB_RLC_AM case 265: //eNB_RLC_TM case 266: //eNB_MAC case 267: //UE_RRC case 268: //UE_S1U case 269: //UE_PDCP case 270: //UE_RLC_UM case 271: //UE_RLC_AM case 272: //UE_RLC_TM args->SDUsource = c-260; break; case 273: //RRCConnectionRequest case 274: //RRCConnectionSetup case 275: //RRCConnectionSetupComplete case 276: //RRCConnectionReconfiguration case 277: //RRCConnectionReconfigurationComplete case 278: //RRCSIB1 case 279: //RRCSIB2_3 args->RRCmessage = c-273; break; default: return 1; } } return 0; } void print_usage(const char* prog) { printf("Usage: %s [options]\n", prog); printf("\n"); printf(" General options:\n"); printf(" -h : print usage\n"); printf(" -v : increase verbosity level [0]\n"); printf(" -o : output .dat file (binary packet data)\n"); printf(" -i : input .dat file (binary packet data)\n"); printf(" -I : input .txt file (ASCII packet data)\n"); printf("\n"); printf(" Packet options:\n"); printf(" --eNB_RRC : set source of packet to eNB_RRC\n"); printf(" --eNB_S1U : set source of packet to eNB_S1U (e.g. IP)\n"); printf(" --eNB_PDCP : set source of packet to eNB_PDCP\n"); printf(" --eNB_RLC_UM : set source of packet to eNB_RLC_UM\n"); printf(" --eNB_RLC_AM : set source of packet to eNB_RLC_AM\n"); printf(" --eNB_RLC_TM : set source of packet to eNB_RLC_TM\n"); printf(" --eNB_MAC : set source of packet to eNB_MAC\n"); printf(" --UE_RRC : set source of packet to UE_RRC\n"); printf(" --UE_S1U : set source of packet to UE_S1U (e.g. IP)\n"); printf(" --UE_PDCP : set source of packet to UE_PDCP\n"); printf(" --UE_RLC_UM : set source of packet to UE_RLC_UM\n"); printf(" --UE_RLC_AM : set source of packet to UE RLC_AM\n"); printf(" --UE_RLC_TM : set source of packet to UE RLC_TM\n"); printf(" --lchan : set logical channel id\n"); printf(" --rbid : set radio bearer id\n"); printf(" --TBsize : set Transport Block Size at MAC layer\n"); printf(" --SDUsize : set the SDU size used by the originating entity (except RRC)\n"); printf(" --RRCConnectionSetup : set the SDU to be an RRCConnectionSetup\n"); printf(" --RRCConnectionSetupComplete : set the SDU to be an RRCConnectionSetupComplete\n"); printf(" --RRCConnectionRequest : set the SDU to be an RRCConnectionRequest\n"); printf(" --RRCConnectionReconfiguration : set the SDU to be an RRCConnectionReconfiguration\n"); printf(" --RRCConnectionReconfigurationComplete : set the SDU to be an RRCConnectionReconfigurationComplete\n"); printf(" --RRCSIB1 : set the SDU to be an RRCSIB1\n"); printf(" --RRCSIB2_3 : set the SDU to be an RRCSIB2_3\n"); } u8 attach_ue0(char *sdu) { u8 Size; u16 Size16; u8 lcid=0; UE_rrc_inst[0].Info[0].State = RRC_SI_RECEIVED; rrc_ue_generate_RRCConnectionRequest(0,131,0); Size = mac_rrc_data_req(0, 131, CCCH,1, &sdu[sizeof(SCH_SUBHEADER_FIXED)],0, 0); Size16 = (u16)Size; generate_ulsch_header((u8 *)sdu, // mac header 1, // num sdus 0, // short padding &Size16, // sdu length &lcid, // sdu lcid NULL, // power headroom NULL, // crnti NULL, // truncated bsr NULL, // short bsr NULL, 0); // post padding return(Size+sizeof(SCH_SUBHEADER_FIXED)); } // This retrieves the RRCConnectionSetup RRC SDU u8 attach_ue1(char *sdu) { // simulate reception of CCCH at eNB(RRCConnectionRequest) mac_rrc_lite_data_ind(0,131,0,UE_rrc_inst[0].Srb0[0].Tx_buffer.Payload, UE_rrc_inst[0].Srb0[0].Tx_buffer.payload_size,1,0); return(mac_rrc_data_req(0, 132, 0,1, sdu, 1, 0)); } // This retrieves the RRCConnectionSetupComplete RRC SDU u16 attach_ue2(char *dcch_sdu_eNB, char dcch_sdu_eNB_len, char *dcch_sdu) { mac_rlc_status_resp_t rlc_status; u16 sdu_len; printf("************* attach_ue2 (CCCH payload %d)\n", eNB_rrc_inst[0].Srb0.Tx_buffer.payload_size); // simulate reception of CCCH at UE (RRCConnectionSetup) mac_rrc_lite_data_ind(0,132,0,dcch_sdu_eNB,dcch_sdu_eNB_len,0,0); // simulate transmission of RRCConnectionSetupComplete rlc_status = mac_rlc_status_ind(1,134,0, DCCH, 100); sdu_len = mac_rlc_data_req(1,133, DCCH, dcch_sdu); return(sdu_len); } // This retrieves the RRCConnectionReconfiguration RRC SDU u16 attach_ue3(char *dcch_sdu_ue, char dcch_sdu_ue_len, char *dcch_sdu_eNB) { mac_rlc_status_resp_t rlc_status; u16 sdu_len; // simulation reception of RRCConnectionSetupComplete //LOG_D(RLC, "Panos-D: attach_ue3 before mac_rlc_data_ind 1 \n"); mac_rlc_data_ind(0,134,1, DCCH, dcch_sdu_ue, dcch_sdu_ue_len, 1, NULL); /// ... and generation of RRCConnectionReconfiguration /// First RLC-AM Control SDU (ACK) rlc_status = mac_rlc_status_ind(0,135,1, DCCH, 100); sdu_len = mac_rlc_data_req(0,135, DCCH, dcch_sdu_eNB); //LOG_D(RLC, "Panos-D: attach_ue3 before mac_rlc_data_ind 2 \n"); mac_rlc_data_ind(1,135,1, DCCH, dcch_sdu_eNB, sdu_len, 1, NULL); // now RRC message rlc_status = mac_rlc_status_ind(0,136,1, DCCH, 100); sdu_len = mac_rlc_data_req(0,136, DCCH, dcch_sdu_eNB); return(sdu_len); } // This retrieves the RRCConnectionReconfigurationComplete RRC SDU u16 attach_ue4(char *dcch_sdu_eNB, char dcch_sdu_eNB_len, char *dcch_sdu_ue) { mac_rlc_status_resp_t rlc_status; u16 sdu_len; // simulation UE reception of RRCConnectionReconfiguration .... mac_rlc_data_ind(1,135,0, DCCH, dcch_sdu_eNB, dcch_sdu_eNB_len, 1, NULL); // ... and generation of RRCConnectionReconfigurationComplete rlc_status = mac_rlc_status_ind(1,135,0, DCCH, 100); sdu_len = mac_rlc_data_req(1,135, DCCH, dcch_sdu_ue); rlc_status = mac_rlc_status_ind(1,136,0, DCCH, 100); sdu_len = mac_rlc_data_req(1,136, DCCH, dcch_sdu_ue); return(sdu_len); } //u8 NB_INST=2; int main (int argc, char **argv) { args_t args; LTE_DL_FRAME_PARMS frame_parms0; LTE_DL_FRAME_PARMS *frame_parms=&frame_parms; char sdu0[16],sdu1[64],sdu2[1024],sdu3[1024],sdu4[1024]; unsigned short sdu_len0,sdu_len1,sdu_len2,sdu_len3,sdu_len4; char ulsch_buffer[1024],dlsch_buffer[1024]; u8 lcid; u8 payload_offset; int i,comp; logInit(); NB_UE_INST = 1; NB_eNB_INST = 1; NB_INST=2; // Parse arguments if(parse_args(argc, argv, &args) > 0) { print_usage(argv[0]); exit(1); } set_taus_seed(0); logInit(); set_glog(LOG_TRACE, 1); for (comp = PHY; comp < MAX_LOG_COMPONENTS ; comp++) set_comp_log(comp, LOG_TRACE, LOG_NONE, 1); /* set_log(OMG, LOG_INFO, 20); set_log(EMU, LOG_INFO, 10); set_log(OCG, LOG_INFO, 1); set_log(MAC, LOG_TRACE, 1); set_log(RLC, LOG_TRACE, 1); set_log(PHY, LOG_DEBUG, 1); set_log(PDCP, LOG_TRACE, 1); set_log(RRC, LOG_TRACE, 1); */ mac_xface = (MAC_xface *)malloc(sizeof(MAC_xface)); init_lte_vars (&frame_parms, 0, 1, 0, 0, 25, 0, 0, 1, 1); l2_init(frame_parms); // Generate eNB SI if (args.input_sib == 0) { openair_rrc_lite_eNB_init(0); } else { printf("Got SI from files (%d,%d,%d,%d,%d)\n",args.input_sib,args.input1_sdu_flag,args.input2_sdu_flag); } openair_rrc_on(0,0); openair_rrc_lite_ue_init(0,0); switch (args.SDUsource) { case eNB_RRC: if (args.RRCmessage == RRCSIB1) { if (args.input1_sdu_flag == 1) { for (i=0; i<args.input1_sdu_len; i++) printf("%02x",args.input1_sdu[i]); printf("\n"); ue_decode_si(0,142,0,args.input1_sdu,args.input1_sdu_len); } else { printf("\n\nSIB1\n\n"); for (i=0; i<eNB_rrc_inst[0].sizeof_SIB1; i++) printf("%02x",eNB_rrc_inst[0].SIB1[i]); printf("\n"); } } else if (args.RRCmessage == RRCSIB2_3) { if (args.input1_sdu_flag == 1) { for (i=0; i<args.input2_sdu_len; i++) printf("%02x",args.input2_sdu[i]); printf("\n"); ue_decode_si(0,149,0,args.input1_sdu,args.input1_sdu_len); } else { printf("\n\nSIB2_3\n\n"); for (i=0; i<eNB_rrc_inst[0].sizeof_SIB23; i++) printf("%02x",eNB_rrc_inst[0].SIB23[i]); printf("\n"); } } else if ((args.input1_sdu_flag == 1)&& ((args.RRCmessage == RRCConnectionSetup) || (args.RRCmessage == RRCConnectionReconfiguration))) { sdu_len0 = attach_ue0(sdu0); ue_send_sdu(0,143,args.input1_sdu,args.input1_sdu_len,0); if (args.RRCmessage == RRCConnectionReconfiguration) ue_send_sdu(0,144,args.input2_sdu,args.input2_sdu_len,0); } else { switch (args.RRCmessage) { case RRCConnectionSetup: printf("Doing eNB RRCConnectionSetup\n"); sdu_len0 = attach_ue0(sdu0); sdu_len1 = attach_ue1(sdu1); lcid = 0; payload_offset = generate_dlsch_header(dlsch_buffer, 1, //num_sdus &sdu_len1, // &lcid, // sdu_lcid 255, // no drx 0, // no timing advance sdu0, // contention res id 0,0); memcpy(&dlsch_buffer[payload_offset],sdu1,sdu_len1); printf("\nRRCConnectionSetup (DLSCH input / MAC output)\n\n"); for (i=0; i<sdu_len1+payload_offset; i++) printf("%02x ",(unsigned char)sdu1[i]); printf("\n"); break; case RRCConnectionReconfiguration: printf("Doing eNB RRCConnectionReconfiguration\n"); sdu_len0 = attach_ue0(sdu0); sdu_len1 = attach_ue1(sdu1); sdu_len2 = attach_ue2(sdu1,sdu_len1,sdu2); sdu_len3 = attach_ue3(sdu2,sdu_len2,sdu3); lcid=1; payload_offset = generate_dlsch_header(dlsch_buffer, // offset = generate_dlsch_header((unsigned char*)eNB_mac_inst[0].DLSCH_pdu[0][0].payload[0], 1, //num_sdus &sdu_len3, // &lcid, 255, // no drx 1, // timing advance NULL, // contention res idk 0,0); memcpy(&dlsch_buffer[payload_offset],sdu3,sdu_len3); printf("\nRRCConnectionReconfiguration (DLSCH input / MAC output)\n\n"); for (i=0; i<sdu_len3+payload_offset; i++) printf("%02x ",(unsigned char)dlsch_buffer[i]); printf("\n"); break; default: printf("Unknown eNB_RRC SDU (%d), exiting\n",args.RRCmessage); break; } break; } break; case eNB_MAC: sdu_len0 = attach_ue0(sdu0); ue_send_sdu(0,143,args.input1_sdu,args.input1_sdu_len,0); break; case UE_RRC: switch (args.RRCmessage) { case RRCConnectionRequest: sdu_len0 = attach_ue0(sdu0); printf("\n\nRRCConnectionRequest\n\n"); for (i=0; i<sdu_len0; i++) printf("%02x ",(unsigned char)sdu0[i]); printf("\n"); break; case RRCConnectionSetupComplete: sdu_len0=attach_ue0(sdu0); sdu_len1 = attach_ue1(sdu1); sdu_len2 = attach_ue2(sdu1,sdu_len1,sdu2); lcid=1; printf("Got sdu of length %d\n",sdu_len2); payload_offset = generate_ulsch_header((u8*)ulsch_buffer, // mac header 1, // num sdus 0, // short pading &sdu_len2, // sdu length &lcid, // sdu lcid NULL, // power headroom NULL, // crnti NULL, // truncated bsr NULL, // short bsr NULL, // long_bsr 0); printf("Got MAC header of length %d\n",payload_offset); memcpy(&ulsch_buffer[payload_offset],sdu2,sdu_len2); printf("\n\nRRCConnectionSetupComplete (ULSCH input / MAC output)\n\n"); for (i=0; i<sdu_len2+payload_offset; i++) printf("%02x ",(unsigned char)ulsch_buffer[i]); printf("\n"); break; case RRCConnectionReconfigurationComplete: sdu_len0=attach_ue0(sdu0); sdu_len1=attach_ue1(sdu1); sdu_len2 = attach_ue2(sdu1,sdu_len1,sdu2); sdu_len3 = attach_ue3(sdu2,sdu_len2,sdu3); sdu_len4 = attach_ue4(sdu3,sdu_len3,sdu4); lcid=1; printf("Got sdu of length %d\n",sdu_len4); payload_offset = generate_ulsch_header((u8*)ulsch_buffer, // mac header 1, // num sdus 0, // short pading &sdu_len4, // sdu length &lcid, // sdu lcid NULL, // power headroom NULL, // crnti NULL, // truncated bsr NULL, // short bsr NULL, // long_bsr 0); printf("Got MAC header of length %d\n",payload_offset); memcpy(&ulsch_buffer[payload_offset],sdu4,sdu_len4); printf("\n\nRRCConnectionReconfigurationComplete (ULSCH input / MAC output)\n\n"); for (i=0; i<sdu_len4+payload_offset; i++) printf("%02x ",(unsigned char)ulsch_buffer[i]); printf("\n"); break; default: printf("Unknown UE_RRC SDU (%d), exiting\n",args.RRCmessage); break; } break; } free(mac_xface); return(0); }