[RFC] add macros for ifnet statistic accounting

Andrey V. Elsukov ae at FreeBSD.org
Fri Dec 19 14:50:52 UTC 2014


On 20.11.2014 20:38, Adrian Chadd wrote:
> On 20 November 2014 09:33, Andrey V. Elsukov <ae at freebsd.org> wrote:
>> Hi All,
>>
>> we already did some changes in network stack in head/, that made ability
>> for merging changes into stable branches much harder.
>>
>> What you think about adding the following macro to head/:
>>
>> --- if_var.h    (revision 274736)
>> +++ if_var.h    (working copy)
>> @@ -111,6 +111,10 @@ typedef enum {
>>         IFCOUNTERS /* Array size. */
>>  } ift_counter;
>>
>> +#define        IFSTAT_ADD(ifp, name, value)    \
>> +    if_inc_counter((ifp), IFCOUNTER_ ## name, (value))
>> +#define        IFSTAT_INC(ifp, name)   IFSTAT_ADD(ifp, name, 1)
>> +
>>  typedef struct ifnet * if_t;
>>
>>  typedef        void (*if_start_fn_t)(if_t);
>>
>>
>> And then make a direct commit to stable/* branches like this:
>>
>> --- if_var.h    (revision 274750)
>> +++ if_var.h    (working copy)
>> @@ -104,6 +104,23 @@ VNET_DECLARE(struct pfil_head, link_pfil_hook);    /*
>>  #define        V_link_pfil_hook        VNET(link_pfil_hook)
>>  #endif /* _KERNEL */
>>
>> +#define        IFSTAT_ADD(ifp, name, value)    \
>> +    IFSTAT_ ## name ## _ADD(ifp, value)
>> +#define        IFSTAT_INC(ifp, name)   IFSTAT_ADD(ifp, name, 1)
>> +
>> +#define        IFSTAT_IPACKETS_ADD(ifp, inc)   (ifp)->if_ipackets += (inc)
>> +#define        IFSTAT_IERRORS_ADD(ifp, inc)    (ifp)->if_ierrors += (inc)
>> +#define        IFSTAT_OPACKETS_ADD(ifp, inc)   (ifp)->if_opackets += (inc)
>> +#define        IFSTAT_OERRORS_ADD(ifp, inc)    (ifp)->if_oerrors += (inc)
>> +#define        IFSTAT_COLLISIONS_ADD(ifp, inc) (ifp)->if_collisions += (inc)
>> +#define        IFSTAT_IBYTES_ADD(ifp, inc)     (ifp)->if_ibytes += (inc)
>> +#define        IFSTAT_OBYTES_ADD(ifp, inc)     (ifp)->if_obytes += (inc)
>> +#define        IFSTAT_IMCASTS_ADD(ifp, inc)    (ifp)->if_imcasts += (inc)
>> +#define        IFSTAT_OMCASTS_ADD(ifp, inc)    (ifp)->if_omcasts += (inc)
>> +#define        IFSTAT_IQDROPS_ADD(ifp, inc)    (ifp)->if_iqdrops += (inc)
>> +#define        IFSTAT_OQDROPS_ADD(ifp, inc)    /* NOP */
>> +#define        IFSTAT_NOPROTO_ADD(ifp, inc)    (ifp)->if_noproto += (inc)
>> +
>>  /*
>>   * Structure defining a queue for a network interface.
>>   */
>>
>> This can make merging a little bit easier, at least for generic code in
>> the network stack.

It looks there are not so much people, who wants this feature. We
discussed this with glebius@ and probably the better solution will be
merging ift_counter enum and adding if_inc_counter() function to
stable/10. I looked how other BSDs doing this accounting and only DfBSD
has macro IFNET_STAT_INC(). But since we are planning to make opaque
ifnet, it doesn't matter how we will do accounting, anyway it will be
incompatible with other BSDs.

If there is no objections I'll commit this after weekend.

Index: if.c
===================================================================
--- if.c	(revision 275939)
+++ if.c	(working copy)
@@ -1450,6 +1450,56 @@ if_rtdel(struct radix_node *rn, void *arg)
 }

 /*
+ * A compatibility function returns ifnet counter values.
+ */
+uint64_t
+if_get_counter_default(struct ifnet *ifp, ift_counter cnt)
+{
+
+	KASSERT(cnt < IFCOUNTERS, ("%s: invalid cnt %d", __func__, 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_NOPROTO: return (ifp->if_noproto);
+	};
+	return (0);
+}
+
+/*
+ * Increase an ifnet counter. Usually used for counters shared
+ * between the stack and a driver, but function supports them all.
+ */
+void
+if_inc_counter(struct ifnet *ifp, ift_counter cnt, int64_t inc)
+{
+
+	KASSERT(cnt < IFCOUNTERS, ("%s: invalid cnt %d", __func__, cnt));
+
+	switch (cnt) {
+	case IFCOUNTER_IPACKETS: ifp->if_ipackets += inc; break;
+	case IFCOUNTER_IERRORS: ifp->if_ierrors += inc; break;
+	case IFCOUNTER_OPACKETS: ifp->if_opackets += inc; break;
+	case IFCOUNTER_OERRORS: ifp->if_oerrors += inc; break;
+	case IFCOUNTER_COLLISIONS: ifp->if_collisions += inc; break;
+	case IFCOUNTER_IBYTES: ifp->if_ibytes += inc; break;
+	case IFCOUNTER_OBYTES: ifp->if_obytes += inc; break;
+	case IFCOUNTER_IMCASTS: ifp->if_imcasts += inc; break;
+	case IFCOUNTER_OMCASTS: ifp->if_omcasts += inc; break;
+	case IFCOUNTER_IQDROPS: ifp->if_iqdrops += inc; break;
+	case IFCOUNTER_NOPROTO: ifp->if_noproto += inc; break;
+	};
+}
+
+/*
  * Wrapper functions for struct ifnet address list locking macros.
These are
  * used by kernel modules to avoid encoding programming interface or binary
  * interface assumptions that may be violated when kernel-internal locking
Index: if_var.h
===================================================================
--- if_var.h	(revision 275939)
+++ if_var.h	(working copy)
@@ -104,6 +104,22 @@ VNET_DECLARE(struct pfil_head, link_pfil_hook);	/*
 #define	V_link_pfil_hook	VNET(link_pfil_hook)
 #endif /* _KERNEL */

+typedef enum {
+	IFCOUNTER_IPACKETS = 0,
+	IFCOUNTER_IERRORS,
+	IFCOUNTER_OPACKETS,
+	IFCOUNTER_OERRORS,
+	IFCOUNTER_COLLISIONS,
+	IFCOUNTER_IBYTES,
+	IFCOUNTER_OBYTES,
+	IFCOUNTER_IMCASTS,
+	IFCOUNTER_OMCASTS,
+	IFCOUNTER_IQDROPS,
+	IFCOUNTER_OQDROPS,
+	IFCOUNTER_NOPROTO,
+	IFCOUNTERS /* Array size. */
+} ift_counter;
+
 /*
  * Structure defining a queue for a network interface.
  */
@@ -981,6 +997,8 @@ typedef	void *if_com_alloc_t(u_char type, struct i
 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);
+uint64_t if_get_counter_default(struct ifnet *, ift_counter);
+void	if_inc_counter(struct ifnet *, ift_counter, int64_t);

 #define IF_LLADDR(ifp)							\
     LLADDR((struct sockaddr_dl *)((ifp)->if_addr->ifa_addr))


-- 
WBR, Andrey V. Elsukov

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 538 bytes
Desc: OpenPGP digital signature
URL: <http://lists.freebsd.org/pipermail/freebsd-net/attachments/20141219/fcc10505/attachment.sig>


More information about the freebsd-net mailing list