Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157399687
D56172.id175370.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D56172.id175370.diff
View Options
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -565,6 +565,9 @@
#define INP_HASH_WLOCK_ASSERT(ipi) mtx_assert(&(ipi)->ipi_hash_lock, \
MA_OWNED)
+VNET_DECLARE(uint32_t, in_pcbhashseed);
+#define V_in_pcbhashseed VNET(in_pcbhashseed)
+
/*
* Wildcard matching hash is not just a microoptimisation! The hash for
* wildcard IPv4 and wildcard IPv6 must be the same, otherwise AF_INET6
@@ -596,6 +599,10 @@
#define INP_PCBPORTHASH(lport, mask) (ntohs((lport)) & (mask))
+#define RIPCB_HASH(inp) (((inp)->inp_vflag & INP_IPV6) ? \
+ IN6_ADDR_JHASH32(&(inp)->in6p_faddr) : \
+ IN_ADDR_JHASH32(&(inp)->inp_faddr))
+
/*
* Flags passed to in_pcblookup*(), inp_smr_lock() and inp_next().
*/
@@ -666,6 +673,9 @@
bool in_pcbrele_rlocked(struct inpcb *);
bool in_pcbrele_wlocked(struct inpcb *);
bool in_pcbrele_rlock(struct inpcb *inp);
+void ripcb_connect(struct inpcb *);
+void ripcb_disconnect(struct inpcb *);
+
#ifdef _SYS_SOCKETVAR_H_
void in_pcbtoxinpcb(const struct inpcb *, struct xinpcb *);
int sysctl_setsockopt(SYSCTL_HANDLER_ARGS, struct inpcbinfo *pcbinfo,
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -2833,6 +2833,42 @@
}
}
+void
+ripcb_connect(struct inpcb *inp)
+{
+ struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
+ uint32_t hash;
+
+ INP_WLOCK_ASSERT(inp);
+ MPASS(inp->inp_flags & INP_UNCONNECTED);
+
+ hash = RIPCB_HASH(inp) & pcbinfo->ipi_hashmask;
+
+ INP_HASH_WLOCK(pcbinfo);
+ CK_LIST_REMOVE(inp, inp_unconn_list);
+ CK_LIST_INSERT_HEAD(&pcbinfo->ipi_hash_exact[hash], inp,
+ inp_hash_exact);
+ INP_HASH_WUNLOCK(pcbinfo);
+ inp->inp_flags &= ~INP_UNCONNECTED;
+}
+
+void
+ripcb_disconnect(struct inpcb *inp)
+{
+ struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
+
+ INP_WLOCK_ASSERT(inp);
+
+ if (inp->inp_flags & INP_UNCONNECTED)
+ return;
+
+ INP_HASH_WLOCK(pcbinfo);
+ CK_LIST_REMOVE(inp, inp_hash_exact);
+ CK_LIST_INSERT_HEAD(&pcbinfo->ipi_list_unconn, inp, inp_unconn_list);
+ INP_HASH_WUNLOCK(pcbinfo);
+ inp->inp_flags |= INP_UNCONNECTED;
+}
+
/*
* Check for alternatives when higher level complains
* about service problems. For now, invalidate cached
diff --git a/sys/netinet/in_pcb_var.h b/sys/netinet/in_pcb_var.h
--- a/sys/netinet/in_pcb_var.h
+++ b/sys/netinet/in_pcb_var.h
@@ -43,9 +43,6 @@
#define INP_UNCONNECTED 0x04000000 /* Not inserted into hashes. */
-VNET_DECLARE(uint32_t, in_pcbhashseed);
-#define V_in_pcbhashseed VNET(in_pcbhashseed)
-
void inp_lock(struct inpcb *inp, const inp_lookup_t lock);
void inp_unlock(struct inpcb *inp, const inp_lookup_t lock);
int inp_trylock(struct inpcb *inp, const inp_lookup_t lock);
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -41,6 +41,7 @@
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
+#include <sys/hash.h>
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/protosw.h>
@@ -140,53 +141,12 @@
SYSCTL_ULONG(_net_inet_raw, OID_AUTO, recvspace, CTLFLAG_RW,
&rip_recvspace, 0, "Maximum space for incoming raw IP datagrams");
-/*
- * Hash functions
- */
-
-#define INP_PCBHASH_RAW_SIZE 256
-#define INP_PCBHASH_RAW(proto, laddr, faddr, mask) \
- (((proto) + (laddr) + (faddr)) % (mask) + 1)
-
-#ifdef INET
-static void
-rip_inshash(struct inpcb *inp)
-{
- struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
- struct inpcbhead *pcbhash;
- int hash;
-
- INP_HASH_WLOCK_ASSERT(pcbinfo);
- INP_WLOCK_ASSERT(inp);
-
- if (inp->inp_ip_p != 0 &&
- inp->inp_laddr.s_addr != INADDR_ANY &&
- inp->inp_faddr.s_addr != INADDR_ANY) {
- hash = INP_PCBHASH_RAW(inp->inp_ip_p, inp->inp_laddr.s_addr,
- inp->inp_faddr.s_addr, pcbinfo->ipi_hashmask);
- } else
- hash = 0;
- pcbhash = &pcbinfo->ipi_hash_exact[hash];
- CK_LIST_INSERT_HEAD(pcbhash, inp, inp_hash_exact);
-}
-
-static void
-rip_delhash(struct inpcb *inp)
-{
-
- INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo);
- INP_WLOCK_ASSERT(inp);
-
- CK_LIST_REMOVE(inp, inp_hash_exact);
-}
-#endif /* INET */
-
INPCBSTORAGE_DEFINE(ripcbstor, inpcb, "rawinp", "ripcb", "riphash");
static void
rip_init(void *arg __unused)
{
-
+#define INP_PCBHASH_RAW_SIZE 256
in_pcbinfo_init(&V_ripcbinfo, &ripcbstor, INP_PCBHASH_RAW_SIZE, 1);
}
VNET_SYSINIT(rip_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, rip_init, NULL);
@@ -250,26 +210,7 @@
};
static bool
-rip_inp_match1(const struct inpcb *inp, void *v)
-{
- struct rip_inp_match_ctx *ctx = v;
-
- if (inp->inp_ip_p != ctx->proto)
- return (false);
-#ifdef INET6
- /* XXX inp locking */
- if ((inp->inp_vflag & INP_IPV4) == 0)
- return (false);
-#endif
- if (inp->inp_laddr.s_addr != ctx->ip->ip_dst.s_addr)
- return (false);
- if (inp->inp_faddr.s_addr != ctx->ip->ip_src.s_addr)
- return (false);
- return (true);
-}
-
-static bool
-rip_inp_match2(const struct inpcb *inp, void *v)
+rip_inp_match(const struct inpcb *inp, void *v)
{
struct rip_inp_match_ctx *ctx = v;
@@ -301,7 +242,7 @@
.proto = proto,
};
struct inpcb_iterator inpi = INP_ITERATOR(&V_ripcbinfo,
- INPLOOKUP_RLOCKPCB, rip_inp_match1, &ctx);
+ INPLOOKUP_RLOCKPCB, rip_inp_match, &ctx);
struct ifnet *ifp;
struct mbuf *m = *mp;
struct inpcb *inp;
@@ -321,8 +262,7 @@
fib = M_GETFIB(m);
ifp = m->m_pkthdr.rcvif;
- inpi.hash = INP_PCBHASH_RAW(proto, ctx.ip->ip_src.s_addr,
- ctx.ip->ip_dst.s_addr, V_ripcbinfo.ipi_hashmask);
+ inpi.mode = IN_ADDR_JHASH32(&ctx.ip->ip_src) & V_ripcbinfo.ipi_hashmask;
while ((inp = inp_next(&inpi)) != NULL) {
INP_RLOCK_ASSERT(inp);
if (jailed_without_vnet(inp->inp_cred) &&
@@ -342,8 +282,7 @@
appended += rip_append(inp, ctx.ip, m, &ripsrc);
}
- inpi.hash = 0;
- inpi.match = rip_inp_match2;
+ inpi.mode = INP_UNCONN_LIST;
MPASS(inpi.inp == NULL);
while ((inp = inp_next(&inpi)) != NULL) {
INP_RLOCK_ASSERT(inp);
@@ -837,9 +776,6 @@
inp = (struct inpcb *)so->so_pcb;
inp->inp_ip_p = proto;
inp->inp_ip_ttl = V_ip_defttl;
- INP_HASH_WLOCK(&V_ripcbinfo);
- rip_inshash(inp);
- INP_HASH_WUNLOCK(&V_ripcbinfo);
INP_WUNLOCK(inp);
return (0);
}
@@ -859,9 +795,6 @@
ip_mrouter_done(so);
INP_WLOCK(inp);
- INP_HASH_WLOCK(&V_ripcbinfo);
- rip_delhash(inp);
- INP_HASH_WUNLOCK(&V_ripcbinfo);
if (ip_rsvp_force_done)
ip_rsvp_force_done(so);
@@ -871,20 +804,17 @@
}
static void
-rip_dodisconnect(struct inpcb *inp)
+rip_dodisconnect(struct inpcb *inp, bool disconnect_socket)
{
- struct inpcbinfo *pcbinfo;
- pcbinfo = inp->inp_pcbinfo;
INP_WLOCK(inp);
- INP_HASH_WLOCK(pcbinfo);
- rip_delhash(inp);
inp->inp_faddr.s_addr = INADDR_ANY;
- rip_inshash(inp);
- INP_HASH_WUNLOCK(pcbinfo);
- SOCK_LOCK(inp->inp_socket);
- inp->inp_socket->so_state &= ~SS_ISCONNECTED;
- SOCK_UNLOCK(inp->inp_socket);
+ ripcb_disconnect(inp);
+ if (disconnect_socket) {
+ SOCK_LOCK(inp->inp_socket);
+ inp->inp_socket->so_state &= ~SS_ISCONNECTED;
+ SOCK_UNLOCK(inp->inp_socket);
+ }
INP_WUNLOCK(inp);
}
@@ -896,7 +826,7 @@
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("rip_abort: inp == NULL"));
- rip_dodisconnect(inp);
+ rip_dodisconnect(inp, true);
}
static void
@@ -907,7 +837,7 @@
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("rip_close: inp == NULL"));
- rip_dodisconnect(inp);
+ rip_dodisconnect(inp, true);
}
static int
@@ -921,7 +851,7 @@
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("rip_disconnect: inp == NULL"));
- rip_dodisconnect(inp);
+ rip_dodisconnect(inp, true);
return (0);
}
@@ -952,11 +882,7 @@
return (EADDRNOTAVAIL);
INP_WLOCK(inp);
- INP_HASH_WLOCK(&V_ripcbinfo);
- rip_delhash(inp);
inp->inp_laddr = addr->sin_addr;
- rip_inshash(inp);
- INP_HASH_WUNLOCK(&V_ripcbinfo);
INP_WUNLOCK(inp);
return (0);
}
@@ -978,11 +904,13 @@
KASSERT(inp != NULL, ("rip_connect: inp == NULL"));
INP_WLOCK(inp);
- INP_HASH_WLOCK(&V_ripcbinfo);
- rip_delhash(inp);
- inp->inp_faddr = addr->sin_addr;
- rip_inshash(inp);
- INP_HASH_WUNLOCK(&V_ripcbinfo);
+ if (inp->inp_faddr.s_addr != INADDR_ANY &&
+ addr->sin_addr.s_addr == INADDR_ANY)
+ rip_dodisconnect(inp, false);
+ if (addr->sin_addr.s_addr != INADDR_ANY) {
+ inp->inp_faddr = addr->sin_addr;
+ ripcb_connect(inp);
+ }
soisconnected(so);
INP_WUNLOCK(inp);
return (0);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, May 22, 12:07 AM (8 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33410187
Default Alt Text
D56172.id175370.diff (8 KB)
Attached To
Mode
D56172: raw ip: move hash table manipulation to inpcb layer
Attached
Detach File
Event Timeline
Log In to Comment