def simulates_forwards(topo, a, b, field="vlan", edge_policy={}): """Determine if b simulates a up to field on one hop.""" p, pp = Consts("p pp", Packet) v, vv = Ints("v vv") # Z3 emits a warning about not finding a pattern for our quantification. # This is fine, so ignore it. set_option("WARNING", False) solv = Solver() solv.add(on_valid_port(topo, p)) # b doesn't need to forward packets on external links that don't satisfy the # ingress predicate edge_option = And(external_link(edge_policy, p), Not(edges_ingress(edge_policy, p))) solv.add( And( forwards(a, p, pp), ForAll([v, vv], Not(Or(forwards_with(b, p, {field: v}, pp, {field: vv}), edge_option)), patterns=[]), ) ) if solv.check() == unsat: set_option("WARNING", True) return None else: set_option("WARNING", True) return solv.model(), (p, pp), HEADER_INDEX
def simulates_forwards2(topo, a, b, field="vlan", edge_policy={}): """Determine if b simulates a up to field on two hop on topo.""" p, pp, q, qq = Consts("p pp q qq", Packet) v, vv, vvv = Ints("v vv, vvv") # Z3 emits a warning about not finding a pattern for our quantification. # This is fine, so ignore it. set_option("WARNING", False) solv = Solver() solv.add(on_valid_port(topo, p)) # b doesn't need to forward packets on external links that don't satisfy the # ingress predicate, but we only care about the first hop edge_option = And(external_link(edge_policy, p), Not(edges_ingress(edge_policy, p))) # This case breaks the And inside the ForAll because they're both False and # z3 can't handle that. # However, it does mean that they simulate each other, because neither # forwards packets, so just short-circuit. if forwards(b, p, pp) is False and forwards(b, q, qq) is False: return None c = And( forwards(a, p, pp), transfer(topo, pp, q), forwards(a, q, qq), ForAll( [v, vv, vvv], Not( Or( And( forwards_with(b, p, {field: v}, pp, {field: vv}), forwards_with(b, q, {field: vv}, qq, {field: vvv}), ), edge_option, ) ), ), ) solv.add(c) if solv.check() == unsat: set_option("WARNING", True) return None else: set_option("WARNING", True) return solv.model(), (p, pp), HEADER_INDEX