Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/ip_reass.c
Show First 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | |||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/hash.h> | #include <sys/hash.h> | ||||
#include <sys/mbuf.h> | #include <sys/mbuf.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/limits.h> | #include <sys/limits.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/socket.h> | |||||
#include <net/if.h> | |||||
#include <net/if_var.h> | |||||
#include <net/rss_config.h> | #include <net/rss_config.h> | ||||
#include <net/netisr.h> | #include <net/netisr.h> | ||||
#include <net/vnet.h> | #include <net/vnet.h> | ||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#include <netinet/ip.h> | #include <netinet/ip.h> | ||||
#include <netinet/ip_var.h> | #include <netinet/ip_var.h> | ||||
#include <netinet/in_rss.h> | #include <netinet/in_rss.h> | ||||
▲ Show 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
#define M_IP_FRAG M_PROTO9 | #define M_IP_FRAG M_PROTO9 | ||||
struct mbuf * | struct mbuf * | ||||
ip_reass(struct mbuf *m) | ip_reass(struct mbuf *m) | ||||
{ | { | ||||
struct ip *ip; | struct ip *ip; | ||||
struct mbuf *p, *q, *nq, *t; | struct mbuf *p, *q, *nq, *t; | ||||
struct ipq *fp; | struct ipq *fp; | ||||
struct ifnet *srcifp; | |||||
struct ipqhead *head; | struct ipqhead *head; | ||||
int i, hlen, next, tmpmax; | int i, hlen, next, tmpmax; | ||||
u_int8_t ecn, ecn0; | u_int8_t ecn, ecn0; | ||||
uint32_t hash, hashkey[3]; | uint32_t hash, hashkey[3]; | ||||
#ifdef RSS | #ifdef RSS | ||||
uint32_t rss_hash, rss_type; | uint32_t rss_hash, rss_type; | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | #endif | ||||
if (ntohs(ip->ip_len) + ntohs(ip->ip_off) > IP_MAXPACKET) { | if (ntohs(ip->ip_len) + ntohs(ip->ip_off) > IP_MAXPACKET) { | ||||
IPSTAT_INC(ips_toolong); | IPSTAT_INC(ips_toolong); | ||||
IPSTAT_INC(ips_fragdropped); | IPSTAT_INC(ips_fragdropped); | ||||
m_freem(m); | m_freem(m); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
/* | /* | ||||
* Store receive network interface pointer for later. | |||||
*/ | |||||
srcifp = m->m_pkthdr.rcvif; | |||||
/* | |||||
* Attempt reassembly; if it succeeds, proceed. | * Attempt reassembly; if it succeeds, proceed. | ||||
* ip_reass() will return a different mbuf. | * ip_reass() will return a different mbuf. | ||||
*/ | */ | ||||
IPSTAT_INC(ips_fragments); | IPSTAT_INC(ips_fragments); | ||||
m->m_pkthdr.PH_loc.ptr = ip; | m->m_pkthdr.PH_loc.ptr = ip; | ||||
/* | /* | ||||
* Presence of header sizes in mbufs | * Presence of header sizes in mbufs | ||||
▲ Show 20 Lines • Show All 233 Lines • ▼ Show 20 Lines | #endif | ||||
ip->ip_src = fp->ipq_src; | ip->ip_src = fp->ipq_src; | ||||
ip->ip_dst = fp->ipq_dst; | ip->ip_dst = fp->ipq_dst; | ||||
TAILQ_REMOVE(head, fp, ipq_list); | TAILQ_REMOVE(head, fp, ipq_list); | ||||
V_ipq[hash].count--; | V_ipq[hash].count--; | ||||
uma_zfree(V_ipq_zone, fp); | uma_zfree(V_ipq_zone, fp); | ||||
m->m_len += (ip->ip_hl << 2); | m->m_len += (ip->ip_hl << 2); | ||||
m->m_data -= (ip->ip_hl << 2); | m->m_data -= (ip->ip_hl << 2); | ||||
/* some debugging cruft by sklower, below, will go away soon */ | /* some debugging cruft by sklower, below, will go away soon */ | ||||
if (m->m_flags & M_PKTHDR) /* XXX this should be done elsewhere */ | if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */ | ||||
m_fixhdr(m); | m_fixhdr(m); | ||||
/* set valid receive interface pointer */ | |||||
m->m_pkthdr.rcvif = srcifp; | |||||
} | |||||
IPSTAT_INC(ips_reassembled); | IPSTAT_INC(ips_reassembled); | ||||
IPQ_UNLOCK(hash); | IPQ_UNLOCK(hash); | ||||
#ifdef RSS | #ifdef RSS | ||||
/* | /* | ||||
* Query the RSS layer for the flowid / flowtype for the | * Query the RSS layer for the flowid / flowtype for the | ||||
* mbuf payload. | * mbuf payload. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 98 Lines • ▼ Show 20 Lines | for (int i = 0; i < IPREASS_NHASH; i++) { | ||||
while(!TAILQ_EMPTY(&V_ipq[i].head)) | while(!TAILQ_EMPTY(&V_ipq[i].head)) | ||||
ipq_drop(&V_ipq[i], TAILQ_FIRST(&V_ipq[i].head)); | ipq_drop(&V_ipq[i], TAILQ_FIRST(&V_ipq[i].head)); | ||||
KASSERT(V_ipq[i].count == 0, | KASSERT(V_ipq[i].count == 0, | ||||
("%s: V_ipq[%d] count %d (V_ipq=%p)", __func__, i, | ("%s: V_ipq[%d] count %d (V_ipq=%p)", __func__, i, | ||||
V_ipq[i].count, V_ipq)); | V_ipq[i].count, V_ipq)); | ||||
IPQ_UNLOCK(i); | IPQ_UNLOCK(i); | ||||
} | } | ||||
} | } | ||||
/* | |||||
* Drain off all datagram fragments belonging to | |||||
* the given network interface. | |||||
*/ | |||||
static void | |||||
ipreass_cleanup(void *arg __unused, struct ifnet *ifp) | |||||
{ | |||||
struct ipq *fp, *temp; | |||||
struct mbuf *m; | |||||
bz: You can fold these two into one line. | |||||
int i; | |||||
Done Inline ActionsCan you add a KASSERT that ifp != NULL? bz: Can you add a KASSERT that ifp != NULL? | |||||
KASSERT(ifp != NULL, ("%s: ifp is NULL", __func__)); | |||||
Done Inline ActionsI'd remove the blank line. bz: I'd remove the blank line. | |||||
#ifdef VIMAGE | |||||
if (!vnet_is_running(ifp->if_vnet)) { | |||||
/* the IPv4 reassembly hash is destroyed */ | |||||
return; | |||||
} | |||||
Done Inline ActionsYou may want to go and have a look how "shutdown" is defined in if_detach_internal(). I think using the same logic here and in IPv6 is probably wise. bz: You may want to go and have a look how "shutdown" is defined in if_detach_internal(). I think… | |||||
Done Inline ActionsI'll update the code. hselasky: I'll update the code. | |||||
Done Inline ActionsThis block can be changed to: /* * Skip processing if IPv4 reassembly is not initialised * or torn down by ipreass_destroy(). */ if (V_ipq_zone == NULL) return; }}} bz: This block can be changed to:
{{{
/*
* Skip processing if IPv4 reassembly is not… | |||||
#endif | |||||
CURVNET_SET_QUIET(ifp->if_vnet); | |||||
Done Inline ActionsCan you do the assignment not on the declaration line; also the declaration could happen at the beginning of the function. Also Why is it mb and not just m? bz: Can you do the assignment not on the declaration line; also the declaration could happen at… | |||||
for (i = 0; i < IPREASS_NHASH; i++) { | |||||
IPQ_LOCK(i); | |||||
/* Scan fragment list. */ | |||||
TAILQ_FOREACH_SAFE(fp, &V_ipq[i].head, ipq_list, temp) { | |||||
for (m = fp->ipq_frags; m != NULL; m = m->m_nextpkt) { | |||||
/* clear no longer valid rcvif pointer */ | |||||
if (m->m_pkthdr.rcvif == ifp) | |||||
m->m_pkthdr.rcvif = NULL; | |||||
} | |||||
} | |||||
IPQ_UNLOCK(i); | |||||
} | |||||
CURVNET_RESTORE(); | |||||
} | |||||
EVENTHANDLER_DEFINE(ifnet_departure_event, ipreass_cleanup, NULL, 0); | |||||
#ifdef VIMAGE | #ifdef VIMAGE | ||||
/* | /* | ||||
* Destroy IP reassembly structures. | * Destroy IP reassembly structures. | ||||
*/ | */ | ||||
void | void | ||||
ipreass_destroy(void) | ipreass_destroy(void) | ||||
{ | { | ||||
ipreass_drain(); | ipreass_drain(); | ||||
uma_zdestroy(V_ipq_zone); | uma_zdestroy(V_ipq_zone); | ||||
Done Inline ActionsPlease add a V_ipq_zone = NULL; here. (If you really want to be fuzzy, you can use a temporary variable but VNET shutdown is single threaded so ...) bz: Please add a V_ipq_zone = NULL; here. (If you really want to be fuzzy, you can use a temporary… | |||||
for (int i = 0; i < IPREASS_NHASH; i++) | for (int i = 0; i < IPREASS_NHASH; i++) | ||||
mtx_destroy(&V_ipq[i].lock); | mtx_destroy(&V_ipq[i].lock); | ||||
} | } | ||||
#endif | #endif | ||||
/* | /* | ||||
* After maxnipq has been updated, propagate the change to UMA. The UMA zone | * After maxnipq has been updated, propagate the change to UMA. The UMA zone | ||||
* max has slightly different semantics than the sysctl, for historical | * max has slightly different semantics than the sysctl, for historical | ||||
▲ Show 20 Lines • Show All 175 Lines • Show Last 20 Lines |
You can fold these two into one line.