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 <vadi...@gmail.com>
---
 trafgen_l3.c    | 33 +++++++++++++++++++++++++++------
 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 389c714..ab294df 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;
 };
 
-- 
2.9.2

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to