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

📄 classifier.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
📖 第 1 页 / 共 4 页
字号:
  assert(start.size() == end.size() && start.size() > 1);  if (in[end[0] - 1] <= 0) {    int s = in[end[0] - 1];    for (int j = 1; j < start.size(); j++)      if (in[end[j] - 1] != s)	goto not_end;    return s;  } not_end:  Vector<int> intersection;  intersect_lists(in, start, end, 0, start.size(), intersection);  return intersection.back();}voidClassifier::DominatorOptimizer::shift_branch(int brno){  // shift a branch by examining its dominators    int s = stateno(brno);  int &to_state = (br(brno) ? expr(s).yes : expr(s).no);  if (to_state <= 0)    return;  if (_domlist_start[s] + 1 == _domlist_start[s+1]) {    // single domlist; faster algorithm    int d = _domlist_start[s];    to_state = dom_shift_branch(brno, to_state, _dom_start[d], _dom_start[d+1], 0);  } else {    Vector<int> vals, start, end;    for (int d = _domlist_start[s]; d < _domlist_start[s+1]; d++) {      start.push_back(vals.size());      (void) dom_shift_branch(brno, to_state, _dom_start[d], _dom_start[d+1], &vals);      end.push_back(vals.size());    }    to_state = last_common_state_in_lists(vals, start, end);  }}voidClassifier::DominatorOptimizer::run(int state){  assert(_domlist_start.size() == state + 1);  calculate_dom(state);  shift_branch(brno(state, true));  shift_branch(brno(state, false));}// OPTIMIZATIONboolClassifier::remove_unused_states(){  // Remove uninteresting exprs  int first = 0;  for (int i = 0; _output_everything < 0 && i < _exprs.size(); i++) {    Expr &e = _exprs[i];    int next = e.yes;    if (e.yes == e.no || e.mask.u == 0) {      if (i == first && next <= 0)	_output_everything = e.yes;      else {	for (int j = 0; j < i; j++) {	  Expr &ee = _exprs[j];	  if (ee.yes == i) ee.yes = next;	  if (ee.no == i) ee.no = next;	}	if (i == 0) first = next;      }    }  }  if (_output_everything < 0 && first > 0)    _exprs[0] = _exprs[first];  // Remove unreachable states  for (int i = 1; i < _exprs.size(); i++) {    for (int j = 0; j < i; j++)	// all branches are forward      if (_exprs[j].yes == i || _exprs[j].no == i)	goto done;    // if we get here, the state is unused    for (int j = i+1; j < _exprs.size(); j++)      _exprs[j-1] = _exprs[j];    _exprs.pop_back();    for (int j = 0; j < _exprs.size(); j++) {      if (_exprs[j].yes >= i) _exprs[j].yes--;      if (_exprs[j].no >= i) _exprs[j].no--;    }    i--;			// shifted downward, so must reconsider `i'   done: ;  }  // Get rid of bad branches  Vector<int> failure_states(_exprs.size(), FAILURE);  bool changed = false;  for (int i = _exprs.size() - 1; i >= 0; i--) {    Expr &e = _exprs[i];    if (e.yes > 0 && failure_states[e.yes] != FAILURE) {      e.yes = failure_states[e.yes];      changed = true;    }    if (e.no > 0 && failure_states[e.no] != FAILURE) {      e.no = failure_states[e.no];      changed = true;    }    if (e.yes == FAILURE)      failure_states[i] = e.no;    else if (e.no == FAILURE)      failure_states[i] = e.yes;  }  return changed;}voidClassifier::combine_compatible_states(){  for (int i = 0; i < _exprs.size(); i++) {    Expr &e = _exprs[i];    if (e.no > 0 && _exprs[e.no].compatible(e) && e.flippable())      e.flip();    if (e.yes <= 0)      continue;    Expr &ee = _exprs[e.yes];    if (e.no == ee.yes && ee.flippable())      ee.flip();    if (e.no == ee.no && ee.compatible(e)) {      e.yes = ee.yes;      if (!e.mask.u)		// but probably ee.mask.u is always != 0...	e.offset = ee.offset;      e.value.u = (e.value.u & e.mask.u) | (ee.value.u & ee.mask.u);      e.mask.u |= ee.mask.u;      i--;    }  }}voidClassifier::bubble_sort_and_exprs(int sort_stopper){  // count inbranches  Vector<int> inbranch(_exprs.size(), -1);  for (int i = 0; i < _exprs.size(); i++) {    Expr &e = _exprs[i];    if (e.yes > 0)      inbranch[e.yes] = (inbranch[e.yes] >= 0 ? 0 : i);    if (e.no > 0)      inbranch[e.no] = (inbranch[e.no] >= 0 ? 0 : i);  }  // do bubblesort  for (int i = 0; i < _exprs.size(); i++)    if (_exprs[i].yes > 0) {      int j = _exprs[i].yes;      Expr &e1 = _exprs[i], &e2 = _exprs[j];      if (e1.no == e2.no && e1.offset > e2.offset && e1.offset < sort_stopper	  && inbranch[j] > 0) {	Expr temp(e2);	e2 = e1;	e2.yes = temp.yes;	e1 = temp;	e1.yes = j;	// step backwards to continue the sort	i = (inbranch[i] > 0 ? inbranch[i] - 1 : i - 1);      }    }}voidClassifier::optimize_exprs(ErrorHandler *errh, int sort_stopper){  // sort 'and' expressions  bubble_sort_and_exprs(sort_stopper);    //{ String sxxx = program_string(this, 0); click_chatter("%s", sxxx.cc()); }  // optimize using dominators  {    DominatorOptimizer dom(this);    for (int i = 0; i < _exprs.size(); i++)      dom.run(i);    //dom.print();    combine_compatible_states();    (void) remove_unused_states();  }    //{ String sxxx = program_string(this, 0); click_chatter("%s", sxxx.cc()); }    // Check for case where all patterns have conflicts: _exprs will be empty  // but _output_everything will still be < 0. We require that, when _exprs  // is empty, _output_everything is >= 0.  if (_exprs.size() == 0 && _output_everything < 0)    _output_everything = noutputs();  else if (_output_everything >= 0)    _exprs.clear();  // Calculate _safe_length  _safe_length = 0;  for (int i = 0; i < _exprs.size(); i++) {    unsigned off = _exprs[i].offset + UBYTES;    for (int j = 3; j >= 0; j--, off--)      if (_exprs[i].mask.c[j])	break;    if (off > _safe_length)      _safe_length = off;  }  _safe_length -= _align_offset;  // Warn on patterns that can't match anything  Vector<int> used_patterns(noutputs() + 1, 0);  if (_output_everything >= 0)    used_patterns[_output_everything] = 1;  else    for (int i = 0; i < _exprs.size(); i++) {      if (_exprs[i].yes <= 0) used_patterns[-_exprs[i].yes] = 1;      if (_exprs[i].no <= 0) used_patterns[-_exprs[i].no] = 1;    }  for (int i = 0; i < noutputs(); i++)    if (!used_patterns[i])      errh->warning("pattern %d matches no packets", i);  //{ String sxxx = program_string(this, 0); click_chatter("%s", sxxx.cc()); }}//// CONFIGURATION//voidClassifier::init_expr_subtree(Vector<int> &tree){  assert(!tree.size());  tree.push_back(0);}voidClassifier::add_expr(Vector<int> &tree, const Expr &e){  _exprs.push_back(e);  Expr &ee = _exprs.back();  ee.yes = SUCCESS;  ee.no = FAILURE;  int level = tree[0];  tree.push_back(level);}voidClassifier::add_expr(Vector<int> &tree, int offset, uint32_t value, uint32_t mask){  Expr e;  e.offset = offset;  e.value.u = value & mask;  e.mask.u = mask;  add_expr(tree, e);}voidClassifier::start_expr_subtree(Vector<int> &tree){  tree[0]++;}voidClassifier::redirect_expr_subtree(int first, int last, int success, int failure){  for (int i = first; i < last; i++) {    Expr &e = _exprs[i];    if (e.yes == SUCCESS)      e.yes = success;    else if (e.yes == FAILURE)      e.yes = failure;    if (e.no == SUCCESS)      e.no = success;    else if (e.no == FAILURE)      e.no = failure;  }}voidClassifier::finish_expr_subtree(Vector<int> &tree, Combiner combiner,				int success, int failure){  int level = tree[0];  // 'subtrees' contains pointers to trees at level 'level'  Vector<int> subtrees;  {    // move backward to parent subtree    int ptr = _exprs.size();    while (ptr > 0 && (tree[ptr] < 0 || tree[ptr] >= level))      ptr--;    // collect child subtrees    for (ptr++; ptr <= _exprs.size(); ptr++)      if (tree[ptr] == level)	subtrees.push_back(ptr - 1);  }  if (subtrees.size()) {    // combine subtrees    // first mark all subtrees as next higher level    tree[subtrees[0] + 1] = level - 1;    for (int e = subtrees[0] + 2; e <= _exprs.size(); e++)      tree[e] = -1;    // loop over expressions    int t;    for (t = 0; t < subtrees.size() - 1; t++) {      int first = subtrees[t];      int next = subtrees[t+1];      if (combiner == C_AND)	redirect_expr_subtree(first, next, next, failure);      else if (combiner == C_OR)	redirect_expr_subtree(first, next, success, next);      else if (combiner == C_TERNARY) {	if (t < subtrees.size() - 2) {	  int next2 = subtrees[t+2];	  redirect_expr_subtree(first, next, next, next2);	  redirect_expr_subtree(next, next2, success, failure);	  t++;	} else			// like C_AND	  redirect_expr_subtree(first, next, next, failure);      } else	redirect_expr_subtree(first, next, success, failure);    }    if (t < subtrees.size()) {      assert(t == subtrees.size() - 1);      redirect_expr_subtree(subtrees[t], _exprs.size(), success, failure);    }  }  tree[0]--;}voidClassifier::negate_expr_subtree(Vector<int> &tree){  // swap 'SUCCESS' and 'FAILURE' within the last subtree  int level = tree[0];  int first = _exprs.size() - 1;  while (first >= 0 && tree[first+1] != level)    first--;  for (int i = first; i < _exprs.size(); i++) {    Expr &e = _exprs[i];    if (e.yes == FAILURE)      e.yes = SUCCESS;    else if (e.yes == SUCCESS)      e.yes = FAILURE;    if (e.no == FAILURE)      e.no = SUCCESS;    else if (e.no == SUCCESS)      e.no = FAILURE;  }}static voidupdate_value_mask(int c, int shift, int &value, int &mask){  int v = 0, m = 0xF;  if (c == '?')    v = m = 0;  else if (c >= '0' && c <= '9')    v = c - '0';  else if (c >= 'A' && c <= 'F')    v = c - 'A' + 10;  else if (c >= 'a' && c <= 'f')    v = c - 'a' + 10;  value |= (v << shift);  mask |= (m << shift);}intClassifier::configure(Vector<String> &conf, ErrorHandler *errh){  set_noutputs(conf.size());    int before = errh->nerrors();  // set align offset  {    int c, o;    if (AlignmentInfo::query(this, 0, c, o) && c >= 4)      // want `data - _align_offset' aligned at 4/(o%4)      _align_offset = (4 - (o % 4)) % 4;    else {#ifndef __i386__      errh->error("no AlignmentInfo available: you may experience unaligned accesses");#endif      _align_offset = 0;    }  }    Vector<int> tree;  init_expr_subtree(tree);  start_expr_subtree(tree);    for (int slot = 0; slot < conf.size(); slot++) {    int i = 0;    int len = conf[slot].length();    const char *s = conf[slot].data();    int slot_branch = _exprs.size();    Vector<Expr> slot_exprs;    start_expr_subtree(tree);    if (s[0] == '-' && len == 1)      // slot accepting everything      i = 1;        while (i < len) {            while (i < len && isspace(s[i]))	i++;      if (i >= len) break;      start_expr_subtree(tree);            // negated?      bool negated = false;      if (s[i] == '!') {	negated = true;

⌨️ 快捷键说明

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