+int
+vnet_pcap_dispatch_trace_configure (vnet_pcap_dispatch_trace_args_t * a)
+{
+ vlib_main_t *vm = vlib_get_main ();
+ vlib_rx_or_tx_t rxtx = a->rxtx;
+ vnet_pcap_t *pp = &vm->pcap[rxtx];
+ pcap_main_t *pm = &pp->pcap_main;
+
+ if (a->status)
+ {
+ if (pp->pcap_enable == 0)
+ {
+ vlib_cli_output
+ (vm, "pcap %s dispatch capture enabled: %d of %d pkts...",
+ (rxtx == VLIB_RX) ? "rx" : "tx",
+ pm->n_packets_captured, pm->n_packets_to_capture);
+ vlib_cli_output (vm, "capture to file %s", pm->file_name);
+ }
+ else
+ vlib_cli_output (vm, "pcap %s dispatch capture disabled",
+ (rxtx == VLIB_RX) ? "rx" : "tx");
+ return 0;
+ }
+
+ /* Consistency checks */
+
+ /* Enable w/ capture already enabled not allowed */
+ if (pp->pcap_enable && a->enable)
+ return VNET_API_ERROR_INVALID_VALUE;
+
+ /* Disable capture with capture already disabled, not interesting */
+ if (pp->pcap_enable == 0 && a->enable == 0)
+ return VNET_API_ERROR_VALUE_EXIST;
+
+ /* Change number of packets to capture while capturing */
+ if (pp->pcap_enable && a->enable
+ && (pm->n_packets_to_capture != a->packets_to_capture))
+ return VNET_API_ERROR_INVALID_VALUE_2;
+
+ if (a->enable)
+ {
+ /* Clean up from previous run, if any */
+ vec_free (pm->file_name);
+ vec_free (pm->pcap_data);
+ memset (pm, 0, sizeof (*pm));
+
+ vec_validate_aligned (vnet_trace_dummy, 2048, CLIB_CACHE_LINE_BYTES);
+ if (pm->lock == 0)
+ clib_spinlock_init (&(pm->lock));
+
+ if (a->filename == 0)
+ a->filename = format (0, "/tmp/%s.pcap%c",
+ (rxtx == VLIB_RX) ? "rx" : "tx", 0);
+
+ pm->file_name = (char *) a->filename;
+ pm->n_packets_captured = 0;
+ pm->packet_type = PCAP_PACKET_TYPE_ethernet;
+ pm->n_packets_to_capture = a->packets_to_capture;
+ pp->pcap_sw_if_index = a->sw_if_index;
+ pp->pcap_enable = 1;
+ }
+ else
+ {
+ pp->pcap_enable = 0;
+ if (pm->n_packets_captured)
+ {
+ clib_error_t *error;
+ pm->n_packets_to_capture = pm->n_packets_captured;
+ vlib_cli_output (vm, "Write %d packets to %s, and stop capture...",
+ pm->n_packets_captured, pm->file_name);
+ error = pcap_write (pm);
+ if (pm->file_descriptor >= 0)
+ pcap_close (pm);
+ /* Report I/O errors... */
+ if (error)
+ {
+ clib_error_report (error);
+ return VNET_API_ERROR_SYSCALL_ERROR_1;
+ }
+ return 0;
+ }
+ else
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+ }
+
+ return 0;
+}
+
+static clib_error_t *