-int tcp_ecn_outbound = 0;
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, ecn_initiate_out,
- CTLFLAG_RW | CTLFLAG_LOCKED, &tcp_ecn_outbound, 0,
- "Initiate ECN for outbound connections");
+static int
+sysctl_change_ecn_setting SYSCTL_HANDLER_ARGS
+{
+#pragma unused(oidp, arg1, arg2)
+ int i, err = 0, changed = 0;
+ struct ifnet *ifp;
+
+ err = sysctl_io_number(req, tcp_ecn_outbound, sizeof(int32_t),
+ &i, &changed);
+ if (err != 0 || req->newptr == USER_ADDR_NULL)
+ return(err);
+
+ if (changed) {
+ if ((tcp_ecn_outbound == 0 || tcp_ecn_outbound == 1) &&
+ (i == 0 || i == 1)) {
+ tcp_ecn_outbound = i;
+ return(err);
+ }
+ if (tcp_ecn_outbound == 2 && (i == 0 || i == 1)) {
+ /*
+ * Reset ECN enable flags on non-cellular
+ * interfaces so that the system default will take
+ * over
+ */
+ ifnet_head_lock_shared();
+ TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
+ if (!IFNET_IS_CELLULAR(ifp)) {
+ ifnet_lock_exclusive(ifp);
+ ifp->if_eflags &= ~IFEF_ECN_DISABLE;
+ ifp->if_eflags &= ~IFEF_ECN_ENABLE;
+ ifnet_lock_done(ifp);
+ }
+ }
+ ifnet_head_done();
+ } else {
+ /*
+ * Set ECN enable flags on non-cellular
+ * interfaces
+ */
+ ifnet_head_lock_shared();
+ TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
+ if (!IFNET_IS_CELLULAR(ifp)) {
+ ifnet_lock_exclusive(ifp);
+ ifp->if_eflags |= IFEF_ECN_ENABLE;
+ ifp->if_eflags &= ~IFEF_ECN_DISABLE;
+ ifnet_lock_done(ifp);
+ }
+ }
+ ifnet_head_done();
+ }
+ tcp_ecn_outbound = i;
+ }
+ /* Change the other one too as the work is done */
+ if (i == 2 || tcp_ecn_inbound == 2)
+ tcp_ecn_inbound = i;
+ return (err);
+}