private synchronized void sendPacket()
    {
        if (flowList_ == null || flowList_.isEmpty() == true) {
            return;
        }

        // submits the first packet in the list
        Packet np = (Packet) flowList_.remove(0);

        boolean ping = false;   // a flag to determine ping packet or not
        int tag = -1;       // event tag ID
        int dest = -1;      // destination ID

        // if a packet belongs to a ping packet
        if (np instanceof InfoPacket)
        {
            ((InfoPacket)np).addExitTime( GridSim.clock() );
            ((InfoPacket)np).addBaudRate( link_.getBaudRate() );
            ping = true;
        }

        // if an entity tries to send a packet to itself
        if ( np.getDestID() == outPort_.get_dest() )
        {
            //System.out.println("Sending packet to self!");
            // then change the destination name and id
            String destName = super.get_name();
            destName = destName.replaceFirst("Output", "Input");
            dest = Sim_system.get_entity_id(destName);

            // for a ping packet, change the tag
            if (ping == true)
            {
                // don't forget to change the packet tag
                tag = GridSimTags.INFOPKT_RETURN;
                ((InfoPacket) np).setTag(tag);
            }
            else {
                tag = np.getTag();
            }
        }
        else  // if an entity tries to send to other entity
        {
            // change or keep the event tag
            tag = GridSimTags.PKT_FORWARD;
            if (np.getTag() == GridSimTags.JUNK_PKT) {
                tag = GridSimTags.JUNK_PKT;
            }

            // sends the packet into the link
            dest = link_.get_id();
        }

        // send the packet
        super.sim_schedule(dest, GridSimTags.SCHEDULE_NOW, tag, np);

        /*****   // DEBUG info **
        System.out.println(super.get_name() + " send to " +
                GridSim.getEntityName(dest) + " tag = " + tag + " time " + GridSim.clock());
        /****/

        // if the list is not empty, then schedule the next packet in the list
        if (flowList_.isEmpty() != true)
        {
            //double delay = np.getSize() * SIZE / link_.getBaudRate();
            double delay = 0.0;
            super.sim_schedule(super.get_id(), delay, GridSimTags.SEND_PACKET);
        }
    }