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>
50 #include <machine/machine_routines.h>
52 #define DBG_LAYER_BEG DLILDBG_CODE(DBG_DLIL_STATIC, 0)
53 #define DBG_LAYER_END DLILDBG_CODE(DBG_DLIL_STATIC, 2)
54 #define DBG_FNC_DLIL_INPUT DLILDBG_CODE(DBG_DLIL_STATIC, (1 << 8))
55 #define DBG_FNC_DLIL_OUTPUT DLILDBG_CODE(DBG_DLIL_STATIC, (2 << 8))
56 #define DBG_FNC_DLIL_IFOUT DLILDBG_CODE(DBG_DLIL_STATIC, (3 << 8))
59 #define MAX_DL_TAGS 50
60 #define MAX_DLIL_FILTERS 50
61 #define MAX_FRAME_TYPE_SIZE 4 /* LONGWORDS */
62 #define MAX_LINKADDR 4 /* LONGWORDS */
63 #define M_NKE M_IFADDR
65 #define PFILT(x) ((struct dlil_filterq_entry *) (x))->variants.pr_filter
66 #define IFILT(x) ((struct dlil_filterq_entry *) (x))->variants.if_filter
70 struct if_proto
*proto
;
71 struct dlil_filterq_head
*pr_flt_head
;
75 struct dlil_stats_str
{
87 struct dlil_filter_id_str
{
89 struct dlil_filterq_head
*head
;
90 struct dlil_filterq_entry
*filter_ptr
;
92 struct if_proto
*proto
;
97 struct if_family_str
{
98 TAILQ_ENTRY(if_family_str
) if_fam_next
;
103 #define DLIL_SHUTDOWN 1
105 int (*add_if
)(struct ifnet
*ifp
);
106 int (*del_if
)(struct ifnet
*ifp
);
107 int (*add_proto
)(struct ddesc_head_str
*demux_desc_head
,
108 struct if_proto
*proto
, u_long dl_tag
);
109 int (*del_proto
)(struct if_proto
*proto
, u_long dl_tag
);
110 int (*ifmod_ioctl
)(struct ifnet
*ifp
, u_long command
, caddr_t data
);
116 struct dlil_stats_str dlil_stats
;
119 struct dlil_filter_id_str dlil_filters
[MAX_DLIL_FILTERS
+1];
122 struct dl_tag_str dl_tag_array
[MAX_DL_TAGS
+1];
125 TAILQ_HEAD(, if_family_str
) if_family_head
;
127 static ifnet_inited
= 0;
129 int dlil_initialized
= 0;
130 decl_simple_lock_data(, dlil_input_lock
)
131 int dlil_input_thread_wakeup
= 0;
133 static struct mbuf
*dlil_input_mbuf_head
= NULL
;
134 static struct mbuf
*dlil_input_mbuf_tail
= NULL
;
135 static struct mbuf
*dlil_input_loop_head
= NULL
;
136 static struct mbuf
*dlil_input_loop_tail
= NULL
;
138 static void dlil_input_thread(void);
139 extern void run_netisr(void);
143 * Internal functions.
147 struct if_family_str
*find_family_module(u_long if_family
)
149 struct if_family_str
*mod
= NULL
;
151 TAILQ_FOREACH(mod
, &if_family_head
, if_fam_next
) {
152 if (mod
->if_family
== (if_family
& 0xffff))
164 struct ifnet
*ifbyfamily(u_long family
, short unit
)
168 TAILQ_FOREACH(ifp
, &ifnet
, if_link
)
169 if ((family
== ifp
->if_family
) &&
170 (ifp
->if_unit
== unit
))
176 struct if_proto
*dlttoproto(dl_tag
)
179 return dl_tag_array
[dl_tag
].proto
;
183 static int dlil_ifp_proto_count(struct ifnet
* ifp
)
186 struct if_proto
* proto
;
187 struct dlil_proto_head
* tmp
;
189 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
191 TAILQ_FOREACH(proto
, tmp
, next
)
197 u_long
ifptodlt(struct ifnet
*ifp
, u_long proto_family
)
199 struct if_proto
*proto
;
200 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
203 TAILQ_FOREACH(proto
, tmp
, next
)
204 if (proto
->protocol_family
== proto_family
)
205 return proto
->dl_tag
;
211 int dlil_find_dltag(u_long if_family
, short unit
, u_long proto_family
, u_long
*dl_tag
)
215 ifp
= ifbyfamily(if_family
, unit
);
219 *dl_tag
= ifptodlt(ifp
, proto_family
);
221 return EPROTONOSUPPORT
;
227 int dlil_get_next_dl_tag(u_long current_tag
, struct dl_tag_attr_str
*next
)
231 for (i
= (current_tag
+1); i
< MAX_DL_TAGS
; i
++)
232 if (dl_tag_array
[i
].ifp
) {
234 next
->if_flags
= dl_tag_array
[i
].ifp
->if_flags
;
235 next
->if_unit
= dl_tag_array
[i
].ifp
->if_unit
;
236 next
->protocol_family
= dl_tag_array
[i
].proto
->protocol_family
;
237 next
->if_family
= dl_tag_array
[i
].ifp
->if_family
;
242 * If we got here, there are no more entries
248 void dlil_post_msg(struct ifnet
*ifp
, u_long event_subclass
, u_long event_code
,
249 struct net_event_data
*event_data
, u_long event_data_len
)
251 struct net_event_data ev_data
;
252 struct kev_msg ev_msg
;
255 * a net event always start with a net_event_data structure
256 * but the caller can generate a simple net event or
257 * provide a longer event structure to post
260 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
261 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
262 ev_msg
.kev_subclass
= event_subclass
;
263 ev_msg
.event_code
= event_code
;
265 if (event_data
== 0) {
266 event_data
= &ev_data
;
267 event_data_len
= sizeof(struct net_event_data
);
270 strncpy(&event_data
->if_name
[0], ifp
->if_name
, IFNAMSIZ
);
271 event_data
->if_family
= ifp
->if_family
;
272 event_data
->if_unit
= (unsigned long) ifp
->if_unit
;
274 ev_msg
.dv
[0].data_length
= event_data_len
;
275 ev_msg
.dv
[0].data_ptr
= event_data
;
276 ev_msg
.dv
[1].data_length
= 0;
278 kev_post_msg(&ev_msg
);
288 printf("dlil_init\n");
290 TAILQ_INIT(&if_family_head
);
291 for (i
=0; i
< MAX_DL_TAGS
; i
++)
292 dl_tag_array
[i
].ifp
= 0;
294 for (i
=0; i
< MAX_DLIL_FILTERS
; i
++)
295 dlil_filters
[i
].type
= 0;
297 bzero(&dlil_stats
, sizeof(dlil_stats
));
299 simple_lock_init(&dlil_input_lock
);
302 * Start up the dlil input thread once everything is initialized
304 (void) kernel_thread(kernel_task
, dlil_input_thread
);
308 u_long
get_new_filter_id()
312 for (i
=1; i
< MAX_DLIL_FILTERS
; i
++)
313 if (dlil_filters
[i
].type
== 0)
320 int dlil_attach_interface_filter(struct ifnet
*ifp
,
321 struct dlil_if_flt_str
*if_filter
,
327 struct dlil_filterq_entry
*tmp_ptr
;
328 struct dlil_filterq_entry
*if_filt
;
329 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
330 boolean_t funnel_state
;
333 MALLOC(tmp_ptr
, struct dlil_filterq_entry
*, sizeof(*tmp_ptr
), M_NKE
, M_WAITOK
);
337 bcopy((caddr_t
) if_filter
, (caddr_t
) &tmp_ptr
->variants
.if_filter
,
338 sizeof(struct dlil_if_flt_str
));
340 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
344 if (insertion_point
!= DLIL_LAST_FILTER
) {
345 TAILQ_FOREACH(if_filt
, fhead
, que
)
346 if (insertion_point
== if_filt
->filter_id
) {
347 TAILQ_INSERT_BEFORE(if_filt
, tmp_ptr
, que
);
352 TAILQ_INSERT_TAIL(fhead
, tmp_ptr
, que
);
354 if (*filter_id
= get_new_filter_id()) {
355 dlil_filters
[*filter_id
].filter_ptr
= tmp_ptr
;
356 dlil_filters
[*filter_id
].head
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
357 dlil_filters
[*filter_id
].type
= DLIL_IF_FILTER
;
358 dlil_filters
[*filter_id
].ifp
= ifp
;
359 tmp_ptr
->filter_id
= *filter_id
;
360 tmp_ptr
->type
= DLIL_IF_FILTER
;
364 kprintf("dlil_attach_interface_filter - can't alloc filter_id\n");
365 TAILQ_REMOVE(fhead
, tmp_ptr
, que
);
366 FREE(tmp_ptr
, M_NKE
);
371 thread_funnel_set(network_flock
, funnel_state
);
376 int dlil_attach_protocol_filter(u_long dl_tag
,
377 struct dlil_pr_flt_str
*pr_filter
,
381 struct dlil_filterq_entry
*tmp_ptr
;
382 struct dlil_filterq_entry
*pr_filt
;
385 boolean_t funnel_state
;
387 if (dl_tag
> MAX_DL_TAGS
)
390 if (dl_tag_array
[dl_tag
].ifp
== 0)
393 MALLOC(tmp_ptr
, struct dlil_filterq_entry
*, sizeof(*tmp_ptr
), M_NKE
, M_WAITOK
);
397 bcopy((caddr_t
) pr_filter
, (caddr_t
) &tmp_ptr
->variants
.pr_filter
,
398 sizeof(struct dlil_pr_flt_str
));
400 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
403 if (insertion_point
!= DLIL_LAST_FILTER
) {
404 TAILQ_FOREACH(pr_filt
, dl_tag_array
[dl_tag
].pr_flt_head
, que
)
405 if (insertion_point
== pr_filt
->filter_id
) {
406 TAILQ_INSERT_BEFORE(pr_filt
, tmp_ptr
, que
);
411 TAILQ_INSERT_TAIL(dl_tag_array
[dl_tag
].pr_flt_head
, tmp_ptr
, que
);
414 if (*filter_id
= get_new_filter_id()) {
415 dlil_filters
[*filter_id
].filter_ptr
= tmp_ptr
;
416 dlil_filters
[*filter_id
].head
= dl_tag_array
[dl_tag
].pr_flt_head
;
417 dlil_filters
[*filter_id
].type
= DLIL_PR_FILTER
;
418 dlil_filters
[*filter_id
].proto
= dl_tag_array
[dl_tag
].proto
;
419 dlil_filters
[*filter_id
].ifp
= dl_tag_array
[dl_tag
].ifp
;
420 tmp_ptr
->filter_id
= *filter_id
;
421 tmp_ptr
->type
= DLIL_PR_FILTER
;
425 kprintf("dlil_attach_protocol_filter - can't alloc filter_id\n");
426 TAILQ_REMOVE(dl_tag_array
[dl_tag
].pr_flt_head
, tmp_ptr
, que
);
427 FREE(tmp_ptr
, M_NKE
);
432 thread_funnel_set(network_flock
, funnel_state
);
438 dlil_detach_filter(u_long filter_id
)
440 struct dlil_filter_id_str
*flt
;
442 boolean_t funnel_state
;
444 if (filter_id
> MAX_DLIL_FILTERS
) {
445 kprintf("dlil_detach_filter - Bad filter_id value %d\n", filter_id
);
449 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
451 flt
= &dlil_filters
[filter_id
];
452 if (flt
->type
== 0) {
453 kprintf("dlil_detach_filter - no such filter_id %d\n", filter_id
);
454 thread_funnel_set(network_flock
, funnel_state
);
459 if (flt
->type
== DLIL_IF_FILTER
) {
460 if (IFILT(flt
->filter_ptr
).filter_detach
)
461 (*IFILT(flt
->filter_ptr
).filter_detach
)(IFILT(flt
->filter_ptr
).cookie
);
464 if (flt
->type
== DLIL_PR_FILTER
) {
465 if (PFILT(flt
->filter_ptr
).filter_detach
)
466 (*PFILT(flt
->filter_ptr
).filter_detach
)(PFILT(flt
->filter_ptr
).cookie
);
470 TAILQ_REMOVE(flt
->head
, flt
->filter_ptr
, que
);
471 FREE(flt
->filter_ptr
, M_NKE
);
474 thread_funnel_set(network_flock
, funnel_state
);
480 dlil_input_thread_continue(void)
483 struct mbuf
*m
, *m_loop
;
486 usimple_lock(&dlil_input_lock
);
487 m
= dlil_input_mbuf_head
;
488 dlil_input_mbuf_head
= NULL
;
489 dlil_input_mbuf_tail
= NULL
;
490 m_loop
= dlil_input_loop_head
;
491 dlil_input_loop_head
= NULL
;
492 dlil_input_loop_tail
= NULL
;
493 usimple_unlock(&dlil_input_lock
);
496 expand_mcl
= dlil_expand_mcl
;
506 * NOTE warning %%% attention !!!!
507 * We should think about putting some thread starvation safeguards if
508 * we deal with long chains of packets.
511 struct mbuf
*m0
= m
->m_nextpkt
;
512 void *header
= m
->m_pkthdr
.header
;
515 m
->m_pkthdr
.header
= NULL
;
516 (void) dlil_input_packet(m
->m_pkthdr
.rcvif
, m
, header
);
521 struct mbuf
*m0
= m
->m_nextpkt
;
522 void *header
= m
->m_pkthdr
.header
;
523 struct ifnet
*ifp
= (struct ifnet
*) m
->m_pkthdr
.aux
;
526 m
->m_pkthdr
.header
= NULL
;
527 m
->m_pkthdr
.aux
= NULL
;
528 (void) dlil_input_packet(ifp
, m
, header
);
535 if (dlil_input_mbuf_head
== NULL
&&
536 dlil_input_loop_head
== NULL
&&
538 assert_wait(&dlil_input_thread_wakeup
, THREAD_UNINT
);
539 #if defined (__i386__)
542 thread_block(dlil_input_thread_continue
);
549 void dlil_input_thread(void)
551 register thread_t self
= current_thread();
552 extern void stack_privilege(thread_t thread
);
554 printf("dlil_input_thread %x\n", self
);
557 * Make sure that this thread
558 * always has a kernel stack, and
559 * bind it to the master cpu.
561 stack_privilege(self
);
562 ml_thread_policy(current_thread(), MACHINE_GROUP
, (MACHINE_NETWORK_GROUP
|MACHINE_NETWORK_NETISR
));
564 /* The dlil thread is always funneled */
565 thread_funnel_set(network_flock
, TRUE
);
566 dlil_initialized
= 1;
567 dlil_input_thread_continue();
571 dlil_input(struct ifnet
*ifp
, struct mbuf
*m_head
, struct mbuf
*m_tail
)
574 * Because of loopbacked multicast we cannot stuff the ifp in
575 * the rcvif of the packet header: loopback has its own dlil
579 usimple_lock(&dlil_input_lock
);
580 if (ifp
->if_type
!= IFT_LOOP
) {
581 if (dlil_input_mbuf_head
== NULL
)
582 dlil_input_mbuf_head
= m_head
;
583 else if (dlil_input_mbuf_tail
!= NULL
)
584 dlil_input_mbuf_tail
->m_nextpkt
= m_head
;
585 dlil_input_mbuf_tail
= m_tail
? m_tail
: m_head
;
587 if (dlil_input_loop_head
== NULL
)
588 dlil_input_loop_head
= m_head
;
589 else if (dlil_input_loop_tail
!= NULL
)
590 dlil_input_loop_tail
->m_nextpkt
= m_head
;
591 dlil_input_loop_tail
= m_tail
? m_tail
: m_head
;
593 usimple_unlock(&dlil_input_lock
);
595 wakeup((caddr_t
)&dlil_input_thread_wakeup
);
601 dlil_input_packet(struct ifnet
*ifp
, struct mbuf
*m
,
604 struct ifnet
*orig_ifp
= 0;
605 struct dlil_filterq_entry
*tmp
;
607 struct if_proto
*ifproto
= 0;
608 struct if_proto
*proto
;
609 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
612 KERNEL_DEBUG(DBG_FNC_DLIL_INPUT
| DBG_FUNC_START
,0,0,0,0,0);
615 * Run interface filters
618 while (orig_ifp
!= ifp
) {
621 TAILQ_FOREACH_REVERSE(tmp
, fhead
, que
, dlil_filterq_head
) {
622 if (IFILT(tmp
).filter_if_input
) {
623 retval
= (*IFILT(tmp
).filter_if_input
)(IFILT(tmp
).cookie
,
628 if (retval
== EJUSTRETURN
)
642 ifp
->if_lastchange
= time
;
645 * Call family demux module. If the demux module finds a match
646 * for the frame it will fill-in the ifproto pointer.
649 retval
= (*ifp
->if_demux
)(ifp
, m
, frame_header
, &ifproto
);
651 if (m
->m_flags
& (M_BCAST
|M_MCAST
))
654 if ((retval
) && (retval
!= EJUSTRETURN
) && (ifp
->offercnt
)) {
656 * No match was found, look for any offers.
658 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
659 TAILQ_FOREACH(proto
, tmp
, next
) {
660 if ((proto
->dl_offer
) && (proto
->dl_offer(m
, frame_header
) == 0)) {
669 if (retval
!= EJUSTRETURN
) {
678 printf("ERROR - dlil_input - if_demux didn't return an if_proto pointer\n");
684 * Call any attached protocol filters.
687 TAILQ_FOREACH_REVERSE(tmp
, &ifproto
->pr_flt_head
, que
, dlil_filterq_head
) {
688 if (PFILT(tmp
).filter_dl_input
) {
689 retval
= (*PFILT(tmp
).filter_dl_input
)(PFILT(tmp
).cookie
,
695 if (retval
== EJUSTRETURN
)
707 retval
= (*ifproto
->dl_input
)(m
, frame_header
,
708 ifp
, ifproto
->dl_tag
,
711 if (retval
== EJUSTRETURN
)
717 KERNEL_DEBUG(DBG_FNC_DLIL_INPUT
| DBG_FUNC_END
,0,0,0,0,0);
723 void ether_input(ifp
, eh
, m
)
725 struct ether_header
*eh
;
729 kprintf("Someone is calling ether_input!!\n");
731 dlil_input(ifp
, m
, NULL
);
736 dlil_event(struct ifnet
*ifp
, struct kern_event_msg
*event
)
738 struct dlil_filterq_entry
*filt
;
740 struct ifnet
*orig_ifp
= 0;
741 struct if_proto
*proto
;
742 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
743 struct kev_msg kev_msg
;
744 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
745 boolean_t funnel_state
;
748 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
750 while (orig_ifp
!= ifp
) {
753 TAILQ_FOREACH_REVERSE(filt
, fhead
, que
, dlil_filterq_head
) {
754 if (IFILT(filt
).filter_if_event
) {
755 retval
= (*IFILT(filt
).filter_if_event
)(IFILT(filt
).cookie
,
760 (void) thread_funnel_set(network_flock
, funnel_state
);
761 if (retval
== EJUSTRETURN
)
775 * Call Interface Module event hook, if any.
779 retval
= ifp
->if_event(ifp
, (caddr_t
) event
);
782 (void) thread_funnel_set(network_flock
, funnel_state
);
784 if (retval
== EJUSTRETURN
)
792 * Call dl_event entry point for all protocols attached to this interface
795 TAILQ_FOREACH(proto
, tmp
, next
) {
797 * Call any attached protocol filters.
800 TAILQ_FOREACH_REVERSE(filt
, &proto
->pr_flt_head
, que
, dlil_filterq_head
) {
801 if (PFILT(filt
).filter_dl_event
) {
802 retval
= (*PFILT(filt
).filter_dl_event
)(PFILT(filt
).cookie
,
806 (void) thread_funnel_set(network_flock
, funnel_state
);
807 if (retval
== EJUSTRETURN
)
817 * Finally, call the dl_event entry point (if any)
821 retval
= (*proto
->dl_event
)(event
, proto
->dl_tag
);
823 if (retval
== EJUSTRETURN
) {
824 (void) thread_funnel_set(network_flock
, funnel_state
);
831 * Now, post this event to the Kernel Event message queue
834 kev_msg
.vendor_code
= event
->vendor_code
;
835 kev_msg
.kev_class
= event
->kev_class
;
836 kev_msg
.kev_subclass
= event
->kev_subclass
;
837 kev_msg
.event_code
= event
->event_code
;
838 kev_msg
.dv
[0].data_ptr
= &event
->event_data
[0];
839 kev_msg
.dv
[0].data_length
= event
->total_size
- KEV_MSG_HEADER_SIZE
;
840 kev_msg
.dv
[1].data_length
= 0;
842 kev_post_msg(&kev_msg
);
844 (void) thread_funnel_set(network_flock
, funnel_state
);
851 dlil_output(u_long dl_tag
,
854 struct sockaddr
*dest
,
860 struct ifnet
*orig_ifp
= 0;
862 struct if_proto
*proto
;
863 struct dlil_filterq_entry
*tmp
;
865 char frame_type_buffer
[MAX_FRAME_TYPE_SIZE
* 4];
866 char dst_linkaddr_buffer
[MAX_LINKADDR
* 4];
867 struct dlil_filterq_head
*fhead
;
870 KERNEL_DEBUG(DBG_FNC_DLIL_OUTPUT
| DBG_FUNC_START
,0,0,0,0,0);
873 * Temporary hackery until all the existing protocols can become fully
874 * "dl_tag aware". Some things only have the ifp, so this handles that
875 * case for the time being.
878 if (dl_tag
> MAX_DL_TAGS
) {
879 /* dl_tag is really an ifnet pointer! */
881 ifp
= (struct ifnet
*) dl_tag
;
882 dl_tag
= ifp
->if_data
.default_proto
;
884 proto
= dl_tag_array
[dl_tag
].proto
;
889 if ((dl_tag
== 0) || (dl_tag_array
[dl_tag
].ifp
== 0))
892 ifp
= dl_tag_array
[dl_tag
].ifp
;
893 proto
= dl_tag_array
[dl_tag
].proto
;
902 frame_type
= frame_type_buffer
;
903 dst_linkaddr
= dst_linkaddr_buffer
;
905 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
907 if ((raw
== 0) && (proto
->dl_pre_output
)) {
908 retval
= (*proto
->dl_pre_output
)(ifp
, &m
, dest
, route
,
909 frame_type
, dst_linkaddr
, dl_tag
);
911 if (retval
== EJUSTRETURN
)
921 * Run any attached protocol filters.
924 if (TAILQ_EMPTY(dl_tag_array
[dl_tag
].pr_flt_head
) == 0) {
925 TAILQ_FOREACH(tmp
, dl_tag_array
[dl_tag
].pr_flt_head
, que
) {
926 if (PFILT(tmp
).filter_dl_output
) {
927 retval
= (*PFILT(tmp
).filter_dl_output
)(PFILT(tmp
).cookie
,
928 &m
, &ifp
, &dest
, dst_linkaddr
, frame_type
);
930 if (retval
== EJUSTRETURN
)
943 * Call framing module
945 if ((raw
== 0) && (ifp
->if_framer
)) {
946 retval
= (*ifp
->if_framer
)(ifp
, &m
, dest
, dst_linkaddr
, frame_type
);
948 if (retval
== EJUSTRETURN
)
960 struct mbuf
*m0
= m
;
962 if (m
->m_pkthdr
.rcvif
)
963 m
->m_pkthdr
.rcvif
= NULL
;
964 ifp
= bridge_dst_lookup(m
);
965 bdg_forward(&m0
, ifp
);
975 * Let interface filters (if any) do their thing ...
978 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
979 if (TAILQ_EMPTY(fhead
) == 0) {
980 while (orig_ifp
!= ifp
) {
982 TAILQ_FOREACH(tmp
, fhead
, que
) {
983 if (IFILT(tmp
).filter_if_output
) {
984 retval
= (*IFILT(tmp
).filter_if_output
)(IFILT(tmp
).cookie
,
988 if (retval
== EJUSTRETURN
)
1005 * Finally, call the driver.
1008 KERNEL_DEBUG(DBG_FNC_DLIL_IFOUT
| DBG_FUNC_START
, 0,0,0,0,0);
1009 retval
= (*ifp
->if_output
)(ifp
, m
);
1010 KERNEL_DEBUG(DBG_FNC_DLIL_IFOUT
| DBG_FUNC_END
, 0,0,0,0,0);
1012 KERNEL_DEBUG(DBG_FNC_DLIL_OUTPUT
| DBG_FUNC_END
,0,0,0,0,0);
1014 if ((retval
== 0) || (retval
== EJUSTRETURN
))
1022 dlil_ioctl(u_long proto_fam
,
1027 struct dlil_filterq_entry
*tmp
;
1028 struct dlil_filterq_head
*fhead
;
1029 int retval
= EOPNOTSUPP
;
1030 int retval2
= EOPNOTSUPP
;
1032 struct if_family_str
*if_family
;
1036 retval
= dlil_find_dltag(ifp
->if_family
, ifp
->if_unit
,
1037 proto_fam
, &dl_tag
);
1040 if (dl_tag_array
[dl_tag
].ifp
!= ifp
)
1044 * Run any attached protocol filters.
1046 TAILQ_FOREACH(tmp
, dl_tag_array
[dl_tag
].pr_flt_head
, que
) {
1047 if (PFILT(tmp
).filter_dl_ioctl
) {
1049 (*PFILT(tmp
).filter_dl_ioctl
)(PFILT(tmp
).cookie
,
1050 dl_tag_array
[dl_tag
].ifp
,
1055 if (retval
== EJUSTRETURN
)
1063 if (dl_tag_array
[dl_tag
].proto
->dl_ioctl
)
1065 (*dl_tag_array
[dl_tag
].proto
->dl_ioctl
)(dl_tag
,
1066 dl_tag_array
[dl_tag
].ifp
,
1070 retval
= EOPNOTSUPP
;
1076 if ((retval
) && (retval
!= EOPNOTSUPP
)) {
1077 if (retval
== EJUSTRETURN
)
1084 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1085 TAILQ_FOREACH(tmp
, fhead
, que
) {
1086 if (IFILT(tmp
).filter_if_ioctl
) {
1087 retval2
= (*IFILT(tmp
).filter_if_ioctl
)(IFILT(tmp
).cookie
, ifp
,
1088 ioctl_code
, ioctl_arg
);
1090 if (retval2
== EJUSTRETURN
)
1099 if_family
= find_family_module(ifp
->if_family
);
1100 if ((if_family
) && (if_family
->ifmod_ioctl
)) {
1101 retval2
= (*if_family
->ifmod_ioctl
)(ifp
, ioctl_code
, ioctl_arg
);
1103 if ((retval2
) && (retval2
!= EOPNOTSUPP
)) {
1104 if (retval2
== EJUSTRETURN
)
1110 if (retval
== EOPNOTSUPP
)
1115 retval2
= (*ifp
->if_ioctl
)(ifp
, ioctl_code
, ioctl_arg
);
1117 if (retval
== EOPNOTSUPP
)
1120 if (retval2
== EOPNOTSUPP
)
1129 dlil_attach_protocol(struct dlil_proto_reg_str
*proto
,
1133 struct if_proto
*ifproto
;
1135 struct if_family_str
*if_family
;
1137 struct dlil_proto_head
*tmp
;
1138 struct kev_dl_proto_data ev_pr_data
;
1140 boolean_t funnel_state
;
1143 if ((proto
->protocol_family
== 0) || (proto
->interface_family
== 0))
1146 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1148 if_family
= find_family_module(proto
->interface_family
);
1149 if ((!if_family
) || (if_family
->flags
& DLIL_SHUTDOWN
)) {
1150 kprintf("dlil_attach_protocol -- no interface family module %d",
1151 proto
->interface_family
);
1153 thread_funnel_set(network_flock
, funnel_state
);
1157 ifp
= ifbyfamily(proto
->interface_family
, proto
->unit_number
);
1159 kprintf("dlil_attach_protocol -- no such interface %d unit %d\n",
1160 proto
->interface_family
, proto
->unit_number
);
1162 thread_funnel_set(network_flock
, funnel_state
);
1166 if (dlil_find_dltag(proto
->interface_family
, proto
->unit_number
,
1167 proto
->protocol_family
, &i
) == 0) {
1168 thread_funnel_set(network_flock
, funnel_state
);
1172 for (i
=1; i
< MAX_DL_TAGS
; i
++)
1173 if (dl_tag_array
[i
].ifp
== 0)
1176 if (i
>= MAX_DL_TAGS
) {
1178 thread_funnel_set(network_flock
, funnel_state
);
1183 * Allocate and init a new if_proto structure
1186 ifproto
= _MALLOC(sizeof(struct if_proto
), M_IFADDR
, M_WAITOK
);
1188 printf("ERROR - DLIL failed if_proto allocation\n");
1189 thread_funnel_set(network_flock
, funnel_state
);
1193 bzero(ifproto
, sizeof(struct if_proto
));
1195 dl_tag_array
[i
].ifp
= ifp
;
1196 dl_tag_array
[i
].proto
= ifproto
;
1197 dl_tag_array
[i
].pr_flt_head
= &ifproto
->pr_flt_head
;
1198 ifproto
->dl_tag
= i
;
1201 if (proto
->default_proto
) {
1202 if (ifp
->if_data
.default_proto
== 0)
1203 ifp
->if_data
.default_proto
= i
;
1205 printf("ERROR - dlil_attach_protocol -- Attempt to attach more than one default protocol\n");
1208 ifproto
->protocol_family
= proto
->protocol_family
;
1209 ifproto
->dl_input
= proto
->input
;
1210 ifproto
->dl_pre_output
= proto
->pre_output
;
1211 ifproto
->dl_event
= proto
->event
;
1212 ifproto
->dl_offer
= proto
->offer
;
1213 ifproto
->dl_ioctl
= proto
->ioctl
;
1215 TAILQ_INIT(&ifproto
->pr_flt_head
);
1218 * Call family module add_proto routine so it can refine the
1219 * demux descriptors as it wishes.
1221 error
= (*if_family
->add_proto
)(&proto
->demux_desc_head
, ifproto
, *dl_tag
);
1223 dl_tag_array
[*dl_tag
].ifp
= 0;
1224 FREE(ifproto
, M_IFADDR
);
1226 thread_funnel_set(network_flock
, funnel_state
);
1231 * Add to if_proto list for this interface
1234 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1235 TAILQ_INSERT_TAIL(tmp
, ifproto
, next
);
1237 if (ifproto
->dl_offer
)
1240 /* the reserved field carries the number of protocol still attached (subject to change) */
1241 ev_pr_data
.proto_family
= proto
->protocol_family
;
1242 ev_pr_data
.proto_remaining_count
= dlil_ifp_proto_count(ifp
);
1243 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_PROTO_ATTACHED
,
1244 (struct net_event_data
*)&ev_pr_data
,
1245 sizeof(struct kev_dl_proto_data
));
1248 thread_funnel_set(network_flock
, funnel_state
);
1255 dlil_detach_protocol(u_long dl_tag
)
1258 struct ifnet
*orig_ifp
=0;
1259 struct if_proto
*proto
;
1260 struct dlil_proto_head
*tmp
;
1261 struct if_family_str
*if_family
;
1262 struct dlil_filterq_entry
*filter
;
1264 struct dlil_filterq_head
*fhead
;
1265 struct kev_dl_proto_data ev_pr_data
;
1266 boolean_t funnel_state
;
1269 if (dl_tag
> MAX_DL_TAGS
)
1272 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1275 if (dl_tag_array
[dl_tag
].ifp
== 0) {
1277 thread_funnel_set(network_flock
, funnel_state
);
1281 ifp
= dl_tag_array
[dl_tag
].ifp
;
1282 proto
= dl_tag_array
[dl_tag
].proto
;
1284 if_family
= find_family_module(ifp
->if_family
);
1285 if (if_family
== NULL
) {
1287 thread_funnel_set(network_flock
, funnel_state
);
1291 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1294 * Call family module del_proto
1297 (*if_family
->del_proto
)(proto
, dl_tag
);
1301 * Remove and deallocate any attached protocol filters
1304 while (filter
= TAILQ_FIRST(&proto
->pr_flt_head
))
1305 dlil_detach_filter(filter
->filter_id
);
1307 if (proto
->dl_offer
)
1310 if (ifp
->if_data
.default_proto
== dl_tag
)
1311 ifp
->if_data
.default_proto
= 0;
1312 dl_tag_array
[dl_tag
].ifp
= 0;
1314 /* the reserved field carries the number of protocol still attached (subject to change) */
1315 ev_pr_data
.proto_family
= proto
->protocol_family
;
1316 TAILQ_REMOVE(tmp
, proto
, next
);
1317 FREE(proto
, M_IFADDR
);
1320 ev_pr_data
.proto_remaining_count
= dlil_ifp_proto_count(ifp
);
1321 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_PROTO_DETACHED
,
1322 (struct net_event_data
*)&ev_pr_data
,
1323 sizeof(struct kev_dl_proto_data
));
1325 if (ifp
->refcnt
== 0 && (ifp
->if_eflags
& IFEF_DETACH_DISABLED
) == 0) {
1326 if (ifp
->if_flags
& IFF_UP
)
1327 printf("WARNING - dlil_detach_protocol - ifp refcnt 0, but IF still up\n");
1329 TAILQ_REMOVE(&ifnet
, ifp
, if_link
);
1331 (*if_family
->del_if
)(ifp
);
1333 if (--if_family
->refcnt
== 0) {
1334 if (if_family
->shutdown
)
1335 (*if_family
->shutdown
)();
1337 TAILQ_REMOVE(&if_family_head
, if_family
, if_fam_next
);
1338 FREE(if_family
, M_IFADDR
);
1341 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1342 while (orig_ifp
!= ifp
) {
1345 TAILQ_FOREACH(filter
, fhead
, que
) {
1346 if (IFILT(filter
).filter_if_free
) {
1347 retval
= (*IFILT(filter
).filter_if_free
)(IFILT(filter
).cookie
, ifp
);
1350 thread_funnel_set(network_flock
, funnel_state
);
1354 if (ifp
!= orig_ifp
)
1359 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_DETACHED
, 0, 0);
1361 (*ifp
->if_free
)(ifp
);
1365 thread_funnel_set(network_flock
, funnel_state
);
1374 dlil_if_attach(struct ifnet
*ifp
)
1376 u_long interface_family
= ifp
->if_family
;
1377 struct if_family_str
*if_family
;
1378 struct dlil_proto_head
*tmp
;
1381 boolean_t funnel_state
;
1383 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1385 if (ifnet_inited
== 0) {
1390 if_family
= find_family_module(interface_family
);
1392 if ((!if_family
) || (if_family
->flags
& DLIL_SHUTDOWN
)) {
1394 kprintf("Attempt to attach interface without family module - %d\n",
1396 thread_funnel_set(network_flock
, funnel_state
);
1402 * Call the family module to fill in the appropriate fields in the
1406 stat
= (*if_family
->add_if
)(ifp
);
1409 kprintf("dlil_if_attach -- add_if failed with %d\n", stat
);
1410 thread_funnel_set(network_flock
, funnel_state
);
1415 * Add the ifp to the interface list.
1418 tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1421 ifp
->if_data
.default_proto
= 0;
1424 TAILQ_INIT(&ifp
->if_flt_head
);
1426 if_family
->refcnt
++;
1428 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_ATTACHED
, 0, 0);
1431 thread_funnel_set(network_flock
, funnel_state
);
1437 dlil_if_detach(struct ifnet
*ifp
)
1439 struct if_proto
*proto
;
1440 struct dlil_filterq_entry
*if_filter
;
1441 struct if_family_str
*if_family
;
1442 struct dlil_filterq_head
*fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1444 struct kev_msg ev_msg
;
1445 boolean_t funnel_state
;
1447 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1449 if (ifp
->if_flags
& IFF_UP
)
1450 printf("WARNING - dlil_if_detach called for UP interface\n");
1452 if_family
= find_family_module(ifp
->if_family
);
1455 kprintf("Attempt to detach interface without family module - %s\n",
1458 thread_funnel_set(network_flock
, funnel_state
);
1462 while (if_filter
= TAILQ_FIRST(fhead
))
1463 dlil_detach_filter(if_filter
->filter_id
);
1467 if (ifp
->refcnt
== 0 && (ifp
->if_eflags
& IFEF_DETACH_DISABLED
) == 0) {
1468 TAILQ_REMOVE(&ifnet
, ifp
, if_link
);
1470 (*if_family
->del_if
)(ifp
);
1472 if (--if_family
->refcnt
== 0) {
1473 if (if_family
->shutdown
)
1474 (*if_family
->shutdown
)();
1476 TAILQ_REMOVE(&if_family_head
, if_family
, if_fam_next
);
1477 FREE(if_family
, M_IFADDR
);
1480 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_DETACHED
, 0, 0);
1482 thread_funnel_set(network_flock
, funnel_state
);
1487 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IF_DETACHING
, 0, 0);
1489 thread_funnel_set(network_flock
, funnel_state
);
1490 return DLIL_WAIT_FOR_FREE
;
1496 dlil_reg_if_modules(u_long interface_family
,
1497 struct dlil_ifmod_reg_str
*ifmod
)
1499 struct if_family_str
*if_family
;
1501 boolean_t funnel_state
;
1504 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1506 if (find_family_module(interface_family
)) {
1507 kprintf("Attempt to register dlil family module more than once - %d\n",
1510 thread_funnel_set(network_flock
, funnel_state
);
1514 if ((!ifmod
->add_if
) || (!ifmod
->del_if
) ||
1515 (!ifmod
->add_proto
) || (!ifmod
->del_proto
)) {
1516 kprintf("dlil_reg_if_modules passed at least one null pointer\n");
1518 thread_funnel_set(network_flock
, funnel_state
);
1522 if_family
= (struct if_family_str
*) _MALLOC(sizeof(struct if_family_str
), M_IFADDR
, M_WAITOK
);
1524 kprintf("dlil_reg_if_modules failed allocation\n");
1526 thread_funnel_set(network_flock
, funnel_state
);
1530 bzero(if_family
, sizeof(struct if_family_str
));
1532 if_family
->if_family
= interface_family
& 0xffff;
1533 if_family
->shutdown
= ifmod
->shutdown
;
1534 if_family
->add_if
= ifmod
->add_if
;
1535 if_family
->del_if
= ifmod
->del_if
;
1536 if_family
->add_proto
= ifmod
->add_proto
;
1537 if_family
->del_proto
= ifmod
->del_proto
;
1538 if_family
->ifmod_ioctl
= ifmod
->ifmod_ioctl
;
1539 if_family
->refcnt
= 1;
1540 if_family
->flags
= 0;
1542 TAILQ_INSERT_TAIL(&if_family_head
, if_family
, if_fam_next
);
1544 thread_funnel_set(network_flock
, funnel_state
);
1548 int dlil_dereg_if_modules(u_long interface_family
)
1550 struct if_family_str
*if_family
;
1552 boolean_t funnel_state
;
1554 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1556 if_family
= find_family_module(interface_family
);
1557 if (if_family
== 0) {
1559 thread_funnel_set(network_flock
, funnel_state
);
1563 if (--if_family
->refcnt
== 0) {
1564 if (if_family
->shutdown
)
1565 (*if_family
->shutdown
)();
1567 TAILQ_REMOVE(&if_family_head
, if_family
, if_fam_next
);
1568 FREE(if_family
, M_IFADDR
);
1571 if_family
->flags
|= DLIL_SHUTDOWN
;
1574 thread_funnel_set(network_flock
, funnel_state
);
1583 * Old if_attach no-op'ed function defined here for temporary backwards compatibility
1589 dlil_if_attach(ifp
);
1595 dlil_inject_if_input(struct mbuf
*m
, char *frame_header
, u_long from_id
)
1597 struct ifnet
*orig_ifp
= 0;
1599 struct if_proto
*ifproto
;
1600 struct if_proto
*proto
;
1601 struct dlil_filterq_entry
*tmp
;
1603 struct dlil_filterq_head
*fhead
;
1607 dlil_stats
.inject_if_in1
++;
1608 if (from_id
> MAX_DLIL_FILTERS
)
1611 if (dlil_filters
[from_id
].type
!= DLIL_IF_FILTER
)
1614 ifp
= dlil_filters
[from_id
].ifp
;
1617 * Let interface filters (if any) do their thing ...
1620 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1623 if (TAILQ_EMPTY(fhead
) == 0) {
1624 while (orig_ifp
!= ifp
) {
1626 TAILQ_FOREACH_REVERSE(tmp
, fhead
, que
, dlil_filterq_head
) {
1627 if ((match_found
) && (IFILT(tmp
).filter_if_input
)) {
1628 retval
= (*IFILT(tmp
).filter_if_input
)(IFILT(tmp
).cookie
,
1633 if (retval
== EJUSTRETURN
)
1643 if (ifp
!= orig_ifp
)
1646 if (from_id
== tmp
->filter_id
)
1652 ifp
->if_lastchange
= time
;
1655 * Call family demux module. If the demux module finds a match
1656 * for the frame it will fill-in the ifproto pointer.
1659 retval
= (*ifp
->if_demux
)(ifp
, m
, frame_header
, &ifproto
);
1661 if (m
->m_flags
& (M_BCAST
|M_MCAST
))
1664 if ((retval
) && (ifp
->offercnt
)) {
1666 * No match was found, look for any offers.
1668 struct dlil_proto_head
*tmp
= (struct dlil_proto_head
*) &ifp
->proto_head
;
1669 TAILQ_FOREACH(proto
, tmp
, next
) {
1670 if ((proto
->dl_offer
) && (proto
->dl_offer(m
, frame_header
) == 0)) {
1679 if (retval
!= EJUSTRETURN
) {
1688 printf("ERROR - dlil_inject_if_input -- if_demux didn't return an if_proto pointer\n");
1694 * Call any attached protocol filters.
1696 TAILQ_FOREACH_REVERSE(tmp
, &ifproto
->pr_flt_head
, que
, dlil_filterq_head
) {
1697 if (PFILT(tmp
).filter_dl_input
) {
1698 retval
= (*PFILT(tmp
).filter_dl_input
)(PFILT(tmp
).cookie
,
1704 if (retval
== EJUSTRETURN
)
1716 retval
= (*ifproto
->dl_input
)(m
, frame_header
,
1717 ifp
, ifproto
->dl_tag
,
1720 dlil_stats
.inject_if_in2
++;
1721 if (retval
== EJUSTRETURN
)
1736 dlil_inject_pr_input(struct mbuf
*m
, char *frame_header
, u_long from_id
)
1738 struct ifnet
*orig_ifp
= 0;
1739 struct dlil_filterq_entry
*tmp
;
1741 struct if_proto
*ifproto
= 0;
1746 dlil_stats
.inject_pr_in1
++;
1747 if (from_id
> MAX_DLIL_FILTERS
)
1750 if (dlil_filters
[from_id
].type
!= DLIL_PR_FILTER
)
1753 ifproto
= dlil_filters
[from_id
].proto
;
1754 ifp
= dlil_filters
[from_id
].ifp
;
1758 * Call any attached protocol filters.
1762 TAILQ_FOREACH_REVERSE(tmp
, &ifproto
->pr_flt_head
, que
, dlil_filterq_head
) {
1763 if ((match_found
) && (PFILT(tmp
).filter_dl_input
)) {
1764 retval
= (*PFILT(tmp
).filter_dl_input
)(PFILT(tmp
).cookie
,
1770 if (retval
== EJUSTRETURN
)
1779 if (tmp
->filter_id
== from_id
)
1784 retval
= (*ifproto
->dl_input
)(m
, frame_header
,
1785 ifp
, ifproto
->dl_tag
,
1788 if (retval
== EJUSTRETURN
)
1794 dlil_stats
.inject_pr_in2
++;
1801 dlil_inject_pr_output(struct mbuf
*m
,
1802 struct sockaddr
*dest
,
1808 struct ifnet
*orig_ifp
= 0;
1810 struct dlil_filterq_entry
*tmp
;
1812 char frame_type_buffer
[MAX_FRAME_TYPE_SIZE
* 4];
1813 char dst_linkaddr_buffer
[MAX_LINKADDR
* 4];
1814 struct dlil_filterq_head
*fhead
;
1819 dlil_stats
.inject_pr_out1
++;
1822 bcopy(frame_type
, &frame_type_buffer
[0], MAX_FRAME_TYPE_SIZE
* 4);
1827 bcopy(dst_linkaddr
, &dst_linkaddr_buffer
, MAX_LINKADDR
* 4);
1832 if (from_id
> MAX_DLIL_FILTERS
)
1835 if (dlil_filters
[from_id
].type
!= DLIL_PR_FILTER
)
1838 ifp
= dlil_filters
[from_id
].ifp
;
1839 dl_tag
= dlil_filters
[from_id
].proto
->dl_tag
;
1842 frame_type
= frame_type_buffer
;
1843 dst_linkaddr
= dst_linkaddr_buffer
;
1845 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1848 * Run any attached protocol filters.
1852 if (TAILQ_EMPTY(dl_tag_array
[dl_tag
].pr_flt_head
) == 0) {
1853 TAILQ_FOREACH(tmp
, dl_tag_array
[dl_tag
].pr_flt_head
, que
) {
1854 if ((match_found
) && (PFILT(tmp
).filter_dl_output
)) {
1855 retval
= (*PFILT(tmp
).filter_dl_output
)(PFILT(tmp
).cookie
,
1856 &m
, &ifp
, &dest
, dst_linkaddr
, frame_type
);
1858 if (retval
== EJUSTRETURN
)
1867 if (tmp
->filter_id
== from_id
)
1874 * Call framing module
1876 if ((raw
== 0) && (ifp
->if_framer
)) {
1877 retval
= (*ifp
->if_framer
)(ifp
, &m
, dest
, dst_linkaddr
, frame_type
);
1879 if (retval
== EJUSTRETURN
)
1892 struct mbuf
*m0
= m
;
1894 if (m
->m_pkthdr
.rcvif
)
1895 m
->m_pkthdr
.rcvif
= NULL
;
1896 ifp
= bridge_dst_lookup(m
);
1897 bdg_forward(&m0
, ifp
);
1907 * Let interface filters (if any) do their thing ...
1910 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1911 if (TAILQ_EMPTY(fhead
) == 0) {
1912 while (orig_ifp
!= ifp
) {
1914 TAILQ_FOREACH(tmp
, fhead
, que
) {
1915 if (IFILT(tmp
).filter_if_output
) {
1916 retval
= (*IFILT(tmp
).filter_if_output
)(IFILT(tmp
).cookie
,
1920 if (retval
== EJUSTRETURN
)
1930 if (ifp
!= orig_ifp
)
1937 * Finally, call the driver.
1940 retval
= (*ifp
->if_output
)(ifp
, m
);
1941 dlil_stats
.inject_pr_out2
++;
1942 if ((retval
== 0) || (retval
== EJUSTRETURN
))
1950 dlil_inject_if_output(struct mbuf
*m
, u_long from_id
)
1952 struct ifnet
*orig_ifp
= 0;
1954 struct dlil_filterq_entry
*tmp
;
1956 struct dlil_filterq_head
*fhead
;
1960 dlil_stats
.inject_if_out1
++;
1961 if (from_id
> MAX_DLIL_FILTERS
)
1964 if (dlil_filters
[from_id
].type
!= DLIL_IF_FILTER
)
1967 ifp
= dlil_filters
[from_id
].ifp
;
1970 * Let interface filters (if any) do their thing ...
1973 fhead
= (struct dlil_filterq_head
*) &ifp
->if_flt_head
;
1976 if (TAILQ_EMPTY(fhead
) == 0) {
1977 while (orig_ifp
!= ifp
) {
1979 TAILQ_FOREACH(tmp
, fhead
, que
) {
1980 if ((match_found
) && (IFILT(tmp
).filter_if_output
)) {
1981 retval
= (*IFILT(tmp
).filter_if_output
)(IFILT(tmp
).cookie
,
1985 if (retval
== EJUSTRETURN
)
1995 if (ifp
!= orig_ifp
)
1998 if (from_id
== tmp
->filter_id
)
2005 * Finally, call the driver.
2008 retval
= (*ifp
->if_output
)(ifp
, m
);
2009 dlil_stats
.inject_if_out2
++;
2010 if ((retval
== 0) || (retval
== EJUSTRETURN
))