2 * Copyright 2009, Colin Günther, coling@gmx.de.
3 * Copyright 2007-2009, Axel Dörfler, axeld@pinc-software.de.
4 * Copyright 2007, Hugo Santos. All Rights Reserved.
5 * Copyright 2004, Marcus Overhagen. All Rights Reserved.
7 * Distributed under the terms of the MIT License.
14 #include <net/if_types.h>
15 #include <sys/sockio.h>
17 #include <compat/sys/bus.h>
18 #include <compat/sys/kernel.h>
19 #include <compat/sys/taskqueue.h>
21 #include <compat/net/if.h>
22 #include <compat/net/if_arp.h>
23 #include <compat/net/if_media.h>
24 #include <compat/net/if_var.h>
25 #include <compat/sys/malloc.h>
27 #include <compat/net/ethernet.h>
30 int ifqmaxlen
= IFQ_MAXLEN
;
33 #define IFNET_HOLD (void *)(uintptr_t)(-1)
37 insert_into_device_name_list(struct ifnet
* ifp
)
40 for (i
= 0; i
< MAX_DEVICES
; i
++) {
41 if (gDeviceNameList
[i
] == NULL
) {
42 gDeviceNameList
[i
] = ifp
->device_name
;
47 panic("too many devices");
52 remove_from_device_name_list(struct ifnet
* ifp
)
55 for (i
= 0; i
< MAX_DEVICES
; i
++) {
56 if (ifp
->device_name
== gDeviceNameList
[i
]) {
58 for (last
= i
+ 1; last
< MAX_DEVICES
; last
++) {
59 if (gDeviceNameList
[last
] == NULL
)
65 gDeviceNameList
[i
] = NULL
;
67 // switch positions with the last entry
68 gDeviceNameList
[i
] = gDeviceNameList
[last
];
69 gDeviceNameList
[last
] = NULL
;
78 ifnet_byindex(u_short idx
)
82 IFNET_RLOCK_NOSLEEP();
83 ifp
= ifnet_byindex_locked(idx
);
84 IFNET_RUNLOCK_NOSLEEP();
91 ifnet_byindex_locked(u_short idx
)
102 ifnet_setbyindex_locked(u_short idx
, struct ifnet
*ifp
)
109 ifnet_setbyindex(u_short idx
, struct ifnet
*ifp
)
112 ifnet_setbyindex_locked(idx
, ifp
);
118 ifindex_alloc_locked(u_short
*idxp
)
122 for (index
= 0; index
< MAX_DEVICES
; index
++) {
123 if (gDevices
[index
] == NULL
) {
128 if (index
== MAX_DEVICES
)
139 ifindex_free_locked(u_short idx
)
141 gDevices
[idx
] = NULL
;
147 if_alloc(u_char type
)
152 struct ifnet
*ifp
= _kernel_malloc(sizeof(struct ifnet
), M_ZERO
);
156 snprintf(semName
, sizeof(semName
), "%s receive", gDriverName
);
158 ifp
->receive_sem
= create_sem(0, semName
);
159 if (ifp
->receive_sem
< B_OK
)
165 ifp
->if_l2com
= _kernel_malloc(sizeof(struct arpcom
), M_ZERO
);
166 if (ifp
->if_l2com
== NULL
)
168 IFP2AC(ifp
)->ac_ifp
= ifp
;
173 if (wlan_if_l2com_alloc(ifp
) != B_OK
)
179 ifp
->link_state_sem
= -1;
183 ifq_init(&ifp
->receive_queue
, semName
);
185 ifp
->scan_done_sem
= -1;
186 // WLAN specific, doesn't hurt when initilized for other devices
188 // Search for the first free device slot, and use that one
190 if (ifindex_alloc_locked(&index
) != ENOERR
) {
192 panic("too many devices");
195 ifnet_setbyindex_locked(index
, IFNET_HOLD
);
198 ifp
->if_index
= index
;
199 ifnet_setbyindex(ifp
->if_index
, ifp
);
201 IF_ADDR_LOCK_INIT(ifp
);
208 _kernel_free(ifp
->if_l2com
);
213 delete_sem(ifp
->receive_sem
);
222 if_free(struct ifnet
*ifp
)
224 // IEEE80211 devices won't be in this list,
225 // so don't try to remove them.
226 if (ifp
->if_type
== IFT_ETHER
)
227 remove_from_device_name_list(ifp
);
230 ifindex_free_locked(ifp
->if_index
);
233 IF_ADDR_LOCK_DESTROY(ifp
);
234 switch (ifp
->if_type
) {
237 _kernel_free(ifp
->if_l2com
);
241 delete_sem(ifp
->receive_sem
);
242 ifq_uninit(&ifp
->receive_queue
);
249 if_initname(struct ifnet
*ifp
, const char *name
, int unit
)
251 dprintf("if_initname(%p, %s, %d)\n", ifp
, name
, unit
);
253 if (name
== NULL
|| name
[0] == '\0')
254 panic("interface goes unnamed");
256 ifp
->if_dname
= name
;
257 ifp
->if_dunit
= unit
;
259 strlcpy(ifp
->if_xname
, name
, sizeof(ifp
->if_xname
));
261 snprintf(ifp
->device_name
, sizeof(ifp
->device_name
), "net/%s/%i",
262 gDriverName
, ifp
->if_index
);
264 driver_printf("%s: /dev/%s\n", gDriverName
, ifp
->device_name
);
266 // For wlan devices we only want to see the cloned wlan device
268 // Remember: For each wlan device, there is a base device of type
269 // IFT_IEEE80211. On top of that a clone device is created of
271 // Haiku shall only see the cloned device as it is the one
272 // FreeBSD 8 uses for wireless i/o, too.
273 if (ifp
->if_type
== IFT_ETHER
)
274 insert_into_device_name_list(ifp
);
276 ifp
->root_device
= find_root_device(unit
);
281 ifq_init(struct ifqueue
*ifq
, const char *name
)
283 ifq
->ifq_head
= NULL
;
284 ifq
->ifq_tail
= NULL
;
286 ifq
->ifq_maxlen
= IFQ_MAXLEN
;
289 mtx_init(&ifq
->ifq_mtx
, name
, NULL
, MTX_DEF
);
294 ifq_uninit(struct ifqueue
*ifq
)
296 mtx_destroy(&ifq
->ifq_mtx
);
301 if_transmit(struct ifnet
*ifp
, struct mbuf
*m
)
305 IFQ_HANDOFF(ifp
, m
, error
);
311 if_attach(struct ifnet
*ifp
)
313 TAILQ_INIT(&ifp
->if_addrhead
);
314 TAILQ_INIT(&ifp
->if_prefixhead
);
315 TAILQ_INIT(&ifp
->if_multiaddrs
);
317 IF_ADDR_LOCK_INIT(ifp
);
319 ifp
->if_lladdr
.sdl_family
= AF_LINK
;
321 ifq_init((struct ifqueue
*) &ifp
->if_snd
, ifp
->if_xname
);
323 if (ifp
->if_transmit
== NULL
) {
324 ifp
->if_transmit
= if_transmit
;
330 if_detach(struct ifnet
*ifp
)
332 if (HAIKU_DRIVER_REQUIRES(FBSD_SWI_TASKQUEUE
))
333 taskqueue_drain(taskqueue_swi
, &ifp
->if_linktask
);
335 IF_ADDR_LOCK_DESTROY(ifp
);
336 ifq_uninit((struct ifqueue
*) &ifp
->if_snd
);
341 if_start(struct ifnet
*ifp
)
343 #ifdef IFF_NEEDSGIANT
344 if (ifp
->if_flags
& IFF_NEEDSGIANT
)
345 panic("freebsd compat.: unsupported giant requirement");
352 if_printf(struct ifnet
*ifp
, const char *format
, ...)
356 va_start(vl
, format
);
357 vsnprintf(buf
, sizeof(buf
), format
, vl
);
360 dprintf("[%s] %s", ifp
->device_name
, buf
);
366 if_link_state_change(struct ifnet
*ifp
, int linkState
)
368 if (ifp
->if_link_state
== linkState
)
371 ifp
->if_link_state
= linkState
;
372 release_sem_etc(ifp
->link_state_sem
, 1, B_DO_NOT_RESCHEDULE
);
376 static struct ifmultiaddr
*
377 if_findmulti(struct ifnet
*ifp
, struct sockaddr
*_address
)
379 struct sockaddr_dl
*address
= (struct sockaddr_dl
*) _address
;
380 struct ifmultiaddr
*ifma
;
382 TAILQ_FOREACH (ifma
, &ifp
->if_multiaddrs
, ifma_link
) {
383 if (memcmp(LLADDR(address
),
384 LLADDR((struct sockaddr_dl
*)ifma
->ifma_addr
), ETHER_ADDR_LEN
) == 0)
393 * if_freemulti: free ifmultiaddr structure and possibly attached related
394 * addresses. The caller is responsible for implementing reference
395 * counting, notifying the driver, handling routing messages, and releasing
396 * any dependent link layer state.
399 if_freemulti(struct ifmultiaddr
*ifma
)
402 KASSERT(ifma
->ifma_refcount
== 0, ("if_freemulti: refcount %d",
403 ifma
->ifma_refcount
));
404 KASSERT(ifma
->ifma_protospec
== NULL
,
405 ("if_freemulti: protospec not NULL"));
407 if (ifma
->ifma_lladdr
!= NULL
)
408 free(ifma
->ifma_lladdr
);
410 // Haiku note: We use a field in the ifmultiaddr struct (ifma_addr_storage)
411 // to store the address and let ifma_addr point to that. We therefore do not
412 // free it here, as it will be freed as part of freeing the if_multiaddr.
413 //free(ifma->ifma_addr);
419 static struct ifmultiaddr
*
420 _if_addmulti(struct ifnet
*ifp
, struct sockaddr
*address
)
422 struct ifmultiaddr
*addr
= if_findmulti(ifp
, address
);
425 addr
->ifma_refcount
++;
429 addr
= (struct ifmultiaddr
*) malloc(sizeof(struct ifmultiaddr
));
433 addr
->ifma_lladdr
= NULL
;
434 addr
->ifma_ifp
= ifp
;
435 addr
->ifma_protospec
= NULL
;
437 memcpy(&addr
->ifma_addr_storage
, address
, sizeof(struct sockaddr_dl
));
438 addr
->ifma_addr
= (struct sockaddr
*) &addr
->ifma_addr_storage
;
440 addr
->ifma_refcount
= 1;
442 TAILQ_INSERT_HEAD(&ifp
->if_multiaddrs
, addr
, ifma_link
);
449 if_addmulti(struct ifnet
*ifp
, struct sockaddr
*address
,
450 struct ifmultiaddr
**out
)
452 struct ifmultiaddr
*result
;
456 result
= _if_addmulti(ifp
, address
);
458 refcount
= result
->ifma_refcount
;
464 if (refcount
== 1 && ifp
->if_ioctl
!= NULL
)
465 ifp
->if_ioctl(ifp
, SIOCADDMULTI
, NULL
);
475 if_delmulti_locked(struct ifnet
*ifp
, struct ifmultiaddr
*ifma
, int detaching
)
477 struct ifmultiaddr
*ll_ifma
;
479 if (ifp
!= NULL
&& ifma
->ifma_ifp
!= NULL
) {
480 KASSERT(ifma
->ifma_ifp
== ifp
,
481 ("%s: inconsistent ifp %p", __func__
, ifp
));
482 IF_ADDR_LOCK_ASSERT(ifp
);
485 ifp
= ifma
->ifma_ifp
;
488 * If the ifnet is detaching, null out references to ifnet,
489 * so that upper protocol layers will notice, and not attempt
490 * to obtain locks for an ifnet which no longer exists. The
491 * routing socket announcement must happen before the ifnet
492 * instance is detached from the system.
496 printf("%s: detaching ifnet instance %p\n", __func__
, ifp
);
499 * ifp may already be nulled out if we are being reentered
500 * to delete the ll_ifma.
504 rt_newmaddrmsg(RTM_DELMADDR
, ifma
);
506 ifma
->ifma_ifp
= NULL
;
510 if (--ifma
->ifma_refcount
> 0)
515 * If this ifma is a network-layer ifma, a link-layer ifma may
516 * have been associated with it. Release it first if so.
518 ll_ifma
= ifma
->ifma_llifma
;
519 if (ll_ifma
!= NULL
) {
520 KASSERT(ifma
->ifma_lladdr
!= NULL
,
521 ("%s: llifma w/o lladdr", __func__
));
523 ll_ifma
->ifma_ifp
= NULL
; /* XXX */
524 if (--ll_ifma
->ifma_refcount
== 0) {
526 TAILQ_REMOVE(&ifp
->if_multiaddrs
, ll_ifma
,
529 if_freemulti(ll_ifma
);
535 TAILQ_REMOVE(&ifp
->if_multiaddrs
, ifma
, ifma_link
);
540 * The last reference to this instance of struct ifmultiaddr
541 * was released; the hardware should be notified of this change.
548 * Delete all multicast group membership for an interface.
549 * Should be used to quickly flush all multicast filters.
552 if_delallmulti(struct ifnet
*ifp
)
554 struct ifmultiaddr
*ifma
;
555 struct ifmultiaddr
*next
;
558 TAILQ_FOREACH_SAFE(ifma
, &ifp
->if_multiaddrs
, ifma_link
, next
)
559 if_delmulti_locked(ifp
, ifma
, 0);
565 if_delete_multiaddr(struct ifnet
*ifp
, struct ifmultiaddr
*ifma
)
567 TAILQ_REMOVE(&ifp
->if_multiaddrs
, ifma
, ifma_link
);
573 if_delmulti(struct ifnet
*ifp
, struct sockaddr
*sa
)
575 struct ifmultiaddr
*ifma
;
580 IFNET_RLOCK_NOSLEEP();
581 TAILQ_FOREACH(oifp
, &V_ifnet
, if_link
)
586 IFNET_RUNLOCK_NOSLEEP();
588 KASSERT(ifp
!= NULL
, ("%s: ifnet went away", __func__
));
595 ifma
= if_findmulti(ifp
, sa
);
597 lastref
= if_delmulti_locked(ifp
, ifma
, 0);
603 if (lastref
&& ifp
->if_ioctl
!= NULL
) {
604 (void)(*ifp
->if_ioctl
)(ifp
, SIOCDELMULTI
, 0);
612 if_purgemaddrs(struct ifnet
*ifp
)
614 struct ifmultiaddr
*ifma
;
615 struct ifmultiaddr
*next
;
618 TAILQ_FOREACH_SAFE(ifma
, &ifp
->if_multiaddrs
, ifma_link
, next
)
619 if_delmulti_locked(ifp
, ifma
, 1);
625 if_addr_rlock(struct ifnet
*ifp
)
632 if_addr_runlock(struct ifnet
*ifp
)
639 if_maddr_rlock(struct ifnet
*ifp
)
646 if_maddr_runlock(struct ifnet
*ifp
)
653 ether_output(struct ifnet
*ifp
, struct mbuf
*m
, struct sockaddr
*dst
,
657 IFQ_HANDOFF(ifp
, m
, error
);
662 static void ether_input(struct ifnet
*ifp
, struct mbuf
*m
)
664 IF_ENQUEUE(&ifp
->receive_queue
, m
);
665 release_sem_etc(ifp
->receive_sem
, 1, B_DO_NOT_RESCHEDULE
);
670 ether_ifattach(struct ifnet
*ifp
, const uint8_t *macAddress
)
672 ifp
->if_addrlen
= ETHER_ADDR_LEN
;
673 ifp
->if_hdrlen
= ETHER_HDR_LEN
;
675 ifp
->if_mtu
= ETHERMTU
;
676 ifp
->if_output
= ether_output
;
677 ifp
->if_input
= ether_input
;
678 ifp
->if_resolvemulti
= NULL
; // done in the stack
679 ifp
->if_broadcastaddr
= etherbroadcastaddr
;
681 memcpy(IF_LLADDR(ifp
), macAddress
, ETHER_ADDR_LEN
);
683 // TODO: according to FreeBSD's if_ethersubr.c, this should be removed
684 // once all drivers are cleaned up.
685 if (macAddress
!= IFP2ENADDR(ifp
))
686 memcpy(IFP2ENADDR(ifp
), macAddress
, ETHER_ADDR_LEN
);
691 ether_ifdetach(struct ifnet
*ifp
)
698 ether_ioctl(struct ifnet
*ifp
, u_long command
, caddr_t data
)
700 struct ifreq
*ifr
= (struct ifreq
*) data
;
704 if (ifr
->ifr_mtu
> ETHERMTU
)
708 // need to fix our ifreq to work with C...
709 // ifp->ifr_mtu = ifr->ifr_mtu;
721 if_inc_counter(struct ifnet
*ifp
, ift_counter cnt
, int64_t inc
)
724 case IFCOUNTER_IPACKETS
:
725 atomic_add(&ifp
->if_ipackets
, inc
);
727 case IFCOUNTER_IERRORS
:
728 atomic_add(&ifp
->if_ierrors
, inc
);
730 case IFCOUNTER_OPACKETS
:
731 atomic_add(&ifp
->if_opackets
, inc
);
733 case IFCOUNTER_OERRORS
:
734 atomic_add(&ifp
->if_oerrors
, inc
);
736 case IFCOUNTER_COLLISIONS
:
737 atomic_add(&ifp
->if_collisions
, inc
);
739 case IFCOUNTER_IBYTES
:
740 atomic_add(&ifp
->if_ibytes
, inc
);
742 case IFCOUNTER_OBYTES
:
743 atomic_add(&ifp
->if_obytes
, inc
);
745 case IFCOUNTER_IMCASTS
:
746 atomic_add(&ifp
->if_imcasts
, inc
);
748 case IFCOUNTER_OMCASTS
:
749 atomic_add(&ifp
->if_omcasts
, inc
);
751 case IFCOUNTER_IQDROPS
:
752 atomic_add(&ifp
->if_iqdrops
, inc
);
754 case IFCOUNTER_OQDROPS
:
755 atomic_add(&ifp
->if_oqdrops
, inc
);
757 case IFCOUNTER_NOPROTO
:
758 atomic_add(&ifp
->if_noproto
, inc
);
761 KASSERT(cnt
< IFCOUNTERS
, ("%s: invalid cnt %d", __func__
, cnt
));