diff options
author | Vadim Kochan <vadim4j@gmail.com> | 2016-08-13 02:11:13 +0300 |
---|---|---|
committer | Tobias Klauser <tklauser@distanz.ch> | 2016-09-21 09:54:41 +0200 |
commit | 573b1fff25af70492deb9e59c0b48d77b0c1ed03 (patch) | |
tree | 46457f4ea0f7fe6c95c025714e8e52b04de41d15 | |
parent | d5bcf8d0f5a2a549c3cbe71e7704bb557c7eb6a3 (diff) |
trafgen: ipv4: Update csum at runtime if needed
Handle 'field_changed' callback to check if IPv4 csum is needed to be
recalculated, if so - update it on 'packet_update' event.
Added 'is_csum_valid' to proto_hdr struct to check if csum needs to be
updated.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
-rw-r--r-- | trafgen_l3.c | 33 | ||||
-rw-r--r-- | trafgen_proto.h | 1 |
2 files changed, 28 insertions, 6 deletions
diff --git a/trafgen_l3.c b/trafgen_l3.c index 2eabef1..9bb0de9 100644 --- a/trafgen_l3.c +++ b/trafgen_l3.c @@ -43,6 +43,30 @@ static void ipv4_header_init(struct proto_hdr *hdr) proto_field_set_default_dev_ipv4(hdr, IP4_SADDR); } +static void ipv4_field_changed(struct proto_field *field) +{ + field->hdr->is_csum_valid = false; +} + +static void ipv4_csum_update(struct proto_hdr *hdr) +{ + struct packet *pkt; + uint16_t csum; + + if (hdr->is_csum_valid) + return; + if (proto_field_is_set(hdr, IP4_CSUM)) + return; + + pkt = packet_get(hdr->pkt_id); + + proto_field_set_default_u16(hdr, IP4_CSUM, 0); + csum = htons(calc_csum(&pkt->payload[hdr->pkt_offset], hdr->len)); + proto_field_set_default_u16(hdr, IP4_CSUM, bswap_16(csum)); + + hdr->is_csum_valid = true; +} + static void ipv4_packet_finish(struct proto_hdr *hdr) { struct packet *pkt = current_packet(); @@ -51,12 +75,7 @@ static void ipv4_packet_finish(struct proto_hdr *hdr) total_len = pkt->len - hdr->pkt_offset; proto_field_set_default_be16(hdr, IP4_LEN, total_len); - if (!proto_field_is_set(hdr, IP4_CSUM)) { - uint16_t csum; - - csum = htons(calc_csum(&pkt->payload[hdr->pkt_offset], hdr->len)); - proto_field_set_u16(hdr, IP4_CSUM, bswap_16(csum)); - } + ipv4_csum_update(hdr); } static void ipv4_set_next_proto(struct proto_hdr *hdr, enum proto_id pid) @@ -90,6 +109,8 @@ static const struct proto_ops ipv4_proto_ops = { .id = PROTO_IP4, .layer = PROTO_L3, .header_init = ipv4_header_init, + .packet_update = ipv4_csum_update, + .field_changed = ipv4_field_changed, .packet_finish = ipv4_packet_finish, .set_next_proto = ipv4_set_next_proto, }; diff --git a/trafgen_proto.h b/trafgen_proto.h index 41e9383..000938c 100644 --- a/trafgen_proto.h +++ b/trafgen_proto.h @@ -48,6 +48,7 @@ struct proto_hdr { uint32_t pkt_id; struct proto_field *fields; size_t fields_count; + bool is_csum_valid; size_t len; }; |