⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fromnlanrdump.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
字号:
// -*- mode: c++; c-basic-offset: 4 -*-/* * fromnlanrdump.{cc,hh} -- element reads packets from NLANR format file * Eddie Kohler * * Copyright (c) 2002 International Computer Science Institute * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, subject to the conditions * listed in the Click LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the Click LICENSE file; the license in that file is * legally binding. */#include <click/config.h>#include "fromnlanrdump.hh"#include <click/confparse.hh>#include <click/packet_anno.hh>#include <click/router.hh>#include <click/standard/scheduleinfo.hh>#include <click/error.hh>#include <click/glue.hh>#include <click/handlercall.hh>#include <clicknet/rfc1483.h>#include <click/userutils.hh>#include "elements/userlevel/fakepcap.hh"#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#ifdef ALLOW_MMAP# include <sys/mman.h>#endifCLICK_DECLS#define	SWAPLONG(y) \	((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))#define	SWAPSHORT(y) \	( (((y)&0xff)<<8) | ((u_short)((y)&0xff00)>>8) )FromNLANRDump::FromNLANRDump()    : Element(0, 1), _packet(0), _end_h(0), _task(this){}FromNLANRDump::~FromNLANRDump(){    delete _end_h;}voidFromNLANRDump::notify_noutputs(int n){    set_noutputs(n <= 1 ? 1 : 2);}intFromNLANRDump::configure(Vector<String> &conf, ErrorHandler *errh){    bool timing = false, stop = false, active = true;    String format = "guess";    Timestamp first_time, first_time_off, last_time, last_time_off, interval;    _sampling_prob = (1 << SAMPLING_SHIFT);    _packet_filepos = 0;    bool force_ip = true;    if (_ff.configure_keywords(conf, 1, this, errh) < 0)	return -1;    if (cp_va_parse(conf, this, errh,		    cpFilename, "dump file name", &_ff.filename(),		    cpKeywords,		    "FORMAT", cpWord, "file format", &format,		    "STOP", cpBool, "stop driver when done?", &stop,		    "ACTIVE", cpBool, "start active?", &active,		    "FORCE_IP", cpBool, "ignored for compatibility", &force_ip,		    "START", cpTimestamp, "starting time", &first_time,		    "START_AFTER", cpTimestamp, "starting time offset", &first_time_off,		    "END", cpTimestamp, "ending time", &last_time,		    "END_AFTER", cpTimestamp, "ending time offset", &last_time_off,		    "INTERVAL", cpTimestamp, "time interval", &interval,		    "END_CALL", cpWriteHandlerCall, "write handler for ending time", &_end_h,		    "FILEPOS", cpFileOffset, "starting file position", &_packet_filepos,		    "SAMPLE", cpUnsignedReal2, "sampling probability", SAMPLING_SHIFT, &_sampling_prob,		    "TIMING", cpBool, "use original packet timing?", &timing,		    cpEnd) < 0)	return -1;    // check sampling rate    if (_sampling_prob > (1 << SAMPLING_SHIFT)) {	errh->warning("SAMPLE probability reduced to 1");	_sampling_prob = (1 << SAMPLING_SHIFT);    } else if (_sampling_prob == 0)	errh->warning("SAMPLE probability is 0; emitting no packets");    // check times    _have_first_time = _have_last_time = true;    _first_time_relative = _last_time_relative = _last_time_interval = false;        if ((bool) first_time + (bool) first_time_off > 1)	return errh->error("'START' and 'START_AFTER' are mutually exclusive");    else if (first_time)	_first_time = first_time;    else if (first_time_off)	_first_time = first_time_off, _first_time_relative = true;    else	_have_first_time = false, _first_time_relative = true;        if ((bool) last_time + (bool) last_time_off + (bool) interval > 1)	return errh->error("'END', 'END_AFTER', and 'INTERVAL' are mutually exclusive");    else if (last_time)	_last_time = last_time;    else if (last_time_off)	_last_time = last_time_off, _last_time_relative = true;    else if (interval)	_last_time = interval, _last_time_interval = true;    else	_have_last_time = false;    if (stop && _end_h)	return errh->error("'END_CALL' and 'STOP' are mutually exclusive");    else if (stop)	_end_h = new HandlerCall(id() + ".stop");    else if (_have_last_time && !_end_h)	_end_h = new HandlerCall(id() + ".active false");    // format    format = format.lower();    if (format == "fr")	_format = C_FR;    else if (format == "fr+")	_format = C_FRPLUS;    else if (format == "tsh")	_format = C_TSH;    else if (format == "guess") {	format = _ff.filename().lower();	if (format.substring(-3).lower() == ".gz")	    format = format.substring(0, format.length() - 3);	else if (format.substring(-2).lower() == ".z")	    format = format.substring(0, format.length() - 2);	else if (format.substring(-4).lower() == ".bz2")	    format = format.substring(0, format.length() - 4);	if (format.substring(-3).lower() == ".fr")	    _format = C_FR;	else if (format.substring(-3).lower() == ".fr+")	    _format = C_FRPLUS;	else if (format.substring(-4).lower() == ".tsh")	    _format = C_TSH;	else {	    errh->warning("cannot guess file format from filename, assuming 'tsh'");	    _format = C_TSH;	}    } else	return errh->error("bad FORMAT");    switch (_format) {      case C_FR: _cell_size = FRCell::SIZE; break;      case C_FRPLUS: _cell_size = FRPlusCell::SIZE; break;      case C_TSH: _cell_size = TSHCell::SIZE; break;    }        // set other variables    _have_any_times = false;    _timing = timing;    _active = active;    return 0;}intFromNLANRDump::initialize(ErrorHandler *errh){    // check handler call, initialize Task    if (_end_h && _end_h->initialize_write(this, errh) < 0)	return -1;    if (output_is_push(0))	ScheduleInfo::initialize_task(this, &_task, _active, errh);    // open file    if (_ff.initialize(errh) < 0)	return -1;        // try reading a packet    if (read_packet(errh))	_time_offset = Timestamp::now() - _packet->timestamp_anno();    // maybe skip ahead in the file    if (_packet_filepos != 0) {	int result = _ff.seek(_packet_filepos, errh);	_packet_filepos = 0;	return result;    } else	return 0;}voidFromNLANRDump::cleanup(CleanupStage){    _ff.cleanup();    if (_packet)	_packet->kill();    _packet = 0;}voidFromNLANRDump::set_active(bool active){    if (_active != active) {	_active = active;	if (active && output_is_push(0) && !_task.scheduled())	    _task.reschedule();    }}voidFromNLANRDump::prepare_times(const Timestamp &tv){    if (_first_time_relative)	_first_time += tv;    if (_last_time_relative)	_last_time += tv;    else if (_last_time_interval)	_last_time += _first_time;    _have_any_times = true;}boolFromNLANRDump::read_packet(ErrorHandler *errh){    const TSHCell *cell;    static TSHCell static_cell;    Timestamp tv;    Packet *p;    bool more = true;    _packet = 0;  retry:    // quit if we sampled or force_ip failed, but we are no longer active    if (!more)	return false;        // record file position    _packet_filepos = _ff.file_pos();    // read the cell    cell = reinterpret_cast<const TSHCell *>(_ff.get_aligned(_cell_size, &static_cell, errh));    if (!cell)	return false;    // check times  check_times:    uint32_t usec = ntohl(cell->timestamp_usec);    if (_format == C_TSH)	tv = Timestamp(ntohl(cell->timestamp_sec), usec & 0xFFFFFF);    else if (_format == C_FRPLUS || _format == C_FR)	tv = Timestamp(ntohl(cell->timestamp_sec), usec);    if (!_have_any_times)	prepare_times(tv);    if (_have_first_time) {	if (tv < _first_time)	    goto retry;	else	    _have_first_time = false;    }    if (_have_last_time && tv >= _last_time) {	_have_last_time = false;	(void) _end_h->call_write(errh);	if (!_active)	    more = false;	// The handler might have scheduled us, in which case we might crash	// at fast_reschedule()! Don't want that -- make sure we are	// unscheduled.	_task.fast_unschedule();	// retry _last_time in case someone changed it	goto check_times;    }        // checking sampling probability    if (_sampling_prob < (1 << SAMPLING_SHIFT)	&& (uint32_t)(random() & ((1<<SAMPLING_SHIFT)-1)) >= _sampling_prob)	goto retry;        // create packet    if (_format != C_FR)	p = _ff.get_packet_from_data(&cell->iph, _cell_size - 8, _cell_size - 8, tv.sec(), tv.subsec(), errh);    else	p = 0;    if (!p)	return false;    fake_pcap_force_ip(p, FAKE_DLT_RAW);    if (p->network_header_length() != sizeof(click_ip)) { // there were ip options	checked_output_push(1, p);	goto retry;    }    if (_format == C_TSH)	// set link annotation	SET_PAINT_ANNO(p, usec >> 24);    _packet = p;    return more;}boolFromNLANRDump::run_task(){    if (!_active)	return false;    bool more;    if (_packet || read_packet(0)) {	if (_timing	    && _packet->timestamp_anno() > Timestamp::now() - _time_offset) {	    _task.fast_reschedule();	    return false;	}	output(0).push(_packet);	more = read_packet(0);    } else	more = false;    if (more)	_task.fast_reschedule();    else if (_end_h)	_end_h->call_write(ErrorHandler::default_handler());    return true;}Packet *FromNLANRDump::pull(int){    if (!_active)	return 0;    bool more;    Packet *p;    if (_packet || read_packet(0)) {	if (_timing	    && _packet->timestamp_anno() > Timestamp::now() - _time_offset)	    return 0;	p = _packet;	more = read_packet(0);    } else {	p = 0;	more = false;    }    if (!more && _end_h)	_end_h->call_write(ErrorHandler::default_handler());    return p;}enum {    H_SAMPLING_PROB, H_ACTIVE, H_ENCAP, H_STOP, H_PACKET_FILEPOS,    H_EXTEND_INTERVAL};StringFromNLANRDump::read_handler(Element *e, void *thunk){    FromNLANRDump *fd = static_cast<FromNLANRDump *>(e);    switch ((intptr_t)thunk) {      case H_SAMPLING_PROB:	return cp_unparse_real2(fd->_sampling_prob, SAMPLING_SHIFT) + "\n";      case H_ACTIVE:	return cp_unparse_bool(fd->_active) + "\n";      case H_ENCAP:	return "IP\n";      case H_PACKET_FILEPOS:	return String(fd->_packet_filepos) + "\n";      default:	return "<error>\n";    }}intFromNLANRDump::write_handler(const String &s_in, Element *e, void *thunk, ErrorHandler *errh){    FromNLANRDump *fd = static_cast<FromNLANRDump *>(e);    String s = cp_uncomment(s_in);    switch ((intptr_t)thunk) {      case H_ACTIVE: {	  bool active;	  if (cp_bool(s, &active)) {	      fd->set_active(active);	      return 0;	  } else	      return errh->error("'active' should be Boolean");      }      case H_STOP:	fd->set_active(false);	fd->router()->please_stop_driver();	return 0;      case H_EXTEND_INTERVAL: {	  Timestamp tv;	  if (cp_time(s, &tv)) {	      fd->_last_time += tv;	      if (fd->_end_h)		  fd->_have_last_time = true, fd->set_active(true);	      return 0;	  } else	      return errh->error("'extend_interval' takes a time interval");      }      default:	return -EINVAL;    }}voidFromNLANRDump::add_handlers(){    add_read_handler("sampling_prob", read_handler, (void *)H_SAMPLING_PROB);    add_read_handler("active", read_handler, (void *)H_ACTIVE);    add_write_handler("active", write_handler, (void *)H_ACTIVE);    add_read_handler("encap", read_handler, (void *)H_ENCAP);    add_write_handler("stop", write_handler, (void *)H_STOP);    add_read_handler("packet_filepos", read_handler, (void *)H_PACKET_FILEPOS);    add_write_handler("extend_interval", write_handler, (void *)H_EXTEND_INTERVAL);    _ff.add_handlers(this);    if (output_is_push(0))	add_task_handlers(&_task);}CLICK_ENDDECLSELEMENT_REQUIRES(userlevel int64 FakePcap FromFile)EXPORT_ELEMENT(FromNLANRDump)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -