def forward_packet(self, in_port, out_port, data): actions = [OFPActionOutput(out_port)] out = OFPPacketOut(datapath=self.dp, buffer_id=ofproto_v1_3.OFP_NO_BUFFER, in_port=in_port, actions=actions, data=data) self.dp.send_msg(out)
def switch_features_handler(self, ev): datapath = ev.msg.datapath # install the table-miss flow entry. match = OFPMatch() actions = [OFPActionOutput(ofproto_v1_3.OFPP_CONTROLLER, ofproto_v1_3.OFPCML_NO_BUFFER)] self.add_flow(datapath, 0, match, actions)
def handle(self, in_port, data): pkt = packet.Packet(data) eth_pkt = pkt.get_protocol(ethernet.ethernet) ports = self.get_forwarding_ports(in_port, eth_pkt) self.forward_packet(in_port, ports[0], data) for port in ports: match = OFPMatch(in_port=in_port, eth_dst=eth_pkt.dst) actions = [OFPActionOutput(port)] self.add_flow(10, match, actions) print 'add flow for %s from port %s to %s' % (self.dp.id,in_port, port)
def handle(self, in_port, data): pkt = packet.Packet(data) eth_pkt = pkt.get_protocol(ethernet.ethernet) self.host_table[eth_pkt.src] = in_port if eth_pkt.dst in self.host_table: port = self.host_table[eth_pkt.dst] match = OFPMatch(in_port=in_port, eth_dst=eth_pkt.dst) actions = [OFPActionOutput(port)] self.add_flow(10, match, actions) self.forward_packet(in_port, port, data) else: self.forward_packet(in_port, ofproto_v1_3.OFPP_FLOOD, data)
def test_convert_instructions(self): """ Test converting instructions from ryu """ ryu_inst = [OFPInstructionWriteMetadata(0x56, 0xff)] inst = Instructions() inst.write_metadata = (0x56, 0xff) self.assertEqual(instructions_from_ryu(ryu_inst), inst) ryu_inst = [OFPInstructionGotoTable(6)] inst = Instructions() inst.goto_table = 6 self.assertEqual(instructions_from_ryu(ryu_inst), inst) output = OFPActionOutput(1) ryu_inst = [OFPInstructionActions(OFPIT_APPLY_ACTIONS, [output])] inst = Instructions() inst.apply_actions = ActionList([('OUTPUT', 1)]) self.assertEqual(instructions_from_ryu(ryu_inst), inst) output = OFPActionOutput(2) ryu_inst = [OFPInstructionActions(OFPIT_WRITE_ACTIONS, [output])] inst = Instructions() inst.write_actions = ActionSet([('OUTPUT', 2)]) self.assertEqual(instructions_from_ryu(ryu_inst), inst)
def _handle_switch_features(self, event): """ Installs the default flow rule for every switch that connects to the controller :param event: The SwitchFeatures event :type event: EventOFPSwitchFeatures :return: None :rtype: None """ datapath = event.msg.datapath self.logger.debug("[S{}] SwitchFeatures Event".format(datapath.id)) self.switches[datapath.id] = datapath self.program_flow(datapath, OFPMatch(), [OFPActionOutput(OFPP_CONTROLLER)], 0, 0, 0) datapath.send_msg(OFPSetConfig(datapath, OFPC_FRAG_NORMAL, 0xffff)) self.handle_switch_features(event)
def test_convert_flow(self): """ Test converting OFPFlowMod and OFPFlowStats from ryu """ ryu_match = OFPMatch(ipv4_src=1, eth_type=0x8100, vlan_vid=0x1100) ryu_write_actions = OFPInstructionActions(OFPIT_WRITE_ACTIONS, [ OFPActionPopVlan(), OFPActionSetField(eth_dst="10:10:10:10:10:10"), OFPActionOutput(7) ]) ryu_instructions = [ OFPInstructionActions(OFPIT_CLEAR_ACTIONS, []), ryu_write_actions, OFPInstructionGotoTable(9), OFPInstructionWriteMetadata(0x99, 0xff) ] ryu_flow_mod = OFPFlowMod(datapath=None, cookie=0xABCD, table_id=3, command=OFPFC_ADD, priority=789, match=ryu_match, instructions=ryu_instructions) ryu_flow_stats = OFPFlowStats(cookie=0xABCD, table_id=3, priority=789, match=ryu_match, instructions=ryu_instructions) match = Match([("IPV4_SRC", 1, None), ("ETH_TYPE", 0x8100, None), ("VLAN_VID", 0x1100, None)]) instructions = Instructions() instructions.goto_table = 9 instructions.clear_actions = True instructions.write_actions.append("POP_VLAN", None) instructions.write_actions.append("SET_FIELD", ("ETH_DST", 0x101010101010)) instructions.write_actions.append("OUTPUT", 7) instructions.write_metadata = (0x99, 0xff) rule = Rule(priority=789, cookie=0xABCD, table=3, match=match, instructions=instructions) self.assertEqual(rule_from_ryu(ryu_flow_stats), rule) self.assertEqual(rule_from_ryu(ryu_flow_mod), rule)
def send_pkt(self, datapath, data, port=OFPP_FLOOD): """ Convenience method that instructs a switch to forward a packet from the controller. :param datapath: The datapath to the switch from which to send :type datapath: Datapath :param data: The data to forward :type data: :param port: The port on which to forward :type port: int """ self.logger.debug("[S{}] Forwarding packet on port {}".format( datapath.id, port)) out = OFPPacketOut(datapath=datapath, actions=[OFPActionOutput(port)], in_port=OFPP_CONTROLLER, data=data, buffer_id=OFP_NO_BUFFER) datapath.send_msg(out)
def handle_packet_in(self, event): """ Installs flow rules for incoming packets using Dijkstra :param event: The PacketIn event :type event: EventOFPPacketIn :return: Any generated flow IDs :rtype: list """ message = event.msg datapath = message.datapath switch_id = datapath.id packet = Packet(message.data) ipv4_info = packet.get_protocol(ipv4) if ipv4_info is None: return [] out_port, src_subnet, dst_subnet = \ self.routing_algo.calculate_routing_decision( switch_id, ipv4_info.src, ipv4_info.dst ) match = OFPMatch(eth_type=ether_types.ETH_TYPE_IP, ipv4_src=src_subnet, ipv4_dst=dst_subnet) # If packets come in very quickly, the flow rule may not be installed # yet. To avoid creating new flows, we check if the flow rules were # already registered in active_flows. for existing_flow in self.active_flows.values(): if existing_flow.is_ipv4_match_equal(switch_id, match): self.send_pkt(datapath, message.data, out_port) return [] actions = [OFPActionOutput(out_port)] flow_id = self.program_flow(datapath=datapath, match=match, actions=actions, priority=10, hard_timeout=120, idle_timeout=5) self.send_pkt(datapath, message.data, out_port) return [flow_id]
def test_convert_actions(self): """ Test all action conversions work correctly """ # First check set returns a set self.assertIs(type(actions_from_ryu([OFPActionOutput(6)], 'set')), ActionSet) # And list a list self.assertIs(type(actions_from_ryu([OFPActionOutput(6)], 'list')), ActionList) # Now check all the action types, OUTPUT etc self.assertEqual(actions_from_ryu([OFPActionOutput(6)], 'list'), ActionList([('OUTPUT', 6)])) self.assertEqual(actions_from_ryu([OFPActionGroup(7)], 'list'), ActionList([('GROUP', 7)])) self.assertEqual(actions_from_ryu([OFPActionSetQueue(8)], 'list'), ActionList([('SET_QUEUE', 8)])) # Push/Pop self.assertEqual(actions_from_ryu([OFPActionPushVlan(0x8100)], 'list'), ActionList([('PUSH_VLAN', 0x8100)])) self.assertEqual(actions_from_ryu([OFPActionPushVlan(0x88a8)], 'list'), ActionList([('PUSH_VLAN', 0x88a8)])) self.assertEqual(actions_from_ryu([OFPActionPopVlan()], 'list'), ActionList([('POP_VLAN', None)])) self.assertEqual(actions_from_ryu([OFPActionPushMpls(0x8847)], 'list'), ActionList([('PUSH_MPLS', 0x8847)])) self.assertEqual(actions_from_ryu([OFPActionPushMpls(0x8848)], 'list'), ActionList([('PUSH_MPLS', 0x8848)])) self.assertEqual(actions_from_ryu([OFPActionPopMpls(0x0800)], 'list'), ActionList([('POP_MPLS', 0x0800)])) self.assertEqual(actions_from_ryu([OFPActionPushPbb(0x88e7)], 'list'), ActionList([('PUSH_PBB', 0x88e7)])) self.assertEqual(actions_from_ryu([OFPActionPopPbb()], 'list'), ActionList([('POP_PBB', None)])) # SET_FIELD, take this chance to check we can do MAC, IPv4/6 conversion # as ryu might be using those. set_field = OFPActionSetField(vlan_vid=100) self.assertEqual(actions_from_ryu([set_field], 'list'), ActionList([("SET_FIELD", ('VLAN_VID', 100))])) set_field = OFPActionSetField(eth_dst="10:11:12:13:14:15") self.assertEqual( actions_from_ryu([set_field], 'list'), ActionList([("SET_FIELD", ('ETH_DST', 0x101112131415))])) set_field = OFPActionSetField(eth_src="10-11-12-13-14-15") self.assertEqual( actions_from_ryu([set_field], 'list'), ActionList([("SET_FIELD", ('ETH_SRC', 0x101112131415))])) set_field = OFPActionSetField(ipv4_dst="192.168.2.1") self.assertEqual(actions_from_ryu([set_field], 'list'), ActionList([("SET_FIELD", ('IPV4_DST', 0xc0a80201))])) set_field = OFPActionSetField(ipv4_src="192.168.2.2") self.assertEqual(actions_from_ryu([set_field], 'list'), ActionList([("SET_FIELD", ('IPV4_SRC', 0xc0a80202))])) set_field = OFPActionSetField(ipv6_src="::") self.assertEqual(actions_from_ryu([set_field], 'list'), ActionList([("SET_FIELD", ('IPV6_SRC', 0x0))])) set_field = OFPActionSetField( ipv6_src="2001:DB8:0123:4567:89ab:cdef:a:a") ipv6_num = 0x20010DB80123456789abcdef000a000a self.assertEqual(actions_from_ryu([set_field], 'list'), ActionList([("SET_FIELD", ('IPV6_SRC', ipv6_num))])) set_field = OFPActionSetField(ipv6_dst="2001:DB8::") ipv6_num = 0x20010DB8000000000000000000000000 self.assertEqual(actions_from_ryu([set_field], 'list'), ActionList([("SET_FIELD", ('IPV6_DST', ipv6_num))])) # TTL self.assertEqual(actions_from_ryu([OFPActionCopyTtlOut()], 'list'), ActionList([('COPY_TTL_OUT', None)])) self.assertEqual(actions_from_ryu([OFPActionCopyTtlIn()], 'list'), ActionList([('COPY_TTL_IN', None)])) self.assertEqual(actions_from_ryu([OFPActionSetMplsTtl(24)], 'list'), ActionList([('SET_MPLS_TTL', 24)])) self.assertEqual(actions_from_ryu([OFPActionDecMplsTtl()], 'list'), ActionList([('DEC_MPLS_TTL', None)])) self.assertEqual(actions_from_ryu([OFPActionSetNwTtl(0xff)], 'list'), ActionList([('SET_NW_TTL', 0xff)])) self.assertEqual(actions_from_ryu([OFPActionDecNwTtl()], 'list'), ActionList([('DEC_NW_TTL', None)]))
priority=0, match=OFPMatch(), instructions=[OFPInstructionGotoTable(1)]), # Table 1, ETH, IP etc. # Routing OFPFlowStats(table_id=1, priority=1008, match=parser.OFPMatch(eth_dst=1, ipv4_dst=("1.0.0.0", "255.0.0.0")), instructions=[ OFPInstructionActions(ofproto_v1_3.OFPIT_APPLY_ACTIONS, [ OFPActionSetField(eth_src=100), OFPActionSetField(eth_dst=20), OFPActionOutput(20) ]) ]), OFPFlowStats(table_id=1, priority=1008, match=OFPMatch(eth_dst=2, ipv4_dst=("1.0.0.0", "255.0.0.0")), instructions=[ OFPInstructionActions(ofproto_v1_3.OFPIT_APPLY_ACTIONS, [ OFPActionSetField(eth_src=100), OFPActionSetField(eth_dst=20), OFPActionOutput(20) ]) ]), OFPFlowStats(table_id=1, priority=1008, match=OFPMatch(eth_dst=1, ipv4_dst=("10.0.0.0", "255.0.0.0")),
FW = [] LEARN = [] m = next_mac() p = next_port() for x in range(NUMBER_MACS): mac = m.next() port = p.next() FW.append( OFPFlowStats(table_id=2, priority=1000, match=OFPMatch(eth_dst=mac), instructions=[ OFPInstructionActions( ofproto_v1_3.OFPIT_WRITE_ACTIONS, [OFPActionOutput(port)]), OFPInstructionGotoTable(3) ])) LEARN.append( OFPFlowStats(table_id=4, priority=1000, match=OFPMatch(in_port=port, eth_src=mac), instructions=[])) flows = [ # Table 0 Mac Term OFPFlowStats(table_id=0, priority=1000, match=OFPMatch(eth_dst=1), instructions=[OFPInstructionGotoTable(1)]), OFPFlowStats(table_id=0,
def get_semantic_flows(self): rq = """ PREFIX : <http://home.eps.hw.ac.uk/~qz1/> select ?p ?param ?val where { { ?p rdf:type/rdfs:subClassOf* of:Flow; ?param ?val. } UNION { ?flow rdf:type/rdfs:subClassOf* of:Flow; of:hasAction ?p. ?p ?param ?val. } UNION { ?p rdf:type/rdfs:subClassOf* of:Flow. ?sw ?param ?p. ?sw :hasID ?val. } } """ res = self.store.query(rq) flows = {} actions = {} ret = {} for (a, b, c) in res: a = a.replace("http://home.eps.hw.ac.uk/~qz1/", "").encode() b = b.replace("http://home.eps.hw.ac.uk/~qz1/", "").encode() c = c.replace("http://home.eps.hw.ac.uk/~qz1/", "").encode() LOG.debug("%s %s %s" % (a, b, c)) if "hasAction" in b: actions[c] = a if "_action" in a: if a not in flows[actions[a]]["actions"]: flows[actions[a]]["actions"][a] = {} flows[actions[a]]["actions"][a][b] = c else: if a not in flows: # We need a datapath here flows[a] = {"match": {}, "datapath": None, "actions": {}} if b in mappings: if b in ["in_port"]: flows[a]["match"][b] = int( c) # append_field(self.match_map[b], c) else: flows[a]["match"][ b] = c # append_field(self.match_map[b], c) if "hasFlow" in b: flows[a]["datapath"] = int(c) for a in flows: dpid = flows[a]["datapath"] if dpid not in ret: ret[dpid] = [] flow_act = [] for act in flows[a]["actions"]: action = flows[a]["actions"][act] if action[ "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"] == "ActionOutput": flow_act.append( OFPActionOutput(int(action["toPort"]), max_len=0xffff)) flow_act = [ OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, flow_act) ] # flows[a]["match"] = OFPMatch(**flows[a]["match"]) ret[dpid].append({ "actions": flow_act, "match": OFPMatch(**flows[a]["match"]) }) return ret