api: pcap capture api update
Allow enabling and disabling pcap capture via the API. A little bug is fixed along the way in vl_api_classify_pcap_set_table_t_handler. Type: improvement Signed-off-by: Maxime Peim <mpeim@cisco.com> Change-Id: I096129c82aecdc82bee5dbfb5e19c76a51d80aab
This commit is contained in:
@ -115,9 +115,8 @@ static void vl_api_classify_pcap_set_table_t_handler
|
||||
u32 table_index = ntohl (mp->table_index);
|
||||
u32 sw_if_index = ntohl (mp->sw_if_index);
|
||||
|
||||
if (sw_if_index == ~0
|
||||
|| sw_if_index >= vec_len (cm->classify_table_index_by_sw_if_index)
|
||||
|| (table_index != ~0 && pool_is_free_index (cm->tables, table_index)))
|
||||
if (sw_if_index == ~0 ||
|
||||
(table_index != ~0 && pool_is_free_index (cm->tables, table_index)))
|
||||
{
|
||||
rv = VNET_API_ERROR_INVALID_VALUE;
|
||||
goto out;
|
||||
|
@ -733,6 +733,47 @@ autoreply define collect_detailed_interface_stats
|
||||
bool enable_disable;
|
||||
};
|
||||
|
||||
/** \brief pcap_trace_on
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param capture_rx - capture received packets
|
||||
@param capture_tx - capture transmitted packets
|
||||
@param capture_drop - capture dropped packets
|
||||
@param filter - is a filter is being used on this capture
|
||||
@param preallocate_data - preallocate the data buffer
|
||||
@param free_data - free the data buffer
|
||||
@param max_packets - depth of local buffer
|
||||
@param max_bytes_per_packet - maximum number of bytes to capture
|
||||
for each packet
|
||||
@param sw_if_index - specify a given interface, or 0 for any
|
||||
@param error - filter packets based on a specific error.
|
||||
@param filename - output filename, will be placed in /tmp
|
||||
*/
|
||||
autoreply define pcap_trace_on
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
bool capture_rx;
|
||||
bool capture_tx;
|
||||
bool capture_drop;
|
||||
bool filter;
|
||||
bool preallocate_data;
|
||||
bool free_data;
|
||||
u32 max_packets [default=1000];
|
||||
u32 max_bytes_per_packet [default=512];
|
||||
vl_api_interface_index_t sw_if_index;
|
||||
string error[128];
|
||||
string filename[64];
|
||||
|
||||
option vat_help = "pcap_trace_on [capture_rx] [capture_tx] [capture_drop] [max_packets <nn>] [sw_if_index <sw_if_index>|0 for any] [error <node>.<error>] [filename <name>] [max_bytes_per_packet <nnnn>] [filter] [preallocate_data] [free_data]";
|
||||
};
|
||||
|
||||
autoreply define pcap_trace_off
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
};
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
|
@ -1604,6 +1604,65 @@ static void
|
||||
REPLY_MACRO (VL_API_SW_INTERFACE_ADDRESS_REPLACE_END_REPLY);
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_pcap_trace_on_t_handler (vl_api_pcap_trace_on_t *mp)
|
||||
{
|
||||
vl_api_pcap_trace_on_reply_t *rmp;
|
||||
unformat_input_t filename, drop_err_name;
|
||||
vnet_pcap_dispatch_trace_args_t capture_args;
|
||||
int rv = 0;
|
||||
|
||||
VALIDATE_SW_IF_INDEX (mp);
|
||||
|
||||
unformat_init_cstring (&filename, (char *) mp->filename);
|
||||
if (!unformat_user (&filename, unformat_vlib_tmpfile,
|
||||
&capture_args.filename))
|
||||
{
|
||||
rv = VNET_API_ERROR_ILLEGAL_NAME;
|
||||
goto out;
|
||||
}
|
||||
|
||||
capture_args.rx_enable = mp->capture_rx;
|
||||
capture_args.tx_enable = mp->capture_tx;
|
||||
capture_args.preallocate_data = mp->preallocate_data;
|
||||
capture_args.free_data = mp->free_data;
|
||||
capture_args.drop_enable = mp->capture_drop;
|
||||
capture_args.status = 0;
|
||||
capture_args.packets_to_capture = ntohl (mp->max_packets);
|
||||
capture_args.sw_if_index = ntohl (mp->sw_if_index);
|
||||
capture_args.filter = mp->filter;
|
||||
capture_args.max_bytes_per_pkt = ntohl (mp->max_bytes_per_packet);
|
||||
capture_args.drop_err = ~0;
|
||||
|
||||
unformat_init_cstring (&drop_err_name, (char *) mp->error);
|
||||
unformat_user (&drop_err_name, unformat_vlib_error, vlib_get_main (),
|
||||
&capture_args.drop_err);
|
||||
|
||||
rv = vnet_pcap_dispatch_trace_configure (&capture_args);
|
||||
|
||||
BAD_SW_IF_INDEX_LABEL;
|
||||
|
||||
out:
|
||||
unformat_free (&filename);
|
||||
unformat_free (&drop_err_name);
|
||||
|
||||
REPLY_MACRO (VL_API_PCAP_TRACE_ON_REPLY);
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_pcap_trace_off_t_handler (vl_api_pcap_trace_off_t *mp)
|
||||
{
|
||||
vl_api_pcap_trace_off_reply_t *rmp;
|
||||
vnet_pcap_dispatch_trace_args_t capture_args;
|
||||
int rv = 0;
|
||||
|
||||
clib_memset (&capture_args, 0, sizeof (capture_args));
|
||||
|
||||
rv = vnet_pcap_dispatch_trace_configure (&capture_args);
|
||||
|
||||
REPLY_MACRO (VL_API_PCAP_TRACE_OFF_REPLY);
|
||||
}
|
||||
|
||||
/*
|
||||
* vpe_api_hookup
|
||||
* Add vpe's API message handlers to the table.
|
||||
|
@ -2390,7 +2390,7 @@ pcap_trace_command_fn (vlib_main_t * vm,
|
||||
* any-interface tests fail.
|
||||
*
|
||||
* - <b>error <node>.<error></b> - filter packets based on a specific error.
|
||||
* For example: error {ip4-udp-lookup}.{No listener for dst port}
|
||||
* For example: error {ip4-udp-lookup}.{no_listener}
|
||||
*
|
||||
* - <b>file <name></b> - Used to specify the output filename. The file will
|
||||
* be placed in the '<em>/tmp</em>' directory, so only the filename is
|
||||
|
@ -1283,6 +1283,18 @@ api_sw_interface_set_interface_name (vat_main_t *vam)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
api_pcap_trace_on (vat_main_t *vam)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
api_pcap_trace_off (vat_main_t *vam)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#include <vnet/interface.api_test.c>
|
||||
|
||||
/*
|
||||
|
@ -3,8 +3,11 @@
|
||||
import os
|
||||
import unittest
|
||||
|
||||
from scapy.layers.l2 import Ether
|
||||
from scapy.layers.inet import IP, UDP
|
||||
from scapy.packet import Raw
|
||||
|
||||
from asfframework import VppTestCase, VppTestRunner
|
||||
from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath
|
||||
|
||||
|
||||
class TestPcap(VppTestCase):
|
||||
@ -14,8 +17,17 @@ class TestPcap(VppTestCase):
|
||||
def setUpClass(cls):
|
||||
super(TestPcap, cls).setUpClass()
|
||||
|
||||
cls.create_pg_interfaces(range(1))
|
||||
for i in cls.pg_interfaces:
|
||||
i.admin_up()
|
||||
i.config_ip4()
|
||||
i.resolve_arp()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
for i in cls.pg_interfaces:
|
||||
i.admin_down()
|
||||
|
||||
super(TestPcap, cls).tearDownClass()
|
||||
|
||||
def setUp(self):
|
||||
@ -86,6 +98,66 @@ class TestPcap(VppTestCase):
|
||||
os.remove("/tmp/rxtx.pcap")
|
||||
os.remove("/tmp/filt.pcap")
|
||||
|
||||
def test_pcap_trace_api(self):
|
||||
"""PCAP API Tests"""
|
||||
|
||||
pkt = (
|
||||
Ether(src=self.pg0.local_mac, dst=self.pg0.remote_mac)
|
||||
/ IP(src=self.pg0.local_ip4, dst=self.pg0.remote_ip4, ttl=2)
|
||||
/ UDP(sport=1234, dport=2345)
|
||||
/ Raw(b"\xa5" * 128)
|
||||
)
|
||||
|
||||
self.vapi.pcap_trace_on(
|
||||
capture_rx=True,
|
||||
capture_tx=True,
|
||||
max_packets=1000,
|
||||
sw_if_index=0,
|
||||
filename="trace_any.pcap",
|
||||
)
|
||||
self.pg_send(self.pg0, pkt * 10)
|
||||
self.vapi.pcap_trace_off()
|
||||
|
||||
self.vapi.cli(
|
||||
f"classify filter pcap mask l3 ip4 src match l3 ip4 src {self.pg0.local_ip4}"
|
||||
)
|
||||
self.vapi.pcap_trace_on(
|
||||
capture_rx=True,
|
||||
capture_tx=True,
|
||||
filter=True,
|
||||
max_packets=1000,
|
||||
sw_if_index=0,
|
||||
filename="trace_any_filter.pcap",
|
||||
)
|
||||
self.pg_send(self.pg0, pkt * 10)
|
||||
self.vapi.pcap_trace_off()
|
||||
self.vapi.cli("classify filter pcap del mask l3 ip4 src")
|
||||
|
||||
pkt = (
|
||||
Ether(src=self.pg0.local_mac, dst=self.pg0.remote_mac)
|
||||
# wrong destination address
|
||||
/ IP(src=self.pg0.local_ip4, dst=self.pg0.local_ip4, ttl=2)
|
||||
/ UDP(sport=1234, dport=2345)
|
||||
/ Raw(b"\xa5" * 128)
|
||||
)
|
||||
|
||||
self.vapi.pcap_trace_on(
|
||||
capture_drop=True,
|
||||
max_packets=1000,
|
||||
sw_if_index=0,
|
||||
error="{ip4-local}.{spoofed_local_packets}",
|
||||
filename="trace_drop_err.pcap",
|
||||
)
|
||||
self.pg_send(self.pg0, pkt * 10)
|
||||
self.vapi.pcap_trace_off()
|
||||
|
||||
self.assertTrue(os.path.exists("/tmp/trace_any.pcap"))
|
||||
self.assertTrue(os.path.exists("/tmp/trace_any_filter.pcap"))
|
||||
self.assertTrue(os.path.exists("/tmp/trace_drop_err.pcap"))
|
||||
os.remove("/tmp/trace_any.pcap")
|
||||
os.remove("/tmp/trace_any_filter.pcap")
|
||||
os.remove("/tmp/trace_drop_err.pcap")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main(testRunner=VppTestRunner)
|
||||
|
Reference in New Issue
Block a user