📄 click-fastclassifier.cc
字号:
String step = program.substring(program.begin(), find(program, '\n')); program = program.substring(step.end() + 1, program.end()); // check for many things if (isdigit((unsigned char) step[0]) || isspace((unsigned char) step[0])) { // real step Classifier_Insn e; int crap, pos; int v[4], m[4]; sscanf(step.c_str(), "%d %d/%2x%2x%2x%2x%%%2x%2x%2x%2x yes->%n", &crap, &e.offset, &v[0], &v[1], &v[2], &v[3], &m[0], &m[1], &m[2], &m[3], &pos); for (int i = 0; i < 4; i++) { e.value.c[i] = v[i]; e.mask.c[i] = m[i]; } // read yes destination step = step.substring(pos); if (step[0] == '[') { sscanf(step.c_str(), "[%d] no->%n", &e.yes, &pos); e.yes = -e.yes; } else sscanf(step.c_str(), "step %d no->%n", &e.yes, &pos); // read no destination step = step.substring(pos); if (step[0] == '[') { sscanf(step.c_str(), "[%d]", &e.no); e.no = -e.no; } else sscanf(step.c_str(), "step %d", &e.no); // push expr onto list prog.program.push_back(e); } else if (sscanf(step.c_str(), "all->[%d]", &prog.output_everything)) /* nada */; else if (sscanf(step.c_str(), "safe length %d", &prog.safe_length)) /* nada */; else if (sscanf(step.c_str(), "alignment offset %d", &prog.align_offset)) { /* nada */; } } // search for an existing fast classifier with the same program bool found_program = false; for (int i = 0; i < all_programs.size() && !found_program; i++) if (prog == all_programs[i]) { program_map.push_back(i); found_program = true; } if (!found_program) { // set new names String class_name = "Fast" + classifier_tname + "@@" + c->name(); String cxx_name = translate_class_name(class_name); prog.eclass = ElementClassT::base_type(class_name); // add new program all_programs.push_back(prog); gen_eclass_names.push_back(class_name); gen_cxxclass_names.push_back(cxx_name); old_configurations.push_back(c->configuration()); program_map.push_back(all_programs.size() - 1); } } // complain if any programs missing for (int i = 0; i < iprograms.size(); i++) if (program_map[i] < 0) errh->fatal("classifier program missing for '%s :: %s'!", classifiers[i]->name_c_str(), classifiers[i]->type_name().c_str());}static voidoutput_classifier_program(int which, StringAccum &header, StringAccum &source, ErrorHandler *){ String cxx_name = gen_cxxclass_names[which]; String class_name = gen_eclass_names[which]; const Classifier_Program &prog = all_programs[which]; FastClassifier_Cid *cid = cids[prog.type]; if (cid->headers) { cid->headers(prog, source); cid->headers = 0; // only call cid->headers once } header << "class " << cxx_name << " : public Element {\n\ void devirtualize_all() { }\n\ public:\n " << cxx_name << "() { }\n ~" << cxx_name << "() { }\n\ const char *class_name() const { return \"" << class_name << "\"; }\n\ const char *port_count() const { return \"1/" << prog.noutputs << "\"; }\n\ const char *processing() const { return PUSH; }\n"; if (prog.output_everything >= 0) { header << " void push(int, Packet *);\n};\n"; source << "void\n" << cxx_name << "::push(int, Packet *p)\n{\n"; if (prog.output_everything < prog.noutputs) source << " output(" << prog.output_everything << ").push(p);\n"; else source << " p->kill();\n"; source << "}\n"; } else { bool need_checked = (prog.safe_length >= cid->guaranteed_packet_length); if (need_checked) { header << " void length_checked_push(Packet *);\n"; source << "void\n" << cxx_name << "::length_checked_push(Packet *p)\n{\n"; cid->checked_body(prog, source); source << "}\n"; } header << " inline void length_unchecked_push(Packet *);\n\ void push(int, Packet *);\n};\n"; source << "inline void\n" << cxx_name << "::length_unchecked_push(Packet *p)\n{\n"; cid->unchecked_body(prog, source); source << "}\n"; source << "void\n" << cxx_name << "::push(int, Packet *p)\n{\n"; cid->push_body(prog, source); source << "}\n"; }}static voidcompile_classifiers(RouterT *r, const String &package_name, RouterT *nr, Vector<ElementT *> &classifiers, int compile_drivers, ErrorHandler *errh){ // create C++ files StringAccum header, source, source_body; header << "#ifndef CLICK_" << package_name << "_HH\n" << "#define CLICK_" << package_name << "_HH\n" << "#include <click/package.hh>\n#include <click/element.hh>\n"; // analyze Classifiers into programs analyze_classifiers(nr, classifiers, errh); // add requirement r->add_requirement(package_name); // write Classifier programs for (int i = 0; i < all_programs.size(); i++) output_classifier_program(i, header, source_body, errh); // change element landmarks and types for (int i = 0; i < classifiers.size(); i++) { ElementT *classifier_e = classifiers[i]; const Classifier_Program &prog = all_programs[program_map[i]]; classifier_e->set_type(prog.eclass); classifier_e->set_configuration(String()); change_landmark(classifier_e); } // write final text header << "#endif\n"; source << "/** click-compile: -w */\n"; { StringAccum elem2package, cmd_sa; int nclasses = gen_cxxclass_names.size(); for (int i = 0; i < nclasses; i++) elem2package << "-\t\"" << package_name << ".hh\"\t" << gen_cxxclass_names[i] << '-' << gen_eclass_names[i] << '\n'; cmd_sa << click_buildtool_prog << " elem2package " << package_name; source << shell_command_output_string(cmd_sa.take_string(), elem2package.take_string(), errh); } source << "CLICK_DECLS\n" << source_body << "CLICK_ENDDECLS\n"; // add source files to archive { ArchiveElement ae = init_archive_element(package_name + ".cc", 0600); ae.data = source.take_string(); r->add_archive(ae); ae.name = package_name + ".hh"; ae.data = header.take_string(); r->add_archive(ae); } // add compiled versions to archive if (compile_drivers) { int source_ae = r->archive_index(package_name + ".cc"); BailErrorHandler berrh(errh); bool tmpdir_populated = false; if (compile_drivers & (1 << Driver::LINUXMODULE)) if (String fn = click_compile_archive_file(r->archive(), &r->archive()[source_ae], package_name, "linuxmodule", "", tmpdir_populated, &berrh)) { ArchiveElement ae = init_archive_element(package_name + ".ko", 0600); ae.data = file_string(fn, errh); r->add_archive(ae); } if (compile_drivers & (1 << Driver::USERLEVEL)) if (String fn = click_compile_archive_file(r->archive(), &r->archive()[source_ae], package_name, "userlevel", "", tmpdir_populated, &berrh)) { ArchiveElement ae = init_archive_element(package_name + ".uo", 0600); ae.data = file_string(fn, errh); r->add_archive(ae); } } // add elementmap to archive { String emap_package = "elementmap-" + package_name + ".xml"; if (r->archive_index(emap_package) < 0) r->add_archive(init_archive_element(emap_package, 0600)); ArchiveElement &ae = r->archive(emap_package); ElementMap em(ae.data); ElementTraits t; t.header_file = package_name + ".hh"; t.source_file = package_name + ".cc"; t.processing_code = "h/h"; t.flow_code = "x/x"; for (int i = 0; i < gen_eclass_names.size(); i++) { t.name = gen_eclass_names[i]; t.cxx = gen_cxxclass_names[i]; em.add(t); } ae.data = em.unparse("fastclassifier"); } // add classifier configurations to archive { if (r->archive_index("fastclassifier_info") < 0) r->add_archive(init_archive_element("fastclassifier_info", 0600)); ArchiveElement &ae = r->archive("fastclassifier_info"); StringAccum sa; for (int i = 0; i < gen_eclass_names.size(); i++) { sa << gen_eclass_names[i] << '\t' << cids[all_programs[i].type]->name << '\t' << cp_quote(old_configurations[i]) << '\n'; } ae.data += sa.take_string(); }}static voidreverse_transformation(RouterT *r, ErrorHandler *){ // parse fastclassifier_config if (r->archive_index("fastclassifier_info") < 0) return; ArchiveElement &fc_ae = r->archive("fastclassifier_info"); Vector<String> click_names, old_type_names, configurations; parse_tabbed_lines(fc_ae.data, &click_names, &old_type_names, &configurations, (void *)0); // prepare type_map : type -> configuration # HashTable<ElementClassT *, int> type_map(-1); for (int i = 0; i < click_names.size(); i++) type_map.set(ElementClassT::base_type(click_names[i]), i); // change configuration for (int i = 0; i < r->nelements(); i++) { ElementT *e = r->element(i); int x = type_map.get(e->type()); if (x >= 0) { e->set_configuration(configurations[x]); e->set_type(ElementClassT::base_type(old_type_names[x])); } } // remove requirements { Vector<String> requirements = r->requirements(); for (int i = 0; i < requirements.size(); i++) if (requirements[i].substring(0, 14) == "fastclassifier") r->remove_requirement(requirements[i]); } // remove archive elements for (int i = 0; i < r->narchive(); i++) { ArchiveElement &ae = r->archive(i); if (ae.name.substring(0, 14) == "fastclassifier" || ae.name == "elementmap-fastclassifier.xml") ae.name = String(); }}extern "C" {void add_fast_classifiers_1();void add_fast_classifiers_2();}intmain(int argc, char **argv){ click_static_initialize(); CLICK_DEFAULT_PROVIDES; ErrorHandler *errh = new PrefixErrorHandler(ErrorHandler::default_handler(), "click-fastclassifier: "); // 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; const char *output_file = 0; int compile_drivers = 0; bool combine_classifiers = true; bool do_compile = true; bool source_only = false; bool config_only = false; bool reverse = false; bool file_is_expr = false; while (1) { int opt = Clp_Next(clp); switch (opt) { case HELP_OPT: usage(); exit(0); break; case VERSION_OPT: printf("click-fastclassifier (Click) %s\n", CLICK_VERSION); printf("Copyright (c) 1999-2000 Massachusetts Institute of Technology\n\Copyright (c) 2000-2001 Mazu Networks, Inc.\n\Copyright (c) 2001 International Computer Science Institute\n\Copyright (c) 2007 Regents of the University of California\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 CLICKPATH_OPT: set_clickpath(clp->vstr); break; case ROUTER_OPT: case EXPRESSION_OPT: router_file: if (router_file) { errh->error("router configuration specified twice"); goto bad_option; } router_file = clp->vstr; file_is_expr = (opt == EXPRESSION_OPT); break; case Clp_NotOption: if (!click_maybe_define(clp->vstr, errh)) goto router_file; break; case OUTPUT_OPT: if (output_file) { errh->error("output file specified twice"); goto bad_option; } output_file = clp->vstr; break; case COMBINE_OPT: combine_classifiers = !clp->negated; break; case COMPILE_OPT: do_compile = !clp->negated; break; case REVERSE_OPT: reverse = !clp->negated; break; case SOURCE_OPT: source_only = !clp->negated; break; case CONFIG_OPT: config_only = !clp->negated; break; case KERNEL_OPT: compile_drivers |= 1 << Driver::LINUXMODULE; break; case USERLEVEL_OPT: compile_drivers |= 1 << Driver::USERLEVEL; break; case QUIET_OPT: quiet_arg = (clp->negated ? "" : "-q "); break; case VERBOSE_OPT: verbose = !clp->negated; break; bad_option: case Clp_BadOption: short_usage(); exit(1); break; case Clp_Done: goto done; } } done: RouterT *r = read_router(router_file, file_is_expr, errh); if (r) r->flatten(errh); if (!r || errh->nerrors() > 0) exit(1); if (source_only || config_only) compile_drivers = 0; // open output file FILE *outf = stdout; if (output_file && strcmp(output_file, "-") != 0) { outf = fopen(output_file, "w"); if (!outf) errh->fatal("%s: %s", output_file, strerror(errno)); } // handle reverse case if (reverse) { reverse_transformation(r, errh); write_router_file(r, outf, errh); exit(0); } // install classifier handlers add_interesting_handler("program"); add_fast_classifiers_1(); add_fast_classifiers_2(); // find Click binaries runclick_prog = clickpath_find_file("click", "bin", CLICK_BINDIR, errh); click_buildtool_prog = clickpath_find_file("click-buildtool", "bin", CLICK_BINDIR, errh); // find Classifiers Vector<ElementT *> classifiers; for (RouterT::iterator x = r->begin_elements(); x; x++) if (cid_name_map.get(x->type_name()) >= 0) classifiers.push_back(x); // quit early if no Classifiers if (classifiers.size() == 0) { if (source_only) errh->message("no Classifiers in router"); else write_router_file(r, outf, errh); exit(0); } // try combining classifiers if (combine_classifiers) { bool any_combined = false; for (int i = 0; i < classifiers.size(); i++) any_combined |= try_combine_classifiers(r, classifiers[i]); if (any_combined) try_remove_classifiers(r, classifiers); } // create classifiers program RouterT *classprogr = classifiers_program(r, classifiers); // figure out package name String package_name; { md5_state_t pms; char buf[MD5_TEXT_DIGEST_MAX_SIZE]; String s = classprogr->configuration_string(); md5_init(&pms); md5_append(&pms, (const md5_byte_t *) s.data(), s.length()); int buflen = md5_finish_text(&pms, buf, 0); md5_free(&pms); package_name = "clickfc_" + String(buf, buflen); } if (do_compile) compile_classifiers(r, package_name, classprogr, classifiers, compile_drivers, errh); // write output if (source_only) { if (r->archive_index(package_name + ".hh") < 0) { errh->error("no source code generated"); exit(1); } const ArchiveElement &aeh = r->archive(package_name + ".hh"); const ArchiveElement &aec = r->archive(package_name + ".cc"); ignore_result(fwrite(aeh.data.data(), 1, aeh.data.length(), outf)); ignore_result(fwrite(aec.data.data(), 1, aec.data.length(), outf)); } else if (config_only) { String config = r->configuration_string(); ignore_result(fwrite(config.data(), 1, config.length(), outf)); } else write_router_file(r, outf, errh); exit(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -