diff --git a/.gitignore b/.gitignore index 89469ca99..570a05cf1 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,4 @@ modules.order /sandesh/gen-c/* /test/cmocka /test/atomic-test/x64 +.vscode/* diff --git a/dp-core/vrouter.c b/dp-core/vrouter.c index 1df483b30..2db270af1 100644 --- a/dp-core/vrouter.c +++ b/dp-core/vrouter.c @@ -370,6 +370,10 @@ vrouter_ops_get_process(void *s_req) resp->vo_udp_coff = vr_udp_coff; resp->vo_flow_hold_limit = vr_flow_hold_limit; resp->vo_mudp = vr_mudp; + resp->vo_packet_dump = 0; + if(vr_get_dump_packets != NULL) { + resp->vo_packet_dump = vr_get_dump_packets(); + } /* Build info */ strncpy(resp->vo_build_info, ContrailBuildInfo, @@ -438,6 +442,8 @@ vrouter_ops_add_process(void *s_req) vr_set_log_type(req->vo_log_type_disable[i], 0); /* Runtime parameters */ + if (req->vo_packet_dump != -1 && vr_set_dump_packets != NULL) + vr_set_dump_packets(req->vo_packet_dump); if (req->vo_perfr != -1) vr_perfr = req->vo_perfr; if (req->vo_perfs != -1) @@ -679,4 +685,3 @@ vr_hugepage_config_process(void *s_req) return; } - diff --git a/include/vrouter.h b/include/vrouter.h index 000883ab9..d47bd47dc 100644 --- a/include/vrouter.h +++ b/include/vrouter.h @@ -233,7 +233,8 @@ struct host_os { int (*hos_offload_flow_create)(struct vr_offload_flow *oflow); int (*hos_offload_flow_destroy)(struct vr_offload_flow *oflow); void (*hos_offload_prepare)(struct vr_packet *pkt, struct vr_forwarding_md *fmd); - + void (*hos_set_dump_packets)(int); + int (*hos_get_dump_packets)(void); }; #define vr_printf vrouter_host->hos_printf @@ -289,6 +290,8 @@ struct host_os { #define vr_offload_flow_destroy vrouter_host->hos_offload_flow_destroy #define vr_offload_flow_create vrouter_host->hos_offload_flow_create #define vr_offload_prepare vrouter_host->hos_offload_prepare +#define vr_set_dump_packets vrouter_host->hos_set_dump_packets +#define vr_get_dump_packets vrouter_host->hos_get_dump_packets extern struct host_os *vrouter_host; diff --git a/sandesh/vr.sandesh b/sandesh/vr.sandesh index 6678fee14..0e4a7b470 100644 --- a/sandesh/vr.sandesh +++ b/sandesh/vr.sandesh @@ -311,6 +311,7 @@ buffer sandesh vrouter_ops { 38: u32 vo_priority_tagging; 39: i32 vo_vif_bridge_entries; 40: i32 vo_vif_oflow_bridge_entries; + 41: i32 vo_packet_dump; } buffer sandesh vr_mem_stats_req { diff --git a/test/windows/SConscript b/test/windows/SConscript index 46945613d..516287f41 100644 --- a/test/windows/SConscript +++ b/test/windows/SConscript @@ -22,7 +22,7 @@ env.Append(LIBS = 'cmocka') env.AppendENVPath('Path', Dir('#build/bin')) -common_tests_src = ['fake_win_packet_raw.c', 'fake_win_memory.c', 'fake_vrouter.c'] +common_tests_src = ['fake_win_packet_raw.c', 'fake_win_memory.c', 'fake_vrouter.c', 'fake_win_packetdump.c'] common_tests_obj = env.Object(common_tests_src) test_suite_base_names = [ diff --git a/test/windows/fake_win_packetdump.c b/test/windows/fake_win_packetdump.c new file mode 100644 index 000000000..c320dc6d0 --- /dev/null +++ b/test/windows/fake_win_packetdump.c @@ -0,0 +1,7 @@ +#include + +void +DontWriteVrPacketToFile(struct vr_packet *packet, char tag[]) {} + +typedef void (*PWRITEVRPACKETTOFILEFUNCTION)(struct vr_packet *packet, char tag[]); +extern PWRITEVRPACKETTOFILEFUNCTION PacketToFileWriter = DontWriteVrPacketToFile; diff --git a/utils/vr_util.c b/utils/vr_util.c index 2a25f13e7..bdf619b9b 100644 --- a/utils/vr_util.c +++ b/utils/vr_util.c @@ -869,7 +869,7 @@ vr_interface_req_destroy(vr_interface_req *req) req->vifr_fat_flow_dst_aggregate_plen_size = 0; } - if (req->vifr_fat_flow_exclude_ip_list_size && + if (req->vifr_fat_flow_exclude_ip_list_size && req->vifr_fat_flow_exclude_ip_list) { free(req->vifr_fat_flow_exclude_ip_list); req->vifr_fat_flow_exclude_ip_list = NULL; @@ -881,7 +881,7 @@ vr_interface_req_destroy(vr_interface_req *req) req->vifr_fat_flow_exclude_ip6_u_list = NULL; req->vifr_fat_flow_exclude_ip6_u_list_size = 0; } - if (req->vifr_fat_flow_exclude_ip6_l_list_size && + if (req->vifr_fat_flow_exclude_ip6_l_list_size && req->vifr_fat_flow_exclude_ip6_l_list) { free(req->vifr_fat_flow_exclude_ip6_l_list); req->vifr_fat_flow_exclude_ip6_l_list = NULL; @@ -1077,7 +1077,7 @@ vr_interface_req_get_copy(vr_interface_req *src) if (!dst->vifr_fat_flow_exclude_ip_list) { goto free_vif; } - memcpy(dst->vifr_fat_flow_exclude_ip_list, src->vifr_fat_flow_exclude_ip_list, + memcpy(dst->vifr_fat_flow_exclude_ip_list, src->vifr_fat_flow_exclude_ip_list, src->vifr_fat_flow_exclude_ip_list_size * sizeof(uint64_t)); dst->vifr_fat_flow_exclude_ip_list_size = src->vifr_fat_flow_exclude_ip_list_size; } @@ -1088,7 +1088,7 @@ vr_interface_req_get_copy(vr_interface_req *src) if (!dst->vifr_fat_flow_exclude_ip6_u_list) { goto free_vif; } - memcpy(dst->vifr_fat_flow_exclude_ip6_u_list, src->vifr_fat_flow_exclude_ip6_u_list, + memcpy(dst->vifr_fat_flow_exclude_ip6_u_list, src->vifr_fat_flow_exclude_ip6_u_list, src->vifr_fat_flow_exclude_ip6_u_list_size * sizeof(uint64_t)); dst->vifr_fat_flow_exclude_ip6_u_list_size = src->vifr_fat_flow_exclude_ip6_u_list_size; } @@ -1098,7 +1098,7 @@ vr_interface_req_get_copy(vr_interface_req *src) if (!dst->vifr_fat_flow_exclude_ip6_l_list) { goto free_vif; } - memcpy(dst->vifr_fat_flow_exclude_ip6_l_list, src->vifr_fat_flow_exclude_ip6_l_list, + memcpy(dst->vifr_fat_flow_exclude_ip6_l_list, src->vifr_fat_flow_exclude_ip6_l_list, src->vifr_fat_flow_exclude_ip6_l_list_size * sizeof(uint64_t)); dst->vifr_fat_flow_exclude_ip6_l_list_size = src->vifr_fat_flow_exclude_ip6_l_list_size; } @@ -2082,6 +2082,7 @@ vr_send_vrouter_set_logging(struct nl_client *cl, unsigned int router_id, req.vo_udp_coff = -1; req.vo_flow_hold_limit = -1; req.vo_mudp = -1; + req.vo_packet_dump = -1; return vr_sendmsg(cl, &req, "vrouter_ops"); } @@ -2092,7 +2093,7 @@ vr_send_vrouter_set_runtime_opts(struct nl_client *cl, unsigned int router_id, int perfr1, int perfr2, int perfr3, int perfp, int perfq1, int perfq2, int perfq3, int udp_coff, int flow_hold_limit, int mudp, int btokens, int binterval, int bstep, - unsigned int priority_tagging) + unsigned int priority_tagging, int packet_dump) { vrouter_ops req; @@ -2124,6 +2125,7 @@ vr_send_vrouter_set_runtime_opts(struct nl_client *cl, unsigned int router_id, req.vo_burst_interval = binterval; req.vo_burst_step = bstep; req.vo_priority_tagging = priority_tagging; + req.vo_packet_dump = packet_dump; /* * We create request to change runtime (sysctl) options only. Log level diff --git a/utils/vrouter.c b/utils/vrouter.c index b31b208ad..094dc237d 100644 --- a/utils/vrouter.c +++ b/utils/vrouter.c @@ -56,6 +56,7 @@ enum opt_vrouter_index { SET_BURST_INTERVAL_INDEX, SET_BURST_STEP_INDEX, SET_PRIORITY_TAGGING_INDEX, + SET_PACKET_DUMP_INDEX, MAX_OPT_INDEX }; @@ -124,6 +125,7 @@ static int perfr1 = -1, perfr2 = -1, perfr3 = -1, perfp = -1, perfq1 = -1; static int perfq2 = -1, perfq3 = -1, udp_coff = -1, flow_hold_limit = -1; static int mudp = -1, burst_tokens = -1, burst_interval = -1, burst_step = -1; static unsigned int priority_tagging = 0; +static int packet_dump = -1; static int platform, vrouter_op = -1; @@ -331,6 +333,7 @@ print_vrouter_parameters(vrouter_ops *req) " Burst Interval %u\n" " Burst Step %u\n" " NIC Priority Tagging %u\n" + " Packet dump %u\n" "\n", req->vo_perfr, req->vo_perfs, @@ -341,7 +344,7 @@ print_vrouter_parameters(vrouter_ops *req) req->vo_flow_used_entries, req->vo_flow_used_oentries, req->vo_bridge_used_entries, req->vo_bridge_used_oentries, req->vo_burst_tokens, req->vo_burst_interval, req->vo_burst_step, - req->vo_priority_tagging + req->vo_priority_tagging, req->vo_packet_dump ); return; @@ -443,7 +446,7 @@ vr_vrouter_op(struct nl_client *cl) perfr1, perfr2, perfr3, perfp, perfq1, perfq2, perfq3, udp_coff, flow_hold_limit, mudp, burst_tokens, burst_interval, burst_step, - priority_tagging); + priority_tagging, packet_dump); } break; @@ -534,6 +537,9 @@ static struct option long_options[] = { [SET_PRIORITY_TAGGING_INDEX] = { "set-priority-tagging", required_argument, &opt[SET_PRIORITY_TAGGING_INDEX], 1 }, + [SET_PACKET_DUMP_INDEX] = { + "packet-dump", required_argument, &opt[SET_PACKET_DUMP_INDEX], 1 + }, [MAX_OPT_INDEX] = {NULL, 0, 0, 0} }; @@ -608,6 +614,7 @@ Usage(void) "--burst_interval timer interval of burst tokens in ms\n" "--burst_step burst tokens to add at every interval\n" "--set-priority-tagging <1 | 0> priority tagging on the NIC\n" + "--packet-dump <1 | 0> dumps packets\n" "--help Prints this message\n" "\n"); break; @@ -900,6 +907,16 @@ parse_long_opts(int opt_index, char *opt_arg) break; + case SET_PACKET_DUMP_INDEX: + vrouter_op = SANDESH_OP_ADD; + packet_dump = (int)strtol(opt_arg, NULL, 0); + if (errno != 0) { + printf("vrouter: Error parsing packet_dump: %s: %s (%d)\n", opt_arg, + strerror(errno), errno); + Usage(); + } + break; + case HELP_OPT_INDEX: default: Usage(); diff --git a/windows/vRouter.vcxproj b/windows/vRouter.vcxproj index 1195df061..1a00b075e 100644 --- a/windows/vRouter.vcxproj +++ b/windows/vRouter.vcxproj @@ -134,6 +134,7 @@ + @@ -194,6 +195,7 @@ + diff --git a/windows/vr_driver.c b/windows/vr_driver.c index 32502f910..69f011587 100644 --- a/windows/vr_driver.c +++ b/windows/vr_driver.c @@ -6,6 +6,7 @@ #include "windows_shmem.h" #include "windows_nbl.h" #include "win_interface.h" +#include "win_packetdump.h" #include #include @@ -270,6 +271,8 @@ InitializeVRouter(pvr_switch_context ctx) static NDIS_STATUS InitializeWindowsComponents(PSWITCH_OBJECT Switch) { + InitPacketDumping(); + pvr_switch_context ctx = NULL; ctx = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(vr_switch_context), VrAllocationTag); diff --git a/windows/vr_host.c b/windows/vr_host.c index 993e68e2d..3327cc281 100644 --- a/windows/vr_host.c +++ b/windows/vr_host.c @@ -9,6 +9,7 @@ #include "vr_windows.h" #include "vrouter.h" +#include "win_packetdump.h" #include "win_callbacks.h" #include "win_packet.h" #include "win_packet_raw.h" @@ -934,6 +935,24 @@ win_register_nic(struct vr_interface* vif, vr_interface_req* vifr) vif_attach(vif); } +static void +win_set_dump_packets(int packets_dump_flag) +{ + if(packets_dump_flag == 1) + EnablePacketDumping(); + else + DisablePacketDumping(); +} + +static int +win_get_dump_packets(void) +{ + if(IsPacketDumpingEnabled()) + return 1; + + return 0; +} + struct host_os windows_host = { .hos_printf = win_printf, .hos_malloc = win_malloc, @@ -984,6 +1003,8 @@ struct host_os windows_host = { .hos_get_enabled_log_types = win_get_enabled_log_types, .hos_soft_reset = win_soft_reset, .hos_register_nic = win_register_nic, + .hos_set_dump_packets = win_set_dump_packets, + .hos_get_dump_packets = win_get_dump_packets, }; struct host_os * diff --git a/windows/win_packetdump.c b/windows/win_packetdump.c new file mode 100644 index 000000000..dd6fba63a --- /dev/null +++ b/windows/win_packetdump.c @@ -0,0 +1,286 @@ +#include "win_packetdump.h" +#include +#include "win_memory.h" +#include "win_packet_raw.h" +#include "win_packet.h" +#include "win_packet_impl.h" +#include "vr_windows.h" + +#define TEMP_BUFFER_SIZE 512 +#define OUTPUT_BUFFER_SIZE 10240 + +static NDIS_IO_WORKITEM_FUNCTION WritePacketToFileWork; +static NDIS_MUTEX packetWriterMutex; + +static VOID +WritePacketToFileWork(PVOID work_item_context, NDIS_HANDLE work_item_handle) +{ + char* outputBuffer = (char*)(work_item_context); + + UNICODE_STRING uniName; + OBJECT_ATTRIBUTES objAttr; + + RtlInitUnicodeString(&uniName, L"\\DosDevices\\C:\\packetsdump.txt"); + InitializeObjectAttributes(&objAttr, &uniName, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, NULL); + + HANDLE handle; + NTSTATUS ntstatus; + IO_STATUS_BLOCK ioStatusBlock; + NDIS_WAIT_FOR_MUTEX(&packetWriterMutex); + ntstatus = ZwCreateFile(&handle, + FILE_APPEND_DATA | SYNCHRONIZE, + &objAttr, &ioStatusBlock, NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_OPEN_IF, + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, 0); + + if(NT_SUCCESS(ntstatus)) { + LARGE_INTEGER byteOffset; + byteOffset.LowPart = FILE_USE_FILE_POINTER_POSITION; + byteOffset.HighPart = -1; + size_t cb; + ntstatus = RtlStringCbLengthA(outputBuffer, OUTPUT_BUFFER_SIZE, &cb); + if(NT_SUCCESS(ntstatus)) { + ntstatus = ZwWriteFile(handle, NULL, NULL, NULL, &ioStatusBlock, + outputBuffer, cb, &byteOffset, NULL); + } + ZwClose(handle); + } + NDIS_RELEASE_MUTEX(&packetWriterMutex); + + NdisFreeIoWorkItem(work_item_handle); + WinRawFree(outputBuffer); +} + +static NTSTATUS +AddVrPacketJSONInformation(struct vr_packet *packet, char* outputBuffer, size_t outputBufferSize) +{ + static const char vrPacketJsonFormat[] = ",\"vrpacket\":{" + "\"vp_data\":%d," + "\"vp_tail\":%d," + "\"vp_len\":%d," + "\"vp_end\":%d," + "\"vp_network_h\":%d," + "\"vp_flags\":%d," + "\"vp_inner_network_h\":%d," + "\"vp_cpu\":%d," + "\"vp_type\":%d," + "\"vp_ttl\":%d," + "\"vp_queue\":%d," + "\"vp_priority\":%d," + "\"vp_if->vif_mtu\":%d" + "}"; + + char tempBuffer[TEMP_BUFFER_SIZE]; + NTSTATUS ntstatus; + ntstatus = RtlStringCbPrintfA(tempBuffer, TEMP_BUFFER_SIZE, vrPacketJsonFormat, + (unsigned long)packet->vp_data, + (unsigned long)packet->vp_tail, + (unsigned long)packet->vp_len, + (unsigned long)packet->vp_end, + (unsigned long)packet->vp_network_h, + (unsigned long)packet->vp_flags, + (unsigned long)packet->vp_inner_network_h, + (unsigned long)packet->vp_cpu, + (unsigned long)packet->vp_type, + (unsigned long)packet->vp_ttl, + (unsigned long)packet->vp_queue, + (unsigned long)packet->vp_priority, + (unsigned long)packet->vp_if->vif_mtu); + if(!NT_SUCCESS(ntstatus)) { + return ntstatus; + } + + ntstatus = RtlStringCbCatA(outputBuffer, outputBufferSize, tempBuffer); + + return ntstatus; +} + +static NTSTATUS +AddPacketMetaDataJSONInformation(struct vr_packet *packet, char* outputBuffer, size_t outputBufferSize) +{ + PWIN_PACKET winPacket = GetWinPacketFromVrPacket(packet); + PWIN_PACKET_RAW winPacketRaw = WinPacketToRawPacket(winPacket); + PNET_BUFFER_LIST nbl = WinPacketRawToNBL(winPacketRaw); + + NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO lso_info; + NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO settings; + + lso_info.Value = NET_BUFFER_LIST_INFO(nbl, TcpLargeSendNetBufferListInfo); + settings.Value = NET_BUFFER_LIST_INFO(nbl, TcpIpChecksumNetBufferListInfo); + + static const char metaDataJsonFormat[] = ",\"metaData\":{" + "\"MSS\":%d," + "\"IsIPv4\":%d," + "\"IsIPv6\":%d," + "\"TcpChecksum\":%d," + "\"UdpChecksum\":%d," + "\"IpHeaderChecksum\":%d," + "\"TcpHeaderOffset\":%d" + "}"; + + char tempBuffer[TEMP_BUFFER_SIZE]; + NTSTATUS ntstatus; + ntstatus = RtlStringCbPrintfA(tempBuffer, TEMP_BUFFER_SIZE, metaDataJsonFormat, + (unsigned long)lso_info.LsoV2Transmit.MSS, + (unsigned long)settings.Transmit.IsIPv4, + (unsigned long)settings.Transmit.IsIPv6, + (unsigned long)settings.Transmit.TcpChecksum, + (unsigned long)settings.Transmit.UdpChecksum, + (unsigned long)settings.Transmit.IpHeaderChecksum, + (unsigned long)settings.Transmit.TcpHeaderOffset); + + if(!NT_SUCCESS(ntstatus)) { + return ntstatus; + } + + ntstatus = RtlStringCbCatA(outputBuffer, outputBufferSize, tempBuffer); + + return ntstatus; +} + +static NTSTATUS +DumpBufferToHex(uint8_t* buffer, size_t bufferSize, char* outputBuffer, size_t outputBufferSize) +{ + char tempBuffer[4]; + NTSTATUS ntstatus; + + ntstatus = RtlStringCbPrintfA(outputBuffer, outputBufferSize, ""); + if(NT_SUCCESS(ntstatus)) { + for (int i = 0; i < bufferSize; i++) { + ntstatus = RtlStringCbPrintfA(tempBuffer, 4, "%02X ", buffer[i]); + if(!NT_SUCCESS(ntstatus)) { + return ntstatus; + } + ntstatus = RtlStringCbCatA(outputBuffer, outputBufferSize, tempBuffer); + if(!NT_SUCCESS(ntstatus)) { + return ntstatus; + } + } + } + + return ntstatus; +} + +static NTSTATUS +AddBytesJSONInformation(struct vr_packet *packet, char* outputBuffer, size_t outputBufferSize) +{ + ULONG packetBufferSize = pkt_len(packet); + uint8_t* packetBuffer = (uint8_t*)WinRawAllocate(packetBufferSize); + + // 2 letters and space for each byte in hex + // plus 0 at the end of the string + size_t packetBytesAsCharBufferSize = packetBufferSize*3 + 1; + char* packetBytesAsCharBuffer = (char*)WinRawAllocate(packetBytesAsCharBufferSize); + + char* tempBuffer = (char*)WinRawAllocate(OUTPUT_BUFFER_SIZE); + + if (packetBuffer == NULL || packetBytesAsCharBuffer == NULL || tempBuffer == NULL) { + if (packetBuffer != NULL) { + WinRawFree(packetBuffer); + } + if(packetBytesAsCharBuffer != NULL) { + WinRawFree(packetBytesAsCharBuffer); + } + if(tempBuffer != NULL) { + WinRawFree(tempBuffer); + } + return STATUS_INSUFFICIENT_RESOURCES; + } + + vr_pcopy(packetBuffer, packet, packet->vp_data, packetBufferSize); + + NTSTATUS ntstatus; + ntstatus = DumpBufferToHex(packetBuffer, packetBufferSize, packetBytesAsCharBuffer, packetBytesAsCharBufferSize); + if(NT_SUCCESS(ntstatus)) { + ntstatus = RtlStringCbPrintfA(tempBuffer, OUTPUT_BUFFER_SIZE, ",\"bytes\":\"%s\"", packetBytesAsCharBuffer); + if(NT_SUCCESS(ntstatus)) { + ntstatus = RtlStringCbCatA(outputBuffer, outputBufferSize, tempBuffer); + } + } + + WinRawFree(packetBuffer); + WinRawFree(packetBytesAsCharBuffer); + WinRawFree(tempBuffer); + + return ntstatus; +} + +static void +WriteVrPacketToFile(struct vr_packet *packet, char tag[]) +{ + static volatile int lastPacketNumber = 0; + int packetNumber = InterlockedIncrement(&lastPacketNumber); + + // Needs initialization before first 'goto clean' + NDIS_HANDLE workItem = NULL; + + char* outputBuffer = (char*)WinRawAllocate(OUTPUT_BUFFER_SIZE); + + if (outputBuffer == NULL) { + return; + } + + if(!NT_SUCCESS(RtlStringCbPrintfA(outputBuffer, OUTPUT_BUFFER_SIZE, "{\"number\":%d,\"tag\":\"%s\"", packetNumber, tag))) { + goto clean; + } + + if(!NT_SUCCESS(AddVrPacketJSONInformation(packet, outputBuffer, OUTPUT_BUFFER_SIZE))) { + goto clean; + } + + if(!NT_SUCCESS(AddPacketMetaDataJSONInformation(packet, outputBuffer, OUTPUT_BUFFER_SIZE))) { + goto clean; + } + + if(!NT_SUCCESS(AddBytesJSONInformation(packet, outputBuffer, OUTPUT_BUFFER_SIZE))) { + goto clean; + } + + if(!NT_SUCCESS(RtlStringCbCatA(outputBuffer, OUTPUT_BUFFER_SIZE, "},\n"))) { + goto clean; + } + + workItem = NdisAllocateIoWorkItem(VrDriverHandle); + if(workItem) { + NdisQueueIoWorkItem(workItem, WritePacketToFileWork, (PVOID)(outputBuffer)); + } + + clean: + if(outputBuffer != NULL && workItem == NULL) { + WinRawFree(outputBuffer); + } +} + +static void +DontWriteVrPacketToFile(struct vr_packet *packet, char tag[]) {} + +PWRITEVRPACKETTOFILEFUNCTION PacketToFileWriter = DontWriteVrPacketToFile; + +void +EnablePacketDumping() +{ + PacketToFileWriter = WriteVrPacketToFile; +} + +void +DisablePacketDumping() +{ + PacketToFileWriter = DontWriteVrPacketToFile; +} + +bool +IsPacketDumpingEnabled() +{ + return PacketToFileWriter == WriteVrPacketToFile; +} + +void +InitPacketDumping() +{ + NDIS_INIT_MUTEX(&packetWriterMutex); +} diff --git a/windows/win_packetdump.h b/windows/win_packetdump.h new file mode 100644 index 000000000..97f725084 --- /dev/null +++ b/windows/win_packetdump.h @@ -0,0 +1,27 @@ +/* + * win_packetdump.h + * + * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved. + */ +#ifndef __WIN_PACKETDUMP_H__ +#define __WIN_PACKETDUMP_H__ + +#include + +void +EnablePacketDumping(); + +void +DisablePacketDumping(); + +bool +IsPacketDumpingEnabled(); + +void +InitPacketDumping(); + +typedef void (*PWRITEVRPACKETTOFILEFUNCTION)(struct vr_packet *packet, char tag[]); + +extern PWRITEVRPACKETTOFILEFUNCTION PacketToFileWriter; + +#endif // __WIN_PACKETDUMP_H__ diff --git a/windows/win_tx_postprocess.c b/windows/win_tx_postprocess.c index cda23276c..f0ab87214 100644 --- a/windows/win_tx_postprocess.c +++ b/windows/win_tx_postprocess.c @@ -12,6 +12,8 @@ #include "win_packet_splitting.h" #include "win_packet.h" +#include "win_packetdump.h" + static void fix_ip_csum_at_offset(struct vr_packet *pkt, unsigned offset) { @@ -156,6 +158,8 @@ fix_ip_v4_csum(struct vr_packet *pkt) PWIN_MULTI_PACKET WinTxPostprocess(struct vr_packet *VrPacket) { + PacketToFileWriter(VrPacket, "before_postprocess"); + if (vr_pkt_type_is_overlay(VrPacket->vp_type)) { fix_tunneled_csum(VrPacket); } else if (VrPacket->vp_type == VP_TYPE_IP) {