📄 click-align.cc
字号:
static const char *program_name;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);}inline Stringaligner_name(int anonymizer){ return String("Align@click_align@") + String(anonymizer);}intmain(int argc, char **argv){ click_static_initialize(); CLICK_DEFAULT_PROVIDES; ErrorHandler *errh = ErrorHandler::default_handler(); // read command line arguments Clp_Parser *clp = Clp_NewParser(argc, argv, sizeof(options) / sizeof(options[0]), options); Clp_SetOptionChar(clp, '+', Clp_ShortNegated); program_name = Clp_ProgramName(clp); const char *router_file = 0; bool file_is_expr = false; const char *output_file = 0; while (1) { int opt = Clp_Next(clp); switch (opt) { case HELP_OPT: usage(); exit(0); break; case VERSION_OPT: printf("click-align (Click) %s\n", CLICK_VERSION); printf("Copyright (C) 1999 Massachusetts Institute of Technology\n\This is free software; see the source for copying conditions.\n\There is NO warranty, not even for merchantability or fitness for a\n\particular purpose.\n"); exit(0); break; case ROUTER_OPT: case EXPRESSION_OPT: case Clp_NotOption: if (router_file) { errh->error("router configuration specified twice"); goto bad_option; } router_file = clp->arg; file_is_expr = (opt == EXPRESSION_OPT); break; case OUTPUT_OPT: if (output_file) { errh->error("output file specified twice"); goto bad_option; } output_file = clp->arg; break; bad_option: case Clp_BadOption: short_usage(); exit(1); break; case Clp_Done: goto done; } } done: prepare_classes(); RouterT *router = read_router(router_file, file_is_expr, errh); if (router) router->flatten(errh); if (!router || errh->nerrors() > 0) exit(1); ElementClassT *align_class = ElementClassT::base_type("Align"); assert(align_class); int original_nelements = router->nelements(); int anonymizer = original_nelements + 1; while (router->eindex(aligner_name(anonymizer)) >= 0) anonymizer++; /* * Add Align elements for required alignments */ int num_aligns_added = 0; { // calculate current alignment RouterAlign ral(router, errh); do { ral.have_output(); } while (ral.have_input()); // calculate desired alignment RouterAlign want_ral(router, errh); do { want_ral.want_input(); } while (want_ral.want_output()); // add required aligns for (int i = 0; i < original_nelements; i++) for (int j = 0; j < ral._icount[i]; j++) { Alignment have = ral._ialign[ ral._ioffset[i] + j ]; Alignment want = want_ral._ialign[ ral._ioffset[i] + j ]; if (have <= want || want.bad()) /* do nothing */; else { ElementT *e = router->get_element (aligner_name(anonymizer), align_class, String(want.chunk()) + ", " + String(want.offset()), "<click-align>"); router->insert_before(e, PortT(router->element(i), j)); anonymizer++; num_aligns_added++; } } } /* * remove duplicate Aligns (Align_1 -> Align_2) */ { const Vector<ConnectionT> &conn = router->connections(); int nhook = conn.size(); for (int i = 0; i < nhook; i++) if (conn[i].live() && conn[i].to_element()->type() == align_class && conn[i].from_element()->type() == align_class) { // skip over hf[i] Vector<PortT> above, below; router->find_connections_to(conn[i].from(), above); router->find_connections_from(conn[i].from(), below); if (below.size() == 1) { for (int j = 0; j < nhook; j++) if (conn[j].to() == conn[i].from()) router->change_connection_to(j, conn[i].to()); } else if (above.size() == 1) { for (int j = 0; j < nhook; j++) if (conn[j].to() == conn[i].to()) router->change_connection_from(j, above[0]); } } } /* * Add Aligns required for adjustment alignments * * Classifier is an example: it can cope with any alignment that is * consistent and has a chunk >= 4. Rather than require a specific alignment * above, we handle Classifier here; required alignments may have generated * an alignment we can deal with. */ { // calculate current alignment RouterAlign ral(router, errh); do { ral.have_output(); } while (ral.have_input()); // calculate adjusted alignment RouterAlign want_ral(ral); want_ral.adjust(); // add required aligns for (int i = 0; i < original_nelements; i++) for (int j = 0; j < ral._icount[i]; j++) { Alignment have = ral._ialign[ ral._ioffset[i] + j ]; Alignment want = want_ral._ialign[ ral._ioffset[i] + j ]; if (have <= want || want.bad()) /* do nothing */; else { ElementT *e = router->get_element (aligner_name(anonymizer), align_class, String(want.chunk()) + ", " + String(want.offset()), "<click-align>"); router->insert_before(e, PortT(router->element(i), j)); anonymizer++; num_aligns_added++; } } } while (1) { // calculate current alignment RouterAlign ral(router, errh); do { ral.have_output(); } while (ral.have_input()); bool changed = false; // skip redundant Aligns const Vector<ConnectionT> &conn = router->connections(); int nhook = conn.size(); for (int i = 0; i < nhook; i++) if (conn[i].live() && conn[i].to_element()->type() == align_class) { Alignment have = ral._oalign[ ral._ooffset[conn[i].from_eindex()] + conn[i].from_port() ]; Alignment want = ral._oalign[ ral._ooffset[conn[i].to_eindex()] ]; if (have <= want) { changed = true; Vector<PortT> align_dest; router->find_connections_from(conn[i].to(), align_dest); for (int j = 0; j < align_dest.size(); j++) router->add_connection(conn[i].from(), align_dest[j]); router->kill_connection(i); } } if (!changed) break; router->remove_duplicate_connections(); } // remove unused Aligns (they have no input) and old AlignmentInfos ElementClassT *aligninfo_class = ElementClassT::base_type("AlignmentInfo"); { for (RouterT::iterator x = router->begin_elements(); x; x++) if (x->type() == align_class && (x->ninputs() == 0 || x->noutputs() == 0)) { x->kill(); num_aligns_added--; } else if (x->type() == aligninfo_class) x->kill(); router->remove_dead_elements(); } // make the AlignmentInfo element { RouterAlign ral(router, errh); do { ral.have_output(); } while (ral.have_input()); // collect alignment information, delete old AlignmentInfos StringAccum sa; for (RouterT::iterator x = router->begin_elements(); x; x++) { if (sa.length()) sa << ",\n "; sa << x->name(); int i = x->eindex(); for (int j = 0; j < ral._icount[i]; j++) { const Alignment &a = ral._ialign[ ral._ioffset[i] + j ]; sa << " " << a.chunk() << " " << a.offset(); } } router->get_element(String("AlignmentInfo@click_align@") + String(router->nelements() + 1), aligninfo_class, sa.take_string(), "<click-align>"); } // warn if added aligns if (num_aligns_added > 0) errh->warning((num_aligns_added > 1 ? "added %d Align elements" : "added %d Align element"), num_aligns_added); // write result if (write_router_file(router, output_file, errh) < 0) exit(1); return 0;}// generate Vector template instance#include <click/vector.cc>template class Vector<Alignment>;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -