aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet6/ip6_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet6/ip6_input.c')
-rw-r--r--sys/netinet6/ip6_input.c88
1 files changed, 81 insertions, 7 deletions
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index fc3816806797..577dc48e7ece 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -144,6 +144,17 @@ static struct netisr_handler ip6_nh = {
#endif
};
+#ifdef RSS
+static struct netisr_handler ip6_direct_nh = {
+ .nh_name = "ip6_direct",
+ .nh_handler = ip6_direct_input,
+ .nh_proto = NETISR_IPV6_DIRECT,
+ .nh_m2cpuid = rss_soft_m2cpuid_v6,
+ .nh_policy = NETISR_POLICY_CPU,
+ .nh_dispatch = NETISR_DISPATCH_HYBRID,
+};
+#endif
+
VNET_DECLARE(struct callout, in6_tmpaddrtimer_ch);
#define V_in6_tmpaddrtimer_ch VNET(in6_tmpaddrtimer_ch)
@@ -222,6 +233,9 @@ ip6_init(void)
}
netisr_register(&ip6_nh);
+#ifdef RSS
+ netisr_register(&ip6_direct_nh);
+#endif
}
/*
@@ -403,6 +417,66 @@ out:
return (1);
}
+#ifdef RSS
+/*
+ * IPv6 direct input routine.
+ *
+ * This is called when reinjecting completed fragments where
+ * all of the previous checking and book-keeping has been done.
+ */
+void
+ip6_direct_input(struct mbuf *m)
+{
+ int off, nxt;
+ int nest;
+ struct m_tag *mtag;
+ struct ip6_direct_ctx *ip6dc;
+
+ mtag = m_tag_locate(m, MTAG_ABI_IPV6, IPV6_TAG_DIRECT, NULL);
+ KASSERT(mtag != NULL, ("Reinjected packet w/o direct ctx tag!"));
+
+ ip6dc = (struct ip6_direct_ctx *)(mtag + 1);
+ nxt = ip6dc->ip6dc_nxt;
+ off = ip6dc->ip6dc_off;
+
+ nest = 0;
+
+ m_tag_delete(m, mtag);
+
+ while (nxt != IPPROTO_DONE) {
+ if (V_ip6_hdrnestlimit && (++nest > V_ip6_hdrnestlimit)) {
+ IP6STAT_INC(ip6s_toomanyhdr);
+ goto bad;
+ }
+
+ /*
+ * protection against faulty packet - there should be
+ * more sanity checks in header chain processing.
+ */
+ if (m->m_pkthdr.len < off) {
+ IP6STAT_INC(ip6s_tooshort);
+ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
+ goto bad;
+ }
+
+#ifdef IPSEC
+ /*
+ * enforce IPsec policy checking if we are seeing last header.
+ * note that we do not visit this with protocols with pcb layer
+ * code - like udp/tcp/raw ip.
+ */
+ if (ip6_ipsec_input(m, nxt))
+ goto bad;
+#endif /* IPSEC */
+
+ nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
+ }
+ return;
+bad:
+ m_freem(m);
+}
+#endif
+
void
ip6_input(struct mbuf *m)
{
@@ -713,6 +787,13 @@ passin:
nxt = ip6->ip6_nxt;
/*
+ * Use mbuf flags to propagate Router Alert option to
+ * ICMPv6 layer, as hop-by-hop options have been stripped.
+ */
+ if (rtalert != ~0)
+ m->m_flags |= M_RTALERT_MLD;
+
+ /*
* Check that the amount of data in the buffers
* is as at least much as the IPv6 header would have us expect.
* Trim mbufs if longer than we expect.
@@ -809,13 +890,6 @@ passin:
goto bad;
#endif /* IPSEC */
- /*
- * Use mbuf flags to propagate Router Alert option to
- * ICMPv6 layer, as hop-by-hop options have been stripped.
- */
- if (nxt == IPPROTO_ICMPV6 && rtalert != ~0)
- m->m_flags |= M_RTALERT_MLD;
-
nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
}
return;