o Remove struct if_data from struct ifnet. Now it is merely API structure
for route(4) socket and ifmib(4) sysctl. o Move fields from if_data to ifnet, but keep all statistic counters separate, since they should disappear later. o Provide function if_data_copy() to fill if_data, utilize it in routing socket and ifmib handler. o Provide overridable ifnet(9) method to fetch counters. If no provided, if_get_counters_compat() would be used, that returns old counters. Sponsored by: Netflix Sponsored by: Nginx, Inc.
This commit is contained in:
parent
546451a2e5
commit
e6485f73de
84
sys/net/if.c
84
sys/net/if.c
@ -605,8 +605,7 @@ if_attach_internal(struct ifnet *ifp, int vmove)
|
||||
if_addgroup(ifp, IFG_ALL);
|
||||
|
||||
getmicrotime(&ifp->if_lastchange);
|
||||
ifp->if_data.ifi_epoch = time_uptime;
|
||||
ifp->if_data.ifi_datalen = sizeof(struct if_data);
|
||||
ifp->if_epoch = time_uptime;
|
||||
|
||||
KASSERT((ifp->if_transmit == NULL && ifp->if_qflush == NULL) ||
|
||||
(ifp->if_transmit != NULL && ifp->if_qflush != NULL),
|
||||
@ -615,7 +614,10 @@ if_attach_internal(struct ifnet *ifp, int vmove)
|
||||
ifp->if_transmit = if_transmit;
|
||||
ifp->if_qflush = if_qflush;
|
||||
}
|
||||
|
||||
|
||||
if (ifp->if_get_counter == NULL)
|
||||
ifp->if_get_counter = if_get_counter_compat;
|
||||
|
||||
if (!vmove) {
|
||||
#ifdef MAC
|
||||
mac_ifnet_create(ifp);
|
||||
@ -1383,6 +1385,77 @@ if_rtdel(struct radix_node *rn, void *arg)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return counter values from old racy non-pcpu counters.
|
||||
*/
|
||||
uint64_t
|
||||
if_get_counter_compat(struct ifnet *ifp, ifnet_counter cnt)
|
||||
{
|
||||
|
||||
switch (cnt) {
|
||||
case IFCOUNTER_IPACKETS:
|
||||
return (ifp->if_ipackets);
|
||||
case IFCOUNTER_IERRORS:
|
||||
return (ifp->if_ierrors);
|
||||
case IFCOUNTER_OPACKETS:
|
||||
return (ifp->if_opackets);
|
||||
case IFCOUNTER_OERRORS:
|
||||
return (ifp->if_oerrors);
|
||||
case IFCOUNTER_COLLISIONS:
|
||||
return (ifp->if_collisions);
|
||||
case IFCOUNTER_IBYTES:
|
||||
return (ifp->if_ibytes);
|
||||
case IFCOUNTER_OBYTES:
|
||||
return (ifp->if_obytes);
|
||||
case IFCOUNTER_IMCASTS:
|
||||
return (ifp->if_imcasts);
|
||||
case IFCOUNTER_OMCASTS:
|
||||
return (ifp->if_omcasts);
|
||||
case IFCOUNTER_IQDROPS:
|
||||
return (ifp->if_iqdrops);
|
||||
case IFCOUNTER_OQDROPS:
|
||||
return (ifp->if_oqdrops);
|
||||
case IFCOUNTER_NOPROTO:
|
||||
return (ifp->if_noproto);
|
||||
}
|
||||
panic("%s: unknown counter %d", __func__, cnt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy data from ifnet to userland API structure if_data.
|
||||
*/
|
||||
void
|
||||
if_data_copy(struct ifnet *ifp, struct if_data *ifd)
|
||||
{
|
||||
|
||||
ifd->ifi_type = ifp->if_type;
|
||||
ifd->ifi_physical = 0;
|
||||
ifd->ifi_addrlen = ifp->if_addrlen;
|
||||
ifd->ifi_hdrlen = ifp->if_hdrlen;
|
||||
ifd->ifi_link_state = ifp->if_link_state;
|
||||
ifd->ifi_vhid = 0;
|
||||
ifd->ifi_datalen = sizeof(struct if_data);
|
||||
ifd->ifi_mtu = ifp->if_mtu;
|
||||
ifd->ifi_metric = ifp->if_metric;
|
||||
ifd->ifi_baudrate = ifp->if_baudrate;
|
||||
ifd->ifi_hwassist = ifp->if_hwassist;
|
||||
ifd->ifi_epoch = ifp->if_epoch;
|
||||
ifd->ifi_lastchange = ifp->if_lastchange;
|
||||
|
||||
ifd->ifi_ipackets = ifp->if_get_counter(ifp, IFCOUNTER_IPACKETS);
|
||||
ifd->ifi_ierrors = ifp->if_get_counter(ifp, IFCOUNTER_IERRORS);
|
||||
ifd->ifi_opackets = ifp->if_get_counter(ifp, IFCOUNTER_OPACKETS);
|
||||
ifd->ifi_oerrors = ifp->if_get_counter(ifp, IFCOUNTER_OERRORS);
|
||||
ifd->ifi_collisions = ifp->if_get_counter(ifp, IFCOUNTER_COLLISIONS);
|
||||
ifd->ifi_ibytes = ifp->if_get_counter(ifp, IFCOUNTER_IBYTES);
|
||||
ifd->ifi_obytes = ifp->if_get_counter(ifp, IFCOUNTER_OBYTES);
|
||||
ifd->ifi_imcasts = ifp->if_get_counter(ifp, IFCOUNTER_IMCASTS);
|
||||
ifd->ifi_omcasts = ifp->if_get_counter(ifp, IFCOUNTER_OMCASTS);
|
||||
ifd->ifi_iqdrops = ifp->if_get_counter(ifp, IFCOUNTER_IQDROPS);
|
||||
ifd->ifi_oqdrops = ifp->if_get_counter(ifp, IFCOUNTER_OQDROPS);
|
||||
ifd->ifi_noproto = ifp->if_get_counter(ifp, IFCOUNTER_NOPROTO);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper functions for struct ifnet address list locking macros. These are
|
||||
* used by kernel modules to avoid encoding programming interface or binary
|
||||
@ -2167,7 +2240,8 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
|
||||
break;
|
||||
|
||||
case SIOCGIFPHYS:
|
||||
ifr->ifr_phys = ifp->if_physical;
|
||||
/* XXXGL: did this ever worked? */
|
||||
ifr->ifr_phys = 0;
|
||||
break;
|
||||
|
||||
case SIOCGIFDESCR:
|
||||
@ -3915,7 +3989,7 @@ if_sendq_prepend(if_t ifp, struct mbuf *m)
|
||||
int
|
||||
if_setifheaderlen(if_t ifp, int len)
|
||||
{
|
||||
((struct ifnet *)ifp)->if_data.ifi_hdrlen = len;
|
||||
((struct ifnet *)ifp)->if_hdrlen = len;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -99,10 +99,9 @@ sysctl_ifdata(SYSCTL_HANDLER_ARGS) /* XXX bad syntax! */
|
||||
bzero(&ifmd, sizeof(ifmd));
|
||||
strlcpy(ifmd.ifmd_name, ifp->if_xname, sizeof(ifmd.ifmd_name));
|
||||
|
||||
#define COPY(fld) ifmd.ifmd_##fld = ifp->if_##fld
|
||||
COPY(pcount);
|
||||
COPY(data);
|
||||
#undef COPY
|
||||
ifmd.ifmd_pcount = ifp->if_pcount;
|
||||
if_data_copy(ifp, &ifmd.ifmd_data);
|
||||
|
||||
ifmd.ifmd_flags = ifp->if_flags | ifp->if_drv_flags;
|
||||
ifmd.ifmd_snd_len = ifp->if_snd.ifq_len;
|
||||
ifmd.ifmd_snd_maxlen = ifp->if_snd.ifq_maxlen;
|
||||
|
@ -94,11 +94,27 @@ VNET_DECLARE(struct pfil_head, link_pfil_hook); /* packet filter hooks */
|
||||
#define V_link_pfil_hook VNET(link_pfil_hook)
|
||||
#endif /* _KERNEL */
|
||||
|
||||
typedef enum {
|
||||
IFCOUNTER_IPACKETS = 1,
|
||||
IFCOUNTER_IERRORS,
|
||||
IFCOUNTER_OPACKETS,
|
||||
IFCOUNTER_OERRORS,
|
||||
IFCOUNTER_COLLISIONS,
|
||||
IFCOUNTER_IBYTES,
|
||||
IFCOUNTER_OBYTES,
|
||||
IFCOUNTER_IMCASTS,
|
||||
IFCOUNTER_OMCASTS,
|
||||
IFCOUNTER_IQDROPS,
|
||||
IFCOUNTER_OQDROPS,
|
||||
IFCOUNTER_NOPROTO,
|
||||
} ifnet_counter;
|
||||
|
||||
typedef void (*if_start_fn_t)(struct ifnet *);
|
||||
typedef int (*if_ioctl_fn_t)(struct ifnet *, u_long, caddr_t);
|
||||
typedef void (*if_init_fn_t)(void *);
|
||||
typedef void (*if_qflush_fn_t)(struct ifnet *);
|
||||
typedef int (*if_transmit_fn_t)(struct ifnet *, struct mbuf *);
|
||||
typedef uint64_t (*if_get_counter_t)(struct ifnet *, ifnet_counter);
|
||||
|
||||
/* Opaque object pointing to interface structure (ifnet) */
|
||||
typedef void *if_t;
|
||||
@ -136,8 +152,21 @@ struct ifnet {
|
||||
size_t if_linkmiblen; /* length of above data */
|
||||
int if_drv_flags; /* driver-managed status flags */
|
||||
u_int if_refcount; /* reference count */
|
||||
|
||||
/* These fields are shared with struct if_data. */
|
||||
uint8_t if_type; /* ethernet, tokenring, etc */
|
||||
uint8_t if_addrlen; /* media address length */
|
||||
uint8_t if_hdrlen; /* media header length */
|
||||
uint8_t if_link_state; /* current link state */
|
||||
uint32_t if_spare32;
|
||||
uint32_t if_mtu; /* maximum transmission unit */
|
||||
uint32_t if_metric; /* routing metric (external only) */
|
||||
uint64_t if_baudrate; /* linespeed */
|
||||
uint64_t if_hwassist; /* HW offload capabilities, see IFCAP */
|
||||
time_t if_epoch; /* uptime at attach or stat reset */
|
||||
struct timeval if_lastchange; /* time of last administrative change */
|
||||
|
||||
struct ifaltq if_snd; /* output queue (includes altq) */
|
||||
struct if_data if_data; /* type information and statistics */
|
||||
struct task if_linktask; /* task for link change events */
|
||||
|
||||
/* Addresses of different protocol families assigned to this if. */
|
||||
@ -190,6 +219,7 @@ struct ifnet {
|
||||
|
||||
void (*if_reassign) /* reassign to vnet routine */
|
||||
(struct ifnet *, struct vnet *, char *);
|
||||
if_get_counter_t if_get_counter; /* get counter values */
|
||||
|
||||
/* Stuff that's only temporary and doesn't belong here. */
|
||||
u_int if_hw_tsomax; /* tso burst length limit, the minimum
|
||||
@ -197,45 +227,31 @@ struct ifnet {
|
||||
* XXXAO: Have to find a better place
|
||||
* for it eventually. */
|
||||
/*
|
||||
* Spare fields are added so that we can modify sensitive data
|
||||
* structures without changing the kernel binary interface, and must
|
||||
* be used with care where binary compatibility is required.
|
||||
* Old, racy and expensive statistics, should not be used in
|
||||
* new drivers.
|
||||
*/
|
||||
uint64_t if_ipackets; /* packets received on interface */
|
||||
uint64_t if_ierrors; /* input errors on interface */
|
||||
uint64_t if_opackets; /* packets sent on interface */
|
||||
uint64_t if_oerrors; /* output errors on interface */
|
||||
uint64_t if_collisions; /* collisions on csma interfaces */
|
||||
uint64_t if_ibytes; /* total number of octets received */
|
||||
uint64_t if_obytes; /* total number of octets sent */
|
||||
uint64_t if_imcasts; /* packets received via multicast */
|
||||
uint64_t if_omcasts; /* packets sent via multicast */
|
||||
uint64_t if_iqdrops; /* dropped on input */
|
||||
uint64_t if_oqdrops; /* dropped on output */
|
||||
uint64_t if_noproto; /* destined for unsupported protocol */
|
||||
|
||||
/*
|
||||
* Spare fields to be added before branching a stable branch, so
|
||||
* that structure can be enhanced without changing the kernel
|
||||
* binary interface.
|
||||
*/
|
||||
char if_cspare[3];
|
||||
int if_ispare[4];
|
||||
void *if_unused[2];
|
||||
void *if_pspare[8]; /* 1 netmap, 7 TDB */
|
||||
};
|
||||
|
||||
#include <net/ifq.h> /* XXXAO: temporary unconditional include */
|
||||
|
||||
/*
|
||||
* XXX These aliases are terribly dangerous because they could apply
|
||||
* to anything.
|
||||
*/
|
||||
#define if_mtu if_data.ifi_mtu
|
||||
#define if_type if_data.ifi_type
|
||||
#define if_physical if_data.ifi_physical
|
||||
#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
|
||||
#define if_ierrors if_data.ifi_ierrors
|
||||
#define if_opackets if_data.ifi_opackets
|
||||
#define if_oerrors if_data.ifi_oerrors
|
||||
#define if_collisions if_data.ifi_collisions
|
||||
#define if_ibytes if_data.ifi_ibytes
|
||||
#define if_obytes if_data.ifi_obytes
|
||||
#define if_imcasts if_data.ifi_imcasts
|
||||
#define if_omcasts if_data.ifi_omcasts
|
||||
#define if_iqdrops if_data.ifi_iqdrops
|
||||
#define if_oqdrops if_data.ifi_oqdrops
|
||||
#define if_noproto if_data.ifi_noproto
|
||||
#define if_lastchange if_data.ifi_lastchange
|
||||
|
||||
/* for compatibility with other BSDs */
|
||||
#define if_addrlist if_addrhead
|
||||
#define if_list if_link
|
||||
@ -513,6 +529,8 @@ typedef void *if_com_alloc_t(u_char type, struct ifnet *ifp);
|
||||
typedef void if_com_free_t(void *com, u_char type);
|
||||
void if_register_com_alloc(u_char type, if_com_alloc_t *a, if_com_free_t *f);
|
||||
void if_deregister_com_alloc(u_char type);
|
||||
void if_data_copy(struct ifnet *, struct if_data *);
|
||||
uint64_t if_get_counter_compat(struct ifnet *, ifnet_counter);
|
||||
|
||||
#define IF_LLADDR(ifp) \
|
||||
LLADDR((struct sockaddr_dl *)((ifp)->if_addr->ifa_addr))
|
||||
|
@ -1252,7 +1252,7 @@ rt_ifmsg(struct ifnet *ifp)
|
||||
ifm = mtod(m, struct if_msghdr *);
|
||||
ifm->ifm_index = ifp->if_index;
|
||||
ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
|
||||
ifm->ifm_data = ifp->if_data;
|
||||
if_data_copy(ifp, &ifm->ifm_data);
|
||||
ifm->ifm_addrs = 0;
|
||||
rt_dispatch(m, AF_UNSPEC);
|
||||
}
|
||||
@ -1574,7 +1574,7 @@ sysctl_iflist_ifml(struct ifnet *ifp, struct rt_addrinfo *info,
|
||||
ifd = &ifm->ifm_data;
|
||||
}
|
||||
|
||||
*ifd = ifp->if_data;
|
||||
if_data_copy(ifp, ifd);
|
||||
|
||||
/* Some drivers still use ifqueue(9), add its stats. */
|
||||
ifd->ifi_oqdrops += ifp->if_snd.ifq_drops;
|
||||
@ -1609,7 +1609,7 @@ sysctl_iflist_ifm(struct ifnet *ifp, struct rt_addrinfo *info,
|
||||
ifd = &ifm->ifm_data;
|
||||
}
|
||||
|
||||
*ifd = ifp->if_data;
|
||||
if_data_copy(ifp, ifd);
|
||||
|
||||
/* Some drivers still use ifqueue(9), add its stats. */
|
||||
ifd->ifi_oqdrops += ifp->if_snd.ifq_drops;
|
||||
|
Loading…
Reference in New Issue
Block a user