From 1c7899c74e68cca6dbfddbed437d11001c0c3722 Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Sat, 8 Jan 2005 12:42:03 +0000 Subject: [PATCH] This change adds reliability for Ethernet trunks built with ng_one2many: - Introduce another ng_ether(4) callback ng_ether_link_state_p, which is called from if_link_state_change(), every time link is changed. - In ng_ether_link_state() send netgraph control message notifying of link state change to a node connected to "lower" hook. Reviewed by: sam MFC after: 2 weeks --- sys/net/if.c | 6 ++++++ sys/netgraph/ng_ether.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/sys/net/if.c b/sys/net/if.c index 1dac78e3df55..55af93339c75 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -79,6 +79,8 @@ #include #endif +void (*ng_ether_link_state_p)(struct ifnet *ifp, int state); + struct mbuf *(*tbr_dequeue_ptr)(struct ifaltq *, int) = NULL; static void if_attachdomain(void *); @@ -978,6 +980,10 @@ if_link_state_change(struct ifnet *ifp, int link_state) KNOTE_UNLOCKED(&ifp->if_klist, link); if (ifp->if_nvlans != 0) (*vlan_link_state_p)(ifp, link); + + if ((ifp->if_type == IFT_ETHER || ifp->if_type == IFT_L2VLAN) && + IFP2AC(ifp)->ac_netgraph != NULL) + (*ng_ether_link_state_p)(ifp, link_state); } } diff --git a/sys/netgraph/ng_ether.c b/sys/netgraph/ng_ether.c index a2873ae380ad..a3932a19a660 100644 --- a/sys/netgraph/ng_ether.c +++ b/sys/netgraph/ng_ether.c @@ -89,6 +89,7 @@ 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); @@ -96,6 +97,7 @@ 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(node_p node, struct mbuf *m); @@ -312,6 +314,33 @@ ng_ether_detach(struct ifnet *ifp) ng_rmnode_self(node); /* remove all netgraph parts */ } +/* + * Notify graph about link event. + * if_link_state_change() has already checked that the state has changed. + */ +static void +ng_ether_link_state(struct ifnet *ifp, int state) +{ + const node_p node = IFP2NG(ifp); + const priv_p priv = NG_NODE_PRIVATE(node); + struct ng_mesg *msg; + int cmd, dummy_error = 0; + + if (priv->lower == NULL) + return; + + if (state == LINK_STATE_UP) + cmd = NGM_LINK_IS_UP; + else if (state == LINK_STATE_DOWN) + cmd = NGM_LINK_IS_DOWN; + else + return; + + NG_MKMESSAGE(msg, NGM_FLOW_COOKIE, cmd, 0, M_NOWAIT); + if (msg != NULL) + NG_SEND_MSG_HOOK(dummy_error, node, msg, priv->lower, 0); +} + /****************************************************************** NETGRAPH NODE METHODS ******************************************************************/ @@ -645,6 +674,7 @@ ng_ether_mod_event(module_t mod, int event, void *data) 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; /* Create nodes for any already-existing Ethernet interfaces */ IFNET_RLOCK(); @@ -672,6 +702,7 @@ ng_ether_mod_event(module_t mod, int event, void *data) ng_ether_output_p = NULL; ng_ether_input_p = NULL; ng_ether_input_orphan_p = NULL; + ng_ether_link_state_p = NULL; break; default: