]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/net/if_loop.c
xnu-3789.60.24.tar.gz
[apple/xnu.git] / bsd / net / if_loop.c
index d051c7611b5f42afc611c79f93b24b12a641c9b3..3baa27434e19ed326f187519eb7e0605ba81aab6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
 #define        LO_BPF_TAP_OUT(_m) {                                            \
        if (lo_statics[0].bpf_callback != NULL) {                       \
                bpf_tap_out(lo_ifp, DLT_NULL, _m,                       \
-                   &((struct loopback_header *)_m->m_pkthdr.header)->protocol,\
-                   sizeof (u_int32_t));                                \
+                   &((struct loopback_header *)_m->m_pkthdr.pkt_hdr)-> \
+                   protocol, sizeof (u_int32_t));                      \
        }                                                               \
 }
 
@@ -151,15 +151,9 @@ struct     loopback_header {
 void loopattach(void);
 static errno_t lo_demux(struct ifnet *, struct mbuf *, char *,
     protocol_family_t *);
-#if !KPI_INTERFACE_EMBEDDED
-static errno_t lo_framer(struct ifnet *, struct mbuf **,
-    const struct sockaddr *,
-    const char *, const char *);
-#else
 static errno_t
 lo_framer(struct ifnet *, struct mbuf **, const struct sockaddr *,
     const char *, const char *, u_int32_t *, u_int32_t *);
-#endif
 static errno_t lo_add_proto(struct ifnet *, protocol_family_t,
     const struct ifnet_demux_desc *, u_int32_t);
 static errno_t lo_del_proto(struct ifnet *, protocol_family_t);
@@ -221,30 +215,24 @@ lo_demux(struct ifnet *ifp, struct mbuf *m, char *frame_header,
        return (0);
 }
 
-#if !KPI_INTERFACE_EMBEDDED
-static errno_t
-lo_framer(struct ifnet *ifp, struct mbuf **m, const struct sockaddr *dest,
-    const char *dest_linkaddr, const char *frame_type)
-#else
 static errno_t
 lo_framer(struct ifnet *ifp, struct mbuf **m, const struct sockaddr *dest,
     const char *dest_linkaddr, const char *frame_type,
     u_int32_t *prepend_len, u_int32_t *postpend_len)
-#endif
 {
 #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);
        }
 
-#if KPI_INTERFACE_EMBEDDED
-       *prepend_len = sizeof (struct loopback_header);
-       *postpend_len = 0;
-#endif /* KPI_INTERFACE_EMBEDDED */
+       if (prepend_len != NULL)
+               *prepend_len = sizeof (struct loopback_header);
+       if (postpend_len != NULL)
+               *postpend_len = 0;
 
        header = mtod(*m, struct loopback_header *);
        bcopy(frame_type, &header->protocol, sizeof (u_int32_t));
@@ -266,6 +254,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.
  *
@@ -281,8 +299,7 @@ lo_output(struct ifnet *ifp, struct mbuf *m_list)
        bzero(&s, sizeof(s));
 
        for (m = m_list; m; m = m->m_nextpkt) {
-               if ((m->m_flags & M_PKTHDR) == 0)
-                       panic("lo_output: no HDR");
+               VERIFY(m->m_flags & M_PKTHDR);
                cnt++;
                len += m->m_pkthdr.len;
 
@@ -294,26 +311,28 @@ lo_output(struct ifnet *ifp, struct mbuf *m_list)
                if (m->m_pkthdr.rcvif == NULL)
                        m->m_pkthdr.rcvif = ifp;
 
-               m->m_pkthdr.header = mtod(m, char *);
-               if (apple_hwcksum_tx != 0) {
-                       /* loopback checksums are always OK */
-                       m->m_pkthdr.csum_data = 0xffff;
-                       m->m_pkthdr.csum_flags =
-                           CSUM_DATA_VALID | CSUM_PSEUDO_HDR |
-                           CSUM_IP_CHECKED | CSUM_IP_VALID;
-               }
+               m->m_pkthdr.pkt_flags |= PKTF_LOOP;
+               m->m_pkthdr.pkt_hdr = mtod(m, char *);
+
+               /* loopback checksums are always OK */
+               m->m_pkthdr.csum_data = 0xffff;
+               m->m_pkthdr.csum_flags =
+                   CSUM_DATA_VALID | CSUM_PSEUDO_HDR |
+                   CSUM_IP_CHECKED | CSUM_IP_VALID;
+
                m_adj(m, sizeof (struct loopback_header));
 
                LO_BPF_TAP_OUT(m);
                if (m->m_nextpkt == NULL) {
                        m_tail = m;
                }
+               lo_tx_compl(ifp, m);
        }
 
        s.packets_in = cnt;
        s.packets_out = cnt;
        s.bytes_in = len;
-       s.bytes_out = len;      
+       s.bytes_out = len;
 
        return (ifnet_input_extended(ifp, m_list, m_tail, &s));
 }
@@ -330,7 +349,7 @@ lo_pre_enqueue(struct ifnet *ifp, struct mbuf *m0)
        int error = 0;
 
        while (m != NULL) {
-               VERIFY((m->m_flags & M_PKTHDR));
+               VERIFY(m->m_flags & M_PKTHDR);
 
                n = m->m_nextpkt;
                m->m_nextpkt = NULL;
@@ -343,14 +362,15 @@ lo_pre_enqueue(struct ifnet *ifp, struct mbuf *m0)
                if (m->m_pkthdr.rcvif == NULL)
                        m->m_pkthdr.rcvif = ifp;
 
-               m->m_pkthdr.header = mtod(m, char *);
-               if (apple_hwcksum_tx != 0) {
-                       /* loopback checksums are always OK */
-                       m->m_pkthdr.csum_data = 0xffff;
-                       m->m_pkthdr.csum_flags =
-                           CSUM_DATA_VALID | CSUM_PSEUDO_HDR |
-                           CSUM_IP_CHECKED | CSUM_IP_VALID;
-               }
+               m->m_pkthdr.pkt_flags |= PKTF_LOOP;
+               m->m_pkthdr.pkt_hdr = mtod(m, char *);
+
+               /* loopback checksums are always OK */
+               m->m_pkthdr.csum_data = 0xffff;
+               m->m_pkthdr.csum_flags =
+                   CSUM_DATA_VALID | CSUM_PSEUDO_HDR |
+                   CSUM_IP_CHECKED | CSUM_IP_VALID;
+
                m_adj(m, sizeof (struct loopback_header));
 
                /*
@@ -415,6 +435,7 @@ lo_start(struct ifnet *ifp)
                        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;
@@ -438,10 +459,9 @@ lo_pre_output(struct ifnet *ifp, protocol_family_t protocol_family,
 #pragma unused(ifp, dst, dst_addr)
        struct rtentry *rt = route;
 
-       (*m)->m_flags |= M_LOOP;
+       VERIFY((*m)->m_flags & M_PKTHDR);
 
-       if (((*m)->m_flags & M_PKTHDR) == 0)
-               panic("looutput no HDR");
+       (*m)->m_flags |= M_LOOP;
 
        if (rt != NULL) {
                u_int32_t rt_flags = rt->rt_flags;
@@ -469,6 +489,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);
@@ -548,6 +583,8 @@ lo_ioctl(struct ifnet *ifp, u_long cmd, void *data)
        }
 
        case SIOCSIFFLAGS:              /* struct ifreq */
+       case SIOCSIFTIMESTAMPENABLE:
+       case SIOCSIFTIMESTAMPDISABLE:
                break;
 
        default:
@@ -653,7 +690,7 @@ loopattach(void)
        lo_init.demux                   = lo_demux;
        lo_init.add_proto               = lo_add_proto;
        lo_init.del_proto               = lo_del_proto;
-       lo_init.framer                  = lo_framer;
+       lo_init.framer_extended         = lo_framer;
        lo_init.softc                   = &lo_statics[0];
        lo_init.ioctl                   = lo_ioctl;
        lo_init.set_bpf_tap             = lo_set_bpf_tap;
@@ -671,7 +708,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);
 
@@ -727,6 +765,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: