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--