summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMohsin Kazmi <sykazmi@cisco.com>2024-10-30 15:00:46 +0000
committerBeno�t Ganne <bganne@cisco.com>2024-11-22 08:49:35 +0000
commitc990aae85a2ec456dad24944978b88f48faa8aa6 (patch)
treef4254f8c50309a974ba2daac0e70a4fd7c2deea7
parent6c880efcce0538303765e4267fb8718e49512f69 (diff)
pg: fix the buffer deletion
Type: fix Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com> Change-Id: I8f0a67706399dad1e5296aafd1cfa92958b2fe82
-rw-r--r--src/vnet/pg/pg.h51
-rw-r--r--test/test_pg_stream.py94
2 files changed, 134 insertions, 11 deletions
diff --git a/src/vnet/pg/pg.h b/src/vnet/pg/pg.h
index 5e99d9af9f6..5e63b58caf6 100644
--- a/src/vnet/pg/pg.h
+++ b/src/vnet/pg/pg.h
@@ -182,14 +182,38 @@ typedef struct pg_stream_t
} pg_stream_t;
always_inline void
-pg_buffer_index_free (pg_buffer_index_t * bi)
+pg_free_buffers (pg_buffer_index_t *bi)
{
vlib_main_t *vm = vlib_get_main ();
- word n_alloc;
- vec_free (bi->edits);
- n_alloc = clib_fifo_elts (bi->buffer_fifo);
- vlib_buffer_free (vm, bi->buffer_fifo, n_alloc);
- clib_fifo_free (bi->buffer_fifo);
+ uword n_elts, head, len;
+
+ if (!bi || !bi->buffer_fifo)
+ return;
+
+ n_elts = clib_fifo_elts (bi->buffer_fifo);
+ if (n_elts)
+ {
+ len = clib_fifo_len (bi->buffer_fifo);
+ head = clib_fifo_head_index (bi->buffer_fifo);
+
+ if (head + n_elts <= len)
+ vlib_buffer_free (vm, &bi->buffer_fifo[head], n_elts);
+ else
+ {
+ vlib_buffer_free (vm, &bi->buffer_fifo[head], len - head);
+ vlib_buffer_free (vm, bi->buffer_fifo, n_elts - (len - head));
+ }
+ }
+}
+
+always_inline void
+pg_buffer_index_free (pg_buffer_index_t *bi)
+{
+ if (bi)
+ {
+ vec_free (bi->edits);
+ clib_fifo_free (bi->buffer_fifo);
+ }
}
always_inline void
@@ -220,11 +244,16 @@ pg_stream_free (pg_stream_t * s)
vec_free (s->replay_packet_templates);
vec_free (s->replay_packet_timestamps);
- {
- pg_buffer_index_t *bi;
- vec_foreach (bi, s->buffer_indices) pg_buffer_index_free (bi);
- vec_free (s->buffer_indices);
- }
+ if (s->buffer_indices)
+ {
+ pg_buffer_index_t *bi;
+ // We only need to free the buffers from the first array, as the buffers
+ // are chained when packet-generator enable is issued.
+ pg_free_buffers (s->buffer_indices);
+ vec_foreach (bi, s->buffer_indices)
+ pg_buffer_index_free (bi);
+ vec_free (s->buffer_indices);
+ }
}
always_inline int
diff --git a/test/test_pg_stream.py b/test/test_pg_stream.py
new file mode 100644
index 00000000000..6c01d3b7b16
--- /dev/null
+++ b/test/test_pg_stream.py
@@ -0,0 +1,94 @@
+#!/usr/bin/env python3
+
+import unittest
+
+from scapy.packet import Raw
+from scapy.layers.l2 import Ether
+from scapy.layers.inet import IP, UDP
+from scapy.layers.inet6 import IPv6
+
+from framework import VppTestCase
+from asfframework import VppTestRunner
+
+
+class TestPgStream(VppTestCase):
+ """PG Stream Test Case"""
+
+ def __init__(self, *args):
+ VppTestCase.__init__(self, *args)
+
+ def setUp(self):
+ super(TestPgStream, self).setUp()
+
+ # Create 3 pg interfaces - one each for ethernet, IPv4, and IPv6.
+ self.create_pg_interfaces(range(0, 1))
+ self.pg_interfaces += self.create_pg_ip4_interfaces(range(1, 2))
+ self.pg_interfaces += self.create_pg_ip6_interfaces(range(2, 3))
+
+ for i in self.pg_interfaces:
+ i.admin_up()
+
+ for i in [self.pg0, self.pg1]:
+ i.config_ip4()
+
+ for i in [self.pg0, self.pg2]:
+ i.config_ip6()
+
+ self.pg0.resolve_arp()
+ self.pg0.resolve_ndp()
+
+ def tearDown(self):
+ super(TestPgStream, self).tearDown()
+ for i in self.pg_interfaces:
+ i.unconfig_ip4()
+ i.admin_down()
+ i.remove_vpp_config()
+
+ def pg_stream(self, count=100, rate=1e6, packet_size=700):
+ rate = str(rate)
+ packet_size = str(packet_size)
+ count = str(count)
+
+ cmds = [
+ "packet-generator new {{\n"
+ " name pg0-stream\n"
+ " limit {count}\n"
+ " node ethernet-input\n"
+ " source pg0\n"
+ " rate {rate}\n"
+ " size {packet_size}+{packet_size}\n"
+ " data {{\n"
+ " IP4: {src_mac} -> 00:02:03:04:05:06\n"
+ " UDP: 192.168.20.20 -> 192.168.10.100\n"
+ " UDP: 1234 -> 4321\n"
+ " incrementing 100\n"
+ " }}\n"
+ "}}\n".format(
+ count=count,
+ rate=rate,
+ packet_size=packet_size,
+ src_mac=self.pg0.local_mac,
+ ),
+ "packet-generator enable",
+ "packet-generator disable",
+ "packet-generator delete pg0-stream",
+ ]
+
+ for cmd in cmds:
+ r = self.vapi.cli_return_response(cmd)
+ if r.retval != 0:
+ if hasattr(r, "reply"):
+ self.logger.info(cmd + " FAIL reply " + r.reply)
+ else:
+ self.logger.info(cmd + " FAIL retval " + str(r.retval))
+
+ def test_pg_stream(self):
+ """PG Stream testing"""
+ self.pg_stream(rate=100, packet_size=64)
+ self.pg_stream(count=1000, rate=1000)
+ self.pg_stream(count=100000, rate=10000, packet_size=1500)
+ self.pg_stream(packet_size=4000)
+
+
+if __name__ == "__main__":
+ unittest.main(testRunner=VppTestRunner)