def __deepcopy__(self, memo): c = type(self).__new__(type(self)) memo[id(self)] = c d = c.__dict__ for k in self.__dict__: if k == "log": d[k] = self.log continue elif k == "state": d[k] = None continue elif k == "model_checker": d[k] = self.model_checker continue elif k == "communicationObjectUsed": d[k] = self.communicationObjectUsed continue elif k == "startActionExecution": d[k] = self.startActionExecution continue elif k == "finishActionExecution": d[k] = self.finishActionExecution continue elif k == "mod": d[k] = self.mod continue try: d[k] = copy.deepcopy(self.__dict__[k], memo) except RuntimeError: utils.crash(k) return c
def __deepcopy__(self, memo): cctxt = copy.deepcopy(self.ctxt, memo) c = type(self)(cctxt) memo[id(self)] = c d = c.__dict__ for k in self.__dict__: if k == "packet_in_cb": d[k] = self.packet_in_cb continue elif k == "datapath_leave_cb": d[k] = self.datapath_leave_cb continue elif k == "datapath_join_cb": d[k] = self.datapath_join_cb continue elif k == "flow_removed_cb": d[k] = self.flow_removed_cb continue elif k == "port_status_cb": d[k] = self.port_status_cb continue elif k == "ctxt": continue try: d[k] = copy.deepcopy(self.__dict__[k], memo) except RuntimeError: utils.crash(k) if hasattr(self, "custom_copy"): if memo["get_app_state"]: self.custom_copy(c, memo) else: utils.crash("custom copy not implemented in Component subclass") return c
def add_inputs(self, inputs): aux = [] count_good = 0 count_bad = 0 if isinstance(inputs, type({})): aux = [inputs["packet"]] elif isinstance(inputs, type([])): aux = map(lambda x: x["packet"], inputs) else: utils.crash("Unknown inputs provided: %s" % inputs) inputs = aux for p in inputs: if self.filter_src_mac: # sanity checks on the input packets macs = self.state.model.getClientMacAddresses() if p["src"] not in macs or p["dst"] not in macs or p[ "src"] != self.mymac or p["src"] == p["dst"]: count_bad += 1 continue ep = ethernet.ethernet("se.packet%d" % self.input_counter) ep.src = MacAddress(p["src"]) ep.dst = MacAddress(p["dst"]) ep.parsed = p["parsed"] ep.next = p["next"] ep.type = p["type"] ep.arr = p["arr"] self.input_counter += 1 count_good += 1 self.pkts[ep.name] = ep self.enableAction("send_packet", ep.name) self.log.info("Accepted %d new packets, discarded %d invalid packets" % (count_good, count_bad))
def __init__(self, opcode, stack, context): GenericOpCode.__init__(self, opcode[0]) if opcode[1] == "BINARY_MODULO": self.name = "%" elif opcode[1] == "COMPARE_OP": self.name = opcode[2] elif opcode[1] == "BINARY_AND": self.name = "&" elif opcode[1] == "BINARY_ADD": self.name = "+" elif opcode[1] == "BINARY_SUBTRACT": self.name = "-" elif opcode[1] == "BINARY_LSHIFT": self.name = "<<" elif opcode[1] == "BINARY_RSHIFT": self.name = ">>" elif opcode[1] == "BINARY_OR": self.name = "|" elif opcode[1] == "BINARY_XOR": self.name = "^" elif opcode[1] == "BINARY_MULTIPLY": self.name = "*" else: utils.crash("Unknown binary operator: %s" % str(opcode)) self.right = stack.pop() self.left = stack.pop()
def __init__(self, opcode, stack, context): GenericOpCode.__init__(self, opcode[0]) self.name = opcode[1] self.target = opcode[2] if not len(stack) > 0: utils.crash("Empty stack while parsing a conditional jump") self.condition = stack.pop()
def enqueuePacket(self, packet, inport): if self.ports[inport].of_status & openflow.OFPPS_LINK_DOWN: return # Drop packet try: self.ports[inport].queueIn(packet) except KeyError: utils.crash("Wrong topology: %s has no port named %s" % (self.name, inport)) self.enableAction("process_packet", skip_dup=True)
def __init__(self, opcode, stack, context): GenericOpCode.__init__(self, opcode[0]) if opcode[1] == "UNARY_NOT": self.name = "not" else: utils.crash("Unknown unary operator: %s" % str(opcode)) self.expr = stack.pop()
def testPoint(self, event_name, **args): for i in self.invariants: if hasattr(i, event_name + "_cb"): method = getattr(i, event_name + "_cb") try: method(**args) except TypeError: utils.crash("Invariant '%s', callback '%s' has wrong arguments. Passing %s" % (i.name, event_name+"_cb", str(args)))
def packet_sent_cb(self, model, sender, receiver, packet): if packet.packet_id == None: utils.crash("packet with no packet_id: %s" % packet) if packet.packet_id in self.packet_store: utils.crash("sending packet with duplicate ID: %s" % packet) else: self.packet_store[packet.packet_id] = [packet, 1] log.debug("sent packet: %s, 1" % packet.name)
def send_openflow(self, dp_id, buffer_id, packet, actions, inport=openflow.OFPP_CONTROLLER): if isinstance(actions, int) or isinstance(actions, long): # NOX API shortcut, does not follow OpenFlow specs, we translate actions = [[openflow.OFPAT_OUTPUT, [0, actions]]] if not isinstance(actions, list): utils.crash("Unknown action type") if (self.ctxt != None): self.ctxt.send_openflow(dp_id, buffer_id, packet, actions, inport)
def buildSTPExprFromStatement(self, stp, stmt, bitlen): """This function is recursive""" if isinstance(stmt, bc.BinaryOperator): STPLeft = self.buildSTPExprFromStatement(stp, stmt.left, bitlen) STPRight = self.buildSTPExprFromStatement(stp, stmt.right, bitlen) if stmt.name == "==": return stp.eqExpr(STPLeft, STPRight) if stmt.name == "&": return stp.bvAndExpr(STPLeft, STPRight) if stmt.name == "<": return stp.sbvLtExpr(STPLeft, STPRight) if stmt.name == ">": return stp.sbvGtExpr(STPLeft, STPRight) if stmt.name == "<=": return stp.sbvLeExpr(STPLeft, STPRight) if stmt.name == ">=": return stp.sbvGeExpr(STPLeft, STPRight) if stmt.name == "!=": return stp.notExpr(stp.eqExpr(STPLeft, STPRight)) else: utils.crash("Cannot build STP for unknown operator %s" % stmt.name) elif isinstance(stmt, bc.Attribute) or isinstance(stmt, bc.LocalReference) or isinstance(stmt, bc.GlobalReference) or isinstance(stmt, bc.Subscr): if stmt.isSymbolic(): sym_var = stmt.reference # could be an expression stpvars = sym_var.getSTPVariable() for name, var, stp_var in stpvars: self.stp_variables[name] = (var, stp_var) if isinstance(sym_var, SymbolicExpression): return stp_mod.ast2stp(sym_var.expr, sym_var.getBitLength()) else: return stpvars[0][2] else: v = long(stmt.value) # Try to get an int return stp_mod.int2stp(v, bitlen) elif isinstance(stmt, bc.FunctionCall): if stmt.name == "ord": # We know that our ord does nothing return self.buildSTPExprFromStatement(stp, stmt.params[0], bitlen) elif stmt.name[-7:] == "has_key": utils.crash("Cannot build STP for has_key call %s" % stmt.name) else: utils.crash("Cannot build STP for unknown function %s" % stmt.name) elif isinstance(stmt, bc.ConstantValue): v = long(stmt.reference) return stp_mod.int2stp(v, bitlen) elif isinstance(stmt, bc.UnaryOperator): if stmt.name == "not": e = self.buildSTPExprFromStatement(stp, stmt.expr, bitlen) if e.getType().isBool(): return stp_mod.notExpr(e) else: # make it boolean, stp does not like things like (a & 1) used as boolean expressions # so we transform the whole not expression to (a & 1) == 0 return stp_mod.eqExpr(e, stp_mod.int2stp(0, bitlen)) else: utils.crash("Unkown unary operator %s" % stmt.name) else: utils.crash("Cannot build STP for unknown class %s" % stmt.__class__.__name__)
def isStatementInteresting(self, stmt): if isinstance(stmt, ConditionalJump) and isinstance( stmt.condition, FunctionCall): utils.crash( "Function call in if statement, broken instrumentation") elif isinstance(stmt, ConditionalJump): return True else: return stmt.isSymbolic()
def __init__(self, opcode, stack, context): GenericOpCode.__init__(self, opcode[0]) if opcode[1] == "BUILD_TUPLE": self.name = "tuple" elif opcode[1] == "BUILD_LIST": self.name = "list" else: utils.crash("Unknown BuildList opcode") self.elems = [ stack.pop() for _i in range(0, opcode[2]) ]
def __init__(self, opcode, stack, context): GenericOpCode.__init__(self, opcode[0]) self.name = "Constant" if opcode[1] == "BUILD_MAP": self.reference = {} # ATTN: This is not a reference to the dict created by the interpreter elif opcode[1] == "LOAD_CONST": self.reference = opcode[2] else: utils.crash("Unknown constant type: %s" % opcode[1]) self.bitlen = 0
def testPoint(self, event_name, **args): for i in self.invariants: if hasattr(i, event_name + "_cb"): method = getattr(i, event_name + "_cb") try: method(**args) except TypeError: utils.crash( "Invariant '%s', callback '%s' has wrong arguments. Passing %s" % (i.name, event_name + "_cb", str(args)))
def buildZ3Expr(self): if self.result == None: utils.crash("This predicate has an unknown result: %s" % self) sym_expr = self._buildZ3Expr() if not is_bool(sym_expr): sym_expr = sym_expr != z3_wrap.int2BitVec(0, self.expr.getBitLength()) if not self.result: sym_expr = Not(sym_expr) return (True, sym_expr)
def process_command(self): """ Process a command from the controller """ self.create_new_state() command = self.command_queue.pop(0) if isinstance(command, PacketOutMessage): self.processPacketOutMessage(command) elif isinstance(command, FlowTableModificationMessage): self.processFlowTableModification(command) else: utils.crash("Switch received an unknown command: %s" % command) return len(self.command_queue) == 0
def __init__(self, opcode, stack, context): GenericOpCode.__init__(self, opcode[0]) self.name = "Constant" if opcode[1] == "BUILD_MAP": self.reference = { } # ATTN: This is not a reference to the dict created by the interpreter elif opcode[1] == "LOAD_CONST": self.reference = opcode[2] else: utils.crash("Unknown constant type: %s" % opcode[1]) self.bitlen = 0
def __init__(self, opcode, stack, context): GenericOpCode.__init__(self, opcode[0]) if opcode[1] == "BUILD_TUPLE": self.name = "tuple" elif opcode[1] == "BUILD_LIST": self.name = "list" else: utils.crash("Unknown BuildList opcode") self.elems = [] for _i in range(0, opcode[2]): self.elems.append(stack.pop())
def __init__(self, value=(0, 0, 0, 0)): if isinstance(value, IpAddress): value = value.data[:] elif isinstance(value, type(())): value = value[:] elif isinstance(value, str): value = value.split(".") value = map(lambda x: int(x), value) value = tuple(value) else: utils.crash("Creating an IpAddress from something unknown") self.data = value
def _getOpID(self, cb_id): """ returns tuple (context_id, op_id)""" cb_id = cb_id + 1 # No 0 if not cb_id != 0: utils.crash("cb_id must be different that zero") key = self.execution_context.filename + ":" + self.execution_context.name if key in self.unique_op_map.keys(): return (self.unique_op_map[key], cb_id) else: self.unique_op_map[key] = self.prime_generator.next() return (self.unique_op_map[key], cb_id)
def syn_packet_received_cb(self, model, receiver, packet): tcp_pkt = packet.find("tcp") if tcp_pkt == None: return if not tcp_pkt.flow_id in self.flows: utils.crash("unknown flow") entry = self.flows[tcp_pkt.flow_id] if entry[0] != packet.src: v = Violation(self, "wrong source MAC address rewriting") self.reportViolation(v) entry = (entry[0], packet.dst) self.flows[tcp_pkt.flow_id] = entry
def _getSTPVariables(self, expr): stp_vars = [] if isinstance(expr, ast.BinOp): stp_vars += self._getSTPVariables(expr.left) stp_vars += self._getSTPVariables(expr.right) elif isinstance(expr, SymbolicType): stp_vars += expr.getSTPVariable() elif isinstance(expr, int) or isinstance(expr, long): pass else: utils.crash("Node type not supported: %s" % expr) return stp_vars
def _do_symbolicEq(self, expr1, expr2): if type(expr1) != type(expr2): return False if isinstance(expr1, ast.BinOp): ret = self._do_symbolicEq(expr1.left, expr2.left) ret |= self._do_symbolicEq(expr1.right, expr2.right) return ret | (type(expr1.op) == type(expr2.op)) elif isinstance(expr1, SymbolicType): return expr1 is expr2 elif isinstance(expr1, int) or isinstance(expr1, long): return expr1 == expr2 else: utils.crash("Node type not supported: %s" % expr1)
def __deepcopy__(self, memo): ccnt = copy.deepcopy(self.cnt, memo) c = Context(ccnt) memo[id(self)] = c d = c.__dict__ for k in self.__dict__: if k == "cnt": continue try: d[k] = copy.deepcopy(self.__dict__[k], memo) except RuntimeError: utils.crash(k) return c
def packet_received_cb(self, model, receiver, packet, port): if receiver.name == "ctrl": return if packet.dst != MacAddress("ff:ff:ff:ff:ff:ff") and receiver.mymac != packet.dst: return if packet.packet_id == None: utils.crash("packet with no packet_id: %s" % packet) if not packet.packet_id in self.packet_store: utils.crash("packet received but never sent: %s" % packet) if self.packet_store[packet.packet_id][1] > 0: # if there was flooding, packet may arrive more times than it was sent self.packet_store[packet.packet_id][1] -= 1 log.debug("received packet: %s, %d" % (packet.name, self.packet_store[packet.packet_id][1]))
def _getSymVariables(self, expr): sym_vars = [] if isinstance(expr, ast.BinOp): sym_vars += self._getSymVariables(expr.left) sym_vars += self._getSymVariables(expr.right) elif isinstance(expr, SymbolicType): sym_vars += expr.getSymVariable() elif isinstance(expr, int) or isinstance(expr, long): pass else: utils.crash("Node type not supported: %s" % expr) return sym_vars
def __init__(self, value=(0, 0, 0, 0, 0, 0)): if isinstance(value, type("")): octets = value.split(":") octets = map(lambda x: int(x, 16), octets) value = octets elif isinstance(value, tuple): pass elif isinstance(value, MacAddress): value = value.data else: import pdb; pdb.set_trace() utils.crash("Creating a MacAddress from something unknown") self.data = tuple(map(lambda x: x, value))
def parse(self, cb, execution_context): """ components is stack, but at the end should contain a list of statements """ components = [] #log.debug("Parsing this codeblock: %s" % cb) while len(cb) > 0: op = cb.pop() if op[1] in OPS_IGNORE: pass elif op[1] in OPS: elem = OPS[op[1]](op, components, execution_context) components.append(elem) else: utils.crash("Opcode %s is unknown: %s" % (op[1], cb)) return components
def _findBitLength(self, expr): if isinstance(expr, ast.BinOp): l = self._findBitLength(expr.left) r = self._findBitLength(expr.right) if l > r: return l else: return r elif isinstance(expr, SymbolicType): return expr.getBitLength() elif isinstance(expr, int) or isinstance(expr, long): return 0 else: utils.crash("Node type not supported: %s" % expr)
def ack_packet_received_cb(self, model, receiver, packet): server_mac = receiver.mymac tcp_pkt = packet.find("tcp") if tcp_pkt == None: return if not tcp_pkt.flow_id in self.flows: utils.crash("unknown flow") entry = self.flows[tcp_pkt.flow_id] if entry[0] != packet.src: v = Violation(self, "wrong source MAC address rewriting") self.reportViolation(v) if entry[1] != server_mac: v = Violation(self, "packet matching one flow sent to another server") self.reportViolation(v)
def __init__(self, value=(0, 0, 0, 0, 0, 0)): if isinstance(value, type("")): octets = value.split(":") octets = map(lambda x: int(x, 16), octets) value = octets elif isinstance(value, tuple): pass elif isinstance(value, MacAddress): value = value.data else: import pdb pdb.set_trace() utils.crash("Creating a MacAddress from something unknown") self.data = tuple(map(lambda x: x, value))
def __init__(self, opcode, stack, context): StorageOpCode.__init__(self, opcode, stack, context) if not len(stack) > 0: utils.crash("Empty stack while parsing an attribute") self.prev = stack.pop() if hasattr(self.prev.reference, self.name): self.reference = getattr(self.prev.reference, self.name) if not self.isSymbolic() and self.shouldSaveValue(): try: self.value = copy.copy(self.reference) except TypeError: utils.crash("exception while copying this object: %s of type %s" % (self.reference, type(self.reference))) else: self.reference = None
def whichBranch(self, branch): """ To be called from the process being executed, this function acts as instrumentation. branch can be either True or False, according to the branch taken after the last conditional jump. """ # print branch, self.engine.tracer.execution_context.frame.f_back.f_code.co_name, self.check_constr_jump if self.tracer.inside_tracing_code: return if len(self.branch_result_stack) > 0: stmt = self.branch_result_stack.pop() self.addBranchAfterJump(stmt, branch) else: utils.crash( "Branch result without a conditional jump, problems with the whichBranch instrumentation" )
def send_openflow(self, dp_id, buffer_id, packet, actions, inport=openflow.OFPP_CONTROLLER): if isinstance(actions, int) or isinstance( actions, long ): # NOX API shortcut, does not follow OpenFlow specs, we translate actions = [[openflow.OFPAT_OUTPUT, [0, actions]]] if not isinstance(actions, list): utils.crash("Unknown action type") if (self.ctxt != None): self.ctxt.send_openflow(dp_id, buffer_id, packet, actions, inport)
def __init__(self, opcode, stack, context): GenericOpCode.__init__(self, opcode[0]) self.params = [] n_pos_params = opcode[2][0] n_kw_params = opcode[2][1] if len(stack) < n_pos_params + n_kw_params*2: utils.crash("Not enough elements on the stack for a function call. Required %d, available %d" % (n_pos_params + n_kw_params*2, len(stack))) for _p in range(n_kw_params): self.params.append(stack.pop()) stack.pop() # ignore the key for _p in range(n_pos_params): self.params.append(stack.pop()) self.params.reverse() self.fun_name = stack.pop() self.name = self.fun_name.name self.reference = self.fun_name.reference
def packet_received_cb(self, model, receiver, packet, port): if receiver.name == "ctrl": return if packet.dst != MacAddress( "ff:ff:ff:ff:ff:ff") and receiver.mymac != packet.dst: return if packet.packet_id == None: utils.crash("packet with no packet_id: %s" % packet) if not packet.packet_id in self.packet_store: utils.crash("packet received but never sent: %s" % packet) if self.packet_store[packet.packet_id][ 1] > 0: # if there was flooding, packet may arrive more times than it was sent self.packet_store[packet.packet_id][1] -= 1 log.debug("received packet: %s, %d" % (packet.name, self.packet_store[packet.packet_id][1]))
def __init__(self, opcode, stack, context): GenericOpCode.__init__(self, opcode[0]) self.name = opcode[2] if not len(stack) > 0: utils.crash("Empty stack while parsing an attribute") self.prev = stack.pop() if hasattr(self.prev.reference, self.name): self.reference = getattr(self.prev.reference, self.name) if not self.isSymbolic() and self.shouldSaveValue(): try: self.value = copy.copy(self.reference) except TypeError: utils.crash( "exception while copying this object: %s of type %s" % (self.reference, type(self.reference))) else: self.reference = None
def packet_received_cb(self, model, receiver, packet, port): log.debug("received packet: %s" % packet) if packet.name == "replier.mobility_inform": # information about move is distributed from this point # in time self.in_move = False if packet.packet_id == None: utils.crash("packet with no packet_id: %s" % packet) if not packet.packet_id in self.packet_store: # we are not tracking this packet return if packet.dst != MacAddress("ff:ff:ff:ff:ff:ff") and receiver.mymac != packet.dst: return if self.packet_store[packet.packet_id][1] > 0: # if there was flooding, a packet may arrive more times than it was sent self.packet_store[packet.packet_id][1] -= 1
def astToZ3Expr(expr, bitlen): if isinstance(expr, ast.BinOp): z3_l = astToZ3Expr(expr.left, bitlen) z3_r = astToZ3Expr(expr.right, bitlen) if isinstance(expr.op, ast.Add): return z3_l + z3_r elif isinstance(expr.op, ast.Sub): return z3_l - z3_r elif isinstance(expr.op, ast.Mult): return z3_l * z3_r elif isinstance(expr.op, ast.LShift): return z3_l << z3_r elif isinstance(expr.op, ast.RShift): return z3_l >> z3_r elif isinstance(expr.op, ast.BitXor): return z3_l ^ z3_r elif isinstance(expr.op, ast.BitOr): return z3_l | z3_r elif isinstance(expr.op, ast.BitAnd): return z3_l & z3_r elif isinstance(expr.op, ast.Eq): return z3_l == z3_r elif isinstance(expr.op, ast.NotEq): return z3_l != z3_r elif isinstance(expr.op, ast.Lt): return z3_l < z3_r elif isinstance(expr.op, ast.Gt): return z3_l > z3_r elif isinstance(expr.op, ast.LtE): return z3_l <= z3_r elif isinstance(expr.op, ast.GtE): return z3_l >= z3_r else: utils.crash( "Unknown BinOp during conversion from ast to Z3 (expressions): %s" % expr.op) elif isinstance(expr, SymbolicExpression): return astToZ3Expr(expr.expr, bitlen) elif isinstance(expr, SymbolicType): return expr.getSymVariable()[0][2] elif isinstance(expr, int) or isinstance(expr, long): return int2BitVec(expr, bitlen) else: utils.crash( "Unknown node during conversion from ast to stp (expressions): %s" % expr)
def runAction(self, action): assert action in self.enabled_actions if not hasattr(self, action.target): raise NotImplementedError(action.target) cb = getattr(self, action.target) self.startActionExecution(self, action) ret = cb(*action.args) if ret == None: self.finishActionExecution() utils.crash("action did not return valid value!") # self.log.debug("Node %s Enabled actions: %s" % (self.name,self.enabled_actions)) if ret == True: self.enabled_actions.remove(action) # self.log.debug("Node %s Enabled actions: %s" % (self.name,self.enabled_actions)) self.finishActionExecution()
def __deepcopy__(self, memo): c = InvariantDispatcher(self.model_checker) memo[id(self)] = c d = c.__dict__ for k in self.__dict__: if k == "model_checker": continue elif k == "violation_counter": d[k] = self.violation_counter continue try: d[k] = copy.deepcopy(self.__dict__[k], memo) except RuntimeError: utils.crash(k) for i in c.invariants: i.updateDispatcher(c) return c
def astToZ3Expr(expr, bitlen): if isinstance(expr, ast.BinOp): z3_l = astToZ3Expr(expr.left, bitlen) z3_r = astToZ3Expr(expr.right, bitlen) if isinstance(expr.op, ast.Add): return z3_l + z3_r elif isinstance(expr.op, ast.Sub): return z3_l - z3_r elif isinstance(expr.op, ast.Mult): return z3_l * z3_r elif isinstance(expr.op, ast.LShift): return z3_l << z3_r elif isinstance(expr.op, ast.RShift): return z3_l >> z3_r elif isinstance(expr.op, ast.BitXor): return z3_l ^ z3_r elif isinstance(expr.op, ast.BitOr): return z3_l | z3_r elif isinstance(expr.op, ast.BitAnd): return z3_l & z3_r elif isinstance(expr.op, ast.Eq): return z3_l == z3_r elif isinstance(expr.op, ast.NotEq): return z3_l != z3_r elif isinstance(expr.op, ast.Lt): return z3_l < z3_r elif isinstance(expr.op, ast.Gt): return z3_l > z3_r elif isinstance(expr.op, ast.LtE): return z3_l <= z3_r elif isinstance(expr.op, ast.GtE): return z3_l >= z3_r else: utils.crash("Unknown BinOp during conversion from ast to Z3 (expressions): %s" % expr.op) elif isinstance(expr, SymbolicExpression): return astToZ3Expr(expr.expr,bitlen) elif isinstance(expr, SymbolicType): return expr.getSymVariable()[0][2] elif isinstance(expr, int) or isinstance(expr, long): return int2BitVec(expr, bitlen) else: utils.crash("Unknown node during conversion from ast to stp (expressions): %s" % expr)
def processActions(self, packet, actions, inport): """Process a set of actions on the packet""" for action in actions: if action[0] == openflow.OFPAT_OUTPUT: port = action[1][1] if port < openflow.OFPP_MAX: peer = self.getPeer(port) if peer == None: continue # Skip disconnected port self.enqueuePacketToNode(peer, packet.copy(), self.getPeerPort(port)) self.state.testPoint("switch_sent_packet_on_port", switch=self, packet=packet, port=port) elif port == openflow.OFPP_FLOOD: self.state.testPoint("switch_flood_packet_start", switch=self, packet=packet) for port in self.ports: if port == inport: continue # Skip the inport peer = self.getPeer(port) if peer == None: continue # Skip disconnected port self.enqueuePacketToNode(peer, packet.copy(), self.getPeerPort(port)) self.state.testPoint("switch_sent_packet_on_port", switch=self, packet=packet, port=port) elif port == openflow.OFPP_CONTROLLER: self.sendQueryToController(packet, inport, openflow.OFPR_ACTION, action[1][0]) elif port == openflow.OFPP_IN_PORT: peer = self.getPeer(inport) if peer == None: continue self.enqueuePacketToNode(peer, packet.copy(), self.getPeerPort(inport)) self.state.testPoint("switch_sent_packet_on_port", switch=self, packet=packet, port=inport) else: utils.crash("Unknown port action: 0x%x" % port) elif action[0] == openflow.OFPAT_SET_DL_SRC: # Set Ethernet source address packet.src = MacAddress(action[1]) elif action[0] == openflow.OFPAT_SET_NW_SRC: # Set IPv4 source address packet.next.srcip = IpAddress(action[1]) # We assume the next is an ipv4 elif action[0] == openflow.OFPAT_SET_DL_DST: # Set Ethernet destination address packet.dst = MacAddress(action[1]) elif action[0] == openflow.OFPAT_SET_NW_DST: # Set IPv4 source address packet.next.dstip = IpAddress(action[1]) # We assume the next is an ipv4 else: utils.crash("Action not implemented: %x" % action[0])