Пример #1
0
/* transmits buffer through SGDMA. Returns number of buffers
 * transmitted, 0 if not possible.
 *
 * tx_lock is held by the caller
 */
int sgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *buffer)
{
	int pktstx = 0;
	struct sgdma_descrip *descbase =
		(struct sgdma_descrip *)priv->tx_dma_desc;

	struct sgdma_descrip *cdesc = &descbase[0];
	struct sgdma_descrip *ndesc = &descbase[1];

	/* wait 'til the tx sgdma is ready for the next transmit request */
	if (sgdma_txbusy(priv))
		return 0;

	sgdma_setup_descrip(cdesc,			/* current descriptor */
			    ndesc,			/* next descriptor */
			    sgdma_txphysaddr(priv, ndesc),
			    buffer->dma_addr,		/* address of packet to xmit */
			    0,				/* write addr 0 for tx dma */
			    buffer->len,		/* length of packet */
			    SGDMA_CONTROL_EOP,		/* Generate EOP */
			    0,				/* read fixed */
			    SGDMA_CONTROL_WR_FIXED);	/* Generate SOP */

	pktstx = sgdma_async_write(priv, cdesc);

	/* enqueue the request to the pending transmit queue */
	queue_tx(priv, buffer);

	return 1;
}
Пример #2
0
static void
send_features_request(struct lswitch *sw)
{
    struct ofpbuf *b;
    int ofp_version = rconn_get_version(sw->rconn);

    ovs_assert(ofp_version > 0 && ofp_version < 0xff);

    /* Send OFPT_FEATURES_REQUEST. */
    b = ofpraw_alloc(OFPRAW_OFPT_FEATURES_REQUEST, ofp_version, 0);
    queue_tx(sw, b);

    /* Send OFPT_SET_CONFIG. */
    struct ofputil_switch_config config = {
        .miss_send_len = OFP_DEFAULT_MISS_SEND_LEN
    };
    queue_tx(sw, ofputil_encode_set_config(&config, ofp_version));
}
Пример #3
0
static void
send_controller_id(struct lswitch *sw)
{
    struct ofpbuf *b;
    int ofp_version = rconn_get_version(sw->rconn);

    ovs_assert(ofp_version > 0 && ofp_version < 0xff);

    b = ofpraw_alloc(OFPRAW_NXT_SET_CONTROLLER_ID, ofp_version, 0);

	struct nx_controller_id *nci = ofpbuf_put_zeros(b, sizeof *nci);
	nci->controller_id = htons(100);

    queue_tx(sw, b);
}
Пример #4
0
static void
process_echo_request(struct lswitch *sw, const struct ofp_header *rq)
{
    queue_tx(sw, make_echo_reply(rq));
}
Пример #5
0
static void
process_packet_in(struct lswitch *sw, const struct ofp_header *oh)
{
    struct ofputil_packet_in pi;
    uint32_t buffer_id;

    uint64_t ofpacts_stub[64];
    struct ofpbuf ofpacts;

    struct ofputil_packet_out po;
    enum ofperr error;
    uint8_t icmp_packet[128];

    const struct mf_field *mf; 
    const struct mf_field *mf_id; 
    union mf_value sf_value, sf_mask;
    union mf_value sf_value_id, sf_mask_id;

    error = ofputil_decode_packet_in(oh, true, &pi, NULL, &buffer_id, NULL);
    if (error) {
        VLOG_WARN_RL(&rl, "failed to decode packet-in: %s",
                     ofperr_to_string(error));
        return;
    }

    /* Ignore packets sent via output to OFPP_CONTROLLER.  This library never
     * uses such an action.  You never know what experiments might be going on,
     * though, and it seems best not to interfere with them. */
    if (pi.reason != OFPR_ACTION || buffer_id != UINT32_MAX) {
        return;
    }

    struct ethhdr *old_pkt = pi.packet;
   
    struct iphdr * old_ipv4 = (struct iphdr*)(old_pkt + 1);
    uint16_t old_tot_len = ntohs(old_ipv4->tot_len);
    uint8_t header_len = old_ipv4->ihl*4;

    if (pi.packet_len < header_len + sizeof(struct ethhdr) + 8 || old_tot_len < header_len + 8)
        return;

    if (old_pkt->h_proto != htons(ETH_P_IP))
        return;

    //VLOG_INFO("AFTER MATCH");

    uint32_t icmp_packet_len = sizeof(struct ethhdr) + sizeof(struct iphdr) + header_len + sizeof(struct icmphdr) + 8;

    icmp_unexpect_ttl(icmp_packet, &pi, header_len, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);

    ofpbuf_use_stack(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);

    mf_id = mf_from_name("tun_id");
    if (!mf_id)
        return;

    sf_value_id.be64 = pi.flow_metadata.flow.tunnel.tun_id;
    sf_mask_id.be64 = OVS_BE64_MAX;
    ofpact_put_set_field(&ofpacts, mf_id, &sf_value_id, &sf_mask_id);

    mf = mf_from_name("tun_dst");
    if (!mf)
        return;

    sf_value.be32 = pi.flow_metadata.flow.tunnel.ip_src;
    sf_mask.be32 = OVS_BE32_MAX;
    ofpact_put_set_field(&ofpacts, mf, &sf_value, &sf_mask);

    ofpact_put_OUTPUT(&ofpacts)->port = OFPP_IN_PORT;

    /* Prepare packet_out in case we need one. */
    po.buffer_id = buffer_id;
    po.packet = icmp_packet;
    po.packet_len = icmp_packet_len;

    po.in_port = pi.flow_metadata.flow.in_port.ofp_port;
    po.ofpacts = ofpacts.data;
    po.ofpacts_len = ofpacts.size;


    queue_tx(sw, ofputil_encode_packet_out(&po, sw->protocol));

    //VLOG_INFO("AFTER MATCH last");
}
Пример #6
0
static void *tx_thread_entry(void *arg)
{
	device_pthread_setaffinity();

	int rc;
	int state;
	struct novacom_tx_packet packet;

	const struct aiocb * list[1];
	list[0] = &txaio;

	LOG_PRINTF("entry\n");
	while (usb_online) {
		// see if we have something to send
		packet.len = novacom_usbll_get_mtu(usbll_handle);
		packet.buf = tx_buffer;
		state = novacom_usbll_get_state(usbll_handle);		
		if (novacom_usbll_prepare_tx_packet(usbll_handle, &packet, 100) != TX_NO_PACKET) {

#if	LOCAL_TRACE_RW
			// write a block back
			LTRACEF("going to write packet\n");
#endif

#if 0
			rc = write(ep1in_fd, packet.buf, packet.len);
			LTRACEF("rc %d\n", rc);
			if (rc < 0) {
				TRACEF("error writing packet\n");
				break;
			}
#else
			rc = queue_tx(ep1in_fd, packet.buf, packet.len);
			if (rc < 0) {
				LOG_PRINTF("USB aio_write error, ret=%d, errno=%d\n", rc, errno);
				usleep(1000*GADGETFS_IO_RETRY_DELAY);
				novacom_usbll_changeback_state(usbll_handle, state);
				continue;
			}
			struct timespec timeout;
			rc = suspend(list, 1, &timeout);
			while (rc < 0 && errno == EAGAIN) {
				LOG_PRINTF("USB aio_suspend (for write) error, ret=%d, errno=%d\n", rc, errno);
				rc = suspend(list, 1, &timeout);
				if (rc >= 0) {
					LOG_PRINTF("USB aio_suspend (for write) ret=%d, errno=%d\n", rc, errno);
				}
			};
#if 0
			//do we need it ???
			if (rc < 0) {
				LTRACEF("timeout on tx\n");
				rc = aio_suspend(list, 1, NULL);
			}
#endif
			if (aio_error(&txaio) != EINPROGRESS) {
				rc = aio_return(&txaio);
				if (rc < 0) {
					/* online->offline transition */
					LOG_PRINTF("USB aio_return (for write) error, ret=%d, \n", rc);
					if( (usb_online != gadgetfs_online) && (true == usb_online) ) {
						int ret = platform_event_wait_timeout(&usb_online_event, TRANSPORT_RECOVERY_TIMEOUT * 1000*2);
						if (!ret) {
							LOG_PRINTF("platform_event_wait_timeout for usb_online_event, ret=%d\n", ret);
						}
						else {
							LOG_PRINTF("platform_event_wait_timeout for usb_online_event, ret=%d, ignored\n", ret);
						}
					}
				}
			}
			else {
				LOG_PRINTF("we should never enter here (EINPROGRESS=%d), USB aio write seems to have problem!\n", EINPROGRESS);
			}
			if (rc < 0) {
				novacom_usbll_changeback_state(usbll_handle, state);
			}
			else {
				static platform_time_t prior;
				static int init = 0;
				static unsigned int tx_bytes = 0, tx_packets = 0;
				platform_time_t curr;

				tx_bytes += packet.len;
				tx_packets++;
				if (!init) {
					platform_get_time(&prior);
					init = 1;
				}
				platform_get_time(&curr);
				if (platform_delta_time_msecs(&prior, &curr) >= 2800) { //logging for every 3sec
					platform_get_time(&prior);
					LOG_PRINTF("wrote %u bytes, %u packets\n",tx_bytes, tx_packets);
				}
			}
#endif
		}
	}

	LOG_PRINTF("shutting down\n");
	platform_event_signal(&tx_shutdown_event);

	return NULL;
}