#include "router.h"
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <list>
using namespace std;
/*
RoutingTable Entry 的定义如下:
typedef struct {
uint32_t addr; // 大端序,IPv4 地址
uint32_t len; // 小端序,前缀长度
uint32_t if_index; // 小端序,出端口编号
uint32_t nexthop; // 大端序,下一跳的 IPv4 地址
} RoutingTableEntry;
约定 addr 和 nexthop 以 **大端序** 存储。
这意味着 1.2.3.4 对应 0x04030201 而不是 0x01020304。
保证 addr 仅最低 len 位可能出现非零。
当 nexthop 为零时这是一条直连路由。
你可以在全局变量中把路由表以一定的数据结构格式保存下来。
*/
//binary tree
struct node{
RoutingTableEntry* entry;
node* child[2];
uint8_t size;
uint8_t pos;
static RoutingTableEntry* q_ans;
node(int pos,RoutingTableEntry* entry){
this->entry = entry;
this->pos = pos;
size = 0;
}
void insert(int p,RoutingTableEntry*& e){
if(this->pos == e->len){
this->entry = e;
return;
}
if(p > 32){
return;
}
else{
if(e->addr & (0x80000000 >> p)){
if(!child[1]){
child[1] = new node(p+1,NULL);
size ++;
}
child[1]->insert(p+1,e);
}
else{
if(!child[0]){
child[0] = new node(p+1,NULL);
size ++;
}
child[0]->insert(p+1,e);
}
}
}
bool del(int p,RoutingTableEntry*& entry){
if(this->entry && this->entry->addr == entry->addr && this->entry->len == entry->len){
this->entry = NULL;
if(!child[0] && !child[1])
return true;
else
return false;
}
if(p == entry -> len) //has been replaced!
return false;
if(entry->addr & (0x80000000 >> p)){
if(child[1]->del(p+1,entry) && !this->entry && !child[0])
return true;
}
else{
if(child[0]->del(p+1,entry) && !this->entry && !child[1])
return true;
}
return false;
}
void query(int pos,uint32_t addr){
if(this->entry != NULL){
node::q_ans = entry;
}
unsigned a = addr & (0x80000000 >> pos);
if(pos > 32){
return;
}
else{
if(a && child[1]){
child[1]->query(pos+1,addr);
}
else if( a == 0 && child[0]){
child[0]->query(pos+1,addr);
}
}
}
};
RoutingTableEntry* node::q_ans = NULL;
node* root = new node(0,NULL);
/**
* @brief 插入/删除一条路由表表项
* @param insert 如果要插入则为 true ,要删除则为 false
* @param entry 要插入/删除的表项
*
* 插入时如果已经存在一条 addr 和 len 都相同的表项,则替换掉原有的。this
// TODO:
*/
void update(bool insert,RoutingTableEntry entry){
//int addr = ((entry.addr & 0xff) << 24) | ((entry.addr & 0xff00) << 8) | ((entry.addr & 0xff0000) >> 8) | ((entry.addr&0xff000000) >> 24);
//printf("%x\n",addr);
RoutingTableEntry* tt = &entry;
if (insert) {
root -> insert(0,tt);
}
else{
root -> del(0,tt);
}
}
/**
* @brief 进行一次路由表的查询,按照最长前缀匹配原则
* @param addr 需要查询的目标地址,大端序
* @param nexthop 如果查询到目标,把表项的 nexthop 写入
* @param if_index 如果查询到目标,把表项的 if_index 写入
* @return 查到则返回 true ,没查到则返回 false
*/
bool prefix_query(uint32_t addr, uint32_t *nexthop) {
// TODO:q_ans
*nexthop = 0;
addr = ntohl(addr);
node::q_ans = NULL;
root->query(0,addr);
if(node::q_ans)
{
*nexthop = node::q_ans -> nexthop;
return true;
}
return false;
}
void init(int n, int q, const RoutingTableEntry *a) {
for (int i = 0; i < n; i++) {
update(true, a[i]);
}
}
unsigned query(unsigned addr) {
node::q_ans = NULL;
root->query(0,addr);
if (node::q_ans)
return node::q_ans->nexthop;
return 0;
}
| Compilation | N/A | N/A | Compile OK | Score: N/A | 显示更多 |
| Testcase #1 | 13.95 us | 28 KB | Accepted | Score: 25 | 显示更多 |
| Testcase #2 | 2.248 ms | 9 MB + 520 KB | Runtime Error | Score: 0 | 显示更多 |
| Testcase #3 | 2.228 ms | 9 MB + 520 KB | Runtime Error | Score: 0 | 显示更多 |
| Testcase #4 | 2.245 ms | 9 MB + 520 KB | Runtime Error | Score: 0 | 显示更多 |