Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys - implement IPv6 pmtud, which is necessary for TCP6.



details:   https://anonhg.NetBSD.org/src/rev/d876aee0a0bb
branches:  trunk
changeset: 474835:d876aee0a0bb
user:      itojun <itojun%NetBSD.org@localhost>
date:      Thu Jul 22 12:56:56 1999 +0000

description:
- implement IPv6 pmtud, which is necessary for TCP6.
- fix memory leak on SO_DEBUG over TCP.

diffstat:

 sys/netinet/tcp_input.c   |   19 ++++-
 sys/netinet/tcp_subr.c    |  159 ++++++++++++++++++++++++++++++++++++++++++---
 sys/netinet/tcp_var.h     |   11 ++-
 sys/netinet6/icmp6.c      |   84 +++++++++++++++++++++++-
 sys/netinet6/ip6_output.c |   10 ++-
 5 files changed, 261 insertions(+), 22 deletions(-)

diffs (truncated from 497 to 300 lines):

diff -r c9b93e90bc87 -r d876aee0a0bb sys/netinet/tcp_input.c
--- a/sys/netinet/tcp_input.c   Thu Jul 22 11:08:30 1999 +0000
+++ b/sys/netinet/tcp_input.c   Thu Jul 22 12:56:56 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tcp_input.c,v 1.88 1999/07/17 12:53:05 itojun Exp $    */
+/*     $NetBSD: tcp_input.c,v 1.89 1999/07/22 12:56:56 itojun Exp $    */
 
 /*
 %%% portions-copyright-nrl-95
@@ -1132,6 +1132,8 @@
                                sowwakeup(so);
                                if (so->so_snd.sb_cc)
                                        (void) tcp_output(tp);
+                               if (tcp_saveti)
+                                       m_freem(tcp_saveti);
                                return;
                        }
                } else if (th->th_ack == tp->snd_una &&
@@ -1157,6 +1159,8 @@
                        TCP_SETUP_ACK(tp, th);
                        if (tp->t_flags & TF_ACKNOW)
                                (void) tcp_output(tp);
+                       if (tcp_saveti)
+                               m_freem(tcp_saveti);
                        return;
                }
        }
@@ -1940,7 +1944,6 @@
        }
        if (so->so_options & SO_DEBUG) {
                tcp_trace(TA_INPUT, ostate, tp, tcp_saveti, 0);
-               m_freem(tcp_saveti);
        }
 
        /*
@@ -1948,6 +1951,8 @@
         */
        if (needoutput || (tp->t_flags & TF_ACKNOW))
                (void) tcp_output(tp);
+       if (tcp_saveti)
+               m_freem(tcp_saveti);
        return;
 
 badsyn:
@@ -1968,6 +1973,8 @@
        m_freem(m);
        tp->t_flags |= TF_ACKNOW;
        (void) tcp_output(tp);
+       if (tcp_saveti)
+               m_freem(tcp_saveti);
        return;
 
 dropwithreset:
@@ -2015,6 +2022,8 @@
                (void)tcp_respond(tp, m, m, th, th->th_seq + tlen, (tcp_seq)0,
                    TH_RST|TH_ACK);
        }
+       if (tcp_saveti)
+               m_freem(tcp_saveti);
        return;
 
 drop:
@@ -2030,11 +2039,11 @@
 #endif
                else
                        so = NULL;
-               if (so && (so->so_options & SO_DEBUG) != 0) {
+               if (so && (so->so_options & SO_DEBUG) != 0)
                        tcp_trace(TA_DROP, ostate, tp, tcp_saveti, 0);
-                       m_freem(tcp_saveti);
-               }
        }
+       if (tcp_saveti)
+               m_freem(tcp_saveti);
        m_freem(m);
        return;
 }
diff -r c9b93e90bc87 -r d876aee0a0bb sys/netinet/tcp_subr.c
--- a/sys/netinet/tcp_subr.c    Thu Jul 22 11:08:30 1999 +0000
+++ b/sys/netinet/tcp_subr.c    Thu Jul 22 12:56:56 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tcp_subr.c,v 1.72 1999/07/14 22:37:14 itojun Exp $     */
+/*     $NetBSD: tcp_subr.c,v 1.73 1999/07/22 12:56:56 itojun Exp $     */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -138,6 +138,7 @@
 #include <netinet/ip6.h>
 #include <netinet6/in6_pcb.h>
 #include <netinet6/ip6_var.h>
+#include <netinet6/in6_var.h>
 #endif
 
 #include <netinet/tcp.h>
@@ -392,6 +393,9 @@
        ip6 = NULL;
 #endif
        if (m == 0) {
+               if (!template)
+                       return EINVAL;
+
                /* get family information from template */
                switch (mtod(template, struct ip *)->ip_v) {
                case 4:
@@ -411,7 +415,7 @@
                MGETHDR(m, M_DONTWAIT, MT_HEADER);
                if (m) {
                        MCLGET(m, M_DONTWAIT);
-                       if (!(m->m_flags & M_EXT)) {
+                       if ((m->m_flags & M_EXT) == 0) {
                                m_free(m);
                                m = NULL;
                        }
@@ -1011,6 +1015,37 @@
 
 #if defined(INET6) && !defined(TCP6)
 void
+tcp6_notify(in6p, error)
+       struct in6pcb *in6p;
+       int error;
+{
+       register struct tcpcb *tp = (struct tcpcb *)in6p->in6p_ppcb;
+       register struct socket *so = in6p->in6p_socket;
+
+       /*
+        * Ignore some errors if we are hooked up.
+        * If connection hasn't completed, has retransmitted several times,
+        * and receives a second error, give up now.  This is better
+        * than waiting a long time to establish a connection that
+        * can never complete.
+        */
+       if (tp->t_state == TCPS_ESTABLISHED &&
+            (error == EHOSTUNREACH || error == ENETUNREACH ||
+             error == EHOSTDOWN)) {
+               return;
+       } else if (TCPS_HAVEESTABLISHED(tp->t_state) == 0 &&
+           tp->t_rxtshift > 3 && tp->t_softerror)
+               so->so_error = error;
+       else 
+               tp->t_softerror = error;
+       wakeup((caddr_t) &so->so_timeo);
+       sorwakeup(so);
+       sowwakeup(so);
+}
+#endif
+
+#if defined(INET6) && !defined(TCP6)
+void
 tcp6_ctlinput(cmd, sa, ip6, m, off)
        int cmd;
        struct sockaddr *sa;
@@ -1018,7 +1053,62 @@
        struct mbuf *m;
        int off;
 {
-       (void)tcp_ctlinput(cmd, sa, (void *)ip6);
+       register struct tcphdr *thp;
+       struct tcphdr th;
+       void (*notify) __P((struct in6pcb *, int)) = tcp6_notify;
+       int nmatch;
+       extern struct in6_addr zeroin6_addr;    /* netinet6/in6_pcb.c */
+
+       if (cmd == PRC_QUENCH)
+               notify = tcp6_quench;
+       else if (cmd == PRC_MSGSIZE)
+               notify = tcp6_mtudisc;
+       else if (!PRC_IS_REDIRECT(cmd) &&
+                ((unsigned)cmd > PRC_NCMDS || inet6ctlerrmap[cmd] == 0))
+               return;
+       if (ip6) {
+               /*
+                * XXX: We assume that when ip6 is non NULL,
+                * M and OFF are valid.
+                */
+
+               /* translate addresses into internal form */
+               if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src)) {
+                       ip6->ip6_src.s6_addr16[1] =
+                               htons(m->m_pkthdr.rcvif->if_index);
+               }
+               if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) {
+                       ip6->ip6_dst.s6_addr16[1] =
+                               htons(m->m_pkthdr.rcvif->if_index);
+               }
+
+               if (m->m_len < off + sizeof(th)) {
+                       /*
+                        * this should be rare case,
+                        * so we compromise on this copy...
+                        */
+                       m_copydata(m, off, sizeof(th), (caddr_t)&th);
+                       thp = &th;
+               } else
+                       thp = (struct tcphdr *)(mtod(m, caddr_t) + off);
+               nmatch = in6_pcbnotify(&tcb6, sa, thp->th_dport, &ip6->ip6_src,
+                   thp->th_sport, cmd, notify);
+               if (nmatch == 0 && syn_cache_count &&
+                   (inet6ctlerrmap[cmd] == EHOSTUNREACH ||
+                    inet6ctlerrmap[cmd] == ENETUNREACH ||
+                    inet6ctlerrmap[cmd] == EHOSTDOWN)) {
+                       struct sockaddr_in6 sin6;
+                       bzero(&sin6, sizeof(sin6));
+                       sin6.sin6_len = sizeof(sin6);
+                       sin6.sin6_family = AF_INET6;
+                       sin6.sin6_port = thp->th_sport;
+                       sin6.sin6_addr = ip6->ip6_src;
+                       syn_cache_unreach((struct sockaddr *)&sin6, sa, thp);
+               }
+       } else {
+               (void) in6_pcbnotify(&tcb6, sa, 0, &zeroin6_addr,
+                                    0, cmd, notify);
+       }
 }
 #endif
 
@@ -1068,17 +1158,9 @@
 
                /* XXX mapped address case */
        }
-#ifdef INET6
-       else if (ip && ip->ip_v == 6 && sa->sa_family == AF_INET6) {
-               /* XXX do something for ip6 */
-       }
-#endif
        else {
                (void)in_pcbnotifyall(&tcbtable, satosin(sa)->sin_addr, errno,
                    notify);
-#ifdef INET6
-               /* XXX do something for ip6 */
-#endif
        }
        return NULL;
 }
@@ -1099,6 +1181,19 @@
                tp->snd_cwnd = tp->t_segsz;
 }
 
+#if defined(INET6) && !defined(TCP6)
+void
+tcp6_quench(in6p, errno)
+       struct in6pcb *in6p;
+       int errno;
+{
+       struct tcpcb *tp = in6totcpcb(in6p);
+
+       if (tp)
+               tp->snd_cwnd = tp->t_segsz;
+}
+#endif
+
 /*
  * On receipt of path MTU corrections, flush old route and replace it
  * with the new one.  Retransmit all unacknowledged packets, to ensure
@@ -1145,6 +1240,48 @@
        }
 }
 
+#if defined(INET6) && !defined(TCP6)
+void
+tcp6_mtudisc(in6p, errno)
+       struct in6pcb *in6p;
+       int errno;
+{
+       struct tcpcb *tp = in6totcpcb(in6p);
+       struct rtentry *rt = in6_pcbrtentry(in6p);
+
+       if (tp != 0) {
+               if (rt != 0) {
+                       /*
+                        * If this was not a host route, remove and realloc.
+                        */
+                       if ((rt->rt_flags & RTF_HOST) == 0) {
+                               in6_rtchange(in6p, errno);
+                               if ((rt = in6_pcbrtentry(in6p)) == 0)
+                                       return;
+                       }
+
+                       /*
+                        * Slow start out of the error condition.  We
+                        * use the MTU because we know it's smaller
+                        * than the previously transmitted segment.
+                        *
+                        * Note: This is more conservative than the
+                        * suggestion in draft-floyd-incr-init-win-03.
+                        */
+                       if (rt->rt_rmx.rmx_mtu != 0)
+                               tp->snd_cwnd =
+                                   TCP_INITIAL_WINDOW(tcp_init_win,
+                                   rt->rt_rmx.rmx_mtu);
+               }
+
+               /*
+                * Resend unacknowledged packets.
+                */
+               tp->snd_nxt = tp->snd_una;
+               tcp_output(tp);
+       }
+}
+#endif
 



Home | Main Index | Thread Index | Old Index