1 /*******************************************************************************
2 * Copyright (c) 2017 Politecnico di Torino and others.
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Apache License, Version 2.0
6 * which accompanies this distribution, and is available at
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *******************************************************************************/
9 package it.polito.verigraph.mcnet.components;
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.List;
15 import com.microsoft.z3.BoolExpr;
16 import com.microsoft.z3.Context;
17 import com.microsoft.z3.DatatypeExpr;
18 import com.microsoft.z3.Expr;
19 import com.microsoft.z3.IntExpr;
20 import com.microsoft.z3.Solver;
21 import com.microsoft.z3.Z3Exception;
22 import it.polito.verigraph.mcnet.components.Core;
23 import it.polito.verigraph.mcnet.components.NetContext;
24 import it.polito.verigraph.mcnet.components.NetworkObject;
25 import it.polito.verigraph.mcnet.components.Tuple;
27 /**Model for a network, encompasses routing and wiring
31 public class Network extends Core{
35 List<BoolExpr> constraints;
36 public List<NetworkObject> elements;
40 public Network(Context ctx,Object[]... args) {
45 protected void init(Context ctx, Object[]... args) {
47 this.nctx = (NetContext) args[0][0];
48 constraints = new ArrayList<BoolExpr>();
49 elements = new ArrayList<NetworkObject>();
53 /**Composes the network linking the configured network objects
57 public void attach (NetworkObject ... elements){
58 for(NetworkObject el : elements)
59 this.elements.add(el);
63 protected void addConstraints(Solver solver) {
65 BoolExpr[] constr = new BoolExpr[constraints.size()];
66 solver.add(constraints.toArray(constr));
67 } catch (Z3Exception e) {
73 * Specify host to address mapping.
74 * Handles the case in which we have more than one address for a node
77 public void setAddressMappings(ArrayList<Tuple<NetworkObject,ArrayList<DatatypeExpr>>> addrmap){
78 // Set address mapping for nodes.
79 for (Tuple<NetworkObject,ArrayList<DatatypeExpr>> entry : addrmap) {
80 NetworkObject node=entry._1;
81 List<DatatypeExpr> addr=entry._2;
82 Expr a_0 = ctx.mkConst(node+"_address_mapping_a_0",nctx.address);
83 ArrayList<BoolExpr> or_clause = new ArrayList<BoolExpr>();
85 // Constraint 1 addrToNode(foreach ad in addr) = node
86 for (DatatypeExpr ad : addr){
87 constraints.add(ctx.mkEq(nctx.addrToNode.apply(ad), node.getZ3Node()));
88 or_clause.add(ctx.mkEq(a_0,ad));
90 // System.out.println("Constraints mapping: " + (ctx.mkEq(nctx.addrToNode.apply(ad), node.getZ3Node())));
93 BoolExpr[] orClause = new BoolExpr[or_clause.size()];
95 // Constraint 2nodeHasAddr(node, a_0) == Or(foreach ad in addr (a_0 == ad))
96 // Note we need the iff here to make sure that we set nodeHasAddr to false
97 // for other addresses.
98 constraints.add(ctx.mkForall(new Expr[]{a_0},
99 ctx.mkEq(ctx.mkOr(or_clause.toArray(orClause)), nctx.nodeHasAddr.apply(node.getZ3Node(), a_0)),1,null,null,null,null));
103 //System.out.println("Constraints mapping: " + constraints);
109 * Don't forward packets addressed to node
112 public void saneSend(NetworkObject node){
113 Expr n_0 = ctx.mkConst(node+"_saneSend_n_0", nctx.node);
114 Expr p_0 = ctx.mkConst(node+"_saneSend_p_0", nctx.packet);
115 IntExpr t_0 = ctx.mkIntConst(node+"_saneSend_t_0");
117 //Constraint send(node, n_0, p, t_0) -> !nodeHasAddr(node, p.dest)
119 ctx.mkForall(new Expr[]{n_0, p_0, t_0},
120 ctx.mkImplies((BoolExpr)nctx.send.apply(node.getZ3Node(),n_0, p_0, t_0),
121 ctx.mkNot((BoolExpr)nctx.nodeHasAddr.apply( node.getZ3Node(),
122 nctx.pf.get("dest").apply(p_0)))),1,null,null,null,null));
126 * Node sends all traffic through gateway
130 public void setGateway (NetworkObject node, NetworkObject gateway){
131 // SetGateway(self, node, gateway): All packets from node are sent through gateway
132 Expr n_0 = ctx.mkConst(node+"_gateway_n_0", nctx.node);
133 Expr p_0 = ctx.mkConst(node+"_gateway_p_0", nctx.packet);
134 IntExpr t_0 = ctx.mkIntConst(node+"_gateway_t_0");
136 //Constraint send(node, n_0, p_0, t_0) -> n_0 = gateway
138 ctx.mkForall(new Expr[]{n_0, p_0, t_0},
140 (BoolExpr)nctx.send.apply(node.getZ3Node(), n_0, p_0, t_0),
141 ctx.mkEq(n_0,gateway.getZ3Node())),1,null,null,null,null));
143 // constraints.add(ctx.mkForall(new Expr[]{n_0, p_0, t_0},
144 // ctx.mkImplies((BoolExpr)nctx.recv.apply(n_0, node.getZ3Node(), p_0, t_0),
145 // ctx.mkEq(n_0,gateway.getZ3Node())),1,null,null,null,null));
149 * Assigns a specific routing table to a network object. Routing entries in the form: address -> node
151 * @param routing_table
153 public void routingTable (NetworkObject node,ArrayList<Tuple<DatatypeExpr,NetworkObject>> routing_table){
154 compositionPolicy(node,routing_table);
158 * Composition policies steer packets between middleboxes.
162 public void compositionPolicy (NetworkObject node,ArrayList<Tuple<DatatypeExpr,NetworkObject>> policy){
163 //Policy is of the form predicate -> node
164 Expr p_0 = ctx.mkConst(node+"_composition_p_0", nctx.packet);
165 Expr n_0 = ctx.mkConst(node+"_composition_n_0", nctx.node);
166 Expr t_0 = ctx.mkIntConst(node+"_composition_t_0");
168 HashMap<String,ArrayList<BoolExpr>> collected = new HashMap<String,ArrayList<BoolExpr>>();
169 HashMap<String,NetworkObject> node_dict = new HashMap<String,NetworkObject>();
171 for(int y=0;y<policy.size();y++){
172 Tuple<DatatypeExpr,NetworkObject> tp = policy.get(y);
173 if(collected.containsKey(""+tp._2)) collected.get(""+tp._2).add(nctx.destAddrPredicate(p_0,tp._1));
175 ArrayList<BoolExpr> alb = new ArrayList<BoolExpr>();
176 alb.add(nctx.destAddrPredicate(p_0,tp._1));
177 collected.put(""+tp._2,alb);
180 node_dict.put(""+tp._2, tp._2);
183 // System.out.println("collected: " + collected);
185 //Constraintforeach rtAddr,rtNode in rt( send(node, n_0, p_0, t_0) &&
186 //Or(foreach rtAddr in rt destAddrPredicate(p_0,rtAddr)) -> n_0 == rtNode )
187 for (Map.Entry<String,ArrayList<BoolExpr>> entry : collected.entrySet()) {
188 BoolExpr[] pred = new BoolExpr[entry.getValue().size()];
189 predicates = ctx.mkOr(entry.getValue().toArray(pred));
191 constraints.add(ctx.mkForall(new Expr[]{n_0, p_0, t_0},
192 ctx.mkImplies(ctx.mkAnd((BoolExpr)nctx.send.apply(node.getZ3Node(), n_0, p_0, t_0), predicates),
193 ctx.mkEq(n_0, node_dict.get(entry.getKey()).getZ3Node())),1,null,null,null,null));
194 /*System.out.println("cnstraints: " + (ctx.mkForall(new Expr[]{n_0, p_0, t_0},
195 ctx.mkImplies(ctx.mkAnd((BoolExpr)nctx.send.apply(node.getZ3Node(), n_0, p_0, t_0), predicates),
196 ctx.mkEq(n_0, node_dict.get(entry.getKey()).getZ3Node())),1,null,null,null,null)));*/
198 //System.out.println("constraints composition policy: " + constraints);
203 * Routing entries are in the form: address -> node. Also allows packet to be sent to another box for further processing
205 * @param routing_table
208 public void routingTableShunt (NetworkObject node,ArrayList<Tuple<DatatypeExpr,NetworkObject>> routing_table,NetworkObject shunt_node){
209 compositionPolicyShunt(node,routing_table,shunt_node);
213 * Composition policies steer packets between middleboxes.Policy is in the form: predicate -> node
215 * @param routing_table
218 public void compositionPolicyShunt (NetworkObject node,ArrayList<Tuple<DatatypeExpr,NetworkObject>> routing_table,NetworkObject shunt_node){
219 Expr p_0 = ctx.mkConst(node+"_composition_p_0", nctx.packet);
220 Expr n_0 = ctx.mkConst(node+"_composition_n_0", nctx.node);
221 Expr t_0 = ctx.mkIntConst(node+"_composition_t_0");
223 HashMap<String,ArrayList<BoolExpr>> collected = new HashMap<String,ArrayList<BoolExpr>>();
224 HashMap<String,NetworkObject> node_dict = new HashMap<String,NetworkObject>();
226 for(int y=0;y<routing_table.size();y++){
227 Tuple<DatatypeExpr,NetworkObject> tp = routing_table.get(y);
228 if(collected.containsKey(""+tp._2)) collected.get(""+tp._2).add(nctx.destAddrPredicate(p_0,tp._1));
230 ArrayList<BoolExpr> alb = new ArrayList<BoolExpr>();
231 alb.add(nctx.destAddrPredicate(p_0,tp._1));
232 collected.put(""+tp._2,alb);
234 node_dict.put(""+tp._2, tp._2);
237 //Constraintforeach rtAddr,rtNode in rt( send(node, n_0, p_0, t_0) &&
238 //Or(foreach rtAddr in rt destAddrPredicate(p_0,rtAddr)) -> n_0 == rtNode )
239 for (Map.Entry<String,ArrayList<BoolExpr>> entry : collected.entrySet()) {
240 BoolExpr[] pred = new BoolExpr[entry.getValue().size()];
241 predicates = ctx.mkOr(entry.getValue().toArray(pred));
243 constraints.add(ctx.mkForall(new Expr[]{n_0, p_0, t_0},
244 ctx.mkImplies(ctx.mkAnd((BoolExpr)nctx.send.apply(node.getZ3Node(), n_0, p_0, t_0), predicates),
245 ctx.mkOr(ctx.mkEq(n_0, node_dict.get(entry.getKey()).getZ3Node()),ctx.mkEq(n_0, shunt_node.getZ3Node()))),1,null,null,null,null));
250 // public void SimpleIsolation (NetworkObject node, ArrayList<DatatypeExpr> addresses){
251 // Expr p = ctx.mkConst(node+"_s_p", nctx.packet);
252 // Expr n = ctx.mkConst(node+"_s_n", nctx.node);
253 // IntExpr t = ctx.mkInt(node+"_s_t");
255 // BoolExpr[] a_pred= new BoolExpr[addresses.size()];
256 // for(int y=0;y<addresses.size();y++){
257 // DatatypeExpr de = addresses.get(y);
258 // a_pred[y] = ctx.mkOr(ctx.mkEq(nctx.pf.get("src").apply(p), de),ctx.mkEq(nctx.pf.get("dest").apply(p), de));
262 // ctx.mkForall(new Expr[]{p, n, t},
263 // ctx.mkImplies((BoolExpr)nctx.recv.apply(n, node.getZ3Node(), p, t),
264 // ctx.mkOr(a_pred)),1,null,null,null,null));
266 // ctx.mkForall(new Expr[]{p, n, t},
267 // ctx.mkImplies((BoolExpr)nctx.send.apply(node.getZ3Node(), n, p, t),
268 // ctx.mkOr(a_pred)),1,null,null,null,null));
273 * Set isolation constraints on a node.
274 * Doesn't need to be set but useful when interfering policies are in play.
279 public void SetIsolationConstraint ( NetworkObject node, ArrayList<NetworkObject> adjacencies){
281 Expr n_0 = ctx.mkConst(node+"_isolation_n_0", nctx.node);
282 Expr p_0 = ctx.mkConst(node+"_isolation_p_0", nctx.packet);
283 IntExpr t_0 = ctx.mkInt(node+"_isolation_t_0");
285 BoolExpr[] adj = new BoolExpr[adjacencies.size()];
286 for(int y=0;y<adjacencies.size();y++){
287 NetworkObject no = adjacencies.get(y);
288 adj[y] = ctx.mkEq(n_0,no.getZ3Node());
290 BoolExpr clause = ctx.mkOr(adj);
292 constraints.add(ctx.mkForall(new Expr[]{n_0, p_0, t_0},
293 ctx.mkImplies((BoolExpr)nctx.send.apply(node.getZ3Node(), n_0, p_0, t_0),
294 clause),1,null,null,null,null));
295 constraints.add(ctx.mkForall(new Expr[]{n_0, p_0, t_0},
296 ctx.mkImplies((BoolExpr)nctx.recv.apply(n_0, node.getZ3Node(), p_0, t_0),
297 clause),1,null,null,null,null));
301 * Return all currently attached endhosts
302 * @return NetworkObject
304 public List<String> EndHosts(){
305 List<String> att_nos = new ArrayList<String>();
306 for(NetworkObject el :elements){
308 //System.out.println("el: "+el);
309 att_nos.add(el.getZ3Node().toString());