// File: /workspace/github_c_makefile_star2_O0/open-mesh-mirror[P]batmand/batman.c
// Function: isBidirectionalNeigh
static int isBidirectionalNeigh(struct orig_node *orig_node, struct orig_node *orig_neigh_node, struct bat_packet *in, uint32_t recv_time, struct batman_if *if_incoming)
{

	struct list_head *list_pos;
	struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
	uint8_t total_count;
	char orig_str[ADDR_STR_LEN], neigh_str[ADDR_STR_LEN];


	if ( orig_node == orig_neigh_node ) {

		list_for_each( list_pos, &orig_node->neigh_list ) {

			tmp_neigh_node = list_entry( list_pos, struct neigh_node, list );

			if ( ( tmp_neigh_node->addr == orig_neigh_node->orig ) && ( tmp_neigh_node->if_incoming == if_incoming ) )
				neigh_node = tmp_neigh_node;

		}

		if ( neigh_node == NULL )
			neigh_node = create_neighbor(orig_node, orig_neigh_node, orig_neigh_node->orig, if_incoming);

		neigh_node->last_valid = recv_time;

	} else {

		/* find packet count of corresponding one hop neighbor */
		list_for_each( list_pos, &orig_neigh_node->neigh_list ) {

			tmp_neigh_node = list_entry( list_pos, struct neigh_node, list );

			if ( ( tmp_neigh_node->addr == orig_neigh_node->orig ) && ( tmp_neigh_node->if_incoming == if_incoming ) )
				neigh_node = tmp_neigh_node;

		}

		if ( neigh_node == NULL )
			neigh_node = create_neighbor(orig_neigh_node, orig_neigh_node, orig_neigh_node->orig, if_incoming);

	}

	orig_node->last_valid = recv_time;

	/* pay attention to not get a value bigger than 100 % */
	total_count = ( orig_neigh_node->bcast_own_sum[if_incoming->if_num] > neigh_node->real_packet_count ? neigh_node->real_packet_count : orig_neigh_node->bcast_own_sum[if_incoming->if_num] );

	/* if we have too few packets (too less data) we set tq_own to zero */
	/* if we receive too few packets it is not considered bidirectional */
	if ( ( total_count < minimum_send ) || ( neigh_node->real_packet_count < minimum_recv ) ) {

		orig_neigh_node->tq_own = 0;

	} else {

		/* neigh_node->real_packet_count is never zero as we only purge old information when getting new information */
		orig_neigh_node->tq_own = (TQ_MAX_VALUE * total_count) / neigh_node->real_packet_count;

	}

	/* 1 - ((1-x)** 3), normalized to TQ_MAX_VALUE */
	/* this does affect the nearly-symmetric links only a little,
	 * but punishes asymetric links more. */
	/* this will give a value between 0 and TQ_MAX_VALUE */
	orig_neigh_node->tq_asym_penalty = TQ_MAX_VALUE - (TQ_MAX_VALUE *
			(local_win_size - neigh_node->real_packet_count) *
			(local_win_size - neigh_node->real_packet_count) *
			(local_win_size - neigh_node->real_packet_count)) /
			(local_win_size * local_win_size * local_win_size);

	in->tq = ((in->tq * orig_neigh_node->tq_own * orig_neigh_node->tq_asym_penalty) / (TQ_MAX_VALUE *  TQ_MAX_VALUE));

	addr_to_string( orig_node->orig, orig_str, ADDR_STR_LEN );
	addr_to_string( orig_neigh_node->orig, neigh_str, ADDR_STR_LEN );

	/*debug_output( 3, "bidirectional: orig = %-15s neigh = %-15s => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, total tq: %3i \n",
	orig_str, neigh_str, total_count, neigh_node->real_packet_count, orig_neigh_node->tq_own, orig_neigh_node->tq_asym_penalty, in->tq );*/
	debug_output(4, "bidirectional: orig = %-15s neigh = %-15s => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, total tq: %3i \n",
		      orig_str, neigh_str, total_count, neigh_node->real_packet_count, orig_neigh_node->tq_own, orig_neigh_node->tq_asym_penalty, in->tq);

	/* if link has the minimum required transmission quality consider it bidirectional */
	if (in->tq >= TQ_TOTAL_BIDRECT_LIMIT)
		return 1;

	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movl %ecx, -0x24(%rbp)
movq %r8, -0x30(%rbp)
movq $0x0, -0x40(%rbp)
movq $0x0, -0x48(%rbp)
movq -0x10(%rbp), %rax
cmpq -0x18(%rbp), %rax
jne 0x4533
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
movq -0x10(%rbp), %rcx
addq $0x48, %rcx
cmpq %rcx, %rax
je 0x4505
movq -0x38(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movl 0x8(%rax), %eax
movq -0x18(%rbp), %rcx
cmpl (%rcx), %eax
jne 0x44f6
movq -0x48(%rbp), %rax
movq 0x30(%rax), %rax
cmpq -0x30(%rbp), %rax
jne 0x44f6
movq -0x48(%rbp), %rax
movq %rax, -0x40(%rbp)
jmp 0x44f8
movq -0x38(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x38(%rbp)
jmp 0x44b8
cmpq $0x0, -0x40(%rbp)
jne 0x4527
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x18(%rbp), %rax
movl (%rax), %edx
movq -0x30(%rbp), %rcx
callq 0x4a60
movq %rax, -0x40(%rbp)
movl -0x24(%rbp), %ecx
movq -0x40(%rbp), %rax
movl %ecx, 0x1c(%rax)
jmp 0x45b0
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
movq -0x18(%rbp), %rcx
addq $0x48, %rcx
cmpq %rcx, %rax
je 0x458c
movq -0x38(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movl 0x8(%rax), %eax
movq -0x18(%rbp), %rcx
cmpl (%rcx), %eax
jne 0x457d
movq -0x48(%rbp), %rax
movq 0x30(%rax), %rax
cmpq -0x30(%rbp), %rax
jne 0x457d
movq -0x48(%rbp), %rax
movq %rax, -0x40(%rbp)
jmp 0x457f
movq -0x38(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x38(%rbp)
jmp 0x453f
cmpq $0x0, -0x40(%rbp)
jne 0x45ae
movq -0x18(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x18(%rbp), %rax
movl (%rax), %edx
movq -0x30(%rbp), %rcx
callq 0x4a60
movq %rax, -0x40(%rbp)
jmp 0x45b0
movl -0x24(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x30(%rax)
movq -0x18(%rbp), %rax
movq 0x20(%rax), %rax
movq -0x30(%rbp), %rcx
movzbl 0x1c(%rcx), %ecx
movzbl (%rax,%rcx), %eax
movq -0x40(%rbp), %rcx
movzbl 0xc(%rcx), %ecx
cmpl %ecx, %eax
jle 0x45e7
movq -0x40(%rbp), %rax
movzbl 0xc(%rax), %eax
movl %eax, -0x74(%rbp)
jmp 0x45fe
movq -0x18(%rbp), %rax
movq 0x20(%rax), %rax
movq -0x30(%rbp), %rcx
movzbl 0x1c(%rcx), %ecx
movzbl (%rax,%rcx), %eax
movl %eax, -0x74(%rbp)
movl -0x74(%rbp), %eax
movb %al, -0x49(%rbp)
movzbl -0x49(%rbp), %eax
movzbl 0x16c9d(%rip), %ecx     # 0x1b2ac
cmpl %ecx, %eax
jl 0x4626
movq -0x40(%rbp), %rax
movzbl 0xc(%rax), %eax
movzbl 0x16c8b(%rip), %ecx     # 0x1b2ad
cmpl %ecx, %eax
jge 0x4630
movq -0x18(%rbp), %rax
movb $0x0, 0x28(%rax)
jmp 0x464e
movzbl -0x49(%rbp), %eax
imull $0xff, %eax, %eax
movq -0x40(%rbp), %rcx
movzbl 0xc(%rcx), %ecx
cltd
idivl %ecx
movb %al, %cl
movq -0x18(%rbp), %rax
movb %cl, 0x28(%rax)
movzbl 0x16c5a(%rip), %eax     # 0x1b2af
movq -0x40(%rbp), %rcx
movzbl 0xc(%rcx), %ecx
subl %ecx, %eax
imull $0xff, %eax, %eax
movzbl 0x16c43(%rip), %ecx     # 0x1b2af
movq -0x40(%rbp), %rdx
movzbl 0xc(%rdx), %edx
subl %edx, %ecx
imull %ecx, %eax
movzbl 0x16c2f(%rip), %ecx     # 0x1b2af
movq -0x40(%rbp), %rdx
movzbl 0xc(%rdx), %edx
subl %edx, %ecx
imull %ecx, %eax
movzbl 0x16c1b(%rip), %ecx     # 0x1b2af
movzbl 0x16c14(%rip), %edx     # 0x1b2af
imull %edx, %ecx
movzbl 0x16c0a(%rip), %edx     # 0x1b2af
imull %edx, %ecx
cltd
idivl %ecx
movl $0xff, %ecx
subl %eax, %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x2c(%rax)
movq -0x20(%rbp), %rax
movzbl 0x10(%rax), %eax
movq -0x18(%rbp), %rcx
movzbl 0x28(%rcx), %ecx
imull %ecx, %eax
movq -0x18(%rbp), %rcx
imull 0x2c(%rcx), %eax
movl $0xfe01, %ecx           # imm = 0xFE01
cltd
idivl %ecx
movb %al, %cl
movq -0x20(%rbp), %rax
movb %cl, 0x10(%rax)
movq -0x10(%rbp), %rax
movl (%rax), %edi
leaq -0x60(%rbp), %rsi
movl $0x10, %edx
callq 0xfa90
movq -0x18(%rbp), %rax
movl (%rax), %edi
leaq -0x70(%rbp), %rsi
movl $0x10, %edx
callq 0xfa90
leaq -0x60(%rbp), %rdx
leaq -0x70(%rbp), %rcx
movzbl -0x49(%rbp), %r8d
movq -0x40(%rbp), %rax
movzbl 0xc(%rax), %r9d
movq -0x18(%rbp), %rax
movzbl 0x28(%rax), %r11d
movq -0x18(%rbp), %rax
movl 0x2c(%rax), %r10d
movq -0x20(%rbp), %rax
movzbl 0x10(%rax), %eax
movl $0x4, %edi
leaq 0x10831(%rip), %rsi     # 0x14f79
movl %r11d, (%rsp)
movl %r10d, 0x8(%rsp)
movl %eax, 0x10(%rsp)
movb $0x0, %al
callq 0x123f0
movq -0x20(%rbp), %rax
movzbl 0x10(%rax), %eax
cmpl $0x1, %eax
jl 0x4772
movl $0x1, -0x4(%rbp)
jmp 0x4779
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x90, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)