Index: tcp_usrreq.c =================================================================== RCS file: /cvs/src/sys/netinet/tcp_usrreq.c,v retrieving revision 1.183 diff -u -p -r1.183 tcp_usrreq.c --- tcp_usrreq.c 25 Feb 2022 23:51:03 -0000 1.183 +++ tcp_usrreq.c 20 May 2022 10:46:31 -0000 @@ -132,7 +132,8 @@ const struct sysctl_bounded_args tcpctl_ struct inpcbtable tcbtable; -int tcp_ident(void *, size_t *, void *, size_t, int); +int tcp_fill_info(const struct tcpcb *, struct mbuf *); +int tcp_ident(void *, size_t *, void *, size_t, int); /* * Process a TCP user request for TCP tb. If this is a send request @@ -425,6 +426,74 @@ tcp_usrreq(struct socket *so, int req, s return (error); } +/* + * Export TCP internal state information via a struct tcp_info. + */ +int +tcp_fill_info(const struct tcpcb *tp, struct mbuf *m) +{ + struct tcp_info *ti; + +printf("%s[%u]\n", __func__, __LINE__); + if (sizeof(*ti) > MLEN) { +printf("%s[%u]\n", __func__, __LINE__); + MCLGETL(m, M_WAITOK, sizeof(*ti)); + if (!ISSET(m->m_flags, M_EXT)) + return (ENOMEM); +printf("%s[%u]\n", __func__, __LINE__); + } + +printf("%s[%u]\n", __func__, __LINE__); + ti = mtod(m, struct tcp_info *); +printf("%s[%u]\n", __func__, __LINE__); + m->m_len = sizeof(*ti); +printf("%s[%u]\n", __func__, __LINE__); + +printf("%s[%u]\n", __func__, __LINE__); + bzero(ti, sizeof(*ti)); +printf("%s[%u]\n", __func__, __LINE__); + +printf("%s[%u]\n", __func__, __LINE__); + ti->tcpi_state = tp->t_state; + if ((tp->t_flags & TF_REQ_TSTMP) && (tp->t_flags & TF_RCVD_TSTMP)) + ti->tcpi_options |= TCPI_OPT_TIMESTAMPS; + if (tp->t_flags & TF_SACK_PERMIT) + ti->tcpi_options |= TCPI_OPT_SACK; + if ((tp->t_flags & TF_REQ_SCALE) && (tp->t_flags & TF_RCVD_SCALE)) { + ti->tcpi_options |= TCPI_OPT_WSCALE; + ti->tcpi_snd_wscale = tp->snd_scale; + ti->tcpi_rcv_wscale = tp->rcv_scale; + } + if (tp->t_flags & TF_ECN_PERMIT) { + ti->tcpi_options |= TCPI_OPT_ECN; + } + + ti->tcpi_rto = tp->t_rxtcur * tick; + ti->tcpi_last_data_recv = (long)(ticks - (int)tp->t_rcvtime) * tick; + ti->tcpi_rtt = ((u_int64_t)tp->t_srtt * tick) >> TCP_RTT_SHIFT; + ti->tcpi_rttvar = ((u_int64_t)tp->t_rttvar * tick) >> TCP_RTTVAR_SHIFT; + + ti->tcpi_snd_ssthresh = tp->snd_ssthresh; + ti->tcpi_snd_cwnd = tp->snd_cwnd; + + /* + * FreeBSD-specific extension fields for tcp_info. + */ + ti->tcpi_rcv_space = tp->rcv_wnd; + ti->tcpi_rcv_nxt = tp->rcv_nxt; + ti->tcpi_snd_wnd = tp->snd_wnd; + ti->tcpi_snd_bwnd = 0; /* Unused, kept for compat. */ + ti->tcpi_snd_nxt = tp->snd_nxt; + ti->tcpi_snd_mss = tp->t_maxseg; + ti->tcpi_rcv_mss = tp->t_maxseg; + ti->tcpi_snd_rexmitpack = tp->t_sndrexmitpack; + ti->tcpi_rcv_ooopack = tp->t_rcvoopack; + ti->tcpi_snd_zerowin = tp->t_sndzerowin; + +printf("%s[%u]\n", __func__, __LINE__); + return (0); +} + int tcp_ctloutput(int op, struct socket *so, int level, int optname, struct mbuf *m) @@ -541,23 +610,29 @@ tcp_ctloutput(int op, struct socket *so, break; case PRCO_GETOPT: - m->m_len = sizeof(int); - switch (optname) { case TCP_NODELAY: + m->m_len = sizeof(int); *mtod(m, int *) = tp->t_flags & TF_NODELAY; break; case TCP_NOPUSH: + m->m_len = sizeof(int); *mtod(m, int *) = tp->t_flags & TF_NOPUSH; break; case TCP_MAXSEG: + m->m_len = sizeof(int); *mtod(m, int *) = tp->t_maxseg; break; case TCP_SACK_ENABLE: + m->m_len = sizeof(int); *mtod(m, int *) = tp->sack_enable; break; + case TCP_INFO: + error = tcp_fill_info(tp, m); + break; #ifdef TCP_SIGNATURE case TCP_MD5SIG: + m->m_len = sizeof(int); *mtod(m, int *) = tp->t_flags & TF_SIGNATURE; break; #endif