void table_row_t::load_value(char* data, index_desc_t* pindex) { // Read the data field by field assert (data); // 1. Get the pre-calculated offsets // current offset for fixed length field values offset_t fixed_offset = get_fixed_offset(); // current offset for variable length field slots offset_t var_slot_offset = get_var_slot_offset(); // current offset for variable length field values offset_t var_offset = get_var_offset(); // 2. Read the data field by field int null_index = -1; for (unsigned i=0; i<_ptable->field_count(); i++) { if (pindex) { bool skip = false; // skip key fields for (unsigned j = 0; j < pindex->field_count(); j++) { if ((int) i == pindex->key_index(j)) { skip = true; break; } } if (skip) continue; } // Check if the field can be NULL. // If it can be NULL, increase the null_index, // and check if the bit in the null_flags bitmap is set. // If it is set, set the corresponding value in the tuple // as null, and go to the next field, ignoring the rest if (_pvalues[i].field_desc()->allow_null()) { null_index++; if (IS_NULL_FLAG(data, null_index)) { _pvalues[i].set_null(); continue; } } // Check if the field is of VARIABLE length. // If it is, copy the offset of the value from the offset part of the // buffer (pointed by var_slot_offset). Then, copy that many chars from // the variable length part of the buffer (pointed by var_offset). // Then increase by one offset index, and offset of the pointer of the // next variable value if (_pvalues[i].is_variable_length()) { offset_t var_len; memcpy(&var_len, VAR_SLOT(data, var_slot_offset), sizeof(offset_t)); _pvalues[i].set_value(data+var_offset, var_len); var_offset += var_len; var_slot_offset += sizeof(offset_t); } else { // If it is of FIXED length, copy the data from the fixed length // part of the buffer (pointed by fixed_offset), and the increase // the fixed offset by the (fixed) size of the field _pvalues[i].set_value(data+fixed_offset, _pvalues[i].maxsize()); fixed_offset += _pvalues[i].maxsize(); } } }
void table_row_t::store_value(char* data, size_t& length, index_desc_t* pindex) { // 1. Get the pre-calculated offsets // current offset for fixed length field values offset_t fixed_offset = get_fixed_offset(); // current offset for variable length field slots offset_t var_slot_offset = get_var_slot_offset(); // current offset for variable length field values offset_t var_offset = get_var_offset(); // 2. calculate the total space of the tuple // (tupsize) : total space of the tuple int tupsize = 0; int null_count = get_null_count(); int fixed_size = get_var_slot_offset() - get_fixed_offset(); // loop over all the variable-sized fields and add their real size (set at ::set()) for (unsigned i=0; i<_ptable->field_count(); i++) { if (_pvalues[i].is_variable_length()) { // If it is of VARIABLE length, then if the value is null // do nothing, else add to the total tuple length the (real) // size of the value plus the size of an offset. if (_pvalues[i].is_null()) continue; tupsize += _pvalues[i].realsize(); tupsize += sizeof(offset_t); } // If it is of FIXED length, then increase the total tuple // length, as well as, the size of the fixed length part of // the tuple by the fixed size of this type of field. // IP: The length of the fixed-sized fields is added after the loop } // Add up the length of the fixed-sized fields tupsize += fixed_size; // In the total tuple length add the size of the bitmap that // shows which fields can be NULL if (null_count) tupsize += (null_count >> 3) + 1; assert (tupsize); if ((long) length < tupsize) { throw runtime_error("Tuple does not fit on allocated buffer"); } length = tupsize; // 4. Copy the fields to the array, field by field int null_index = -1; // iterate over all fields for (unsigned i=0; i<_ptable->field_count(); i++) { // skip fields which are part of the given index if (pindex) { bool skip = false; for (unsigned j=0; j<pindex->field_count(); j++) { if ((int) i == pindex->key_index(j)) { skip = true; break; } } if (skip) continue; } // Check if the field can be NULL. // If it can be NULL, increase the null_index, and // if it is indeed NULL set the corresponding bit if (_pvalues[i].field_desc()->allow_null()) { null_index++; if (_pvalues[i].is_null()) { SET_NULL_FLAG(data, null_index); } } // Check if the field is of VARIABLE length. // If it is, copy the field value to the variable length part of the // buffer, to position (buffer + var_offset) // and increase the var_offset. if (_pvalues[i].is_variable_length()) { _pvalues[i].copy_value(data + var_offset); int offset = _pvalues[i].realsize(); var_offset += offset; // set the offset offset_t len = offset; memcpy(VAR_SLOT(data, var_slot_offset), &len, sizeof(offset_t)); var_slot_offset += sizeof(offset_t); } else { // If it is of FIXED length, then copy the field value to the // fixed length part of the buffer, to position // (buffer + fixed_offset) // and increase the fixed_offset _pvalues[i].copy_value(data + fixed_offset); fixed_offset += _pvalues[i].maxsize(); } } }
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()); } }