[BACK]Return to if_etherbridge.h CVS log [TXT][DIR] Up to [local] / src / sys / net

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_ */