+/*
+ * Generate an error message based on a format, arguments, and an
+ * rte_errno, with a message for the rte_errno after the formatted output.
+ */
+static void dpdk_fmt_errmsg_for_rte_errno(char *errbuf, size_t errbuflen,
+ int errnum, const char *fmt, ...)
+{
+ va_list ap;
+ size_t msglen;
+ char *p;
+ size_t errbuflen_remaining;
+
+ va_start(ap, fmt);
+ pcap_vsnprintf(errbuf, errbuflen, fmt, ap);
+ va_end(ap);
+ msglen = strlen(errbuf);
+
+ /*
+ * Do we have enough space to append ": "?
+ * Including the terminating '\0', that's 3 bytes.
+ */
+ if (msglen + 3 > errbuflen) {
+ /* No - just give them what we've produced. */
+ return;
+ }
+ p = errbuf + msglen;
+ errbuflen_remaining = errbuflen - msglen;
+ *p++ = ':';
+ *p++ = ' ';
+ *p = '\0';
+ msglen += 2;
+ errbuflen_remaining -= 2;
+
+ /*
+ * Now append the string for the error code.
+ * rte_strerror() is thread-safe, at least as of dpdk 18.11,
+ * unlike strerror() - it uses strerror_r() rather than strerror()
+ * for UN*X errno values, and prints to what I assume is a per-thread
+ * buffer (based on the "PER_LCORE" in "RTE_DEFINE_PER_LCORE" used
+ * to declare the buffers statically) for DPDK errors.
+ */
+ pcap_snprintf(p, errbuflen_remaining, "%s", rte_strerror(errnum));
+}
+