summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/net/if.c103
-rw-r--r--sys/net/if.h22
-rw-r--r--sys/net/if_var.h13
-rw-r--r--sys/sys/sockio.h4
4 files changed, 138 insertions, 4 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 3169e06ab61..fd0e8539ca6 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.292 2014/06/26 13:08:25 mpi Exp $ */
+/* $OpenBSD: if.c,v 1.293 2014/07/08 04:02:14 dlg Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
@@ -178,6 +178,8 @@ int if_cloners_count;
struct pool ifaddr_item_pl;
+int net_livelocked(void);
+
/*
* Network interface utility routines.
*
@@ -2379,3 +2381,102 @@ ifnewlladdr(struct ifnet *ifp)
}
splx(s);
}
+
+int
+net_livelocked()
+{
+ extern int ticks;
+ extern int m_clticks;
+
+ return (ticks - m_clticks > 1);
+}
+
+void
+if_rxr_init(struct if_rxring *rxr, u_int lwm, u_int hwm)
+{
+ extern int ticks;
+
+ memset(rxr, 0, sizeof(*rxr));
+
+ rxr->rxr_adjusted = ticks;
+ rxr->rxr_cwm = rxr->rxr_lwm = lwm;
+ rxr->rxr_hwm = hwm;
+}
+
+static inline void
+if_rxr_adjust_cwm(struct if_rxring *rxr)
+{
+ extern int ticks;
+
+ if (net_livelocked()) {
+ if (rxr->rxr_cwm > rxr->rxr_lwm)
+ rxr->rxr_cwm--;
+ else
+ return;
+ } else if (rxr->rxr_alive > 4)
+ return;
+ else if (rxr->rxr_cwm < rxr->rxr_hwm)
+ rxr->rxr_cwm++;
+
+ rxr->rxr_adjusted = ticks;
+}
+
+u_int
+if_rxr_get(struct if_rxring *rxr, u_int max)
+{
+ extern int ticks;
+ u_int diff;
+
+ if (ticks - rxr->rxr_adjusted >= 1) {
+ /* we're free to try for an adjustment */
+ if_rxr_adjust_cwm(rxr);
+ }
+
+ if (rxr->rxr_alive >= rxr->rxr_cwm)
+ return (0);
+
+ diff = min(rxr->rxr_cwm - rxr->rxr_alive, max);
+ rxr->rxr_alive += diff;
+
+ return (diff);
+}
+
+int
+if_rxr_info_ioctl(struct if_rxrinfo *uifri, u_int t, struct if_rxring_info *e)
+{
+ struct if_rxrinfo kifri;
+ int error;
+ u_int n;
+
+ error = copyin(uifri, &kifri, sizeof(kifri));
+ if (error)
+ return (error);
+
+ n = min(t, kifri.ifri_total);
+ kifri.ifri_total = t;
+
+ if (n > 0) {
+ error = copyout(e, kifri.ifri_entries, sizeof(*e) * n);
+ if (error)
+ return (error);
+ }
+
+ return (copyout(&kifri, uifri, sizeof(kifri)));
+}
+
+int
+if_rxr_ioctl(struct if_rxrinfo *ifri, const char *name, u_int size,
+ struct if_rxring *rxr)
+{
+ struct if_rxring_info ifr;
+
+ memset(&ifr, 0, sizeof(ifr));
+
+ if (name != NULL)
+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+
+ ifr.ifr_size = size;
+ ifr.ifr_info = *rxr;
+
+ return (if_rxr_info_ioctl(ifri, 1, &ifr));
+}
diff --git a/sys/net/if.h b/sys/net/if.h
index 696e5a14fa7..23c0bec0d30 100644
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.h,v 1.154 2014/06/13 07:28:12 mpi Exp $ */
+/* $OpenBSD: if.h,v 1.155 2014/07/08 04:02:14 dlg Exp $ */
/* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */
/*
@@ -79,6 +79,26 @@ struct mclpool {
u_short mcl_lwm;
};
+struct if_rxring {
+ int rxr_adjusted;
+ u_int rxr_alive;
+ u_int rxr_cwm;
+ u_int rxr_lwm;
+ u_int rxr_hwm;
+};
+
+struct if_rxring_info {
+ char ifr_name[16]; /* name of the ring */
+ u_int ifr_size; /* size of the packets on the ring */
+ struct if_rxring ifr_info;
+};
+
+/* Structure used in SIOCGIFRXR request. */
+struct if_rxrinfo {
+ u_int ifri_total;
+ struct if_rxring_info *ifri_entries;
+};
+
/*
* Structure defining statistics and other data kept regarding a network
* interface.
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 86ca9dd4d30..cd40d8becdd 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_var.h,v 1.11 2014/05/26 08:33:48 mpi Exp $ */
+/* $OpenBSD: if_var.h,v 1.12 2014/07/08 04:02:14 dlg Exp $ */
/* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */
/*
@@ -449,6 +449,17 @@ void ifa_add(struct ifnet *, struct ifaddr *);
void ifa_del(struct ifnet *, struct ifaddr *);
void ifa_update_broadaddr(struct ifnet *, struct ifaddr *,
struct sockaddr *);
+
+void if_rxr_init(struct if_rxring *, u_int, u_int);
+u_int if_rxr_get(struct if_rxring *, u_int);
+
+#define if_rxr_put(_r, _c) do { (_r)->rxr_alive -= (_c); } while (0)
+#define if_rxr_inuse(_r) ((_r)->rxr_alive)
+
+int if_rxr_info_ioctl(struct if_rxrinfo *, u_int, struct if_rxring_info *);
+int if_rxr_ioctl(struct if_rxrinfo *, const char *, u_int,
+ struct if_rxring *);
+
#endif /* _KERNEL */
#endif /* _NET_IF_VAR_H_ */
diff --git a/sys/sys/sockio.h b/sys/sys/sockio.h
index aa220bb6d69..3b96f210d57 100644
--- a/sys/sys/sockio.h
+++ b/sys/sys/sockio.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sockio.h,v 1.53 2013/10/13 10:10:04 reyk Exp $ */
+/* $OpenBSD: sockio.h,v 1.54 2014/07/08 04:02:14 dlg Exp $ */
/* $NetBSD: sockio.h,v 1.5 1995/08/23 00:40:47 thorpej Exp $ */
/*-
@@ -199,4 +199,6 @@
#define SIOCSETPFLOW _IOW('i', 253, struct ifreq)
#define SIOCGETPFLOW _IOWR('i', 254, struct ifreq)
+#define SIOCGIFRXR _IOW('i', 170, struct ifreq)
+
#endif /* !_SYS_SOCKIO_H_ */