<commit_before>#include <iostream>
#include <fstream>
#include <list>

#include <time.h>
#include <string.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>

#include "util.hpp"
#include "table.hpp"
#include "naive.hpp"
//#include "dxr.hpp"
#include "basicTrie.hpp"
#include "pcTrie.hpp"

#define CHALLENGE_VERSION 1

using namespace std;

struct challenge_header {
	uint32_t version;
	uint32_t num_entries;
	uint32_t reserved_1;
	uint32_t reserved_2;
};

struct challenge_entry {
	uint32_t addr;
	uint32_t next_hop;
};

void print_usage(string name){
	cout << "Usage: " << name << endl;
	cout << "\t --algo <name>\t\t\t\t valid: Naive, BasicTrie, PCTrie (default: BasicTrie)" << endl;
	cout << "\t --dump-fib <rib>" << endl;
	cout << "\t --dump-challenge <fib> <challenge>" << endl;
	cout << "\t --run-challenge <fib> <challenge>" << endl;
	cout << "\t --convert-challenge <old> <new>" << endl;
};

void dump_challenge(Table& table, string filename){
#define NUM_ENTRIES 10000000

	ofstream challenge_file (filename, ios::out | ios::binary);
	struct challenge_header header;
	header.version = CHALLENGE_VERSION;
	header.num_entries = NUM_ENTRIES;
	header.reserved_1 = 0;
	header.reserved_2 = 0;
	challenge_file.write((char*) &header, sizeof(challenge_header));

	BasicTrie lpm(table);

	for(int i=0; i<NUM_ENTRIES; i++){
		challenge_entry entry;
		entry.addr = random();
		entry.next_hop = lpm.route(entry.addr);
		challenge_file.write((char*) &entry, sizeof(challenge_entry));
	}

	challenge_file.close();
};

template <typename LPM>
void run_challenge(Table& table, string challenge_filename){
	// read the challenge file
	int fd = open(challenge_filename.c_str(), 0);
	challenge_header header;
	int ret = read(fd, &header, sizeof(challenge_header));
	if(ret != sizeof(challenge_header)){
		cerr << "Error while reader challenge_header!" << endl;
		return;
	}
	if(header.version != CHALLENGE_VERSION){
		cerr << "challenge version is not supported!" << endl;
		return;
	}

	char* mmap_base =  (char*) mmap(
			NULL,
			header.num_entries * sizeof(challenge_entry) + sizeof(challenge_header),
			PROT_READ,
			MAP_PRIVATE,
			fd,
			0);

	if(mmap_base == MAP_FAILED){
		cerr << "mmap failed! errno: " << errno << endl;
		return;
	}

	challenge_entry* entries = (challenge_entry*) (mmap_base + sizeof(challenge_header));

	int failed = 0;
	int success = 0;

	LPM lpm(table);

	clock_t start = clock();
	for(unsigned int i=0; i<header.num_entries; i++){
		uint32_t res = lpm.route(entries[i].addr);
		if(unlikely(res != entries[i].next_hop)){
			cout << "Failed IP: " << ip_to_str(entries[i].addr) << endl;
			cout << "Expected : " << ip_to_str(entries[i].next_hop) << endl;
			cout << "Got      : " << ip_to_str(res) << endl << endl;
			failed++;
		} else {
			success++;
		}
	}
	clock_t end = clock();

	float seconds = (1.0*(end-start)) / CLOCKS_PER_SEC;

	cerr << "Lookups took " << seconds << " seconds" << endl;
	cerr << "Rate: " << ((success + failed) / seconds) / 1000000 << " Mlps" << endl;

	cout << "Successful lookups: " << success << endl;
	cout << "Failed lookups: " << failed << endl;
};

void convert_challenge(string old_file, string new_file){
	// read the challenge file
	list<pair<uint32_t, uint32_t>> challenge;
	ifstream dump(old_file);<commit_msg>populate challenge map + repeat challenge 10 times<commit_after>#include <iostream>
#include <fstream>
#include <list>

#include <time.h>
#include <string.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>

#include "util.hpp"
#include "table.hpp"
#include "naive.hpp"
//#include "dxr.hpp"
#include "basicTrie.hpp"
#include "pcTrie.hpp"

#define CHALLENGE_VERSION 1

using namespace std;

struct challenge_header {
	uint32_t version;
	uint32_t num_entries;
	uint32_t reserved_1;
	uint32_t reserved_2;
};

struct challenge_entry {
	uint32_t addr;
	uint32_t next_hop;
};

void print_usage(string name){
	cout << "Usage: " << name << endl;
	cout << "\t --algo <name>\t\t\t\t valid: Naive, BasicTrie, PCTrie (default: BasicTrie)" << endl;
	cout << "\t --dump-fib <rib>" << endl;
	cout << "\t --dump-challenge <fib> <challenge>" << endl;
	cout << "\t --run-challenge <fib> <challenge>" << endl;
	cout << "\t --convert-challenge <old> <new>" << endl;
};

void dump_challenge(Table& table, string filename){
#define NUM_ENTRIES 10000000

	ofstream challenge_file (filename, ios::out | ios::binary);
	struct challenge_header header;
	header.version = CHALLENGE_VERSION;
	header.num_entries = NUM_ENTRIES;
	header.reserved_1 = 0;
	header.reserved_2 = 0;
	challenge_file.write((char*) &header, sizeof(challenge_header));

	BasicTrie lpm(table);

	for(int i=0; i<NUM_ENTRIES; i++){
		challenge_entry entry;
		entry.addr = random();
		entry.next_hop = lpm.route(entry.addr);
		challenge_file.write((char*) &entry, sizeof(challenge_entry));
	}

	challenge_file.close();
};

template <typename LPM>
void run_challenge(Table& table, string challenge_filename){
	// read the challenge file
	int fd = open(challenge_filename.c_str(), 0);
	challenge_header header;
	int ret = read(fd, &header, sizeof(challenge_header));
	if(ret != sizeof(challenge_header)){
		cerr << "Error while reader challenge_header!" << endl;
		return;
	}
	if(header.version != CHALLENGE_VERSION){
		cerr << "challenge version is not supported!" << endl;
		return;
	}

	char* mmap_base =  (char*) mmap(
			NULL,
			header.num_entries * sizeof(challenge_entry) + sizeof(challenge_header),
			PROT_READ,
			MAP_PRIVATE | MAP_POPULATE,
			fd,
			0);

	if(mmap_base == MAP_FAILED){
		cerr << "mmap failed! errno: " << errno << endl;
		return;
	}

	challenge_entry* entries = (challenge_entry*) (mmap_base + sizeof(challenge_header));

	int failed = 0;
	int success = 0;

	LPM lpm(table);

	clock_t start = clock();
	for(int reps=0; reps<10; reps++){
		for(unsigned int i=0; i<header.num_entries; i++){
			uint32_t res = lpm.route(entries[i].addr);
			if(unlikely(res != entries[i].next_hop)){
				cout << "Failed IP: " << ip_to_str(entries[i].addr) << endl;
				cout << "Expected : " << ip_to_str(entries[i].next_hop) << endl;
				cout << "Got      : " << ip_to_str(res) << endl << endl;
				failed++;
			} else {
				success++;
			}
		}
	}
	clock_t end = clock();

	float seconds = (1.0*(end-start)) / CLOCKS_PER_SEC;

	cerr << "Lookups took " << seconds << " seconds" << endl;
	cerr << "Rate: " << ((success + failed) / seconds) / 1000000 << " Mlps" << endl;

	cout << "Successful lookups: " << success << endl;
	cout << "Failed lookups: " << failed << endl;
};

void convert_challenge(string old_file, string new_file){
	// read the challenge file
	list<pair<uint32_t, uint32_t>> challenge;
	ifstream dump(old_file);
{'fraction_non_alphanumeric': 0.16389583639841107, 'fraction_numerical': 0.014859496836839783, 'mean_word_length': 4.5, 'pattern_counts': {'":': 0, '<': 228, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1915282', 'n_tokens_mistral': 2758, 'n_tokens_neox': 2465, 'n_words': 592}