1#[allow(dead_code)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
24#[repr(u16)]
25pub enum OxmClass {
26 OpenflowBasic = 0x8000,
28 Experimenter = 0xffff,
30 Nxm0 = 0x0000,
32 Nxm1 = 0x0001,
34}
35
36#[allow(dead_code)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
39#[repr(u8)]
40pub enum OxmField {
41 InPort = 0,
43 InPhyPort = 1,
45 Metadata = 2,
47 EthDst = 3,
49 EthSrc = 4,
51 EthType = 5,
53 VlanVid = 6,
55 VlanPcp = 7,
57 IpDscp = 8,
59 IpEcn = 9,
61 IpProto = 10,
63 Ipv4Src = 11,
65 Ipv4Dst = 12,
67 TcpSrc = 13,
69 TcpDst = 14,
71 UdpSrc = 15,
73 UdpDst = 16,
75 SctpSrc = 17,
77 SctpDst = 18,
79 Icmpv4Type = 19,
81 Icmpv4Code = 20,
83 ArpOp = 21,
85 ArpSpa = 22,
87 ArpTpa = 23,
89 ArpSha = 24,
91 ArpTha = 25,
93 Ipv6Src = 26,
95 Ipv6Dst = 27,
97 Ipv6Flabel = 28,
99 Icmpv6Type = 29,
101 Icmpv6Code = 30,
103 TunnelId = 38,
105}
106
107#[allow(dead_code)]
116#[derive(Debug, Clone, Copy, PartialEq, Eq)]
117#[repr(u8)]
118pub enum NxmField {
119 Reg0 = 0,
124 Reg1 = 1,
126 Reg2 = 2,
128 Reg3 = 3,
130 Reg4 = 4,
132 Reg5 = 5,
134 Reg6 = 6,
136 Reg7 = 7,
138 Reg8 = 8,
140 Reg9 = 9,
142 Reg10 = 10,
144 Reg11 = 11,
146 Reg12 = 12,
148 Reg13 = 13,
150 Reg14 = 14,
152 Reg15 = 15,
154
155 TunId = 16,
160 TunIpv4Src = 31,
162 TunIpv4Dst = 32,
164 PktMark = 33,
166
167 CtState = 105,
172 CtZone = 106,
174 CtMark = 107,
176 CtLabel = 108,
178
179 XxReg0 = 111,
184 XxReg1 = 112,
186 XxReg2 = 113,
188 XxReg3 = 114,
190}
191
192#[allow(dead_code)]
196pub mod ct_state {
197 pub const TRK: u32 = 0x20;
199 pub const NEW: u32 = 0x01;
201 pub const EST: u32 = 0x02;
203 pub const REL: u32 = 0x04;
205 pub const RPL: u32 = 0x08;
207 pub const INV: u32 = 0x10;
209 pub const SNAT: u32 = 0x40;
211 pub const DNAT: u32 = 0x80;
213}
214
215#[allow(dead_code)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
221pub struct OxmHeader {
222 pub class: OxmClass,
224 pub field: u8,
226 pub has_mask: bool,
228 pub length: u8,
230}
231
232#[allow(dead_code)] impl OxmHeader {
234 #[must_use]
236 pub const fn new(class: OxmClass, field: u8, has_mask: bool, length: u8) -> Self {
237 Self {
238 class,
239 field,
240 has_mask,
241 length,
242 }
243 }
244
245 #[must_use]
247 pub const fn openflow_basic(field: OxmField, has_mask: bool, length: u8) -> Self {
248 Self {
249 class: OxmClass::OpenflowBasic,
250 field: field as u8,
251 has_mask,
252 length,
253 }
254 }
255
256 #[must_use]
267 pub const fn encode(self) -> [u8; 4] {
268 let class_val = self.class as u16;
269 let field_and_mask = (self.field << 1) | (self.has_mask as u8);
270
271 [
272 (class_val >> 8) as u8, class_val as u8, field_and_mask, self.length, ]
277 }
278
279 #[must_use]
281 pub const fn as_u32(self) -> u32 {
282 let bytes = self.encode();
283 u32::from_be_bytes(bytes)
284 }
285}
286
287#[allow(dead_code)]
295#[must_use]
296pub fn encode_u8(class: OxmClass, field: u8, value: u8) -> Vec<u8> {
297 let header = OxmHeader::new(class, field, false, 1);
298 let mut buf = Vec::with_capacity(5);
299 buf.extend_from_slice(&header.encode());
300 buf.push(value);
301 buf
302}
303
304#[allow(dead_code)]
306#[must_use]
307pub fn encode_u8_field(field: OxmField, value: u8) -> Vec<u8> {
308 encode_u8(OxmClass::OpenflowBasic, field as u8, value)
309}
310
311#[allow(dead_code)]
315#[must_use]
316pub fn encode_u16(class: OxmClass, field: u8, value: u16) -> Vec<u8> {
317 let header = OxmHeader::new(class, field, false, 2);
318 let mut buf = Vec::with_capacity(6);
319 buf.extend_from_slice(&header.encode());
320 buf.extend_from_slice(&value.to_be_bytes());
321 buf
322}
323
324#[allow(dead_code)]
326#[must_use]
327pub fn encode_u16_field(field: OxmField, value: u16) -> Vec<u8> {
328 encode_u16(OxmClass::OpenflowBasic, field as u8, value)
329}
330
331#[allow(dead_code)]
335#[must_use]
336pub fn encode_u16_masked(class: OxmClass, field: u8, value: u16, mask: u16) -> Vec<u8> {
337 let header = OxmHeader::new(class, field, true, 4);
338 let mut buf = Vec::with_capacity(8);
339 buf.extend_from_slice(&header.encode());
340 buf.extend_from_slice(&value.to_be_bytes());
341 buf.extend_from_slice(&mask.to_be_bytes());
342 buf
343}
344
345#[allow(dead_code)]
349#[must_use]
350pub fn encode_u32(class: OxmClass, field: u8, value: u32) -> Vec<u8> {
351 let header = OxmHeader::new(class, field, false, 4);
352 let mut buf = Vec::with_capacity(8);
353 buf.extend_from_slice(&header.encode());
354 buf.extend_from_slice(&value.to_be_bytes());
355 buf
356}
357
358#[allow(dead_code)]
360#[must_use]
361pub fn encode_u32_field(field: OxmField, value: u32) -> Vec<u8> {
362 encode_u32(OxmClass::OpenflowBasic, field as u8, value)
363}
364
365#[allow(dead_code)]
369#[must_use]
370pub fn encode_u64(class: OxmClass, field: u8, value: u64) -> Vec<u8> {
371 let header = OxmHeader::new(class, field, false, 8);
372 let mut buf = Vec::with_capacity(12);
373 buf.extend_from_slice(&header.encode());
374 buf.extend_from_slice(&value.to_be_bytes());
375 buf
376}
377
378#[allow(dead_code)]
380#[must_use]
381pub fn encode_u64_field(field: OxmField, value: u64) -> Vec<u8> {
382 encode_u64(OxmClass::OpenflowBasic, field as u8, value)
383}
384
385#[allow(dead_code)]
389#[must_use]
390pub fn encode_mac(class: OxmClass, field: u8, value: [u8; 6]) -> Vec<u8> {
391 let header = OxmHeader::new(class, field, false, 6);
392 let mut buf = Vec::with_capacity(10);
393 buf.extend_from_slice(&header.encode());
394 buf.extend_from_slice(&value);
395 buf
396}
397
398#[allow(dead_code)]
400#[must_use]
401pub fn encode_mac_field(field: OxmField, value: [u8; 6]) -> Vec<u8> {
402 encode_mac(OxmClass::OpenflowBasic, field as u8, value)
403}
404
405#[allow(dead_code)]
414#[must_use]
415pub fn encode_u32_masked(class: OxmClass, field: u8, value: u32, mask: u32) -> Vec<u8> {
416 let header = OxmHeader::new(class, field, true, 8);
417 let mut buf = Vec::with_capacity(12);
418 buf.extend_from_slice(&header.encode());
419 buf.extend_from_slice(&value.to_be_bytes());
420 buf.extend_from_slice(&mask.to_be_bytes());
421 buf
422}
423
424#[allow(dead_code)]
426#[must_use]
427pub fn encode_u32_masked_field(field: OxmField, value: u32, mask: u32) -> Vec<u8> {
428 encode_u32_masked(OxmClass::OpenflowBasic, field as u8, value, mask)
429}
430
431#[allow(dead_code)]
436#[must_use]
437pub fn encode_mac_masked(class: OxmClass, field: u8, value: [u8; 6], mask: [u8; 6]) -> Vec<u8> {
438 let header = OxmHeader::new(class, field, true, 12);
439 let mut buf = Vec::with_capacity(16);
440 buf.extend_from_slice(&header.encode());
441 buf.extend_from_slice(&value);
442 buf.extend_from_slice(&mask);
443 buf
444}
445
446#[allow(dead_code)]
448#[must_use]
449pub fn encode_mac_masked_field(field: OxmField, value: [u8; 6], mask: [u8; 6]) -> Vec<u8> {
450 encode_mac_masked(OxmClass::OpenflowBasic, field as u8, value, mask)
451}
452
453#[allow(dead_code)]
458#[must_use]
459pub fn encode_u64_masked(class: OxmClass, field: u8, value: u64, mask: u64) -> Vec<u8> {
460 let header = OxmHeader::new(class, field, true, 16);
461 let mut buf = Vec::with_capacity(20);
462 buf.extend_from_slice(&header.encode());
463 buf.extend_from_slice(&value.to_be_bytes());
464 buf.extend_from_slice(&mask.to_be_bytes());
465 buf
466}
467
468#[allow(dead_code)]
470#[must_use]
471pub fn encode_u64_masked_field(field: OxmField, value: u64, mask: u64) -> Vec<u8> {
472 encode_u64_masked(OxmClass::OpenflowBasic, field as u8, value, mask)
473}
474
475#[allow(dead_code, clippy::missing_panics_doc)]
484#[must_use]
485pub fn encode_reg(reg_num: u8, value: u32) -> Vec<u8> {
486 assert!(reg_num <= 15, "Register number must be 0-15");
487 encode_u32(OxmClass::Nxm1, reg_num, value)
488}
489
490#[allow(dead_code, clippy::missing_panics_doc)]
494#[must_use]
495pub fn encode_reg_masked(reg_num: u8, value: u32, mask: u32) -> Vec<u8> {
496 assert!(reg_num <= 15, "Register number must be 0-15");
497 encode_u32_masked(OxmClass::Nxm1, reg_num, value, mask)
498}
499
500#[allow(dead_code)]
502#[must_use]
503pub fn encode_nxm_u32(field: NxmField, value: u32) -> Vec<u8> {
504 encode_u32(OxmClass::Nxm1, field as u8, value)
505}
506
507#[allow(dead_code)]
509#[must_use]
510pub fn encode_nxm_u32_masked(field: NxmField, value: u32, mask: u32) -> Vec<u8> {
511 encode_u32_masked(OxmClass::Nxm1, field as u8, value, mask)
512}
513
514#[allow(dead_code)]
518#[must_use]
519pub fn encode_tun_id(value: u64) -> Vec<u8> {
520 encode_u64(OxmClass::Nxm1, NxmField::TunId as u8, value)
521}
522
523#[allow(dead_code)]
527#[must_use]
528pub fn encode_tun_id_masked(value: u64, mask: u64) -> Vec<u8> {
529 encode_u64_masked(OxmClass::Nxm1, NxmField::TunId as u8, value, mask)
530}
531
532#[allow(dead_code)]
536#[must_use]
537pub fn encode_tun_ipv4_src(addr: u32) -> Vec<u8> {
538 encode_u32(OxmClass::Nxm1, NxmField::TunIpv4Src as u8, addr)
539}
540
541#[allow(dead_code)]
545#[must_use]
546pub fn encode_tun_ipv4_dst(addr: u32) -> Vec<u8> {
547 encode_u32(OxmClass::Nxm1, NxmField::TunIpv4Dst as u8, addr)
548}
549
550#[allow(dead_code)]
554#[must_use]
555pub fn encode_pkt_mark(value: u32) -> Vec<u8> {
556 encode_u32(OxmClass::Nxm1, NxmField::PktMark as u8, value)
557}
558
559#[allow(dead_code)]
563#[must_use]
564pub fn encode_pkt_mark_masked(value: u32, mask: u32) -> Vec<u8> {
565 encode_u32_masked(OxmClass::Nxm1, NxmField::PktMark as u8, value, mask)
566}
567
568#[allow(dead_code)]
574#[must_use]
575pub fn encode_ct_state(state: u32) -> Vec<u8> {
576 encode_u32(OxmClass::Nxm1, NxmField::CtState as u8, state)
577}
578
579#[allow(dead_code)]
583#[must_use]
584pub fn encode_ct_state_masked(state: u32, mask: u32) -> Vec<u8> {
585 encode_u32_masked(OxmClass::Nxm1, NxmField::CtState as u8, state, mask)
586}
587
588#[allow(dead_code)]
592#[must_use]
593pub fn encode_ct_zone(zone: u16) -> Vec<u8> {
594 encode_u16(OxmClass::Nxm1, NxmField::CtZone as u8, zone)
595}
596
597#[allow(dead_code)]
601#[must_use]
602pub fn encode_ct_mark(mark: u32) -> Vec<u8> {
603 encode_u32(OxmClass::Nxm1, NxmField::CtMark as u8, mark)
604}
605
606#[allow(dead_code, clippy::similar_names)]
610#[must_use]
611pub fn encode_ct_mark_masked(mark: u32, mask: u32) -> Vec<u8> {
612 encode_u32_masked(OxmClass::Nxm1, NxmField::CtMark as u8, mark, mask)
613}
614
615#[allow(dead_code)]
619#[must_use]
620pub fn encode_ct_label(label: u128) -> Vec<u8> {
621 let header = OxmHeader::new(OxmClass::Nxm1, NxmField::CtLabel as u8, false, 16);
622 let mut buf = Vec::with_capacity(20);
623 buf.extend_from_slice(&header.encode());
624 buf.extend_from_slice(&label.to_be_bytes());
625 buf
626}
627
628#[allow(dead_code)]
632#[must_use]
633pub fn encode_ct_label_masked(label: u128, mask: u128) -> Vec<u8> {
634 let header = OxmHeader::new(OxmClass::Nxm1, NxmField::CtLabel as u8, true, 32);
635 let mut buf = Vec::with_capacity(36);
636 buf.extend_from_slice(&header.encode());
637 buf.extend_from_slice(&label.to_be_bytes());
638 buf.extend_from_slice(&mask.to_be_bytes());
639 buf
640}
641
642#[allow(dead_code)]
657#[must_use]
658pub fn encode_xxreg(reg_num: u8, value: u128) -> Vec<u8> {
659 assert!(reg_num <= 3, "Extended register number must be 0-3");
660 let field = NxmField::XxReg0 as u8 + reg_num;
661 let header = OxmHeader::new(OxmClass::Nxm1, field, false, 16);
662 let mut buf = Vec::with_capacity(20);
663 buf.extend_from_slice(&header.encode());
664 buf.extend_from_slice(&value.to_be_bytes());
665 buf
666}
667
668#[allow(dead_code)]
676#[must_use]
677pub fn encode_xxreg_masked(reg_num: u8, value: u128, mask: u128) -> Vec<u8> {
678 assert!(reg_num <= 3, "Extended register number must be 0-3");
679 let field = NxmField::XxReg0 as u8 + reg_num;
680 let header = OxmHeader::new(OxmClass::Nxm1, field, true, 32);
681 let mut buf = Vec::with_capacity(36);
682 buf.extend_from_slice(&header.encode());
683 buf.extend_from_slice(&value.to_be_bytes());
684 buf.extend_from_slice(&mask.to_be_bytes());
685 buf
686}
687
688#[allow(dead_code)]
694#[must_use]
695pub fn encode_xxreg_ipv6(reg_num: u8, addr: std::net::Ipv6Addr) -> Vec<u8> {
696 encode_xxreg(reg_num, u128::from(addr))
697}
698
699#[allow(dead_code)]
703#[must_use]
704pub fn encode_xxreg_ipv6_masked(reg_num: u8, addr: std::net::Ipv6Addr, mask: std::net::Ipv6Addr) -> Vec<u8> {
705 encode_xxreg_masked(reg_num, u128::from(addr), u128::from(mask))
706}
707
708#[allow(dead_code)]
720#[must_use]
721pub const fn prefix_to_mask_v6(prefix_len: u8) -> u128 {
722 if prefix_len == 0 {
723 0
724 } else if prefix_len >= 128 {
725 u128::MAX
726 } else {
727 u128::MAX << (128 - prefix_len)
728 }
729}
730
731#[allow(dead_code)]
748#[must_use]
749pub const fn prefix_to_mask(prefix_len: u8) -> u32 {
750 if prefix_len == 0 {
751 0
752 } else if prefix_len >= 32 {
753 0xffff_ffff
754 } else {
755 0xffff_ffff << (32 - prefix_len)
757 }
758}
759
760#[allow(dead_code)]
771#[must_use]
772pub fn encode_ipv4_prefix(field: OxmField, addr: u32, prefix_len: u8) -> Vec<u8> {
773 let mask = prefix_to_mask(prefix_len);
774 encode_u32_masked_field(field, addr & mask, mask)
775}
776
777pub trait OxmEncode {
786 fn encode(&self) -> Vec<u8>;
791}
792
793#[allow(dead_code)]
798#[derive(Debug, Clone, PartialEq, Eq)]
799pub enum OxmMatchField {
800 InPort(u32),
802 InPhyPort(u32),
804 Metadata(u64),
806 MetadataMasked(u64, u64),
808 EthDst([u8; 6]),
810 EthDstMasked([u8; 6], [u8; 6]),
812 EthSrc([u8; 6]),
814 EthSrcMasked([u8; 6], [u8; 6]),
816 EthType(u16),
818 VlanVid(u16),
820 VlanVidMasked(u16, u16),
822 VlanPcp(u8),
824 IpDscp(u8),
826 IpEcn(u8),
828 IpProto(u8),
830 Ipv4Src(u32),
832 Ipv4SrcMasked(u32, u32),
834 Ipv4Dst(u32),
836 Ipv4DstMasked(u32, u32),
838 TcpSrc(u16),
840 TcpDst(u16),
842 UdpSrc(u16),
844 UdpDst(u16),
846 SctpSrc(u16),
848 SctpDst(u16),
850 Icmpv4Type(u8),
852 Icmpv4Code(u8),
854 ArpOp(u16),
856 ArpSpa(u32),
858 ArpSpaMasked(u32, u32),
860 ArpTpa(u32),
862 ArpTpaMasked(u32, u32),
864 ArpSha([u8; 6]),
866 ArpTha([u8; 6]),
868 TunnelId(u64),
870 TunnelIdMasked(u64, u64),
872}
873
874#[allow(dead_code)]
875impl OxmEncode for OxmMatchField {
876 fn encode(&self) -> Vec<u8> {
877 match self {
878 Self::InPort(v) => encode_u32_field(OxmField::InPort, *v),
879 Self::InPhyPort(v) => encode_u32_field(OxmField::InPhyPort, *v),
880 Self::Metadata(v) => encode_u64_field(OxmField::Metadata, *v),
881 Self::MetadataMasked(v, m) => encode_u64_masked_field(OxmField::Metadata, *v, *m),
882 Self::EthDst(v) => encode_mac_field(OxmField::EthDst, *v),
883 Self::EthDstMasked(v, m) => encode_mac_masked_field(OxmField::EthDst, *v, *m),
884 Self::EthSrc(v) => encode_mac_field(OxmField::EthSrc, *v),
885 Self::EthSrcMasked(v, m) => encode_mac_masked_field(OxmField::EthSrc, *v, *m),
886 Self::EthType(v) => encode_u16_field(OxmField::EthType, *v),
887 Self::VlanVid(v) => encode_u16_field(OxmField::VlanVid, *v),
888 Self::VlanVidMasked(v, m) => {
889 encode_u16_masked(OxmClass::OpenflowBasic, OxmField::VlanVid as u8, *v, *m)
890 }
891 Self::VlanPcp(v) => encode_u8_field(OxmField::VlanPcp, *v),
892 Self::IpDscp(v) => encode_u8_field(OxmField::IpDscp, *v),
893 Self::IpEcn(v) => encode_u8_field(OxmField::IpEcn, *v),
894 Self::IpProto(v) => encode_u8_field(OxmField::IpProto, *v),
895 Self::Ipv4Src(v) => encode_u32_field(OxmField::Ipv4Src, *v),
896 Self::Ipv4SrcMasked(v, m) => encode_u32_masked_field(OxmField::Ipv4Src, *v, *m),
897 Self::Ipv4Dst(v) => encode_u32_field(OxmField::Ipv4Dst, *v),
898 Self::Ipv4DstMasked(v, m) => encode_u32_masked_field(OxmField::Ipv4Dst, *v, *m),
899 Self::TcpSrc(v) => encode_u16_field(OxmField::TcpSrc, *v),
900 Self::TcpDst(v) => encode_u16_field(OxmField::TcpDst, *v),
901 Self::UdpSrc(v) => encode_u16_field(OxmField::UdpSrc, *v),
902 Self::UdpDst(v) => encode_u16_field(OxmField::UdpDst, *v),
903 Self::SctpSrc(v) => encode_u16_field(OxmField::SctpSrc, *v),
904 Self::SctpDst(v) => encode_u16_field(OxmField::SctpDst, *v),
905 Self::Icmpv4Type(v) => encode_u8_field(OxmField::Icmpv4Type, *v),
906 Self::Icmpv4Code(v) => encode_u8_field(OxmField::Icmpv4Code, *v),
907 Self::ArpOp(v) => encode_u16_field(OxmField::ArpOp, *v),
908 Self::ArpSpa(v) => encode_u32_field(OxmField::ArpSpa, *v),
909 Self::ArpSpaMasked(v, m) => encode_u32_masked_field(OxmField::ArpSpa, *v, *m),
910 Self::ArpTpa(v) => encode_u32_field(OxmField::ArpTpa, *v),
911 Self::ArpTpaMasked(v, m) => encode_u32_masked_field(OxmField::ArpTpa, *v, *m),
912 Self::ArpSha(v) => encode_mac_field(OxmField::ArpSha, *v),
913 Self::ArpTha(v) => encode_mac_field(OxmField::ArpTha, *v),
914 Self::TunnelId(v) => encode_u64_field(OxmField::TunnelId, *v),
915 Self::TunnelIdMasked(v, m) => encode_u64_masked_field(OxmField::TunnelId, *v, *m),
916 }
917 }
918}
919
920#[allow(dead_code)]
925#[derive(Debug, Clone, PartialEq, Eq)]
926pub enum NxmMatchField {
927 Reg(u8, u32),
929 RegMasked(u8, u32, u32),
931 XxReg(u8, u128),
933 XxRegMasked(u8, u128, u128),
935 TunId(u64),
937 TunIdMasked(u64, u64),
939 TunIpv4Src(u32),
941 TunIpv4Dst(u32),
943 PktMark(u32),
945 PktMarkMasked(u32, u32),
947 CtState(u32),
949 CtStateMasked(u32, u32),
951 CtZone(u16),
953 CtMark(u32),
955 CtMarkMasked(u32, u32),
957 CtLabel(u128),
959 CtLabelMasked(u128, u128),
961}
962
963#[allow(dead_code)]
964impl OxmEncode for NxmMatchField {
965 fn encode(&self) -> Vec<u8> {
966 match self {
967 Self::Reg(n, v) => encode_reg(*n, *v),
968 Self::RegMasked(n, v, m) => encode_reg_masked(*n, *v, *m),
969 Self::XxReg(n, v) => encode_xxreg(*n, *v),
970 Self::XxRegMasked(n, v, m) => encode_xxreg_masked(*n, *v, *m),
971 Self::TunId(v) => encode_tun_id(*v),
972 Self::TunIdMasked(v, m) => encode_tun_id_masked(*v, *m),
973 Self::TunIpv4Src(v) => encode_tun_ipv4_src(*v),
974 Self::TunIpv4Dst(v) => encode_tun_ipv4_dst(*v),
975 Self::PktMark(v) => encode_pkt_mark(*v),
976 Self::PktMarkMasked(v, m) => encode_pkt_mark_masked(*v, *m),
977 Self::CtState(v) => encode_ct_state(*v),
978 Self::CtStateMasked(v, m) => encode_ct_state_masked(*v, *m),
979 Self::CtZone(v) => encode_ct_zone(*v),
980 Self::CtMark(v) => encode_ct_mark(*v),
981 Self::CtMarkMasked(v, m) => encode_ct_mark_masked(*v, *m),
982 Self::CtLabel(v) => encode_ct_label(*v),
983 Self::CtLabelMasked(v, m) => encode_ct_label_masked(*v, *m),
984 }
985 }
986}
987
988#[allow(dead_code)]
993#[derive(Debug, Clone, PartialEq, Eq)]
994pub enum MatchField {
995 Oxm(OxmMatchField),
997 Nxm(NxmMatchField),
999}
1000
1001#[allow(dead_code)]
1002impl OxmEncode for MatchField {
1003 fn encode(&self) -> Vec<u8> {
1004 match self {
1005 Self::Oxm(f) => f.encode(),
1006 Self::Nxm(f) => f.encode(),
1007 }
1008 }
1009}
1010
1011impl From<OxmMatchField> for MatchField {
1013 fn from(f: OxmMatchField) -> Self {
1014 Self::Oxm(f)
1015 }
1016}
1017
1018impl From<NxmMatchField> for MatchField {
1019 fn from(f: NxmMatchField) -> Self {
1020 Self::Nxm(f)
1021 }
1022}
1023
1024#[allow(dead_code)] pub fn oxm_header(class: OxmClass, field: OxmField, has_mask: bool, length: u8) -> u32 {
1029 let class_val = class as u32;
1030 let field_val = (field as u32) << 1;
1031 let mask_val = if has_mask { 1u32 } else { 0u32 };
1032 let len_val = length as u32;
1033
1034 (class_val << 16) | (field_val << 8) | (mask_val << 8) | len_val
1035}
1036
1037#[cfg(test)]
1038mod tests {
1039 use super::*;
1040
1041 #[test]
1042 fn oxm_header_in_port() {
1043 let header = OxmHeader::openflow_basic(OxmField::InPort, false, 4);
1045 let bytes = header.encode();
1046
1047 assert_eq!(bytes, [0x80, 0x00, 0x00, 0x04]);
1053 assert_eq!(header.as_u32(), 0x8000_0004);
1054 }
1055
1056 #[test]
1057 fn oxm_header_eth_type() {
1058 let header = OxmHeader::openflow_basic(OxmField::EthType, false, 2);
1060 let bytes = header.encode();
1061
1062 assert_eq!(bytes, [0x80, 0x00, 0x0a, 0x02]);
1064 assert_eq!(header.as_u32(), 0x8000_0a02);
1065 }
1066
1067 #[test]
1068 fn oxm_header_eth_dst_masked() {
1069 let header = OxmHeader::openflow_basic(OxmField::EthDst, true, 12);
1071 let bytes = header.encode();
1072
1073 assert_eq!(bytes, [0x80, 0x00, 0x07, 0x0c]);
1075 assert_eq!(header.as_u32(), 0x8000_070c);
1076 }
1077
1078 #[test]
1079 fn oxm_header_ipv4_src_no_mask() {
1080 let header = OxmHeader::openflow_basic(OxmField::Ipv4Src, false, 4);
1082 let bytes = header.encode();
1083
1084 assert_eq!(bytes, [0x80, 0x00, 0x16, 0x04]);
1086 assert_eq!(header.as_u32(), 0x8000_1604);
1087 }
1088
1089 #[test]
1090 fn oxm_header_ipv4_src_masked() {
1091 let header = OxmHeader::openflow_basic(OxmField::Ipv4Src, true, 8);
1093 let bytes = header.encode();
1094
1095 assert_eq!(bytes, [0x80, 0x00, 0x17, 0x08]);
1097 assert_eq!(header.as_u32(), 0x8000_1708);
1098 }
1099
1100 #[test]
1101 fn oxm_header_tcp_dst() {
1102 let header = OxmHeader::openflow_basic(OxmField::TcpDst, false, 2);
1104 let bytes = header.encode();
1105
1106 assert_eq!(bytes, [0x80, 0x00, 0x1c, 0x02]);
1108 }
1109
1110 #[test]
1111 fn oxm_header_metadata_masked() {
1112 let header = OxmHeader::openflow_basic(OxmField::Metadata, true, 16);
1114 let bytes = header.encode();
1115
1116 assert_eq!(bytes, [0x80, 0x00, 0x05, 0x10]);
1118 }
1119
1120 #[test]
1121 fn oxm_header_nxm_register() {
1122 let header = OxmHeader::new(OxmClass::Nxm1, 0, false, 4);
1124 let bytes = header.encode();
1125
1126 assert_eq!(bytes, [0x00, 0x01, 0x00, 0x04]);
1127 assert_eq!(header.as_u32(), 0x0001_0004);
1128 }
1129
1130 #[test]
1131 fn oxm_header_nxm_register_masked() {
1132 let header = OxmHeader::new(OxmClass::Nxm1, 0, true, 8);
1134 let bytes = header.encode();
1135
1136 assert_eq!(bytes, [0x00, 0x01, 0x01, 0x08]);
1138 }
1139
1140 #[test]
1141 fn oxm_header_tunnel_id() {
1142 let header = OxmHeader::openflow_basic(OxmField::TunnelId, false, 8);
1144 let bytes = header.encode();
1145
1146 assert_eq!(bytes, [0x80, 0x00, 0x4c, 0x08]);
1148 }
1149
1150 #[test]
1151 fn oxm_header_compatible_with_legacy_function() {
1152 let header = OxmHeader::openflow_basic(OxmField::EthType, false, 2);
1154 let legacy = oxm_header(OxmClass::OpenflowBasic, OxmField::EthType, false, 2);
1155
1156 assert_eq!(header.as_u32(), legacy);
1157 }
1158
1159 #[test]
1164 fn encode_u8_ip_proto_tcp() {
1165 let bytes = encode_u8_field(OxmField::IpProto, 6);
1168
1169 assert_eq!(bytes.len(), 5);
1170 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x14, 0x01]);
1173 assert_eq!(bytes[4], 6);
1175 }
1176
1177 #[test]
1178 fn encode_u8_ip_dscp() {
1179 let bytes = encode_u8_field(OxmField::IpDscp, 46);
1182
1183 assert_eq!(bytes.len(), 5);
1184 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x10, 0x01]);
1186 assert_eq!(bytes[4], 46);
1187 }
1188
1189 #[test]
1190 fn encode_u16_eth_type_ipv4() {
1191 let bytes = encode_u16_field(OxmField::EthType, 0x0800);
1194
1195 assert_eq!(bytes.len(), 6);
1196 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x0a, 0x02]);
1198 assert_eq!(&bytes[4..6], &[0x08, 0x00]);
1200 }
1201
1202 #[test]
1203 fn encode_u16_tcp_dst_http() {
1204 let bytes = encode_u16_field(OxmField::TcpDst, 80);
1207
1208 assert_eq!(bytes.len(), 6);
1209 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x1c, 0x02]);
1211 assert_eq!(&bytes[4..6], &[0x00, 0x50]);
1213 }
1214
1215 #[test]
1216 fn encode_u16_vlan_vid() {
1217 let bytes = encode_u16_field(OxmField::VlanVid, 100);
1220
1221 assert_eq!(bytes.len(), 6);
1222 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x0c, 0x02]);
1224 assert_eq!(&bytes[4..6], &[0x00, 0x64]);
1226 }
1227
1228 #[test]
1229 fn encode_u32_in_port() {
1230 let bytes = encode_u32_field(OxmField::InPort, 1);
1233
1234 assert_eq!(bytes.len(), 8);
1235 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x00, 0x04]);
1237 assert_eq!(&bytes[4..8], &[0x00, 0x00, 0x00, 0x01]);
1239 }
1240
1241 #[test]
1242 fn encode_u32_ipv4_src() {
1243 let ip: u32 = (10 << 24) | (0 << 16) | (0 << 8) | 1;
1246 let bytes = encode_u32_field(OxmField::Ipv4Src, ip);
1247
1248 assert_eq!(bytes.len(), 8);
1249 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x16, 0x04]);
1251 assert_eq!(&bytes[4..8], &[10, 0, 0, 1]);
1253 }
1254
1255 #[test]
1256 fn encode_u32_ipv4_dst() {
1257 let ip: u32 = (192 << 24) | (168 << 16) | (1 << 8) | 1;
1260 let bytes = encode_u32_field(OxmField::Ipv4Dst, ip);
1261
1262 assert_eq!(bytes.len(), 8);
1263 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x18, 0x04]);
1265 assert_eq!(&bytes[4..8], &[192, 168, 1, 1]);
1266 }
1267
1268 #[test]
1269 fn encode_u64_metadata() {
1270 let bytes = encode_u64_field(OxmField::Metadata, 0x123456789ABCDEF0);
1273
1274 assert_eq!(bytes.len(), 12);
1275 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x04, 0x08]);
1277 assert_eq!(
1279 &bytes[4..12],
1280 &[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]
1281 );
1282 }
1283
1284 #[test]
1285 fn encode_u64_tunnel_id() {
1286 let bytes = encode_u64_field(OxmField::TunnelId, 42);
1289
1290 assert_eq!(bytes.len(), 12);
1291 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x4c, 0x08]);
1293 assert_eq!(&bytes[4..12], &[0, 0, 0, 0, 0, 0, 0, 42]);
1295 }
1296
1297 #[test]
1298 fn encode_mac_eth_src() {
1299 let mac = [0x00, 0x11, 0x22, 0x33, 0x44, 0x55];
1302 let bytes = encode_mac_field(OxmField::EthSrc, mac);
1303
1304 assert_eq!(bytes.len(), 10);
1305 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x08, 0x06]);
1307 assert_eq!(&bytes[4..10], &mac);
1308 }
1309
1310 #[test]
1311 fn encode_mac_eth_dst() {
1312 let mac = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
1315 let bytes = encode_mac_field(OxmField::EthDst, mac);
1316
1317 assert_eq!(bytes.len(), 10);
1318 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x06, 0x06]);
1320 assert_eq!(&bytes[4..10], &mac);
1321 }
1322
1323 #[test]
1324 fn encode_mac_arp_sha() {
1325 let mac = [0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe];
1328 let bytes = encode_mac_field(OxmField::ArpSha, mac);
1329
1330 assert_eq!(bytes.len(), 10);
1331 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x30, 0x06]);
1333 assert_eq!(&bytes[4..10], &mac);
1334 }
1335
1336 #[test]
1337 fn encode_nxm_register_raw() {
1338 let bytes = encode_u32(OxmClass::Nxm1, 0, 0x12345678);
1340
1341 assert_eq!(bytes.len(), 8);
1342 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0x00, 0x04]);
1343 assert_eq!(&bytes[4..8], &[0x12, 0x34, 0x56, 0x78]);
1344 }
1345
1346 #[test]
1351 fn prefix_to_mask_24() {
1352 assert_eq!(prefix_to_mask(24), 0xffff_ff00);
1354 }
1355
1356 #[test]
1357 fn prefix_to_mask_16() {
1358 assert_eq!(prefix_to_mask(16), 0xffff_0000);
1360 }
1361
1362 #[test]
1363 fn prefix_to_mask_8() {
1364 assert_eq!(prefix_to_mask(8), 0xff00_0000);
1366 }
1367
1368 #[test]
1369 fn prefix_to_mask_32() {
1370 assert_eq!(prefix_to_mask(32), 0xffff_ffff);
1372 }
1373
1374 #[test]
1375 fn prefix_to_mask_0() {
1376 assert_eq!(prefix_to_mask(0), 0x0000_0000);
1378 }
1379
1380 #[test]
1381 fn prefix_to_mask_various() {
1382 assert_eq!(prefix_to_mask(1), 0x8000_0000);
1383 assert_eq!(prefix_to_mask(25), 0xffff_ff80);
1384 assert_eq!(prefix_to_mask(30), 0xffff_fffc); assert_eq!(prefix_to_mask(31), 0xffff_fffe); }
1387
1388 #[test]
1389 fn encode_u32_masked_ipv4_24() {
1390 let addr: u32 = 10 << 24; let mask: u32 = 0xffff_ff00; let bytes = encode_u32_masked_field(OxmField::Ipv4Dst, addr, mask);
1395
1396 assert_eq!(bytes.len(), 12);
1397 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x19, 0x08]);
1400 assert_eq!(&bytes[4..8], &[10, 0, 0, 0]);
1402 assert_eq!(&bytes[8..12], &[255, 255, 255, 0]);
1404 }
1405
1406 #[test]
1407 fn encode_u32_masked_ipv4_16() {
1408 let addr: u32 = (192 << 24) | (168 << 16); let mask: u32 = 0xffff_0000; let bytes = encode_u32_masked_field(OxmField::Ipv4Src, addr, mask);
1413
1414 assert_eq!(bytes.len(), 12);
1415 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x17, 0x08]);
1417 assert_eq!(&bytes[4..8], &[192, 168, 0, 0]);
1418 assert_eq!(&bytes[8..12], &[255, 255, 0, 0]);
1419 }
1420
1421 #[test]
1422 fn encode_ipv4_prefix_convenience() {
1423 let addr: u32 = (10 << 24) | (0 << 16) | (0 << 8) | 1; let bytes = encode_ipv4_prefix(OxmField::Ipv4Dst, addr, 24);
1427
1428 assert_eq!(bytes.len(), 12);
1429 assert_eq!(&bytes[4..8], &[10, 0, 0, 0]);
1431 assert_eq!(&bytes[8..12], &[255, 255, 255, 0]);
1432 }
1433
1434 #[test]
1435 fn encode_mac_masked_oui() {
1436 let mac = [0x00, 0x11, 0x22, 0x00, 0x00, 0x00];
1439 let mask = [0xff, 0xff, 0xff, 0x00, 0x00, 0x00];
1440 let bytes = encode_mac_masked_field(OxmField::EthSrc, mac, mask);
1441
1442 assert_eq!(bytes.len(), 16);
1443 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x09, 0x0c]);
1446 assert_eq!(&bytes[4..10], &mac);
1447 assert_eq!(&bytes[10..16], &mask);
1448 }
1449
1450 #[test]
1451 fn encode_mac_masked_multicast() {
1452 let mac = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00];
1455 let mask = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00];
1456 let bytes = encode_mac_masked_field(OxmField::EthDst, mac, mask);
1457
1458 assert_eq!(bytes.len(), 16);
1459 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x07, 0x0c]);
1461 assert_eq!(&bytes[4..10], &mac);
1462 assert_eq!(&bytes[10..16], &mask);
1463 }
1464
1465 #[test]
1466 fn encode_u64_masked_metadata() {
1467 let value: u64 = 0x1234_0000_0000_0000;
1470 let mask: u64 = 0xffff_0000_0000_0000;
1471 let bytes = encode_u64_masked_field(OxmField::Metadata, value, mask);
1472
1473 assert_eq!(bytes.len(), 20);
1474 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x05, 0x10]);
1477 assert_eq!(&bytes[4..12], &[0x12, 0x34, 0, 0, 0, 0, 0, 0]);
1478 assert_eq!(&bytes[12..20], &[0xff, 0xff, 0, 0, 0, 0, 0, 0]);
1479 }
1480
1481 #[test]
1482 fn encode_nxm_register_masked() {
1483 let bytes = encode_u32_masked(OxmClass::Nxm1, 0, 0xabcd_0000, 0xffff_0000);
1485
1486 assert_eq!(bytes.len(), 12);
1487 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0x01, 0x08]);
1490 assert_eq!(&bytes[4..8], &[0xab, 0xcd, 0x00, 0x00]);
1491 assert_eq!(&bytes[8..12], &[0xff, 0xff, 0x00, 0x00]);
1492 }
1493
1494 #[test]
1499 fn encode_reg_0() {
1500 let bytes = encode_reg(0, 0x12345678);
1502
1503 assert_eq!(bytes.len(), 8);
1504 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0x00, 0x04]);
1506 assert_eq!(&bytes[4..8], &[0x12, 0x34, 0x56, 0x78]);
1507 }
1508
1509 #[test]
1510 fn encode_reg_15() {
1511 let bytes = encode_reg(15, 0xdeadbeef);
1513
1514 assert_eq!(bytes.len(), 8);
1515 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0x1e, 0x04]);
1518 assert_eq!(&bytes[4..8], &[0xde, 0xad, 0xbe, 0xef]);
1519 }
1520
1521 #[test]
1522 fn encode_reg_masked_partial() {
1523 let bytes = encode_reg_masked(5, 0x42, 0x000000ff);
1525
1526 assert_eq!(bytes.len(), 12);
1527 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0x0b, 0x08]);
1530 assert_eq!(&bytes[4..8], &[0x00, 0x00, 0x00, 0x42]);
1531 assert_eq!(&bytes[8..12], &[0x00, 0x00, 0x00, 0xff]);
1532 }
1533
1534 #[test]
1535 fn encode_tun_id_value() {
1536 let bytes = encode_tun_id(1000);
1538
1539 assert_eq!(bytes.len(), 12);
1540 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0x20, 0x08]);
1543 assert_eq!(&bytes[4..12], &[0, 0, 0, 0, 0, 0, 0x03, 0xe8]);
1545 }
1546
1547 #[test]
1548 fn encode_tun_id_masked_value() {
1549 let bytes = encode_tun_id_masked(0x12345678_00000000, 0xffffffff_00000000);
1551
1552 assert_eq!(bytes.len(), 20);
1553 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0x21, 0x10]);
1556 }
1557
1558 #[test]
1559 fn encode_tun_ipv4_src_value() {
1560 let addr: u32 = (10 << 24) | 1;
1562 let bytes = encode_tun_ipv4_src(addr);
1563
1564 assert_eq!(bytes.len(), 8);
1565 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0x3e, 0x04]);
1568 assert_eq!(&bytes[4..8], &[10, 0, 0, 1]);
1569 }
1570
1571 #[test]
1572 fn encode_tun_ipv4_dst_value() {
1573 let addr: u32 = (192 << 24) | (168 << 16) | (1 << 8) | 1;
1575 let bytes = encode_tun_ipv4_dst(addr);
1576
1577 assert_eq!(bytes.len(), 8);
1578 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0x40, 0x04]);
1581 assert_eq!(&bytes[4..8], &[192, 168, 1, 1]);
1582 }
1583
1584 #[test]
1585 fn encode_pkt_mark_value() {
1586 let bytes = encode_pkt_mark(0x100);
1588
1589 assert_eq!(bytes.len(), 8);
1590 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0x42, 0x04]);
1593 assert_eq!(&bytes[4..8], &[0x00, 0x00, 0x01, 0x00]);
1594 }
1595
1596 #[test]
1597 fn encode_pkt_mark_masked_value() {
1598 let bytes = encode_pkt_mark_masked(0xff00, 0xff00);
1600
1601 assert_eq!(bytes.len(), 12);
1602 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0x43, 0x08]);
1604 }
1605
1606 #[test]
1607 fn encode_ct_state_tracked_established() {
1608 let state = ct_state::TRK | ct_state::EST;
1610 let bytes = encode_ct_state(state);
1611
1612 assert_eq!(bytes.len(), 8);
1613 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0xd2, 0x04]);
1616 assert_eq!(&bytes[4..8], &[0x00, 0x00, 0x00, 0x22]);
1618 }
1619
1620 #[test]
1621 fn encode_ct_state_masked_new() {
1622 let state = ct_state::TRK | ct_state::NEW;
1624 let mask = ct_state::TRK | ct_state::NEW;
1625 let bytes = encode_ct_state_masked(state, mask);
1626
1627 assert_eq!(bytes.len(), 12);
1628 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0xd3, 0x08]);
1630 assert_eq!(&bytes[4..8], &[0x00, 0x00, 0x00, 0x21]);
1632 assert_eq!(&bytes[8..12], &[0x00, 0x00, 0x00, 0x21]);
1633 }
1634
1635 #[test]
1636 fn encode_ct_zone_value() {
1637 let bytes = encode_ct_zone(100);
1639
1640 assert_eq!(bytes.len(), 6);
1641 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0xd4, 0x02]);
1644 assert_eq!(&bytes[4..6], &[0x00, 0x64]);
1646 }
1647
1648 #[test]
1649 fn encode_ct_mark_value() {
1650 let bytes = encode_ct_mark(0xaabbccdd);
1652
1653 assert_eq!(bytes.len(), 8);
1654 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0xd6, 0x04]);
1657 assert_eq!(&bytes[4..8], &[0xaa, 0xbb, 0xcc, 0xdd]);
1658 }
1659
1660 #[test]
1661 fn encode_ct_mark_masked_value() {
1662 let bytes = encode_ct_mark_masked(0xff000000, 0xff000000);
1664
1665 assert_eq!(bytes.len(), 12);
1666 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0xd7, 0x08]);
1668 assert_eq!(&bytes[4..8], &[0xff, 0x00, 0x00, 0x00]);
1669 assert_eq!(&bytes[8..12], &[0xff, 0x00, 0x00, 0x00]);
1670 }
1671
1672 #[test]
1673 fn encode_ct_label_value() {
1674 let label: u128 = 0x123456789abcdef0_123456789abcdef0;
1676 let bytes = encode_ct_label(label);
1677
1678 assert_eq!(bytes.len(), 20);
1679 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0xd8, 0x10]);
1682 assert_eq!(
1683 &bytes[4..20],
1684 &[
1685 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
1686 0xde, 0xf0
1687 ]
1688 );
1689 }
1690
1691 #[test]
1692 fn encode_ct_label_masked_value() {
1693 let label: u128 = 0xdeadbeef_00000000_00000000_00000000;
1695 let mask: u128 = 0xffffffff_00000000_00000000_00000000;
1696 let bytes = encode_ct_label_masked(label, mask);
1697
1698 assert_eq!(bytes.len(), 36);
1699 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0xd9, 0x20]);
1702 }
1703
1704 #[test]
1705 fn encode_nxm_u32_via_enum() {
1706 let bytes = encode_nxm_u32(NxmField::PktMark, 0x42);
1708
1709 assert_eq!(bytes.len(), 8);
1710 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0x42, 0x04]);
1712 assert_eq!(&bytes[4..8], &[0x00, 0x00, 0x00, 0x42]);
1713 }
1714
1715 #[test]
1716 fn ct_state_flags_correct() {
1717 assert_eq!(ct_state::NEW, 0x01);
1719 assert_eq!(ct_state::EST, 0x02);
1720 assert_eq!(ct_state::REL, 0x04);
1721 assert_eq!(ct_state::RPL, 0x08);
1722 assert_eq!(ct_state::INV, 0x10);
1723 assert_eq!(ct_state::TRK, 0x20);
1724 assert_eq!(ct_state::SNAT, 0x40);
1725 assert_eq!(ct_state::DNAT, 0x80);
1726 }
1727
1728 #[test]
1733 fn encode_xxreg_0() {
1734 let value: u128 = 0x0123456789abcdef_fedcba9876543210;
1736 let bytes = encode_xxreg(0, value);
1737
1738 assert_eq!(bytes.len(), 20);
1739 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0xde, 0x10]);
1742 assert_eq!(
1743 &bytes[4..20],
1744 &[
1745 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54,
1746 0x32, 0x10
1747 ]
1748 );
1749 }
1750
1751 #[test]
1752 fn encode_xxreg_3() {
1753 let value: u128 = 0xdeadbeef_cafebabe_12345678_9abcdef0;
1755 let bytes = encode_xxreg(3, value);
1756
1757 assert_eq!(bytes.len(), 20);
1758 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0xe4, 0x10]);
1761 }
1762
1763 #[test]
1764 fn encode_xxreg_masked_high64() {
1765 let value: u128 = 0xaabbccdd_eeff0011_00000000_00000000;
1767 let mask: u128 = 0xffffffff_ffffffff_00000000_00000000;
1768 let bytes = encode_xxreg_masked(1, value, mask);
1769
1770 assert_eq!(bytes.len(), 36);
1771 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0xe1, 0x20]);
1774 }
1775
1776 #[test]
1777 fn encode_xxreg_ipv6_address() {
1778 use std::net::Ipv6Addr;
1779
1780 let addr: Ipv6Addr = "2001:db8::1".parse().unwrap();
1782 let bytes = encode_xxreg_ipv6(0, addr);
1783
1784 assert_eq!(bytes.len(), 20);
1785 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0xde, 0x10]);
1787 assert_eq!(
1789 &bytes[4..20],
1790 &[0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01]
1791 );
1792 }
1793
1794 #[test]
1795 fn encode_xxreg_ipv6_masked_prefix() {
1796 use std::net::Ipv6Addr;
1797
1798 let addr: Ipv6Addr = "2001:db8::".parse().unwrap();
1800 let mask: Ipv6Addr = "ffff:ffff::".parse().unwrap();
1801 let bytes = encode_xxreg_ipv6_masked(2, addr, mask);
1802
1803 assert_eq!(bytes.len(), 36);
1804 assert_eq!(&bytes[0..4], &[0x00, 0x01, 0xe3, 0x20]);
1807 }
1808
1809 #[test]
1810 fn prefix_to_mask_v6_64() {
1811 assert_eq!(
1813 prefix_to_mask_v6(64),
1814 0xffffffff_ffffffff_00000000_00000000
1815 );
1816 }
1817
1818 #[test]
1819 fn prefix_to_mask_v6_128() {
1820 assert_eq!(prefix_to_mask_v6(128), u128::MAX);
1822 }
1823
1824 #[test]
1825 fn prefix_to_mask_v6_0() {
1826 assert_eq!(prefix_to_mask_v6(0), 0);
1828 }
1829
1830 #[test]
1831 fn prefix_to_mask_v6_various() {
1832 assert_eq!(prefix_to_mask_v6(32), 0xffffffff_00000000_00000000_00000000);
1833 assert_eq!(prefix_to_mask_v6(48), 0xffffffff_ffff0000_00000000_00000000);
1834 assert_eq!(
1835 prefix_to_mask_v6(96),
1836 0xffffffff_ffffffff_ffffffff_00000000
1837 );
1838 assert_eq!(
1839 prefix_to_mask_v6(120),
1840 0xffffffff_ffffffff_ffffffff_ffffff00
1841 );
1842 }
1843
1844 #[test]
1845 fn xxreg_field_numbers() {
1846 assert_eq!(NxmField::XxReg0 as u8, 111);
1848 assert_eq!(NxmField::XxReg1 as u8, 112);
1849 assert_eq!(NxmField::XxReg2 as u8, 113);
1850 assert_eq!(NxmField::XxReg3 as u8, 114);
1851 }
1852
1853 #[test]
1858 fn trait_oxm_in_port() {
1859 let field = OxmMatchField::InPort(1);
1860 let bytes = field.encode();
1861
1862 assert_eq!(bytes, encode_u32_field(OxmField::InPort, 1));
1864 assert_eq!(bytes.len(), 8);
1865 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x00, 0x04]);
1866 }
1867
1868 #[test]
1869 fn trait_oxm_eth_type() {
1870 let field = OxmMatchField::EthType(0x0800);
1871 let bytes = field.encode();
1872
1873 assert_eq!(bytes, encode_u16_field(OxmField::EthType, 0x0800));
1874 assert_eq!(bytes.len(), 6);
1875 }
1876
1877 #[test]
1878 fn trait_oxm_ipv4_src_masked() {
1879 let field = OxmMatchField::Ipv4SrcMasked(0x0a000000, 0xffffff00);
1881 let bytes = field.encode();
1882
1883 assert_eq!(
1884 bytes,
1885 encode_u32_masked_field(OxmField::Ipv4Src, 0x0a000000, 0xffffff00)
1886 );
1887 assert_eq!(bytes.len(), 12);
1888 }
1889
1890 #[test]
1891 fn trait_oxm_eth_dst() {
1892 let mac = [0x00, 0x11, 0x22, 0x33, 0x44, 0x55];
1893 let field = OxmMatchField::EthDst(mac);
1894 let bytes = field.encode();
1895
1896 assert_eq!(bytes, encode_mac_field(OxmField::EthDst, mac));
1897 assert_eq!(bytes.len(), 10);
1898 }
1899
1900 #[test]
1901 fn trait_oxm_eth_src_masked() {
1902 let mac = [0x00, 0x11, 0x22, 0x00, 0x00, 0x00];
1904 let mask = [0xff, 0xff, 0xff, 0x00, 0x00, 0x00];
1905 let field = OxmMatchField::EthSrcMasked(mac, mask);
1906 let bytes = field.encode();
1907
1908 assert_eq!(bytes, encode_mac_masked_field(OxmField::EthSrc, mac, mask));
1909 assert_eq!(bytes.len(), 16);
1910 }
1911
1912 #[test]
1913 fn trait_oxm_tcp_dst() {
1914 let field = OxmMatchField::TcpDst(80);
1915 let bytes = field.encode();
1916
1917 assert_eq!(bytes, encode_u16_field(OxmField::TcpDst, 80));
1918 }
1919
1920 #[test]
1921 fn trait_oxm_ip_proto() {
1922 let field = OxmMatchField::IpProto(6); let bytes = field.encode();
1924
1925 assert_eq!(bytes, encode_u8_field(OxmField::IpProto, 6));
1926 assert_eq!(bytes.len(), 5);
1927 }
1928
1929 #[test]
1930 fn trait_nxm_reg() {
1931 let field = NxmMatchField::Reg(0, 0x12345678);
1932 let bytes = field.encode();
1933
1934 assert_eq!(bytes, encode_reg(0, 0x12345678));
1935 assert_eq!(bytes.len(), 8);
1936 }
1937
1938 #[test]
1939 fn trait_nxm_reg_masked() {
1940 let field = NxmMatchField::RegMasked(5, 0xff00, 0xff00);
1941 let bytes = field.encode();
1942
1943 assert_eq!(bytes, encode_reg_masked(5, 0xff00, 0xff00));
1944 assert_eq!(bytes.len(), 12);
1945 }
1946
1947 #[test]
1948 fn trait_nxm_tun_id() {
1949 let field = NxmMatchField::TunId(1000);
1950 let bytes = field.encode();
1951
1952 assert_eq!(bytes, encode_tun_id(1000));
1953 assert_eq!(bytes.len(), 12);
1954 }
1955
1956 #[test]
1957 fn trait_nxm_ct_state() {
1958 let state = ct_state::TRK | ct_state::EST;
1959 let field = NxmMatchField::CtState(state);
1960 let bytes = field.encode();
1961
1962 assert_eq!(bytes, encode_ct_state(state));
1963 }
1964
1965 #[test]
1966 fn trait_nxm_ct_zone() {
1967 let field = NxmMatchField::CtZone(100);
1968 let bytes = field.encode();
1969
1970 assert_eq!(bytes, encode_ct_zone(100));
1971 assert_eq!(bytes.len(), 6);
1972 }
1973
1974 #[test]
1975 fn trait_nxm_xxreg() {
1976 let field = NxmMatchField::XxReg(0, 0x123456789abcdef0_fedcba9876543210);
1977 let bytes = field.encode();
1978
1979 assert_eq!(
1980 bytes,
1981 encode_xxreg(0, 0x123456789abcdef0_fedcba9876543210)
1982 );
1983 assert_eq!(bytes.len(), 20);
1984 }
1985
1986 #[test]
1987 fn trait_unified_match_field_oxm() {
1988 let field: MatchField = OxmMatchField::EthType(0x0800).into();
1989 let bytes = field.encode();
1990
1991 assert_eq!(bytes, encode_u16_field(OxmField::EthType, 0x0800));
1992 }
1993
1994 #[test]
1995 fn trait_unified_match_field_nxm() {
1996 let field: MatchField = NxmMatchField::Reg(0, 42).into();
1997 let bytes = field.encode();
1998
1999 assert_eq!(bytes, encode_reg(0, 42));
2000 }
2001
2002 #[test]
2003 fn trait_match_list_encoding() {
2004 let fields: Vec<MatchField> = vec![
2006 OxmMatchField::EthType(0x0800).into(),
2007 OxmMatchField::IpProto(6).into(),
2008 OxmMatchField::TcpDst(80).into(),
2009 NxmMatchField::Reg(0, 1).into(),
2010 ];
2011
2012 let mut encoded = Vec::new();
2013 for field in &fields {
2014 encoded.extend(field.encode());
2015 }
2016
2017 assert_eq!(encoded.len(), 25);
2019 }
2020
2021 #[test]
2022 fn trait_oxm_vlan_vid_masked() {
2023 let field = OxmMatchField::VlanVidMasked(0x1064, 0x1fff); let bytes = field.encode();
2026
2027 assert_eq!(bytes.len(), 8);
2028 assert_eq!(&bytes[0..4], &[0x80, 0x00, 0x0d, 0x04]);
2031 }
2032
2033 #[test]
2034 fn trait_oxm_metadata_masked() {
2035 let field = OxmMatchField::MetadataMasked(0xff00_0000_0000_0000, 0xff00_0000_0000_0000);
2036 let bytes = field.encode();
2037
2038 assert_eq!(bytes.len(), 20);
2039 }
2040
2041 #[test]
2042 fn trait_nxm_ct_label() {
2043 let label: u128 = 0x12345678_9abcdef0_12345678_9abcdef0;
2044 let field = NxmMatchField::CtLabel(label);
2045 let bytes = field.encode();
2046
2047 assert_eq!(bytes, encode_ct_label(label));
2048 assert_eq!(bytes.len(), 20);
2049 }
2050}