frameassembly 1.4.4

Compile .fasm code into deterministic .pcap/.pcapng captures across 81 L2-L7 protocols to test firewalls, IDS rules, SNMPv3 traps, Wireshark & Rust.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
//! Layer 2, Layer 3, Layer 4, and SNMP field accumulation for [`FrameBuilder`].
//!
//! This module implements [`FrameBuilder::apply_field`], which updates the statement accumulator's
//! intermediate fields when a [`ParsedField`] modifier is parsed from a frame statement. It handles
//! all universal timing and payload modifiers, Layer 2 Ethernet/VLAN/MPLS/ARP/LLDP/STP/LACP/EAPOL
//! fields, Layer 3 IP/ICMP/NDP/IGMP/MLD/GRE/VXLAN/GENEVE/IPsec/IKEv2/WireGuard/OSPF/BGP/RIP/VRRP/HSRP/PIM/BFD/OpenFlow
//! fields, Layer 4 TCP/UDP/SCTP fields, and SNMPv1/v2c/v3 USM/VarBind attributes, delegating
//! generic Layer 7 attributes to [`FrameBuilder::apply_l7_field`].

use crate::ast::*;
use super::fields::ParsedField;
use super::statement::FrameBuilder;

impl<'a> FrameBuilder<'a> {
    /// Applies a single [`ParsedField`] to the builder state.
    pub(crate) fn apply_field(&mut self, f: &ParsedField<'a>) {
        match f {
            ParsedField::SrcPort(v, span) => {
                self.record_mod("SRCPORT", *span);
                self.src_port = Some(*v);
                self.netflow_spec.srcport = Some(*v);
                self.ipfix_spec.srcport = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::DstPort(v, span) => {
                self.record_mod("DSTPORT", *span);
                self.dst_port = Some(*v);
                self.netflow_spec.dstport = Some(*v);
                self.ipfix_spec.dstport = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Seq(v, span) => {
                self.record_mod("SEQ", *span);
                self.seq = Some(*v);
                self.gre_seq = Some(*v);
                self.tacacs_spec.seq = Some(*v as u8);
                self.rtp_spec.seq = Some(*v as u16);
                self.sflow_spec.seq = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::AckNum(v, span) => {
                self.record_mod("ACKNUM", *span);
                self.ack_num = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Win(v, span) => {
                self.record_mod("WIN", *span);
                self.win = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Payload(v, span) => {
                self.record_mod("PAYLOAD", *span);
                self.payload = Some(v.clone());
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::HexPayload(v, span) => {
                self.record_mod("HEXPAYLOAD", *span);
                self.hex_payload = Some(v.clone());
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Community(v, span) => {
                self.record_mod("COMMUNITY", *span);
                self.community = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::User(v, span) => {
                self.record_mod("USER", *span);
                self.user = Some(*v);
                self.radius_spec.user = Some(*v);
                self.tacacs_spec.user = Some(*v);
                self.mysql_spec.user = Some(*v);
                self.postgres_spec.user = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::SysUpTime(v, span) => {
                self.record_mod("SYSUPTIME", *span);
                self.sys_up_time = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::PduType(v, span) => {
                self.record_mod("PDUTYPE", *span);
                self.pdu_type = Some(v.clone());
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Wait(v, span) => {
                self.record_mod("WAIT", *span);
                self.wait = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Oid(v, span) => {
                self.record_mod("OID", *span);
                self.oid = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Flag(flag, span) => {
                self.flags.push(flag.clone());
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Enterprise(v, span) => {
                self.record_mod("ENTERPRISE", *span);
                self.enterprise = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::AgentIp(v, span) => {
                self.record_mod("AGENTIP", *span);
                self.agent_ip = Some(*v);
                self.sflow_spec.agent_ip = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::GenTrap(v, span) => {
                self.record_mod("GENTRAP", *span);
                self.gen_trap = Some(*v);
                self.gentrap_span = Some(*span);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::SpecTrap(v, span) => {
                self.record_mod("SPECTRAP", *span);
                self.spec_trap = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::EngineId(v, span) => {
                self.record_mod("ENGINEID", *span);
                self.engine_id = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::EngineBoots(v, span) => {
                self.record_mod("ENGINEBOOTS", *span);
                self.engine_boots = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::EngineTime(v, span) => {
                self.record_mod("ENGINETIME", *span);
                self.engine_time = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::ContextName(v, span) => {
                self.record_mod("CONTEXTNAME", *span);
                self.context_name = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Auth(t, p, span) => {
                self.record_mod("AUTH", *span);
                self.auth = Some((t.clone(), *p));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Priv(t, p, span) => {
                self.record_mod("PRIV", *span);
                self.priv_param = Some((t.clone(), *p));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::VarBind(v, span) => {
                self.varbinds.push(v.clone());
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::NonRepeaters(v, span) => {
                self.record_mod("NONREPEATERS", *span);
                self.non_repeaters = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::MaxRepetitions(v, span) => {
                self.record_mod("MAXREPETITIONS", *span);
                self.max_repetitions = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::ReqId(v, span) => {
                self.record_mod("REQID", *span);
                self.req_id = Some(*v);
                self.opcua_spec.req_id = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Vlan(v, span) => {
                self.record_mod("VLAN", *span);
                self.vlan_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Dscp(v, span) => {
                self.record_mod("DSCP", *span);
                self.dscp_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Ecn(v, span) => {
                self.record_mod("ECN", *span);
                self.ecn_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Ttl(v, span) => {
                self.record_mod("TTL", *span);
                self.ttl_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::FlowLabel(v, span) => {
                self.record_mod("FLOWLABEL", *span);
                self.flowlabel_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Protocol(p, span) => {
                self.record_mod("PROTOCOL", *span);
                self.protocol = Some(p.clone());
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Pcp(v, span) => {
                self.record_mod("PCP", *span);
                self.pcp_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Dei(v, span) => {
                self.record_mod("DEI", *span);
                self.dei_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Qinq(v, span) => {
                self.record_mod("QINQ", *span);
                self.qinq_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::InnerVlan(v, span) => {
                self.record_mod("INNER_VLAN", *span);
                self.inner_vlan_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Mpls(v, span) => {
                self.record_mod("MPLS", *span);
                self.mpls_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Exp(v, span) => {
                self.record_mod("EXP", *span);
                self.exp_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Bos(v, span) => {
                self.record_mod("BOS", *span);
                self.bos_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::MplsTtl(v, span) => {
                self.record_mod("MPLS_TTL", *span);
                self.mpls_ttl_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::SrcMac(v, span) => {
                self.record_mod("SRCMAC", *span);
                self.src_mac_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::DstMac(v, span) => {
                self.record_mod("DSTMAC", *span);
                self.dst_mac_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::EtherType(v, span) => {
                self.record_mod("ETHERTYPE", *span);
                self.ethertype_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::IpId(v, span) => {
                self.record_mod("IPID", *span);
                self.ipid_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Df(span) => {
                self.record_mod("DF", *span);
                self.df_val = true;
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Mf(span) => {
                self.record_mod("MF", *span);
                self.mf_val = true;
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::FragOffset(v, span) => {
                self.record_mod("FRAGOFFSET", *span);
                self.frag_offset_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Transport(v, span) => {
                self.record_mod("TRANSPORT", *span);
                self.transport_val = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Urgent(v, span) => {
                self.record_mod("URGENT", *span);
                self.urgent_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Mss(v, span) => {
                self.record_mod("MSS", *span);
                self.mss_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Wscale(v, span) => {
                self.record_mod("WSCALE", *span);
                self.wscale_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::SackPerm(span) => {
                self.record_mod("SACK_PERM", *span);
                self.sack_perm_val = true;
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Tsval(v, span) => {
                self.record_mod("TSVAL", *span);
                self.tsval_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Tsecr(v, span) => {
                self.record_mod("TSECR", *span);
                self.tsecr_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Vtag(v, span) => {
                self.record_mod("VTAG", *span);
                self.vtag_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Stream(v, span) => {
                self.record_mod("STREAM", *span);
                self.stream_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Ssn(v, span) => {
                self.record_mod("SSN", *span);
                self.ssn_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Ppid(v, span) => {
                self.record_mod("PPID", *span);
                self.ppid_val = Some((*v, *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Chunk(v, span) => {
                self.record_mod("CHUNK", *span);
                self.chunk_val = Some((v.clone(), *span));
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::ArpOpcode(v, span) => {
                self.record_mod("OPCODE", *span);
                self.arp_opcode = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Gratuitous(span) => {
                self.record_mod("GARP", *span);
                self.is_gratuitous = true;
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Sha(v, span) => {
                self.record_mod("SHA", *span);
                self.sha = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Spa(v, span) => {
                self.record_mod("SPA", *span);
                self.spa = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Tha(v, span) => {
                self.record_mod("THA", *span);
                self.tha = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Tpa(v, span) => {
                self.record_mod("TPA", *span);
                self.tpa = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::ChassisId(v, span) => {
                self.record_mod("CHASSIS_ID", *span);
                self.chassis_id = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::PortIdVal(ps, pu, span) => {
                self.record_mod("PORT_ID", *span);
                if let Some(s) = ps {
                    self.port_id_str = Some(*s);
                }
                if let Some(u) = pu {
                    self.port_id_u16 = Some(*u);
                }
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::SysName(v, span) => {
                self.record_mod("SYSNAME", *span);
                self.sysname = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::SysDesc(v, span) => {
                self.record_mod("SYSDESC", *span);
                self.sysdesc = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::RootId(v, span) => {
                self.record_mod("ROOT_ID", *span);
                self.root_id = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::BridgeId(v, span) => {
                self.record_mod("BRIDGE_ID", *span);
                self.bridge_id = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Cost(v, span) => {
                self.record_mod("COST", *span);
                self.stp_cost = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::MaxAge(v, span) => {
                self.record_mod("MAX_AGE", *span);
                self.max_age = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::HelloTime(v, span) => {
                self.record_mod("HELLO_TIME", *span);
                self.hello_time = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::ForwardDelay(v, span) => {
                self.record_mod("FORWARD_DELAY", *span);
                self.forward_delay = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Rstp(span) => {
                self.record_mod("RSTP", *span);
                self.is_rstp = true;
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::FlagsByte(v, span) => {
                self.record_mod("FLAGS", *span);
                self.stp_flags = Some(*v);
                self.ike_flags = Some(*v);
                self.tacacs_spec.flags = Some(*v);
                self.memcached_spec.flags = Some(*v as u32);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::ActorSys(v, span) => {
                self.record_mod("ACTOR_SYS", *span);
                self.actor_sys = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::ActorKey(v, span) => {
                self.record_mod("ACTOR_KEY", *span);
                self.actor_key = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::ActorPort(v, span) => {
                self.record_mod("ACTOR_PORT", *span);
                self.actor_port = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::PartnerSys(v, span) => {
                self.record_mod("PARTNER_SYS", *span);
                self.partner_sys = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::PartnerKey(v, span) => {
                self.record_mod("PARTNER_KEY", *span);
                self.partner_key = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::PartnerPort(v, span) => {
                self.record_mod("PARTNER_PORT", *span);
                self.partner_port = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::ActorState(v, span) => {
                self.record_mod("ACTOR_STATE", *span);
                self.actor_state = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::PartnerState(v, span) => {
                self.record_mod("PARTNER_STATE", *span);
                self.partner_state = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::VersionByte(v, span) => {
                self.record_mod("VERSION", *span);
                self.version_byte = Some(*v);
                self.quic_spec.version = Some(*v as u32);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::EapolType(v, span) => {
                self.record_mod("EAPOL_TYPE", *span);
                self.eapol_type = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::EapCode(v, span) => {
                self.record_mod("EAP_CODE", *span);
                self.eap_code = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::EapId(v, span) => {
                self.record_mod("EAP_ID", *span);
                self.eap_id = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::EapMethod(v, span) => {
                self.record_mod("EAP_METHOD", *span);
                self.eap_method = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Identity(v, span) => {
                self.record_mod("IDENTITY", *span);
                self.identity_str = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::IcmpTypeChoice(v, span) => {
                self.record_mod("ICMP_TYPE_CHOICE", *span);
                self.icmp_type_choice = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::IcmpId(v, span) => {
                self.record_mod("ICMP_ID", *span);
                self.icmp_id_val = Some(*v);
                self.radius_spec.id = Some(*v as u8);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Gateway(v, span) => {
                self.record_mod("GATEWAY", *span);
                self.gateway_ip = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::NdpType(v, span) => {
                self.record_mod("NDP_TYPE", *span);
                self.ndp_type = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::TargetVal(ip, mac, span) => {
                self.record_mod("TARGET", *span);
                if let Some(i) = ip {
                    self.target_ip = Some(*i);
                }
                if let Some(m) = mac {
                    self.tlla_mac = Some(*m);
                }
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Slla(v, span) => {
                self.record_mod("SLLA", *span);
                self.slla_mac = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Tlla(v, span) => {
                self.record_mod("TLLA", *span);
                self.tlla_mac = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::RouterLifetime(v, span) => {
                self.record_mod("ROUTER_LIFETIME", *span);
                self.router_lifetime = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::IgmpType(v, span) => {
                self.record_mod("IGMP_TYPE", *span);
                self.igmp_type = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::GroupVal(ip, g, span) => {
                self.record_mod("GROUP", *span);
                if let Some(i) = ip {
                    self.group_ip = Some(*i);
                }
                if let Some(u) = g {
                    self.hsrp_group = Some(*u);
                }
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::MaxResp(v, span) => {
                self.record_mod("MAX_RESP", *span);
                self.max_resp = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::MldType(v, span) => {
                self.record_mod("MLD_TYPE", *span);
                self.mld_type = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::MulticastAddr(v, span) => {
                self.record_mod("MULTICAST_ADDR", *span);
                self.multicast_addr = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::MaxRespDelay(v, span) => {
                self.record_mod("MAX_RESP_DELAY", *span);
                self.max_resp_delay = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::GreKey(v, span) => {
                self.record_mod("GRE_KEY", *span);
                self.gre_key = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::GreSeq(v, span) => {
                self.record_mod("GRE_SEQ", *span);
                self.gre_seq = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::GreProto(v, span) => {
                self.record_mod("GRE_PROTO", *span);
                self.gre_proto = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::ChecksumFlag(span) => {
                self.record_mod("CHECKSUM", *span);
                self.gre_checksum = true;
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Vni(v, span) => {
                self.record_mod("VNI", *span);
                self.vni_val = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::OptClass(v, span) => {
                self.record_mod("OPT_CLASS", *span);
                self.opt_class = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::OptType(v, span) => {
                self.record_mod("OPT_TYPE", *span);
                self.opt_type = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::ProtocolType(v, span) => {
                self.record_mod("PROTOCOL_TYPE", *span);
                self.protocol_type = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Spi(v, span) => {
                self.record_mod("SPI", *span);
                self.spi_val = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Iv(v, span) => {
                self.record_mod("IV", *span);
                self.iv_val = Some(v.clone());
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Icv(v, span) => {
                self.record_mod("ICV", *span);
                self.icv_val = Some(v.clone());
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::NextHeader(v, span) => {
                self.record_mod("NEXT_HEADER", *span);
                self.next_header_val = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::InitiatorSpi(v, span) => {
                self.record_mod("INITIATOR_SPI", *span);
                self.initiator_spi = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::ResponderSpi(v, span) => {
                self.record_mod("RESPONDER_SPI", *span);
                self.responder_spi = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::IkeExchange(v, span) => {
                self.record_mod("IKE_EXCHANGE", *span);
                self.ike_exchange = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::MsgId(v, span) => {
                self.record_mod("MSG_ID", *span);
                self.ike_msgid = Some(*v);
                self.ldap_spec.msgid = Some(*v as i32);
                self.coap_spec.msgid = Some(*v as u16);
                self.smb_spec.msgid = Some(*v as u64);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::NextPayload(v, span) => {
                self.record_mod("NEXT_PAYLOAD", *span);
                self.next_payload = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::WireguardType(v, span) => {
                self.record_mod("WG_TYPE", *span);
                self.wireguard_type = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Sender(v, span) => {
                self.record_mod("SENDER", *span);
                self.wg_sender = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Receiver(v, span) => {
                self.record_mod("RECEIVER", *span);
                self.wg_receiver = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Counter(v, span) => {
                self.record_mod("COUNTER", *span);
                self.wg_counter = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::OspfType(v, span) => {
                self.record_mod("OSPF_TYPE", *span);
                self.ospf_type = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::HelloWord(span) => {
                self.pim_is_hello = true;
                if self.ospf_type.is_none() {
                    self.ospf_type = Some(OspfType::Hello);
                }
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::RouterId(v, span) => {
                self.record_mod("ROUTER_ID", *span);
                self.router_id_ip = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::AreaId(v, span) => {
                self.record_mod("AREA_ID", *span);
                self.area_id_val = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::HelloInterval(v, span) => {
                self.record_mod("HELLO_INTERVAL", *span);
                self.hello_interval = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::DeadInterval(v, span) => {
                self.record_mod("DEAD_INTERVAL", *span);
                self.dead_interval = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::PriorityVal(v, span) => {
                self.record_mod("PRIORITY", *span);
                self.priority_val = Some(*v);
                self.of_priority = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::BgpType(v, span) => {
                self.record_mod("BGP_TYPE", *span);
                self.bgp_type = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Asn(v, span) => {
                self.record_mod("ASN", *span);
                self.asn_val = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::HoldTime(v, span) => {
                self.record_mod("HOLD_TIME", *span);
                self.holdtime_val = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::BgpId(v, span) => {
                self.record_mod("BGP_ID", *span);
                self.bgpid_ip = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::PrefixVal(ip, st, span) => {
                self.record_mod("PREFIX", *span);
                if let Some(i) = ip {
                    self.rip_prefix = Some(*i);
                }
                if let Some(s) = st {
                    self.prefix_str = Some(*s);
                }
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::NextHop(v, span) => {
                self.record_mod("NEXT_HOP", *span);
                self.nexthop_ip = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Metric(v, span) => {
                self.record_mod("METRIC", *span);
                self.rip_metric = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::TagVal(u, s, span) => {
                self.record_mod("TAG", *span);
                if let Some(v) = u {
                    self.rip_tag = Some(*v);
                }
                if let Some(str_val) = s {
                    self.imap_spec.tag = Some(*str_val);
                    self.nfs_spec.tag = Some(*str_val);
                }
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Vrid(v, span) => {
                self.record_mod("VRID", *span);
                self.vrid_val = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::AdvInt(v, span) => {
                self.record_mod("ADV_INT", *span);
                self.adv_int_val = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Vip(v, span) => {
                self.record_mod("VIP", *span);
                self.vip_ip = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::HsrpState(v, span) => {
                self.record_mod("STATE", *span);
                self.hsrp_state = Some(*v);
                self.bfd_state = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::HelloTimeHsrp(v, span) => {
                self.record_mod("HELLO_TIME_HSRP", *span);
                self.hsrp_hellotime = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::PimJoinPrune(span) => {
                self.record_mod("JOIN_PRUNE", *span);
                self.pim_is_join_prune = true;
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::PimRegister(span) => {
                self.record_mod("REGISTER", *span);
                self.pim_is_register = true;
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::SourceIp(v, span) => {
                self.record_mod("SOURCE", *span);
                self.pim_source = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Rp(v, span) => {
                self.record_mod("RP", *span);
                self.pim_rp = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::DrPriority(v, span) => {
                self.record_mod("DR_PRIORITY", *span);
                self.pim_dr_priority = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Diag(v, span) => {
                self.record_mod("DIAG", *span);
                self.bfd_diag = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::MyDisc(v, span) => {
                self.record_mod("MY_DISC", *span);
                self.bfd_my_disc = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::YourDisc(v, span) => {
                self.record_mod("YOUR_DISC", *span);
                self.bfd_your_disc = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::MinTx(v, span) => {
                self.record_mod("MIN_TX", *span);
                self.bfd_min_tx = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::MinRx(v, span) => {
                self.record_mod("MIN_RX", *span);
                self.bfd_min_rx = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Mult(v, span) => {
                self.record_mod("MULT", *span);
                self.bfd_mult = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::OpenflowType(v, span) => {
                self.record_mod("OPENFLOW_TYPE", *span);
                self.openflow_type = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Xid(v, span) => {
                self.record_mod("XID", *span);
                self.of_xid = Some(*v);
                self.dhcp_spec.xid = Some(*v);
                self.nfs_spec.xid = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::Dpid(v, span) => {
                self.record_mod("DPID", *span);
                self.of_dpid = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::TableId(v, span) => {
                self.record_mod("TABLE_ID", *span);
                self.of_table_id = Some(*v);
                self.stmt_end_offset = self.stmt_end_offset.max(span.0 + span.1);
            }
            ParsedField::L7StringField(..)
            | ParsedField::L7U32Field(..)
            | ParsedField::L7U64Field(..)
            | ParsedField::L7IpField(..)
            | ParsedField::L7MacField(..)
            | ParsedField::L7Flag(..)
            | ParsedField::L7Header(..) => {
                self.apply_l7_field(f);
            }
        }
    }
}