[tcpdump-workers] [RFC PATCH] Add new `pcap_set_buffer_size1` API.
From: Mario Rugiero The current `pcap_set_buffer_size` sets a limit of 2GiB buffer size. This changeset implements a backwards compatible mechanism to set bigger buffers. A new `pcap_set_buffer_size1` call is created, taking a `size_t` instead of an `int`, allowing for buffers as big as the platform allows. The `buffer_size` field of `struct pcap_opt` was promoted to `size_t`. Due to some contexts requiring smaller maximum buffers, a new field named `max_buffer_size` of type `size_t` was added to the same structure to account for that. This field is initialized by default to `INT_MAX` to preserve the behaviour of the older API. Then, each driver is expected, but not mandated, to fix it to a more appropriate value for the platform. In this RFC, Linux and DPDK are used as examples. diff --git a/pcap-dpdk.c b/pcap-dpdk.c index 6c2f21fc..81df91e3 100644 --- a/pcap-dpdk.c +++ b/pcap-dpdk.c @@ -962,10 +962,12 @@ pcap_t * pcap_dpdk_create(const char *device, char *ebuf, int *is_ours) p = pcap_create_common(ebuf, sizeof(struct pcap_dpdk)); if (p == NULL) return NULL; p->activate_op = pcap_dpdk_activate; + p->opt.max_buffer_size = SIZE_MAX; + return p; } int pcap_dpdk_findalldevs(pcap_if_list_t *devlistp, char *ebuf) { diff --git a/pcap-int.h b/pcap-int.h index b614efbe..64604bc4 100644 --- a/pcap-int.h +++ b/pcap-int.h @@ -110,11 +110,12 @@ extern "C" { ((c) >= 'a' && (c) <= 'f')) struct pcap_opt { char*device; int timeout;/* timeout for buffering */ - u_int buffer_size; + size_t max_buffer_size;/* platform's max buffer size - backends *should* override it */ + size_t buffer_size; int promisc; int rfmon; /* monitor mode */ int immediate; /* immediate mode - deliver packets as soon as they arrive */ int nonblock; /* non-blocking mode - don't wait for packets to be delivered, return "no packets available" */ int tstamp_type; diff --git a/pcap.c b/pcap.c index ebb992bf..a9e8bbeb 100644 --- a/pcap.c +++ b/pcap.c @@ -2352,10 +2352,11 @@ pcap_create_common(char *ebuf, size_t size) initialize_ops(p); /* put in some defaults*/ p->snapshot = 0;/* max packet size unspecified */ p->opt.timeout = 0; /* no timeout specified */ + p->opt.max_buffer_size = INT_MAX; /* default to old API's max for compatibility */ p->opt.buffer_size = 0; /* use the platform's default */ p->opt.promisc = 0; p->opt.rfmon = 0; p->opt.immediate = 0; p->opt.tstamp_type = -1;/* default to not setting time stamp type */ @@ -2492,10 +2493,21 @@ pcap_set_buffer_size(pcap_t *p, int buffer_size) } p->opt.buffer_size = buffer_size; return (0); } +int +pcap_set_buffer_size1(pcap_t *p, size_t buffer_size) +{ + if (pcap_check_activated(p)) + return (PCAP_ERROR_ACTIVATED); + if (buffer_size > p->opt.max_buffer_size) + return (PCAP_ERROR_BUFFER_TOO_BIG); + p->opt.buffer_size = buffer_size; + return (0); +} + int pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision) { int i; diff --git a/pcap/pcap.h b/pcap/pcap.h index 21ea980a..f78ad351 100644 --- a/pcap/pcap.h +++ b/pcap/pcap.h @@ -303,10 +303,11 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, #define PCAP_ERROR_PERM_DENIED -8 /* no permission to open the device */ #define PCAP_ERROR_IFACE_NOT_UP-9 /* interface isn't up */ #define PCAP_ERROR_CANTSET_TSTAMP_TYPE -10 /* this device doesn't support setting the time stamp type */ #define PCAP_ERROR_PROMISC_PERM_DENIED -11 /* you don't have permission to capture in promiscuous mode */ #define PCAP_ERROR_TSTAMP_PRECISION_NOTSUP -12 /* the requested time stamp precision is not supported */ +#define PCAP_ERROR_BUFFER_TOO_BIG -13 /* passed an invalid argument */ /* * Warning codes for the pcap API. * These will all be positive and non-zero, so they won't look like * errors. @@ -338,10 +339,11 @@ PCAP_API int pcap_can_set_rfmon(pcap_t *); PCAP_API int pcap_set_rfmon(pcap_t *, int); PCAP_API int pcap_set_timeout(pcap_t *, int); PCAP_API int pcap_set_tstamp_type(pcap_t *, int); PCAP_API int pcap_set_immediate_mode(pcap_t *, int); PCAP_API int pcap_set_buffer_size(pcap_t *, int); +PCAP_API int pcap_set_buffer_size1(pcap_t *, size_t); PCAP_API int pcap_set_tstamp_precision(pcap_t *, int); PCAP_API int pcap_get_tstamp_precision(pcap_t *); PCAP_API int pcap_activate(pcap_t *); PCAP_API int pcap_list_tstamp_types(pcap_t *, int **); -- 2.20.1 ___ tcpdump-workers mailing list tcpdump-workers@lists.tcpdump.org https://lists.sandelman.ca/mailman/listinfo/tcpdump-workers
[tcpdump-workers] [RFC PATCH v2] Add new `pcap_set_buffer_size1` API.
From: Mario Rugiero The current `pcap_set_buffer_size` sets a limit of 2GiB buffer size. This changeset implements a backwards compatible mechanism to set bigger buffers. A new `pcap_set_buffer_size_ex` call is created, taking a `size_t` instead of an `int`, allowing for buffers as big as the platform allows. The `buffer_size` field of `struct pcap_opt` was promoted to `size_t`. Due to some contexts requiring smaller maximum buffers, a new field named `max_buffer_size` of type `size_t` was added to the same structure to account for that, as well as an analogous `min_buffer_size`. This field is initialized by default to `INT_MAX` to preserve the behaviour of the older API. Then, each driver is expected, but not mandated, to fix them to more suitable values for the platform. In this RFC, Linux and DPDK are used as examples. --- pcap-dpdk.c | 2 ++ pcap-int.h | 4 +++- pcap-linux.c | 1 + pcap.c | 15 +++ pcap/pcap.h | 5 + 5 files changed, 26 insertions(+), 1 deletion(-) diff --git a/pcap-dpdk.c b/pcap-dpdk.c index 6c2f21fc..81df91e3 100644 --- a/pcap-dpdk.c +++ b/pcap-dpdk.c @@ -964,6 +964,8 @@ pcap_t * pcap_dpdk_create(const char *device, char *ebuf, int *is_ours) if (p == NULL) return NULL; p->activate_op = pcap_dpdk_activate; + p->opt.max_buffer_size = SIZE_MAX; + return p; } diff --git a/pcap-int.h b/pcap-int.h index b614efbe..5faa1efb 100644 --- a/pcap-int.h +++ b/pcap-int.h @@ -112,7 +112,9 @@ extern "C" { struct pcap_opt { char*device; int timeout;/* timeout for buffering */ - u_int buffer_size; + size_t min_buffer_size;/* platform's min buffer size - backends *should* override it */ + size_t max_buffer_size;/* platform's max buffer size - backends *should* override it */ + size_t buffer_size; int promisc; int rfmon; /* monitor mode */ int immediate; /* immediate mode - deliver packets as soon as they arrive */ diff --git a/pcap-linux.c b/pcap-linux.c index 31c1a6a0..3b558237 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -517,6 +517,7 @@ pcap_create_interface(const char *device, char *ebuf) handle->activate_op = pcap_activate_linux; handle->can_set_rfmon_op = pcap_can_set_rfmon_linux; + handle->opt.max_buffer_size = SIZE_MAX; #if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP) /* diff --git a/pcap.c b/pcap.c index ebb992bf..f25fe4a9 100644 --- a/pcap.c +++ b/pcap.c @@ -2354,6 +2354,8 @@ pcap_create_common(char *ebuf, size_t size) /* put in some defaults*/ p->snapshot = 0;/* max packet size unspecified */ p->opt.timeout = 0; /* no timeout specified */ + p->opt.min_buffer_size = 0; + p->opt.max_buffer_size = INT_MAX; /* default to old API's max for compatibility */ p->opt.buffer_size = 0; /* use the platform's default */ p->opt.promisc = 0; p->opt.rfmon = 0; @@ -2494,6 +2496,19 @@ pcap_set_buffer_size(pcap_t *p, int buffer_size) return (0); } +int +pcap_set_buffer_size_ex(pcap_t *p, size_t buffer_size) +{ + if (pcap_check_activated(p)) + return (PCAP_ERROR_ACTIVATED); + if (buffer_size > p->opt.max_buffer_size) + return (PCAP_ERROR_BUFFER_TOO_BIG); + if (buffer_size < p->opt.min_buffer_size) + return (PCAP_ERROR_BUFFER_TOO_SMALL); + p->opt.buffer_size = buffer_size; + return (0); +} + int pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision) { diff --git a/pcap/pcap.h b/pcap/pcap.h index 21ea980a..303d58f2 100644 --- a/pcap/pcap.h +++ b/pcap/pcap.h @@ -305,6 +305,8 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, #define PCAP_ERROR_CANTSET_TSTAMP_TYPE -10 /* this device doesn't support setting the time stamp type */ #define PCAP_ERROR_PROMISC_PERM_DENIED -11 /* you don't have permission to capture in promiscuous mode */ #define PCAP_ERROR_TSTAMP_PRECISION_NOTSUP -12 /* the requested time stamp precision is not supported */ +#define PCAP_ERROR_BUFFER_TOO_SMALL -13 /* attempted to set a buffer below the minimum size */ +#define PCAP_ERROR_BUFFER_TOO_BIG -14 /* attempted to set a buffer below the maximum size */ /* * Warning codes for the pcap API. @@ -340,6 +342,9 @@ PCAP_API intpcap_set_timeout(pcap_t *, int); PCAP_API int pcap_set_tstamp_type(pcap_t *, int); PCAP_API int pcap_set_immediate_mode(pcap_t *, int); PCAP_API int pcap_set_buffer_size(pcap_t *, int); +PCAP_API int pcap_set_buffer_size_ex(pcap_t *, size_t); +PCAP_API size_tpcap_get_min_buffer_size(pcap_t *); +PCAP_API size_tpcap_get_max_buffer_size(pcap_t *); PCAP_API int pcap_set_tstamp_precision(pcap_t *, int); PCAP_API int pcap_get_tstamp_precision(pcap_t *); PCAP_API int pcap_activate(pcap_t *); -- 2.20.1