diff options
author | Vadim Kochan <vadim4j@gmail.com> | 2016-08-13 02:11:10 +0300 |
---|---|---|
committer | Tobias Klauser <tklauser@distanz.ch> | 2016-09-21 09:50:06 +0200 |
commit | e7dd63060e448bf6667c92a3b774cec0feeff452 (patch) | |
tree | c00b4dfe777d74b60cf6c4f6141a45c0a3176f48 | |
parent | 6197f02044e2fe6689b52dad0a0c75bdc0eb185b (diff) |
trafgen: proto: Update field value at runtime
Add basic infrastructure for update proto field value at runtime by
dynamic field function.
Extended 'struct packet_dyn' with proto fields which has dynamically
changing values at runtime.
Added 'field_changed' callback for proto header which may be used for
check if csum updating is needed. This callback is called after field
was changed at runtime.
Added 'packet_update' callback to let proto header know when to apply
final proto header changes at runtime (e.g. - csum update).
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
-rw-r--r-- | trafgen.c | 9 | ||||
-rw-r--r-- | trafgen_conf.h | 7 | ||||
-rw-r--r-- | trafgen_proto.c | 32 | ||||
-rw-r--r-- | trafgen_proto.h | 15 |
4 files changed, 63 insertions, 0 deletions
@@ -619,6 +619,15 @@ static inline void packet_apply_dyn_elements(int idx) apply_randomizer(idx); apply_csum16(idx); } + + if (packet_dyn_has_fields(&packet_dyn[idx])) { + uint32_t i; + + for (i = 0; i < packet_dyn[idx].flen; i++) + proto_field_dyn_apply(packet_dyn[idx].fields[i]); + + proto_packet_update(idx); + } } static void xmit_slowpath_or_die(struct ctx *ctx, unsigned int cpu, unsigned long orig_num) diff --git a/trafgen_conf.h b/trafgen_conf.h index 934f8fe..61da012 100644 --- a/trafgen_conf.h +++ b/trafgen_conf.h @@ -49,6 +49,8 @@ struct packet_dyn { size_t rlen; struct csum16 *csum; size_t slen; + struct proto_field **fields; + size_t flen; }; static inline bool packet_dyn_has_elems(struct packet_dyn *p) @@ -61,6 +63,11 @@ static inline bool packet_dyn_has_only_csums(struct packet_dyn *p) return (p->clen == 0 && p->rlen == 0 && p->slen); } +static inline bool packet_dyn_has_fields(struct packet_dyn *p) +{ + return p->flen; +} + extern void compile_packets_str(char *str, bool verbose, unsigned int cpu); extern void compile_packets(char *file, bool verbose, unsigned int cpu, bool invoke_cpp, char *const cpp_argv[]); diff --git a/trafgen_proto.c b/trafgen_proto.c index d976c14..96fd6da 100644 --- a/trafgen_proto.c +++ b/trafgen_proto.c @@ -409,6 +409,19 @@ void protos_init(const char *dev) protos_l4_init(); } +void proto_packet_update(uint32_t idx) +{ + struct packet *pkt = packet_get(idx); + ssize_t i; + + for (i = pkt->headers_count - 1; i >= 0; i--) { + struct proto_hdr *hdr = pkt->headers[i]; + + if (hdr->ops->packet_update) + hdr->ops->packet_update(hdr); + } +} + void proto_packet_finish(void) { struct proto_hdr **headers = current_packet()->headers; @@ -424,3 +437,22 @@ void proto_packet_finish(void) ops->packet_finish(hdr); } } + +void proto_field_func_add(struct proto_hdr *hdr, uint32_t fid, + struct proto_field_func *func) +{ + struct proto_field *field = proto_field_by_id(hdr, fid); + + bug_on(!func); + + field->func.update_field = func->update_field; +} + +void proto_field_dyn_apply(struct proto_field *field) +{ + if (field->func.update_field) + field->func.update_field(field); + + if (field->hdr->ops->field_changed) + field->hdr->ops->field_changed(field); +} diff --git a/trafgen_proto.h b/trafgen_proto.h index 9716aa2..6cdc51f 100644 --- a/trafgen_proto.h +++ b/trafgen_proto.h @@ -27,6 +27,7 @@ enum proto_layer { PROTO_L4, }; +struct proto_field; struct proto_hdr; struct proto_ops { @@ -35,7 +36,9 @@ struct proto_ops { void (*header_init)(struct proto_hdr *hdr); void (*header_finish)(struct proto_hdr *hdr); + void (*field_changed)(struct proto_field *field); void (*packet_finish)(struct proto_hdr *hdr); + void (*packet_update)(struct proto_hdr *hdr); void (*set_next_proto)(struct proto_hdr *hdr, enum proto_id pid); }; @@ -48,6 +51,10 @@ struct proto_hdr { size_t len; }; +struct proto_field_func { + void (*update_field)(struct proto_field *field); +}; + struct proto_field { uint32_t id; size_t len; @@ -56,6 +63,7 @@ struct proto_field { /* might be negative (e.g. VLAN TPID field) */ int16_t offset; + struct proto_field_func func; bool is_set; uint16_t pkt_offset; struct proto_hdr *hdr; @@ -67,6 +75,8 @@ extern void proto_ops_register(const struct proto_ops *ops); extern struct proto_hdr *proto_header_push(enum proto_id pid); extern void proto_header_finish(struct proto_hdr *hdr); extern void proto_packet_finish(void); +extern void proto_packet_update(uint32_t idx); + extern struct proto_hdr *proto_lower_default_add(struct proto_hdr *hdr, enum proto_id pid); @@ -113,4 +123,9 @@ extern void proto_field_set_default_dev_ipv4(struct proto_hdr *hdr, uint32_t fid extern void proto_field_set_dev_ipv6(struct proto_hdr *hdr, uint32_t fid); extern void proto_field_set_default_dev_ipv6(struct proto_hdr *hdr, uint32_t fid); +extern void proto_field_dyn_apply(struct proto_field *field); + +extern void proto_field_func_add(struct proto_hdr *hdr, uint32_t fid, + struct proto_field_func *func); + #endif /* TRAFGEN_PROTO_H */ |