From owner-svn-src-all@FreeBSD.ORG Tue May 24 14:10:34 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5A54C106564A; Tue, 24 May 2011 14:10:34 +0000 (UTC) (envelope-from zec@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 403918FC08; Tue, 24 May 2011 14:10:34 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p4OEAYnU071555; Tue, 24 May 2011 14:10:34 GMT (envelope-from zec@svn.freebsd.org) Received: (from zec@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p4OEAYGH071553; Tue, 24 May 2011 14:10:34 GMT (envelope-from zec@svn.freebsd.org) Message-Id: <201105241410.p4OEAYGH071553@svn.freebsd.org> From: Marko Zec Date: Tue, 24 May 2011 14:10:34 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r222255 - head/sys/netgraph X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 24 May 2011 14:10:34 -0000 Author: zec Date: Tue May 24 14:10:33 2011 New Revision: 222255 URL: http://svn.freebsd.org/changeset/base/222255 Log: Provide fake link status information in an attempt to let ng_eiface(4) virtual ifnets more realistically mimic physical ethernet interfaces. The main motivation behind this change is to allow for ng_eiface(4) interfaces to participate in STP if_bridge(4) configurations. When announcing link status changes, switch to the vnet to which the ifnet belongs, since it is possible for ng_eiface ifnets to be assigned to a vnet different from the one in which its netgraph node resides. MFC after: 3 days Modified: head/sys/netgraph/ng_eiface.c Modified: head/sys/netgraph/ng_eiface.c ============================================================================== --- head/sys/netgraph/ng_eiface.c Tue May 24 13:36:41 2011 (r222254) +++ head/sys/netgraph/ng_eiface.c Tue May 24 14:10:33 2011 (r222255) @@ -41,6 +41,7 @@ #include #include +#include #include #include #include @@ -76,6 +77,8 @@ static const struct ng_cmdlist ng_eiface /* Node private data */ struct ng_eiface_private { struct ifnet *ifp; /* per-interface network data */ + struct ifmedia media; /* (fake) media information */ + int link_status; /* fake */ int unit; /* Interface unit number */ node_p node; /* Our netgraph node */ hook_p ether; /* Hook for ethernet stream */ @@ -127,6 +130,7 @@ static VNET_DEFINE(struct unrhdr *, ng_e static int ng_eiface_ioctl(struct ifnet *ifp, u_long command, caddr_t data) { + const priv_p priv = (priv_p)ifp->if_softc; struct ifreq *const ifr = (struct ifreq *)data; int s, error = 0; @@ -170,6 +174,12 @@ ng_eiface_ioctl(struct ifnet *ifp, u_lon ifp->if_mtu = ifr->ifr_mtu; break; + /* (Fake) media type manipulation */ + case SIOCSIFMEDIA: + case SIOCGIFMEDIA: + error = ifmedia_ioctl(ifp, ifr, &priv->media, command); + break; + /* Stuff that's not supported */ case SIOCADDMULTI: case SIOCDELMULTI: @@ -280,7 +290,6 @@ ng_eiface_start2(node_p node, hook_p hoo static void ng_eiface_start(struct ifnet *ifp) { - const priv_p priv = (priv_p)ifp->if_softc; /* Don't do anything if output is active */ @@ -328,6 +337,41 @@ ng_eiface_print_ioctl(struct ifnet *ifp, } #endif /* DEBUG */ +/* + * ifmedia stuff + */ +static int +ng_eiface_mediachange(struct ifnet *ifp) +{ + const priv_p priv = (priv_p)ifp->if_softc; + struct ifmedia *ifm = &priv->media; + + if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) + return (EINVAL); + if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) + ifp->if_baudrate = ifmedia_baudrate(IFM_ETHER | IFM_1000_T); + else + ifp->if_baudrate = ifmedia_baudrate(ifm->ifm_media); + + return (0); +} + +static void +ng_eiface_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) +{ + const priv_p priv = (priv_p)ifp->if_softc; + struct ifmedia *ifm = &priv->media; + + if (ifm->ifm_cur->ifm_media == (IFM_ETHER | IFM_AUTO) && + (priv->link_status & IFM_ACTIVE)) + ifmr->ifm_active = IFM_ETHER | IFM_1000_T | IFM_FDX; + else + ifmr->ifm_active = ifm->ifm_cur->ifm_media; + ifmr->ifm_status = priv->link_status; + + return; +} + /************************************************************************ NETGRAPH NODE STUFF ************************************************************************/ @@ -371,6 +415,18 @@ ng_eiface_constructor(node_p node) ifp->if_flags = (IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST); ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_JUMBO_MTU; ifp->if_capenable = IFCAP_VLAN_MTU | IFCAP_JUMBO_MTU; + ifmedia_init(&priv->media, 0, ng_eiface_mediachange, + ng_eiface_mediastatus); + ifmedia_add(&priv->media, IFM_ETHER | IFM_10_T, 0, NULL); + ifmedia_add(&priv->media, IFM_ETHER | IFM_10_T | IFM_FDX, 0, NULL); + ifmedia_add(&priv->media, IFM_ETHER | IFM_100_TX, 0, NULL); + ifmedia_add(&priv->media, IFM_ETHER | IFM_100_TX | IFM_FDX, 0, NULL); + ifmedia_add(&priv->media, IFM_ETHER | IFM_1000_T, 0, NULL); + ifmedia_add(&priv->media, IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL); + ifmedia_add(&priv->media, IFM_ETHER | IFM_10G_T | IFM_FDX, 0, NULL); + ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO, 0, NULL); + ifmedia_set(&priv->media, IFM_ETHER | IFM_AUTO); + priv->link_status = IFM_AVALID; /* Give this node the same name as the interface (if possible) */ if (ng_name_node(node, ifp->if_xname) != 0) @@ -379,6 +435,7 @@ ng_eiface_constructor(node_p node) /* Attach the interface */ ether_ifattach(ifp, eaddr); + ifp->if_baudrate = ifmedia_baudrate(IFM_ETHER | IFM_1000_T); /* Done */ return (0); @@ -401,7 +458,10 @@ ng_eiface_newhook(node_p node, hook_p ho NG_HOOK_SET_PRIVATE(hook, &priv->ether); NG_HOOK_SET_TO_INBOUND(hook); + priv->link_status |= IFM_ACTIVE; + CURVNET_SET_QUIET(ifp->if_vnet); if_link_state_change(ifp, LINK_STATE_UP); + CURVNET_RESTORE(); return (0); } @@ -486,16 +546,20 @@ ng_eiface_rcvmsg(node_p node, item_p ite } /* end of inner switch() */ break; case NGM_FLOW_COOKIE: + CURVNET_SET_QUIET(ifp->if_vnet); switch (msg->header.cmd) { case NGM_LINK_IS_UP: + priv->link_status |= IFM_ACTIVE; if_link_state_change(ifp, LINK_STATE_UP); break; case NGM_LINK_IS_DOWN: + priv->link_status &= ~IFM_ACTIVE; if_link_state_change(ifp, LINK_STATE_DOWN); break; default: break; } + CURVNET_RESTORE(); break; default: error = EINVAL; @@ -557,6 +621,7 @@ ng_eiface_rmnode(node_p node) * hence we have to change the current vnet context here. */ CURVNET_SET_QUIET(ifp->if_vnet); + ifmedia_removeall(&priv->media); ether_ifdetach(ifp); if_free(ifp); CURVNET_RESTORE(); @@ -576,6 +641,10 @@ ng_eiface_disconnect(hook_p hook) const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); priv->ether = NULL; + priv->link_status &= ~IFM_ACTIVE; + CURVNET_SET_QUIET(priv->ifp->if_vnet); + if_link_state_change(priv->ifp, LINK_STATE_DOWN); + CURVNET_RESTORE(); return (0); }