Helper for public AddField functions. DoAddField inserts `field` as the `idx`th field for this table. If `mt_attr_name` is set, the `offset` field of `field` will be ignored and the inserted field will use the offset of `mt_attr_name` as reported by the module `m`. Returns 0 on success, non-zero errno on failure.
| 389 | // module `m`. |
| 390 | // Returns 0 on success, non-zero errno on failure. |
| 391 | Error DoAddField(const ExactMatchField &field, |
| 392 | const std::string &mt_attr_name, int idx, |
| 393 | Module *m = nullptr) { |
| 394 | if (idx >= MAX_FIELDS) { |
| 395 | return MakeError(EINVAL, |
| 396 | Format("idx %d is not in [0,%d)", idx, MAX_FIELDS)); |
| 397 | } |
| 398 | ExactMatchField *f = &fields_[idx]; |
| 399 | f->size = field.size; |
| 400 | if (f->size < 1 || f->size > MAX_FIELD_SIZE) { |
| 401 | return MakeError(EINVAL, Format("idx %d: 'size' must be in [1,%d]", idx, |
| 402 | MAX_FIELD_SIZE)); |
| 403 | } |
| 404 | |
| 405 | if (mt_attr_name.length() > 0) { |
| 406 | f->attr_id = m->AddMetadataAttr(mt_attr_name, f->size, |
| 407 | metadata::Attribute::AccessMode::kRead); |
| 408 | if (f->attr_id < 0) { |
| 409 | return MakeError(-f->attr_id, |
| 410 | Format("idx %d: add_metadata_attr() failed", idx)); |
| 411 | } |
| 412 | } else { |
| 413 | f->attr_id = -1; |
| 414 | f->offset = field.offset; |
| 415 | if (f->offset < 0 || f->offset > 1024) { |
| 416 | return MakeError(EINVAL, Format("idx %d: invalid 'offset'", idx)); |
| 417 | } |
| 418 | } |
| 419 | |
| 420 | int force_be = (f->attr_id < 0); |
| 421 | |
| 422 | if (field.mask == 0) { |
| 423 | /* by default all bits are considered */ |
| 424 | f->mask = SetBitsHigh<uint64_t>(f->size * 8); |
| 425 | } else { |
| 426 | if (!utils::uint64_to_bin(&f->mask, field.mask, f->size, |
| 427 | utils::is_be_system() | force_be)) { |
| 428 | return MakeError( |
| 429 | EINVAL, Format("idx %d: not a valid %d-byte mask", idx, f->size)); |
| 430 | } |
| 431 | } |
| 432 | |
| 433 | if (f->mask == 0) { |
| 434 | return MakeError(EINVAL, Format("idx %d: empty mask", idx)); |
| 435 | } |
| 436 | |
| 437 | num_fields_++; |
| 438 | f->pos = raw_key_size_; |
| 439 | raw_key_size_ += f->size; |
| 440 | total_key_size_ = align_ceil(raw_key_size_, sizeof(uint64_t)); |
| 441 | |
| 442 | return MakeError(0); |
| 443 | } |
| 444 | |
| 445 | // unaligend key size, used as an accumulator for calls to AddField() |
| 446 | size_t raw_key_size_; |
nothing calls this directly
no test coverage detected