/* * Allocate mbuf for flow stat (and latency) info sending * m - Original mbuf (can be complicated mbuf data structure) * fsp_head - return pointer in which the flow stat info should be filled * is_const - is the given mbuf const * return new mbuf structure in which the fsp_head can be written. If needed, orginal mbuf is freed. */ rte_mbuf_t * CGenNodeStateless::alloc_flow_stat_mbuf(rte_mbuf_t *m, struct flow_stat_payload_header *&fsp_head , bool is_const) { rte_mbuf_t *m_ret = NULL, *m_lat = NULL; uint16_t fsp_head_size = sizeof(struct flow_stat_payload_header); if (is_const) { // const mbuf case if (rte_pktmbuf_data_len(m) > 128) { m_ret = CGlobalInfo::pktmbuf_alloc_small(get_socket_id()); assert(m_ret); // alloc mbuf just for the latency header m_lat = CGlobalInfo::pktmbuf_alloc( get_socket_id(), fsp_head_size); assert(m_lat); fsp_head = (struct flow_stat_payload_header *)rte_pktmbuf_append(m_lat, fsp_head_size); rte_pktmbuf_attach(m_ret, m); rte_pktmbuf_trim(m_ret, sizeof(struct flow_stat_payload_header)); utl_rte_pktmbuf_add_after2(m_ret, m_lat); // ref count was updated when we took the (const) mbuf, and again in rte_pktmbuf_attach // so need do decrease now, to avoid leak. rte_pktmbuf_refcnt_update(m, -1); return m_ret; } else { // Short packet. Just copy all bytes. m_ret = CGlobalInfo::pktmbuf_alloc( get_socket_id(), rte_pktmbuf_data_len(m) ); assert(m_ret); char *p = rte_pktmbuf_mtod(m, char*); char *p_new = rte_pktmbuf_append(m_ret, rte_pktmbuf_data_len(m)); memcpy(p_new , p, rte_pktmbuf_data_len(m)); fsp_head = (struct flow_stat_payload_header *)(p_new + rte_pktmbuf_data_len(m) - fsp_head_size); rte_pktmbuf_free(m); return m_ret; } } else { // Field engine (vm) if (rte_pktmbuf_is_contiguous(m)) {
/** * @brief Send packet from specified device * * @param devId uint8_t, ID of DPDK device * @param mBuf MBuf_t*, memory buffer * * @return int, count of transmitted packets */ int DPDKAdapter::sendMbufBurstWithoutFree(uint8_t devId, MBuf_t** burst, uint8_t size) { if (devId > RTE_MAX_ETHPORTS) { qCritical("Device ID is out of range"); return -1; } if (size > DPDK_TX_MAX_PKT_BURST) { qCritical("Maximum packet burst value is exceeded"); return -2; } // Nothing to do if (!burst) { qWarning("There is nothing to send"); return 0; } for (uint8_t i = 0; i < size; i++) { rte_pktmbuf_refcnt_update(burst[i], 1); } return rte_eth_tx_burst(devId, 0, burst, size); }
int dpdpcap_transmit_in_loop(pcap_t *p, const u_char *buf, int size, int number) { int transmitLcoreId = 0; int i = 0; if (p == NULL || buf == NULL || p->deviceId < 0 || p->deviceId > RTE_MAX_ETHPORTS) { snprintf (errbuf_g, PCAP_ERRBUF_SIZE, "Invalid parameter"); return DPDKPCAP_FAILURE; } for (i = 0; i < DEF_PKT_BURST; i++) { mbuf_g[i] = rte_pktmbuf_alloc(txPool); if (mbuf_g[i] == NULL) { snprintf (errbuf_g, PCAP_ERRBUF_SIZE, "Could not allocate buffer on port %d\n", p->deviceId); return DPDKPCAP_FAILURE; } struct rte_mbuf* mbuf = mbuf_g[i]; if (mbuf->buf_len < size) { snprintf (errbuf_g, PCAP_ERRBUF_SIZE, "Can not copy packet data : packet size %d, mbuf length %d, port %d\n", size, mbuf->buf_len, p->deviceId); return DPDKPCAP_FAILURE; } rte_memcpy(mbuf->pkt.data, buf, size); mbuf->pkt.data_len = size; mbuf->pkt.pkt_len = size; mbuf->pkt.nb_segs = 1; rte_pktmbuf_refcnt_update(mbuf, 1); } dpdkpcap_tx_args_t args; args.number = number; args.portId = p->deviceId; transmitLcoreId = p->deviceId + 1; debug("Transferring TX loop to the core %u\n", transmitLcoreId); if (rte_eal_remote_launch(txLoop, &args, transmitLcoreId) < 0) { snprintf (errbuf_g, PCAP_ERRBUF_SIZE, "Can not run TX on a slave core: transmitLcoreId %d\n", transmitLcoreId); return DPDKPCAP_FAILURE; } rte_eal_wait_lcore(transmitLcoreId); return DPDKPCAP_OK; }
/* flood forward of the input packet */ static inline void flood_forward(struct rte_mbuf *m, uint8_t rx_port, uint8_t nb_ports) { uint8_t port; struct rte_mbuf *pkt; /* Mark all packet's segments as referenced port_num times */ rte_pktmbuf_refcnt_update(m, (uint16_t)nb_ports); for (port = 0; port < nb_ports; port++) { /* skip for own port */ if (unlikely (port == rx_port)) continue; pkt = m; flood_send_pkt(pkt, port); } rte_pktmbuf_free(m); }
static int txLoop(void* arg) { int ret = 0; dpdkpcap_tx_args_t* args_p = (dpdkpcap_tx_args_t*)arg; int number = args_p->number; int portId = args_p->portId; int lcoreId = rte_lcore_id(); int packets = 0; int i = 0; debug("Starting transmit: core %u, port %u, packets num %d\n", lcoreId, portId, number); while (1) { ret = rte_eth_tx_burst(portId, 0, mbuf_g, DEF_PKT_BURST); if (ret < DEF_PKT_BURST) { debug("Transmitted %u packets\n", ret); } for (i = 0; i < ret; i++) { // rte_pktmbuf_free(mbuf_g[i]); rte_pktmbuf_refcnt_update(mbuf_g[i], 1); } packets += ret; if (args_p->number > 0) { if (number < 1) break; number -= ret; } } debug("Finished transmit on core %u\n", lcoreId); return DPDKPCAP_OK; }