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