freebsd_network: Adaptations in preparation for the OpenBSD layer.

Most of these changes however add things that FreeBSD has (with a few
exceptions noted in comments) which the OpenBSD shim layer merely needs
to make use of.

(FreeBSD used to have support for IFF_NEEDSGIANT but removed it. The
support instated here is very similar to what FreeBSD used to have.)
This commit is contained in:
Augustin Cavalier
2022-06-09 01:28:54 -04:00
parent 6a9406a172
commit 8548a4adc6
22 changed files with 309 additions and 69 deletions
+1
View File
@@ -25,6 +25,7 @@ KernelStaticLibrary libfreebsd_network.a :
fbsd_subr_bufring.c
fbsd_subr_sbuf.c
fbsd_time.c
fbsd_timingsafe.c
fbsd_usb_error.c
fbsd_usb_util.c
fbsd_usb_lookup.c
+23 -2
View File
@@ -297,6 +297,23 @@ rman_get_virtual(struct resource *res)
}
bus_addr_t
rman_get_start(struct resource *res)
{
return res->r_bushandle;
}
bus_size_t
rman_get_size(struct resource *res)
{
area_info info;
if (get_area_info(res->r_mapped_area, &info) != B_OK)
return 0;
return info.size;
}
// #pragma mark - Interrupt handling
@@ -329,7 +346,13 @@ intr_handler(void *data)
//device_printf(intr->dev, "in soft interrupt handler.\n");
atomic_or(&intr->handling, 1);
if ((intr->flags & INTR_MPSAFE) == 0)
mtx_lock(&Giant);
intr->handler(intr->arg);
if ((intr->flags & INTR_MPSAFE) == 0)
mtx_unlock(&Giant);
atomic_and(&intr->handling, 0);
HAIKU_REENABLE_INTERRUPTS(intr->dev);
}
@@ -355,8 +378,6 @@ int
bus_setup_intr(device_t dev, struct resource *res, int flags,
driver_filter_t* filter, driver_intr_t handler, void *arg, void **_cookie)
{
/* TODO check MPSAFE etc */
struct internal_intr *intr = (struct internal_intr *)malloc(
sizeof(struct internal_intr));
char semName[64];
+10
View File
@@ -5,6 +5,7 @@
#include <OS.h>
#include <compat/sys/kernel.h>
#include <compat/sys/time.h>
int32_t
@@ -12,3 +13,12 @@ _get_ticks()
{
return USEC_2_TICKS(system_time());
}
void
getmicrouptime(struct timeval *tvp)
{
bigtime_t usecs = system_time();
tvp->tv_sec = usecs / 1000000;
tvp->tv_usec = usecs % 1000000;
}
@@ -70,6 +70,7 @@
#define IFF_MONITOR 0x00400000 /* (n) user-requested monitor mode */
#define IFF_PPROMISC 0x00800000 /* (n) user-requested promisc mode */
#define IFF_NOGROUP 0x01000000 /* (n) interface is not part of any groups */
#define IFF_NEEDSGIANT 0x02000000 /* (i) hold Giant over hook calls (OpenBSD compatibility) */
#define LINK_STATE_UNKNOWN 0
#define LINK_STATE_DOWN 1
@@ -258,7 +258,6 @@ struct ifnet {
void *if_afdata[AF_MAX];
int if_afdata_initialized;
struct mtx if_afdata_mtx;
struct task if_starttask; /* task for IFF_NEEDSGIANT */
struct task if_linktask; /* task for link change events */
struct mtx if_addr_mtx; /* mutex to protect address lists */
@@ -752,6 +751,10 @@ int ifioctl(struct socket *, u_long, caddr_t, struct thread *);
int ifpromisc(struct ifnet *, int);
struct ifnet *ifunit(const char *);
/* Haiku extension for OpenBSD compat */
int if_alloc_inplace(struct ifnet *ifp, u_char type);
void if_free_inplace(struct ifnet *ifp);
struct ifaddr *ifa_ifwithaddr(struct sockaddr *);
struct ifaddr *ifa_ifwithbroadaddr(struct sockaddr *);
struct ifaddr *ifa_ifwithdstaddr(struct sockaddr *);
@@ -13,12 +13,17 @@
typedef void (*task_fn_t)(void *context, int pending);
struct task {
int ta_pending;
int ta_priority;
int ta_flags;
task_fn_t ta_handler;
void *ta_argument;
int ta_pending;
struct list_link ta_link;
};
#define TASK_NEEDSGIANT (1 << 0) /* Haiku extension, OpenBSD compatibility */
#endif
@@ -269,7 +269,7 @@ buf_ring_advance_sc(struct buf_ring *br)
static __inline void
buf_ring_putback_sc(struct buf_ring *br, void *_new)
{
KASSERT(br->br_cons_head != br->br_prod_tail,
KASSERT_FREEBSD(br->br_cons_head != br->br_prod_tail,
("Buf-Ring has none in putback")) ;
br->br_ring[br->br_cons_head] = _new;
}
@@ -207,8 +207,11 @@ enum {
FBSD_SWI_TASKQUEUE = 1 << 2,
FBSD_THREAD_TASKQUEUE = 1 << 3,
FBSD_WLAN_FEATURE = 1 << 4,
FBSD_WLAN = FBSD_WLAN_FEATURE | FBSD_TASKQUEUES
| FBSD_THREAD_TASKQUEUE,
OBSD_WLAN = FBSD_WLAN_FEATURE | FBSD_TASKQUEUES
| FBSD_FAST_TASKQUEUE,
};
#define HAIKU_DRIVER_REQUIREMENTS(flags) \
@@ -16,6 +16,9 @@ extern int random(void);
u_int read_random(void *, u_int);
void arc4rand(void *ptr, u_int len, int reseed);
uint32_t arc4random(void);
void arc4random_buf(void *ptr, size_t len);
int timingsafe_bcmp(const void *, const void *, size_t);
static __inline int imax(int a, int b) { return (a > b ? a : b); }
static __inline int imin(int a, int b) { return (a < b ? a : b); }
@@ -43,7 +43,7 @@ void _kernel_contigfree(void *addr, unsigned long size);
#define kernel_malloc(size, base, flags) \
_kernel_malloc(size, flags)
#define kernel_free(ptr, base) \
#define kernel_free(ptr, tag) \
_kernel_free(ptr)
#define kernel_contigmalloc(size, type, flags, low, high, alignment, boundary) \
@@ -212,6 +212,16 @@ m_cljset(struct mbuf *m, void *cl, int type)
m->m_flags |= M_EXT;
}
/* These are for OpenBSD compatibility. */
#define MTAG_ABI_COMPAT 0 /* compatibility ABI */
static __inline struct m_tag *
m_tag_find(struct mbuf *m, uint16_t type, struct m_tag *start)
{
return (SLIST_EMPTY(&m->m_pkthdr.tags) ? (struct m_tag *)NULL :
m_tag_locate(m, MTAG_ABI_COMPAT, type, start));
}
/* mbufq */
struct mbufq {
@@ -215,6 +215,12 @@ struct pkthdr {
uint8_t rsstype; /* hash type */
uint16_t tso_segsz;
uint16_t ether_vtag;
/* Layer specific non-persistent local storage for reassembly, etc. */
union {
uintptr_t unintptr[1];
void* ptr;
} PH_loc;
};
struct m_tag {
@@ -1,9 +1,3 @@
/*
* Copyright 2007, Hugo Santos. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
/*-
* Copyright 1998 Massachusetts Institute of Technology
*
@@ -61,30 +55,7 @@ bus_space_handle_t rman_get_bushandle(struct resource *);
bus_space_tag_t rman_get_bustag(struct resource *);
int rman_get_rid(struct resource *);
void* rman_get_virtual(struct resource *);
bus_addr_t rman_get_start(struct resource *);
bus_size_t rman_get_size(struct resource *);
static inline u_long
rman_get_start(struct resource *resourcePointer)
{
return resourcePointer->r_bushandle;
}
static inline uint32_t
rman_make_alignment_flags(uint32_t size)
{
int i;
/*
* Find the hightest bit set, and add one if more than one bit
* set. We're effectively computing the ceil(log2(size)) here.
*/
for (i = 31; i > 0; i--)
if ((1 << i) & size)
break;
if (~(1 << i) & size)
i++;
return RF_ALIGNMENT_LOG2(i);
}
#endif /* _FBSD_COMPAT_SYS_RMAN_H_ */
@@ -1,5 +1,5 @@
/*
* Copyright 2009 Haiku Inc. All rights reserved.
* Copyright 2009-2022, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _FBSD_COMPAT_SYS_SYSLOG_H_
@@ -7,5 +7,7 @@
#define LOG_ERR 3 /* error conditions */
#define LOG_WARNING 4 /* warning conditions */
#endif /* _FBSD_COMPAT_SYS_SYSLOG_H_ */
@@ -41,13 +41,14 @@ int printf(const char *format, ...) __printflike(1, 2);
#endif
#ifdef INVARIANTS
#define KASSERT(cond,msg) do { \
#define KASSERT_FREEBSD(cond,msg) do { \
if (!(cond)) \
panic msg; \
} while (0)
#define KASSERT(cond,msg) KASSERT_FREEBSD(cond,msg)
#else
#define KASSERT(exp,msg) do { \
} while (0)
#define KASSERT_FREEBSD(exp,msg) do {} while (0)
#define KASSERT(cond,msg) KASSERT_FREEBSD(cond,msg)
#endif
#define DELAY(n) \
@@ -1,6 +1,39 @@
/*
* Copyright 2020, Haiku, Inc. All rights reserved.
* All rights reserved. Distributed under the terms of the MIT License.
* Copyright 2020-2022, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)time.h 8.5 (Berkeley) 5/4/95
* $FreeBSD$
*/
#ifndef _FBSD_COMPAT_SYS_TIME_H_
#define _FBSD_COMPAT_SYS_TIME_H_
@@ -21,7 +54,21 @@
#define time_uptime USEC_2_TICKS(system_time())
int ppsratecheck(struct timeval*, int*, int);
/* Operations on timevals. */
#define timevalclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0)
#define timevalisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
#define timevalcmp(tvp, uvp, cmp) \
(((tvp)->tv_sec == (uvp)->tv_sec) ? \
((tvp)->tv_usec cmp (uvp)->tv_usec) : \
((tvp)->tv_sec cmp (uvp)->tv_sec))
void getmicrouptime(struct timeval *tvp);
int ppsratecheck(struct timeval *, int *, int);
int ratecheck(struct timeval *, const struct timeval *);
void timevaladd(struct timeval *t1, const struct timeval *t2);
void timevalsub(struct timeval *t1, const struct timeval *t2);
#endif /* _FBSD_COMPAT_SYS_TIME_H_ */
+29 -6
View File
@@ -49,6 +49,8 @@ compat_open(const char *name, uint32 flags, void **cookie)
return B_BUSY;
}
IFF_LOCKGIANT(ifp);
ifp->if_init(ifp->if_softc);
if (!HAIKU_DRIVER_REQUIRES(FBSD_WLAN_FEATURE)) {
@@ -68,6 +70,8 @@ compat_open(const char *name, uint32 flags, void **cookie)
ifp->flags &= ~DEVICE_CLOSED;
ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL);
IFF_UNLOCKGIANT(ifp);
*cookie = ifp;
return B_OK;
}
@@ -184,7 +188,11 @@ compat_write(void *cookie, off_t position, const void *buffer,
memcpy(mtod(mb, void *), buffer, mb->m_len);
*numBytes = length;
return ifp->if_output(ifp, mb, NULL, NULL);
IFF_LOCKGIANT(ifp);
int result = ifp->if_output(ifp, mb, NULL, NULL);
IFF_UNLOCKGIANT(ifp);
return result;
}
@@ -192,6 +200,7 @@ static status_t
compat_control(void *cookie, uint32 op, void *arg, size_t length)
{
struct ifnet *ifp = cookie;
status_t status;
//if_printf(ifp, "compat_control(op %lu, %p, [%lu])\n", op,
// arg, length);
@@ -228,7 +237,11 @@ compat_control(void *cookie, uint32 op, void *arg, size_t length)
ifp->if_flags |= IFF_PROMISC;
else
ifp->if_flags &= ~IFF_PROMISC;
return ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL);
IFF_LOCKGIANT(ifp);
status = ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL);
IFF_UNLOCKGIANT(ifp);
return status;
}
case ETHER_GETFRAMESIZE:
@@ -273,10 +286,13 @@ compat_control(void *cookie, uint32 op, void *arg, size_t length)
if (user_memcpy(LLADDR(&address), arg, ETHER_ADDR_LEN) < B_OK)
return B_BAD_ADDRESS;
IFF_LOCKGIANT(ifp);
if (op == ETHER_ADDMULTI)
return if_addmulti(ifp, (struct sockaddr *)&address, NULL);
return if_delmulti(ifp, (struct sockaddr *)&address);
status = if_addmulti(ifp, (struct sockaddr *)&address, NULL);
else
status = if_delmulti(ifp, (struct sockaddr *)&address);
IFF_UNLOCKGIANT(ifp);
return status;
}
case ETHER_GET_LINK_STATE:
@@ -289,7 +305,9 @@ compat_control(void *cookie, uint32 op, void *arg, size_t length)
return EINVAL;
memset(&mediareq, 0, sizeof(mediareq));
IFF_LOCKGIANT(ifp);
status = ifp->if_ioctl(ifp, SIOCGIFMEDIA, (caddr_t)&mediareq);
IFF_UNLOCKGIANT(ifp);
if (status < B_OK)
return status;
@@ -313,7 +331,12 @@ compat_control(void *cookie, uint32 op, void *arg, size_t length)
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
case SIOCSIFMTU:
return ifp->if_ioctl(ifp, op, (caddr_t)arg);
{
IFF_LOCKGIANT(ifp);
status = ifp->if_ioctl(ifp, op, (caddr_t)arg);
IFF_UNLOCKGIANT(ifp);
return status;
}
}
return wlan_control(cookie, op, arg, length);
+80 -1
View File
@@ -31,6 +31,46 @@
#include <sys/kernel.h>
#include <sys/time.h>
/*
* ratecheck(): simple time-based rate-limit checking.
*/
int
ratecheck(struct timeval *lasttime, const struct timeval *mininterval)
{
struct timeval tv, delta;
int rv = 0;
getmicrouptime(&tv); /* NB: 10ms precision */
delta = tv;
timevalsub(&delta, lasttime);
/*
* check for 0,0 is so that the message will be seen at least once,
* even if interval is huge.
*/
if (timevalcmp(&delta, mininterval, >=) ||
(lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) {
*lasttime = tv;
rv = 1;
}
return (rv);
}
/*
* ppsratecheck(): packets (or events) per second limitation.
*
* Return 0 if the limit is to be enforced (e.g. the caller
* should drop a packet because of the rate limitation).
*
* maxpps of 0 always causes zero to be returned. maxpps of -1
* always causes 1 to be returned; this effectively defeats rate
* limiting.
*
* Note that we maintain the struct timeval for compatibility
* with other bsd systems. We reuse the storage and just monitor
* clock ticks for minimal overhead.
*/
int
ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps)
{
@@ -48,6 +88,45 @@ ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps)
return (maxpps != 0);
} else {
(*curpps)++; /* NB: ignore potential overflow */
return (maxpps < 0 || *curpps < maxpps);
return (maxpps < 0 || *curpps <= maxpps);
}
}
static void
timevalfix(struct timeval *t1)
{
if (t1->tv_usec < 0) {
t1->tv_sec--;
t1->tv_usec += 1000000;
}
if (t1->tv_usec >= 1000000) {
t1->tv_sec++;
t1->tv_usec -= 1000000;
}
}
/*
* Add and subtract routines for timevals.
* N.B.: subtract routine doesn't deal with
* results which are before the beginning,
* it just gets very confused in this case.
* Caveat emptor.
*/
void
timevaladd(struct timeval *t1, const struct timeval *t2)
{
t1->tv_sec += t2->tv_sec;
t1->tv_usec += t2->tv_usec;
timevalfix(t1);
}
void
timevalsub(struct timeval *t1, const struct timeval *t2)
{
t1->tv_sec -= t2->tv_sec;
t1->tv_usec -= t2->tv_usec;
timevalfix(t1);
}
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2010 Damien Miller. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/libkern.h>
int
timingsafe_bcmp(const void *b1, const void *b2, size_t n)
{
const unsigned char *p1 = b1, *p2 = b2;
int ret = 0;
for (; n > 0; n--)
ret |= *p1++ ^ *p2++;
return (ret != 0);
}
+29 -16
View File
@@ -149,21 +149,17 @@ ifindex_free_locked(u_short idx)
}
struct ifnet *
if_alloc(u_char type)
int
if_alloc_inplace(struct ifnet *ifp, u_char type)
{
char semName[64];
u_short index;
struct ifnet *ifp = _kernel_malloc(sizeof(struct ifnet), M_ZERO);
if (ifp == NULL)
return NULL;
snprintf(semName, sizeof(semName), "%s receive", gDriverName);
ifp->receive_sem = create_sem(0, semName);
if (ifp->receive_sem < B_OK)
goto err1;
return ifp->receive_sem;
ifp->link_state_sem = -1;
ifp->open_count = 0;
@@ -188,7 +184,7 @@ if_alloc(u_char type)
ifnet_setbyindex(ifp->if_index, ifp);
IF_ADDR_LOCK_INIT(ifp);
return ifp;
return 0;
err3:
switch (type) {
@@ -200,14 +196,28 @@ err3:
err2:
delete_sem(ifp->receive_sem);
err1:
_kernel_free(ifp);
return NULL;
return -1;
}
struct ifnet *
if_alloc(u_char type)
{
struct ifnet *ifp = _kernel_malloc(sizeof(struct ifnet), M_ZERO);
if (ifp == NULL)
return NULL;
if (if_alloc_inplace(ifp, type) != 0) {
_kernel_free(ifp);
return NULL;
}
return ifp;
}
void
if_free(struct ifnet *ifp)
if_free_inplace(struct ifnet *ifp)
{
// IEEE80211 devices won't be in this list,
// so don't try to remove them.
@@ -227,6 +237,13 @@ if_free(struct ifnet *ifp)
delete_sem(ifp->receive_sem);
ifq_uninit(&ifp->receive_queue);
}
void
if_free(struct ifnet *ifp)
{
if_free_inplace(ifp);
_kernel_free(ifp);
}
@@ -397,10 +414,6 @@ if_detach(struct ifnet *ifp)
void
if_start(struct ifnet *ifp)
{
#ifdef IFF_NEEDSGIANT
if (ifp->if_flags & IFF_NEEDSGIANT)
panic("freebsd compat.: unsupported giant requirement");
#endif
ifp->if_start(ifp);
}
+8 -2
View File
@@ -1,6 +1,5 @@
/*
* Copyright 2009, Colin Günther, coling@gmx.de. All rights reserved.
* Copyright 2018, Haiku, Inc. All rights reserved.
* Copyright 2018-2022, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
@@ -36,3 +35,10 @@ arc4random(void)
arc4rand(&ret, sizeof ret, 0);
return ret;
}
void
arc4random_buf(void *ptr, size_t len)
{
arc4rand(ptr, len, 0);
}
@@ -127,7 +127,13 @@ tq_handle_thread(void *data)
pending = t->ta_pending;
t->ta_pending = 0;
if ((t->ta_flags & TASK_NEEDSGIANT) != 0)
mtx_lock(&Giant);
t->ta_handler(t->ta_argument, pending);
if ((t->ta_flags & TASK_NEEDSGIANT) != 0)
mtx_unlock(&Giant);
}
return 0;
@@ -489,6 +495,7 @@ void
task_init(struct task *task, int prio, task_fn_t handler, void *context)
{
task->ta_priority = prio;
task->ta_flags = 0;
task->ta_handler = handler;
task->ta_argument = context;
task->ta_pending = 0;