ng_ether: refactor to use interface EVENTHANDLER(9)s

This commit is contained in:
Gleb Smirnoff
2025-12-21 14:13:58 -08:00
parent 349fcf079c
commit 0bd0c3295a
5 changed files with 64 additions and 120 deletions
-4
View File
@@ -460,10 +460,6 @@ extern uint32_t ether_crc32_be(const uint8_t *, size_t);
extern void ether_demux(struct ifnet *, struct mbuf *);
extern void ether_ifattach(struct ifnet *, const u_int8_t *);
extern void ether_ifdetach(struct ifnet *);
#ifdef VIMAGE
struct vnet;
extern void ether_reassign(struct ifnet *, struct vnet *, char *);
#endif
extern int ether_ioctl(struct ifnet *, u_long, caddr_t);
extern int ether_output(struct ifnet *, struct mbuf *,
const struct sockaddr *, struct route *);
-5
View File
@@ -239,7 +239,6 @@ static MALLOC_DEFINE(M_IFDESCR, "ifdescr", "ifnet descriptions");
static struct sx ifdescr_sx;
SX_SYSINIT(ifdescr_sx, &ifdescr_sx, "ifnet descr");
void (*ng_ether_link_state_p)(struct ifnet *ifp, int state);
void (*lagg_linkstate_p)(struct ifnet *ifp, int state);
/* These are external hooks for CARP. */
void (*carp_linkstate_p)(struct ifnet *ifp);
@@ -2031,10 +2030,6 @@ do_link_state_change(void *arg, int pending)
rt_ifmsg(ifp, 0);
if (ifp->if_vlantrunk != NULL)
(*vlan_link_state_p)(ifp);
if ((ifp->if_type == IFT_ETHER || ifp->if_type == IFT_L2VLAN) &&
ifp->if_l2com != NULL)
(*ng_ether_link_state_p)(ifp, link_state);
if (ifp->if_carp)
(*carp_linkstate_p)(ifp);
if (ifp->if_bridge)
-2
View File
@@ -801,8 +801,6 @@ bridge_reassign(struct ifnet *ifp, struct vnet *newvnet, char *arg)
}
BRIDGE_UNLOCK(sc);
ether_reassign(ifp, newvnet, arg);
}
#endif
-32
View File
@@ -98,8 +98,6 @@ VNET_DEFINE(pfil_head_t, link_pfil_head); /* Packet filter hooks */
void (*ng_ether_input_p)(struct ifnet *ifp, struct mbuf **mp);
void (*ng_ether_input_orphan_p)(struct ifnet *ifp, struct mbuf *m);
int (*ng_ether_output_p)(struct ifnet *ifp, struct mbuf **mp);
void (*ng_ether_attach_p)(struct ifnet *ifp);
void (*ng_ether_detach_p)(struct ifnet *ifp);
/* if_bridge(4) support */
void (*bridge_dn_p)(struct mbuf *, struct ifnet *);
@@ -988,9 +986,6 @@ ether_ifattach(struct ifnet *ifp, const u_int8_t *lla)
ifp->if_input = ether_input;
ifp->if_resolvemulti = ether_resolvemulti;
ifp->if_requestencap = ether_requestencap;
#ifdef VIMAGE
ifp->if_reassign = ether_reassign;
#endif
if (ifp->if_baudrate == 0)
ifp->if_baudrate = IF_Mbps(10); /* just a default */
ifp->if_broadcastaddr = etherbroadcastaddr;
@@ -1006,8 +1001,6 @@ ether_ifattach(struct ifnet *ifp, const u_int8_t *lla)
bcopy(lla, ifp->if_hw_addr, ifp->if_addrlen);
bpfattach(ifp, DLT_EN10MB, ETHER_HDR_LEN);
if (ng_ether_attach_p != NULL)
(*ng_ether_attach_p)(ifp);
/* Announce Ethernet MAC address if non-zero. */
for (i = 0; i < ifp->if_addrlen; i++)
@@ -1035,35 +1028,10 @@ ether_ifdetach(struct ifnet *ifp)
sdl = (struct sockaddr_dl *)(ifp->if_addr->ifa_addr);
uuid_ether_del(LLADDR(sdl));
if (ifp->if_l2com != NULL) {
KASSERT(ng_ether_detach_p != NULL,
("ng_ether_detach_p is NULL"));
(*ng_ether_detach_p)(ifp);
}
bpfdetach(ifp);
if_detach(ifp);
}
#ifdef VIMAGE
void
ether_reassign(struct ifnet *ifp, struct vnet *new_vnet, char *unused __unused)
{
if (ifp->if_l2com != NULL) {
KASSERT(ng_ether_detach_p != NULL,
("ng_ether_detach_p is NULL"));
(*ng_ether_detach_p)(ifp);
}
if (ng_ether_attach_p != NULL) {
CURVNET_SET_QUIET(new_vnet);
(*ng_ether_attach_p)(ifp);
CURVNET_RESTORE();
}
}
#endif
SYSCTL_DECL(_net_link);
SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
"Ethernet");
+64 -77
View File
@@ -92,17 +92,11 @@ typedef struct private *priv_p;
extern void (*ng_ether_input_p)(struct ifnet *ifp, struct mbuf **mp);
extern void (*ng_ether_input_orphan_p)(struct ifnet *ifp, struct mbuf *m);
extern int (*ng_ether_output_p)(struct ifnet *ifp, struct mbuf **mp);
extern void (*ng_ether_attach_p)(struct ifnet *ifp);
extern void (*ng_ether_detach_p)(struct ifnet *ifp);
extern void (*ng_ether_link_state_p)(struct ifnet *ifp, int state);
/* Functional hooks called from if_ethersubr.c */
static void ng_ether_input(struct ifnet *ifp, struct mbuf **mp);
static void ng_ether_input_orphan(struct ifnet *ifp, struct mbuf *m);
static int ng_ether_output(struct ifnet *ifp, struct mbuf **mp);
static void ng_ether_attach(struct ifnet *ifp);
static void ng_ether_detach(struct ifnet *ifp);
static void ng_ether_link_state(struct ifnet *ifp, int state);
/* Other functions */
static int ng_ether_rcv_lower(hook_p node, item_p item);
@@ -117,7 +111,8 @@ static ng_rcvdata_t ng_ether_rcvdata;
static ng_disconnect_t ng_ether_disconnect;
static int ng_ether_mod_event(module_t mod, int event, void *data);
static eventhandler_tag ng_ether_ifnet_arrival_cookie;
static eventhandler_tag ifnet_arrival_tag, ifnet_departure_tag,
ifnet_rename_tag, ifnet_linkstate_tag;
/* List of commands and how to convert arguments to/from ASCII */
static const struct ng_cmdlist ng_ether_cmdlist[] = {
@@ -299,13 +294,19 @@ ng_ether_output(struct ifnet *ifp, struct mbuf **mp)
* A new Ethernet interface has been attached.
* Create a new node for it, etc.
*/
static void
ng_ether_attach(struct ifnet *ifp)
static int
ng_ether_attach(struct ifnet *ifp, void *arg __unused)
{
char name[IFNAMSIZ];
priv_p priv;
node_p node;
if ((ifp)->if_type != IFT_ETHER &&
(ifp)->if_type != IFT_L2VLAN &&
(ifp)->if_type != IFT_BRIDGE)
return (0);
MPASS(IFP2NG(ifp) == NULL);
/*
* Do not create / attach an ether node to this ifnet if
* a netgraph node with the same name already exists.
@@ -316,25 +317,17 @@ ng_ether_attach(struct ifnet *ifp)
ng_ether_sanitize_ifname(ifp->if_xname, name);
if ((node = ng_name2noderef(NULL, name)) != NULL) {
NG_NODE_UNREF(node);
return;
return (0);
}
/* Create node */
KASSERT(!IFP2NG(ifp), ("%s: node already exists?", __func__));
if (ng_make_node_common(&ng_ether_typestruct, &node) != 0) {
log(LOG_ERR, "%s: can't %s for %s\n",
__func__, "create node", ifp->if_xname);
return;
return (0);
}
/* Allocate private data */
priv = malloc(sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO);
if (priv == NULL) {
log(LOG_ERR, "%s: can't %s for %s\n",
__func__, "allocate memory", ifp->if_xname);
NG_NODE_UNREF(node);
return;
}
priv = malloc(sizeof(*priv), M_NETGRAPH, M_WAITOK | M_ZERO);
NG_NODE_SET_PRIVATE(node, priv);
priv->ifp = ifp;
IFP2NG(ifp) = node;
@@ -343,17 +336,38 @@ ng_ether_attach(struct ifnet *ifp)
/* Try to give the node the same name as the interface */
if (ng_name_node(node, name) != 0)
log(LOG_WARNING, "%s: can't name node %s\n", __func__, name);
return (0);
}
static void
ng_ether_arrival(void *arg __unused, struct ifnet *ifp)
{
(void)ng_ether_attach(ifp, NULL);
}
#define RETURN_IF_NOT_ETHERNET_OR_DETACHED(ifp) do { \
if ((ifp)->if_type != IFT_ETHER && \
(ifp)->if_type != IFT_L2VLAN && \
(ifp)->if_type != IFT_BRIDGE) \
return; \
if (IFP2NG(ifp) == NULL) \
return; \
} while (0)
/*
* An Ethernet interface is being detached.
* REALLY Destroy its node.
*/
static void
ng_ether_detach(struct ifnet *ifp)
ng_ether_detach(void *arg __unused, struct ifnet *ifp)
{
const node_p node = IFP2NG(ifp);
const priv_p priv = NG_NODE_PRIVATE(node);
priv_p priv;
RETURN_IF_NOT_ETHERNET_OR_DETACHED(ifp);
priv = NG_NODE_PRIVATE(node);
taskqueue_drain(taskqueue_swi, &ifp->if_linktask);
NG_NODE_REALLY_DIE(node); /* Force real removal of node */
@@ -372,13 +386,17 @@ ng_ether_detach(struct ifnet *ifp)
* if_link_state_change() has already checked that the state has changed.
*/
static void
ng_ether_link_state(struct ifnet *ifp, int state)
ng_ether_link_state(void *arg __unused, struct ifnet *ifp, int state)
{
const node_p node = IFP2NG(ifp);
const priv_p priv = NG_NODE_PRIVATE(node);
priv_p priv;
struct ng_mesg *msg;
int cmd, dummy_error = 0;
RETURN_IF_NOT_ETHERNET_OR_DETACHED(ifp);
priv = NG_NODE_PRIVATE(node);
if (state == LINK_STATE_UP)
cmd = NGM_LINK_IS_UP;
else if (state == LINK_STATE_DOWN)
@@ -399,31 +417,17 @@ ng_ether_link_state(struct ifnet *ifp, int state)
}
/*
* Interface arrival notification handler.
* The notification is produced in two cases:
* o a new interface arrives
* o an existing interface got renamed
* Currently the first case is handled by ng_ether_attach via special
* hook ng_ether_attach_p.
* Interface has been renamed.
*/
static void
ng_ether_ifnet_arrival_event(void *arg __unused, struct ifnet *ifp)
ng_ether_rename(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_L2VLAN &&
ifp->if_type != IFT_BRIDGE)
return;
RETURN_IF_NOT_ETHERNET_OR_DETACHED(ifp);
/*
* 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);
@@ -629,7 +633,7 @@ ng_ether_rcvmsg(node_p node, item_p item, hook_p lasthook)
break;
}
case NGM_ETHER_DETACH:
ng_ether_detach(priv->ifp);
ng_ether_detach(NULL, priv->ifp);
break;
default:
error = EINVAL;
@@ -810,22 +814,19 @@ ng_ether_mod_event(module_t mod, int event, void *data)
switch (event) {
case MOD_LOAD:
/* Register function hooks */
if (ng_ether_attach_p != NULL) {
error = EEXIST;
break;
}
ng_ether_attach_p = ng_ether_attach;
ng_ether_detach_p = ng_ether_detach;
ng_ether_output_p = ng_ether_output;
ng_ether_input_p = ng_ether_input;
ng_ether_input_orphan_p = ng_ether_input_orphan;
ng_ether_link_state_p = ng_ether_link_state;
ng_ether_ifnet_arrival_cookie =
EVENTHANDLER_REGISTER(ifnet_arrival_event,
ng_ether_ifnet_arrival_event, NULL, EVENTHANDLER_PRI_ANY);
ifnet_arrival_tag = EVENTHANDLER_REGISTER(ifnet_arrival_event,
ng_ether_arrival, NULL, EVENTHANDLER_PRI_ANY);
ifnet_departure_tag =
EVENTHANDLER_REGISTER(ifnet_departure_event,
ng_ether_detach, NULL, EVENTHANDLER_PRI_ANY);
ifnet_rename_tag = EVENTHANDLER_REGISTER(ifnet_rename_event,
ng_ether_rename, NULL, EVENTHANDLER_PRI_ANY);
ifnet_linkstate_tag = EVENTHANDLER_REGISTER(ifnet_link_event,
ng_ether_link_state, NULL, EVENTHANDLER_PRI_ANY);
break;
case MOD_UNLOAD:
@@ -838,16 +839,16 @@ ng_ether_mod_event(module_t mod, int event, void *data)
* is MOD_UNLOAD, so there's no need to detach any nodes.
*/
EVENTHANDLER_DEREGISTER(ifnet_arrival_event,
ng_ether_ifnet_arrival_cookie);
EVENTHANDLER_DEREGISTER(ifnet_arrival_event, ifnet_arrival_tag);
EVENTHANDLER_DEREGISTER(ifnet_departure_event,
ifnet_departure_tag);
EVENTHANDLER_DEREGISTER(ifnet_rename_event, ifnet_rename_tag);
EVENTHANDLER_DEREGISTER(ifnet_link_event, ifnet_linkstate_tag);
/* Unregister function hooks */
ng_ether_attach_p = NULL;
ng_ether_detach_p = NULL;
ng_ether_output_p = NULL;
ng_ether_input_p = NULL;
ng_ether_input_orphan_p = NULL;
ng_ether_link_state_p = NULL;
break;
default:
@@ -858,23 +859,9 @@ ng_ether_mod_event(module_t mod, int event, void *data)
}
static void
vnet_ng_ether_init(const void *unused)
ng_ether_vnet_init(void *arg __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();
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
if (ifp->if_type == IFT_ETHER ||
ifp->if_type == IFT_L2VLAN ||
ifp->if_type == IFT_BRIDGE)
ng_ether_attach(ifp);
}
IFNET_RUNLOCK();
if_foreach_sleep(NULL, NULL, ng_ether_attach, NULL);
}
VNET_SYSINIT(vnet_ng_ether_init, SI_SUB_PSEUDO, SI_ORDER_ANY,
vnet_ng_ether_init, NULL);
VNET_SYSINIT(ng_ether_vnet_init, SI_SUB_PROTO_IF, SI_ORDER_ANY,
ng_ether_vnet_init, NULL);