1 /*
2 * This software is Copyright (c) 2016-2018 Denis Burykin
3 * [denis_burykin yahoo com], [denis-burykin2014 yandex ru]
4 * and it is hereby released to the general public under the following terms:
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted.
7 *
8 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <stdarg.h>
13 #include <libusb-1.0/libusb.h>
14
15 #include "../memory.h"
16
17 #include "ztex.h"
18 #include "inouttraffic.h"
19 #include "device.h"
20 #include "task.h"
21 #include "jtr_device.h"
22 #include "jtr_mask.h"
23
24 #include "pkt_comm/pkt_comm.h"
25 #include "pkt_comm/word_list.h"
26 #include "pkt_comm/word_gen.h"
27 #include "pkt_comm/cmp_config.h"
28 #include "pkt_comm/inpkt.h"
29
30
jtr_device_error(const char * s,...)31 void jtr_device_error(const char *s, ...) {
32 va_list ap;
33 va_start(ap, s);
34 vfprintf(stderr, s, ap);
35 va_end(ap);
36 }
37
38
jtr_device_new(struct jtr_device_list * jtr_device_list,struct device * device,int fpga_num,struct pkt_comm * comm)39 struct jtr_device *jtr_device_new(
40 struct jtr_device_list *jtr_device_list,
41 struct device *device, int fpga_num,
42 struct pkt_comm *comm)
43 {
44 struct jtr_device *self = mem_alloc(sizeof(struct jtr_device));
45
46 self->next = jtr_device_list->device;
47 jtr_device_list->device = self;
48 self->device = device;
49 self->fpga_num = fpga_num;
50 self->comm = comm;
51
52 self->cmp_config_id = -1;
53 self->task_id_next = 1;
54
55 return self;
56 }
57
58
jtr_device_list_new(struct device_list * device_list)59 struct jtr_device_list *jtr_device_list_new(struct device_list *device_list)
60 {
61 struct jtr_device_list *self = mem_alloc(sizeof(struct jtr_device_list));
62 self->device = NULL;
63
64 // Create 1 JtR device for each fpga
65 struct device *device;
66 for (device = device_list->device; device; device = device->next) {
67 if (!device_valid(device))
68 continue;
69
70 int i;
71 for (i = 0; i < device->num_of_fpgas; i++) {
72 struct fpga *fpga = &device->fpga[i];
73 jtr_device_new(self, device, i, fpga->comm);
74 //printf("jtr_device_new(%d,%d,%d,%d)\n",self, device, i, fpga->comm);
75 }
76 }
77
78 return self;
79 }
80
81
jtr_device_id(struct jtr_device * dev)82 char *jtr_device_id(struct jtr_device *dev)
83 {
84 static char device_id[32];
85 if (!dev)
86 return "";
87 sprintf(device_id, "%s #%d", dev->device->ztex_device->snString,
88 dev->fpga_num + 1);
89 return device_id;
90 }
91
92 //////////////////////////////////////////////////////////////////////////////
93
94 int libusb_initialized;
95
96 // Global inouttraffic device list
97 struct device_list *device_list;
98
99 // Global jtr_device_list
100 struct jtr_device_list *jtr_device_list;
101
102 int PKT_DEBUG = 1;
103
104
105 //////////////////////////////////////////////////////////////////////////////
106
jtr_device_list_init()107 struct jtr_device_list *jtr_device_list_init()
108 {
109 if (!libusb_initialized) {
110 int result = libusb_init(NULL);
111 if (result < 0) {
112 fprintf(stderr, "libusb_init() returns %d: %s\n",
113 result, libusb_error_name(result));
114 return NULL;
115 }
116 libusb_initialized = 1;
117 }
118 //ZTEX_DEBUG=1;
119 //DEBUG = 1; // print I/O function calls
120 //DEBUG = 2; // print all I/O data in hex
121 PKT_DEBUG = 1; // print erroneous packets recieved from devices
122 //PKT_DEBUG = 2; // print all application packets recieved from devices
123
124 // devices aren't initialized
125 if (!device_list) {
126 device_list = device_init_scan(jtr_bitstream);
127
128 int device_count = device_list_count(device_list);
129 if (!device_count) {
130 fprintf(stderr, "no valid ZTEX devices found\n");
131 return NULL;
132 }
133
134 // devices already initialized
135 // - upload bitstream of proper type if necessary
136 // - soft reset, initialize fpgas
137 } else {
138 device_list_init(device_list, jtr_bitstream);
139
140 int device_count = device_list_count(device_list);
141 if (!device_count) {
142 fprintf(stderr, "no valid ZTEX devices found\n");
143 return NULL;
144 }
145 }
146
147 // Create jtr_devices from inouttraffic devices
148 // TODO: remove old jtr_device's if any
149 jtr_device_list = jtr_device_list_new(device_list);
150 return jtr_device_list;
151 }
152
153
jtr_device_list_print()154 void jtr_device_list_print()
155 {
156 device_list_print(device_list);
157 }
158
159
jtr_device_list_print_count()160 void jtr_device_list_print_count()
161 {
162 int device_count = device_list_count(device_list);
163 fprintf(stderr, "%d device(s) ZTEX 1.15y ready\n", device_count);
164 }
165
166
jtr_device_list_count()167 int jtr_device_list_count()
168 {
169 if (!jtr_device_list)
170 return 0;
171
172 int count = 0;
173 struct jtr_device *dev;
174 for (dev = jtr_device_list->device; dev; dev = dev->next)
175 count++;
176
177 return count;
178 }
179
180
jtr_device_list_merge(struct jtr_device_list * jtr_device_list,struct jtr_device_list * jtr_device_list_1)181 void jtr_device_list_merge(
182 struct jtr_device_list *jtr_device_list,
183 struct jtr_device_list *jtr_device_list_1)
184 {
185 if (!jtr_device_list || !jtr_device_list_1) {
186 fprintf(stderr, "jtr_device_list_merge: invalid args\n");
187 exit(-1);
188 }
189
190 struct jtr_device *dev, *dev_next;
191 for (dev = jtr_device_list_1->device; dev; dev = dev_next) {
192 dev_next = dev->next;
193 dev->next = jtr_device_list->device;
194 jtr_device_list->device = dev;
195 }
196 MEM_FREE(jtr_device_list_1);
197 }
198
199
jtr_device_delete(struct jtr_device_list * jtr_device_list,struct jtr_device * jtr_device)200 void jtr_device_delete(
201 struct jtr_device_list *jtr_device_list,
202 struct jtr_device *jtr_device)
203 {
204 if (!jtr_device_list->device)
205 return;
206
207 if (jtr_device_list->device == jtr_device) {
208 jtr_device_list->device = jtr_device->next;
209 MEM_FREE(jtr_device);
210 return;
211 }
212
213 struct jtr_device *dev;
214 for (dev = jtr_device_list->device; dev; dev = dev->next) {
215 if (dev->next == jtr_device) {
216 struct jtr_device *next_device = jtr_device->next;
217 MEM_FREE(jtr_device);
218 dev->next = next_device;
219 return;
220 }
221 }
222 }
223
224
jtr_device_by_device(struct jtr_device_list * jtr_device_list,struct device * device)225 struct jtr_device *jtr_device_by_device(
226 struct jtr_device_list *jtr_device_list,
227 struct device *device)
228 {
229 struct jtr_device *dev;
230 for (dev = jtr_device_list->device; dev; dev = dev->next)
231 if (dev->device == device)
232 return dev;
233 return NULL;
234 }
235
236
jtr_device_list_check()237 int jtr_device_list_check()
238 {
239 // timely scan for new devices
240 struct device_list *device_list_1
241 = device_timely_scan(device_list, jtr_bitstream);
242 int found_devices_num = device_list_count(device_list_1);
243 if (found_devices_num) {
244 fprintf(stderr, "Found %d device(s) ZTEX 1.15y\n", found_devices_num);
245 ztex_dev_list_print(device_list_1->ztex_dev_list);
246
247 // found devices - merge into global device list
248 struct jtr_device_list *jtr_device_list_1
249 = jtr_device_list_new(device_list_1);
250 jtr_device_list_merge(jtr_device_list, jtr_device_list_1);
251 device_list_merge(device_list, device_list_1);
252 }
253 else {
254 free(device_list_1->ztex_dev_list);
255 free(device_list_1);
256 }
257 return found_devices_num;
258 }
259
260
jtr_device_list_set_app_mode(unsigned char mode)261 int jtr_device_list_set_app_mode(unsigned char mode)
262 {
263 return device_list_set_app_mode(device_list, mode);
264 }
265
266
jtr_device_list_rw(struct task_list * task_list)267 int jtr_device_list_rw(struct task_list *task_list)
268 {
269 int data_transfer = 0;
270 int device_count = 0;
271 struct device *device;
272 for (device = device_list->device; device; device = device->next) {
273 if (!device_valid(device))
274 continue;
275
276 int result = device_pkt_rw(device);
277 if (result > 0)
278 data_transfer = 1;
279 if (result >= 0) {
280 device_count ++;
281 continue;
282 }
283
284 fprintf(stderr, "SN %s error %d doing r/w of FPGAs (%s)\n",
285 device->ztex_device->snString, result, libusb_error_name(result) );
286
287 // Physical device I/O error.
288 device_stop(device, task_list, NULL);
289
290 } // for (device_list)
291
292 return !device_count ? -1 : data_transfer;
293 }
294
295
device_stop(struct device * device,struct task_list * task_list,char * error_msg)296 int device_stop(
297 struct device *device,
298 struct task_list *task_list,
299 char *error_msg)
300 {
301 // jtr_devices for this physical device might have assigned tasks.
302 // - deassign tasks
303 // - remove jtr_devices for failed physical device
304 //
305 int num_deassigned = 0;
306 for (;;) {
307 struct jtr_device *jtr_dev;
308 jtr_dev = jtr_device_by_device(jtr_device_list, device);
309 if (!jtr_dev)
310 break;
311 num_deassigned += tasks_deassign(task_list, jtr_dev);
312 jtr_device_delete(jtr_device_list, jtr_dev);
313 }
314
315 if (error_msg)
316 fprintf(stderr, "SN %s: %s\n",
317 device->ztex_device->snString, error_msg);
318
319 // Device is excluded from operation, becomes subject for device_*_scan().
320 // TODO: maybe perform hardware reset?
321 //
322 device_invalidate(device);
323
324 //fprintf(stderr, "Deassigned: %d\n",num_deassigned);
325 return num_deassigned;
326 }
327
328
329 ///////////////////////////////////////////////////////////////////////
330 //
331 //
332 // Handling of input application-level data packets
333 //
334 //
335 ///////////////////////////////////////////////////////////////////////
336
337
338 // Find task that matches given input packet
339 // Return NULL if no match
inpkt_check_task(struct pkt * inpkt,struct jtr_device * dev,struct task_list * task_list)340 static struct task *inpkt_check_task(struct pkt *inpkt,
341 struct jtr_device *dev, struct task_list *task_list)
342 {
343 unsigned int pkt_id = pkt_get_id(inpkt);
344 struct task *task = task_find(task_list, dev, pkt_id);
345 if (!task) {
346 if (PKT_DEBUG >= 1)
347 fprintf(stderr, "%s %s id=%d: no task\n",
348 jtr_device_id(dev), inpkt_type_name(inpkt->type), pkt_id);
349 return NULL;
350 }
351
352 if (task->status == TASK_COMPLETE) {
353 if (PKT_DEBUG >= 1)
354 fprintf(stderr, "%s %s id=%d: task already completed\n",
355 jtr_device_id(dev), inpkt_type_name(inpkt->type), pkt_id);
356
357 } else if (task->status != TASK_ASSIGNED) {
358 if (PKT_DEBUG >= 1)
359 fprintf(stderr, "%s %s id=%d: task not assigned\n",
360 jtr_device_id(dev), inpkt_type_name(inpkt->type), pkt_id);
361 return NULL;
362 }
363 return task;
364 }
365
366
367 // Check if word_id,gen_id,hash_num from CMP_* packet are valid
368 // Return false if data isn't valid
inpkt_check_cmp(struct jtr_device * jtr_dev,struct pkt * inpkt,struct task * task,int word_id,unsigned int gen_id,int hash_num)369 static int inpkt_check_cmp(struct jtr_device *jtr_dev,
370 struct pkt *inpkt, struct task *task,
371 int word_id, unsigned int gen_id, int hash_num)
372 {
373 if (word_id >= task->num_keys) {
374 if (PKT_DEBUG >= 1)
375 fprintf(stderr, "%s %s id=%d: word_id=%d, num_keys=%d\n",
376 jtr_device_id(jtr_dev), inpkt_type_name(inpkt->type),
377 inpkt->id, word_id, task->num_keys);
378 return 0;
379 }
380 if (gen_id >= mask_num_cand()) {
381 if (PKT_DEBUG >= 1)
382 fprintf(stderr, "%s %s id=%d: gen_id=%u, mask_num_cand=%d\n",
383 jtr_device_id(jtr_dev), inpkt_type_name(inpkt->type),
384 inpkt->id, gen_id, mask_num_cand());
385 return 0;
386 }
387 if (hash_num >= cmp_config.num_hashes) {
388 if (PKT_DEBUG >= 1)
389 fprintf(stderr, "%s %s id=%d: hash_num=%d, num_hashes=%d\n",
390 jtr_device_id(jtr_dev), inpkt_type_name(inpkt->type),
391 inpkt->id, hash_num, cmp_config.num_hashes);
392 return 0;
393 }
394 return 1;
395 }
396
397
jtr_device_list_process_inpkt(struct task_list * task_list)398 struct jtr_device *jtr_device_list_process_inpkt(
399 struct task_list *task_list)
400 {
401 struct jtr_device *dev;
402 for (dev = jtr_device_list->device; dev; dev = dev->next) {
403 int bad_input = 0;
404
405 // Fetch input packets from pkt_comm_queue
406 struct pkt *inpkt;
407 while ( (inpkt = pkt_queue_fetch(dev->comm->input_queue) ) ) {
408
409 struct task *task = inpkt_check_task(inpkt, dev, task_list);
410 if (!task) {
411 // Bad packet from the device.
412 pkt_delete(inpkt);
413 bad_input = 1;
414 break;
415 }
416
417 // Computed result received
418 if (inpkt->type == PKT_TYPE_RESULT1) {
419
420 struct pkt_result *pkt_result = pkt_result_new(inpkt);
421
422 if (PKT_DEBUG >= 2)
423 fprintf(stderr,"%s RESULT1 id=%d: w:%d g:%u\n",
424 jtr_device_id(dev), pkt_result->id,
425 pkt_result->word_id, pkt_result->gen_id);
426
427 if (!inpkt_check_cmp(dev, inpkt, task, pkt_result->word_id,
428 pkt_result->gen_id, -1)) {
429 pkt_result_delete(pkt_result);
430 bad_input = 1;
431 break;
432 }
433
434 struct task_result *task_result = task_result_new(
435 task, task->keys
436 + pkt_result->word_id * jtr_fmt_params->plaintext_length,
437 !task->range_info ? NULL :
438 task->range_info + pkt_result->word_id * MASK_FMT_INT_PLHDR,
439 pkt_result->gen_id, NULL
440 );
441
442 task_result->binary = mem_alloc(pkt_result->result_len);
443 memcpy(task_result->binary, pkt_result->result,
444 pkt_result->result_len);
445
446 pkt_result_delete(pkt_result);
447
448 int expected_total = task->num_keys * mask_num_cand();
449 task->num_processed ++;
450 if (task->num_processed > expected_total) {
451 fprintf(stderr, "%s RESULT1: keys=%d, "
452 "mask=%d, processed=%u (must be %u)\n",
453 jtr_device_id(dev), task->num_keys, mask_num_cand(),
454 task->num_processed, expected_total);
455 bad_input = 1;
456 break;
457 }
458 else if (task->num_processed == expected_total) {
459 task->status = TASK_COMPLETE;
460 }
461 task_update_mtime(task);
462
463 // Comparator found equality & it sends computed result
464 } else if (inpkt->type == PKT_TYPE_CMP_RESULT) {
465
466 struct pkt_cmp_result *pkt_cmp_result
467 = pkt_cmp_result_new(inpkt);
468
469 if (PKT_DEBUG >= 2)
470 fprintf(stderr,"%s CMP_RESULT id=%d: w:%d g:%u h:%d\n",
471 jtr_device_id(dev),
472 pkt_cmp_result->id, pkt_cmp_result->word_id,
473 pkt_cmp_result->gen_id, pkt_cmp_result->hash_num);
474
475 if (!inpkt_check_cmp(dev, inpkt, task,
476 pkt_cmp_result->word_id, pkt_cmp_result->gen_id,
477 pkt_cmp_result->hash_num)) {
478 pkt_cmp_result_delete(pkt_cmp_result);
479 bad_input = 1;
480 break;
481 }
482
483 struct task_result *task_result = task_result_new(
484 task, task->keys
485 + pkt_cmp_result->word_id * jtr_fmt_params->plaintext_length,
486 !task->range_info ? NULL :
487 task->range_info + pkt_cmp_result->word_id * MASK_FMT_INT_PLHDR,
488 pkt_cmp_result->gen_id,
489 cmp_config.pw[pkt_cmp_result->hash_num]
490 );
491
492 task_result->binary = mem_alloc(pkt_cmp_result->result_len);
493 memcpy(task_result->binary, pkt_cmp_result->result,
494 pkt_cmp_result->result_len);
495
496 pkt_cmp_result_delete(pkt_cmp_result);
497
498
499 // Comparator found equality
500 } else if (inpkt->type == PKT_TYPE_CMP_EQUAL) {
501
502 struct pkt_equal *pkt_equal = pkt_equal_new(inpkt);
503
504 if (PKT_DEBUG >= 2)
505 fprintf(stderr,"%s CMP_EQUAL id=%d: w:%d g:%u h:%d\n",
506 jtr_device_id(dev),
507 pkt_equal->id, pkt_equal->word_id,
508 pkt_equal->gen_id, pkt_equal->hash_num);
509
510 if (!inpkt_check_cmp(dev, inpkt, task,
511 pkt_equal->word_id, pkt_equal->gen_id,
512 pkt_equal->hash_num)) {
513 free(pkt_equal);
514 bad_input = 1;
515 break;
516 }
517
518 task_result_new(task, task->keys
519 + pkt_equal->word_id * jtr_fmt_params->plaintext_length,
520 !task->range_info ? NULL :
521 task->range_info + pkt_equal->word_id * MASK_FMT_INT_PLHDR,
522 pkt_equal->gen_id,
523 cmp_config.pw[pkt_equal->hash_num]);
524
525 free(pkt_equal);
526
527 // Processing of an input packet done
528 // (task processing is complete)
529 } else if (inpkt->type == PKT_TYPE_PROCESSING_DONE) {
530
531 struct pkt_done *pkt_done = pkt_done_new(inpkt);
532
533 // In a design with several onboard generators/arbiters,
534 // each one sends PKT_DONE
535 int expected_total = task->num_keys * mask_num_cand();
536
537 if (PKT_DEBUG >= 2)
538 fprintf(stderr, "%s PROCESSING_DONE id=%d: %u(+%d) of %d\n",
539 jtr_device_id(dev), pkt_done->id,
540 pkt_done->num_processed, task->num_processed,
541 expected_total);
542
543 task->num_processed += pkt_done->num_processed;
544 free(pkt_done);
545
546 if (task->num_processed > expected_total) {
547 fprintf(stderr, "%s PROCESSING_DONE: keys=%d, "
548 "mask=%d, processed=%u (must be %u)\n",
549 jtr_device_id(dev), task->num_keys, mask_num_cand(),
550 task->num_processed, expected_total);
551 bad_input = 1;
552 break;
553 }
554 else if (task->num_processed == expected_total) {
555 task->status = TASK_COMPLETE;
556 task_update_mtime(task);
557 }
558
559 // Unknown packet type
560 } else {
561 if (PKT_DEBUG >= 1)
562 fprintf(stderr, "%s %s type=0x%02x id=%d: len=%d\n",
563 jtr_device_id(dev), inpkt_type_name(inpkt->type),
564 inpkt->type, inpkt->id, inpkt->data_len);
565 pkt_delete(inpkt);
566 bad_input = 1;
567 break;
568 }
569 } // while (input packets)
570
571 if (bad_input)
572 // Incorrect packets received from jtr_device.
573 return dev;
574
575 } // for (jtr_device_list)
576
577 return NULL;
578 }
579
580
581 //libusb_exit(NULL);
582
583
584