Subject: Re: [review please] tcp syn cache cleanup code for sc->sc_so
To: Jason Thorpe <thorpej@nas.nasa.gov>
From: None <itojun@iijlab.net>
List: tech-net
Date: 08/24/1999 18:28:47
------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <22773.935486911.1@coconut.itojun.org>
Content-Transfer-Encoding: 7bit
>Perhaps something like a per-listen-socket queue of associated SYN
>cache entries ... so you just have immediate access to them when
>you nuke the listen socket...
How about this? (ignore some of extra changes in diffs)
itojun
------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <22773.935486911.2@coconut.itojun.org>
Content-Transfer-Encoding: 7bit
Index: tcp_input.c
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/sys/netinet/tcp_input.c,v
retrieving revision 1.5
retrieving revision 1.9
diff -c -r1.5 -r1.9
*** tcp_input.c 1999/08/19 12:11:59 1.5
--- tcp_input.c 1999/08/24 09:19:09 1.9
***************
*** 2330,2335 ****
--- 2330,2337 ----
#define SYN_CACHE_RM(sc) \
do { \
LIST_REMOVE((sc), sc_bucketq); \
+ (sc)->sc_tp = NULL; \
+ LIST_REMOVE((sc), sc_tpq); \
tcp_syn_cache[(sc)->sc_bucketidx].sch_length--; \
TAILQ_REMOVE(&tcp_syn_cache_timeq[(sc)->sc_rxtshift], (sc), sc_timeq); \
syn_cache_count--; \
***************
*** 2380,2387 ****
}
void
! syn_cache_insert(sc)
struct syn_cache *sc;
{
struct syn_cache_head *scp;
struct syn_cache *sc2;
--- 2382,2390 ----
}
void
! syn_cache_insert(sc, tp)
struct syn_cache *sc;
+ struct tcpcb *tp;
{
struct syn_cache_head *scp;
struct syn_cache *sc2;
***************
*** 2472,2477 ****
--- 2475,2483 ----
SYN_CACHE_TIMER_ARM(sc);
TAILQ_INSERT_TAIL(&tcp_syn_cache_timeq[sc->sc_rxtshift], sc, sc_timeq);
+ /* Link it from tcpcb entry */
+ LIST_INSERT_HEAD(&tp->t_sc, sc, sc_tpq);
+
/* Put it into the bucket. */
LIST_INSERT_HEAD(&scp->sch_bucket, sc, sc_bucketq);
scp->sch_length++;
***************
*** 2545,2550 ****
--- 2551,2586 ----
}
/*
+ * Remove syn cache created by the specified tcb entry,
+ * because this does not make sense to keep them
+ * (if there's no tcb entry, syn cache entry will never be used)
+ */
+ void
+ syn_cache_cleanup(tp)
+ struct tcpcb *tp;
+ {
+ struct syn_cache *sc, *nsc;
+ int s;
+
+ s = splsoftnet();
+
+ for (sc = LIST_FIRST(&tp->t_sc); sc != NULL; sc = nsc) {
+ nsc = LIST_NEXT(sc, sc_tpq);
+
+ #ifdef DIAGNOSTIC
+ if (sc->sc_tp != tp)
+ panic("invalid sc_tp in syn_cache_cleanup");
+ #endif
+ SYN_CACHE_RM(sc);
+ SYN_CACHE_PUT(sc);
+ }
+ /* just for safety */
+ LIST_INIT(&tp->t_sc);
+
+ splx(s);
+ }
+
+ /*
* Find an entry in the syn cache.
*/
struct syn_cache *
***************
*** 3119,3127 ****
sc->sc_requested_s_scale = 15;
sc->sc_request_r_scale = 15;
}
! sc->sc_so = so;
if (syn_cache_respond(sc, m) == 0) {
! syn_cache_insert(sc);
tcpstat.tcps_sndacks++;
tcpstat.tcps_sndtotal++;
} else {
--- 3155,3163 ----
sc->sc_requested_s_scale = 15;
sc->sc_request_r_scale = 15;
}
! sc->sc_tp = tp;
if (syn_cache_respond(sc, m) == 0) {
! syn_cache_insert(sc, tp);
tcpstat.tcps_sndacks++;
tcpstat.tcps_sndtotal++;
} else {
***************
*** 3187,3194 ****
m->m_data += max_linkhdr;
m->m_len = m->m_pkthdr.len = tlen;
#ifdef IPSEC
! /* use IPsec policy on listening socket, on SYN ACK */
! m->m_pkthdr.rcvif = (struct ifnet *)sc->sc_so;
#else
m->m_pkthdr.rcvif = NULL;
#endif
--- 3223,3244 ----
m->m_data += max_linkhdr;
m->m_len = m->m_pkthdr.len = tlen;
#ifdef IPSEC
! if (sc->sc_tp) {
! struct tcpcb *tp;
! struct socket *so;
!
! tp = sc->sc_tp;
! if (tp->t_inpcb)
! so = tp->t_inpcb->inp_socket;
! #ifdef INET6
! else if (tp->t_in6pcb)
! so = tp->t_in6pcb->in6p_socket;
! #endif
! else
! so = NULL;
! /* use IPsec policy on listening socket, on SYN ACK */
! m->m_pkthdr.rcvif = (struct ifnet *)so;
! }
#else
m->m_pkthdr.rcvif = NULL;
#endif
***************
*** 3327,3333 ****
#ifdef INET6
case AF_INET6:
error = ip6_output(m, NULL /*XXX*/, (struct route_in6 *)ro,
! 0, NULL);
break;
#endif
default:
--- 3377,3383 ----
#ifdef INET6
case AF_INET6:
error = ip6_output(m, NULL /*XXX*/, (struct route_in6 *)ro,
! 0, NULL, NULL);
break;
#endif
default:
Index: tcp_output.c
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/sys/netinet/tcp_output.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -c -r1.4 -r1.5
*** tcp_output.c 1999/08/11 06:04:32 1.4
--- tcp_output.c 1999/08/23 15:25:41 1.5
***************
*** 1060,1077 ****
{
struct ip6_pktopts *opts;
- #if BSD >= 43
if (tp->t_in6pcb)
opts = tp->t_in6pcb->in6p_outputopts;
else
opts = NULL;
error = ip6_output(m, opts, (struct route_in6 *)ro,
! so->so_options & SO_DONTROUTE, 0);
! #else
! opts = NULL;
! error = ip6_output(m, opts, (struct route_in6 *)ro,
! so->so_options & SO_DONTROUTE);
! #endif
break;
}
#endif
--- 1060,1071 ----
{
struct ip6_pktopts *opts;
if (tp->t_in6pcb)
opts = tp->t_in6pcb->in6p_outputopts;
else
opts = NULL;
error = ip6_output(m, opts, (struct route_in6 *)ro,
! so->so_options & SO_DONTROUTE, 0, NULL);
break;
}
#endif
Index: tcp_subr.c
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/sys/netinet/tcp_subr.c,v
retrieving revision 1.5
retrieving revision 1.9
diff -c -r1.5 -r1.9
*** tcp_subr.c 1999/08/11 06:04:32 1.5
--- tcp_subr.c 1999/08/24 09:19:09 1.9
***************
*** 656,662 ****
break;
#ifdef INET6
case AF_INET6:
! error = ip6_output(m, NULL, (struct route_in6 *)ro, 0, NULL);
break;
#endif
default:
--- 656,663 ----
break;
#ifdef INET6
case AF_INET6:
! error = ip6_output(m, NULL, (struct route_in6 *)ro, 0, NULL,
! NULL);
break;
#endif
default:
***************
*** 705,710 ****
--- 706,712 ----
tp->t_peermss = tcp_mssdflt;
tp->t_ourmss = tcp_mssdflt;
tp->t_segsz = tcp_mssdflt;
+ LIST_INIT(&tp->t_sc);
tp->t_flags = 0;
if (tcp_do_rfc1323 && tcp_do_win_scale)
***************
*** 897,902 ****
--- 899,905 ----
TCP_REASS_UNLOCK(tp);
TCP_CLEAR_DELACK(tp);
+ syn_cache_cleanup(tp);
if (tp->t_template) {
m_free(tp->t_template);
Index: tcp_var.h
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/sys/netinet/tcp_var.h,v
retrieving revision 1.4
retrieving revision 1.7
diff -c -r1.4 -r1.7
*** tcp_var.h 1999/08/12 13:58:16 1.4
--- tcp_var.h 1999/08/24 09:19:10 1.7
***************
*** 224,229 ****
--- 224,232 ----
/* SACK stuff */
struct ipqehead timeq; /* time sequenced queue (for SACK) */
+
+ /* pointer for syn cache entries*/
+ LIST_HEAD(, syn_cache) t_sc; /* list of entries by this tcb */
};
#ifdef _KERNEL
***************
*** 367,373 ****
u_int16_t sc_ourmaxseg;
u_int8_t sc_request_r_scale : 4,
sc_requested_s_scale : 4;
! struct socket *sc_so; /* listening socket */
};
struct syn_cache_head {
--- 370,378 ----
u_int16_t sc_ourmaxseg;
u_int8_t sc_request_r_scale : 4,
sc_requested_s_scale : 4;
!
! struct tcpcb *sc_tp; /* tcb for listening socket */
! LIST_ENTRY(syn_cache) sc_tpq; /* list of entries by same tp */
};
struct syn_cache_head {
***************
*** 679,691 ****
struct tcphdr *, unsigned int, unsigned int,
struct socket *so, struct mbuf *));
void syn_cache_init __P((void));
! void syn_cache_insert __P((struct syn_cache *));
struct syn_cache *syn_cache_lookup __P((struct sockaddr *, struct sockaddr *,
struct syn_cache_head **));
void syn_cache_reset __P((struct sockaddr *, struct sockaddr *,
struct tcphdr *));
int syn_cache_respond __P((struct syn_cache *, struct mbuf *));
void syn_cache_timer __P((void));
int tcp_newreno __P((struct tcpcb *, struct tcphdr *));
#endif
--- 684,697 ----
struct tcphdr *, unsigned int, unsigned int,
struct socket *so, struct mbuf *));
void syn_cache_init __P((void));
! void syn_cache_insert __P((struct syn_cache *, struct tcpcb *));
struct syn_cache *syn_cache_lookup __P((struct sockaddr *, struct sockaddr *,
struct syn_cache_head **));
void syn_cache_reset __P((struct sockaddr *, struct sockaddr *,
struct tcphdr *));
int syn_cache_respond __P((struct syn_cache *, struct mbuf *));
void syn_cache_timer __P((void));
+ void syn_cache_cleanup __P((struct tcpcb *));
int tcp_newreno __P((struct tcpcb *, struct tcphdr *));
#endif
------- =_aaaaaaaaaa0--