1% EtherCat test campaign 2 3# 4# execute test: 5# $ test/run_tests -P "load_contrib('ethercat')" -t test/contrib/ethercat.uts 6# 7 8+ LEBitFields 9= regression test 10 11TEST_SAMPLE_ENUM = { 12 0x01: 'one', 13 0x02: 'two', 14 0x03: 'three', 15 0x04: 'four', 16 0x05: 'five', 17 0x06: 'six', 18 0x07: 'seven' 19} 20 21class BitFieldUserExampleLE(Packet): 22 23 fields_desc = [ 24 LEBitEnumField('a', 0, 2, TEST_SAMPLE_ENUM), 25 LEBitField('b', 0, 18), 26 LEBitField('c', 0, 5), 27 LEBitField('d', 0, 23), 28 ] 29 30class BitFieldUserExample(Packet): 31 32 fields_desc = [ 33 BitEnumField('a', 0, 2, TEST_SAMPLE_ENUM), 34 BitField('b', 0, 18), 35 BitField('c', 0, 5), 36 BitField('d', 0, 23), 37 ] 38 39test_data = [ 40 { 41 'a':0x01, 42 'b':0x00, 43 'c':0x00, 44 'd':0x123456 45 }, 46 { 47 'a': 0x00, 48 'b': 0b111111111111111111, 49 'c': 0x00, 50 'd': 0x112233 51 }, 52 { 53 'a': 0x00, 54 'b': 0x00, 55 'c': 0x01, 56 'd': 0x00 57 }, 58] 59 60for data in test_data: 61 bf_le = BitFieldUserExampleLE(**data) 62 bf = BitFieldUserExample(**data) 63 # rebuild big-endian and little-endian bitfields from its own binary expressions 64 bf_le = BitFieldUserExampleLE(bf_le.do_build()) 65 bf = BitFieldUserExample(bf.do_build()) 66 ''' disabled as only required for 'visual debugging' 67 from scapy.compat import raw 68 # dump content for debugging 69 bitstr = '' 70 hexstr = '' 71 for i in bytearray(raw(bf)): 72 bitstr += '{:08b} '.format(i) 73 hexstr += '{:02x} '.format(i) 74 print('BE - BITS: {} HEX: {} ({})'.format(bitstr, hexstr, data)) 75 bitstr = '' 76 hexstr = '' 77 for i in bytearray(raw(bf_le)): 78 bitstr += '{:08b} '.format(i) 79 hexstr += '{:02x} '.format(i) 80 print('LE - BITS: {} HEX: {} ({})'.format(bitstr, hexstr, data)) 81 ''' 82 # compare values 83 for key in data: 84 assert getattr(bf,key) == data[key] 85 assert (getattr(bf_le, key) == data[key]) 86 87= Avoid mix of LEBitFields and BitFields 88 89TEST_SAMPLE_ENUM = { 90 0x01: 'one', 91 0x02: 'two', 92 0x03: 'three', 93 0x04: 'four', 94 0x05: 'five', 95 0x06: 'six', 96 0x07: 'seven' 97} 98 99class MissingFieldSameLEFieldTypes(Packet): 100 101 fields_desc = [ 102 LEBitEnumField('a', 0, 2, TEST_SAMPLE_ENUM), 103 LEBitField('b', 0, 18), 104 ] 105 106try: 107 frm = MissingFieldSameLEFieldTypes().build() 108 assert False 109except LEBitFieldSequenceException: 110 pass 111 112 113class MissingFieldDifferentLEFieldTypes(Packet): 114 115 fields_desc = [ 116 LEBitEnumField('a', 0, 2, TEST_SAMPLE_ENUM), 117 LEBitField('b', 0, 18), 118 ] 119 120try: 121 frm = MissingFieldDifferentLEFieldTypes().build() 122 assert False 123except LEBitFieldSequenceException: 124 pass 125 126 127class MixedBitFieldTypesLEBE(Packet): 128 129 fields_desc = [ 130 LEBitField('a', 0, 12), 131 BitField('b', 0, 4), 132 ] 133 134try: 135 frm = MixedBitFieldTypesLEBE().build() 136 assert False 137except LEBitFieldSequenceException: 138 pass 139 140 141class MixedBitFieldTypesBELE(Packet): 142 143 fields_desc = [ 144 BitField('b', 0, 4), 145 LEBitField('a', 0, 12), 146 ] 147 148try: 149 frm = MixedBitFieldTypesBELE().build() 150 assert False 151except LEBitFieldSequenceException: 152 pass 153 154################################################ 155+ EtherCat header layer handling 156= EtherCat and padding 157 158frm = Ether() / EtherCat() 159# even with padding the length must be zero 160# the Ether(do_build()) forces the calculation of all (post_build generated) fields 161frm = Ether(frm.do_build()) 162assert frm[EtherCat].length == 0 163assert len(frm) == 60 164frm = Ether()/Dot1Q()/Dot1Q()/EtherCat() 165frm = Ether()/EtherCat() 166assert len(frm) == 60 167frm = Ether(frm.do_build()) 168assert frm[EtherCat].length == 0 169 170= EtherCat and RawPayload 171 172frm=Ether()/EtherCat()/Raw(b'0123456789') 173assert len(frm) == 60 174frm = Ether(frm.do_build()) 175assert frm[EtherCat].length == 10 176frm = Ether()/EtherCat()/Raw(b'012345678901234567890123456789012345678901234567890123456789') 177frm = Ether(frm.do_build()) 178assert len(frm) == 76 179assert frm[EtherCat].length == 60 180 181= EtherCat - test invalid length detection 182 183nums_11_bits = [random.randint(0, 65535) & 0b11111111111 for dummy in range(0, 23)] 184nums_4_bits = [random.randint(0, 16) & 0b1111 for dummy in range(0, 23)] 185 186old_max_list_count = conf.max_list_count 187conf.max_list_count = 3000 188 189frm = Ether()/EtherCat()/EtherCatAPRD(adp=0x1234, ado=0x5678, irq=0xbad0, wkc=0xbeef, data=[1]*2035, c=1) 190frm = Ether(frm.do_build()) 191assert frm[EtherCat].length == 2047 192assert len(frm[EtherCatAPRD].data) == 2035 193assert frm[EtherCatAPRD].c == 1 194 195data_oversized = False 196try: 197 frm = Ether()/EtherCat()/EtherCatAPRD(adp=0x1234, ado=0x5678, irq=0xbad0, wkc=0xbeef, data=[2]*2048, c=1) 198 frm = Ether(frm.do_build()) 199except ValueError as err: 200 data_oversized = True 201 assert 'data size' in str(err) 202 203assert data_oversized == True 204dlpdu_oversized = False 205try: 206 frm = Ether()/EtherCat()/EtherCatAPRD(adp=0x1234, ado=0x5678, irq=0xbad0, wkc=0xbeef, data=[2]*2036, c=1) 207 frm = Ether(frm.do_build()) 208except ValueError as err: 209 dlpdu_oversized = True 210 assert 'EtherCat message' in str(err) 211 212assert dlpdu_oversized == True 213 214frm = Ether()/EtherCat(_reserved=1)/EtherCatAPRD(adp=0x1234, ado=0x5678, irq=0xbad0, wkc=0xbeef, data=[3], c=0) 215frm = Ether(frm.do_build()) 216assert frm[EtherCatAPRD].c == 0 217 218 219assert frm[EtherCat]._reserved == 0 220 221conf.max_list_count = old_max_list_count 222 223= EtherCat and Type12 DLPDU layers 224 225for type_id in EtherCat.ETHERCAT_TYPE12_DLPDU_TYPES: 226 data = [random.randint(0, 255) for dummy in range(random.randint(1, 10))] 227 frm = Ether() / EtherCat() / EtherCat.ETHERCAT_TYPE12_DLPDU_TYPES[type_id](data= data) 228 frm = Ether(frm.do_build()) 229 # expect to have one layer of current Type12 DLPDU type 230 dlpdu_lyr = frm[EtherCat.ETHERCAT_TYPE12_DLPDU_TYPES[type_id]] 231 assert dlpdu_lyr.data == data 232 233= EtherCat and Type12 DLPDU layer using structure used for physical and broadcast addressing 234 235# the code is the same for all layer sharing this structure - no need to test em all 236test_data = [121,99,110,104,114,109,58,41] 237frm = Ether()/EtherCat()/EtherCatAPRD(adp=0x1234, ado=0x5678, irq=0xbad0, wkc=0xbeef, data=test_data) 238frm = Ether(frm.do_build()) 239aprd_lyr = frm[EtherCatAPRD] 240assert aprd_lyr.adp == 0x1234 241assert aprd_lyr.ado == 0x5678 242assert aprd_lyr.irq == 0xbad0 243assert aprd_lyr.wkc == 0xbeef 244assert aprd_lyr.data == test_data 245 246= EtherCat and Type12 DLPDU layer using structure used for logical addressing 247 248test_data = [116,104,101,116,97,111,105,115,103,114,101,97,116] 249frm = Ether() / EtherCat() / EtherCatLRD(adr=0x11223344, irq=0xbad0, wkc=0xbeef, data=test_data) 250frm = Ether(frm.do_build()) 251aprd_lyr = frm[EtherCatLRD] 252assert (aprd_lyr.adr == 0x11223344) 253assert (aprd_lyr.irq == 0xbad0) 254assert (aprd_lyr.wkc == 0xbeef) 255assert (aprd_lyr.data == test_data) 256 257= EtherCat and randomly stacked Type12 DLPDU layers 258 259for outer_dummy in range(10): 260 frm = Ether()/EtherCat() 261 layer_ids = [] 262 for inner_dummy in range(random.randint(1, 20)): 263 layer_id = random.choice(list(EtherCat.ETHERCAT_TYPE12_DLPDU_TYPES)) 264 layer_ids.append(layer_id) 265 frm = frm / EtherCat.ETHERCAT_TYPE12_DLPDU_TYPES[layer_id]() 266 # build frame and convert back 267 frm = Ether(frm.do_build()) 268 idx = 0 269 for layer_id in layer_ids: 270 assert type(EtherCat.ETHERCAT_TYPE12_DLPDU_TYPES[layer_id]()) == type(frm[2 + idx]) 271 idx += 1 272