trafgen: man: Add description for 'pfc()' function
[netsniff-ng.git] / trafgen_parser.y
blob8ebf46455153cd7327a5e83f7d44145e735098da
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2012 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
5 * Swiss federal institute of technology (ETH Zurich)
6 * Subject to the GPL, version 2.
7 */
9 /* yaac-func-prefix: yy */
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <stdint.h>
16 #include <stdbool.h>
17 #include <errno.h>
18 #include <libgen.h>
19 #include <signal.h>
20 #include <unistd.h>
21 #include <net/if_arp.h>
22 #include <netinet/in.h>
23 #include <linux/icmp.h>
24 #include <linux/if_ether.h>
25 #include <linux/icmpv6.h>
27 #include "xmalloc.h"
28 #include "trafgen_parser.tab.h"
29 #include "trafgen_conf.h"
30 #include "trafgen_proto.h"
31 #include "trafgen_l2.h"
32 #include "trafgen_l3.h"
33 #include "trafgen_l4.h"
34 #include "built_in.h"
35 #include "die.h"
36 #include "str.h"
37 #include "csum.h"
38 #include "cpp.h"
40 #define YYERROR_VERBOSE 0
41 #define YYDEBUG 0
42 #define YYENABLE_NLS 1
43 #define YYLTYPE_IS_TRIVIAL 1
44 #define ENABLE_NLS 1
46 extern FILE *yyin;
47 extern int yylex(void);
48 extern void yy_scan_string(char *);
49 extern void yylex_destroy();
50 extern void yyerror(const char *);
51 extern int yylineno;
52 extern char *yytext;
54 extern struct packet *packets;
55 extern size_t plen;
57 #define packet_last (plen - 1)
59 #define payload_last (packets[packet_last].len - 1)
61 extern struct packet_dyn *packet_dyn;
62 extern size_t dlen;
64 #define packetd_last (dlen - 1)
66 #define packetdc_last (packet_dyn[packetd_last].clen - 1)
67 #define packetdr_last (packet_dyn[packetd_last].rlen - 1)
68 #define packetds_last (packet_dyn[packetd_last].slen - 1)
70 static int our_cpu, min_cpu = -1, max_cpu = -1;
72 enum field_expr_type_t {
73 FIELD_EXPR_UNKNOWN,
74 FIELD_EXPR_NUMB,
75 FIELD_EXPR_MAC,
76 FIELD_EXPR_IP4_ADDR,
77 FIELD_EXPR_IP6_ADDR,
78 FIELD_EXPR_INC,
79 FIELD_EXPR_RND,
82 struct proto_field_expr {
83 enum field_expr_type_t type;
84 struct proto_field *field;
86 union {
87 struct in_addr ip4_addr;
88 struct in6_addr ip6_addr;
89 long long int number;
90 uint8_t bytes[256];
91 struct proto_field_func func;
92 } val;
95 static struct proto_field_expr field_expr;
96 static struct proto_hdr *hdr;
98 static inline int test_ignore(void)
100 if (min_cpu < 0 && max_cpu < 0)
101 return 0;
102 else if (max_cpu >= our_cpu && min_cpu <= our_cpu)
103 return 0;
104 else
105 return 1;
108 static inline void __init_new_packet_slot(struct packet *slot)
110 slot->payload = NULL;
111 slot->len = 0;
114 static inline void __init_new_counter_slot(struct packet_dyn *slot)
116 slot->cnt = NULL;
117 slot->clen = 0;
120 static inline void __init_new_randomizer_slot(struct packet_dyn *slot)
122 slot->rnd = NULL;
123 slot->rlen = 0;
126 static inline void __init_new_csum_slot(struct packet_dyn *slot)
128 slot->csum = NULL;
129 slot->slen = 0;
132 static inline void __init_new_fields_slot(struct packet_dyn *slot)
134 slot->fields = NULL;
135 slot->flen = 0;
138 static inline void __setup_new_counter(struct counter *c, uint8_t start,
139 uint8_t stop, uint8_t stepping,
140 int type)
142 c->min = start;
143 c->max = stop;
144 c->inc = stepping;
145 c->val = (type == TYPE_INC) ? start : stop;
146 c->off = payload_last;
147 c->type = type;
150 static inline void __setup_new_randomizer(struct randomizer *r)
152 r->off = payload_last;
155 static inline void __setup_new_csum16(struct csum16 *s, off_t from, off_t to,
156 enum csum which)
158 s->off = payload_last - 1;
159 s->from = from;
160 s->to = to;
161 s->which = which;
164 static void realloc_packet(void)
166 if (test_ignore())
167 return;
169 plen++;
170 packets = xrealloc(packets, plen * sizeof(*packets));
172 __init_new_packet_slot(&packets[packet_last]);
174 dlen++;
175 packet_dyn = xrealloc(packet_dyn, dlen * sizeof(*packet_dyn));
177 __init_new_counter_slot(&packet_dyn[packetd_last]);
178 __init_new_randomizer_slot(&packet_dyn[packetd_last]);
179 __init_new_csum_slot(&packet_dyn[packetd_last]);
180 __init_new_fields_slot(&packet_dyn[packetd_last]);
183 struct packet *current_packet(void)
185 return &packets[packet_last];
188 uint32_t current_packet_id(void)
190 return packet_last;
193 struct packet *packet_get(uint32_t id)
195 return &packets[id];
198 static void set_byte(uint8_t val)
200 struct packet *pkt = &packets[packet_last];
202 if (test_ignore())
203 return;
205 pkt->len++;
206 pkt->payload = xrealloc(pkt->payload, pkt->len);
207 pkt->payload[payload_last] = val;
210 static void set_multi_byte(uint8_t *s, size_t len)
212 size_t i;
214 for (i = 0; i < len; ++i)
215 set_byte(s[i]);
218 void set_fill(uint8_t val, size_t len)
220 size_t i;
221 struct packet *pkt = &packets[packet_last];
223 if (test_ignore())
224 return;
226 pkt->len += len;
227 pkt->payload = xrealloc(pkt->payload, pkt->len);
228 for (i = 0; i < len; ++i)
229 pkt->payload[payload_last - i] = val;
232 static void __set_csum16_dynamic(size_t from, size_t to, enum csum which)
234 struct packet *pkt = &packets[packet_last];
235 struct packet_dyn *pktd = &packet_dyn[packetd_last];
237 pkt->len += 2;
238 pkt->payload = xrealloc(pkt->payload, pkt->len);
240 pktd->slen++;
241 pktd->csum = xrealloc(pktd->csum, pktd->slen * sizeof(struct csum16));
243 __setup_new_csum16(&pktd->csum[packetds_last], from, to, which);
246 static void __set_csum16_static(size_t from, size_t to, enum csum which __maybe_unused)
248 struct packet *pkt = &packets[packet_last];
249 uint16_t sum;
250 uint8_t *psum;
252 sum = htons(calc_csum(pkt->payload + from, to - from));
253 psum = (uint8_t *) &sum;
255 set_byte(psum[0]);
256 set_byte(psum[1]);
259 static inline bool is_dynamic_csum(enum csum which)
261 switch (which) {
262 case CSUM_UDP:
263 case CSUM_TCP:
264 case CSUM_UDP6:
265 case CSUM_TCP6:
266 return true;
267 default:
268 return false;
272 static void set_csum16(size_t from, size_t to, enum csum which)
274 struct packet *pkt = &packets[packet_last];
275 struct packet_dyn *pktd = &packet_dyn[packetd_last];
277 if (test_ignore())
278 return;
280 if (to < from) {
281 size_t tmp = to;
283 to = from;
284 from = tmp;
287 bug_on(!(from < to));
289 if (packet_dyn_has_elems(pktd) || to >= pkt->len || is_dynamic_csum(which))
290 __set_csum16_dynamic(from, to, which);
291 else
292 __set_csum16_static(from, to, which);
295 static void set_rnd(size_t len)
297 size_t i;
298 struct packet *pkt = &packets[packet_last];
300 if (test_ignore())
301 return;
303 pkt->len += len;
304 pkt->payload = xrealloc(pkt->payload, pkt->len);
305 for (i = 0; i < len; ++i)
306 pkt->payload[payload_last - i] = (uint8_t) rand();
309 static void set_sequential_inc(uint8_t start, size_t len, uint8_t stepping)
311 size_t i;
312 struct packet *pkt = &packets[packet_last];
314 if (test_ignore())
315 return;
317 pkt->len += len;
318 pkt->payload = xrealloc(pkt->payload, pkt->len);
319 for (i = 0; i < len; ++i) {
320 off_t off = len - 1 - i;
322 pkt->payload[payload_last - off] = start;
323 start += stepping;
327 static void set_sequential_dec(uint8_t start, size_t len, uint8_t stepping)
329 size_t i;
330 struct packet *pkt = &packets[packet_last];
332 if (test_ignore())
333 return;
335 pkt->len += len;
336 pkt->payload = xrealloc(pkt->payload, pkt->len);
337 for (i = 0; i < len; ++i) {
338 int off = len - 1 - i;
340 pkt->payload[payload_last - off] = start;
341 start -= stepping;
345 static void set_dynamic_rnd(void)
347 struct packet *pkt = &packets[packet_last];
348 struct packet_dyn *pktd = &packet_dyn[packetd_last];
350 if (test_ignore())
351 return;
353 pkt->len++;
354 pkt->payload = xrealloc(pkt->payload, pkt->len);
356 pktd->rlen++;
357 pktd->rnd = xrealloc(pktd->rnd, pktd->rlen * sizeof(struct randomizer));
359 __setup_new_randomizer(&pktd->rnd[packetdr_last]);
362 static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping,
363 int type)
365 struct packet *pkt = &packets[packet_last];
366 struct packet_dyn *pktd = &packet_dyn[packetd_last];
368 if (test_ignore())
369 return;
371 pkt->len++;
372 pkt->payload = xrealloc(pkt->payload, pkt->len);
374 pktd->clen++;
375 pktd->cnt = xrealloc(pktd->cnt, pktd->clen * sizeof(struct counter));
377 __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type);
380 static void proto_add(enum proto_id pid)
382 hdr = proto_header_push(pid);
385 static void proto_field_set(uint32_t fid)
387 field_expr.field = proto_field_by_id(hdr, fid);
390 static void proto_field_func_setup(struct proto_field *field, struct proto_field_func *func)
392 struct packet_dyn *pkt_dyn;
394 proto_field_func_add(field->hdr, field->id, func);
396 pkt_dyn = &packet_dyn[packetd_last];
397 pkt_dyn->flen++;
398 pkt_dyn->fields = xrealloc(pkt_dyn->fields, pkt_dyn->flen *
399 sizeof(struct proto_field *));
400 pkt_dyn->fields[pkt_dyn->flen - 1] = field;
403 static void proto_field_expr_eval(void)
405 struct proto_field *field = field_expr.field;
407 switch (field_expr.type) {
408 case FIELD_EXPR_NUMB:
409 if (field->len == 1)
410 proto_field_set_u8(hdr, field->id, field_expr.val.number);
411 else if (field->len == 2)
412 proto_field_set_be16(hdr, field->id, field_expr.val.number);
413 else if (field->len == 4)
414 proto_field_set_be32(hdr, field->id, field_expr.val.number);
415 else
416 bug();
417 break;
419 case FIELD_EXPR_MAC:
420 proto_field_set_bytes(hdr, field->id, field_expr.val.bytes);
421 break;
423 case FIELD_EXPR_IP4_ADDR:
424 proto_field_set_u32(hdr, field->id, field_expr.val.ip4_addr.s_addr);
425 break;
427 case FIELD_EXPR_IP6_ADDR:
428 proto_field_set_bytes(hdr, field->id,
429 (uint8_t *)&field_expr.val.ip6_addr.s6_addr);
430 break;
432 case FIELD_EXPR_INC:
433 case FIELD_EXPR_RND:
434 if (field_expr.val.func.min
435 && field_expr.val.func.min >= field_expr.val.func.max)
436 panic("dinc(): min(%u) can't be >= max(%u)\n",
437 field_expr.val.func.min, field_expr.val.func.max);
439 proto_field_func_setup(field, &field_expr.val.func);
440 break;
442 case FIELD_EXPR_UNKNOWN:
443 default:
444 bug();
447 memset(&field_expr, 0, sizeof(field_expr));
452 %union {
453 struct in_addr ip4_addr;
454 struct in6_addr ip6_addr;
455 long long int number;
456 uint8_t bytes[256];
457 char *str;
460 %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE
461 %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CSUMUDP6 K_CSUMTCP6 K_CONST8 K_CONST16 K_CONST32 K_CONST64
463 %token K_DADDR K_SADDR K_ETYPE K_TYPE
464 %token K_TIME K_PRIO
465 %token K_OPER K_SHA K_SPA K_THA K_TPA K_REQUEST K_REPLY K_PTYPE K_HTYPE
466 %token K_PROT K_TTL K_DSCP K_ECN K_TOS K_LEN K_ID K_FLAGS K_FRAG K_IHL K_VER K_CSUM K_DF K_MF
467 %token K_FLOW K_NEXT_HDR K_HOP_LIMIT
468 %token K_CODE K_ECHO_REQUEST K_ECHO_REPLY
469 %token K_SPORT K_DPORT
470 %token K_SEQ K_ACK_SEQ K_DOFF K_CWR K_ECE K_URG K_ACK K_PSH K_RST K_SYN K_FIN K_WINDOW K_URG_PTR
471 %token K_TPID K_TCI K_PCP K_DEI K_1Q K_1AD
472 %token K_LABEL K_TC K_LAST K_EXP
474 %token K_ADDR K_MTU
476 %token K_ETH
477 %token K_PAUSE
478 %token K_PFC
479 %token K_VLAN K_MPLS
480 %token K_ARP
481 %token K_IP4 K_IP6
482 %token K_ICMP4 K_ICMP6
483 %token K_UDP K_TCP
485 %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
487 %token number string mac ip4_addr ip6_addr
489 %type <number> number expression
490 %type <str> string
491 %type <bytes> mac
492 %type <ip4_addr> ip4_addr
493 %type <ip6_addr> ip6_addr
495 %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^'
499 packets
500 : { }
501 | packets packet { }
502 | packets inline_comment { }
503 | packets K_WHITE { }
506 inline_comment
507 : K_COMMENT { }
510 cpu_delim
511 : ':' { }
512 | '-' { }
515 delimiter_nowhite
516 : ',' { }
517 | ',' K_WHITE { }
520 noenforce_white
521 : { }
522 | K_WHITE { }
523 | delimiter_nowhite { }
526 skip_white
527 : { }
528 | K_WHITE { }
530 packet
531 : '{' noenforce_white payload noenforce_white '}' {
532 min_cpu = max_cpu = -1;
534 proto_packet_finish();
536 realloc_packet();
538 | K_CPU '(' number cpu_delim number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
539 min_cpu = $3;
540 max_cpu = $5;
542 if (min_cpu > max_cpu) {
543 int tmp = min_cpu;
545 min_cpu = max_cpu;
546 max_cpu = tmp;
549 proto_packet_finish();
551 realloc_packet();
553 | K_CPU '(' number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' {
554 min_cpu = max_cpu = $3;
556 proto_packet_finish();
558 realloc_packet();
562 payload
563 : elem { }
564 | payload elem_delimiter { }
567 delimiter
568 : delimiter_nowhite { }
569 | K_WHITE { }
572 elem_delimiter
573 : delimiter elem { }
576 elem
577 : number { set_byte((uint8_t) $1); }
578 | string { set_multi_byte((uint8_t *) $1 + 1, strlen($1) - 2); }
579 | fill { }
580 | rnd { }
581 | drnd { }
582 | seqinc { }
583 | seqdec { }
584 | dinc { }
585 | ddec { }
586 | csum { }
587 | const { }
588 | proto { proto_header_finish(hdr); }
589 | inline_comment { }
592 expression
593 : number
594 { $$ = $1; }
595 | expression '+' expression
596 { $$ = $1 + $3; }
597 | expression '-' expression
598 { $$ = $1 - $3; }
599 | expression '*' expression
600 { $$ = $1 * $3; }
601 | expression '/' expression
602 { $$ = $1 / $3; }
603 | expression '%' expression
604 { $$ = $1 % $3; }
605 | expression '&' expression
606 { $$ = $1 & $3; }
607 | expression '|' expression
608 { $$ = $1 | $3; }
609 | expression '^' expression
610 { $$ = $1 ^ $3; }
611 | expression '<' '<' expression
612 { $$ = $1 << $4; }
613 | expression '>' '>' expression
614 { $$ = $1 >> $4; }
615 | '-' expression
616 { $$ = -1 * $2; }
617 | '(' expression ')'
618 { $$ = $2;}
621 fill
622 : K_FILL '(' number delimiter number ')'
623 { set_fill($3, $5); }
626 const
627 : K_CONST8 '(' expression ')'
628 { set_byte((uint8_t) $3); }
629 | K_CONST16 '(' expression ')' {
630 uint16_t __c = cpu_to_be16((uint16_t) $3);
632 set_multi_byte((uint8_t *) &__c, sizeof(__c));
634 | K_CONST32 '(' expression ')' {
635 uint32_t __c = cpu_to_be32((uint32_t) $3);
637 set_multi_byte((uint8_t *) &__c, sizeof(__c));
639 | K_CONST64 '(' expression ')' {
640 uint64_t __c = cpu_to_be64((uint64_t) $3);
642 set_multi_byte((uint8_t *) &__c, sizeof(__c));
647 : K_RND '(' number ')'
648 { set_rnd($3); }
651 csum
652 : K_CSUMIP '(' number delimiter number ')'
653 { set_csum16($3, $5, CSUM_IP); }
654 | K_CSUMTCP '(' number delimiter number ')'
655 { set_csum16($3, $5, CSUM_TCP); }
656 | K_CSUMUDP '(' number delimiter number ')'
657 { set_csum16($3, $5, CSUM_UDP); }
658 | K_CSUMTCP6 '(' number delimiter number ')'
659 { set_csum16($3, $5, CSUM_TCP6); }
660 | K_CSUMUDP6 '(' number delimiter number ')'
661 { set_csum16($3, $5, CSUM_UDP6); }
664 seqinc
665 : K_SEQINC '(' number delimiter number ')'
666 { set_sequential_inc($3, $5, 1); }
667 | K_SEQINC '(' number delimiter number delimiter number ')'
668 { set_sequential_inc($3, $5, $7); }
671 seqdec
672 : K_SEQDEC '(' number delimiter number ')'
673 { set_sequential_dec($3, $5, 1); }
674 | K_SEQDEC '(' number delimiter number delimiter number ')'
675 { set_sequential_dec($3, $5, $7); }
678 drnd
679 : K_DRND '(' ')'
680 { set_dynamic_rnd(); }
681 | K_DRND '(' number ')'
683 int i, max = $3;
684 for (i = 0; i < max; ++i)
685 set_dynamic_rnd();
689 dinc
690 : K_DINC '(' number delimiter number ')'
691 { set_dynamic_incdec($3, $5, 1, TYPE_INC); }
692 | K_DINC '(' number delimiter number delimiter number ')'
693 { set_dynamic_incdec($3, $5, $7, TYPE_INC); }
696 ddec
697 : K_DDEC '(' number delimiter number ')'
698 { set_dynamic_incdec($3, $5, 1, TYPE_DEC); }
699 | K_DDEC '(' number delimiter number delimiter number ')'
700 { set_dynamic_incdec($3, $5, $7, TYPE_DEC); }
703 proto
704 : eth_proto { }
705 | pause_proto { }
706 | pfc_proto { }
707 | vlan_proto { }
708 | mpls_proto { }
709 | arp_proto { }
710 | ip4_proto { }
711 | ip6_proto { }
712 | icmp4_proto { }
713 | icmpv6_proto { }
714 | udp_proto { }
715 | tcp_proto { }
718 field_expr
719 : number { field_expr.type = FIELD_EXPR_NUMB;
720 field_expr.val.number = $1; }
721 | mac { field_expr.type = FIELD_EXPR_MAC;
722 memcpy(field_expr.val.bytes, $1, sizeof(field_expr.val.bytes)); }
723 | ip4_addr { field_expr.type = FIELD_EXPR_IP4_ADDR;
724 field_expr.val.ip4_addr = $1; }
725 | ip6_addr { field_expr.type = FIELD_EXPR_IP6_ADDR;
726 field_expr.val.ip6_addr = $1; }
727 | K_DINC '(' ')' { field_expr.type = FIELD_EXPR_INC;
728 field_expr.val.func.type = PROTO_FIELD_FUNC_INC;
729 field_expr.val.func.inc = 1; }
730 | K_DINC '(' number ')'
731 { field_expr.type = FIELD_EXPR_INC;
732 field_expr.val.func.type = PROTO_FIELD_FUNC_INC;
733 field_expr.val.func.inc = $3; }
734 | K_DINC '(' number delimiter number ')'
735 { field_expr.type = FIELD_EXPR_INC;
736 field_expr.val.func.type = PROTO_FIELD_FUNC_INC;
737 field_expr.val.func.type |= PROTO_FIELD_FUNC_MIN;
738 field_expr.val.func.min = $3;
739 field_expr.val.func.max = $5;
740 field_expr.val.func.inc = 1; }
741 | K_DINC '(' number delimiter number delimiter number ')'
742 { field_expr.type = FIELD_EXPR_INC;
743 field_expr.val.func.type = PROTO_FIELD_FUNC_INC;
744 field_expr.val.func.type |= PROTO_FIELD_FUNC_MIN;
745 field_expr.val.func.min = $3;
746 field_expr.val.func.max = $5;
747 field_expr.val.func.inc = $7; }
748 | K_DRND '(' ')' { field_expr.type = FIELD_EXPR_RND;
749 field_expr.val.func.type = PROTO_FIELD_FUNC_RND; }
750 | K_DRND '(' number delimiter number ')'
751 { field_expr.type = FIELD_EXPR_RND;
752 field_expr.val.func.type = PROTO_FIELD_FUNC_RND;
753 field_expr.val.func.min = $3;
754 field_expr.val.func.max = $5; }
757 eth_proto
758 : eth '(' eth_param_list ')' { }
762 : K_ETH { proto_add(PROTO_ETH); }
765 eth_param_list
766 : { }
767 | eth_expr { }
768 | eth_expr delimiter eth_param_list { }
771 eth_type
772 : K_ETYPE { }
773 | K_TYPE { }
774 | K_PROT { }
777 eth_field
778 : K_DADDR { proto_field_set(ETH_DST_ADDR); }
779 | K_SADDR { proto_field_set(ETH_SRC_ADDR); }
780 | eth_type { proto_field_set(ETH_TYPE); }
782 eth_expr
783 : eth_field skip_white '=' skip_white field_expr
784 { proto_field_expr_eval(); }
787 pause_proto
788 : pause '(' pause_param_list ')' { }
791 pause
792 : K_PAUSE { proto_add(PROTO_PAUSE); }
795 pause_param_list
796 : { }
797 | pause_expr { }
798 | pause_expr delimiter pause_param_list { }
801 pause_field
802 : K_CODE { proto_field_set(PAUSE_OPCODE); }
803 | K_TIME { proto_field_set(PAUSE_TIME); }
806 pause_expr
807 : pause_field skip_white '=' skip_white field_expr
808 { proto_field_expr_eval(); }
811 pfc_proto
812 : pfc '(' pfc_param_list ')' { }
816 : K_PFC { proto_add(PROTO_PFC); }
819 pfc_param_list
820 : { }
821 | pfc_expr { }
822 | pfc_expr delimiter pfc_param_list { }
825 pfc_field
826 : K_CODE { proto_field_set(PFC_OPCODE); }
827 | K_PRIO { proto_field_set(PFC_PRIO); }
828 | K_PRIO '(' number ')'
829 { if ($3 > 7) {
830 yyerror("pfc: Invalid prio(index) parameter");
831 panic("pfc: prio(0)..prio(7) is allowed only\n");
833 proto_field_set(PFC_PRIO_0 + $3); }
834 | K_TIME '(' number ')'
835 { if ($3 > 7) {
836 yyerror("pfc: Invalid time(index) parameter");
837 panic("pfc: time(0)..time(7) is allowed only\n");
839 proto_field_set(PFC_TIME_0 + $3); }
842 pfc_expr
843 : pfc_field skip_white '=' skip_white field_expr
844 { proto_field_expr_eval(); }
847 vlan_proto
848 : vlan '(' vlan_param_list ')' { }
851 vlan
852 : K_VLAN { proto_add(PROTO_VLAN); }
855 vlan_param_list
856 : { }
857 | vlan_expr { }
858 | vlan_expr delimiter vlan_param_list { }
861 vlan_type
862 : K_TPID { }
863 | K_PROT
866 vlan_field
867 : vlan_type { proto_field_set(VLAN_TPID); }
868 | K_TCI { proto_field_set(VLAN_TCI); }
869 | K_PCP { proto_field_set(VLAN_PCP); }
870 | K_DEI { proto_field_set(VLAN_DEI); }
871 | K_ID { proto_field_set(VLAN_VID); }
874 vlan_expr
875 : vlan_field skip_white '=' skip_white field_expr
876 { proto_field_expr_eval(); }
877 | K_1Q
878 { proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021Q); }
879 | K_1AD
880 { proto_field_set_be16(hdr, VLAN_TPID, ETH_P_8021AD); }
883 mpls_proto
884 : mpls '(' mpls_param_list ')' { }
887 mpls
888 : K_MPLS { proto_add(PROTO_MPLS); }
891 mpls_param_list
892 : { }
893 | mpls_expr { }
894 | mpls_expr delimiter mpls_param_list { }
897 mpls_tc
898 : K_TC { }
899 | K_EXP { }
902 mpls_field
903 : K_LABEL { proto_field_set(MPLS_LABEL); }
904 | mpls_tc { proto_field_set(MPLS_TC); }
905 | K_LAST { proto_field_set(MPLS_LAST); }
906 | K_TTL { proto_field_set(MPLS_TTL); }
909 mpls_expr
910 : mpls_field skip_white '=' skip_white field_expr
911 { proto_field_expr_eval(); }
913 arp_proto
914 : arp '(' arp_param_list ')' { }
917 arp_param_list
918 : { }
919 | arp_expr { }
920 | arp_expr delimiter arp_param_list { }
923 arp_field
924 : K_HTYPE
925 { proto_field_set(ARP_HTYPE); }
926 | K_PTYPE
927 { proto_field_set(ARP_PTYPE); }
928 | K_SHA
929 { proto_field_set(ARP_SHA); }
930 | K_THA
931 { proto_field_set(ARP_THA); }
932 | K_SPA
933 { proto_field_set(ARP_SPA); }
934 | K_TPA
935 { proto_field_set(ARP_TPA); }
938 arp_expr
939 : arp_field skip_white '=' skip_white field_expr
940 { proto_field_expr_eval(); }
941 | K_OPER skip_white '=' skip_white field_expr
942 { proto_field_set(ARP_OPER);
943 proto_field_expr_eval(); }
944 | K_OPER skip_white '=' skip_white K_REQUEST
945 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
946 | K_OPER skip_white '=' skip_white K_REPLY
947 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
948 | K_REQUEST
949 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REQUEST); }
950 | K_REPLY
951 { proto_field_set_be16(hdr, ARP_OPER, ARPOP_REPLY); }
954 : K_ARP { proto_add(PROTO_ARP); }
957 ip4_proto
958 : ip4 '(' ip4_param_list ')' { }
961 ip4_param_list
962 : { }
963 | ip4_expr { }
964 | ip4_expr delimiter ip4_param_list { }
967 ip4_field
968 : K_VER { proto_field_set(IP4_VER); }
969 | K_IHL { proto_field_set(IP4_IHL); }
970 | K_DADDR { proto_field_set(IP4_DADDR); }
971 | K_SADDR { proto_field_set(IP4_SADDR); }
972 | K_PROT { proto_field_set(IP4_PROTO); }
973 | K_TTL { proto_field_set(IP4_TTL); }
974 | K_DSCP { proto_field_set(IP4_DSCP); }
975 | K_ECN { proto_field_set(IP4_ECN); }
976 | K_TOS { proto_field_set(IP4_TOS); }
977 | K_LEN { proto_field_set(IP4_LEN); }
978 | K_ID { proto_field_set(IP4_ID); }
979 | K_FLAGS { proto_field_set(IP4_FLAGS); }
980 | K_FRAG { proto_field_set(IP4_FRAG_OFFS); }
981 | K_CSUM { proto_field_set(IP4_CSUM); }
984 ip4_expr
985 : ip4_field skip_white '=' skip_white field_expr
986 { proto_field_expr_eval(); }
987 | K_DF { proto_field_set_be16(hdr, IP4_DF, 1); }
988 | K_MF { proto_field_set_be16(hdr, IP4_MF, 1); }
992 : K_IP4 { proto_add(PROTO_IP4); }
995 ip6_proto
996 : ip6 '(' ip6_param_list ')' { }
999 ip6_param_list
1000 : { }
1001 | ip6_expr { }
1002 | ip6_expr delimiter ip6_param_list { }
1005 ip6_hop_limit
1006 : K_HOP_LIMIT { }
1007 | K_TTL { }
1010 ip6_field
1011 : K_VER { proto_field_set(IP6_VER); }
1012 | K_TC { proto_field_set(IP6_CLASS); }
1013 | K_FLOW { proto_field_set(IP6_FLOW_LBL); }
1014 | K_LEN { proto_field_set(IP6_LEN); }
1015 | K_NEXT_HDR { proto_field_set(IP6_NEXT_HDR); }
1016 | ip6_hop_limit { proto_field_set(IP6_HOP_LIMIT); }
1017 | K_SADDR { proto_field_set(IP6_SADDR); }
1018 | K_DADDR { proto_field_set(IP6_DADDR) ; }
1021 ip6_expr
1022 : ip6_field skip_white '=' skip_white field_expr
1023 { proto_field_expr_eval(); }
1027 : K_IP6 { proto_add(PROTO_IP6); }
1030 icmp4_proto
1031 : icmp4 '(' icmp4_param_list ')' { }
1034 icmp4_param_list
1035 : { }
1036 | icmp4_expr { }
1037 | icmp4_expr delimiter icmp4_param_list { }
1040 icmp4_field
1041 : K_TYPE { proto_field_set(ICMPV4_TYPE); }
1042 | K_CODE { proto_field_set(ICMPV4_CODE); }
1043 | K_ID { proto_field_set(ICMPV4_ID); }
1044 | K_SEQ { proto_field_set(ICMPV4_SEQ); }
1045 | K_MTU { proto_field_set(ICMPV4_MTU); }
1046 | K_ADDR { proto_field_set(ICMPV4_REDIR_ADDR); }
1049 icmp4_expr
1050 : icmp4_field skip_white '=' skip_white field_expr
1051 { proto_field_expr_eval(); }
1052 | K_ECHO_REQUEST
1053 { proto_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHO);
1054 proto_field_set_u8(hdr, ICMPV4_CODE, 0); }
1055 | K_ECHO_REPLY
1056 { proto_field_set_u8(hdr, ICMPV4_TYPE, ICMP_ECHOREPLY);
1057 proto_field_set_u8(hdr, ICMPV4_CODE, 0); }
1060 icmp4
1061 : K_ICMP4 { proto_add(PROTO_ICMP4); }
1064 icmpv6_proto
1065 : icmp6 '(' icmp6_param_list ')' { }
1067 icmp6_param_list
1068 : { }
1069 | icmp6_expr { }
1070 | icmp6_expr delimiter icmp6_param_list { }
1073 icmp6_field
1074 : K_CODE { proto_field_set(ICMPV6_CODE); }
1075 | K_CSUM { proto_field_set(ICMPV6_CSUM); }
1078 icmp6_expr
1079 : icmp6_field skip_white '=' skip_white field_expr
1080 { proto_field_expr_eval(); }
1081 | K_TYPE skip_white '=' skip_white field_expr
1082 { proto_field_set(ICMPV6_TYPE);
1083 proto_field_expr_eval(); }
1084 | K_TYPE skip_white '=' K_ECHO_REQUEST
1085 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
1086 | K_ECHO_REQUEST
1087 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REQUEST); }
1088 | K_TYPE skip_white '=' K_ECHO_REPLY
1089 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
1090 | K_ECHO_REPLY
1091 { proto_field_set_u8(hdr, ICMPV6_TYPE, ICMPV6_ECHO_REPLY); }
1093 icmp6
1094 : K_ICMP6 { proto_add(PROTO_ICMP6); }
1097 udp_proto
1098 : udp '(' udp_param_list ')' { }
1101 udp_param_list
1102 : { }
1103 | udp_expr { }
1104 | udp_expr delimiter udp_param_list { }
1107 udp_field
1108 : K_SPORT { proto_field_set(UDP_SPORT); }
1109 | K_DPORT { proto_field_set(UDP_DPORT); }
1110 | K_LEN { proto_field_set(UDP_LEN); }
1111 | K_CSUM { proto_field_set(UDP_CSUM); }
1114 udp_expr
1115 : udp_field skip_white '=' skip_white field_expr
1116 { proto_field_expr_eval(); }
1120 : K_UDP { proto_add(PROTO_UDP); }
1123 tcp_proto
1124 : tcp '(' tcp_param_list ')' { }
1127 tcp_param_list
1128 : { }
1129 | tcp_expr { }
1130 | tcp_expr delimiter tcp_param_list { }
1133 tcp_field
1134 : K_SPORT { proto_field_set(TCP_SPORT); }
1135 | K_DPORT { proto_field_set(TCP_DPORT); }
1136 | K_SEQ { proto_field_set(TCP_SEQ); }
1137 | K_ACK_SEQ { proto_field_set(TCP_ACK_SEQ); }
1138 | K_DOFF { proto_field_set(TCP_DOFF); }
1139 | K_WINDOW { proto_field_set(TCP_WINDOW); }
1140 | K_CSUM { proto_field_set(TCP_CSUM); }
1141 | K_URG_PTR { proto_field_set(TCP_URG_PTR); }
1144 tcp_expr
1145 : tcp_field skip_white '=' skip_white field_expr
1146 { proto_field_expr_eval(); }
1147 | K_CWR { proto_field_set_be16(hdr, TCP_CWR, 1); }
1148 | K_ECE { proto_field_set_be16(hdr, TCP_ECE, 1); }
1149 | K_URG { proto_field_set_be16(hdr, TCP_URG, 1); }
1150 | K_ACK { proto_field_set_be16(hdr, TCP_ACK, 1); }
1151 | K_PSH { proto_field_set_be16(hdr, TCP_PSH, 1); }
1152 | K_RST { proto_field_set_be16(hdr, TCP_RST, 1); }
1153 | K_SYN { proto_field_set_be16(hdr, TCP_SYN, 1); }
1154 | K_FIN { proto_field_set_be16(hdr, TCP_FIN, 1); }
1158 : K_TCP { proto_add(PROTO_TCP); }
1163 static void finalize_packet(void)
1165 /* XXX hack ... we allocated one packet pointer too much */
1166 plen--;
1167 dlen--;
1170 static void dump_conf(void)
1172 size_t i, j;
1174 for (i = 0; i < plen; ++i) {
1175 printf("[%zu] pkt\n", i);
1176 printf(" len %zu cnts %zu rnds %zu\n",
1177 packets[i].len,
1178 packet_dyn[i].clen,
1179 packet_dyn[i].rlen);
1181 printf(" payload ");
1182 for (j = 0; j < packets[i].len; ++j)
1183 printf("%02x ", packets[i].payload[j]);
1184 printf("\n");
1186 for (j = 0; j < packet_dyn[i].clen; ++j)
1187 printf(" cnt%zu [%u,%u], inc %u, off %jd type %s\n", j,
1188 packet_dyn[i].cnt[j].min,
1189 packet_dyn[i].cnt[j].max,
1190 packet_dyn[i].cnt[j].inc,
1191 (intmax_t)packet_dyn[i].cnt[j].off,
1192 packet_dyn[i].cnt[j].type == TYPE_INC ?
1193 "inc" : "dec");
1195 for (j = 0; j < packet_dyn[i].rlen; ++j)
1196 printf(" rnd%zu off %jd\n", j,
1197 (intmax_t)packet_dyn[i].rnd[j].off);
1201 void cleanup_packets(void)
1203 size_t i, j;
1205 for (i = 0; i < plen; ++i) {
1206 struct packet *pkt = &packets[i];
1208 if (pkt->len > 0)
1209 xfree(pkt->payload);
1211 for (j = 0; j < pkt->headers_count; j++) {
1212 struct proto_hdr *hdr = pkt->headers[j];
1214 if (hdr->fields)
1215 xfree(hdr->fields);
1216 xfree(hdr);
1220 free(packets);
1222 for (i = 0; i < dlen; ++i) {
1223 free(packet_dyn[i].cnt);
1224 free(packet_dyn[i].rnd);
1225 free(packet_dyn[i].fields);
1228 free(packet_dyn);
1231 void compile_packets(char *file, bool verbose, unsigned int cpu,
1232 bool invoke_cpp, char *const cpp_argv[])
1234 char tmp_file[128];
1235 int ret = -1;
1237 if (access(file, R_OK)) {
1238 fprintf(stderr, "Cannot access %s: %s!\n", file, strerror(errno));
1239 die();
1242 memset(tmp_file, 0, sizeof(tmp_file));
1243 our_cpu = cpu;
1245 if (invoke_cpp) {
1246 if (cpp_exec(file, tmp_file, sizeof(tmp_file), cpp_argv)) {
1247 fprintf(stderr, "Failed to invoke C preprocessor!\n");
1248 goto err;
1250 file = tmp_file;
1253 if (!strncmp("-", file, strlen("-")))
1254 yyin = stdin;
1255 else
1256 yyin = fopen(file, "r");
1257 if (!yyin) {
1258 fprintf(stderr, "Cannot open %s: %s!\n", file, strerror(errno));
1259 goto err;
1262 realloc_packet();
1263 if (yyparse() != 0)
1264 goto err;
1265 finalize_packet();
1267 if (our_cpu == 0 && verbose)
1268 dump_conf();
1270 ret = 0;
1271 err:
1272 if (yyin && yyin != stdin)
1273 fclose(yyin);
1275 if (invoke_cpp)
1276 unlink(tmp_file);
1277 if (ret)
1278 die();
1281 void compile_packets_str(char *str, bool verbose, unsigned int cpu)
1283 int ret = 1;
1285 our_cpu = cpu;
1286 realloc_packet();
1288 yy_scan_string(str);
1289 if (yyparse() != 0)
1290 goto err;
1292 finalize_packet();
1293 if (our_cpu == 0 && verbose)
1294 dump_conf();
1296 ret = 0;
1297 err:
1298 yylex_destroy();
1300 if (ret)
1301 die();
1304 void yyerror(const char *err)
1306 fprintf(stderr, "Syntax error at line %d, char '%s': %s\n", yylineno, yytext, err);