]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/net/if_loop.c
xnu-6153.41.3.tar.gz
[apple/xnu.git] / bsd / net / if_loop.c
index 3baa27434e19ed326f187519eb7e0605ba81aab6..b767144406c0734046e6d76faa07d5b82c09b102 100644 (file)
 
 #include <pexpert/pexpert.h>
 
-#define        LOMTU           16384
-#define        LOSNDQ_MAXLEN   256
-
-#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.pkt_hdr)-> \
-                   protocol, sizeof (u_int32_t));                      \
-       }                                                               \
+#define LOMTU           16384
+#define LOSNDQ_MAXLEN   256
+
+#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.pkt_hdr)-> \
+                   protocol, sizeof (u_int32_t));                      \
+       }                                                               \
 }
 
-#define        LO_BPF_TAP_OUT_MULTI(_m) {                                      \
-       if (lo_statics[0].bpf_callback != NULL) {                       \
-               struct mbuf *_n;                                        \
-               for (_n = _m; _n != NULL; _n = _n->m_nextpkt)           \
-                       LO_BPF_TAP_OUT(_n);                             \
-       }                                                               \
+#define LO_BPF_TAP_OUT_MULTI(_m) {                                      \
+       if (lo_statics[0].bpf_callback != NULL) {                       \
+               struct mbuf *_n;                                        \
+               for (_n = _m; _n != NULL; _n = _n->m_nextpkt)           \
+                       LO_BPF_TAP_OUT(_n);                             \
+       }                                                               \
 }
 
 struct lo_statics_str {
-       int             bpf_mode;
-       bpf_packet_func bpf_callback;
+       int             bpf_mode;
+       bpf_packet_func bpf_callback;
 };
 
 static struct lo_statics_str lo_statics[NLOOP];
@@ -143,8 +143,8 @@ static int lo_txstart = 0;
 
 struct ifnet *lo_ifp = NULL;
 
-struct loopback_header {
-       protocol_family_t       protocol;
+struct  loopback_header {
+       protocol_family_t       protocol;
 };
 
 /* Local forward declerations */
@@ -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,
@@ -212,7 +203,7 @@ lo_demux(struct ifnet *ifp, struct mbuf *m, char *frame_header,
 
        *protocol_family = header->protocol;
 
-       return (0);
+       return 0;
 }
 
 static errno_t
@@ -223,20 +214,22 @@ 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, 1);
+       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 EJUSTRETURN;
        }
 
-       if (prepend_len != NULL)
-               *prepend_len = sizeof (struct loopback_header);
-       if (postpend_len != NULL)
+       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));
-       return (0);
+       bcopy(frame_type, &header->protocol, sizeof(u_int32_t));
+       return 0;
 }
 
 static errno_t
@@ -244,14 +237,14 @@ lo_add_proto(struct ifnet *interface, protocol_family_t protocol_family,
     const struct ifnet_demux_desc *demux_array, u_int32_t demux_count)
 {
 #pragma unused(interface, protocol_family, demux_array, demux_count)
-       return (0);
+       return 0;
 }
 
 static errno_t
 lo_del_proto(struct ifnet *ifp, protocol_family_t protocol)
 {
 #pragma unused(ifp, protocol)
-       return (0);
+       return 0;
 }
 
 static void
@@ -271,15 +264,17 @@ lo_tx_compl(struct ifnet *ifp, struct mbuf *m)
                        net_timernsec(&now, &ts);
 
                        error = mbuf_set_timestamp(m, ts, TRUE);
-                       if (error != 0)
+                       if (error != 0) {
                                printf("%s: mbuf_set_timestamp() failed %d\n",
-                                       __func__, error);
+                                   __func__, error);
+                       }
                }
        }
        error = mbuf_set_status(m, KERN_SUCCESS);
-       if (error != 0)
+       if (error != 0) {
                printf("%s: mbuf_set_status() failed %d\n",
-                       __func__, error);
+                   __func__, error);
+       }
 
        ifnet_tx_compl(ifp, m);
 }
@@ -308,8 +303,9 @@ lo_output(struct ifnet *ifp, struct mbuf *m_list)
                 *  This is used to match multicast packets, sent looping
                 *  back, with the appropriate group record on input.
                 */
-               if (m->m_pkthdr.rcvif == NULL)
+               if (m->m_pkthdr.rcvif == NULL) {
                        m->m_pkthdr.rcvif = ifp;
+               }
 
                m->m_pkthdr.pkt_flags |= PKTF_LOOP;
                m->m_pkthdr.pkt_hdr = mtod(m, char *);
@@ -320,7 +316,7 @@ lo_output(struct ifnet *ifp, struct mbuf *m_list)
                    CSUM_DATA_VALID | CSUM_PSEUDO_HDR |
                    CSUM_IP_CHECKED | CSUM_IP_VALID;
 
-               m_adj(m, sizeof (struct loopback_header));
+               m_adj(m, sizeof(struct loopback_header));
 
                LO_BPF_TAP_OUT(m);
                if (m->m_nextpkt == NULL) {
@@ -334,7 +330,7 @@ lo_output(struct ifnet *ifp, struct mbuf *m_list)
        s.bytes_in = len;
        s.bytes_out = len;
 
-       return (ifnet_input_extended(ifp, m_list, m_tail, &s));
+       return ifnet_input_extended(ifp, m_list, m_tail, &s);
 }
 
 /*
@@ -359,8 +355,9 @@ lo_pre_enqueue(struct ifnet *ifp, struct mbuf *m0)
                 *  This is used to match multicast packets, sent looping
                 *  back, with the appropriate group record on input.
                 */
-               if (m->m_pkthdr.rcvif == NULL)
+               if (m->m_pkthdr.rcvif == NULL) {
                        m->m_pkthdr.rcvif = ifp;
+               }
 
                m->m_pkthdr.pkt_flags |= PKTF_LOOP;
                m->m_pkthdr.pkt_hdr = mtod(m, char *);
@@ -371,7 +368,7 @@ lo_pre_enqueue(struct ifnet *ifp, struct mbuf *m0)
                    CSUM_DATA_VALID | CSUM_PSEUDO_HDR |
                    CSUM_IP_CHECKED | CSUM_IP_VALID;
 
-               m_adj(m, sizeof (struct loopback_header));
+               m_adj(m, sizeof(struct loopback_header));
 
                /*
                 * Let the callee free it in case of error,
@@ -382,7 +379,7 @@ lo_pre_enqueue(struct ifnet *ifp, struct mbuf *m0)
                m = n;
        }
 
-       return (error);
+       return error;
 }
 
 /*
@@ -400,41 +397,26 @@ lo_start(struct ifnet *ifp)
 {
        struct ifnet_stat_increment_param s;
 
-       bzero(&s, sizeof (s));
+       bzero(&s, sizeof(s));
 
        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,
-                           &m_tail, &cnt, &len) != 0)
+                           &m_tail, &cnt, &len) != 0) {
                                break;
+                       }
                } else {
                        if (ifnet_dequeue_service_class_multi(ifp,
                            lo_dequeue_sc, lo_dequeue_max, &m,
-                           &m_tail, &cnt, &len) != 0)
+                           &m_tail, &cnt, &len) != 0) {
                                break;
+                       }
                }
 
                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 */
@@ -468,17 +450,17 @@ lo_pre_output(struct ifnet *ifp, protocol_family_t protocol_family,
                if (rt_flags & (RTF_REJECT | RTF_BLACKHOLE)) {
                        if (rt_flags & RTF_BLACKHOLE) {
                                m_freem(*m);
-                               return (EJUSTRETURN);
+                               return EJUSTRETURN;
                        } else {
-                               return ((rt_flags & RTF_HOST) ?
-                                   EHOSTUNREACH : ENETUNREACH);
+                               return (rt_flags & RTF_HOST) ?
+                                      EHOSTUNREACH : ENETUNREACH;
                        }
                }
        }
 
-       bcopy(&protocol_family, frame_type, sizeof (protocol_family));
+       bcopy(&protocol_family, frame_type, sizeof(protocol_family));
 
-       return (0);
+       return 0;
 }
 
 /*
@@ -499,14 +481,16 @@ lo_input(struct ifnet *ifp, protocol_family_t protocol_family, struct mbuf *m)
                net_timernsec(&now, &ts);
 
                error = mbuf_set_timestamp(m, ts, TRUE);
-               if (error != 0)
+               if (error != 0) {
                        printf("%s: mbuf_set_timestamp() failed %d\n",
-                               __func__, error);
+                           __func__, error);
+               }
        }
 
-       if (proto_input(protocol_family, m) != 0)
+       if (proto_input(protocol_family, m) != 0) {
                m_freem(m);
-       return (0);
+       }
+       return 0;
 }
 
 /* ARGSUSED */
@@ -535,11 +519,10 @@ lo_ioctl(struct ifnet *ifp, u_long cmd, void *data)
        int error = 0;
 
        switch (cmd) {
-
-       case SIOCSIFADDR: {             /* struct ifaddr pointer */
+       case SIOCSIFADDR: {             /* struct ifaddr pointer */
                struct ifaddr *ifa = data;
 
-               ifnet_set_flags(ifp, IFF_UP|IFF_RUNNING, IFF_UP|IFF_RUNNING);
+               ifnet_set_flags(ifp, IFF_UP | IFF_RUNNING, IFF_UP | IFF_RUNNING);
                IFA_LOCK_SPIN(ifa);
                ifa->ifa_rtrequest = lo_rtrequest;
                IFA_UNLOCK(ifa);
@@ -549,16 +532,15 @@ lo_ioctl(struct ifnet *ifp, u_long cmd, void *data)
                break;
        }
 
-       case SIOCADDMULTI:              /* struct ifreq */
-       case SIOCDELMULTI: {            /* struct ifreq */
+       case SIOCADDMULTI:              /* struct ifreq */
+       case SIOCDELMULTI: {            /* struct ifreq */
                struct ifreq *ifr = data;
 
                if (ifr == NULL) {
-                       error = EAFNOSUPPORT;           /* XXX */
+                       error = EAFNOSUPPORT;           /* XXX */
                        break;
                }
                switch (ifr->ifr_addr.sa_family) {
-
 #if INET
                case AF_INET:
                        break;
@@ -575,14 +557,14 @@ lo_ioctl(struct ifnet *ifp, u_long cmd, void *data)
                break;
        }
 
-       case SIOCSIFMTU: {              /* struct ifreq */
+       case SIOCSIFMTU: {              /* struct ifreq */
                struct ifreq *ifr = data;
 
-               bcopy(&ifr->ifr_mtu, &ifp->if_mtu, sizeof (int));
+               bcopy(&ifr->ifr_mtu, &ifp->if_mtu, sizeof(int));
                break;
        }
 
-       case SIOCSIFFLAGS:              /* struct ifreq */
+       case SIOCSIFFLAGS:              /* struct ifreq */
        case SIOCSIFTIMESTAMPENABLE:
        case SIOCSIFTIMESTAMPDISABLE:
                break;
@@ -591,7 +573,7 @@ lo_ioctl(struct ifnet *ifp, u_long cmd, void *data)
                error = EOPNOTSUPP;
                break;
        }
-       return (error);
+       return error;
 }
 #endif /* NLOOP > 0 */
 
@@ -599,10 +581,10 @@ lo_ioctl(struct ifnet *ifp, u_long cmd, void *data)
 static errno_t
 lo_attach_proto(struct ifnet *ifp, protocol_family_t protocol_family)
 {
-       struct ifnet_attach_proto_param_v2      proto;
-       errno_t                                                 result = 0;
+       struct ifnet_attach_proto_param_v2      proto;
+       errno_t                                                 result = 0;
 
-       bzero(&proto, sizeof (proto));
+       bzero(&proto, sizeof(proto));
        proto.input = lo_input;
        proto.pre_output = lo_pre_output;
 
@@ -613,7 +595,7 @@ lo_attach_proto(struct ifnet *ifp, protocol_family_t protocol_family)
                    "returned=%d\n", protocol_family, result);
        }
 
-       return (result);
+       return result;
 }
 
 static void
@@ -623,14 +605,16 @@ lo_reg_if_mods(void)
 
        /* Register protocol registration functions */
        if ((error = proto_register_plumber(PF_INET,
-           APPLE_IF_FAM_LOOPBACK, lo_attach_proto, NULL)) != 0)
+           APPLE_IF_FAM_LOOPBACK, lo_attach_proto, NULL)) != 0) {
                printf("proto_register_plumber failed for AF_INET "
                    "error=%d\n", error);
+       }
 
        if ((error = proto_register_plumber(PF_INET6,
-           APPLE_IF_FAM_LOOPBACK, lo_attach_proto, NULL)) != 0)
+           APPLE_IF_FAM_LOOPBACK, lo_attach_proto, NULL)) != 0) {
                printf("proto_register_plumber failed for AF_INET6 "
                    "error=%d\n", error);
+       }
 }
 
 static errno_t
@@ -642,18 +626,18 @@ lo_set_bpf_tap(struct ifnet *ifp, bpf_tap_mode mode,
        lo_statics[0].bpf_mode = mode;
 
        switch (mode) {
-               case BPF_TAP_DISABLE:
-               case BPF_TAP_INPUT:
-                       lo_statics[0].bpf_callback = NULL;
-                       break;
+       case BPF_TAP_DISABLE:
+       case BPF_TAP_INPUT:
+               lo_statics[0].bpf_callback = NULL;
+               break;
 
-               case BPF_TAP_OUTPUT:
-               case BPF_TAP_INPUT_OUTPUT:
-                       lo_statics[0].bpf_callback = bpf_callback;
-                       break;
+       case BPF_TAP_OUTPUT:
+       case BPF_TAP_INPUT_OUTPUT:
+               lo_statics[0].bpf_callback = bpf_callback;
+               break;
        }
 
-       return (0);
+       return 0;
 }
 
 /* ARGSUSED */
@@ -661,39 +645,40 @@ void
 loopattach(void)
 {
        struct ifnet_init_eparams lo_init;
-       errno_t result = 0;
+       errno_t result = 0;
 
-       PE_parse_boot_argn("lo_txstart", &lo_txstart, sizeof (lo_txstart));
+       PE_parse_boot_argn("lo_txstart", &lo_txstart, sizeof(lo_txstart));
 
        lo_reg_if_mods();
 
        lo_statics[0].bpf_callback = NULL;
        lo_statics[0].bpf_mode = BPF_TAP_DISABLE;
 
-       bzero(&lo_init, sizeof (lo_init));
-       lo_init.ver                     = IFNET_INIT_CURRENT_VERSION;
-       lo_init.len                     = sizeof (lo_init);
-       lo_init.sndq_maxlen             = LOSNDQ_MAXLEN;
+       bzero(&lo_init, sizeof(lo_init));
+       lo_init.ver                     = IFNET_INIT_CURRENT_VERSION;
+       lo_init.len                     = sizeof(lo_init);
+       lo_init.sndq_maxlen             = LOSNDQ_MAXLEN;
        if (lo_txstart) {
-               lo_init.flags           = 0;
-               lo_init.pre_enqueue     = lo_pre_enqueue;
-               lo_init.start           = lo_start;
+               lo_init.flags           = 0;
+               lo_init.pre_enqueue     = lo_pre_enqueue;
+               lo_init.start           = lo_start;
                lo_init.output_sched_model = lo_sched_model;
        } else {
-               lo_init.flags           = IFNET_INIT_LEGACY;
-               lo_init.output          = lo_output;
+               lo_init.flags           = IFNET_INIT_LEGACY;
+               lo_init.output          = lo_output;
        }
-       lo_init.name                    = "lo";
-       lo_init.unit                    = 0;
-       lo_init.family                  = IFNET_FAMILY_LOOPBACK;
-       lo_init.type                    = IFT_LOOP;
-       lo_init.demux                   = lo_demux;
-       lo_init.add_proto               = lo_add_proto;
-       lo_init.del_proto               = lo_del_proto;
-       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;
+       lo_init.flags                   |= IFNET_INIT_NX_NOAUTO;
+       lo_init.name                    = "lo";
+       lo_init.unit                    = 0;
+       lo_init.family                  = IFNET_FAMILY_LOOPBACK;
+       lo_init.type                    = IFT_LOOP;
+       lo_init.demux                   = lo_demux;
+       lo_init.add_proto               = lo_add_proto;
+       lo_init.del_proto               = lo_del_proto;
+       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;
 
        result = ifnet_allocate_extended(&lo_init, &lo_ifp);
        if (result != 0) {
@@ -710,7 +695,7 @@ loopattach(void)
            IFNET_CSUM_TCPIPV6 | IFNET_CSUM_UDPIPV6 | IFNET_IPV6_FRAGMENT |
            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_hdrlen(lo_ifp, sizeof(struct loopback_header));
        ifnet_set_eflags(lo_ifp, IFEF_SENDLIST, IFEF_SENDLIST);
 
 #if CONFIG_MACF_NET
@@ -723,7 +708,14 @@ loopattach(void)
                    __func__, result);
                /* NOTREACHED */
        }
-       bpfattach(lo_ifp, DLT_NULL, sizeof (u_int32_t));
+       /*
+        * Disable ECN on loopback as ECN serves no purpose and otherwise
+        * TCP connections are subject to heuristics like SYN retransmits on RST
+        */
+       lo_ifp->if_eflags &= ~IFEF_ECN_ENABLE;
+       lo_ifp->if_eflags |= IFEF_ECN_DISABLE;
+
+       bpfattach(lo_ifp, DLT_NULL, sizeof(u_int32_t));
 }
 
 static int
@@ -736,17 +728,19 @@ sysctl_dequeue_max SYSCTL_HANDLER_ARGS
        i = lo_dequeue_max;
 
        err = sysctl_handle_int(oidp, &i, 0, req);
-       if (err != 0 || req->newptr == USER_ADDR_NULL)
-               return (err);
+       if (err != 0 || req->newptr == USER_ADDR_NULL) {
+               return err;
+       }
 
-       if (i < 1)
+       if (i < 1) {
                i = 1;
-       else if (i > LOSNDQ_MAXLEN)
+       } else if (i > LOSNDQ_MAXLEN) {
                i = LOSNDQ_MAXLEN;
+       }
 
        lo_dequeue_max = i;
 
-       return (err);
+       return err;
 }
 
 static int
@@ -759,8 +753,9 @@ sysctl_sched_model SYSCTL_HANDLER_ARGS
        i = lo_sched_model;
 
        err = sysctl_handle_int(oidp, &i, 0, req);
-       if (err != 0 || req->newptr == USER_ADDR_NULL)
-               return (err);
+       if (err != 0 || req->newptr == USER_ADDR_NULL) {
+               return err;
+       }
 
        switch (i) {
        case IFNET_SCHED_MODEL_NORMAL:
@@ -773,10 +768,11 @@ sysctl_sched_model SYSCTL_HANDLER_ARGS
                break;
        }
 
-       if (err == 0 && (err = ifnet_set_output_sched_model(lo_ifp, i)) == 0)
+       if (err == 0 && (err = ifnet_set_output_sched_model(lo_ifp, i)) == 0) {
                lo_sched_model = i;
+       }
 
-       return (err);
+       return err;
 }
 
 static int
@@ -789,17 +785,20 @@ sysctl_dequeue_scidx SYSCTL_HANDLER_ARGS
        i = lo_dequeue_scidx;
 
        err = sysctl_handle_int(oidp, &i, 0, req);
-       if (err != 0 || req->newptr == USER_ADDR_NULL)
-               return (err);
+       if (err != 0 || req->newptr == USER_ADDR_NULL) {
+               return err;
+       }
 
-       if (!MBUF_VALID_SCIDX(i))
-               return (EINVAL);
+       if (!MBUF_VALID_SCIDX(i)) {
+               return EINVAL;
+       }
 
-       if (lo_sched_model != IFNET_SCHED_MODEL_DRIVER_MANAGED)
-               return (ENODEV);
+       if (lo_sched_model != IFNET_SCHED_MODEL_DRIVER_MANAGED) {
+               return ENODEV;
+       }
 
        lo_dequeue_sc = m_service_class_from_idx(i);
        lo_dequeue_scidx = MBUF_SCIDX(lo_dequeue_sc);
 
-       return (err);
+       return err;
 }