summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
authorandre <andre@FreeBSD.org>2004-05-03 13:48:35 +0000
committerandre <andre@FreeBSD.org>2004-05-03 13:48:35 +0000
commit25ae331e1251bd9562a10f53fdb2f054f7b21dfe (patch)
tree26d69d96320d4278394e06ff25df74de9314a2fc /sys/net
parentf8ee348f1d1b903d0b117c893b5f73aed4e5bce8 (diff)
downloadFreeBSD-src-25ae331e1251bd9562a10f53fdb2f054f7b21dfe.zip
FreeBSD-src-25ae331e1251bd9562a10f53fdb2f054f7b21dfe.tar.gz
Link state change notification of ethernet media to the routing socket.
o Extend the if_data structure with an ifi_link_state field and provide the corresponding defines for the valid states. o The mii_linkchg() callback updates the ifi_link_state field and calls rt_ifmsg() to notify listeners on the routing socket in addition to the kqueue KNOTE. o If vlans are configured on a physical interface notify and update all vlan pseudo devices as well with the vlan_link_state() callback. No objections by: sam, wpaul, ru, bms Brucification by: bde
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if.h8
-rw-r--r--sys/net/if_var.h1
-rw-r--r--sys/net/if_vlan.c25
3 files changed, 34 insertions, 0 deletions
diff --git a/sys/net/if.h b/sys/net/if.h
index 625dfe0..2266fee 100644
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -104,6 +104,7 @@ struct if_data {
u_char ifi_physical; /* e.g., AUI, Thinnet, 10base-T, etc */
u_char ifi_addrlen; /* media address length */
u_char ifi_hdrlen; /* media header length */
+ u_char ifi_link_state; /* current link state */
u_char ifi_recvquota; /* polling quota for receive intrs */
u_char ifi_xmitquota; /* polling quota for xmit intrs */
u_long ifi_mtu; /* maximum transmission unit */
@@ -155,6 +156,13 @@ struct if_data {
IFF_POLLING)
/*
+ * Values for if_link_state.
+ */
+#define LINK_STATE_UNKNOWN 0 /* link invalid/unknown */
+#define LINK_STATE_DOWN 1 /* link is down */
+#define LINK_STATE_UP 2 /* link is up */
+
+/*
* Some convenience macros used for setting ifi_baudrate.
* XXX 1000 vs. 1024? --thorpej@netbsd.org
*/
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 3d3cad5..541f214 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -197,6 +197,7 @@ typedef void if_init_f_t(void *);
#define if_addrlen if_data.ifi_addrlen
#define if_hdrlen if_data.ifi_hdrlen
#define if_metric if_data.ifi_metric
+#define if_link_state if_data.ifi_link_state
#define if_baudrate if_data.ifi_baudrate
#define if_hwassist if_data.ifi_hwassist
#define if_ipackets if_data.ifi_ipackets
diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c
index 87eabb7..25ca790 100644
--- a/sys/net/if_vlan.c
+++ b/sys/net/if_vlan.c
@@ -125,6 +125,7 @@ static int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr);
static int vlan_setmulti(struct ifnet *ifp);
static int vlan_unconfig(struct ifnet *ifp);
static int vlan_config(struct ifvlan *ifv, struct ifnet *p);
+static void vlan_link_state(struct ifnet *ifp, int link);
struct if_clone vlan_cloner = IF_CLONE_INITIALIZER(VLANNAME,
vlan_clone_create, vlan_clone_destroy, 0, IF_MAXUNIT);
@@ -209,6 +210,9 @@ vlan_setmulti(struct ifnet *ifp)
*/
extern void (*vlan_input_p)(struct ifnet *, struct mbuf *);
+/* For MII eyes only... */
+extern void (*vlan_link_state_p)(struct ifnet *, int);
+
static int
vlan_modevent(module_t mod, int type, void *data)
{
@@ -218,11 +222,13 @@ vlan_modevent(module_t mod, int type, void *data)
LIST_INIT(&ifv_list);
VLAN_LOCK_INIT();
vlan_input_p = vlan_input;
+ vlan_link_state_p = vlan_link_state;
if_clone_attach(&vlan_cloner);
break;
case MOD_UNLOAD:
if_clone_detach(&vlan_cloner);
vlan_input_p = NULL;
+ vlan_link_state_p = NULL;
while (!LIST_EMPTY(&ifv_list))
vlan_clone_destroy(&LIST_FIRST(&ifv_list)->ifv_if);
VLAN_LOCK_DESTROY();
@@ -532,6 +538,7 @@ vlan_config(struct ifvlan *ifv, struct ifnet *p)
*/
ifv->ifv_if.if_flags = (p->if_flags &
(IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX | IFF_POINTOPOINT));
+ ifv->ifv_if.if_link_state = p->if_link_state;
/*
* If the parent interface can do hardware-assisted
@@ -622,6 +629,7 @@ vlan_unconfig(struct ifnet *ifp)
ifv->ifv_p = NULL;
ifv->ifv_if.if_mtu = ETHERMTU; /* XXX why not 0? */
ifv->ifv_flags = 0;
+ ifv->ifv_if.if_link_state = LINK_STATE_UNKNOWN;
/* Clear our MAC address. */
ifa = ifaddr_byindex(ifv->ifv_if.if_index);
@@ -657,6 +665,23 @@ vlan_set_promisc(struct ifnet *ifp)
return (error);
}
+/* Inform all vlans that their parent has changed link state */
+static void
+vlan_link_state(struct ifnet *ifp, int link)
+{
+ struct ifvlan *ifv;
+
+ VLAN_LOCK();
+ LIST_FOREACH(ifv, &ifv_list, ifv_list) {
+ if (ifv->ifv_p == ifp) {
+ ifv->ifv_if.if_link_state = ifv->ifv_p->if_link_state;
+ rt_ifmsg(&(ifv->ifv_if));
+ KNOTE(&ifp->if_klist, link);
+ }
+ }
+ VLAN_UNLOCK();
+}
+
static int
vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
OpenPOWER on IntegriCloud