| 222 | } |
| 223 | |
| 224 | void ExactMatch::ProcessBatch(Context *ctx, bess::PacketBatch *batch) { |
| 225 | gate_idx_t default_gate; |
| 226 | ExactMatchKey keys[bess::PacketBatch::kMaxBurst] __ymm_aligned; |
| 227 | |
| 228 | default_gate = ACCESS_ONCE(default_gate_); |
| 229 | |
| 230 | const auto buffer_fn = [&](bess::Packet *pkt, const ExactMatchField &f) { |
| 231 | int attr_id = f.attr_id; |
| 232 | if (attr_id >= 0) { |
| 233 | return ptr_attr<uint8_t>(this, attr_id, pkt); |
| 234 | } |
| 235 | return pkt->head_data<uint8_t *>() + f.offset; |
| 236 | }; |
| 237 | table_.MakeKeys(batch, buffer_fn, keys); |
| 238 | |
| 239 | int cnt = batch->cnt(); |
| 240 | for (int i = 0; i < cnt; i++) { |
| 241 | bess::Packet *pkt = batch->pkts()[i]; |
| 242 | EmitPacket(ctx, pkt, table_.Find(keys[i], default_gate)); |
| 243 | } |
| 244 | } |
| 245 | |
| 246 | std::string ExactMatch::GetDesc() const { |
| 247 | return bess::utils::Format("%zu fields, %zu rules", table_.num_fields(), |