/*
- * 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)); \
} \
}
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);
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));
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.
*
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;
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));
}
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;
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));
/*
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;
#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;
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.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;
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: