mobile / csn1: extend GSM RR support and include unit tests
This commit is contained in:
parent
e592af3cbb
commit
7d3e13c8db
|
@ -111,6 +111,7 @@ class CSN1Obj(Element):
|
|||
ret.append('H')
|
||||
return ''.join(ret)
|
||||
|
||||
|
||||
def __init__(self, **kw):
|
||||
if 'name' in kw and kw['name']:
|
||||
self._name = kw['name']
|
||||
|
@ -216,7 +217,7 @@ class CSN1Obj(Element):
|
|||
return self._val
|
||||
|
||||
def __call__(self):
|
||||
return self._val
|
||||
return self.get_val()
|
||||
|
||||
def _resolve_ref(self, ref):
|
||||
"""resolves the reference for dynamic values
|
||||
|
@ -256,6 +257,11 @@ class CSN1Obj(Element):
|
|||
# raise(CSN1Err('not implemented'))
|
||||
|
||||
def _from_char(self, char):
|
||||
# TODO: ultimately, this offset reset could be removed...
|
||||
self._off = 0
|
||||
self._from_char_csn(char)
|
||||
|
||||
def _from_char_csn(self, char):
|
||||
global _root_obj
|
||||
#
|
||||
if self._par is None:
|
||||
|
@ -279,6 +285,7 @@ class CSN1Obj(Element):
|
|||
else:
|
||||
# static number of repetitions
|
||||
num = self._num
|
||||
#csnlog('%-20s: offset %i' % (self._name, self._off))
|
||||
if num == 1:
|
||||
self._from_char_obj(char)
|
||||
elif num > 1:
|
||||
|
@ -316,6 +323,11 @@ class CSN1Obj(Element):
|
|||
_root_obj = root_obj
|
||||
|
||||
def _to_pack(self):
|
||||
# TODO: ultimately, this offset reset could be removed...
|
||||
self._off = 0
|
||||
return self._to_pack_csn()
|
||||
|
||||
def _to_pack_csn(self):
|
||||
global _root_obj
|
||||
#
|
||||
if self._par is None:
|
||||
|
@ -332,6 +344,7 @@ class CSN1Obj(Element):
|
|||
else:
|
||||
# static number of repetitions
|
||||
num = self._num
|
||||
#csnlog('%-20s: offset %i' % (self._name, self._off))
|
||||
if num == 1:
|
||||
ret.extend( self._to_pack_obj() )
|
||||
elif num == -1 or num > 1:
|
||||
|
@ -422,8 +435,8 @@ class CSN1Bit(CSN1Obj):
|
|||
self._bit = kw['bit']
|
||||
if 'type' in kw and kw['type'] != self.__class__._type:
|
||||
self._type = kw['type']
|
||||
if 'dict' in kw and kw['dict'] is not None:
|
||||
self._dic = kw['dict']
|
||||
if 'dic' in kw and kw['dic'] is not None:
|
||||
self._dic = kw['dic']
|
||||
|
||||
def _repr_val(self):
|
||||
if self._REPR == 'B' and self._type == CSN1T_UINT:
|
||||
|
@ -502,27 +515,47 @@ class CSN1Val(CSN1Obj):
|
|||
"""Class to handle a CSN.1 value
|
||||
|
||||
specific internal attributes:
|
||||
- stat: fixed bit string or 'null'
|
||||
- val: bit string or 'null'
|
||||
|
||||
specific init args:
|
||||
- val: fixed bit string or 'null' to set _stat attribute
|
||||
"""
|
||||
|
||||
_val = ''
|
||||
_val = None
|
||||
|
||||
def __init__(self, **kw):
|
||||
CSN1Obj.__init__(self, **kw)
|
||||
if 'L' in self._val or 'H' in self._val:
|
||||
if 'name' in kw and kw['name']:
|
||||
self._name = kw['name']
|
||||
if 'num' in kw and kw['num'] != 1:
|
||||
self._num = kw['num']
|
||||
if 'lref' in kw and kw['lref'] is not None:
|
||||
self._lref = kw['lref']
|
||||
# self._val can be used temporarly during encoding / decoding
|
||||
# hence the need to keep the static value into another attribute _stat
|
||||
if 'val' in kw:
|
||||
self._stat = kw['val']
|
||||
else:
|
||||
assert()
|
||||
# offset for dealing with L / H bits
|
||||
self._off = 0
|
||||
# verification and constraint on the static value
|
||||
if 'L' in self._stat or 'H' in self._stat:
|
||||
# TODO: support mixed padding L/H and non-padding 0/1 values
|
||||
assert( '0' not in self._val )
|
||||
assert( '1' not in self._val )
|
||||
assert( '0' not in self._stat )
|
||||
assert( '1' not in self._stat )
|
||||
self._pad_gsm = 1
|
||||
else:
|
||||
self._pad_gsm = 0
|
||||
if self._val[-2:] == '**':
|
||||
self._val = self._val[:-2]
|
||||
if self._stat[-2:] == '**':
|
||||
self._stat = self._stat[:-2]
|
||||
self._num = -1
|
||||
|
||||
#def set_val(self, val):
|
||||
# # CSN1Val is static, should never be updated
|
||||
# pass
|
||||
def set_val(self, val):
|
||||
self._val = val
|
||||
|
||||
def get_val(self):
|
||||
return self._val
|
||||
|
||||
def _repr_val(self):
|
||||
return self._val.__repr__()
|
||||
|
@ -530,52 +563,55 @@ class CSN1Val(CSN1Obj):
|
|||
_show_val = _repr_val
|
||||
|
||||
def _from_char_obj(self, char):
|
||||
if self._val == 'null':
|
||||
if self._stat == 'null':
|
||||
return
|
||||
bit = len(self._val)
|
||||
if bit:
|
||||
try:
|
||||
val = char.get_uint(bit)
|
||||
except CharpyErr:
|
||||
raise(CSN1NoCharErr())
|
||||
else:
|
||||
if self._pad_gsm:
|
||||
# convert val to a bit-string to be compared to self._val
|
||||
val_p = CSN1Obj.conv_b_pad_gsm(uint_to_bitstr(val, bit), self._off)
|
||||
if self._val != val_p:
|
||||
raise(CSN1InvalidValueErr())
|
||||
else:
|
||||
if int(self._val, 2) != val:
|
||||
raise(CSN1InvalidValueErr())
|
||||
self._off = (self._off + bit) % 8
|
||||
|
||||
def _to_pack_obj(self):
|
||||
if self._val == 'null':
|
||||
return []
|
||||
bit = len(self._val)
|
||||
bit = len(self._stat)
|
||||
if not bit:
|
||||
return []
|
||||
return
|
||||
try:
|
||||
val = char.get_uint(bit)
|
||||
except CharpyErr:
|
||||
raise(CSN1NoCharErr())
|
||||
else:
|
||||
if self._pad_gsm:
|
||||
bl = []
|
||||
for i, c in enumerate(self._val):
|
||||
p = self.Lv[self._off+i]
|
||||
if c == 'L':
|
||||
# padding value
|
||||
bl.append(p)
|
||||
else:
|
||||
# non-padding value
|
||||
bl.append(p^1)
|
||||
self._off = (self._off + bit) % 8
|
||||
return [(CSN1T_UINT, bitlist_to_uint(bl), bit)]
|
||||
# convert val to a bit-string to be compared to self._stat
|
||||
val_p = CSN1Obj.conv_b_pad_gsm(uint_to_bitstr(val, bit), self._off)
|
||||
if self._stat != val_p:
|
||||
raise(CSN1InvalidValueErr())
|
||||
else:
|
||||
self._val = self._stat
|
||||
else:
|
||||
self._off = (self._off + bit) % 8
|
||||
return [(CSN1T_UINT, int(self._val, 2), bit)]
|
||||
if int(self._stat, 2) != val:
|
||||
raise(CSN1InvalidValueErr())
|
||||
else:
|
||||
self._val = self._stat
|
||||
self._off = (self._off + bit) % 8
|
||||
|
||||
def _to_pack_obj(self):
|
||||
if self._stat == 'null':
|
||||
return []
|
||||
bit = len(self._stat)
|
||||
if not bit:
|
||||
return []
|
||||
if self._pad_gsm:
|
||||
bl = []
|
||||
for i, c in enumerate(self._stat):
|
||||
p = self.Lv[self._off+i]
|
||||
if c == 'L':
|
||||
# padding value
|
||||
bl.append(p)
|
||||
else:
|
||||
# non-padding value
|
||||
bl.append(p^1)
|
||||
self._off = (self._off + bit) % 8
|
||||
return [(CSN1T_UINT, bitlist_to_uint(bl), bit)]
|
||||
else:
|
||||
self._off = (self._off + bit) % 8
|
||||
return [(CSN1T_UINT, int(self._stat, 2), bit)]
|
||||
|
||||
def clone(self):
|
||||
kw = self._clone_get_kw()
|
||||
if self._val != self.__class__._val:
|
||||
kw['val'] = self._val
|
||||
kw['val'] = self._stat
|
||||
return self.__class__(**kw)
|
||||
|
||||
|
||||
|
@ -585,6 +621,9 @@ class CSN1Ref(CSN1Obj):
|
|||
specific internal attributes:
|
||||
- obj: ASN1Obj instance
|
||||
- val: value according to obj
|
||||
|
||||
specific init args:
|
||||
- obj
|
||||
"""
|
||||
|
||||
_obj = None
|
||||
|
@ -613,7 +652,7 @@ class CSN1Ref(CSN1Obj):
|
|||
obj_off, obj_val = self._obj._off, self._obj._val
|
||||
self._obj._off = self._off
|
||||
try:
|
||||
self._obj._from_char(char)
|
||||
self._obj._from_char_csn(char)
|
||||
except (CSN1NoCharErr, CSN1InvalidValueErr) as err:
|
||||
# restore offset and val
|
||||
self._obj._off, self._obj._val = obj_off, obj_val
|
||||
|
@ -628,7 +667,7 @@ class CSN1Ref(CSN1Obj):
|
|||
# transfer offset and value to self._obj
|
||||
obj_off, obj_val = self._obj._off, self._obj._val
|
||||
self._obj._off, self._obj._val = self._off, self._val
|
||||
ret = self._obj._to_pack()
|
||||
ret = self._obj._to_pack_csn()
|
||||
# restore offset and value
|
||||
self._off = self._obj._off
|
||||
self._obj._off, self._obj._val = obj_off, obj_val
|
||||
|
@ -647,6 +686,10 @@ class CSN1List(CSN1Obj):
|
|||
- list : list of CSN1Obj instances
|
||||
- trunc: enables the list of values to be truncated
|
||||
- val : list of CSN1Obj values
|
||||
|
||||
specific init args:
|
||||
- list
|
||||
- trunc
|
||||
"""
|
||||
|
||||
_list = []
|
||||
|
@ -694,7 +737,7 @@ class CSN1List(CSN1Obj):
|
|||
obj_off, obj_val = Obj._off, Obj._val
|
||||
Obj._off = self._off
|
||||
try:
|
||||
Obj._from_char(char)
|
||||
Obj._from_char_csn(char)
|
||||
except (CSN1NoCharErr, CSN1InvalidValueErr) as err:
|
||||
# restore offset and val
|
||||
Obj._off, Obj._val = obj_off, obj_val
|
||||
|
@ -715,7 +758,7 @@ class CSN1List(CSN1Obj):
|
|||
# transfer offset and value to Obj
|
||||
obj_off, obj_val = Obj._off, Obj._val
|
||||
Obj._off, Obj._val = self._off, val
|
||||
ret.extend( Obj._to_pack() )
|
||||
ret.extend( Obj._to_pack_csn() )
|
||||
# restore offset and value
|
||||
self._off = Obj._off
|
||||
Obj._off, Obj._val = obj_off, obj_val
|
||||
|
@ -861,7 +904,7 @@ class CSN1Alt(CSN1Obj):
|
|||
obj_off, obj_val = Obj._off, Obj._val
|
||||
Obj._off = self._off
|
||||
try:
|
||||
Obj._from_char(char)
|
||||
Obj._from_char_csn(char)
|
||||
except (CSN1NoCharErr, CSN1InvalidValueErr) as err:
|
||||
# restore offset and val
|
||||
Obj._off, Obj._val = obj_off, obj_val
|
||||
|
@ -905,7 +948,7 @@ class CSN1Alt(CSN1Obj):
|
|||
# transfer offset and value to Obj
|
||||
obj_off, obj_val = Obj._off, Obj._val
|
||||
Obj._off, Obj._val = self._off, val
|
||||
ret.extend( Obj._to_pack() )
|
||||
ret.extend( Obj._to_pack_csn() )
|
||||
# restore offset and value
|
||||
self._off = Obj._off
|
||||
Obj._off, Obj._val = obj_off, obj_val
|
||||
|
@ -928,7 +971,7 @@ class CSN1Alt(CSN1Obj):
|
|||
|
||||
|
||||
class CSN1SelfRef(CSN1Obj):
|
||||
"""Class to handle a reference to the root CSN1 object
|
||||
"""Class to handle a reference to a root CSN1 object
|
||||
|
||||
specific internal attributes:
|
||||
- val: value according to the root object
|
||||
|
@ -956,23 +999,24 @@ class CSN1SelfRef(CSN1Obj):
|
|||
raise(CSN1Err('{0}: no root object referenced'.format(self._name)))
|
||||
# preserve already existing root object value and offset
|
||||
# and transfer offset to it
|
||||
root_obj_off, root_obj_val = _root_obj._off, _root_obj._val
|
||||
obj_off, obj_val = _root_obj._off, _root_obj._val
|
||||
_root_obj._off = self._off
|
||||
_root_obj._from_char(char)
|
||||
_root_obj._from_char_csn(char)
|
||||
self._off, self._val = _root_obj._off, _root_obj._val
|
||||
# restore initial value and offset
|
||||
_root_obj._off, _root_obj._val = root_obj_off, root_obj_val
|
||||
_root_obj._off, _root_obj._val = obj_off, obj_val
|
||||
|
||||
def _to_pack_obj(self):
|
||||
global _root_obj
|
||||
if _root_obj is None:
|
||||
raise(CSN1Err('{0}: no root object referenced'.format(self._name)))
|
||||
# preserve already existing root object value
|
||||
root_obj_off, root_obj_val = _root_obj._off, _root_obj._val
|
||||
obj_off, obj_val = _root_obj._off, _root_obj._val
|
||||
_root_obj._off, _root_obj._val = self._off, self._val
|
||||
ret = _root_obj._to_pack()
|
||||
# restore initial value
|
||||
_root_obj._off, _root_obj._val = root_obj_off, root_obj_val
|
||||
ret = _root_obj._to_pack_csn()
|
||||
# restore initial offset and value
|
||||
self._off = _root_obj._off
|
||||
_root_obj._off, _root_obj._val = obj_off, obj_val
|
||||
return ret
|
||||
|
||||
def clone(self):
|
||||
|
|
|
@ -107,6 +107,8 @@ WARN: unable to process arithmetic expression, (M-1)
|
|||
|
||||
## 24.008
|
||||
## ms_ra_capability_value_part.py
|
||||
## 44.018
|
||||
## ia_rest_octets.py
|
||||
|
||||
# create a dict:
|
||||
_AccessTechnoType_dict = {
|
||||
|
@ -126,7 +128,9 @@ _AccessTechnoType_dict = {
|
|||
13 : 'GSM T 810',
|
||||
}
|
||||
# ref it with a kdic=_AccessTechnoType_dict
|
||||
# within the object ms_ra_capability_value_part_struct
|
||||
# within the object ms_ra_capability_value_part.ms_ra_capability_value_part_struct
|
||||
# and a dic=_AccessTechnoType_dict
|
||||
# within the object ia_rest_octets.access_technologies_request_struct
|
||||
|
||||
|
||||
## 44.018
|
||||
|
|
|
@ -37,6 +37,23 @@ from pycrate_csn1dir.egprs_window_size_ie import egprs_window_size_ie
|
|||
from pycrate_csn1dir.packet_timing_advance_ie import packet_timing_advance_ie
|
||||
from pycrate_csn1dir.egprs_level_ie import egprs_level_ie
|
||||
|
||||
_AccessTechnoType_dict = {
|
||||
0 : 'GSM P',
|
||||
1 : 'GSM E --note that GSM E covers GSM P',
|
||||
2 : 'GSM R --note that GSM R covers GSM E and GSM P',
|
||||
3 : 'GSM 1800',
|
||||
4 : 'GSM 1900',
|
||||
5 : 'GSM 450',
|
||||
6 : 'GSM 480',
|
||||
7 : 'GSM 850',
|
||||
8 : 'GSM 750',
|
||||
9 : 'GSM T 380',
|
||||
10 : 'GSM T 410',
|
||||
11 : 'unused',
|
||||
12 : 'GSM 710',
|
||||
13 : 'GSM T 810',
|
||||
}
|
||||
|
||||
# code automatically generated by pycrate_csn1
|
||||
# change object type with type=CSN1T_BSTR (default type is CSN1T_UINT) in init
|
||||
# add dict for value interpretation with dic={...} in CSN1Bit init
|
||||
|
@ -49,7 +66,7 @@ Spare_padding = spare_padding
|
|||
Spare_Padding = spare_padding
|
||||
|
||||
access_technologies_request_struct = CSN1List(name='access_technologies_request_struct', list=[
|
||||
CSN1Bit(name='access_technology_type', bit=4),
|
||||
CSN1Bit(name='access_technology_type', bit=4, dic=_AccessTechnoType_dict),
|
||||
CSN1Alt(alt={
|
||||
'0': ('', []),
|
||||
'1': ('', [
|
||||
|
|
|
@ -89,7 +89,7 @@ class Layer3(Envelope):
|
|||
self._sec = sec
|
||||
# build a list of (tag length, tag value) for the optional part
|
||||
# configure IE set by **kw as non-transparent and set their value
|
||||
self._opts = []
|
||||
self._opts, self._rest = [], None
|
||||
if val is None:
|
||||
# go faster by just looking for optional IE
|
||||
for ie in self._content:
|
||||
|
@ -97,6 +97,9 @@ class Layer3(Envelope):
|
|||
# optional IE
|
||||
T = ie[0]
|
||||
self._opts.append( (T.get_bl(), T(), ie) )
|
||||
elif isinstance(ie, RestOctets):
|
||||
# rest octets
|
||||
self._rest = ie
|
||||
else:
|
||||
for ie in self._content:
|
||||
if isinstance(ie, (Type1V, Type1TV)):
|
||||
|
@ -128,6 +131,8 @@ class Layer3(Envelope):
|
|||
self._opts.append( (8, ie[0](), ie) )
|
||||
if ie._name in val:
|
||||
ie._trans = False
|
||||
elif isinstance(ie, RestOctets):
|
||||
self._rest = ie
|
||||
elif ie._name in val:
|
||||
ie.set_val(val[ie._name])
|
||||
|
||||
|
@ -145,9 +150,13 @@ class Layer3(Envelope):
|
|||
# in case some optional IE are set (with transparency enabled)
|
||||
# they are decoded as much as the char buffer allows it
|
||||
# 1) decode mandatory part
|
||||
if self._rest is not None:
|
||||
self._rest.set_trans(True)
|
||||
dec_brk = self.DEC_BREAK_ON_UNK_IE
|
||||
self.DEC_BREAK_ON_UNK_IE = True
|
||||
Envelope._from_char(self, char)
|
||||
# 2) decode optional part
|
||||
opts = self._opts[:]
|
||||
opts, dec = self._opts[:], False
|
||||
while char.len_bit() >= 8:
|
||||
T4, T8, dec = char.to_uint(4), char.to_uint(8), False
|
||||
for i, opt in enumerate(opts):
|
||||
|
@ -163,11 +172,16 @@ class Layer3(Envelope):
|
|||
if not dec:
|
||||
# unknown IEI
|
||||
if self.DEC_BREAK_ON_UNK_IE:
|
||||
log('%s, unknown IE remaining, not decoded' % self._name)
|
||||
#log('%s, unknown IE remaining, not decoded' % self._name)
|
||||
break
|
||||
else:
|
||||
char._cur += 8
|
||||
self._dec_unk_ie(T8, char)
|
||||
# 3) decode rest octets
|
||||
if not dec and self._rest is not None:
|
||||
self._rest.set_trans(False)
|
||||
self.DEC_BREAK_ON_UNK_IE = dec_brk
|
||||
self._rest._from_char(char)
|
||||
|
||||
def _dec_unk_ie(self, T8, char):
|
||||
if T8 & 0x80:
|
||||
|
@ -515,17 +529,23 @@ class Type6TLVE(IE):
|
|||
self[2].set_blauto(lambda: 8*self[1].get_val())
|
||||
|
||||
|
||||
class RestOctets(Type3V):
|
||||
class RestOctets(IE):
|
||||
"""Rest octets (or Type5) IE is a specific IE only used in GSM / GPRS
|
||||
its content is a single buffer of variable length, which is tied to the
|
||||
L2PseudoLength at the beginning of the L3 GSM message containing it
|
||||
"""
|
||||
_GEN = (
|
||||
BufAuto('V', rep=REPR_HEX),
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
Type3V.__init__(self, *args, **kwargs)
|
||||
# The length of V is not fixed, but tied to the L2PseudoLength element
|
||||
# prefixing the envelope element
|
||||
self[0].set_blauto(lambda: 176 - (self.get_env()[0][0].get_val()<<3))
|
||||
IE.__init__(self, *args, **kwargs)
|
||||
self[0].PAD_VAL = b'+' # 0x2b, GSM padding
|
||||
if self[0]._bl is None:
|
||||
# in case the length is not fixed at init, it is handled in
|
||||
# a dynamic way, tied to the L2PseudoLength element prefixing the
|
||||
# parent Layer3 envelope
|
||||
self[0].set_blauto(lambda: 176 - (self.get_env()[0][0].get_val()<<3))
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
|
|
|
@ -92,8 +92,11 @@ from pycrate_csn1dir.gprs_broadcast_information_value_part import gprs_broa
|
|||
from pycrate_csn1dir.mprach_description_value_part import mprach_description_value_part
|
||||
from pycrate_csn1dir.mbms_p_t_m_channel_description_value_part import mbms_p_t_m_channel_description_value_part
|
||||
from pycrate_csn1dir.mbms_session_parameters_list_value_part import mbms_session_parameters_list_value_part
|
||||
from pycrate_csn1dir.ec_packet_channel_description_type_1 import ec_packet_channel_description_type_1
|
||||
from pycrate_csn1dir.rr_packet_downlink_assignment_type_2_value_part import \
|
||||
rr_packet_downlink_assignment_type_2_value_part
|
||||
from pycrate_csn1dir.ec_immediate_assignment_type_2_message_content import \
|
||||
ec_immediate_assignment_type_2_message_content
|
||||
from pycrate_csn1dir.cell_selection_indicator_after_release_of_all_tch_and_sdcch_value_part import \
|
||||
cell_selection_indicator_after_release_of_all_tch_and_sdcch_value_part
|
||||
|
||||
|
@ -102,45 +105,13 @@ from pycrate_csn1dir.cell_selection_indicator_after_release_of_all_tch_and_sdcch
|
|||
# generic objects
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
'''to be removed
|
||||
def smod(n, m):
|
||||
"""
|
||||
offset remainder of the euclidian division of n by m:
|
||||
1 <= (n smod m) <= m and there exists k such that
|
||||
n = (k*m) + (n smod m);
|
||||
"""
|
||||
r = n%m
|
||||
if r == 0:
|
||||
return m
|
||||
else:
|
||||
return r
|
||||
|
||||
|
||||
def build_ext_dict(d, kend=None):
|
||||
"""extends a dict d that has only integral keys
|
||||
"""
|
||||
if not d:
|
||||
return {}
|
||||
di = sorted(d.items())
|
||||
ret = [di[0]]
|
||||
for i in range(1, len(di)):
|
||||
while di[i][0] > 1+ret[-1][0]:
|
||||
# hole in d, extend ret
|
||||
ret.append( (ret[-1][0]+1, ret[-1][1]) )
|
||||
ret.append( di[i] )
|
||||
if kend:
|
||||
while kend > ret[-1][0]:
|
||||
ret.append( (ret[-1][0]+1, ret[-1][1]) )
|
||||
return dict(ret)
|
||||
'''
|
||||
|
||||
class BitMap(Buf):
|
||||
"""handles bit map
|
||||
|
||||
derives from the Buf object and includes get() / set() / unset() methods
|
||||
for handling bit value at given offset
|
||||
"""
|
||||
_pre = REPR_BIN
|
||||
_rep = REPR_HEX
|
||||
|
||||
# dedicated method to get, set and unset at a given offset
|
||||
def get(self, off):
|
||||
|
@ -401,8 +372,8 @@ class FreqListBitmap0(BitMap):
|
|||
"""returns the list of ARFCNs set
|
||||
"""
|
||||
arfcns = []
|
||||
ar_uint = self.to_uint()
|
||||
for i in range(0, 124):
|
||||
ar_uint, ar_bl = self.to_uint(), 124
|
||||
for i in range(0, ar_bl):
|
||||
if ar_uint & (1<<i):
|
||||
arfcns.append(1+i)
|
||||
arfcns.sort()
|
||||
|
@ -411,9 +382,9 @@ class FreqListBitmap0(BitMap):
|
|||
def encode(self, arfcns):
|
||||
"""sets a list of ARFCNs
|
||||
"""
|
||||
ar_uint = 0
|
||||
ar_uint, ar_bl = 0, 124
|
||||
for ar in set(arfcns):
|
||||
if isinstance(ar, integer_types) and 0 < ar <= 124:
|
||||
if isinstance(ar, integer_types) and 0 < ar <= ar_bl:
|
||||
ar_uint += 1<<(124-ar)
|
||||
self.set_val(uint_to_bytes(ar_uint, 124))
|
||||
|
||||
|
@ -446,7 +417,7 @@ class CellChanAlt2(_FreqListAlt2):
|
|||
0: CellChanRange512(),
|
||||
1: CellChanRange256(),
|
||||
2: CellChanRange128(),
|
||||
3: FreqListBitmapVar('CellChanBitmapVar')},
|
||||
3: FreqListBitmapVar('CellChanBitmapVar', bl=111)},
|
||||
sel=lambda self: self.get_env()[0].get_val())
|
||||
)
|
||||
|
||||
|
@ -825,7 +796,7 @@ class CtrlChanDesc(Envelope):
|
|||
Uint('BS-AG-BLKS-RES', bl=3),
|
||||
Uint('CCCHConf', bl=3, dic=_CCCHConf_dict),
|
||||
Uint('SI22Ind', bl=1, dic={1:'SI22 broadcasted'}),
|
||||
Uint('CBQ3', bl=1, dic=_CBQ3_dict),
|
||||
Uint('CBQ3', bl=2, dic=_CBQ3_dict),
|
||||
Uint('spare', bl=2),
|
||||
Uint('BS-PA-MFRMS', bl=3),
|
||||
Uint8('T3212', dic={0:'periodic location updating shall not be used in the cell'})
|
||||
|
@ -902,7 +873,7 @@ class FreqListAlt2(_FreqListAlt2):
|
|||
)
|
||||
|
||||
|
||||
class FreqListAlt1(_FreqList):
|
||||
class FreqListAlt1(_FreqListAlt1):
|
||||
_GEN = (
|
||||
Uint('FmtExt', bl=1, dic={0:'range 1024'}),
|
||||
Alt(GEN={
|
||||
|
@ -958,7 +929,7 @@ class FreqShortListAlt2(_FreqListAlt2):
|
|||
0: FreqShortListRange512(),
|
||||
1: FreqShortListRange256(),
|
||||
2: FreqShortListRange128(),
|
||||
3: FreqListBitmapVar('FreqShortListBitmapVar')},
|
||||
3: FreqListBitmapVar('FreqShortListBitmapVar', bl=55)},
|
||||
sel=lambda self: self.get_env()[0].get_val())
|
||||
)
|
||||
|
||||
|
@ -1087,7 +1058,10 @@ class L2PseudoLength(Envelope):
|
|||
)
|
||||
def __init__(self, *args, **kwargs):
|
||||
Envelope.__init__(self, *args, **kwargs)
|
||||
self[0].set_valauto(lambda: self._get_l2pl())
|
||||
if self[0]._val is None:
|
||||
# in case the Value is not fixed at init, it is handled in
|
||||
# a dynamic way
|
||||
self[0].set_valauto(lambda: self._get_l2pl())
|
||||
|
||||
def _get_l2pl(self):
|
||||
l2pl = 0
|
||||
|
@ -1191,6 +1165,20 @@ class NeighbourCellChan(Envelope):
|
|||
DEFAULT=Buf('undefined', rep=REPR_HEX),
|
||||
sel=lambda self: self.get_env()[0].get_val())
|
||||
)
|
||||
|
||||
def decode(self):
|
||||
"""returns the list of ARFCNs set
|
||||
"""
|
||||
try:
|
||||
return self[3].get_alt().decode()
|
||||
except:
|
||||
return []
|
||||
|
||||
def encode(self, arfcns):
|
||||
"""sets the list of ARFCNs
|
||||
"""
|
||||
# TODO: choose the best possible encoding ?!
|
||||
raise(PycrateErr('not implemented'))
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
|
@ -1210,6 +1198,20 @@ class NeighbourCellChan2(Envelope):
|
|||
1: CellChanAlt1()},
|
||||
sel=lambda self: self.get_env()[0].get_val())
|
||||
)
|
||||
|
||||
def decode(self):
|
||||
"""returns the list of ARFCNs set
|
||||
"""
|
||||
try:
|
||||
return self[3].get_alt().decode()
|
||||
except:
|
||||
return []
|
||||
|
||||
def encode(self, arfcns):
|
||||
"""sets the list of ARFCNs
|
||||
"""
|
||||
# TODO: choose the best possible encoding ?!
|
||||
raise(PycrateErr('not implemented'))
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
|
|
|
@ -749,7 +749,7 @@ def get_tbf(l3msg):
|
|||
|
||||
class RRImmediateAssignment(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(excl=(0, 9, 10)),
|
||||
L2PseudoLength(),
|
||||
RRHeader(val={'Type':63}),
|
||||
Type1V('DedicatedModeOrTBF', val={'V':0}, IE=DedicatedModeOrTBF()),
|
||||
Type1V('PageMode', val={'V':0}, dic=PageMode_dict),
|
||||
|
@ -815,7 +815,7 @@ class RRImmediateAssignmentExt(Layer3):
|
|||
|
||||
class RRImmediateAssignmentReject(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':19}),
|
||||
RRHeader(val={'Type':58}),
|
||||
Type1V('FeatureInd', val={'V':0}, IE=FeatureInd()),
|
||||
Type1V('PageMode', val={'V':0}, dic=PageMode_dict),
|
||||
|
@ -827,7 +827,7 @@ class RRImmediateAssignmentReject(Layer3):
|
|||
Type3V('WaitInd3', val={'V':b'\0'}, bl={'V':8}, IE=T3122()),
|
||||
Type3V('RequestRef4', val={'V':b'\0\0\0'}, bl={'V':24}, IE=RequestRef()),
|
||||
Type3V('WaitInd4', val={'V':b'\0'}, bl={'V':8}, IE=T3122()),
|
||||
RestOctets('IARRestOctets', IE=iar_rest_octets)
|
||||
RestOctets('IARRestOctets', bl={'V': 24}, IE=iar_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -858,9 +858,9 @@ class RRMeasurementReport(Layer3):
|
|||
|
||||
class RRNotificationNCH(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':1}),
|
||||
RRHeader(val={'Type':32}),
|
||||
RestOctets('NTNRestOctets', IE=ntn_rest_octets),
|
||||
RestOctets('NTNRestOctets', bl={'V':160}, IE=ntn_rest_octets),
|
||||
)
|
||||
|
||||
|
||||
|
@ -985,7 +985,7 @@ class RRPagingReq2(Layer3):
|
|||
|
||||
class RRPagingReq3(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':19}),
|
||||
RRHeader(val={'Type':36}),
|
||||
Type1V('ChanNeeded', val={'V':0}, IE=ChanNeeded()),
|
||||
Type1V('PageMode', val={'V':0}, dic=PageMode_dict),
|
||||
|
@ -993,7 +993,7 @@ class RRPagingReq3(Layer3):
|
|||
Type3V('ID2', val={'V':4*b'\0'}, bl={'V':32}, IE=TMSI()),
|
||||
Type3V('ID3', val={'V':4*b'\0'}, bl={'V':32}, IE=TMSI()),
|
||||
Type3V('ID4', val={'V':4*b'\0'}, bl={'V':32}, IE=TMSI()),
|
||||
RestOctets('P3RestOctets', IE=p3_rest_octets)
|
||||
RestOctets('P3RestOctets', bl={'V':24}, IE=p3_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1088,11 +1088,11 @@ class RRStatus(Layer3):
|
|||
|
||||
class RRSystemInfo1(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':21}),
|
||||
RRHeader(val={'Type':25}),
|
||||
Type3V('CellChan', val={'V':16*b'\0'}, bl={'V':128}, IE=CellChan()),
|
||||
Type3V('RACHCtrl', val={'V':b'\0\0\0'}, bl={'V':24}, IE=RACHCtrl()),
|
||||
RestOctets('SI1RestOctets', IE=si1_rest_octets)
|
||||
RestOctets('SI1RestOctets', bl={'V':8}, IE=si1_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1103,7 +1103,7 @@ class RRSystemInfo1(Layer3):
|
|||
|
||||
class RRSystemInfo2(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':22}),
|
||||
RRHeader(val={'Type':26}),
|
||||
Type3V('BCCHFreqList', val={'V':16*b'\0'}, bl={'V':128}, IE=NeighbourCellChan()),
|
||||
Type3V('NCCPermitted', val={'V':b'\0'}, bl={'V':8}, IE=NCCPermitted()),
|
||||
|
@ -1118,11 +1118,11 @@ class RRSystemInfo2(Layer3):
|
|||
|
||||
class RRSystemInfo2bis(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':21}),
|
||||
RRHeader(val={'Type':2}),
|
||||
Type3V('ExtBCCHFreqList', val={'V':16*b'\0'}, bl={'V':128}, IE=NeighbourCellChan()),
|
||||
Type3V('RACHCtrl', val={'V':b'\0\0\0'}, bl={'V':24}, IE=RACHCtrl()),
|
||||
RestOctets('SI2bisRestOctets', IE=si2bis_rest_octets)
|
||||
RestOctets('SI2bisRestOctets', bl={'V':8}, IE=si2bis_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1133,10 +1133,10 @@ class RRSystemInfo2bis(Layer3):
|
|||
|
||||
class RRSystemInfo2ter(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':18}),
|
||||
RRHeader(val={'Type':3}),
|
||||
Type3V('ExtBCCHFreqList', val={'V':16*b'\0'}, bl={'V':128}, IE=NeighbourCellChan2()),
|
||||
RestOctets('SI2terRestOctets', IE=si2ter_rest_octets)
|
||||
RestOctets('SI2terRestOctets', bl={'V':32}, IE=si2ter_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1147,9 +1147,9 @@ class RRSystemInfo2ter(Layer3):
|
|||
|
||||
class RRSystemInfo2quater(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':1}),
|
||||
RRHeader(val={'Type':7}),
|
||||
RestOctets('SI2quaterRestOctets', IE=si2quater_rest_octets)
|
||||
RestOctets('SI2quaterRestOctets', bl={'V':160}, IE=si2quater_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1160,9 +1160,9 @@ class RRSystemInfo2quater(Layer3):
|
|||
|
||||
class RRSystemInfo2n(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':1}),
|
||||
RRHeader(val={'Type':69}),
|
||||
RestOctets('SI2nRestOctets', IE=si2n_rest_octets)
|
||||
RestOctets('SI2nRestOctets', bl={'V':160}, IE=si2n_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1173,7 +1173,7 @@ class RRSystemInfo2n(Layer3):
|
|||
|
||||
class RRSystemInfo3(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':18}),
|
||||
RRHeader(val={'Type':27}),
|
||||
Type3V('CellId', val={'V':b'\0\0'}, bl={'V':16}, IE=CellId()),
|
||||
Type3V('LAI', val={'V': b'\0\xf1\x10\0\0'}, bl={'V':40}, IE=LAI()),
|
||||
|
@ -1181,7 +1181,7 @@ class RRSystemInfo3(Layer3):
|
|||
Type3V('CellOpt', val={'V':b'\0'}, bl={'V':8}, IE=CellOpt()),
|
||||
Type3V('CellSelParams', val={'V':b'\0\0'}, bl={'V':16}, IE=CellSelParams()),
|
||||
Type3V('RACHCtrl', val={'V':b'\0\0\0'}, bl={'V':24}, IE=RACHCtrl()),
|
||||
RestOctets('SI3RestOctets', IE=si3_rest_octet)
|
||||
RestOctets('SI3RestOctets', bl={'V':32}, IE=si3_rest_octet)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1210,7 +1210,7 @@ class RRSystemInfo4(Layer3):
|
|||
|
||||
class RRSystemInfo5(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':18}),
|
||||
RRHeaderSACCH(val={'Type':29}),
|
||||
Type3V('BCCHFreqList', val={'V':16*b'\0'}, bl={'V':128}, IE=NeighbourCellChan())
|
||||
)
|
||||
|
@ -1223,7 +1223,7 @@ class RRSystemInfo5(Layer3):
|
|||
|
||||
class RRSystemInfo5bis(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':18}),
|
||||
RRHeaderSACCH(val={'Type':5}),
|
||||
Type3V('ExtBCCHFreqList', val={'V':16*b'\0'}, bl={'V':128}, IE=NeighbourCellChan())
|
||||
)
|
||||
|
@ -1236,7 +1236,7 @@ class RRSystemInfo5bis(Layer3):
|
|||
|
||||
class RRSystemInfo5ter(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':18}),
|
||||
RRHeaderSACCH(val={'Type':6}),
|
||||
Type3V('ExtBCCHFreqList', val={'V':16*b'\0'}, bl={'V':128}, IE=NeighbourCellChan2())
|
||||
)
|
||||
|
@ -1249,13 +1249,13 @@ class RRSystemInfo5ter(Layer3):
|
|||
|
||||
class RRSystemInfo6(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':11}),
|
||||
RRHeaderSACCH(val={'Type':30}),
|
||||
Type3V('CellId', val={'V':b'\0\0'}, bl={'V':16}, IE=CellId()),
|
||||
Type3V('LAI', val={'V': b'\0\xf1\x10\0\0'}, bl={'V':40}, IE=LAI()),
|
||||
Type3V('CellOpt', val={'V':b'\0'}, bl={'V':8}, IE=CellOpt()),
|
||||
Type3V('NCCPermitted', val={'V':b'\0'}, bl={'V':8}, IE=NCCPermitted()),
|
||||
RestOctets('SI6RestOctets', IE=si6_rest_octets)
|
||||
RestOctets('SI6RestOctets', bl={'V':56}, IE=si6_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1266,9 +1266,9 @@ class RRSystemInfo6(Layer3):
|
|||
|
||||
class RRSystemInfo7(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':1}),
|
||||
RRHeader(val={'Type':31}),
|
||||
RestOctets('SI7RestOctets', IE=si4_rest_octets)
|
||||
RestOctets('SI7RestOctets', bl={'V':160}, IE=si4_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1279,9 +1279,9 @@ class RRSystemInfo7(Layer3):
|
|||
|
||||
class RRSystemInfo8(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':1}),
|
||||
RRHeader(val={'Type':24}),
|
||||
RestOctets('SI7RestOctets', IE=si4_rest_octets)
|
||||
RestOctets('SI7RestOctets', bl={'V':160}, IE=si4_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1292,10 +1292,10 @@ class RRSystemInfo8(Layer3):
|
|||
|
||||
class RRSystemInfo9(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':1}),
|
||||
RRHeader(val={'Type':4}),
|
||||
Type3V('RACHCtrl', val={'V':b'\0\0\0'}, bl={'V':24}, IE=RACHCtrl()),
|
||||
RestOctets('SI9RestOctets', IE=si9_rest_octets)
|
||||
RestOctets('SI9RestOctets', bl={'V':136}, IE=si9_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1306,9 +1306,9 @@ class RRSystemInfo9(Layer3):
|
|||
|
||||
class RRSystemInfo13(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':0}),
|
||||
RRHeader(val={'Type':0}),
|
||||
RestOctets('SI13RestOctets', IE=si_13_rest_octets)
|
||||
RestOctets('SI13RestOctets', bl={'V':160}, IE=si_13_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1319,9 +1319,9 @@ class RRSystemInfo13(Layer3):
|
|||
|
||||
class RRSystemInfo16(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':1}),
|
||||
RRHeader(val={'Type':61}),
|
||||
RestOctets('SI16RestOctets', IE=si16_rest_octets)
|
||||
RestOctets('SI16RestOctets', bl={'V':160}, IE=si16_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1332,9 +1332,9 @@ class RRSystemInfo16(Layer3):
|
|||
|
||||
class RRSystemInfo17(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':1}),
|
||||
RRHeader(val={'Type':62}),
|
||||
RestOctets('SI17RestOctets', IE=si17_rest_octets)
|
||||
RestOctets('SI17RestOctets', bl={'V':160}, IE=si17_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1345,9 +1345,9 @@ class RRSystemInfo17(Layer3):
|
|||
|
||||
class RRSystemInfo19(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':1}),
|
||||
RRHeader(val={'Type':65}),
|
||||
RestOctets('SI19RestOctets', IE=si_19_rest_octets)
|
||||
RestOctets('SI19RestOctets', bl={'V':160}, IE=si_19_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1358,9 +1358,9 @@ class RRSystemInfo19(Layer3):
|
|||
|
||||
class RRSystemInfo18(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':1}),
|
||||
RRHeader(val={'Type':64}),
|
||||
RestOctets('SI18RestOctets', IE=si_18_rest_octets)
|
||||
RestOctets('SI18RestOctets', bl={'V':160}, IE=si_18_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1371,9 +1371,9 @@ class RRSystemInfo18(Layer3):
|
|||
|
||||
class RRSystemInfo20(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':1}),
|
||||
RRHeader(val={'Type':66}),
|
||||
RestOctets('SI20RestOctets', IE=si_18_rest_octets)
|
||||
RestOctets('SI20RestOctets', bl={'V':160}, IE=si_18_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1384,9 +1384,9 @@ class RRSystemInfo20(Layer3):
|
|||
|
||||
class RRSystemInfo14(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':18}), # this 44.018 spec does not make sens at all !!!
|
||||
RRHeaderSACCH(val={'Type':1}),
|
||||
RestOctets('SI14RestOctets', IE=si14_rest_octets)
|
||||
RestOctets('SI14RestOctets', bl={'V':128}, IE=si14_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1397,9 +1397,9 @@ class RRSystemInfo14(Layer3):
|
|||
|
||||
class RRSystemInfo15(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':1}),
|
||||
RRHeader(val={'Type':67}),
|
||||
RestOctets('SI15RestOctets', IE=si15_rest_octets)
|
||||
RestOctets('SI15RestOctets', bl={'V':160}, IE=si15_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1410,9 +1410,9 @@ class RRSystemInfo15(Layer3):
|
|||
|
||||
class RRSystemInfo13alt(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':0}),
|
||||
RRHeader(val={'Type':68}),
|
||||
RestOctets('SI13altRestOctets', IE=si_13alt_rest_octets)
|
||||
RestOctets('SI13altRestOctets', bl={'V':160}, IE=si_13alt_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1423,9 +1423,9 @@ class RRSystemInfo13alt(Layer3):
|
|||
|
||||
class RRSystemInfo21(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':2}),
|
||||
RRHeader(val={'Type':70}),
|
||||
RestOctets('SI21RestOctets', IE=si_21_rest_octets)
|
||||
RestOctets('SI21RestOctets', bl={'V':160}, IE=si_21_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1436,9 +1436,9 @@ class RRSystemInfo21(Layer3):
|
|||
|
||||
class RRSystemInfo22(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':2}),
|
||||
RRHeader(val={'Type':71}),
|
||||
RestOctets('SI22RestOctets', IE=si_22_rest_octets)
|
||||
RestOctets('SI22RestOctets', bl={'V':160}, IE=si_22_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1449,9 +1449,9 @@ class RRSystemInfo22(Layer3):
|
|||
|
||||
class RRSystemInfo23(Layer3):
|
||||
_GEN = (
|
||||
L2PseudoLength(),
|
||||
L2PseudoLength(val={'Value':2}),
|
||||
RRHeader(val={'Type':79}),
|
||||
RestOctets('SI23RestOctets', IE=si_23_rest_octets)
|
||||
RestOctets('SI23RestOctets', bl={'V':160}, IE=si_23_rest_octets)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1736,9 +1736,14 @@ class RRECImmediateAssignment1(Layer3):
|
|||
Type1V('FeatureInd', val={'V':0}, IE=FeatureInd()),
|
||||
Type1V('PageMode', val={'V':0}, dic=PageMode_dict),
|
||||
Type3V('RequestRef', val={'V':b'\0\0\0'}, bl={'V':24}, IE=RequestRef()),
|
||||
Type3V('ECPacketChannelDesc1', val={'V':b'\0\0'}, bl={'V':16}, ),
|
||||
RestOctets('ECFixedUplinkAlloc', )
|
||||
)
|
||||
Type3V('ECPacketChannelDesc1', val={'V':b'\0\0'}, bl={'V':16}, IE=ec_packet_channel_description_type_1),
|
||||
Type3V('ECFixedUplinkAlloc', val={'V':4*b'\0'}, IE=ec_immediate_assignment_type_2_message_content),
|
||||
RestOctets('rest')
|
||||
)
|
||||
def __init__(self, *args, **kwargs):
|
||||
Layer3.__init__(self, *args, **kwargs)
|
||||
self[0][0].set_valauto(lambda: (64+self[6].get_bl())>>3)
|
||||
self[6][0].set_blauto(lambda: (self[0][0].get_val()<<3)-64)
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
|
|
|
@ -47,6 +47,12 @@ rr_pdu_mo = tuple(map(unhexlify, (
|
|||
)))
|
||||
|
||||
rr_pdu_mt = tuple(map(unhexlify, (
|
||||
# DCCH
|
||||
'063505', # ciphering mode cmd
|
||||
'060d00', # channel release
|
||||
)))
|
||||
|
||||
rr_pdu_l2_mt = tuple(map(unhexlify, (
|
||||
# BCCH
|
||||
'2d063f110e600c7f1d3800004bc26b0284b510f32b2b2b', # immediate assignment
|
||||
'35063f0178b18207ec1704021fff2b2b2b2b2b2b2b2b2b',
|
||||
|
@ -63,13 +69,11 @@ rr_pdu_mt = tuple(map(unhexlify, (
|
|||
'49061bfae102f8100310c8021e1785407900008000029b', # SI type 3
|
||||
'31061c02f810031085407900008000572b2b2b2b2b2b2b', # SI type 4
|
||||
# SACCH
|
||||
'061d00000000000000000000000000007eff', # SI type 5
|
||||
'061e87e902f810031097ff2b2b2b2b2b2b2b', # SI type 6
|
||||
# DCCH
|
||||
'063505', # ciphering mode cmd
|
||||
'060d00', # channel release
|
||||
'49061d00000000000000000000000000007eff', # SI type 5
|
||||
'2d061e87e902f810031097ff2b2b2b2b2b2b2b', # SI type 6
|
||||
)))
|
||||
|
||||
|
||||
def test_gsmrr_mo(rr_pdu=rr_pdu_mo):
|
||||
for pdu in rr_pdu:
|
||||
m, e = parse_NAS_MO(pdu)
|
||||
|
@ -79,6 +83,15 @@ def test_gsmrr_mo(rr_pdu=rr_pdu_mo):
|
|||
m.set_val(v)
|
||||
assert( m.to_bytes() == pdu )
|
||||
|
||||
def test_gsmrr_l2_mt(rr_pdu=rr_pdu_l2_mt):
|
||||
for pdu in rr_pdu:
|
||||
m, e = parse_NAS_MT(pdu, wl2=True)
|
||||
assert( e == 0 )
|
||||
m.reautomate()
|
||||
v = m.get_val()
|
||||
m.set_val(v)
|
||||
assert( m.to_bytes() == pdu )
|
||||
|
||||
def test_gsmrr_mt(rr_pdu=rr_pdu_mt):
|
||||
for pdu in rr_pdu:
|
||||
m, e = parse_NAS_MT(pdu)
|
||||
|
@ -91,11 +104,15 @@ def test_gsmrr_mt(rr_pdu=rr_pdu_mt):
|
|||
def test_perf():
|
||||
|
||||
print('[+] GSM RR MO decoding and re-encoding')
|
||||
Ta = timeit(test_gsmrr_mo, number=10)
|
||||
Ta = timeit(test_gsmrr_mo, number=20)
|
||||
print('test_nas_mo: {0:.4f}'.format(Ta))
|
||||
|
||||
print('[+] GSM RR MT decoding and re-encoding')
|
||||
Tb = timeit(test_gsmrr_mt, number=10)
|
||||
Tb = timeit(test_gsmrr_mt, number=100)
|
||||
print('test_nas_mt: {0:.4f}'.format(Tb))
|
||||
|
||||
print('[+] GSM RR L2 MT decoding and re-encoding')
|
||||
Tb = timeit(test_gsmrr_l2_mt, number=5)
|
||||
print('test_nas_mt: {0:.4f}'.format(Tb))
|
||||
|
||||
print('[+] GSM RR total time: {0:.4f}'.format(Ta+Tb))
|
||||
|
|
Loading…
Reference in New Issue