def setUpClass(cls): """Setup TestStruct.""" reason = FlowRemovedReason.OFPRR_IDLE_TIMEOUT match = Match(in_port=80, dl_vlan=1, dl_vlan_pcp=1, dl_type=1, nw_tos=1, nw_proto=1, tp_src=80, tp_dst=80, dl_src=HWAddress('00:00:00:00:00:00'), dl_dst=HWAddress('00:00:00:00:00:00'), nw_src=IPAddress('192.168.0.1'), nw_dst=IPAddress('192.168.0.2')) super().setUpClass() super().set_raw_dump_file('v0x01', 'ofpt_flow_removed') super().set_raw_dump_object(FlowRemoved, xid=12, match=match, cookie=0, priority=1, reason=reason, duration_sec=4, duration_nsec=23, idle_timeout=9, packet_count=10, byte_count=4) super().set_minimum_size(88)
def as_flow_mod(self, flow_type=FlowModCommand.OFPFC_ADD): """Transform a Flow object into a flow_mod message. Args: flow_type (|flow_mod_command|): type of flow_mod to be converted. Returns: |flow_mod|: Instance of FlowMod with Flow attributes. """ flow_mod = FlowMod() flow_mod.command = flow_type flow_mod_attributes = [ 'buffer_id', 'idle_timeout', 'hard_timeout', 'priority' ] for attribute_name in flow_mod_attributes: value = getattr(self, attribute_name) if value is not None: setattr(flow_mod, attribute_name, value) flow_mod.match = Match() match_attributes = [ 'in_port', 'dl_src', 'dl_dst', 'dl_vlan', 'dl_type', 'nw_src', 'nw_dst', 'tp_dst' ] for attribute_name in match_attributes: value = getattr(self, attribute_name) if value is not None: setattr(flow_mod.match, attribute_name, value) if self.actions is not None: for action in self.actions: flow_mod.actions.append(action.as_of_action()) return flow_mod
class FlowStatsRequest(GenericStruct): """Body for ofp_stats_request of type OFPST_FLOW.""" match = Match() table_id = UBInt8() #: Align to 32 bits. pad = Pad(1) out_port = UBInt16() def __init__(self, match=None, table_id=0xff, out_port=Port.OFPP_NONE): """Create a FlowStatsRequest with the optional parameters below. Args: match (:class:`~pyof.v0x01.common.flow_match.Match`): Fields to match. table_id (int): ID of table to read (from pyof_table_stats) 0xff for all tables or 0xfe for emergency. out_port (:class:`int`, :class:`~pyof.v0x01.common.phy_port.Port`): Require matching entries to include this as an output port. A value of :attr:`.Port.OFPP_NONE` indicates no restriction. """ super().__init__() self.match = Match() if match is None else match self.table_id = table_id self.out_port = out_port
def handle_packet_in(self, event): """Handle PacketIn Event. Install flows allowing communication between switch ports. Args: event (KytosPacketIn): Received Event """ log.debug("PacketIn Received") packet_in = event.content['message'] ethernet = Ethernet() ethernet.unpack(packet_in.data.value) # Ignore LLDP packets or packets not generated by table-miss flows if (ethernet.destination in settings.lldp_macs or packet_in.reason != PacketInReason.OFPR_NO_MATCH): return # Learn the port where the sender is connected in_port = packet_in.in_port.value switch = event.source.switch switch.update_mac_table(ethernet.source, in_port) ports = switch.where_is_mac(ethernet.destination) # Add a flow to the switch if the destination is known if ports: flow_mod = FlowMod() flow_mod.command = FlowModCommand.OFPFC_ADD flow_mod.match = Match() flow_mod.match.dl_src = ethernet.source.value flow_mod.match.dl_dst = ethernet.destination.value flow_mod.match.dl_type = ethernet.ether_type flow_mod.actions.append(ActionOutput(port=ports[0])) event_out = KytosEvent(name=('kytos/of_l2ls.messages.out.' 'ofpt_flow_mod'), content={ 'destination': event.source, 'message': flow_mod }) self.controller.buffers.msg_out.put(event_out) # Send the packet to correct destination or flood it packet_out = PacketOut() packet_out.buffer_id = packet_in.buffer_id packet_out.in_port = packet_in.in_port packet_out.data = packet_in.data port = ports[0] if ports else Port.OFPP_FLOOD packet_out.actions.append(ActionOutput(port=port)) event_out = KytosEvent(name=('kytos/of_l2ls.messages.out.' 'ofpt_packet_out'), content={ 'destination': event.source, 'message': packet_out }) self.controller.buffers.msg_out.put(event_out)
class FlowRemoved(GenericMessage): """Flow removed (datapath -> controller).""" #: :class:`~.header.Header`: OpenFlow Header header = Header(message_type=Type.OFPT_FLOW_REMOVED) #: :class:`~.flow_match.Match`: OpenFlow Header match = Match() cookie = UBInt64() priority = UBInt16() reason = UBInt8(enum_ref=FlowRemovedReason) #: Align to 32-bits. pad = Pad(1) duration_sec = UBInt32() duration_nsec = UBInt32() idle_timeout = UBInt16() #: Align to 64-bits. pad2 = Pad(2) packet_count = UBInt64() byte_count = UBInt64() def __init__(self, xid=None, match=None, cookie=None, priority=None, reason=None, duration_sec=None, duration_nsec=None, idle_timeout=None, packet_count=None, byte_count=None): """Assign parameters to object attributes. Args: xid (int): OpenFlow Header's xid. match (Match): Fields' description. cookie (int): Opaque controller-issued identifier. priority (int): Priority level of flow entry. reason (FlowRemovedReason): Why the flow was removed. duration_sec (int): Time the flow was alive in seconds. duration_nsec (int): Time the flow was alive in nanoseconds in addition to duration_sec. idle_timeout (int): Idle timeout from original flow mod. packet_count (int): Number of packets. byte_count (int): Byte count. """ super().__init__(xid) self.match = match self.cookie = cookie self.priority = priority self.reason = reason self.duration_sec = duration_sec self.duration_nsec = duration_nsec self.idle_timeout = idle_timeout self.packet_count = packet_count self.byte_count = byte_count
def _get_match(): """Function used to built Match instance used by AggregateStatsRequest.""" return Match(in_port=80, dl_src="01:02:03:04:05:06", dl_dst="01:02:03:04:05:06", dl_vlan=1, dl_vlan_pcp=1, dl_type=1, nw_tos=1, nw_proto=1, nw_src='192.168.0.1', nw_dst='192.168.0.1', tp_src=80, tp_dst=80)
def _get_match(): """Function used to return a Match instance.""" return Match(in_port=80, dl_src='01:02:03:04:05:06', dl_dst='01:02:03:04:05:06', dl_vlan=1, dl_vlan_pcp=1, dl_type=1, nw_tos=1, nw_proto=1, nw_src='192.168.0.1', nw_dst='192.168.0.1', tp_src=80, tp_dst=80)
class FlowMod(GenericMessage): """Modifies the flow table from the controller.""" header = Header(message_type=Type.OFPT_FLOW_MOD) match = Match() cookie = UBInt64() command = UBInt16(enum_ref=FlowModCommand) idle_timeout = UBInt16() hard_timeout = UBInt16() priority = UBInt16() buffer_id = UBInt32() out_port = UBInt16(enum_ref=Port) flags = UBInt16(enum_ref=FlowModFlags) actions = ListOfActions() def __init__(self, xid=None, match=None, cookie=0, command=None, idle_timeout=0, hard_timeout=0, priority=0, buffer_id=NO_BUFFER, out_port=Port.OFPP_NONE, flags=FlowModFlags.OFPFF_CHECK_OVERLAP, actions=None): """The constructor just assings parameters to object attributes. Args: xid (int): xid to be used on the message header. match (Match): Fields to match. cookie (int): Opaque controller-issued identifier. command (FlowModCommand): One of OFPFC_*. idle_timeout (int): Idle time before discarding (seconds). hard_timeout (int): Max time before discarding (seconds). priority (int): Priority level of flow entry. buffer_idle (int): Buffered packet to apply to (or -1). Not meaningful for OFPFC_DELETE*. out_port (Port): For OFPFC_DELETE* commands, require matching entries to include this as an output port. A value of OFPP_NONE indicates no restriction. flags (FlowModFlags): One of OFPFF_*. actions (ListOfActions): The action length is inferred from the length field in the header. """ super().__init__(xid) self.match = match self.cookie = cookie self.command = command self.idle_timeout = idle_timeout self.hard_timeout = hard_timeout self.priority = priority self.buffer_id = buffer_id self.out_port = out_port self.flags = flags self.actions = [] if actions is None else actions
def __init__(self, match=Match(), table_id=0xff, out_port=Port.OFPP_NONE): """The constructor just assings parameters to object attributes. Args: match (Match): Fields to match. table_id (int): ID of table to read (from pyof_table_stats) 0xff for all tables or 0xfe for emergency. out_port (int): Require matching entries to include this as an output port. A value of OFPP_NONE indicates no restriction. """ super().__init__() self.match = match self.table_id = table_id self.out_port = out_port
def __init__(self, match=Match(), table_id=0xff, out_port=Port.OFPP_NONE): """Create a AggregateStatsRequest with the optional parameters below. Args: match (~pyof.v0x01.common.flow_match.Match): Fields to match. table_id (int): ID of table to read (from pyof_table_stats) 0xff for all tables or 0xfe for emergency. out_port (int): Require matching entries to include this as an output port. A value of OFPP_NONE indicates no restriction. """ super().__init__() self.match = match self.table_id = table_id self.out_port = out_port
def ipv6_drop(self, event): """Install a flow on the switch that drop all incoming ipv6 packets.""" switch = event.content['switch'] if switch.connection.protocol.version is not 0x01: return flow_mod = FlowMod() flow_mod.command = FlowModCommand.OFPFC_ADD flow_mod.match = Match() flow_mod.match.dl_type = 0x86dd # ipv6 event_out = KytosEvent(name=('kytos/of_ipv6drop.messages.out.' 'ofpt_flow_mod'), content={'destination': switch.connection, 'message': flow_mod}) log.info('Sending "IPv6 DROP" flow to switch %s', switch.id) self.controller.buffers.msg_out.put(event_out)
def __init__(self, xid=None, match=None, cookie=0, command=None, idle_timeout=0, hard_timeout=0, priority=0, buffer_id=NO_BUFFER, out_port=Port.OFPP_NONE, flags=FlowModFlags.OFPFF_SEND_FLOW_REM, actions=None): """Create a FlowMod with the optional parameters below. Args: xid (int): xid to be used on the message header. match (~pyof.v0x01.common.flow_match.Match): Fields to match. cookie (int): Opaque controller-issued identifier. command (~pyof.v0x01.controller2switch.flow_mod.FlowModCommand): One of OFPFC_*. idle_timeout (int): Idle time before discarding (seconds). hard_timeout (int): Max time before discarding (seconds). priority (int): Priority level of flow entry. buffer_idle (int): Buffered packet to apply to (or -1). Not meaningful for OFPFC_DELETE*. out_port (~pyof.v0x01.common.phy_port.Port): For OFPFC_DELETE* commands, require matching entries to include this as an output port. A value of OFPP_NONE indicates no restriction. flags (~pyof.v0x01.controller2switch.flow_mod.FlowModFlags): One of OFPFF_*. actions (~pyof.v0x01.common.action.ListOfActions): The action length is inferred from the length field in the header. """ super().__init__(xid) self.match = match or Match() self.cookie = cookie self.command = command self.idle_timeout = idle_timeout self.hard_timeout = hard_timeout self.priority = priority self.buffer_id = buffer_id self.out_port = out_port self.flags = flags self.actions = actions or []
class AggregateStatsRequest(GenericStruct): """Body for ofp_stats_request of type OFPST_AGGREGATE.""" match = Match() table_id = UBInt8() #: Align to 32 bits pad = Pad(1) out_port = UBInt16() def __init__(self, match=Match(), table_id=0xff, out_port=Port.OFPP_NONE): """Create a AggregateStatsRequest with the optional parameters below. Args: match (~pyof.v0x01.common.flow_match.Match): Fields to match. table_id (int): ID of table to read (from pyof_table_stats) 0xff for all tables or 0xfe for emergency. out_port (int): Require matching entries to include this as an output port. A value of OFPP_NONE indicates no restriction. """ super().__init__() self.match = match self.table_id = table_id self.out_port = out_port
class FlowStatsRequest(GenericStruct): """Body for ofp_stats_request of type OFPST_FLOW.""" match = Match() table_id = UBInt8() #: Align to 32 bits. pad = Pad(1) out_port = UBInt16() def __init__(self, match=Match(), table_id=0xff, out_port=Port.OFPP_NONE): """The constructor just assings parameters to object attributes. Args: match (Match): Fields to match. table_id (int): ID of table to read (from pyof_table_stats) 0xff for all tables or 0xfe for emergency. out_port (:class:`int`, :class:`.Port`): Require matching entries to include this as an output port. A value of :attr:`.Port.OFPP_NONE` indicates no restriction. """ super().__init__() self.match = match self.table_id = table_id self.out_port = out_port
def _get_match(): """Return a Match object.""" return Match()
def generate_flow_mod_message(self, xid, srcIpAddress): match = Match(dl_type=2048, nw_src=IPAddress(srcIpAddress)) message = FlowMod(xid=xid, match=match, command=FlowModCommand.OFPFC_ADD) return message.pack()
class FlowStats(GenericStruct): """Body of reply to OFPST_FLOW request.""" length = UBInt16() table_id = UBInt8() #: Align to 32 bits. pad = Pad(1) match = Match() duration_sec = UBInt32() duration_nsec = UBInt32() priority = UBInt16() idle_timeout = UBInt16() hard_timeout = UBInt16() #: Align to 64-bits pad2 = Pad(6) cookie = UBInt64() packet_count = UBInt64() byte_count = UBInt64() actions = ListOfActions() def __init__(self, length=None, table_id=None, match=None, duration_sec=None, duration_nsec=None, priority=None, idle_timeout=None, hard_timeout=None, cookie=None, packet_count=None, byte_count=None, actions=None): """Create a FlowStats with the optional parameters below. Args: length (int): Length of this entry. table_id (int): ID of table flow came from. match (~pyof.v0x01.common.flow_match.Match): Description of fields. duration_sec (int): Time flow has been alive in seconds. duration_nsec (int): Time flow has been alive in nanoseconds in addition to duration_sec. priority (int): Priority of the entry. Only meaningful when this is not an exact-match entry. idle_timeout (int): Number of seconds idle before expiration. hard_timeout (int): Number of seconds before expiration. cookie (int): Opaque controller-issued identifier. packet_count (int): Number of packets in flow. byte_count (int): Number of bytes in flow. actions (:class:`~pyof.v0x01.common.actions.ListOfActions`): List of Actions. """ super().__init__() self.length = length self.table_id = table_id self.match = match self.duration_sec = duration_sec self.duration_nsec = duration_nsec self.priority = priority self.idle_timeout = idle_timeout self.hard_timeout = hard_timeout self.cookie = cookie self.packet_count = packet_count self.byte_count = byte_count self.actions = [] if actions is None else actions def unpack(self, buff, offset=0): """Unpack *buff* into this object. Do nothing, since the _length is already defined and it is just a Pad. Keep buff and offset just for compability with other unpack methods. Args: buff (bytes): Buffer where data is located. offset (int): Where data stream begins. """ self.length = UBInt16() self.length.unpack(buff, offset) max_length = offset + self.length.value super().unpack(buff[:max_length], offset)