All of lore.kernel.org
 help / color / mirror / Atom feed
From: John McNamara <john.mcnamara@intel.com>
To: dev@dpdk.org
Cc: Tero Aho <tero.aho@coriant.com>
Subject: [PATCH] pcap: add support for jumbo frames
Date: Wed,  8 Jul 2015 16:53:20 +0100	[thread overview]
Message-ID: <1436370800-31437-1-git-send-email-john.mcnamara@intel.com> (raw)

From: Tero Aho <tero.aho@coriant.com>

Extend eth_pcap rx and tx to support jumbo frames.

On the receive side read large packets into multiple mbufs and
on the transmit side convert them back to a single pcap buffer.

Signed-off-by: Tero Aho <tero.aho@coriant.com>
Signed-off-by: John McNamara <john.mcnamara@intel.com>
---
 drivers/net/pcap/rte_eth_pcap.c | 129 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 113 insertions(+), 16 deletions(-)

diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
index a6ed5bd..682628f 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/rte_eth_pcap.c
@@ -47,7 +47,7 @@
 #include <pcap.h>
 
 #define RTE_ETH_PCAP_SNAPSHOT_LEN 65535
-#define RTE_ETH_PCAP_SNAPLEN 4096
+#define RTE_ETH_PCAP_SNAPLEN ETHER_MAX_JUMBO_FRAME_LEN
 #define RTE_ETH_PCAP_PROMISC 1
 #define RTE_ETH_PCAP_TIMEOUT -1
 #define ETH_PCAP_RX_PCAP_ARG  "rx_pcap"
@@ -59,6 +59,7 @@
 #define ETH_PCAP_ARG_MAXLEN	64
 
 static char errbuf[PCAP_ERRBUF_SIZE];
+static unsigned char tx_pcap_data[RTE_ETH_PCAP_SNAPLEN];
 static struct timeval start_time;
 static uint64_t start_cycles;
 static uint64_t hz;
@@ -127,6 +128,61 @@ static struct rte_eth_link pmd_link = {
 		.link_status = 0
 };
 
+static int
+eth_pcap_rx_jumbo(struct rte_mempool *mb_pool,
+		  struct rte_mbuf *mbuf,
+		  const u_char *data,
+		  uint16_t data_len)
+{
+	struct rte_mbuf *m = mbuf;
+
+	/* Copy the first segment. */
+	uint16_t len = rte_pktmbuf_tailroom(mbuf);
+
+	rte_memcpy(rte_pktmbuf_append(mbuf, len), data, len);
+	data_len -= len;
+	data += len;
+
+	while (data_len > 0) {
+		/* Allocate next mbuf and point to that. */
+		m->next = rte_pktmbuf_alloc(mb_pool);
+
+		if (unlikely(!m->next))
+			return -1;
+
+		m = m->next;
+
+		/* Headroom is not needed in chained mbufs. */
+		rte_pktmbuf_prepend(m, rte_pktmbuf_headroom(m));
+		m->pkt_len = 0;
+		m->data_len = 0;
+
+		/* Copy next segment. */
+		len = RTE_MIN(rte_pktmbuf_tailroom(m), data_len);
+		rte_memcpy(rte_pktmbuf_append(m, len), data, len);
+
+		mbuf->nb_segs++;
+		data_len -= len;
+		data += len;
+	}
+
+	return mbuf->nb_segs;
+}
+
+/* Copy data from mbuf chain to a buffer suitable for writing to a PCAP file. */
+static void
+eth_pcap_gather_data(unsigned char *data, struct rte_mbuf *mbuf)
+{
+	uint16_t data_len = 0;
+
+	while (mbuf) {
+		rte_memcpy(data + data_len, rte_pktmbuf_mtod(mbuf, void *),
+			   mbuf->data_len);
+
+		data_len += mbuf->data_len;
+		mbuf = mbuf->next;
+	}
+}
 
 static uint16_t
 eth_pcap_rx(void *queue,
@@ -166,17 +222,19 @@ eth_pcap_rx(void *queue,
 			rte_memcpy(rte_pktmbuf_mtod(mbuf, void *), packet,
 					header.len);
 			mbuf->data_len = (uint16_t)header.len;
-			mbuf->pkt_len = mbuf->data_len;
-			mbuf->port = pcap_q->in_port;
-			bufs[num_rx] = mbuf;
-			num_rx++;
 		} else {
-			/* pcap packet will not fit in the mbuf, so drop packet */
-			RTE_LOG(ERR, PMD,
-					"PCAP packet %d bytes will not fit in mbuf (%d bytes)\n",
-					header.len, buf_size);
-			rte_pktmbuf_free(mbuf);
+			/* Try read jumbo frame into multi mbufs. */
+			if (unlikely(eth_pcap_rx_jumbo(pcap_q->mb_pool,
+						       mbuf,
+						       packet,
+						       header.len) == -1))
+				break;
 		}
+
+		mbuf->pkt_len = (uint16_t)header.len;
+		mbuf->port = pcap_q->in_port;
+		bufs[num_rx] = mbuf;
+		num_rx++;
 	}
 	pcap_q->rx_pkts += num_rx;
 	return num_rx;
@@ -214,10 +272,29 @@ eth_pcap_tx_dumper(void *queue,
 	for (i = 0; i < nb_pkts; i++) {
 		mbuf = bufs[i];
 		calculate_timestamp(&header.ts);
-		header.len = mbuf->data_len;
+		header.len = mbuf->pkt_len;
 		header.caplen = header.len;
-		pcap_dump((u_char *)dumper_q->dumper, &header,
-				rte_pktmbuf_mtod(mbuf, void*));
+
+		if (likely(mbuf->nb_segs == 1)) {
+			pcap_dump((u_char *)dumper_q->dumper, &header,
+				  rte_pktmbuf_mtod(mbuf, void*));
+		} else {
+			if (mbuf->pkt_len <= ETHER_MAX_JUMBO_FRAME_LEN) {
+				eth_pcap_gather_data(tx_pcap_data, mbuf);
+				pcap_dump((u_char *)dumper_q->dumper, &header,
+					  tx_pcap_data);
+			} else {
+				RTE_LOG(ERR, PMD,
+					"Dropping PCAP packet. "
+					"Size (%d) > max jumbo size (%d).\n",
+					mbuf->pkt_len,
+					ETHER_MAX_JUMBO_FRAME_LEN);
+
+				rte_pktmbuf_free(mbuf);
+				break;
+			}
+		}
+
 		rte_pktmbuf_free(mbuf);
 		num_tx++;
 	}
@@ -252,9 +329,29 @@ eth_pcap_tx(void *queue,
 
 	for (i = 0; i < nb_pkts; i++) {
 		mbuf = bufs[i];
-		ret = pcap_sendpacket(tx_queue->pcap,
-				rte_pktmbuf_mtod(mbuf, u_char *),
-				mbuf->data_len);
+
+		if (likely(mbuf->nb_segs == 1)) {
+			ret = pcap_sendpacket(tx_queue->pcap,
+					      rte_pktmbuf_mtod(mbuf, u_char *),
+					      mbuf->pkt_len);
+		} else {
+			if (mbuf->pkt_len <= ETHER_MAX_JUMBO_FRAME_LEN) {
+				eth_pcap_gather_data(tx_pcap_data, mbuf);
+				ret = pcap_sendpacket(tx_queue->pcap,
+						      tx_pcap_data,
+						      mbuf->pkt_len);
+			} else {
+				RTE_LOG(ERR, PMD,
+					"Dropping PCAP packet. "
+					"Size (%d) > max jumbo size (%d).\n",
+					mbuf->pkt_len,
+					ETHER_MAX_JUMBO_FRAME_LEN);
+
+				rte_pktmbuf_free(mbuf);
+				break;
+			}
+		}
+
 		if (unlikely(ret != 0))
 			break;
 		num_tx++;
-- 
1.8.1.4

             reply	other threads:[~2015-07-08 15:53 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-08 15:53 John McNamara [this message]
2015-07-08 15:57 ` [PATCH] pcap: add support for jumbo frames Mcnamara, John
2015-07-10 10:55 ` Gonzalez Monroy, Sergio
2015-07-10 21:16   ` Thomas Monjalon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1436370800-31437-1-git-send-email-john.mcnamara@intel.com \
    --to=john.mcnamara@intel.com \
    --cc=dev@dpdk.org \
    --cc=tero.aho@coriant.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.