def _as_of_flow_mod(self, command): """Return pyof FlowMod with a ``command`` to add or delete a flow. Actions become items of the ``instructions`` attribute. """ of_flow_mod = super()._as_of_flow_mod(command) of_actions = [action.as_of_action() for action in self.actions] of_instruction = InstructionApplyAction(actions=of_actions) of_flow_mod.instructions = [of_instruction] return of_flow_mod
def _build_lldp_flow_mod(self, version): """Build a FlodMod message to send LLDP to the controller. Args: version (int): OpenFlow version. Returns: FlowMod message for the specific given OpenFlow version, if it is supported. None if the OpenFlow version is not supported. """ if version == 0x01: flow_mod = FM10() flow_mod.command = FMC.OFPFC_ADD flow_mod.priority = settings.FLOW_PRIORITY flow_mod.match.dl_type = EtherType.LLDP if self.vlan_id: flow_mod.match.dl_vlan = self.vlan_id flow_mod.actions.append(AO10(port=Port10.OFPP_CONTROLLER)) elif version == 0x04: flow_mod = FM13() flow_mod.command = FMC.OFPFC_ADD flow_mod.priority = settings.FLOW_PRIORITY match_lldp = OxmTLV() match_lldp.oxm_field = OxmOfbMatchField.OFPXMT_OFB_ETH_TYPE match_lldp.oxm_value = EtherType.LLDP.to_bytes(2, 'big') flow_mod.match.oxm_match_fields.append(match_lldp) if self.vlan_id: match_vlan = OxmTLV() match_vlan.oxm_field = OxmOfbMatchField.OFPXMT_OFB_VLAN_VID vlan_value = self.vlan_id | VlanId.OFPVID_PRESENT match_vlan.oxm_value = vlan_value.to_bytes(2, 'big') flow_mod.match.oxm_match_fields.append(match_vlan) instruction = InstructionApplyAction() instruction.actions.append(AO13(port=Port13.OFPP_CONTROLLER)) flow_mod.instructions.append(instruction) else: flow_mod = None return flow_mod
def from_dict(self, dictionary): """Return an OF 1.0 FlowMod message from serialized dictionary.""" flow_mod = FlowMod() instruction = InstructionApplyAction() flow_mod.instructions.append(instruction) for field, data in dictionary.items(): if field in self.flow_attributes: setattr(flow_mod, field, data) elif field == 'match': tlvs = self._match_from_dict(data) flow_mod.match.oxm_match_fields.append(list(tlvs)) elif field == 'actions': actions = self._actions_from_list(data) instruction.actions.extend(list(actions)) return flow_mod
def to_ofmsg(self): # TODO openflow version flow_mod = FM13() flow_mod.command = FMC.OFPFC_ADD if self.type == Operation.ADD else ( FMC.OFPFC_MODIFY if self.type == Operation.MOD else FMC.OFPFC_DELETE) flow_mod.priority = self.priority for f, v in self.match.items(): field = of_field_str2val.get(f) assert field is not None # TODO assert isinstance(v, bytes) # TODO value type flow_mod.match.oxm_match_fields.append( OxmTLV(oxm_field=field, oxm_value=v)) # Port13.OFPP_CONTROLLER if None not in self.action['output']: inst = InstructionApplyAction( actions=[AO13(port=p) for p in self.action['output']]) flow_mod.instructions.append(inst) return flow_mod.pack()
def install_table_miss_flow(self, event): flow_mod = FlowMod() flow_mod.command = FlowModCommand.OFPFC_ADD action = ActionOutput(port=PortNo.OFPP_CONTROLLER) instruction = InstructionApplyAction() instruction.actions.append(action) flow_mod.instructions.append(instruction) destination = event.content['switch'].connection event_out = KytosEvent(name=('kytos/of_l2ls.messages.out.' 'ofpt_flow_mod'), content={ 'destination': destination, 'message': flow_mod }) self.controller.buffers.msg_out.put(event_out)
def _build_default_flow_mod(self, version): if version == 0x01: flow_mod = FM10() flow_mod.command = FMC.OFPFC_ADD flow_mod.priority = 0 # flow_mod.match.dl_type = EtherType.LLDP flow_mod.actions.append(AO10(port=Port10.OFPP_CONTROLLER)) elif version == 0x04: flow_mod = FM13() flow_mod.command = FMC.OFPFC_ADD flow_mod.priority = 0 # match_lldp = OxmTLV() # match_lldp.oxm_field = OxmOfbMatchField.OFPXMT_OFB_ETH_TYPE # match_lldp.oxm_value = EtherType.LLDP.to_bytes(2, 'big') # flow_mod.match.oxm_match_fields.append(match_lldp) instruction = InstructionApplyAction() instruction.actions.append(AO13(port=Port13.OFPP_CONTROLLER)) flow_mod.instructions.append(instruction) else: flow_mod = None return flow_mod
def _create_flow_mod(version, packet, port): """Create a FlowMod message with the appropriate version and data.""" if version == '0x01': flow_mod = FlowMod10() flow_mod.match.dl_src = packet.source.value flow_mod.match.dl_dst = packet.destination.value flow_mod.match.dl_type = packet.ether_type flow_mod.actions.append(Output10(port=port)) else: flow_mod = FlowMod13() match_dl_type = OxmTLV() match_dl_type.oxm_field = OxmOfbMatchField.OFPXMT_OFB_ETH_TYPE match_dl_type.oxm_value = packet.ether_type.value.to_bytes( 2, 'big') flow_mod.match.oxm_match_fields.append(match_dl_type) match_dl_src = OxmTLV() match_dl_src.oxm_field = OxmOfbMatchField.OFPXMT_OFB_ETH_SRC match_dl_src.oxm_value = packet.source.pack() flow_mod.match.oxm_match_fields.append(match_dl_src) match_dl_dst = OxmTLV() match_dl_dst.oxm_field = OxmOfbMatchField.OFPXMT_OFB_ETH_DST match_dl_dst.oxm_value = packet.destination.pack() flow_mod.match.oxm_match_fields.append(match_dl_dst) action = Output13(port=port) instruction = InstructionApplyAction() instruction.actions.append(action) flow_mod.instructions.append(instruction) flow_mod.command = FlowModCommand.OFPFC_ADD flow_mod.priority = settings.FLOW_PRIORITY return flow_mod
def install_table_miss_flow(self, event): """Install the TableMiss Flow in OF1.3 switches. This is needed because those drop packets by default. """ if event.content['switch'].ofp_version == '0x04': flow_mod = FlowMod13() flow_mod.command = FlowModCommand.OFPFC_ADD action = Output13(port=Port13.OFPP_CONTROLLER) instruction = InstructionApplyAction() instruction.actions.append(action) flow_mod.instructions.append(instruction) destination = event.content['switch'].connection event_out = KytosEvent(name=('kytos/of_l2ls.messages.out.' 'ofpt_flow_mod'), content={ 'destination': destination, 'message': flow_mod }) self.controller.buffers.msg_out.put(event_out)
def _new_list_of_instructions(): """Crate new ListOfInstruction.""" output = ActionOutput(port=PortNo.OFPP_CONTROLLER) loa = ListOfActions([output]) instruction = InstructionApplyAction(loa) return ListOfInstruction([instruction])
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 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.priority = settings.flow_priority match_dl_type = OxmTLV() match_dl_type.oxm_field = OxmOfbMatchField.OFPXMT_OFB_ETH_TYPE match_dl_type.oxm_value = ethernet.ether_type.value.to_bytes( 2, 'big') flow_mod.match.oxm_match_fields.append(match_dl_type) match_dl_src = OxmTLV() match_dl_src.oxm_field = OxmOfbMatchField.OFPXMT_OFB_ETH_SRC match_dl_src.oxm_value = ethernet.source.pack() flow_mod.match.oxm_match_fields.append(match_dl_src) match_dl_dst = OxmTLV() match_dl_dst.oxm_field = OxmOfbMatchField.OFPXMT_OFB_ETH_DST match_dl_dst.oxm_value = ethernet.destination.pack() flow_mod.match.oxm_match_fields.append(match_dl_dst) action = ActionOutput(port=ports[0]) instruction = InstructionApplyAction() instruction.actions.append(action) flow_mod.instructions.append(instruction) 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 = in_port packet_out.data = packet_in.data port = ports[0] if ports else PortNo.OFPP_FLOOD out_action = ActionOutput(port=port) packet_out.actions.append(out_action) 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)