-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathURRCMessages.cpp_reject
2244 lines (1943 loc) · 101 KB
/
URRCMessages.cpp_reject
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* OpenBTS provides an open source alternative to legacy telco protocols and
* traditionally complex, proprietary hardware systems.
*
* Copyright 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero General
* Public License version 3. See the COPYING and NOTICE files in the main
* directory for licensing information.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
*/
#include "UMTSTransfer.h"
#include "URRCMessages.h"
#include "MACEngine.h"
#include "AsnHelper.h"
#include "Logger.h"
#include "SgsnExport.h"
#include "URRC.h"
#include "UMTSLogicalChannel.h"
//#include "asn_system.h" included from AsnHelper.h
namespace ASN {
//#include "BIT_STRING.h"
#include "UL-CCCH-Message.h"
#include "DL-CCCH-Message.h"
#include "UL-DCCH-Message.h"
#include "DL-DCCH-Message.h"
#include "InitialUE-Identity.h"
#define PAT_SAMSUNG_TEST 1 // Try to get the samsung galaxy to accept this message.
#include "asn_SEQUENCE_OF.h"
//#include "RRCConnectionRequest.h"
//#include "RRCConnectionSetup.h"
};
#define CASENAME(x) case x: return #x;
#define CASEASNCOMMENT(foo) case ASN::foo: return #foo;
using namespace SGSN;
namespace UMTS {
const std::string descrRrcConnectionSetup("RRC_Connection_Setup_Message");
const std::string descrRrcConnectionRelease("RRC_Connection_Release_Message");
const std::string descrRrcConnectionReleaseAsReject("RRC_Connection_Release_As_Reject_Message");
const std::string descrRrcConnectionReject("RRC_Connection_Reject_Message");
const std::string descrRadioBearerSetup("RRC Radio Bearer Setup Message");
const std::string descrRadioBearerRelease("RRC Radio Bearer Release Message");
const std::string descrCellUpdateConfirm("RRC Cell Update Confirm Message");
const std::string descrSecurityModeCommand("RRC Security Mode Command");
typedef unsigned char uchar;
static const char *asnUlDcchMsg2Name(ASN::UL_DCCH_MessageType_PR mtype)
{
switch (mtype) {
CASEASNCOMMENT(UL_DCCH_MessageType_PR_activeSetUpdateComplete)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_activeSetUpdateFailure)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_cellChangeOrderFromUTRANFailure)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_counterCheckResponse)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_handoverToUTRANComplete)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_initialDirectTransfer)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_handoverFromUTRANFailure)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_measurementControlFailure)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_measurementReport)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_physicalChannelReconfigurationComplete)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_physicalChannelReconfigurationFailure)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_radioBearerReconfigurationComplete)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_radioBearerReconfigurationFailure)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_radioBearerReleaseComplete)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_radioBearerReleaseFailure)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_radioBearerSetupComplete)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_radioBearerSetupFailure)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_rrcConnectionReleaseComplete)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_rrcConnectionSetupComplete)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_rrcStatus)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_securityModeComplete)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_securityModeFailure)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_signallingConnectionReleaseIndication)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_transportChannelReconfigurationComplete)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_transportChannelReconfigurationFailure)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_transportFormatCombinationControlFailure)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_ueCapabilityInformation)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_uplinkDirectTransfer)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_utranMobilityInformationConfirm)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_utranMobilityInformationFailure)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_mbmsModificationRequest)
CASEASNCOMMENT(UL_DCCH_MessageType_PR_spare1)
default: return "UL_DCCH_unrecognized_message_type";
}
}
static const char *asnUlCcchMsg2Name(ASN::UL_CCCH_MessageType_PR type)
{
switch (type) {
CASEASNCOMMENT(UL_CCCH_MessageType_PR_cellUpdate)
CASEASNCOMMENT(UL_CCCH_MessageType_PR_rrcConnectionRequest)
CASEASNCOMMENT(UL_CCCH_MessageType_PR_uraUpdate)
default:
return "UL_CCCH_unrecognized_message_type";
}
}
static string getRBFailureCause(ASN::FailureCauseWithProtErr_t *failureCause)
{
unsigned failcode = failureCause->present;
string msg;
switch (failcode) {
case ASN::FailureCauseWithProtErr_PR_configurationUnsupported:
msg = "configurationUnsupported"; break;
case ASN::FailureCauseWithProtErr_PR_physicalChannelFailure:
msg = "physicalChannelASN::Failure"; break;
case ASN::FailureCauseWithProtErr_PR_incompatibleSimultaneousReconfiguration:
msg = "incompatibleSimultaneousReconfiguration"; break;
case ASN::FailureCauseWithProtErr_PR_compressedModeRuntimeError:
msg = "compressedModeRuntimeError"; break;
case ASN::FailureCauseWithProtErr_PR_protocolError:
msg = "protocolError";
// The protocolError choice has additional info, but since our spec has only one
// possible value for that info, it is of little interest so ignore it.
break;
case ASN::FailureCauseWithProtErr_PR_cellUpdateOccurred:
msg = "cellUpdateOccurred"; break;
case ASN::FailureCauseWithProtErr_PR_invalidConfiguration:
msg = "invalidConfiguration"; break;
case ASN::FailureCauseWithProtErr_PR_configurationIncomplete:
msg = "configurationIncomplete"; break;
case ASN::FailureCauseWithProtErr_PR_unsupportedMeasurement:
msg = "unsupportedMeasurement"; break;
case ASN::FailureCauseWithProtErr_PR_mbmsSessionAlreadyReceivedCorrectly:
msg ="mbmsSessionAlreadyReceivedCorrectly"; break;
case ASN::FailureCauseWithProtErr_PR_lowerPriorityMBMSService:
msg = "lowerPriorityMBMSService"; break;
default:
msg = "unknown type"; break;
}
return msg;
}
ASN::RRC_StateIndicator UEState2Asn(UEState state)
{
switch (state) {
case stIdleMode:
LOG(ERR) << "UE is unexpectedly in idle mode";
// Assume CELL_FACH and fall through.
return ASN::RRC_StateIndicator_cell_FACH;
case stCELL_FACH: return ASN::RRC_StateIndicator_cell_FACH;
case stCELL_DCH: return ASN::RRC_StateIndicator_cell_DCH;
case stCELL_PCH: return ASN::RRC_StateIndicator_cell_PCH;
case stURA_PCH: return ASN::RRC_StateIndicator_ura_PCH;
default: assert(0);
}
}
// Run the Integrity Protection Algorithm and ASN encode the message.
// Return result in &result.
static bool encodeDcchMsg(UEInfo *uep, RbId rbid, ASN::DL_DCCH_Message_t *msg, ByteVector &result, string descr)
{
if (uep->integrity.isStarted()) {
// Step 1: Set the integrity check info to the values for encoding specified in 10.3.3.16.
ASN::IntegrityCheckInfo *ici = RN_CALLOC(ASN::IntegrityCheckInfo);
msg->integrityCheckInfo = ici;
ici->messageAuthenticationCode = allocAsnBIT_STRING(32);
// The RBID goes in the 5 LSB of the 32-bit string that will
// later hold the MAC-I [Message Authentication Code].
AsnBitString2BVTemp(ici->messageAuthenticationCode).setField(32-5,rbid-0*1,5);
ici->rrc_MessageSequenceNumber = 0; // 10.3.3.16 of 25.331;
// Step 2: Encode the message
if (!uperEncodeToBV(&ASN::asn_DEF_DL_DCCH_Message,msg,result,descr)) {return false;}
// After encoding it is safe to advance the COUNT-I, ie, this message advances
// the RRC SN [sequence number.]
//uep->integrity.advanceDlRrcSn(rbid);
// Step 3: Run the message through the Integrity Protection Algorithm.
uint32_t maci = uep->integrity.runF9(rbid,1,result);
// After encoding it is safe to advance the COUNT-I, ie, this message advances
// the RRC SN [sequence number.]
ici->rrc_MessageSequenceNumber = uep->integrity.getDlRrcSn(rbid); // 10.3.3.16 of 25.331
uep->integrity.advanceDlRrcSn(rbid);
// Step 4: Set the Message Authentication Code in the message.
AsnBitString2BVTemp(ici->messageAuthenticationCode).setField(0,maci,32);
}
// Encode the message (again), completely oblivious to cpu cycles consumed.
if (!uperEncodeToBV(&ASN::asn_DEF_DL_DCCH_Message,msg,result,descr)) {return false;}
std::string comment = format("DL_DCCH %s message size=%d",descr.c_str(),result.size());
asnLogMsg(rbid, &ASN::asn_DEF_DL_DCCH_Message, msg,comment.c_str(),uep);
//if (gConfig.getNum("UMTS.Debug.Messages")) {
// asn_fprint(stdout,&ASN::asn_DEF_DL_DCCH_Message, msg);
// std::string readable = asn2string(&ASN::asn_DEF_DL_DCCH_Message, msg);
// fprintf(stdout,"Encoded message size=%d bytes\n%s",result.size());
// fflush(stdout);
//}
return true;
}
// Return TRUE on success.
static bool encodeCcchMsg(ASN::DL_CCCH_Message_t *msg, ByteVector &result,
string descr, // Description for the log
UEInfo *uep, // UE for the log, or NULL if none.
uint32_t urnti // URNTI for the log, unneeded if uep is non-null.
)
{
// We can just return: uperEncodeToBV printed a message on failure.
bool stat = uperEncodeToBV(&ASN::asn_DEF_DL_CCCH_Message,msg,result,descr);
if (stat) {
string comment = format("DL_CCCH %s message size=%d",descr.c_str(),result.size());
asnLogMsg(0, &ASN::asn_DEF_DL_CCCH_Message, msg,comment.c_str(),uep,urnti);
}
//if (gConfig.getNum("UMTS.Debug.Messages")) {
// asn_fprint(stdout,&ASN::asn_DEF_DL_CCCH_Message, msg);
// fprintf(stdout,"Encoded message size=%d bytes\n",result.size());
// fflush(stdout);
//}
return stat;
}
// Same as RB_InformationSetup but without PDCP info.
// The list we put these things in may be either SRB_InformationSetupList or SRB_InformationSetupList2,
// which are 100% identical, but nevertheless the result list type must be void**
// 25.331 10.3.4.24
static void toAsnSRB_InformationSetupList(RrcMasterChConfig *masterConfig, void*srblist)
{
// Set up SRBs.
for (unsigned rbid = SRB1; rbid <= SRB3; rbid++) {
RBInfo *rb = masterConfig->getRB(rbid);
assert(rb->valid());
ASN::SRB_InformationSetup *srbie = RN_CALLOC(ASN::SRB_InformationSetup);
srbie->rb_Identity = RN_CALLOC(long);
*srbie->rb_Identity = rbid;
srbie->rlc_InfoChoice.present = ASN::RLC_InfoChoice_PR_rlc_Info;
rb->toAsnRLC_Info(&srbie->rlc_InfoChoice.choice.rlc_Info);
// This assumes uplink and downlink are configured with identical TrCh.
// They dont have to be.
TrChId tcid = rb->mTrChAssigned;
defaultRbMappingInfoToAsn(masterConfig->getUlTrChInfo(tcid),
masterConfig->getDlTrChInfo(tcid),rbid,&srbie->rb_MappingInfo);
ASN_SEQUENCE_ADD(srblist,srbie);
}
}
// This is almost the same as above, but allows you to change
// only the RBMappinginfo, not other RLC programming.
// We can use it to switch the SRBs between CELL_DCH and CELL_FACH mode,
// because it allows us to specify a new TrCh, which implies a new TFS,
// which allows the new rlcs to resize to match the new TFS.
static ASN::RB_InformationAffectedList *toAsnRB_InformationAffectedList(
RrcMasterChConfig *masterConfig)
{
ASN::RB_InformationAffectedList *result = RN_CALLOC(ASN::RB_InformationAffectedList);
// Set up SRBs.
for (unsigned rbid = SRB1; rbid <= SRB3; rbid++) {
RBInfo *rb = masterConfig->getRB(rbid);
assert(rb->valid());
ASN::RB_InformationAffected *srbie = RN_CALLOC(ASN::RB_InformationAffected);
srbie->rb_Identity = rbid;
// This assumes uplink and downlink are configured with identical TrCh.
// They dont have to be.
TrChId tcid = rb->mTrChAssigned;
defaultRbMappingInfoToAsn(masterConfig->getUlTrChInfo(tcid),
masterConfig->getDlTrChInfo(tcid),rbid,&srbie->rb_MappingInfo);
ASN_SEQUENCE_ADD(&result->list,srbie);
}
return result;
}
static void toAsnRAB_Identity(int rbid,ASN::RAB_Identity_t *rabp)
{
// 10.3.1.14: RAB Identity "This information uniquely identifies a RAB within a CN domain."
// TODO: There are different kinds for GSM-MAP or ANSI-41, but I dont think it matters
// because we dont use it and the phone shouldnt care, although it may need to be unique,
// which we can insure simply by using the rbid.
rabp->present = ASN::RAB_Identity_PR_gsm_MAP_RAB_Identity;
setAsnBIT_STRING(&rabp->choice.gsm_MAP_RAB_Identity,(uint8_t*)calloc(1,1),8);
AsnBitString2BVTemp(&rabp->choice.gsm_MAP_RAB_Identity).setField(0,rbid,8);
}
// 3GPP 25.331 10.3.4.8
// ASN RAB_Info_t rab_Info;
void toAsnRAB_Info(RBInfo *rb,ASN::RAB_Info_t *rabInfoIE)
{
// RAB_Identity_t rab_Identity;
toAsnRAB_Identity(rb->mRbId,&rabInfoIE->rab_Identity);
// CN_DomainIdentity_t cn_DomainIdentity; // cs or ps?
bool csdomain = rb->isCsDomain();
rabInfoIE->cn_DomainIdentity = toAsnEnumerated(
csdomain ? ASN::CN_DomainIdentity_cs_domain : ASN::CN_DomainIdentity_ps_domain);
// NAS_Synchronisation_Indicator_t *nas_Synchronisation_Indicator /* OPTIONAL */;
// Re_EstablishmentTimer_t re_EstablishmentTimer;
// TODO: Which should we use here? Choice is T314 or T315
// 25.331 13.1 implies T314 is for CS and T315 is for PS, so why are they asking us?
// Also says see 8.3.1.13 and 8.3.1.14
rabInfoIE->re_EstablishmentTimer = toAsnEnumerated(
csdomain ? ASN::Re_EstablishmentTimer_useT314 : ASN::Re_EstablishmentTimer_useT315);
// Finished with RAB_Info_t
}
// 3GPP 10.3.4.20
// ASN RB_InformationSetup
static ASN::RB_InformationSetup *toAsnRB_InformationSetup(RrcMasterChConfig *masterConfig, RBInfo *rb)
{
assert(rb->valid());
int rbid = rb->mRbId;
ASN::RB_InformationSetup *rbie = RN_CALLOC(ASN::RB_InformationSetup);
// RB_Identity_t rb_Identity;
rbie->rb_Identity = rbid;
// struct PDCP_Info *pdcp_Info /* OPTIONAL */;
// We dont use PDCP. So why is it here at all? Maybe it is mandatory for non-signalling RBs?
rbie->pdcp_Info = RN_CALLOC(ASN::PDCP_Info);
rbie->pdcp_Info->losslessSRNS_RelocSupport = RN_CALLOC(ASN::LosslessSRNS_RelocSupport);
rbie->pdcp_Info->losslessSRNS_RelocSupport->present = ASN::LosslessSRNS_RelocSupport_PR_notSupported;
//rbie->pdcpInfo->mLosslessSRNS_RelocSupport->choice = ASN::NULL;
rbie->pdcp_Info->pdcp_PDU_Header = toAsnEnumerated(ASN::PDCP_PDU_Header_absent);
// RLC_InfoChoice_t rlc_InfoChoice;
rbie->rlc_InfoChoice.present = ASN::RLC_InfoChoice_PR_rlc_Info;
rb->toAsnRLC_Info(&rbie->rlc_InfoChoice.choice.rlc_Info);
// RB_MappingInfo_t rb_MappingInfo;
TrChId tcid = rb->mTrChAssigned; // The TrCh carrying this rb.
defaultRbMappingInfoToAsn(masterConfig->getUlTrChInfo(tcid),
masterConfig->getDlTrChInfo(tcid),rbid,&rbie->rb_MappingInfo);
return rbie;
}
// 3GPP 25.331 10.3.4.10
// ASN struct RAB_InformationSetup
// For a CS connection we use three consecutive rbids.
static ASN::RAB_InformationSetup *toAsnRAB_InformationSetup(
RrcMasterChConfig *masterConfig, int rbid,
int *pNumRBperRAB) // Return the number of RBs in this RAB. 1 for PS and 3 for CS.
{
ASN::RAB_InformationSetup *result = RN_CALLOC(ASN::RAB_InformationSetup);
// RAB_Info_t rab_Info;
RBInfo *rb = masterConfig->getRB(rbid);
toAsnRAB_Info(rb,&result->rab_Info);
*pNumRBperRAB = rb->isCsDomain() ? 3 : 1;
// RB_InformationSetupList_t rb_InformationSetupList;
// A_SEQUENCE_OF(struct RB_InformationSetup) list
for (int i = 0; i < *pNumRBperRAB; i++, rbid++) {
rb = masterConfig->getRB(rbid);
// 3GPP 10.3.4.20
ASN::RB_InformationSetup *rbInfoIE = toAsnRB_InformationSetup(masterConfig, rb);
ASN_SEQUENCE_ADD(&result->rb_InformationSetupList.list,rbInfoIE);
}
return result;
}
// 3GPP 25.331 10.3.4.10 RAB Information for Setup.
static void toAsnRAB_InformationSetupList(RrcMasterChConfig *masterConfig, ASN::RAB_InformationSetupList *rbSetupListIE)
{
// For PS each RB is a RAB using one rb-id. There can be multiple RABs,
// although I think we will only setup one at a time because the UE can
// only ask for one at a time.
// For voice, the first 3 RBs constitute a RAB with 3 'sub-rab-flows' for the AMR codec.
// We dont allow mixing cs and ps connections on the same UE.
for (unsigned rbid = 5; rbid < masterConfig->mNumRB; ) {
RBInfo *rb = masterConfig->getRB(rbid);
if (!rb || ! rb->valid()) { continue; }
int numRBperRAB;
ASN::RAB_InformationSetup *rabSetupIE =
toAsnRAB_InformationSetup(masterConfig, rbid, &numRBperRAB);
ASN_SEQUENCE_ADD(&rbSetupListIE->list,rabSetupIE);
rbid += numRBperRAB; // Advance by the number of rbids used by this RAB.
}
}
static ASN::UL_CommonTransChInfo *toAsnUL_CommonTransChInfo(RrcMasterChConfig *masterConfig)
{
ASN::UL_CommonTransChInfo *result = RN_CALLOC(ASN::UL_CommonTransChInfo);
// struct TFC_Subset *tfc_Subset /* OPTIONAL */;
// struct TFCS *prach_TFCS /* OPTIONAL */;
// struct UL_CommonTransChInfo__modeSpecificInfo {...} modeSpecificInfo;
// The whole modeSpecificInfo is optional, even though it is not marked as such in ASN.
typedef ASN::UL_CommonTransChInfo::UL_CommonTransChInfo__modeSpecificInfo msi;
result->modeSpecificInfo = RN_CALLOC(msi);
result->modeSpecificInfo->present = ASN::UL_CommonTransChInfo__modeSpecificInfo_PR_fdd;
masterConfig->getUlTfcs()->toAsnTfcs(&result->modeSpecificInfo->choice.fdd.ul_TFCS,TrChUlDCHType);
return result;
}
static ASN::DL_CommonTransChInfo *toAsnDL_CommonTransChInfo(RrcMasterChConfig *masterConfig)
{
// struct DL_CommonTransChInfo
ASN::DL_CommonTransChInfo *result = RN_CALLOC(ASN::DL_CommonTransChInfo);
// struct TFCS *sccpch_TFCS /* OPTIONAL */;
// struct DL_CommonTransChInfo__modeSpecificInfo
// DL_CommonTransChInfo__modeSpecificInfo_PR present;
result->modeSpecificInfo.present = ASN::DL_CommonTransChInfo__modeSpecificInfo_PR_fdd;
// union DL_CommonTransChInfo__modeSpecificInfo_u {...} choice;
// struct DL_CommonTransChInfo__modeSpecificInfo__fdd {...} fdd;
// struct DL_CommonTransChInfo__modeSpecificInfo__fdd__dl_Parameters {...} *dl_Parameters;
typedef ASN::DL_CommonTransChInfo::
DL_CommonTransChInfo__modeSpecificInfo::
DL_CommonTransChInfo__modeSpecificInfo_u::
DL_CommonTransChInfo__modeSpecificInfo__fdd::
DL_CommonTransChInfo__modeSpecificInfo__fdd__dl_Parameters longthing;
result->modeSpecificInfo.choice.fdd.dl_Parameters = RN_CALLOC(longthing);
// This is where you can say same as uplink: (but we dont)
// DL_CommonTransChInfo__modeSpecificInfo__fdd__dl_Parameters_PR present;
result->modeSpecificInfo.choice.fdd.dl_Parameters->present =
ASN::DL_CommonTransChInfo__modeSpecificInfo__fdd__dl_Parameters_PR_dl_DCH_TFCS;
// union DL_CommonTransChInfo__modeSpecificInfo__fdd__dl_Parameters_u {...} choice;
// TFCS_t dl_DCH_TFCS;
masterConfig->getDlTfcs()->toAsnTfcs(
&result->modeSpecificInfo.choice.fdd.dl_Parameters->choice.dl_DCH_TFCS,TrChDlDCHType);
return result;
}
ASN::UL_AddReconfTransChInfoList *toAsnUL_AddReconfTransChInfoList(RrcMasterChConfig *masterConfig)
{
ASN::UL_AddReconfTransChInfoList *result = RN_CALLOC(ASN::UL_AddReconfTransChInfoList);
unsigned numtc = masterConfig->getUlNumTrCh();
// This assumes transport channels always start at 0.
for (TrChId tcid = 0; tcid < numtc; tcid++) {
//TrChInfo *tc = masterConfig->getUlTrChInfo(tcid);
// typedef struct UL_AddReconfTransChInformation
ASN::UL_AddReconfTransChInformation *addTcIE =
RN_CALLOC(ASN::UL_AddReconfTransChInformation);
// UL_TrCH_Type_t ul_TransportChannelType; // dch or usch.
asn_long2INTEGER(&addTcIE->ul_TransportChannelType,ASN::UL_TrCH_Type_dch);
// TransportChannelIdentity_t transportChannelIdentity;
addTcIE->transportChannelIdentity = tcid+1; // ASN TrCh starts at 1
// TransportFormatSet_t transportFormatSet;
masterConfig->getUlTfs()->toAsnTfs(&addTcIE->transportFormatSet);
ASN_SEQUENCE_ADD(&result->list,addTcIE);
}
return result;
}
// Create a fake uplink TrCh, needed just to align an ASN struct.
static void toAsnFakeUL_AddReconfTransChInfoList(ASN::UL_AddReconfTransChInfoList *ulchlist)
{
// The easiest way to do this is to manufacturer a TFS and use that:
UlTrChInfo ulfoo;
ulfoo.setTrCh(TrChRACHType,1,true);
ulfoo.getTfs()
->setSemiStatic(10,RrcDefs::Convolutional,ASN::CodingRate_half,256,16)
// ->setCommonCh() This did not work - failed to ASN encode.
->setDedicatedCh()
->addTF(0+4,0);
ASN::UL_AddReconfTransChInformation *dummyUlDCH = RN_CALLOC(ASN::UL_AddReconfTransChInformation);
asn_long2INTEGER(&dummyUlDCH->ul_TransportChannelType,ASN::UL_TrCH_Type_dch);
dummyUlDCH->transportChannelIdentity = 31;
// This does not work; asn_CHOICE does not except PR_NOTHING, anywhere!
//dummyUlDCH->transportFormatSet.present = ASN::TransportFormatSet_PR_NOTHING;
ulfoo.getTfs()->toAsnTfs(&dummyUlDCH->transportFormatSet);
ASN_SEQUENCE_ADD(&ulchlist->list,dummyUlDCH);
}
static ASN::DL_AddReconfTransChInfoList *toAsnDL_AddReconfTransChInfoList(RrcMasterChConfig *masterConfig)
{
ASN::DL_AddReconfTransChInfoList *result = RN_CALLOC(ASN::DL_AddReconfTransChInfoList);
unsigned numtc = masterConfig->getDlNumTrCh();
// This assumes transport channels always start at 0.
for (TrChId tcid = 0; tcid < numtc; tcid++) {
//TrChInfo *tc = getDlTrChInfo(tcid);
// v typedef struct DL_AddReconfTransChInformation
ASN::DL_AddReconfTransChInformation *addTcIE =
RN_CALLOC(ASN::DL_AddReconfTransChInformation);
// . DL_TrCH_Type_t dl_TransportChannelType;
asn_long2INTEGER(&addTcIE->dl_TransportChannelType,ASN::DL_TrCH_Type_dch);
// TransportChannelIdentity_t dl_transportChannelIdentity;
addTcIE->dl_transportChannelIdentity = tcid+1;
// vv struct DL_AddReconfTransChInformation__tfs_SignallingMode {...} tfs_SignallingMode;
// .. DL_AddReconfTransChInformation__tfs_SignallingMode_PR present;
addTcIE->tfs_SignallingMode.present = ASN::DL_AddReconfTransChInformation__tfs_SignallingMode_PR_explicit_config;
// vvv union DL_AddReconfTransChInformation__tfs_SignallingMode_u {...} choice;
// ... TransportFormatSet_t explicit_config;
// vvvv typedef struct TransportFormatSet
masterConfig->getDlTfs()->toAsnTfs(&addTcIE->tfs_SignallingMode.choice.explicit_config);
// ^^^^ struct TransportFormatSet
// ^^^ union DL_AddReconfTransChInformation__tfs_SignallingMode_u {...} choice;
// .. struct QualityTarget *dch_QualityTarget /* OPTIONAL */;
// .. struct TM_SignallingInfo *dummy /* OPTIONAL */;
// ^^ struct DL_AddReconfTransChInformation__tfs_SignallingMode {...} tfs_SignallingMode;
ASN_SEQUENCE_ADD(&result->list,addTcIE);
// ^ struct DL_AddReconfTransChInfoList
}
return result;
}
void toAsnDL_AddReconfTransChInfoListSameAsUl(
ASN::DL_AddReconfTransChInfoList *dlchlist,
int dltcid, // Downlink 1-based TrCh-id to configure
int ultcid) // Uplink 1-based TrCh-id to copy to downlink trch.
{
ASN::DL_AddReconfTransChInformation *dummyDlDCH =
RN_CALLOC(ASN::DL_AddReconfTransChInformation);
asn_long2INTEGER(&dummyDlDCH->dl_TransportChannelType,ASN::DL_TrCH_Type_dch);
dummyDlDCH->dl_transportChannelIdentity = dltcid;
// Since this is just a dummy structure, use the simplest type,which is sameAsUlTrCh.
dummyDlDCH->tfs_SignallingMode.present = ASN::DL_AddReconfTransChInformation__tfs_SignallingMode_PR_sameAsULTrCH;
asn_long2INTEGER(&dummyDlDCH->tfs_SignallingMode.choice.sameAsULTrCH.ul_TransportChannelType,
ASN::UL_TrCH_Type_dch);
dummyDlDCH->tfs_SignallingMode.choice.sameAsULTrCH.ul_TransportChannelIdentity = ultcid;
ASN_SEQUENCE_ADD(&dlchlist->list,dummyDlDCH);
}
ByteVector* sendDirectTransfer(UEInfo* uep, ByteVector &dlpdu, const char *descr, bool psDomain)
{
ASN::DL_DCCH_Message_t msg;
memset(&msg,0,sizeof(msg));
msg.message.present = ASN::DL_DCCH_MessageType_PR_downlinkDirectTransfer;
ASN::DownlinkDirectTransfer_t *ddt = &msg.message.choice.downlinkDirectTransfer;
ddt->present = ASN::DownlinkDirectTransfer_PR_r3;
ASN::DownlinkDirectTransfer_r3_IEs *ies = &ddt->choice.r3.downlinkDirectTransfer_r3;
ies->rrc_TransactionIdentifier = uep->newTransactionId();
ies->cn_DomainIdentity = psDomain ? toAsnEnumerated(ASN::CN_DomainIdentity_ps_domain) : toAsnEnumerated(ASN::CN_DomainIdentity_cs_domain);
ies->nas_Message.buf = dlpdu.begin();
ies->nas_Message.size = dlpdu.size();
ByteVector *result = new ByteVector(dlpdu.size()+100);
RN_MEMLOG(ByteVector,result);
if (!encodeDcchMsg(uep,SRB3,&msg,*result,descr)) {return NULL;}
return result;
}
static void toAsnURNTI(ASN::U_RNTI_t *urnti,unsigned srncid,unsigned srnti)
{
setAsnBIT_STRING(&urnti->srnc_Identity,(uint8_t*)calloc(1,2),12);
AsnBitString2BVTemp(urnti->srnc_Identity).setField(0,srncid,12);
setAsnBIT_STRING(&urnti->s_RNTI,(uint8_t*)calloc(1,3),20);
AsnBitString2BVTemp(urnti->s_RNTI).setField(0,srnti,20);
}
static ASN::C_RNTI_t *toAsnCRNTI(unsigned crnti)
{
// C_RNTI_t *new_c_RNTI /* OPTIONAL */;
ASN::C_RNTI_t *result = RN_CALLOC(ASN::C_RNTI_t);
// new_c_RNTI is a BIT_STRING_t
setAsnBIT_STRING(result,(uint8_t*)calloc(1,2),16);
AsnBitString2BVTemp(result).setField(0,crnti,16);
return result;
}
// NOTE: The RRC Connection Setup messages are defined as using CCCH and SRB0 which is TM
// uplink and UM downlink. That makes sense because uplink messages are small and the downlink
// message is huge and may need to be segmented.
// Note that for CCCH downlink messages the MAC does not include a UE-id, in fact,
// it doesn't have one yet because the RRC Connection Setup message is what is going
// to supply the URNTI and CRNTI; rather the UE-id is included in the message.
// Apparently the UE monitors the entire CCCH all the time in order to gather all the
// segments of all the messages and must look at them all to see if they are for it.
// Note that this message is still small: the rlc-info for TM&UM is pretty small,
// and the TrCh info comes from SIB5/6.
// Release 3 version of this message. The samsung and other phones did not seem to like this,
// so 11-16-2012 tried switching to release 4 version.
void sendRrcConnectionSetup(UEInfo *uep, ASN::InitialUE_Identity *ueInitialId)
{
ASN::DL_CCCH_Message msg;
memset(&msg,0,sizeof(msg));
msg.message.present = ASN::DL_CCCH_MessageType_PR_rrcConnectionSetup;
ASN::RRCConnectionSetup *csp = &msg.message.choice.rrcConnectionSetup;
unsigned transactionId = uep->newTransactionId();
ByteVector result(1000);
bool version4 = false; // Use version4 of this message.
bool version5 = false; // Use version5 of this message with a default config.
if (version4 | version5) {
csp->present = ASN::RRCConnectionSetup_PR_later_than_r3; // Guessing we can use any of the variants.
// WARNING: Now there are temporarily two pointers to the memory in UE_Identity.
csp->choice.later_than_r3.initialUE_Identity = *ueInitialId;
csp->choice.later_than_r3.rrc_TransactionIdentifier = transactionId;
//ASN::RRCConnectionSetup::RRCConnectionSetup_u::RRCConnectionSetup__later_than_r3 *iep =
//&csp->choice.later_than_r3;
//iep->initialUE_Identity = *ueInitialId;
//iep->rrc_TransactionIdentifier = transactionId;
//typedef ASN::RRCConnectionSetup::RRCConnectionSetup_u::RRCConnectionSetup__later_than_r3 later_than_r3_t;
//ASN::RRCConnectionSetup::RRCConnectionSetup_u::RRCConnectionSetup__later_than_r3::RRCConnectionSetup__later_than_r3__criticalExtensions *extp = &iep->criticalExtensions;
if (version5) {
// version 5 of the message. A little verbose here...
csp->choice.later_than_r3.criticalExtensions.present = ASN::RRCConnectionSetup__later_than_r3__criticalExtensions_PR_criticalExtensions;
csp->choice.later_than_r3.criticalExtensions.choice.criticalExtensions.present = ASN::RRCConnectionSetup__later_than_r3__criticalExtensions__criticalExtensions_PR_r5;
ASN::RRCConnectionSetup_r5_IEs_t *ie5 = &csp->choice.later_than_r3.criticalExtensions.choice.criticalExtensions.choice.r5.rrcConnectionSetup_r5;
// ActivationTime_t *activationTime /* OPTIONAL */;
// U_RNTI_t new_U_RNTI;
toAsnURNTI(&ie5->new_U_RNTI,uep->getSrncId(),uep->getSRNTI());
// C_RNTI_t *new_c_RNTI /* OPTIONAL */;
ie5->new_c_RNTI = toAsnCRNTI(uep->mCRNTI);
// RRC_StateIndicator_t rrc_StateIndicator;
asn_long2INTEGER(&ie5->rrc_StateIndicator,ASN::RRC_StateIndicator_cell_FACH);
// UTRAN_DRX_CycleLengthCoefficient_t utran_DRX_CycleLengthCoeff;
ie5->utran_DRX_CycleLengthCoeff = 3; // Must be in range 3..9
ie5->specificationMode.present = ASN::RRCConnectionSetup_r5_IEs__specificationMode_PR_preconfiguration;
ie5->specificationMode.choice.preconfiguration.preConfigMode.present =
ASN::RRCConnectionSetup_r5_IEs__specificationMode__preconfiguration__preConfigMode_PR_defaultConfig;
asn_long2INTEGER(&ie5->specificationMode.choice.preconfiguration.preConfigMode.choice.defaultConfig.defaultConfigMode,ASN::DefaultConfigMode_fdd);
ie5->specificationMode.choice.preconfiguration.preConfigMode.choice.defaultConfig.defaultConfigIdentity = 0;
} else {
// version 4 of the message.
csp->choice.later_than_r3.criticalExtensions.present = ASN::RRCConnectionSetup__later_than_r3__criticalExtensions_PR_r4;
ASN::RRCConnectionSetup_r4_IEs_t *ie4 = &csp->choice.later_than_r3.criticalExtensions.choice.r4.rrcConnectionSetup_r4;
// ActivationTime_t *activationTime /* OPTIONAL */;
// U_RNTI_t new_U_RNTI;
toAsnURNTI(&ie4->new_U_RNTI,uep->getSrncId(),uep->getSRNTI());
// C_RNTI_t *new_c_RNTI /* OPTIONAL */;
ie4->new_c_RNTI = toAsnCRNTI(uep->mCRNTI);
// RRC_StateIndicator_t rrc_StateIndicator;
// 11-17-2012: Tried cell_pch state instead, to see if Samsung likes that better.
// Nope. Still sends protocol error.
asn_long2INTEGER(&ie4->rrc_StateIndicator,ASN::RRC_StateIndicator_cell_FACH);
// UTRAN_DRX_CycleLengthCoefficient_t utran_DRX_CycleLengthCoeff;
ie4->utran_DRX_CycleLengthCoeff = 3; // Must be in range 3..9
// struct CapabilityUpdateRequirement_r4 *capabilityUpdateRequirement /* OPTIONAL */;
// SRB_InformationSetupList2_t srb_InformationSetupList;
toAsnSRB_InformationSetupList(gRrcDcchConfig, &ie4->srb_InformationSetupList.list);
if (0) {
// As a debug measure to try to get the Samsung to work, try putting in the TrCh items.
// But this is just not right, the DL_CommonTransChInfo IEs dont even have an option of setting up a FACH TrCh config.
// struct UL_CommonTransChInfo_r4 *ul_CommonTransChInfo /* OPTIONAL */;
ie4->ul_CommonTransChInfo = RN_CALLOC(ASN::UL_CommonTransChInfo_r4);
typedef ASN::UL_CommonTransChInfo_r4::UL_CommonTransChInfo_r4__modeSpecificInfo ulmode;
ie4->ul_CommonTransChInfo->modeSpecificInfo = RN_CALLOC(ulmode);
ie4->ul_CommonTransChInfo->modeSpecificInfo->present = ASN::UL_CommonTransChInfo_r4__modeSpecificInfo_PR_fdd;
gRrcDcchConfig->getUlTfcs()->toAsnTfcs(&ie4->ul_CommonTransChInfo->modeSpecificInfo->choice.fdd.ul_TFCS,TrChUlDCHType);
// struct UL_AddReconfTransChInfoList *ul_AddReconfTransChInfoList /* OPTIONAL */;
ie4->ul_AddReconfTransChInfoList = toAsnUL_AddReconfTransChInfoList(gRrcDcchConfig);
// struct DL_CommonTransChInfo_r4 *dl_CommonTransChInfo /* OPTIONAL */;
ie4->dl_CommonTransChInfo = RN_CALLOC(ASN::DL_CommonTransChInfo_r4);
typedef ASN::DL_CommonTransChInfo_r4::DL_CommonTransChInfo_r4__modeSpecificInfo dlmode;
ie4->dl_CommonTransChInfo->modeSpecificInfo = RN_CALLOC(dlmode);
ie4->dl_CommonTransChInfo->modeSpecificInfo->present = ASN::DL_CommonTransChInfo_r4__modeSpecificInfo_PR_fdd;
typedef ASN::DL_CommonTransChInfo_r4::
DL_CommonTransChInfo_r4__modeSpecificInfo::
DL_CommonTransChInfo_r4__modeSpecificInfo_u::
DL_CommonTransChInfo_r4__modeSpecificInfo__fdd::
DL_CommonTransChInfo_r4__modeSpecificInfo__fdd__dl_Parameters dl_ridiculous;
ie4->dl_CommonTransChInfo->modeSpecificInfo->choice.fdd.dl_Parameters = RN_CALLOC(dl_ridiculous);
ie4->dl_CommonTransChInfo->modeSpecificInfo->choice.fdd.dl_Parameters->present =
ASN::DL_CommonTransChInfo_r4__modeSpecificInfo__fdd__dl_Parameters_PR_sameAsUL;
// struct DL_AddReconfTransChInfoList_r4 *dl_AddReconfTransChInfoList /* OPTIONAL */;
//gRrcCcchConfig->getDlTfs()->toAsnTfs(&fachPchInfo->transportFormatSet);
//gRrcCcchConfig->getUlTfs()->toAsnTfs((prach_SI->rach_TransportFormatSet = RN_CALLOC(ASN::TransportFormatSet)));
}
// struct FrequencyInfo *frequencyInfo /* OPTIONAL */;
// MaxAllowedUL_TX_Power_t *maxAllowedUL_TX_Power /* OPTIONAL */;
// struct UL_ChannelRequirement_r4 *ul_ChannelRequirement /* OPTIONAL */;
// struct DL_CommonInformation_r4 *dl_CommonInformation /* OPTIONAL */;
// struct DL_InformationPerRL_List_r4 *dl_InformationPerRL_List /* OPTIONAL */;
} // version 4
if (!encodeCcchMsg(&msg,result,descrRrcConnectionSetup,uep,0)) {return;}
// Zero out the initialUE_Identity that we copied above so that there
// is only one copy of it and we dont try to free it twice.
memset(&csp->choice.later_than_r3.initialUE_Identity,0,sizeof(ASN::InitialUE_Identity_t));
} else {
// Version 3 of this message.
// struct RRCConnectionSetup_r3_IEs
csp->present = ASN::RRCConnectionSetup_PR_r3; // Guessing we can use any of the variants.
ASN::RRCConnectionSetup_r3_IEs_t *iep = &csp->choice.r3.rrcConnectionSetup_r3;
// InitialUE_Identity_t initialUE_Identity;
// WARNING: Now there are temporarily two pointers to the memory in UE_Identity.
iep->initialUE_Identity = *ueInitialId;
// RRC_TransactionIdentifier_t rrc_TransactionIdentifier;
iep->rrc_TransactionIdentifier = transactionId;
// ActivationTime_t *activationTime /* OPTIONAL */;
// U_RNTI_t new_U_RNTI;
// U-RNTI is mandatory.
// They took apart the U_RNTI into its constituent parts, which was kinda dumb:
// the parts are 12 bit SRNC id and 20 bit S-RNTI.
toAsnURNTI(&iep->new_U_RNTI,uep->getSrncId(),uep->getSRNTI());
//setAsnBIT_STRING(&iep->new_U_RNTI.srnc_Identity,(uint8_t*)calloc(1,2),12);
//AsnBitString2BVTemp(iep->new_U_RNTI.srnc_Identity).setField(0,uep->getSrncId(),12);
//setAsnBIT_STRING(&iep->new_U_RNTI.s_RNTI,(uint8_t*)calloc(1,3),20);
//AsnBitString2BVTemp(iep->new_U_RNTI.s_RNTI).setField(0,uep->getSRNTI(),20);
// srnti = 0x12345;
//ByteVector tst(3);
//tst.setField(0,srnti,20);
//printf("SRNTI=0x%x bv=%s\n",srnti,tst.hexstr().c_str());
// C_RNTI_t *new_c_RNTI /* OPTIONAL */;
// C-RNTI
iep->new_c_RNTI = toAsnCRNTI(uep->mCRNTI);
//iep->new_c_RNTI = RN_CALLOC(ASN::C_RNTI_t);
// new_c_RNTI is a BIT_STRING_t
//setAsnBIT_STRING(iep->new_c_RNTI,(uint8_t*)calloc(1,2),16);
//AsnBitString2BVTemp(iep->new_c_RNTI).setField(0,uep->mCRNTI,16);
// RRC_StateIndicator_t rrc_StateIndicator;
asn_long2INTEGER(&iep->rrc_StateIndicator,ASN::RRC_StateIndicator_cell_FACH);
// UTRAN_DRX_CycleLengthCoefficient_t utran_DRX_CycleLengthCoeff;
// 10.3.3.49: DRC mode. "Refers to 'k' in the formula 25.304 Discontinous Reception".
iep->utran_DRX_CycleLengthCoeff = 3; // Must be in range 3..9
// skip optional CapabilityUpdateRequirement
// struct CapabilityUpdateRequirement *capabilityUpdateRequirement /* OPTIONAL */;
iep->capabilityUpdateRequirement = RN_CALLOC(ASN::CapabilityUpdateRequirement);
iep->capabilityUpdateRequirement->ue_RadioCapabilityFDDUpdateRequirement = true;
iep->capabilityUpdateRequirement->ue_RadioCapabilityTDDUpdateRequirement = false;
// SRB_InformationSetupList2_t srb_InformationSetupList;
toAsnSRB_InformationSetupList(gRrcDcchConfig, &iep->srb_InformationSetupList.list);
// struct UL_CommonTransChInfo *ul_CommonTransChInfo /* OPTIONAL */;
// struct DL_CommonInformation *dl_CommonInformation /* OPTIONAL */;
// UL_AddReconfTransChInfoList_t ul_AddReconfTransChInfoList;
// DL_AddReconfTransChInfoList_t dl_AddReconfTransChInfoList;
// All the TrCh info is optional, and not used in our case because we are
// defining RACH/FACH rather than DCH, BUT...
// For ul_ and dl_AddReconfTransChInfoList we are required to put in something anyway,
// and 8.1.3.4 recommends a single zero-sized TF.
// You can not use the "NOTHING" option - the ASN compiler just uses
// that to mark an uninitialized value and fails.
toAsnFakeUL_AddReconfTransChInfoList(&iep->ul_AddReconfTransChInfoList);
toAsnDL_AddReconfTransChInfoListSameAsUl(&iep->dl_AddReconfTransChInfoList,31,31);
// These IEs are all skipped, needed only for DCH:
// struct UL_ChannelRequirement *ul_ChannelRequirement /* OPTIONAL */;
// struct DL_InformationPerRL_List *dl_InformationPerRL_List /* OPTIONAL */;
//PhCh *phch = new PhCh(DPDCHType,256,254,256,9999,NULL);
//iep->ul_ChannelRequirement = phch->toAsnUL_ChannelRequirement();
//iep->dl_CommonInformation = phch->toAsnDL_CommonInformation();
//iep->dl_InformationPerRL_List = phch->toAsnDL_InformationPerRL_List();
/*ASN::DL_InformationPerRL_List *result2 = RN_CALLOC(ASN::DL_InformationPerRL_List);
ASN::DL_InformationPerRL *one = RN_CALLOC(ASN::DL_InformationPerRL);
one->modeSpecificInfo.present = ASN::DL_InformationPerRL__modeSpecificInfo_PR_fdd;
int primarySC = gConfig.getNum("UMTS.Downlink.ScramblingCode");
one->modeSpecificInfo.choice.fdd.primaryCPICH_Info.primaryScramblingCode = primarySC;
//one->dl_DPCH_InfoPerRL = toAsnDL_DPCH_InfoPerRL();
ASN_SEQUENCE_ADD(&result2->list,one);
iep->dl_InformationPerRL_List = result2;*/
// struct FrequencyInfo *frequencyInfo /* OPTIONAL */;
// TODO: Do we need this?
// MaxAllowedUL_TX_Power_t *maxAllowedUL_TX_Power /* OPTIONAL */;
if (!encodeCcchMsg(&msg,result,descrRrcConnectionSetup,uep,0)) {return;}
// Zero out the initialUE_Identity that we copied above so that there
// is only one copy of it and we dont try to free it twice.
memset(&iep->initialUE_Identity,0,sizeof(ASN::InitialUE_Identity_t));
}
LOG(INFO) << "gNodeB: " << gNodeB.clock().get() << ", SCCPCH: " << result;
// TODO: This crashes
// ASN_STRUCT_FREE_CONTENTS_ONLY(ASN::asn_DEF_DL_CCCH_Message,&msg);
// Configure the UE to be ready for incoming on the new SRBs...
uep->ueConnectRlc(gRrcDcchConfig,stCELL_FACH);
// Set a UeTransaction: see ueWriteLowSide for its use.
// there is no chance that other unrelated messages can happen simultaneously.
// But we will print an error if the received transaction does not match.
// The Rab Mask parameter is not relevant for this transaction type.
UeTransaction(uep,UeTransaction::ttRrcConnectionSetup, 0, transactionId,stCELL_FACH);
gMacSwitch.writeHighSideCcch(result,descrRrcConnectionSetup);
}
// Add by Sitraka for reject :
// Could be done with DL_CCCH but need to get *ueInitialId on *uep
void sendRrcConnectionReject(UEInfo *uep, ASN::InitialUE_Identity *ueInitialId){
ASN::DL_CCCH_Message msg;
memset(&msg,0,sizeof(msg));
msg.message.present = ASN::DL_CCCH_MessageType_PR_rrcConnectionReject;
ASN::RRCConnectionReject *reject = &msg.message.choice.rrcConnectionReject;
// Creating RRCConnectionReject now
//msg.message.choice.rrcConnectionReject.present = ASN::RRCConnectionReject_PR_r3;
reject->present = ASN::RRCConnectionReject_PR_r3;
ASN::RRCConnectionReject_r3_IEs_t *ies =
&msg.message.choice.rrcConnectionReject.choice.r3.rrcConnectionReject_r3;
// initial UE identity
ies->initialUE_Identity = *ueInitialId;
// transaction ID
unsigned transactionId = uep->newTransactionId();
ies->rrc_TransactionIdentifier = transactionId;
// rejection cause : Congestion or Unspecified
ies->rejectionCause = toAsnEnumerated(ASN::RejectionCause_congestion);
//waitTime 0 until 16 sec
ies->waitTime = 0;
// OPTIONNAL FOR REDIRECTION INFO PART ON Reject R3
/*Specifying redirected channel*/
ASN::RRCConnectionReject_v690ext_IEs *v690 = &reject->choice.r3.laterNonCriticalExtensions->v690NonCriticalExtensions->rrcConnectionReject_v690ext;
//In generated code C : struct GSM_TargetCellInfoList *redirectionInfo_v690ext
//Just idea : v690->redirectionInfo_v690ext = (ASN::GSM_TargetCellInfoList*)calloc(1, sizeof(ASN::GSM_TargetCellInfoList));
ASN::GSM_TargetCellInfoList *gsmTargetList = v690->redirectionInfo_v690ext;
// Set the number of GSM-TargetCellInfo instances
gsmTargetList->list.count = 2;
// Allocate memory for the GSM-TargetCellInfo instances
gsmTargetList->list.array = (ASN::GSM_TargetCellInfo**)calloc(gsmTargetList->list.count, sizeof(ASN::GSM_TargetCellInfo *));
// Set the fields of the first GSM-TargetCellInfo instance
(gsmTargetList->list.array[0])->bcch_ARFCN = 512;
// Frequency band : dcs1800BandUsed or pcs1900BandUsed
(gsmTargetList->list.array[0])->frequency_band = toAsnEnumerated(ASN::Frequency_Band_dcs1800BandUsed);
//(gsmTargetList->list.array[0])->bsic = 3; // BSIC IS NCC + BCC
// Set the fields of the second GSM-TargetCellInfo instance
(gsmTargetList->list.array[1])->bcch_ARFCN = 514;
//(gsmTargetList->list.array[1])->bsic = 5; // BSIC IS NCC + BCC
(gsmTargetList->list.array[1])->frequency_band = toAsnEnumerated(ASN::Frequency_Band_dcs1800BandUsed);
// FUTUR CASE : LATHER-THAN-R3
// WARNING: Now there are temporarily two pointers to the memory in UE_Identity.
//reject->present = ASN::RRCConnectionReject_PR_later_than_r3; // Guessing we can use any of the variants.
//reject->choice.later_than_r3.initialUE_Identity = *ueInitialId;
//reject->choice.later_than_r3.rrc_TransactionIdentifier = transactionId;
// FOR THE BYTE RESULT
ByteVector result(1000);
// WRITE THE ASN : choice 0 for urnti or may be uep->
if (!encodeCcchMsg(&msg,result,descrRrcConnectionSetup,uep,0)) {return;}
gMacSwitch.writeHighSideCcch(result,descrRrcConnectionReject);
}
// Add by Sitraka for reject2 :
// Could be done with DL_DCCH but need to get *ueInitialId on *uep
void sendRrcConnectionReject(UEInfo *uep){
ASN::DL_CCCH_Message msg;
memset(&msg,0,sizeof(msg));
msg.message.present = ASN::DL_CCCH_MessageType_PR_rrcConnectionReject;
ASN::RRCConnectionReject *reject = &msg.message.choice.rrcConnectionReject;
// Creating RRCConnectionReject now
//msg.message.choice.rrcConnectionReject.present = ASN::RRCConnectionReject_PR_r3;
reject->present = ASN::RRCConnectionReject_PR_r3;
ASN::RRCConnectionReject_r3_IEs_t *ies =
&msg.message.choice.rrcConnectionReject.choice.r3.rrcConnectionReject_r3;
// initial UE identity AsnUeId mUid = uep->mUid;
/*
ASN::InitialUE_Identity_PR idType;
public:
ByteVector mImsi, mImei, mTmsiDS41;
UInt32_z mMcc, mMnc;
UInt32_z mTmsi, mPtmsi, mEsn;
UInt16_z mLac;
UInt8_z mRac;
*/
//ies->initialUE_Identity.present = ASN::InitialUE_Identity_PR;
ASN::InitialUE_Identity ueInitialId;
ueInitialId.present = ASN::InitialUE_Identity_PR_NOTHING;
uep->mUid.asnParse(ueInitialId);
ies->initialUE_Identity = ueInitialId;
//ueInitialId.imsi = uep->mUid.mImsi;
// transaction ID
unsigned transactionId = uep->newTransactionId();
ies->rrc_TransactionIdentifier = transactionId;
// rejection cause : Congestion or Unspecified
ies->rejectionCause = toAsnEnumerated(ASN::RejectionCause_congestion);
//waitTime 0 until 16 sec
ies->waitTime = 0;
// OPTIONNAL FOR REDIRECTION INFO PART ON Reject R3
/*Specifying redirected channel*/
ASN::RRCConnectionReject_v690ext_IEs *v690 = &reject->choice.r3.laterNonCriticalExtensions->v690NonCriticalExtensions->rrcConnectionReject_v690ext;
//In generated code C : struct GSM_TargetCellInfoList *redirectionInfo_v690ext
//Just idea : v690->redirectionInfo_v690ext = (ASN::GSM_TargetCellInfoList*)calloc(1, sizeof(ASN::GSM_TargetCellInfoList));
ASN::GSM_TargetCellInfoList *gsmTargetList = v690->redirectionInfo_v690ext;
// Set the number of GSM-TargetCellInfo instances
gsmTargetList->list.count = 2;
// Allocate memory for the GSM-TargetCellInfo instances
gsmTargetList->list.array = (ASN::GSM_TargetCellInfo**)calloc(gsmTargetList->list.count, sizeof(ASN::GSM_TargetCellInfo *));
// Set the fields of the first GSM-TargetCellInfo instance
(gsmTargetList->list.array[0])->bcch_ARFCN = 512;
// Frequency band : dcs1800BandUsed or pcs1900BandUsed
(gsmTargetList->list.array[0])->frequency_band = toAsnEnumerated(ASN::Frequency_Band_dcs1800BandUsed);
//(gsmTargetList->list.array[0])->bsic = 3; // BSIC IS NCC + BCC
// Set the fields of the second GSM-TargetCellInfo instance
(gsmTargetList->list.array[1])->bcch_ARFCN = 514;
//(gsmTargetList->list.array[1])->bsic = 5; // BSIC IS NCC + BCC
(gsmTargetList->list.array[1])->frequency_band = toAsnEnumerated(ASN::Frequency_Band_dcs1800BandUsed);
// FUTUR CASE : LATHER-THAN-R3
// WARNING: Now there are temporarily two pointers to the memory in UE_Identity.
//reject->present = ASN::RRCConnectionReject_PR_later_than_r3; // Guessing we can use any of the variants.
//reject->choice.later_than_r3.initialUE_Identity = *ueInitialId;
//reject->choice.later_than_r3.rrc_TransactionIdentifier = transactionId;
// FOR THE BYTE RESULT
ByteVector result(1000);
// WRITE THE ASN : choice 0 for urnti or may be uep->msGetHandle()
if (!encodeCcchMsg(&msg,result,descrRrcConnectionSetup,uep,uep->msGetHandle())) {return;}
gMacSwitch.writeHighSideCcch(result,descrRrcConnectionReject);
}
// Sent when an unrecognized UE tries to talk to us.
// Tell it to release the connection and start over.
static void sendRrcConnectionReleaseCcch(int32_t urnti)
{
ASN::DL_CCCH_Message_t msg;
memset(&msg,0,sizeof(msg));
msg.message.present = ASN::DL_CCCH_MessageType_PR_rrcConnectionRelease;
ASN::RRCConnectionRelease_CCCH *m1 = &msg.message.choice.rrcConnectionRelease;
m1->present = ASN::RRCConnectionRelease_CCCH_PR_r3;
ASN::RRCConnectionRelease_CCCH_r3_IEs *m2 = &m1->choice.r3.rrcConnectionRelease_CCCH_r3;
unsigned srncid = urnti >> 20 & 0xfff;
unsigned srnti = urnti & 0xfffff;
toAsnURNTI(&m2->u_RNTI, srncid,srnti);
ASN::RRCConnectionRelease_r3_IEs_t *m3 = &m2->rrcConnectionRelease;
m3->rrc_TransactionIdentifier = 0; // bogus, because we are not expecting a reply.
m3->releaseCause = toAsnEnumerated(ASN::ReleaseCause_unspecified); // TODO: What cause should we use?
ByteVector result(1000);
if (!encodeCcchMsg(&msg,result,descrRrcConnectionRelease,NULL,urnti)) {return;}
gMacSwitch.writeHighSideCcch(result,descrRrcConnectionRelease);
}
// This puts the phone in idle mode.
void sendRrcConnectionRelease(UEInfo *uep) //, ASN::InitialUE_Identity *ueInitialId
{
ASN::DL_CCCH_Message_t msg;
memset(&msg,0,sizeof(msg));
msg.message.present = ASN::DL_CCCH_MessageType_PR_rrcConnectionReject;
ASN::RRCConnectionReject *reject = &msg.message.choice.rrcConnectionReject;
// Creating RRCConnectionReject now
//msg.message.choice.rrcConnectionReject.present = ASN::RRCConnectionReject_PR_r3;
reject->present = ASN::RRCConnectionReject_PR_r3;
ASN::RRCConnectionReject_r3_IEs_t *ies =
&msg.message.choice.rrcConnectionReject.choice.r3.rrcConnectionReject_r3;
//ies->initialUE_Identity.present = ASN::InitialUE_Identity_PR;