Update, if_vether(4) refactored and to if_bridge(4) dedicated extensions
reimplemented.

From OpenBSD ported if_vether(4) interface denotes own interface type
constant. Further, net/if_ethersubr.c was extended by

	void	(*vether_pppoe_proxy_change_p)(struct ifnet *,
		struct ether_header *, struct pppoe_hdr *);

and

	struct mbuf *	(*vether_pppoe_proxy_p)(struct ifnet *,
		struct mbuf *);

where maps to subr performing rfc-2516 proxyfieing tasks in net/if_vether.c,
if IPv[46] SDU are throught by if_bridge(4) associated IAP diverted
from rfc-2516 based downstream. Vether_pppoe_proxy_change() maps
rfc-2516 session identifier to instance of if_vether(4) if any is
if_bridge(4) member and proxyfieing is enabled. Any instance of if_vether(4)
maps to OID subtree of

	net.link.ether

during interface lifetime. Suppose vether0:

	# sysctl net.link.ether.vether0.pppoe_proxy=1

enables this feature, If there were IPv[46] PDU diverted by if_bridge(4)
dedicated IAP from rfc-2516 downstream, if_vether(4) is used to reinject
those upstream, e. g performed by natd(8). Running instance inherites lla
(FEC) of remote site where BRAS (or point of presence from TSP) remains.

ATTENTION - THIS FEATURUE IS STILL UNTESTED! BUT, TO THIS ISSUE RELATED
ACTIVITIES ARE IN PROGRESS! PURPOSE OF THIS COMMIT IS TO SHOW UP PROGRESS
DUE TO ONGOING IMPLEMENTAION ISSUES AND MAY UNDERSTAND AS DVELOPEMENT
STATUS REPORT!

	Any interface maps to an instance of if_brigde(4) passes incoming frames
to if_bridge(4) by bridge_input() (see net/if_ethersubr.h) to distinguish if
either frame may local processed by destined interface or forwarded by
if_bridge(4).
	Instances of if_vether(4) operates as communication endpoints, this
implies that no running instance of if_bridge(4) is allowed forward any by
if_vether(4) received frame. I've itroduced IFT_VETHER as constant
(see net/if_types.h) to identify instances of if_vether(4), if they are
if_bridge(4) member, e. g. by

	if (ifp->if_type == IFT_VETHER)
		return (m);

in bridge_input(). This step, was neccessary to avoid occourence of broadcast
storms, if an instance of if_vether(4) receives frames with multi- / broadcast
destination address.
	It is obvious that frame IO by if_vether(4) depends on if_bridge(4),
further, sending of frames depends on bridge_output() and is implemented as
follos:

	if (m->m_pkthdr.rcvif == NULL) {
		switch (ether_type) {
		case ETHERTYPE_PPPOEDISC:
		case ETHERTYPE_PPPOE:	/* FALLTHROUGH */
			m->m_pkthdr.rcvif = ifp;
			BRIDGE_OUTPUT(ifp, m, error);
			break;
		default:
			m_freem(m);
			continue;
		}
	} else if (m->m_pkthdr.rcvif != ifp) {
		m->m_pkthdr.rcvif = ifp;
		(*ifp->if_input)(ifp, m);
	} else {
		m_freem(m);
		continue;
	}

in vether_start_locked().
	Further, due to introduced constant, minor changes took place in
ng_ether(4):

static void
ng_ether_ifnet_arrival_event(void *arg __unused, struct ifnet *ifp)
{
	char name[IFNAMSIZ];
	node_p node;

	/* Only ethernet interfaces are of interest. */
	if (ifp->if_type != IFT_ETHER
		&& ifp->if_type != IFT_VETHER /* XXX: applied constant */
	    && ifp->if_type != IFT_L2VLAN)
		return;

	/*
	 * Just return if it's a new interface without an ng_ether companion.
	 */
	node = IFP2NG(ifp);
	if (node == NULL)
		return;

	/* Try to give the node the same name as the new interface name */
	ng_ether_sanitize_ifname(ifp->if_xname, name);
	if (ng_name_node(node, name) != 0)
		log(LOG_WARNING, "%s: can't re-name node %s\n", __func__, name);
}

and

static void
vnet_ng_ether_init(const void *unused)
{
	struct ifnet *ifp;

	/* If module load was rejected, don't attach to vnets. */
	if (ng_ether_attach_p != ng_ether_attach)
		return;

	/* Create nodes for any already-existing Ethernet interfaces. */
	IFNET_RLOCK();
	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
		if (ifp->if_type == IFT_ETHER
		    || ifp->if_type == IFT_VETHER /* XXX: applied constant */
		    || ifp->if_type == IFT_L2VLAN)
			ng_ether_attach(ifp);
	}
	IFNET_RUNLOCK();
}

which make ng_ether(4) make capable to register targeted instance of
if_vether(4) as Ethernet interface. Further, similar changes in if_bridge(4)
took place:

static void
bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif,
    int gone)
{
	struct ifnet *ifs = bif->bif_ifp;
	struct ifnet *fif = NULL;

	BRIDGE_LOCK_ASSERT(sc);

	if (bif->bif_flags & IFBIF_STP)
		bstp_disable(&bif->bif_stp);

	ifs->if_bridge = NULL;
	BRIDGE_XLOCK(sc);
	LIST_REMOVE(bif, bif_next);
	BRIDGE_XDROP(sc);

	/*
	 * If removing the interface that gave the bridge its mac address, set
	 * the mac address of the bridge to the address of the next member, or
	 * to its default address if no members are left.
	 */
	if (bridge_inherit_mac && sc->sc_ifaddr == ifs) {
		if (LIST_EMPTY(&sc->sc_iflist)) {
			bcopy(sc->sc_defaddr,
			    IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN);
			sc->sc_ifaddr = NULL;
		} else {
			fif = LIST_FIRST(&sc->sc_iflist)->bif_ifp;
			bcopy(IF_LLADDR(fif),
			    IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN);
			sc->sc_ifaddr = fif;
		}
		EVENTHANDLER_INVOKE(iflladdr_event, sc->sc_ifp);
	}

	bridge_linkcheck(sc);
	bridge_mutecaps(sc);	/* recalcuate now this interface is removed */
	bridge_rtdelete(sc, ifs, IFBF_FLUSHALL);
	KASSERT(bif->bif_addrcnt == 0,
	    ("%s: %d bridge routes referenced", __func__, bif->bif_addrcnt));

	BRIDGE_UNLOCK(sc);
	if (!gone) {
		switch (ifs->if_type) {
		case IFT_ETHER:
		case IFT_VETHER: /* XXX: applied constant */
		case IFT_L2VLAN:
			/*
			 * Take the interface out of promiscuous mode.
			 */
			(void) ifpromisc(ifs, 0);
			break;

		case IFT_GIF:
			break;
		case IFT_MPLS:
			if (MPLS_IFINFO_RT(ifs) != NULL) {
				GET_MPLS_IFINFO_RT(ifs)->mrt_flags &= ~MRT_PW2;
				GET_MPLS_IFINFO_RT(ifs)->mrt_nh_smpls.smpls_vprd = 0;
			}
			break;
		default:
			panic("bridge_delete_member: impossible");
			break;
		}
		/* reneable any interface capabilities */
		bridge_set_ifcap(sc, bif, bif->bif_savedcaps);
	}
	bstp_destroy(&bif->bif_stp);	/* prepare to free */
	BRIDGE_LOCK(sc);
	free(bif, M_DEVBUF);
}

and

static int
bridge_ioctl_add(struct bridge_softc *sc, void *arg)
{
	struct ifbreq *req = arg;
	struct bridge_iflist *bif = NULL;
	struct ifnet *ifs;
	int error = 0;

	ifs = ifunit(req->ifbr_ifsname);
	if (ifs == NULL)
		return (ENOENT);
	if (ifs->if_ioctl == NULL)	/* must be supported */
		return (EINVAL);

	/* If it's in the span list, it can't be a member. */
	LIST_FOREACH(bif, &sc->sc_spanlist, bif_next)
		if (ifs == bif->bif_ifp)
			return (EBUSY);

	if (ifs->if_bridge == sc)
		return (EEXIST);

	if (ifs->if_bridge != NULL)
		return (EBUSY);

	switch (ifs->if_type) {
	case IFT_ETHER:
	case IFT_VETHER: /* XXX: applied constant */
	case IFT_L2VLAN:
	case IFT_GIF:
		/* permitted interface types */
		break;
	case IFT_MPLS:
		if (MPLS_IFINFO_RT(ifs) != NULL) {
			GET_MPLS_IFINFO_RT(ifs)->mrt_flags |= MRT_PW2;
			GET_MPLS_IFINFO_RT(ifs)->mrt_nh_smpls.smpls_vprd =
				MPLS_LABEL_SET(MPLS_RD_ETHDEMUX);
		}
		break;
	default:
		return (EINVAL);
	}

	/*
	 * Two valid inet6 addresses with link-local scope must not be
	 * on the parent interface and the member interfaces at the
	 * same time.  This restriction is needed to prevent violation
	 * of link-local scope zone.  Attempts to add a member
	 * interface which has inet6 addresses when the parent has
	 * inet6 triggers removal of all inet6 addresses on the member
	 * interface.
	 */

	/* Check if the parent interface has a link-local scope addr. */
	if (V_allow_llz_overlap == 0 &&
	    in6ifa_llaonifp(sc->sc_ifp) != NULL) {
		/*
		 * If any, remove all inet6 addresses from the member
		 * interfaces.
		 */
		BRIDGE_XLOCK(sc);
		LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
 			if (in6ifa_llaonifp(bif->bif_ifp)) {
				BRIDGE_UNLOCK(sc);
				in6_ifdetach(bif->bif_ifp);
				BRIDGE_LOCK(sc);
				if_printf(sc->sc_ifp,
				    "IPv6 addresses on %s have been removed "
				    "before adding it as a member to prevent "
				    "IPv6 address scope violation.\n",
				    bif->bif_ifp->if_xname);
			}
		}
		BRIDGE_XDROP(sc);
		if (in6ifa_llaonifp(ifs)) {
			BRIDGE_UNLOCK(sc);
			in6_ifdetach(ifs);
			BRIDGE_LOCK(sc);
			if_printf(sc->sc_ifp,
			    "IPv6 addresses on %s have been removed "
			    "before adding it as a member to prevent "
			    "IPv6 address scope violation.\n",
			    ifs->if_xname);
		}
	}
	/* Allow the first Ethernet member to define the MTU */
	if (LIST_EMPTY(&sc->sc_iflist))
		sc->sc_ifp->if_mtu = ifs->if_mtu;
	else if (sc->sc_ifp->if_mtu != ifs->if_mtu) {
		if_printf(sc->sc_ifp, "invalid MTU: %lu(%s) != %lu\n",
		    ifs->if_mtu, ifs->if_xname, sc->sc_ifp->if_mtu);
		return (EINVAL);
	}

	bif = malloc(sizeof(*bif), M_DEVBUF, M_NOWAIT|M_ZERO);
	if (bif == NULL)
		return (ENOMEM);

	bif->bif_ifp = ifs;
	bif->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER;
	bif->bif_savedcaps = ifs->if_capenable;

	/*
	 * Assign the interface's MAC address to the bridge if it's the first
	 * member and the MAC address of the bridge has not been changed from
	 * the default randomly generated one.
	 */
	if (bridge_inherit_mac && LIST_EMPTY(&sc->sc_iflist) &&
	    !memcmp(IF_LLADDR(sc->sc_ifp), sc->sc_defaddr, ETHER_ADDR_LEN)) {
		bcopy(IF_LLADDR(ifs), IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN);
		sc->sc_ifaddr = ifs;
		EVENTHANDLER_INVOKE(iflladdr_event, sc->sc_ifp);
	}

	ifs->if_bridge = sc;
	bstp_create(&sc->sc_stp, &bif->bif_stp, bif->bif_ifp);
	/*
	 * XXX: XLOCK HERE!?!
	 *
	 * NOTE: insert_***HEAD*** should be safe for the traversals.
	 */
	LIST_INSERT_HEAD(&sc->sc_iflist, bif, bif_next);

	/* Set interface capabilities to the intersection set of all members */
	bridge_mutecaps(sc);
	bridge_linkcheck(sc);

	/* Place the interface into promiscuous mode */
	switch (ifs->if_type) {
		case IFT_ETHER:
		case IFT_VETHER: /* XXX: applied constant */
		case IFT_L2VLAN:
			BRIDGE_UNLOCK(sc);
			error = ifpromisc(ifs, 1);
			BRIDGE_LOCK(sc);
			break;
	}

	if (error) {
		bridge_delete_member(sc, bif, 0);
		free(bif, M_DEVBUF);
	}
	return (error);
}

Now, I'm starting testing rfc-2516 proxyfieing. Possible changes on
implementation maybe commited soon.