From e9d25d5832d5f92a29c1400cc636c0a344e2a3c7 Mon Sep 17 00:00:00 2001 From: VSuryaprasad-hcl <159443973+VSuryaprasad-HCL@users.noreply.github.com> Date: Wed, 27 Nov 2024 22:56:25 +0000 Subject: [PATCH 01/17] [P4_Symbolic] Adding p4_symbolic/symbolic/expected/conditional_nonlattice. [Remove disjointness check on set of tables that get evaluate in each branch of a conditional.] (#767) Co-authored-by: kishanps --- .../expected/conditional_nonlattice.smt2 | 290 ++++++++++++++++++ .../expected/conditional_nonlattice.txt | 18 ++ 2 files changed, 308 insertions(+) create mode 100644 p4_symbolic/symbolic/expected/conditional_nonlattice.smt2 create mode 100644 p4_symbolic/symbolic/expected/conditional_nonlattice.txt diff --git a/p4_symbolic/symbolic/expected/conditional_nonlattice.smt2 b/p4_symbolic/symbolic/expected/conditional_nonlattice.smt2 new file mode 100644 index 00000000..cfba9e48 --- /dev/null +++ b/p4_symbolic/symbolic/expected/conditional_nonlattice.smt2 @@ -0,0 +1,290 @@ +; +(set-info :status unknown) +(declare-fun standard_metadata.ingress_port () (_ BitVec 9)) +(declare-fun standard_metadata.egress_spec () (_ BitVec 9)) +(declare-fun ethernet.dst_addr () (_ BitVec 48)) +(assert + (let (($x170 (= standard_metadata.ingress_port (_ bv19 9)))) + (let (($x165 (= standard_metadata.ingress_port (_ bv18 9)))) + (let (($x160 (= standard_metadata.ingress_port (_ bv17 9)))) + (let (($x155 (= standard_metadata.ingress_port (_ bv16 9)))) + (let (($x150 (= standard_metadata.ingress_port (_ bv15 9)))) + (let (($x145 (= standard_metadata.ingress_port (_ bv14 9)))) + (let (($x140 (= standard_metadata.ingress_port (_ bv13 9)))) + (let (($x135 (= standard_metadata.ingress_port (_ bv12 9)))) + (let (($x130 (= standard_metadata.ingress_port (_ bv11 9)))) + (let (($x125 (= standard_metadata.ingress_port (_ bv10 9)))) + (let (($x120 (= standard_metadata.ingress_port (_ bv9 9)))) + (let (($x115 (= standard_metadata.ingress_port (_ bv8 9)))) + (let (($x110 (= standard_metadata.ingress_port (_ bv7 9)))) + (let (($x105 (= standard_metadata.ingress_port (_ bv6 9)))) + (let (($x100 (= standard_metadata.ingress_port (_ bv5 9)))) + (let (($x95 (= standard_metadata.ingress_port (_ bv4 9)))) + (let (($x90 (= standard_metadata.ingress_port (_ bv3 9)))) + (let (($x85 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x80 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x86 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x80) $x85))) + (let (($x121 (or (or (or (or (or (or (or $x86 $x90) $x95) $x100) $x105) $x110) $x115) $x120))) + (let (($x156 (or (or (or (or (or (or (or $x121 $x125) $x130) $x135) $x140) $x145) $x150) $x155))) + (or (or (or $x156 $x160) $x165) $x170)))))))))))))))))))))))) +(assert + (let (($x37 (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv15 4))))) + (let (($x31 (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv10 4))))) + (let (($x33 (and true $x31))) + (let (($x39 (and $x33 $x37))) + (let (($x40 (and $x33 (not $x37)))) + (let (($x50 (bvugt standard_metadata.ingress_port (concat (_ bv0 6) (_ bv5 3))))) + (let (($x34 (and true (not $x31)))) + (let (($x52 (and $x34 $x50))) + (let ((?x54 (ite $x52 (_ bv511 9) (ite $x40 (_ bv511 9) (ite $x39 (_ bv511 9) standard_metadata.egress_spec))))) + (let (($x53 (and $x34 (not $x50)))) + (let ((?x66 (ite (and true (not (and true (= ethernet.dst_addr (_ bv1 48))))) (_ bv511 9) (ite $x53 (_ bv511 9) ?x54)))) + (let (($x61 (= ethernet.dst_addr (_ bv1 48)))) + (let (($x62 (and true $x61))) + (let (($x63 (and true $x62))) + (let ((?x71 (ite $x63 (_ bv1 9) ?x66))) + (let (($x93 (or (or (or (or false (= ?x71 (_ bv0 9))) (= ?x71 (_ bv1 9))) (= ?x71 (_ bv2 9))) (= ?x71 (_ bv3 9))))) + (let (($x113 (or (or (or (or $x93 (= ?x71 (_ bv4 9))) (= ?x71 (_ bv5 9))) (= ?x71 (_ bv6 9))) (= ?x71 (_ bv7 9))))) + (let (($x133 (or (or (or (or $x113 (= ?x71 (_ bv8 9))) (= ?x71 (_ bv9 9))) (= ?x71 (_ bv10 9))) (= ?x71 (_ bv11 9))))) + (let (($x153 (or (or (or (or $x133 (= ?x71 (_ bv12 9))) (= ?x71 (_ bv13 9))) (= ?x71 (_ bv14 9))) (= ?x71 (_ bv15 9))))) + (let (($x173 (or (or (or (or $x153 (= ?x71 (_ bv16 9))) (= ?x71 (_ bv17 9))) (= ?x71 (_ bv18 9))) (= ?x71 (_ bv19 9))))) + (let (($x73 (= ?x71 (_ bv511 9)))) + (or $x73 $x173))))))))))))))))))))))) +(assert + (let (($x50 (bvugt standard_metadata.ingress_port (concat (_ bv0 6) (_ bv5 3))))) + (let (($x34 (and true (not (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv10 4))))))) + (let (($x52 (and $x34 $x50))) + (let (($x37 (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv15 4))))) + (let (($x31 (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv10 4))))) + (let (($x33 (and true $x31))) + (let (($x39 (and $x33 $x37))) + (let (($x58 (ite $x31 (ite $x37 $x39 false) (ite $x50 $x52 false)))) + (let (($x40 (and $x33 (not $x37)))) + (let ((?x54 (ite $x52 (_ bv511 9) (ite $x40 (_ bv511 9) (ite $x39 (_ bv511 9) standard_metadata.egress_spec))))) + (let (($x53 (and $x34 (not $x50)))) + (let ((?x66 (ite (and true (not (and true (= ethernet.dst_addr (_ bv1 48))))) (_ bv511 9) (ite $x53 (_ bv511 9) ?x54)))) + (let (($x61 (= ethernet.dst_addr (_ bv1 48)))) + (let (($x62 (and true $x61))) + (let (($x63 (and true $x62))) + (let ((?x71 (ite $x63 (_ bv1 9) ?x66))) + (let (($x73 (= ?x71 (_ bv511 9)))) + (and (and (not $x73) $x58) (= (- 1) (- 1))))))))))))))))))))) +(check-sat) + +; +(set-info :status unknown) +(declare-fun standard_metadata.ingress_port () (_ BitVec 9)) +(declare-fun standard_metadata.egress_spec () (_ BitVec 9)) +(declare-fun ethernet.dst_addr () (_ BitVec 48)) +(assert + (let (($x170 (= standard_metadata.ingress_port (_ bv19 9)))) + (let (($x165 (= standard_metadata.ingress_port (_ bv18 9)))) + (let (($x160 (= standard_metadata.ingress_port (_ bv17 9)))) + (let (($x155 (= standard_metadata.ingress_port (_ bv16 9)))) + (let (($x150 (= standard_metadata.ingress_port (_ bv15 9)))) + (let (($x145 (= standard_metadata.ingress_port (_ bv14 9)))) + (let (($x140 (= standard_metadata.ingress_port (_ bv13 9)))) + (let (($x135 (= standard_metadata.ingress_port (_ bv12 9)))) + (let (($x130 (= standard_metadata.ingress_port (_ bv11 9)))) + (let (($x125 (= standard_metadata.ingress_port (_ bv10 9)))) + (let (($x120 (= standard_metadata.ingress_port (_ bv9 9)))) + (let (($x115 (= standard_metadata.ingress_port (_ bv8 9)))) + (let (($x110 (= standard_metadata.ingress_port (_ bv7 9)))) + (let (($x105 (= standard_metadata.ingress_port (_ bv6 9)))) + (let (($x100 (= standard_metadata.ingress_port (_ bv5 9)))) + (let (($x95 (= standard_metadata.ingress_port (_ bv4 9)))) + (let (($x90 (= standard_metadata.ingress_port (_ bv3 9)))) + (let (($x85 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x80 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x86 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x80) $x85))) + (let (($x121 (or (or (or (or (or (or (or $x86 $x90) $x95) $x100) $x105) $x110) $x115) $x120))) + (let (($x156 (or (or (or (or (or (or (or $x121 $x125) $x130) $x135) $x140) $x145) $x150) $x155))) + (or (or (or $x156 $x160) $x165) $x170)))))))))))))))))))))))) +(assert + (let (($x37 (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv15 4))))) + (let (($x31 (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv10 4))))) + (let (($x33 (and true $x31))) + (let (($x39 (and $x33 $x37))) + (let (($x40 (and $x33 (not $x37)))) + (let (($x50 (bvugt standard_metadata.ingress_port (concat (_ bv0 6) (_ bv5 3))))) + (let (($x34 (and true (not $x31)))) + (let (($x52 (and $x34 $x50))) + (let ((?x54 (ite $x52 (_ bv511 9) (ite $x40 (_ bv511 9) (ite $x39 (_ bv511 9) standard_metadata.egress_spec))))) + (let (($x53 (and $x34 (not $x50)))) + (let ((?x66 (ite (and true (not (and true (= ethernet.dst_addr (_ bv1 48))))) (_ bv511 9) (ite $x53 (_ bv511 9) ?x54)))) + (let (($x61 (= ethernet.dst_addr (_ bv1 48)))) + (let (($x62 (and true $x61))) + (let (($x63 (and true $x62))) + (let ((?x71 (ite $x63 (_ bv1 9) ?x66))) + (let (($x93 (or (or (or (or false (= ?x71 (_ bv0 9))) (= ?x71 (_ bv1 9))) (= ?x71 (_ bv2 9))) (= ?x71 (_ bv3 9))))) + (let (($x113 (or (or (or (or $x93 (= ?x71 (_ bv4 9))) (= ?x71 (_ bv5 9))) (= ?x71 (_ bv6 9))) (= ?x71 (_ bv7 9))))) + (let (($x133 (or (or (or (or $x113 (= ?x71 (_ bv8 9))) (= ?x71 (_ bv9 9))) (= ?x71 (_ bv10 9))) (= ?x71 (_ bv11 9))))) + (let (($x153 (or (or (or (or $x133 (= ?x71 (_ bv12 9))) (= ?x71 (_ bv13 9))) (= ?x71 (_ bv14 9))) (= ?x71 (_ bv15 9))))) + (let (($x173 (or (or (or (or $x153 (= ?x71 (_ bv16 9))) (= ?x71 (_ bv17 9))) (= ?x71 (_ bv18 9))) (= ?x71 (_ bv19 9))))) + (let (($x73 (= ?x71 (_ bv511 9)))) + (or $x73 $x173))))))))))))))))))))))) +(assert + (let (($x34 (and true (not (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv10 4))))))) + (let (($x53 (and $x34 (not (bvugt standard_metadata.ingress_port (concat (_ bv0 6) (_ bv5 3))))))) + (let (($x50 (bvugt standard_metadata.ingress_port (concat (_ bv0 6) (_ bv5 3))))) + (let (($x31 (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv10 4))))) + (let (($x33 (and true $x31))) + (let (($x40 (and $x33 (not (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv15 4))))))) + (let (($x37 (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv15 4))))) + (let (($x59 (ite $x31 (ite $x37 false $x40) (ite $x50 false $x53)))) + (let ((?x44 (ite $x40 (_ bv511 9) (ite (and $x33 $x37) (_ bv511 9) standard_metadata.egress_spec)))) + (let (($x52 (and $x34 $x50))) + (let ((?x66 (ite (and true (not (and true (= ethernet.dst_addr (_ bv1 48))))) (_ bv511 9) (ite $x53 (_ bv511 9) (ite $x52 (_ bv511 9) ?x44))))) + (let (($x61 (= ethernet.dst_addr (_ bv1 48)))) + (let (($x62 (and true $x61))) + (let (($x63 (and true $x62))) + (let ((?x71 (ite $x63 (_ bv1 9) ?x66))) + (let (($x73 (= ?x71 (_ bv511 9)))) + (and (and (not $x73) $x59) (= (- 1) (- 1)))))))))))))))))))) +(check-sat) + +; +(set-info :status unknown) +(declare-fun standard_metadata.ingress_port () (_ BitVec 9)) +(declare-fun standard_metadata.egress_spec () (_ BitVec 9)) +(declare-fun ethernet.dst_addr () (_ BitVec 48)) +(assert + (let (($x170 (= standard_metadata.ingress_port (_ bv19 9)))) + (let (($x165 (= standard_metadata.ingress_port (_ bv18 9)))) + (let (($x160 (= standard_metadata.ingress_port (_ bv17 9)))) + (let (($x155 (= standard_metadata.ingress_port (_ bv16 9)))) + (let (($x150 (= standard_metadata.ingress_port (_ bv15 9)))) + (let (($x145 (= standard_metadata.ingress_port (_ bv14 9)))) + (let (($x140 (= standard_metadata.ingress_port (_ bv13 9)))) + (let (($x135 (= standard_metadata.ingress_port (_ bv12 9)))) + (let (($x130 (= standard_metadata.ingress_port (_ bv11 9)))) + (let (($x125 (= standard_metadata.ingress_port (_ bv10 9)))) + (let (($x120 (= standard_metadata.ingress_port (_ bv9 9)))) + (let (($x115 (= standard_metadata.ingress_port (_ bv8 9)))) + (let (($x110 (= standard_metadata.ingress_port (_ bv7 9)))) + (let (($x105 (= standard_metadata.ingress_port (_ bv6 9)))) + (let (($x100 (= standard_metadata.ingress_port (_ bv5 9)))) + (let (($x95 (= standard_metadata.ingress_port (_ bv4 9)))) + (let (($x90 (= standard_metadata.ingress_port (_ bv3 9)))) + (let (($x85 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x80 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x86 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x80) $x85))) + (let (($x121 (or (or (or (or (or (or (or $x86 $x90) $x95) $x100) $x105) $x110) $x115) $x120))) + (let (($x156 (or (or (or (or (or (or (or $x121 $x125) $x130) $x135) $x140) $x145) $x150) $x155))) + (or (or (or $x156 $x160) $x165) $x170)))))))))))))))))))))))) +(assert + (let (($x37 (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv15 4))))) + (let (($x31 (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv10 4))))) + (let (($x33 (and true $x31))) + (let (($x39 (and $x33 $x37))) + (let (($x40 (and $x33 (not $x37)))) + (let (($x50 (bvugt standard_metadata.ingress_port (concat (_ bv0 6) (_ bv5 3))))) + (let (($x34 (and true (not $x31)))) + (let (($x52 (and $x34 $x50))) + (let ((?x54 (ite $x52 (_ bv511 9) (ite $x40 (_ bv511 9) (ite $x39 (_ bv511 9) standard_metadata.egress_spec))))) + (let (($x53 (and $x34 (not $x50)))) + (let ((?x66 (ite (and true (not (and true (= ethernet.dst_addr (_ bv1 48))))) (_ bv511 9) (ite $x53 (_ bv511 9) ?x54)))) + (let (($x61 (= ethernet.dst_addr (_ bv1 48)))) + (let (($x62 (and true $x61))) + (let (($x63 (and true $x62))) + (let ((?x71 (ite $x63 (_ bv1 9) ?x66))) + (let (($x93 (or (or (or (or false (= ?x71 (_ bv0 9))) (= ?x71 (_ bv1 9))) (= ?x71 (_ bv2 9))) (= ?x71 (_ bv3 9))))) + (let (($x113 (or (or (or (or $x93 (= ?x71 (_ bv4 9))) (= ?x71 (_ bv5 9))) (= ?x71 (_ bv6 9))) (= ?x71 (_ bv7 9))))) + (let (($x133 (or (or (or (or $x113 (= ?x71 (_ bv8 9))) (= ?x71 (_ bv9 9))) (= ?x71 (_ bv10 9))) (= ?x71 (_ bv11 9))))) + (let (($x153 (or (or (or (or $x133 (= ?x71 (_ bv12 9))) (= ?x71 (_ bv13 9))) (= ?x71 (_ bv14 9))) (= ?x71 (_ bv15 9))))) + (let (($x173 (or (or (or (or $x153 (= ?x71 (_ bv16 9))) (= ?x71 (_ bv17 9))) (= ?x71 (_ bv18 9))) (= ?x71 (_ bv19 9))))) + (let (($x73 (= ?x71 (_ bv511 9)))) + (or $x73 $x173))))))))))))))))))))))) +(assert + (let (($x61 (= ethernet.dst_addr (_ bv1 48)))) + (let (($x62 (and true $x61))) + (let (($x63 (and true $x62))) + (let ((?x68 (ite $x63 0 (- 1)))) + (let (($x37 (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv15 4))))) + (let (($x31 (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv10 4))))) + (let (($x33 (and true $x31))) + (let (($x39 (and $x33 $x37))) + (let (($x40 (and $x33 (not $x37)))) + (let (($x50 (bvugt standard_metadata.ingress_port (concat (_ bv0 6) (_ bv5 3))))) + (let (($x34 (and true (not $x31)))) + (let (($x52 (and $x34 $x50))) + (let ((?x54 (ite $x52 (_ bv511 9) (ite $x40 (_ bv511 9) (ite $x39 (_ bv511 9) standard_metadata.egress_spec))))) + (let (($x53 (and $x34 (not $x50)))) + (let ((?x71 (ite $x63 (_ bv1 9) (ite (and true (not $x62)) (_ bv511 9) (ite $x53 (_ bv511 9) ?x54))))) + (let (($x73 (= ?x71 (_ bv511 9)))) + (and (and (not $x73) true) (= ?x68 (- 1)))))))))))))))))))) +(check-sat) + +; +(set-info :status unknown) +(declare-fun standard_metadata.ingress_port () (_ BitVec 9)) +(declare-fun standard_metadata.egress_spec () (_ BitVec 9)) +(declare-fun ethernet.dst_addr () (_ BitVec 48)) +(assert + (let (($x170 (= standard_metadata.ingress_port (_ bv19 9)))) + (let (($x165 (= standard_metadata.ingress_port (_ bv18 9)))) + (let (($x160 (= standard_metadata.ingress_port (_ bv17 9)))) + (let (($x155 (= standard_metadata.ingress_port (_ bv16 9)))) + (let (($x150 (= standard_metadata.ingress_port (_ bv15 9)))) + (let (($x145 (= standard_metadata.ingress_port (_ bv14 9)))) + (let (($x140 (= standard_metadata.ingress_port (_ bv13 9)))) + (let (($x135 (= standard_metadata.ingress_port (_ bv12 9)))) + (let (($x130 (= standard_metadata.ingress_port (_ bv11 9)))) + (let (($x125 (= standard_metadata.ingress_port (_ bv10 9)))) + (let (($x120 (= standard_metadata.ingress_port (_ bv9 9)))) + (let (($x115 (= standard_metadata.ingress_port (_ bv8 9)))) + (let (($x110 (= standard_metadata.ingress_port (_ bv7 9)))) + (let (($x105 (= standard_metadata.ingress_port (_ bv6 9)))) + (let (($x100 (= standard_metadata.ingress_port (_ bv5 9)))) + (let (($x95 (= standard_metadata.ingress_port (_ bv4 9)))) + (let (($x90 (= standard_metadata.ingress_port (_ bv3 9)))) + (let (($x85 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x80 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x86 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x80) $x85))) + (let (($x121 (or (or (or (or (or (or (or $x86 $x90) $x95) $x100) $x105) $x110) $x115) $x120))) + (let (($x156 (or (or (or (or (or (or (or $x121 $x125) $x130) $x135) $x140) $x145) $x150) $x155))) + (or (or (or $x156 $x160) $x165) $x170)))))))))))))))))))))))) +(assert + (let (($x37 (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv15 4))))) + (let (($x31 (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv10 4))))) + (let (($x33 (and true $x31))) + (let (($x39 (and $x33 $x37))) + (let (($x40 (and $x33 (not $x37)))) + (let (($x50 (bvugt standard_metadata.ingress_port (concat (_ bv0 6) (_ bv5 3))))) + (let (($x34 (and true (not $x31)))) + (let (($x52 (and $x34 $x50))) + (let ((?x54 (ite $x52 (_ bv511 9) (ite $x40 (_ bv511 9) (ite $x39 (_ bv511 9) standard_metadata.egress_spec))))) + (let (($x53 (and $x34 (not $x50)))) + (let ((?x66 (ite (and true (not (and true (= ethernet.dst_addr (_ bv1 48))))) (_ bv511 9) (ite $x53 (_ bv511 9) ?x54)))) + (let (($x61 (= ethernet.dst_addr (_ bv1 48)))) + (let (($x62 (and true $x61))) + (let (($x63 (and true $x62))) + (let ((?x71 (ite $x63 (_ bv1 9) ?x66))) + (let (($x93 (or (or (or (or false (= ?x71 (_ bv0 9))) (= ?x71 (_ bv1 9))) (= ?x71 (_ bv2 9))) (= ?x71 (_ bv3 9))))) + (let (($x113 (or (or (or (or $x93 (= ?x71 (_ bv4 9))) (= ?x71 (_ bv5 9))) (= ?x71 (_ bv6 9))) (= ?x71 (_ bv7 9))))) + (let (($x133 (or (or (or (or $x113 (= ?x71 (_ bv8 9))) (= ?x71 (_ bv9 9))) (= ?x71 (_ bv10 9))) (= ?x71 (_ bv11 9))))) + (let (($x153 (or (or (or (or $x133 (= ?x71 (_ bv12 9))) (= ?x71 (_ bv13 9))) (= ?x71 (_ bv14 9))) (= ?x71 (_ bv15 9))))) + (let (($x173 (or (or (or (or $x153 (= ?x71 (_ bv16 9))) (= ?x71 (_ bv17 9))) (= ?x71 (_ bv18 9))) (= ?x71 (_ bv19 9))))) + (let (($x73 (= ?x71 (_ bv511 9)))) + (or $x73 $x173))))))))))))))))))))))) +(assert + (let (($x61 (= ethernet.dst_addr (_ bv1 48)))) + (let (($x62 (and true $x61))) + (let (($x63 (and true $x62))) + (let ((?x68 (ite $x63 0 (- 1)))) + (let (($x37 (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv15 4))))) + (let (($x31 (bvugt standard_metadata.ingress_port (concat (_ bv0 5) (_ bv10 4))))) + (let (($x33 (and true $x31))) + (let (($x39 (and $x33 $x37))) + (let (($x40 (and $x33 (not $x37)))) + (let (($x50 (bvugt standard_metadata.ingress_port (concat (_ bv0 6) (_ bv5 3))))) + (let (($x34 (and true (not $x31)))) + (let (($x52 (and $x34 $x50))) + (let ((?x54 (ite $x52 (_ bv511 9) (ite $x40 (_ bv511 9) (ite $x39 (_ bv511 9) standard_metadata.egress_spec))))) + (let (($x53 (and $x34 (not $x50)))) + (let ((?x71 (ite $x63 (_ bv1 9) (ite (and true (not $x62)) (_ bv511 9) (ite $x53 (_ bv511 9) ?x54))))) + (let (($x73 (= ?x71 (_ bv511 9)))) + (let (($x269 (and (not $x73) true))) + (and $x269 (= ?x68 0)))))))))))))))))))) +(check-sat) + diff --git a/p4_symbolic/symbolic/expected/conditional_nonlattice.txt b/p4_symbolic/symbolic/expected/conditional_nonlattice.txt new file mode 100644 index 00000000..625c5f30 --- /dev/null +++ b/p4_symbolic/symbolic/expected/conditional_nonlattice.txt @@ -0,0 +1,18 @@ +Finding packet for table MyIngress.t_1 and row -1 + Dropped = 0 + standard_metadata.ingress_port = #b000001000 + standard_metadata.egress_spec = #b000000001 + +Finding packet for table MyIngress.t_2 and row -1 + Dropped = 0 + standard_metadata.ingress_port = #b000000000 + standard_metadata.egress_spec = #b000000001 + +Finding packet for table MyIngress.t_3 and row -1 +Cannot find solution! + +Finding packet for table MyIngress.t_3 and row 0 + Dropped = 0 + standard_metadata.ingress_port = #b000000000 + standard_metadata.egress_spec = #b000000001 + From 27ca03c152a0927a3df8b4b9e686750629c87fac Mon Sep 17 00:00:00 2001 From: VSuryaprasad-hcl <159443973+VSuryaprasad-HCL@users.noreply.github.com> Date: Wed, 27 Nov 2024 22:57:02 +0000 Subject: [PATCH 02/17] [P4_Symbolic] Adding p4_symbolic/testdata/conditional/conditional_nonlattice files. [Remove disjointness check on set of tables that get evaluate in each branch of a conditional.] (#768) Co-authored-by: kishanps --- .../conditional/conditional_nonlattice.p4 | 145 ++++++++++++++++++ .../conditional_nonlattice_entries.pb.txt | 28 ++++ 2 files changed, 173 insertions(+) create mode 100644 p4_symbolic/testdata/conditional/conditional_nonlattice.p4 create mode 100644 p4_symbolic/testdata/conditional/conditional_nonlattice_entries.pb.txt diff --git a/p4_symbolic/testdata/conditional/conditional_nonlattice.p4 b/p4_symbolic/testdata/conditional/conditional_nonlattice.p4 new file mode 100644 index 00000000..b4f24b82 --- /dev/null +++ b/p4_symbolic/testdata/conditional/conditional_nonlattice.p4 @@ -0,0 +1,145 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* -*- P4_16 -*- */ +#include +#include + +typedef bit<9> egress_spec_t; +typedef bit<48> mac_addr_t; + +header ethernet_t { + mac_addr_t dst_addr; + mac_addr_t src_addr; + bit<16> ether_type; +} + +struct metadata { + /* empty */ +} + +struct headers { + ethernet_t ethernet; +} + +parser MyParser(packet_in packet, + out headers hdr, + inout metadata meta, + inout standard_metadata_t standard_metadata) { + + state start { + transition parse_ethernet; + } + + state parse_ethernet { + packet.extract(hdr.ethernet); + transition accept; + } +} + + +control MyIngress(inout headers hdr, + inout metadata meta, + inout standard_metadata_t standard_metadata) { + action drop() { + mark_to_drop(standard_metadata); + } + + action forward(mac_addr_t dst_addr, egress_spec_t port) { + standard_metadata.egress_spec = port; + hdr.ethernet.dst_addr = dst_addr; + } + + table t_1 { + key = { + hdr.ethernet.ether_type: exact; + } + actions = { + @proto_id(1) drop; + @proto_id(2) forward; + } + size = 1024; + default_action = drop(); + } + table t_2 { + key = { + hdr.ethernet.src_addr: exact; + } + actions = { + @proto_id(1) drop; + @proto_id(2) forward; + } + size = 1024; + default_action = drop(); + } + table t_3 { + key = { + hdr.ethernet.dst_addr: exact; + } + actions = { + @proto_id(1) drop; + @proto_id(2) forward; + } + size = 1024; + default_action = drop(); + } + + apply { + if (standard_metadata.ingress_port > 10) { + if (standard_metadata.ingress_port > 15) { + t_1.apply(); + } else { + t_2.apply(); + } + } else { + if (standard_metadata.ingress_port > 5) { + t_1.apply(); + } else { + t_2.apply(); + } + } + t_3.apply(); + } +} + +control MyEgress(inout headers hdr, + inout metadata meta, + inout standard_metadata_t standard_metadata) { + apply { } +} + + + +control MyDeparser(packet_out packet, in headers hdr) { + apply { + packet.emit(hdr.ethernet); + } +} + +control MyComputeChecksum(inout headers hdr, inout metadata meta) { + apply { } +} + +control MyVerifyChecksum(inout headers hdr, inout metadata meta) { + apply { } +} + +V1Switch( +MyParser(), +MyVerifyChecksum(), +MyIngress(), +MyEgress(), +MyComputeChecksum(), +MyDeparser() +) main; diff --git a/p4_symbolic/testdata/conditional/conditional_nonlattice_entries.pb.txt b/p4_symbolic/testdata/conditional/conditional_nonlattice_entries.pb.txt new file mode 100644 index 00000000..1fda5aa3 --- /dev/null +++ b/p4_symbolic/testdata/conditional/conditional_nonlattice_entries.pb.txt @@ -0,0 +1,28 @@ +updates { + type: INSERT + entity { + table_entry { + table_id: 44506558 # hdr.ethernet.dst_addr + match { + field_id: 1 # dst_addr + exact { + value: "\x00\x00\x00\x00\x00\x01" + } + } + action { + action { + action_id: 29683729 # MyIngress.forward + params { + param_id: 1 # dst_addr + value: "\x00\x00\x00\x00\x00\x02" + } + params { + param_id: 2 # port + value: "\01" + } + } + } + } + } +} + From 58073c6fa8f15810dfce178efd7135e633e4cb9b Mon Sep 17 00:00:00 2001 From: VSuryaprasad-hcl <159443973+VSuryaprasad-HCL@users.noreply.github.com> Date: Wed, 27 Nov 2024 22:57:40 +0000 Subject: [PATCH 03/17] [P4_Symbolic] Remove disjointness check on set of tables that get evaluate in each branch of a conditional. (#769) Co-authored-by: kishanps Co-authored-by: kheradmandG --- p4_symbolic/symbolic/conditional.cc | 8 +- p4_symbolic/symbolic/expected/basic.smt2 | 47 +- .../symbolic/expected/conditional.smt2 | 138 +++--- .../expected/conditional_sequence.smt2 | 350 ++++++++------- p4_symbolic/symbolic/expected/hardcoded.smt2 | 26 +- .../symbolic/expected/table_hit_1.smt2 | 156 ++++--- .../symbolic/expected/table_hit_2.smt2 | 425 ++++++++++-------- p4_symbolic/symbolic/expected/vrf.smt2 | 152 ++++--- p4_symbolic/symbolic/expected/vrf.txt | 14 +- p4_symbolic/symbolic/table.cc | 14 +- p4_symbolic/symbolic/test.bzl | 2 - p4_symbolic/symbolic/util.cc | 27 +- 12 files changed, 730 insertions(+), 629 deletions(-) diff --git a/p4_symbolic/symbolic/conditional.cc b/p4_symbolic/symbolic/conditional.cc index 945c18bb..85815e51 100644 --- a/p4_symbolic/symbolic/conditional.cc +++ b/p4_symbolic/symbolic/conditional.cc @@ -66,10 +66,10 @@ absl::StatusOr EvaluateConditional( data_plane, get_next_control_for_branch(conditional.else_branch()), state, translator, else_guard)); - // Now we have two traces that need merging. The two traces are guaranteed to - // contain different table matches (see go/optimized-symbolic-execution). - ASSIGN_OR_RETURN(SymbolicTableMatches merged_matches, - util::MergeDisjointTableMatches(if_matches, else_matches)); + // Now we have two traces that need merging. + ASSIGN_OR_RETURN( + SymbolicTableMatches merged_matches, + util::MergeMatchesOnCondition(condition, if_matches, else_matches)); if (!conditional.optimized_symbolic_execution_info() .continue_to_merge_point()) { diff --git a/p4_symbolic/symbolic/expected/basic.smt2 b/p4_symbolic/symbolic/expected/basic.smt2 index ea71f237..670ef6d1 100644 --- a/p4_symbolic/symbolic/expected/basic.smt2 +++ b/p4_symbolic/symbolic/expected/basic.smt2 @@ -5,8 +5,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun ipv4.$valid$ () Bool) (assert - (let (($x123 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x123))) + (let (($x125 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x125))) (assert (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) @@ -34,7 +34,8 @@ (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) (let (($x60 (and $x42 $x46))) - (let ((?x112 (ite $x60 1 ?x102))) + (let ((?x120 (ite ipv4.$valid$ (ite $x60 1 ?x102) (- 1)))) + (let (($x119 (ite ipv4.$valid$ $x42 false))) (let (($x61 (not $x46))) (let (($x65 (and $x61 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))))) (let (($x69 (and $x65 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))))) @@ -46,7 +47,7 @@ (let (($x63 (and (and $x42 $x61) $x50))) (let ((?x113 (ite $x60 (_ bv1 9) (ite $x63 (_ bv0 9) (ite $x67 (_ bv1 9) (ite $x71 (_ bv1 9) ?x77)))))) (let (($x41 (= ?x113 (_ bv511 9)))) - (and (and (not $x41) $x42) (= ?x112 (- 1))))))))))))))))))))))) + (and (and (not $x41) $x119) (= ?x120 (- 1)))))))))))))))))))))))) (check-sat) ; @@ -56,8 +57,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun ipv4.$valid$ () Bool) (assert - (let (($x123 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x123))) + (let (($x125 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x125))) (assert (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) @@ -85,7 +86,8 @@ (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) (let (($x60 (and $x42 $x46))) - (let ((?x112 (ite $x60 1 ?x102))) + (let ((?x120 (ite ipv4.$valid$ (ite $x60 1 ?x102) (- 1)))) + (let (($x119 (ite ipv4.$valid$ $x42 false))) (let (($x61 (not $x46))) (let (($x65 (and $x61 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))))) (let (($x69 (and $x65 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))))) @@ -97,8 +99,8 @@ (let (($x63 (and (and $x42 $x61) $x50))) (let ((?x113 (ite $x60 (_ bv1 9) (ite $x63 (_ bv0 9) (ite $x67 (_ bv1 9) (ite $x71 (_ bv1 9) ?x77)))))) (let (($x41 (= ?x113 (_ bv511 9)))) - (let (($x244 (and (not $x41) $x42))) - (and $x244 (= ?x112 0))))))))))))))))))))))) + (let (($x246 (and (not $x41) $x119))) + (and $x246 (= ?x120 0)))))))))))))))))))))))) (check-sat) ; @@ -108,8 +110,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun ipv4.$valid$ () Bool) (assert - (let (($x123 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x123))) + (let (($x125 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x125))) (assert (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) @@ -137,7 +139,8 @@ (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) (let (($x60 (and $x42 $x46))) - (let ((?x112 (ite $x60 1 ?x102))) + (let ((?x120 (ite ipv4.$valid$ (ite $x60 1 ?x102) (- 1)))) + (let (($x119 (ite ipv4.$valid$ $x42 false))) (let (($x61 (not $x46))) (let (($x65 (and $x61 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))))) (let (($x69 (and $x65 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))))) @@ -149,7 +152,7 @@ (let (($x63 (and (and $x42 $x61) $x50))) (let ((?x113 (ite $x60 (_ bv1 9) (ite $x63 (_ bv0 9) (ite $x67 (_ bv1 9) (ite $x71 (_ bv1 9) ?x77)))))) (let (($x41 (= ?x113 (_ bv511 9)))) - (and (and (not $x41) $x42) (= ?x112 1)))))))))))))))))))))) + (and (and (not $x41) $x119) (= ?x120 1))))))))))))))))))))))) (check-sat) ; @@ -159,8 +162,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun ipv4.$valid$ () Bool) (assert - (let (($x123 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x123))) + (let (($x125 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x125))) (assert (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) @@ -188,7 +191,8 @@ (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) (let (($x60 (and $x42 $x46))) - (let ((?x112 (ite $x60 1 ?x102))) + (let ((?x120 (ite ipv4.$valid$ (ite $x60 1 ?x102) (- 1)))) + (let (($x119 (ite ipv4.$valid$ $x42 false))) (let (($x61 (not $x46))) (let (($x65 (and $x61 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))))) (let (($x69 (and $x65 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))))) @@ -200,7 +204,7 @@ (let (($x63 (and (and $x42 $x61) $x50))) (let ((?x113 (ite $x60 (_ bv1 9) (ite $x63 (_ bv0 9) (ite $x67 (_ bv1 9) (ite $x71 (_ bv1 9) ?x77)))))) (let (($x41 (= ?x113 (_ bv511 9)))) - (and (and (not $x41) $x42) (= ?x112 2)))))))))))))))))))))) + (and (and (not $x41) $x119) (= ?x120 2))))))))))))))))))))))) (check-sat) ; @@ -210,8 +214,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun ipv4.$valid$ () Bool) (assert - (let (($x123 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x123))) + (let (($x125 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x125))) (assert (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) @@ -239,7 +243,8 @@ (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) (let (($x60 (and $x42 $x46))) - (let ((?x112 (ite $x60 1 ?x102))) + (let ((?x120 (ite ipv4.$valid$ (ite $x60 1 ?x102) (- 1)))) + (let (($x119 (ite ipv4.$valid$ $x42 false))) (let (($x61 (not $x46))) (let (($x65 (and $x61 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))))) (let (($x69 (and $x65 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))))) @@ -251,6 +256,6 @@ (let (($x63 (and (and $x42 $x61) $x50))) (let ((?x113 (ite $x60 (_ bv1 9) (ite $x63 (_ bv0 9) (ite $x67 (_ bv1 9) (ite $x71 (_ bv1 9) ?x77)))))) (let (($x41 (= ?x113 (_ bv511 9)))) - (and (and (not $x41) $x42) (= ?x112 3)))))))))))))))))))))) + (and (and (not $x41) $x119) (= ?x120 3))))))))))))))))))))))) (check-sat) diff --git a/p4_symbolic/symbolic/expected/conditional.smt2 b/p4_symbolic/symbolic/expected/conditional.smt2 index 194deea5..29458bd6 100644 --- a/p4_symbolic/symbolic/expected/conditional.smt2 +++ b/p4_symbolic/symbolic/expected/conditional.smt2 @@ -4,30 +4,31 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun ethernet.dst_addr () (_ BitVec 48)) (assert - (let (($x59 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x59))) + (let (($x61 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x61))) (assert (let (($x31 (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv0 1))))) (let (($x33 (and true $x31))) (let (($x34 (and true (not $x31)))) - (let ((?x45 (ite (and true (not (and true (= ethernet.dst_addr (_ bv1 48))))) (_ bv511 9) (ite $x34 (_ bv511 9) (ite $x33 (_ bv511 9) standard_metadata.egress_spec))))) - (let (($x40 (= ethernet.dst_addr (_ bv1 48)))) - (let (($x41 (and true $x40))) - (let (($x42 (and true $x41))) - (let ((?x50 (ite $x42 (_ bv1 9) ?x45))) - (let (($x52 (= ?x50 (_ bv511 9)))) - (or $x52 (or (or false (= ?x50 (_ bv0 9))) (= ?x50 (_ bv1 9)))))))))))))) + (let ((?x47 (ite (and true (not (and true (= ethernet.dst_addr (_ bv1 48))))) (_ bv511 9) (ite $x34 (_ bv511 9) (ite $x33 (_ bv511 9) standard_metadata.egress_spec))))) + (let (($x42 (= ethernet.dst_addr (_ bv1 48)))) + (let (($x43 (and true $x42))) + (let (($x44 (and true $x43))) + (let ((?x52 (ite $x44 (_ bv1 9) ?x47))) + (let (($x54 (= ?x52 (_ bv511 9)))) + (or $x54 (or (or false (= ?x52 (_ bv0 9))) (= ?x52 (_ bv1 9)))))))))))))) (assert (let (($x31 (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv0 1))))) (let (($x33 (and true $x31))) + (let (($x39 (ite $x31 $x33 false))) (let (($x34 (and true (not $x31)))) - (let ((?x45 (ite (and true (not (and true (= ethernet.dst_addr (_ bv1 48))))) (_ bv511 9) (ite $x34 (_ bv511 9) (ite $x33 (_ bv511 9) standard_metadata.egress_spec))))) - (let (($x40 (= ethernet.dst_addr (_ bv1 48)))) - (let (($x41 (and true $x40))) - (let (($x42 (and true $x41))) - (let ((?x50 (ite $x42 (_ bv1 9) ?x45))) - (let (($x52 (= ?x50 (_ bv511 9)))) - (and (and (not $x52) $x33) (= (- 1) (- 1))))))))))))) + (let ((?x47 (ite (and true (not (and true (= ethernet.dst_addr (_ bv1 48))))) (_ bv511 9) (ite $x34 (_ bv511 9) (ite $x33 (_ bv511 9) standard_metadata.egress_spec))))) + (let (($x42 (= ethernet.dst_addr (_ bv1 48)))) + (let (($x43 (and true $x42))) + (let (($x44 (and true $x43))) + (let ((?x52 (ite $x44 (_ bv1 9) ?x47))) + (let (($x54 (= ?x52 (_ bv511 9)))) + (and (and (not $x54) $x39) (= (- 1) (- 1)))))))))))))) (check-sat) ; @@ -36,30 +37,31 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun ethernet.dst_addr () (_ BitVec 48)) (assert - (let (($x59 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x59))) + (let (($x61 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x61))) (assert (let (($x31 (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv0 1))))) (let (($x33 (and true $x31))) (let (($x34 (and true (not $x31)))) - (let ((?x45 (ite (and true (not (and true (= ethernet.dst_addr (_ bv1 48))))) (_ bv511 9) (ite $x34 (_ bv511 9) (ite $x33 (_ bv511 9) standard_metadata.egress_spec))))) - (let (($x40 (= ethernet.dst_addr (_ bv1 48)))) - (let (($x41 (and true $x40))) - (let (($x42 (and true $x41))) - (let ((?x50 (ite $x42 (_ bv1 9) ?x45))) - (let (($x52 (= ?x50 (_ bv511 9)))) - (or $x52 (or (or false (= ?x50 (_ bv0 9))) (= ?x50 (_ bv1 9)))))))))))))) + (let ((?x47 (ite (and true (not (and true (= ethernet.dst_addr (_ bv1 48))))) (_ bv511 9) (ite $x34 (_ bv511 9) (ite $x33 (_ bv511 9) standard_metadata.egress_spec))))) + (let (($x42 (= ethernet.dst_addr (_ bv1 48)))) + (let (($x43 (and true $x42))) + (let (($x44 (and true $x43))) + (let ((?x52 (ite $x44 (_ bv1 9) ?x47))) + (let (($x54 (= ?x52 (_ bv511 9)))) + (or $x54 (or (or false (= ?x52 (_ bv0 9))) (= ?x52 (_ bv1 9)))))))))))))) (assert (let (($x34 (and true (not (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv0 1))))))) (let (($x31 (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv0 1))))) - (let (($x33 (and true $x31))) - (let ((?x45 (ite (and true (not (and true (= ethernet.dst_addr (_ bv1 48))))) (_ bv511 9) (ite $x34 (_ bv511 9) (ite $x33 (_ bv511 9) standard_metadata.egress_spec))))) - (let (($x40 (= ethernet.dst_addr (_ bv1 48)))) - (let (($x41 (and true $x40))) - (let (($x42 (and true $x41))) - (let ((?x50 (ite $x42 (_ bv1 9) ?x45))) - (let (($x52 (= ?x50 (_ bv511 9)))) - (and (and (not $x52) $x34) (= (- 1) (- 1))))))))))))) + (let (($x40 (ite $x31 false $x34))) + (let ((?x38 (ite $x34 (_ bv511 9) (ite (and true $x31) (_ bv511 9) standard_metadata.egress_spec)))) + (let ((?x47 (ite (and true (not (and true (= ethernet.dst_addr (_ bv1 48))))) (_ bv511 9) ?x38))) + (let (($x42 (= ethernet.dst_addr (_ bv1 48)))) + (let (($x43 (and true $x42))) + (let (($x44 (and true $x43))) + (let ((?x52 (ite $x44 (_ bv1 9) ?x47))) + (let (($x54 (= ?x52 (_ bv511 9)))) + (and (and (not $x54) $x40) (= (- 1) (- 1)))))))))))))) (check-sat) ; @@ -68,31 +70,31 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun ethernet.dst_addr () (_ BitVec 48)) (assert - (let (($x59 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x59))) + (let (($x61 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x61))) (assert (let (($x31 (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv0 1))))) (let (($x33 (and true $x31))) (let (($x34 (and true (not $x31)))) - (let ((?x45 (ite (and true (not (and true (= ethernet.dst_addr (_ bv1 48))))) (_ bv511 9) (ite $x34 (_ bv511 9) (ite $x33 (_ bv511 9) standard_metadata.egress_spec))))) - (let (($x40 (= ethernet.dst_addr (_ bv1 48)))) - (let (($x41 (and true $x40))) - (let (($x42 (and true $x41))) - (let ((?x50 (ite $x42 (_ bv1 9) ?x45))) - (let (($x52 (= ?x50 (_ bv511 9)))) - (or $x52 (or (or false (= ?x50 (_ bv0 9))) (= ?x50 (_ bv1 9)))))))))))))) + (let ((?x47 (ite (and true (not (and true (= ethernet.dst_addr (_ bv1 48))))) (_ bv511 9) (ite $x34 (_ bv511 9) (ite $x33 (_ bv511 9) standard_metadata.egress_spec))))) + (let (($x42 (= ethernet.dst_addr (_ bv1 48)))) + (let (($x43 (and true $x42))) + (let (($x44 (and true $x43))) + (let ((?x52 (ite $x44 (_ bv1 9) ?x47))) + (let (($x54 (= ?x52 (_ bv511 9)))) + (or $x54 (or (or false (= ?x52 (_ bv0 9))) (= ?x52 (_ bv1 9)))))))))))))) (assert - (let (($x40 (= ethernet.dst_addr (_ bv1 48)))) - (let (($x41 (and true $x40))) - (let (($x42 (and true $x41))) - (let ((?x47 (ite $x42 0 (- 1)))) + (let (($x42 (= ethernet.dst_addr (_ bv1 48)))) + (let (($x43 (and true $x42))) + (let (($x44 (and true $x43))) + (let ((?x49 (ite $x44 0 (- 1)))) (let (($x31 (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv0 1))))) (let (($x33 (and true $x31))) (let (($x34 (and true (not $x31)))) - (let ((?x45 (ite (and true (not $x41)) (_ bv511 9) (ite $x34 (_ bv511 9) (ite $x33 (_ bv511 9) standard_metadata.egress_spec))))) - (let ((?x50 (ite $x42 (_ bv1 9) ?x45))) - (let (($x52 (= ?x50 (_ bv511 9)))) - (and (and (not $x52) true) (= ?x47 (- 1)))))))))))))) + (let ((?x47 (ite (and true (not $x43)) (_ bv511 9) (ite $x34 (_ bv511 9) (ite $x33 (_ bv511 9) standard_metadata.egress_spec))))) + (let ((?x52 (ite $x44 (_ bv1 9) ?x47))) + (let (($x54 (= ?x52 (_ bv511 9)))) + (and (and (not $x54) true) (= ?x49 (- 1)))))))))))))) (check-sat) ; @@ -101,31 +103,31 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun ethernet.dst_addr () (_ BitVec 48)) (assert - (let (($x59 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x59))) + (let (($x61 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x61))) (assert (let (($x31 (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv0 1))))) (let (($x33 (and true $x31))) (let (($x34 (and true (not $x31)))) - (let ((?x45 (ite (and true (not (and true (= ethernet.dst_addr (_ bv1 48))))) (_ bv511 9) (ite $x34 (_ bv511 9) (ite $x33 (_ bv511 9) standard_metadata.egress_spec))))) - (let (($x40 (= ethernet.dst_addr (_ bv1 48)))) - (let (($x41 (and true $x40))) - (let (($x42 (and true $x41))) - (let ((?x50 (ite $x42 (_ bv1 9) ?x45))) - (let (($x52 (= ?x50 (_ bv511 9)))) - (or $x52 (or (or false (= ?x50 (_ bv0 9))) (= ?x50 (_ bv1 9)))))))))))))) + (let ((?x47 (ite (and true (not (and true (= ethernet.dst_addr (_ bv1 48))))) (_ bv511 9) (ite $x34 (_ bv511 9) (ite $x33 (_ bv511 9) standard_metadata.egress_spec))))) + (let (($x42 (= ethernet.dst_addr (_ bv1 48)))) + (let (($x43 (and true $x42))) + (let (($x44 (and true $x43))) + (let ((?x52 (ite $x44 (_ bv1 9) ?x47))) + (let (($x54 (= ?x52 (_ bv511 9)))) + (or $x54 (or (or false (= ?x52 (_ bv0 9))) (= ?x52 (_ bv1 9)))))))))))))) (assert - (let (($x40 (= ethernet.dst_addr (_ bv1 48)))) - (let (($x41 (and true $x40))) - (let (($x42 (and true $x41))) - (let ((?x47 (ite $x42 0 (- 1)))) + (let (($x42 (= ethernet.dst_addr (_ bv1 48)))) + (let (($x43 (and true $x42))) + (let (($x44 (and true $x43))) + (let ((?x49 (ite $x44 0 (- 1)))) (let (($x31 (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv0 1))))) (let (($x33 (and true $x31))) (let (($x34 (and true (not $x31)))) - (let ((?x45 (ite (and true (not $x41)) (_ bv511 9) (ite $x34 (_ bv511 9) (ite $x33 (_ bv511 9) standard_metadata.egress_spec))))) - (let ((?x50 (ite $x42 (_ bv1 9) ?x45))) - (let (($x52 (= ?x50 (_ bv511 9)))) - (let (($x95 (and (not $x52) true))) - (and $x95 (= ?x47 0)))))))))))))) + (let ((?x47 (ite (and true (not $x43)) (_ bv511 9) (ite $x34 (_ bv511 9) (ite $x33 (_ bv511 9) standard_metadata.egress_spec))))) + (let ((?x52 (ite $x44 (_ bv1 9) ?x47))) + (let (($x54 (= ?x52 (_ bv511 9)))) + (let (($x97 (and (not $x54) true))) + (and $x97 (= ?x49 0)))))))))))))) (check-sat) diff --git a/p4_symbolic/symbolic/expected/conditional_sequence.smt2 b/p4_symbolic/symbolic/expected/conditional_sequence.smt2 index 43922001..521c9730 100644 --- a/p4_symbolic/symbolic/expected/conditional_sequence.smt2 +++ b/p4_symbolic/symbolic/expected/conditional_sequence.smt2 @@ -4,17 +4,19 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun h1.f1 () (_ BitVec 8)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x90))) + (let (($x106 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x106))) (assert - (let (($x92 (= standard_metadata.egress_spec (_ bv1 9)))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (or $x76 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x92))))) + (let (($x108 (= standard_metadata.egress_spec (_ bv1 9)))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (or $x92 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x108))))) (assert - (let (($x41 (and true (not (= h1.f1 (concat (_ bv0 7) (_ bv0 1))))))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (let (($x134 (not $x76))) - (and (and $x134 $x41) (= (- 1) (- 1))))))) + (let ((?x37 (concat (_ bv0 7) (_ bv0 1)))) + (let (($x38 (= h1.f1 ?x37))) + (let (($x44 (ite $x38 false (and true (not $x38))))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (let (($x150 (not $x92))) + (and (and $x150 $x44) (= (- 1) (- 1))))))))) (check-sat) ; @@ -23,17 +25,19 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun h1.f2 () (_ BitVec 8)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x90))) + (let (($x106 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x106))) (assert - (let (($x92 (= standard_metadata.egress_spec (_ bv1 9)))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (or $x76 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x92))))) + (let (($x108 (= standard_metadata.egress_spec (_ bv1 9)))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (or $x92 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x108))))) (assert - (let (($x46 (and true (not (= h1.f2 (concat (_ bv0 7) (_ bv0 1))))))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (let (($x134 (not $x76))) - (and (and $x134 $x46) (= (- 1) (- 1))))))) + (let ((?x37 (concat (_ bv0 7) (_ bv0 1)))) + (let (($x45 (= h1.f2 ?x37))) + (let (($x50 (ite $x45 false (and true (not $x45))))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (let (($x150 (not $x92))) + (and (and $x150 $x50) (= (- 1) (- 1))))))))) (check-sat) ; @@ -42,17 +46,19 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun h1.f3 () (_ BitVec 8)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x90))) + (let (($x106 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x106))) (assert - (let (($x92 (= standard_metadata.egress_spec (_ bv1 9)))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (or $x76 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x92))))) + (let (($x108 (= standard_metadata.egress_spec (_ bv1 9)))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (or $x92 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x108))))) (assert - (let (($x50 (and true (not (= h1.f3 (concat (_ bv0 7) (_ bv0 1))))))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (let (($x134 (not $x76))) - (and (and $x134 $x50) (= (- 1) (- 1))))))) + (let ((?x37 (concat (_ bv0 7) (_ bv0 1)))) + (let (($x51 (= h1.f3 ?x37))) + (let (($x56 (ite $x51 false (and true (not $x51))))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (let (($x150 (not $x92))) + (and (and $x150 $x56) (= (- 1) (- 1))))))))) (check-sat) ; @@ -61,17 +67,19 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun h1.f4 () (_ BitVec 8)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x90))) + (let (($x106 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x106))) (assert - (let (($x92 (= standard_metadata.egress_spec (_ bv1 9)))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (or $x76 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x92))))) + (let (($x108 (= standard_metadata.egress_spec (_ bv1 9)))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (or $x92 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x108))))) (assert - (let (($x54 (and true (not (= h1.f4 (concat (_ bv0 7) (_ bv0 1))))))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (let (($x134 (not $x76))) - (and (and $x134 $x54) (= (- 1) (- 1))))))) + (let ((?x37 (concat (_ bv0 7) (_ bv0 1)))) + (let (($x57 (= h1.f4 ?x37))) + (let (($x62 (ite $x57 false (and true (not $x57))))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (let (($x150 (not $x92))) + (and (and $x150 $x62) (= (- 1) (- 1))))))))) (check-sat) ; @@ -80,17 +88,19 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun h1.f5 () (_ BitVec 8)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x90))) + (let (($x106 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x106))) (assert - (let (($x92 (= standard_metadata.egress_spec (_ bv1 9)))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (or $x76 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x92))))) + (let (($x108 (= standard_metadata.egress_spec (_ bv1 9)))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (or $x92 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x108))))) (assert - (let (($x58 (and true (not (= h1.f5 (concat (_ bv0 7) (_ bv0 1))))))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (let (($x134 (not $x76))) - (and (and $x134 $x58) (= (- 1) (- 1))))))) + (let ((?x37 (concat (_ bv0 7) (_ bv0 1)))) + (let (($x63 (= h1.f5 ?x37))) + (let (($x68 (ite $x63 false (and true (not $x63))))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (let (($x150 (not $x92))) + (and (and $x150 $x68) (= (- 1) (- 1))))))))) (check-sat) ; @@ -99,17 +109,19 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun h1.f6 () (_ BitVec 8)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x90))) + (let (($x106 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x106))) (assert - (let (($x92 (= standard_metadata.egress_spec (_ bv1 9)))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (or $x76 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x92))))) + (let (($x108 (= standard_metadata.egress_spec (_ bv1 9)))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (or $x92 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x108))))) (assert - (let (($x62 (and true (not (= h1.f6 (concat (_ bv0 7) (_ bv0 1))))))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (let (($x134 (not $x76))) - (and (and $x134 $x62) (= (- 1) (- 1))))))) + (let ((?x37 (concat (_ bv0 7) (_ bv0 1)))) + (let (($x69 (= h1.f6 ?x37))) + (let (($x74 (ite $x69 false (and true (not $x69))))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (let (($x150 (not $x92))) + (and (and $x150 $x74) (= (- 1) (- 1))))))))) (check-sat) ; @@ -118,17 +130,19 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun h1.f7 () (_ BitVec 8)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x90))) + (let (($x106 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x106))) (assert - (let (($x92 (= standard_metadata.egress_spec (_ bv1 9)))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (or $x76 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x92))))) + (let (($x108 (= standard_metadata.egress_spec (_ bv1 9)))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (or $x92 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x108))))) (assert - (let (($x66 (and true (not (= h1.f7 (concat (_ bv0 7) (_ bv0 1))))))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (let (($x134 (not $x76))) - (and (and $x134 $x66) (= (- 1) (- 1))))))) + (let ((?x37 (concat (_ bv0 7) (_ bv0 1)))) + (let (($x75 (= h1.f7 ?x37))) + (let (($x80 (ite $x75 false (and true (not $x75))))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (let (($x150 (not $x92))) + (and (and $x150 $x80) (= (- 1) (- 1))))))))) (check-sat) ; @@ -137,17 +151,19 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun h1.f8 () (_ BitVec 8)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x90))) + (let (($x106 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x106))) (assert - (let (($x92 (= standard_metadata.egress_spec (_ bv1 9)))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (or $x76 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x92))))) + (let (($x108 (= standard_metadata.egress_spec (_ bv1 9)))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (or $x92 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x108))))) (assert - (let (($x70 (and true (not (= h1.f8 (concat (_ bv0 7) (_ bv0 1))))))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (let (($x134 (not $x76))) - (and (and $x134 $x70) (= (- 1) (- 1))))))) + (let ((?x37 (concat (_ bv0 7) (_ bv0 1)))) + (let (($x81 (= h1.f8 ?x37))) + (let (($x86 (ite $x81 false (and true (not $x81))))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (let (($x150 (not $x92))) + (and (and $x150 $x86) (= (- 1) (- 1))))))))) (check-sat) ; @@ -156,19 +172,19 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun h1.f1 () (_ BitVec 8)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x90))) + (let (($x106 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x106))) (assert - (let (($x92 (= standard_metadata.egress_spec (_ bv1 9)))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (or $x76 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x92))))) + (let (($x108 (= standard_metadata.egress_spec (_ bv1 9)))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (or $x92 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x108))))) (assert (let ((?x37 (concat (_ bv0 7) (_ bv0 1)))) (let (($x38 (= h1.f1 ?x37))) - (let (($x40 (and true $x38))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (let (($x134 (not $x76))) - (and (and $x134 $x40) (= (- 1) (- 1))))))))) + (let (($x43 (ite $x38 (and true $x38) false))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (let (($x150 (not $x92))) + (and (and $x150 $x43) (= (- 1) (- 1))))))))) (check-sat) ; @@ -177,19 +193,19 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun h1.f2 () (_ BitVec 8)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x90))) + (let (($x106 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x106))) (assert - (let (($x92 (= standard_metadata.egress_spec (_ bv1 9)))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (or $x76 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x92))))) + (let (($x108 (= standard_metadata.egress_spec (_ bv1 9)))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (or $x92 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x108))))) (assert (let ((?x37 (concat (_ bv0 7) (_ bv0 1)))) - (let (($x43 (= h1.f2 ?x37))) - (let (($x45 (and true $x43))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (let (($x134 (not $x76))) - (and (and $x134 $x45) (= (- 1) (- 1))))))))) + (let (($x45 (= h1.f2 ?x37))) + (let (($x49 (ite $x45 (and true $x45) false))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (let (($x150 (not $x92))) + (and (and $x150 $x49) (= (- 1) (- 1))))))))) (check-sat) ; @@ -198,19 +214,19 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun h1.f3 () (_ BitVec 8)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x90))) + (let (($x106 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x106))) (assert - (let (($x92 (= standard_metadata.egress_spec (_ bv1 9)))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (or $x76 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x92))))) + (let (($x108 (= standard_metadata.egress_spec (_ bv1 9)))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (or $x92 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x108))))) (assert (let ((?x37 (concat (_ bv0 7) (_ bv0 1)))) - (let (($x47 (= h1.f3 ?x37))) - (let (($x49 (and true $x47))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (let (($x134 (not $x76))) - (and (and $x134 $x49) (= (- 1) (- 1))))))))) + (let (($x51 (= h1.f3 ?x37))) + (let (($x55 (ite $x51 (and true $x51) false))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (let (($x150 (not $x92))) + (and (and $x150 $x55) (= (- 1) (- 1))))))))) (check-sat) ; @@ -219,19 +235,19 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun h1.f4 () (_ BitVec 8)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x90))) + (let (($x106 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x106))) (assert - (let (($x92 (= standard_metadata.egress_spec (_ bv1 9)))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (or $x76 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x92))))) + (let (($x108 (= standard_metadata.egress_spec (_ bv1 9)))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (or $x92 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x108))))) (assert (let ((?x37 (concat (_ bv0 7) (_ bv0 1)))) - (let (($x51 (= h1.f4 ?x37))) - (let (($x53 (and true $x51))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (let (($x134 (not $x76))) - (and (and $x134 $x53) (= (- 1) (- 1))))))))) + (let (($x57 (= h1.f4 ?x37))) + (let (($x61 (ite $x57 (and true $x57) false))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (let (($x150 (not $x92))) + (and (and $x150 $x61) (= (- 1) (- 1))))))))) (check-sat) ; @@ -240,19 +256,19 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun h1.f5 () (_ BitVec 8)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x90))) + (let (($x106 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x106))) (assert - (let (($x92 (= standard_metadata.egress_spec (_ bv1 9)))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (or $x76 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x92))))) + (let (($x108 (= standard_metadata.egress_spec (_ bv1 9)))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (or $x92 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x108))))) (assert (let ((?x37 (concat (_ bv0 7) (_ bv0 1)))) - (let (($x55 (= h1.f5 ?x37))) - (let (($x57 (and true $x55))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (let (($x134 (not $x76))) - (and (and $x134 $x57) (= (- 1) (- 1))))))))) + (let (($x63 (= h1.f5 ?x37))) + (let (($x67 (ite $x63 (and true $x63) false))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (let (($x150 (not $x92))) + (and (and $x150 $x67) (= (- 1) (- 1))))))))) (check-sat) ; @@ -261,19 +277,19 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun h1.f6 () (_ BitVec 8)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x90))) + (let (($x106 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x106))) (assert - (let (($x92 (= standard_metadata.egress_spec (_ bv1 9)))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (or $x76 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x92))))) + (let (($x108 (= standard_metadata.egress_spec (_ bv1 9)))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (or $x92 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x108))))) (assert (let ((?x37 (concat (_ bv0 7) (_ bv0 1)))) - (let (($x59 (= h1.f6 ?x37))) - (let (($x61 (and true $x59))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (let (($x134 (not $x76))) - (and (and $x134 $x61) (= (- 1) (- 1))))))))) + (let (($x69 (= h1.f6 ?x37))) + (let (($x73 (ite $x69 (and true $x69) false))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (let (($x150 (not $x92))) + (and (and $x150 $x73) (= (- 1) (- 1))))))))) (check-sat) ; @@ -282,19 +298,19 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun h1.f7 () (_ BitVec 8)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x90))) + (let (($x106 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x106))) (assert - (let (($x92 (= standard_metadata.egress_spec (_ bv1 9)))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (or $x76 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x92))))) + (let (($x108 (= standard_metadata.egress_spec (_ bv1 9)))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (or $x92 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x108))))) (assert (let ((?x37 (concat (_ bv0 7) (_ bv0 1)))) - (let (($x63 (= h1.f7 ?x37))) - (let (($x65 (and true $x63))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (let (($x134 (not $x76))) - (and (and $x134 $x65) (= (- 1) (- 1))))))))) + (let (($x75 (= h1.f7 ?x37))) + (let (($x79 (ite $x75 (and true $x75) false))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (let (($x150 (not $x92))) + (and (and $x150 $x79) (= (- 1) (- 1))))))))) (check-sat) ; @@ -303,19 +319,19 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun h1.f8 () (_ BitVec 8)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x90))) + (let (($x106 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x106))) (assert - (let (($x92 (= standard_metadata.egress_spec (_ bv1 9)))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (or $x76 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x92))))) + (let (($x108 (= standard_metadata.egress_spec (_ bv1 9)))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (or $x92 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x108))))) (assert (let ((?x37 (concat (_ bv0 7) (_ bv0 1)))) - (let (($x67 (= h1.f8 ?x37))) - (let (($x69 (and true $x67))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (let (($x134 (not $x76))) - (and (and $x134 $x69) (= (- 1) (- 1))))))))) + (let (($x81 (= h1.f8 ?x37))) + (let (($x85 (ite $x81 (and true $x81) false))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (let (($x150 (not $x92))) + (and (and $x150 $x85) (= (- 1) (- 1))))))))) (check-sat) ; @@ -324,16 +340,16 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun h1.fr () (_ BitVec 8)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x90))) + (let (($x106 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x106))) (assert - (let (($x92 (= standard_metadata.egress_spec (_ bv1 9)))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (or $x76 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x92))))) + (let (($x108 (= standard_metadata.egress_spec (_ bv1 9)))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (or $x92 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x108))))) (assert - (let (($x74 (and true (and true (= h1.fr (_ bv255 8)))))) - (let ((?x78 (ite $x74 0 (- 1)))) - (and (and (not (= standard_metadata.egress_spec (_ bv511 9))) true) (= ?x78 (- 1)))))) + (let (($x90 (and true (and true (= h1.fr (_ bv255 8)))))) + (let ((?x94 (ite $x90 0 (- 1)))) + (and (and (not (= standard_metadata.egress_spec (_ bv511 9))) true) (= ?x94 (- 1)))))) (check-sat) ; @@ -342,14 +358,14 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun h1.fr () (_ BitVec 8)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x90))) + (let (($x106 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x106))) (assert - (let (($x92 (= standard_metadata.egress_spec (_ bv1 9)))) - (let (($x76 (= standard_metadata.egress_spec (_ bv511 9)))) - (or $x76 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x92))))) + (let (($x108 (= standard_metadata.egress_spec (_ bv1 9)))) + (let (($x92 (= standard_metadata.egress_spec (_ bv511 9)))) + (or $x92 (or (or false (= standard_metadata.egress_spec (_ bv0 9))) $x108))))) (assert - (let (($x74 (and true (and true (= h1.fr (_ bv255 8)))))) - (let ((?x78 (ite $x74 0 (- 1)))) - (and (and (not (= standard_metadata.egress_spec (_ bv511 9))) true) (= ?x78 0))))) + (let (($x90 (and true (and true (= h1.fr (_ bv255 8)))))) + (let ((?x94 (ite $x90 0 (- 1)))) + (and (and (not (= standard_metadata.egress_spec (_ bv511 9))) true) (= ?x94 0))))) (check-sat) diff --git a/p4_symbolic/symbolic/expected/hardcoded.smt2 b/p4_symbolic/symbolic/expected/hardcoded.smt2 index d9199890..76c947da 100644 --- a/p4_symbolic/symbolic/expected/hardcoded.smt2 +++ b/p4_symbolic/symbolic/expected/hardcoded.smt2 @@ -3,24 +3,25 @@ (declare-fun standard_metadata.ingress_port () (_ BitVec 9)) (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (assert - (let (($x45 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x45))) + (let (($x47 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x47))) (assert (let ((?x26 (concat (_ bv0 8) (_ bv0 1)))) (let (($x27 (= standard_metadata.ingress_port ?x26))) (let (($x29 (and true $x27))) (let (($x30 (and true (not $x27)))) (let ((?x35 (ite $x30 ?x26 (ite $x29 (concat (_ bv0 8) (_ bv1 1)) standard_metadata.egress_spec)))) - (let (($x37 (= ?x35 (_ bv511 9)))) - (or $x37 (or (or false (= ?x35 (_ bv0 9))) (= ?x35 (_ bv1 9))))))))))) + (let (($x39 (= ?x35 (_ bv511 9)))) + (or $x39 (or (or false (= ?x35 (_ bv0 9))) (= ?x35 (_ bv1 9))))))))))) (assert (let ((?x26 (concat (_ bv0 8) (_ bv0 1)))) (let (($x27 (= standard_metadata.ingress_port ?x26))) (let (($x29 (and true $x27))) + (let (($x36 (ite $x27 $x29 false))) (let (($x30 (and true (not $x27)))) (let ((?x35 (ite $x30 ?x26 (ite $x29 (concat (_ bv0 8) (_ bv1 1)) standard_metadata.egress_spec)))) - (let (($x37 (= ?x35 (_ bv511 9)))) - (and (and (not $x37) $x29) (= (- 1) (- 1)))))))))) + (let (($x39 (= ?x35 (_ bv511 9)))) + (and (and (not $x39) $x36) (= (- 1) (- 1))))))))))) (check-sat) ; @@ -28,23 +29,24 @@ (declare-fun standard_metadata.ingress_port () (_ BitVec 9)) (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (assert - (let (($x45 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x45))) + (let (($x47 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x47))) (assert (let ((?x26 (concat (_ bv0 8) (_ bv0 1)))) (let (($x27 (= standard_metadata.ingress_port ?x26))) (let (($x29 (and true $x27))) (let (($x30 (and true (not $x27)))) (let ((?x35 (ite $x30 ?x26 (ite $x29 (concat (_ bv0 8) (_ bv1 1)) standard_metadata.egress_spec)))) - (let (($x37 (= ?x35 (_ bv511 9)))) - (or $x37 (or (or false (= ?x35 (_ bv0 9))) (= ?x35 (_ bv1 9))))))))))) + (let (($x39 (= ?x35 (_ bv511 9)))) + (or $x39 (or (or false (= ?x35 (_ bv0 9))) (= ?x35 (_ bv1 9))))))))))) (assert (let (($x30 (and true (not (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv0 1))))))) (let ((?x26 (concat (_ bv0 8) (_ bv0 1)))) (let (($x27 (= standard_metadata.ingress_port ?x26))) + (let (($x37 (ite $x27 false $x30))) (let (($x29 (and true $x27))) (let ((?x35 (ite $x30 ?x26 (ite $x29 (concat (_ bv0 8) (_ bv1 1)) standard_metadata.egress_spec)))) - (let (($x37 (= ?x35 (_ bv511 9)))) - (and (and (not $x37) $x30) (= (- 1) (- 1)))))))))) + (let (($x39 (= ?x35 (_ bv511 9)))) + (and (and (not $x39) $x37) (= (- 1) (- 1))))))))))) (check-sat) diff --git a/p4_symbolic/symbolic/expected/table_hit_1.smt2 b/p4_symbolic/symbolic/expected/table_hit_1.smt2 index 8860c77c..12f99633 100644 --- a/p4_symbolic/symbolic/expected/table_hit_1.smt2 +++ b/p4_symbolic/symbolic/expected/table_hit_1.smt2 @@ -5,38 +5,41 @@ (declare-fun ethernet.ether_type () (_ BitVec 16)) (declare-fun ethernet.src_addr () (_ BitVec 48)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv7 9)))) - (let (($x85 (= standard_metadata.ingress_port (_ bv6 9)))) - (let (($x80 (= standard_metadata.ingress_port (_ bv5 9)))) - (let (($x75 (= standard_metadata.ingress_port (_ bv4 9)))) - (let (($x70 (= standard_metadata.ingress_port (_ bv3 9)))) - (let (($x66 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x62 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x67 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x62) $x66))) - (or (or (or (or (or $x67 $x70) $x75) $x80) $x85) $x90)))))))))) + (let (($x92 (= standard_metadata.ingress_port (_ bv7 9)))) + (let (($x87 (= standard_metadata.ingress_port (_ bv6 9)))) + (let (($x82 (= standard_metadata.ingress_port (_ bv5 9)))) + (let (($x77 (= standard_metadata.ingress_port (_ bv4 9)))) + (let (($x72 (= standard_metadata.ingress_port (_ bv3 9)))) + (let (($x68 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x64 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x69 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x64) $x68))) + (or (or (or (or (or $x69 $x72) $x77) $x82) $x87) $x92)))))))))) (assert (let ((?x36 (ite (and true (not (and true (= ethernet.ether_type (_ bv16 16))))) (_ bv511 9) standard_metadata.egress_spec))) (let (($x29 (= ethernet.ether_type (_ bv16 16)))) (let (($x30 (and true $x29))) (let (($x31 (and true $x30))) - (let (($x44 (and true (and (distinct (ite $x31 0 (- 1)) (- 1)) true)))) + (let ((?x38 (ite $x31 0 (- 1)))) + (let (($x43 (and (distinct ?x38 (- 1)) true))) + (let (($x44 (and true $x43))) (let (($x48 (and $x44 (and true (= ethernet.src_addr (_ bv256 48)))))) (let ((?x54 (ite $x48 (_ bv3 9) (ite $x31 (_ bv2 9) ?x36)))) - (let (($x73 (or (or (or (or false (= ?x54 (_ bv0 9))) (= ?x54 (_ bv1 9))) (= ?x54 (_ bv2 9))) (= ?x54 (_ bv3 9))))) - (let (($x93 (or (or (or (or $x73 (= ?x54 (_ bv4 9))) (= ?x54 (_ bv5 9))) (= ?x54 (_ bv6 9))) (= ?x54 (_ bv7 9))))) - (let (($x49 (= ?x54 (_ bv511 9)))) - (or $x49 $x93)))))))))))) + (let (($x75 (or (or (or (or false (= ?x54 (_ bv0 9))) (= ?x54 (_ bv1 9))) (= ?x54 (_ bv2 9))) (= ?x54 (_ bv3 9))))) + (let (($x95 (or (or (or (or $x75 (= ?x54 (_ bv4 9))) (= ?x54 (_ bv5 9))) (= ?x54 (_ bv6 9))) (= ?x54 (_ bv7 9))))) + (let (($x56 (= ?x54 (_ bv511 9)))) + (or $x56 $x95)))))))))))))) (assert (let (($x29 (= ethernet.ether_type (_ bv16 16)))) (let (($x30 (and true $x29))) (let (($x31 (and true $x30))) (let ((?x38 (ite $x31 0 (- 1)))) (let ((?x41 (ite $x31 (_ bv2 9) (ite (and true (not $x30)) (_ bv511 9) standard_metadata.egress_spec)))) - (let (($x44 (and true (and (distinct ?x38 (- 1)) true)))) + (let (($x43 (and (distinct ?x38 (- 1)) true))) + (let (($x44 (and true $x43))) (let (($x48 (and $x44 (and true (= ethernet.src_addr (_ bv256 48)))))) (let ((?x54 (ite $x48 (_ bv3 9) ?x41))) - (let (($x49 (= ?x54 (_ bv511 9)))) - (and (and (not $x49) true) (= ?x38 (- 1))))))))))))) + (let (($x56 (= ?x54 (_ bv511 9)))) + (and (and (not $x56) true) (= ?x38 (- 1)))))))))))))) (check-sat) ; @@ -46,39 +49,42 @@ (declare-fun ethernet.ether_type () (_ BitVec 16)) (declare-fun ethernet.src_addr () (_ BitVec 48)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv7 9)))) - (let (($x85 (= standard_metadata.ingress_port (_ bv6 9)))) - (let (($x80 (= standard_metadata.ingress_port (_ bv5 9)))) - (let (($x75 (= standard_metadata.ingress_port (_ bv4 9)))) - (let (($x70 (= standard_metadata.ingress_port (_ bv3 9)))) - (let (($x66 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x62 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x67 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x62) $x66))) - (or (or (or (or (or $x67 $x70) $x75) $x80) $x85) $x90)))))))))) + (let (($x92 (= standard_metadata.ingress_port (_ bv7 9)))) + (let (($x87 (= standard_metadata.ingress_port (_ bv6 9)))) + (let (($x82 (= standard_metadata.ingress_port (_ bv5 9)))) + (let (($x77 (= standard_metadata.ingress_port (_ bv4 9)))) + (let (($x72 (= standard_metadata.ingress_port (_ bv3 9)))) + (let (($x68 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x64 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x69 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x64) $x68))) + (or (or (or (or (or $x69 $x72) $x77) $x82) $x87) $x92)))))))))) (assert (let ((?x36 (ite (and true (not (and true (= ethernet.ether_type (_ bv16 16))))) (_ bv511 9) standard_metadata.egress_spec))) (let (($x29 (= ethernet.ether_type (_ bv16 16)))) (let (($x30 (and true $x29))) (let (($x31 (and true $x30))) - (let (($x44 (and true (and (distinct (ite $x31 0 (- 1)) (- 1)) true)))) + (let ((?x38 (ite $x31 0 (- 1)))) + (let (($x43 (and (distinct ?x38 (- 1)) true))) + (let (($x44 (and true $x43))) (let (($x48 (and $x44 (and true (= ethernet.src_addr (_ bv256 48)))))) (let ((?x54 (ite $x48 (_ bv3 9) (ite $x31 (_ bv2 9) ?x36)))) - (let (($x73 (or (or (or (or false (= ?x54 (_ bv0 9))) (= ?x54 (_ bv1 9))) (= ?x54 (_ bv2 9))) (= ?x54 (_ bv3 9))))) - (let (($x93 (or (or (or (or $x73 (= ?x54 (_ bv4 9))) (= ?x54 (_ bv5 9))) (= ?x54 (_ bv6 9))) (= ?x54 (_ bv7 9))))) - (let (($x49 (= ?x54 (_ bv511 9)))) - (or $x49 $x93)))))))))))) + (let (($x75 (or (or (or (or false (= ?x54 (_ bv0 9))) (= ?x54 (_ bv1 9))) (= ?x54 (_ bv2 9))) (= ?x54 (_ bv3 9))))) + (let (($x95 (or (or (or (or $x75 (= ?x54 (_ bv4 9))) (= ?x54 (_ bv5 9))) (= ?x54 (_ bv6 9))) (= ?x54 (_ bv7 9))))) + (let (($x56 (= ?x54 (_ bv511 9)))) + (or $x56 $x95)))))))))))))) (assert (let (($x29 (= ethernet.ether_type (_ bv16 16)))) (let (($x30 (and true $x29))) (let (($x31 (and true $x30))) (let ((?x38 (ite $x31 0 (- 1)))) (let ((?x41 (ite $x31 (_ bv2 9) (ite (and true (not $x30)) (_ bv511 9) standard_metadata.egress_spec)))) - (let (($x44 (and true (and (distinct ?x38 (- 1)) true)))) + (let (($x43 (and (distinct ?x38 (- 1)) true))) + (let (($x44 (and true $x43))) (let (($x48 (and $x44 (and true (= ethernet.src_addr (_ bv256 48)))))) (let ((?x54 (ite $x48 (_ bv3 9) ?x41))) - (let (($x49 (= ?x54 (_ bv511 9)))) - (let (($x206 (and (not $x49) true))) - (and $x206 (= ?x38 0))))))))))))) + (let (($x56 (= ?x54 (_ bv511 9)))) + (let (($x208 (and (not $x56) true))) + (and $x208 (= ?x38 0)))))))))))))) (check-sat) ; @@ -88,39 +94,43 @@ (declare-fun ethernet.ether_type () (_ BitVec 16)) (declare-fun ethernet.src_addr () (_ BitVec 48)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv7 9)))) - (let (($x85 (= standard_metadata.ingress_port (_ bv6 9)))) - (let (($x80 (= standard_metadata.ingress_port (_ bv5 9)))) - (let (($x75 (= standard_metadata.ingress_port (_ bv4 9)))) - (let (($x70 (= standard_metadata.ingress_port (_ bv3 9)))) - (let (($x66 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x62 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x67 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x62) $x66))) - (or (or (or (or (or $x67 $x70) $x75) $x80) $x85) $x90)))))))))) + (let (($x92 (= standard_metadata.ingress_port (_ bv7 9)))) + (let (($x87 (= standard_metadata.ingress_port (_ bv6 9)))) + (let (($x82 (= standard_metadata.ingress_port (_ bv5 9)))) + (let (($x77 (= standard_metadata.ingress_port (_ bv4 9)))) + (let (($x72 (= standard_metadata.ingress_port (_ bv3 9)))) + (let (($x68 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x64 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x69 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x64) $x68))) + (or (or (or (or (or $x69 $x72) $x77) $x82) $x87) $x92)))))))))) (assert (let ((?x36 (ite (and true (not (and true (= ethernet.ether_type (_ bv16 16))))) (_ bv511 9) standard_metadata.egress_spec))) (let (($x29 (= ethernet.ether_type (_ bv16 16)))) (let (($x30 (and true $x29))) (let (($x31 (and true $x30))) - (let (($x44 (and true (and (distinct (ite $x31 0 (- 1)) (- 1)) true)))) + (let ((?x38 (ite $x31 0 (- 1)))) + (let (($x43 (and (distinct ?x38 (- 1)) true))) + (let (($x44 (and true $x43))) (let (($x48 (and $x44 (and true (= ethernet.src_addr (_ bv256 48)))))) (let ((?x54 (ite $x48 (_ bv3 9) (ite $x31 (_ bv2 9) ?x36)))) - (let (($x73 (or (or (or (or false (= ?x54 (_ bv0 9))) (= ?x54 (_ bv1 9))) (= ?x54 (_ bv2 9))) (= ?x54 (_ bv3 9))))) - (let (($x93 (or (or (or (or $x73 (= ?x54 (_ bv4 9))) (= ?x54 (_ bv5 9))) (= ?x54 (_ bv6 9))) (= ?x54 (_ bv7 9))))) - (let (($x49 (= ?x54 (_ bv511 9)))) - (or $x49 $x93)))))))))))) + (let (($x75 (or (or (or (or false (= ?x54 (_ bv0 9))) (= ?x54 (_ bv1 9))) (= ?x54 (_ bv2 9))) (= ?x54 (_ bv3 9))))) + (let (($x95 (or (or (or (or $x75 (= ?x54 (_ bv4 9))) (= ?x54 (_ bv5 9))) (= ?x54 (_ bv6 9))) (= ?x54 (_ bv7 9))))) + (let (($x56 (= ?x54 (_ bv511 9)))) + (or $x56 $x95)))))))))))))) (assert (let (($x29 (= ethernet.ether_type (_ bv16 16)))) (let (($x30 (and true $x29))) (let (($x31 (and true $x30))) (let ((?x38 (ite $x31 0 (- 1)))) - (let (($x44 (and true (and (distinct ?x38 (- 1)) true)))) + (let (($x43 (and (distinct ?x38 (- 1)) true))) + (let (($x44 (and true $x43))) (let (($x48 (and $x44 (and true (= ethernet.src_addr (_ bv256 48)))))) - (let ((?x51 (ite $x48 0 (- 1)))) + (let ((?x50 (ite $x43 (ite $x48 0 (- 1)) (- 1)))) + (let (($x49 (ite $x43 $x44 false))) (let ((?x41 (ite $x31 (_ bv2 9) (ite (and true (not $x30)) (_ bv511 9) standard_metadata.egress_spec)))) (let ((?x54 (ite $x48 (_ bv3 9) ?x41))) - (let (($x49 (= ?x54 (_ bv511 9)))) - (and (and (not $x49) $x44) (= ?x51 (- 1)))))))))))))) + (let (($x56 (= ?x54 (_ bv511 9)))) + (and (and (not $x56) $x49) (= ?x50 (- 1)))))))))))))))) (check-sat) ; @@ -130,38 +140,42 @@ (declare-fun ethernet.ether_type () (_ BitVec 16)) (declare-fun ethernet.src_addr () (_ BitVec 48)) (assert - (let (($x90 (= standard_metadata.ingress_port (_ bv7 9)))) - (let (($x85 (= standard_metadata.ingress_port (_ bv6 9)))) - (let (($x80 (= standard_metadata.ingress_port (_ bv5 9)))) - (let (($x75 (= standard_metadata.ingress_port (_ bv4 9)))) - (let (($x70 (= standard_metadata.ingress_port (_ bv3 9)))) - (let (($x66 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x62 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x67 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x62) $x66))) - (or (or (or (or (or $x67 $x70) $x75) $x80) $x85) $x90)))))))))) + (let (($x92 (= standard_metadata.ingress_port (_ bv7 9)))) + (let (($x87 (= standard_metadata.ingress_port (_ bv6 9)))) + (let (($x82 (= standard_metadata.ingress_port (_ bv5 9)))) + (let (($x77 (= standard_metadata.ingress_port (_ bv4 9)))) + (let (($x72 (= standard_metadata.ingress_port (_ bv3 9)))) + (let (($x68 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x64 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x69 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x64) $x68))) + (or (or (or (or (or $x69 $x72) $x77) $x82) $x87) $x92)))))))))) (assert (let ((?x36 (ite (and true (not (and true (= ethernet.ether_type (_ bv16 16))))) (_ bv511 9) standard_metadata.egress_spec))) (let (($x29 (= ethernet.ether_type (_ bv16 16)))) (let (($x30 (and true $x29))) (let (($x31 (and true $x30))) - (let (($x44 (and true (and (distinct (ite $x31 0 (- 1)) (- 1)) true)))) + (let ((?x38 (ite $x31 0 (- 1)))) + (let (($x43 (and (distinct ?x38 (- 1)) true))) + (let (($x44 (and true $x43))) (let (($x48 (and $x44 (and true (= ethernet.src_addr (_ bv256 48)))))) (let ((?x54 (ite $x48 (_ bv3 9) (ite $x31 (_ bv2 9) ?x36)))) - (let (($x73 (or (or (or (or false (= ?x54 (_ bv0 9))) (= ?x54 (_ bv1 9))) (= ?x54 (_ bv2 9))) (= ?x54 (_ bv3 9))))) - (let (($x93 (or (or (or (or $x73 (= ?x54 (_ bv4 9))) (= ?x54 (_ bv5 9))) (= ?x54 (_ bv6 9))) (= ?x54 (_ bv7 9))))) - (let (($x49 (= ?x54 (_ bv511 9)))) - (or $x49 $x93)))))))))))) + (let (($x75 (or (or (or (or false (= ?x54 (_ bv0 9))) (= ?x54 (_ bv1 9))) (= ?x54 (_ bv2 9))) (= ?x54 (_ bv3 9))))) + (let (($x95 (or (or (or (or $x75 (= ?x54 (_ bv4 9))) (= ?x54 (_ bv5 9))) (= ?x54 (_ bv6 9))) (= ?x54 (_ bv7 9))))) + (let (($x56 (= ?x54 (_ bv511 9)))) + (or $x56 $x95)))))))))))))) (assert (let (($x29 (= ethernet.ether_type (_ bv16 16)))) (let (($x30 (and true $x29))) (let (($x31 (and true $x30))) (let ((?x38 (ite $x31 0 (- 1)))) - (let (($x44 (and true (and (distinct ?x38 (- 1)) true)))) + (let (($x43 (and (distinct ?x38 (- 1)) true))) + (let (($x44 (and true $x43))) (let (($x48 (and $x44 (and true (= ethernet.src_addr (_ bv256 48)))))) - (let ((?x51 (ite $x48 0 (- 1)))) + (let ((?x50 (ite $x43 (ite $x48 0 (- 1)) (- 1)))) + (let (($x49 (ite $x43 $x44 false))) (let ((?x41 (ite $x31 (_ bv2 9) (ite (and true (not $x30)) (_ bv511 9) standard_metadata.egress_spec)))) (let ((?x54 (ite $x48 (_ bv3 9) ?x41))) - (let (($x49 (= ?x54 (_ bv511 9)))) - (and (and (not $x49) $x44) (= ?x51 0))))))))))))) + (let (($x56 (= ?x54 (_ bv511 9)))) + (and (and (not $x56) $x49) (= ?x50 0))))))))))))))) (check-sat) diff --git a/p4_symbolic/symbolic/expected/table_hit_2.smt2 b/p4_symbolic/symbolic/expected/table_hit_2.smt2 index 684383af..68790db9 100644 --- a/p4_symbolic/symbolic/expected/table_hit_2.smt2 +++ b/p4_symbolic/symbolic/expected/table_hit_2.smt2 @@ -6,41 +6,43 @@ (declare-fun h1.f2 () (_ BitVec 8)) (declare-fun h1.f3 () (_ BitVec 8)) (assert - (let (($x94 (= standard_metadata.ingress_port (_ bv7 9)))) - (let (($x89 (= standard_metadata.ingress_port (_ bv6 9)))) - (let (($x84 (= standard_metadata.ingress_port (_ bv5 9)))) - (let (($x79 (= standard_metadata.ingress_port (_ bv4 9)))) - (let (($x74 (= standard_metadata.ingress_port (_ bv3 9)))) - (let (($x70 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x66 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x71 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x66) $x70))) - (or (or (or (or (or $x71 $x74) $x79) $x84) $x89) $x94)))))))))) + (let (($x100 (= standard_metadata.ingress_port (_ bv7 9)))) + (let (($x95 (= standard_metadata.ingress_port (_ bv6 9)))) + (let (($x90 (= standard_metadata.ingress_port (_ bv5 9)))) + (let (($x85 (= standard_metadata.ingress_port (_ bv4 9)))) + (let (($x80 (= standard_metadata.ingress_port (_ bv3 9)))) + (let (($x76 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x72 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x77 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x72) $x76))) + (or (or (or (or (or $x77 $x80) $x85) $x90) $x95) $x100)))))))))) (assert (let (($x37 (and true (and true (= h1.f1 (_ bv255 8)))))) (let ((?x43 (ite $x37 (_ bv1 9) (ite true (concat (_ bv0 8) (_ bv0 1)) standard_metadata.egress_spec)))) - (let (($x45 (and true (and (distinct (ite $x37 0 (- 1)) (- 1)) true)))) - (let (($x48 (and $x45 (and true (= h1.f2 (_ bv255 8)))))) (let ((?x41 (ite $x37 0 (- 1)))) - (let (($x49 (= ?x41 (- 1)))) - (let (($x50 (and true $x49))) - (let (($x56 (and $x50 (and true (= h1.f3 (_ bv255 8)))))) - (let ((?x61 (ite $x56 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) - (let (($x77 (or (or (or (or false (= ?x61 (_ bv0 9))) (= ?x61 (_ bv1 9))) (= ?x61 (_ bv2 9))) (= ?x61 (_ bv3 9))))) - (let (($x97 (or (or (or (or $x77 (= ?x61 (_ bv4 9))) (= ?x61 (_ bv5 9))) (= ?x61 (_ bv6 9))) (= ?x61 (_ bv7 9))))) - (let (($x39 (= ?x61 (_ bv511 9)))) - (or $x39 $x97)))))))))))))) + (let (($x44 (and (distinct ?x41 (- 1)) true))) + (let (($x45 (and true $x44))) + (let (($x48 (and $x45 (and true (= h1.f2 (_ bv255 8)))))) + (let (($x54 (= ?x41 (- 1)))) + (let (($x55 (and true $x54))) + (let (($x58 (and $x55 (and true (= h1.f3 (_ bv255 8)))))) + (let ((?x63 (ite $x58 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) + (let (($x83 (or (or (or (or false (= ?x63 (_ bv0 9))) (= ?x63 (_ bv1 9))) (= ?x63 (_ bv2 9))) (= ?x63 (_ bv3 9))))) + (let (($x103 (or (or (or (or $x83 (= ?x63 (_ bv4 9))) (= ?x63 (_ bv5 9))) (= ?x63 (_ bv6 9))) (= ?x63 (_ bv7 9))))) + (let (($x39 (= ?x63 (_ bv511 9)))) + (or $x39 $x103))))))))))))))) (assert (let (($x37 (and true (and true (= h1.f1 (_ bv255 8)))))) (let ((?x41 (ite $x37 0 (- 1)))) - (let (($x49 (= ?x41 (- 1)))) + (let (($x54 (= ?x41 (- 1)))) (let ((?x43 (ite $x37 (_ bv1 9) (ite true (concat (_ bv0 8) (_ bv0 1)) standard_metadata.egress_spec)))) - (let (($x45 (and true (and (distinct ?x41 (- 1)) true)))) + (let (($x44 (and (distinct ?x41 (- 1)) true))) + (let (($x45 (and true $x44))) (let (($x48 (and $x45 (and true (= h1.f2 (_ bv255 8)))))) - (let (($x50 (and true $x49))) - (let (($x56 (and $x50 (and true (= h1.f3 (_ bv255 8)))))) - (let ((?x61 (ite $x56 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) - (let (($x39 (= ?x61 (_ bv511 9)))) - (and (and (not $x39) true) $x49)))))))))))) + (let (($x55 (and true $x54))) + (let (($x58 (and $x55 (and true (= h1.f3 (_ bv255 8)))))) + (let ((?x63 (ite $x58 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) + (let (($x39 (= ?x63 (_ bv511 9)))) + (and (and (not $x39) true) $x54))))))))))))) (check-sat) ; @@ -51,38 +53,43 @@ (declare-fun h1.f2 () (_ BitVec 8)) (declare-fun h1.f3 () (_ BitVec 8)) (assert - (let (($x94 (= standard_metadata.ingress_port (_ bv7 9)))) - (let (($x89 (= standard_metadata.ingress_port (_ bv6 9)))) - (let (($x84 (= standard_metadata.ingress_port (_ bv5 9)))) - (let (($x79 (= standard_metadata.ingress_port (_ bv4 9)))) - (let (($x74 (= standard_metadata.ingress_port (_ bv3 9)))) - (let (($x70 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x66 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x71 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x66) $x70))) - (or (or (or (or (or $x71 $x74) $x79) $x84) $x89) $x94)))))))))) + (let (($x100 (= standard_metadata.ingress_port (_ bv7 9)))) + (let (($x95 (= standard_metadata.ingress_port (_ bv6 9)))) + (let (($x90 (= standard_metadata.ingress_port (_ bv5 9)))) + (let (($x85 (= standard_metadata.ingress_port (_ bv4 9)))) + (let (($x80 (= standard_metadata.ingress_port (_ bv3 9)))) + (let (($x76 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x72 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x77 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x72) $x76))) + (or (or (or (or (or $x77 $x80) $x85) $x90) $x95) $x100)))))))))) (assert (let (($x37 (and true (and true (= h1.f1 (_ bv255 8)))))) (let ((?x43 (ite $x37 (_ bv1 9) (ite true (concat (_ bv0 8) (_ bv0 1)) standard_metadata.egress_spec)))) - (let (($x45 (and true (and (distinct (ite $x37 0 (- 1)) (- 1)) true)))) + (let ((?x41 (ite $x37 0 (- 1)))) + (let (($x44 (and (distinct ?x41 (- 1)) true))) + (let (($x45 (and true $x44))) (let (($x48 (and $x45 (and true (= h1.f2 (_ bv255 8)))))) - (let (($x50 (and true (= (ite $x37 0 (- 1)) (- 1))))) - (let (($x56 (and $x50 (and true (= h1.f3 (_ bv255 8)))))) - (let ((?x61 (ite $x56 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) - (let (($x77 (or (or (or (or false (= ?x61 (_ bv0 9))) (= ?x61 (_ bv1 9))) (= ?x61 (_ bv2 9))) (= ?x61 (_ bv3 9))))) - (let (($x97 (or (or (or (or $x77 (= ?x61 (_ bv4 9))) (= ?x61 (_ bv5 9))) (= ?x61 (_ bv6 9))) (= ?x61 (_ bv7 9))))) - (let (($x39 (= ?x61 (_ bv511 9)))) - (or $x39 $x97)))))))))))) + (let (($x54 (= ?x41 (- 1)))) + (let (($x55 (and true $x54))) + (let (($x58 (and $x55 (and true (= h1.f3 (_ bv255 8)))))) + (let ((?x63 (ite $x58 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) + (let (($x83 (or (or (or (or false (= ?x63 (_ bv0 9))) (= ?x63 (_ bv1 9))) (= ?x63 (_ bv2 9))) (= ?x63 (_ bv3 9))))) + (let (($x103 (or (or (or (or $x83 (= ?x63 (_ bv4 9))) (= ?x63 (_ bv5 9))) (= ?x63 (_ bv6 9))) (= ?x63 (_ bv7 9))))) + (let (($x39 (= ?x63 (_ bv511 9)))) + (or $x39 $x103))))))))))))))) (assert (let (($x37 (and true (and true (= h1.f1 (_ bv255 8)))))) (let ((?x41 (ite $x37 0 (- 1)))) (let ((?x43 (ite $x37 (_ bv1 9) (ite true (concat (_ bv0 8) (_ bv0 1)) standard_metadata.egress_spec)))) - (let (($x45 (and true (and (distinct ?x41 (- 1)) true)))) + (let (($x44 (and (distinct ?x41 (- 1)) true))) + (let (($x45 (and true $x44))) (let (($x48 (and $x45 (and true (= h1.f2 (_ bv255 8)))))) - (let (($x50 (and true (= ?x41 (- 1))))) - (let (($x56 (and $x50 (and true (= h1.f3 (_ bv255 8)))))) - (let ((?x61 (ite $x56 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) - (let (($x39 (= ?x61 (_ bv511 9)))) - (and (and (not $x39) true) (= ?x41 0)))))))))))) + (let (($x54 (= ?x41 (- 1)))) + (let (($x55 (and true $x54))) + (let (($x58 (and $x55 (and true (= h1.f3 (_ bv255 8)))))) + (let ((?x63 (ite $x58 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) + (let (($x39 (= ?x63 (_ bv511 9)))) + (and (and (not $x39) true) (= ?x41 0)))))))))))))) (check-sat) ; @@ -93,39 +100,45 @@ (declare-fun h1.f2 () (_ BitVec 8)) (declare-fun h1.f3 () (_ BitVec 8)) (assert - (let (($x94 (= standard_metadata.ingress_port (_ bv7 9)))) - (let (($x89 (= standard_metadata.ingress_port (_ bv6 9)))) - (let (($x84 (= standard_metadata.ingress_port (_ bv5 9)))) - (let (($x79 (= standard_metadata.ingress_port (_ bv4 9)))) - (let (($x74 (= standard_metadata.ingress_port (_ bv3 9)))) - (let (($x70 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x66 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x71 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x66) $x70))) - (or (or (or (or (or $x71 $x74) $x79) $x84) $x89) $x94)))))))))) + (let (($x100 (= standard_metadata.ingress_port (_ bv7 9)))) + (let (($x95 (= standard_metadata.ingress_port (_ bv6 9)))) + (let (($x90 (= standard_metadata.ingress_port (_ bv5 9)))) + (let (($x85 (= standard_metadata.ingress_port (_ bv4 9)))) + (let (($x80 (= standard_metadata.ingress_port (_ bv3 9)))) + (let (($x76 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x72 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x77 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x72) $x76))) + (or (or (or (or (or $x77 $x80) $x85) $x90) $x95) $x100)))))))))) (assert (let (($x37 (and true (and true (= h1.f1 (_ bv255 8)))))) (let ((?x43 (ite $x37 (_ bv1 9) (ite true (concat (_ bv0 8) (_ bv0 1)) standard_metadata.egress_spec)))) - (let (($x45 (and true (and (distinct (ite $x37 0 (- 1)) (- 1)) true)))) + (let ((?x41 (ite $x37 0 (- 1)))) + (let (($x44 (and (distinct ?x41 (- 1)) true))) + (let (($x45 (and true $x44))) (let (($x48 (and $x45 (and true (= h1.f2 (_ bv255 8)))))) - (let (($x50 (and true (= (ite $x37 0 (- 1)) (- 1))))) - (let (($x56 (and $x50 (and true (= h1.f3 (_ bv255 8)))))) - (let ((?x61 (ite $x56 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) - (let (($x77 (or (or (or (or false (= ?x61 (_ bv0 9))) (= ?x61 (_ bv1 9))) (= ?x61 (_ bv2 9))) (= ?x61 (_ bv3 9))))) - (let (($x97 (or (or (or (or $x77 (= ?x61 (_ bv4 9))) (= ?x61 (_ bv5 9))) (= ?x61 (_ bv6 9))) (= ?x61 (_ bv7 9))))) - (let (($x39 (= ?x61 (_ bv511 9)))) - (or $x39 $x97)))))))))))) + (let (($x54 (= ?x41 (- 1)))) + (let (($x55 (and true $x54))) + (let (($x58 (and $x55 (and true (= h1.f3 (_ bv255 8)))))) + (let ((?x63 (ite $x58 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) + (let (($x83 (or (or (or (or false (= ?x63 (_ bv0 9))) (= ?x63 (_ bv1 9))) (= ?x63 (_ bv2 9))) (= ?x63 (_ bv3 9))))) + (let (($x103 (or (or (or (or $x83 (= ?x63 (_ bv4 9))) (= ?x63 (_ bv5 9))) (= ?x63 (_ bv6 9))) (= ?x63 (_ bv7 9))))) + (let (($x39 (= ?x63 (_ bv511 9)))) + (or $x39 $x103))))))))))))))) (assert (let (($x37 (and true (and true (= h1.f1 (_ bv255 8)))))) (let ((?x41 (ite $x37 0 (- 1)))) - (let (($x45 (and true (and (distinct ?x41 (- 1)) true)))) + (let (($x44 (and (distinct ?x41 (- 1)) true))) + (let (($x45 (and true $x44))) (let (($x48 (and $x45 (and true (= h1.f2 (_ bv255 8)))))) - (let ((?x51 (ite $x48 0 (- 1)))) + (let (($x54 (= ?x41 (- 1)))) + (let ((?x65 (ite $x54 (- 1) (ite $x44 (ite $x48 0 (- 1)) (- 1))))) + (let (($x64 (ite $x54 false (ite $x44 $x45 false)))) (let ((?x43 (ite $x37 (_ bv1 9) (ite true (concat (_ bv0 8) (_ bv0 1)) standard_metadata.egress_spec)))) - (let (($x50 (and true (= ?x41 (- 1))))) - (let (($x56 (and $x50 (and true (= h1.f3 (_ bv255 8)))))) - (let ((?x61 (ite $x56 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) - (let (($x39 (= ?x61 (_ bv511 9)))) - (and (and (not $x39) $x45) (= ?x51 (- 1)))))))))))))) + (let (($x55 (and true $x54))) + (let (($x58 (and $x55 (and true (= h1.f3 (_ bv255 8)))))) + (let ((?x63 (ite $x58 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) + (let (($x39 (= ?x63 (_ bv511 9)))) + (and (and (not $x39) $x64) (= ?x65 (- 1))))))))))))))))) (check-sat) ; @@ -136,39 +149,45 @@ (declare-fun h1.f2 () (_ BitVec 8)) (declare-fun h1.f3 () (_ BitVec 8)) (assert - (let (($x94 (= standard_metadata.ingress_port (_ bv7 9)))) - (let (($x89 (= standard_metadata.ingress_port (_ bv6 9)))) - (let (($x84 (= standard_metadata.ingress_port (_ bv5 9)))) - (let (($x79 (= standard_metadata.ingress_port (_ bv4 9)))) - (let (($x74 (= standard_metadata.ingress_port (_ bv3 9)))) - (let (($x70 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x66 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x71 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x66) $x70))) - (or (or (or (or (or $x71 $x74) $x79) $x84) $x89) $x94)))))))))) + (let (($x100 (= standard_metadata.ingress_port (_ bv7 9)))) + (let (($x95 (= standard_metadata.ingress_port (_ bv6 9)))) + (let (($x90 (= standard_metadata.ingress_port (_ bv5 9)))) + (let (($x85 (= standard_metadata.ingress_port (_ bv4 9)))) + (let (($x80 (= standard_metadata.ingress_port (_ bv3 9)))) + (let (($x76 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x72 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x77 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x72) $x76))) + (or (or (or (or (or $x77 $x80) $x85) $x90) $x95) $x100)))))))))) (assert (let (($x37 (and true (and true (= h1.f1 (_ bv255 8)))))) (let ((?x43 (ite $x37 (_ bv1 9) (ite true (concat (_ bv0 8) (_ bv0 1)) standard_metadata.egress_spec)))) - (let (($x45 (and true (and (distinct (ite $x37 0 (- 1)) (- 1)) true)))) + (let ((?x41 (ite $x37 0 (- 1)))) + (let (($x44 (and (distinct ?x41 (- 1)) true))) + (let (($x45 (and true $x44))) (let (($x48 (and $x45 (and true (= h1.f2 (_ bv255 8)))))) - (let (($x50 (and true (= (ite $x37 0 (- 1)) (- 1))))) - (let (($x56 (and $x50 (and true (= h1.f3 (_ bv255 8)))))) - (let ((?x61 (ite $x56 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) - (let (($x77 (or (or (or (or false (= ?x61 (_ bv0 9))) (= ?x61 (_ bv1 9))) (= ?x61 (_ bv2 9))) (= ?x61 (_ bv3 9))))) - (let (($x97 (or (or (or (or $x77 (= ?x61 (_ bv4 9))) (= ?x61 (_ bv5 9))) (= ?x61 (_ bv6 9))) (= ?x61 (_ bv7 9))))) - (let (($x39 (= ?x61 (_ bv511 9)))) - (or $x39 $x97)))))))))))) + (let (($x54 (= ?x41 (- 1)))) + (let (($x55 (and true $x54))) + (let (($x58 (and $x55 (and true (= h1.f3 (_ bv255 8)))))) + (let ((?x63 (ite $x58 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) + (let (($x83 (or (or (or (or false (= ?x63 (_ bv0 9))) (= ?x63 (_ bv1 9))) (= ?x63 (_ bv2 9))) (= ?x63 (_ bv3 9))))) + (let (($x103 (or (or (or (or $x83 (= ?x63 (_ bv4 9))) (= ?x63 (_ bv5 9))) (= ?x63 (_ bv6 9))) (= ?x63 (_ bv7 9))))) + (let (($x39 (= ?x63 (_ bv511 9)))) + (or $x39 $x103))))))))))))))) (assert (let (($x37 (and true (and true (= h1.f1 (_ bv255 8)))))) (let ((?x41 (ite $x37 0 (- 1)))) - (let (($x45 (and true (and (distinct ?x41 (- 1)) true)))) + (let (($x44 (and (distinct ?x41 (- 1)) true))) + (let (($x45 (and true $x44))) (let (($x48 (and $x45 (and true (= h1.f2 (_ bv255 8)))))) - (let ((?x51 (ite $x48 0 (- 1)))) + (let (($x54 (= ?x41 (- 1)))) + (let ((?x65 (ite $x54 (- 1) (ite $x44 (ite $x48 0 (- 1)) (- 1))))) + (let (($x64 (ite $x54 false (ite $x44 $x45 false)))) (let ((?x43 (ite $x37 (_ bv1 9) (ite true (concat (_ bv0 8) (_ bv0 1)) standard_metadata.egress_spec)))) - (let (($x50 (and true (= ?x41 (- 1))))) - (let (($x56 (and $x50 (and true (= h1.f3 (_ bv255 8)))))) - (let ((?x61 (ite $x56 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) - (let (($x39 (= ?x61 (_ bv511 9)))) - (and (and (not $x39) $x45) (= ?x51 0))))))))))))) + (let (($x55 (and true $x54))) + (let (($x58 (and $x55 (and true (= h1.f3 (_ bv255 8)))))) + (let ((?x63 (ite $x58 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) + (let (($x39 (= ?x63 (_ bv511 9)))) + (and (and (not $x39) $x64) (= ?x65 0)))))))))))))))) (check-sat) ; @@ -179,39 +198,45 @@ (declare-fun h1.f2 () (_ BitVec 8)) (declare-fun h1.f3 () (_ BitVec 8)) (assert - (let (($x94 (= standard_metadata.ingress_port (_ bv7 9)))) - (let (($x89 (= standard_metadata.ingress_port (_ bv6 9)))) - (let (($x84 (= standard_metadata.ingress_port (_ bv5 9)))) - (let (($x79 (= standard_metadata.ingress_port (_ bv4 9)))) - (let (($x74 (= standard_metadata.ingress_port (_ bv3 9)))) - (let (($x70 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x66 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x71 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x66) $x70))) - (or (or (or (or (or $x71 $x74) $x79) $x84) $x89) $x94)))))))))) + (let (($x100 (= standard_metadata.ingress_port (_ bv7 9)))) + (let (($x95 (= standard_metadata.ingress_port (_ bv6 9)))) + (let (($x90 (= standard_metadata.ingress_port (_ bv5 9)))) + (let (($x85 (= standard_metadata.ingress_port (_ bv4 9)))) + (let (($x80 (= standard_metadata.ingress_port (_ bv3 9)))) + (let (($x76 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x72 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x77 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x72) $x76))) + (or (or (or (or (or $x77 $x80) $x85) $x90) $x95) $x100)))))))))) (assert (let (($x37 (and true (and true (= h1.f1 (_ bv255 8)))))) (let ((?x43 (ite $x37 (_ bv1 9) (ite true (concat (_ bv0 8) (_ bv0 1)) standard_metadata.egress_spec)))) - (let (($x45 (and true (and (distinct (ite $x37 0 (- 1)) (- 1)) true)))) + (let ((?x41 (ite $x37 0 (- 1)))) + (let (($x44 (and (distinct ?x41 (- 1)) true))) + (let (($x45 (and true $x44))) (let (($x48 (and $x45 (and true (= h1.f2 (_ bv255 8)))))) - (let (($x50 (and true (= (ite $x37 0 (- 1)) (- 1))))) - (let (($x56 (and $x50 (and true (= h1.f3 (_ bv255 8)))))) - (let ((?x61 (ite $x56 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) - (let (($x77 (or (or (or (or false (= ?x61 (_ bv0 9))) (= ?x61 (_ bv1 9))) (= ?x61 (_ bv2 9))) (= ?x61 (_ bv3 9))))) - (let (($x97 (or (or (or (or $x77 (= ?x61 (_ bv4 9))) (= ?x61 (_ bv5 9))) (= ?x61 (_ bv6 9))) (= ?x61 (_ bv7 9))))) - (let (($x39 (= ?x61 (_ bv511 9)))) - (or $x39 $x97)))))))))))) + (let (($x54 (= ?x41 (- 1)))) + (let (($x55 (and true $x54))) + (let (($x58 (and $x55 (and true (= h1.f3 (_ bv255 8)))))) + (let ((?x63 (ite $x58 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) + (let (($x83 (or (or (or (or false (= ?x63 (_ bv0 9))) (= ?x63 (_ bv1 9))) (= ?x63 (_ bv2 9))) (= ?x63 (_ bv3 9))))) + (let (($x103 (or (or (or (or $x83 (= ?x63 (_ bv4 9))) (= ?x63 (_ bv5 9))) (= ?x63 (_ bv6 9))) (= ?x63 (_ bv7 9))))) + (let (($x39 (= ?x63 (_ bv511 9)))) + (or $x39 $x103))))))))))))))) (assert (let (($x37 (and true (and true (= h1.f1 (_ bv255 8)))))) (let ((?x41 (ite $x37 0 (- 1)))) - (let (($x50 (and true (= ?x41 (- 1))))) - (let (($x56 (and $x50 (and true (= h1.f3 (_ bv255 8)))))) - (let ((?x59 (ite $x56 0 (- 1)))) + (let (($x54 (= ?x41 (- 1)))) + (let (($x55 (and true $x54))) + (let (($x58 (and $x55 (and true (= h1.f3 (_ bv255 8)))))) + (let ((?x60 (ite $x54 (ite $x58 0 (- 1)) (- 1)))) + (let (($x59 (ite $x54 $x55 false))) (let ((?x43 (ite $x37 (_ bv1 9) (ite true (concat (_ bv0 8) (_ bv0 1)) standard_metadata.egress_spec)))) - (let (($x45 (and true (and (distinct ?x41 (- 1)) true)))) + (let (($x44 (and (distinct ?x41 (- 1)) true))) + (let (($x45 (and true $x44))) (let (($x48 (and $x45 (and true (= h1.f2 (_ bv255 8)))))) - (let ((?x61 (ite $x56 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) - (let (($x39 (= ?x61 (_ bv511 9)))) - (and (and (not $x39) $x50) (= ?x59 (- 1)))))))))))))) + (let ((?x63 (ite $x58 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) + (let (($x39 (= ?x63 (_ bv511 9)))) + (and (and (not $x39) $x59) (= ?x60 (- 1))))))))))))))))) (check-sat) ; @@ -222,39 +247,45 @@ (declare-fun h1.f2 () (_ BitVec 8)) (declare-fun h1.f3 () (_ BitVec 8)) (assert - (let (($x94 (= standard_metadata.ingress_port (_ bv7 9)))) - (let (($x89 (= standard_metadata.ingress_port (_ bv6 9)))) - (let (($x84 (= standard_metadata.ingress_port (_ bv5 9)))) - (let (($x79 (= standard_metadata.ingress_port (_ bv4 9)))) - (let (($x74 (= standard_metadata.ingress_port (_ bv3 9)))) - (let (($x70 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x66 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x71 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x66) $x70))) - (or (or (or (or (or $x71 $x74) $x79) $x84) $x89) $x94)))))))))) + (let (($x100 (= standard_metadata.ingress_port (_ bv7 9)))) + (let (($x95 (= standard_metadata.ingress_port (_ bv6 9)))) + (let (($x90 (= standard_metadata.ingress_port (_ bv5 9)))) + (let (($x85 (= standard_metadata.ingress_port (_ bv4 9)))) + (let (($x80 (= standard_metadata.ingress_port (_ bv3 9)))) + (let (($x76 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x72 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x77 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x72) $x76))) + (or (or (or (or (or $x77 $x80) $x85) $x90) $x95) $x100)))))))))) (assert (let (($x37 (and true (and true (= h1.f1 (_ bv255 8)))))) (let ((?x43 (ite $x37 (_ bv1 9) (ite true (concat (_ bv0 8) (_ bv0 1)) standard_metadata.egress_spec)))) - (let (($x45 (and true (and (distinct (ite $x37 0 (- 1)) (- 1)) true)))) + (let ((?x41 (ite $x37 0 (- 1)))) + (let (($x44 (and (distinct ?x41 (- 1)) true))) + (let (($x45 (and true $x44))) (let (($x48 (and $x45 (and true (= h1.f2 (_ bv255 8)))))) - (let (($x50 (and true (= (ite $x37 0 (- 1)) (- 1))))) - (let (($x56 (and $x50 (and true (= h1.f3 (_ bv255 8)))))) - (let ((?x61 (ite $x56 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) - (let (($x77 (or (or (or (or false (= ?x61 (_ bv0 9))) (= ?x61 (_ bv1 9))) (= ?x61 (_ bv2 9))) (= ?x61 (_ bv3 9))))) - (let (($x97 (or (or (or (or $x77 (= ?x61 (_ bv4 9))) (= ?x61 (_ bv5 9))) (= ?x61 (_ bv6 9))) (= ?x61 (_ bv7 9))))) - (let (($x39 (= ?x61 (_ bv511 9)))) - (or $x39 $x97)))))))))))) + (let (($x54 (= ?x41 (- 1)))) + (let (($x55 (and true $x54))) + (let (($x58 (and $x55 (and true (= h1.f3 (_ bv255 8)))))) + (let ((?x63 (ite $x58 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) + (let (($x83 (or (or (or (or false (= ?x63 (_ bv0 9))) (= ?x63 (_ bv1 9))) (= ?x63 (_ bv2 9))) (= ?x63 (_ bv3 9))))) + (let (($x103 (or (or (or (or $x83 (= ?x63 (_ bv4 9))) (= ?x63 (_ bv5 9))) (= ?x63 (_ bv6 9))) (= ?x63 (_ bv7 9))))) + (let (($x39 (= ?x63 (_ bv511 9)))) + (or $x39 $x103))))))))))))))) (assert (let (($x37 (and true (and true (= h1.f1 (_ bv255 8)))))) (let ((?x41 (ite $x37 0 (- 1)))) - (let (($x50 (and true (= ?x41 (- 1))))) - (let (($x56 (and $x50 (and true (= h1.f3 (_ bv255 8)))))) - (let ((?x59 (ite $x56 0 (- 1)))) + (let (($x54 (= ?x41 (- 1)))) + (let (($x55 (and true $x54))) + (let (($x58 (and $x55 (and true (= h1.f3 (_ bv255 8)))))) + (let ((?x60 (ite $x54 (ite $x58 0 (- 1)) (- 1)))) + (let (($x59 (ite $x54 $x55 false))) (let ((?x43 (ite $x37 (_ bv1 9) (ite true (concat (_ bv0 8) (_ bv0 1)) standard_metadata.egress_spec)))) - (let (($x45 (and true (and (distinct ?x41 (- 1)) true)))) + (let (($x44 (and (distinct ?x41 (- 1)) true))) + (let (($x45 (and true $x44))) (let (($x48 (and $x45 (and true (= h1.f2 (_ bv255 8)))))) - (let ((?x61 (ite $x56 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) - (let (($x39 (= ?x61 (_ bv511 9)))) - (and (and (not $x39) $x50) (= ?x59 0))))))))))))) + (let ((?x63 (ite $x58 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) + (let (($x39 (= ?x63 (_ bv511 9)))) + (and (and (not $x39) $x59) (= ?x60 0)))))))))))))))) (check-sat) ; @@ -265,37 +296,43 @@ (declare-fun h1.f2 () (_ BitVec 8)) (declare-fun h1.f3 () (_ BitVec 8)) (assert - (let (($x94 (= standard_metadata.ingress_port (_ bv7 9)))) - (let (($x89 (= standard_metadata.ingress_port (_ bv6 9)))) - (let (($x84 (= standard_metadata.ingress_port (_ bv5 9)))) - (let (($x79 (= standard_metadata.ingress_port (_ bv4 9)))) - (let (($x74 (= standard_metadata.ingress_port (_ bv3 9)))) - (let (($x70 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x66 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x71 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x66) $x70))) - (or (or (or (or (or $x71 $x74) $x79) $x84) $x89) $x94)))))))))) + (let (($x100 (= standard_metadata.ingress_port (_ bv7 9)))) + (let (($x95 (= standard_metadata.ingress_port (_ bv6 9)))) + (let (($x90 (= standard_metadata.ingress_port (_ bv5 9)))) + (let (($x85 (= standard_metadata.ingress_port (_ bv4 9)))) + (let (($x80 (= standard_metadata.ingress_port (_ bv3 9)))) + (let (($x76 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x72 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x77 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x72) $x76))) + (or (or (or (or (or $x77 $x80) $x85) $x90) $x95) $x100)))))))))) (assert (let (($x37 (and true (and true (= h1.f1 (_ bv255 8)))))) (let ((?x43 (ite $x37 (_ bv1 9) (ite true (concat (_ bv0 8) (_ bv0 1)) standard_metadata.egress_spec)))) - (let (($x45 (and true (and (distinct (ite $x37 0 (- 1)) (- 1)) true)))) + (let ((?x41 (ite $x37 0 (- 1)))) + (let (($x44 (and (distinct ?x41 (- 1)) true))) + (let (($x45 (and true $x44))) (let (($x48 (and $x45 (and true (= h1.f2 (_ bv255 8)))))) - (let (($x50 (and true (= (ite $x37 0 (- 1)) (- 1))))) - (let (($x56 (and $x50 (and true (= h1.f3 (_ bv255 8)))))) - (let ((?x61 (ite $x56 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) - (let (($x77 (or (or (or (or false (= ?x61 (_ bv0 9))) (= ?x61 (_ bv1 9))) (= ?x61 (_ bv2 9))) (= ?x61 (_ bv3 9))))) - (let (($x97 (or (or (or (or $x77 (= ?x61 (_ bv4 9))) (= ?x61 (_ bv5 9))) (= ?x61 (_ bv6 9))) (= ?x61 (_ bv7 9))))) - (let (($x39 (= ?x61 (_ bv511 9)))) - (or $x39 $x97)))))))))))) + (let (($x54 (= ?x41 (- 1)))) + (let (($x55 (and true $x54))) + (let (($x58 (and $x55 (and true (= h1.f3 (_ bv255 8)))))) + (let ((?x63 (ite $x58 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) + (let (($x83 (or (or (or (or false (= ?x63 (_ bv0 9))) (= ?x63 (_ bv1 9))) (= ?x63 (_ bv2 9))) (= ?x63 (_ bv3 9))))) + (let (($x103 (or (or (or (or $x83 (= ?x63 (_ bv4 9))) (= ?x63 (_ bv5 9))) (= ?x63 (_ bv6 9))) (= ?x63 (_ bv7 9))))) + (let (($x39 (= ?x63 (_ bv511 9)))) + (or $x39 $x103))))))))))))))) (assert (let (($x37 (and true (and true (= h1.f1 (_ bv255 8)))))) (let ((?x43 (ite $x37 (_ bv1 9) (ite true (concat (_ bv0 8) (_ bv0 1)) standard_metadata.egress_spec)))) - (let (($x45 (and true (and (distinct (ite $x37 0 (- 1)) (- 1)) true)))) + (let ((?x41 (ite $x37 0 (- 1)))) + (let (($x44 (and (distinct ?x41 (- 1)) true))) + (let (($x45 (and true $x44))) (let (($x48 (and $x45 (and true (= h1.f2 (_ bv255 8)))))) - (let (($x50 (and true (= (ite $x37 0 (- 1)) (- 1))))) - (let (($x56 (and $x50 (and true (= h1.f3 (_ bv255 8)))))) - (let ((?x61 (ite $x56 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) - (let (($x39 (= ?x61 (_ bv511 9)))) - (and (and (not $x39) true) (= (- 1) (- 1)))))))))))) + (let (($x54 (= ?x41 (- 1)))) + (let (($x55 (and true $x54))) + (let (($x58 (and $x55 (and true (= h1.f3 (_ bv255 8)))))) + (let ((?x63 (ite $x58 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) + (let (($x39 (= ?x63 (_ bv511 9)))) + (and (and (not $x39) true) (= (- 1) (- 1))))))))))))))) (check-sat) ; @@ -306,36 +343,42 @@ (declare-fun h1.f2 () (_ BitVec 8)) (declare-fun h1.f3 () (_ BitVec 8)) (assert - (let (($x94 (= standard_metadata.ingress_port (_ bv7 9)))) - (let (($x89 (= standard_metadata.ingress_port (_ bv6 9)))) - (let (($x84 (= standard_metadata.ingress_port (_ bv5 9)))) - (let (($x79 (= standard_metadata.ingress_port (_ bv4 9)))) - (let (($x74 (= standard_metadata.ingress_port (_ bv3 9)))) - (let (($x70 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x66 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x71 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x66) $x70))) - (or (or (or (or (or $x71 $x74) $x79) $x84) $x89) $x94)))))))))) + (let (($x100 (= standard_metadata.ingress_port (_ bv7 9)))) + (let (($x95 (= standard_metadata.ingress_port (_ bv6 9)))) + (let (($x90 (= standard_metadata.ingress_port (_ bv5 9)))) + (let (($x85 (= standard_metadata.ingress_port (_ bv4 9)))) + (let (($x80 (= standard_metadata.ingress_port (_ bv3 9)))) + (let (($x76 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x72 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x77 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x72) $x76))) + (or (or (or (or (or $x77 $x80) $x85) $x90) $x95) $x100)))))))))) (assert (let (($x37 (and true (and true (= h1.f1 (_ bv255 8)))))) (let ((?x43 (ite $x37 (_ bv1 9) (ite true (concat (_ bv0 8) (_ bv0 1)) standard_metadata.egress_spec)))) - (let (($x45 (and true (and (distinct (ite $x37 0 (- 1)) (- 1)) true)))) + (let ((?x41 (ite $x37 0 (- 1)))) + (let (($x44 (and (distinct ?x41 (- 1)) true))) + (let (($x45 (and true $x44))) (let (($x48 (and $x45 (and true (= h1.f2 (_ bv255 8)))))) - (let (($x50 (and true (= (ite $x37 0 (- 1)) (- 1))))) - (let (($x56 (and $x50 (and true (= h1.f3 (_ bv255 8)))))) - (let ((?x61 (ite $x56 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) - (let (($x77 (or (or (or (or false (= ?x61 (_ bv0 9))) (= ?x61 (_ bv1 9))) (= ?x61 (_ bv2 9))) (= ?x61 (_ bv3 9))))) - (let (($x97 (or (or (or (or $x77 (= ?x61 (_ bv4 9))) (= ?x61 (_ bv5 9))) (= ?x61 (_ bv6 9))) (= ?x61 (_ bv7 9))))) - (let (($x39 (= ?x61 (_ bv511 9)))) - (or $x39 $x97)))))))))))) + (let (($x54 (= ?x41 (- 1)))) + (let (($x55 (and true $x54))) + (let (($x58 (and $x55 (and true (= h1.f3 (_ bv255 8)))))) + (let ((?x63 (ite $x58 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) + (let (($x83 (or (or (or (or false (= ?x63 (_ bv0 9))) (= ?x63 (_ bv1 9))) (= ?x63 (_ bv2 9))) (= ?x63 (_ bv3 9))))) + (let (($x103 (or (or (or (or $x83 (= ?x63 (_ bv4 9))) (= ?x63 (_ bv5 9))) (= ?x63 (_ bv6 9))) (= ?x63 (_ bv7 9))))) + (let (($x39 (= ?x63 (_ bv511 9)))) + (or $x39 $x103))))))))))))))) (assert (let (($x37 (and true (and true (= h1.f1 (_ bv255 8)))))) (let ((?x43 (ite $x37 (_ bv1 9) (ite true (concat (_ bv0 8) (_ bv0 1)) standard_metadata.egress_spec)))) - (let (($x45 (and true (and (distinct (ite $x37 0 (- 1)) (- 1)) true)))) + (let ((?x41 (ite $x37 0 (- 1)))) + (let (($x44 (and (distinct ?x41 (- 1)) true))) + (let (($x45 (and true $x44))) (let (($x48 (and $x45 (and true (= h1.f2 (_ bv255 8)))))) - (let (($x50 (and true (= (ite $x37 0 (- 1)) (- 1))))) - (let (($x56 (and $x50 (and true (= h1.f3 (_ bv255 8)))))) - (let ((?x61 (ite $x56 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) - (let (($x39 (= ?x61 (_ bv511 9)))) - (and (and (not $x39) true) (= (- 1) (- 1)))))))))))) + (let (($x54 (= ?x41 (- 1)))) + (let (($x55 (and true $x54))) + (let (($x58 (and $x55 (and true (= h1.f3 (_ bv255 8)))))) + (let ((?x63 (ite $x58 (_ bv3 9) (ite $x48 (_ bv2 9) ?x43)))) + (let (($x39 (= ?x63 (_ bv511 9)))) + (and (and (not $x39) true) (= (- 1) (- 1))))))))))))))) (check-sat) diff --git a/p4_symbolic/symbolic/expected/vrf.smt2 b/p4_symbolic/symbolic/expected/vrf.smt2 index 2bf13d32..c6082986 100644 --- a/p4_symbolic/symbolic/expected/vrf.smt2 +++ b/p4_symbolic/symbolic/expected/vrf.smt2 @@ -8,8 +8,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun scalars.local_metadata_t.vrf_is_valid () (_ BitVec 1)) (assert - (let (($x86 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x86))) + (let (($x169 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x169))) (assert (let ((?x50 (concat (_ bv0 9) (_ bv0 1)))) (let (($x64 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -30,7 +30,8 @@ (let ((?x47 (ite false (_ bv1 1) (_ bv0 1)))) (let ((?x76 (ite true (_ bv1 1) (_ bv0 1)))) (let ((?x82 (ite $x65 ?x76 (ite $x68 ?x76 (ite true ?x47 scalars.local_metadata_t.vrf_is_valid))))) - (let (($x85 (and $x53 (bvuge ?x82 (_ bv1 1))))) + (let (($x83 (bvuge ?x82 (_ bv1 1)))) + (let (($x85 (and $x53 $x83))) (let ((?x125 (ite (and $x85 (and $x118 (not $x108))) (_ bv511 9) standard_metadata.egress_spec))) (let (($x120 (and (and $x85 $x118) $x108))) (let (($x116 (and (and $x85 $x114) $x102))) @@ -38,7 +39,7 @@ (let (($x109 (and $x85 $x91))) (let ((?x158 (ite $x109 (_ bv1 9) (ite $x112 (_ bv0 9) (ite $x116 (_ bv1 9) (ite $x120 (_ bv1 9) ?x125)))))) (let (($x52 (= ?x158 (_ bv511 9)))) - (or $x52 (or (or false (= ?x158 (_ bv0 9))) (= ?x158 (_ bv1 9)))))))))))))))))))))))))))))))) + (or $x52 (or (or false (= ?x158 (_ bv0 9))) (= ?x158 (_ bv1 9))))))))))))))))))))))))))))))))) (assert (let ((?x50 (concat (_ bv0 9) (_ bv0 1)))) (let (($x64 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -53,13 +54,15 @@ (let ((?x47 (ite false (_ bv1 1) (_ bv0 1)))) (let ((?x76 (ite true (_ bv1 1) (_ bv0 1)))) (let ((?x82 (ite $x65 ?x76 (ite $x68 ?x76 (ite true ?x47 scalars.local_metadata_t.vrf_is_valid))))) - (let (($x85 (and $x53 (bvuge ?x82 (_ bv1 1))))) + (let (($x83 (bvuge ?x82 (_ bv1 1)))) + (let (($x85 (and $x53 $x83))) (let (($x102 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))) (= ?x81 ?x80)))) (let (($x96 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))) $x90))) (let ((?x149 (ite (and $x85 $x96) 0 (ite (and $x85 $x102) 3 (ite (and $x85 $x108) 2 (- 1)))))) (let (($x91 (and (and true (= ipv4.dstAddr (_ bv168427520 32))) $x90))) (let (($x109 (and $x85 $x91))) - (let ((?x157 (ite $x109 1 ?x149))) + (let ((?x70 (ite ipv4.$valid$ (ite $x83 (ite $x109 1 ?x149) (- 1)) (- 1)))) + (let (($x69 (ite ipv4.$valid$ (ite $x83 $x85 false) false))) (let (($x123 (and $x85 (and (and (and (not $x91) (not $x96)) (not $x102)) (not $x108))))) (let (($x120 (and (and $x85 (and (and (not $x91) (not $x96)) (not $x102))) $x108))) (let (($x116 (and (and $x85 (and (not $x91) (not $x96))) $x102))) @@ -67,7 +70,7 @@ (let (($x112 (and (and $x85 (not $x91)) $x96))) (let ((?x158 (ite $x109 (_ bv1 9) (ite $x112 (_ bv0 9) ?x142)))) (let (($x52 (= ?x158 (_ bv511 9)))) - (and (and (not $x52) $x85) (= ?x157 (- 1))))))))))))))))))))))))))))))) + (and (and (not $x52) $x69) (= ?x70 (- 1))))))))))))))))))))))))))))))))) (check-sat) ; @@ -80,8 +83,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun scalars.local_metadata_t.vrf_is_valid () (_ BitVec 1)) (assert - (let (($x86 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x86))) + (let (($x169 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x169))) (assert (let ((?x50 (concat (_ bv0 9) (_ bv0 1)))) (let (($x64 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -102,7 +105,8 @@ (let ((?x47 (ite false (_ bv1 1) (_ bv0 1)))) (let ((?x76 (ite true (_ bv1 1) (_ bv0 1)))) (let ((?x82 (ite $x65 ?x76 (ite $x68 ?x76 (ite true ?x47 scalars.local_metadata_t.vrf_is_valid))))) - (let (($x85 (and $x53 (bvuge ?x82 (_ bv1 1))))) + (let (($x83 (bvuge ?x82 (_ bv1 1)))) + (let (($x85 (and $x53 $x83))) (let ((?x125 (ite (and $x85 (and $x118 (not $x108))) (_ bv511 9) standard_metadata.egress_spec))) (let (($x120 (and (and $x85 $x118) $x108))) (let (($x116 (and (and $x85 $x114) $x102))) @@ -110,7 +114,7 @@ (let (($x109 (and $x85 $x91))) (let ((?x158 (ite $x109 (_ bv1 9) (ite $x112 (_ bv0 9) (ite $x116 (_ bv1 9) (ite $x120 (_ bv1 9) ?x125)))))) (let (($x52 (= ?x158 (_ bv511 9)))) - (or $x52 (or (or false (= ?x158 (_ bv0 9))) (= ?x158 (_ bv1 9)))))))))))))))))))))))))))))))) + (or $x52 (or (or false (= ?x158 (_ bv0 9))) (= ?x158 (_ bv1 9))))))))))))))))))))))))))))))))) (assert (let ((?x50 (concat (_ bv0 9) (_ bv0 1)))) (let (($x64 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -125,13 +129,15 @@ (let ((?x47 (ite false (_ bv1 1) (_ bv0 1)))) (let ((?x76 (ite true (_ bv1 1) (_ bv0 1)))) (let ((?x82 (ite $x65 ?x76 (ite $x68 ?x76 (ite true ?x47 scalars.local_metadata_t.vrf_is_valid))))) - (let (($x85 (and $x53 (bvuge ?x82 (_ bv1 1))))) + (let (($x83 (bvuge ?x82 (_ bv1 1)))) + (let (($x85 (and $x53 $x83))) (let (($x102 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))) (= ?x81 ?x80)))) (let (($x96 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))) $x90))) (let ((?x149 (ite (and $x85 $x96) 0 (ite (and $x85 $x102) 3 (ite (and $x85 $x108) 2 (- 1)))))) (let (($x91 (and (and true (= ipv4.dstAddr (_ bv168427520 32))) $x90))) (let (($x109 (and $x85 $x91))) - (let ((?x157 (ite $x109 1 ?x149))) + (let ((?x70 (ite ipv4.$valid$ (ite $x83 (ite $x109 1 ?x149) (- 1)) (- 1)))) + (let (($x69 (ite ipv4.$valid$ (ite $x83 $x85 false) false))) (let (($x123 (and $x85 (and (and (and (not $x91) (not $x96)) (not $x102)) (not $x108))))) (let (($x120 (and (and $x85 (and (and (not $x91) (not $x96)) (not $x102))) $x108))) (let (($x116 (and (and $x85 (and (not $x91) (not $x96))) $x102))) @@ -139,8 +145,8 @@ (let (($x112 (and (and $x85 (not $x91)) $x96))) (let ((?x158 (ite $x109 (_ bv1 9) (ite $x112 (_ bv0 9) ?x142)))) (let (($x52 (= ?x158 (_ bv511 9)))) - (let (($x307 (and (not $x52) $x85))) - (and $x307 (= ?x157 0))))))))))))))))))))))))))))))) + (let (($x309 (and (not $x52) $x69))) + (and $x309 (= ?x70 0))))))))))))))))))))))))))))))))) (check-sat) ; @@ -153,8 +159,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun scalars.local_metadata_t.vrf_is_valid () (_ BitVec 1)) (assert - (let (($x86 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x86))) + (let (($x169 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x169))) (assert (let ((?x50 (concat (_ bv0 9) (_ bv0 1)))) (let (($x64 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -175,7 +181,8 @@ (let ((?x47 (ite false (_ bv1 1) (_ bv0 1)))) (let ((?x76 (ite true (_ bv1 1) (_ bv0 1)))) (let ((?x82 (ite $x65 ?x76 (ite $x68 ?x76 (ite true ?x47 scalars.local_metadata_t.vrf_is_valid))))) - (let (($x85 (and $x53 (bvuge ?x82 (_ bv1 1))))) + (let (($x83 (bvuge ?x82 (_ bv1 1)))) + (let (($x85 (and $x53 $x83))) (let ((?x125 (ite (and $x85 (and $x118 (not $x108))) (_ bv511 9) standard_metadata.egress_spec))) (let (($x120 (and (and $x85 $x118) $x108))) (let (($x116 (and (and $x85 $x114) $x102))) @@ -183,7 +190,7 @@ (let (($x109 (and $x85 $x91))) (let ((?x158 (ite $x109 (_ bv1 9) (ite $x112 (_ bv0 9) (ite $x116 (_ bv1 9) (ite $x120 (_ bv1 9) ?x125)))))) (let (($x52 (= ?x158 (_ bv511 9)))) - (or $x52 (or (or false (= ?x158 (_ bv0 9))) (= ?x158 (_ bv1 9)))))))))))))))))))))))))))))))) + (or $x52 (or (or false (= ?x158 (_ bv0 9))) (= ?x158 (_ bv1 9))))))))))))))))))))))))))))))))) (assert (let ((?x50 (concat (_ bv0 9) (_ bv0 1)))) (let (($x64 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -198,13 +205,15 @@ (let ((?x47 (ite false (_ bv1 1) (_ bv0 1)))) (let ((?x76 (ite true (_ bv1 1) (_ bv0 1)))) (let ((?x82 (ite $x65 ?x76 (ite $x68 ?x76 (ite true ?x47 scalars.local_metadata_t.vrf_is_valid))))) - (let (($x85 (and $x53 (bvuge ?x82 (_ bv1 1))))) + (let (($x83 (bvuge ?x82 (_ bv1 1)))) + (let (($x85 (and $x53 $x83))) (let (($x102 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))) (= ?x81 ?x80)))) (let (($x96 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))) $x90))) (let ((?x149 (ite (and $x85 $x96) 0 (ite (and $x85 $x102) 3 (ite (and $x85 $x108) 2 (- 1)))))) (let (($x91 (and (and true (= ipv4.dstAddr (_ bv168427520 32))) $x90))) (let (($x109 (and $x85 $x91))) - (let ((?x157 (ite $x109 1 ?x149))) + (let ((?x70 (ite ipv4.$valid$ (ite $x83 (ite $x109 1 ?x149) (- 1)) (- 1)))) + (let (($x69 (ite ipv4.$valid$ (ite $x83 $x85 false) false))) (let (($x123 (and $x85 (and (and (and (not $x91) (not $x96)) (not $x102)) (not $x108))))) (let (($x120 (and (and $x85 (and (and (not $x91) (not $x96)) (not $x102))) $x108))) (let (($x116 (and (and $x85 (and (not $x91) (not $x96))) $x102))) @@ -212,7 +221,7 @@ (let (($x112 (and (and $x85 (not $x91)) $x96))) (let ((?x158 (ite $x109 (_ bv1 9) (ite $x112 (_ bv0 9) ?x142)))) (let (($x52 (= ?x158 (_ bv511 9)))) - (and (and (not $x52) $x85) (= ?x157 1)))))))))))))))))))))))))))))) + (and (and (not $x52) $x69) (= ?x70 1)))))))))))))))))))))))))))))))) (check-sat) ; @@ -225,8 +234,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun scalars.local_metadata_t.vrf_is_valid () (_ BitVec 1)) (assert - (let (($x86 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x86))) + (let (($x169 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x169))) (assert (let ((?x50 (concat (_ bv0 9) (_ bv0 1)))) (let (($x64 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -247,7 +256,8 @@ (let ((?x47 (ite false (_ bv1 1) (_ bv0 1)))) (let ((?x76 (ite true (_ bv1 1) (_ bv0 1)))) (let ((?x82 (ite $x65 ?x76 (ite $x68 ?x76 (ite true ?x47 scalars.local_metadata_t.vrf_is_valid))))) - (let (($x85 (and $x53 (bvuge ?x82 (_ bv1 1))))) + (let (($x83 (bvuge ?x82 (_ bv1 1)))) + (let (($x85 (and $x53 $x83))) (let ((?x125 (ite (and $x85 (and $x118 (not $x108))) (_ bv511 9) standard_metadata.egress_spec))) (let (($x120 (and (and $x85 $x118) $x108))) (let (($x116 (and (and $x85 $x114) $x102))) @@ -255,7 +265,7 @@ (let (($x109 (and $x85 $x91))) (let ((?x158 (ite $x109 (_ bv1 9) (ite $x112 (_ bv0 9) (ite $x116 (_ bv1 9) (ite $x120 (_ bv1 9) ?x125)))))) (let (($x52 (= ?x158 (_ bv511 9)))) - (or $x52 (or (or false (= ?x158 (_ bv0 9))) (= ?x158 (_ bv1 9)))))))))))))))))))))))))))))))) + (or $x52 (or (or false (= ?x158 (_ bv0 9))) (= ?x158 (_ bv1 9))))))))))))))))))))))))))))))))) (assert (let ((?x50 (concat (_ bv0 9) (_ bv0 1)))) (let (($x64 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -270,13 +280,15 @@ (let ((?x47 (ite false (_ bv1 1) (_ bv0 1)))) (let ((?x76 (ite true (_ bv1 1) (_ bv0 1)))) (let ((?x82 (ite $x65 ?x76 (ite $x68 ?x76 (ite true ?x47 scalars.local_metadata_t.vrf_is_valid))))) - (let (($x85 (and $x53 (bvuge ?x82 (_ bv1 1))))) + (let (($x83 (bvuge ?x82 (_ bv1 1)))) + (let (($x85 (and $x53 $x83))) (let (($x102 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))) (= ?x81 ?x80)))) (let (($x96 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))) $x90))) (let ((?x149 (ite (and $x85 $x96) 0 (ite (and $x85 $x102) 3 (ite (and $x85 $x108) 2 (- 1)))))) (let (($x91 (and (and true (= ipv4.dstAddr (_ bv168427520 32))) $x90))) (let (($x109 (and $x85 $x91))) - (let ((?x157 (ite $x109 1 ?x149))) + (let ((?x70 (ite ipv4.$valid$ (ite $x83 (ite $x109 1 ?x149) (- 1)) (- 1)))) + (let (($x69 (ite ipv4.$valid$ (ite $x83 $x85 false) false))) (let (($x123 (and $x85 (and (and (and (not $x91) (not $x96)) (not $x102)) (not $x108))))) (let (($x120 (and (and $x85 (and (and (not $x91) (not $x96)) (not $x102))) $x108))) (let (($x116 (and (and $x85 (and (not $x91) (not $x96))) $x102))) @@ -284,7 +296,7 @@ (let (($x112 (and (and $x85 (not $x91)) $x96))) (let ((?x158 (ite $x109 (_ bv1 9) (ite $x112 (_ bv0 9) ?x142)))) (let (($x52 (= ?x158 (_ bv511 9)))) - (and (and (not $x52) $x85) (= ?x157 2)))))))))))))))))))))))))))))) + (and (and (not $x52) $x69) (= ?x70 2)))))))))))))))))))))))))))))))) (check-sat) ; @@ -297,8 +309,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun scalars.local_metadata_t.vrf_is_valid () (_ BitVec 1)) (assert - (let (($x86 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x86))) + (let (($x169 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x169))) (assert (let ((?x50 (concat (_ bv0 9) (_ bv0 1)))) (let (($x64 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -319,7 +331,8 @@ (let ((?x47 (ite false (_ bv1 1) (_ bv0 1)))) (let ((?x76 (ite true (_ bv1 1) (_ bv0 1)))) (let ((?x82 (ite $x65 ?x76 (ite $x68 ?x76 (ite true ?x47 scalars.local_metadata_t.vrf_is_valid))))) - (let (($x85 (and $x53 (bvuge ?x82 (_ bv1 1))))) + (let (($x83 (bvuge ?x82 (_ bv1 1)))) + (let (($x85 (and $x53 $x83))) (let ((?x125 (ite (and $x85 (and $x118 (not $x108))) (_ bv511 9) standard_metadata.egress_spec))) (let (($x120 (and (and $x85 $x118) $x108))) (let (($x116 (and (and $x85 $x114) $x102))) @@ -327,7 +340,7 @@ (let (($x109 (and $x85 $x91))) (let ((?x158 (ite $x109 (_ bv1 9) (ite $x112 (_ bv0 9) (ite $x116 (_ bv1 9) (ite $x120 (_ bv1 9) ?x125)))))) (let (($x52 (= ?x158 (_ bv511 9)))) - (or $x52 (or (or false (= ?x158 (_ bv0 9))) (= ?x158 (_ bv1 9)))))))))))))))))))))))))))))))) + (or $x52 (or (or false (= ?x158 (_ bv0 9))) (= ?x158 (_ bv1 9))))))))))))))))))))))))))))))))) (assert (let ((?x50 (concat (_ bv0 9) (_ bv0 1)))) (let (($x64 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -342,13 +355,15 @@ (let ((?x47 (ite false (_ bv1 1) (_ bv0 1)))) (let ((?x76 (ite true (_ bv1 1) (_ bv0 1)))) (let ((?x82 (ite $x65 ?x76 (ite $x68 ?x76 (ite true ?x47 scalars.local_metadata_t.vrf_is_valid))))) - (let (($x85 (and $x53 (bvuge ?x82 (_ bv1 1))))) + (let (($x83 (bvuge ?x82 (_ bv1 1)))) + (let (($x85 (and $x53 $x83))) (let (($x102 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))) (= ?x81 ?x80)))) (let (($x96 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))) $x90))) (let ((?x149 (ite (and $x85 $x96) 0 (ite (and $x85 $x102) 3 (ite (and $x85 $x108) 2 (- 1)))))) (let (($x91 (and (and true (= ipv4.dstAddr (_ bv168427520 32))) $x90))) (let (($x109 (and $x85 $x91))) - (let ((?x157 (ite $x109 1 ?x149))) + (let ((?x70 (ite ipv4.$valid$ (ite $x83 (ite $x109 1 ?x149) (- 1)) (- 1)))) + (let (($x69 (ite ipv4.$valid$ (ite $x83 $x85 false) false))) (let (($x123 (and $x85 (and (and (and (not $x91) (not $x96)) (not $x102)) (not $x108))))) (let (($x120 (and (and $x85 (and (and (not $x91) (not $x96)) (not $x102))) $x108))) (let (($x116 (and (and $x85 (and (not $x91) (not $x96))) $x102))) @@ -356,7 +371,7 @@ (let (($x112 (and (and $x85 (not $x91)) $x96))) (let ((?x158 (ite $x109 (_ bv1 9) (ite $x112 (_ bv0 9) ?x142)))) (let (($x52 (= ?x158 (_ bv511 9)))) - (and (and (not $x52) $x85) (= ?x157 3)))))))))))))))))))))))))))))) + (and (and (not $x52) $x69) (= ?x70 3)))))))))))))))))))))))))))))))) (check-sat) ; @@ -369,8 +384,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun scalars.local_metadata_t.vrf_is_valid () (_ BitVec 1)) (assert - (let (($x86 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x86))) + (let (($x169 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x169))) (assert (let ((?x50 (concat (_ bv0 9) (_ bv0 1)))) (let (($x64 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -391,7 +406,8 @@ (let ((?x47 (ite false (_ bv1 1) (_ bv0 1)))) (let ((?x76 (ite true (_ bv1 1) (_ bv0 1)))) (let ((?x82 (ite $x65 ?x76 (ite $x68 ?x76 (ite true ?x47 scalars.local_metadata_t.vrf_is_valid))))) - (let (($x85 (and $x53 (bvuge ?x82 (_ bv1 1))))) + (let (($x83 (bvuge ?x82 (_ bv1 1)))) + (let (($x85 (and $x53 $x83))) (let ((?x125 (ite (and $x85 (and $x118 (not $x108))) (_ bv511 9) standard_metadata.egress_spec))) (let (($x120 (and (and $x85 $x118) $x108))) (let (($x116 (and (and $x85 $x114) $x102))) @@ -399,13 +415,14 @@ (let (($x109 (and $x85 $x91))) (let ((?x158 (ite $x109 (_ bv1 9) (ite $x112 (_ bv0 9) (ite $x116 (_ bv1 9) (ite $x120 (_ bv1 9) ?x125)))))) (let (($x52 (= ?x158 (_ bv511 9)))) - (or $x52 (or (or false (= ?x158 (_ bv0 9))) (= ?x158 (_ bv1 9)))))))))))))))))))))))))))))))) + (or $x52 (or (or false (= ?x158 (_ bv0 9))) (= ?x158 (_ bv1 9))))))))))))))))))))))))))))))))) (assert (let (($x64 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) (let (($x53 (and true ipv4.$valid$))) (let (($x59 (and true (= (bvand ipv4.srcAddr (_ bv153159945 32)) (_ bv2162944 32))))) (let (($x65 (and $x53 $x59))) - (let ((?x79 (ite $x65 0 (ite (and $x53 $x64) 1 (- 1))))) + (let ((?x84 (ite ipv4.$valid$ (ite $x65 0 (ite (and $x53 $x64) 1 (- 1))) (- 1)))) + (let (($x71 (ite ipv4.$valid$ $x53 false))) (let ((?x50 (concat (_ bv0 9) (_ bv0 1)))) (let (($x68 (and (and $x53 (not $x59)) $x64))) (let ((?x80 (concat (_ bv0 9) (_ bv1 1)))) @@ -421,7 +438,8 @@ (let ((?x47 (ite false (_ bv1 1) (_ bv0 1)))) (let ((?x76 (ite true (_ bv1 1) (_ bv0 1)))) (let ((?x82 (ite $x65 ?x76 (ite $x68 ?x76 (ite true ?x47 scalars.local_metadata_t.vrf_is_valid))))) - (let (($x85 (and $x53 (bvuge ?x82 (_ bv1 1))))) + (let (($x83 (bvuge ?x82 (_ bv1 1)))) + (let (($x85 (and $x53 $x83))) (let ((?x125 (ite (and $x85 (and $x118 (not $x108))) (_ bv511 9) standard_metadata.egress_spec))) (let (($x120 (and (and $x85 $x118) $x108))) (let (($x116 (and (and $x85 $x114) $x102))) @@ -429,7 +447,7 @@ (let (($x109 (and $x85 $x91))) (let ((?x158 (ite $x109 (_ bv1 9) (ite $x112 (_ bv0 9) (ite $x116 (_ bv1 9) (ite $x120 (_ bv1 9) ?x125)))))) (let (($x52 (= ?x158 (_ bv511 9)))) - (and (and (not $x52) $x53) (= ?x79 (- 1)))))))))))))))))))))))))))))))) + (and (and (not $x52) $x71) (= ?x84 (- 1)))))))))))))))))))))))))))))))))) (check-sat) ; @@ -442,8 +460,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun scalars.local_metadata_t.vrf_is_valid () (_ BitVec 1)) (assert - (let (($x86 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x86))) + (let (($x169 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x169))) (assert (let ((?x50 (concat (_ bv0 9) (_ bv0 1)))) (let (($x64 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -464,7 +482,8 @@ (let ((?x47 (ite false (_ bv1 1) (_ bv0 1)))) (let ((?x76 (ite true (_ bv1 1) (_ bv0 1)))) (let ((?x82 (ite $x65 ?x76 (ite $x68 ?x76 (ite true ?x47 scalars.local_metadata_t.vrf_is_valid))))) - (let (($x85 (and $x53 (bvuge ?x82 (_ bv1 1))))) + (let (($x83 (bvuge ?x82 (_ bv1 1)))) + (let (($x85 (and $x53 $x83))) (let ((?x125 (ite (and $x85 (and $x118 (not $x108))) (_ bv511 9) standard_metadata.egress_spec))) (let (($x120 (and (and $x85 $x118) $x108))) (let (($x116 (and (and $x85 $x114) $x102))) @@ -472,13 +491,14 @@ (let (($x109 (and $x85 $x91))) (let ((?x158 (ite $x109 (_ bv1 9) (ite $x112 (_ bv0 9) (ite $x116 (_ bv1 9) (ite $x120 (_ bv1 9) ?x125)))))) (let (($x52 (= ?x158 (_ bv511 9)))) - (or $x52 (or (or false (= ?x158 (_ bv0 9))) (= ?x158 (_ bv1 9)))))))))))))))))))))))))))))))) + (or $x52 (or (or false (= ?x158 (_ bv0 9))) (= ?x158 (_ bv1 9))))))))))))))))))))))))))))))))) (assert (let (($x64 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) (let (($x53 (and true ipv4.$valid$))) (let (($x59 (and true (= (bvand ipv4.srcAddr (_ bv153159945 32)) (_ bv2162944 32))))) (let (($x65 (and $x53 $x59))) - (let ((?x79 (ite $x65 0 (ite (and $x53 $x64) 1 (- 1))))) + (let ((?x84 (ite ipv4.$valid$ (ite $x65 0 (ite (and $x53 $x64) 1 (- 1))) (- 1)))) + (let (($x71 (ite ipv4.$valid$ $x53 false))) (let ((?x50 (concat (_ bv0 9) (_ bv0 1)))) (let (($x68 (and (and $x53 (not $x59)) $x64))) (let ((?x80 (concat (_ bv0 9) (_ bv1 1)))) @@ -494,7 +514,8 @@ (let ((?x47 (ite false (_ bv1 1) (_ bv0 1)))) (let ((?x76 (ite true (_ bv1 1) (_ bv0 1)))) (let ((?x82 (ite $x65 ?x76 (ite $x68 ?x76 (ite true ?x47 scalars.local_metadata_t.vrf_is_valid))))) - (let (($x85 (and $x53 (bvuge ?x82 (_ bv1 1))))) + (let (($x83 (bvuge ?x82 (_ bv1 1)))) + (let (($x85 (and $x53 $x83))) (let ((?x125 (ite (and $x85 (and $x118 (not $x108))) (_ bv511 9) standard_metadata.egress_spec))) (let (($x120 (and (and $x85 $x118) $x108))) (let (($x116 (and (and $x85 $x114) $x102))) @@ -502,7 +523,7 @@ (let (($x109 (and $x85 $x91))) (let ((?x158 (ite $x109 (_ bv1 9) (ite $x112 (_ bv0 9) (ite $x116 (_ bv1 9) (ite $x120 (_ bv1 9) ?x125)))))) (let (($x52 (= ?x158 (_ bv511 9)))) - (and (and (not $x52) $x53) (= ?x79 0))))))))))))))))))))))))))))))) + (and (and (not $x52) $x71) (= ?x84 0))))))))))))))))))))))))))))))))) (check-sat) ; @@ -515,8 +536,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun scalars.local_metadata_t.vrf_is_valid () (_ BitVec 1)) (assert - (let (($x86 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x86))) + (let (($x169 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x169))) (assert (let ((?x50 (concat (_ bv0 9) (_ bv0 1)))) (let (($x64 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -537,7 +558,8 @@ (let ((?x47 (ite false (_ bv1 1) (_ bv0 1)))) (let ((?x76 (ite true (_ bv1 1) (_ bv0 1)))) (let ((?x82 (ite $x65 ?x76 (ite $x68 ?x76 (ite true ?x47 scalars.local_metadata_t.vrf_is_valid))))) - (let (($x85 (and $x53 (bvuge ?x82 (_ bv1 1))))) + (let (($x83 (bvuge ?x82 (_ bv1 1)))) + (let (($x85 (and $x53 $x83))) (let ((?x125 (ite (and $x85 (and $x118 (not $x108))) (_ bv511 9) standard_metadata.egress_spec))) (let (($x120 (and (and $x85 $x118) $x108))) (let (($x116 (and (and $x85 $x114) $x102))) @@ -545,13 +567,14 @@ (let (($x109 (and $x85 $x91))) (let ((?x158 (ite $x109 (_ bv1 9) (ite $x112 (_ bv0 9) (ite $x116 (_ bv1 9) (ite $x120 (_ bv1 9) ?x125)))))) (let (($x52 (= ?x158 (_ bv511 9)))) - (or $x52 (or (or false (= ?x158 (_ bv0 9))) (= ?x158 (_ bv1 9)))))))))))))))))))))))))))))))) + (or $x52 (or (or false (= ?x158 (_ bv0 9))) (= ?x158 (_ bv1 9))))))))))))))))))))))))))))))))) (assert (let (($x64 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) (let (($x53 (and true ipv4.$valid$))) (let (($x59 (and true (= (bvand ipv4.srcAddr (_ bv153159945 32)) (_ bv2162944 32))))) (let (($x65 (and $x53 $x59))) - (let ((?x79 (ite $x65 0 (ite (and $x53 $x64) 1 (- 1))))) + (let ((?x84 (ite ipv4.$valid$ (ite $x65 0 (ite (and $x53 $x64) 1 (- 1))) (- 1)))) + (let (($x71 (ite ipv4.$valid$ $x53 false))) (let ((?x50 (concat (_ bv0 9) (_ bv0 1)))) (let (($x68 (and (and $x53 (not $x59)) $x64))) (let ((?x80 (concat (_ bv0 9) (_ bv1 1)))) @@ -567,7 +590,8 @@ (let ((?x47 (ite false (_ bv1 1) (_ bv0 1)))) (let ((?x76 (ite true (_ bv1 1) (_ bv0 1)))) (let ((?x82 (ite $x65 ?x76 (ite $x68 ?x76 (ite true ?x47 scalars.local_metadata_t.vrf_is_valid))))) - (let (($x85 (and $x53 (bvuge ?x82 (_ bv1 1))))) + (let (($x83 (bvuge ?x82 (_ bv1 1)))) + (let (($x85 (and $x53 $x83))) (let ((?x125 (ite (and $x85 (and $x118 (not $x108))) (_ bv511 9) standard_metadata.egress_spec))) (let (($x120 (and (and $x85 $x118) $x108))) (let (($x116 (and (and $x85 $x114) $x102))) @@ -575,7 +599,7 @@ (let (($x109 (and $x85 $x91))) (let ((?x158 (ite $x109 (_ bv1 9) (ite $x112 (_ bv0 9) (ite $x116 (_ bv1 9) (ite $x120 (_ bv1 9) ?x125)))))) (let (($x52 (= ?x158 (_ bv511 9)))) - (and (and (not $x52) $x53) (= ?x79 1))))))))))))))))))))))))))))))) + (and (and (not $x52) $x71) (= ?x84 1))))))))))))))))))))))))))))))))) (check-sat) ; @@ -588,8 +612,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun scalars.local_metadata_t.vrf_is_valid () (_ BitVec 1)) (assert - (let (($x86 (= standard_metadata.ingress_port (_ bv1 9)))) - (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x86))) + (let (($x169 (= standard_metadata.ingress_port (_ bv1 9)))) + (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x169))) (assert (let ((?x50 (concat (_ bv0 9) (_ bv0 1)))) (let (($x64 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -610,7 +634,8 @@ (let ((?x47 (ite false (_ bv1 1) (_ bv0 1)))) (let ((?x76 (ite true (_ bv1 1) (_ bv0 1)))) (let ((?x82 (ite $x65 ?x76 (ite $x68 ?x76 (ite true ?x47 scalars.local_metadata_t.vrf_is_valid))))) - (let (($x85 (and $x53 (bvuge ?x82 (_ bv1 1))))) + (let (($x83 (bvuge ?x82 (_ bv1 1)))) + (let (($x85 (and $x53 $x83))) (let ((?x125 (ite (and $x85 (and $x118 (not $x108))) (_ bv511 9) standard_metadata.egress_spec))) (let (($x120 (and (and $x85 $x118) $x108))) (let (($x116 (and (and $x85 $x114) $x102))) @@ -618,7 +643,7 @@ (let (($x109 (and $x85 $x91))) (let ((?x158 (ite $x109 (_ bv1 9) (ite $x112 (_ bv0 9) (ite $x116 (_ bv1 9) (ite $x120 (_ bv1 9) ?x125)))))) (let (($x52 (= ?x158 (_ bv511 9)))) - (or $x52 (or (or false (= ?x158 (_ bv0 9))) (= ?x158 (_ bv1 9)))))))))))))))))))))))))))))))) + (or $x52 (or (or false (= ?x158 (_ bv0 9))) (= ?x158 (_ bv1 9))))))))))))))))))))))))))))))))) (assert (let ((?x50 (concat (_ bv0 9) (_ bv0 1)))) (let (($x64 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -639,7 +664,8 @@ (let ((?x47 (ite false (_ bv1 1) (_ bv0 1)))) (let ((?x76 (ite true (_ bv1 1) (_ bv0 1)))) (let ((?x82 (ite $x65 ?x76 (ite $x68 ?x76 (ite true ?x47 scalars.local_metadata_t.vrf_is_valid))))) - (let (($x85 (and $x53 (bvuge ?x82 (_ bv1 1))))) + (let (($x83 (bvuge ?x82 (_ bv1 1)))) + (let (($x85 (and $x53 $x83))) (let ((?x125 (ite (and $x85 (and $x118 (not $x108))) (_ bv511 9) standard_metadata.egress_spec))) (let (($x120 (and (and $x85 $x118) $x108))) (let (($x116 (and (and $x85 $x114) $x102))) @@ -647,5 +673,5 @@ (let (($x109 (and $x85 $x91))) (let ((?x158 (ite $x109 (_ bv1 9) (ite $x112 (_ bv0 9) (ite $x116 (_ bv1 9) (ite $x120 (_ bv1 9) ?x125)))))) (let (($x52 (= ?x158 (_ bv511 9)))) - (and (and (not $x52) true) (= (- 1) (- 1))))))))))))))))))))))))))))))) + (and (and (not $x52) true) (= (- 1) (- 1)))))))))))))))))))))))))))))))) (check-sat) diff --git a/p4_symbolic/symbolic/expected/vrf.txt b/p4_symbolic/symbolic/expected/vrf.txt index c2573bf9..297fffc0 100644 --- a/p4_symbolic/symbolic/expected/vrf.txt +++ b/p4_symbolic/symbolic/expected/vrf.txt @@ -6,7 +6,7 @@ Finding packet for table packet_ingress.ipv4_lpm_table and row 0 standard_metadata.ingress_port = #b000000000 standard_metadata.egress_spec = #b000000000 ipv4.srcAddr = #x29210000 - ipv4.dstAddr = #x0a0a0080 + ipv4.dstAddr = #x0a0a0004 ethernet.dstAddr = #x000000000000 scalars.local_metadata_t.vrf = VRF1 scalars.local_metadata_t.vrf_is_valid = #b1 @@ -44,8 +44,8 @@ Finding packet for table packet_ingress.ipv4_lpm_table and row 3 Finding packet for table packet_ingress.set_vrf_table and row -1 Dropped = 0 standard_metadata.ingress_port = #b000000000 - standard_metadata.egress_spec = #b000000001 - ipv4.srcAddr = #x21000809 + standard_metadata.egress_spec = #b000000000 + ipv4.srcAddr = #x20000909 ipv4.dstAddr = #x00000000 ethernet.dstAddr = #x000000000000 scalars.local_metadata_t.vrf = VRF1 @@ -66,7 +66,7 @@ Finding packet for table packet_ingress.set_vrf_table and row 1 standard_metadata.ingress_port = #b000000000 standard_metadata.egress_spec = #b000000001 ipv4.srcAddr = #x21210000 - ipv4.dstAddr = #x0a000000 + ipv4.dstAddr = #x0a140000 ethernet.dstAddr = #x00000000000a scalars.local_metadata_t.vrf = VRF1 scalars.local_metadata_t.vrf_is_valid = #b1 @@ -76,7 +76,7 @@ Finding packet for table tbl_vrf133 and row -1 standard_metadata.ingress_port = #b000000000 standard_metadata.egress_spec = #b000000001 ipv4.srcAddr = #x21210000 - ipv4.dstAddr = #x0a000000 - ethernet.dstAddr = #x000000000000 + ipv4.dstAddr = #x0a140000 + ethernet.dstAddr = #x00000000000a scalars.local_metadata_t.vrf = VRF1 - scalars.local_metadata_t.vrf_is_valid = #b0 + scalars.local_metadata_t.vrf_is_valid = #b1 diff --git a/p4_symbolic/symbolic/table.cc b/p4_symbolic/symbolic/table.cc index 39d0ed24..ab5add35 100644 --- a/p4_symbolic/symbolic/table.cc +++ b/p4_symbolic/symbolic/table.cc @@ -484,15 +484,17 @@ absl::StatusOr EvaluateTable( for (const auto &[action, next_control] : sorted_action_to_next_control) { if (next_control != merge_point) { if (action == ir::TableHitAction() || action == ir::TableMissAction()) { - z3::expr branch_guard = action == ir::TableHitAction() - ? (match_index != kDefaultActionEntryIndex) - : (match_index == kDefaultActionEntryIndex); + z3::expr branch_condition = + action == ir::TableHitAction() + ? (match_index != kDefaultActionEntryIndex) + : (match_index == kDefaultActionEntryIndex); ASSIGN_OR_RETURN( SymbolicTableMatches branch_matches, control::EvaluateControl(data_plane, next_control, state, - translator, guard && branch_guard)); - ASSIGN_OR_RETURN(merged_matches, util::MergeDisjointTableMatches( - merged_matches, branch_matches)); + translator, guard && branch_condition)); + ASSIGN_OR_RETURN(merged_matches, + util::MergeMatchesOnCondition( + branch_condition, branch_matches, merged_matches)); } else { return absl::UnimplementedError( absl::Substitute("Conditional on executed table action is not " diff --git a/p4_symbolic/symbolic/test.bzl b/p4_symbolic/symbolic/test.bzl index b0b58d53..ea6166a6 100644 --- a/p4_symbolic/symbolic/test.bzl +++ b/p4_symbolic/symbolic/test.bzl @@ -105,8 +105,6 @@ def end_to_end_test( ("--entries=$(location %s)" % table_entries if table_entries else ""), ("--debug=$(location %s)" % smt_output_file), ("--port_count=%d" % port_count), - # Redirect stderr to stdout, so we can capture both. - "2>&1", # Use `tee` to simultaneously capture output in file yet still print it to stdout, to # ease debugging. ("| tee $(location %s)" % test_output_file), diff --git a/p4_symbolic/symbolic/util.cc b/p4_symbolic/symbolic/util.cc index 4e1e6903..e17ac707 100644 --- a/p4_symbolic/symbolic/util.cc +++ b/p4_symbolic/symbolic/util.cc @@ -21,6 +21,7 @@ #include "absl/status/status.h" #include "absl/strings/str_format.h" #include "absl/strings/substitute.h" +#include "glog/logging.h" #include "p4_pdpi/utils/ir.h" #include "p4_symbolic/symbolic/operators.h" #include "p4_symbolic/z3_util.h" @@ -139,18 +140,12 @@ absl::StatusOr MergeMatchesOnCondition( const SymbolicTableMatches &false_matches) { SymbolicTableMatches merged; - // Add all tables matches in true_trace. + // Merge all tables matches in true_trace (including ones in both traces). for (const auto &[name, true_match] : true_matches) { - // The table should not be applied in the other branch. - if (false_matches.contains(name)) { - return absl::InternalError( - absl::Substitute("Table '$0' was symbolically executed both in true " - "and false branches, this is not expected", - name)); - } - - // Get the default match for the false branch. - const SymbolicTableMatch false_match = DefaultTableMatch(); + // Find match in other trace (or use default). + const SymbolicTableMatch false_match = false_matches.contains(name) + ? false_matches.at(name) + : DefaultTableMatch(); // Merge this match. ASSIGN_OR_RETURN( @@ -165,14 +160,12 @@ absl::StatusOr MergeMatchesOnCondition( }}); } - // Add all tables matches in false_matches. + // Merge all tables matches in false_matches only. for (const auto &[name, false_match] : false_matches) { - // The table should not be applied in the other branch. if (true_matches.contains(name)) { - return absl::InternalError( - absl::Substitute("Table '$0' was symbolically executed both in true " - "and false branches, this is not expected", - name)); + // Already covered. + LOG(WARNING) << "Table '" << name << "' is evaluated more than once."; + continue; } // Get the default match for the true branch. From 5f92cb8bee50a141df82f5c85a56a03183ac2ab4 Mon Sep 17 00:00:00 2001 From: bibhuprasad-hcl <161687009+bibhuprasad-hcl@users.noreply.github.com> Date: Wed, 27 Nov 2024 22:58:16 +0000 Subject: [PATCH 04/17] Use generic testbed interface in BERT test. (#770) Co-authored-by: smolkaj Co-authored-by: kishanps --- tests/gnoi/BUILD.bazel | 4 +- tests/gnoi/bert_tests.cc | 808 ++++++++++++++++++++++++--------------- tests/gnoi/bert_tests.h | 79 +++- 3 files changed, 579 insertions(+), 312 deletions(-) diff --git a/tests/gnoi/BUILD.bazel b/tests/gnoi/BUILD.bazel index fa89d2b2..80ffa3d6 100644 --- a/tests/gnoi/BUILD.bazel +++ b/tests/gnoi/BUILD.bazel @@ -31,7 +31,9 @@ cc_library( "//gutil:testing", "//lib/gnmi:gnmi_helper", "//lib/validator:validator_lib", - "//thinkit:mirror_testbed_fixture", + "//thinkit:control_device", + "//thinkit:generic_testbed", + "//thinkit:generic_testbed_fixture", "//thinkit:test_environment", "@com_github_gnoi//diag:diag_cc_proto", "@com_github_google_glog//:glog", diff --git a/tests/gnoi/bert_tests.cc b/tests/gnoi/bert_tests.cc index b12fed12..81704c6d 100644 --- a/tests/gnoi/bert_tests.cc +++ b/tests/gnoi/bert_tests.cc @@ -15,6 +15,7 @@ #include "tests/gnoi/bert_tests.h" #include + #include "absl/container/flat_hash_set.h" #include "absl/flags/flag.h" #include "absl/random/random.h" @@ -28,11 +29,14 @@ #include "gmock/gmock.h" #include "google/protobuf/text_format.h" #include "google/protobuf/util/message_differencer.h" +#include "grpcpp/impl/codegen/client_context.h" #include "gtest/gtest.h" #include "gutil/status_matchers.h" #include "gutil/testing.h" #include "lib/gnmi/gnmi_helper.h" #include "lib/validator/validator_lib.h" +#include "thinkit/control_device.h" +#include "thinkit/generic_testbed.h" #include "thinkit/test_environment.h" ABSL_FLAG(uint32_t, idx_seed, static_cast(std::time(nullptr)), @@ -67,6 +71,8 @@ constexpr absl::Duration kPollInterval = absl::Seconds(30); constexpr absl::Duration kWaitTime = absl::Seconds(30); // Wait time for ports to be up after re-enabling admin down ports. constexpr absl::Duration kPortsUpWaitTime = absl::Seconds(30); +// Wait time for BERT recovery phase. +constexpr absl::Duration kWaitForRecoveryComplete = absl::Seconds(90); constexpr uint8_t kMaxAllowedInterfacesToRunBert = 96; @@ -102,12 +108,12 @@ const std::string BuildOpenConfigInterface(absl::string_view interface_name) { interface_name); } -void SendStartBertRequestSuccessfully( - gnoi::diag::StartBERTRequest& request, +void SendStartBertRequestSuccessfullyOnSut( + const gnoi::diag::StartBERTRequest& request, gnoi::diag::Diag::StubInterface& gnoi_diag_stub) { gnoi::diag::StartBERTResponse response; grpc::ClientContext context; - LOG(INFO) << "StartBERT request: " << request.ShortDebugString(); + LOG(INFO) << "StartBERT request on SUT: " << request.ShortDebugString(); ASSERT_OK(gnoi_diag_stub.StartBERT(&context, request, &response)); // Verify response. @@ -117,7 +123,7 @@ void SendStartBertRequestSuccessfully( for (int idx = 0; idx < response.per_port_responses_size(); ++idx) { auto per_port_response = response.per_port_responses(idx); - SCOPED_TRACE(absl::StrCat("Verifying StartBERT port response: ", + SCOPED_TRACE(absl::StrCat("Verifying StartBERT port response on SUT: ", per_port_response.ShortDebugString())); EXPECT_EQ(per_port_response.status(), gnoi::diag::BERT_STATUS_OK); EXPECT_TRUE( @@ -126,6 +132,32 @@ void SendStartBertRequestSuccessfully( } } +void SendStartBertRequestSuccessfullyOnControlSwitch( + const gnoi::diag::StartBERTRequest& request, + thinkit::ControlDevice& control_device) { + LOG(INFO) << "StartBERT request on control switch: " + << request.ShortDebugString(); + + ASSERT_OK_AND_ASSIGN(gnoi::diag::StartBERTResponse response, + control_device.StartBERT(request)); + + // Verify response. + ASSERT_THAT(response.per_port_responses(), + SizeIs(request.per_port_requests_size())); + EXPECT_EQ(response.bert_operation_id(), request.bert_operation_id()); + + for (int idx = 0; idx < response.per_port_responses_size(); ++idx) { + auto per_port_response = response.per_port_responses(idx); + SCOPED_TRACE( + absl::StrCat("Verifying StartBERT port response on control switch: ", + per_port_response.ShortDebugString())); + EXPECT_EQ(per_port_response.status(), gnoi::diag::BERT_STATUS_OK); + EXPECT_TRUE( + MessageDifferencer::Equals(per_port_response.interface(), + request.per_port_requests(idx).interface())); + } +} + absl::StatusOr GetInterfaceNameFromOcInterfacePath( const gnoi::types::Path& interface) { // Validate if interface is in valid format(either in OpenConfig format or @@ -180,38 +212,75 @@ void SetAdminStateOnInterfaceList(gnmi::gNMI::StubInterface& gnmi_stub, } bool IsInterfaceInList(absl::string_view interface, - std::vector& interfaces) { + const std::vector& interfaces) { return std::find(interfaces.begin(), interfaces.end(), interface) != interfaces.end(); } void WaitForBertToCompleteOnInterfaces( gnmi::gNMI::StubInterface& sut_gnmi_stub, - gnmi::gNMI::StubInterface& control_switch_gnmi_stub, - std::vector& interfaces, int max_poll_count) { + std::vector sut_interfaces, + thinkit::ControlDevice& control_device, + gnoi::diag::GetBERTResultRequest control_switch_result_request, + int max_poll_count) { for (int count = 0; count < max_poll_count; ++count) { absl::SleepFor(kPollInterval); // If port is no longer in "TESTING" oper state on both sides of the link, // linkqual has completed on the link and full result is ready. - for (auto it = interfaces.begin(); it != interfaces.end();) { + for (auto it = sut_interfaces.begin(); it != sut_interfaces.end();) { ASSERT_OK_AND_ASSIGN( pins_test::OperStatus oper_status, pins_test::GetInterfaceOperStatusOverGnmi(sut_gnmi_stub, *it)); if (oper_status != pins_test::OperStatus::kTesting) { - ASSERT_OK_AND_ASSIGN(oper_status, - pins_test::GetInterfaceOperStatusOverGnmi( - control_switch_gnmi_stub, *it)); - if (oper_status != pins_test::OperStatus::kTesting) { - it = interfaces.erase(it); - continue; - } + it = sut_interfaces.erase(it); + continue; } ++it; } - if (interfaces.empty()) break; + + // Check if BERT is completed on control switch - we cannot check + // "TESTING" mode on control device so read BERT result and verify that + // BERT either failed, or succeeded and the error count per minute field + // is completely populated (size is equal to number of minutes). If status + // is OK and error count per minute field isn't completely populated, BERT + // is still in progress. + if (control_switch_result_request.per_port_requests_size() != 0) { + gnoi::diag::GetBERTResultRequest tmp_result_request; + tmp_result_request.set_bert_operation_id( + control_switch_result_request.bert_operation_id()); + ASSERT_OK_AND_ASSIGN( + gnoi::diag::GetBERTResultResponse result_response, + control_device.GetBERTResult(control_switch_result_request)); + ASSERT_THAT( + result_response.per_port_responses(), + SizeIs(control_switch_result_request.per_port_requests_size())); + int testDurationMinutes = absl::ToInt64Minutes(kTestDuration); + for (const auto& result : result_response.per_port_responses()) { + if (result.status() == gnoi::diag::BERT_STATUS_OK && + result.error_count_per_minute_size() < testDurationMinutes) { + *(tmp_result_request.add_per_port_requests()->mutable_interface()) = + result.interface(); + } + } + control_switch_result_request = tmp_result_request; + } + if (sut_interfaces.empty() && + (control_switch_result_request.per_port_requests_size() == 0)) + break; } - EXPECT_THAT(interfaces, testing::IsEmpty()); + EXPECT_THAT(sut_interfaces, testing::IsEmpty()); + EXPECT_THAT(control_switch_result_request.per_port_requests(), + testing::IsEmpty()); + // For SUT ports, verification of non-TESTING mode is enough to indicate the + // completion of BERT. However for the control switch, there is a possibility + // that when the result was read, results were fully populated but recovery + // steps were not completed yet, if control switch BERT steps were running + // behind the SUT BERT steps - we cannot differentiate if BERT is completed or + // post BERT recovery steps are still in progress based on BERT results on + // control switch. Sleeping for some extra time ensures that control switch + // BERT is completed. + absl::SleepFor(kWaitForRecoveryComplete); } void VerifyBertResultForSuccess( @@ -245,7 +314,7 @@ void VerifyBertResultForSuccess( // Helps in getting the BERT result on a set of ports and if BERT is running on // the port, forces admin status down by disabling it. It also modifies the // list of ports in request by removing the port that was running BERT. -void CheckRunningBertAndForceAdminDownHelper( +void CheckRunningBertAndForceAdminDownHelperSut( gnoi::diag::Diag::StubInterface& gnoi_diag_stub, gnmi::gNMI::StubInterface& gnmi_stub, gnoi::diag::GetBERTResultRequest* request) { @@ -253,7 +322,7 @@ void CheckRunningBertAndForceAdminDownHelper( grpc::ClientContext context; ASSERT_OK(gnoi_diag_stub.GetBERTResult(&context, *request, &response)); - ASSERT_THAT(response.per_port_responses(), + ASSERT_THAT(response.per_port_responses(), SizeIs(request->per_port_requests_size())); request->clear_per_port_requests(); for (const auto& result : response.per_port_responses()) { @@ -277,15 +346,42 @@ void CheckRunningBertAndForceAdminDownHelper( } } +void CheckRunningBertAndForceAdminDownHelperControlSwitch( + thinkit::ControlDevice& control_device, + gnoi::diag::GetBERTResultRequest* request) { + gnoi::diag::GetBERTResultResponse response; + + ASSERT_OK_AND_ASSIGN(response, control_device.GetBERTResult(*request)); + + ASSERT_THAT(response.per_port_responses(), + SizeIs(request->per_port_requests_size())); + request->clear_per_port_requests(); + for (const auto& result : response.per_port_responses()) { + // Check if BERT is running. + if ((result.status() == gnoi::diag::BERT_STATUS_OK) && + (result.peer_lock_established())) { + ASSERT_OK_AND_ASSIGN( + const std::string interface, + GetInterfaceNameFromOcInterfacePath(result.interface())); + // Disable the admin status. + EXPECT_OK(control_device.SetAdminLinkState({interface}, + thinkit::LinkState::kDown)); + } else { + // Get result for interfaces again that didn't start BERT in last poll. + *(request->add_per_port_requests()->mutable_interface()) = + result.interface(); + } + } +} + // Checks if BERT is running on the ports where we are supposed to force admin // status DOWN. If BERT is running, force admin status to DOWN on port. void CheckRunningBertAndForceAdminDown( gnoi::diag::Diag::StubInterface& sut_gnoi_diag_stub, - gnoi::diag::Diag::StubInterface& control_switch_gnoi_diag_stub, - gnmi::gNMI::StubInterface& sut_gnmi_stub, - gnmi::gNMI::StubInterface& control_switch_gnmi_stub, - absl::string_view op_id, std::vector& sut_interfaces, - std::vector& control_switch_interfaces) { + thinkit::ControlDevice& control_device, + gnmi::gNMI::StubInterface& sut_gnmi_stub, absl::string_view op_id, + const std::vector& sut_interfaces, + const std::vector& control_switch_interfaces) { gnoi::diag::GetBERTResultRequest sut_request; sut_request.set_bert_operation_id(std::string(op_id)); for (const std::string& interface : sut_interfaces) { @@ -310,15 +406,15 @@ void CheckRunningBertAndForceAdminDown( absl::SleepFor(kPollInterval); if (sut_request.per_port_requests_size() > 0) { // Check BERT status on SUT and force admin status down. - ASSERT_NO_FATAL_FAILURE(CheckRunningBertAndForceAdminDownHelper( + ASSERT_NO_FATAL_FAILURE(CheckRunningBertAndForceAdminDownHelperSut( sut_gnoi_diag_stub, sut_gnmi_stub, &sut_request)); } if (control_switch_request.per_port_requests_size() > 0) { // Check BERT status on control switch and force admin status down. - ASSERT_NO_FATAL_FAILURE(CheckRunningBertAndForceAdminDownHelper( - control_switch_gnoi_diag_stub, control_switch_gnmi_stub, - &control_switch_request)); + ASSERT_NO_FATAL_FAILURE( + CheckRunningBertAndForceAdminDownHelperControlSwitch( + control_device, &control_switch_request)); } if (sut_request.per_port_requests().empty() && control_switch_request.per_port_requests().empty()) { @@ -327,7 +423,7 @@ void CheckRunningBertAndForceAdminDown( --max_poll_count; } - EXPECT_THAT(sut_request.per_port_requests(), testing::IsEmpty()); + EXPECT_THAT(sut_request.per_port_requests(), testing::IsEmpty()); EXPECT_THAT(control_switch_request.per_port_requests(), testing::IsEmpty()); } @@ -335,20 +431,10 @@ void CheckRunningBertAndForceAdminDown( // failure result on ports where admin status was forced to DOWN. Other ports // are expected to have successful BERT results. void GetAndVerifyBertResultsWithAdminDownInterfaces( - gnoi::diag::Diag::StubInterface& gnoi_diag_stub, - gnoi::diag::StartBERTRequest& bert_request, - std::vector& sut_admin_down_interfaces, - std::vector& control_switch_admin_down_interfaces) { - gnoi::diag::GetBERTResultRequest result_request; - result_request.set_bert_operation_id(bert_request.bert_operation_id()); - for (unsigned idx = 0; idx < bert_request.per_port_requests_size(); ++idx) { - *(result_request.add_per_port_requests()->mutable_interface()) = - bert_request.per_port_requests(idx).interface(); - } - gnoi::diag::GetBERTResultResponse result_response; - grpc::ClientContext result_context; - ASSERT_OK(gnoi_diag_stub.GetBERTResult(&result_context, result_request, - &result_response)); + const gnoi::diag::StartBERTRequest& bert_request, + const gnoi::diag::GetBERTResultResponse& result_response, + const std::vector& sut_admin_down_interfaces, + const std::vector& control_switch_admin_down_interfaces) { ASSERT_THAT(result_response.per_port_responses(), SizeIs(bert_request.per_port_requests_size())); for (unsigned idx = 0; idx < result_response.per_port_responses_size(); @@ -380,36 +466,93 @@ void GetAndVerifyBertResultsWithAdminDownInterfaces( } } -void SelectNUpInterfaces(int port_count_to_select, - gnmi::gNMI::StubInterface& gnmi_stub, - std::vector* interfaces) { - // Get all the interfaces that are operational status "UP". - ASSERT_OK_AND_ASSIGN(*interfaces, - pins_test::GetUpInterfacesOverGnmi(gnmi_stub)); - // Choose random ports. - ASSERT_GE(interfaces->size(), port_count_to_select); - std::shuffle(interfaces->begin(), interfaces->end(), absl::BitGen()); - interfaces->resize(port_count_to_select); +gnoi::diag::GetBERTResultRequest GetBertResultRequestFromStartRequest( + const gnoi::diag::StartBERTRequest& start_request) { + gnoi::diag::GetBERTResultRequest result_request; + result_request.set_bert_operation_id(start_request.bert_operation_id()); + for (const auto& per_port_request : start_request.per_port_requests()) { + *(result_request.add_per_port_requests()->mutable_interface()) = + per_port_request.interface(); + } + return result_request; +} + +void VerifyOperStatusOnSetOfSutInterfaces(gnmi::gNMI::StubInterface& gnmi_stub, + std::vector& interfaces, + absl::string_view oper_status) { + LOG(INFO) << "Verifying operational state " << oper_status + << " on interfaces."; + ASSERT_OK_AND_ASSIGN(auto interface_to_oper_status_map, + pins_test::GetInterfaceToOperStatusMapOverGnmi( + gnmi_stub, /*timeout=*/absl::Seconds(60))); + for (const std::string& interface : interfaces) { + SCOPED_TRACE(absl::StrCat("Interface: ", interface)); + EXPECT_NE(interface_to_oper_status_map.count(interface), 0); + EXPECT_EQ(interface_to_oper_status_map[interface], oper_status); + } +} + +absl::Status ValidateControlSwitchPortsUp( + thinkit::ControlDevice& control_device, + const std::vector& interfaces) { + ASSIGN_OR_RETURN( + const auto up_interfaces, + control_device.GetUpLinks(absl::Span(interfaces))); + + std::vector down_interfaces; + for (const std::string& interface : interfaces) { + if (!up_interfaces.contains(interface)) { + down_interfaces.push_back(interface); + } + } + + if (!down_interfaces.empty()) { + return absl::InternalError( + absl::StrCat("Some interfaces are not up on control switch: ", + absl::StrJoin(down_interfaces, "\n"))); + } + return absl::OkStatus(); +} + +std::vector SelectNInterfacesFromList( + int port_count_to_select, std::vector interfaces) { + if (interfaces.size() < port_count_to_select) { + return std::vector(); + } + std::shuffle(interfaces.begin(), interfaces.end(), absl::BitGen()); + interfaces.resize(port_count_to_select); + return interfaces; +} + +bool IsListPartOfInterfaceList(const std::vector& list, + const std::vector& interface_list) { + for (const std::string& interface : list) { + if (IsInterfaceInList(interface, interface_list) == false) { + return false; + } + } + return true; } // Test StartBERT with invalid request parameters. TEST_P(BertTest, StartBertFailsIfRequestParametersInvalid) { - GetMirrorTestbed().Environment().SetTestCaseID( - "c1dcb1cc-4806-45cc-8f8a-676beafde103"); - thinkit::Switch& sut = GetMirrorTestbed().Sut(); - ASSERT_OK(pins_test::PortsUp(sut)); - ASSERT_OK_AND_ASSIGN(auto sut_gnoi_diag_stub, sut.CreateGnoiDiagStub()); + ASSERT_NO_FATAL_FAILURE( + InitializeTestEnvironment("c1dcb1cc-4806-45cc-8f8a-676beafde103")); + thinkit::Switch& sut = generic_testbed_->Sut(); + ASSERT_OK( + pins_test::PortsUp(sut, absl::Span(sut_interfaces_))); // Select one operational state "up" port. std::string interface = absl::GetFlag(FLAGS_interface); - if (interface.empty()) { - std::vector interfaces; - ASSERT_OK_AND_ASSIGN( - std::unique_ptr sut_gnmi_stub, - sut.CreateGnmiStub()); - ASSERT_NO_FATAL_FAILURE( - SelectNUpInterfaces(1, *sut_gnmi_stub, &interfaces)); - interface = interfaces[0]; + if (!interface.empty()) { + // Verify that provided interfaces are part of SUT's UP interfaces. + ASSERT_TRUE(IsInterfaceInList(interface, sut_interfaces_)) + << "SUT test interface selected for test: " + << interface << "./n UP interfaces on SUT: " + << absl::StrJoin(sut_interfaces_, ","); + } else { + sut_test_interfaces_ = SelectNInterfacesFromList(1, sut_interfaces_); + interface = sut_test_interfaces_[0]; } LOG(INFO) << "Selected interface: " << interface << ". To repeat the test with same interface, use " @@ -421,7 +564,7 @@ TEST_P(BertTest, StartBertFailsIfRequestParametersInvalid) { absl::StrCat("OpId-", absl::ToUnixMillis(absl::Now()))); *(valid_request.add_per_port_requests()) = gutil::ParseProtoOrDie( - BuildPerPortStartBertRequest("interface")); + BuildPerPortStartBertRequest(interface)); gnoi::diag::StartBERTResponse response; // Case 1: BERT test duration is 0 secs. @@ -432,7 +575,7 @@ TEST_P(BertTest, StartBertFailsIfRequestParametersInvalid) { grpc::ClientContext context; LOG(INFO) << "Sending StartBERT request: " << too_short_time_request.ShortDebugString(); - EXPECT_THAT(gutil::GrpcStatusToAbslStatus(sut_gnoi_diag_stub->StartBERT( + EXPECT_THAT(gutil::GrpcStatusToAbslStatus(sut_diag_stub_->StartBERT( &context, too_short_time_request, &response)), gutil::StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("is too short"))); @@ -448,7 +591,7 @@ TEST_P(BertTest, StartBertFailsIfRequestParametersInvalid) { grpc::ClientContext context; LOG(INFO) << "Sending StartBERT request: " << too_long_time_request.ShortDebugString(); - EXPECT_THAT(gutil::GrpcStatusToAbslStatus(sut_gnoi_diag_stub->StartBERT( + EXPECT_THAT(gutil::GrpcStatusToAbslStatus(sut_diag_stub_->StartBERT( &context, too_long_time_request, &response)), gutil::StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("is too long"))); @@ -463,7 +606,7 @@ TEST_P(BertTest, StartBertFailsIfRequestParametersInvalid) { grpc::ClientContext context; LOG(INFO) << "Sending StartBERT request: " << unset_prbs_polynomial_request.ShortDebugString(); - EXPECT_THAT(gutil::GrpcStatusToAbslStatus(sut_gnoi_diag_stub->StartBERT( + EXPECT_THAT(gutil::GrpcStatusToAbslStatus(sut_diag_stub_->StartBERT( &context, unset_prbs_polynomial_request, &response)), gutil::StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("PRBS polynomial is not set"))); @@ -480,13 +623,13 @@ TEST_P(BertTest, StartBertFailsIfRequestParametersInvalid) { grpc::ClientContext context; LOG(INFO) << "Sending StartBERT request: " << invalid_interface_request.ShortDebugString(); - EXPECT_THAT(gutil::GrpcStatusToAbslStatus(sut_gnoi_diag_stub->StartBERT( + EXPECT_THAT(gutil::GrpcStatusToAbslStatus(sut_diag_stub_->StartBERT( &context, invalid_interface_request, &response)), gutil::StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Interface is invalid"))); } - // TODO (b/176913347): Enable the all ports UP check. - // ASSERT_OK(pins_test::PortsUp(sut)); + ASSERT_OK( + pins_test::PortsUp(sut, absl::Span(sut_interfaces_))); } // Test StopBERT RPC with invalid argument in the request. @@ -494,12 +637,11 @@ TEST_P(BertTest, StartBertFailsIfRequestParametersInvalid) { // 2) If StopBERT RPC is requested on a port that is not running BERT, RPC // should fail. TEST_P(BertTest, StopBertfailsIfRequestParametersInvalid) { - GetMirrorTestbed().Environment().SetTestCaseID( - "224db9cf-c709-486d-a0d3-6ab64c1a1e1f"); - thinkit::Switch& sut = GetMirrorTestbed().Sut(); - - ASSERT_OK(pins_test::PortsUp(sut)); - ASSERT_OK_AND_ASSIGN(auto sut_gnoi_diag_stub, sut.CreateGnoiDiagStub()); + ASSERT_NO_FATAL_FAILURE( + InitializeTestEnvironment("224db9cf-c709-486d-a0d3-6ab64c1a1e1f")); + thinkit::Switch& sut = generic_testbed_->Sut(); + ASSERT_OK( + pins_test::PortsUp(sut, absl::Span(sut_interfaces_))); // Request StopBERT RPC on an invalid port, RPC should fail. { @@ -515,7 +657,7 @@ TEST_P(BertTest, StopBertfailsIfRequestParametersInvalid) { LOG(INFO) << "Sending StopBERT request: " << request.ShortDebugString(); EXPECT_THAT( gutil::GrpcStatusToAbslStatus( - sut_gnoi_diag_stub->StopBERT(&context, request, &response)), + sut_diag_stub_->StopBERT(&context, request, &response)), gutil::StatusIs( absl::StatusCode::kInvalidArgument, AllOf(HasSubstr("Interface is invalid"), @@ -526,12 +668,15 @@ TEST_P(BertTest, StopBertfailsIfRequestParametersInvalid) { { // Select one operational state "up" port. std::string interface = absl::GetFlag(FLAGS_interface); - if (interface.empty()) { - std::vector interfaces; - ASSERT_OK_AND_ASSIGN(auto sut_gnmi_stub, sut.CreateGnmiStub()); - ASSERT_NO_FATAL_FAILURE( - SelectNUpInterfaces(1, *sut_gnmi_stub, &interfaces)); - interface = interfaces[0]; + if (!interface.empty()) { + // Verify that provided interfaces are part of SUT's UP interfaces. + ASSERT_TRUE(IsInterfaceInList(interface, sut_interfaces_)) + << "SUT test interface selected for test: " + << interface << "./n UP interfaces on SUT: " + << absl::StrJoin(sut_interfaces_, ","); + } else { + sut_test_interfaces_ = SelectNInterfacesFromList(1, sut_interfaces_); + interface = sut_test_interfaces_[0]; } LOG(INFO) << "Selected interface: " << interface << ". To repeat the test with same interface, use " @@ -549,13 +694,12 @@ TEST_P(BertTest, StopBertfailsIfRequestParametersInvalid) { LOG(INFO) << "Sending StopBERT request: " << request.ShortDebugString(); EXPECT_THAT( gutil::GrpcStatusToAbslStatus( - sut_gnoi_diag_stub->StopBERT(&context, request, &response)), + sut_diag_stub_->StopBERT(&context, request, &response)), gutil::StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Operation ID is not found on interface"))); } - - // TODO (b/176913347): Enable the all ports UP check. - // ASSERT_OK(pins_test::PortsUp(sut)); + ASSERT_OK( + pins_test::PortsUp(sut, absl::Span(sut_interfaces_))); } // Test GetBERTResult RPC with invalid argument in the request. @@ -563,11 +707,11 @@ TEST_P(BertTest, StopBertfailsIfRequestParametersInvalid) { // 2) If GetBERTResult RPC is requested on a port that never ran BERT before, // RPC should fail. TEST_P(BertTest, GetBertResultFailsIfRequestParametersInvalid) { - GetMirrorTestbed().Environment().SetTestCaseID( - "4f837d7a-ab44-4694-9ca9-399d576757f4"); - thinkit::Switch& sut = GetMirrorTestbed().Sut(); - ASSERT_OK(pins_test::PortsUp(sut)); - ASSERT_OK_AND_ASSIGN(auto sut_gnoi_diag_stub, sut.CreateGnoiDiagStub()); + ASSERT_NO_FATAL_FAILURE( + InitializeTestEnvironment("4f837d7a-ab44-4694-9ca9-399d576757f4")); + thinkit::Switch& sut = generic_testbed_->Sut(); + ASSERT_OK( + pins_test::PortsUp(sut, absl::Span(sut_interfaces_))); // Request GetBERTResult RPC on an invalid port, RPC should fail. { @@ -582,7 +726,7 @@ TEST_P(BertTest, GetBertResultFailsIfRequestParametersInvalid) { grpc::ClientContext context; LOG(INFO) << "Sending GetBERTResult request: " << result_request.ShortDebugString(); - EXPECT_THAT(gutil::GrpcStatusToAbslStatus(sut_gnoi_diag_stub->GetBERTResult( + EXPECT_THAT(gutil::GrpcStatusToAbslStatus(sut_diag_stub_->GetBERTResult( &context, result_request, &result_response)), gutil::StatusIs( absl::StatusCode::kInvalidArgument, @@ -593,12 +737,15 @@ TEST_P(BertTest, GetBertResultFailsIfRequestParametersInvalid) { { // Select one operational state "up" port. std::string interface = absl::GetFlag(FLAGS_interface); - if (interface.empty()) { - std::vector interfaces; - ASSERT_OK_AND_ASSIGN(auto sut_gnmi_stub, sut.CreateGnmiStub()); - ASSERT_NO_FATAL_FAILURE( - SelectNUpInterfaces(1, *sut_gnmi_stub, &interfaces)); - interface = interfaces[0]; + if (!interface.empty()) { + // Verify that provided interfaces are part of SUT's UP interfaces. + ASSERT_TRUE(IsInterfaceInList(interface, sut_interfaces_)) + << "SUT test interface selected for test: " + << interface << "./n UP interfaces on SUT: " + << absl::StrJoin(sut_interfaces_, ","); + } else { + sut_test_interfaces_ = SelectNInterfacesFromList(1, sut_interfaces_); + interface = sut_test_interfaces_[0]; } LOG(INFO) << "Selected interface: " << interface << ". To repeat the test with same interface, use " @@ -616,33 +763,35 @@ TEST_P(BertTest, GetBertResultFailsIfRequestParametersInvalid) { grpc::ClientContext context; LOG(INFO) << "Sending GetBERTResult request: " << result_request.ShortDebugString(); - EXPECT_THAT(gutil::GrpcStatusToAbslStatus(sut_gnoi_diag_stub->GetBERTResult( + EXPECT_THAT(gutil::GrpcStatusToAbslStatus(sut_diag_stub_->GetBERTResult( &context, result_request, &result_response)), gutil::StatusIs(absl::StatusCode::kInvalidArgument, AllOf(HasSubstr("Result is not found for intf"), HasSubstr(interface)))); } - - ASSERT_OK(pins_test::PortsUp(sut)); + ASSERT_OK( + pins_test::PortsUp(sut, absl::Span(sut_interfaces_))); } - // Test StartBERT fails if peer port is not running BERT. TEST_P(BertTest, StartBertfailsIfPeerPortNotRunningBert) { - GetMirrorTestbed().Environment().SetTestCaseID( - "37e48922-0616-4d16-8fd3-975897491956"); - thinkit::Switch& sut = GetMirrorTestbed().Sut(); - ASSERT_OK_AND_ASSIGN(auto sut_gnmi_stub, sut.CreateGnmiStub()); - ASSERT_OK(pins_test::PortsUp(sut)); - ASSERT_OK_AND_ASSIGN(auto sut_gnoi_diag_stub, sut.CreateGnoiDiagStub()); + ASSERT_NO_FATAL_FAILURE( + InitializeTestEnvironment("37e48922-0616-4d16-8fd3-975897491956")); + thinkit::Switch& sut = generic_testbed_->Sut(); + ASSERT_OK( + pins_test::PortsUp(sut, absl::Span(sut_interfaces_))); // Select one operational state "up" port. std::string interface = absl::GetFlag(FLAGS_interface); - if (interface.empty()) { - std::vector interfaces; - ASSERT_NO_FATAL_FAILURE( - SelectNUpInterfaces(1, *sut_gnmi_stub, &interfaces)); - interface = interfaces[0]; + if (!interface.empty()) { + // Verify that provided interfaces are part of SUT's UP interfaces. + ASSERT_TRUE(IsInterfaceInList(interface, sut_interfaces_)) + << "SUT test interface selected for test: " + << interface << "./n UP interfaces on SUT: " + << absl::StrJoin(sut_interfaces_, ","); + } else { + sut_test_interfaces_ = SelectNInterfacesFromList(1, sut_interfaces_); + interface = sut_test_interfaces_[0]; } LOG(INFO) << "Selected interface: " << interface << ". To repeat the test with same interface, use " @@ -655,19 +804,20 @@ TEST_P(BertTest, StartBertfailsIfPeerPortNotRunningBert) { *(bert_request.add_per_port_requests()) = gutil::ParseProtoOrDie( BuildPerPortStartBertRequest(interface)); - gnoi::diag::StartBERTResponse bert_response; - grpc::ClientContext context; - LOG(INFO) << "Sending StartBERT request: " << bert_request.ShortDebugString(); + + LOG(INFO) << "Sending StartBERT request on SUT:"; + ASSERT_NO_FATAL_FAILURE( + SendStartBertRequestSuccessfullyOnSut(bert_request, *sut_diag_stub_)); // Poll for allowed BERT delay duration. int max_poll_count = ceil(ToInt64Seconds(kDelayDuration) / ToInt64Seconds(kPollInterval)); bool poll_timeout = true; - for (int count = 0; count < max_poll_count; ++count) { + for (int count = 0; count < max_poll_count; ++count) { absl::SleepFor(kPollInterval); ASSERT_OK_AND_ASSIGN( pins_test::OperStatus oper_status, - pins_test::GetInterfaceOperStatusOverGnmi(*sut_gnmi_stub, interface)); + pins_test::GetInterfaceOperStatusOverGnmi(*sut_gnmi_stub_, interface)); // If port is "UP" and no longer in "TESTING" oper state, BERT has completed // on the port and full BERT result is ready for read. if (oper_status == pins_test::OperStatus::kUp) { @@ -675,6 +825,7 @@ TEST_P(BertTest, StartBertfailsIfPeerPortNotRunningBert) { break; } } + if (poll_timeout == true) { LOG(WARNING) << "BERT is not completed on the port in maximum allowed time."; @@ -684,14 +835,13 @@ TEST_P(BertTest, StartBertfailsIfPeerPortNotRunningBert) { result_request.set_bert_operation_id(bert_request.bert_operation_id()); *(result_request.add_per_port_requests()->mutable_interface()) = bert_request.per_port_requests(0).interface(); - gnoi::diag::GetBERTResultResponse result_response; grpc::ClientContext result_context; - EXPECT_OK(sut_gnoi_diag_stub->GetBERTResult(&result_context, result_request, - &result_response)); + EXPECT_OK(sut_diag_stub_->GetBERTResult(&result_context, result_request, + &result_response)); LOG(INFO) << "Result: " << result_response.ShortDebugString(); - // TODO (b/176913347): Enable the all ports UP check. - // ASSERT_OK(pins_test::PortsUp(sut)); + ASSERT_OK( + pins_test::PortsUp(sut, absl::Span(sut_interfaces_))); // Verify the response. ASSERT_THAT(result_response.per_port_responses(), SizeIs(1)); EXPECT_EQ(result_response.per_port_responses(0).status(), @@ -707,40 +857,59 @@ TEST_P(BertTest, StartBertfailsIfPeerPortNotRunningBert) { // 3) Operation id that was used earlier to start the BERT test will fail to // start BERT if used again. TEST_P(BertTest, StartBertSucceeds) { - GetMirrorTestbed().Environment().SetTestCaseID( - "b31a796a-d078-4d45-b785-f09ec598e05a"); - thinkit::Switch& sut = GetMirrorTestbed().Sut(); - ASSERT_OK_AND_ASSIGN(auto sut_gnmi_stub, sut.CreateGnmiStub()); - ASSERT_OK(pins_test::PortsUp(sut)); - ASSERT_OK_AND_ASSIGN(auto sut_gnoi_diag_stub, sut.CreateGnoiDiagStub()); + ASSERT_NO_FATAL_FAILURE( + InitializeTestEnvironment("b31a796a-d078-4d45-b785-f09ec598e05a")); + thinkit::Switch& sut = generic_testbed_->Sut(); + ASSERT_OK( + pins_test::PortsUp(sut, absl::Span(sut_interfaces_))); - thinkit::Switch& control_switch = GetMirrorTestbed().ControlSwitch(); - ASSERT_OK_AND_ASSIGN(auto control_switch_gnmi_stub, - control_switch.CreateGnmiStub()); - ASSERT_OK(pins_test::PortsUp(control_switch)); - ASSERT_OK_AND_ASSIGN(auto control_switch_gnoi_diag_stub, - control_switch.CreateGnoiDiagStub()); + thinkit::ControlDevice& control_device = generic_testbed_->ControlDevice(); + ASSERT_OK(ValidateControlSwitchPortsUp(control_device, peer_interfaces_)); // Select 2 operational state "up" ports. - std::vector interfaces = absl::GetFlag(FLAGS_interfaces); - if (interfaces.empty()) { - ASSERT_OK_AND_ASSIGN(std::unique_ptr sut_gnmi_stub, - sut.CreateGnmiStub()); - ASSERT_NO_FATAL_FAILURE( - SelectNUpInterfaces(2, *sut_gnmi_stub, &interfaces)); + sut_test_interfaces_ = absl::GetFlag(FLAGS_interfaces); + constexpr int kNumInterfaces = 2; + if (!sut_test_interfaces_.empty()) { + // Verify that provided interfaces are part of SUT's UP interfaces. + ASSERT_TRUE( + IsListPartOfInterfaceList(sut_test_interfaces_, sut_interfaces_)) + << "SUT test infaces selected for test: " + << absl::StrJoin(sut_test_interfaces_, ",") + << "./n UP interfaces on SUT: " << absl::StrJoin(sut_interfaces_, ","); + } else { + sut_test_interfaces_ = + SelectNInterfacesFromList(kNumInterfaces, sut_interfaces_); + } + ASSERT_THAT(sut_test_interfaces_, SizeIs(kNumInterfaces)); + // Get peer test interfaces corresponding to SUT test interfaces. + ASSERT_OK_AND_ASSIGN(peer_test_interfaces_, + GetPeerInterfacesForSutInterfaces(sut_test_interfaces_)); + LOG(INFO) << "Selected {SUT, control_device} interfaces: "; + for (size_t idx = 0; idx < sut_test_interfaces_.size(); ++idx) { + LOG(INFO) << "{" << sut_test_interfaces_[idx] << ", " + << peer_test_interfaces_[idx] << "}, "; } - ASSERT_THAT(interfaces, SizeIs(2)); - LOG(INFO) << "Selected interfaces: " << absl::StrJoin(interfaces, ",") - << ". To repeat the test with same interfaces, " - << "use --test_arg=--interfaces=" << absl::StrJoin(interfaces, ",") + + LOG(INFO) << "To repeat the test with same SUT interfaces, " + << "use --test_arg=--interfaces=" + << absl::StrJoin(sut_test_interfaces_, ",") << " in test arguments."; - gnoi::diag::StartBERTRequest bert_request; - // Create the BERT request. - bert_request.set_bert_operation_id( - absl::StrCat("OpId-", absl::ToUnixMillis(absl::Now()))); - for (const std::string& interface : interfaces) { - *(bert_request.add_per_port_requests()) = + gnoi::diag::StartBERTRequest bert_request_sut; + gnoi::diag::StartBERTRequest bert_request_control_switch; + std::string op_id = absl::StrCat("OpId-", absl::ToUnixMillis(absl::Now())); + // Create the BERT request for SUT. + bert_request_sut.set_bert_operation_id(op_id); + for (const std::string& interface : sut_test_interfaces_) { + *(bert_request_sut.add_per_port_requests()) = + gutil::ParseProtoOrDie( + BuildPerPortStartBertRequest(interface)); + } + + // Create the BERT request for control switch. + bert_request_control_switch.set_bert_operation_id(op_id); + for (const std::string& interface : peer_test_interfaces_) { + *(bert_request_control_switch.add_per_port_requests()) = gutil::ParseProtoOrDie( BuildPerPortStartBertRequest(interface)); } @@ -748,59 +917,43 @@ TEST_P(BertTest, StartBertSucceeds) { // Request StartBert on the SUT switch. LOG(INFO) << "Sending StartBERT request on SUT:"; ASSERT_NO_FATAL_FAILURE( - SendStartBertRequestSuccessfully(bert_request, *sut_gnoi_diag_stub)); + SendStartBertRequestSuccessfullyOnSut(bert_request_sut, *sut_diag_stub_)); // Request StartBert on the control switch. LOG(INFO) << "Sending StartBERT request on control switch:"; - ASSERT_NO_FATAL_FAILURE(SendStartBertRequestSuccessfully( - bert_request, *control_switch_gnoi_diag_stub)); + ASSERT_NO_FATAL_FAILURE(SendStartBertRequestSuccessfullyOnControlSwitch( + bert_request_control_switch, control_device)); // Get start timestamp. absl::Time start_time = absl::Now(); // Wait before reading the oper status. absl::SleepFor(kWaitToReadOperStatus); - // Verify that ports should be in TESTING mode now. - for (const std::string& interface : interfaces) { - SCOPED_TRACE( - absl::StrCat("Getting operational status for interface: ", interface)); - ASSERT_OK_AND_ASSIGN( - pins_test::OperStatus oper_status, - pins_test::GetInterfaceOperStatusOverGnmi(*sut_gnmi_stub, interface)); - ASSERT_EQ(oper_status, pins_test::OperStatus::kTesting); - ASSERT_OK_AND_ASSIGN(oper_status, - pins_test::GetInterfaceOperStatusOverGnmi( - *control_switch_gnmi_stub, interface)); - ASSERT_EQ(oper_status, pins_test::OperStatus::kTesting); - } + // Verify TESTING operational state on SUT ports running linkqual. + ASSERT_NO_FATAL_FAILURE(VerifyOperStatusOnSetOfSutInterfaces( + *sut_gnmi_stub_, sut_test_interfaces_, /*oper_status=*/"TESTING")); // Request another StartBert on the same ports on SUT and it should fail. { - gnoi::diag::StartBERTRequest second_bert_request = bert_request; + gnoi::diag::StartBERTRequest second_bert_request = bert_request_sut; second_bert_request.set_bert_operation_id( absl::StrCat("OpId-", absl::ToUnixMillis(absl::Now()))); // Request StartBert on the SUT switch. LOG(INFO) << "Sending second StartBERT request on SUT:"; - ASSERT_NO_FATAL_FAILURE(SendStartBertRequestSuccessfully( - second_bert_request, *sut_gnoi_diag_stub)); + ASSERT_NO_FATAL_FAILURE(SendStartBertRequestSuccessfullyOnSut( + second_bert_request, *sut_diag_stub_)); // Wait some time before querying the result. absl::SleepFor(kWaitTime); - gnoi::diag::GetBERTResultRequest result_request; - result_request.set_bert_operation_id( - second_bert_request.bert_operation_id()); - for (int idx = 0; idx < interfaces.size(); ++idx) { - *(result_request.add_per_port_requests()->mutable_interface()) = - second_bert_request.per_port_requests(idx).interface(); - } - + gnoi::diag::GetBERTResultRequest result_request = + GetBertResultRequestFromStartRequest(second_bert_request); gnoi::diag::GetBERTResultResponse result_response; grpc::ClientContext result_context; - EXPECT_OK(sut_gnoi_diag_stub->GetBERTResult(&result_context, result_request, - &result_response)); + EXPECT_OK(sut_diag_stub_->GetBERTResult(&result_context, result_request, + &result_response)); LOG(INFO) << "Result: " << result_response.ShortDebugString(); EXPECT_THAT(result_response.per_port_responses(), - SizeIs(interfaces.size())); + SizeIs(sut_test_interfaces_.size())); for (const auto& per_port_result : result_response.per_port_responses()) { EXPECT_EQ(per_port_result.status(), gnoi::diag::BERT_STATUS_PORT_ALREADY_IN_BERT) @@ -813,51 +966,47 @@ TEST_P(BertTest, StartBertSucceeds) { (absl::Now() - start_time) - absl::Seconds(1)) / kPollInterval; - std::vector interfaces_running_bert = interfaces; ASSERT_NO_FATAL_FAILURE(WaitForBertToCompleteOnInterfaces( - *sut_gnmi_stub, *control_switch_gnmi_stub, interfaces_running_bert, + *sut_gnmi_stub_, sut_test_interfaces_, control_device, + GetBertResultRequestFromStartRequest(bert_request_control_switch), max_poll_count)); - gnoi::diag::GetBERTResultRequest result_request; - result_request.set_bert_operation_id(bert_request.bert_operation_id()); - for (int idx = 0; idx < interfaces.size(); ++idx) { - *(result_request.add_per_port_requests()->mutable_interface()) = - bert_request.per_port_requests(idx).interface(); - } // Get the BERT result from the SUT. - { + gnoi::diag::GetBERTResultRequest result_request_sut = + GetBertResultRequestFromStartRequest(bert_request_sut); gnoi::diag::GetBERTResultResponse result_response; grpc::ClientContext result_context; - EXPECT_OK(sut_gnoi_diag_stub->GetBERTResult(&result_context, result_request, - &result_response)); + EXPECT_OK(sut_diag_stub_->GetBERTResult(&result_context, result_request_sut, + &result_response)); LOG(INFO) << "Result: " << result_response.ShortDebugString(); ASSERT_THAT(result_response.per_port_responses(), - SizeIs(bert_request.per_port_requests_size())); + SizeIs(bert_request_sut.per_port_requests_size())); for (int idx = 0; idx < result_response.per_port_responses_size(); ++idx) { VerifyBertResultForSuccess( result_response.per_port_responses(idx), - bert_request.bert_operation_id(), - bert_request.per_port_requests(idx).interface(), - bert_request.per_port_requests(idx).prbs_polynomial()); + bert_request_sut.bert_operation_id(), + bert_request_sut.per_port_requests(idx).interface(), + bert_request_sut.per_port_requests(idx).prbs_polynomial()); } } - + // Get the BERT result from the control switch. { - gnoi::diag::GetBERTResultResponse result_response; - grpc::ClientContext result_context; - EXPECT_OK(control_switch_gnoi_diag_stub->GetBERTResult( - &result_context, result_request, &result_response)); + gnoi::diag::GetBERTResultRequest result_request_control_switch = + GetBertResultRequestFromStartRequest(bert_request_control_switch); + ASSERT_OK_AND_ASSIGN( + gnoi::diag::GetBERTResultResponse result_response, + control_device.GetBERTResult(result_request_control_switch)); LOG(INFO) << "Result: " << result_response.ShortDebugString(); ASSERT_THAT(result_response.per_port_responses(), - SizeIs(bert_request.per_port_requests_size())); + SizeIs(bert_request_control_switch.per_port_requests_size())); for (int idx = 0; idx < result_response.per_port_responses_size(); ++idx) { VerifyBertResultForSuccess( result_response.per_port_responses(idx), - bert_request.bert_operation_id(), - bert_request.per_port_requests(idx).interface(), - bert_request.per_port_requests(idx).prbs_polynomial()); + bert_request_control_switch.bert_operation_id(), + bert_request_control_switch.per_port_requests(idx).interface(), + bert_request_control_switch.per_port_requests(idx).prbs_polynomial()); } } @@ -867,19 +1016,19 @@ TEST_P(BertTest, StartBertSucceeds) { gnoi::diag::StartBERTResponse bert_response; grpc::ClientContext context; LOG(INFO) << "Sending StartBERT request: " - << bert_request.ShortDebugString(); + << bert_request_sut.ShortDebugString(); EXPECT_THAT( - gutil::GrpcStatusToAbslStatus(sut_gnoi_diag_stub->StartBERT( - &context, bert_request, &bert_response)), + gutil::GrpcStatusToAbslStatus(sut_diag_stub_->StartBERT( + &context, bert_request_sut, &bert_response)), gutil::StatusIs(absl::StatusCode::kInvalidArgument, AllOf(HasSubstr("Invalid request"), - HasSubstr(bert_request.bert_operation_id()), + HasSubstr(bert_request_sut.bert_operation_id()), HasSubstr("exists")))) << "Response: " << bert_response.ShortDebugString(); } - // TODO (b/176913347): Enable the all ports UP check. - // ASSERT_OK(pins_test::PortsUp(sut)); - // ASSERT_OK(pins_test::PortsUp(control_switch)); + ASSERT_OK( + pins_test::PortsUp(sut, absl::Span(sut_interfaces_))); + ASSERT_OK(ValidateControlSwitchPortsUp(control_device, peer_interfaces_)); } // Runs the BERT test on current maximum allowed number of interfaces. During @@ -889,80 +1038,95 @@ TEST_P(BertTest, StartBertSucceeds) { // This helps us verify a mix of operation during BERT - unexpected software or // hardware errors. TEST_P(BertTest, RunBertOnMaximumAllowedPorts) { - GetMirrorTestbed().Environment().SetTestCaseID( - "ce526e97-2a62-4044-9dce-8fc74b232e4b"); - thinkit::Switch& sut = GetMirrorTestbed().Sut(); - ASSERT_OK_AND_ASSIGN(auto sut_gnmi_stub, sut.CreateGnmiStub()); - ASSERT_OK(pins_test::PortsUp(sut)); - ASSERT_OK_AND_ASSIGN(auto sut_gnoi_diag_stub, sut.CreateGnoiDiagStub()); + ASSERT_NO_FATAL_FAILURE( + InitializeTestEnvironment("ce526e97-2a62-4044-9dce-8fc74b232e4b")); + thinkit::Switch& sut = generic_testbed_->Sut(); + ASSERT_OK( + pins_test::PortsUp(sut, absl::Span(sut_interfaces_))); - thinkit::Switch& control_switch = GetMirrorTestbed().ControlSwitch(); - ASSERT_OK_AND_ASSIGN(auto control_switch_gnmi_stub, - control_switch.CreateGnmiStub()); - ASSERT_OK(pins_test::PortsUp(control_switch)); - ASSERT_OK_AND_ASSIGN(auto control_switch_gnoi_diag_stub, - control_switch.CreateGnoiDiagStub()); + thinkit::ControlDevice& control_device = generic_testbed_->ControlDevice(); + ASSERT_OK(ValidateControlSwitchPortsUp(control_device, peer_interfaces_)); // Get all the interfaces that are operational status "UP". - ASSERT_OK_AND_ASSIGN(std::vector interfaces, - pins_test::GetUpInterfacesOverGnmi(*sut_gnmi_stub)); + sut_test_interfaces_ = sut_interfaces_; // For this test, we need at least 5 UP interfaces. - ASSERT_GE(interfaces.size(), 5); + ASSERT_GE(sut_test_interfaces_.size(), 5); // Resize the interface list if UP ports are more than max number of allowed // ports. - if (interfaces.size() > kMaxAllowedInterfacesToRunBert) { - interfaces.resize(kMaxAllowedInterfacesToRunBert); + if (sut_test_interfaces_.size() > kMaxAllowedInterfacesToRunBert) { + sut_test_interfaces_.resize(kMaxAllowedInterfacesToRunBert); } // Select 'N' ports on control switch and 'N' ports on SUT for admin down. - int num_interfaces_to_disable = 1 + (interfaces.size() / 16); + int num_interfaces_to_disable = 1 + (sut_test_interfaces_.size() / 16); // Seed the std::rand(). LOG(INFO) << "Seeding pseudo-random number generator with seed: " << absl::GetFlag(FLAGS_idx_seed); // Select SUT interfaces in the range [0..interfaces/2). std::vector sut_interfaces_for_admin_down; - std::sample(interfaces.begin(), interfaces.begin() + interfaces.size() / 2, + std::sample(sut_test_interfaces_.begin(), + sut_test_interfaces_.begin() + sut_test_interfaces_.size() / 2, std::back_inserter(sut_interfaces_for_admin_down), num_interfaces_to_disable, std::mt19937(absl::GetFlag(FLAGS_idx_seed))); - // Select control switch interfaces in the range [interfaces/2..interfaces]. - std::vector control_switch_interfaces_for_admin_down; - std::sample(interfaces.begin() + interfaces.size() / 2, interfaces.end(), - std::back_inserter(control_switch_interfaces_for_admin_down), + // Select SUT interfaces whose peer interfaces on control switch will be admin + // disabled in the range + // [sut_test_interfaces_/2..sut_test_interfaces_.size()). + std::vector sut_interfaces_for_peer_select; + std::sample(sut_test_interfaces_.begin() + sut_test_interfaces_.size() / 2, + sut_test_interfaces_.end(), + std::back_inserter(sut_interfaces_for_peer_select), num_interfaces_to_disable, std::mt19937(absl::GetFlag(FLAGS_idx_seed))); - - LOG(INFO) << "Starting BERT on " << interfaces.size() - << " interfaces: " << absl::StrJoin(interfaces, ","); + // Get control switch interfaces for admin disable. + ASSERT_OK_AND_ASSIGN( + std::vector control_switch_interfaces_for_admin_down, + GetPeerInterfacesForSutInterfaces(sut_interfaces_for_peer_select)); + + LOG(INFO) << "Starting BERT on " << sut_test_interfaces_.size() + << " {SUT, control_device} links: "; + for (const std::string& interface : sut_test_interfaces_) { + LOG(INFO) << "{" << interface << ", " + << sut_to_peer_interface_mapping_[interface] << "}, "; + } LOG(INFO) << "Interfaces selected on SUT for admin down: " << absl::StrJoin(sut_interfaces_for_admin_down, ","); LOG(INFO) << "Interfaces selected on control switch for admin down: " << absl::StrJoin(control_switch_interfaces_for_admin_down, ","); - gnoi::diag::StartBERTRequest bert_request; - // Create the BERT request. - bert_request.set_bert_operation_id( - absl::StrCat("OpId-", absl::ToUnixMillis(absl::Now()))); - for (const std::string& interface : interfaces) { - *(bert_request.add_per_port_requests()) = + gnoi::diag::StartBERTRequest bert_request_sut; + gnoi::diag::StartBERTRequest bert_request_control_switch; + // Create the BERT request for SUT and control switch. + std::string op_id = absl::StrCat("OpId-", absl::ToUnixMillis(absl::Now())); + bert_request_sut.set_bert_operation_id(op_id); + bert_request_control_switch.set_bert_operation_id(op_id); + for (const std::string& interface : sut_test_interfaces_) { + *(bert_request_sut.add_per_port_requests()) = gutil::ParseProtoOrDie( BuildPerPortStartBertRequest(interface)); + const std::string peer_interface = + sut_to_peer_interface_mapping_[interface]; + *(bert_request_control_switch.add_per_port_requests()) = + gutil::ParseProtoOrDie( + BuildPerPortStartBertRequest(peer_interface)); } // Request StartBert on the SUT switch. LOG(INFO) << "Sending StartBERT request on SUT:"; ASSERT_NO_FATAL_FAILURE( - SendStartBertRequestSuccessfully(bert_request, *sut_gnoi_diag_stub)); + SendStartBertRequestSuccessfullyOnSut(bert_request_sut, *sut_diag_stub_)); // Request StartBert on the control switch. LOG(INFO) << "Sending StartBERT request on control switch:"; - ASSERT_NO_FATAL_FAILURE(SendStartBertRequestSuccessfully( - bert_request, *control_switch_gnoi_diag_stub)); + ASSERT_NO_FATAL_FAILURE(SendStartBertRequestSuccessfullyOnControlSwitch( + bert_request_control_switch, control_device)); absl::Time start_time = absl::Now(); // Give some time to BERT to move in SYNC state. absl::SleepFor(absl::Seconds(90)); - + ASSERT_NO_FATAL_FAILURE(CheckRunningBertAndForceAdminDown( + *sut_diag_stub_, control_device, *sut_gnmi_stub_, op_id, + sut_interfaces_for_admin_down, control_switch_interfaces_for_admin_down)); absl::Time end_time = absl::Now(); // Wait for BERT to finish on test interfaces. @@ -970,86 +1134,117 @@ TEST_P(BertTest, RunBertOnMaximumAllowedPorts) { (end_time - start_time) - absl::Seconds(1)) / kPollInterval; - std::vector interfaces_running_bert = interfaces; ASSERT_NO_FATAL_FAILURE(WaitForBertToCompleteOnInterfaces( - *sut_gnmi_stub, *control_switch_gnmi_stub, interfaces_running_bert, + *sut_gnmi_stub_, sut_test_interfaces_, control_device, + GetBertResultRequestFromStartRequest(bert_request_control_switch), max_poll_count)); + // Get the BERT result from SUT and verify it. + LOG(INFO) << "Verify BERT results on SUT interfaces."; + grpc::ClientContext context; + gnoi::diag::GetBERTResultResponse bert_response_sut; + ASSERT_OK(sut_diag_stub_->GetBERTResult( + &context, GetBertResultRequestFromStartRequest(bert_request_sut), + &bert_response_sut)); + ASSERT_NO_FATAL_FAILURE(GetAndVerifyBertResultsWithAdminDownInterfaces( + bert_request_sut, bert_response_sut, sut_interfaces_for_admin_down, + control_switch_interfaces_for_admin_down)); + // Get the BERT result from control switch and verify it. + LOG(INFO) << "Verify BERT results on control switch interfaces."; + ASSERT_OK_AND_ASSIGN( + gnoi::diag::GetBERTResultResponse bert_response_control_switch, + control_device.GetBERTResult( + GetBertResultRequestFromStartRequest(bert_request_control_switch))); + ASSERT_NO_FATAL_FAILURE(GetAndVerifyBertResultsWithAdminDownInterfaces( + bert_request_control_switch, bert_response_control_switch, + sut_interfaces_for_admin_down, control_switch_interfaces_for_admin_down)); + + // Enable admin state on SUT and control switch interfaces. + ASSERT_NO_FATAL_FAILURE(SetAdminStateOnInterfaceList( + *sut_gnmi_stub_, sut_interfaces_for_admin_down, kEnabledTrue)); + ASSERT_OK(control_device.SetAdminLinkState( + control_switch_interfaces_for_admin_down, thinkit::LinkState::kUp)); + // Wait for some time before checking the port status. absl::SleepFor(kPortsUpWaitTime); ASSERT_OK(pins_test::PortsUp(sut)); - ASSERT_OK(pins_test::PortsUp(control_switch)); + ASSERT_OK(ValidateControlSwitchPortsUp(control_device, peer_interfaces_)); } // Run BERT on a port. Issue StopBERT on the SUT port, this causes BERT to // stop on SUT and this will cause BERT failure on control switch as control // switch side port will lose lock with its peer port on SUT side. TEST_P(BertTest, StopBertSucceeds) { - GetMirrorTestbed().Environment().SetTestCaseID( - "be7b6653-51b9-4231-a438-d9589bbcb677"); - thinkit::Switch& sut = GetMirrorTestbed().Sut(); - ASSERT_OK_AND_ASSIGN(auto sut_gnmi_stub, sut.CreateGnmiStub()); - ASSERT_OK(pins_test::PortsUp(sut)); - ASSERT_OK_AND_ASSIGN(auto sut_gnoi_diag_stub, sut.CreateGnoiDiagStub()); + ASSERT_NO_FATAL_FAILURE( + InitializeTestEnvironment("be7b6653-51b9-4231-a438-d9589bbcb677")); + thinkit::Switch& sut = generic_testbed_->Sut(); + ASSERT_OK( + pins_test::PortsUp(sut, absl::Span(sut_interfaces_))); - thinkit::Switch& control_switch = GetMirrorTestbed().ControlSwitch(); - ASSERT_OK_AND_ASSIGN(auto control_switch_gnmi_stub, - control_switch.CreateGnmiStub()); - ASSERT_OK(pins_test::PortsUp(control_switch)); - ASSERT_OK_AND_ASSIGN(auto control_switch_gnoi_diag_stub, - control_switch.CreateGnoiDiagStub()); + thinkit::ControlDevice& control_device = generic_testbed_->ControlDevice(); + ASSERT_OK(ValidateControlSwitchPortsUp(control_device, peer_interfaces_)); // Select one operational state "up" port. std::string interface = absl::GetFlag(FLAGS_interface); - if (interface.empty()) { - std::vector interfaces; - ASSERT_NO_FATAL_FAILURE(SelectNUpInterfaces(/*port_count_to_select=*/1, - *sut_gnmi_stub, &interfaces)); - interface = interfaces[0]; + if (!interface.empty()) { + // Verify that provided interfaces are part of SUT's UP interfaces. + ASSERT_TRUE(IsInterfaceInList(interface, sut_interfaces_)) + << "SUT test interface selected for test: " + << interface << "./n UP interfaces on SUT: " + << absl::StrJoin(sut_interfaces_, ","); + } else { + sut_test_interfaces_ = SelectNInterfacesFromList(1, sut_interfaces_); + interface = sut_test_interfaces_[0]; } - LOG(INFO) << "Selected interface: " - << interface << ". To repeat the test with same interface, use " + ASSERT_OK_AND_ASSIGN(peer_test_interfaces_, + GetPeerInterfacesForSutInterfaces(sut_test_interfaces_)); + std::string peer_interface = peer_test_interfaces_[0]; + LOG(INFO) << "Selected {SUT, control interface}: {" << interface << ", " + << peer_interface + << "}. To repeat the test with same SUT interface, use " << "--test_arg=--interface=" << interface << " in test arguments."; - gnoi::diag::StartBERTRequest bert_request; + gnoi::diag::StartBERTRequest bert_request_sut; + gnoi::diag::StartBERTRequest bert_request_control_switch; + std::string op_id = absl::StrCat("OpId-", absl::ToUnixMillis(absl::Now())); // Create the BERT request. - bert_request.set_bert_operation_id( - absl::StrCat("OpId-", absl::ToUnixMillis(absl::Now()))); - *(bert_request.add_per_port_requests()) = + bert_request_sut.set_bert_operation_id(op_id); + *(bert_request_sut.add_per_port_requests()) = gutil::ParseProtoOrDie( BuildPerPortStartBertRequest(interface)); + bert_request_control_switch.set_bert_operation_id(op_id); + *(bert_request_control_switch.add_per_port_requests()) = + gutil::ParseProtoOrDie( + BuildPerPortStartBertRequest(peer_interface)); // Request StartBert on the SUT switch. LOG(INFO) << "Sending StartBERT request on SUT:"; ASSERT_NO_FATAL_FAILURE( - SendStartBertRequestSuccessfully(bert_request, *sut_gnoi_diag_stub)); + SendStartBertRequestSuccessfullyOnSut(bert_request_sut, *sut_diag_stub_)); // Request StartBert on the control switch. LOG(INFO) << "Sending StartBERT request on control switch:"; - ASSERT_NO_FATAL_FAILURE(SendStartBertRequestSuccessfully( - bert_request, *control_switch_gnoi_diag_stub)); + ASSERT_NO_FATAL_FAILURE(SendStartBertRequestSuccessfullyOnControlSwitch( + bert_request_control_switch, control_device)); absl::Time start_time = absl::Now(); // Wait before reading the oper status. absl::SleepFor(kWaitToReadOperStatus); - // Verify that port should be in TESTING mode now. + // Verify that SUT port should be in TESTING mode now. { ASSERT_OK_AND_ASSIGN( pins_test::OperStatus oper_status, - pins_test::GetInterfaceOperStatusOverGnmi(*sut_gnmi_stub, interface)); - ASSERT_EQ(oper_status, pins_test::OperStatus::kTesting); - ASSERT_OK_AND_ASSIGN(oper_status, - pins_test::GetInterfaceOperStatusOverGnmi( - *control_switch_gnmi_stub, interface)); + pins_test::GetInterfaceOperStatusOverGnmi(*sut_gnmi_stub_, interface)); ASSERT_EQ(oper_status, pins_test::OperStatus::kTesting); } - gnoi::diag::GetBERTResultRequest result_request; - result_request.set_bert_operation_id(bert_request.bert_operation_id()); - *(result_request.add_per_port_requests()->mutable_interface()) = - bert_request.per_port_requests(0).interface(); + gnoi::diag::GetBERTResultRequest result_request_control_switch; + result_request_control_switch.set_bert_operation_id(op_id); + *(result_request_control_switch.add_per_port_requests() + ->mutable_interface()) = + bert_request_control_switch.per_port_requests(0).interface(); // Verify control switch side BERT has acquired the lock and is running now. { @@ -1059,11 +1254,10 @@ TEST_P(BertTest, StopBertSucceeds) { while (remaining_poll_count > 0) { absl::SleepFor(kPollInterval); gnoi::diag::GetBERTResultResponse response; - grpc::ClientContext context; - EXPECT_OK(control_switch_gnoi_diag_stub->GetBERTResult( - &context, result_request, &response)); + ASSERT_OK_AND_ASSIGN(response, control_device.GetBERTResult( + result_request_control_switch)); ASSERT_THAT(response.per_port_responses(), - SizeIs(bert_request.per_port_requests_size())); + SizeIs(bert_request_control_switch.per_port_requests_size())); ASSERT_EQ(response.per_port_responses(0).status(), gnoi::diag::BERT_STATUS_OK); if (response.per_port_responses(0).peer_lock_established()) { @@ -1078,14 +1272,14 @@ TEST_P(BertTest, StopBertSucceeds) { // Request StopBERT on SUT. { gnoi::diag::StopBERTRequest stop_request; - stop_request.set_bert_operation_id(bert_request.bert_operation_id()); + stop_request.set_bert_operation_id(op_id); *(stop_request.add_per_port_requests()->mutable_interface()) = - bert_request.per_port_requests(0).interface(); + bert_request_sut.per_port_requests(0).interface(); gnoi::diag::StopBERTResponse response; grpc::ClientContext context; LOG(INFO) << "Sending StopBERT request on SUT: " << stop_request.ShortDebugString(); - EXPECT_OK(sut_gnoi_diag_stub->StopBERT(&context, stop_request, &response)); + EXPECT_OK(sut_diag_stub_->StopBERT(&context, stop_request, &response)); // Verify response. ASSERT_THAT(response.per_port_responses(), @@ -1110,18 +1304,21 @@ TEST_P(BertTest, StopBertSucceeds) { std::vector interfaces_running_bert = {interface}; ASSERT_NO_FATAL_FAILURE(WaitForBertToCompleteOnInterfaces( - *sut_gnmi_stub, *control_switch_gnmi_stub, interfaces_running_bert, + *sut_gnmi_stub_, sut_test_interfaces_, control_device, + GetBertResultRequestFromStartRequest(bert_request_control_switch), max_poll_count)); // Get the BERT result from the SUT. BERT status should be OK. { + gnoi::diag::GetBERTResultRequest result_request_sut = + GetBertResultRequestFromStartRequest(bert_request_sut); gnoi::diag::GetBERTResultResponse response; grpc::ClientContext context; EXPECT_OK( - sut_gnoi_diag_stub->GetBERTResult(&context, result_request, &response)); + sut_diag_stub_->GetBERTResult(&context, result_request_sut, &response)); LOG(INFO) << "SUT BERT Result: " << response.ShortDebugString(); ASSERT_THAT(response.per_port_responses(), - SizeIs(bert_request.per_port_requests_size())); + SizeIs(bert_request_sut.per_port_requests_size())); EXPECT_EQ(response.per_port_responses(0).status(), gnoi::diag::BERT_STATUS_OK); } @@ -1130,12 +1327,11 @@ TEST_P(BertTest, StopBertSucceeds) { // peer lock loss. { gnoi::diag::GetBERTResultResponse response; - grpc::ClientContext context; - EXPECT_OK(control_switch_gnoi_diag_stub->GetBERTResult( - &context, result_request, &response)); + ASSERT_OK_AND_ASSIGN( + response, control_device.GetBERTResult(result_request_control_switch)); LOG(INFO) << "Control switch BERT Result: " << response.ShortDebugString(); ASSERT_THAT(response.per_port_responses(), - SizeIs(bert_request.per_port_requests_size())); + SizeIs(bert_request_control_switch.per_port_requests_size())); EXPECT_EQ(response.per_port_responses(0).status(), gnoi::diag::BERT_STATUS_PEER_LOCK_LOST); EXPECT_TRUE(response.per_port_responses(0).peer_lock_established()); @@ -1143,7 +1339,7 @@ TEST_P(BertTest, StopBertSucceeds) { } ASSERT_OK(pins_test::PortsUp(sut)); - ASSERT_OK(pins_test::PortsUp(control_switch)); + ASSERT_OK(ValidateControlSwitchPortsUp(control_device, peer_interfaces_)); } } // namespace bert diff --git a/tests/gnoi/bert_tests.h b/tests/gnoi/bert_tests.h index aef0c8c9..9ad3157a 100644 --- a/tests/gnoi/bert_tests.h +++ b/tests/gnoi/bert_tests.h @@ -12,15 +12,84 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef GOOGLE_TESTS_GNOI_BERT_TESTS_H_ -#define GOOGLE_TESTS_GNOI_BERT_TESTS_H_ +#ifndef PINS_TESTS_GNOI_BERT_TESTS_H_ +#define PINS_TESTS_GNOI_BERT_TESTS_H_ -#include "thinkit/mirror_testbed_fixture.h" +#include "absl/strings/substitute.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "gutil/status_matchers.h" +#include "gutil/testing.h" +#include "thinkit/generic_testbed_fixture.h" namespace bert { -class BertTest : public thinkit::MirrorTestbedFixture {}; +class BertTest : public thinkit::GenericTestbedFixture<> { + public: + BertTest() + : generic_testbed_(nullptr), + sut_gnmi_stub_(nullptr), + sut_diag_stub_(nullptr) {} + + void InitializeTestEnvironment(absl::string_view test_id) { + thinkit::TestRequirements requirements = + gutil::ParseProtoOrDie( + R"pb(interface_requirements { + count: 1 + interface_mode: CONTROL_INTERFACE + })pb"); + + ASSERT_OK_AND_ASSIGN(generic_testbed_, + GetTestbedWithRequirements(requirements)); + generic_testbed_->Environment().SetTestCaseID(test_id); + + absl::flat_hash_map interface_info = + generic_testbed_->GetSutInterfaceInfo(); + + for (const auto &[interface, info] : interface_info) { + if ((info.interface_modes.contains(thinkit::CONTROL_INTERFACE)) == thinkit::CONTROL_INTERFACE) { + sut_interfaces_.push_back(interface); + peer_interfaces_.push_back(info.peer_interface_name); + sut_to_peer_interface_mapping_[interface] = info.peer_interface_name; + } + } + + ASSERT_OK_AND_ASSIGN(sut_gnmi_stub_, + generic_testbed_->Sut().CreateGnmiStub()); + ASSERT_OK_AND_ASSIGN(sut_diag_stub_, + generic_testbed_->Sut().CreateGnoiDiagStub()); + } + + absl::StatusOr> GetPeerInterfacesForSutInterfaces( + const std::vector &sut_interfaces) { + std::vector peer_interfaces; + peer_interfaces.reserve(sut_interfaces.size()); + for (const std::string &sut_interface : sut_interfaces) { + if (sut_to_peer_interface_mapping_.count(sut_interface) == 0) { + return absl::NotFoundError(absl::Substitute( + "Failed to find peer for SUT interface $0", sut_interface)); + } + peer_interfaces.push_back(sut_to_peer_interface_mapping_[sut_interface]); + } + return peer_interfaces; + } + + protected: + std::unique_ptr generic_testbed_; + std::unique_ptr sut_gnmi_stub_; + std::unique_ptr sut_diag_stub_; + // List of SUT interfaces. + std::vector sut_interfaces_; + // List of control switch interfaces. + std::vector peer_interfaces_; + // List of SUT interfaces that are under test. + std::vector sut_test_interfaces_; + // List of control switch interfaces that are under test. + std::vector peer_test_interfaces_; + // A mapping of SUT interface and its peer interface on control switch. + absl::flat_hash_map sut_to_peer_interface_mapping_; +}; } // namespace bert -#endif // GOOGLE_TESTS_GNOI_BERT_TESTS_H_ +#endif // PINS_TESTS_GNOI_BERT_TESTS_H_ From d8d305e8f800b6734fdcfd3fde83a8923a6d3858 Mon Sep 17 00:00:00 2001 From: bibhuprasad-hcl <161687009+bibhuprasad-hcl@users.noreply.github.com> Date: Wed, 27 Nov 2024 22:59:13 +0000 Subject: [PATCH 05/17] [Thinkit] Check PortsUp only on test interfaces.Increase gNOI factory reset test time limit. (#771) Co-authored-by: smolkaj Co-authored-by: kishanps --- tests/gnoi/bert_tests.cc | 6 ++++-- tests/gnoi/factory_reset_test.cc | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/gnoi/bert_tests.cc b/tests/gnoi/bert_tests.cc index 81704c6d..33c860c6 100644 --- a/tests/gnoi/bert_tests.cc +++ b/tests/gnoi/bert_tests.cc @@ -1168,7 +1168,8 @@ TEST_P(BertTest, RunBertOnMaximumAllowedPorts) { // Wait for some time before checking the port status. absl::SleepFor(kPortsUpWaitTime); - ASSERT_OK(pins_test::PortsUp(sut)); + ASSERT_OK( + pins_test::PortsUp(sut, absl::Span(sut_interfaces_))); ASSERT_OK(ValidateControlSwitchPortsUp(control_device, peer_interfaces_)); } @@ -1338,7 +1339,8 @@ TEST_P(BertTest, StopBertSucceeds) { EXPECT_TRUE(response.per_port_responses(0).peer_lock_lost()); } - ASSERT_OK(pins_test::PortsUp(sut)); + ASSERT_OK( + pins_test::PortsUp(sut, absl::Span(sut_interfaces_))); ASSERT_OK(ValidateControlSwitchPortsUp(control_device, peer_interfaces_)); } diff --git a/tests/gnoi/factory_reset_test.cc b/tests/gnoi/factory_reset_test.cc index 1f42349a..34da0a61 100644 --- a/tests/gnoi/factory_reset_test.cc +++ b/tests/gnoi/factory_reset_test.cc @@ -38,7 +38,7 @@ namespace factory_reset { constexpr absl::Duration kFactoryResetWaitForDownTime = absl::Seconds(60); -constexpr absl::Duration kFactoryResetWaitForUpTime = absl::Minutes(18); +constexpr absl::Duration kFactoryResetWaitForUpTime = absl::Minutes(25); constexpr absl::Duration kSshSessionTimeout = absl::Seconds(5); void IssueGnoiFactoryResetAndValidateStatus( From c2fd6bfddea02c42b43d328311a9c60d19c8e356 Mon Sep 17 00:00:00 2001 From: VSuryaprasad-hcl <159443973+VSuryaprasad-HCL@users.noreply.github.com> Date: Wed, 27 Nov 2024 22:59:51 +0000 Subject: [PATCH 06/17] [Dvaas] Compare ports of dvaas::Adding test_run_validation_test_runner to dvaas. (#773) Co-authored-by: kishanps --- dvaas/BUILD.bazel | 18 +- dvaas/test_run_validation_test_runner.cc | 446 +++++++++++++++++++++++ 2 files changed, 463 insertions(+), 1 deletion(-) create mode 100644 dvaas/test_run_validation_test_runner.cc diff --git a/dvaas/BUILD.bazel b/dvaas/BUILD.bazel index a7179a9a..20ce7c20 100644 --- a/dvaas/BUILD.bazel +++ b/dvaas/BUILD.bazel @@ -321,4 +321,20 @@ cc_test( "@com_google_googletest//:gtest_main", "@com_google_protobuf//:protobuf", ], -) \ No newline at end of file +) + +# go/golden-test-with-coverage +cc_test( + name = "test_run_validation_test_runner", + srcs = ["test_run_validation_test_runner.cc"], + linkstatic = True, + deps = [ + ":test_run_validation", + ":test_vector", + ":test_vector_cc_proto", + "//gutil:testing", + "//p4_pdpi/packetlib", + "@com_google_absl//absl/strings", + "@com_google_absl//absl/types:optional", + ], +) diff --git a/dvaas/test_run_validation_test_runner.cc b/dvaas/test_run_validation_test_runner.cc new file mode 100644 index 00000000..473755e0 --- /dev/null +++ b/dvaas/test_run_validation_test_runner.cc @@ -0,0 +1,446 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/strings/substitute.h" +#include "absl/types/optional.h" +#include "dvaas/test_run_validation.h" +#include "dvaas/test_vector.h" +#include "dvaas/test_vector.pb.h" +#include "gutil/testing.h" +#include "p4_pdpi/packetlib/packetlib.h" + +namespace dvaas { +namespace { + +using ::gutil::ParseProtoOrDie; + +// A test case for the `ValidateTestRun` function. +struct TestCase { + // Human-readable description of this test case, for documentation. + std::string description; + // The inputs to the `ValidateTestRun` function to be + // used by this test case. + PacketTestVector test_vector; + SwitchOutput actual_output; +}; + +// Defines and returns test cases (i.e., inputs) for the +// `ValidateTestRun` oracle, which will produce error +// messages when given these inputs. Used to test the quality of the oracle's +// error messages. +std::vector TestCases() { + std::vector tests; + + { + TestCase& test = tests.emplace_back(); + test = TestCase{ + .description = + "Packet is expected to be forwarded (out of one\nof several " + "acceptable ports), but gets dropped.", + .test_vector = ParseProtoOrDie(R"pb( + input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "02:08:02:08:10:40" + ethernet_source: "40:04:10:04:04:20" + ethertype: "0x86dd" + } + } + headers { + ipv6_header { + version: "0x6" + dscp: "0x00" + ecn: "0x0" + flow_label: "0x00000" + payload_length: "0x00ee" + next_header: "0x3a" + hop_limit: "0x80" + ipv6_source: "fe80::" + ipv6_destination: "2002:a05:6860:4f00::" + } + } + headers { + icmp_header { + type: "0x00" + code: "0x00" + checksum: "0x1461" + rest_of_header: "0x00000000" + } + } + payload: "test packet" + } + } + } + # Acceptable outputs filled in below. + )pb"), + // The packet gets dropped -- no output. + .actual_output = SwitchOutput(), + }; + // We expect the packet to be forwarded unmodified, out of one of several + // acceptable ports (due to WCMP, for example). + for (std::string port : {"8", "12", "16", "20"}) { + auto& acceptable_output = + *test.test_vector.add_acceptable_outputs()->add_packets(); + acceptable_output = test.test_vector.input().packet(); + acceptable_output.set_port(port); + } + } + + { + TestCase& test = tests.emplace_back(); + test = TestCase{ + .description = + "Submit-to-ingress packet is expected to be\nforwarded and " + "mirrored and punted, but doesn't get punted.", + .test_vector = ParseProtoOrDie(R"pb( + input { + type: SUBMIT_TO_INGRESS + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "02:08:02:08:10:40" + ethernet_source: "40:04:10:04:04:20" + ethertype: "0x86dd" + } + } + headers { + ipv6_header { + version: "0x6" + dscp: "0x00" + ecn: "0x0" + flow_label: "0x00000" + payload_length: "0x00ee" + next_header: "0x3a" + hop_limit: "0x80" + ipv6_source: "fe80::" + ipv6_destination: "2002:a05:6860:4f00::" + } + } + headers { + icmp_header { + type: "0x00" + code: "0x00" + checksum: "0x1461" + rest_of_header: "0x00000000" + } + } + payload: "test packet" + } + } + } + acceptable_outputs { + # The mirrored (and encapsulated) packet. + packets { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "00:1a:11:17:5f:80" + ethernet_source: "00:02:03:04:05:06" + ethertype: "0x0800" + } + } + headers { + ipv4_header { + version: "0x4" + ihl: "0x5" + dscp: "0x00" + ecn: "0x0" + total_length: "0x0116" + identification: "0x0000" + flags: "0x2" + fragment_offset: "0x0000" + ttl: "0x40" + protocol: "0x2f" + checksum: "0xbe0b" + ipv4_source: "10.206.196.0" + ipv4_destination: "172.20.0.203" + } + } + # Mirrored packets get encapsulated but packetlib does not parse + # inner headers, hence the strange payload here containing the + # encapsulated headers. + payload: "\000\000\210\276\002\n\000 \000\000\002*\020\200\000\005\010\000Ex\000\360\000\000\000\000\020\375\323\372\n\000\000\000\n5\300jtest packet" + } + } + # The forwarded packet. + packets { + port: "31" + parsed { + headers { + ethernet_header { + ethernet_destination: "00:1a:11:17:5f:80" + ethernet_source: "02:2a:10:00:00:06" + ethertype: "0x0800" + } + } + headers { + ipv4_header { + version: "0x4" + ihl: "0x5" + dscp: "0x1e" + ecn: "0x0" + total_length: "0x00f0" + identification: "0x0000" + flags: "0x0" + fragment_offset: "0x0000" + ttl: "0x0f" + protocol: "0xfd" + checksum: "0xd4fa" + ipv4_source: "10.0.0.0" + ipv4_destination: "10.53.192.106" + } + } + payload: "test packet" + } + } + # The punted packet. + packet_ins { + metadata { + name: "ingress_port" + value: { str: "1" } + } + metadata { + name: "target_egress_port" + value: { str: "1" } + } + parsed { + headers { + ethernet_header { + ethernet_destination: "02:0a:00:20:00:00" + ethernet_source: "02:2a:10:80:00:05" + ethertype: "0x0800" + } + } + headers { + ipv4_header { + version: "0x4" + ihl: "0x5" + dscp: "0x1e" + ecn: "0x0" + total_length: "0x00f0" + identification: "0x0000" + flags: "0x0" + fragment_offset: "0x0000" + ttl: "0x10" + protocol: "0xfd" + checksum: "0xd3fa" + ipv4_source: "10.0.0.0" + ipv4_destination: "10.53.192.106" + } + } + payload: "test packet" + } + } + } + )pb"), + }; + // Actual output: the forwarded and mirrored packet, but not the punted + // packet. + *test.actual_output.mutable_packets() = + test.test_vector.acceptable_outputs(0).packets(); + } + + { + TestCase& test = tests.emplace_back(); + test = TestCase{ + .description = + "Packet gets forwarded with an unexpected\nmodification of two " + "header fields.", + .test_vector = ParseProtoOrDie(R"pb( + input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "02:03:04:05:06:07" + ethernet_source: "00:01:02:03:04:05" + ethertype: "0x0800" + } + } + headers { + ipv4_header { + version: "0x4" + ihl: "0x5" + dscp: "0x1c" + ecn: "0x0" + total_length: "0x012e" + identification: "0x0000" + flags: "0x0" + fragment_offset: "0x0000" + ttl: "0x20" + protocol: "0x11" + checksum: "0x1b62" + ipv4_source: "10.0.0.0" + ipv4_destination: "10.206.105.32" + } + } + headers { + udp_header { + source_port: "0x0000" + destination_port: "0x0000" + length: "0x011a" + checksum: "0xad82" + } + } + payload: "test packet" + } + } + } + # Acceptable outputs and actual output filled in below. + )pb"), + // Overridden below. + .actual_output = SwitchOutput(), + }; + + // We expect the packet to be forwarded out of port 12 unmodified. + auto& acceptable_output = + *test.test_vector.add_acceptable_outputs()->add_packets(); + acceptable_output = test.test_vector.input().packet(); + acceptable_output.set_port("12"); + + // The packet instead gets forwarded with two header field modifications. + auto& actual_output = *test.actual_output.add_packets(); + actual_output = acceptable_output; + actual_output.mutable_parsed() + ->mutable_headers(1) + ->mutable_ipv4_header() + ->set_dscp("0x00"); + actual_output.mutable_parsed() + ->mutable_headers(1) + ->mutable_ipv4_header() + ->set_checksum("0x0000"); + } + + { + TestCase& test = tests.emplace_back(); + test = TestCase{ + .description = "Packet gets forwarded with an unexpected port.", + .test_vector = ParseProtoOrDie(R"pb( + input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "02:03:04:05:06:07" + ethernet_source: "00:01:02:03:04:05" + ethertype: "0x0888" + } + } + payload: "test packet" + } + } + } + # Acceptable outputs and actual output filled in below. + )pb"), + // Overridden below. + .actual_output = SwitchOutput(), + }; + + // Set expected packet to be forwarded out of port 12. + Packet& acceptable_output = + *test.test_vector.add_acceptable_outputs()->add_packets(); + acceptable_output = test.test_vector.input().packet(); + acceptable_output.set_port("12"); + + // Set actual packet to be forwarded out of port 15. + Packet& actual_output = *test.actual_output.add_packets(); + actual_output = acceptable_output; + actual_output.set_port("15"); + } + + { + TestCase& test = tests.emplace_back(); + test = TestCase{ + .description = "Packet gets punted with wrong metadata.", + .test_vector = ParseProtoOrDie(R"pb( + input { + type: DATAPLANE + packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "02:03:04:05:06:07" + ethernet_source: "00:01:02:03:04:05" + ethertype: "0x0888" + } + } + payload: "test packet" + } + } + } + acceptable_outputs { + packet_ins { + metadata { + name: "ingress_port" + value: { str: "1" } + } + metadata { + name: "target_egress_port" + value: { str: "2" } + } + parsed: {} # Filled in below. + } + } + # Acceptable outputs and actual output filled in below. + )pb"), + // Overridden below. + .actual_output = SwitchOutput(), + }; + + // Complete expected output. + PacketIn& acceptable_output = + *test.test_vector.mutable_acceptable_outputs(0)->mutable_packet_ins(0); + *acceptable_output.mutable_parsed() = + test.test_vector.input().packet().parsed(); + + // Set 'target_egress_port' in actual packet to 3. + PacketIn& actual_output = *test.actual_output.add_packet_ins(); + actual_output = acceptable_output; + actual_output.mutable_metadata(1)->mutable_value()->set_str("3"); + } + + return tests; +} + +void main() { + for (auto& test : TestCases()) { + PacketTestRun test_run; + *test_run.mutable_test_vector() = test.test_vector; + *test_run.mutable_actual_output() = test.actual_output; + PacketTestValidationResult result = ValidateTestRun(test_run); + CHECK(result.has_failure()) // Crash OK: this is test code. + << "for test case with description '" << test.description << "'"; + std::cout << std::string(80, '=') + << "\nValidateTestRun Test: " << test.description << "\n" + << std::string(80, '=') << "\n" + << result.failure().description() << "\n\n"; + } +} + +} // namespace +} // namespace dvaas + +int main() { dvaas::main(); } From 48c330e0159036dc3c07ff9ec5c5a0fad5de1b5e Mon Sep 17 00:00:00 2001 From: VSuryaprasad-hcl <159443973+VSuryaprasad-HCL@users.noreply.github.com> Date: Wed, 27 Nov 2024 23:00:27 +0000 Subject: [PATCH 07/17] [P4_Symbolic] Pull common Z3 operations into util library to make them reusable. Change EvaluateSaiPipeline to take a forwarding pipeline config instead of a SAI Instantiation. (#774) Co-authored-by: kishanps Co-authored-by: kheradmandG --- p4_symbolic/BUILD.bazel | 2 ++ p4_symbolic/parser.cc | 10 +++++++++ p4_symbolic/parser.h | 6 ++++++ p4_symbolic/sai/deparser.cc | 35 +++++++++----------------------- p4_symbolic/sai/deparser_test.cc | 9 ++++---- 5 files changed, 33 insertions(+), 29 deletions(-) diff --git a/p4_symbolic/BUILD.bazel b/p4_symbolic/BUILD.bazel index 6c044033..1f0d54f1 100644 --- a/p4_symbolic/BUILD.bazel +++ b/p4_symbolic/BUILD.bazel @@ -48,12 +48,14 @@ cc_library( "//gutil:io", "//gutil:proto", "//gutil:status", + "//p4_pdpi:ir", "//p4_pdpi:ir_cc_proto", "//p4_symbolic/bmv2", "//p4_symbolic/ir", "//p4_symbolic/ir:ir_cc_proto", "//p4_symbolic/ir:pdpi_driver", "//p4_symbolic/symbolic", + "@com_github_p4lang_p4runtime//:p4runtime_cc_proto", "@com_google_absl//absl/types:span", ], ) diff --git a/p4_symbolic/parser.cc b/p4_symbolic/parser.cc index bf167715..00fa8a19 100644 --- a/p4_symbolic/parser.cc +++ b/p4_symbolic/parser.cc @@ -16,6 +16,8 @@ #include "gutil/io.h" #include "gutil/proto.h" +#include "p4/v1/p4runtime.pb.h" +#include "p4_pdpi/ir.h" #include "p4_symbolic/bmv2/bmv2.h" #include "p4_symbolic/ir/ir.h" #include "p4_symbolic/ir/pdpi_driver.h" @@ -79,4 +81,12 @@ absl::StatusOr ParseToIr( return p4_symbolic::symbolic::Dataplane{program, ir_table_entries}; } +absl::StatusOr ParseToIr( + const p4::v1::ForwardingPipelineConfig &config, + absl::Span table_entries) { + ASSIGN_OR_RETURN(const pdpi::IrP4Info ir_p4info, + pdpi::CreateIrP4Info(config.p4info())); + return ParseToIr(config.p4_device_config(), ir_p4info, table_entries); +} + } // namespace p4_symbolic diff --git a/p4_symbolic/parser.h b/p4_symbolic/parser.h index f1987087..34d286eb 100644 --- a/p4_symbolic/parser.h +++ b/p4_symbolic/parser.h @@ -22,6 +22,7 @@ #include "absl/types/span.h" #include "gutil/status.h" +#include "p4/v1/p4runtime.pb.h" #include "p4_pdpi/ir.pb.h" #include "p4_symbolic/ir/ir.pb.h" #include "p4_symbolic/symbolic/symbolic.h" @@ -35,10 +36,15 @@ absl::StatusOr ParseToIr( absl::StatusOr ParseToIr( const std::string &bmv2_json_path, const std::string &p4info_path, absl::Span table_entries); + absl::StatusOr ParseToIr( const std::string &bmv2_json, const pdpi::IrP4Info &p4info, absl::Span table_entries); +absl::StatusOr ParseToIr( + const p4::v1::ForwardingPipelineConfig &config, + absl::Span table_entries); + } // namespace p4_symbolic #endif // P4_SYMBOLIC_PARSER_H_ diff --git a/p4_symbolic/sai/deparser.cc b/p4_symbolic/sai/deparser.cc index f8699f8b..3bdbc9bb 100644 --- a/p4_symbolic/sai/deparser.cc +++ b/p4_symbolic/sai/deparser.cc @@ -29,28 +29,13 @@ #include "p4_pdpi/string_encodings/hex_string.h" #include "p4_symbolic/sai/fields.h" #include "p4_symbolic/symbolic/symbolic.h" +#include "p4_symbolic/z3_util.h" #include "z3++.h" namespace p4_symbolic { namespace { -absl::StatusOr EvalBool(const z3::expr& bool_expr, - const z3::model& model) { - auto value = model.eval(bool_expr, true).bool_value(); - switch (value) { - case Z3_L_FALSE: - return false; - case Z3_L_TRUE: - return true; - default: - break; - } - return gutil::InternalErrorBuilder() - << "boolean expression '" << bool_expr - << "' evaluated to unexpected Boolean value " << value; -} - template absl::StatusOr> EvalBitvector(const z3::expr& bv_expr, const z3::model& model) { @@ -76,14 +61,14 @@ template absl::Status Deparse(const z3::expr& field, const z3::model& model, pdpi::BitString& result) { ASSIGN_OR_RETURN(std::bitset bits, - EvalBitvector(field, model)); + EvalZ3Bitvector(field, model)); result.AppendBits(bits); return absl::OkStatus(); } absl::Status Deparse(const SaiEthernet& header, const z3::model& model, pdpi::BitString& result) { - ASSIGN_OR_RETURN(bool valid, EvalBool(header.valid, model)); + ASSIGN_OR_RETURN(bool valid, EvalZ3Bool(header.valid, model)); if (valid) { RETURN_IF_ERROR(Deparse<48>(header.dst_addr, model, result)); RETURN_IF_ERROR(Deparse<48>(header.src_addr, model, result)); @@ -94,7 +79,7 @@ absl::Status Deparse(const SaiEthernet& header, const z3::model& model, absl::Status Deparse(const SaiIpv4& header, const z3::model& model, pdpi::BitString& result) { - ASSIGN_OR_RETURN(bool valid, EvalBool(header.valid, model)); + ASSIGN_OR_RETURN(bool valid, EvalZ3Bool(header.valid, model)); if (valid) { RETURN_IF_ERROR(Deparse<4>(header.version, model, result)); RETURN_IF_ERROR(Deparse<4>(header.ihl, model, result)); @@ -117,7 +102,7 @@ absl::Status Deparse(const SaiIpv4& header, const z3::model& model, absl::Status Deparse(const SaiIpv6& header, const z3::model& model, pdpi::BitString& result) { - ASSIGN_OR_RETURN(bool valid, EvalBool(header.valid, model)); + ASSIGN_OR_RETURN(bool valid, EvalZ3Bool(header.valid, model)); if (valid) { RETURN_IF_ERROR(Deparse<4>(header.version, model, result)); RETURN_IF_ERROR(Deparse<6>(header.dscp, model, result)); @@ -134,7 +119,7 @@ absl::Status Deparse(const SaiIpv6& header, const z3::model& model, absl::Status Deparse(const SaiUdp& header, const z3::model& model, pdpi::BitString& result) { - ASSIGN_OR_RETURN(bool valid, EvalBool(header.valid, model)); + ASSIGN_OR_RETURN(bool valid, EvalZ3Bool(header.valid, model)); if (valid) { RETURN_IF_ERROR(Deparse<16>(header.src_port, model, result)); RETURN_IF_ERROR(Deparse<16>(header.dst_port, model, result)); @@ -146,7 +131,7 @@ absl::Status Deparse(const SaiUdp& header, const z3::model& model, absl::Status Deparse(const SaiTcp& header, const z3::model& model, pdpi::BitString& result) { - ASSIGN_OR_RETURN(bool valid, EvalBool(header.valid, model)); + ASSIGN_OR_RETURN(bool valid, EvalZ3Bool(header.valid, model)); if (valid) { RETURN_IF_ERROR(Deparse<16>(header.src_port, model, result)); RETURN_IF_ERROR(Deparse<16>(header.dst_port, model, result)); @@ -164,7 +149,7 @@ absl::Status Deparse(const SaiTcp& header, const z3::model& model, absl::Status Deparse(const SaiIcmp& header, const z3::model& model, pdpi::BitString& result) { - ASSIGN_OR_RETURN(bool valid, EvalBool(header.valid, model)); + ASSIGN_OR_RETURN(bool valid, EvalZ3Bool(header.valid, model)); if (valid) { RETURN_IF_ERROR(Deparse<8>(header.type, model, result)); RETURN_IF_ERROR(Deparse<8>(header.code, model, result)); @@ -178,7 +163,7 @@ absl::Status Deparse(const SaiIcmp& header, const z3::model& model, absl::Status Deparse(const SaiArp& header, const z3::model& model, pdpi::BitString& result) { - ASSIGN_OR_RETURN(bool valid, EvalBool(header.valid, model)); + ASSIGN_OR_RETURN(bool valid, EvalZ3Bool(header.valid, model)); if (valid) { RETURN_IF_ERROR(Deparse<16>(header.hw_type, model, result)); RETURN_IF_ERROR(Deparse<16>(header.proto_type, model, result)); @@ -195,7 +180,7 @@ absl::Status Deparse(const SaiArp& header, const z3::model& model, absl::Status Deparse(const SaiGre& header, const z3::model& model, pdpi::BitString& result) { - ASSIGN_OR_RETURN(bool valid, EvalBool(header.valid, model)); + ASSIGN_OR_RETURN(bool valid, EvalZ3Bool(header.valid, model)); if (valid) { RETURN_IF_ERROR(Deparse<1>(header.checksum_present, model, result)); RETURN_IF_ERROR(Deparse<1>(header.routing_present, model, result)); diff --git a/p4_symbolic/sai/deparser_test.cc b/p4_symbolic/sai/deparser_test.cc index f0270bd5..5d09dc76 100644 --- a/p4_symbolic/sai/deparser_test.cc +++ b/p4_symbolic/sai/deparser_test.cc @@ -33,6 +33,7 @@ #include "p4_symbolic/sai/sai.h" #include "p4_symbolic/symbolic/symbolic.h" #include "sai_p4/instantiations/google/instantiations.h" +#include "sai_p4/instantiations/google/sai_nonstandard_platforms.h" #include "z3++.h" namespace p4_symbolic { @@ -44,10 +45,10 @@ class SaiDeparserTest : public testing::TestWithParam { public: void SetUp() override { testing::TestWithParam::SetUp(); - sai::Instantiation instantiation = GetParam(); - std::vector entries; - std::vector ports; - ASSERT_OK_AND_ASSIGN(state_, EvaluateSaiPipeline(instantiation, entries, ports)); + const auto config = sai::GetNonstandardForwardingPipelineConfig( + /*instantiation=*/GetParam(), sai::NonstandardPlatform::kP4Symbolic); + ASSERT_OK_AND_ASSIGN( + state_, EvaluateSaiPipeline(config, /*entries=*/{}, /*ports=*/{})); } protected: From 51bec4d8ce4daf2e8c93b30e3947d12e4ce7f0c2 Mon Sep 17 00:00:00 2001 From: bibhuprasad-hcl <161687009+bibhuprasad-hcl@users.noreply.github.com> Date: Wed, 27 Nov 2024 23:01:58 +0000 Subject: [PATCH 08/17] [Thinkit] BERT test. Adding instantiation param for watch port tests. (#775) Co-authored-by: smolkaj Co-authored-by: kishanps --- tests/forwarding/watch_port_test.cc | 129 +++++++++++++++------------- tests/forwarding/watch_port_test.h | 6 +- tests/gnoi/bert_tests.cc | 7 +- 3 files changed, 73 insertions(+), 69 deletions(-) diff --git a/tests/forwarding/watch_port_test.cc b/tests/forwarding/watch_port_test.cc index 743e812e..ac292010 100644 --- a/tests/forwarding/watch_port_test.cc +++ b/tests/forwarding/watch_port_test.cc @@ -441,19 +441,21 @@ void WatchPortTestFixture::SetUp() { testbed.ControlSwitch(), gnmi_config, /*timeout=*/absl::Minutes(3))); - ASSERT_OK(testbed.Environment().StoreTestArtifact("p4info.pb.txt", - GetP4Info().DebugString())); + ASSERT_OK(testbed.Environment().StoreTestArtifact( + "p4info.pb.txt", GetParam().p4_info.DebugString())); // Setup SUT & control switch. ASSERT_OK_AND_ASSIGN(sut_p4_session_, pdpi::P4RuntimeSession::CreateWithP4InfoAndClearTables( - testbed.Sut(), GetP4Info())); + testbed.Sut(), GetParam().p4_info)); ASSERT_OK_AND_ASSIGN(control_p4_session_, pdpi::P4RuntimeSession::CreateWithP4InfoAndClearTables( - testbed.ControlSwitch(), GetP4Info())); - ASSERT_OK(SetUpSut(*sut_p4_session_, GetIrP4Info(), kVrfId)); - ASSERT_OK(SetUpControlSwitch(*control_p4_session_, GetIrP4Info())); + testbed.ControlSwitch(), GetParam().p4_info)); + ASSERT_OK_AND_ASSIGN(const pdpi::IrP4Info ir_p4info, + pdpi::CreateIrP4Info(GetParam().p4_info)); + ASSERT_OK(SetUpSut(*sut_p4_session_, ir_p4info, kVrfId)); + ASSERT_OK(SetUpControlSwitch(*control_p4_session_, ir_p4info)); // Create GNMI stub for admin operations. ASSERT_OK_AND_ASSIGN(sut_gnmi_stub_, testbed.Sut().CreateGnmiStub()); @@ -462,12 +464,12 @@ void WatchPortTestFixture::SetUp() { // Start the receiver thread for control switch to listen for packets from // SUT, this thread is terminated in the TearDown. - receive_packet_thread_ = std::thread([&]() { + receive_packet_thread_ = std::thread([&, ir_p4info]() { p4::v1::StreamMessageResponse pi_response; while (control_p4_session_->StreamChannelRead(pi_response)) { absl::MutexLock lock(&test_data_.mutex); sai::StreamMessageResponse pd_response; - ASSERT_OK(pdpi::PiStreamMessageResponseToPd(GetIrP4Info(), pi_response, + ASSERT_OK(pdpi::PiStreamMessageResponseToPd(ir_p4info, pi_response, &pd_response)) << " PacketIn PI to PD failed: "; ASSERT_TRUE(pd_response.has_packet()) @@ -536,15 +538,6 @@ void WatchPortTestFixture::TearDown() { testbed.TearDown(); } -// TODO: Parameterize over the different instantiations like -// MiddleBlock, FBR400. -const p4::config::v1::P4Info& WatchPortTestFixture::GetP4Info() { - return sai::GetP4Info(sai::Instantiation::kMiddleblock); -} -const pdpi::IrP4Info& WatchPortTestFixture::GetIrP4Info() { - return sai::GetIrP4Info(sai::Instantiation::kMiddleblock); -} - namespace { // Verifies basic WCMP behavior by programming a group with multiple members @@ -561,19 +554,21 @@ TEST_P(WatchPortTestFixture, VerifyBasicWcmpPacketDistribution) { CreateGroupMembers(group_size, controller_port_ids)); const int input_port = controller_port_ids[kDefaultInputPortIndex]; - ASSERT_OK(SetUpInputPortForPacketReceive(*sut_p4_session_, GetIrP4Info(), - input_port)); + ASSERT_OK_AND_ASSIGN(const pdpi::IrP4Info ir_p4info, + pdpi::CreateIrP4Info(GetParam().p4_info)); + ASSERT_OK( + SetUpInputPortForPacketReceive(*sut_p4_session_, ir_p4info, input_port)); // Programs the required router interfaces, nexthops for wcmp group. - ASSERT_OK(pins::ProgramNextHops(environment, *sut_p4_session_, GetIrP4Info(), + ASSERT_OK(pins::ProgramNextHops(environment, *sut_p4_session_, ir_p4info, members)); ASSERT_OK(pins::ProgramGroupWithMembers(environment, *sut_p4_session_, - GetIrP4Info(), kGroupId, members, + ir_p4info, kGroupId, members, p4::v1::Update::INSERT)) << "Failed to program WCMP group: "; // Program default routing for all packets on SUT. - ASSERT_OK(ProgramDefaultRoutes(*sut_p4_session_, GetIrP4Info(), kVrfId, + ASSERT_OK(ProgramDefaultRoutes(*sut_p4_session_, ir_p4info, kVrfId, p4::v1::Update::INSERT)); // Generate test configuration, pick any field (IP_SRC) used by hashing to @@ -598,7 +593,7 @@ TEST_P(WatchPortTestFixture, VerifyBasicWcmpPacketDistribution) { // Send 5000 packets and check for packet distribution. ASSERT_OK(SendNPacketsToSut(kNumTestPackets, test_config, members, - controller_port_ids, GetIrP4Info(), + controller_port_ids, ir_p4info, *control_p4_session_, environment)); test_data_.total_packets_sent = kNumTestPackets; @@ -620,7 +615,7 @@ TEST_P(WatchPortTestFixture, VerifyBasicWcmpPacketDistribution) { absl::flat_hash_set expected_member_ports = CreateExpectedMemberPorts(members); - ASSERT_OK(VerifyGroupMembersFromP4Read(*sut_p4_session_, GetIrP4Info(), + ASSERT_OK(VerifyGroupMembersFromP4Read(*sut_p4_session_, ir_p4info, kGroupId, members)); // Verifies the actual members inferred from receive traffic matches the @@ -645,17 +640,19 @@ TEST_P(WatchPortTestFixture, VerifyBasicWatchPortAction) { CreateGroupMembers(group_size, controller_port_ids)); const int input_port = controller_port_ids[kDefaultInputPortIndex]; - ASSERT_OK(SetUpInputPortForPacketReceive(*sut_p4_session_, GetIrP4Info(), - input_port)); + ASSERT_OK_AND_ASSIGN(const pdpi::IrP4Info ir_p4info, + pdpi::CreateIrP4Info(GetParam().p4_info)); + ASSERT_OK( + SetUpInputPortForPacketReceive(*sut_p4_session_, ir_p4info, input_port)); // Programs the required router interfaces, nexthops for wcmp group. - ASSERT_OK(pins::ProgramNextHops(environment, *sut_p4_session_, GetIrP4Info(), + ASSERT_OK(pins::ProgramNextHops(environment, *sut_p4_session_, ir_p4info, members)); ASSERT_OK(pins::ProgramGroupWithMembers(environment, *sut_p4_session_, - GetIrP4Info(), kGroupId, members, + ir_p4info, kGroupId, members, p4::v1::Update::INSERT)); // Program default routing for all packets on SUT. - ASSERT_OK(ProgramDefaultRoutes(*sut_p4_session_, GetIrP4Info(), kVrfId, + ASSERT_OK(ProgramDefaultRoutes(*sut_p4_session_, ir_p4info, kVrfId, p4::v1::Update::INSERT)); // Generate test configuration, pick any field used by hashing to vary for @@ -704,7 +701,7 @@ TEST_P(WatchPortTestFixture, VerifyBasicWatchPortAction) { // Send 5000 packets and check for packet distribution. ASSERT_OK(SendNPacketsToSut(kNumTestPackets, test_config, members, - controller_port_ids, GetIrP4Info(), + controller_port_ids, ir_p4info, *control_p4_session_, environment)); test_data_.total_packets_sent = kNumTestPackets; @@ -732,7 +729,7 @@ TEST_P(WatchPortTestFixture, VerifyBasicWatchPortAction) { expected_member_ports.insert(selected_port_id); } - ASSERT_OK(VerifyGroupMembersFromP4Read(*sut_p4_session_, GetIrP4Info(), + ASSERT_OK(VerifyGroupMembersFromP4Read(*sut_p4_session_, ir_p4info, kGroupId, members)); // Verifies the actual members inferred from receive traffic matches the // expected members. @@ -762,17 +759,19 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionInCriticalState) { CreateGroupMembers(group_size, controller_port_ids)); const int input_port = controller_port_ids[kDefaultInputPortIndex]; - ASSERT_OK(SetUpInputPortForPacketReceive(*sut_p4_session_, GetIrP4Info(), - input_port)); + ASSERT_OK_AND_ASSIGN(const pdpi::IrP4Info ir_p4info, + pdpi::CreateIrP4Info(GetParam().p4_info)); + ASSERT_OK( + SetUpInputPortForPacketReceive(*sut_p4_session_, ir_p4info, input_port)); // Program the required router interfaces, nexthops for wcmp group. - ASSERT_OK(pins::ProgramNextHops(environment, *sut_p4_session_, GetIrP4Info(), + ASSERT_OK(pins::ProgramNextHops(environment, *sut_p4_session_, ir_p4info, members)); ASSERT_OK(pins::ProgramGroupWithMembers(environment, *sut_p4_session_, - GetIrP4Info(), kGroupId, members, + ir_p4info, kGroupId, members, p4::v1::Update::INSERT)); // Program default routing for all packets on SUT. - ASSERT_OK(ProgramDefaultRoutes(*sut_p4_session_, GetIrP4Info(), kVrfId, + ASSERT_OK(ProgramDefaultRoutes(*sut_p4_session_, ir_p4info, kVrfId, p4::v1::Update::INSERT)); // Generate test configuration, pick any field used by hashing to vary for @@ -824,7 +823,7 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionInCriticalState) { // Send 5000 packets and check for packet distribution. ASSERT_OK(SendNPacketsToSut(kNumTestPackets, test_config, members, - controller_port_ids, GetIrP4Info(), + controller_port_ids, ir_p4info, *control_p4_session_, environment)); test_data_.total_packets_sent = kNumTestPackets; @@ -840,7 +839,7 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionInCriticalState) { << " and actual: " << test.output.size() << "packets received for " << DescribeTestConfig(test_config); - ASSERT_OK(VerifyGroupMembersFromP4Read(*sut_p4_session_, GetIrP4Info(), + ASSERT_OK(VerifyGroupMembersFromP4Read(*sut_p4_session_, ir_p4info, kGroupId, members)); // Count the received packets and create the expected_member_ports for admin @@ -873,17 +872,19 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionForSingleMember) { CreateGroupMembers(group_size, controller_port_ids)); const int input_port = controller_port_ids[kDefaultInputPortIndex]; - ASSERT_OK(SetUpInputPortForPacketReceive(*sut_p4_session_, GetIrP4Info(), - input_port)); + ASSERT_OK_AND_ASSIGN(const pdpi::IrP4Info ir_p4info, + pdpi::CreateIrP4Info(GetParam().p4_info)); + ASSERT_OK( + SetUpInputPortForPacketReceive(*sut_p4_session_, ir_p4info, input_port)); // Programs the required router interfaces, nexthops for wcmp group. - ASSERT_OK(pins::ProgramNextHops(environment, *sut_p4_session_, GetIrP4Info(), + ASSERT_OK(pins::ProgramNextHops(environment, *sut_p4_session_, ir_p4info, members)); ASSERT_OK(pins::ProgramGroupWithMembers(environment, *sut_p4_session_, - GetIrP4Info(), kGroupId, members, + ir_p4info, kGroupId, members, p4::v1::Update::INSERT)); // Program default routing for all packets on SUT. - ASSERT_OK(ProgramDefaultRoutes(*sut_p4_session_, GetIrP4Info(), kVrfId, + ASSERT_OK(ProgramDefaultRoutes(*sut_p4_session_, ir_p4info, kVrfId, p4::v1::Update::INSERT)); // Generate test configuration, pick any field used by hashing to vary for @@ -933,7 +934,7 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionForSingleMember) { // Send 5000 packets and check for packet distribution. ASSERT_OK(SendNPacketsToSut(kNumTestPackets, test_config, members, - controller_port_ids, GetIrP4Info(), + controller_port_ids, ir_p4info, *control_p4_session_, environment)); test_data_.total_packets_sent = kNumTestPackets; @@ -963,7 +964,7 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionForSingleMember) { ASSERT_OK_AND_ASSIGN(auto num_packets_per_port, CountNumPacketsPerPort(test.output)); - ASSERT_OK(VerifyGroupMembersFromP4Read(*sut_p4_session_, GetIrP4Info(), + ASSERT_OK(VerifyGroupMembersFromP4Read(*sut_p4_session_, ir_p4info, kGroupId, members)); // Verifies the actual members inferred from receive traffic matches the @@ -989,17 +990,19 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionForMemberModify) { CreateGroupMembers(group_size, controller_port_ids)); const int input_port = controller_port_ids[kDefaultInputPortIndex]; - ASSERT_OK(SetUpInputPortForPacketReceive(*sut_p4_session_, GetIrP4Info(), - input_port)); + ASSERT_OK_AND_ASSIGN(const pdpi::IrP4Info ir_p4info, + pdpi::CreateIrP4Info(GetParam().p4_info)); + ASSERT_OK( + SetUpInputPortForPacketReceive(*sut_p4_session_, ir_p4info, input_port)); // Programs the required router interfaces, nexthops for wcmp group. - ASSERT_OK(pins::ProgramNextHops(environment, *sut_p4_session_, GetIrP4Info(), + ASSERT_OK(pins::ProgramNextHops(environment, *sut_p4_session_, ir_p4info, members)); ASSERT_OK(pins::ProgramGroupWithMembers(environment, *sut_p4_session_, - GetIrP4Info(), kGroupId, members, + ir_p4info, kGroupId, members, p4::v1::Update::INSERT)); // Program default routing for all packets on SUT. - ASSERT_OK(ProgramDefaultRoutes(*sut_p4_session_, GetIrP4Info(), kVrfId, + ASSERT_OK(ProgramDefaultRoutes(*sut_p4_session_, ir_p4info, kVrfId, p4::v1::Update::INSERT)); // Generate test configuration, pick any field used by hashing to vary for @@ -1038,7 +1041,7 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionForMemberModify) { // Send Modify request to remove the down member from the group. members.erase(members.begin() + random_member_index); ASSERT_OK(pins::ProgramGroupWithMembers(environment, *sut_p4_session_, - GetIrP4Info(), kGroupId, members, + ir_p4info, kGroupId, members, p4::v1::Update::MODIFY)); // Bring the down member watch port up. ASSERT_OK(SetInterfaceAdminState(*control_gnmi_stub_, selected_port_name, @@ -1050,7 +1053,7 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionForMemberModify) { // Send 5000 packets and check for packet distribution. ASSERT_OK(SendNPacketsToSut(kNumTestPackets, test_config, members, - controller_port_ids, GetIrP4Info(), + controller_port_ids, ir_p4info, *control_p4_session_, environment)); test_data_.total_packets_sent = kNumTestPackets; @@ -1072,7 +1075,7 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionForMemberModify) { absl::flat_hash_set expected_member_ports = CreateExpectedMemberPorts(members); - ASSERT_OK(VerifyGroupMembersFromP4Read(*sut_p4_session_, GetIrP4Info(), + ASSERT_OK(VerifyGroupMembersFromP4Read(*sut_p4_session_, ir_p4info, kGroupId, members)); // Verifies the actual members inferred from receive traffic matches the @@ -1084,11 +1087,11 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionForMemberModify) { } // Delete default routes to prepare for delete group. - ASSERT_OK(ProgramDefaultRoutes(*sut_p4_session_, GetIrP4Info(), kVrfId, + ASSERT_OK(ProgramDefaultRoutes(*sut_p4_session_, ir_p4info, kVrfId, p4::v1::Update::DELETE)); // Delete group and verify no errors. - ASSERT_OK(DeleteGroup(*sut_p4_session_, GetIrP4Info(), kGroupId)); + ASSERT_OK(DeleteGroup(*sut_p4_session_, ir_p4info, kGroupId)); }; // Add ActionProfileGroup member whose watch port is down (during create) and @@ -1099,8 +1102,10 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionForDownPortMemberInsert) { environment.SetTestCaseID("e54da480-d2cc-42c6-bced-0354b5ab3329"); absl::Span controller_port_ids = GetParam().port_ids; const int input_port = controller_port_ids[kDefaultInputPortIndex]; - ASSERT_OK(SetUpInputPortForPacketReceive(*sut_p4_session_, GetIrP4Info(), - input_port)); + ASSERT_OK_AND_ASSIGN(const pdpi::IrP4Info ir_p4info, + pdpi::CreateIrP4Info(GetParam().p4_info)); + ASSERT_OK( + SetUpInputPortForPacketReceive(*sut_p4_session_, ir_p4info, input_port)); const int group_size = kNumWcmpMembersForTest; ASSERT_OK_AND_ASSIGN(std::vector members, @@ -1120,13 +1125,13 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionForDownPortMemberInsert) { AdminState::kDown)); // Programs the required router interfaces, nexthops for wcmp group. - ASSERT_OK(pins::ProgramNextHops(environment, *sut_p4_session_, GetIrP4Info(), + ASSERT_OK(pins::ProgramNextHops(environment, *sut_p4_session_, ir_p4info, members)); ASSERT_OK(pins::ProgramGroupWithMembers(environment, *sut_p4_session_, - GetIrP4Info(), kGroupId, members, + ir_p4info, kGroupId, members, p4::v1::Update::INSERT)); // Program default routing for all packets on SUT. - ASSERT_OK(ProgramDefaultRoutes(*sut_p4_session_, GetIrP4Info(), kVrfId, + ASSERT_OK(ProgramDefaultRoutes(*sut_p4_session_, ir_p4info, kVrfId, p4::v1::Update::INSERT)); // Generate test configuration, pick any field used by hashing to vary for @@ -1163,7 +1168,7 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionForDownPortMemberInsert) { // Send 5000 packets and check for packet distribution. ASSERT_OK(SendNPacketsToSut(kNumTestPackets, test_config, members, - controller_port_ids, GetIrP4Info(), + controller_port_ids, ir_p4info, *control_p4_session_, environment)); test_data_.total_packets_sent = kNumTestPackets; @@ -1190,7 +1195,7 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionForDownPortMemberInsert) { ASSERT_OK_AND_ASSIGN(auto num_packets_per_port, CountNumPacketsPerPort(test.output)); - ASSERT_OK(VerifyGroupMembersFromP4Read(*sut_p4_session_, GetIrP4Info(), + ASSERT_OK(VerifyGroupMembersFromP4Read(*sut_p4_session_, ir_p4info, kGroupId, members)); // Verifies the actual members inferred from receive traffic matches the // expected members. diff --git a/tests/forwarding/watch_port_test.h b/tests/forwarding/watch_port_test.h index 08570edd..d00d14f9 100644 --- a/tests/forwarding/watch_port_test.h +++ b/tests/forwarding/watch_port_test.h @@ -39,6 +39,8 @@ namespace pins { struct WatchPortTestParams { thinkit::MirrorTestbedInterface* testbed; std::string gnmi_config; + // P4Info to be used based on a specific instantiation. + p4::config::v1::P4Info p4_info; // TODO: Remove port ids from here and derive from gNMI config. std::vector port_ids; // Optional function that raises critical alarm in the system. @@ -57,10 +59,6 @@ class WatchPortTestFixture void TearDown() override; - // Returns the P4Info used by the test, for now just Middleblock. - const p4::config::v1::P4Info& GetP4Info(); - const pdpi::IrP4Info& GetIrP4Info(); - TestData test_data_; std::unique_ptr sut_p4_session_; std::unique_ptr control_p4_session_; diff --git a/tests/gnoi/bert_tests.cc b/tests/gnoi/bert_tests.cc index 33c860c6..5014534c 100644 --- a/tests/gnoi/bert_tests.cc +++ b/tests/gnoi/bert_tests.cc @@ -90,7 +90,7 @@ const std::string BuildPerPortStartBertRequest( key { key: "name" value: '$0' } } } - prbs_polynomial: PRBS_POLYNOMIAL_PRBS23 + prbs_polynomial: PRBS_POLYNOMIAL_PRBS31 test_duration_in_secs: $1 )pb", interface_name, ToInt64Seconds(kTestDuration)); @@ -979,7 +979,7 @@ TEST_P(BertTest, StartBertSucceeds) { grpc::ClientContext result_context; EXPECT_OK(sut_diag_stub_->GetBERTResult(&result_context, result_request_sut, &result_response)); - LOG(INFO) << "Result: " << result_response.ShortDebugString(); + LOG(INFO) << "SUT BERT result: " << result_response.ShortDebugString(); ASSERT_THAT(result_response.per_port_responses(), SizeIs(bert_request_sut.per_port_requests_size())); for (int idx = 0; idx < result_response.per_port_responses_size(); ++idx) { @@ -998,7 +998,8 @@ TEST_P(BertTest, StartBertSucceeds) { ASSERT_OK_AND_ASSIGN( gnoi::diag::GetBERTResultResponse result_response, control_device.GetBERTResult(result_request_control_switch)); - LOG(INFO) << "Result: " << result_response.ShortDebugString(); + LOG(INFO) << "Control switch BERT result: " + << result_response.ShortDebugString(); ASSERT_THAT(result_response.per_port_responses(), SizeIs(bert_request_control_switch.per_port_requests_size())); for (int idx = 0; idx < result_response.per_port_responses_size(); ++idx) { From 84276bb6a63c2b086a70456024ffc7614b2d7885 Mon Sep 17 00:00:00 2001 From: VSuryaprasad-hcl <159443973+VSuryaprasad-HCL@users.noreply.github.com> Date: Wed, 27 Nov 2024 23:02:47 +0000 Subject: [PATCH 09/17] [Dvaas] Compare ports of dvaas::Adding test_run_validation_test expected output to dvaas. (#776) Co-authored-by: kishanps --- dvaas/BUILD.bazel | 7 + .../test_run_validation_test.expected.output | 668 ++++++++++++++++++ 2 files changed, 675 insertions(+) create mode 100644 dvaas/test_run_validation_test.expected.output diff --git a/dvaas/BUILD.bazel b/dvaas/BUILD.bazel index 20ce7c20..5850808e 100644 --- a/dvaas/BUILD.bazel +++ b/dvaas/BUILD.bazel @@ -338,3 +338,10 @@ cc_test( "@com_google_absl//absl/types:optional", ], ) + +cmd_diff_test( + name = "test_run_validation_golden_test", + actual_cmd = "$(execpath :test_run_validation_test_runner)", + expected = ":test_run_validation_test.expected.output", + tools = [":test_run_validation_test_runner"], +) diff --git a/dvaas/test_run_validation_test.expected.output b/dvaas/test_run_validation_test.expected.output new file mode 100644 index 00000000..5fcfd264 --- /dev/null +++ b/dvaas/test_run_validation_test.expected.output @@ -0,0 +1,668 @@ +================================================================================ +ValidateTestRun Test: Packet is expected to be forwarded (out of one +of several acceptable ports), but gets dropped. +================================================================================ +Expected: DATAPLANE packet gets forwarded (1 copies) + Actual: DATAPLANE packet got dropped +- acceptable output #1 has mismatched number of packets (actual: 0 expected: 1) +- acceptable output #2 has mismatched number of packets (actual: 0 expected: 1) +- acceptable output #3 has mismatched number of packets (actual: 0 expected: 1) +- acceptable output #4 has mismatched number of packets (actual: 0 expected: 1) + +Details dumped below. + +== INPUT ======================================================================= +type: DATAPLANE +packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "02:08:02:08:10:40" + ethernet_source: "40:04:10:04:04:20" + ethertype: "0x86dd" + } + } + headers { + ipv6_header { + version: "0x6" + dscp: "0x00" + ecn: "0x0" + flow_label: "0x00000" + payload_length: "0x00ee" + next_header: "0x3a" + hop_limit: "0x80" + ipv6_source: "fe80::" + ipv6_destination: "2002:a05:6860:4f00::" + } + } + headers { + icmp_header { + type: "0x00" + code: "0x00" + checksum: "0x1461" + rest_of_header: "0x00000000" + } + } + payload: "test packet" + } +} +== EXPECTED OUTPUT ============================================================= +-- Acceptable output: Alternative #1 -- +packets { + port: "8" + parsed { + headers { + ethernet_header { + ethernet_destination: "02:08:02:08:10:40" + ethernet_source: "40:04:10:04:04:20" + ethertype: "0x86dd" + } + } + headers { + ipv6_header { + version: "0x6" + dscp: "0x00" + ecn: "0x0" + flow_label: "0x00000" + payload_length: "0x00ee" + next_header: "0x3a" + hop_limit: "0x80" + ipv6_source: "fe80::" + ipv6_destination: "2002:a05:6860:4f00::" + } + } + headers { + icmp_header { + type: "0x00" + code: "0x00" + checksum: "0x1461" + rest_of_header: "0x00000000" + } + } + payload: "test packet" + } +} +-- Acceptable output: Alternative #2 -- +packets { + port: "12" + parsed { + headers { + ethernet_header { + ethernet_destination: "02:08:02:08:10:40" + ethernet_source: "40:04:10:04:04:20" + ethertype: "0x86dd" + } + } + headers { + ipv6_header { + version: "0x6" + dscp: "0x00" + ecn: "0x0" + flow_label: "0x00000" + payload_length: "0x00ee" + next_header: "0x3a" + hop_limit: "0x80" + ipv6_source: "fe80::" + ipv6_destination: "2002:a05:6860:4f00::" + } + } + headers { + icmp_header { + type: "0x00" + code: "0x00" + checksum: "0x1461" + rest_of_header: "0x00000000" + } + } + payload: "test packet" + } +} +-- Acceptable output: Alternative #3 -- +packets { + port: "16" + parsed { + headers { + ethernet_header { + ethernet_destination: "02:08:02:08:10:40" + ethernet_source: "40:04:10:04:04:20" + ethertype: "0x86dd" + } + } + headers { + ipv6_header { + version: "0x6" + dscp: "0x00" + ecn: "0x0" + flow_label: "0x00000" + payload_length: "0x00ee" + next_header: "0x3a" + hop_limit: "0x80" + ipv6_source: "fe80::" + ipv6_destination: "2002:a05:6860:4f00::" + } + } + headers { + icmp_header { + type: "0x00" + code: "0x00" + checksum: "0x1461" + rest_of_header: "0x00000000" + } + } + payload: "test packet" + } +} +-- Acceptable output: Alternative #4 -- +packets { + port: "20" + parsed { + headers { + ethernet_header { + ethernet_destination: "02:08:02:08:10:40" + ethernet_source: "40:04:10:04:04:20" + ethertype: "0x86dd" + } + } + headers { + ipv6_header { + version: "0x6" + dscp: "0x00" + ecn: "0x0" + flow_label: "0x00000" + payload_length: "0x00ee" + next_header: "0x3a" + hop_limit: "0x80" + ipv6_source: "fe80::" + ipv6_destination: "2002:a05:6860:4f00::" + } + } + headers { + icmp_header { + type: "0x00" + code: "0x00" + checksum: "0x1461" + rest_of_header: "0x00000000" + } + } + payload: "test packet" + } +} + + +================================================================================ +ValidateTestRun Test: Submit-to-ingress packet is expected to be +forwarded and mirrored and punted, but doesn't get punted. +================================================================================ +Expected: SUBMIT_TO_INGRESS packet gets forwarded (2 copies) and punted (1 copies) + Actual: SUBMIT_TO_INGRESS packet got forwarded (2 copies) +- acceptable output #1 has mismatched number of packet ins (actual: 0 expected: 1) + +Details dumped below. + +== INPUT ======================================================================= +type: SUBMIT_TO_INGRESS +packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "02:08:02:08:10:40" + ethernet_source: "40:04:10:04:04:20" + ethertype: "0x86dd" + } + } + headers { + ipv6_header { + version: "0x6" + dscp: "0x00" + ecn: "0x0" + flow_label: "0x00000" + payload_length: "0x00ee" + next_header: "0x3a" + hop_limit: "0x80" + ipv6_source: "fe80::" + ipv6_destination: "2002:a05:6860:4f00::" + } + } + headers { + icmp_header { + type: "0x00" + code: "0x00" + checksum: "0x1461" + rest_of_header: "0x00000000" + } + } + payload: "test packet" + } +} +== ACTUAL OUTPUT =============================================================== +packets { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "00:1a:11:17:5f:80" + ethernet_source: "00:02:03:04:05:06" + ethertype: "0x0800" + } + } + headers { + ipv4_header { + version: "0x4" + ihl: "0x5" + dscp: "0x00" + ecn: "0x0" + total_length: "0x0116" + identification: "0x0000" + flags: "0x2" + fragment_offset: "0x0000" + ttl: "0x40" + protocol: "0x2f" + checksum: "0xbe0b" + ipv4_source: "10.206.196.0" + ipv4_destination: "172.20.0.203" + } + } + payload: "\000\000\210\276\002\n\000 \000\000\002*\020\200\000\005\010\000Ex\000\360\000\000\000\000\020\375\323\372\n\000\000\000\n5\300jtest packet" + } +} +packets { + port: "31" + parsed { + headers { + ethernet_header { + ethernet_destination: "00:1a:11:17:5f:80" + ethernet_source: "02:2a:10:00:00:06" + ethertype: "0x0800" + } + } + headers { + ipv4_header { + version: "0x4" + ihl: "0x5" + dscp: "0x1e" + ecn: "0x0" + total_length: "0x00f0" + identification: "0x0000" + flags: "0x0" + fragment_offset: "0x0000" + ttl: "0x0f" + protocol: "0xfd" + checksum: "0xd4fa" + ipv4_source: "10.0.0.0" + ipv4_destination: "10.53.192.106" + } + } + payload: "test packet" + } +} +== EXPECTED OUTPUT ============================================================= +-- Acceptable output: Alternative #1 -- +packets { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "00:1a:11:17:5f:80" + ethernet_source: "00:02:03:04:05:06" + ethertype: "0x0800" + } + } + headers { + ipv4_header { + version: "0x4" + ihl: "0x5" + dscp: "0x00" + ecn: "0x0" + total_length: "0x0116" + identification: "0x0000" + flags: "0x2" + fragment_offset: "0x0000" + ttl: "0x40" + protocol: "0x2f" + checksum: "0xbe0b" + ipv4_source: "10.206.196.0" + ipv4_destination: "172.20.0.203" + } + } + payload: "\000\000\210\276\002\n\000 \000\000\002*\020\200\000\005\010\000Ex\000\360\000\000\000\000\020\375\323\372\n\000\000\000\n5\300jtest packet" + } +} +packets { + port: "31" + parsed { + headers { + ethernet_header { + ethernet_destination: "00:1a:11:17:5f:80" + ethernet_source: "02:2a:10:00:00:06" + ethertype: "0x0800" + } + } + headers { + ipv4_header { + version: "0x4" + ihl: "0x5" + dscp: "0x1e" + ecn: "0x0" + total_length: "0x00f0" + identification: "0x0000" + flags: "0x0" + fragment_offset: "0x0000" + ttl: "0x0f" + protocol: "0xfd" + checksum: "0xd4fa" + ipv4_source: "10.0.0.0" + ipv4_destination: "10.53.192.106" + } + } + payload: "test packet" + } +} +packet_ins { + metadata { + name: "ingress_port" + value { + str: "1" + } + } + metadata { + name: "target_egress_port" + value { + str: "1" + } + } + parsed { + headers { + ethernet_header { + ethernet_destination: "02:0a:00:20:00:00" + ethernet_source: "02:2a:10:80:00:05" + ethertype: "0x0800" + } + } + headers { + ipv4_header { + version: "0x4" + ihl: "0x5" + dscp: "0x1e" + ecn: "0x0" + total_length: "0x00f0" + identification: "0x0000" + flags: "0x0" + fragment_offset: "0x0000" + ttl: "0x10" + protocol: "0xfd" + checksum: "0xd3fa" + ipv4_source: "10.0.0.0" + ipv4_destination: "10.53.192.106" + } + } + payload: "test packet" + } +} + + +================================================================================ +ValidateTestRun Test: Packet gets forwarded with an unexpected +modification of two header fields. +================================================================================ +Expected: DATAPLANE packet gets forwarded (1 copies) + Actual: DATAPLANE packet got forwarded (1 copies), but with unexpected modifications +- acceptable output #1 has packet 0 with mismatched header fields: + modified: headers[1].ipv4_header.dscp: "0x1c" -> "0x00" + modified: headers[1].ipv4_header.checksum: "0x1b62" -> "0x0000" + +Details dumped below. + +== INPUT ======================================================================= +type: DATAPLANE +packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "02:03:04:05:06:07" + ethernet_source: "00:01:02:03:04:05" + ethertype: "0x0800" + } + } + headers { + ipv4_header { + version: "0x4" + ihl: "0x5" + dscp: "0x1c" + ecn: "0x0" + total_length: "0x012e" + identification: "0x0000" + flags: "0x0" + fragment_offset: "0x0000" + ttl: "0x20" + protocol: "0x11" + checksum: "0x1b62" + ipv4_source: "10.0.0.0" + ipv4_destination: "10.206.105.32" + } + } + headers { + udp_header { + source_port: "0x0000" + destination_port: "0x0000" + length: "0x011a" + checksum: "0xad82" + } + } + payload: "test packet" + } +} +== ACTUAL OUTPUT =============================================================== +packets { + port: "12" + parsed { + headers { + ethernet_header { + ethernet_destination: "02:03:04:05:06:07" + ethernet_source: "00:01:02:03:04:05" + ethertype: "0x0800" + } + } + headers { + ipv4_header { + version: "0x4" + ihl: "0x5" + dscp: "0x00" + ecn: "0x0" + total_length: "0x012e" + identification: "0x0000" + flags: "0x0" + fragment_offset: "0x0000" + ttl: "0x20" + protocol: "0x11" + checksum: "0x0000" + ipv4_source: "10.0.0.0" + ipv4_destination: "10.206.105.32" + } + } + headers { + udp_header { + source_port: "0x0000" + destination_port: "0x0000" + length: "0x011a" + checksum: "0xad82" + } + } + payload: "test packet" + } +} +== EXPECTED OUTPUT ============================================================= +-- Acceptable output: Alternative #1 -- +packets { + port: "12" + parsed { + headers { + ethernet_header { + ethernet_destination: "02:03:04:05:06:07" + ethernet_source: "00:01:02:03:04:05" + ethertype: "0x0800" + } + } + headers { + ipv4_header { + version: "0x4" + ihl: "0x5" + dscp: "0x1c" + ecn: "0x0" + total_length: "0x012e" + identification: "0x0000" + flags: "0x0" + fragment_offset: "0x0000" + ttl: "0x20" + protocol: "0x11" + checksum: "0x1b62" + ipv4_source: "10.0.0.0" + ipv4_destination: "10.206.105.32" + } + } + headers { + udp_header { + source_port: "0x0000" + destination_port: "0x0000" + length: "0x011a" + checksum: "0xad82" + } + } + payload: "test packet" + } +} + + +================================================================================ +ValidateTestRun Test: Packet gets forwarded with an unexpected port. +================================================================================ +Expected: DATAPLANE packet gets forwarded (1 copies) + Actual: DATAPLANE packet got forwarded (1 copies), but with unexpected modifications +- acceptable output #1 has packet 0 with mismatched ports: + "12" -> "15" +Details dumped below. + +== INPUT ======================================================================= +type: DATAPLANE +packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "02:03:04:05:06:07" + ethernet_source: "00:01:02:03:04:05" + ethertype: "0x0888" + } + } + payload: "test packet" + } +} +== ACTUAL OUTPUT =============================================================== +packets { + port: "15" + parsed { + headers { + ethernet_header { + ethernet_destination: "02:03:04:05:06:07" + ethernet_source: "00:01:02:03:04:05" + ethertype: "0x0888" + } + } + payload: "test packet" + } +} +== EXPECTED OUTPUT ============================================================= +-- Acceptable output: Alternative #1 -- +packets { + port: "12" + parsed { + headers { + ethernet_header { + ethernet_destination: "02:03:04:05:06:07" + ethernet_source: "00:01:02:03:04:05" + ethertype: "0x0888" + } + } + payload: "test packet" + } +} + + +================================================================================ +ValidateTestRun Test: Packet gets punted with wrong metadata. +================================================================================ +Expected: DATAPLANE packet gets punted (1 copies) + Actual: DATAPLANE packet got punted (1 copies), but with unexpected modifications +- acceptable output #1 has packet in 0 with mismatched value for metadata field 'target_egress_port': + modified: str: "2" -> "3" + +Details dumped below. + +== INPUT ======================================================================= +type: DATAPLANE +packet { + port: "1" + parsed { + headers { + ethernet_header { + ethernet_destination: "02:03:04:05:06:07" + ethernet_source: "00:01:02:03:04:05" + ethertype: "0x0888" + } + } + payload: "test packet" + } +} +== ACTUAL OUTPUT =============================================================== +packet_ins { + metadata { + name: "ingress_port" + value { + str: "1" + } + } + metadata { + name: "target_egress_port" + value { + str: "3" + } + } + parsed { + headers { + ethernet_header { + ethernet_destination: "02:03:04:05:06:07" + ethernet_source: "00:01:02:03:04:05" + ethertype: "0x0888" + } + } + payload: "test packet" + } +} +== EXPECTED OUTPUT ============================================================= +-- Acceptable output: Alternative #1 -- +packet_ins { + metadata { + name: "ingress_port" + value { + str: "1" + } + } + metadata { + name: "target_egress_port" + value { + str: "2" + } + } + parsed { + headers { + ethernet_header { + ethernet_destination: "02:03:04:05:06:07" + ethernet_source: "00:01:02:03:04:05" + ethertype: "0x0888" + } + } + payload: "test packet" + } +} From e488658183e9e844133b4dba8f992f57d098d301 Mon Sep 17 00:00:00 2001 From: VSuryaprasad-hcl <159443973+VSuryaprasad-HCL@users.noreply.github.com> Date: Wed, 27 Nov 2024 23:03:25 +0000 Subject: [PATCH 10/17] [P4_Symbolic] Adding p4_symbolic/ir/expected/default_transition.txt [Extend IR proto and translation to support parsers.] (#778) Co-authored-by: kishanps Co-authored-by: kheradmandG --- .../ir/expected/default_transition.txt | 200 ++++++++++++++++++ .../parser/extract_parser_operation.p4 | 60 ++++++ .../testdata/parser/set_parser_operation.p4 | 78 +++++++ 3 files changed, 338 insertions(+) create mode 100644 p4_symbolic/ir/expected/default_transition.txt create mode 100644 p4_symbolic/testdata/parser/extract_parser_operation.p4 create mode 100644 p4_symbolic/testdata/parser/set_parser_operation.p4 diff --git a/p4_symbolic/ir/expected/default_transition.txt b/p4_symbolic/ir/expected/default_transition.txt new file mode 100644 index 00000000..7cb24ed3 --- /dev/null +++ b/p4_symbolic/ir/expected/default_transition.txt @@ -0,0 +1,200 @@ +headers { + key: "ethernet" + value { + name: "ethernet_t" + id: 2 + fields { + key: "dst_addr" + value { + name: "dst_addr" + bitwidth: 48 + } + } + fields { + key: "ether_type" + value { + name: "ether_type" + bitwidth: 16 + } + } + fields { + key: "src_addr" + value { + name: "src_addr" + bitwidth: 48 + } + } + } +} +headers { + key: "scalars" + value { + name: "scalars_0" + } +} +headers { + key: "standard_metadata" + value { + name: "standard_metadata" + id: 1 + fields { + key: "_padding" + value { + name: "_padding" + bitwidth: 3 + } + } + fields { + key: "checksum_error" + value { + name: "checksum_error" + bitwidth: 1 + } + } + fields { + key: "deq_qdepth" + value { + name: "deq_qdepth" + bitwidth: 19 + } + } + fields { + key: "deq_timedelta" + value { + name: "deq_timedelta" + bitwidth: 32 + } + } + fields { + key: "egress_global_timestamp" + value { + name: "egress_global_timestamp" + bitwidth: 48 + } + } + fields { + key: "egress_port" + value { + name: "egress_port" + bitwidth: 9 + } + } + fields { + key: "egress_rid" + value { + name: "egress_rid" + bitwidth: 16 + } + } + fields { + key: "egress_spec" + value { + name: "egress_spec" + bitwidth: 9 + } + } + fields { + key: "enq_qdepth" + value { + name: "enq_qdepth" + bitwidth: 19 + } + } + fields { + key: "enq_timestamp" + value { + name: "enq_timestamp" + bitwidth: 32 + } + } + fields { + key: "ingress_global_timestamp" + value { + name: "ingress_global_timestamp" + bitwidth: 48 + } + } + fields { + key: "ingress_port" + value { + name: "ingress_port" + bitwidth: 9 + } + } + fields { + key: "instance_type" + value { + name: "instance_type" + bitwidth: 32 + } + } + fields { + key: "mcast_grp" + value { + name: "mcast_grp" + bitwidth: 16 + } + } + fields { + key: "packet_length" + value { + name: "packet_length" + bitwidth: 32 + } + } + fields { + key: "parser_error" + value { + name: "parser_error" + bitwidth: 32 + } + } + fields { + key: "priority" + value { + name: "priority" + bitwidth: 3 + } + } + } +} +pipeline { + key: "egress" + value { + name: "egress" + initial_control: "__END_OF_PIPELINE__" + } +} +pipeline { + key: "ingress" + value { + name: "ingress" + initial_control: "__END_OF_PIPELINE__" + } +} +parsers { + key: "parser" + value { + name: "parser" + initial_state: "start" + parse_states { + key: "start" + value { + name: "start" + parser_ops { + extract { + header { + header_name: "ethernet" + } + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + } +} + diff --git a/p4_symbolic/testdata/parser/extract_parser_operation.p4 b/p4_symbolic/testdata/parser/extract_parser_operation.p4 new file mode 100644 index 00000000..cd7e1374 --- /dev/null +++ b/p4_symbolic/testdata/parser/extract_parser_operation.p4 @@ -0,0 +1,60 @@ +#include +#include "../common/headers.p4" + +struct local_metadata_t { + /* empty */ +} + +struct headers_t { + ethernet_t ethernet; +} + +parser packet_parser(packet_in packet, out headers_t headers, + inout local_metadata_t local_metadata, + inout standard_metadata_t standard_metadata) { + state start { + transition parse_ethernet; + } + + state parse_ethernet { + packet.extract(headers.ethernet); + transition accept; + } +} + +control empty_verify_checksum(inout headers_t headers, + inout local_metadata_t local_metadata) { + apply {} +} // control empty_verify_checksum + +control ingress(inout headers_t headers, + inout local_metadata_t local_metadata, + inout standard_metadata_t standard_metadata) { + apply {} +} // control ingress + +control egress(inout headers_t headers, + inout local_metadata_t local_metadata, + inout standard_metadata_t standard_metadata) { + apply {} +} // control egress + +control empty_compute_checksum(inout headers_t headers, + inout local_metadata_t local_metadata) { + apply {} +} // control empty_compute_checksum + +control packet_deparser(packet_out packet, in headers_t headers) { + apply { + packet.emit(headers.ethernet); + } +} // control packet_deparser + +V1Switch( + packet_parser(), + empty_verify_checksum(), + ingress(), + egress(), + empty_compute_checksum(), + packet_deparser() +) main; diff --git a/p4_symbolic/testdata/parser/set_parser_operation.p4 b/p4_symbolic/testdata/parser/set_parser_operation.p4 new file mode 100644 index 00000000..76e5e2ed --- /dev/null +++ b/p4_symbolic/testdata/parser/set_parser_operation.p4 @@ -0,0 +1,78 @@ +#include +#include "../common/headers.p4" + +struct local_metadata_t { + ethernet_addr_t dst_mac; + ethernet_addr_t src_mac; + ether_type_t ether_type; + int<16> signed_integer1; + int<16> signed_integer2; +} + +struct headers_t { + ethernet_t ethernet; + ipv4_t ipv4; +} + +parser packet_parser(packet_in packet, out headers_t headers, + inout local_metadata_t local_metadata, + inout standard_metadata_t standard_metadata) { + state start { + transition parse_ethernet; + } + + state parse_ethernet { + local_metadata.ether_type = packet.lookahead(); + local_metadata.signed_integer1 = -0x01; + local_metadata.signed_integer2 = 0x02; + packet.extract(headers.ethernet); + local_metadata.dst_mac = headers.ethernet.dst_addr; + local_metadata.src_mac = ((headers.ethernet.src_addr & 48w0xFFFFFFFFFF00)); + transition select(local_metadata.ether_type) { + ETHERTYPE_IPV4: parse_ipv4; + default: accept; + } + } + + state parse_ipv4 { + packet.extract(headers.ipv4); + transition accept; + } +} + +control empty_verify_checksum(inout headers_t headers, + inout local_metadata_t local_metadata) { + apply {} +} // control empty_verify_checksum + +control ingress(inout headers_t headers, + inout local_metadata_t local_metadata, + inout standard_metadata_t standard_metadata) { + apply {} +} // control ingress + +control egress(inout headers_t headers, + inout local_metadata_t local_metadata, + inout standard_metadata_t standard_metadata) { + apply {} +} // control egress + +control empty_compute_checksum(inout headers_t headers, + inout local_metadata_t local_metadata) { + apply {} +} // control empty_compute_checksum + +control packet_deparser(packet_out packet, in headers_t headers) { + apply { + packet.emit(headers.ethernet); + } +} // control packet_deparser + +V1Switch( + packet_parser(), + empty_verify_checksum(), + ingress(), + egress(), + empty_compute_checksum(), + packet_deparser() +) main; From 456074cfb3e6804f72c456f47695b6a963f6ede5 Mon Sep 17 00:00:00 2001 From: bibhuprasad-hcl <161687009+bibhuprasad-hcl@users.noreply.github.com> Date: Wed, 27 Nov 2024 23:05:12 +0000 Subject: [PATCH 11/17] [Thinkit] Remove ingress RIF requirement on input traffic port. (#779) Co-authored-by: smolkaj Co-authored-by: kishanps --- tests/forwarding/watch_port_test.cc | 58 +---------------------------- 1 file changed, 2 insertions(+), 56 deletions(-) diff --git a/tests/forwarding/watch_port_test.cc b/tests/forwarding/watch_port_test.cc index ac292010..eb55cee4 100644 --- a/tests/forwarding/watch_port_test.cc +++ b/tests/forwarding/watch_port_test.cc @@ -104,37 +104,6 @@ constexpr int kNumTestPackets = 5000; // arrive. constexpr int kDefaultInputPortIndex = 0; -// Helper function that sets up the input port for packet recieve. -// Creates the router interface for the input port. Without this input packets -// get dropped (b/190736007). -absl::Status SetUpInputPortForPacketReceive(pdpi::P4RuntimeSession& p4_session, - const pdpi::IrP4Info& ir_p4info, - int input_port) { - ASSIGN_OR_RETURN( - p4::v1::WriteRequest write_request, - pdpi::PdWriteRequestToPi( - ir_p4info, gutil::ParseProtoOrDie(absl::Substitute( - R"pb( - updates { - type: INSERT - table_entry { - router_interface_table_entry { - match { router_interface_id: "$0" } - action { - set_port_and_src_mac { - port: "$1" - src_mac: "00:02:03:04:05:06" - } - } - } - } - } - )pb", - input_port, input_port)))); - - return pdpi::SetMetadataAndSendPiWriteRequest(&p4_session, write_request); -} - // Helper function that creates/deletes V4, V6 default route entries. absl::Status ProgramDefaultRoutes(pdpi::P4RuntimeSession& p4_session, const pdpi::IrP4Info& ir_p4info, @@ -552,12 +521,8 @@ TEST_P(WatchPortTestFixture, VerifyBasicWcmpPacketDistribution) { const int group_size = kNumWcmpMembersForTest; ASSERT_OK_AND_ASSIGN(std::vector members, CreateGroupMembers(group_size, controller_port_ids)); - - const int input_port = controller_port_ids[kDefaultInputPortIndex]; ASSERT_OK_AND_ASSIGN(const pdpi::IrP4Info ir_p4info, pdpi::CreateIrP4Info(GetParam().p4_info)); - ASSERT_OK( - SetUpInputPortForPacketReceive(*sut_p4_session_, ir_p4info, input_port)); // Programs the required router interfaces, nexthops for wcmp group. ASSERT_OK(pins::ProgramNextHops(environment, *sut_p4_session_, ir_p4info, @@ -638,12 +603,8 @@ TEST_P(WatchPortTestFixture, VerifyBasicWatchPortAction) { const int group_size = kNumWcmpMembersForTest; ASSERT_OK_AND_ASSIGN(std::vector members, CreateGroupMembers(group_size, controller_port_ids)); - - const int input_port = controller_port_ids[kDefaultInputPortIndex]; ASSERT_OK_AND_ASSIGN(const pdpi::IrP4Info ir_p4info, pdpi::CreateIrP4Info(GetParam().p4_info)); - ASSERT_OK( - SetUpInputPortForPacketReceive(*sut_p4_session_, ir_p4info, input_port)); // Programs the required router interfaces, nexthops for wcmp group. ASSERT_OK(pins::ProgramNextHops(environment, *sut_p4_session_, ir_p4info, @@ -757,12 +718,8 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionInCriticalState) { const int group_size = kNumWcmpMembersForTest; ASSERT_OK_AND_ASSIGN(std::vector members, CreateGroupMembers(group_size, controller_port_ids)); - - const int input_port = controller_port_ids[kDefaultInputPortIndex]; ASSERT_OK_AND_ASSIGN(const pdpi::IrP4Info ir_p4info, pdpi::CreateIrP4Info(GetParam().p4_info)); - ASSERT_OK( - SetUpInputPortForPacketReceive(*sut_p4_session_, ir_p4info, input_port)); // Program the required router interfaces, nexthops for wcmp group. ASSERT_OK(pins::ProgramNextHops(environment, *sut_p4_session_, ir_p4info, @@ -870,12 +827,8 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionForSingleMember) { const int group_size = 1; ASSERT_OK_AND_ASSIGN(std::vector members, CreateGroupMembers(group_size, controller_port_ids)); - - const int input_port = controller_port_ids[kDefaultInputPortIndex]; ASSERT_OK_AND_ASSIGN(const pdpi::IrP4Info ir_p4info, pdpi::CreateIrP4Info(GetParam().p4_info)); - ASSERT_OK( - SetUpInputPortForPacketReceive(*sut_p4_session_, ir_p4info, input_port)); // Programs the required router interfaces, nexthops for wcmp group. ASSERT_OK(pins::ProgramNextHops(environment, *sut_p4_session_, ir_p4info, @@ -988,12 +941,8 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionForMemberModify) { const int group_size = kNumWcmpMembersForTest; ASSERT_OK_AND_ASSIGN(std::vector members, CreateGroupMembers(group_size, controller_port_ids)); - - const int input_port = controller_port_ids[kDefaultInputPortIndex]; ASSERT_OK_AND_ASSIGN(const pdpi::IrP4Info ir_p4info, pdpi::CreateIrP4Info(GetParam().p4_info)); - ASSERT_OK( - SetUpInputPortForPacketReceive(*sut_p4_session_, ir_p4info, input_port)); // Programs the required router interfaces, nexthops for wcmp group. ASSERT_OK(pins::ProgramNextHops(environment, *sut_p4_session_, ir_p4info, @@ -1101,11 +1050,6 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionForDownPortMemberInsert) { GetParam().testbed->GetMirrorTestbed().Environment(); environment.SetTestCaseID("e54da480-d2cc-42c6-bced-0354b5ab3329"); absl::Span controller_port_ids = GetParam().port_ids; - const int input_port = controller_port_ids[kDefaultInputPortIndex]; - ASSERT_OK_AND_ASSIGN(const pdpi::IrP4Info ir_p4info, - pdpi::CreateIrP4Info(GetParam().p4_info)); - ASSERT_OK( - SetUpInputPortForPacketReceive(*sut_p4_session_, ir_p4info, input_port)); const int group_size = kNumWcmpMembersForTest; ASSERT_OK_AND_ASSIGN(std::vector members, @@ -1125,6 +1069,8 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionForDownPortMemberInsert) { AdminState::kDown)); // Programs the required router interfaces, nexthops for wcmp group. + ASSERT_OK_AND_ASSIGN(const pdpi::IrP4Info ir_p4info, + pdpi::CreateIrP4Info(GetParam().p4_info)); ASSERT_OK(pins::ProgramNextHops(environment, *sut_p4_session_, ir_p4info, members)); ASSERT_OK(pins::ProgramGroupWithMembers(environment, *sut_p4_session_, From cbeceb26badcdac159f4ee45a155ece416b3be76 Mon Sep 17 00:00:00 2001 From: VSuryaprasad-hcl <159443973+VSuryaprasad-HCL@users.noreply.github.com> Date: Wed, 27 Nov 2024 23:05:55 +0000 Subject: [PATCH 12/17] [Dvaas] Fix bug where sut p4info is used to translate control switch packet ins (#780) Co-authored-by: kishanps --- dvaas/BUILD.bazel | 14 ++++- dvaas/arriba_test_vector_validation.cc | 23 +++++--- dvaas/packet_injection.cc | 43 +++++++++++---- dvaas/packet_injection.h | 22 +++++--- dvaas/port_id_map.cc | 75 ++++++++++++++++++++++++++ dvaas/port_id_map.h | 9 ++++ 6 files changed, 161 insertions(+), 25 deletions(-) diff --git a/dvaas/BUILD.bazel b/dvaas/BUILD.bazel index 5850808e..3bbbf0b0 100644 --- a/dvaas/BUILD.bazel +++ b/dvaas/BUILD.bazel @@ -52,23 +52,25 @@ cc_library( srcs = ["packet_injection.cc"], hdrs = ["packet_injection.h"], deps = [ + ":port_id_map", ":test_vector", ":test_vector_cc_proto", "//gutil:status", + "//lib/p4rt:p4rt_port", "//p4_pdpi:ir", + "//p4_pdpi:ir_cc_proto", "//p4_pdpi:p4_runtime_session", "//p4_pdpi/packetlib", "//p4_pdpi/packetlib:packetlib_cc_proto", "//tests/forwarding:util", "@com_github_p4lang_p4runtime//:p4runtime_cc_proto", "@com_google_absl//absl/container:btree", - "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", + "@com_google_absl//absl/time", ], ) - cc_library( name = "test_run_validation", srcs = ["test_run_validation.cc"], @@ -101,6 +103,7 @@ cc_library( hdrs = ["arriba_test_vector_validation.h"], deps = [ ":packet_injection", + ":port_id_map", ":test_run_validation", ":test_vector", ":test_vector_cc_proto", @@ -111,6 +114,7 @@ cc_library( "//p4_pdpi:p4_runtime_session_extras", "//sai_p4/instantiations/google/test_tools:test_entries", "//thinkit:mirror_testbed", + "@com_github_google_glog//:glog", "@com_github_p4lang_p4runtime//:p4runtime_cc_proto", "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/status", @@ -193,16 +197,22 @@ cc_library( hdrs = ["port_id_map.h"], deps = [ "//gutil:status", + "//gutil:test_artifact_writer", + "//lib/gnmi:gnmi_helper", "//lib/p4rt:p4rt_port", "@com_github_gnmi//proto/gnmi:gnmi_cc_grpc_proto", + "@com_google_absl//absl/algorithm:container", + "@com_google_absl//absl/container:btree", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", + "@com_google_absl//absl/strings:str_format", ], ) + cc_test( name = "port_id_map_test", srcs = ["port_id_map_test.cc"], diff --git a/dvaas/arriba_test_vector_validation.cc b/dvaas/arriba_test_vector_validation.cc index b9e69224..f27bd914 100644 --- a/dvaas/arriba_test_vector_validation.cc +++ b/dvaas/arriba_test_vector_validation.cc @@ -19,9 +19,11 @@ #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "dvaas/packet_injection.h" +#include "dvaas/port_id_map.h" #include "dvaas/test_run_validation.h" #include "dvaas/test_vector.h" #include "dvaas/test_vector.pb.h" +#include "glog/logging.h" #include "gutil/status.h" #include "gutil/test_artifact_writer.h" #include "p4/v1/p4runtime.pb.h" @@ -37,7 +39,8 @@ absl::Status ValidateAgaistArribaTestVector( pdpi::P4RuntimeSession& sut, pdpi::P4RuntimeSession& control_switch, const ArribaTestVector& arriba_test_vector, const ArribaTestVectorValidationParams& params) { - // Prepare control switch. + // Prepare the control switch. + LOG(INFO) << "Installing entires to punt all packets on the control switch"; ASSIGN_OR_RETURN(p4::v1::GetForwardingPipelineConfigResponse config, GetForwardingPipelineConfig(&control_switch)); ASSIGN_OR_RETURN(pdpi::IrP4Info ir_p4info, @@ -50,7 +53,8 @@ absl::Status ValidateAgaistArribaTestVector( RETURN_IF_ERROR(pdpi::ClearTableEntries(&control_switch)); RETURN_IF_ERROR(pdpi::InstallPiEntities(control_switch, punt_entities)); - // Prepare SUT. + // Prepare the SUT. + LOG(INFO) << "Installing entries from the given test vector on the SUT"; RETURN_IF_ERROR(pdpi::ClearTableEntries(&sut)); RETURN_IF_ERROR( pdpi::InstallIrTableEntries(sut, arriba_test_vector.ir_table_entries())); @@ -66,11 +70,16 @@ absl::Status ValidateAgaistArribaTestVector( gutil::BazelTestArtifactWriter artifact_writer; // Send tests to switch and collect results. - ASSIGN_OR_RETURN( - PacketTestRuns test_runs, - SendTestPacketsAndCollectOutputs(sut, control_switch, test_vector_by_id, - packet_statistics, - params.max_packets_to_send_per_second)); + ASSIGN_OR_RETURN(PacketTestRuns test_runs, + SendTestPacketsAndCollectOutputs( + sut, control_switch, test_vector_by_id, + { + .max_packets_to_send_per_second = + params.max_packets_to_send_per_second, + .mirror_testbed_port_map = + MirrorTestbedP4rtPortIdMap::CreateIdentityMap(), + }, + packet_statistics)); // Compare the switch output with expected output for each test vector. return ValidateTestRuns(test_runs, params.switch_output_diff_params, diff --git a/dvaas/packet_injection.cc b/dvaas/packet_injection.cc index 5c88c40f..d108caac 100644 --- a/dvaas/packet_injection.cc +++ b/dvaas/packet_injection.cc @@ -14,14 +14,20 @@ #include "dvaas/packet_injection.h" +#include +#include #include #include "absl/container/btree_map.h" +#include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/escaping.h" +#include "absl/time/time.h" +#include "dvaas/port_id_map.h" #include "dvaas/test_vector.h" #include "dvaas/test_vector.pb.h" #include "gutil/status.h" +#include "lib/p4rt/p4rt_port.h" #include "p4/v1/p4runtime.pb.h" #include "p4_pdpi/ir.h" #include "p4_pdpi/p4_runtime_session.h" @@ -32,6 +38,8 @@ namespace dvaas { namespace { +using pins_test::P4rtPortId; + // Utils. // Reads P4Info from the `device` and convert it to IrP4Info. absl::StatusOr GetIrP4Info( @@ -95,6 +103,20 @@ CollectStreamMessageResponsesAndReturnTaggedPacketIns( return tagged_packet_ins; } +// Returns the SUT egress port corresponding to the punted packet on control +// switch given the `mirror_testbed_port_map`. +absl::StatusOr GetSutEgressPortFromControlSwitchPacketIn( + const pdpi::IrPacketIn& packet_in, + const MirrorTestbedP4rtPortIdMap& mirror_testbed_port_map) { + ASSIGN_OR_RETURN(const std::string control_switch_ingress_port_p4rt_encoding, + GetIngressPortFromIrPacketIn(packet_in)); + ASSIGN_OR_RETURN(const P4rtPortId control_switch_ingress_port, + P4rtPortId::MakeFromP4rtEncoding( + control_switch_ingress_port_p4rt_encoding)); + return mirror_testbed_port_map.GetSutPortConnectedToControlSwitchPort( + control_switch_ingress_port); +} + } // namespace absl::StatusOr GetIngressPortFromIrPacketIn( @@ -109,10 +131,7 @@ absl::StatusOr GetIngressPortFromIrPacketIn( absl::StatusOr SendTestPacketsAndCollectOutputs( pdpi::P4RuntimeSession& sut, pdpi::P4RuntimeSession& control_switch, const PacketTestVectorById& packet_test_vector_by_id, - PacketStatistics& statistics, - std::optional max_packets_to_send_per_second, - const IsExpectedUnsolicitedPacketFunctionType& - is_expected_unsolicited_packet) { + const PacketInjectionParams& parameters, PacketStatistics& statistics) { LOG(INFO) << "Injecting test packets into the dataplane " << packet_test_vector_by_id.size(); statistics.total_packets_injected += packet_test_vector_by_id.size(); @@ -124,8 +143,9 @@ absl::StatusOr SendTestPacketsAndCollectOutputs( // Compute per packet injection delay. std::optional injection_delay; - if (max_packets_to_send_per_second.has_value()) { - injection_delay = absl::Milliseconds(1e3 / *max_packets_to_send_per_second); + if (parameters.max_packets_to_send_per_second.has_value()) { + injection_delay = + absl::Milliseconds(1e3 / *parameters.max_packets_to_send_per_second); } // Send packets. @@ -149,7 +169,8 @@ absl::StatusOr SendTestPacketsAndCollectOutputs( const absl::Duration kCollectionDuration = absl::Seconds(3); absl::StatusOr> control_packet_ins = CollectStreamMessageResponsesAndReturnTaggedPacketIns( - control_switch, kCollectionDuration, is_expected_unsolicited_packet); + control_switch, kCollectionDuration, + parameters.is_expected_unsolicited_packet); RETURN_IF_ERROR(control_packet_ins.status()) << "while collecting the output of control_switch"; LOG(INFO) << "Collected " << control_packet_ins->size() @@ -158,7 +179,7 @@ absl::StatusOr SendTestPacketsAndCollectOutputs( absl::StatusOr> sut_packet_ins = CollectStreamMessageResponsesAndReturnTaggedPacketIns( - sut, kCollectionDuration, is_expected_unsolicited_packet); + sut, kCollectionDuration, parameters.is_expected_unsolicited_packet); RETURN_IF_ERROR(sut_packet_ins.status()) << "while collecting the output of SUT"; LOG(INFO) << "Collected " << sut_packet_ins->size() @@ -181,8 +202,10 @@ absl::StatusOr SendTestPacketsAndCollectOutputs( ASSIGN_OR_RETURN( pdpi::IrPacketIn ir_packet_in, pdpi::PiPacketInToIr(control_ir_p4info, packet_in.packet_in)); - ASSIGN_OR_RETURN(*forwarded_output.mutable_port(), - GetIngressPortFromIrPacketIn(ir_packet_in)); + ASSIGN_OR_RETURN(const P4rtPortId sut_egress_port, + GetSutEgressPortFromControlSwitchPacketIn( + ir_packet_in, parameters.mirror_testbed_port_map)); + *forwarded_output.mutable_port() = sut_egress_port.GetP4rtEncoding(); } // Processing the output of SUT. diff --git a/dvaas/packet_injection.h b/dvaas/packet_injection.h index 9bea129f..3c398be5 100644 --- a/dvaas/packet_injection.h +++ b/dvaas/packet_injection.h @@ -18,10 +18,9 @@ #include #include #include -#include -#include "absl/container/flat_hash_set.h" #include "absl/status/statusor.h" +#include "dvaas/port_id_map.h" #include "dvaas/test_vector.h" #include "dvaas/test_vector.pb.h" #include "p4_pdpi/ir.pb.h" @@ -72,6 +71,20 @@ inline bool DefaultIsExpectedUnsolicitedPacket( absl::StatusOr GetIngressPortFromIrPacketIn( const pdpi::IrPacketIn& packet_in); +struct PacketInjectionParams { + // Max number of packets to be injected per second. If null, there will be no + // rate limit for packet injection. + std::optional max_packets_to_send_per_second; + // For a packet in from SUT or control switch without a test tag (i.e. an + // "unsolicited packet"), if this function return false, packet injection + // fails immediately. + const IsExpectedUnsolicitedPacketFunctionType is_expected_unsolicited_packet = + DefaultIsExpectedUnsolicitedPacket; + // The mapping of P4RT port IDs for connected interfaces between SUT and the + // control switch. + MirrorTestbedP4rtPortIdMap mirror_testbed_port_map; +}; + // Determines the switch's behavior when receiving test packets by: // - Injecting those packets to the control switch egress to send to the SUT. // - Determining the set of packets that were forwarded (punted from control @@ -79,10 +92,7 @@ absl::StatusOr GetIngressPortFromIrPacketIn( absl::StatusOr SendTestPacketsAndCollectOutputs( pdpi::P4RuntimeSession& sut, pdpi::P4RuntimeSession& control_switch, const PacketTestVectorById& packet_test_vector_by_id, - PacketStatistics& statistics, - std::optional max_packets_to_send_per_second, - const IsExpectedUnsolicitedPacketFunctionType& - is_expected_unsolicited_packet = DefaultIsExpectedUnsolicitedPacket); + const PacketInjectionParams& parameters, PacketStatistics& statistics); } // namespace dvaas diff --git a/dvaas/port_id_map.cc b/dvaas/port_id_map.cc index 54abecbf..0ca38f43 100644 --- a/dvaas/port_id_map.cc +++ b/dvaas/port_id_map.cc @@ -14,13 +14,24 @@ #include "dvaas/port_id_map.h" +#include +#include + +#include "absl/algorithm/container.h" +#include "absl/container/btree_set.h" #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" #include "absl/status/status.h" #include "absl/status/statusor.h" +#include "absl/strings/str_format.h" +#include "absl/strings/str_join.h" +#include "absl/strings/string_view.h" #include "absl/strings/substitute.h" #include "gutil/status.h" +#include "gutil/test_artifact_writer.h" +#include "lib/gnmi/gnmi_helper.h" #include "lib/p4rt/p4rt_port.h" +#include "proto/gnmi/gnmi.grpc.pb.h" namespace dvaas { @@ -82,4 +93,68 @@ MirrorTestbedP4rtPortIdMap::GetSutPortConnectedToControlSwitchPort( } } +absl::Status CheckAndStoreMappedAndUnmappedPortIds( + const MirrorTestbedP4rtPortIdMap& port_id_map, + gnmi::gNMI::StubInterface& sut, gnmi::gNMI::StubInterface& control_switch, + gutil::TestArtifactWriter& writer) { + // Get all sut ports and control switch ports. + auto match_all_predicate = [](auto) { return true; }; + ASSIGN_OR_RETURN(std::vector all_sut_ports, + pins_test::GetMatchingP4rtPortIds(sut, match_all_predicate)); + ASSIGN_OR_RETURN( + std::vector all_control_ports, + pins_test::GetMatchingP4rtPortIds(control_switch, match_all_predicate)); + + absl::btree_set unmapped_sut_ports( + all_sut_ports.begin(), all_sut_ports.end()); + absl::btree_set unmapped_control_ports( + all_control_ports.begin(), all_control_ports.end()); + + // Collect port mappings in the artifact string. + std::string artifact_string = "Control <-> SUT"; + for (const pins_test::P4rtPortId& control_port : all_control_ports) { + auto sut_port = + port_id_map.GetSutPortConnectedToControlSwitchPort(control_port); + if (!sut_port.ok()) continue; + // The port is mapped. + // Ensure that it is mapped to an existing port. + if (!unmapped_sut_ports.contains(*sut_port)) { + if (absl::c_find(all_sut_ports, *sut_port) != all_sut_ports.end()) { + // Two control ports are mapped to the same SUT port. That should never + // happen based on an invariant of the class. + return gutil::InvalidArgumentErrorBuilder() << absl::Substitute( + "Two control switch P4RT port IDs (including '$0') are " + "mapped to the same SUT P4RT port ID '$1'", + control_port, *sut_port); + } else { + // The mapped port doesn't exist at all. + return gutil::InvalidArgumentErrorBuilder() << absl::Substitute( + "SUT P4RT port ID '$0' does not exist, but is mapped to by " + "control switch P4RT port ID '$1'", + *sut_port, control_port); + } + } + + // Consider both ports mapped and add the mapping to the artifact string. + unmapped_sut_ports.erase(*sut_port); + unmapped_control_ports.erase(control_port); + absl::StrAppendFormat(&artifact_string, "\n% 7s <-> %s", + control_port.GetP4rtEncoding(), + sut_port->GetP4rtEncoding()); + } + + // Record unmapped ports. + if (!unmapped_sut_ports.empty()) { + absl::StrAppendFormat(&artifact_string, "\n\nUnmapped SUT ports: %s", + absl::StrJoin(unmapped_sut_ports, ", ")); + } + if (!unmapped_control_ports.empty()) { + absl::StrAppendFormat(&artifact_string, "\n\nUnmapped control ports: %s", + absl::StrJoin(unmapped_control_ports, ", ")); + } + + return writer.AppendToTestArtifact("mirror_testbed_port_map.txt", + artifact_string); +} + } // namespace dvaas diff --git a/dvaas/port_id_map.h b/dvaas/port_id_map.h index 0d9080ab..0246b5c0 100644 --- a/dvaas/port_id_map.h +++ b/dvaas/port_id_map.h @@ -21,6 +21,7 @@ #include "absl/container/flat_hash_map.h" #include "absl/status/status.h" #include "absl/status/statusor.h" +#include "gutil/test_artifact_writer.h" #include "lib/p4rt/p4rt_port.h" #include "proto/gnmi/gnmi.grpc.pb.h" @@ -78,6 +79,14 @@ class MirrorTestbedP4rtPortIdMap { control_to_sut_port_map_; }; +// Records the mapping between control and SUT ports as an artifact, noting +// any unmapped ports in both. +// Also, ensures that mapped ports exist. +absl::Status CheckAndStoreMappedAndUnmappedPortIds( + const MirrorTestbedP4rtPortIdMap& port_id_map, + gnmi::gNMI::StubInterface& sut, gnmi::gNMI::StubInterface& control_switch, + gutil::TestArtifactWriter& writer); + } // namespace dvaas #endif // PINS_DVAAS_PORT_ID_MAP_H_ From a7a59e2f2568ba1cf7c8e4f670d79502e01dc0b5 Mon Sep 17 00:00:00 2001 From: bibhuprasad-hcl <161687009+bibhuprasad-hcl@users.noreply.github.com> Date: Wed, 27 Nov 2024 23:06:42 +0000 Subject: [PATCH 13/17] [Thinkit] Try different speed configurations as Ixia connections may depend on testbed (#783) Co-authored-by: smolkaj Co-authored-by: Srikishen Pondicherry Shanmugam --- tests/forwarding/watch_port_test.cc | 1 - tests/gnmi/ethcounter_ixia_test.cc | 92 ++++++++++++++++++++--------- 2 files changed, 64 insertions(+), 29 deletions(-) diff --git a/tests/forwarding/watch_port_test.cc b/tests/forwarding/watch_port_test.cc index eb55cee4..ff970274 100644 --- a/tests/forwarding/watch_port_test.cc +++ b/tests/forwarding/watch_port_test.cc @@ -1050,7 +1050,6 @@ TEST_P(WatchPortTestFixture, VerifyWatchPortActionForDownPortMemberInsert) { GetParam().testbed->GetMirrorTestbed().Environment(); environment.SetTestCaseID("e54da480-d2cc-42c6-bced-0354b5ab3329"); absl::Span controller_port_ids = GetParam().port_ids; - const int group_size = kNumWcmpMembersForTest; ASSERT_OK_AND_ASSIGN(std::vector members, CreateGroupMembers(group_size, controller_port_ids)); diff --git a/tests/gnmi/ethcounter_ixia_test.cc b/tests/gnmi/ethcounter_ixia_test.cc index 09a39bea..08e279d5 100644 --- a/tests/gnmi/ethcounter_ixia_test.cc +++ b/tests/gnmi/ethcounter_ixia_test.cc @@ -61,6 +61,7 @@ constexpr char kOpsDown[] = "\"DOWN\""; // NOLINT constexpr char kOpsUp[] = "\"UP\""; constexpr char kSpeed100GB[] = "\"openconfig-if-ethernet:SPEED_100GB\""; +constexpr char kSpeed200GB[] = "\"openconfig-if-ethernet:SPEED_200GB\""; constexpr char kLoopbackFalse[] = "false"; // NOLINT constexpr char kLoopbackTrue[] = "true"; @@ -308,6 +309,41 @@ absl::StatusOr CheckLinkUp(absl::string_view iface, return (ops_response == kOpsUp); } +// Structure represents a link between SUT and Ixia. +// This is represented by Ixia interface name and the SUT's gNMI interface +// name. +struct IxiaLink { + std::string ixia_interface; + std::string sut_interface; +}; + +// Go over the connections and return vector of connections +// whose links are up. +absl::StatusOr> GetReadyIxiaLinks( + thinkit::GenericTestbed &generic_testbed, + gnmi::gNMI::StubInterface &gnmi_stub) { + std::vector links; + + absl::flat_hash_map interface_info = + generic_testbed.GetSutInterfaceInfo(); + // Loop through the interface_info looking for Ixia/SUT interface pairs, + // checking if the link is up. Add the pair to connections. + for (const auto &[interface, info] : interface_info) { + bool sut_link_up = false; + if (info.interface_modes.contains(thinkit::TRAFFIC_GENERATOR)) { + ASSIGN_OR_RETURN(sut_link_up, CheckLinkUp(interface, &gnmi_stub)); + if (sut_link_up) { + links.push_back({ + .ixia_interface = info.peer_interface_name, + .sut_interface = interface, + }); + } + } + } + + return links; +} + absl::StatusOr CheckLoopback(absl::string_view iface, gnmi::gNMI::StubInterface *gnmi_stub) { std::string ops_state_path = absl::StrCat("interfaces/interface[name=", iface, @@ -557,11 +593,11 @@ TEST_P(ExampleIxiaTestFixture, TestInFcsErrors) { generic_testbed->Sut().CreateGnmiStub()); // go through all the ports that interface to the Ixia and set them - // to 100GB since the Ixia ports are all 100GB. + // to 200GB since the Ixia ports are all 200GB. for (const auto &[interface, info] : interface_info) { if (info.interface_modes.contains(thinkit::TRAFFIC_GENERATOR)) { LOG(INFO) << "gwc: Host Interface " << interface; - EXPECT_OK(SetPortSpeed(kSpeed100GB, interface, gnmi_stub.get())); + EXPECT_OK(SetPortSpeed(kSpeed200GB, interface, gnmi_stub.get())); } } @@ -744,11 +780,11 @@ TEST_P(ExampleIxiaTestFixture, TestIPv4Pkts) { generic_testbed->Sut().CreateGnmiStub()); // go through all the ports that interface to the Ixia and set them - // to 100GB since the Ixia ports are all 100GB. + // to 200GB since the Ixia ports are all 200GB. for (const auto &[interface, info] : interface_info) { if (info.interface_modes.contains(thinkit::TRAFFIC_GENERATOR)) { LOG(INFO) << "Host Interface " << interface; - EXPECT_OK(SetPortSpeed(kSpeed100GB, interface, gnmi_stub.get())); + EXPECT_OK(SetPortSpeed(kSpeed200GB, interface, gnmi_stub.get())); } } @@ -758,33 +794,29 @@ TEST_P(ExampleIxiaTestFixture, TestIPv4Pkts) { // Loop through the interface_info looking for Ixia/SUT interface pairs, // checking if the link is up. we need one pair with link up for the // ingress interface/IXIA traffic generation - std::string ixia_interface = ""; - std::string sut_in_interface = ""; - - for (const auto &[interface, info] : interface_info) { - if (info.interface_modes.contains(thinkit::TRAFFIC_GENERATOR)) { - auto sut_link_up = CheckLinkUp(interface, gnmi_stub.get()); - EXPECT_TRUE(sut_link_up.ok()); - if (sut_link_up.ok() && sut_link_up.value()) { - ixia_interface = info.peer_interface_name; - sut_in_interface = interface; - break; + ASSERT_OK_AND_ASSIGN(std::vector ready_links, + GetReadyIxiaLinks(*generic_testbed, *gnmi_stub)); + + // If links didnt come up, lets try 100GB as some testbeds have 100GB + // IXIA connections. + if (ready_links.empty()) { + for (const auto &[interface, info] : interface_info) { + if (info.interface_modes.contains(thinkit::TRAFFIC_GENERATOR)) { + ASSERT_OK(SetPortSpeed(kSpeed100GB, interface, gnmi_stub.get())); } } + absl::SleepFor(absl::Seconds(20)); + + ASSERT_OK_AND_ASSIGN(ready_links, + GetReadyIxiaLinks(*generic_testbed, *gnmi_stub)); } - // Now loop through again and pick an egress interface. This one doesn't - // have to be up, just a different interface. - std::string sut_out_interface = ""; + ASSERT_GE(ready_links.size(), 2) << "Ixia links are not ready"; - for (const auto &[interface, info] : interface_info) { - if (info.interface_modes.contains(thinkit::TRAFFIC_GENERATOR)) { - if (interface != sut_in_interface) { - sut_out_interface = interface; - break; - } - } - } + std::string ixia_interface = ready_links[0].ixia_interface; + std::string sut_in_interface = ready_links[0].sut_interface; + + std::string sut_out_interface = ready_links[1].sut_interface; ASSERT_FALSE(ixia_interface.empty()); ASSERT_FALSE(sut_in_interface.empty()); @@ -967,8 +999,12 @@ TEST_P(ExampleIxiaTestFixture, TestIPv4Pkts) { EXPECT_EQ(delta_out.out_broadcast_pkts, 0); EXPECT_EQ(delta_out.out_errors, 0); EXPECT_EQ(delta_out.out_discards, 0); - EXPECT_GE(delta_out.out_ipv4_pkts, delta_out.out_pkts - 10); - EXPECT_LE(delta_out.out_ipv4_pkts, delta_out.out_pkts + 10); + + // TODO: Remove mask after bug is addressed. + if (!generic_testbed->Environment().MaskKnownFailures()) { + EXPECT_GE(delta_out.out_ipv4_pkts, delta_out.out_pkts - 10); + EXPECT_LE(delta_out.out_ipv4_pkts, delta_out.out_pkts + 10); + } EXPECT_EQ(delta_out.out_ipv6_pkts, 0); EXPECT_EQ(delta_out.out_ipv6_discarded_pkts, 0); EXPECT_LE(delta_in.in_ipv4_pkts, delta_out.out_pkts + 10); From ecf3d91e50acd286112f0480e8af5a293b951d4a Mon Sep 17 00:00:00 2001 From: VSuryaprasad-hcl <159443973+VSuryaprasad-HCL@users.noreply.github.com> Date: Wed, 27 Nov 2024 23:07:22 +0000 Subject: [PATCH 14/17] [Dvaas] adding Data plane validation. (#784) Co-authored-by: kishanps --- dvaas/dataplane_validation.cc | 340 ++++++++++++++++++++++++++++++++++ 1 file changed, 340 insertions(+) create mode 100644 dvaas/dataplane_validation.cc diff --git a/dvaas/dataplane_validation.cc b/dvaas/dataplane_validation.cc new file mode 100644 index 00000000..38b12642 --- /dev/null +++ b/dvaas/dataplane_validation.cc @@ -0,0 +1,340 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dvaas/dataplane_validation.h" + +#include +#include +#include +#include +#include + +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_join.h" +#include "absl/strings/string_view.h" +#include "dvaas/output_writer.h" +#include "dvaas/packet_injection.h" +#include "dvaas/port_id_map.h" +#include "dvaas/switch_api.h" +#include "dvaas/test_vector.h" +#include "dvaas/test_vector.pb.h" +#include "dvaas/user_provided_packet_test_vector.h" +#include "dvaas/validation_result.h" +#include "glog/logging.h" +#include "gutil/status.h" +#include "gutil/test_artifact_writer.h" +#include "gutil/version.h" +#include "lib/gnmi/gnmi_helper.h" +#include "lib/gnmi/openconfig.pb.h" +#include "lib/p4rt/p4rt_port.h" +#include "p4/v1/p4runtime.pb.h" +#include "p4_pdpi/ir.h" +#include "p4_pdpi/ir.pb.h" +#include "p4_pdpi/p4_runtime_session.h" +#include "p4_pdpi/p4_runtime_session_extras.h" +#include "p4_pdpi/packetlib/packetlib.pb.h" +#include "p4_symbolic/packet_synthesizer/packet_synthesizer.pb.h" +#include "proto/gnmi/gnmi.pb.h" +#include "tests/lib/switch_test_setup_helpers.h" +#include "thinkit/mirror_testbed.h" + +namespace dvaas { +namespace { + +using ::p4_symbolic::packet_synthesizer::SynthesizedPacket; +using ::pins_test::P4rtPortId; + +std::string ToString( + const std::vector& synthesized_packets) { + return absl::StrJoin(synthesized_packets, "\n\n\n", + [](std::string* out, auto& packet) { + absl::StrAppend(out, packet.DebugString()); + }); +} + +std::string ToString(const PacketTestVectorById& packet_test_vector_by_id) { + return absl::StrJoin(packet_test_vector_by_id, + absl::StrCat("\n", std::string(80, '-'), "\n\n"), + [](std::string* out, auto& it) { + absl::StrAppend(out, it.second.DebugString()); + }); +} + +// We use a custom test artifact writer that prefixes file names and adds +// headers to contents. +class DvaasTestArtifactWriter : public gutil::TestArtifactWriter { + public: + DvaasTestArtifactWriter(gutil::TestArtifactWriter& underlying_writer, + const DataplaneValidationParams& params) + : underlying_writer_(underlying_writer), params_(params) {} + + absl::Status StoreTestArtifact(absl::string_view filename, + absl::string_view contents) override { + return underlying_writer_.StoreTestArtifact(FixFileName(filename), + FixContents(contents)); + } + + absl::Status AppendToTestArtifact(absl::string_view filename, + absl::string_view contents) override { + return underlying_writer_.AppendToTestArtifact(FixFileName(filename), + FixContents(contents)); + } + + private: + gutil::TestArtifactWriter& underlying_writer_; + const DataplaneValidationParams& params_; + + std::string FixFileName(absl::string_view filename) { + return absl::StrCat(params_.artifact_prefix, "_", filename); + } + std::string FixContents(absl::string_view contents) { + return absl::StrCat(params_.get_artifact_header.has_value() + ? (*params_.get_artifact_header)() + : "", + contents, "\n\n\n"); + } +}; + +// Determines the P4 specification DVaaS should use, and performs some sanity +// checks to ensure the specification is compatible with the SUT. +absl::StatusOr InferP4Specification( + const DataplaneValidationParams& params, + const DataplaneValidationBackend& backend, SwitchApi& sut) { + P4Specification p4_spec; + if (params.specification_override.has_value()) { + p4_spec = *params.specification_override; + } else { + ASSIGN_OR_RETURN(p4_spec, backend.InferP4Specification(sut)); + } + + // Sanity check if the P4 specification is plausibly accurate. + ASSIGN_OR_RETURN( + gutil::Version p4_symbolic_config_version, + gutil::ParseVersion( + p4_spec.p4_symbolic_config.p4info().pkg_info().version())); + ASSIGN_OR_RETURN( + gutil::Version bmv2_config_version, + gutil::ParseVersion( + p4_spec.p4_symbolic_config.p4info().pkg_info().version())); + ASSIGN_OR_RETURN(gutil::Version sut_config_version, + pdpi::GetPkgInfoVersion(sut.p4rt.get())); + if (p4_symbolic_config_version != bmv2_config_version) { + if (params.specification_override.has_value()) { + LOG(WARNING) << "P4 specification override you provided is inconsistent: " + "P4Info versions for p4-symbolic and BMv2 do not match: " + << p4_symbolic_config_version << " vs " + << bmv2_config_version; + } else { + return gutil::InternalErrorBuilder() + << "P4 specification inferred by DVaaS backend is inconsistent: " + "P4Info versions for p4-symbolic and BMv2 do not match: " + << p4_symbolic_config_version << " vs " << bmv2_config_version; + } + } + if (bmv2_config_version != sut_config_version) { + if (params.specification_override.has_value()) { + LOG(WARNING) << "P4 specification override you provided is inconsistent " + "with the P4Info version of the SUT: override version " + << p4_symbolic_config_version << " vs SUT version " + << sut_config_version; + } else { + return gutil::InternalErrorBuilder() + << "P4 specification inferred by DVaaS backend is inconsistent " + "with the P4Info version of the SUT: inferred version " + << p4_symbolic_config_version << " vs SUT version" + << sut_config_version; + } + } + return p4_spec; +} + +} // namespace + +// Generates and returns test vectors using the backend functions +// `SynthesizePackets` and `GeneratePacketTestVectors`. Reads the table entries, +// P4Info, and relevant P4RT port IDs from the switch. +absl::StatusOr GenerateTestVectors( + const DataplaneValidationParams& params, SwitchApi& sut, + DataplaneValidationBackend& backend, gutil::TestArtifactWriter& writer) { + // Determine the P4 specification to test against. + ASSIGN_OR_RETURN(P4Specification p4_spec, + InferP4Specification(params, backend, sut)); + RETURN_IF_ERROR(writer.AppendToTestArtifact( + "sut_p4_symbolic_config.txt", p4_spec.p4_symbolic_config.DebugString())); + RETURN_IF_ERROR(writer.AppendToTestArtifact( + "sut_bmv2_config.txt", p4_spec.bmv2_config.DebugString())); + + // Read P4Info and entries from SUT, sorted for determinism. + ASSIGN_OR_RETURN(pdpi::IrP4Info ir_p4info, pdpi::GetIrP4Info(*sut.p4rt)); + ASSIGN_OR_RETURN(pdpi::IrTableEntries entries, + pdpi::ReadIrTableEntriesSorted(*sut.p4rt)); + + // Get enabled Ethernet ports from SUT's GNMI config. + ASSIGN_OR_RETURN(std::vector ports, + pins_test::GetMatchingP4rtPortIds( + *sut.gnmi, pins_test::IsEnabledEthernetInterface)); + if (ports.empty()) { + return absl::InvalidArgumentError("Set of available P4RT ports is empty"); + } + const P4rtPortId& default_ingress_port = ports[0]; + + // Synthesize test packets. + LOG(INFO) << "Synthesizing test packets"; + ASSIGN_OR_RETURN( + std::vector synthesized_packets, + backend.SynthesizePackets(ir_p4info, entries, p4_spec.p4_symbolic_config, + ports, [&](absl::string_view stats) { + return writer.AppendToTestArtifact( + "test_packet_stats.txt", stats); + })); + RETURN_IF_ERROR(writer.AppendToTestArtifact("synthesized_packets.txt", + ToString(synthesized_packets))); + + // Generate test vectors with output prediction from the synthesized + // packets. + LOG(INFO) << "Generating test vectors with output prediction"; + return backend.GeneratePacketTestVectors( + ir_p4info, entries, p4_spec.bmv2_config, ports, synthesized_packets, + default_ingress_port); +} + +absl::StatusOr DataplaneValidator::ValidateDataplane( + SwitchApi& sut, SwitchApi& control_switch, + const DataplaneValidationParams& params) { + // Set up custom writer that prefixes artifact names and adds headers. + std::unique_ptr writer = + std::make_unique(artifact_writer_, params); + + // Configure control switch. + { + // Read P4Info from control switch. + ASSIGN_OR_RETURN(pdpi::IrP4Info ir_info, + pdpi::GetIrP4Info(*control_switch.p4rt)); + + // Clear control switch table entries and install punt entries instead. + RETURN_IF_ERROR(pdpi::ClearTableEntries(control_switch.p4rt.get())); + ASSIGN_OR_RETURN(pdpi::IrEntities punt_entries, + backend_->GetEntitiesToPuntAllPackets(ir_info)); + RETURN_IF_ERROR( + pdpi::InstallIrEntities(*control_switch.p4rt, punt_entries)); + } + + // Read and store table entries on SUT as an artifact. + ASSIGN_OR_RETURN(pdpi::IrTableEntries entries, + pdpi::ReadIrTableEntriesSorted(*sut.p4rt)); + RETURN_IF_ERROR(writer->AppendToTestArtifact("sut_ir_table_entries.txt", + entries.DebugString())); + + // Store port mapping as an artifact (identity if not given a value). + MirrorTestbedP4rtPortIdMap mirror_testbed_port_map = + params.mirror_testbed_port_map_override.has_value() + ? *params.mirror_testbed_port_map_override + : MirrorTestbedP4rtPortIdMap::CreateIdentityMap(); + RETURN_IF_ERROR(CheckAndStoreMappedAndUnmappedPortIds( + mirror_testbed_port_map, *sut.gnmi, *control_switch.gnmi, *writer)); + + // Generate test vectors. + PacketTestVectorById test_vectors; + if (params.packet_test_vector_override.empty()) { + LOG(INFO) << "Auto-generating test vectors"; + ASSIGN_OR_RETURN(test_vectors, + GenerateTestVectors(params, sut, *backend_, *writer)); + } else { + LOG(INFO) << "Checking user-provided test vectors for well-formedness"; + ASSIGN_OR_RETURN(test_vectors, LegitimizeUserProvidedTestVectors( + params.packet_test_vector_override)); + } + RETURN_IF_ERROR( + writer->AppendToTestArtifact("test_vectors.txt", ToString(test_vectors))); + + // Send tests to switch and collect results. + ASSIGN_OR_RETURN( + PacketTestRuns test_runs, + SendTestPacketsAndCollectOutputs( + *sut.p4rt.get(), *control_switch.p4rt.get(), test_vectors, + { + .max_packets_to_send_per_second = + params.max_packets_to_send_per_second, + .is_expected_unsolicited_packet = + [&](const packetlib::Packet packet) -> bool { + return backend_->IsExpectedUnsolicitedPacket(packet); + }, + .mirror_testbed_port_map = mirror_testbed_port_map, + }, + packet_statistics_)); + RETURN_IF_ERROR(writer->AppendToTestArtifact("test_runs.textproto", + test_runs.DebugString())); + + ValidationResult validation_result(std::move(test_runs), + params.switch_output_diff_params); + RETURN_IF_ERROR(writer->AppendToTestArtifact( + "test_vector_failures.txt", + absl::StrJoin(validation_result.GetAllFailures(), "\n\n"))); + return validation_result; +} + +absl::StatusOr DataplaneValidator::ValidateDataplane( + thinkit::MirrorTestbed& testbed, const DataplaneValidationParams& params) { + // Set up connections. + SwitchApi sut, control_switch; + ASSIGN_OR_RETURN(sut.p4rt, pdpi::P4RuntimeSession::Create(testbed.Sut())); + ASSIGN_OR_RETURN(sut.gnmi, testbed.Sut().CreateGnmiStub()); + ASSIGN_OR_RETURN(control_switch.p4rt, + pdpi::P4RuntimeSession::Create(testbed.ControlSwitch())); + ASSIGN_OR_RETURN(control_switch.gnmi, + testbed.ControlSwitch().CreateGnmiStub()); + + std::optional original_control_interfaces; + if (!params.mirror_testbed_port_map_override.has_value()) { + // TODO: Infer port ID mapping from mirror testbed interface + // names instead of changing control switch's port configuration. + + // Store the original control switch gNMI interface config before changing + // it. + ASSIGN_OR_RETURN(original_control_interfaces, + pins_test::GetInterfacesAsProto(*control_switch.gnmi, + gnmi::GetRequest::CONFIG)); + // Set up control switch to be a mirror of SUT. + RETURN_IF_ERROR(pdpi::ClearTableEntries(control_switch.p4rt.get())); + // Mirror testbed ports. + RETURN_IF_ERROR( + pins_test::MirrorSutP4rtPortIdConfigToControlSwitch(testbed)); + + // Ensure that all enabled ports are up for control switch. + RETURN_IF_ERROR( + pins_test::WaitForEnabledInterfacesToBeUp(testbed.ControlSwitch())) + .SetPrepend() + << "expected enabled interfaces on control switch to be up: "; + } + + // Ensure that all enabled ports are up for SUT. + RETURN_IF_ERROR(pins_test::WaitForEnabledInterfacesToBeUp(testbed.Sut())) + .SetPrepend() + << "expected enabled interfaces on SUT to be up: "; + + // Do not return on error in order to restore the original control switch gNMI + // interface config's P4RT IDs. + absl::StatusOr result = + ValidateDataplane(sut, control_switch, params); + + if (original_control_interfaces.has_value()) { + RETURN_IF_ERROR(pins_test::SetInterfaceP4rtIds( + *control_switch.gnmi, *original_control_interfaces)); + } + return result; +} + +} // namespace dvaas From d789b14f7a8db6b018e2799e80f34fa78309090b Mon Sep 17 00:00:00 2001 From: VSuryaprasad-hcl <159443973+VSuryaprasad-HCL@users.noreply.github.com> Date: Wed, 27 Nov 2024 23:08:05 +0000 Subject: [PATCH 15/17] [P4_Symbolic] Adding p4_symbolic/ir/expected/extract_parser_operation.txt [Extend IR proto and translation to support parsers.] (#785) Co-authored-by: kishanps Co-authored-by: kheradmandG --- .../ir/expected/extract_parser_operation.txt | 200 ++++++++++++++++++ p4_symbolic/ir/ir.proto | 119 ++++++++++- 2 files changed, 317 insertions(+), 2 deletions(-) create mode 100644 p4_symbolic/ir/expected/extract_parser_operation.txt diff --git a/p4_symbolic/ir/expected/extract_parser_operation.txt b/p4_symbolic/ir/expected/extract_parser_operation.txt new file mode 100644 index 00000000..7cb24ed3 --- /dev/null +++ b/p4_symbolic/ir/expected/extract_parser_operation.txt @@ -0,0 +1,200 @@ +headers { + key: "ethernet" + value { + name: "ethernet_t" + id: 2 + fields { + key: "dst_addr" + value { + name: "dst_addr" + bitwidth: 48 + } + } + fields { + key: "ether_type" + value { + name: "ether_type" + bitwidth: 16 + } + } + fields { + key: "src_addr" + value { + name: "src_addr" + bitwidth: 48 + } + } + } +} +headers { + key: "scalars" + value { + name: "scalars_0" + } +} +headers { + key: "standard_metadata" + value { + name: "standard_metadata" + id: 1 + fields { + key: "_padding" + value { + name: "_padding" + bitwidth: 3 + } + } + fields { + key: "checksum_error" + value { + name: "checksum_error" + bitwidth: 1 + } + } + fields { + key: "deq_qdepth" + value { + name: "deq_qdepth" + bitwidth: 19 + } + } + fields { + key: "deq_timedelta" + value { + name: "deq_timedelta" + bitwidth: 32 + } + } + fields { + key: "egress_global_timestamp" + value { + name: "egress_global_timestamp" + bitwidth: 48 + } + } + fields { + key: "egress_port" + value { + name: "egress_port" + bitwidth: 9 + } + } + fields { + key: "egress_rid" + value { + name: "egress_rid" + bitwidth: 16 + } + } + fields { + key: "egress_spec" + value { + name: "egress_spec" + bitwidth: 9 + } + } + fields { + key: "enq_qdepth" + value { + name: "enq_qdepth" + bitwidth: 19 + } + } + fields { + key: "enq_timestamp" + value { + name: "enq_timestamp" + bitwidth: 32 + } + } + fields { + key: "ingress_global_timestamp" + value { + name: "ingress_global_timestamp" + bitwidth: 48 + } + } + fields { + key: "ingress_port" + value { + name: "ingress_port" + bitwidth: 9 + } + } + fields { + key: "instance_type" + value { + name: "instance_type" + bitwidth: 32 + } + } + fields { + key: "mcast_grp" + value { + name: "mcast_grp" + bitwidth: 16 + } + } + fields { + key: "packet_length" + value { + name: "packet_length" + bitwidth: 32 + } + } + fields { + key: "parser_error" + value { + name: "parser_error" + bitwidth: 32 + } + } + fields { + key: "priority" + value { + name: "priority" + bitwidth: 3 + } + } + } +} +pipeline { + key: "egress" + value { + name: "egress" + initial_control: "__END_OF_PIPELINE__" + } +} +pipeline { + key: "ingress" + value { + name: "ingress" + initial_control: "__END_OF_PIPELINE__" + } +} +parsers { + key: "parser" + value { + name: "parser" + initial_state: "start" + parse_states { + key: "start" + value { + name: "start" + parser_ops { + extract { + header { + header_name: "ethernet" + } + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + } +} + diff --git a/p4_symbolic/ir/ir.proto b/p4_symbolic/ir/ir.proto index 9abc03fc..2dd45b02 100644 --- a/p4_symbolic/ir/ir.proto +++ b/p4_symbolic/ir/ir.proto @@ -20,8 +20,8 @@ // The bmv2 proto is used to initially parse the JSON format, which is then // processed by our tool and transformed into the IR. // The IR does not cover all the features of P4 programs. -// Specifically, we intentionally ignore parsers, de-parsers, stacks and unions, -// checksum calculations, and extern definitions. +// Specifically, we intentionally ignore de-parsers, stacks, unions, checksum +// calculations, and extern definitions. // Additionally, some types of expressions and statements are unsupported, these // are described in the relevant sections of this file. // See the bmv2 JSON format reference for more information: @@ -48,6 +48,8 @@ message P4Program { map conditionals = 4; // Pipelines, keyed by their name. map pipeline = 5; + // Parsers, keyed by parser names. + map parsers = 6; // TODO: If needed in the future, action calls can be added here, for // action calls that are not wrapped in other control constructs. @@ -69,6 +71,111 @@ message HeaderField { bool signed = 3; } +// A P4 parser definition. +message Parser { + // The name of the parser. + string name = 1; + // The name of the initial state of the state machine, usually "start". + string initial_state = 2; + // Defines all parse states of the state machine. + map parse_states = 3; +} + +// Defines a parse state. +// A parse state defines a state and its outgoing transitions in the parser's +// state machine. +message ParseState { + string name = 1; + // Operations performed in the parse state in the order defined by the P4 + // program. + repeated ParserOperation parser_ops = 2; + // Fields of the transition key for the parser state (usually just one field). + repeated ParserTransitionKeyField transition_key_fields = 3; + // All transitions from this state to the next states. + repeated ParserTransition transitions = 4; + // Control flow information for optimized symbolic execution. + OptimizedSymbolicExecutionInfo optimized_symbolic_execution_info = 5; +} + +// Defines a parser operation, which corresponds to a single statement in a +// parse state. For instance, a parser operation can be a "set" operation +// (corresponding to an assignment statement), an "extract" operation +// (corresponding to an "extract" method call), or other primitives supported by +// the target implementation. +// +// Reference: +// https://github.com/p4lang/behavioral-model/blob/main/docs/JSON_format.md#parser-operations. +// +// Note that only "extract" and "set" operations are supported for now since +// others are not required at the moment. To support more complicated parsers, +// other operations may be supported in the future. +message ParserOperation { + // Defines an "extract" parser operation, which performs extraction for a + // fixed-width header. + message Extract { + // The name of the header instance to be extracted. + HeaderValue header = 1; + } + + // Defines a "set" parser operation, which sets a field with the given value. + message Set { + // The field whose value is to be updated with the rvalue. + FieldValue lvalue = 1; + + // The value used to update the field specified by the lvalue. + oneof rvalue { + FieldValue field_rvalue = 2; + HexstrValue hexstr_rvalue = 3; + LookaheadValue lookahead_rvalue = 4; + RExpression expression_rvalue = 5; + } + } + + oneof operation { + Extract extract = 1; + Set set = 3; + } +} + +// A single field in a transition key used in a parse state. +message ParserTransitionKeyField { + oneof key_field { + // Specifies a header field as part of the transition key. + FieldValue field = 1; + // Specifies the lookahead value as part of the transition key. + // It evalutes to a set of bits from the input packet without advancing the + // current read position. + LookaheadValue lookahead = 2; + } +} + +// Defines a transition between two parse states. +message ParserTransition { + oneof transition { + // A default transition, applied when no other transitions are matched. + DefaultTransition default_transition = 1; + // A hex string transition, applied when the given hex string matches the + // key. + HexStringTransition hex_string_transition = 2; + } +} + +// Defines a default transition. +message DefaultTransition { + // The name of the next state + string next_state = 1; +} + +// Defines a hex string transition. +message HexStringTransition { + // Hex string value to be matched against the key. + string value = 1; + // Hex string mask, to be ANDed with both the key and the value if not empty. + string mask = 2; + // The name of the next state. + string next_state = 3; +} + // Overall action structure, combining definition with implementation. message Action { pdpi.IrActionDefinition action_definition = 1; @@ -269,6 +376,14 @@ message StringValue { string value = 1; } +// A lookahead value. +message LookaheadValue { + // Bit offset of the lookahead operation. + int32 offset = 1; + // Bit width of the lookahead operation. + int32 bitwidth = 2; +} + // A variable used within an LValue or RValue. message Variable { string name = 1; From 746902f48bccbe92d63d0d1f722383d07e45a98e Mon Sep 17 00:00:00 2001 From: VSuryaprasad-hcl <159443973+VSuryaprasad-HCL@users.noreply.github.com> Date: Wed, 27 Nov 2024 23:08:49 +0000 Subject: [PATCH 16/17] [P4_Symbolic] Extend IR proto and translation to support parsers. (#786) Co-authored-by: kishanps Co-authored-by: kheradmandG --- p4_symbolic/ir/BUILD.bazel | 24 +- p4_symbolic/ir/expected/basic.txt | 55 +++ .../ir/expected/complex_conditional.txt | 25 + p4_symbolic/ir/expected/conditional.txt | 25 + .../ir/expected/conditional_sequence.txt | 25 + p4_symbolic/ir/expected/hardcoded.txt | 18 + .../ir/expected/hex_string_transition.txt | 62 +++ p4_symbolic/ir/expected/reflector.txt | 18 + p4_symbolic/ir/expected/sai_parser.txt | 451 ++++++++++++++++++ p4_symbolic/ir/expected/set_invalid.txt | 25 + p4_symbolic/ir/expected/string_optional.txt | 18 + p4_symbolic/ir/expected/table.txt | 18 + p4_symbolic/ir/expected/table_hit_1.txt | 25 + p4_symbolic/ir/expected/table_hit_2.txt | 25 + p4_symbolic/ir/ir.cc | 364 +++++++++++++- .../testdata/parser/hex_string_transition.p4 | 1 - 16 files changed, 1150 insertions(+), 29 deletions(-) diff --git a/p4_symbolic/ir/BUILD.bazel b/p4_symbolic/ir/BUILD.bazel index 0b1b73e9..7a3595a5 100644 --- a/p4_symbolic/ir/BUILD.bazel +++ b/p4_symbolic/ir/BUILD.bazel @@ -90,7 +90,7 @@ cc_library( "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", - "@com_google_absl//absl/strings:str_format", + "@com_google_absl//absl/strings:str_format", ], ) @@ -211,10 +211,30 @@ ir_parsing_test( p4_program = "//p4_symbolic/testdata:parser/sai_parser.p4", ) +ir_parsing_test( + name = "extract_parser_operation_test", + golden_file = "expected/extract_parser_operation.txt", + p4_deps = ["//p4_symbolic/testdata:common/headers.p4"], + p4_program = "//p4_symbolic/testdata:parser/extract_parser_operation.p4", +) + +ir_parsing_test( + name = "set_parser_operation_test", + golden_file = "expected/set_parser_operation.txt", + p4_deps = ["//p4_symbolic/testdata:common/headers.p4"], + p4_program = "//p4_symbolic/testdata:parser/set_parser_operation.p4", +) + +ir_parsing_test( + name = "default_transition_test", + golden_file = "expected/default_transition.txt", + p4_deps = ["//p4_symbolic/testdata:common/headers.p4"], + p4_program = "//p4_symbolic/testdata:parser/default_transition.p4", +) + ir_parsing_test( name = "hex_string_transition_test", golden_file = "expected/hex_string_transition.txt", p4_deps = ["//p4_symbolic/testdata:common/headers.p4"], p4_program = "//p4_symbolic/testdata:parser/hex_string_transition.p4", ) - diff --git a/p4_symbolic/ir/expected/basic.txt b/p4_symbolic/ir/expected/basic.txt index 7a48ed5f..2450de59 100644 --- a/p4_symbolic/ir/expected/basic.txt +++ b/p4_symbolic/ir/expected/basic.txt @@ -643,6 +643,61 @@ pipeline { initial_control: "node_2" } } +parsers { + key: "parser" + value { + name: "parser" + initial_state: "start" + parse_states { + key: "parse_ipv4" + value { + name: "parse_ipv4" + parser_ops { + extract { + header { + header_name: "ipv4" + } + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + parse_states { + key: "start" + value { + name: "start" + parser_ops { + extract { + header { + header_name: "ethernet" + } + } + } + transition_key_fields { + field { + header_name: "ethernet" + field_name: "etherType" + } + } + transitions { + hex_string_transition { + value: "0x0800" + next_state: "parse_ipv4" + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + } +} =====MyIngress.ipv4_lpm Entries===== diff --git a/p4_symbolic/ir/expected/complex_conditional.txt b/p4_symbolic/ir/expected/complex_conditional.txt index 57adf136..43a08830 100644 --- a/p4_symbolic/ir/expected/complex_conditional.txt +++ b/p4_symbolic/ir/expected/complex_conditional.txt @@ -2071,4 +2071,29 @@ pipeline { initial_control: "node_2" } } +parsers { + key: "parser" + value { + name: "parser" + initial_state: "start" + parse_states { + key: "start" + value { + name: "start" + parser_ops { + extract { + header { + header_name: "h1" + } + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + } +} diff --git a/p4_symbolic/ir/expected/conditional.txt b/p4_symbolic/ir/expected/conditional.txt index c7c7db71..e179bee4 100644 --- a/p4_symbolic/ir/expected/conditional.txt +++ b/p4_symbolic/ir/expected/conditional.txt @@ -703,4 +703,29 @@ pipeline { initial_control: "node_2" } } +parsers { + key: "parser" + value { + name: "parser" + initial_state: "start" + parse_states { + key: "start" + value { + name: "start" + parser_ops { + extract { + header { + header_name: "ethernet" + } + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + } +} diff --git a/p4_symbolic/ir/expected/conditional_sequence.txt b/p4_symbolic/ir/expected/conditional_sequence.txt index 4c033e97..0a6f1a98 100644 --- a/p4_symbolic/ir/expected/conditional_sequence.txt +++ b/p4_symbolic/ir/expected/conditional_sequence.txt @@ -2340,4 +2340,29 @@ pipeline { initial_control: "node_2" } } +parsers { + key: "parser" + value { + name: "parser" + initial_state: "start" + parse_states { + key: "start" + value { + name: "start" + parser_ops { + extract { + header { + header_name: "h1" + } + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + } +} diff --git a/p4_symbolic/ir/expected/hardcoded.txt b/p4_symbolic/ir/expected/hardcoded.txt index f0fc90fd..68e34315 100644 --- a/p4_symbolic/ir/expected/hardcoded.txt +++ b/p4_symbolic/ir/expected/hardcoded.txt @@ -279,4 +279,22 @@ pipeline { initial_control: "node_2" } } +parsers { + key: "parser" + value { + name: "parser" + initial_state: "start" + parse_states { + key: "start" + value { + name: "start" + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + } +} diff --git a/p4_symbolic/ir/expected/hex_string_transition.txt b/p4_symbolic/ir/expected/hex_string_transition.txt index fb63ca77..ea9b2f3d 100644 --- a/p4_symbolic/ir/expected/hex_string_transition.txt +++ b/p4_symbolic/ir/expected/hex_string_transition.txt @@ -284,4 +284,66 @@ pipeline { initial_control: "__END_OF_PIPELINE__" } } +parsers { + key: "parser" + value { + name: "parser" + initial_state: "start" + parse_states { + key: "parse_ipv4" + value { + name: "parse_ipv4" + parser_ops { + extract { + header { + header_name: "ipv4" + } + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + parse_states { + key: "start" + value { + name: "start" + parser_ops { + extract { + header { + header_name: "ethernet" + } + } + } + transition_key_fields { + field { + header_name: "ethernet" + field_name: "ether_type" + } + } + transitions { + hex_string_transition { + value: "0x0000" + mask: "0xfe00" + next_state: "__END_OF_PARSER__" + } + } + transitions { + hex_string_transition { + value: "0x0800" + next_state: "parse_ipv4" + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + } +} diff --git a/p4_symbolic/ir/expected/reflector.txt b/p4_symbolic/ir/expected/reflector.txt index 6c4289e8..47a1d412 100644 --- a/p4_symbolic/ir/expected/reflector.txt +++ b/p4_symbolic/ir/expected/reflector.txt @@ -198,4 +198,22 @@ pipeline { initial_control: "tbl_reflector54" } } +parsers { + key: "parser" + value { + name: "parser" + initial_state: "start" + parse_states { + key: "start" + value { + name: "start" + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + } +} diff --git a/p4_symbolic/ir/expected/sai_parser.txt b/p4_symbolic/ir/expected/sai_parser.txt index e118214b..e22d0a0e 100644 --- a/p4_symbolic/ir/expected/sai_parser.txt +++ b/p4_symbolic/ir/expected/sai_parser.txt @@ -1117,4 +1117,455 @@ pipeline { initial_control: "__END_OF_PIPELINE__" } } +parsers { + key: "parser" + value { + name: "parser" + initial_state: "start" + parse_states { + key: "parse_8021q_vlan" + value { + name: "parse_8021q_vlan" + parser_ops { + extract { + header { + header_name: "vlan" + } + } + } + transition_key_fields { + field { + header_name: "vlan" + field_name: "ether_type" + } + } + transitions { + hex_string_transition { + value: "0x0800" + next_state: "parse_ipv4" + } + } + transitions { + hex_string_transition { + value: "0x86dd" + next_state: "parse_ipv6" + } + } + transitions { + hex_string_transition { + value: "0x0806" + next_state: "parse_arp" + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + parse_states { + key: "parse_arp" + value { + name: "parse_arp" + parser_ops { + extract { + header { + header_name: "arp" + } + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + parse_states { + key: "parse_ethernet" + value { + name: "parse_ethernet" + parser_ops { + extract { + header { + header_name: "ethernet" + } + } + } + transition_key_fields { + field { + header_name: "ethernet" + field_name: "ether_type" + } + } + transitions { + hex_string_transition { + value: "0x0800" + next_state: "parse_ipv4" + } + } + transitions { + hex_string_transition { + value: "0x86dd" + next_state: "parse_ipv6" + } + } + transitions { + hex_string_transition { + value: "0x0806" + next_state: "parse_arp" + } + } + transitions { + hex_string_transition { + value: "0x8100" + next_state: "parse_8021q_vlan" + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + parse_states { + key: "parse_icmp" + value { + name: "parse_icmp" + parser_ops { + extract { + header { + header_name: "icmp" + } + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + parse_states { + key: "parse_ipv4" + value { + name: "parse_ipv4" + parser_ops { + extract { + header { + header_name: "ipv4" + } + } + } + transition_key_fields { + field { + header_name: "ipv4" + field_name: "protocol" + } + } + transitions { + hex_string_transition { + value: "0x01" + next_state: "parse_icmp" + } + } + transitions { + hex_string_transition { + value: "0x06" + next_state: "parse_tcp" + } + } + transitions { + hex_string_transition { + value: "0x11" + next_state: "parse_udp" + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + parse_states { + key: "parse_ipv6" + value { + name: "parse_ipv6" + parser_ops { + extract { + header { + header_name: "ipv6" + } + } + } + transition_key_fields { + field { + header_name: "ipv6" + field_name: "next_header" + } + } + transitions { + hex_string_transition { + value: "0x3a" + next_state: "parse_icmp" + } + } + transitions { + hex_string_transition { + value: "0x06" + next_state: "parse_tcp" + } + } + transitions { + hex_string_transition { + value: "0x11" + next_state: "parse_udp" + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + parse_states { + key: "parse_packet_out_header" + value { + name: "parse_packet_out_header" + parser_ops { + extract { + header { + header_name: "packet_out_header" + } + } + } + transitions { + default_transition { + next_state: "parse_ethernet" + } + } + } + } + parse_states { + key: "parse_tcp" + value { + name: "parse_tcp" + parser_ops { + extract { + header { + header_name: "tcp" + } + } + } + parser_ops { + set { + lvalue { + header_name: "scalars" + field_name: "local_metadata_t._l4_src_port6" + } + field_rvalue { + header_name: "tcp" + field_name: "src_port" + } + } + } + parser_ops { + set { + lvalue { + header_name: "scalars" + field_name: "local_metadata_t._l4_dst_port7" + } + field_rvalue { + header_name: "tcp" + field_name: "dst_port" + } + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + parse_states { + key: "parse_udp" + value { + name: "parse_udp" + parser_ops { + extract { + header { + header_name: "udp" + } + } + } + parser_ops { + set { + lvalue { + header_name: "scalars" + field_name: "local_metadata_t._l4_src_port6" + } + field_rvalue { + header_name: "udp" + field_name: "src_port" + } + } + } + parser_ops { + set { + lvalue { + header_name: "scalars" + field_name: "local_metadata_t._l4_dst_port7" + } + field_rvalue { + header_name: "udp" + field_name: "dst_port" + } + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + parse_states { + key: "start" + value { + name: "start" + parser_ops { + set { + lvalue { + header_name: "scalars" + field_name: "local_metadata_t._vlan_id_valid1" + } + expression_rvalue { + builtin_expression { + arguments { + bool_value { + } + } + } + } + } + } + parser_ops { + set { + lvalue { + header_name: "scalars" + field_name: "local_metadata_t._vlan_id0" + } + hexstr_rvalue { + value: "0x0000" + } + } + } + parser_ops { + set { + lvalue { + header_name: "scalars" + field_name: "local_metadata_t._admit_to_l32" + } + expression_rvalue { + builtin_expression { + arguments { + bool_value { + } + } + } + } + } + } + parser_ops { + set { + lvalue { + header_name: "scalars" + field_name: "local_metadata_t._vrf_id3" + } + hexstr_rvalue { + value: "0x0000" + } + } + } + parser_ops { + set { + lvalue { + header_name: "scalars" + field_name: "local_metadata_t._packet_rewrites_src_mac4" + } + hexstr_rvalue { + value: "0x000000000000" + } + } + } + parser_ops { + set { + lvalue { + header_name: "scalars" + field_name: "local_metadata_t._packet_rewrites_dst_mac5" + } + hexstr_rvalue { + value: "0x000000000000" + } + } + } + parser_ops { + set { + lvalue { + header_name: "scalars" + field_name: "local_metadata_t._l4_src_port6" + } + hexstr_rvalue { + value: "0x0000" + } + } + } + parser_ops { + set { + lvalue { + header_name: "scalars" + field_name: "local_metadata_t._l4_dst_port7" + } + hexstr_rvalue { + value: "0x0000" + } + } + } + parser_ops { + set { + lvalue { + header_name: "scalars" + field_name: "local_metadata_t._wcmp_selector_input8" + } + hexstr_rvalue { + value: "0x0000" + } + } + } + transition_key_fields { + field { + header_name: "standard_metadata" + field_name: "ingress_port" + } + } + transitions { + hex_string_transition { + value: "0x01fe" + next_state: "parse_packet_out_header" + } + } + transitions { + default_transition { + next_state: "parse_ethernet" + } + } + } + } + } +} diff --git a/p4_symbolic/ir/expected/set_invalid.txt b/p4_symbolic/ir/expected/set_invalid.txt index 1090835e..527795d7 100644 --- a/p4_symbolic/ir/expected/set_invalid.txt +++ b/p4_symbolic/ir/expected/set_invalid.txt @@ -346,4 +346,29 @@ pipeline { initial_control: "tbl_set_invalid61" } } +parsers { + key: "parser" + value { + name: "parser" + initial_state: "start" + parse_states { + key: "start" + value { + name: "start" + parser_ops { + extract { + header { + header_name: "h" + } + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + } +} diff --git a/p4_symbolic/ir/expected/string_optional.txt b/p4_symbolic/ir/expected/string_optional.txt index 46bdc2da..89ebd7a0 100644 --- a/p4_symbolic/ir/expected/string_optional.txt +++ b/p4_symbolic/ir/expected/string_optional.txt @@ -553,4 +553,22 @@ pipeline { initial_control: "tbl_program92" } } +parsers { + key: "parser" + value { + name: "parser" + initial_state: "start" + parse_states { + key: "start" + value { + name: "start" + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + } +} diff --git a/p4_symbolic/ir/expected/table.txt b/p4_symbolic/ir/expected/table.txt index 70eccfa3..5562dc43 100644 --- a/p4_symbolic/ir/expected/table.txt +++ b/p4_symbolic/ir/expected/table.txt @@ -323,6 +323,24 @@ pipeline { initial_control: "MyIngress.ports_exact" } } +parsers { + key: "parser" + value { + name: "parser" + initial_state: "start" + parse_states { + key: "start" + value { + name: "start" + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + } +} =====MyIngress.ports_exact Entries===== diff --git a/p4_symbolic/ir/expected/table_hit_1.txt b/p4_symbolic/ir/expected/table_hit_1.txt index d04c3744..bf9d7767 100644 --- a/p4_symbolic/ir/expected/table_hit_1.txt +++ b/p4_symbolic/ir/expected/table_hit_1.txt @@ -581,4 +581,29 @@ pipeline { initial_control: "MyIngress.t_1" } } +parsers { + key: "parser" + value { + name: "parser" + initial_state: "start" + parse_states { + key: "start" + value { + name: "start" + parser_ops { + extract { + header { + header_name: "ethernet" + } + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + } +} diff --git a/p4_symbolic/ir/expected/table_hit_2.txt b/p4_symbolic/ir/expected/table_hit_2.txt index e5d555db..57b2a433 100644 --- a/p4_symbolic/ir/expected/table_hit_2.txt +++ b/p4_symbolic/ir/expected/table_hit_2.txt @@ -723,4 +723,29 @@ pipeline { initial_control: "tbl_table_hit_2l83" } } +parsers { + key: "parser" + value { + name: "parser" + initial_state: "start" + parse_states { + key: "start" + value { + name: "start" + parser_ops { + extract { + header { + header_name: "h1" + } + } + } + transitions { + default_transition { + next_state: "__END_OF_PARSER__" + } + } + } + } + } +} diff --git a/p4_symbolic/ir/ir.cc b/p4_symbolic/ir/ir.cc index 9e0f9f1d..c117e726 100644 --- a/p4_symbolic/ir/ir.cc +++ b/p4_symbolic/ir/ir.cc @@ -29,10 +29,12 @@ #include "absl/status/statusor.h" #include "absl/strings/match.h" #include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "absl/strings/strip.h" #include "gutil/status.h" #include "p4/config/v1/p4info.pb.h" +#include "p4_symbolic/bmv2/bmv2.pb.h" #include "p4_symbolic/ir/cfg.h" #include "p4_symbolic/ir/ir.pb.h" @@ -46,6 +48,11 @@ std::string Bmv2ToIrControlName(const std::string &control_name) { return control_name.empty() ? EndOfPipeline() : control_name; } +// Turns BMv2-style names of parse states to P4-Symbolic's IR-style names. +std::string Bmv2ToIrParseStateName(const std::string &state_name) { + return state_name.empty() ? EndOfParser() : state_name; +} + // Forward declaration to enable mutual recursion with (sub) expression parsing // functions, e.g. ExtractBinaryExpression, ExtractUnaryExpression, etc. absl::StatusOr ExtractRValue(const google::protobuf::Value &bmv2_value, @@ -309,15 +316,30 @@ absl::StatusOr ExtractBuiltinExpression( absl::StatusOr ExtractRExpression( const google::protobuf::Struct &bmv2_expression, const std::vector &variables) { - RExpression output; + // An expression in the BMv2 format may have its value be a single other + // expression, whose value may also be another single expression, etc., until + // the actual value of the expression is reached. This is analogous to having + // an expression wrapped in multiple layers of parentheses. This conditional + // recursively navigates to the inner most expression. + if (!bmv2_expression.fields().contains("op") && + bmv2_expression.fields().contains("type") && + bmv2_expression.fields().at("type").has_string_value() && + bmv2_expression.fields().at("type").string_value() == "expression" && + bmv2_expression.fields().contains("value") && + bmv2_expression.fields().at("value").has_struct_value()) { + return ExtractRExpression( + bmv2_expression.fields().at("value").struct_value(), variables); + } + // Integrity check. - if (bmv2_expression.fields().count("op") != 1 || - bmv2_expression.fields().count("right") != 1) { + if (!bmv2_expression.fields().contains("op") || + !bmv2_expression.fields().contains("right")) { return absl::InvalidArgumentError( absl::StrCat("RExpression must contain 'op' and 'right', found ", bmv2_expression.DebugString())); } + RExpression output; const std::string &operation = bmv2_expression.fields().at("op").string_value(); ASSIGN_OR_RETURN(RExpression::ExpressionCase expression_case, @@ -456,30 +478,10 @@ absl::StatusOr ExtractRValue( return output; } case bmv2::ExpressionType::expression: { - const google::protobuf::Struct *expression = - &(struct_value.fields().at("value").struct_value()); - - // This loop is only needed because bmv2 format has this annoying thing - // where an expression may have its value be a single other expression - // which value may also be another single expression, etc, until - // finally the actual value of the expression is reached. - // This is the bmv2 format analogous case to having an expression - // wrapped in many useless paranthesis. An example of this can be found - // at //p4-samples/ipv4-routing/basic.json after `make build` is run in - // that directory. - while (expression->fields().count("op") != 1) { - if (expression->fields().count("type") != 1 || - expression->fields().at("type").string_value() != "expression" || - expression->fields().count("value") != 1) { - return absl::InvalidArgumentError( - absl::StrCat("Expression must contain 'op' at some level, found ", - expression->DebugString())); - } - expression = &(expression->fields().at("value").struct_value()); - } - + const google::protobuf::Struct &expression = + struct_value.fields().at("value").struct_value(); ASSIGN_OR_RETURN(*(output.mutable_expression_value()), - ExtractRExpression(*expression, variables)); + ExtractRExpression(expression, variables)); return output; } default: @@ -729,6 +731,280 @@ absl::StatusOr ExtractTable( return output; } +// Translates the "extract" parser operation from the BMv2 protobuf message. +absl::StatusOr ExtractExtractParserOp( + const bmv2::ParserOperation &bmv2_op) { + ParserOperation::Extract result; + + // The "extract" parser operation must have exactly 1 parameter. + if (bmv2_op.parameters_size() != 1) { + return gutil::InvalidArgumentErrorBuilder() + << "Parser extract op must have 1 parameter, found " + << bmv2_op.DebugString(); + } + + const ::google::protobuf::Struct &bmv2_param = bmv2_op.parameters(0); + + // Make sure the parameter struct contains the correct fields. + if (!bmv2_param.fields().contains("type") || + !bmv2_param.fields().at("type").has_string_value() || + !bmv2_param.fields().contains("value") || + !bmv2_param.fields().at("value").has_string_value()) { + return gutil::InvalidArgumentErrorBuilder() + << "Extract operation has an invalid parameter: " + << bmv2_param.DebugString(); + } + + const std::string &bmv2_type = bmv2_param.fields().at("type").string_value(); + const std::string &bmv2_value = + bmv2_param.fields().at("value").string_value(); + + if (bmv2_type == "regular") { + // `bmv2_value` is the name of the header to be extracted. + result.mutable_header()->set_header_name(bmv2_value); + } else if (bmv2_type == "stack" || bmv2_type == "union_stack") { + // Stacks and union stacks are not supported at the moment. + return absl::UnimplementedError( + absl::StrFormat("Unsupported parameter type '%s'", bmv2_type)); + } else { + return absl::InvalidArgumentError( + absl::StrFormat("Parameter type must be one of [regular, stack, " + "union_stack]. Found '%s'", + bmv2_type)); + } + + return result; +} + +// Translates the "set" parser operation from the BMv2 protobuf message. +absl::StatusOr ExtractSetParserOp( + const bmv2::ParserOperation &bmv2_op) { + ParserOperation::Set result; + + // The "set" parser operation must have exactly 2 parameters. + if (bmv2_op.parameters_size() != 2) { + return absl::InvalidArgumentError(absl::StrCat( + "Parser set op must have 2 parameters, found ", bmv2_op.DebugString())); + } + + const ::google::protobuf::Struct &bmv2_lparam = bmv2_op.parameters(0); + const ::google::protobuf::Struct &bmv2_rparam = bmv2_op.parameters(1); + + // Make sure the L-parameter struct contains the correct fields. + if (!bmv2_lparam.fields().contains("type") || + !bmv2_lparam.fields().at("type").has_string_value() || + !bmv2_lparam.fields().contains("value") || + !bmv2_lparam.fields().at("value").has_list_value()) { + return gutil::InvalidArgumentErrorBuilder() + << "Set operation has invalid parameters: " + << bmv2_lparam.DebugString(); + } + + // Translate the L-parameter of the "set" parser operation. + const std::string &bmv2_ltype = + bmv2_lparam.fields().at("type").string_value(); + if (bmv2_ltype != "field") { + return absl::InvalidArgumentError(absl::StrFormat( + "Parameter type must be 'field'. Found '%s'", bmv2_ltype)); + } + + FieldValue &lvalue = *result.mutable_lvalue(); + const ::google::protobuf::ListValue &bmv2_lvalue = + bmv2_lparam.fields().at("value").list_value(); + lvalue.set_header_name(bmv2_lvalue.values(0).string_value()); + lvalue.set_field_name(bmv2_lvalue.values(1).string_value()); + + // Make sure the R-parameter struct contains the correct fields. + if (!bmv2_rparam.fields().contains("type") || + !bmv2_rparam.fields().at("type").has_string_value() || + !bmv2_rparam.fields().contains("value")) { + return gutil::InvalidArgumentErrorBuilder() + << "Set operation has invalid parameters: " + << bmv2_rparam.DebugString(); + } + + // Translate the R-parameter of "set" parser operation. + const std::string &bmv2_rtype = + bmv2_rparam.fields().at("type").string_value(); + + if (bmv2_rtype == "field") { + FieldValue &rvalue = *result.mutable_field_rvalue(); + const ::google::protobuf::ListValue &bmv2_field_value = + bmv2_rparam.fields().at("value").list_value(); + rvalue.set_header_name(bmv2_field_value.values(0).string_value()); + rvalue.set_field_name(bmv2_field_value.values(1).string_value()); + } else if (bmv2_rtype == "hexstr") { + HexstrValue &rvalue = *result.mutable_hexstr_rvalue(); + const std::string &bmv2_hexstr = + bmv2_rparam.fields().at("value").string_value(); + if (absl::StartsWith(bmv2_hexstr, "-")) { + rvalue.set_value(std::string(absl::StripPrefix(bmv2_hexstr, "-"))); + rvalue.set_negative(true); + } else { + rvalue.set_value(bmv2_hexstr); + rvalue.set_negative(false); + } + } else if (bmv2_rtype == "lookahead") { + LookaheadValue &rvalue = *result.mutable_lookahead_rvalue(); + const ::google::protobuf::ListValue &bmv2_lookahead = + bmv2_rparam.fields().at("value").list_value(); + rvalue.set_offset(bmv2_lookahead.values(0).number_value()); + rvalue.set_bitwidth(bmv2_lookahead.values(1).number_value()); + } else if (bmv2_rtype == "expression") { + RExpression &rvalue = *result.mutable_expression_rvalue(); + const google::protobuf::Struct &bmv2_expression = + bmv2_rparam.fields().at("value").struct_value(); + ASSIGN_OR_RETURN(rvalue, ExtractRExpression(bmv2_expression, {})); + } else { + return absl::InvalidArgumentError( + absl::StrFormat("Invalid parameter type '%s'", bmv2_rtype)); + } + + return result; +} + +// Translates parser operations. +// Currently only "extract" and "set" parser operations are supported since +// others are not required at the moment. +absl::StatusOr ExtractParserOperation( + const bmv2::ParserOperation &bmv2_op) { + ParserOperation result; + + switch (bmv2_op.op()) { + case bmv2::ParserOperation::extract: { + ASSIGN_OR_RETURN(*result.mutable_extract(), + ExtractExtractParserOp(bmv2_op)); + break; + } + case bmv2::ParserOperation::set: { + ASSIGN_OR_RETURN(*result.mutable_set(), ExtractSetParserOp(bmv2_op)); + break; + } + default: { + return absl::UnimplementedError( + absl::StrCat("Unsupported parser op: ", bmv2_op.DebugString())); + } + } + + return result; +} + +// Translates parser transition key fields. +absl::StatusOr ExtractParserTransitionKeyField( + const bmv2::ParserTransitionKeyField &bmv2_key_field) { + ParserTransitionKeyField result; + + switch (bmv2_key_field.type()) { + case bmv2::ParserTransitionKeyField::field: { + FieldValue &field = *result.mutable_field(); + const ::google::protobuf::ListValue &bmv2_value = bmv2_key_field.value(); + field.set_header_name(bmv2_value.values(0).string_value()); + field.set_field_name(bmv2_value.values(1).string_value()); + break; + } + case bmv2::ParserTransitionKeyField::lookahead: + case bmv2::ParserTransitionKeyField::stack_field: + case bmv2::ParserTransitionKeyField::union_stack_field: { + return absl::UnimplementedError( + absl::StrCat("Unsupported parser transition key field type: ", + bmv2_key_field.type())); + } + default: { + return absl::InvalidArgumentError( + absl::StrCat("Invalid parser transition key field: ", + bmv2_key_field.DebugString())); + } + } + + return result; +} + +// Translates a parser's state transition from the BMv2 protobuf message. +absl::StatusOr ExtractParserTransition( + const bmv2::ParserTransition &bmv2_transition) { + ParserTransition result; + const std::string &bmv2_value = bmv2_transition.value(); + const std::string &bmv2_mask = bmv2_transition.mask(); + const std::string &bmv2_next_state = bmv2_transition.next_state(); + + switch (bmv2_transition.type()) { + case bmv2::ParserTransitionType::default_: { + DefaultTransition &default_transition = + *result.mutable_default_transition(); + default_transition.set_next_state( + Bmv2ToIrParseStateName(bmv2_next_state)); + break; + } + + case bmv2::ParserTransitionType::hexstr: { + HexStringTransition &hexstr_transition = + *result.mutable_hex_string_transition(); + + if (bmv2_value.empty()) { + return absl::InvalidArgumentError(absl::StrCat( + "Empty hex string value: ", bmv2_transition.DebugString())); + } + + hexstr_transition.set_value(bmv2_value); + hexstr_transition.set_mask(bmv2_mask); + hexstr_transition.set_next_state(Bmv2ToIrParseStateName(bmv2_next_state)); + break; + } + + case bmv2::ParserTransitionType::parse_vset: { + return absl::UnimplementedError( + absl::StrCat("Unsupported parser transition type: ", + bmv2_transition.DebugString())); + } + + default: { + return absl::InvalidArgumentError( + absl::StrCat("Parser transition type must be one of [default, " + "hexstr, parse_vset]. Found: ", + bmv2_transition.DebugString())); + } + } + + return result; +} + +// Translates a parse state from the BMv2 protobuf message. +absl::StatusOr ExtractParseState( + const bmv2::ParseState &bmv2_parse_state) { + ParseState state; + state.set_name(bmv2_parse_state.name()); + + for (const auto &op : bmv2_parse_state.parser_ops()) { + ASSIGN_OR_RETURN(*state.add_parser_ops(), ExtractParserOperation(op)); + } + + for (const auto &key_field : bmv2_parse_state.transition_key()) { + ASSIGN_OR_RETURN(*state.add_transition_key_fields(), + ExtractParserTransitionKeyField(key_field)); + } + + for (const auto &transition : bmv2_parse_state.transitions()) { + ASSIGN_OR_RETURN(*state.add_transitions(), + ExtractParserTransition(transition)); + } + + return state; +} + +// Translates a parser from the BMv2 protobuf message. +absl::StatusOr ExtractParser(const bmv2::Parser &bmv2_parser) { + Parser parser; + parser.set_name(bmv2_parser.name()); + parser.set_initial_state(bmv2_parser.init_state()); + + for (const auto &parse_state : bmv2_parser.parse_states()) { + ASSIGN_OR_RETURN((*parser.mutable_parse_states())[parse_state.name()], + ExtractParseState(parse_state)); + } + + return parser; +} + } // namespace // Main Translation function. @@ -747,6 +1023,42 @@ absl::StatusOr Bmv2AndP4infoToIr(const bmv2::P4Program &bmv2, } } + // Check the number of parsers. The current implementation of the P4 compiler + // compresses all the parsers in the P4 program into one big parser with name + // mangling, where the name of each parse state is prefixed with the name of + // its original parser. + // For instance, the compilation output of the following P4 program snippet + // may contain states named "main_parser_parse_ethernet" and + // "ipv4_parser_parse_ipv4". Some trivial states may also be merged together + // by the compiler. + // + // ```p4 + // parser main_parser { + // state start { + // ... + // } + // state parse_ethernet { + // ... + // ipv4_parser.apply(); + // transition accept; + // } + // } + // + // parser ipv4_parser { + // ... + // } + // ``` + if (bmv2.parsers_size() != 1) { + return absl::InvalidArgumentError( + absl::StrCat("Expected single parser. Found: ", bmv2.parsers_size())); + } + + // Translate parsers from bmv2. + for (const bmv2::Parser &bmv2_parser : bmv2.parsers()) { + Parser &extracted_parser = (*output.mutable_parsers())[bmv2_parser.name()]; + ASSIGN_OR_RETURN(extracted_parser, ExtractParser(bmv2_parser)); + } + // In reality, pdpi.actions_by_name is keyed on aliases and // not fully qualified names. std::unordered_map diff --git a/p4_symbolic/testdata/parser/hex_string_transition.p4 b/p4_symbolic/testdata/parser/hex_string_transition.p4 index 5c28ea09..922dd50c 100644 --- a/p4_symbolic/testdata/parser/hex_string_transition.p4 +++ b/p4_symbolic/testdata/parser/hex_string_transition.p4 @@ -68,4 +68,3 @@ V1Switch( empty_compute_checksum(), packet_deparser() ) main; - From d4495ee2da1cdb5a46e8454050a64fdc1c9a4e01 Mon Sep 17 00:00:00 2001 From: VSuryaprasad-hcl <159443973+VSuryaprasad-HCL@users.noreply.github.com> Date: Wed, 27 Nov 2024 23:09:35 +0000 Subject: [PATCH 17/17] [Dvaas] adding Data plane validation header to Dvaas. (#789) Co-authored-by: kishanps --- dvaas/BUILD.bazel | 41 +++++ dvaas/dataplane_validation.h | 279 +++++++++++++++++++++++++++++++++++ 2 files changed, 320 insertions(+) create mode 100644 dvaas/dataplane_validation.h diff --git a/dvaas/BUILD.bazel b/dvaas/BUILD.bazel index 3bbbf0b0..2ca01581 100644 --- a/dvaas/BUILD.bazel +++ b/dvaas/BUILD.bazel @@ -355,3 +355,44 @@ cmd_diff_test( expected = ":test_run_validation_test.expected.output", tools = [":test_run_validation_test_runner"], ) + +cc_library( + name = "dataplane_validation", + srcs = ["dataplane_validation.cc"], + hdrs = ["dataplane_validation.h"], + deps = [ + ":output_writer", + ":packet_injection", + ":port_id_map", + ":switch_api", + ":test_run_validation", + ":test_vector", + ":test_vector_cc_proto", + ":user_provided_packet_test_vector", + ":validation_result", + "//gutil:status", + "//gutil:test_artifact_writer", + "//gutil:version", + "//lib/gnmi:gnmi_helper", + "//lib/gnmi:openconfig_cc_proto", + "//lib/p4rt:p4rt_port", + "//p4_pdpi:ir", + "//p4_pdpi:ir_cc_proto", + "//p4_pdpi:p4_runtime_session", + "//p4_pdpi:p4_runtime_session_extras", + "//p4_pdpi/packetlib:packetlib_cc_proto", + "//p4_symbolic/packet_synthesizer:packet_synthesizer_cc_proto", + "//tests/lib:switch_test_setup_helpers", + "//thinkit:mirror_testbed", + "@com_github_gnmi//proto/gnmi:gnmi_cc_proto", + "@com_github_google_glog//:glog", + "@com_github_p4lang_p4runtime//:p4runtime_cc_proto", + "@com_google_absl//absl/container:flat_hash_map", + "@com_google_absl//absl/container:flat_hash_set", + "@com_google_absl//absl/status", + "@com_google_absl//absl/status:statusor", + "@com_google_absl//absl/strings", + "@com_google_absl//absl/types:span", + "@com_google_protobuf//:protobuf", + ], +) diff --git a/dvaas/dataplane_validation.h b/dvaas/dataplane_validation.h new file mode 100644 index 00000000..c78807cf --- /dev/null +++ b/dvaas/dataplane_validation.h @@ -0,0 +1,279 @@ +// Library for validating dataplane behavior of a switch under test using +// automatically synthesized test packets. See go/dvaas for more details. + +/* Copyright 2024 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#ifndef PINS_DVAAS_DATAPLANE_VALIDATION_H_ +#define PINS_DVAAS_DATAPLANE_VALIDATION_H_ + +#include +#include +#include +#include +#include +#include + +#include "absl/container/flat_hash_map.h" +#include "absl/container/flat_hash_set.h" +#include "absl/status/statusor.h" +#include "absl/types/span.h" +#include "dvaas/output_writer.h" +#include "dvaas/packet_injection.h" +#include "dvaas/port_id_map.h" +#include "dvaas/switch_api.h" +#include "dvaas/test_run_validation.h" +#include "dvaas/test_vector.h" +#include "dvaas/test_vector.pb.h" +#include "dvaas/validation_result.h" +#include "google/protobuf/descriptor.h" +#include "gutil/test_artifact_writer.h" +#include "lib/p4rt/p4rt_port.h" +#include "p4_pdpi/ir.pb.h" +#include "p4_pdpi/packetlib/packetlib.pb.h" +#include "p4_symbolic/packet_synthesizer/packet_synthesizer.pb.h" +#include "thinkit/mirror_testbed.h" + +namespace dvaas { + +// -- User Facing API ---------------------------------------------------------- + +// P4 artifacts specifying the switch control plane API and its intended +// dataplane behavior. +struct P4Specification { + // P4-Symbolic is the packet generator that we use. Its P4Info and device + // configuration may need to be specifically modified to workaround + // potential P4-Symbolic issues. + p4::v1::ForwardingPipelineConfig p4_symbolic_config; + + // BMv2 is the switch simulator that we compare the dataplane results to. It + // is instantiated with a BMv2 compatible forwarding pipeline config + // containing a P4Info and a device configuration. These may need to be + // specifically modified for BMv2 due to some missing features, e.g. the + // lack of support for @p4runtime_translation. + p4::v1::ForwardingPipelineConfig bmv2_config; +}; + +// Specifies user-facing parameters of DVaaS. These are also the parameters that +// are likely to vary across tests. +struct DataplaneValidationParams { + // Parameters to control the comparison between the actual switch + // output and the expected switch output per input packet. + SwitchOutputDiffParams switch_output_diff_params; + + // Prefix to add to the names of artifacts written by DVaaS. + std::string artifact_prefix = "dvaas"; + + // Optional parameter that, if set, is used by DVaaS to generate a header to + // append to each artifact before writing to it. + std::optional> get_artifact_header; + + // If set, causes DVaaS to use the given P4Specification instead of inferring + // one from the SUT. + std::optional specification_override; + + // Max number of packets to send per second. If no rate is given, DVaaS will + // send packets as quickly as it can. + std::optional max_packets_to_send_per_second; + + // Optionally, a list of custom packet test vectors. If non-empty, automated + // test vector generation is disabled and only the given test vectors are used + // for validation. + // + // See `user_provided_packet_test_vector.h` for documentation on how to define + // valid test vectors. + std::vector packet_test_vector_override; + + // Optionally, can be used to override the default assumption that each SUT + // port is connected to a control switch port with the same OpenConfig + // interface name. + // NOTE: Not required for valid mirror testbeds. This is a workaround for + // non-standard testbeds only. + std::optional mirror_testbed_port_map_override; +}; + +// Forward declaration. See below for description. +class DataplaneValidationBackend; + +// Used to validate the dataplane behavior of a mirror testbed. See go/dvaas for +// more details. +// WARNING: This class is NOT thread-safe. +class DataplaneValidator { + public: + DataplaneValidator() = delete; + explicit DataplaneValidator( + std::unique_ptr backend) + : backend_(std::move(backend)) {} + + // Validates that the `testbed.Sut()` processes packets according to the + // P4Specification of the switch as follows: + // + // 1. Opens P4RT and gNMI connections to SUT and control switch. + // + // 2. Mirrors the SUT P4RT port ID <-> interface mapping to the control + // switch. If a port map override is provided, this step is skipped and the + // provided port map gets used. + // + // 3. Generates test packets that together satisfy some coverage goal, which + // can be tweaked using the `params`. By default, generates test packets to + // hit every table entry installed on the switch at least once. + // + // 4. Sends those test packets to the switch and a P4 simulator, where the + // simulator is initialized using the switch's P4Specification. + // + // 5. Validates that the switch forwards/punts/drops packets as the P4 + // simulator predicts. + // + // Preconditions: + // 1. Both switches must be configured with a P4Info and gNMI config. + // 2. Enabled ports must be up. + // + // Post-conditions on success: + // 1. The only entries installed on control switch will be those returned by + // `GetEntriesToPuntAllPackets`. + // 2. Any preexisting P4RT connections to SUT and control switch will be + // non-primary. + // 3. The gNMI configs will be unchanged. + // + // Returns an Ok status if dataplane validation succeeds, or an error status + // detailing invalid dataplane behaviors otherwise. + absl::StatusOr ValidateDataplane( + thinkit::MirrorTestbed& testbed, + const DataplaneValidationParams& params = {}); + + // Same as above `ValidateDataplane`, but has these differences: + // Preconditions: + // 1. The `sut` and `control_switch` P4RT connections must be primary. + // TODO: Remove this pre-condition. + // 2. Either a SUT <-> control switch P4RT port map must be passed in `params` + // or the P4RT port ID <-> interface mapping of the control switch in the + // gNMI config must be the same as the SUT. + // + // Post-conditions: + // 1. Pre-existing connections are left as they are. + // 2. gNMI configs will be unchanged. + absl::StatusOr ValidateDataplane( + SwitchApi& sut, SwitchApi& control_switch, + const DataplaneValidationParams& params = {}); + + // Returns statistics about all packets sent during the lifetime of the + // DataplaneValidator. If dataplane validation has failed, the returned + // statistics may be inaccurate and are instead lower bounds on the true + // values. + PacketStatistics GetCurrentPacketStatistics() const { + return packet_statistics_; + } + + private: + std::unique_ptr backend_; + // Used to write artifacts. + gutil::BazelTestArtifactWriter artifact_writer_; + // Records packet statistics during dataplane validation. + PacketStatistics packet_statistics_; +}; + +// -- Backend API -------------------------------------------------------------- +// NOTICE: This portion of the API is only for DVaaS maintainers. Users need not +// worry about anything below this line! +// ----------------------------------------------------------------------------- + +// Abstract internals of Dataplane Validator. Specifies those +// parameters that we expect to be constant throughout a system, as opposed to +// DataplaneValidationParams, which specifies those that we expect may change +// between tests. +// These are abstract for one or more of the following reasons: +// 1. Some functions (e.g. IsExpectedUnsolicitedPacket, +// GetEntriesToPuntAllPackets, and InferP4Specification) are non-portable in +// that they differ by system, but are unlikely to change between tests of +// the same system. Thus, there is no reason for users to implement these +// individually. +// 2. Some functions (e.g. SynthesizePackets and +// GeneratePacketTestVectors) do not +// yet have open-source implementations and thus need to be instantiated +// outside of tests. Ideally, these would disappear from the +// DataplaneValidationBackend as they become open-source and instead be +// integrated directly into the DVaaS implementation. +// +// NOTE: Users are not expected to implement this class! +class DataplaneValidationBackend { + public: + // Synthesizes packets to send to the switch. We don't want to be tied to a + // specific packet synthesis implementation (our current implementation is not + // even open-source yet), so DVaaS takes the synthesis function as an input + // parameter. + virtual absl::StatusOr< + std::vector> + SynthesizePackets(const pdpi::IrP4Info& ir_p4info, + const pdpi::IrTableEntries& ir_entries, + const p4::v1::ForwardingPipelineConfig& p4_symbolic_config, + absl::Span ports, + const OutputWriterFunctionType& write_stats) const = 0; + + // Generates a map of test ID to PacketTestVector with output prediction + // given a list of `synthesized_packets` for the given input (program, + // entries, ports, etc.). We don't want to be tied to a specific test vector + // generation implementation (the current implementation relies on a + // non-open-source BMv2 wrapper), so DVaaS takes the function as an input. + // + // Note: The packets and ports used as input in the returned test vectors + // should be slightly modified versions of the input `synthesize_packets`: + // 1. If the ingress port is not specified in the synthesized packet, + // `default_ingress_port` is used. + // 2. The payload of the original packet is tagged with the test vector ID. + // The tagged payload can be used associate the outputs of the device + // under test with its inputs. + // 3. The packet will be padded to minimum size and the computed fields + // recomputed. + virtual absl::StatusOr GeneratePacketTestVectors( + const pdpi::IrP4Info& ir_p4info, const pdpi::IrTableEntries& ir_entries, + const p4::v1::ForwardingPipelineConfig& bmv2_config, + absl::Span ports, + std::vector& + synthesized_packets, + const pins_test::P4rtPortId& default_ingress_port) const = 0; + + // Checks whether an unsolicited (i.e. without a tagged payload) packet + // received from SUT or control switch is expected. The logic that determines + // this is application dependent, so DVaaS takes this as an input. + virtual bool IsExpectedUnsolicitedPacket( + const packetlib::Packet& packet) const = 0; + + // Returns a set of entities that cause all received packets to be punted, + // given the `switch_p4info` installed on the switch. The test *will* install + // these entities on the control switch and the user *must* ensure that the + // entities cause *all* packets to be punted. Otherwise, test behavior is + // undefined. + virtual absl::StatusOr GetEntitiesToPuntAllPackets( + const pdpi::IrP4Info& switch_p4info) const = 0; + + // Returns the P4Specification that models the given `sut`. Used only if the + // `specification_override` parameter is unset. + // May query the SUT, but should not change it. + virtual absl::StatusOr InferP4Specification( + SwitchApi& sut) const = 0; + + virtual ~DataplaneValidationBackend() = default; +}; + +// Generates and returns test vectors using the backend functions +// `SynthesizePackets` and `GeneratePacketTestVectors`. Reads the table entries, +// P4Info, and relevant P4RT port IDs from the switch. +absl::StatusOr GenerateTestVectors( + const DataplaneValidationParams& params, SwitchApi& sut, + DataplaneValidationBackend& backend, gutil::TestArtifactWriter& writer); + +} // namespace dvaas + +#endif // PINS_DVAAS_DATAPLANE_VALIDATION_H_