diff options
Diffstat (limited to 'sys/netinet6/ip6_input.c')
| -rw-r--r-- | sys/netinet6/ip6_input.c | 88 |
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; |
