2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1999 Apple Computer, Inc.
25 * Data Link Inteface Layer
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/malloc.h>
36 #include <sys/socket.h>
37 #include <net/if_dl.h>
39 #include <net/if_var.h>
41 #include <sys/kern_event.h>
42 #include <sys/kdebug.h>
45 #include <kern/thread.h>
46 #include <kern/task.h>
47 #include <net/netisr.h>
48 #include <net/if_types.h>
51 #define DBG_LAYER_BEG DLILDBG_CODE(DBG_DLIL_STATIC, 0)
52 #define DBG_LAYER_END DLILDBG_CODE(DBG_DLIL_STATIC, 2)
53 #define DBG_FNC_DLIL_INPUT DLILDBG_CODE(DBG_DLIL_STATIC, (1 << 8))
54 #define DBG_FNC_DLIL_OUTPUT DLILDBG_CODE(DBG_DLIL_STATIC, (2 << 8))
55 #define DBG_FNC_DLIL_IFOUT DLILDBG_CODE(DBG_DLIL_STATIC, (3 << 8))
58 #define MAX_DL_TAGS 50
59 #define MAX_DLIL_FILTERS 50
60 #define MAX_FRAME_TYPE_SIZE 4 /* LONGWORDS */
61 #define MAX_LINKADDR 4 /* LONGWORDS */
62 #define M_NKE M_IFADDR
64 #define PFILT(x) ((struct dlil_filterq_entry *) (x))->variants.pr_filter
65 #define IFILT(x) ((struct dlil_filterq_entry *) (x))->variants.if_filter
69 struct if_proto
*proto
;
70 struct dlil_filterq_head
*pr_flt_head
;
74 struct dlil_stats_str
{
86 struct dlil_filter_id_str
{
88 struct dlil_filterq_head
*head
;
89 struct dlil_filterq_entry
*filter_ptr
;
91 struct if_proto
*proto
;
96 struct if_family_str
{
97 TAILQ_ENTRY(if_family_str
) if_fam_next
;
102 #define DLIL_SHUTDOWN 1
104 int (*add_if
)(struct ifnet
*ifp
);
105 int (*del_if
)(struct ifnet
*ifp
);
106 int (*add_proto
)(struct ddesc_head_str
*demux_desc_head
,
107 struct if_proto
*proto
, u_long dl_tag
);
108 int (*del_proto
)(struct if_proto
*proto
, u_long dl_tag
);
109 int (*ifmod_ioctl
)(struct ifnet
*ifp
, u_long command
, caddr_t data
);
115 struct dlil_stats_str dlil_stats
;
118 struct dlil_filter_id_str dlil_filters
[MAX_DLIL_FILTERS
+1];
121 struct dl_tag_str dl_tag_array
[MAX_DL_TAGS
+1];
124 TAILQ_HEAD(, if_family_str
) if_family_head
;
126 static ifnet_inited
= 0;
128 int dlil_initialized
= 0;
129 decl_simple_lock_data(, dlil_input_lock
)
130 int dlil_input_thread_wakeup
= 0;
132 static struct mbuf
*dlil_input_mbuf_head
= NULL
;
133 static struct mbuf
*dlil_input_mbuf_tail
= NULL
;
134 static struct mbuf
*dlil_input_loop_head
= NULL
;
135 static struct mbuf
*dlil_input_loop_tail
= NULL
;
137 static void dlil_input_thread(void);
138 extern void run_netisr(void);
142 * Internal functions.
146 struct if_family_str
*find_family_module(u_long if_family
)
148 struct if_family_str
*mod
= NULL
;
150 TAILQ_FOREACH(mod
, &if_family_head
, if_fam_next
) {
151 if (mod
->if_family
== (if_family
& 0xffff))
163 struct ifnet
*ifbyfamily(u_long family
, short unit
)
167 TAILQ_FOREACH(ifp
, &ifnet
, if_link
)
168 if ((family
== ifp
->if_family
) &&
169 (ifp
->if_unit
== unit
))
175 struct if_proto
*dlttoproto(dl_tag
)
178 return dl_tag_array
[dl_tag
].proto
;
182 static int dlil_ifp_proto_count(struct ifnet
* ifp
)
185 struct if_proto
* proto
;
186 struct dlil_proto_head
* tmp
;
188 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
190 TAILQ_FOREACH(proto
, tmp
, next
)
196 u_long
ifptodlt(struct ifnet
*ifp
, u_long proto_family
)
198 struct if_proto
*proto
;
199 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
202 TAILQ_FOREACH(proto
, tmp
, next
)
203 if (proto
->protocol_family
== proto_family
)
204 return proto
->dl_tag
;
210 int dlil_find_dltag(u_long if_family
, short unit
, u_long proto_family
, u_long
*dl_tag
)
214 ifp
= ifbyfamily(if_family
, unit
);
218 *dl_tag
= ifptodlt(ifp
, proto_family
);
220 return EPROTONOSUPPORT
;
226 int dlil_get_next_dl_tag(u_long current_tag
, struct dl_tag_attr_str
*next
)
230 for (i
= (current_tag
+1); i
< MAX_DL_TAGS
; i
++)
231 if (dl_tag_array
[i
].ifp
) {
233 next
->if_flags
= dl_tag_array
[i
].ifp
->if_flags
;
234 next
->if_unit
= dl_tag_array
[i
].ifp
->if_unit
;
235 next
->protocol_family
= dl_tag_array
[i
].proto
->protocol_family
;
236 next
->if_family
= dl_tag_array
[i
].ifp
->if_family
;
241 * If we got here, there are no more entries
247 void dlil_post_msg(struct ifnet
*ifp
, u_long event_subclass
, u_long event_code
,
248 struct net_event_data
*event_data
, u_long event_data_len
)
250 struct net_event_data ev_data
;
251 struct kev_msg ev_msg
;
254 * a net event always start with a net_event_data structure
255 * but the caller can generate a simple net event or
256 * provide a longer event structure to post
259 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
260 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
261 ev_msg
.kev_subclass
= event_subclass
;
262 ev_msg
.event_code
= event_code
;
264 if (event_data
== 0) {
265 event_data
= &ev_data
;
266 event_data_len
= sizeof(struct net_event_data
);
269 strncpy(&event_data
->if_name
[0], ifp
->if_name
, IFNAMSIZ
);
270 event_data
->if_family
= ifp
->if_family
;
271 event_data
->if_unit
= (unsigned long) ifp
->if_unit
;
273 ev_msg
.dv
[0].data_length
= event_data_len
;
274 ev_msg
.dv
[0].data_ptr
= event_data
;
275 ev_msg
.dv
[1].data_length
= 0;
277 kev_post_msg(&ev_msg
);
287 printf("dlil_init\n");
289 TAILQ_INIT(&if_family_head
);
290 for (i
=0; i
< MAX_DL_TAGS
; i
++)
291 dl_tag_array
[i
].ifp
= 0;
293 for (i
=0; i
< MAX_DLIL_FILTERS
; i
++)
294 dlil_filters
[i
].type
= 0;
296 bzero(&dlil_stats
, sizeof(dlil_stats
));
298 simple_lock_init(&dlil_input_lock
);
301 * Start up the dlil input thread once everything is initialized
303 (void) kernel_thread(kernel_task
, dlil_input_thread
);
307 u_long
get_new_filter_id()
311 for (i
=1; i
< MAX_DLIL_FILTERS
; i
++)
312 if (dlil_filters
[i
].type
== 0)
319 int dlil_attach_interface_filter(struct ifnet
*ifp
,
320 struct dlil_if_flt_str
*if_filter
,
326 struct dlil_filterq_entry
*tmp_ptr
;
327 struct dlil_filterq_entry
*if_filt
;
328 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
329 boolean_t funnel_state
;
332 MALLOC(tmp_ptr
, struct dlil_filterq_entry
*, sizeof(*tmp_ptr
), M_NKE
, M_WAITOK
);
336 bcopy((caddr_t
) if_filter
, (caddr_t
) &tmp_ptr
->variants
.if_filter
,
337 sizeof(struct dlil_if_flt_str
));
339 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
343 if (insertion_point
!= DLIL_LAST_FILTER
) {
344 TAILQ_FOREACH(if_filt
, fhead
, que
)
345 if (insertion_point
== if_filt
->filter_id
) {
346 TAILQ_INSERT_BEFORE(if_filt
, tmp_ptr
, que
);
351 TAILQ_INSERT_TAIL(fhead
, tmp_ptr
, que
);
353 if (*filter_id
= get_new_filter_id()) {
354 dlil_filters
[*filter_id
].filter_ptr
= tmp_ptr
;
355 dlil_filters
[*filter_id
].head
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
356 dlil_filters
[*filter_id
].type
= DLIL_IF_FILTER
;
357 dlil_filters
[*filter_id
].ifp
= ifp
;
358 tmp_ptr
->filter_id
= *filter_id
;
359 tmp_ptr
->type
= DLIL_IF_FILTER
;
363 kprintf("dlil_attach_interface_filter - can't alloc filter_id\n");
364 TAILQ_REMOVE(fhead
, tmp_ptr
, que
);
365 FREE(tmp_ptr
, M_NKE
);
370 thread_funnel_set(network_flock
, funnel_state
);
375 int dlil_attach_protocol_filter(u_long dl_tag
,
376 struct dlil_pr_flt_str
*pr_filter
,
380 struct dlil_filterq_entry
*tmp_ptr
;
381 struct dlil_filterq_entry
*pr_filt
;
384 boolean_t funnel_state
;
386 if (dl_tag
> MAX_DL_TAGS
)
389 if (dl_tag_array
[dl_tag
].ifp
== 0)
392 MALLOC(tmp_ptr
, struct dlil_filterq_entry
*, sizeof(*tmp_ptr
), M_NKE
, M_WAITOK
);
396 bcopy((caddr_t
) pr_filter
, (caddr_t
) &tmp_ptr
->variants
.pr_filter
,
397 sizeof(struct dlil_pr_flt_str
));
399 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
402 if (insertion_point
!= DLIL_LAST_FILTER
) {
403 TAILQ_FOREACH(pr_filt
, dl_tag_array
[dl_tag
].pr_flt_head
, que
)
404 if (insertion_point
== pr_filt
->filter_id
) {
405 TAILQ_INSERT_BEFORE(pr_filt
, tmp_ptr
, que
);
410 TAILQ_INSERT_TAIL(dl_tag_array
[dl_tag
].pr_flt_head
, tmp_ptr
, que
);
413 if (*filter_id
= get_new_filter_id()) {
414 dlil_filters
[*filter_id
].filter_ptr
= tmp_ptr
;
415 dlil_filters
[*filter_id
].head
= dl_tag_array
[dl_tag
].pr_flt_head
;
416 dlil_filters
[*filter_id
].type
= DLIL_PR_FILTER
;
417 dlil_filters
[*filter_id
].proto
= dl_tag_array
[dl_tag
].proto
;
418 dlil_filters
[*filter_id
].ifp
= dl_tag_array
[dl_tag
].ifp
;
419 tmp_ptr
->filter_id
= *filter_id
;
420 tmp_ptr
->type
= DLIL_PR_FILTER
;
424 kprintf("dlil_attach_protocol_filter - can't alloc filter_id\n");
425 TAILQ_REMOVE(dl_tag_array
[dl_tag
].pr_flt_head
, tmp_ptr
, que
);
426 FREE(tmp_ptr
, M_NKE
);
431 thread_funnel_set(network_flock
, funnel_state
);
437 dlil_detach_filter(u_long filter_id
)
439 struct dlil_filter_id_str
*flt
;
441 boolean_t funnel_state
;
443 if (filter_id
> MAX_DLIL_FILTERS
) {
444 kprintf("dlil_detach_filter - Bad filter_id value %d\n", filter_id
);
448 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
450 flt
= &dlil_filters
[filter_id
];
451 if (flt
->type
== 0) {
452 kprintf("dlil_detach_filter - no such filter_id %d\n", filter_id
);
453 thread_funnel_set(network_flock
, funnel_state
);
458 if (flt
->type
== DLIL_IF_FILTER
) {
459 if (IFILT(flt
->filter_ptr
).filter_detach
)
460 (*IFILT(flt
->filter_ptr
).filter_detach
)(IFILT(flt
->filter_ptr
).cookie
);
463 if (flt
->type
== DLIL_PR_FILTER
) {
464 if (PFILT(flt
->filter_ptr
).filter_detach
)
465 (*PFILT(flt
->filter_ptr
).filter_detach
)(PFILT(flt
->filter_ptr
).cookie
);
469 TAILQ_REMOVE(flt
->head
, flt
->filter_ptr
, que
);
470 FREE(flt
->filter_ptr
, M_NKE
);
473 thread_funnel_set(network_flock
, funnel_state
);
479 dlil_input_thread_continue(void)
482 struct mbuf
*m
, *m_loop
;
485 usimple_lock(&dlil_input_lock
);
486 m
= dlil_input_mbuf_head
;
487 dlil_input_mbuf_head
= NULL
;
488 dlil_input_mbuf_tail
= NULL
;
489 m_loop
= dlil_input_loop_head
;
490 dlil_input_loop_head
= NULL
;
491 dlil_input_loop_tail
= NULL
;
492 usimple_unlock(&dlil_input_lock
);
495 expand_mcl
= dlil_expand_mcl
;
505 * NOTE warning %%% attention !!!!
506 * We should think about putting some thread starvation safeguards if
507 * we deal with long chains of packets.
510 struct mbuf
*m0
= m
->m_nextpkt
;
511 void *header
= m
->m_pkthdr
.header
;
514 m
->m_pkthdr
.header
= NULL
;
515 (void) dlil_input_packet(m
->m_pkthdr
.rcvif
, m
, header
);
520 struct mbuf
*m0
= m
->m_nextpkt
;
521 void *header
= m
->m_pkthdr
.header
;
522 struct ifnet
*ifp
= (struct ifnet
*) m
->m_pkthdr
.aux
;
525 m
->m_pkthdr
.header
= NULL
;
526 m
->m_pkthdr
.aux
= NULL
;
527 (void) dlil_input_packet(ifp
, m
, header
);
534 if (dlil_input_mbuf_head
== NULL
&&
535 dlil_input_loop_head
== NULL
&&
537 assert_wait(&dlil_input_thread_wakeup
, THREAD_UNINT
);
538 #if defined (__i386__)
541 thread_block(dlil_input_thread_continue
);
548 void dlil_input_thread(void)
550 register thread_t self
= current_thread();
551 extern void stack_privilege(thread_t thread
);
553 printf("dlil_input_thread %x\n", self
);
556 * Make sure that this thread
557 * always has a kernel stack, and
558 * bind it to the master cpu.
560 stack_privilege(self
);
562 /* The dlil thread is always funneled */
563 thread_funnel_set(network_flock
, TRUE
);
564 dlil_initialized
= 1;
565 dlil_input_thread_continue();
569 dlil_input(struct ifnet
*ifp
, struct mbuf
*m_head
, struct mbuf
*m_tail
)
572 * Because of loopbacked multicast we cannot stuff the ifp in
573 * the rcvif of the packet header: loopback has its own dlil
577 usimple_lock(&dlil_input_lock
);
578 if (ifp
->if_type
!= IFT_LOOP
) {
579 if (dlil_input_mbuf_head
== NULL
)
580 dlil_input_mbuf_head
= m_head
;
581 else if (dlil_input_mbuf_tail
!= NULL
)
582 dlil_input_mbuf_tail
->m_nextpkt
= m_head
;
583 dlil_input_mbuf_tail
= m_tail
? m_tail
: m_head
;
585 if (dlil_input_loop_head
== NULL
)
586 dlil_input_loop_head
= m_head
;
587 else if (dlil_input_loop_tail
!= NULL
)
588 dlil_input_loop_tail
->m_nextpkt
= m_head
;
589 dlil_input_loop_tail
= m_tail
? m_tail
: m_head
;
591 usimple_unlock(&dlil_input_lock
);
593 wakeup((caddr_t
)&dlil_input_thread_wakeup
);
599 dlil_input_packet(struct ifnet
*ifp
, struct mbuf
*m
,
602 struct ifnet
*orig_ifp
= 0;
603 struct dlil_filterq_entry
*tmp
;
605 struct if_proto
*ifproto
= 0;
606 struct if_proto
*proto
;
607 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
610 KERNEL_DEBUG(DBG_FNC_DLIL_INPUT
| DBG_FUNC_START
,0,0,0,0,0);
613 * Run interface filters
616 while (orig_ifp
!= ifp
) {
619 TAILQ_FOREACH_REVERSE(tmp
, fhead
, que
, dlil_filterq_head
) {
620 if (IFILT(tmp
).filter_if_input
) {
621 retval
= (*IFILT(tmp
).filter_if_input
)(IFILT(tmp
).cookie
,
626 if (retval
== EJUSTRETURN
)
640 ifp
->if_lastchange
= time
;
643 * Call family demux module. If the demux module finds a match
644 * for the frame it will fill-in the ifproto pointer.
647 retval
= (*ifp
->if_demux
)(ifp
, m
, frame_header
, &ifproto
);
649 if (m
->m_flags
& (M_BCAST
|M_MCAST
))
652 if ((retval
) && (retval
!= EJUSTRETURN
) && (ifp
->offercnt
)) {
654 * No match was found, look for any offers.
656 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
657 TAILQ_FOREACH(proto
, tmp
, next
) {
658 if ((proto
->dl_offer
) && (proto
->dl_offer(m
, frame_header
) == 0)) {
667 if (retval
!= EJUSTRETURN
) {
676 printf("ERROR - dlil_input - if_demux didn't return an if_proto pointer\n");
682 * Call any attached protocol filters.
685 TAILQ_FOREACH_REVERSE(tmp
, &ifproto
->pr_flt_head
, que
, dlil_filterq_head
) {
686 if (PFILT(tmp
).filter_dl_input
) {
687 retval
= (*PFILT(tmp
).filter_dl_input
)(PFILT(tmp
).cookie
,
693 if (retval
== EJUSTRETURN
)
705 retval
= (*ifproto
->dl_input
)(m
, frame_header
,
706 ifp
, ifproto
->dl_tag
,
709 if (retval
== EJUSTRETURN
)
715 KERNEL_DEBUG(DBG_FNC_DLIL_INPUT
| DBG_FUNC_END
,0,0,0,0,0);
721 void ether_input(ifp
, eh
, m
)
723 struct ether_header
*eh
;
727 kprintf("Someone is calling ether_input!!\n");
729 dlil_input(ifp
, m
, NULL
);
734 dlil_event(struct ifnet
*ifp
, struct kern_event_msg
*event
)
736 struct dlil_filterq_entry
*filt
;
738 struct ifnet
*orig_ifp
= 0;
739 struct if_proto
*proto
;
740 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
741 struct kev_msg kev_msg
;
742 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
743 boolean_t funnel_state
;
746 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
748 while (orig_ifp
!= ifp
) {
751 TAILQ_FOREACH_REVERSE(filt
, fhead
, que
, dlil_filterq_head
) {
752 if (IFILT(filt
).filter_if_event
) {
753 retval
= (*IFILT(filt
).filter_if_event
)(IFILT(filt
).cookie
,
758 (void) thread_funnel_set(network_flock
, funnel_state
);
759 if (retval
== EJUSTRETURN
)
773 * Call Interface Module event hook, if any.
777 retval
= ifp
->if_event(ifp
, (caddr_t
) event
);
780 (void) thread_funnel_set(network_flock
, funnel_state
);
782 if (retval
== EJUSTRETURN
)
790 * Call dl_event entry point for all protocols attached to this interface
793 TAILQ_FOREACH(proto
, tmp
, next
) {
795 * Call any attached protocol filters.
798 TAILQ_FOREACH_REVERSE(filt
, &proto
->pr_flt_head
, que
, dlil_filterq_head
) {
799 if (PFILT(filt
).filter_dl_event
) {
800 retval
= (*PFILT(filt
).filter_dl_event
)(PFILT(filt
).cookie
,
804 (void) thread_funnel_set(network_flock
, funnel_state
);
805 if (retval
== EJUSTRETURN
)
815 * Finally, call the dl_event entry point (if any)
819 retval
= (*proto
->dl_event
)(event
, proto
->dl_tag
);
821 if (retval
== EJUSTRETURN
) {
822 (void) thread_funnel_set(network_flock
, funnel_state
);
829 * Now, post this event to the Kernel Event message queue
832 kev_msg
.vendor_code
= event
->vendor_code
;
833 kev_msg
.kev_class
= event
->kev_class
;
834 kev_msg
.kev_subclass
= event
->kev_subclass
;
835 kev_msg
.event_code
= event
->event_code
;
836 kev_msg
.dv
[0].data_ptr
= &event
->event_data
[0];
837 kev_msg
.dv
[0].data_length
= event
->total_size
- KEV_MSG_HEADER_SIZE
;
838 kev_msg
.dv
[1].data_length
= 0;
840 kev_post_msg(&kev_msg
);
842 (void) thread_funnel_set(network_flock
, funnel_state
);
849 dlil_output(u_long dl_tag
,
852 struct sockaddr
*dest
,
858 struct ifnet
*orig_ifp
= 0;
860 struct if_proto
*proto
;
861 struct dlil_filterq_entry
*tmp
;
863 char frame_type_buffer
[MAX_FRAME_TYPE_SIZE
* 4];
864 char dst_linkaddr_buffer
[MAX_LINKADDR
* 4];
865 struct dlil_filterq_head
*fhead
;
868 KERNEL_DEBUG(DBG_FNC_DLIL_OUTPUT
| DBG_FUNC_START
,0,0,0,0,0);
871 * Temporary hackery until all the existing protocols can become fully
872 * "dl_tag aware". Some things only have the ifp, so this handles that
873 * case for the time being.
876 if (dl_tag
> MAX_DL_TAGS
) {
877 /* dl_tag is really an ifnet pointer! */
879 ifp
= (struct ifnet
*) dl_tag
;
880 dl_tag
= ifp
->if_data
.default_proto
;
882 proto
= dl_tag_array
[dl_tag
].proto
;
887 if ((dl_tag
== 0) || (dl_tag_array
[dl_tag
].ifp
== 0))
890 ifp
= dl_tag_array
[dl_tag
].ifp
;
891 proto
= dl_tag_array
[dl_tag
].proto
;
900 frame_type
= frame_type_buffer
;
901 dst_linkaddr
= dst_linkaddr_buffer
;
903 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
905 if ((raw
== 0) && (proto
->dl_pre_output
)) {
906 retval
= (*proto
->dl_pre_output
)(ifp
, &m
, dest
, route
,
907 frame_type
, dst_linkaddr
, dl_tag
);
909 if (retval
== EJUSTRETURN
)
919 * Run any attached protocol filters.
922 if (TAILQ_EMPTY(dl_tag_array
[dl_tag
].pr_flt_head
) == 0) {
923 TAILQ_FOREACH(tmp
, dl_tag_array
[dl_tag
].pr_flt_head
, que
) {
924 if (PFILT(tmp
).filter_dl_output
) {
925 retval
= (*PFILT(tmp
).filter_dl_output
)(PFILT(tmp
).cookie
,
926 &m
, &ifp
, &dest
, dst_linkaddr
, frame_type
);
928 if (retval
== EJUSTRETURN
)
941 * Call framing module
943 if ((raw
== 0) && (ifp
->if_framer
)) {
944 retval
= (*ifp
->if_framer
)(ifp
, &m
, dest
, dst_linkaddr
, frame_type
);
946 if (retval
== EJUSTRETURN
)
958 struct mbuf
*m0
= m
;
960 if (m
->m_pkthdr
.rcvif
)
961 m
->m_pkthdr
.rcvif
= NULL
;
962 ifp
= bridge_dst_lookup(m
);
963 bdg_forward(&m0
, ifp
);
973 * Let interface filters (if any) do their thing ...
976 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
977 if (TAILQ_EMPTY(fhead
) == 0) {
978 while (orig_ifp
!= ifp
) {
980 TAILQ_FOREACH(tmp
, fhead
, que
) {
981 if (IFILT(tmp
).filter_if_output
) {
982 retval
= (*IFILT(tmp
).filter_if_output
)(IFILT(tmp
).cookie
,
986 if (retval
== EJUSTRETURN
)
1003 * Finally, call the driver.
1006 KERNEL_DEBUG(DBG_FNC_DLIL_IFOUT
| DBG_FUNC_START
, 0,0,0,0,0);
1007 retval
= (*ifp
->if_output
)(ifp
, m
);
1008 KERNEL_DEBUG(DBG_FNC_DLIL_IFOUT
| DBG_FUNC_END
, 0,0,0,0,0);
1010 KERNEL_DEBUG(DBG_FNC_DLIL_OUTPUT
| DBG_FUNC_END
,0,0,0,0,0);
1012 if ((retval
== 0) || (retval
== EJUSTRETURN
))
1020 dlil_ioctl(u_long proto_fam
,
1025 struct dlil_filterq_entry
*tmp
;
1026 struct dlil_filterq_head
*fhead
;
1027 int retval
= EOPNOTSUPP
;
1028 int retval2
= EOPNOTSUPP
;
1030 struct if_family_str
*if_family
;
1034 retval
= dlil_find_dltag(ifp
->if_family
, ifp
->if_unit
,
1035 proto_fam
, &dl_tag
);
1038 if (dl_tag_array
[dl_tag
].ifp
!= ifp
)
1042 * Run any attached protocol filters.
1044 TAILQ_FOREACH(tmp
, dl_tag_array
[dl_tag
].pr_flt_head
, que
) {
1045 if (PFILT(tmp
).filter_dl_ioctl
) {
1047 (*PFILT(tmp
).filter_dl_ioctl
)(PFILT(tmp
).cookie
,
1048 dl_tag_array
[dl_tag
].ifp
,
1053 if (retval
== EJUSTRETURN
)
1061 if (dl_tag_array
[dl_tag
].proto
->dl_ioctl
)
1063 (*dl_tag_array
[dl_tag
].proto
->dl_ioctl
)(dl_tag
,
1064 dl_tag_array
[dl_tag
].ifp
,
1068 retval
= EOPNOTSUPP
;
1074 if ((retval
) && (retval
!= EOPNOTSUPP
)) {
1075 if (retval
== EJUSTRETURN
)
1082 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1083 TAILQ_FOREACH(tmp
, fhead
, que
) {
1084 if (IFILT(tmp
).filter_if_ioctl
) {
1085 retval2
= (*IFILT(tmp
).filter_if_ioctl
)(IFILT(tmp
).cookie
, ifp
,
1086 ioctl_code
, ioctl_arg
);
1088 if (retval2
== EJUSTRETURN
)
1097 if_family
= find_family_module(ifp
->if_family
);
1098 if ((if_family
) && (if_family
->ifmod_ioctl
)) {
1099 retval2
= (*if_family
->ifmod_ioctl
)(ifp
, ioctl_code
, ioctl_arg
);
1101 if ((retval2
) && (retval2
!= EOPNOTSUPP
)) {
1102 if (retval2
== EJUSTRETURN
)
1108 if (retval
== EOPNOTSUPP
)
1113 retval2
= (*ifp
->if_ioctl
)(ifp
, ioctl_code
, ioctl_arg
);
1115 if (retval
== EOPNOTSUPP
)
1118 if (retval2
== EOPNOTSUPP
)
1127 dlil_attach_protocol(struct dlil_proto_reg_str
*proto
,
1131 struct if_proto
*ifproto
;
1133 struct if_family_str
*if_family
;
1135 struct dlil_proto_head
*tmp
;
1136 struct kev_dl_proto_data ev_pr_data
;
1138 boolean_t funnel_state
;
1141 if ((proto
->protocol_family
== 0) || (proto
->interface_family
== 0))
1144 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1146 if_family
= find_family_module(proto
->interface_family
);
1147 if ((!if_family
) || (if_family
->flags
& DLIL_SHUTDOWN
)) {
1148 kprintf("dlil_attach_protocol -- no interface family module %d",
1149 proto
->interface_family
);
1151 thread_funnel_set(network_flock
, funnel_state
);
1155 ifp
= ifbyfamily(proto
->interface_family
, proto
->unit_number
);
1157 kprintf("dlil_attach_protocol -- no such interface %d unit %d\n",
1158 proto
->interface_family
, proto
->unit_number
);
1160 thread_funnel_set(network_flock
, funnel_state
);
1164 if (dlil_find_dltag(proto
->interface_family
, proto
->unit_number
,
1165 proto
->protocol_family
, &i
) == 0) {
1166 thread_funnel_set(network_flock
, funnel_state
);
1170 for (i
=1; i
< MAX_DL_TAGS
; i
++)
1171 if (dl_tag_array
[i
].ifp
== 0)
1174 if (i
>= MAX_DL_TAGS
) {
1176 thread_funnel_set(network_flock
, funnel_state
);
1181 * Allocate and init a new if_proto structure
1184 ifproto
= _MALLOC(sizeof(struct if_proto
), M_IFADDR
, M_WAITOK
);
1186 printf("ERROR - DLIL failed if_proto allocation\n");
1187 thread_funnel_set(network_flock
, funnel_state
);
1191 bzero(ifproto
, sizeof(struct if_proto
));
1193 dl_tag_array
[i
].ifp
= ifp
;
1194 dl_tag_array
[i
].proto
= ifproto
;
1195 dl_tag_array
[i
].pr_flt_head
= &ifproto
->pr_flt_head
;
1196 ifproto
->dl_tag
= i
;
1199 if (proto
->default_proto
) {
1200 if (ifp
->if_data
.default_proto
== 0)
1201 ifp
->if_data
.default_proto
= i
;
1203 printf("ERROR - dlil_attach_protocol -- Attempt to attach more than one default protocol\n");
1206 ifproto
->protocol_family
= proto
->protocol_family
;
1207 ifproto
->dl_input
= proto
->input
;
1208 ifproto
->dl_pre_output
= proto
->pre_output
;
1209 ifproto
->dl_event
= proto
->event
;
1210 ifproto
->dl_offer
= proto
->offer
;
1211 ifproto
->dl_ioctl
= proto
->ioctl
;
1213 TAILQ_INIT(&ifproto
->pr_flt_head
);
1216 * Call family module add_proto routine so it can refine the
1217 * demux descriptors as it wishes.
1219 error
= (*if_family
->add_proto
)(&proto
->demux_desc_head
, ifproto
, *dl_tag
);
1221 dl_tag_array
[*dl_tag
].ifp
= 0;
1222 FREE(ifproto
, M_IFADDR
);
1224 thread_funnel_set(network_flock
, funnel_state
);
1229 * Add to if_proto list for this interface
1232 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1233 TAILQ_INSERT_TAIL(tmp
, ifproto
, next
);
1235 if (ifproto
->dl_offer
)
1238 /* the reserved field carries the number of protocol still attached (subject to change) */
1239 ev_pr_data
.proto_family
= proto
->protocol_family
;
1240 ev_pr_data
.proto_remaining_count
= dlil_ifp_proto_count(ifp
);
1241 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_PROTO_ATTACHED
,
1242 (struct net_event_data
*)&ev_pr_data
,
1243 sizeof(struct kev_dl_proto_data
));
1246 thread_funnel_set(network_flock
, funnel_state
);
1253 dlil_detach_protocol(u_long dl_tag
)
1256 struct ifnet
*orig_ifp
=0;
1257 struct if_proto
*proto
;
1258 struct dlil_proto_head
*tmp
;
1259 struct if_family_str
*if_family
;
1260 struct dlil_filterq_entry
*filter
;
1262 struct dlil_filterq_head
*fhead
;
1263 struct kev_dl_proto_data ev_pr_data
;
1264 boolean_t funnel_state
;
1267 if (dl_tag
> MAX_DL_TAGS
)
1270 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1273 if (dl_tag_array
[dl_tag
].ifp
== 0) {
1275 thread_funnel_set(network_flock
, funnel_state
);
1279 ifp
= dl_tag_array
[dl_tag
].ifp
;
1280 proto
= dl_tag_array
[dl_tag
].proto
;
1282 if_family
= find_family_module(ifp
->if_family
);
1283 if (if_family
== NULL
) {
1285 thread_funnel_set(network_flock
, funnel_state
);
1289 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1292 * Call family module del_proto
1295 (*if_family
->del_proto
)(proto
, dl_tag
);
1299 * Remove and deallocate any attached protocol filters
1302 while (filter
= TAILQ_FIRST(&proto
->pr_flt_head
))
1303 dlil_detach_filter(filter
->filter_id
);
1305 if (proto
->dl_offer
)
1308 if (ifp
->if_data
.default_proto
== dl_tag
)
1309 ifp
->if_data
.default_proto
= 0;
1310 dl_tag_array
[dl_tag
].ifp
= 0;
1312 /* the reserved field carries the number of protocol still attached (subject to change) */
1313 ev_pr_data
.proto_family
= proto
->protocol_family
;
1314 TAILQ_REMOVE(tmp
, proto
, next
);
1315 FREE(proto
, M_IFADDR
);
1318 ev_pr_data
.proto_remaining_count
= dlil_ifp_proto_count(ifp
);
1319 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_PROTO_DETACHED
,
1320 (struct net_event_data
*)&ev_pr_data
,
1321 sizeof(struct kev_dl_proto_data
));
1323 if (ifp
->refcnt
== 0 && (ifp
->if_eflags
& IFEF_DETACH_DISABLED
) == 0) {
1324 if (ifp
->if_flags
& IFF_UP
)
1325 printf("WARNING - dlil_detach_protocol - ifp refcnt 0, but IF still up\n");
1327 TAILQ_REMOVE(&ifnet
, ifp
, if_link
);
1329 (*if_family
->del_if
)(ifp
);
1331 if (--if_family
->refcnt
== 0) {
1332 if (if_family
->shutdown
)
1333 (*if_family
->shutdown
)();
1335 TAILQ_REMOVE(&if_family_head
, if_family
, if_fam_next
);
1336 FREE(if_family
, M_IFADDR
);
1339 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1340 while (orig_ifp
!= ifp
) {
1343 TAILQ_FOREACH(filter
, fhead
, que
) {
1344 if (IFILT(filter
).filter_if_free
) {
1345 retval
= (*IFILT(filter
).filter_if_free
)(IFILT(filter
).cookie
, ifp
);
1348 thread_funnel_set(network_flock
, funnel_state
);
1352 if (ifp
!= orig_ifp
)
1357 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_DETACHED
, 0, 0);
1359 (*ifp
->if_free
)(ifp
);
1363 thread_funnel_set(network_flock
, funnel_state
);
1372 dlil_if_attach(struct ifnet
*ifp
)
1374 u_long interface_family
= ifp
->if_family
;
1375 struct if_family_str
*if_family
;
1376 struct dlil_proto_head
*tmp
;
1379 boolean_t funnel_state
;
1381 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1383 if (ifnet_inited
== 0) {
1388 if_family
= find_family_module(interface_family
);
1390 if ((!if_family
) || (if_family
->flags
& DLIL_SHUTDOWN
)) {
1392 kprintf("Attempt to attach interface without family module - %d\n",
1394 thread_funnel_set(network_flock
, funnel_state
);
1400 * Call the family module to fill in the appropriate fields in the
1404 stat
= (*if_family
->add_if
)(ifp
);
1407 kprintf("dlil_if_attach -- add_if failed with %d\n", stat
);
1408 thread_funnel_set(network_flock
, funnel_state
);
1413 * Add the ifp to the interface list.
1416 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1419 ifp
->if_data
.default_proto
= 0;
1422 TAILQ_INIT(&ifp
->if_flt_head
);
1424 if_family
->refcnt
++;
1426 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_ATTACHED
, 0, 0);
1429 thread_funnel_set(network_flock
, funnel_state
);
1435 dlil_if_detach(struct ifnet
*ifp
)
1437 struct if_proto
*proto
;
1438 struct dlil_filterq_entry
*if_filter
;
1439 struct if_family_str
*if_family
;
1440 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1442 struct kev_msg ev_msg
;
1443 boolean_t funnel_state
;
1445 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1447 if (ifp
->if_flags
& IFF_UP
)
1448 printf("WARNING - dlil_if_detach called for UP interface\n");
1450 if_family
= find_family_module(ifp
->if_family
);
1453 kprintf("Attempt to detach interface without family module - %s\n",
1456 thread_funnel_set(network_flock
, funnel_state
);
1460 while (if_filter
= TAILQ_FIRST(fhead
))
1461 dlil_detach_filter(if_filter
->filter_id
);
1465 if (ifp
->refcnt
== 0 && (ifp
->if_eflags
& IFEF_DETACH_DISABLED
) == 0) {
1466 TAILQ_REMOVE(&ifnet
, ifp
, if_link
);
1468 (*if_family
->del_if
)(ifp
);
1470 if (--if_family
->refcnt
== 0) {
1471 if (if_family
->shutdown
)
1472 (*if_family
->shutdown
)();
1474 TAILQ_REMOVE(&if_family_head
, if_family
, if_fam_next
);
1475 FREE(if_family
, M_IFADDR
);
1478 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_DETACHED
, 0, 0);
1480 thread_funnel_set(network_flock
, funnel_state
);
1485 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_DETACHING
, 0, 0);
1487 thread_funnel_set(network_flock
, funnel_state
);
1488 return DLIL_WAIT_FOR_FREE
;
1494 dlil_reg_if_modules(u_long interface_family
,
1495 struct dlil_ifmod_reg_str
*ifmod
)
1497 struct if_family_str
*if_family
;
1499 boolean_t funnel_state
;
1502 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1504 if (find_family_module(interface_family
)) {
1505 kprintf("Attempt to register dlil family module more than once - %d\n",
1508 thread_funnel_set(network_flock
, funnel_state
);
1512 if ((!ifmod
->add_if
) || (!ifmod
->del_if
) ||
1513 (!ifmod
->add_proto
) || (!ifmod
->del_proto
)) {
1514 kprintf("dlil_reg_if_modules passed at least one null pointer\n");
1516 thread_funnel_set(network_flock
, funnel_state
);
1520 if_family
= (struct if_family_str
*) _MALLOC(sizeof(struct if_family_str
), M_IFADDR
, M_WAITOK
);
1522 kprintf("dlil_reg_if_modules failed allocation\n");
1524 thread_funnel_set(network_flock
, funnel_state
);
1528 bzero(if_family
, sizeof(struct if_family_str
));
1530 if_family
->if_family
= interface_family
& 0xffff;
1531 if_family
->shutdown
= ifmod
->shutdown
;
1532 if_family
->add_if
= ifmod
->add_if
;
1533 if_family
->del_if
= ifmod
->del_if
;
1534 if_family
->add_proto
= ifmod
->add_proto
;
1535 if_family
->del_proto
= ifmod
->del_proto
;
1536 if_family
->ifmod_ioctl
= ifmod
->ifmod_ioctl
;
1537 if_family
->refcnt
= 1;
1538 if_family
->flags
= 0;
1540 TAILQ_INSERT_TAIL(&if_family_head
, if_family
, if_fam_next
);
1542 thread_funnel_set(network_flock
, funnel_state
);
1546 int dlil_dereg_if_modules(u_long interface_family
)
1548 struct if_family_str
*if_family
;
1550 boolean_t funnel_state
;
1552 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1554 if_family
= find_family_module(interface_family
);
1555 if (if_family
== 0) {
1557 thread_funnel_set(network_flock
, funnel_state
);
1561 if (--if_family
->refcnt
== 0) {
1562 if (if_family
->shutdown
)
1563 (*if_family
->shutdown
)();
1565 TAILQ_REMOVE(&if_family_head
, if_family
, if_fam_next
);
1566 FREE(if_family
, M_IFADDR
);
1569 if_family
->flags
|= DLIL_SHUTDOWN
;
1572 thread_funnel_set(network_flock
, funnel_state
);
1581 * Old if_attach no-op'ed function defined here for temporary backwards compatibility
1587 dlil_if_attach(ifp
);
1593 dlil_inject_if_input(struct mbuf
*m
, char *frame_header
, u_long from_id
)
1595 struct ifnet
*orig_ifp
= 0;
1597 struct if_proto
*ifproto
;
1598 struct if_proto
*proto
;
1599 struct dlil_filterq_entry
*tmp
;
1601 struct dlil_filterq_head
*fhead
;
1605 dlil_stats
.inject_if_in1
++;
1606 if (from_id
> MAX_DLIL_FILTERS
)
1609 if (dlil_filters
[from_id
].type
!= DLIL_IF_FILTER
)
1612 ifp
= dlil_filters
[from_id
].ifp
;
1615 * Let interface filters (if any) do their thing ...
1618 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1621 if (TAILQ_EMPTY(fhead
) == 0) {
1622 while (orig_ifp
!= ifp
) {
1624 TAILQ_FOREACH_REVERSE(tmp
, fhead
, que
, dlil_filterq_head
) {
1625 if ((match_found
) && (IFILT(tmp
).filter_if_input
)) {
1626 retval
= (*IFILT(tmp
).filter_if_input
)(IFILT(tmp
).cookie
,
1631 if (retval
== EJUSTRETURN
)
1641 if (ifp
!= orig_ifp
)
1644 if (from_id
== tmp
->filter_id
)
1650 ifp
->if_lastchange
= time
;
1653 * Call family demux module. If the demux module finds a match
1654 * for the frame it will fill-in the ifproto pointer.
1657 retval
= (*ifp
->if_demux
)(ifp
, m
, frame_header
, &ifproto
);
1659 if (m
->m_flags
& (M_BCAST
|M_MCAST
))
1662 if ((retval
) && (ifp
->offercnt
)) {
1664 * No match was found, look for any offers.
1666 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1667 TAILQ_FOREACH(proto
, tmp
, next
) {
1668 if ((proto
->dl_offer
) && (proto
->dl_offer(m
, frame_header
) == 0)) {
1677 if (retval
!= EJUSTRETURN
) {
1686 printf("ERROR - dlil_inject_if_input -- if_demux didn't return an if_proto pointer\n");
1692 * Call any attached protocol filters.
1694 TAILQ_FOREACH_REVERSE(tmp
, &ifproto
->pr_flt_head
, que
, dlil_filterq_head
) {
1695 if (PFILT(tmp
).filter_dl_input
) {
1696 retval
= (*PFILT(tmp
).filter_dl_input
)(PFILT(tmp
).cookie
,
1702 if (retval
== EJUSTRETURN
)
1714 retval
= (*ifproto
->dl_input
)(m
, frame_header
,
1715 ifp
, ifproto
->dl_tag
,
1718 dlil_stats
.inject_if_in2
++;
1719 if (retval
== EJUSTRETURN
)
1734 dlil_inject_pr_input(struct mbuf
*m
, char *frame_header
, u_long from_id
)
1736 struct ifnet
*orig_ifp
= 0;
1737 struct dlil_filterq_entry
*tmp
;
1739 struct if_proto
*ifproto
= 0;
1744 dlil_stats
.inject_pr_in1
++;
1745 if (from_id
> MAX_DLIL_FILTERS
)
1748 if (dlil_filters
[from_id
].type
!= DLIL_PR_FILTER
)
1751 ifproto
= dlil_filters
[from_id
].proto
;
1752 ifp
= dlil_filters
[from_id
].ifp
;
1756 * Call any attached protocol filters.
1760 TAILQ_FOREACH_REVERSE(tmp
, &ifproto
->pr_flt_head
, que
, dlil_filterq_head
) {
1761 if ((match_found
) && (PFILT(tmp
).filter_dl_input
)) {
1762 retval
= (*PFILT(tmp
).filter_dl_input
)(PFILT(tmp
).cookie
,
1768 if (retval
== EJUSTRETURN
)
1777 if (tmp
->filter_id
== from_id
)
1782 retval
= (*ifproto
->dl_input
)(m
, frame_header
,
1783 ifp
, ifproto
->dl_tag
,
1786 if (retval
== EJUSTRETURN
)
1792 dlil_stats
.inject_pr_in2
++;
1799 dlil_inject_pr_output(struct mbuf
*m
,
1800 struct sockaddr
*dest
,
1806 struct ifnet
*orig_ifp
= 0;
1808 struct dlil_filterq_entry
*tmp
;
1810 char frame_type_buffer
[MAX_FRAME_TYPE_SIZE
* 4];
1811 char dst_linkaddr_buffer
[MAX_LINKADDR
* 4];
1812 struct dlil_filterq_head
*fhead
;
1817 dlil_stats
.inject_pr_out1
++;
1820 bcopy(frame_type
, &frame_type_buffer
[0], MAX_FRAME_TYPE_SIZE
* 4);
1825 bcopy(dst_linkaddr
, &dst_linkaddr_buffer
, MAX_LINKADDR
* 4);
1830 if (from_id
> MAX_DLIL_FILTERS
)
1833 if (dlil_filters
[from_id
].type
!= DLIL_PR_FILTER
)
1836 ifp
= dlil_filters
[from_id
].ifp
;
1837 dl_tag
= dlil_filters
[from_id
].proto
->dl_tag
;
1840 frame_type
= frame_type_buffer
;
1841 dst_linkaddr
= dst_linkaddr_buffer
;
1843 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1846 * Run any attached protocol filters.
1850 if (TAILQ_EMPTY(dl_tag_array
[dl_tag
].pr_flt_head
) == 0) {
1851 TAILQ_FOREACH(tmp
, dl_tag_array
[dl_tag
].pr_flt_head
, que
) {
1852 if ((match_found
) && (PFILT(tmp
).filter_dl_output
)) {
1853 retval
= (*PFILT(tmp
).filter_dl_output
)(PFILT(tmp
).cookie
,
1854 &m
, &ifp
, &dest
, dst_linkaddr
, frame_type
);
1856 if (retval
== EJUSTRETURN
)
1865 if (tmp
->filter_id
== from_id
)
1872 * Call framing module
1874 if ((raw
== 0) && (ifp
->if_framer
)) {
1875 retval
= (*ifp
->if_framer
)(ifp
, &m
, dest
, dst_linkaddr
, frame_type
);
1877 if (retval
== EJUSTRETURN
)
1890 struct mbuf
*m0
= m
;
1892 if (m
->m_pkthdr
.rcvif
)
1893 m
->m_pkthdr
.rcvif
= NULL
;
1894 ifp
= bridge_dst_lookup(m
);
1895 bdg_forward(&m0
, ifp
);
1905 * Let interface filters (if any) do their thing ...
1908 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1909 if (TAILQ_EMPTY(fhead
) == 0) {
1910 while (orig_ifp
!= ifp
) {
1912 TAILQ_FOREACH(tmp
, fhead
, que
) {
1913 if (IFILT(tmp
).filter_if_output
) {
1914 retval
= (*IFILT(tmp
).filter_if_output
)(IFILT(tmp
).cookie
,
1918 if (retval
== EJUSTRETURN
)
1928 if (ifp
!= orig_ifp
)
1935 * Finally, call the driver.
1938 retval
= (*ifp
->if_output
)(ifp
, m
);
1939 dlil_stats
.inject_pr_out2
++;
1940 if ((retval
== 0) || (retval
== EJUSTRETURN
))
1948 dlil_inject_if_output(struct mbuf
*m
, u_long from_id
)
1950 struct ifnet
*orig_ifp
= 0;
1952 struct dlil_filterq_entry
*tmp
;
1954 struct dlil_filterq_head
*fhead
;
1958 dlil_stats
.inject_if_out1
++;
1959 if (from_id
> MAX_DLIL_FILTERS
)
1962 if (dlil_filters
[from_id
].type
!= DLIL_IF_FILTER
)
1965 ifp
= dlil_filters
[from_id
].ifp
;
1968 * Let interface filters (if any) do their thing ...
1971 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1974 if (TAILQ_EMPTY(fhead
) == 0) {
1975 while (orig_ifp
!= ifp
) {
1977 TAILQ_FOREACH(tmp
, fhead
, que
) {
1978 if ((match_found
) && (IFILT(tmp
).filter_if_output
)) {
1979 retval
= (*IFILT(tmp
).filter_if_output
)(IFILT(tmp
).cookie
,
1983 if (retval
== EJUSTRETURN
)
1993 if (ifp
!= orig_ifp
)
1996 if (from_id
== tmp
->filter_id
)
2003 * Finally, call the driver.
2006 retval
= (*ifp
->if_output
)(ifp
, m
);
2007 dlil_stats
.inject_if_out2
++;
2008 if ((retval
== 0) || (retval
== EJUSTRETURN
))