'send a packet out some port
This handles virtual ports and does validation.
packet: instance of ethernet
out_port, in_port: the integer port number
max_len: maximum packet payload length to send to controller'

def _output_packet(self, packet, out_port, in_port, max_len=None):

    assert assert_type('packet', packet, ethernet, none_ok=False)
    def real_send(port_no, allow_in_port=False):
        if (type(port_no) == ofp_phy_port):
            port_no = port_no.port_no
        if ((port_no == in_port) and (not allow_in_port)):
            self.log.warn('Dropping    packet    sent    on    port    %i:    Input    port', port_no)
            return
        if (port_no not in self.ports):
            self.log.warn('Dropping    packet    sent    on    port    %i:    Invalid    port', port_no)
            return
        if (self.ports[port_no].config & OFPPC_NO_FWD):
            self.log.warn('Dropping    packet    sent    on    port    %i:    Forwarding    disabled', port_no)
            return
        if (self.ports[port_no].config & OFPPC_PORT_DOWN):
            self.log.warn('Dropping    packet    sent    on    port    %i:    Port    down', port_no)
            return
        if (self.ports[port_no].state & OFPPS_LINK_DOWN):
            self.log.debug('Dropping    packet    sent    on    port    %i:    Link    down', port_no)
            return
        self.port_stats[port_no].tx_packets += 1
        self.port_stats[port_no].tx_bytes += len(packet.pack())
        self._output_packet_physical(packet, port_no)
    if (out_port < OFPP_MAX):
        real_send(out_port)
    elif (out_port == OFPP_IN_PORT):
        real_send(in_port, allow_in_port=True)
    elif (out_port == OFPP_FLOOD):
        for (no, port) in self.ports.iteritems():
            if (no == in_port):
                continue
            if (port.config & OFPPC_NO_FLOOD):
                continue
            real_send(port)
    elif (out_port == OFPP_ALL):
        for (no, port) in self.ports.iteritems():
            if (no == in_port):
                continue
            real_send(port)
    elif (out_port == OFPP_CONTROLLER):
        buffer_id = self._buffer_packet(packet, in_port)
        self.send_packet_in(in_port, buffer_id, packet, reason=OFPR_ACTION, data_length=max_len)
    elif (out_port == OFPP_TABLE):
        self.rx_packet(packet, in_port)
    else:
        self.log.warn('Unsupported    virtual    output    port:    %d', out_port)
