+#if NSTF
+extern void stfattach(void);
+#endif /* NSTF */
+
+SYSCTL_DECL(_net_inet6_ip6);
+
+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,
+ * copy the contents of the mbuf chain into a new chain, and free the original
+ * one. Create some head room in the first mbuf of the new chain, in case
+ * it's needed later on.
+ *
+ * RFC 2460 says that IPv6 headers are 64-bit aligned, but network interfaces
+ * mostly align to 32-bit boundaries. Care should be taken never to use 64-bit
+ * load/store operations on the fields in IPv6 headers.
+ */
+#if defined(__i386__) || defined(__x86_64__)
+#define IP6_HDR_ALIGNMENT_FIXUP(_m, _ifp, _action) do { } while (0)
+#else /* !__i386__ && !__x86_64__ */
+#define IP6_HDR_ALIGNMENT_FIXUP(_m, _ifp, _action) do { \
+ if (!IP6_HDR_ALIGNED_P(mtod(_m, caddr_t))) { \
+ struct mbuf *_n; \
+ struct ifnet *__ifp = (_ifp); \
+ atomic_add_64(&(__ifp)->if_alignerrs, 1); \
+ if (((_m)->m_flags & M_PKTHDR) && \
+ (_m)->m_pkthdr.pkt_hdr != NULL) \
+ (_m)->m_pkthdr.pkt_hdr = NULL; \
+ _n = m_defrag_offset(_m, max_linkhdr, M_NOWAIT); \
+ if (_n == NULL) { \
+ ip6stat.ip6s_toosmall++; \
+ m_freem(_m); \
+ (_m) = NULL; \
+ _action; \
+ } else { \
+ VERIFY(_n != (_m)); \
+ (_m) = _n; \
+ } \
+ } \
+} while (0)
+#endif /* !__i386__ && !__x86_64__ */
+
+static void
+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 */
+}