12 #include <netinet/in.h>
14 #include <sys/socket.h>
15 #include <sys/types.h>
24 * Private data for capturing on SNF devices.
27 snf_handle_t snf_handle; /* opaque device handle */
28 snf_ring_t snf_ring; /* opaque device ring handle */
34 snf_set_datalink(pcap_t *p, int dlt)
41 snf_pcap_stats(pcap_t *p, struct pcap_stat *ps)
43 struct snf_ring_stats stats;
46 if ((rc = snf_ring_getstats(ps->snf_ring, &stats))) {
47 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_get_stats: %s",
51 ps->ps_recv = stats.ring_pkt_recv + stats.ring_pkt_overflow;
52 ps->ps_drop = stats.ring_pkt_overflow;
53 ps->ps_ifdrop = stats.nic_pkt_overflow + stats.nic_pkt_bad;
58 snf_platform_cleanup(pcap_t *p)
66 snf_ring_close(ps->snf_ring);
67 snf_close(ps->snf_handle);
68 pcap_cleanup_live_common(p);
72 snf_getnonblock(pcap_t *p, char *errbuf)
74 struct pcap_snf *ps = p->priv;
76 return (ps->snf_timeout == 0);
80 snf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
82 struct pcap_snf *ps = p->priv;
87 if (p->opt.timeout <= 0)
88 ps->snf_timeout = -1; /* forever */
90 ps->snf_timeout = p->opt.timeout;
95 #define _NSEC_PER_SEC 1000000000
99 snf_timestamp_to_timeval(const int64_t ts_nanosec)
104 return (struct timeval) { 0, 0 };
105 tv.tv_sec = ts_nanosec / _NSEC_PER_SEC;
106 tv.tv_usec = (ts_nanosec % _NSEC_PER_SEC) / 1000;
111 snf_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
113 struct pcap_snf *ps = p->priv;
114 struct pcap_pkthdr hdr;
115 int i, flags, err, caplen, n;
116 struct snf_recv_req req;
122 while (n < cnt || PACKET_COUNT_IS_UNLIMITED(cnt)) {
124 * Has "pcap_breakloop()" been called?
135 err = snf_ring_recv(ps->snf_ring, ps->snf_timeout, &req);
138 if (err == EBUSY || err == EAGAIN)
143 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_read: %s",
150 if (caplen > p->snapshot)
151 caplen = p->snapshot;
153 if ((p->fcode.bf_insns == NULL) ||
154 bpf_filter(p->fcode.bf_insns, req.pkt_addr, req.length, caplen)) {
155 hdr.ts = snf_timestamp_to_timeval(req.timestamp);
157 hdr.len = req.length;
158 callback(user, &hdr, req.pkt_addr);
166 snf_setfilter(pcap_t *p, struct bpf_program *fp)
171 strncpy(p->errbuf, "setfilter: No filter specified",
176 /* Make our private copy of the filter */
178 if (install_bpf_program(p, fp) < 0)
185 snf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
187 strlcpy(p->errbuf, "Sending packets isn't supported with snf",
193 snf_activate(pcap_t* p)
195 struct pcap_snf *ps = p->priv;
196 char *device = p->opt.source;
197 const char *nr = NULL;
201 if (device == NULL) {
202 snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
203 "device is NULL: %s", pcap_strerror(errno));
207 /* In Libpcap, we set pshared by default if NUM_RINGS is set to > 1.
208 * Since libpcap isn't thread-safe */
209 if ((nr = getenv("SNF_NUM_RINGS")) && *nr && atoi(nr) > 1)
210 flags |= SNF_F_PSHARED;
214 err = snf_open(ps->snf_boardnum,
215 0, /* let SNF API parse SNF_NUM_RINGS, if set */
216 NULL, /* default RSS, or use SNF_RSS_FLAGS env */
217 0, /* default to SNF_DATARING_SIZE from env */
218 flags, /* may want pshared */
221 snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
222 "snf_open failed: %s", pcap_strerror(err));
226 err = snf_ring_open(ps->snf_handle, &ps->snf_ring);
228 snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
229 "snf_ring_open failed: %s", pcap_strerror(err));
233 if (p->opt.timeout <= 0)
234 ps->snf_timeout = -1;
236 ps->snf_timeout = p->opt.timeout;
238 err = snf_start(ps->snf_handle);
240 snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
241 "snf_start failed: %s", pcap_strerror(err));
246 * "select()" and "poll()" don't work on snf descriptors.
248 p->selectable_fd = -1;
249 p->linktype = DLT_EN10MB;
250 p->read_op = snf_read;
251 p->inject_op = snf_inject;
252 p->setfilter_op = snf_setfilter;
253 p->setdirection_op = NULL; /* Not implemented.*/
254 p->set_datalink_op = snf_set_datalink;
255 p->getnonblock_op = snf_getnonblock;
256 p->setnonblock_op = snf_setnonblock;
257 p->stats_op = snf_pcap_stats;
258 p->cleanup_op = snf_platform_cleanup;
263 snf_findalldevs(pcap_if_t **devlistp, char *errbuf)
266 * There are no platform-specific devices since each device
267 * exists as a regular Ethernet device.
273 snf_create(const char *device, char *ebuf, int *is_ours)
277 struct snf_ifaddrs *ifaddrs, *ifa;
281 if (snf_init(SNF_VERSION_API)) {
282 /* Can't initialize the API, so no SNF devices */
288 * Match a given interface name to our list of interface names, from
289 * which we can obtain the intended board number
291 if (snf_getifaddrs(&ifaddrs) || ifaddrs == NULL) {
292 /* Can't get SNF addresses */
296 devlen = strlen(device) + 1;
299 if (!strncmp(device, ifa->snf_ifa_name, devlen)) {
300 boardnum = ifa->snf_ifa_boardnum;
303 ifa = ifa->snf_ifa_next;
305 snf_freeifaddrs(ifaddrs);
309 * If we can't find the device by name, support the name "snfX"
310 * and "snf10gX" where X is the board number.
312 if (sscanf(device, "snf10g%d", &boardnum) != 1 &&
313 sscanf(device, "snf%d", &boardnum) != 1) {
314 /* Nope, not a supported name */
320 /* OK, it's probably ours. */
323 p = pcap_create_common(device, ebuf, sizeof (struct pcap_snf));
328 p->activate_op = snf_activate;
329 ps->snf_boardnum = boardnum;