From fac5a67eb5d4928f7efbf1f0d731a7e93f0f8193 Mon Sep 17 00:00:00 2001 From: Vadim Kochan Date: Tue, 26 Jan 2016 22:25:06 +0200 Subject: trafgen: l2: Add ARP header generation logic Add ARP protocol header fields generation. By default htype ethernet (1) and ptype IPv4 (0x0800) and the corresponding hlen/plen values will be initialized and the opcode is set to ARP Request (1). Source MAC and IP address are set to the device's addresses if not specified. Signed-off-by: Vadim Kochan [tk: rephrase and extend commit message] Signed-off-by: Tobias Klauser --- trafgen_l2.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ trafgen_l2.h | 12 ++++++++++++ 2 files changed, 62 insertions(+) diff --git a/trafgen_l2.c b/trafgen_l2.c index 1082049..4bbeea1 100644 --- a/trafgen_l2.c +++ b/trafgen_l2.c @@ -3,6 +3,9 @@ * Subject to the GPL, version 2. */ +#include +#include + #include "built_in.h" #include "trafgen_l2.h" #include "trafgen_proto.h" @@ -26,7 +29,54 @@ static struct proto_hdr eth_hdr = { .header_init = eth_header_init, }; +static struct proto_field arp_fields[] = { + { .id = ARP_HTYPE, .len = 2 }, + { .id = ARP_PTYPE, .len = 2, .offset = 2 }, + { .id = ARP_HLEN, .len = 1, .offset = 4 }, + { .id = ARP_PLEN, .len = 1, .offset = 5 }, + { .id = ARP_OPER, .len = 2, .offset = 6 }, + { .id = ARP_SHA, .len = 6, .offset = 8 }, + { .id = ARP_SPA, .len = 4, .offset = 14 }, + { .id = ARP_THA, .len = 6, .offset = 18 }, + { .id = ARP_TPA, .len = 4, .offset = 24 }, +}; + +static void arp_header_init(struct proto_hdr *hdr) +{ + struct proto_hdr *lower; + + proto_lower_default_add(PROTO_ETH); + + lower = proto_current_header(); + + if (lower->id == PROTO_ETH) { + uint8_t bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + proto_field_set_default_bytes(lower, ETH_DST_ADDR, bcast); + proto_field_set_default_be16(lower, ETH_PROTO_ID, ETH_P_ARP); + } + + proto_header_fields_add(hdr, arp_fields, array_size(arp_fields)); + + /* Generate Announce request by default */ + proto_field_set_default_be16(hdr, ARP_HTYPE, ARPHRD_ETHER); + proto_field_set_default_be16(hdr, ARP_PTYPE, ETH_P_IP); + proto_field_set_default_u8(hdr, ARP_HLEN, 6); + proto_field_set_default_u8(hdr, ARP_PLEN, 4); + proto_field_set_default_be16(hdr, ARP_OPER, ARPOP_REQUEST); + proto_field_set_default_dev_mac(hdr, ARP_SHA); + proto_field_set_default_dev_ipv4(hdr, ARP_SPA); + proto_field_set_default_dev_ipv4(hdr, ARP_TPA); +} + +static struct proto_hdr arp_hdr = { + .id = PROTO_ARP, + .layer = PROTO_L2, + .header_init = arp_header_init, +}; + void protos_l2_init(void) { proto_header_register(ð_hdr); + proto_header_register(&arp_hdr); } diff --git a/trafgen_l2.h b/trafgen_l2.h index e0d9702..7643bc3 100644 --- a/trafgen_l2.h +++ b/trafgen_l2.h @@ -7,6 +7,18 @@ enum eth_field { ETH_PROTO_ID, }; +enum arp_field { + ARP_HTYPE, + ARP_PTYPE, + ARP_HLEN, + ARP_PLEN, + ARP_OPER, + ARP_SHA, + ARP_SPA, + ARP_THA, + ARP_TPA, +}; + extern void protos_l2_init(void); #endif /* TRAFGEN_L2_H */ -- cgit v1.2.3-54-g00ecf