]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/net/if_loop.c
xnu-4570.20.62.tar.gz
[apple/xnu.git] / bsd / net / if_loop.c
index f659d3582f95f8d74b3e9e5589179f87270a7e23..00a8345e3a8fe7a8536f9d47fe802e144b58edbd 100644 (file)
@@ -177,15 +177,6 @@ SYSCTL_DECL(_net_link);
 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,
@@ -223,7 +214,7 @@ lo_framer(struct ifnet *ifp, struct mbuf **m, const struct sockaddr *dest,
 #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);
@@ -254,6 +245,36 @@ lo_del_proto(struct ifnet *ifp, protocol_family_t protocol)
        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.
  *
@@ -296,6 +317,7 @@ lo_output(struct ifnet *ifp, struct mbuf *m_list)
                if (m->m_nextpkt == NULL) {
                        m_tail = m;
                }
+               lo_tx_compl(ifp, m);
        }
 
        s.packets_in = cnt;
@@ -374,8 +396,6 @@ lo_start(struct ifnet *ifp)
        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,
@@ -389,21 +409,7 @@ lo_start(struct ifnet *ifp)
                }
 
                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;
@@ -457,6 +463,21 @@ static errno_t
 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);
@@ -536,6 +557,8 @@ lo_ioctl(struct ifnet *ifp, u_long cmd, void *data)
        }
 
        case SIOCSIFFLAGS:              /* struct ifreq */
+       case SIOCSIFTIMESTAMPENABLE:
+       case SIOCSIFTIMESTAMPDISABLE:
                break;
 
        default:
@@ -634,6 +657,7 @@ loopattach(void)
                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;
@@ -659,7 +683,8 @@ loopattach(void)
        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);
 
@@ -715,6 +740,7 @@ sysctl_sched_model SYSCTL_HANDLER_ARGS
        switch (i) {
        case IFNET_SCHED_MODEL_NORMAL:
        case IFNET_SCHED_MODEL_DRIVER_MANAGED:
+       case IFNET_SCHED_MODEL_FQ_CODEL:
                break;
 
        default: