📄 click-align.cc
字号:
/* * click-align.cc -- alignment enforcer for Click configurations * Eddie Kohler * * Copyright (c) 1999-2000 Massachusetts Institute of Technology * Copyright (c) 2007 Regents of the University of California * * 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 <click/pathvars.h>#include <click/error.hh>#include <click/confparse.hh>#include <click/straccum.hh>#include <click/driver.hh>#include "lexert.hh"#include "routert.hh"#include "alignment.hh"#include "alignclass.hh"#include "elementmap.hh"#include "toolutils.hh"#include <click/clp.h>#include <stdio.h>#include <ctype.h>#include <algorithm>static ElementMap element_map;struct RouterAlign { RouterT *_router; Vector<int> _icount; Vector<int> _ocount; Vector<int> _ioffset; Vector<int> _ooffset; Vector<Alignment> _ialign; Vector<Alignment> _oalign; Vector<Aligner *> _aligners; RouterAlign(RouterT *, ErrorHandler *); int iindex_eindex(int) const; int iindex_port(int) const; int oindex_eindex(int) const; int oindex_port(int) const; bool have_input(); void have_output(); void want_input(); bool want_output(); void adjust(); void print(FILE *);};RouterAlign::RouterAlign(RouterT *r, ErrorHandler *errh) : _router(r){ int ne = r->nelements(); int id = 0, od = 0; for (int i = 0; i < ne; i++) { _ioffset.push_back(id); _ooffset.push_back(od); ElementT *e = r->element(i); _icount.push_back(e->ninputs()); _ocount.push_back(e->noutputs()); id += e->ninputs(); od += e->noutputs(); } _ioffset.push_back(id); _ooffset.push_back(od); // set alignments _ialign.assign(id, Alignment()); _oalign.assign(od, Alignment()); // find aligners _aligners.assign(_router->nelements(), default_aligner()); for (RouterT::iterator x = _router->begin_elements(); x; x++) { AlignClass *eclass = (AlignClass *)x->type()->cast("AlignClass"); if (eclass) _aligners[x->eindex()] = eclass->create_aligner(x, _router, errh); }}intRouterAlign::iindex_eindex(int ii) const{ int ne = _icount.size(); for (int i = 0; i < ne; i++) if (ii < _ioffset[i+1]) return i; return -1;}intRouterAlign::iindex_port(int ii) const{ int ne = _icount.size(); for (int i = 0; i < ne; i++) if (ii < _ioffset[i+1]) return ii - _ioffset[i]; return -1;}intRouterAlign::oindex_eindex(int oi) const{ int ne = _icount.size(); for (int i = 0; i < ne; i++) if (oi < _ooffset[i+1]) return i; return -1;}intRouterAlign::oindex_port(int oi) const{ int ne = _icount.size(); for (int i = 0; i < ne; i++) if (oi < _ooffset[i+1]) return oi - _ooffset[i]; return -1;}voidRouterAlign::have_output(){ int ne = _icount.size(); for (int i = 0; i < ne; i++) { Traits t = element_map.traits(_router->etype_name(i)); _aligners[i]->have_flow(_ialign.begin() + _ioffset[i], _icount[i], _oalign.begin() + _ooffset[i], _ocount[i], _router->element(i)->flow_code()); }}boolRouterAlign::have_input(){ const Vector<ConnectionT> &conn = _router->connections(); int nh = conn.size(); int nialign = _ialign.size(); Vector<Alignment> new_ialign(nialign, Alignment()); for (int i = 0; i < nh; i++) if (conn[i].live()) { int ioff = _ioffset[conn[i].to_eindex()] + conn[i].to_port(); int ooff = _ooffset[conn[i].from_eindex()] + conn[i].from_port(); new_ialign[ioff] |= _oalign[ooff]; } // see if anything happened bool changed = false; for (int i = 0; i < nialign && !changed; i++) if (new_ialign[i] != _ialign[i]) changed = true; _ialign.swap(new_ialign); return changed;}voidRouterAlign::want_input(){ int ne = _icount.size(); for (int i = 0; i < ne; i++) { Traits t = element_map.traits(_router->etype_name(i)); _aligners[i]->want_flow(_ialign.begin() + _ioffset[i], _icount[i], _oalign.begin() + _ooffset[i], _ocount[i], _router->element(i)->flow_code()); }}boolRouterAlign::want_output(){ const Vector<ConnectionT> &conn = _router->connections(); int nh = conn.size(); int noalign = _oalign.size(); Vector<Alignment> new_oalign(noalign, Alignment()); for (int i = 0; i < nh; i++) if (conn[i].live()) { int ioff = _ioffset[conn[i].to_eindex()] + conn[i].to_port(); int ooff = _ooffset[conn[i].from_eindex()] + conn[i].from_port(); new_oalign[ooff] &= _ialign[ioff]; } /* for (int i = 0; i < noalign; i++) if (new_oalign[i].bad()) new_oalign[i] = Alignment(); */ // see if anything happened bool changed = false; for (int i = 0; i < noalign && !changed; i++) if (new_oalign[i] != _oalign[i]) { /* fprintf(stderr, "%s[%d] %s <- %s\n", _router->ename(oindex_eindex(i)).c_str(), oindex_port(i), new_oalign[i].s().c_str(), _oalign[i].s().c_str()); */ changed = true; } _oalign.swap(new_oalign); return changed;}voidRouterAlign::adjust(){ int ne = _icount.size(); for (int i = 0; i < ne; i++) _aligners[i]->adjust_flow(_ialign.begin() + _ioffset[i], _icount[i], _oalign.begin() + _ooffset[i], _ocount[i]);}voidRouterAlign::print(FILE *f){ for (RouterT::iterator x = _router->begin_elements(); x; x++) { int i = x->eindex(); fprintf(f, "%s :", x->name_c_str()); for (int j = 0; j < _icount[i]; j++) { const Alignment &a = _ialign[ _ioffset[i] + j ]; fprintf(f, " %d/%d", a.modulus(), a.offset()); } fprintf(f, " -"); for (int j = 0; j < _ocount[i]; j++) { const Alignment &a = _oalign[ _ooffset[i] + j ]; fprintf(f, " %d/%d", a.modulus(), a.offset()); } fprintf(f, "\n"); } fprintf(f, "\n");}static ElementClassT *class_factory(const String &name){ if (name == "Align") return new AlignAlignClass; if (name == "Strip" || name == "Unstrip") return new StripAlignClass(name, name == "Strip"); if (name == "CheckIPHeader" || name == "CheckIPHeader2" || name == "MarkIPHeader") return new CheckIPHeaderAlignClass(name); if (name == "Classifier") return new AlignClass(name, new ClassifierAligner); if (name == "EtherEncap") return new AlignClass(name, new ShifterAligner(-14)); if (name == "FromDevice" || name == "PollDevice" || name == "FromHost" || name == "SR2SetChecksum" || name == "SR2CheckHeader" || name == "SetSRChecksum" || name == "CheckSRHeader") return new AlignClass(name, new GeneratorAligner(Alignment(4, 2))); if (name == "InfiniteSource" || name == "RatedSource" || name == "ICMPError") return new AlignClass(name, new GeneratorAligner(Alignment(4, 0))); if (name == "ToHost") return new AlignClass(name, new WantAligner(Alignment(4, 2))); if (name == "IPEncap" || name == "UDPIPEncap" || name == "ICMPPingEncap" || name == "RandomUDPIPEncap" || name == "RoundRobinUDPIPEncap" || name == "RoundRobinTCPIPEncap") return new AlignClass(name, new WantAligner(Alignment(4, 0))); if (name == "ARPResponder" || name == "ARPQuerier") return new AlignClass(name, new WantAligner(Alignment(2, 0))); if (name == "IPInputCombo") return new AlignClass(name, new CombinedAligner(new ShifterAligner(14), new WantAligner(Alignment(4, 2)))); if (name == "GridEncap") return new AlignClass(name, new CombinedAligner(new ShifterAligner(98), new WantAligner(Alignment(4, 0)))); if (name == "Idle" || name == "Discard") return new AlignClass(name, new NullAligner); return new AlignClass(name, default_aligner());}#define HELP_OPT 300#define VERSION_OPT 301#define ROUTER_OPT 303#define EXPRESSION_OPT 304#define OUTPUT_OPT 305#define FIRST_DRIVER_OPT 1000#define USERLEVEL_OPT (1000 + Driver::USERLEVEL)#define LINUXMODULE_OPT (1000 + Driver::LINUXMODULE)#define BSDMODULE_OPT (1000 + Driver::BSDMODULE)static const Clp_Option options[] = { { "bsdmodule", 'b', BSDMODULE_OPT, 0, 0 }, { "expression", 'e', EXPRESSION_OPT, Clp_ValString, 0 }, { "file", 'f', ROUTER_OPT, Clp_ValString, 0 }, { "help", 0, HELP_OPT, 0, 0 }, { "linuxmodule", 'l', LINUXMODULE_OPT, 0, 0 }, { "output", 'o', OUTPUT_OPT, Clp_ValString, 0 }, { "userlevel", 'u', USERLEVEL_OPT, 0, 0 }, { "version", 'v', VERSION_OPT, 0, 0 },};static const char *program_name;static int specified_driver = -1;voidshort_usage(){ fprintf(stderr, "Usage: %s [OPTION]... [ROUTERFILE]\n\Try '%s --help' for more information.\n", program_name, program_name);}voidusage(){ printf("\'Click-align' adds any required 'Align' elements to a Click router\n\configuration. The resulting router will work on machines that don't allow\n\unaligned accesses. Its configuration is written to the standard output.\n\\n\Usage: %s [OPTION]... [ROUTERFILE]\n\\n\Options:\n\ -f, --file FILE Read router configuration from FILE.\n\ -e, --expression EXPR Use EXPR as router configuration.\n\ -o, --output FILE Write output to FILE.\n\ --help Print this message and exit.\n\ -v, --version Print version number and exit.\n\\n\Report bugs to <click@pdos.lcs.mit.edu>.\n", program_name);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -