SYSCTL_NODE(_net_link, OID_AUTO, loopback, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
"loopback interface");
-#define LO_BW_SLEEP 10
-static u_int32_t lo_bw_sleep_usec = LO_BW_SLEEP;
-SYSCTL_UINT(_net_link_loopback, OID_AUTO, bw_sleep_usec,
- CTLFLAG_RW | CTLFLAG_LOCKED, &lo_bw_sleep_usec, LO_BW_SLEEP, "");
-
-static u_int32_t lo_bw_measure = 0;
-SYSCTL_UINT(_net_link_loopback, OID_AUTO, bw_measure,
- CTLFLAG_RW | CTLFLAG_LOCKED, &lo_bw_measure, 0, "");
-
static u_int32_t lo_dequeue_max = LOSNDQ_MAXLEN;
SYSCTL_PROC(_net_link_loopback, OID_AUTO, max_dequeue,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, &lo_dequeue_max, LOSNDQ_MAXLEN,
#pragma unused(ifp, dest, dest_linkaddr)
struct loopback_header *header;
- M_PREPEND(*m, sizeof (struct loopback_header), M_WAITOK);
+ M_PREPEND(*m, sizeof (struct loopback_header), M_WAITOK, 1);
if (*m == NULL) {
/* Tell caller not to try to free passed-in mbuf */
return (EJUSTRETURN);
return (0);
}
+static void
+lo_tx_compl(struct ifnet *ifp, struct mbuf *m)
+{
+ errno_t error;
+
+ if ((ifp->if_xflags & IFXF_TIMESTAMP_ENABLED) != 0) {
+ boolean_t requested;
+
+ error = mbuf_get_timestamp_requested(m, &requested);
+ if (requested) {
+ struct timespec now;
+ u_int64_t ts;
+
+ nanouptime(&now);
+ net_timernsec(&now, &ts);
+
+ error = mbuf_set_timestamp(m, ts, TRUE);
+ if (error != 0)
+ printf("%s: mbuf_set_timestamp() failed %d\n",
+ __func__, error);
+ }
+ }
+ error = mbuf_set_status(m, KERN_SUCCESS);
+ if (error != 0)
+ printf("%s: mbuf_set_status() failed %d\n",
+ __func__, error);
+
+ ifnet_tx_compl(ifp, m);
+}
+
/*
* Output callback.
*
if (m->m_nextpkt == NULL) {
m_tail = m;
}
+ lo_tx_compl(ifp, m);
}
s.packets_in = cnt;
for (;;) {
struct mbuf *m = NULL, *m_tail = NULL;
u_int32_t cnt, len = 0;
- int sleep_chan = 0;
- struct timespec ts;
if (lo_sched_model == IFNET_SCHED_MODEL_NORMAL) {
if (ifnet_dequeue_multi(ifp, lo_dequeue_max, &m,
}
LO_BPF_TAP_OUT_MULTI(m);
-
- if (lo_bw_measure) {
- if (cnt >= if_bw_measure_size)
- ifnet_transmit_burst_start(ifp, m);
- if (lo_bw_sleep_usec > 0) {
- bzero(&ts, sizeof(ts));
- ts.tv_nsec = (lo_bw_sleep_usec << 10) * cnt;
-
- /* Add msleep with timeout */
- (void) msleep(&sleep_chan, NULL,
- PSOCK, "lo_start", &ts);
- }
- if (cnt >= if_bw_measure_size)
- ifnet_transmit_burst_end(ifp, m_tail);
- }
+ lo_tx_compl(ifp, m);
/* stats are required for extended variant */
s.packets_in = cnt;
lo_input(struct ifnet *ifp, protocol_family_t protocol_family, struct mbuf *m)
{
#pragma unused(ifp, protocol_family)
+
+ if ((ifp->if_xflags & IFXF_TIMESTAMP_ENABLED) != 0) {
+ errno_t error;
+ struct timespec now;
+ u_int64_t ts;
+
+ nanouptime(&now);
+ net_timernsec(&now, &ts);
+
+ error = mbuf_set_timestamp(m, ts, TRUE);
+ if (error != 0)
+ printf("%s: mbuf_set_timestamp() failed %d\n",
+ __func__, error);
+ }
+
if (proto_input(protocol_family, m) != 0)
m_freem(m);
return (0);
}
case SIOCSIFFLAGS: /* struct ifreq */
+ case SIOCSIFTIMESTAMPENABLE:
+ case SIOCSIFTIMESTAMPDISABLE:
break;
default:
lo_init.flags = IFNET_INIT_LEGACY;
lo_init.output = lo_output;
}
+ lo_init.flags |= IFNET_INIT_NX_NOAUTO;
lo_init.name = "lo";
lo_init.unit = 0;
lo_init.family = IFNET_FAMILY_LOOPBACK;
ifnet_set_offload(lo_ifp,
IFNET_CSUM_IP | IFNET_CSUM_TCP | IFNET_CSUM_UDP |
IFNET_CSUM_TCPIPV6 | IFNET_CSUM_UDPIPV6 | IFNET_IPV6_FRAGMENT |
- IFNET_CSUM_FRAGMENT | IFNET_IP_FRAGMENT | IFNET_MULTIPAGES);
+ IFNET_CSUM_FRAGMENT | IFNET_IP_FRAGMENT | IFNET_MULTIPAGES |
+ IFNET_TX_STATUS | IFNET_SW_TIMESTAMP);
ifnet_set_hdrlen(lo_ifp, sizeof (struct loopback_header));
ifnet_set_eflags(lo_ifp, IFEF_SENDLIST, IFEF_SENDLIST);
switch (i) {
case IFNET_SCHED_MODEL_NORMAL:
case IFNET_SCHED_MODEL_DRIVER_MANAGED:
+ case IFNET_SCHED_MODEL_FQ_CODEL:
break;
default: