/** * Clone a match object, preparing it to continue from where it left off * @param mt the match to copy * @param log the log to report errors to * @return a copy of mt or NULL on failure */ match *match_clone( match *mt, plugin_log *log ) { match *mt2 = NULL; if ( mt->end.current != NULL ) { mt2 = match_copy( mt, log ); if ( mt2 != NULL ) { // pick up where our parent left off mt2->start = mt->end; mt2->end = mt->end; mt2->len = 0; mt2->maximal = 0; // reset because we are starting again mt2->freq = 0; mt->end = mt->prev; match_pop_versions( mt ); // the queue belongs to mt, not to us if ( mt2->queue != NULL ) { match_state_dispose( mt2->queue ); mt2->queue = NULL; }// this should probably be deleted //mt2->text_off = match_text_end(mt); } } return mt2; }
/** * Make an exact deep copy of a match * @param mt the match to copy * @param log the log to report errors to * @return a copy of mt or NULL on failure */ match *match_copy( match *mt, plugin_log *log ) { match *mt2 = calloc( 1, sizeof(match) ); if ( mt2 != NULL ) { mt2->start = mt->start; mt2->end = mt->end; mt2->prev = mt->prev; if ( mt->prev_bs != NULL ) mt2->prev_bs = bitset_clone( mt->prev_bs ); if ( mt->bs != NULL ) mt2->bs = bitset_clone( mt->bs ); mt2->st_off = mt->st_off; //mt2->text_off = 0; mt2->text_off = mt->text_off; mt2->len = mt->len; mt2->maximal = mt->maximal; mt2->freq = mt->freq; mt2->cards = mt->cards; mt2->st = mt->st; if ( mt->next != NULL ) mt2->next = match_copy( mt->next, log ); if ( mt->queue != NULL ) mt2->queue = match_state_copy(mt->queue,log); mt2->loc = mt->loc; } else plugin_log_add( log, "match: failed to duplicate match object\n"); return mt2; }
static int emit_rule(struct xswitch *sw, struct flow_table *ft, struct trace_tree *tree, struct match *ma, int priority, struct action *ac_pi) { int i; struct trace_tree_L *tl; struct trace_tree_V *tv; struct trace_tree_T *tt; struct trace_tree_D *td; struct trace_tree_G *tg; struct msgbuf *msg; struct match *maa; struct action *a; char buf[128], buf2[128]; struct expr *move_expr; switch(tree->type) { case TT_L: tl = (struct trace_tree_L *)tree; match_dump(ma, buf, 128); action_dump(tl->ac, buf2, 128); xdebug("tid %d: %2d, %s, %s\n", flow_table_get_tid(ft), priority, buf, buf2); if(tl->index == -1) { tl->index = flow_table_get_entry_index(ft); msg = msg_flow_entry_add(ft, tl->index, priority, ma, tl->ac); } else { msg = msg_flow_entry_mod(ft, tl->index, priority, ma, tl->ac); } xswitch_send(sw, msg); return priority + 1; case TT_V: tv = (struct trace_tree_V *)tree; for(i = 0; i < tv->num_branches; i++) { maa = match_copy(ma); match_add(maa, tv->name, tv->branches[i].value, value_from_64(0xffffffffffffffffull)); priority = emit_rule(sw, ft, tv->branches[i].tree, maa, priority, ac_pi); match_free(maa); } return priority; case TT_T: tt = (struct trace_tree_T *)tree; priority = emit_rule(sw, ft, tt->f, ma, priority, ac_pi); maa = match_copy(ma); match_add(maa, tt->name, tt->value, value_from_64(0xffffffffffffffffull)); action_dump(ac_pi, buf, 128); xdebug("tid %d: %2d, BARRIER, %s\n", flow_table_get_tid(ft), priority, buf); if(tt->barrier_index == -1) { tt->barrier_index = flow_table_get_entry_index(ft); msg = msg_flow_entry_add(ft, tt->barrier_index, priority, maa, ac_pi); } else { msg = msg_flow_entry_mod(ft, tt->barrier_index, priority, maa, ac_pi); } xswitch_send(sw, msg); priority = emit_rule(sw, ft, tt->t, maa, priority + 1, ac_pi); match_free(maa); return priority; case TT_G: tg = (struct trace_tree_G *)tree; if(tg->ft == NULL) { int tid = sw->next_table_id++; // add a new table tg->ft = header_make_flow_table(tg->new_spec, tid); msg = msg_flow_table_add(tg->ft); xswitch_send(sw, msg); init_entry(sw, tg->ft); } // insert GOTO_TABLE into orig table a = action(); if(tg->old_spec) move_expr = header_get_length(tg->old_spec); else move_expr = expr_value(0); expr_generate_action(move_expr, tg->old_spec, tg->ft, tg->stack_base, a); match_dump(ma, buf, 128); action_dump(a, buf2, 128); xdebug("tid %d: %2d, %s, %s\n", flow_table_get_tid(ft), priority, buf, buf2); if(tg->index == -1) { tg->index = flow_table_get_entry_index(ft); msg = msg_flow_entry_add(ft, tg->index, priority, ma, a); } else { msg = msg_flow_entry_mod(ft, tg->index, priority, ma, a); } xswitch_send(sw, msg); action_free(a); maa = match(); emit_rule(sw, tg->ft, tg->t, maa, 1, ac_pi); match_free(maa); return priority + 1; case TT_D: td = (struct trace_tree_D *)tree; return emit_rule(sw, ft, td->t, ma, priority, ac_pi); case TT_E: return priority; } assert(0); }
static int json_printer_ft(char *buf, int pos, struct trace_tree *tree, struct match *ma, int *priority, struct action *ac_pi, struct header *h) { int i; struct trace_tree_L *tl; struct trace_tree_V *tv; struct trace_tree_T *tt; struct trace_tree_D *td; struct trace_tree_G *tg; struct match *maa; struct action *a; char buf2[128]; struct expr *move_expr; switch(tree->type) { case TT_L: tl = (struct trace_tree_L *)tree; pos = json_printer_fe(buf, pos, *priority, h, ma, tl->ac); (*priority)++; return pos; case TT_V: tv = (struct trace_tree_V *)tree; for(i = 0; i < tv->num_branches; i++) { maa = match_copy(ma); match_add(maa, tv->name, tv->branches[i].value, value_from_64(0xffffffffffffffffull)); pos = json_printer_ft(buf, pos, tv->branches[i].tree, maa, priority, ac_pi, h); match_free(maa); } return pos; case TT_T: tt = (struct trace_tree_T *)tree; pos = json_printer_ft(buf, pos, tt->f, ma, priority, ac_pi, h); maa = match_copy(ma); match_add(maa, tt->name, tt->value, value_from_64(0xffffffffffffffffull)); pos = json_printer_fe(buf, pos, *priority, h, maa, ac_pi); (*priority)++; pos = json_printer_ft(buf, pos, tt->t, maa, priority, ac_pi, h); match_free(maa); return pos; case TT_G: tg = (struct trace_tree_G *)tree; // insert GOTO_TABLE into orig table a = action(); if(tg->old_spec) move_expr = header_get_length(tg->old_spec); else move_expr = expr_value(0); expr_generate_action(move_expr, tg->old_spec, tg->ft, tg->stack_base, a); action_dump(a, buf2, 128); pos = json_printer_fe(buf, pos, *priority, h, ma, a); action_free(a); (*priority)++; return pos; case TT_D: td = (struct trace_tree_D *)tree; return json_printer_ft(buf, pos, td->t, ma, priority, ac_pi, h); case TT_E: return pos; } assert(0); }