summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Kochan <vadim4j@gmail.com>2016-08-13 02:11:10 +0300
committerTobias Klauser <tklauser@distanz.ch>2016-09-21 09:50:06 +0200
commite7dd63060e448bf6667c92a3b774cec0feeff452 (patch)
treec00b4dfe777d74b60cf6c4f6141a45c0a3176f48
parent6197f02044e2fe6689b52dad0a0c75bdc0eb185b (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.c9
-rw-r--r--trafgen_conf.h7
-rw-r--r--trafgen_proto.c32
-rw-r--r--trafgen_proto.h15
4 files changed, 63 insertions, 0 deletions
diff --git a/trafgen.c b/trafgen.c
index b76b5d7..553dfa5 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -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 */