tcp_output.c (248373) | tcp_output.c (249372) |
---|---|
1/*- 2 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 16 unchanged lines hidden (view full) --- 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)tcp_output.c 8.4 (Berkeley) 5/24/95 30 */ 31 32#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 16 unchanged lines hidden (view full) --- 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)tcp_output.c 8.4 (Berkeley) 5/24/95 30 */ 31 32#include <sys/cdefs.h> |
33__FBSDID("$FreeBSD: head/sys/netinet/tcp_output.c 248373 2013-03-16 08:58:28Z glebius $"); | 33__FBSDID("$FreeBSD: head/sys/netinet/tcp_output.c 249372 2013-04-11 18:23:56Z glebius $"); |
34 35#include "opt_inet.h" 36#include "opt_inet6.h" 37#include "opt_ipsec.h" 38#include "opt_tcpdebug.h" 39 40#include <sys/param.h> 41#include <sys/systm.h> --- 805 unchanged lines hidden (view full) --- 847 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 848 else 849#endif 850 m = m_gethdr(M_NOWAIT, MT_DATA); 851 852 if (m == NULL) { 853 SOCKBUF_UNLOCK(&so->so_snd); 854 error = ENOBUFS; | 34 35#include "opt_inet.h" 36#include "opt_inet6.h" 37#include "opt_ipsec.h" 38#include "opt_tcpdebug.h" 39 40#include <sys/param.h> 41#include <sys/systm.h> --- 805 unchanged lines hidden (view full) --- 847 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 848 else 849#endif 850 m = m_gethdr(M_NOWAIT, MT_DATA); 851 852 if (m == NULL) { 853 SOCKBUF_UNLOCK(&so->so_snd); 854 error = ENOBUFS; |
855 sack_rxmit = 0; |
|
855 goto out; 856 } 857 858 m->m_data += max_linkhdr; 859 m->m_len = hdrlen; 860 861 /* 862 * Start the m_copy functions from the closest mbuf --- 6 unchanged lines hidden (view full) --- 869 mtod(m, caddr_t) + hdrlen); 870 m->m_len += len; 871 } else { 872 m->m_next = m_copy(mb, moff, (int)len); 873 if (m->m_next == NULL) { 874 SOCKBUF_UNLOCK(&so->so_snd); 875 (void) m_free(m); 876 error = ENOBUFS; | 856 goto out; 857 } 858 859 m->m_data += max_linkhdr; 860 m->m_len = hdrlen; 861 862 /* 863 * Start the m_copy functions from the closest mbuf --- 6 unchanged lines hidden (view full) --- 870 mtod(m, caddr_t) + hdrlen); 871 m->m_len += len; 872 } else { 873 m->m_next = m_copy(mb, moff, (int)len); 874 if (m->m_next == NULL) { 875 SOCKBUF_UNLOCK(&so->so_snd); 876 (void) m_free(m); 877 error = ENOBUFS; |
878 sack_rxmit = 0; |
|
877 goto out; 878 } 879 } 880 881 /* 882 * If we're sending everything we've got, set PUSH. 883 * (This will keep happy those implementations which only 884 * give data to the user when a buffer fills or --- 11 unchanged lines hidden (view full) --- 896 else if (SEQ_GT(tp->snd_up, tp->snd_una)) 897 TCPSTAT_INC(tcps_sndurg); 898 else 899 TCPSTAT_INC(tcps_sndwinup); 900 901 m = m_gethdr(M_NOWAIT, MT_DATA); 902 if (m == NULL) { 903 error = ENOBUFS; | 879 goto out; 880 } 881 } 882 883 /* 884 * If we're sending everything we've got, set PUSH. 885 * (This will keep happy those implementations which only 886 * give data to the user when a buffer fills or --- 11 unchanged lines hidden (view full) --- 898 else if (SEQ_GT(tp->snd_up, tp->snd_una)) 899 TCPSTAT_INC(tcps_sndurg); 900 else 901 TCPSTAT_INC(tcps_sndwinup); 902 903 m = m_gethdr(M_NOWAIT, MT_DATA); 904 if (m == NULL) { 905 error = ENOBUFS; |
906 sack_rxmit = 0; |
|
904 goto out; 905 } 906#ifdef INET6 907 if (isipv6 && (MHLEN < hdrlen + max_linkhdr) && 908 MHLEN >= hdrlen) { 909 MH_ALIGN(m, hdrlen); 910 } else 911#endif --- 206 unchanged lines hidden (view full) --- 1118 ("%s: mbuf chain shorter than expected: %ld + %u + %u - %u != %u", 1119 __func__, len, hdrlen, ipoptlen, ipsec_optlen, m_length(m, NULL))); 1120#else 1121 KASSERT(len + hdrlen + ipoptlen == m_length(m, NULL), 1122 ("%s: mbuf chain shorter than expected: %ld + %u + %u != %u", 1123 __func__, len, hdrlen, ipoptlen, m_length(m, NULL))); 1124#endif 1125 | 907 goto out; 908 } 909#ifdef INET6 910 if (isipv6 && (MHLEN < hdrlen + max_linkhdr) && 911 MHLEN >= hdrlen) { 912 MH_ALIGN(m, hdrlen); 913 } else 914#endif --- 206 unchanged lines hidden (view full) --- 1121 ("%s: mbuf chain shorter than expected: %ld + %u + %u - %u != %u", 1122 __func__, len, hdrlen, ipoptlen, ipsec_optlen, m_length(m, NULL))); 1123#else 1124 KASSERT(len + hdrlen + ipoptlen == m_length(m, NULL), 1125 ("%s: mbuf chain shorter than expected: %ld + %u + %u != %u", 1126 __func__, len, hdrlen, ipoptlen, m_length(m, NULL))); 1127#endif 1128 |
1126 /* 1127 * In transmit state, time the transmission and arrange for 1128 * the retransmit. In persist state, just set snd_max. 1129 */ 1130 if ((tp->t_flags & TF_FORCEDATA) == 0 || 1131 !tcp_timer_active(tp, TT_PERSIST)) { 1132 tcp_seq startseq = tp->snd_nxt; 1133 1134 /* 1135 * Advance snd_nxt over sequence space of this segment. 1136 */ 1137 if (flags & (TH_SYN|TH_FIN)) { 1138 if (flags & TH_SYN) 1139 tp->snd_nxt++; 1140 if (flags & TH_FIN) { 1141 tp->snd_nxt++; 1142 tp->t_flags |= TF_SENTFIN; 1143 } 1144 } 1145 if (sack_rxmit) 1146 goto timer; 1147 tp->snd_nxt += len; 1148 if (SEQ_GT(tp->snd_nxt, tp->snd_max)) { 1149 tp->snd_max = tp->snd_nxt; 1150 /* 1151 * Time this transmission if not a retransmission and 1152 * not currently timing anything. 1153 */ 1154 if (tp->t_rtttime == 0) { 1155 tp->t_rtttime = ticks; 1156 tp->t_rtseq = startseq; 1157 TCPSTAT_INC(tcps_segstimed); 1158 } 1159 } 1160 1161 /* 1162 * Set retransmit timer if not currently set, 1163 * and not doing a pure ack or a keep-alive probe. 1164 * Initial value for retransmit timer is smoothed 1165 * round-trip time + 2 * round-trip time variance. 1166 * Initialize shift counter which is used for backoff 1167 * of retransmit time. 1168 */ 1169timer: 1170 if (!tcp_timer_active(tp, TT_REXMT) && 1171 ((sack_rxmit && tp->snd_nxt != tp->snd_max) || 1172 (tp->snd_nxt != tp->snd_una))) { 1173 if (tcp_timer_active(tp, TT_PERSIST)) { 1174 tcp_timer_activate(tp, TT_PERSIST, 0); 1175 tp->t_rxtshift = 0; 1176 } 1177 tcp_timer_activate(tp, TT_REXMT, tp->t_rxtcur); 1178 } 1179 } else { 1180 /* 1181 * Persist case, update snd_max but since we are in 1182 * persist mode (no window) we do not update snd_nxt. 1183 */ 1184 int xlen = len; 1185 if (flags & TH_SYN) 1186 ++xlen; 1187 if (flags & TH_FIN) { 1188 ++xlen; 1189 tp->t_flags |= TF_SENTFIN; 1190 } 1191 if (SEQ_GT(tp->snd_nxt + xlen, tp->snd_max)) 1192 tp->snd_max = tp->snd_nxt + len; 1193 } 1194 | |
1195 /* Run HHOOK_TCP_ESTABLISHED_OUT helper hooks. */ 1196 hhook_run_tcp_est_out(tp, th, &to, len, tso); 1197 1198#ifdef TCPDEBUG 1199 /* 1200 * Trace. 1201 */ 1202 if (so->so_options & SO_DEBUG) { --- 74 unchanged lines hidden (view full) --- 1277 ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0), 0, 1278 tp->t_inpcb); 1279 1280 if (error == EMSGSIZE && ro.ro_rt != NULL) 1281 mtu = ro.ro_rt->rt_rmx.rmx_mtu; 1282 RO_RTFREE(&ro); 1283 } 1284#endif /* INET */ | 1129 /* Run HHOOK_TCP_ESTABLISHED_OUT helper hooks. */ 1130 hhook_run_tcp_est_out(tp, th, &to, len, tso); 1131 1132#ifdef TCPDEBUG 1133 /* 1134 * Trace. 1135 */ 1136 if (so->so_options & SO_DEBUG) { --- 74 unchanged lines hidden (view full) --- 1211 ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0), 0, 1212 tp->t_inpcb); 1213 1214 if (error == EMSGSIZE && ro.ro_rt != NULL) 1215 mtu = ro.ro_rt->rt_rmx.rmx_mtu; 1216 RO_RTFREE(&ro); 1217 } 1218#endif /* INET */ |
1219 1220out: 1221 /* 1222 * In transmit state, time the transmission and arrange for 1223 * the retransmit. In persist state, just set snd_max. 1224 */ 1225 if ((tp->t_flags & TF_FORCEDATA) == 0 || 1226 !tcp_timer_active(tp, TT_PERSIST)) { 1227 tcp_seq startseq = tp->snd_nxt; 1228 1229 /* 1230 * Advance snd_nxt over sequence space of this segment. 1231 */ 1232 if (flags & (TH_SYN|TH_FIN)) { 1233 if (flags & TH_SYN) 1234 tp->snd_nxt++; 1235 if (flags & TH_FIN) { 1236 tp->snd_nxt++; 1237 tp->t_flags |= TF_SENTFIN; 1238 } 1239 } 1240 if (sack_rxmit) 1241 goto timer; 1242 tp->snd_nxt += len; 1243 if (SEQ_GT(tp->snd_nxt, tp->snd_max)) { 1244 tp->snd_max = tp->snd_nxt; 1245 /* 1246 * Time this transmission if not a retransmission and 1247 * not currently timing anything. 1248 */ 1249 if (tp->t_rtttime == 0) { 1250 tp->t_rtttime = ticks; 1251 tp->t_rtseq = startseq; 1252 TCPSTAT_INC(tcps_segstimed); 1253 } 1254 } 1255 1256 /* 1257 * Set retransmit timer if not currently set, 1258 * and not doing a pure ack or a keep-alive probe. 1259 * Initial value for retransmit timer is smoothed 1260 * round-trip time + 2 * round-trip time variance. 1261 * Initialize shift counter which is used for backoff 1262 * of retransmit time. 1263 */ 1264timer: 1265 if (!tcp_timer_active(tp, TT_REXMT) && 1266 ((sack_rxmit && tp->snd_nxt != tp->snd_max) || 1267 (tp->snd_nxt != tp->snd_una))) { 1268 if (tcp_timer_active(tp, TT_PERSIST)) { 1269 tcp_timer_activate(tp, TT_PERSIST, 0); 1270 tp->t_rxtshift = 0; 1271 } 1272 tcp_timer_activate(tp, TT_REXMT, tp->t_rxtcur); 1273 } 1274 } else { 1275 /* 1276 * Persist case, update snd_max but since we are in 1277 * persist mode (no window) we do not update snd_nxt. 1278 */ 1279 int xlen = len; 1280 if (flags & TH_SYN) 1281 ++xlen; 1282 if (flags & TH_FIN) { 1283 ++xlen; 1284 tp->t_flags |= TF_SENTFIN; 1285 } 1286 if (SEQ_GT(tp->snd_nxt + xlen, tp->snd_max)) 1287 tp->snd_max = tp->snd_nxt + len; 1288 } 1289 |
|
1285 if (error) { 1286 1287 /* 1288 * We know that the packet was lost, so back out the 1289 * sequence number advance, if any. 1290 * 1291 * If the error is EPERM the packet got blocked by the 1292 * local firewall. Normally we should terminate the --- 11 unchanged lines hidden (view full) --- 1304 if (sack_rxmit) { 1305 p->rxmit -= len; 1306 tp->sackhint.sack_bytes_rexmit -= len; 1307 KASSERT(tp->sackhint.sack_bytes_rexmit >= 0, 1308 ("sackhint bytes rtx >= 0")); 1309 } else 1310 tp->snd_nxt -= len; 1311 } | 1290 if (error) { 1291 1292 /* 1293 * We know that the packet was lost, so back out the 1294 * sequence number advance, if any. 1295 * 1296 * If the error is EPERM the packet got blocked by the 1297 * local firewall. Normally we should terminate the --- 11 unchanged lines hidden (view full) --- 1309 if (sack_rxmit) { 1310 p->rxmit -= len; 1311 tp->sackhint.sack_bytes_rexmit -= len; 1312 KASSERT(tp->sackhint.sack_bytes_rexmit >= 0, 1313 ("sackhint bytes rtx >= 0")); 1314 } else 1315 tp->snd_nxt -= len; 1316 } |
1312out: | |
1313 SOCKBUF_UNLOCK_ASSERT(&so->so_snd); /* Check gotos. */ 1314 switch (error) { 1315 case EPERM: 1316 tp->t_softerror = error; 1317 return (error); 1318 case ENOBUFS: 1319 if (!tcp_timer_active(tp, TT_REXMT) && 1320 !tcp_timer_active(tp, TT_PERSIST)) --- 236 unchanged lines hidden --- | 1317 SOCKBUF_UNLOCK_ASSERT(&so->so_snd); /* Check gotos. */ 1318 switch (error) { 1319 case EPERM: 1320 tp->t_softerror = error; 1321 return (error); 1322 case ENOBUFS: 1323 if (!tcp_timer_active(tp, TT_REXMT) && 1324 !tcp_timer_active(tp, TT_PERSIST)) --- 236 unchanged lines hidden --- |