Page MenuHomeFreeBSD

D37597.diff
No OneTemporary

D37597.diff

diff --git a/sys/dev/usb/usb_pf.c b/sys/dev/usb/usb_pf.c
--- a/sys/dev/usb/usb_pf.c
+++ b/sys/dev/usb/usb_pf.c
@@ -209,7 +209,7 @@
ifp->if_ioctl = usbpf_ioctl;
if_attach(ifp);
ifp->if_flags |= IFF_UP;
- rt_ifmsg(ifp);
+ rt_ifmsg(ifp, IFF_UP);
/*
* XXX According to the specification of DLT_USB, it indicates
* packets beginning with USB setup header. But not sure all
diff --git a/sys/net/if.h b/sys/net/if.h
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -164,6 +164,7 @@
#define IFF_DYING 0x200000 /* (n) interface is winding down */
#define IFF_RENAMING 0x400000 /* (n) interface is being renamed */
#define IFF_NOGROUP 0x800000 /* (n) interface is not part of any groups */
+#define IFF_NETLINK_1 0x1000000 /* (n) used by netlink */
/*
* Old names for driver flags so that user space tools can continue to use
diff --git a/sys/net/if.c b/sys/net/if.c
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -2138,7 +2138,7 @@
if (ifp->if_carp)
(*carp_linkstate_p)(ifp);
- rt_ifmsg(ifp);
+ rt_ifmsg(ifp, IFF_UP);
}
/*
@@ -2155,7 +2155,7 @@
getmicrotime(&ifp->if_lastchange);
if (ifp->if_carp)
(*carp_linkstate_p)(ifp);
- rt_ifmsg(ifp);
+ rt_ifmsg(ifp, IFF_UP);
#ifdef INET6
in6_if_up(ifp);
#endif
@@ -2199,7 +2199,7 @@
link_state = ifp->if_link_state;
CURVNET_SET(ifp->if_vnet);
- rt_ifmsg(ifp);
+ rt_ifmsg(ifp, 0);
if (ifp->if_vlantrunk != NULL)
(*vlan_link_state_p)(ifp);
@@ -2845,7 +2845,7 @@
error = (*ifp->if_ioctl)(ifp, cmd, data);
if (error == 0) {
getmicrotime(&ifp->if_lastchange);
- rt_ifmsg(ifp);
+ rt_ifmsg(ifp, 0);
#ifdef INET
DEBUGNET_NOTIFY_MTU(ifp);
#endif
@@ -3274,7 +3274,7 @@
if (error)
goto recover;
/* Notify userland that interface flags have changed */
- rt_ifmsg(ifp);
+ rt_ifmsg(ifp, flag);
return (0);
recover:
diff --git a/sys/net/route.h b/sys/net/route.h
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -412,7 +412,7 @@
struct rib_head;
void rt_ieee80211msg(struct ifnet *, int, void *, size_t);
-void rt_ifmsg(struct ifnet *);
+void rt_ifmsg(struct ifnet *, int);
void rt_missmsg(int, struct rt_addrinfo *, int, int);
void rt_missmsg_fib(int, struct rt_addrinfo *, int, int, int);
int rt_addrmsg(int, struct ifaddr *, int);
diff --git a/sys/net/route.c b/sys/net/route.c
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -695,12 +695,28 @@
return (rtsock_routemsg_info(cmd, info, fibnum));
}
+void
+rt_ifmsg(struct ifnet *ifp, int if_flags_mask)
+{
+ rtsock_callback_p->ifmsg_f(ifp, if_flags_mask);
+ netlink_callback_p->ifmsg_f(ifp, if_flags_mask);
+}
+
/* Netlink-related callbacks needed to glue rtsock, netlink and linuxolator */
static void
ignore_route_event(uint32_t fibnum, const struct rib_cmd_info *rc)
{
}
-static struct rtbridge ignore_cb = { .route_f = ignore_route_event };
+
+static void
+ignore_ifmsg_event(struct ifnet *ifp, int if_flags_mask)
+{
+}
+
+static struct rtbridge ignore_cb = {
+ .route_f = ignore_route_event,
+ .ifmsg_f = ignore_ifmsg_event,
+};
void *linux_netlink_p = NULL; /* Callback pointer for Linux translator functions */
struct rtbridge *rtsock_callback_p = &ignore_cb;
diff --git a/sys/net/route/route_ctl.h b/sys/net/route/route_ctl.h
--- a/sys/net/route/route_ctl.h
+++ b/sys/net/route/route_ctl.h
@@ -191,8 +191,10 @@
/* Event bridge */
typedef void route_event_f(uint32_t fibnum, const struct rib_cmd_info *rc);
+typedef void ifmsg_event_f(struct ifnet *ifp, int if_flags_mask);
struct rtbridge{
route_event_f *route_f;
+ ifmsg_event_f *ifmsg_f;
};
extern struct rtbridge *rtsock_callback_p;
extern struct rtbridge *netlink_callback_p;
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -220,6 +220,7 @@
static bool can_export_rte(struct ucred *td_ucred, bool rt_is_host,
const struct sockaddr *rt_dst);
static void rtsock_notify_event(uint32_t fibnum, const struct rib_cmd_info *rc);
+static void rtsock_ifmsg(struct ifnet *ifp, int if_flags_mask);
static struct netisr_handler rtsock_nh = {
.nh_name = "rtsock",
@@ -297,7 +298,10 @@
#endif
report_route_event(rc, (void *)(uintptr_t)fibnum);
}
-static struct rtbridge rtsbridge = { .route_f = rts_handle_route_event };
+static struct rtbridge rtsbridge = {
+ .route_f = rts_handle_route_event,
+ .ifmsg_f = rtsock_ifmsg,
+};
static struct rtbridge *rtsbridge_orig_p;
static void
@@ -1916,8 +1920,8 @@
* This routine is called to generate a message from the routing
* socket indicating that the status of a network interface has changed.
*/
-void
-rt_ifmsg(struct ifnet *ifp)
+static void
+rtsock_ifmsg(struct ifnet *ifp, int if_flags_mask __unused)
{
struct if_msghdr *ifm;
struct mbuf *m;
diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c
--- a/sys/net80211/ieee80211_freebsd.c
+++ b/sys/net80211/ieee80211_freebsd.c
@@ -1020,7 +1020,7 @@
}
void
-ieee80211_notify_ifnet_change(struct ieee80211vap *vap)
+ieee80211_notify_ifnet_change(struct ieee80211vap *vap, int if_flags_mask)
{
struct ifnet *ifp = vap->iv_ifp;
@@ -1028,7 +1028,7 @@
"interface state change");
CURVNET_SET(ifp->if_vnet);
- rt_ifmsg(ifp);
+ rt_ifmsg(ifp, if_flags_mask);
CURVNET_RESTORE();
}
diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h
--- a/sys/net80211/ieee80211_proto.h
+++ b/sys/net80211/ieee80211_proto.h
@@ -462,5 +462,5 @@
void ieee80211_notify_country(struct ieee80211vap *,
const uint8_t [IEEE80211_ADDR_LEN], const uint8_t cc[2]);
void ieee80211_notify_radio(struct ieee80211com *, int);
-void ieee80211_notify_ifnet_change(struct ieee80211vap *);
+void ieee80211_notify_ifnet_change(struct ieee80211vap *, int);
#endif /* _NET80211_IEEE80211_PROTO_H_ */
diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c
--- a/sys/net80211/ieee80211_proto.c
+++ b/sys/net80211/ieee80211_proto.c
@@ -1993,7 +1993,7 @@
* back in here and complete the work.
*/
ifp->if_drv_flags |= IFF_DRV_RUNNING;
- ieee80211_notify_ifnet_change(vap);
+ ieee80211_notify_ifnet_change(vap, IFF_DRV_RUNNING);
/*
* We are not running; if this we are the first vap
@@ -2107,7 +2107,7 @@
ieee80211_new_state_locked(vap, IEEE80211_S_INIT, -1);
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
ifp->if_drv_flags &= ~IFF_DRV_RUNNING; /* mark us stopped */
- ieee80211_notify_ifnet_change(vap);
+ ieee80211_notify_ifnet_change(vap, IFF_DRV_RUNNING);
if (--ic->ic_nrunning == 0) {
IEEE80211_DPRINTF(vap,
IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
diff --git a/sys/netlink/netlink_route.c b/sys/netlink/netlink_route.c
--- a/sys/netlink/netlink_route.c
+++ b/sys/netlink/netlink_route.c
@@ -106,7 +106,10 @@
return (error);
}
-static struct rtbridge nlbridge = { .route_f = rtnl_handle_route_event };
+static struct rtbridge nlbridge = {
+ .route_f = rtnl_handle_route_event,
+ .ifmsg_f = rtnl_handle_ifnet_event,
+};
static struct rtbridge *nlbridge_orig_p;
static void
diff --git a/sys/netlink/route/iface.c b/sys/netlink/route/iface.c
--- a/sys/netlink/route/iface.c
+++ b/sys/netlink/route/iface.c
@@ -68,7 +68,7 @@
int dumped;
};
-static eventhandler_tag ifdetach_event, ifattach_event, ifaddr_event;
+static eventhandler_tag ifdetach_event, ifattach_event, iflink_event, ifaddr_event;
static SLIST_HEAD(, nl_cloner) nl_cloners = SLIST_HEAD_INITIALIZER(nl_cloners);
@@ -234,11 +234,13 @@
* @nw: message writer
* @ifp: target interface
* @hdr: template header
+ * @if_flags_mask: changed if_[drv]_flags bitmask
*
* This function is called without epoch and MAY sleep.
*/
static bool
-dump_iface(struct nl_writer *nw, struct ifnet *ifp, const struct nlmsghdr *hdr)
+dump_iface(struct nl_writer *nw, struct ifnet *ifp, const struct nlmsghdr *hdr,
+ int if_flags_mask)
{
struct ifinfomsg *ifinfo;
@@ -253,13 +255,15 @@
ifinfo->ifi_type = ifp->if_type;
ifinfo->ifi_index = ifp->if_index;
ifinfo->ifi_flags = ifp_flags_to_netlink(ifp);
- ifinfo->ifi_change = 0;
-
- nlattr_add_string(nw, IFLA_IFNAME, if_name(ifp));
+ ifinfo->ifi_change = if_flags_mask;
struct if_state ifs = {};
get_operstate(ifp, &ifs);
+ if (ifs.ifla_operstate == IF_OPER_UP)
+ ifinfo->ifi_flags |= IFF_LOWER_UP;
+
+ nlattr_add_string(nw, IFLA_IFNAME, if_name(ifp));
nlattr_add_u8(nw, IFLA_OPERSTATE, ifs.ifla_operstate);
nlattr_add_u8(nw, IFLA_CARRIER, ifs.ifla_carrier);
@@ -387,7 +391,7 @@
NLP_LOG(LOG_DEBUG3, nlp, "fast track -> searching index %u", attrs.ifi_index);
if (ifp != NULL) {
if (match_iface(&attrs, ifp)) {
- if (!dump_iface(wa.nw, ifp, &wa.hdr))
+ if (!dump_iface(wa.nw, ifp, &wa.hdr, 0))
error = ENOMEM;
} else
error = ESRCH;
@@ -439,7 +443,7 @@
NL_LOG(LOG_DEBUG2, "Matched %d interface(s), dumping", offset);
for (int i = 0; error == 0 && i < offset; i++) {
- if (!dump_iface(wa.nw, match_array[i], &wa.hdr))
+ if (!dump_iface(wa.nw, match_array[i], &wa.hdr, 0))
error = ENOMEM;
}
for (int i = 0; i < offset; i++)
@@ -767,9 +771,9 @@
}
static void
-rtnl_handle_ifattach(void *arg, struct ifnet *ifp)
+rtnl_handle_ifevent(struct ifnet *ifp, int nlmsg_type, int if_flags_mask)
{
- struct nlmsghdr hdr = { .nlmsg_type = NL_RTM_NEWLINK };
+ struct nlmsghdr hdr = { .nlmsg_type = nlmsg_type };
struct nl_writer nw = {};
if (!nl_has_listeners(NETLINK_ROUTE, RTNLGRP_LINK))
@@ -779,25 +783,36 @@
NL_LOG(LOG_DEBUG, "error allocating mbuf");
return;
}
- dump_iface(&nw, ifp, &hdr);
+ dump_iface(&nw, ifp, &hdr, if_flags_mask);
nlmsg_flush(&nw);
}
+static void
+rtnl_handle_ifattach(void *arg, struct ifnet *ifp)
+{
+ NL_LOG(LOG_DEBUG2, "ifnet %s", if_name(ifp));
+ rtnl_handle_ifevent(ifp, NL_RTM_NEWLINK, 0);
+}
+
static void
rtnl_handle_ifdetach(void *arg, struct ifnet *ifp)
{
- struct nlmsghdr hdr = { .nlmsg_type = NL_RTM_DELLINK };
- struct nl_writer nw = {};
+ NL_LOG(LOG_DEBUG2, "ifnet %s", if_name(ifp));
+ rtnl_handle_ifevent(ifp, NL_RTM_DELLINK, 0);
+}
- if (!nl_has_listeners(NETLINK_ROUTE, RTNLGRP_LINK))
- return;
+static void
+rtnl_handle_iflink(void *arg, struct ifnet *ifp)
+{
+ NL_LOG(LOG_DEBUG2, "ifnet %s", if_name(ifp));
+ rtnl_handle_ifevent(ifp, NL_RTM_NEWLINK, 0);
+}
- if (!nlmsg_get_group_writer(&nw, NLMSG_LARGE, NETLINK_ROUTE, RTNLGRP_LINK)) {
- NL_LOG(LOG_DEBUG, "error allocating mbuf");
- return;
- }
- dump_iface(&nw, ifp, &hdr);
- nlmsg_flush(&nw);
+void
+rtnl_handle_ifnet_event(struct ifnet *ifp, int if_flags_mask)
+{
+ NL_LOG(LOG_DEBUG2, "ifnet %s", if_name(ifp));
+ rtnl_handle_ifevent(ifp, NL_RTM_NEWLINK, if_flags_mask);
}
static const struct rtnl_cmd_handler cmd_handlers[] = {
@@ -867,6 +882,9 @@
ifaddr_event = EVENTHANDLER_REGISTER(
rt_addrmsg, rtnl_handle_ifaddr, NULL,
EVENTHANDLER_PRI_ANY);
+ iflink_event = EVENTHANDLER_REGISTER(
+ ifnet_link_event, rtnl_handle_iflink, NULL,
+ EVENTHANDLER_PRI_ANY);
NL_VERIFY_PARSERS(all_parsers);
rtnl_iface_drivers_register();
rtnl_register_messages(cmd_handlers, NL_ARRAY_LEN(cmd_handlers));
@@ -878,4 +896,5 @@
EVENTHANDLER_DEREGISTER(ifnet_arrival_event, ifattach_event);
EVENTHANDLER_DEREGISTER(ifnet_departure_event, ifdetach_event);
EVENTHANDLER_DEREGISTER(rt_addrmsg, ifaddr_event);
+ EVENTHANDLER_DEREGISTER(ifnet_link_event, iflink_event);
}
diff --git a/sys/netlink/route/interface.h b/sys/netlink/route/interface.h
--- a/sys/netlink/route/interface.h
+++ b/sys/netlink/route/interface.h
@@ -42,6 +42,9 @@
unsigned ifi_change; /* IFF_* change mask */
};
+/* Linux-specific link-level state flag */
+#define IFF_LOWER_UP IFF_NETLINK_1
+
#ifndef _KERNEL
/* Compatilbility helpers */
#define _IFINFO_HDRLEN ((int)sizeof(struct ifinfomsg))
diff --git a/sys/netlink/route/route_var.h b/sys/netlink/route/route_var.h
--- a/sys/netlink/route/route_var.h
+++ b/sys/netlink/route/route_var.h
@@ -88,6 +88,7 @@
void rtnl_ifaces_destroy(void);
void rtnl_iface_add_cloner(struct nl_cloner *cloner);
void rtnl_iface_del_cloner(struct nl_cloner *cloner);
+void rtnl_handle_ifnet_event(struct ifnet *ifp, int if_change_mask);
/* iface_drivers.c */
void rtnl_iface_drivers_register(void);

File Metadata

Mime Type
text/plain
Expires
Tue, Nov 19, 1:23 AM (22 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14708062
Default Alt Text
D37597.diff (11 KB)

Event Timeline