struct t_value * exec_i_assign(struct t_exec *exec, struct t_icode *icode) { struct t_var *var; struct t_value *ret = NULL; struct t_value *opnd1, *opnd2; debug(2, "%s(): Begin\n", __FUNCTION__); opnd2 = list_pop(&exec->stack); assert(opnd2); opnd1 = list_pop(&exec->stack); assert(opnd1); debug(3, "%s(): Got operands from stack\n", __FUNCTION__); if (opnd2->type == VAL_VAR) { debug(3, "%s(): Fetching value for opnd2\n", __FUNCTION__); var = var_lookup(exec, opnd2->name); opnd2 = var->value; assert(opnd2); } if (opnd1->type != VAL_VAR) { fprintf(stderr, "Left side of assignment must be a variable. Got %s=%d instead.\n", value_types[opnd1->type], opnd1->intval); return NULL; } debug(3, "%s(): Looking up opnd1 var name=%s\n", __FUNCTION__, opnd1->name); var = var_lookup(exec, opnd1->name); if (var) { if (var->value->type != opnd2->type) { fprintf(stderr, "Type mismatch when assigning new value: %s = %s\n", opnd1->name, value_types[opnd2->type]); return NULL; } } else { var = var_new(opnd1->name, opnd2); list_push(&exec->vars, var); } debug(3, "%s(): Copying value to variable\n", __FUNCTION__); if (var->value->type == VAL_INT) { var->value->intval = opnd2->intval; ret = create_num_from_int(var->value->intval); list_push(&exec->values, ret); debug(3, "%s(): New int val: %d\n", __FUNCTION__, ret->intval); } else if (var->value->type == VAL_STRING) { var->value->stringval = opnd2->stringval; ret = var->value; debug(3, "%s(): Assigned string: %s\n", __FUNCTION__, ret->stringval); } else { fprintf(stderr, "Don't know how to assign %s type value\n", value_types[opnd2->type]); return NULL; } list_push(&exec->stack, ret); return ret; }
var_t *var_add(var_table_t *hashtable, char *str, BYTE type, block_t *parent) { var_t *new_list; var_t *current_list; unsigned int hashval = var_hash(hashtable, str); if ((new_list = malloc(sizeof(var_t))) == NULL) return NULL; current_list = var_lookup(hashtable, str); /* item already exists, dont insert it again. */ if (current_list != NULL) return current_list; // NULL; /* Insert into list */ new_list->v.data = NULL; new_list->v.data_size = 0; new_list->v.name = strdup(str); new_list->v.type = type; // TODO: figure out shit with level new_list->v.level = 0; new_list->parent = parent; new_list->next = hashtable->table[hashval]; hashtable->table[hashval] = new_list; return new_list; }
inline struct var * var_lookup(struct var *tree, char *key) { if (!tree) return NULL; if (strcmp(tree->name, key) == 0) return tree; return var_lookup((strcmp(tree->name, key) > 0) ? tree->left : tree-> right, key); }
int var_fetch_int(char *var_name) { struct var *v = var_lookup(vars, var_name); if ( v == NULL ) return 0; switch ( v->type ) { case int_t: return v->value.i; case string_t: return 0; case mu: return 0; } return 0; }
/* Synchronizes var with vars[] if necessary Var is NOT modified */ void var_sync(bombyx_env_t *env, var *a) { if (a->ref) { op_copy(env, &(a->ref)->v, a); } else if (a->name) { var_t *vt = var_lookup(env->vars, a->name); if (vt) { op_copy(env, &vt->v, a); } else { runtime_error(env, "Variable '%s' not found.", a->name); } } }
/* retrieve a variable's contents, and make a string if need be */ char * var_fetch(char *var_name) { struct var *v = var_lookup(vars, var_name); if (v) { char *foo; switch (v->type) { case mu: fprintf( stderr, "var_fetch: unhandled var type\n" ); exit( -1 ); case string_t: return v->value.s; case int_t: foo = (char *) malloc(16); sprintf(foo, "%i", v->value.i); return foo; } } return NULL; }
static int parse_single_var(char *val, size_t len, const char *name) { struct var *match; match = var_lookup(name); if (match) { if (strlen(match->val) + 1 > len) { set_errf("Variables '%s' with value '%s' is too long\n", match->name, match->val); return -1; } strncpy(val, match->val, len); return 0; } else { /* name + 1 to skip leading '$' */ if (lua_to_string(prox_lua(), GLOBAL, name + 1, val, len) >= 0) return 0; } set_errf("Variable '%s' not defined!", name); return 1; }
type_t var_type(struct var * tree, char *key) { struct var *v = var_lookup(tree, key); return v ? v->type : mu; }
struct t_value * exec_icode(struct t_exec *exec, struct t_icode *icode) { struct t_value *ret; struct t_value *opnd1, *opnd2; struct t_value *val1, *val2; struct t_icode_op op; struct t_var *var; debug(1, "%s(): Executing icode addr=%d: %s\n", __FUNCTION__, icode->addr, format_icode(&exec->parser, icode)); if (icode->type < 0 || icode->type >= operations_len) { fprintf(stderr, "Invalid operation type (value=%d)\n", icode->type); return NULL; } op = operations[icode->type]; if (op.opnd_count == 0) { ret = op.op0(exec, icode); } else if (op.opnd_count == 1) { opnd1 = list_pop(&exec->stack); assert(opnd1); if (opnd1->type == VAL_VAR) { var = var_lookup(exec, opnd1->name); val1 = var->value; assert(opnd1); } else { val1 = opnd1; } ret = op.op1(exec, icode, val1); list_push(&exec->stack, ret); } else if (op.opnd_count == 2) { opnd2 = list_pop(&exec->stack); assert(opnd2); opnd1 = list_pop(&exec->stack); assert(opnd1); if (opnd1->type == VAL_VAR) { var = var_lookup(exec, opnd1->name); val1 = var->value; assert(val1); } else { val1 = opnd1; } if (opnd2->type == VAL_VAR) { var = var_lookup(exec, opnd2->name); val2 = var->value; assert(val2); } else { val2 = opnd2; } ret = op.op2(exec, icode, val1, val2); list_push(&exec->stack, ret); } else { fprintf(stderr, "Invalid number of operations (%d) for op '%s'\n", op.opnd_count, icodes[icode->type]); return NULL; } return ret; }
static char * exec_instr( pInstr s ) { pCell tc, tc2; char buffer[16]; switch (s->opcode) { case SET: /* operand must be a string */ tc = temp_pop(); switch (tc->type) { case mu: fprintf(stderr, "exec_inst/SET: warning - unhandled case mu\n" ); break; case string_t: var_put(s->operand.contents.s, tc->contents.s); break; case int_t: var_put_int(s->operand.contents.s, tc->contents.i); break; } break; case EMIT: tc = temp_pop(); switch (tc->type) { case mu: fprintf(stderr, "exec_inst/EMIT: warning - unhandled case mu\n" ); break; case string_t: return tc->contents.s; case int_t: sprintf(buffer, "%i", tc->contents.i); return strdup(buffer); } case PUSHV: { struct var *v = var_lookup(vars, s->operand.contents.s); if (v == 0) { fprintf(stderr, "attempted to use unknown variable \"%s\" in expression.\n", s->operand.contents.s); push_str("(NULL)"); } else { switch (v->type) { case mu: fprintf(stderr, "exec_inst/PUSHV: warning - unhandled case mu\n" ); break; case string_t: push_str(strdup(v->value.s)); break; case int_t: push_int(v->value.i); break; } } } break; case INVOKE: { pRule r = rule_find(rule_base, s->operand.contents.s); if (r) { push_str(resolve_rule(rule_base, r)); } else { fprintf(stderr, "attempted to invoke non-existent rule \"%s\" in expression.\n", s->operand.contents.s); push_str(NULL); } } break; case PUSH: switch (s->operand.type) { case mu: fprintf(stderr, "exec_inst/PUSH: warning - unhandled case mu\n" ); break; case string_t: push_str(strdup(s->operand.contents.s)); break; case int_t: push_int(s->operand.contents.i); break; } break; case ADD: tc = temp_pop(); tc2 = temp_pop(); if ((tc->type == int_t) && (tc2->type == int_t)) { push_int(tc->contents.i + tc2->contents.i); } else { char *s0, *s1; /* string concatenation */ s0 = ((tc->type == int_t) ? itoa(tc->contents.i) : (tc->contents.s)); s1 = ((tc2->type == int_t) ? itoa(tc2->contents.i) : (tc2->contents.s)); push_str(concat(s1, s0)); free(s0); free(s1); } break; case SUB: tc = temp_pop(); tc2 = temp_pop(); if ((tc->type == int_t) && (tc2->type == int_t)) { push_int(tc2->contents.i + tc->contents.i); } break; case MUL: tc = temp_pop(); tc2 = temp_pop(); if ((tc->type == int_t) && (tc2->type == int_t)) { push_int(tc->contents.i * tc2->contents.i); } break; case DIV: tc = temp_pop(); tc2 = temp_pop(); if ((tc->type == int_t) && (tc2->type == int_t)) { push_int(tc2->contents.i / tc->contents.i); } break; case MOD: tc = temp_pop(); tc2 = temp_pop(); if ((tc->type == int_t) && (tc2->type == int_t)) { push_int(tc2->contents.i % tc->contents.i); } break; case RANDOM: tc2 = temp_pop(); tc = temp_pop(); if ((tc->type == int_t) && (tc2->type == int_t)) { push_int((ranq1() % (tc2->contents.i - tc->contents.i + 1)) + tc->contents.i); } break; case LESSER: tc2 = temp_pop(); tc = temp_pop(); if ((tc->type == int_t) && (tc2->type == int_t)) { push_int(min(tc->contents.i, tc2->contents.i)); } break; case GREATER: tc2 = temp_pop(); tc = temp_pop(); if ((tc->type == int_t) && (tc2->type == int_t)) { push_int(max(tc->contents.i, tc2->contents.i)); } break; } return NULL; }
void StreamVm::build_program(){ /* build the commands into a buffer */ m_instructions.clear(); int var_cnt=0; clean_max_field_cnt(); uint32_t ins_id=0; for (auto inst : m_inst_list) { StreamVmInstruction::instruction_type_t ins_type=inst->get_instruction_type(); /* itFIX_IPV4_CS */ if (ins_type == StreamVmInstruction::itFIX_IPV4_CS) { StreamVmInstructionFixChecksumIpv4 *lpFix =(StreamVmInstructionFixChecksumIpv4 *)inst; if ( (lpFix->m_pkt_offset + IPV4_HDR_LEN) > m_pkt_size ) { std::stringstream ss; ss << "instruction id '" << ins_id << "' fix ipv4 command offset " << lpFix->m_pkt_offset << " is too high relative to packet size "<< m_pkt_size; err(ss.str()); } uint16_t offset_next_layer = IPV4_HDR_LEN; if ( m_pkt ){ IPHeader * ipv4= (IPHeader *)(m_pkt+lpFix->m_pkt_offset); offset_next_layer = ipv4->getSize(); } if (offset_next_layer<IPV4_HDR_LEN) { offset_next_layer=IPV4_HDR_LEN; } if ( (lpFix->m_pkt_offset + offset_next_layer) > m_pkt_size ) { std::stringstream ss; ss << "instruction id '" << ins_id << "' fix ipv4 command offset " << lpFix->m_pkt_offset << "plus "<<offset_next_layer<< " is too high relative to packet size "<< m_pkt_size; err(ss.str()); } /* calculate this offset from the packet */ add_field_cnt(lpFix->m_pkt_offset + offset_next_layer); StreamDPOpIpv4Fix ipv_fix; ipv_fix.m_offset = lpFix->m_pkt_offset; ipv_fix.m_op = StreamDPVmInstructions::ditFIX_IPV4_CS; m_instructions.add_command(&ipv_fix,sizeof(ipv_fix)); } /* flow man */ if (ins_type == StreamVmInstruction::itFLOW_MAN) { StreamVmInstructionFlowMan *lpMan =(StreamVmInstructionFlowMan *)inst; var_cnt++; if (lpMan->m_size_bytes == 1 ){ if ( (lpMan->m_step == 1) || (lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ) ){ uint8_t op=StreamDPVmInstructions::ditINC8; if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){ op = StreamDPVmInstructions::ditINC8 ; } if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){ op = StreamDPVmInstructions::ditDEC8 ; } if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ){ op = StreamDPVmInstructions::ditRANDOM8 ; } StreamDPOpFlowVar8 fv8; fv8.m_op = op; fv8.m_flow_offset = get_var_offset(lpMan->m_var_name); fv8.m_min_val = (uint8_t)lpMan->m_min_value; fv8.m_max_val = (uint8_t)lpMan->m_max_value; m_instructions.add_command(&fv8,sizeof(fv8)); }else{ uint8_t op=StreamDPVmInstructions::ditINC8_STEP; if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){ op = StreamDPVmInstructions::ditINC8_STEP ; } if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){ op = StreamDPVmInstructions::ditDEC8_STEP ; } StreamDPOpFlowVar8Step fv8; fv8.m_op = op; fv8.m_flow_offset = get_var_offset(lpMan->m_var_name); fv8.m_min_val = (uint8_t)lpMan->m_min_value; fv8.m_max_val = (uint8_t)lpMan->m_max_value; fv8.m_step = (uint8_t)lpMan->m_step; m_instructions.add_command(&fv8,sizeof(fv8)); } } if (lpMan->m_size_bytes == 2 ){ uint8_t op; if ( (lpMan->m_step == 1) || (lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ) ){ op = StreamDPVmInstructions::ditINC16; if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){ op = StreamDPVmInstructions::ditINC16 ; } if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){ op = StreamDPVmInstructions::ditDEC16 ; } if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ){ op = StreamDPVmInstructions::ditRANDOM16 ; } StreamDPOpFlowVar16 fv16; fv16.m_op = op; fv16.m_flow_offset = get_var_offset(lpMan->m_var_name); fv16.m_min_val = (uint16_t)lpMan->m_min_value; fv16.m_max_val = (uint16_t)lpMan->m_max_value; m_instructions.add_command(&fv16,sizeof(fv16)); }else{ op = StreamDPVmInstructions::ditINC16_STEP; if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){ op = StreamDPVmInstructions::ditINC16_STEP ; } if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){ op = StreamDPVmInstructions::ditDEC16_STEP ; } StreamDPOpFlowVar16Step fv16; fv16.m_op = op; fv16.m_flow_offset = get_var_offset(lpMan->m_var_name); fv16.m_min_val = (uint16_t)lpMan->m_min_value; fv16.m_max_val = (uint16_t)lpMan->m_max_value; fv16.m_step = (uint16_t)lpMan->m_step; m_instructions.add_command(&fv16,sizeof(fv16)); } } if (lpMan->m_size_bytes == 4 ){ uint8_t op; if ( (lpMan->m_step == 1) || (lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ) ){ op = StreamDPVmInstructions::ditINC32; if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){ op = StreamDPVmInstructions::ditINC32 ; } if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){ op = StreamDPVmInstructions::ditDEC32 ; } if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ){ op = StreamDPVmInstructions::ditRANDOM32 ; } StreamDPOpFlowVar32 fv32; fv32.m_op = op; fv32.m_flow_offset = get_var_offset(lpMan->m_var_name); fv32.m_min_val = (uint32_t)lpMan->m_min_value; fv32.m_max_val = (uint32_t)lpMan->m_max_value; m_instructions.add_command(&fv32,sizeof(fv32)); }else{ op = StreamDPVmInstructions::ditINC32_STEP; if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){ op = StreamDPVmInstructions::ditINC32_STEP ; } if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){ op = StreamDPVmInstructions::ditDEC32_STEP ; } StreamDPOpFlowVar32Step fv32; fv32.m_op = op; fv32.m_flow_offset = get_var_offset(lpMan->m_var_name); fv32.m_min_val = (uint32_t)lpMan->m_min_value; fv32.m_max_val = (uint32_t)lpMan->m_max_value; fv32.m_step = (uint32_t)lpMan->m_step; m_instructions.add_command(&fv32,sizeof(fv32)); } } if (lpMan->m_size_bytes == 8 ){ uint8_t op; if ( (lpMan->m_step == 1) || (lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ) ){ op = StreamDPVmInstructions::ditINC64; if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){ op = StreamDPVmInstructions::ditINC64 ; } if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){ op = StreamDPVmInstructions::ditDEC64 ; } if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM ){ op = StreamDPVmInstructions::ditRANDOM64 ; } StreamDPOpFlowVar64 fv64; fv64.m_op = op; fv64.m_flow_offset = get_var_offset(lpMan->m_var_name); fv64.m_min_val = (uint64_t)lpMan->m_min_value; fv64.m_max_val = (uint64_t)lpMan->m_max_value; m_instructions.add_command(&fv64,sizeof(fv64)); }else{ op = StreamDPVmInstructions::ditINC64_STEP; if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_INC ){ op = StreamDPVmInstructions::ditINC64_STEP ; } if ( lpMan->m_op == StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC ){ op = StreamDPVmInstructions::ditDEC64_STEP ; } StreamDPOpFlowVar64Step fv64; fv64.m_op = op; fv64.m_flow_offset = get_var_offset(lpMan->m_var_name); fv64.m_min_val = (uint64_t)lpMan->m_min_value; fv64.m_max_val = (uint64_t)lpMan->m_max_value; fv64.m_step = (uint64_t)lpMan->m_step; m_instructions.add_command(&fv64,sizeof(fv64)); } } } if (ins_type == StreamVmInstruction::itPKT_WR) { StreamVmInstructionWriteToPkt *lpPkt =(StreamVmInstructionWriteToPkt *)inst; VmFlowVarRec var; if ( var_lookup(lpPkt->m_flow_var_name ,var) == false){ std::stringstream ss; ss << "instruction id '" << ins_id << "' packet write with no valid flow varible name '" << lpPkt->m_flow_var_name << "'" ; err(ss.str()); } if (lpPkt->m_pkt_offset + var.m_size_bytes > m_pkt_size ) { std::stringstream ss; ss << "instruction id '" << ins_id << "' packet write with packet_offset " << lpPkt->m_pkt_offset + var.m_size_bytes << " bigger than packet size "<< m_pkt_size; err(ss.str()); } add_field_cnt(lpPkt->m_pkt_offset + var.m_size_bytes); uint8_t op_size=var.m_size_bytes; bool is_big = lpPkt->m_is_big_endian; uint8_t flags = (is_big?StreamDPOpPktWrBase::PKT_WR_IS_BIG:0); uint8_t flow_offset = get_var_offset(lpPkt->m_flow_var_name); if (op_size == 1) { StreamDPOpPktWr8 pw8; pw8.m_op = StreamDPVmInstructions::itPKT_WR8; pw8.m_flags =flags; pw8.m_offset =flow_offset; pw8.m_pkt_offset = lpPkt->m_pkt_offset; pw8.m_val_offset = (int8_t)lpPkt->m_add_value; m_instructions.add_command(&pw8,sizeof(pw8)); } if (op_size == 2) { StreamDPOpPktWr16 pw16; pw16.m_op = StreamDPVmInstructions::itPKT_WR16; pw16.m_flags =flags; pw16.m_offset =flow_offset; pw16.m_pkt_offset = lpPkt->m_pkt_offset; pw16.m_val_offset = (int16_t)lpPkt->m_add_value; m_instructions.add_command(&pw16,sizeof(pw16)); } if (op_size == 4) { StreamDPOpPktWr32 pw32; pw32.m_op = StreamDPVmInstructions::itPKT_WR32; pw32.m_flags =flags; pw32.m_offset =flow_offset; pw32.m_pkt_offset = lpPkt->m_pkt_offset; pw32.m_val_offset = (int32_t)lpPkt->m_add_value; m_instructions.add_command(&pw32,sizeof(pw32)); } if (op_size == 8) { StreamDPOpPktWr64 pw64; pw64.m_op = StreamDPVmInstructions::itPKT_WR64; pw64.m_flags =flags; pw64.m_offset =flow_offset; pw64.m_pkt_offset = lpPkt->m_pkt_offset; pw64.m_val_offset = (int64_t)lpPkt->m_add_value; m_instructions.add_command(&pw64,sizeof(pw64)); } } if (ins_type == StreamVmInstruction::itPKT_WR_MASK) { StreamVmInstructionWriteMaskToPkt *lpPkt =(StreamVmInstructionWriteMaskToPkt *)inst; VmFlowVarRec var; uint8_t cast_size = lpPkt->m_pkt_cast_size; if (!((cast_size==4)||(cast_size==2)||(cast_size==1))){ std::stringstream ss; ss << "instruction id '" << ins_id << " cast size should be 1,2,4 it is "<<lpPkt->m_pkt_cast_size; err(ss.str()); } if ( var_lookup(lpPkt->m_flow_var_name ,var) == false){ std::stringstream ss; ss << "instruction id '" << ins_id << "' packet write with no valid flow varible name '" << lpPkt->m_flow_var_name << "'" ; err(ss.str()); } if (lpPkt->m_pkt_offset + lpPkt->m_pkt_cast_size > m_pkt_size ) { std::stringstream ss; ss << "instruction id '" << ins_id << "' packet write with packet_offset " << (lpPkt->m_pkt_offset + lpPkt->m_pkt_cast_size) << " bigger than packet size "<< m_pkt_size; err(ss.str()); } add_field_cnt(lpPkt->m_pkt_offset + lpPkt->m_pkt_cast_size); uint8_t op_size = var.m_size_bytes; bool is_big = lpPkt->m_is_big_endian; uint8_t flags = (is_big?StreamDPOpPktWrMask::MASK_PKT_WR_IS_BIG:0); uint8_t flow_offset = get_var_offset(lpPkt->m_flow_var_name); /* read LSB in case of 64bit varible */ if (op_size == 8) { op_size = 4; if ( is_big ) { flow_offset +=4; } } StreamDPOpPktWrMask pmask; pmask.m_op = StreamDPVmInstructions::itPKT_WR_MASK; pmask.m_flags = flags; pmask.m_var_offset = flow_offset; pmask.m_shift = lpPkt->m_shift; pmask.m_add_value = lpPkt->m_add_value; pmask.m_pkt_cast_size = cast_size; pmask.m_flowv_cast_size = op_size; pmask.m_pkt_offset = lpPkt->m_pkt_offset; pmask.m_mask = lpPkt->m_mask; m_instructions.add_command(&pmask,sizeof(pmask)); } if (ins_type == StreamVmInstruction::itFLOW_CLIENT) { var_cnt++; StreamVmInstructionFlowClient *lpMan =(StreamVmInstructionFlowClient *)inst; if ( lpMan->is_unlimited_flows() ){ StreamDPOpClientsUnLimit client_cmd; client_cmd.m_op = StreamDPVmInstructions::itCLIENT_VAR_UNLIMIT; client_cmd.m_flow_offset = get_var_offset(lpMan->m_var_name+".ip"); /* start offset */ client_cmd.m_flags = 0; /* not used */ client_cmd.m_pad = 0; client_cmd.m_min_ip = lpMan->m_client_min; client_cmd.m_max_ip = lpMan->m_client_max; m_instructions.add_command(&client_cmd,sizeof(client_cmd)); }else{ StreamDPOpClientsLimit client_cmd; client_cmd.m_op = StreamDPVmInstructions::itCLIENT_VAR; client_cmd.m_flow_offset = get_var_offset(lpMan->m_var_name+".ip"); /* start offset */ client_cmd.m_flags = 0; /* not used */ client_cmd.m_pad = 0; client_cmd.m_min_port = lpMan->m_port_min; client_cmd.m_max_port = lpMan->m_port_max; client_cmd.m_min_ip = lpMan->m_client_min; client_cmd.m_max_ip = lpMan->m_client_max; client_cmd.m_limit_flows = lpMan->m_limit_num_flows; m_instructions.add_command(&client_cmd,sizeof(client_cmd)); } } if (ins_type == StreamVmInstruction::itPKT_SIZE_CHANGE ) { StreamVmInstructionChangePktSize *lpPkt =(StreamVmInstructionChangePktSize *)inst; VmFlowVarRec var; if ( var_lookup(lpPkt->m_flow_var_name ,var) == false){ std::stringstream ss; ss << "instruction id '" << ins_id << "' packet size with no valid flow varible name '" << lpPkt->m_flow_var_name << "'" ; err(ss.str()); } if ( var.m_size_bytes != 2 ) { std::stringstream ss; ss << "instruction id '" << ins_id << "' packet size change should point to a flow varible with size 2 "; err(ss.str()); } uint8_t flow_offset = get_var_offset(lpPkt->m_flow_var_name); StreamDPOpPktSizeChange pkt_size_ch; pkt_size_ch.m_op =StreamDPVmInstructions::itPKT_SIZE_CHANGE; pkt_size_ch.m_flow_offset = flow_offset; m_instructions.add_command(&pkt_size_ch,sizeof(pkt_size_ch)); } ins_id++; } if ( var_cnt ==0 ){ std::stringstream ss; ss << "It is not valid to have a VM program without a variable or tuple generator "; err(ss.str()); } }
void StreamVm::build_flow_var_table() { var_clear_table(); m_cur_var_offset=0; uint32_t ins_id=0; /* scan all flow var instruction and build */ /* if we found allocate BSS +4 bytes */ if ( m_is_random_var ){ VmFlowVarRec var; var.m_offset = m_cur_var_offset; var.m_ins.m_ins_flowv = NULL; var.m_size_bytes = sizeof(uint32_t); var_add("___random___",var); m_cur_var_offset += sizeof(uint32_t); } for (auto inst : m_inst_list) { if ( inst->get_instruction_type() == StreamVmInstruction::itFLOW_MAN ){ StreamVmInstructionFlowMan * ins_man=(StreamVmInstructionFlowMan *)inst; /* check that instruction is valid */ ins_man->sanity_check(ins_id,this); VmFlowVarRec var; /* if this is the first time */ if ( var_lookup( ins_man->m_var_name,var) == true){ std::stringstream ss; ss << "instruction id '" << ins_id << "' flow variable name " << ins_man->m_var_name << " already exists"; err(ss.str()); }else{ var.m_offset=m_cur_var_offset; var.m_ins.m_ins_flowv = ins_man; var.m_size_bytes = ins_man->m_size_bytes; var_add(ins_man->m_var_name,var); m_cur_var_offset += ins_man->m_size_bytes; } } if ( inst->get_instruction_type() == StreamVmInstruction::itFLOW_CLIENT ){ StreamVmInstructionFlowClient * ins_man=(StreamVmInstructionFlowClient *)inst; VmFlowVarRec var; /* if this is the first time */ if ( var_lookup( ins_man->m_var_name+".ip",var) == true){ std::stringstream ss; ss << "instruction id '" << ins_id << "' client variable name " << ins_man->m_var_name << " already exists"; err(ss.str()); } if ( var_lookup( ins_man->m_var_name+".port",var) == true){ std::stringstream ss; ss << "instruction id '" << ins_id << "' client variable name " << ins_man->m_var_name << " already exists"; err(ss.str()); } if ( var_lookup( ins_man->m_var_name+".flow_limit",var) == true){ std::stringstream ss; ss << "instruction id '" << ins_id << "' client variable name " << ins_man->m_var_name << " already exists"; err(ss.str()); } var.m_offset = m_cur_var_offset; var.m_ins.m_ins_flow_client = ins_man; var.m_size_bytes =4; VmFlowVarRec var_port; var_port.m_offset = m_cur_var_offset+4; var_port.m_ins.m_ins_flow_client = ins_man; var_port.m_size_bytes =2; VmFlowVarRec var_flow_limit; var_flow_limit.m_offset = m_cur_var_offset+6; var_flow_limit.m_ins.m_ins_flow_client = ins_man; var_flow_limit.m_size_bytes =4; var_add(ins_man->m_var_name+".ip",var); var_add(ins_man->m_var_name+".port",var_port); var_add(ins_man->m_var_name+".flow_limit",var_flow_limit); m_cur_var_offset += StreamVmInstructionFlowClient::get_flow_var_size(); assert(sizeof(StreamDPFlowClient)==StreamVmInstructionFlowClient::get_flow_var_size()); } /* limit the flow var size */ if (m_cur_var_offset > StreamVm::svMAX_FLOW_VAR ) { std::stringstream ss; ss << "too many flow varibles current size is :" << m_cur_var_offset << " maximum support is " << StreamVm::svMAX_FLOW_VAR; err(ss.str()); } ins_id++; } ins_id=0; /* second interation for sanity check and fixups*/ for (auto inst : m_inst_list) { if (inst->get_instruction_type() == StreamVmInstruction::itPKT_SIZE_CHANGE ) { StreamVmInstructionChangePktSize *lpPkt =(StreamVmInstructionChangePktSize *)inst; VmFlowVarRec var; if ( var_lookup(lpPkt->m_flow_var_name ,var) == false){ std::stringstream ss; ss << "instruction id '" << ins_id << "' packet size with no valid flow varible name '" << lpPkt->m_flow_var_name << "'" ; err(ss.str()); } if ( var.m_size_bytes != 2 ) { std::stringstream ss; ss << "instruction id '" << ins_id << "' packet size change should point to a flow varible with size 2 "; err(ss.str()); } if ( var.m_ins.m_ins_flowv->m_max_value > m_pkt_size) { var.m_ins.m_ins_flowv->m_max_value =m_pkt_size; } if (var.m_ins.m_ins_flowv->m_min_value > m_pkt_size) { var.m_ins.m_ins_flowv->m_min_value = m_pkt_size; } if ( var.m_ins.m_ins_flowv->m_min_value >= var.m_ins.m_ins_flowv->m_max_value ) { std::stringstream ss; ss << "instruction id '" << ins_id << "' min packet size " << var.m_ins.m_ins_flowv->m_min_value << " is bigger or eq to max packet size " << var.m_ins.m_ins_flowv->m_max_value; err(ss.str()); } if ( var.m_ins.m_ins_flowv->m_min_value < 60) { var.m_ins.m_ins_flowv->m_min_value =60; } m_expected_pkt_size = (var.m_ins.m_ins_flowv->m_min_value + var.m_ins.m_ins_flowv->m_max_value) / 2; } }/* for */ }
uint16_t StreamVm::get_var_offset(const std::string &var_name){ VmFlowVarRec var; bool res=var_lookup(var_name,var); assert(res); return (var.m_offset); }