// File: /workspace/github_cpp_makefile_star2_O2/adamiaonr[P]rid-analytics/src/rid-router.cpp
// Function: RID_Router::forward(unsigned char, std::map<int, std::vector<unsigned char, std::allocator<unsigned char>>, std::less<int>, std::allocator<std::pair<int const, std::vector<unsigned char, std::allocator<unsigned char>>>>>*, long double, std::vector<long double, std::allocator<long double>>*, std::vector<std::vector<long double, std::allocator<long double>>, std::allocator<std::vector<long double, std::allocator<long double>>>>&, std::vector<std::vector<long double, std::allocator<long double>>, std::allocator<std::vector<long double, std::allocator<long double>>>>&)
int RID_Router::forward(
    uint8_t ingress_iface,
    std::map<int, std::vector<uint8_t> > * tree_bitmasks,
    __float080 in_prob,
    std::vector<__float080> * in_fptree_prob,
    std::vector<std::vector<__float080> > & iface_probs,
    std::vector<std::vector<__float080> > & out_fptree_probs) {

    std::cout << "RID_Router::forward() : [INFO] *** forwarding *** " << 
        "\n\tfrom : " << this->get_next_hop(ingress_iface).router->get_id() << 
        "\n\tinto : " << this->get_id() << "[" << (int) ingress_iface << "]" << std::endl;

    // check which ifaces are eligible to be on prefix trees (of any size)
    for (uint8_t i = 0; i < this->iface_num; i++) {
        std::fill(this->iface_on_fptree[i].begin(), this->iface_on_fptree[i].end(), false);
        is_iface_on_fptree(i, tree_bitmasks);
    }

    // mark blocked ifaces for basic loop prevention
    // don't forward over ifaces w/ no entries associated w/ them
    for (uint8_t i = 0; i < this->iface_num; i++) {

        this->blocked_ifaces[i] = false;
        
        if (this->fwd_table[i].num_entries == 0)
            this->blocked_ifaces[i] = true;
    }
    // don't foward over ingress iface
    this->blocked_ifaces[ingress_iface] = true;

    std::cout << "RID_Router::forward() : [INFO] blocked ifaces {";
    for (uint8_t k = 0; k < this->blocked_ifaces.size(); k++) {
        std::cout << "[" << (int) k << "]:" << (int) this->blocked_ifaces[k] << ", ";        
    }
    std::cout << "}" << std::endl;

    // save the ingress probabilities for each diff. prefix tree size (i.e. 
    // the probability that a packet is already bound to a tree of size p)

    std::cout << "RID_Router::forward() : P(in) = " << in_prob << std::endl;
    std::cout << "RID_Router::forward() : P(in_fptree = p) :" << std::endl; 
    for (uint8_t fptree_size = 0; fptree_size <= this->req_size; fptree_size++)
        std::cout << "\tP(p = " << (int) fptree_size << "]) = " << (*in_fptree_prob)[fptree_size] << std::endl;

    // get the iface probs P(I = i), i.e. the probability of having iface i 
    // chosen as an egress iface 

    // as input, we pass: 
    //  - iface data from the fwd_table[] which has an influence in fp rate 
    //    and/or iface prob calculation
    //  - in_prob : probability of having a request forwarded 
    //              into this router by the previous router.
    //  - in_fptree_prob : probabilities of having the request coming into this 
    //                     router while 'bound' to a fp tree of size p
    std::vector<std::vector<Prob::fp_data *> > iface_fp_data(2);
    for (uint8_t i = 0; i < this->iface_num; i++) {

        iface_fp_data[0].push_back(get_fp_data(this, i));
        iface_fp_data[1].push_back(get_fp_data(this, i, true));
    }

    if (this->prob_mod->calc_probs(
        &(iface_fp_data),
        tree_bitmasks,
        in_prob,
        in_fptree_prob, 
        iface_probs, 
        out_fptree_probs) < 0) return -1;

    std::cout << "RID_Router::forward() : [INFO] iface probs :" << std::endl;
    for (uint8_t i = 0; i < this->iface_num; i++)
        std::cout << "\tP(I = " << (int) i << ") = " << iface_probs[i][0] << " : " << iface_probs[i][1] << " : " << iface_probs[i][2] << std::endl;

    for (uint8_t i = 0; i < iface_fp_data[0].size(); i++) {
        delete iface_fp_data[0][i];
    }

    for (uint8_t i = 0; i < iface_fp_data[0].size(); i++) {
        delete iface_fp_data[1][i];
    }

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movq %r9, %r13
movq %r8, 0x18(%rsp)
movq %rcx, 0x28(%rsp)
movq %rdx, 0x20(%rsp)
movl %esi, %r15d
movq %rdi, %r14
fldt 0xc0(%rsp)
fstpt 0x54(%rsp)
movq 0x22ba1(%rip), %rdi     # 0x3afb0
leaq 0x1249f(%rip), %rsi     # 0x2a8b5
callq 0x43a0
leaq 0x124c6(%rip), %rsi     # 0x2a8e8
movq %rax, %rdi
callq 0x43a0
movq %rax, %rbx
movl %r15d, %ebp
movq 0x30(%r14), %rax
imulq $0xa0, %rbp, %rcx
movq 0x90(%rax,%rcx), %rsi
leaq 0x30(%rsp), %r12
movq %r12, %rdi
callq 0x4510
movq %rbx, %rdi
movq %r12, %rsi
callq 0x4360
leaq 0x12490(%rip), %rsi     # 0x2a8f2
movq %rax, %rdi
callq 0x43a0
movq %rax, %rbx
leaq 0x68(%rsp), %rdi
movq %r14, %rsi
callq 0x4510
leaq 0x68(%rsp), %rsi
movq %rbx, %rdi
callq 0x4360
leaq 0x130b5(%rip), %rsi     # 0x2b543
movq %rax, %rdi
callq 0x43a0
movzbl %r15b, %esi
movq %rax, %rdi
callq 0x46d0
leaq 0xf3b5(%rip), %rsi      # 0x2785e
movq %rax, %rdi
callq 0x43a0
movq %rax, %rdi
callq 0x41e0
leaq 0x68(%rsp), %rdi
callq 0x41c0
leaq 0x30(%rsp), %rbx
movq %rbx, %rdi
callq 0x41c0
pushq $0x18
popq %r12
xorl %r15d, %r15d
movzbl 0x24(%r14), %eax
cmpq %rax, %r15
jae 0x1851e
movq 0x88(%r14), %rax
movq -0x18(%rax,%r12), %rdi
movq -0x8(%rax,%r12), %rdx
movl (%rax,%r12), %ecx
movb $0x0, 0x30(%rsp)
xorl %esi, %esi
movq %rbx, %r8
callq 0x1a6f2
movq %r14, %rdi
movl %r15d, %esi
movq 0x20(%rsp), %rdx
callq 0x18948
incq %r15
addq $0x28, %r12
jmp 0x184d7
leaq 0x60(%r14), %r15
pushq $0x58
popq %r12
xorl %ebx, %ebx
movzbl %al, %eax
cmpq %rax, %rbx
jae 0x1856a
movq %r15, %rdi
movq %rbx, %rsi
callq 0x1905e
notq %rdx
andq %rdx, (%rax)
movq 0x30(%r14), %rax
cmpq $0x0, (%rax,%r12)
jne 0x1855a
movq %r15, %rdi
movq %rbx, %rsi
callq 0x1905e
orq %rdx, (%rax)
incq %rbx
movb 0x24(%r14), %al
addq $0xa0, %r12
jmp 0x18528
movq %r13, 0x60(%rsp)
movq %r15, %rdi
movq %rbp, %rsi
callq 0x1905e
orq %rdx, (%rax)
movq 0x22a2c(%rip), %rdi     # 0x3afb0
leaq 0x12371(%rip), %rsi     # 0x2a8fc
callq 0x43a0
xorl %eax, %eax
leaq 0x12393(%rip), %r13     # 0x2a92c
leaq 0x12108(%rip), %rbx     # 0x2a6a8
movzbl %al, %ebp
movq 0x70(%r14), %rax
movl 0x78(%r14), %ecx
subq 0x60(%r14), %rax
leaq (%rcx,%rax,8), %rax
cmpq %rbp, %rax
jbe 0x1860f
movq 0x229f1(%rip), %rdi     # 0x3afb0
leaq 0x12f7d(%rip), %rsi     # 0x2b543
callq 0x43a0
movq %rax, %rdi
movl %ebp, %esi
callq 0x46d0
movq %rax, %rdi
movq %r13, %rsi
callq 0x43a0
movq %rax, %r12
movq %r15, %rdi
movq %rbp, %rsi
callq 0x1905e
xorl %esi, %esi
testq %rdx, (%rax)
setne %sil
movq %r12, %rdi
callq 0x46d0
movq %rax, %rdi
movq %rbx, %rsi
callq 0x43a0
leal 0x1(%rbp), %eax
jmp 0x185a0
movq 0x2299a(%rip), %r15     # 0x3afb0
leaq 0x12312(%rip), %rsi     # 0x2a92f
movq %r15, %rdi
callq 0x43a0
movq %rax, %rdi
callq 0x41e0
leaq 0x122fd(%rip), %rsi     # 0x2a931
movq %r15, %rdi
callq 0x43a0
fldt 0x54(%rsp)
fstpt (%rsp)
movq %rax, %rdi
callq 0x4220
movq %rax, %rdi
callq 0x41e0
leaq 0x122f8(%rip), %rsi     # 0x2a952
movq %r15, %rdi
callq 0x43a0
movq %rax, %rdi
callq 0x41e0
xorl %ebp, %ebp
leaq 0x1230a(%rip), %rbx     # 0x2a97d
leaq 0x1230b(%rip), %r12     # 0x2a985
cmpb 0x21(%r14), %bpl
ja 0x186cd
movzbl %bpl, %r13d
movq %r15, %rdi
movq %rbx, %rsi
callq 0x43a0
movq %rax, %rdi
movl %r13d, %esi
callq 0x46d0
movq %rax, %rdi
movq %r12, %rsi
callq 0x43a0
movq 0x28(%rsp), %rcx
movq (%rcx), %rcx
shll $0x4, %r13d
fldt (%rcx,%r13)
fstpt (%rsp)
movq %rax, %rdi
callq 0x4220
movq %rax, %rdi
callq 0x41e0
incb %bpl
jmp 0x1867a
leaq 0x30(%rsp), %rdi
pushq $0x2
popq %rsi
leaq 0x68(%rsp), %rdx
callq 0x190e8
xorl %r13d, %r13d
leaq 0x68(%rsp), %rbx
pushq $0x1
popq %rbp
cmpb 0x24(%r14), %r13b
jae 0x18747
movq 0x30(%rsp), %r12
movzbl %r13b, %r15d
movq %r14, %rdi
movq %r14, %rsi
movl %r15d, %edx
xorl %ecx, %ecx
callq 0x17f86
movq %rax, 0x68(%rsp)
movq %r12, %rdi
movq %rbx, %rsi
callq 0x1a900
movq 0x30(%rsp), %r12
movq %r14, %rdi
movq %r14, %rsi
movl %r15d, %edx
movl %ebp, %ecx
callq 0x17f86
addq $0x18, %r12
movq %rax, 0x68(%rsp)
movq %r12, %rdi
movq %rbx, %rsi
callq 0x1a900
incb %r13b
jmp 0x186ea
movq 0xa0(%r14), %rdi
fldt 0x54(%rsp)
fstpt (%rsp)
leaq 0x30(%rsp), %rsi
movq 0x20(%rsp), %rdx
movq 0x28(%rsp), %rcx
movq 0x18(%rsp), %r8
movq 0x60(%rsp), %r9
callq 0x24c0c
testl %eax, %eax
js 0x188e7
movq 0x2282e(%rip), %rdi     # 0x3afb0
leaq 0x12202(%rip), %rsi     # 0x2a98b
callq 0x43a0
movq %rax, %rdi
callq 0x41e0
xorl %ebx, %ebx
leaq 0x12219(%rip), %r12     # 0x2a9b8
leaq 0x121e0(%rip), %r13     # 0x2a986
leaq 0x12ac0(%rip), %rbp     # 0x2b26d
xorl %r15d, %r15d
movzbl 0x24(%r14), %eax
cmpq %rax, %r15
jae 0x1885a
movq 0x227eb(%rip), %rdi     # 0x3afb0
movq %r12, %rsi
callq 0x43a0
movq %rax, %rdi
movl %r15d, %esi
callq 0x46d0
movq %rax, %rdi
movq %r13, %rsi
callq 0x43a0
movq 0x18(%rsp), %rcx
movq (%rcx), %rcx
movq (%rcx,%rbx), %rcx
fldt (%rcx)
fstpt (%rsp)
movq %rax, %rdi
callq 0x4220
movq %rax, %rdi
movq %rbp, %rsi
callq 0x43a0
movq 0x18(%rsp), %rcx
movq (%rcx), %rcx
movq (%rcx,%rbx), %rcx
fldt 0x10(%rcx)
fstpt (%rsp)
movq %rax, %rdi
callq 0x4220
movq %rax, %rdi
movq %rbp, %rsi
callq 0x43a0
movq 0x18(%rsp), %rcx
movq (%rcx), %rcx
movq (%rcx,%rbx), %rcx
fldt 0x20(%rcx)
fstpt (%rsp)
movq %rax, %rdi
callq 0x4220
movq %rax, %rdi
callq 0x41e0
incq %r15
addq $0x18, %rbx
jmp 0x187b0
xorl %r14d, %r14d
movzbl %r14b, %r14d
movq 0x30(%rsp), %rax
movq (%rax), %rdx
movq 0x8(%rax), %rcx
movq %rcx, %rsi
subq %rdx, %rsi
sarq $0x3, %rsi
cmpq %r14, %rsi
jbe 0x1889f
movq (%rdx,%r14,8), %rbx
testq %rbx, %rbx
je 0x1888d
movq %rbx, %rdi
callq 0x1913a
movl $0xc0, %esi
movq %rbx, %rdi
callq 0x43d0
incb %r14b
jmp 0x1885d
xorl %ebx, %ebx
xorl %r15d, %r15d
subq %rdx, %rcx
movzbl %r15b, %r15d
sarq $0x3, %rcx
cmpq %r15, %rcx
jbe 0x188ea
movq 0x18(%rax), %rax
movq (%rax,%r15,8), %r14
testq %r14, %r14
je 0x188c9
movq %r14, %rdi
callq 0x1913a
movl $0xc0, %esi
movq %r14, %rdi
callq 0x43d0
incb %r15b
movq 0x30(%rsp), %rax
movq (%rax), %rdx
movq 0x8(%rax), %rcx
jmp 0x188a4
pushq $-0x1
popq %rbx
leaq 0x30(%rsp), %rdi
callq 0x1916a
movl %ebx, %eax
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
jmp 0x18940
jmp 0x1890f
movq %rax, %rbx
jmp 0x18923
jmp 0x18933
movq %rax, %rbx
leaq 0x68(%rsp), %rdi
callq 0x41c0
leaq 0x30(%rsp), %rdi
callq 0x41c0
jmp 0x18940
jmp 0x18933
jmp 0x18933
movq %rax, %rbx
leaq 0x30(%rsp), %rdi
callq 0x1916a
movq %rbx, %rdi
callq 0x4700