/*
- * Copyright (c) 2003-2015 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2016 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <net/ntstat.h>
#include <net/init.h>
#include <net/net_osdep.h>
+#include <net/net_perf.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
extern int ipsec_bypass;
#endif /* IPSEC */
-#if IPFW2
-#include <netinet6/ip6_fw.h>
-#endif /* IPFW2 */
-
#if DUMMYNET
#include <netinet/ip_fw.h>
#include <netinet/ip_dummynet.h>
#define ICMP6_IFSTAT_REQUIRE_ALIGNED_64(f) \
_CASSERT(!(offsetof(struct icmp6_ifstat, f) % sizeof (uint64_t)))
-#if IPFW2
-/* firewall hooks */
-ip6_fw_chk_t *ip6_fw_chk_ptr;
-ip6_fw_ctl_t *ip6_fw_ctl_ptr;
-int ip6_fw_enable = 1;
-#endif /* IPFW2 */
-
struct ip6stat ip6stat;
decl_lck_mtx_data(, proxy6_lock);
extern int loopattach_done;
extern void addrsel_policy_init(void);
+static int sysctl_reset_ip6_input_stats SYSCTL_HANDLER_ARGS;
+static int sysctl_ip6_input_measure_bins SYSCTL_HANDLER_ARGS;
+static int sysctl_ip6_input_getperf SYSCTL_HANDLER_ARGS;
static void ip6_init_delayed(void);
static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
SYSCTL_DECL(_net_inet6_ip6);
-int ip6_doscopedroute = 1;
-SYSCTL_INT(_net_inet6_ip6, OID_AUTO, scopedroute,
- CTLFLAG_RD | CTLFLAG_LOCKED, &ip6_doscopedroute, 0,
- "Enable IPv6 scoped routing");
-
static uint32_t ip6_adj_clear_hwcksum = 0;
SYSCTL_UINT(_net_inet6_ip6, OID_AUTO, adj_clear_hwcksum,
CTLFLAG_RW | CTLFLAG_LOCKED, &ip6_adj_clear_hwcksum, 0,
"Invalidate hwcksum info when adjusting length");
+static int ip6_input_measure = 0;
+SYSCTL_PROC(_net_inet6_ip6, OID_AUTO, input_perf,
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
+ &ip6_input_measure, 0, sysctl_reset_ip6_input_stats, "I", "Do time measurement");
+
+static uint64_t ip6_input_measure_bins = 0;
+SYSCTL_PROC(_net_inet6_ip6, OID_AUTO, input_perf_bins,
+ CTLTYPE_QUAD | CTLFLAG_RW | CTLFLAG_LOCKED, &ip6_input_measure_bins, 0,
+ sysctl_ip6_input_measure_bins, "I",
+ "bins for chaining performance data histogram");
+
+static net_perf_t net_perf;
+SYSCTL_PROC(_net_inet6_ip6, OID_AUTO, input_perf_data,
+ CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED,
+ 0, 0, sysctl_ip6_input_getperf, "S,net_perf",
+ "IP6 input performance data (struct net_perf, net/net_perf.h)");
+
/*
* On platforms which require strict alignment (currently for anything but
* i386 or x86_64), check if the IP header pointer is 32-bit aligned; if not,
ip6_proto_input(protocol_family_t protocol, mbuf_t packet)
{
#pragma unused(protocol)
+#if INET
+ struct timeval start_tv;
+ if (ip6_input_measure)
+ net_perf_start_time(&net_perf, &start_tv);
+#endif /* INET */
ip6_input(packet);
+#if INET
+ if (ip6_input_measure) {
+ net_perf_measure_time(&net_perf, &start_tv, 1);
+ net_perf_histogram(&net_perf, 1);
+ }
+#endif /* INET */
}
/*
return;
ip6_initialized = 1;
- PE_parse_boot_argn("net.inet6.ip6.scopedroute", &ip6_doscopedroute,
- sizeof (ip6_doscopedroute));
-
pr = pffindproto_locked(PF_INET6, IPPROTO_RAW, SOCK_RAW);
if (pr == NULL) {
panic("%s: Unable to find [PF_INET6,IPPROTO_RAW,SOCK_RAW]\n",
int nxt = 0, ours = 0;
struct ifnet *inifp, *deliverifp = NULL;
ipfilter_t inject_ipfref = NULL;
- int seen;
+ int seen = 1;
struct in6_ifaddr *ia6 = NULL;
struct sockaddr_in6 *dst6;
#if DUMMYNET
}
ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
+
/*
* Check against address spoofing/corruption.
*/
goto bad;
}
#endif
-#if IPFW2
- /*
- * Check with the firewall...
- */
- if (ip6_fw_enable && ip6_fw_chk_ptr) {
- u_short port = 0;
- /* If ipfw says divert, we have to just drop packet */
- /* use port as a dummy argument */
- if ((*ip6_fw_chk_ptr)(&ip6, NULL, &port, &m)) {
- m_freem(m);
- m = NULL;
- }
- if (!m)
- goto done;
- }
-#endif /* IPFW2 */
/*
* Naively assume we can attribute inbound data to the route we would
/*
* Call IP filter
*/
- if (!TAILQ_EMPTY(&ipv6_filters)) {
+ if (!TAILQ_EMPTY(&ipv6_filters) && !IFNET_IS_INTCOPROC(inifp)) {
ipf_ref();
TAILQ_FOREACH(filter, &ipv6_filters, ipf_link) {
if (seen == 0) {
* opthead + hbhlen is located in continuous memory region.
*/
int
-ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
- struct mbuf *m;
- u_int8_t *opthead;
- int hbhlen;
- u_int32_t *rtalertp;
- u_int32_t *plenp;
+ip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen,
+ u_int32_t *rtalertp, u_int32_t *plenp)
{
struct ip6_hdr *ip6;
int optlen = 0;
}
break;
case IPPROTO_ROUTING:
- if (!in6p->inp_flags & IN6P_RTHDR)
+ if (!(in6p->inp_flags & IN6P_RTHDR))
break;
mp = sbcreatecontrol_mbuf((caddr_t)ip6e, elen,
* we develop `neater' mechanism to process extension headers.
*/
char *
-ip6_get_prevhdr(m, off)
- struct mbuf *m;
- int off;
+ip6_get_prevhdr(struct mbuf *m, int off)
{
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
default:
return (-1);
}
-
- return (-1);
}
/*
0, 0, 0, 0,
ENOPROTOOPT
};
+
+static int
+sysctl_reset_ip6_input_stats SYSCTL_HANDLER_ARGS
+{
+#pragma unused(arg1, arg2)
+ int error, i;
+
+ i = ip6_input_measure;
+ error = sysctl_handle_int(oidp, &i, 0, req);
+ if (error || req->newptr == USER_ADDR_NULL)
+ goto done;
+ /* impose bounds */
+ if (i < 0 || i > 1) {
+ error = EINVAL;
+ goto done;
+ }
+ if (ip6_input_measure != i && i == 1) {
+ net_perf_initialize(&net_perf, ip6_input_measure_bins);
+ }
+ ip6_input_measure = i;
+done:
+ return (error);
+}
+
+static int
+sysctl_ip6_input_measure_bins SYSCTL_HANDLER_ARGS
+{
+#pragma unused(arg1, arg2)
+ int error;
+ uint64_t i;
+
+ i = ip6_input_measure_bins;
+ error = sysctl_handle_quad(oidp, &i, 0, req);
+ if (error || req->newptr == USER_ADDR_NULL)
+ goto done;
+ /* validate data */
+ if (!net_perf_validate_bins(i)) {
+ error = EINVAL;
+ goto done;
+ }
+ ip6_input_measure_bins = i;
+done:
+ return (error);
+}
+
+static int
+sysctl_ip6_input_getperf SYSCTL_HANDLER_ARGS
+{
+#pragma unused(oidp, arg1, arg2)
+ if (req->oldptr == USER_ADDR_NULL)
+ req->oldlen = (size_t)sizeof (struct ipstat);
+
+ return (SYSCTL_OUT(req, &net_perf, MIN(sizeof (net_perf), req->oldlen)));
+}