dlg@kbuild ~$ kstat ifstat egre0:0:ifstat:0 up: true link: true baudrate: 0 ibytes: 117208 bytes ipackets: 1196 packets ierrors: 0 packets iqdrops: 0 packets obytes: 0 bytes opackets: 0 packets oerrors: 0 packets oqdrops: 0 packets enc0:0:ifstat:0 up: false link: true baudrate: 0 ibytes: 0 bytes ipackets: 0 packets ierrors: 0 packets iqdrops: 0 packets obytes: 0 bytes opackets: 0 packets oerrors: 0 packets oqdrops: 0 packets lo0:0:ifstat:0 up: true link: true baudrate: 0 ibytes: 0 bytes ipackets: 0 packets ierrors: 0 packets iqdrops: 0 packets obytes: 0 bytes opackets: 0 packets oerrors: 0 packets oqdrops: 0 packets pflog0:0:ifstat:0 up: true link: true baudrate: 0 ibytes: 0 bytes ipackets: 0 packets ierrors: 0 packets iqdrops: 0 packets obytes: 18240 bytes opackets: 240 packets oerrors: 0 packets oqdrops: 0 packets veb0:0:ifstat:0 up: true link: true baudrate: 0 ibytes: 2006167 bytes ipackets: 9898 packets ierrors: 0 packets iqdrops: 0 packets obytes: 2006167 bytes opackets: 9898 packets oerrors: 0 packets oqdrops: 0 packets vmx0:0:ifstat:0 up: true link: true baudrate: 10000000000 ibytes: 1722796 bytes ipackets: 8232 packets ierrors: 0 packets iqdrops: 0 packets obytes: 283371 bytes opackets: 1666 packets oerrors: 0 packets oqdrops: 0 packets vmx1:0:ifstat:0 up: false link: true baudrate: 10000000000 ibytes: 0 bytes ipackets: 0 packets ierrors: 0 packets iqdrops: 0 packets obytes: 42 bytes opackets: 1 packets oerrors: 0 packets oqdrops: 0 packets vport0:0:ifstat:0 up: true link: true baudrate: 0 ibytes: 1722736 bytes ipackets: 8231 packets ierrors: 0 packets iqdrops: 0 packets obytes: 283371 bytes opackets: 1666 packets oerrors: 0 packets oqdrops: 0 packets vxlan0:0:ifstat:0 up: true link: true baudrate: 0 ibytes: 0 bytes ipackets: 0 packets ierrors: 0 packets iqdrops: 0 packets obytes: 0 bytes opackets: 0 packets oerrors: 0 packets oqdrops: 0 packets Index: if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.700 diff -u -p -r1.700 if.c --- if.c 12 Jun 2023 21:19:54 -0000 1.700 +++ if.c 24 Jun 2023 00:10:25 -0000 @@ -70,6 +70,7 @@ #include "ppp.h" #include "pppoe.h" #include "if_wg.h" +#include "kstat.h" #include #include @@ -135,6 +136,10 @@ #include #endif +#if NKSTAT > 0 +#include +#endif + #include void if_attachsetup(struct ifnet *); @@ -176,6 +181,11 @@ void ifa_print_all(void); void if_qstart_compat(struct ifqueue *); +#if NKSTAT > 0 +static void if_kstat_attach(struct ifnet *); +static void if_kstat_detach(struct ifnet *); +#endif + /* * interface index map * @@ -497,6 +507,10 @@ if_attachsetup(struct ifnet *ifp) /* Announce the interface. */ rtm_ifannounce(ifp, IFAN_ARRIVAL); + +#if NKSTAT > 0 + if_kstat_attach(ifp); +#endif } /* @@ -1127,6 +1141,10 @@ if_detach(struct ifnet *ifp) #endif NET_LOCK(); +#if NKSTAT > 0 + if_kstat_detach(ifp); +#endif + s = splnet(); ifp->if_ioctl = if_detached_ioctl; ifp->if_watchdog = NULL; @@ -2759,6 +2777,127 @@ if_getdata(struct ifnet *ifp, struct if_ ifiq_add_data(ifiq, data); } } + +#if NKSTAT +struct if_kstat_data { + struct kstat_kv kd_up; + struct kstat_kv kd_link; + struct kstat_kv kd_baudrate; + struct kstat_kv kd_ibytes; + struct kstat_kv kd_ipackets; + struct kstat_kv kd_ierrors; + struct kstat_kv kd_iqdrops; + struct kstat_kv kd_obytes; + struct kstat_kv kd_opackets; + struct kstat_kv kd_oerrors; + struct kstat_kv kd_oqdrops; +}; + +static const struct if_kstat_data if_kstat_data_template = { + KSTAT_KV_INITIALIZER("up", KSTAT_KV_T_BOOL), + KSTAT_KV_INITIALIZER("link", KSTAT_KV_T_BOOL), + KSTAT_KV_UNIT_INITIALIZER("baudrate", + KSTAT_KV_T_UINT64, KSTAT_KV_U_NONE), + + KSTAT_KV_UNIT_INITIALIZER("ibytes", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_BYTES), + KSTAT_KV_UNIT_INITIALIZER("ipackets", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("ierrors", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("iqdrops", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + + KSTAT_KV_UNIT_INITIALIZER("obytes", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_BYTES), + KSTAT_KV_UNIT_INITIALIZER("opackets", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("oerrors", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("oqdrops", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), +}; + +static int if_kstat_read(struct kstat *); + +static void +if_kstat_attach(struct ifnet *ifp) +{ + struct kstat *ks; + struct if_kstat_data *kd; + + kd = malloc(sizeof(*kd), M_DEVBUF, M_WAITOK|M_CANFAIL|M_ZERO); + if (kd == NULL) + return; + + ks = kstat_create(ifp->if_xname, 0, "ifstat", 0, KSTAT_T_KV, 0); + if (ks == NULL) { + free(kd, M_DEVBUF, sizeof(*kd)); + return; + } + + *kd = if_kstat_data_template; + + /* which lock? */ + ks->ks_softc = ifp; + ks->ks_data = kd; + ks->ks_datalen = sizeof(*kd); + ks->ks_read = if_kstat_read; + + ifp->if_kstat = ks; + + kstat_install(ks); +} + +static int +if_kstat_read(struct kstat *ks) +{ + struct ifnet *ifp = ks->ks_softc; + struct if_kstat_data *kd = ks->ks_data; + struct if_data data; + + memset(&data, 0, sizeof(data)); + + NET_LOCK_SHARED(); + if_getdata(ifp, &data); + + kstat_kv_bool(&kd->kd_up) = !!ISSET(ifp->if_flags, IFF_RUNNING); + kstat_kv_bool(&kd->kd_link) = LINK_STATE_IS_UP(ifp->if_link_state); + NET_UNLOCK_SHARED(); + + nanouptime(&ks->ks_updated); + + kstat_kv_u64(&kd->kd_baudrate) = data.ifi_baudrate; + + kstat_kv_u64(&kd->kd_ibytes) = data.ifi_ibytes; + kstat_kv_u64(&kd->kd_ipackets) = data.ifi_ipackets; + kstat_kv_u64(&kd->kd_ierrors) = data.ifi_ierrors; + kstat_kv_u64(&kd->kd_iqdrops) = data.ifi_iqdrops; + + kstat_kv_u64(&kd->kd_obytes) = data.ifi_obytes; + kstat_kv_u64(&kd->kd_opackets) = data.ifi_opackets; + kstat_kv_u64(&kd->kd_oerrors) = data.ifi_oerrors; + kstat_kv_u64(&kd->kd_oqdrops) = data.ifi_oqdrops; + + return (0); +} + +static void +if_kstat_detach(struct ifnet *ifp) +{ + struct kstat *ks = ifp->if_kstat; + struct if_kstat_data *kd; + + if (ks == NULL) + return; + + kstat_remove(ks); + kd = ks->ks_data; + kstat_destroy(ks); + + free(kd, M_DEVBUF, sizeof(*kd)); +} +#endif /* * Dummy functions replaced in ifnet during detach (if protocols decide to Index: if_var.h =================================================================== RCS file: /cvs/src/sys/net/if_var.h,v retrieving revision 1.127 diff -u -p -r1.127 if_var.h --- if_var.h 30 May 2023 08:30:01 -0000 1.127 +++ if_var.h 24 Jun 2023 00:10:25 -0000 @@ -89,6 +89,7 @@ struct rtentry; struct ifnet; struct task; struct cpumem; +struct kstat; /* * Structure describing a `cloning' interface. @@ -183,6 +184,7 @@ struct ifnet { /* and the entries */ struct ifiqueue if_rcv; /* rx/input queue */ struct ifiqueue **if_iqs; /* [I] pointer to the array of iqs */ unsigned int if_niqs; /* [I] number of input queues */ + struct kstat *if_kstat; struct sockaddr_dl *if_sadl; /* [N] pointer to our sockaddr_dl */