10 #include <limits.h> /* for INT_MAX */
13 #include <netinet/in.h>
15 #include <sys/socket.h>
16 #include <sys/types.h>
26 * Private data for capturing on SNF devices.
29 snf_handle_t snf_handle
; /* opaque device handle */
30 snf_ring_t snf_ring
; /* opaque device ring handle */
31 snf_inject_t snf_inj
; /* inject handle, if inject is used */
37 snf_set_datalink(pcap_t
*p
, int dlt
)
44 snf_pcap_stats(pcap_t
*p
, struct pcap_stat
*ps
)
46 struct snf_ring_stats stats
;
47 struct pcap_snf
*snfps
= p
->priv
;
50 if ((rc
= snf_ring_getstats(snfps
->snf_ring
, &stats
))) {
51 pcapint_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
55 ps
->ps_recv
= stats
.ring_pkt_recv
+ stats
.ring_pkt_overflow
;
56 ps
->ps_drop
= stats
.ring_pkt_overflow
;
57 ps
->ps_ifdrop
= stats
.nic_pkt_overflow
+ stats
.nic_pkt_bad
;
62 snf_platform_cleanup(pcap_t
*p
)
64 struct pcap_snf
*ps
= p
->priv
;
67 snf_inject_close(ps
->snf_inj
);
68 snf_ring_close(ps
->snf_ring
);
69 snf_close(ps
->snf_handle
);
70 pcapint_cleanup_live_common(p
);
74 snf_getnonblock(pcap_t
*p
)
76 struct pcap_snf
*ps
= p
->priv
;
78 return (ps
->snf_timeout
== 0);
82 snf_setnonblock(pcap_t
*p
, int nonblock
)
84 struct pcap_snf
*ps
= p
->priv
;
89 if (p
->opt
.timeout
<= 0)
90 ps
->snf_timeout
= -1; /* forever */
92 ps
->snf_timeout
= p
->opt
.timeout
;
97 #define _NSEC_PER_SEC 1000000000
101 snf_timestamp_to_timeval(const int64_t ts_nanosec
, const int tstamp_precision
)
105 static const struct timeval zero_timeval
;
110 tv
.tv_sec
= ts_nanosec
/ _NSEC_PER_SEC
;
111 tv_nsec
= (ts_nanosec
% _NSEC_PER_SEC
);
113 /* libpcap expects tv_usec to be nanos if using nanosecond precision. */
114 if (tstamp_precision
== PCAP_TSTAMP_PRECISION_NANO
)
115 tv
.tv_usec
= tv_nsec
;
117 tv
.tv_usec
= tv_nsec
/ 1000;
123 snf_read(pcap_t
*p
, int cnt
, pcap_handler callback
, u_char
*user
)
125 struct pcap_snf
*ps
= p
->priv
;
126 struct pcap_pkthdr hdr
;
128 struct snf_recv_req req
;
132 * This can conceivably process more than INT_MAX packets,
133 * which would overflow the packet count, causing it either
134 * to look like a negative number, and thus cause us to
135 * return a value that looks like an error, or overflow
136 * back into positive territory, and thus cause us to
137 * return a too-low count.
139 * Therefore, if the packet count is unlimited, we clip
140 * it at INT_MAX; this routine is not expected to
141 * process packets indefinitely, so that's not an issue.
143 if (PACKET_COUNT_IS_UNLIMITED(cnt
))
147 timeout
= ps
->snf_timeout
;
150 * Has "pcap_breakloop()" been called?
155 return PCAP_ERROR_BREAK
;
161 err
= snf_ring_recv(ps
->snf_ring
, timeout
, &req
);
164 if (err
== EBUSY
|| err
== EAGAIN
) {
167 else if (err
== EINTR
) {
172 pcapint_fmt_errmsg_for_errno(p
->errbuf
,
173 PCAP_ERRBUF_SIZE
, err
, "%s", __func__
);
179 * In this libpcap module the two length arguments of
180 * pcapint_filter() (the wire length and the captured length)
181 * are always equal because SNF captures full packets.
183 * The wire and the capture length of this packet is
184 * req.length, the snapshot length configured for this pcap
185 * handle is p->snapshot.
188 if (caplen
> p
->snapshot
)
189 caplen
= p
->snapshot
;
191 if ((p
->fcode
.bf_insns
== NULL
) ||
192 pcapint_filter(p
->fcode
.bf_insns
, req
.pkt_addr
, req
.length
, req
.length
)) {
193 hdr
.ts
= snf_timestamp_to_timeval(req
.timestamp
, p
->opt
.tstamp_precision
);
195 hdr
.len
= req
.length
;
196 callback(user
, &hdr
, req
.pkt_addr
);
200 /* After one successful packet is received, we won't block
201 * again for that timeout. */
209 snf_inject(pcap_t
*p
, const void *buf
, int size
)
211 struct pcap_snf
*ps
= p
->priv
;
213 if (ps
->snf_inj
== NULL
) {
214 rc
= snf_inject_open(ps
->snf_boardnum
, 0, &ps
->snf_inj
);
216 pcapint_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
217 rc
, "snf_inject_open");
222 rc
= snf_inject_send(ps
->snf_inj
, -1, 0, buf
, size
);
227 pcapint_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
228 rc
, "snf_inject_send");
234 snf_activate(pcap_t
* p
)
236 struct pcap_snf
*ps
= p
->priv
;
237 const char *nr
= NULL
;
239 int flags
= -1, ring_id
= -1;
241 /* In Libpcap, we set pshared by default if NUM_RINGS is set to > 1.
242 * Since libpcap isn't thread-safe */
243 if ((nr
= getenv("SNF_FLAGS")) && *nr
)
244 flags
= strtol(nr
, NULL
, 0);
245 else if ((nr
= getenv("SNF_NUM_RINGS")) && *nr
&& atoi(nr
) > 1)
246 flags
= SNF_F_PSHARED
;
251 /* Allow pcap_set_buffer_size() to set dataring_size.
252 * Default is zero which allows setting from env SNF_DATARING_SIZE.
253 * pcap_set_buffer_size() is in bytes while snf_open() accepts values
254 * between 0 and 1048576 in Megabytes. Values in this range are
257 err
= snf_open(ps
->snf_boardnum
,
258 0, /* let SNF API parse SNF_NUM_RINGS, if set */
259 NULL
, /* default RSS, or use SNF_RSS_FLAGS env */
260 (p
->opt
.buffer_size
> 0 && p
->opt
.buffer_size
< 1048576) ? 1048576 : p
->opt
.buffer_size
, /* default to SNF_DATARING_SIZE from env */
261 flags
, /* may want pshared */
264 pcapint_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
265 err
, "snf_open failed");
269 if ((nr
= getenv("SNF_PCAP_RING_ID")) && *nr
) {
270 ring_id
= (int) strtol(nr
, NULL
, 0);
272 err
= snf_ring_open_id(ps
->snf_handle
, ring_id
, &ps
->snf_ring
);
274 pcapint_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
275 err
, "snf_ring_open_id(ring=%d) failed", ring_id
);
280 * Turn a negative snapshot value (invalid), a snapshot value of
281 * 0 (unspecified), or a value bigger than the normal maximum
282 * value, into the maximum allowed value.
284 * If some application really *needs* a bigger snapshot
285 * length, we should just increase MAXIMUM_SNAPLEN.
287 if (p
->snapshot
<= 0 || p
->snapshot
> MAXIMUM_SNAPLEN
)
288 p
->snapshot
= MAXIMUM_SNAPLEN
;
290 if (p
->opt
.timeout
<= 0)
291 ps
->snf_timeout
= -1;
293 ps
->snf_timeout
= p
->opt
.timeout
;
295 err
= snf_start(ps
->snf_handle
);
297 pcapint_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
298 err
, "snf_start failed");
303 * "select()" and "poll()" don't work on snf descriptors.
306 p
->selectable_fd
= -1;
308 p
->linktype
= DLT_EN10MB
;
309 p
->read_op
= snf_read
;
310 p
->inject_op
= snf_inject
;
311 p
->setfilter_op
= pcapint_install_bpf_program
;
312 p
->setdirection_op
= NULL
; /* Not implemented.*/
313 p
->set_datalink_op
= snf_set_datalink
;
314 p
->getnonblock_op
= snf_getnonblock
;
315 p
->setnonblock_op
= snf_setnonblock
;
316 p
->stats_op
= snf_pcap_stats
;
317 p
->cleanup_op
= snf_platform_cleanup
;
322 #define MAX_DESC_LENGTH 128
324 snf_findalldevs(pcap_if_list_t
*devlistp
, char *errbuf
)
328 struct sockaddr_in addr
;
330 struct snf_ifaddrs
*ifaddrs
, *ifa
;
331 char name
[MAX_DESC_LENGTH
];
332 char desc
[MAX_DESC_LENGTH
];
333 int allports
= 0, merge
= 0;
334 const char *nr
= NULL
;
336 if (snf_init(SNF_VERSION_API
)) {
337 pcapint_fmt_errmsg_for_errno(errbuf
, PCAP_ERRBUF_SIZE
,
342 if (snf_getifaddrs(&ifaddrs
) || ifaddrs
== NULL
)
344 pcapint_fmt_errmsg_for_errno(errbuf
, PCAP_ERRBUF_SIZE
,
345 errno
, "snf_getifaddrs");
348 if ((nr
= getenv("SNF_FLAGS")) && *nr
) {
350 merge
= strtol(nr
, NULL
, 0);
352 (void)snprintf(errbuf
, PCAP_ERRBUF_SIZE
,
353 "%s: SNF_FLAGS is not a valid number", __func__
);
356 merge
= merge
& SNF_F_AGGREGATE_PORTMASK
;
359 for (ifa
= ifaddrs
; ifa
!= NULL
; ifa
= ifa
->snf_ifa_next
) {
361 * Myricom SNF adapter ports may appear as regular
362 * network interfaces, which would already have been
363 * added to the list of adapters by pcapint_platform_finddevs()
364 * regardless of whether this build is SNF-only or not.
366 * Our create routine intercepts pcap_create() calls for
367 * those interfaces and arranges that they will be
368 * opened using the SNF API instead.
370 * So if we already have an entry for the device, we
371 * don't add an additional entry for it, we just
372 * update the description for it, if any, to indicate
373 * which snfN device it is. Otherwise, we add an entry
376 * In either case, if SNF_F_AGGREGATE_PORTMASK is set
377 * in SNF_FLAGS, we add this port to the bitmask
378 * of ports, which we use to generate a device
379 * we can use to capture on all ports.
381 * Generate the description string. If port aggregation
382 * is set, use 2^{port number} as the unit number,
383 * rather than {port number}.
385 (void)snprintf(desc
, MAX_DESC_LENGTH
,
386 "Myricom %ssnf%u, Rx rings: %u, Tx handles: %u",
387 merge
? "Merge Bitmask Port " : "",
388 merge
? 1U << ifa
->snf_ifa_portnum
: ifa
->snf_ifa_portnum
,
389 ifa
->snf_ifa_maxrings
,
390 ifa
->snf_ifa_maxinject
);
392 * Add the port to the bitmask.
395 allports
|= 1 << ifa
->snf_ifa_portnum
;
397 * See if there's already an entry for the device
398 * with the name ifa->snf_ifa_name.
400 dev
= pcapint_find_dev(devlistp
, ifa
->snf_ifa_name
);
403 * Yes. Update its description.
405 * This is the expected and the most likely result.
406 * In this case the device's .flags already has the
407 * PCAP_IF_UP and PCAP_IF_RUNNING bits mapped from the
408 * regular network interface flags, as well as the
409 * PCAP_IF_CONNECTION_STATUS bits mapped from the
410 * current struct snf_ifaddrs; .addresses has already
415 desc_str
= strdup(desc
);
416 if (desc_str
== NULL
) {
417 pcapint_fmt_errmsg_for_errno(errbuf
,
418 PCAP_ERRBUF_SIZE
, errno
,
419 "%s strdup", __func__
);
422 free(dev
->description
);
423 dev
->description
= desc_str
;
426 * No. Add an entry for it.
428 * Possibly a race condition. In this case the device
429 * will still work, but will not have addresses, also
430 * snf_ifaddrs includes the operational (i.e. link
431 * detect), but not the administrative state of the
434 const bpf_u_int32 flags
=
435 ifa
->snf_ifa_link_state
== SNF_LINK_UP
?
436 PCAP_IF_CONNECTION_STATUS_CONNECTED
:
437 PCAP_IF_CONNECTION_STATUS_DISCONNECTED
;
438 dev
= pcapint_add_dev(devlistp
, ifa
->snf_ifa_name
, flags
, desc
,
444 * On Windows, fill in IP# from device name
446 int ret
= inet_pton(AF_INET
, dev
->name
, &addr
.sin_addr
);
449 * Successful conversion of device name
452 addr
.sin_family
= AF_INET
;
453 if (pcapint_add_addr_to_dev(dev
, &addr
, sizeof(addr
),
454 NULL
, 0, NULL
, 0, NULL
, 0, errbuf
) == -1)
456 } else if (ret
== -1) {
460 pcapint_fmt_errmsg_for_errno(errbuf
,
461 PCAP_ERRBUF_SIZE
, errno
,
462 "%s inet_pton", __func__
);
468 snf_freeifaddrs(ifaddrs
);
470 * Create a snfX entry if port aggregation is enabled
474 * Add a new entry with all ports bitmask
476 (void)snprintf(name
,MAX_DESC_LENGTH
,"snf%d",allports
);
477 (void)snprintf(desc
,MAX_DESC_LENGTH
,"Myricom Merge Bitmask All Ports snf%d",
480 * XXX - is there any notion of "up" and "running" that
481 * would apply to this device, given that it handles
484 * Presumably, there's no notion of "connected" vs.
485 * "disconnected", as "is this plugged into a network?"
486 * would be a per-port property.
488 if (pcapint_add_dev(devlistp
, name
,
489 PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE
, desc
,
493 * XXX - should we give it a list of addresses with all
494 * the addresses for all the ports?
502 * If an SNF device exists for the given regular network interface name, copy
503 * its struct snf_ifaddrs to the provided pointer if the pointer is not NULL.
506 * 0 if such SNF device does not exist
507 * 1 if such SNF device exists
508 * PCAP_ERROR on an SNF API error
511 snf_device_exists(const char *device
, struct snf_ifaddrs
*out
, char *errbuf
)
513 if (snf_init(SNF_VERSION_API
)) {
514 pcapint_fmt_errmsg_for_errno(errbuf
, PCAP_ERRBUF_SIZE
,
518 struct snf_ifaddrs
*ifaddrs
;
519 if (snf_getifaddrs(&ifaddrs
) || ifaddrs
== NULL
) {
520 pcapint_fmt_errmsg_for_errno(errbuf
, PCAP_ERRBUF_SIZE
,
521 errno
, "snf_getifaddrs");
525 for (struct snf_ifaddrs
*ifa
= ifaddrs
; ifa
; ifa
= ifa
->snf_ifa_next
)
526 if (! strcmp(device
, ifa
->snf_ifa_name
)) {
532 snf_freeifaddrs(ifaddrs
);
537 * If an SNF device exists for the given regular network interface name,
538 * replace the PCAP_IF_CONNECTION_STATUS part of the provided flags with the
539 * link state from the SNF API.
541 * The matter is, for a regular network interface that is administratively
542 * down the operational (link) state appears -- at least on Linux -- down and
543 * an attempt to capture on the interface would fail with ENETDOWN. The SNF
544 * API works differently: regardless of the administrative state it allows to
545 * use an SNF device and reports the same link state as the device's "link up"
549 * 0 if such SNF device does not exist
550 * 1 if such SNF device exists
551 * PCAP_ERROR on an SNF API error
554 snf_get_if_flags(const char *device
, bpf_u_int32
*flags
, char *errbuf
)
556 struct snf_ifaddrs ifa
;
557 int exists
= snf_device_exists(device
, &ifa
, errbuf
);
561 *flags
&= ~PCAP_IF_CONNECTION_STATUS
;
562 switch (ifa
.snf_ifa_link_state
) {
564 *flags
|= PCAP_IF_CONNECTION_STATUS_CONNECTED
;
567 *flags
|= PCAP_IF_CONNECTION_STATUS_DISCONNECTED
;
570 snprintf(errbuf
, PCAP_ERRBUF_SIZE
,
571 "invalid snf_ifa_link_state value %u",
572 ifa
.snf_ifa_link_state
);
579 snf_create(const char *device
, char *ebuf
, int *is_ours
)
583 struct snf_ifaddrs ifa
;
587 * Match a given interface name to our list of interface names, from
588 * which we can obtain the intended board number
590 int exists
= snf_device_exists(device
, &ifa
, ebuf
);
592 /* Can't use the API, so no SNF devices */
599 * If we can't find the device by name, support the name "snfX"
600 * and "snf10gX" where X is the board number.
602 if (sscanf(device
, "snf10g%d", &boardnum
) != 1 &&
603 sscanf(device
, "snf%d", &boardnum
) != 1) {
604 /* Nope, not a supported name */
610 /* OK, it's probably ours. */
613 p
= PCAP_CREATE_COMMON(ebuf
, struct pcap_snf
);
619 * We support microsecond and nanosecond time stamps.
621 p
->tstamp_precision_list
= malloc(2 * sizeof(u_int
));
622 if (p
->tstamp_precision_list
== NULL
) {
623 pcapint_fmt_errmsg_for_errno(ebuf
, PCAP_ERRBUF_SIZE
, errno
,
628 p
->tstamp_precision_list
[0] = PCAP_TSTAMP_PRECISION_MICRO
;
629 p
->tstamp_precision_list
[1] = PCAP_TSTAMP_PRECISION_NANO
;
630 p
->tstamp_precision_count
= 2;
632 p
->activate_op
= snf_activate
;
633 ps
->snf_boardnum
= boardnum
;
639 * This libpcap build supports only SNF cards, not regular network
644 * There are no regular interfaces, just SNF interfaces.
647 can_be_bound(const char *name
)
649 char dummy
[PCAP_ERRBUF_SIZE
];
650 return snf_device_exists(name
, NULL
, dummy
) == 1;
654 * Even though this is an SNF-only build, use the regular "findalldevs" code
655 * for device enumeration, but pick only network interfaces that correspond to
656 * SNF devices. Use SNF-specific interpretation of device flags.
659 pcapint_platform_finddevs(pcap_if_list_t
*devlistp
, char *errbuf
)
661 return pcapint_findalldevs_interfaces(devlistp
, errbuf
, can_be_bound
,
666 * Attempts to open a regular interface fail.
669 pcapint_create_interface(const char *device _U_
, char *errbuf
)
671 snprintf(errbuf
, PCAP_ERRBUF_SIZE
, PCAP_ENODEV_MESSAGE
, "SNF");
676 * Libpcap version string.
679 pcap_lib_version(void)
681 return (PCAP_VERSION_STRING
" (SNF-only)");