2 * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1982, 1986, 1993
30 * The Regents of the University of California. All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * @(#)if_loop.c 8.1 (Berkeley) 6/10/93
61 * $FreeBSD: src/sys/net/if_loop.c,v 1.47.2.5 2001/07/03 11:01:41 ume Exp $
64 * NOTICE: This file was modified by SPARTA, Inc. in 2006 to introduce
65 * support for mandatory and extensible security protections. This notice
66 * is included in support of clause 2.2 (b) of the Apple Public License,
71 * Loopback interface driver for protocol testing and timing.
77 #error "More than one loopback interface is not supported."
80 #include <sys/param.h>
81 #include <sys/systm.h>
82 #include <sys/kernel.h>
84 #include <sys/socket.h>
85 #include <sys/sockio.h>
86 #include <sys/mcache.h>
87 #include <sys/sysctl.h>
90 #include <net/if_types.h>
91 #include <net/route.h>
93 #include <sys/malloc.h>
96 #include <netinet/in.h>
97 #include <netinet/in_var.h>
102 #include <netinet/in.h>
104 #include <netinet6/in6_var.h>
105 #include <netinet/ip6.h>
108 #include <net/dlil.h>
109 #include <net/kpi_protocol.h>
112 #include <security/mac_framework.h>
115 #include <pexpert/pexpert.h>
118 #define LOSNDQ_MAXLEN 256
120 #define LO_BPF_TAP_OUT(_m) { \
121 if (lo_statics[0].bpf_callback != NULL) { \
122 bpf_tap_out(lo_ifp, DLT_NULL, _m, \
123 &((struct loopback_header *)_m->m_pkthdr.header)->protocol,\
124 sizeof (u_int32_t)); \
128 #define LO_BPF_TAP_OUT_MULTI(_m) { \
129 if (lo_statics[0].bpf_callback != NULL) { \
131 for (_n = _m; _n != NULL; _n = _n->m_nextpkt) \
132 LO_BPF_TAP_OUT(_n); \
136 struct lo_statics_str
{
138 bpf_packet_func bpf_callback
;
141 static struct lo_statics_str lo_statics
[NLOOP
];
142 static int lo_txstart
= 0;
144 struct ifnet
*lo_ifp
= NULL
;
146 struct loopback_header
{
147 protocol_family_t protocol
;
150 /* Local forward declerations */
151 void loopattach(void);
152 static errno_t
lo_demux(struct ifnet
*, struct mbuf
*, char *,
153 protocol_family_t
*);
154 #if !KPI_INTERFACE_EMBEDDED
155 static errno_t
lo_framer(struct ifnet
*, struct mbuf
**,
156 const struct sockaddr
*,
157 const char *, const char *);
160 lo_framer(struct ifnet
*, struct mbuf
**, const struct sockaddr
*,
161 const char *, const char *, u_int32_t
*, u_int32_t
*);
163 static errno_t
lo_add_proto(struct ifnet
*, protocol_family_t
,
164 const struct ifnet_demux_desc
*, u_int32_t
);
165 static errno_t
lo_del_proto(struct ifnet
*, protocol_family_t
);
166 static int lo_output(struct ifnet
*, struct mbuf
*);
167 static errno_t
lo_pre_enqueue(struct ifnet
*, struct mbuf
*);
168 static void lo_start(struct ifnet
*);
169 static errno_t
lo_pre_output(struct ifnet
*, protocol_family_t
, struct mbuf
**,
170 const struct sockaddr
*, void *, char *, char *);
171 static errno_t
lo_input(struct ifnet
*, protocol_family_t
, struct mbuf
*);
172 static void lo_rtrequest(int, struct rtentry
*, struct sockaddr
*);
173 static errno_t
lo_ioctl(struct ifnet
*, u_long
, void *);
174 static errno_t
lo_attach_proto(struct ifnet
*, protocol_family_t
);
175 static void lo_reg_if_mods(void);
176 static errno_t
lo_set_bpf_tap(struct ifnet
*, bpf_tap_mode
, bpf_packet_func
);
177 static int sysctl_dequeue_max SYSCTL_HANDLER_ARGS
;
178 static int sysctl_sched_model SYSCTL_HANDLER_ARGS
;
179 static int sysctl_dequeue_scidx SYSCTL_HANDLER_ARGS
;
181 SYSCTL_DECL(_net_link
);
183 SYSCTL_NODE(_net_link
, OID_AUTO
, loopback
, CTLFLAG_RW
| CTLFLAG_LOCKED
, 0,
184 "loopback interface");
186 #define LO_BW_SLEEP 10
187 static u_int32_t lo_bw_sleep_usec
= LO_BW_SLEEP
;
188 SYSCTL_UINT(_net_link_loopback
, OID_AUTO
, bw_sleep_usec
,
189 CTLFLAG_RW
| CTLFLAG_LOCKED
, &lo_bw_sleep_usec
, LO_BW_SLEEP
, "");
191 static u_int32_t lo_bw_measure
= 0;
192 SYSCTL_UINT(_net_link_loopback
, OID_AUTO
, bw_measure
,
193 CTLFLAG_RW
| CTLFLAG_LOCKED
, &lo_bw_measure
, 0, "");
195 static u_int32_t lo_dequeue_max
= LOSNDQ_MAXLEN
;
196 SYSCTL_PROC(_net_link_loopback
, OID_AUTO
, max_dequeue
,
197 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_LOCKED
, &lo_dequeue_max
, LOSNDQ_MAXLEN
,
198 sysctl_dequeue_max
, "I", "Maximum number of packets dequeued at a time");
200 static u_int32_t lo_sched_model
= IFNET_SCHED_MODEL_NORMAL
;
201 SYSCTL_PROC(_net_link_loopback
, OID_AUTO
, sched_model
,
202 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_LOCKED
, &lo_sched_model
,
203 IFNET_SCHED_MODEL_NORMAL
, sysctl_sched_model
, "I", "Scheduling model");
205 static u_int32_t lo_dequeue_sc
= MBUF_SC_BE
;
206 static int lo_dequeue_scidx
= MBUF_SCIDX(MBUF_SC_BE
);
207 SYSCTL_PROC(_net_link_loopback
, OID_AUTO
, dequeue_sc
,
208 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_LOCKED
, &lo_dequeue_scidx
,
209 MBUF_SC_BE
, sysctl_dequeue_scidx
, "I", "Dequeue a specific SC index");
212 lo_demux(struct ifnet
*ifp
, struct mbuf
*m
, char *frame_header
,
213 protocol_family_t
*protocol_family
)
215 #pragma unused(ifp, m)
216 struct loopback_header
*header
=
217 (struct loopback_header
*)(void *)frame_header
;
219 *protocol_family
= header
->protocol
;
224 #if !KPI_INTERFACE_EMBEDDED
226 lo_framer(struct ifnet
*ifp
, struct mbuf
**m
, const struct sockaddr
*dest
,
227 const char *dest_linkaddr
, const char *frame_type
)
230 lo_framer(struct ifnet
*ifp
, struct mbuf
**m
, const struct sockaddr
*dest
,
231 const char *dest_linkaddr
, const char *frame_type
,
232 u_int32_t
*prepend_len
, u_int32_t
*postpend_len
)
235 #pragma unused(ifp, dest, dest_linkaddr)
236 struct loopback_header
*header
;
238 M_PREPEND(*m
, sizeof (struct loopback_header
), M_WAITOK
);
240 /* Tell caller not to try to free passed-in mbuf */
241 return (EJUSTRETURN
);
244 #if KPI_INTERFACE_EMBEDDED
245 *prepend_len
= sizeof (struct loopback_header
);
247 #endif /* KPI_INTERFACE_EMBEDDED */
249 header
= mtod(*m
, struct loopback_header
*);
250 bcopy(frame_type
, &header
->protocol
, sizeof (u_int32_t
));
255 lo_add_proto(struct ifnet
*interface
, protocol_family_t protocol_family
,
256 const struct ifnet_demux_desc
*demux_array
, u_int32_t demux_count
)
258 #pragma unused(interface, protocol_family, demux_array, demux_count)
263 lo_del_proto(struct ifnet
*ifp
, protocol_family_t protocol
)
265 #pragma unused(ifp, protocol)
272 * This routine is called only when lo_txstart is disabled.
275 lo_output(struct ifnet
*ifp
, struct mbuf
*m_list
)
277 struct mbuf
*m
, *m_tail
= NULL
;
278 struct ifnet_stat_increment_param s
;
279 u_int32_t cnt
= 0, len
= 0;
281 bzero(&s
, sizeof(s
));
283 for (m
= m_list
; m
; m
= m
->m_nextpkt
) {
284 if ((m
->m_flags
& M_PKTHDR
) == 0)
285 panic("lo_output: no HDR");
287 len
+= m
->m_pkthdr
.len
;
290 * Don't overwrite the rcvif field if it is in use.
291 * This is used to match multicast packets, sent looping
292 * back, with the appropriate group record on input.
294 if (m
->m_pkthdr
.rcvif
== NULL
)
295 m
->m_pkthdr
.rcvif
= ifp
;
297 m
->m_pkthdr
.header
= mtod(m
, char *);
298 if (apple_hwcksum_tx
!= 0) {
299 /* loopback checksums are always OK */
300 m
->m_pkthdr
.csum_data
= 0xffff;
301 m
->m_pkthdr
.csum_flags
=
302 CSUM_DATA_VALID
| CSUM_PSEUDO_HDR
|
303 CSUM_IP_CHECKED
| CSUM_IP_VALID
;
305 m_adj(m
, sizeof (struct loopback_header
));
308 if (m
->m_nextpkt
== NULL
) {
318 return (ifnet_input_extended(ifp
, m_list
, m_tail
, &s
));
322 * Pre-enqueue callback.
324 * This routine is called only when lo_txstart is enabled.
327 lo_pre_enqueue(struct ifnet
*ifp
, struct mbuf
*m0
)
329 struct mbuf
*m
= m0
, *n
;
333 VERIFY((m
->m_flags
& M_PKTHDR
));
339 * Don't overwrite the rcvif field if it is in use.
340 * This is used to match multicast packets, sent looping
341 * back, with the appropriate group record on input.
343 if (m
->m_pkthdr
.rcvif
== NULL
)
344 m
->m_pkthdr
.rcvif
= ifp
;
346 m
->m_pkthdr
.header
= mtod(m
, char *);
347 if (apple_hwcksum_tx
!= 0) {
348 /* loopback checksums are always OK */
349 m
->m_pkthdr
.csum_data
= 0xffff;
350 m
->m_pkthdr
.csum_flags
=
351 CSUM_DATA_VALID
| CSUM_PSEUDO_HDR
|
352 CSUM_IP_CHECKED
| CSUM_IP_VALID
;
354 m_adj(m
, sizeof (struct loopback_header
));
357 * Let the callee free it in case of error,
358 * and perform any necessary accounting.
360 (void) ifnet_enqueue(ifp
, m
);
369 * Start output callback.
371 * This routine is invoked by the start worker thread; because we never call
372 * it directly, there is no need do deploy any serialization mechanism other
373 * than what's already used by the worker thread, i.e. this is already single
376 * This routine is called only when lo_txstart is enabled.
379 lo_start(struct ifnet
*ifp
)
381 struct ifnet_stat_increment_param s
;
383 bzero(&s
, sizeof (s
));
386 struct mbuf
*m
= NULL
, *m_tail
= NULL
;
387 u_int32_t cnt
, len
= 0;
391 if (lo_sched_model
== IFNET_SCHED_MODEL_NORMAL
) {
392 if (ifnet_dequeue_multi(ifp
, lo_dequeue_max
, &m
,
393 &m_tail
, &cnt
, &len
) != 0)
396 if (ifnet_dequeue_service_class_multi(ifp
,
397 lo_dequeue_sc
, lo_dequeue_max
, &m
,
398 &m_tail
, &cnt
, &len
) != 0)
402 LO_BPF_TAP_OUT_MULTI(m
);
405 if (cnt
>= if_bw_measure_size
)
406 ifnet_transmit_burst_start(ifp
, m
);
407 if (lo_bw_sleep_usec
> 0) {
408 bzero(&ts
, sizeof(ts
));
409 ts
.tv_nsec
= (lo_bw_sleep_usec
<< 10) * cnt
;
411 /* Add msleep with timeout */
412 (void) msleep(&sleep_chan
, NULL
,
413 PSOCK
, "lo_start", &ts
);
415 if (cnt
>= if_bw_measure_size
)
416 ifnet_transmit_burst_end(ifp
, m_tail
);
419 /* stats are required for extended variant */
425 (void) ifnet_input_extended(ifp
, m
, m_tail
, &s
);
430 * This is a common pre-output route used by INET and INET6. This could
431 * (should?) be split into separate pre-output routines for each protocol.
434 lo_pre_output(struct ifnet
*ifp
, protocol_family_t protocol_family
,
435 struct mbuf
**m
, const struct sockaddr
*dst
, void *route
, char *frame_type
,
438 #pragma unused(ifp, dst, dst_addr)
439 struct rtentry
*rt
= route
;
441 (*m
)->m_flags
|= M_LOOP
;
443 if (((*m
)->m_flags
& M_PKTHDR
) == 0)
444 panic("looutput no HDR");
447 u_int32_t rt_flags
= rt
->rt_flags
;
448 if (rt_flags
& (RTF_REJECT
| RTF_BLACKHOLE
)) {
449 if (rt_flags
& RTF_BLACKHOLE
) {
451 return (EJUSTRETURN
);
453 return ((rt_flags
& RTF_HOST
) ?
454 EHOSTUNREACH
: ENETUNREACH
);
459 bcopy(&protocol_family
, frame_type
, sizeof (protocol_family
));
465 * lo_input - This should work for all attached protocols that use the
466 * ifq/schednetisr input mechanism.
469 lo_input(struct ifnet
*ifp
, protocol_family_t protocol_family
, struct mbuf
*m
)
471 #pragma unused(ifp, protocol_family)
472 if (proto_input(protocol_family
, m
) != 0)
479 lo_rtrequest(int cmd
, struct rtentry
*rt
, struct sockaddr
*sa
)
481 #pragma unused(cmd, sa)
483 RT_LOCK_ASSERT_HELD(rt
);
484 rt
->rt_rmx
.rmx_mtu
= rt
->rt_ifp
->if_mtu
; /* for ISO */
486 * For optimal performance, the send and receive buffers
487 * should be at least twice the MTU plus a little more for
490 rt
->rt_rmx
.rmx_recvpipe
= rt
->rt_rmx
.rmx_sendpipe
= 3 * LOMTU
;
495 * Process an ioctl request.
498 lo_ioctl(struct ifnet
*ifp
, u_long cmd
, void *data
)
504 case SIOCSIFADDR
: { /* struct ifaddr pointer */
505 struct ifaddr
*ifa
= data
;
507 ifnet_set_flags(ifp
, IFF_UP
|IFF_RUNNING
, IFF_UP
|IFF_RUNNING
);
509 ifa
->ifa_rtrequest
= lo_rtrequest
;
512 * Everything else is done at a higher level.
517 case SIOCADDMULTI
: /* struct ifreq */
518 case SIOCDELMULTI
: { /* struct ifreq */
519 struct ifreq
*ifr
= data
;
522 error
= EAFNOSUPPORT
; /* XXX */
525 switch (ifr
->ifr_addr
.sa_family
) {
537 error
= EAFNOSUPPORT
;
543 case SIOCSIFMTU
: { /* struct ifreq */
544 struct ifreq
*ifr
= data
;
546 bcopy(&ifr
->ifr_mtu
, &ifp
->if_mtu
, sizeof (int));
550 case SIOCSIFFLAGS
: /* struct ifreq */
559 #endif /* NLOOP > 0 */
563 lo_attach_proto(struct ifnet
*ifp
, protocol_family_t protocol_family
)
565 struct ifnet_attach_proto_param_v2 proto
;
568 bzero(&proto
, sizeof (proto
));
569 proto
.input
= lo_input
;
570 proto
.pre_output
= lo_pre_output
;
572 result
= ifnet_attach_protocol_v2(ifp
, protocol_family
, &proto
);
574 if (result
&& result
!= EEXIST
) {
575 printf("lo_attach_proto: ifnet_attach_protocol for %u "
576 "returned=%d\n", protocol_family
, result
);
587 /* Register protocol registration functions */
588 if ((error
= proto_register_plumber(PF_INET
,
589 APPLE_IF_FAM_LOOPBACK
, lo_attach_proto
, NULL
)) != 0)
590 printf("proto_register_plumber failed for AF_INET "
591 "error=%d\n", error
);
593 if ((error
= proto_register_plumber(PF_INET6
,
594 APPLE_IF_FAM_LOOPBACK
, lo_attach_proto
, NULL
)) != 0)
595 printf("proto_register_plumber failed for AF_INET6 "
596 "error=%d\n", error
);
600 lo_set_bpf_tap(struct ifnet
*ifp
, bpf_tap_mode mode
,
601 bpf_packet_func bpf_callback
)
603 VERIFY(ifp
== lo_ifp
);
605 lo_statics
[0].bpf_mode
= mode
;
608 case BPF_TAP_DISABLE
:
610 lo_statics
[0].bpf_callback
= NULL
;
614 case BPF_TAP_INPUT_OUTPUT
:
615 lo_statics
[0].bpf_callback
= bpf_callback
;
626 struct ifnet_init_eparams lo_init
;
629 PE_parse_boot_argn("lo_txstart", &lo_txstart
, sizeof (lo_txstart
));
633 lo_statics
[0].bpf_callback
= NULL
;
634 lo_statics
[0].bpf_mode
= BPF_TAP_DISABLE
;
636 bzero(&lo_init
, sizeof (lo_init
));
637 lo_init
.ver
= IFNET_INIT_CURRENT_VERSION
;
638 lo_init
.len
= sizeof (lo_init
);
639 lo_init
.sndq_maxlen
= LOSNDQ_MAXLEN
;
642 lo_init
.pre_enqueue
= lo_pre_enqueue
;
643 lo_init
.start
= lo_start
;
644 lo_init
.output_sched_model
= lo_sched_model
;
646 lo_init
.flags
= IFNET_INIT_LEGACY
;
647 lo_init
.output
= lo_output
;
651 lo_init
.family
= IFNET_FAMILY_LOOPBACK
;
652 lo_init
.type
= IFT_LOOP
;
653 lo_init
.demux
= lo_demux
;
654 lo_init
.add_proto
= lo_add_proto
;
655 lo_init
.del_proto
= lo_del_proto
;
656 lo_init
.framer
= lo_framer
;
657 lo_init
.softc
= &lo_statics
[0];
658 lo_init
.ioctl
= lo_ioctl
;
659 lo_init
.set_bpf_tap
= lo_set_bpf_tap
;
661 result
= ifnet_allocate_extended(&lo_init
, &lo_ifp
);
663 panic("%s: couldn't allocate loopback ifnet (%d)\n",
668 ifnet_set_mtu(lo_ifp
, LOMTU
);
669 ifnet_set_flags(lo_ifp
, IFF_LOOPBACK
| IFF_MULTICAST
,
670 IFF_LOOPBACK
| IFF_MULTICAST
);
671 ifnet_set_offload(lo_ifp
,
672 IFNET_CSUM_IP
| IFNET_CSUM_TCP
| IFNET_CSUM_UDP
|
673 IFNET_CSUM_TCPIPV6
| IFNET_CSUM_UDPIPV6
| IFNET_IPV6_FRAGMENT
|
674 IFNET_CSUM_FRAGMENT
| IFNET_IP_FRAGMENT
| IFNET_MULTIPAGES
);
675 ifnet_set_hdrlen(lo_ifp
, sizeof (struct loopback_header
));
676 ifnet_set_eflags(lo_ifp
, IFEF_SENDLIST
, IFEF_SENDLIST
);
679 mac_ifnet_label_init(ifp
);
682 result
= ifnet_attach(lo_ifp
, NULL
);
684 panic("%s: couldn't attach loopback ifnet (%d)\n",
688 bpfattach(lo_ifp
, DLT_NULL
, sizeof (u_int32_t
));
692 sysctl_dequeue_max SYSCTL_HANDLER_ARGS
694 #pragma unused(arg1, arg2)
700 err
= sysctl_handle_int(oidp
, &i
, 0, req
);
701 if (err
!= 0 || req
->newptr
== USER_ADDR_NULL
)
706 else if (i
> LOSNDQ_MAXLEN
)
715 sysctl_sched_model SYSCTL_HANDLER_ARGS
717 #pragma unused(arg1, arg2)
723 err
= sysctl_handle_int(oidp
, &i
, 0, req
);
724 if (err
!= 0 || req
->newptr
== USER_ADDR_NULL
)
728 case IFNET_SCHED_MODEL_NORMAL
:
729 case IFNET_SCHED_MODEL_DRIVER_MANAGED
:
737 if (err
== 0 && (err
= ifnet_set_output_sched_model(lo_ifp
, i
)) == 0)
744 sysctl_dequeue_scidx SYSCTL_HANDLER_ARGS
746 #pragma unused(arg1, arg2)
750 i
= lo_dequeue_scidx
;
752 err
= sysctl_handle_int(oidp
, &i
, 0, req
);
753 if (err
!= 0 || req
->newptr
== USER_ADDR_NULL
)
756 if (!MBUF_VALID_SCIDX(i
))
759 if (lo_sched_model
!= IFNET_SCHED_MODEL_DRIVER_MANAGED
)
762 lo_dequeue_sc
= m_service_class_from_idx(i
);
763 lo_dequeue_scidx
= MBUF_SCIDX(lo_dequeue_sc
);