summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--trafgen_parser.y361
-rw-r--r--trafgen_proto.c2
-rw-r--r--trafgen_proto.h2
3 files changed, 218 insertions, 147 deletions
diff --git a/trafgen_parser.y b/trafgen_parser.y
index d643ad2..1e7bd5c 100644
--- a/trafgen_parser.y
+++ b/trafgen_parser.y
@@ -69,6 +69,27 @@ extern size_t dlen;
static int our_cpu, min_cpu = -1, max_cpu = -1;
+enum field_expr_type_t {
+ FIELD_EXPR_UNKNOWN,
+ FIELD_EXPR_NUMB,
+ FIELD_EXPR_MAC,
+ FIELD_EXPR_IP4_ADDR,
+ FIELD_EXPR_IP6_ADDR,
+};
+
+struct proto_field_expr {
+ enum field_expr_type_t type;
+ struct proto_field *field;
+
+ union {
+ struct in_addr ip4_addr;
+ struct in6_addr ip6_addr;
+ long long int number;
+ uint8_t bytes[256];
+ } val;
+};
+
+static struct proto_field_expr field_expr;
static struct proto_hdr *hdr;
static inline int test_ignore(void)
@@ -351,6 +372,48 @@ static void proto_add(enum proto_id pid)
hdr = proto_header_push(pid);
}
+static void proto_field_set(uint32_t fid)
+{
+ field_expr.field = proto_field_by_id(hdr, fid);
+}
+
+static void proto_field_expr_eval(void)
+{
+ struct proto_field *field = field_expr.field;
+
+ switch (field_expr.type) {
+ case FIELD_EXPR_NUMB:
+ if (field->len == 1)
+ proto_field_set_u8(hdr, field->id, field_expr.val.number);
+ else if (field->len == 2)
+ proto_field_set_be16(hdr, field->id, field_expr.val.number);
+ else if (field->len == 4)
+ proto_field_set_be32(hdr, field->id, field_expr.val.number);
+ else
+ bug();
+ break;
+
+ case FIELD_EXPR_MAC:
+ proto_field_set_bytes(hdr, field->id, field_expr.val.bytes);
+ break;
+
+ case FIELD_EXPR_IP4_ADDR:
+ proto_field_set_u32(hdr, field->id, field_expr.val.ip4_addr.s_addr);
+ break;
+
+ case FIELD_EXPR_IP6_ADDR:
+ proto_field_set_bytes(hdr, field->id,
+ (uint8_t *)&field_expr.val.ip6_addr.s6_addr);
+ break;
+
+ case FIELD_EXPR_UNKNOWN:
+ default:
+ bug();
+ }
+
+ memset(&field_expr, 0, sizeof(field_expr));
+}
+
%}
%union {
@@ -614,6 +677,17 @@ proto
| tcp_proto { }
;
+field_expr
+ : number { field_expr.type = FIELD_EXPR_NUMB;
+ field_expr.val.number = $1; }
+ | mac { field_expr.type = FIELD_EXPR_MAC;
+ memcpy(field_expr.val.bytes, $1, sizeof(field_expr.val.bytes)); }
+ | ip4_addr { field_expr.type = FIELD_EXPR_IP4_ADDR;
+ field_expr.val.ip4_addr = $1; }
+ | ip6_addr { field_expr.type = FIELD_EXPR_IP6_ADDR;
+ field_expr.val.ip6_addr = $1; }
+ ;
+
eth_proto
: eth '(' eth_param_list ')' { }
;
@@ -624,8 +698,8 @@ eth
eth_param_list
: { }
- | eth_field { }
- | eth_field delimiter eth_param_list { }
+ | eth_expr { }
+ | eth_expr delimiter eth_param_list { }
;
eth_type
@@ -635,12 +709,13 @@ eth_type
;
eth_field
- : K_DADDR skip_white '=' skip_white mac
- { proto_field_set_bytes(hdr, ETH_DST_ADDR, $5); }
- | K_SADDR skip_white '=' skip_white mac
- { proto_field_set_bytes(hdr, ETH_SRC_ADDR, $5); }
- | eth_type skip_white '=' skip_white number
- { proto_field_set_be16(hdr, ETH_TYPE, $5); }
+ : K_DADDR { proto_field_set(ETH_DST_ADDR); }
+ | K_SADDR { proto_field_set(ETH_SRC_ADDR); }
+ | eth_type { proto_field_set(ETH_TYPE); }
+
+eth_expr
+ : eth_field skip_white '=' skip_white field_expr
+ { proto_field_expr_eval(); }
;
vlan_proto
@@ -653,8 +728,8 @@ vlan
vlan_param_list
: { }
- | vlan_field { }
- | vlan_field delimiter vlan_param_list { }
+ | vlan_expr { }
+ | vlan_expr delimiter vlan_param_list { }
;
vlan_type
@@ -663,20 +738,20 @@ vlan_type
;
vlan_field
- : vlan_type skip_white '=' skip_white number
- { proto_field_set_be16(hdr, VLAN_TPID, $5); }
+ : vlan_type { proto_field_set(VLAN_TPID); }
+ | K_TCI { proto_field_set(VLAN_TCI); }
+ | K_PCP { proto_field_set(VLAN_PCP); }
+ | K_DEI { proto_field_set(VLAN_DEI); }
+ | K_ID { proto_field_set(VLAN_VID); }
+ ;
+
+vlan_expr
+ : vlan_field skip_white '=' skip_white field_expr
+ { proto_field_expr_eval(); }
| K_1Q
{ proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021Q); }
| K_1AD
{ proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021AD); }
- | K_TCI skip_white '=' skip_white number
- { proto_field_set_be16(hdr, VLAN_TCI, $5); }
- | K_PCP skip_white '=' skip_white number
- { proto_field_set_be16(hdr, VLAN_PCP, $5); }
- | K_DEI skip_white '=' skip_white number
- { proto_field_set_be16(hdr, VLAN_DEI, $5); }
- | K_ID skip_white '=' skip_white number
- { proto_field_set_be16(hdr, VLAN_VID, $5); }
;
mpls_proto
@@ -689,8 +764,8 @@ mpls
mpls_param_list
: { }
- | mpls_field { }
- | mpls_field delimiter mpls_param_list { }
+ | mpls_expr { }
+ | mpls_expr delimiter mpls_param_list { }
;
mpls_tc
@@ -699,49 +774,55 @@ mpls_tc
;
mpls_field
- : K_LABEL skip_white '=' skip_white number
- { proto_field_set_be32(hdr, MPLS_LABEL, $5); }
- | mpls_tc skip_white '=' skip_white number
- { proto_field_set_be32(hdr, MPLS_TC, $5); }
- | K_LAST skip_white '=' skip_white number
- { proto_field_set_be32(hdr, MPLS_LAST, $5); }
- | K_TTL skip_white '=' skip_white number
- { proto_field_set_be32(hdr, MPLS_TTL, $5); }
+ : K_LABEL { proto_field_set(MPLS_LABEL); }
+ | mpls_tc { proto_field_set(MPLS_TC); }
+ | K_LAST { proto_field_set(MPLS_LAST); }
+ | K_TTL { proto_field_set(MPLS_TTL); }
;
+mpls_expr
+ : mpls_field skip_white '=' skip_white field_expr
+ { proto_field_expr_eval(); }
+
arp_proto
: arp '(' arp_param_list ')' { }
;
arp_param_list
: { }
- | arp_field { }
- | arp_field delimiter arp_param_list { }
+ | arp_expr { }
+ | arp_expr delimiter arp_param_list { }
;
arp_field
- : K_OPER skip_white '=' skip_white K_REQUEST
+ : K_HTYPE
+ { proto_field_set(ARP_HTYPE); }
+ | K_PTYPE
+ { proto_field_set(ARP_PTYPE); }
+ | K_SHA
+ { proto_field_set(ARP_SHA); }
+ | K_THA
+ { proto_field_set(ARP_THA); }
+ | K_SPA
+ { proto_field_set(ARP_SPA); }
+ | K_TPA
+ { proto_field_set(ARP_TPA); }
+ ;
+
+arp_expr
+ : arp_field skip_white '=' skip_white field_expr
+ { proto_field_expr_eval(); }
+ | K_OPER skip_white '=' skip_white field_expr
+ { proto_field_set(ARP_OPER);
+ proto_field_expr_eval(); }
+ | K_OPER skip_white '=' skip_white K_REQUEST
{ proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
| K_OPER skip_white '=' skip_white K_REPLY
{ proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
- | K_OPER skip_white '=' skip_white number
- { proto_field_set_be16(hdr, ARP_OPER, $5); }
| K_REQUEST
{ proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
| K_REPLY
{ proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
- | K_HTYPE skip_white '=' skip_white number
- { proto_field_set_be16(hdr, ARP_HTYPE, $5); }
- | K_PTYPE skip_white '=' skip_white number
- { proto_field_set_be16(hdr, ARP_PTYPE, $5); }
- | K_SHA skip_white '=' skip_white mac
- { proto_field_set_bytes(hdr, ARP_SHA, $5); }
- | K_THA skip_white '=' skip_white mac
- { proto_field_set_bytes(hdr, ARP_THA, $5); }
- | K_SPA skip_white '=' skip_white ip4_addr
- { proto_field_set_u32(hdr, ARP_SPA, $5.s_addr); }
- | K_TPA skip_white '=' skip_white ip4_addr
- { proto_field_set_u32(hdr, ARP_TPA, $5.s_addr); }
;
arp
: K_ARP { proto_add(PROTO_ARP); }
@@ -753,41 +834,32 @@ ip4_proto
ip4_param_list
: { }
- | ip4_field { }
- | ip4_field delimiter ip4_param_list { }
+ | ip4_expr { }
+ | ip4_expr delimiter ip4_param_list { }
;
ip4_field
- : K_VER skip_white '=' skip_white number
- { proto_field_set_u8(hdr, IP4_VER, $5); }
- | K_IHL skip_white '=' skip_white number
- { proto_field_set_u8(hdr, IP4_IHL, $5); }
- | K_DADDR skip_white '=' skip_white ip4_addr
- { proto_field_set_u32(hdr, IP4_DADDR, $5.s_addr); }
- | K_SADDR skip_white '=' skip_white ip4_addr
- { proto_field_set_u32(hdr, IP4_SADDR, $5.s_addr); }
- | K_PROT skip_white '=' skip_white number
- { proto_field_set_u8(hdr, IP4_PROTO, $5); }
- | K_TTL skip_white '=' skip_white number
- { proto_field_set_u8(hdr, IP4_TTL, $5); }
- | K_DSCP skip_white '=' skip_white number
- { proto_field_set_u8(hdr, IP4_DSCP, $5); }
- | K_ECN skip_white '=' skip_white number
- { proto_field_set_u8(hdr, IP4_ECN, $5); }
- | K_TOS skip_white '=' skip_white number
- { proto_field_set_u8(hdr, IP4_TOS, $5); }
- | K_LEN skip_white '=' skip_white number
- { proto_field_set_be16(hdr, IP4_LEN, $5); }
- | K_ID skip_white '=' skip_white number
- { proto_field_set_be16(hdr, IP4_ID, $5); }
- | K_FLAGS skip_white '=' skip_white number
- { proto_field_set_be16(hdr, IP4_FLAGS, $5); }
+ : K_VER { proto_field_set(IP4_VER); }
+ | K_IHL { proto_field_set(IP4_IHL); }
+ | K_DADDR { proto_field_set(IP4_DADDR); }
+ | K_SADDR { proto_field_set(IP4_SADDR); }
+ | K_PROT { proto_field_set(IP4_PROTO); }
+ | K_TTL { proto_field_set(IP4_TTL); }
+ | K_DSCP { proto_field_set(IP4_DSCP); }
+ | K_ECN { proto_field_set(IP4_ECN); }
+ | K_TOS { proto_field_set(IP4_TOS); }
+ | K_LEN { proto_field_set(IP4_LEN); }
+ | K_ID { proto_field_set(IP4_ID); }
+ | K_FLAGS { proto_field_set(IP4_FLAGS); }
+ | K_FRAG { proto_field_set(IP4_FRAG_OFFS); }
+ | K_CSUM { proto_field_set(IP4_CSUM); }
+ ;
+
+ip4_expr
+ : ip4_field skip_white '=' skip_white field_expr
+ { proto_field_expr_eval(); }
| K_DF { proto_field_set_be16(hdr, IP4_DF, 1); }
| K_MF { proto_field_set_be16(hdr, IP4_MF, 1); }
- | K_FRAG skip_white '=' skip_white number
- { proto_field_set_be16(hdr, IP4_FRAG_OFFS, $5); }
- | K_CSUM skip_white '=' skip_white number
- { proto_field_set_be16(hdr, IP4_CSUM, $5); }
;
ip4
@@ -800,8 +872,8 @@ ip6_proto
ip6_param_list
: { }
- | ip6_field { }
- | ip6_field delimiter ip6_param_list { }
+ | ip6_expr { }
+ | ip6_expr delimiter ip6_param_list { }
;
ip6_hop_limit
@@ -810,22 +882,19 @@ ip6_hop_limit
;
ip6_field
- : K_VER skip_white '=' skip_white number
- { proto_field_set_be32(hdr, IP6_VER, $5); }
- | K_TC skip_white '=' skip_white number
- { proto_field_set_be32(hdr, IP6_CLASS, $5); }
- | K_FLOW skip_white '=' skip_white number
- { proto_field_set_be32(hdr, IP6_FLOW_LBL, $5); }
- | K_LEN skip_white '=' skip_white number
- { proto_field_set_be16(hdr, IP6_LEN, $5); }
- | K_NEXT_HDR skip_white '=' skip_white number
- { proto_field_set_u8(hdr, IP6_NEXT_HDR, $5); }
- | ip6_hop_limit skip_white '=' skip_white number
- { proto_field_set_u8(hdr, IP6_HOP_LIMIT, $5); }
- | K_SADDR skip_white '=' skip_white ip6_addr
- { proto_field_set_bytes(hdr, IP6_SADDR, (uint8_t *)&($5.s6_addr)); }
- | K_DADDR skip_white '=' skip_white ip6_addr
- { proto_field_set_bytes(hdr, IP6_DADDR, (uint8_t *)&($5.s6_addr)); }
+ : K_VER { proto_field_set(IP6_VER); }
+ | K_TC { proto_field_set(IP6_CLASS); }
+ | K_FLOW { proto_field_set(IP6_FLOW_LBL); }
+ | K_LEN { proto_field_set(IP6_LEN); }
+ | K_NEXT_HDR { proto_field_set(IP6_NEXT_HDR); }
+ | ip6_hop_limit { proto_field_set(IP6_HOP_LIMIT); }
+ | K_SADDR { proto_field_set(IP6_SADDR); }
+ | K_DADDR { proto_field_set(IP6_DADDR) ; }
+ ;
+
+ip6_expr
+ : ip6_field skip_white '=' skip_white field_expr
+ { proto_field_expr_eval(); }
;
ip6
@@ -838,23 +907,22 @@ icmp4_proto
icmp4_param_list
: { }
- | icmp4_field { }
- | icmp4_field delimiter icmp4_param_list { }
+ | icmp4_expr { }
+ | icmp4_expr delimiter icmp4_param_list { }
;
icmp4_field
- : K_TYPE skip_white '=' skip_white number
- { proto_field_set_u8(hdr, ICMPV4_TYPE, $5); }
- | K_CODE skip_white '=' skip_white number
- { proto_field_set_u8(hdr, ICMPV4_CODE, $5); }
- | K_ID skip_white '=' skip_white number
- { proto_field_set_be16(hdr, ICMPV4_ID, $5); }
- | K_SEQ skip_white '=' skip_white number
- { proto_field_set_be16(hdr, ICMPV4_SEQ, $5); }
- | K_MTU skip_white '=' skip_white number
- { proto_field_set_be16(hdr, ICMPV4_MTU, $5); }
- | K_ADDR skip_white '=' skip_white ip4_addr
- { proto_field_set_u32(hdr, ICMPV4_REDIR_ADDR, $5.s_addr); }
+ : K_TYPE { proto_field_set(ICMPV4_TYPE); }
+ | K_CODE { proto_field_set(ICMPV4_CODE); }
+ | K_ID { proto_field_set(ICMPV4_ID); }
+ | K_SEQ { proto_field_set(ICMPV4_SEQ); }
+ | K_MTU { proto_field_set(ICMPV4_MTU); }
+ | K_ADDR { proto_field_set(ICMPV4_REDIR_ADDR); }
+ ;
+
+icmp4_expr
+ : icmp4_field skip_white '=' skip_white field_expr
+ { proto_field_expr_eval(); }
| K_ECHO_REQUEST
{ proto_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHO);
proto_field_set_u8(hdr, ICMPV4_CODE, 0); }
@@ -872,13 +940,21 @@ icmpv6_proto
icmp6_param_list
: { }
- | icmp6_field { }
- | icmp6_field delimiter icmp6_param_list { }
+ | icmp6_expr { }
+ | icmp6_expr delimiter icmp6_param_list { }
;
icmp6_field
- : K_TYPE skip_white '=' skip_white number
- { proto_field_set_u8(hdr, ICMPV6_TYPE, $5); }
+ : K_CODE { proto_field_set(ICMPV6_CODE); }
+ | K_CSUM { proto_field_set(ICMPV6_CSUM); }
+ ;
+
+icmp6_expr
+ : icmp6_field skip_white '=' skip_white field_expr
+ { proto_field_expr_eval(); }
+ | K_TYPE skip_white '=' skip_white field_expr
+ { proto_field_set(ICMPV6_TYPE);
+ proto_field_expr_eval(); }
| K_TYPE skip_white '=' K_ECHO_REQUEST
{ proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
| K_ECHO_REQUEST
@@ -887,12 +963,7 @@ icmp6_field
{ proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
| K_ECHO_REPLY
{ proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
- | K_CODE skip_white '=' skip_white number
- { proto_field_set_u8(hdr, ICMPV6_CODE, $5); }
- | K_CSUM skip_white '=' skip_white number
- { proto_field_set_be16(hdr, ICMPV6_CSUM, $5); }
;
-
icmp6
: K_ICMP6 { proto_add(PROTO_ICMP6); }
;
@@ -903,19 +974,20 @@ udp_proto
udp_param_list
: { }
- | udp_field { }
- | udp_field delimiter udp_param_list { }
+ | udp_expr { }
+ | udp_expr delimiter udp_param_list { }
;
udp_field
- : K_SPORT skip_white '=' skip_white number
- { proto_field_set_be16(hdr, UDP_SPORT, $5); }
- | K_DPORT skip_white '=' skip_white number
- { proto_field_set_be16(hdr, UDP_DPORT, $5); }
- | K_LEN skip_white '=' skip_white number
- { proto_field_set_be16(hdr, UDP_LEN, $5); }
- | K_CSUM skip_white '=' skip_white number
- { proto_field_set_be16(hdr, UDP_CSUM, $5); }
+ : K_SPORT { proto_field_set(UDP_SPORT); }
+ | K_DPORT { proto_field_set(UDP_DPORT); }
+ | K_LEN { proto_field_set(UDP_LEN); }
+ | K_CSUM { proto_field_set(UDP_CSUM); }
+ ;
+
+udp_expr
+ : udp_field skip_white '=' skip_white field_expr
+ { proto_field_expr_eval(); }
;
udp
@@ -928,21 +1000,24 @@ tcp_proto
tcp_param_list
: { }
- | tcp_field { }
- | tcp_field delimiter tcp_param_list { }
+ | tcp_expr { }
+ | tcp_expr delimiter tcp_param_list { }
;
tcp_field
- : K_SPORT skip_white '=' skip_white number
- { proto_field_set_be16(hdr, TCP_SPORT, $5); }
- | K_DPORT skip_white '=' skip_white number
- { proto_field_set_be16(hdr, TCP_DPORT, $5); }
- | K_SEQ skip_white '=' skip_white number
- { proto_field_set_be32(hdr, TCP_SEQ, $5); }
- | K_ACK_SEQ skip_white '=' skip_white number
- { proto_field_set_be32(hdr, TCP_ACK_SEQ, $5); }
- | K_DOFF skip_white '=' skip_white number
- { proto_field_set_be16(hdr, TCP_DOFF, $5); }
+ : K_SPORT { proto_field_set(TCP_SPORT); }
+ | K_DPORT { proto_field_set(TCP_DPORT); }
+ | K_SEQ { proto_field_set(TCP_SEQ); }
+ | K_ACK_SEQ { proto_field_set(TCP_ACK_SEQ); }
+ | K_DOFF { proto_field_set(TCP_DOFF); }
+ | K_WINDOW { proto_field_set(TCP_WINDOW); }
+ | K_CSUM { proto_field_set(TCP_CSUM); }
+ | K_URG_PTR { proto_field_set(TCP_URG_PTR); }
+ ;
+
+tcp_expr
+ : tcp_field skip_white '=' skip_white field_expr
+ { proto_field_expr_eval(); }
| K_CWR { proto_field_set_be16(hdr, TCP_CWR, 1); }
| K_ECE { proto_field_set_be16(hdr, TCP_ECE, 1); }
| K_URG { proto_field_set_be16(hdr, TCP_URG, 1); }
@@ -951,12 +1026,6 @@ tcp_field
| K_RST { proto_field_set_be16(hdr, TCP_RST, 1); }
| K_SYN { proto_field_set_be16(hdr, TCP_SYN, 1); }
| K_FIN { proto_field_set_be16(hdr, TCP_FIN, 1); }
- | K_WINDOW skip_white '=' skip_white number
- { proto_field_set_be16(hdr, TCP_WINDOW, $5); }
- | K_CSUM skip_white '=' skip_white number
- { proto_field_set_be16(hdr, TCP_CSUM, $5); }
- | K_URG_PTR skip_white '=' skip_white number
- { proto_field_set_be16(hdr, TCP_URG_PTR, $5); }
;
tcp
diff --git a/trafgen_proto.c b/trafgen_proto.c
index f4b2828..0b791f7 100644
--- a/trafgen_proto.c
+++ b/trafgen_proto.c
@@ -107,7 +107,7 @@ void proto_header_fields_add(struct proto_hdr *hdr,
}
}
-static struct proto_field *proto_field_by_id(struct proto_hdr *hdr, uint32_t fid)
+struct proto_field *proto_field_by_id(struct proto_hdr *hdr, uint32_t fid)
{
/* Assume the fields are stored in the same order as the respective
* enum, so the index can be used for faster lookup here.
diff --git a/trafgen_proto.h b/trafgen_proto.h
index 2e50402..a8b97eb 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -143,4 +143,6 @@ 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);
+extern struct proto_field *proto_field_by_id(struct proto_hdr *hdr, uint32_t fid);
+
#endif /* TRAFGEN_PROTO_H */