diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/if.c | 103 | ||||
-rw-r--r-- | sys/net/if.h | 22 | ||||
-rw-r--r-- | sys/net/if_var.h | 13 | ||||
-rw-r--r-- | sys/sys/sockio.h | 4 |
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_ */ |