/* 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; }
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)); }
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); }
static void process_echo_request(struct lswitch *sw, const struct ofp_header *rq) { queue_tx(sw, make_echo_reply(rq)); }
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"); }
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; }