def check(self, dpid): datapath = self.datapaths[dpid] ofp = datapath.ofproto parser = datapath.ofproto_parser #this is the flowtable to check oriFlowtable = self.flowTables[dpid] for i in range(1, topo.switchNum + 1): self.ready[i] = 0 for port in range(1, topo.maxPort[dpid] + 1): if topo.isSwitch(dpid, port): remoteSwitchID = topo.getRemoteSwitch(dpid, port) remotePort = topo.getRemotePort(dpid, port) #request toTable self.requestFlowTable(self.datapaths[remoteSwitchID], topo.getToTableID(remoteSwitchID, remotePort)) #request fromTable self.requestFlowTable(self.datapaths[remoteSwitchID], topo.getFromTableID(remoteSwitchID, remotePort)) print 'request send' #check if all counter tables are ready while not self.isReady(dpid): print 'not ready' hub.sleep(1) print 'ready to check' for rule in oriFlowtable: match = rule.match instruction = rule.instructions[0] #forward rule if isinstance(instruction, parser.OFPInstructionActions): forwardPort = instruction.actions[0].port #ignore broadcast rule if forwardPort > topo.maxPort[dpid]: continue #get the sum of in-packet inPacket = 0 if "in_port" in rule.match: #match field is port inPort = rule.match["in_port"] remoteSwitchID = topo.getRemoteSwitch(dpid, inPort) remotePort = topo.getRemotePort(dpid, port) toTableID = topo.getToTableID(remoteSwitchID, remotePort) inPacket = self.sumAllCounters(self.counterTables[remoteSwitchID][toTableID]) elif "ipv4_dst" in rule.match: #match field is ipv4 for port in range(1, topo.maxPort[dpid] + 1): if topo.isSwitch(dpid, port): remoteSwitchID = topo.getRemoteSwitch(dpid, port) remotePort = topo.getRemotePort(dpid, port) toTableID = topo.getToTableID(remoteSwitchID, remotePort) counterRule = self.findRule(match, self.counterTables[remoteSwitchID][toTableID]) print counterRule.packet_count, "packets from switch", remoteSwitchID inPacket += counterRule.packet_count print "sum of in-packet:", inPacket ''' #get the sum of out-packet (real) remoteSwitchID = topo.getRemoteSwitch(dpid, forwardPort) remotePort = topo.getRemotePort(dpid, forwardPort) fromTableID = topo.getFromTableID(remoteSwitchID, remotePort) counterRule = self.findRule(match, self.counterTables[remoteSwitchID][fromTableID]) outPacket = counterRule.packet_count ''' #get the sum of out-packet (fake) remoteSwitchID = topo.getRemoteSwitch(dpid, forwardPort) remotePort = topo.getRemotePort(dpid, forwardPort) fromTableID = topo.getFromTableID(remoteSwitchID, remotePort) outPacket = self.sumAllCounters(self.counterTables[remoteSwitchID][fromTableID]) print "out-packet:", outPacket ''' if rule.action == fowarding: dst_switch = table_B.action.out_dst sum = 0 #count the sum of in-packet for all injacent switch of B except dst_switch: get their to_B table for t in all to_B tables: for rules r in table t: if r.match_field == match: sum += counter # for all rules r in dst_switch.from_B table: if r.match_field == match: if (r.counter == sum): this rule passed the test else: this rule failed the test #can break and assume this switch is compromised else if rule.action == dropping: for all injacent switches of B: get their from_B table for all table t in all from_B table: for all rules r in table t: if r.match_field == match: if counter != 0: boooo! ''' return True
def _flow_stats_reply_handler(self, ev): body = ev.msg.body datapath = ev.msg.datapath dpid = datapath.id ofp = datapath.ofproto parser = datapath.ofproto_parser #add rule if not self.isFinish(): #save the original flow table self.flowTables[dpid] = body #create default rules for every table on this switch for port in range(1, topo.maxPort[dpid] + 1): if topo.isSwitch(dpid, port): #add forwarding rule on toTable on this switch toTableID = topo.getToTableID(dpid, port) adder.addFWDefaultRule(self.datapaths[dpid], toTableID, port) #add goto main table rule on fromTable on this switch fromTableID = topo.getFromTableID(dpid, port) adder.addGTDefaultRule(self.datapaths[dpid], fromTableID, topo.getMainTableID(dpid)) #add goto fromTable rule on t0 adder.addGTRuleByPort(self.datapaths[dpid], 0, port, fromTableID) #add default rule on table 0, so packet from host won't ask controller adder.addGTDefaultRule(self.datapaths[dpid], 0, topo.getMainTableID(dpid)) #process each rule for rule in body: print rule instruction = rule.instructions[0] #forward rule if isinstance(instruction, parser.OFPInstructionActions): forwardPort = rule.instructions[0].actions[0].port if not 1 <= forwardPort <= 255: continue for port in range(1, topo.maxPort[dpid] + 1): if topo.isSwitch(dpid, port): remoteSwitchID = topo.getRemoteSwitch(dpid, port) remotePort = topo.getRemotePort(dpid, port) #add forwarding rule on toTable on remote switch toTableID = topo.getToTableID(remoteSwitchID, remotePort) adder.addFWRuleByMatch(self.datapaths[remoteSwitchID], toTableID, rule.match, remotePort) #add goto main table rule on fromTable on remote switch fromTableID = topo.getFromTableID(remoteSwitchID, remotePort) adder.addGTRuleByMatch(self.datapaths[remoteSwitchID], fromTableID, rule.match, topo.getMainTableID(remoteSwitchID)) #add goto toTable rule to main table on this switch mainTableID = topo.getMainTableID(dpid) forwardPort = rule.instructions[0].actions[0].port toTableID = topo.getToTableID(dpid, forwardPort) adder.addGTRuleByMatch(self.datapaths[dpid], mainTableID, rule.match, toTableID) #delete this rule on t0 adder.removeRule(self.datapaths[dpid], rule) #goto table rule else: pass self.finish[dpid] = True #save table to check else: tableID = body[0].table_id self.counterTables[dpid][tableID] = body self.ready[dpid] += 1 print 'table', tableID, 'on switch', dpid, 'is received'