File: [local] / src / sys / net / if_etherbridge.h (download)
Revision 1.4, Mon Jul 5 04:17:41 2021 UTC (2 years, 11 months ago) by dlg
Branch: MAIN
CVS Tags: OPENBSD_7_5_BASE, OPENBSD_7_5, OPENBSD_7_4_BASE, OPENBSD_7_4, OPENBSD_7_3_BASE, OPENBSD_7_3, OPENBSD_7_2_BASE, OPENBSD_7_2, OPENBSD_7_1_BASE, OPENBSD_7_1, OPENBSD_7_0_BASE, OPENBSD_7_0, HEAD Changes since 1.3: +1 -2 lines
etherbridge_map was way too clever, so simplify it.
the code tried to carry state from the quick smr based lookup through
to the actual map update under the mutex, but this led to refcnt
leaks, and logic errors. the simplification is that if the smr based
checks say the map needs updating, we prepare the update and then
forget what we learnt inside the smr critical section and redo them
under the mutex again.
entries in an etherbridge map are either in it or they aren't, so
we don't need to refcnt them. this means the thing that takes an
entry out of the map becomes directly responsible for destroy it,
so they can do the smr call or barrier directly rather than via a
refcnt.
found by hrvoje popovski while testing the stack running in parallel,
and fix tested by him too.
ok sashan@
|
/* $OpenBSD: if_etherbridge.h,v 1.4 2021/07/05 04:17:41 dlg Exp $ */
/*
* Copyright (c) 2018, 2021 David Gwynne <dlg@openbsd.org>
*
* 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.
*/
#ifndef _NET_ETHERBRIDGE_H_
#define _NET_ETHERBRIDGE_H_
#define ETHERBRIDGE_TABLE_BITS 8
#define ETHERBRIDGE_TABLE_SIZE (1U << ETHERBRIDGE_TABLE_BITS)
#define ETHERBRIDGE_TABLE_MASK (ETHERBRIDGE_TABLE_SIZE - 1)
struct etherbridge_ops {
int (*eb_op_port_eq)(void *, void *, void *);
void *(*eb_op_port_take)(void *, void *);
void (*eb_op_port_rele)(void *, void *);
size_t (*eb_op_port_ifname)(void *, char *, size_t, void *);
void (*eb_op_port_sa)(void *, struct sockaddr_storage *, void *);
};
struct etherbridge;
struct eb_entry {
SMR_TAILQ_ENTRY(eb_entry) ebe_lentry;
union {
RBT_ENTRY(eb_entry) _ebe_tentry;
TAILQ_ENTRY(eb_entry) _ebe_qentry;
} _ebe_entries;
#define ebe_tentry _ebe_entries._ebe_tentry
#define ebe_qentry _ebe_entries._ebe_qentry
uint64_t ebe_addr;
void *ebe_port;
unsigned int ebe_type;
#define EBE_DYNAMIC 0x0
#define EBE_STATIC 0x1
#define EBE_DEAD 0xdead
time_t ebe_age;
struct etherbridge *ebe_etherbridge;
struct smr_entry ebe_smr_entry;
};
SMR_TAILQ_HEAD(eb_list, eb_entry);
RBT_HEAD(eb_tree, eb_entry);
TAILQ_HEAD(eb_queue, eb_entry);
struct etherbridge {
const char *eb_name;
const struct etherbridge_ops *eb_ops;
void *eb_cookie;
struct mutex eb_lock;
unsigned int eb_num;
unsigned int eb_max;
int eb_max_age; /* seconds */
struct timeout eb_tmo_age;
struct eb_list *eb_table;
struct eb_tree eb_tree;
};
int etherbridge_init(struct etherbridge *, const char *,
const struct etherbridge_ops *, void *);
int etherbridge_up(struct etherbridge *);
int etherbridge_down(struct etherbridge *);
void etherbridge_destroy(struct etherbridge *);
void etherbridge_map(struct etherbridge *, void *, uint64_t);
void etherbridge_map_ea(struct etherbridge *, void *,
const struct ether_addr *);
void *etherbridge_resolve(struct etherbridge *, uint64_t);
void *etherbridge_resolve_ea(struct etherbridge *,
const struct ether_addr *);
void etherbridge_detach_port(struct etherbridge *, void *);
/* ioctl support */
int etherbridge_set_max(struct etherbridge *, struct ifbrparam *);
int etherbridge_get_max(struct etherbridge *, struct ifbrparam *);
int etherbridge_set_tmo(struct etherbridge *, struct ifbrparam *);
int etherbridge_get_tmo(struct etherbridge *, struct ifbrparam *);
int etherbridge_rtfind(struct etherbridge *, struct ifbaconf *);
int etherbridge_add_addr(struct etherbridge *, void *,
const struct ether_addr *, unsigned int);
int etherbridge_del_addr(struct etherbridge *, const struct ether_addr *);
void etherbridge_flush(struct etherbridge *, uint32_t);
static inline unsigned int
etherbridge_num(const struct etherbridge *eb)
{
return (eb->eb_num);
}
#endif /* _NET_ETHERBRIDGE_H_ */