// File: 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
movq %rsp, %rbp
subq $0x2a0, %rsp            # imm = 0x2A0
movb %sil, %al
fldt 0x10(%rbp)
movq %rdi, -0x10(%rbp)
movb %al, -0x11(%rbp)
movq %rdx, -0x20(%rbp)
fstpt -0x30(%rbp)
movq %rcx, -0x38(%rbp)
movq %r8, -0x40(%rbp)
movq %r9, -0x48(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x1a0(%rbp)
movq 0x4eb3b(%rip), %rdi     # 0x81fb8
leaq 0x30295(%rip), %rsi     # 0x63719
callq 0x5480
movq %rax, %rdi
leaq 0x302b9(%rip), %rsi     # 0x6374c
callq 0x5480
movq -0x1a0(%rbp), %rdi
movq %rax, -0x198(%rbp)
movzbl -0x11(%rbp), %esi
callq 0x35610
movq %rax, -0x78(%rbp)
movb %dl, -0x70(%rbp)
movq -0x78(%rbp), %rsi
leaq -0x68(%rbp), %rdi
movq %rdi, -0x190(%rbp)
callq 0x35650
movq -0x198(%rbp), %rdi
movq -0x190(%rbp), %rsi
callq 0x5430
movq %rax, -0x188(%rbp)
jmp 0x334e6
movq -0x188(%rbp), %rdi
leaq 0x30262(%rip), %rsi     # 0x63756
callq 0x5480
movq %rax, -0x1a8(%rbp)
jmp 0x33502
movq -0x1a0(%rbp), %rsi
leaq -0xa8(%rbp), %rdi
callq 0x35650
jmp 0x33517
movq -0x1a8(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x5430
movq %rax, -0x1b0(%rbp)
jmp 0x33533
movq -0x1b0(%rbp), %rdi
leaq 0x30f49(%rip), %rsi     # 0x6448a
callq 0x5480
movq %rax, -0x1b8(%rbp)
jmp 0x3354f
movq -0x1b8(%rbp), %rdi
movzbl -0x11(%rbp), %esi
callq 0x58f0
movq %rax, -0x1c0(%rbp)
jmp 0x33568
movq -0x1c0(%rbp), %rdi
leaq 0x2c77b(%rip), %rsi     # 0x5fcf1
callq 0x5480
movq %rax, -0x1c8(%rbp)
jmp 0x33584
movq -0x1c8(%rbp), %rdi
movq 0x4e9fe(%rip), %rsi     # 0x81f90
callq 0x54f0
jmp 0x33599
leaq -0xa8(%rbp), %rdi
callq 0x52f0
leaq -0x68(%rbp), %rdi
callq 0x52f0
movb $0x0, -0xa9(%rbp)
movq -0x1a0(%rbp), %rcx
movzbl -0xa9(%rbp), %eax
movzbl 0x24(%rcx), %ecx
cmpl %ecx, %eax
jge 0x336f6
movq -0x1a0(%rbp), %rdi
addq $0x88, %rdi
movq %rdi, -0x1d0(%rbp)
movzbl -0xa9(%rbp), %eax
movl %eax, %esi
callq 0x34fa0
movq %rax, %rdi
callq 0x356e0
movq -0x1d0(%rbp), %rdi
movl %edx, -0xc8(%rbp)
movq %rax, -0xd0(%rbp)
movl -0xc8(%rbp), %eax
movl %eax, -0xb8(%rbp)
movq -0xd0(%rbp), %rax
movq %rax, -0xc0(%rbp)
movzbl -0xa9(%rbp), %eax
movl %eax, %esi
callq 0x34fa0
movq %rax, %rdi
callq 0x35720
movl %edx, -0xe8(%rbp)
movq %rax, -0xf0(%rbp)
movq -0xf0(%rbp), %rax
movq %rax, -0xe0(%rbp)
movl -0xe8(%rbp), %eax
movl %eax, -0xd8(%rbp)
movb $0x0, -0xf1(%rbp)
movq -0xc0(%rbp), %rdi
movl -0xb8(%rbp), %esi
movq -0xe0(%rbp), %rdx
movl -0xd8(%rbp), %ecx
leaq -0xf1(%rbp), %r8
callq 0x35680
movq -0x1a0(%rbp), %rdi
movzbl -0xa9(%rbp), %esi
movq -0x20(%rbp), %rdx
callq 0x33ef0
movb -0xa9(%rbp), %al
addb $0x1, %al
movb %al, -0xa9(%rbp)
jmp 0x335b5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x336e8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x52f0
leaq -0x68(%rbp), %rdi
callq 0x52f0
jmp 0x33ede
movb $0x0, -0xf2(%rbp)
movq -0x1a0(%rbp), %rcx
movzbl -0xf2(%rbp), %eax
movzbl 0x24(%rcx), %ecx
cmpl %ecx, %eax
jge 0x337b9
movq -0x1a0(%rbp), %rdi
addq $0x60, %rdi
movzbl -0xf2(%rbp), %eax
movl %eax, %esi
callq 0x35120
movq %rax, -0x108(%rbp)
movq %rdx, -0x100(%rbp)
leaq -0x108(%rbp), %rdi
xorl %esi, %esi
callq 0x355a0
movq -0x1a0(%rbp), %rdi
addq $0x30, %rdi
movzbl -0xf2(%rbp), %eax
movl %eax, %esi
callq 0x34a20
cmpq $0x0, 0x58(%rax)
jne 0x337a4
movq -0x1a0(%rbp), %rdi
addq $0x60, %rdi
movzbl -0xf2(%rbp), %eax
movl %eax, %esi
callq 0x35120
movq %rax, -0x118(%rbp)
movq %rdx, -0x110(%rbp)
leaq -0x118(%rbp), %rdi
movl $0x1, %esi
callq 0x355a0
jmp 0x337a6
movb -0xf2(%rbp), %al
addb $0x1, %al
movb %al, -0xf2(%rbp)
jmp 0x336fd
movq -0x1a0(%rbp), %rdi
addq $0x60, %rdi
movzbl -0x11(%rbp), %eax
movl %eax, %esi
callq 0x35120
movq %rax, -0x128(%rbp)
movq %rdx, -0x120(%rbp)
leaq -0x128(%rbp), %rdi
movl $0x1, %esi
callq 0x355a0
movq 0x4e7c3(%rip), %rdi     # 0x81fb8
leaq 0x2ff64(%rip), %rsi     # 0x63760
callq 0x5480
movb $0x0, -0x129(%rbp)
movq -0x1a0(%rbp), %rdi
movzbl -0x129(%rbp), %eax
movq %rax, -0x1d8(%rbp)
addq $0x60, %rdi
callq 0x35740
movq %rax, %rcx
movq -0x1d8(%rbp), %rax
cmpq %rcx, %rax
jae 0x338d7
movq 0x4e778(%rip), %rdi     # 0x81fb8
leaq 0x30c43(%rip), %rsi     # 0x6448a
callq 0x5480
movq %rax, %rdi
movzbl -0x129(%rbp), %esi
callq 0x58f0
movq %rax, %rdi
leaq 0x2ff2b(%rip), %rsi     # 0x63790
callq 0x5480
movq -0x1a0(%rbp), %rdi
movq %rax, -0x1e0(%rbp)
addq $0x60, %rdi
movzbl -0x129(%rbp), %eax
movl %eax, %esi
callq 0x35120
movq %rax, -0x140(%rbp)
movq %rdx, -0x138(%rbp)
leaq -0x140(%rbp), %rdi
callq 0x35180
movq -0x1e0(%rbp), %rdi
andb $0x1, %al
movzbl %al, %esi
callq 0x58f0
movq %rax, %rdi
leaq 0x2fc5a(%rip), %rsi     # 0x63519
callq 0x5480
movb -0x129(%rbp), %al
addb $0x1, %al
movb %al, -0x129(%rbp)
jmp 0x33808
movq 0x4e6da(%rip), %rdi     # 0x81fb8
movq %rdi, -0x1e8(%rbp)
leaq 0x2fea7(%rip), %rsi     # 0x63793
callq 0x5480
movq %rax, %rdi
movq 0x4e695(%rip), %rsi     # 0x81f90
callq 0x54f0
movq -0x1e8(%rbp), %rdi
leaq 0x2fe87(%rip), %rsi     # 0x63795
callq 0x5480
movq %rax, %rdi
fldt -0x30(%rbp)
movq %rsp, %rax
fstpt (%rax)
callq 0x55b0
movq %rax, %rdi
movq 0x4e663(%rip), %rsi     # 0x81f90
callq 0x54f0
movq 0x4e67f(%rip), %rdi     # 0x81fb8
leaq 0x2fe76(%rip), %rsi     # 0x637b6
callq 0x5480
movq %rax, %rdi
movq 0x4e641(%rip), %rsi     # 0x81f90
callq 0x54f0
movb $0x0, -0x141(%rbp)
movq -0x1a0(%rbp), %rcx
movzbl -0x141(%rbp), %eax
movzbl 0x21(%rcx), %ecx
cmpl %ecx, %eax
jg 0x339f0
movq 0x4e640(%rip), %rdi     # 0x81fb8
leaq 0x2fe62(%rip), %rsi     # 0x637e1
callq 0x5480
movq %rax, %rdi
movzbl -0x141(%rbp), %esi
callq 0x58f0
movq %rax, %rdi
leaq 0x2fe4c(%rip), %rsi     # 0x637e9
callq 0x5480
movq %rax, -0x1f0(%rbp)
movq -0x38(%rbp), %rdi
movzbl -0x141(%rbp), %eax
movl %eax, %esi
callq 0x34c70
movq -0x1f0(%rbp), %rdi
fldt (%rax)
movq %rsp, %rax
fstpt (%rax)
callq 0x55b0
movq %rax, %rdi
movq 0x4e5b8(%rip), %rsi     # 0x81f90
callq 0x54f0
movb -0x141(%rbp), %al
addb $0x1, %al
movb %al, -0x141(%rbp)
jmp 0x3395b
leaq -0x161(%rbp), %rdi
movq %rdi, -0x1f8(%rbp)
callq 0x357a0
movq -0x1f8(%rbp), %rdx
leaq -0x160(%rbp), %rdi
movl $0x2, %esi
callq 0x357c0
jmp 0x33a1d
leaq -0x161(%rbp), %rdi
callq 0x35830
movb $0x0, -0x162(%rbp)
movq -0x1a0(%rbp), %rcx
movzbl -0x162(%rbp), %eax
movzbl 0x24(%rcx), %ecx
cmpl %ecx, %eax
jge 0x33b63
xorl %eax, %eax
movl %eax, -0x20c(%rbp)
movl %eax, %esi
leaq -0x160(%rbp), %rdi
callq 0x35850
movq -0x1a0(%rbp), %rsi
movl -0x20c(%rbp), %ecx
movq %rax, -0x208(%rbp)
movzbl -0x162(%rbp), %edx
movq %rsi, %rdi
callq 0x329d0
movq %rax, -0x200(%rbp)
jmp 0x33a8c
movq -0x208(%rbp), %rdi
movq -0x200(%rbp), %rax
movq %rax, -0x170(%rbp)
leaq -0x170(%rbp), %rsi
callq 0x35870
jmp 0x33aaf
leaq -0x160(%rbp), %rdi
movl $0x1, %esi
callq 0x35850
movq -0x1a0(%rbp), %rsi
movq %rax, -0x220(%rbp)
movzbl -0x162(%rbp), %edx
movl $0x1, %ecx
movq %rsi, %rdi
callq 0x329d0
movq %rax, -0x218(%rbp)
jmp 0x33aeb
movq -0x220(%rbp), %rdi
movq -0x218(%rbp), %rax
movq %rax, -0x178(%rbp)
leaq -0x178(%rbp), %rsi
callq 0x35870
jmp 0x33b0e
jmp 0x33b10
movb -0x162(%rbp), %al
addb $0x1, %al
movb %al, -0x162(%rbp)
jmp 0x33a30
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x161(%rbp), %rdi
callq 0x35830
jmp 0x33ede
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x160(%rbp), %rdi
callq 0x35950
jmp 0x33ede
movq -0x1a0(%rbp), %rax
movq 0xa0(%rax), %rdi
movq -0x20(%rbp), %rdx
fldt -0x30(%rbp)
movq -0x38(%rbp), %rcx
movq -0x40(%rbp), %r8
movq -0x48(%rbp), %r9
movq %rsp, %rax
fstpt (%rax)
leaq -0x160(%rbp), %rsi
callq 0x5cc00
movl %eax, -0x224(%rbp)
jmp 0x33b9d
movl -0x224(%rbp), %eax
cmpl $0x0, %eax
jge 0x33bbe
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x17c(%rbp)
jmp 0x33ec6
movq 0x4e3f3(%rip), %rdi     # 0x81fb8
leaq 0x2fc23(%rip), %rsi     # 0x637ef
callq 0x5480
movq %rax, -0x230(%rbp)
jmp 0x33bda
movq -0x230(%rbp), %rdi
movq 0x4e3a8(%rip), %rsi     # 0x81f90
callq 0x54f0
jmp 0x33bef
movb $0x0, -0x17d(%rbp)
movq -0x1a0(%rbp), %rcx
movzbl -0x17d(%rbp), %eax
movzbl 0x24(%rcx), %ecx
cmpl %ecx, %eax
jge 0x33d76
movq 0x4e3a1(%rip), %rdi     # 0x81fb8
leaq 0x2fbfe(%rip), %rsi     # 0x6381c
callq 0x5480
movq %rax, -0x238(%rbp)
jmp 0x33c2c
movq -0x238(%rbp), %rdi
movzbl -0x17d(%rbp), %esi
callq 0x58f0
movq %rax, -0x240(%rbp)
jmp 0x33c48
movq -0x240(%rbp), %rdi
leaq 0x2fb94(%rip), %rsi     # 0x637ea
callq 0x5480
movq %rax, -0x248(%rbp)
jmp 0x33c64
movq -0x40(%rbp), %rdi
movzbl -0x17d(%rbp), %eax
movl %eax, %esi
callq 0x358a0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x34c70
movq -0x248(%rbp), %rdi
fldt (%rax)
movq %rsp, %rax
fstpt (%rax)
callq 0x55b0
movq %rax, -0x250(%rbp)
jmp 0x33c9e
movq -0x250(%rbp), %rdi
leaq 0x30508(%rip), %rsi     # 0x641b4
callq 0x5480
movq %rax, -0x258(%rbp)
jmp 0x33cba
movq -0x40(%rbp), %rdi
movzbl -0x17d(%rbp), %eax
movl %eax, %esi
callq 0x358a0
movq %rax, %rdi
movl $0x1, %esi
callq 0x34c70
movq -0x258(%rbp), %rdi
fldt (%rax)
movq %rsp, %rax
fstpt (%rax)
callq 0x55b0
movq %rax, -0x260(%rbp)
jmp 0x33cf5
movq -0x260(%rbp), %rdi
leaq 0x304b1(%rip), %rsi     # 0x641b4
callq 0x5480
movq %rax, -0x268(%rbp)
jmp 0x33d11
movq -0x40(%rbp), %rdi
movzbl -0x17d(%rbp), %eax
movl %eax, %esi
callq 0x358a0
movq %rax, %rdi
movl $0x2, %esi
callq 0x34c70
movq -0x268(%rbp), %rdi
fldt (%rax)
movq %rsp, %rax
fstpt (%rax)
callq 0x55b0
movq %rax, -0x270(%rbp)
jmp 0x33d4c
movq -0x270(%rbp), %rdi
movq 0x4e236(%rip), %rsi     # 0x81f90
callq 0x54f0
jmp 0x33d61
jmp 0x33d63
movb -0x17d(%rbp), %al
addb $0x1, %al
movb %al, -0x17d(%rbp)
jmp 0x33bf6
movb $0x0, -0x17e(%rbp)
movzbl -0x17e(%rbp), %eax
movq %rax, -0x278(%rbp)
leaq -0x160(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x35850
movq %rax, %rdi
callq 0x358c0
movq %rax, %rcx
movq -0x278(%rbp), %rax
cmpq %rcx, %rax
jae 0x33e15
leaq -0x160(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x35850
movq %rax, %rdi
movzbl -0x17e(%rbp), %eax
movl %eax, %esi
callq 0x358e0
movq (%rax), %rax
movq %rax, -0x280(%rbp)
cmpq $0x0, %rax
je 0x33e00
movq -0x280(%rbp), %rdi
callq 0x35900
movq -0x280(%rbp), %rdi
movl $0xc0, %esi
callq 0x54b0
jmp 0x33e02
movb -0x17e(%rbp), %al
addb $0x1, %al
movb %al, -0x17e(%rbp)
jmp 0x33d7d
movb $0x0, -0x17f(%rbp)
movzbl -0x17f(%rbp), %eax
movq %rax, -0x288(%rbp)
leaq -0x160(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x35850
movq %rax, %rdi
callq 0x358c0
movq %rax, %rcx
movq -0x288(%rbp), %rax
cmpq %rcx, %rax
jae 0x33eb5
leaq -0x160(%rbp), %rdi
movl $0x1, %esi
callq 0x35850
movq %rax, %rdi
movzbl -0x17f(%rbp), %eax
movl %eax, %esi
callq 0x358e0
movq (%rax), %rax
movq %rax, -0x290(%rbp)
cmpq $0x0, %rax
je 0x33ea0
movq -0x290(%rbp), %rdi
callq 0x35900
movq -0x290(%rbp), %rdi
movl $0xc0, %esi
callq 0x54b0
jmp 0x33ea2
movb -0x17f(%rbp), %al
addb $0x1, %al
movb %al, -0x17f(%rbp)
jmp 0x33e1c
movl $0x0, -0x4(%rbp)
movl $0x1, -0x17c(%rbp)
leaq -0x160(%rbp), %rdi
callq 0x35950
movl -0x4(%rbp), %eax
addq $0x2a0, %rsp            # imm = 0x2A0
popq %rbp
retq
movq -0x80(%rbp), %rdi
callq 0x5920
nopw (%rax,%rax)