summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Kochan <vadim4j@gmail.com>2016-02-08 08:01:51 +0200
committerTobias Klauser <tklauser@distanz.ch>2016-02-23 13:15:50 +0100
commitf02fcdbd2cb4dc041783def773e446c179bd57f1 (patch)
tree9c1167852b94242eec1fa7aa4f03c6df31f0c04d
parentb14fd7ed1bdbe0644601b9f0e854af1b19811f30 (diff)
trafgen: proto: Fix bad field masking
Current logic does OR of existing field value & shift-masked specified value, which is not enough as 0s bits from the specified value will be not set (be cause of OR), so fixed it by reseting original field value by AND with reverted field mask, in otherwords - bits part of original field value is reset to 0s and only after OR-ed with specified shift-masked value. Signed-off-by: Vadim Kochan <vadim4j@gmail.com> Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
-rw-r--r--trafgen_proto.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/trafgen_proto.c b/trafgen_proto.c
index efa8fce..214547e 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -182,7 +182,9 @@ static void __proto_field_set_bytes(struct proto_hdr *hdr, uint32_t fid,
uint8_t *bytes, bool is_default, bool is_be)
{
struct proto_field *field;
- uint8_t *payload;
+ uint8_t *payload, *p8;
+ uint16_t *p16;
+ uint32_t *p32;
uint32_t v32;
uint16_t v16;
uint8_t v8;
@@ -195,18 +197,32 @@ static void __proto_field_set_bytes(struct proto_hdr *hdr, uint32_t fid,
payload = &current_packet()->payload[field->pkt_offset];
if (field->len == 1) {
+ p8 = payload;
+ *p8 = field->mask ? *p8 & ~field->mask : *p8;
+
v8 = field_shift_and_mask(field, *bytes);
- v8 = field->mask ? (v8 | *payload) : v8;
+ v8 = field->mask ? (v8 | *p8) : v8;
+
bytes = &v8;
} else if (field->len == 2) {
+ p16 = (uint16_t *)payload;
+ *p16 = be16_to_cpu(*p16);
+ *p16 = cpu_to_be16(field->mask ? *p16 & ~field->mask : *p16);
+
v16 = field_shift_and_mask(field, *(uint16_t *)bytes);
v16 = is_be ? cpu_to_be16(v16) : v16;
- v16 = field->mask ? (v16 | *(uint16_t *)payload) : v16;
+ v16 = field->mask ? (v16 | *p16) : v16;
+
bytes = (uint8_t *)&v16;
} else if (field->len == 4) {
+ p32 = (uint32_t *)payload;
+ *p32 = be32_to_cpu(*p32);
+ *p32 = cpu_to_be32(field->mask ? *p32 & ~field->mask : *p32);
+
v32 = field_shift_and_mask(field, *(uint32_t *)bytes);
v32 = is_be ? cpu_to_be32(v32) : v32;
- v32 = field->mask ? (v32 | *(uint32_t *)payload) : v32;
+ v32 = field->mask ? (v32 | *p32) : v32;
+
bytes = (uint8_t *)&v32;
}