void ParserOpSet<ParserLookAhead>::operator()(Packet *pkt, const char *data, size_t *bytes_parsed) const { (void) bytes_parsed; static thread_local ByteContainer bc; PHV *phv = pkt->get_phv(); Field &f_dst = phv->get_field(dst.header, dst.offset); int f_bits = f_dst.get_nbits(); /* I expect the first case to be the most common one. In the first case, we extract the packet bytes to the field bytes and sync the bignum value. The second case requires extracting the packet bytes to the ByteContainer, then importing the bytes into the field's bignum value, then finally exporting the bignum value to the field's byte array. I could alternatively write a more general extract function which would account for a potential size difference between source and destination. */ // TODO(antonin) if (src.bitwidth == f_bits) { data += src.byte_offset; f_dst.extract(data, src.bit_offset); } else { bc.clear(); src.peek(data, &bc); f_dst.set(bc); } BMLOG_DEBUG_PKT( *pkt, "Parser set: setting field ({}, {}) from lookahead ({}, {}), " "new value is {}", dst.header, dst.offset, src.bit_offset, src.bitwidth, f_dst); }
void LearnEngine::LearnList::add_sample(const PHV &phv) { static thread_local ByteContainer sample; sample.clear(); builder(phv, &sample); std::unique_lock<std::mutex> lock(mutex); const auto it = filter.find(sample); if(it != filter.end()) return; buffer.insert(buffer.end(), sample.begin(), sample.end()); num_samples++; auto filter_it = filter.insert(filter.end(), std::move(sample)); FilterPtrs &filter_ptrs = old_buffers[buffer_id]; filter_ptrs.unacked_count++; filter_ptrs.buffer.push_back(filter_it); if(num_samples == 1 && max_samples > 1) { buffer_started = clock::now(); b_can_send.notify_one(); // wake transmit thread to update cond var wait time } else if(num_samples >= max_samples) { while(buffer_tmp.size() != 0) { b_can_swap.wait(lock); } swap_buffers(); b_can_send.notify_one(); } }
const ParseState * ParseState::find_next_state(Packet *pkt, const char *data, size_t *bytes_parsed) const { // execute parser ops PHV *phv = pkt->get_phv(); register_sync.lock_registers(); for (auto &parser_op : parser_ops) (*parser_op)(pkt, data + *bytes_parsed, bytes_parsed); register_sync.unlock_registers(); if (!has_switch) { BMLOG_DEBUG_PKT( *pkt, "Parser state '{}' has no switch, going to default next state", get_name()); return default_next_state; } // build key static thread_local ByteContainer key; key.clear(); key_builder(*phv, data + *bytes_parsed, &key); BMLOG_DEBUG_PKT(*pkt, "Parser state '{}': key is {}", get_name(), key.to_hex()); // try the matches in order const ParseState *next_state = NULL; for (const auto &switch_case : parser_switch) if (switch_case.match(key, &next_state)) return next_state; return default_next_state; }