1317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger/* 2317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger * Plugable TCP congestion control support and newReno 3317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger * congestion control. 402582e9bcc36ed503ffede46e104a885dea222fbMasanari Iida * Based on ideas from I/O scheduler support and Web100. 5317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger * 6317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger * Copyright (C) 2005 Stephen Hemminger <shemminger@osdl.org> 7317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger */ 8317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 9afd465030acb4098abcb6b965a5aebc7ea2209e0Joe Perches#define pr_fmt(fmt) "TCP: " fmt 10afd465030acb4098abcb6b965a5aebc7ea2209e0Joe Perches 11317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger#include <linux/module.h> 12317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger#include <linux/mm.h> 13317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger#include <linux/types.h> 14317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger#include <linux/list.h> 155a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/gfp.h> 16317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger#include <net/tcp.h> 17317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 18317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemmingerstatic DEFINE_SPINLOCK(tcp_cong_list_lock); 19317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemmingerstatic LIST_HEAD(tcp_cong_list); 20317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 21317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger/* Simple linear search, don't expect many entries! */ 22317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemmingerstatic struct tcp_congestion_ops *tcp_ca_find(const char *name) 23317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger{ 24317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger struct tcp_congestion_ops *e; 25317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 265f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger list_for_each_entry_rcu(e, &tcp_cong_list, list) { 27317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger if (strcmp(e->name, name) == 0) 28317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger return e; 29317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger } 30317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 31317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger return NULL; 32317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger} 33317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 34317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger/* 35d08df601a30df9e36c29f3214315f4f0c8784c68Robert P. J. Day * Attach new congestion control algorithm to the list 36317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger * of available options. 37317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger */ 38317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemmingerint tcp_register_congestion_control(struct tcp_congestion_ops *ca) 39317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger{ 40317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger int ret = 0; 41317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 42317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger /* all algorithms must implement ssthresh and cong_avoid ops */ 4372dc5b9225c53310c010b68a70ea97c8c8e24bdfStephen Hemminger if (!ca->ssthresh || !ca->cong_avoid) { 44afd465030acb4098abcb6b965a5aebc7ea2209e0Joe Perches pr_err("%s does not implement required ops\n", ca->name); 45317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger return -EINVAL; 46317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger } 47317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 48317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger spin_lock(&tcp_cong_list_lock); 49317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger if (tcp_ca_find(ca->name)) { 50afd465030acb4098abcb6b965a5aebc7ea2209e0Joe Perches pr_notice("%s already registered\n", ca->name); 51317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger ret = -EEXIST; 52317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger } else { 533d2573f7ebe507e372a23cdd3c8b03305d6e90aaStephen Hemminger list_add_tail_rcu(&ca->list, &tcp_cong_list); 54afd465030acb4098abcb6b965a5aebc7ea2209e0Joe Perches pr_info("%s registered\n", ca->name); 55317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger } 56317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger spin_unlock(&tcp_cong_list_lock); 57317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 58317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger return ret; 59317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger} 60317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen HemmingerEXPORT_SYMBOL_GPL(tcp_register_congestion_control); 61317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 62317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger/* 63317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger * Remove congestion control algorithm, called from 64317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger * the module's remove function. Module ref counts are used 65317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger * to ensure that this can't be done till all sockets using 66317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger * that method are closed. 67317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger */ 68317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemmingervoid tcp_unregister_congestion_control(struct tcp_congestion_ops *ca) 69317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger{ 70317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger spin_lock(&tcp_cong_list_lock); 71317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger list_del_rcu(&ca->list); 72317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger spin_unlock(&tcp_cong_list_lock); 73317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger} 74317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen HemmingerEXPORT_SYMBOL_GPL(tcp_unregister_congestion_control); 75317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 76317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger/* Assign choice of congestion control. */ 7755d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphalvoid tcp_assign_congestion_control(struct sock *sk) 78317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger{ 796687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Melo struct inet_connection_sock *icsk = inet_csk(sk); 80317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger struct tcp_congestion_ops *ca; 81317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 8255d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal rcu_read_lock(); 8355d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal list_for_each_entry_rcu(ca, &tcp_cong_list, list) { 8455d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal if (likely(try_module_get(ca->owner))) { 8555d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal icsk->icsk_ca_ops = ca; 8655d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal goto out; 87317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger } 8855d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal /* Fallback to next available. The last really 8955d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal * guaranteed fallback is Reno from this list. 9055d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal */ 91317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger } 9255d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphalout: 9355d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal rcu_read_unlock(); 9455d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal 9555d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal /* Clear out private data before diag gets it and 9655d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal * the ca has not been initialized. 9755d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal */ 9855d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal if (ca->get_info) 9955d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv)); 10055d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal} 10155d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal 10255d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphalvoid tcp_init_congestion_control(struct sock *sk) 10355d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal{ 10455d8694fa82c9b5858ae5a78a210353961f908f9Florian Westphal const struct inet_connection_sock *icsk = inet_csk(sk); 105317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 1066687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Melo if (icsk->icsk_ca_ops->init) 1076687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Melo icsk->icsk_ca_ops->init(sk); 108317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger} 109317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 110317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger/* Manage refcounts on socket close. */ 1116687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Melovoid tcp_cleanup_congestion_control(struct sock *sk) 112317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger{ 1136687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Melo struct inet_connection_sock *icsk = inet_csk(sk); 1146687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Melo 1156687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Melo if (icsk->icsk_ca_ops->release) 1166687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Melo icsk->icsk_ca_ops->release(sk); 1176687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Melo module_put(icsk->icsk_ca_ops->owner); 118317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger} 119317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 120317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger/* Used by sysctl to change default congestion control */ 121317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemmingerint tcp_set_default_congestion_control(const char *name) 122317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger{ 123317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger struct tcp_congestion_ops *ca; 124317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger int ret = -ENOENT; 125317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 126317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger spin_lock(&tcp_cong_list_lock); 127317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger ca = tcp_ca_find(name); 12895a5afca4a8d2e1cb77e1d4bc6ff9f718dc32f7aJohannes Berg#ifdef CONFIG_MODULES 129a8f80e8ff94ecba629542d9b4b5f5a8ee3eb565cEric Paris if (!ca && capable(CAP_NET_ADMIN)) { 130317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger spin_unlock(&tcp_cong_list_lock); 131317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 132317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger request_module("tcp_%s", name); 133317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger spin_lock(&tcp_cong_list_lock); 134317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger ca = tcp_ca_find(name); 135317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger } 136317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger#endif 137317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 138317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger if (ca) { 139164891aadf1721fca4dce473bb0e0998181537c6Stephen Hemminger ca->flags |= TCP_CONG_NON_RESTRICTED; /* default is always allowed */ 140317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger list_move(&ca->list, &tcp_cong_list); 141317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger ret = 0; 142317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger } 143317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger spin_unlock(&tcp_cong_list_lock); 144317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 145317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger return ret; 146317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger} 147317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 148b1736a71404b3961f061c795a81210aa7f945fc0Stephen Hemminger/* Set default value from kernel configuration at bootup */ 149b1736a71404b3961f061c795a81210aa7f945fc0Stephen Hemmingerstatic int __init tcp_congestion_default(void) 150b1736a71404b3961f061c795a81210aa7f945fc0Stephen Hemminger{ 151b1736a71404b3961f061c795a81210aa7f945fc0Stephen Hemminger return tcp_set_default_congestion_control(CONFIG_DEFAULT_TCP_CONG); 152b1736a71404b3961f061c795a81210aa7f945fc0Stephen Hemminger} 153b1736a71404b3961f061c795a81210aa7f945fc0Stephen Hemmingerlate_initcall(tcp_congestion_default); 154b1736a71404b3961f061c795a81210aa7f945fc0Stephen Hemminger 1553ff825b28d3345ef381eceae22bf9d92231f23dcStephen Hemminger/* Build string with list of available congestion control values */ 1563ff825b28d3345ef381eceae22bf9d92231f23dcStephen Hemmingervoid tcp_get_available_congestion_control(char *buf, size_t maxlen) 1573ff825b28d3345ef381eceae22bf9d92231f23dcStephen Hemminger{ 1583ff825b28d3345ef381eceae22bf9d92231f23dcStephen Hemminger struct tcp_congestion_ops *ca; 1593ff825b28d3345ef381eceae22bf9d92231f23dcStephen Hemminger size_t offs = 0; 1603ff825b28d3345ef381eceae22bf9d92231f23dcStephen Hemminger 1613ff825b28d3345ef381eceae22bf9d92231f23dcStephen Hemminger rcu_read_lock(); 1623ff825b28d3345ef381eceae22bf9d92231f23dcStephen Hemminger list_for_each_entry_rcu(ca, &tcp_cong_list, list) { 1633ff825b28d3345ef381eceae22bf9d92231f23dcStephen Hemminger offs += snprintf(buf + offs, maxlen - offs, 1643ff825b28d3345ef381eceae22bf9d92231f23dcStephen Hemminger "%s%s", 1653ff825b28d3345ef381eceae22bf9d92231f23dcStephen Hemminger offs == 0 ? "" : " ", ca->name); 1663ff825b28d3345ef381eceae22bf9d92231f23dcStephen Hemminger } 1673ff825b28d3345ef381eceae22bf9d92231f23dcStephen Hemminger rcu_read_unlock(); 1683ff825b28d3345ef381eceae22bf9d92231f23dcStephen Hemminger} 1693ff825b28d3345ef381eceae22bf9d92231f23dcStephen Hemminger 170317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger/* Get current default congestion control */ 171317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemmingervoid tcp_get_default_congestion_control(char *name) 172317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger{ 173317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger struct tcp_congestion_ops *ca; 174317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger /* We will always have reno... */ 175317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger BUG_ON(list_empty(&tcp_cong_list)); 176317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 177317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger rcu_read_lock(); 178317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger ca = list_entry(tcp_cong_list.next, struct tcp_congestion_ops, list); 179317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger strncpy(name, ca->name, TCP_CA_NAME_MAX); 180317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger rcu_read_unlock(); 181317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger} 182317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 183ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger/* Built list of non-restricted congestion control values */ 184ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemmingervoid tcp_get_allowed_congestion_control(char *buf, size_t maxlen) 185ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger{ 186ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger struct tcp_congestion_ops *ca; 187ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger size_t offs = 0; 188ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger 189ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger *buf = '\0'; 190ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger rcu_read_lock(); 191ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger list_for_each_entry_rcu(ca, &tcp_cong_list, list) { 192164891aadf1721fca4dce473bb0e0998181537c6Stephen Hemminger if (!(ca->flags & TCP_CONG_NON_RESTRICTED)) 193ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger continue; 194ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger offs += snprintf(buf + offs, maxlen - offs, 195ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger "%s%s", 196ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger offs == 0 ? "" : " ", ca->name); 197ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger } 198ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger rcu_read_unlock(); 199ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger} 200ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger 201ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger/* Change list of non-restricted congestion control */ 202ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemmingerint tcp_set_allowed_congestion_control(char *val) 203ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger{ 204ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger struct tcp_congestion_ops *ca; 205c34186ed008229e7f7e3f1de8e6acf6374995358Julia Lawall char *saved_clone, *clone, *name; 206ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger int ret = 0; 207ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger 208c34186ed008229e7f7e3f1de8e6acf6374995358Julia Lawall saved_clone = clone = kstrdup(val, GFP_USER); 209ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger if (!clone) 210ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger return -ENOMEM; 211ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger 212ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger spin_lock(&tcp_cong_list_lock); 213ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger /* pass 1 check for bad entries */ 214ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger while ((name = strsep(&clone, " ")) && *name) { 215ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger ca = tcp_ca_find(name); 216ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger if (!ca) { 217ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger ret = -ENOENT; 218ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger goto out; 219ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger } 220ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger } 221ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger 222164891aadf1721fca4dce473bb0e0998181537c6Stephen Hemminger /* pass 2 clear old values */ 223ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger list_for_each_entry_rcu(ca, &tcp_cong_list, list) 224164891aadf1721fca4dce473bb0e0998181537c6Stephen Hemminger ca->flags &= ~TCP_CONG_NON_RESTRICTED; 225ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger 226ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger /* pass 3 mark as allowed */ 227ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger while ((name = strsep(&val, " ")) && *name) { 228ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger ca = tcp_ca_find(name); 229ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger WARN_ON(!ca); 230ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger if (ca) 231164891aadf1721fca4dce473bb0e0998181537c6Stephen Hemminger ca->flags |= TCP_CONG_NON_RESTRICTED; 232ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger } 233ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemmingerout: 234ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger spin_unlock(&tcp_cong_list_lock); 235c34186ed008229e7f7e3f1de8e6acf6374995358Julia Lawall kfree(saved_clone); 236ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger 237ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger return ret; 238ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger} 239ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger 2405f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger/* Change congestion control for socket */ 2416687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Meloint tcp_set_congestion_control(struct sock *sk, const char *name) 2425f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger{ 2436687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Melo struct inet_connection_sock *icsk = inet_csk(sk); 2445f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger struct tcp_congestion_ops *ca; 2455f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger int err = 0; 2465f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger 2475f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger rcu_read_lock(); 2485f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger ca = tcp_ca_find(name); 2494d4d3d1e8807d6aa9822eeedf7fe8500e1b7e38dStephen Hemminger 25035bfbc94070e480f350c868abc4ff9f77e7f2051Stephen Hemminger /* no change asking for existing value */ 2516687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Melo if (ca == icsk->icsk_ca_ops) 2525f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger goto out; 2535f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger 25495a5afca4a8d2e1cb77e1d4bc6ff9f718dc32f7aJohannes Berg#ifdef CONFIG_MODULES 25535bfbc94070e480f350c868abc4ff9f77e7f2051Stephen Hemminger /* not found attempt to autoload module */ 256a8f80e8ff94ecba629542d9b4b5f5a8ee3eb565cEric Paris if (!ca && capable(CAP_NET_ADMIN)) { 25735bfbc94070e480f350c868abc4ff9f77e7f2051Stephen Hemminger rcu_read_unlock(); 25835bfbc94070e480f350c868abc4ff9f77e7f2051Stephen Hemminger request_module("tcp_%s", name); 25935bfbc94070e480f350c868abc4ff9f77e7f2051Stephen Hemminger rcu_read_lock(); 26035bfbc94070e480f350c868abc4ff9f77e7f2051Stephen Hemminger ca = tcp_ca_find(name); 26135bfbc94070e480f350c868abc4ff9f77e7f2051Stephen Hemminger } 26235bfbc94070e480f350c868abc4ff9f77e7f2051Stephen Hemminger#endif 2635f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger if (!ca) 2645f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger err = -ENOENT; 2655f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger 26652e804c6dfaa5df1e4b0e290357b82ad4e4cda2cEric W. Biederman else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) || 26752e804c6dfaa5df1e4b0e290357b82ad4e4cda2cEric W. Biederman ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))) 268ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger err = -EPERM; 269ce7bc3bf15cbf5dc5a5587ccb6b04c5b4dde4336Stephen Hemminger 2705f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger else if (!try_module_get(ca->owner)) 2715f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger err = -EBUSY; 2725f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger 2735f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger else { 2746687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Melo tcp_cleanup_congestion_control(sk); 2756687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Melo icsk->icsk_ca_ops = ca; 2764d4d3d1e8807d6aa9822eeedf7fe8500e1b7e38dStephen Hemminger 2774d4d3d1e8807d6aa9822eeedf7fe8500e1b7e38dStephen Hemminger if (sk->sk_state != TCP_CLOSE && icsk->icsk_ca_ops->init) 2786687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Melo icsk->icsk_ca_ops->init(sk); 2795f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger } 2805f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger out: 2815f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger rcu_read_unlock(); 2825f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger return err; 2835f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger} 2845f8ef48d240963093451bcf83df89f1a1364f51dStephen Hemminger 2859f9843a751d0a2057f9f3d313886e7e5e6ebaac9Yuchung Cheng/* Slow start is used when congestion window is no greater than the slow start 2869f9843a751d0a2057f9f3d313886e7e5e6ebaac9Yuchung Cheng * threshold. We base on RFC2581 and also handle stretch ACKs properly. 2879f9843a751d0a2057f9f3d313886e7e5e6ebaac9Yuchung Cheng * We do not implement RFC3465 Appropriate Byte Counting (ABC) per se but 2889f9843a751d0a2057f9f3d313886e7e5e6ebaac9Yuchung Cheng * something better;) a packet is only considered (s)acked in its entirety to 2899f9843a751d0a2057f9f3d313886e7e5e6ebaac9Yuchung Cheng * defend the ACK attacks described in the RFC. Slow start processes a stretch 2909f9843a751d0a2057f9f3d313886e7e5e6ebaac9Yuchung Cheng * ACK of degree N as if N acks of degree 1 are received back to back except 2919f9843a751d0a2057f9f3d313886e7e5e6ebaac9Yuchung Cheng * ABC caps N to 2. Slow start exits when cwnd grows over ssthresh and 2929f9843a751d0a2057f9f3d313886e7e5e6ebaac9Yuchung Cheng * returns the leftover acks to adjust cwnd in congestion avoidance mode. 29340efc6fa179f440a008333ea98f701bc35a1f97fStephen Hemminger */ 294a12a601ed163578084a48708ae376805f79a1ccfLi RongQingvoid tcp_slow_start(struct tcp_sock *tp, u32 acked) 29540efc6fa179f440a008333ea98f701bc35a1f97fStephen Hemminger{ 2969f9843a751d0a2057f9f3d313886e7e5e6ebaac9Yuchung Cheng u32 cwnd = tp->snd_cwnd + acked; 297a02ba041664171563e6418ccdf3b363d32d6a43bStephen Hemminger 2989f9843a751d0a2057f9f3d313886e7e5e6ebaac9Yuchung Cheng if (cwnd > tp->snd_ssthresh) 2999f9843a751d0a2057f9f3d313886e7e5e6ebaac9Yuchung Cheng cwnd = tp->snd_ssthresh + 1; 3009f9843a751d0a2057f9f3d313886e7e5e6ebaac9Yuchung Cheng tp->snd_cwnd = min(cwnd, tp->snd_cwnd_clamp); 30140efc6fa179f440a008333ea98f701bc35a1f97fStephen Hemminger} 30240efc6fa179f440a008333ea98f701bc35a1f97fStephen HemmingerEXPORT_SYMBOL_GPL(tcp_slow_start); 30340efc6fa179f440a008333ea98f701bc35a1f97fStephen Hemminger 304758ce5c8d11d6fc57fe5f1dbc237aa8ff6386eacIlpo Järvinen/* In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd (or alternative w) */ 305758ce5c8d11d6fc57fe5f1dbc237aa8ff6386eacIlpo Järvinenvoid tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w) 306758ce5c8d11d6fc57fe5f1dbc237aa8ff6386eacIlpo Järvinen{ 307758ce5c8d11d6fc57fe5f1dbc237aa8ff6386eacIlpo Järvinen if (tp->snd_cwnd_cnt >= w) { 308758ce5c8d11d6fc57fe5f1dbc237aa8ff6386eacIlpo Järvinen if (tp->snd_cwnd < tp->snd_cwnd_clamp) 309758ce5c8d11d6fc57fe5f1dbc237aa8ff6386eacIlpo Järvinen tp->snd_cwnd++; 310758ce5c8d11d6fc57fe5f1dbc237aa8ff6386eacIlpo Järvinen tp->snd_cwnd_cnt = 0; 311758ce5c8d11d6fc57fe5f1dbc237aa8ff6386eacIlpo Järvinen } else { 312758ce5c8d11d6fc57fe5f1dbc237aa8ff6386eacIlpo Järvinen tp->snd_cwnd_cnt++; 313758ce5c8d11d6fc57fe5f1dbc237aa8ff6386eacIlpo Järvinen } 314758ce5c8d11d6fc57fe5f1dbc237aa8ff6386eacIlpo Järvinen} 315758ce5c8d11d6fc57fe5f1dbc237aa8ff6386eacIlpo JärvinenEXPORT_SYMBOL_GPL(tcp_cong_avoid_ai); 316758ce5c8d11d6fc57fe5f1dbc237aa8ff6386eacIlpo Järvinen 317317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger/* 318317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger * TCP Reno congestion control 319317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger * This is special case used for fallback as well. 320317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger */ 321317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger/* This is Jacobson's slow start and congestion avoidance. 322317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger * SIGCOMM '88, p. 328. 323317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger */ 324249015515fe3fc9818d86cb5c83bbc92505ad7dcEric Dumazetvoid tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 acked) 325317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger{ 3266687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Melo struct tcp_sock *tp = tcp_sk(sk); 3276687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Melo 328249015515fe3fc9818d86cb5c83bbc92505ad7dcEric Dumazet if (!tcp_is_cwnd_limited(sk)) 329317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger return; 330317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 3317faffa1c7fb9b8e8917e3225d4e2638270c0a48bStephen Hemminger /* In "safe" area, increase. */ 332e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki if (tp->snd_cwnd <= tp->snd_ssthresh) 3339f9843a751d0a2057f9f3d313886e7e5e6ebaac9Yuchung Cheng tcp_slow_start(tp, acked); 334e905a9edab7f4f14f9213b52234e4a346c690911YOSHIFUJI Hideaki /* In dangerous area, increase slowly. */ 335ca2eb5679f8ddffff60156af42595df44a315ef0Stephen Hemminger else 336758ce5c8d11d6fc57fe5f1dbc237aa8ff6386eacIlpo Järvinen tcp_cong_avoid_ai(tp, tp->snd_cwnd); 337317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger} 338317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen HemmingerEXPORT_SYMBOL_GPL(tcp_reno_cong_avoid); 339317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 340317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger/* Slow start threshold is half the congestion window (min 2) */ 3416687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Melou32 tcp_reno_ssthresh(struct sock *sk) 342317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger{ 3436687e988d9aeaccad6774e6a8304f681f3ec0a03Arnaldo Carvalho de Melo const struct tcp_sock *tp = tcp_sk(sk); 344688d1945bc89bd585ec67b5b83121f499e6290bbstephen hemminger 345317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger return max(tp->snd_cwnd >> 1U, 2U); 346317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger} 347317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen HemmingerEXPORT_SYMBOL_GPL(tcp_reno_ssthresh); 348317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger 349317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemmingerstruct tcp_congestion_ops tcp_reno = { 350164891aadf1721fca4dce473bb0e0998181537c6Stephen Hemminger .flags = TCP_CONG_NON_RESTRICTED, 351317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger .name = "reno", 352317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger .owner = THIS_MODULE, 353317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger .ssthresh = tcp_reno_ssthresh, 354317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger .cong_avoid = tcp_reno_cong_avoid, 355317a76f9a44b437d6301718f4e5d08bd93f98da7Stephen Hemminger}; 356