1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright 2019 Ramon Fried <rfried.dev@gmail.com> 4 */ 5 6#include <common.h> 7#include <net.h> 8#include <net/pcap.h> 9#include <time.h> 10#include <asm/io.h> 11 12#define LINKTYPE_ETHERNET 1 13 14static bool initialized; 15static bool running; 16static bool buffer_full; 17static void *buf; 18static unsigned int max_size; 19static unsigned int pos; 20 21static unsigned long incoming_count; 22static unsigned long outgoing_count; 23 24struct pcap_header { 25 u32 magic; 26 u16 version_major; 27 u16 version_minor; 28 s32 thiszone; 29 u32 sigfigs; 30 u32 snaplen; 31 u32 network; 32}; 33 34struct pcap_packet_header { 35 u32 ts_sec; 36 u32 ts_usec; 37 u32 incl_len; 38 u32 orig_len; 39}; 40 41static struct pcap_header file_header = { 42 .magic = 0xa1b2c3d4, 43 .version_major = 2, 44 .version_minor = 4, 45 .snaplen = 65535, 46 .network = LINKTYPE_ETHERNET, 47}; 48 49int pcap_init(phys_addr_t paddr, unsigned long size) 50{ 51 buf = map_physmem(paddr, size, 0); 52 if (!buf) { 53 printf("Failed mapping PCAP memory\n"); 54 return -ENOMEM; 55 } 56 57 printf("PCAP capture initialized: addr: 0x%lx max length: %lu\n", 58 (unsigned long)buf, size); 59 60 memcpy(buf, &file_header, sizeof(file_header)); 61 pos = sizeof(file_header); 62 max_size = size; 63 initialized = true; 64 running = false; 65 buffer_full = false; 66 incoming_count = 0; 67 outgoing_count = 0; 68 return 0; 69} 70 71int pcap_start_stop(bool start) 72{ 73 if (!initialized) { 74 printf("error: pcap was not initialized\n"); 75 return -ENODEV; 76 } 77 78 running = start; 79 80 return 0; 81} 82 83int pcap_clear(void) 84{ 85 if (!initialized) { 86 printf("error: pcap was not initialized\n"); 87 return -ENODEV; 88 } 89 90 pos = sizeof(file_header); 91 incoming_count = 0; 92 outgoing_count = 0; 93 buffer_full = false; 94 95 printf("pcap capture cleared\n"); 96 return 0; 97} 98 99int pcap_post(const void *packet, size_t len, bool outgoing) 100{ 101 struct pcap_packet_header header; 102 u64 cur_time = timer_get_us(); 103 104 if (!initialized || !running || !buf) 105 return -ENODEV; 106 107 if (buffer_full) 108 return -ENOMEM; 109 110 if ((pos + len + sizeof(header)) >= max_size) { 111 buffer_full = true; 112 printf("\n!!! Buffer is full, consider increasing buffer size !!!\n"); 113 return -ENOMEM; 114 } 115 116 header.ts_sec = cur_time / 1000000; 117 header.ts_usec = cur_time % 1000000; 118 header.incl_len = len; 119 header.orig_len = len; 120 121 memcpy(buf + pos, &header, sizeof(header)); 122 pos += sizeof(header); 123 memcpy(buf + pos, packet, len); 124 pos += len; 125 126 if (outgoing) 127 outgoing_count++; 128 else 129 incoming_count++; 130 131 env_set_hex("pcapsize", pos); 132 133 return 0; 134} 135 136int pcap_print_status(void) 137{ 138 if (!initialized) { 139 printf("pcap was not initialized\n"); 140 return -ENODEV; 141 } 142 printf("PCAP status:\n"); 143 printf("\tInitialized addr: 0x%lx\tmax length: %u\n", 144 (unsigned long)buf, max_size); 145 printf("\tStatus: %s.\t file size: %u\n", running ? "Active" : "Idle", 146 pos); 147 printf("\tIncoming packets: %lu Outgoing packets: %lu\n", 148 incoming_count, outgoing_count); 149 150 return 0; 151} 152 153bool pcap_active(void) 154{ 155 return running; 156} 157