+ return ret;
+}
+
+boolean_t
+tcp_heuristic_do_ecn(struct tcpcb *tp)
+{
+ struct tcp_cache_key_src tcks;
+
+ tcp_cache_key_src_create(tp, &tcks);
+ return tcp_heuristic_do_ecn_common(&tcks);
+}
+
+boolean_t
+tcp_heuristic_do_ecn_with_address(struct ifnet *ifp,
+ union sockaddr_in_4_6 *local_address)
+{
+ struct tcp_cache_key_src tcks;
+
+ memset(&tcks, 0, sizeof(tcks));
+ tcks.ifp = ifp;
+
+ calculate_tcp_clock();
+
+ if (local_address->sa.sa_family == AF_INET6) {
+ memcpy(&tcks.laddr.addr6, &local_address->sin6.sin6_addr, sizeof(struct in6_addr));
+ tcks.af = AF_INET6;
+ } else if (local_address->sa.sa_family == AF_INET) {
+ memcpy(&tcks.laddr.addr, &local_address->sin.sin_addr, sizeof(struct in_addr));
+ tcks.af = AF_INET;
+ }
+
+ return tcp_heuristic_do_ecn_common(&tcks);
+}
+
+void
+tcp_heuristics_ecn_update(struct necp_tcp_ecn_cache *necp_buffer,
+ struct ifnet *ifp, union sockaddr_in_4_6 *local_address)
+{
+ struct tcp_cache_key_src tcks;
+
+ memset(&tcks, 0, sizeof(tcks));
+ tcks.ifp = ifp;
+
+ calculate_tcp_clock();
+
+ if (local_address->sa.sa_family == AF_INET6) {
+ memcpy(&tcks.laddr.addr6, &local_address->sin6.sin6_addr, sizeof(struct in6_addr));
+ tcks.af = AF_INET6;
+ } else if (local_address->sa.sa_family == AF_INET) {
+ memcpy(&tcks.laddr.addr, &local_address->sin.sin_addr, sizeof(struct in_addr));
+ tcks.af = AF_INET;
+ }
+
+ if (necp_buffer->necp_tcp_ecn_heuristics_success) {
+ tcp_heuristic_reset_counters(&tcks, TCPCACHE_F_ECN);
+ } else if (necp_buffer->necp_tcp_ecn_heuristics_loss) {
+ tcp_heuristic_inc_counters(&tcks, TCPCACHE_F_ECN);
+ } else if (necp_buffer->necp_tcp_ecn_heuristics_drop_rst) {
+ tcp_heuristic_inc_counters(&tcks, TCPCACHE_F_ECN_DROPRST);
+ } else if (necp_buffer->necp_tcp_ecn_heuristics_drop_rxmt) {
+ tcp_heuristic_inc_counters(&tcks, TCPCACHE_F_ECN_DROPRXMT);
+ } else if (necp_buffer->necp_tcp_ecn_heuristics_syn_rst) {
+ tcp_heuristic_inc_counters(&tcks, TCPCACHE_F_ECN_SYNRST);
+ } else if (necp_buffer->necp_tcp_ecn_heuristics_aggressive) {
+ tcp_heuristic_ecn_aggressive_common(&tcks);
+ }
+
+ return;
+}
+
+boolean_t
+tcp_heuristic_do_tfo_with_address(struct ifnet *ifp,
+ union sockaddr_in_4_6 *local_address, union sockaddr_in_4_6 *remote_address,
+ uint8_t *cookie, uint8_t *cookie_len)
+{
+ struct tcp_cache_key_src tcks;
+
+ memset(&tcks, 0, sizeof(tcks));
+ tcks.ifp = ifp;
+
+ calculate_tcp_clock();
+
+ if (remote_address->sa.sa_family == AF_INET6) {
+ memcpy(&tcks.laddr.addr6, &local_address->sin6.sin6_addr, sizeof(struct in6_addr));
+ memcpy(&tcks.faddr.addr6, &remote_address->sin6.sin6_addr, sizeof(struct in6_addr));
+ tcks.af = AF_INET6;
+ } else if (remote_address->sa.sa_family == AF_INET) {
+ memcpy(&tcks.laddr.addr, &local_address->sin.sin_addr, sizeof(struct in_addr));
+ memcpy(&tcks.faddr.addr, &remote_address->sin.sin_addr, sizeof(struct in_addr));
+ tcks.af = AF_INET;
+ }
+
+ if (tcp_heuristic_do_tfo_common(&tcks)) {
+ if (!tcp_cache_get_cookie_common(&tcks, cookie, cookie_len)) {
+ *cookie_len = 0;
+ }
+ return TRUE;
+ }
+
+ return FALSE;