aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/Kconfig53
-rw-r--r--net/ipv4/cipso_ipv4.c267
-rw-r--r--net/ipv4/sysctl_net_ipv4.c6
-rw-r--r--net/ipv4/tcp_cong.c2
4 files changed, 116 insertions, 212 deletions
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 1650b64415..30af4a4dfc 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -448,24 +448,22 @@ config INET_TCP_DIAG
448 depends on INET_DIAG 448 depends on INET_DIAG
449 def_tristate INET_DIAG 449 def_tristate INET_DIAG
450 450
451config TCP_CONG_ADVANCED 451menuconfig TCP_CONG_ADVANCED
452 bool "TCP: advanced congestion control" 452 bool "TCP: advanced congestion control"
453 ---help--- 453 ---help---
454 Support for selection of various TCP congestion control 454 Support for selection of various TCP congestion control
455 modules. 455 modules.
456 456
457 Nearly all users can safely say no here, and a safe default 457 Nearly all users can safely say no here, and a safe default
458 selection will be made (BIC-TCP with new Reno as a fallback). 458 selection will be made (CUBIC with new Reno as a fallback).
459 459
460 If unsure, say N. 460 If unsure, say N.
461 461
462# TCP Reno is builtin (required as fallback) 462if TCP_CONG_ADVANCED
463menu "TCP congestion control"
464 depends on TCP_CONG_ADVANCED
465 463
466config TCP_CONG_BIC 464config TCP_CONG_BIC
467 tristate "Binary Increase Congestion (BIC) control" 465 tristate "Binary Increase Congestion (BIC) control"
468 default y 466 default m
469 ---help--- 467 ---help---
470 BIC-TCP is a sender-side only change that ensures a linear RTT 468 BIC-TCP is a sender-side only change that ensures a linear RTT
471 fairness under large windows while offering both scalability and 469 fairness under large windows while offering both scalability and
@@ -479,7 +477,7 @@ config TCP_CONG_BIC
479 477
480config TCP_CONG_CUBIC 478config TCP_CONG_CUBIC
481 tristate "CUBIC TCP" 479 tristate "CUBIC TCP"
482 default m 480 default y
483 ---help--- 481 ---help---
484 This is version 2.0 of BIC-TCP which uses a cubic growth function 482 This is version 2.0 of BIC-TCP which uses a cubic growth function
485 among other techniques. 483 among other techniques.
@@ -574,12 +572,49 @@ config TCP_CONG_VENO
574 loss packets. 572 loss packets.
575 See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf 573 See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf
576 574
577endmenu 575choice
576 prompt "Default TCP congestion control"
577 default DEFAULT_CUBIC
578 help
579 Select the TCP congestion control that will be used by default
580 for all connections.
578 581
579config TCP_CONG_BIC 582 config DEFAULT_BIC
583 bool "Bic" if TCP_CONG_BIC=y
584
585 config DEFAULT_CUBIC
586 bool "Cubic" if TCP_CONG_CUBIC=y
587
588 config DEFAULT_HTCP
589 bool "Htcp" if TCP_CONG_HTCP=y
590
591 config DEFAULT_VEGAS
592 bool "Vegas" if TCP_CONG_VEGAS=y
593
594 config DEFAULT_WESTWOOD
595 bool "Westwood" if TCP_CONG_WESTWOOD=y
596
597 config DEFAULT_RENO
598 bool "Reno"
599
600endchoice
601
602endif
603
604config TCP_CONG_CUBIC
580 tristate 605 tristate
581 depends on !TCP_CONG_ADVANCED 606 depends on !TCP_CONG_ADVANCED
582 default y 607 default y
583 608
609config DEFAULT_TCP_CONG
610 string
611 default "bic" if DEFAULT_BIC
612 default "cubic" if DEFAULT_CUBIC
613 default "htcp" if DEFAULT_HTCP
614 default "vegas" if DEFAULT_VEGAS
615 default "westwood" if DEFAULT_WESTWOOD
616 default "reno" if DEFAULT_RENO
617 default "cubic"
618
584source "net/ipv4/ipvs/Kconfig" 619source "net/ipv4/ipvs/Kconfig"
585 620
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 80a2a0911b..e6ce0b3ba6 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -259,7 +259,7 @@ void cipso_v4_cache_invalidate(void)
259 u32 iter; 259 u32 iter;
260 260
261 for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) { 261 for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) {
262 spin_lock(&cipso_v4_cache[iter].lock); 262 spin_lock_bh(&cipso_v4_cache[iter].lock);
263 list_for_each_entry_safe(entry, 263 list_for_each_entry_safe(entry,
264 tmp_entry, 264 tmp_entry,
265 &cipso_v4_cache[iter].list, list) { 265 &cipso_v4_cache[iter].list, list) {
@@ -267,7 +267,7 @@ void cipso_v4_cache_invalidate(void)
267 cipso_v4_cache_entry_free(entry); 267 cipso_v4_cache_entry_free(entry);
268 } 268 }
269 cipso_v4_cache[iter].size = 0; 269 cipso_v4_cache[iter].size = 0;
270 spin_unlock(&cipso_v4_cache[iter].lock); 270 spin_unlock_bh(&cipso_v4_cache[iter].lock);
271 } 271 }
272 272
273 return; 273 return;
@@ -309,7 +309,7 @@ static int cipso_v4_cache_check(const unsigned char *key,
309 309
310 hash = cipso_v4_map_cache_hash(key, key_len); 310 hash = cipso_v4_map_cache_hash(key, key_len);
311 bkt = hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); 311 bkt = hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
312 spin_lock(&cipso_v4_cache[bkt].lock); 312 spin_lock_bh(&cipso_v4_cache[bkt].lock);
313 list_for_each_entry(entry, &cipso_v4_cache[bkt].list, list) { 313 list_for_each_entry(entry, &cipso_v4_cache[bkt].list, list) {
314 if (entry->hash == hash && 314 if (entry->hash == hash &&
315 entry->key_len == key_len && 315 entry->key_len == key_len &&
@@ -318,7 +318,7 @@ static int cipso_v4_cache_check(const unsigned char *key,
318 secattr->cache.free = entry->lsm_data.free; 318 secattr->cache.free = entry->lsm_data.free;
319 secattr->cache.data = entry->lsm_data.data; 319 secattr->cache.data = entry->lsm_data.data;
320 if (prev_entry == NULL) { 320 if (prev_entry == NULL) {
321 spin_unlock(&cipso_v4_cache[bkt].lock); 321 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
322 return 0; 322 return 0;
323 } 323 }
324 324
@@ -333,12 +333,12 @@ static int cipso_v4_cache_check(const unsigned char *key,
333 &prev_entry->list); 333 &prev_entry->list);
334 } 334 }
335 335
336 spin_unlock(&cipso_v4_cache[bkt].lock); 336 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
337 return 0; 337 return 0;
338 } 338 }
339 prev_entry = entry; 339 prev_entry = entry;
340 } 340 }
341 spin_unlock(&cipso_v4_cache[bkt].lock); 341 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
342 342
343 return -ENOENT; 343 return -ENOENT;
344} 344}
@@ -387,7 +387,7 @@ int cipso_v4_cache_add(const struct sk_buff *skb,
387 entry->lsm_data.data = secattr->cache.data; 387 entry->lsm_data.data = secattr->cache.data;
388 388
389 bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); 389 bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
390 spin_lock(&cipso_v4_cache[bkt].lock); 390 spin_lock_bh(&cipso_v4_cache[bkt].lock);
391 if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) { 391 if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) {
392 list_add(&entry->list, &cipso_v4_cache[bkt].list); 392 list_add(&entry->list, &cipso_v4_cache[bkt].list);
393 cipso_v4_cache[bkt].size += 1; 393 cipso_v4_cache[bkt].size += 1;
@@ -398,7 +398,7 @@ int cipso_v4_cache_add(const struct sk_buff *skb,
398 list_add(&entry->list, &cipso_v4_cache[bkt].list); 398 list_add(&entry->list, &cipso_v4_cache[bkt].list);
399 cipso_v4_cache_entry_free(old_entry); 399 cipso_v4_cache_entry_free(old_entry);
400 } 400 }
401 spin_unlock(&cipso_v4_cache[bkt].lock); 401 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
402 402
403 return 0; 403 return 0;
404 404
@@ -530,197 +530,42 @@ struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
530} 530}
531 531
532/** 532/**
533 * cipso_v4_doi_dump_all - Dump all the CIPSO DOI definitions into a sk_buff 533 * cipso_v4_doi_walk - Iterate through the DOI definitions
534 * @headroom: the amount of headroom to allocate for the sk_buff 534 * @skip_cnt: skip past this number of DOI definitions, updated
535 * @callback: callback for each DOI definition
536 * @cb_arg: argument for the callback function
535 * 537 *
536 * Description: 538 * Description:
537 * Dump a list of all the configured DOI values into a sk_buff. The returned 539 * Iterate over the DOI definition list, skipping the first @skip_cnt entries.
538 * sk_buff has room at the front of the sk_buff for @headroom bytes. See 540 * For each entry call @callback, if @callback returns a negative value stop
539 * net/netlabel/netlabel_cipso_v4.h for the LISTALL message format. This 541 * 'walking' through the list and return. Updates the value in @skip_cnt upon
540 * function may fail if another process is changing the DOI list at the same 542 * return. Returns zero on success, negative values on failure.
541 * time. Returns a pointer to a sk_buff on success, NULL on error.
542 * 543 *
543 */ 544 */
544struct sk_buff *cipso_v4_doi_dump_all(size_t headroom) 545int cipso_v4_doi_walk(u32 *skip_cnt,
546 int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
547 void *cb_arg)
545{ 548{
546 struct sk_buff *skb = NULL; 549 int ret_val = -ENOENT;
547 struct cipso_v4_doi *iter;
548 u32 doi_cnt = 0; 550 u32 doi_cnt = 0;
549 ssize_t buf_len; 551 struct cipso_v4_doi *iter_doi;
550 552
551 buf_len = NETLBL_LEN_U32;
552 rcu_read_lock(); 553 rcu_read_lock();
553 list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list) 554 list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list)
554 if (iter->valid) { 555 if (iter_doi->valid) {
555 doi_cnt += 1; 556 if (doi_cnt++ < *skip_cnt)
556 buf_len += 2 * NETLBL_LEN_U32; 557 continue;
557 } 558 ret_val = callback(iter_doi, cb_arg);
558 559 if (ret_val < 0) {
559 skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC); 560 doi_cnt--;
560 if (skb == NULL) 561 goto doi_walk_return;
561 goto doi_dump_all_failure;
562
563 if (nla_put_u32(skb, NLA_U32, doi_cnt) != 0)
564 goto doi_dump_all_failure;
565 buf_len -= NETLBL_LEN_U32;
566 list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
567 if (iter->valid) {
568 if (buf_len < 2 * NETLBL_LEN_U32)
569 goto doi_dump_all_failure;
570 if (nla_put_u32(skb, NLA_U32, iter->doi) != 0)
571 goto doi_dump_all_failure;
572 if (nla_put_u32(skb, NLA_U32, iter->type) != 0)
573 goto doi_dump_all_failure;
574 buf_len -= 2 * NETLBL_LEN_U32;
575 }
576 rcu_read_unlock();
577
578 return skb;
579
580doi_dump_all_failure:
581 rcu_read_unlock();
582 kfree(skb);
583 return NULL;
584}
585
586/**
587 * cipso_v4_doi_dump - Dump a CIPSO DOI definition into a sk_buff
588 * @doi: the DOI value
589 * @headroom: the amount of headroom to allocate for the sk_buff
590 *
591 * Description:
592 * Lookup the DOI definition matching @doi and dump it's contents into a
593 * sk_buff. The returned sk_buff has room at the front of the sk_buff for
594 * @headroom bytes. See net/netlabel/netlabel_cipso_v4.h for the LIST message
595 * format. This function may fail if another process is changing the DOI list
596 * at the same time. Returns a pointer to a sk_buff on success, NULL on error.
597 *
598 */
599struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom)
600{
601 struct sk_buff *skb = NULL;
602 struct cipso_v4_doi *iter;
603 u32 tag_cnt = 0;
604 u32 lvl_cnt = 0;
605 u32 cat_cnt = 0;
606 ssize_t buf_len;
607 ssize_t tmp;
608
609 rcu_read_lock();
610 iter = cipso_v4_doi_getdef(doi);
611 if (iter == NULL)
612 goto doi_dump_failure;
613 buf_len = NETLBL_LEN_U32;
614 switch (iter->type) {
615 case CIPSO_V4_MAP_PASS:
616 buf_len += NETLBL_LEN_U32;
617 while(tag_cnt < CIPSO_V4_TAG_MAXCNT &&
618 iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) {
619 tag_cnt += 1;
620 buf_len += NETLBL_LEN_U8;
621 }
622 break;
623 case CIPSO_V4_MAP_STD:
624 buf_len += 3 * NETLBL_LEN_U32;
625 while (tag_cnt < CIPSO_V4_TAG_MAXCNT &&
626 iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) {
627 tag_cnt += 1;
628 buf_len += NETLBL_LEN_U8;
629 }
630 for (tmp = 0; tmp < iter->map.std->lvl.local_size; tmp++)
631 if (iter->map.std->lvl.local[tmp] !=
632 CIPSO_V4_INV_LVL) {
633 lvl_cnt += 1;
634 buf_len += NETLBL_LEN_U32 + NETLBL_LEN_U8;
635 }
636 for (tmp = 0; tmp < iter->map.std->cat.local_size; tmp++)
637 if (iter->map.std->cat.local[tmp] !=
638 CIPSO_V4_INV_CAT) {
639 cat_cnt += 1;
640 buf_len += NETLBL_LEN_U32 + NETLBL_LEN_U16;
641 } 562 }
642 break;
643 }
644
645 skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
646 if (skb == NULL)
647 goto doi_dump_failure;
648
649 if (nla_put_u32(skb, NLA_U32, iter->type) != 0)
650 goto doi_dump_failure;
651 buf_len -= NETLBL_LEN_U32;
652 if (iter != cipso_v4_doi_getdef(doi))
653 goto doi_dump_failure;
654 switch (iter->type) {
655 case CIPSO_V4_MAP_PASS:
656 if (nla_put_u32(skb, NLA_U32, tag_cnt) != 0)
657 goto doi_dump_failure;
658 buf_len -= NETLBL_LEN_U32;
659 for (tmp = 0;
660 tmp < CIPSO_V4_TAG_MAXCNT &&
661 iter->tags[tmp] != CIPSO_V4_TAG_INVALID;
662 tmp++) {
663 if (buf_len < NETLBL_LEN_U8)
664 goto doi_dump_failure;
665 if (nla_put_u8(skb, NLA_U8, iter->tags[tmp]) != 0)
666 goto doi_dump_failure;
667 buf_len -= NETLBL_LEN_U8;
668 } 563 }
669 break;
670 case CIPSO_V4_MAP_STD:
671 if (nla_put_u32(skb, NLA_U32, tag_cnt) != 0)
672 goto doi_dump_failure;
673 if (nla_put_u32(skb, NLA_U32, lvl_cnt) != 0)
674 goto doi_dump_failure;
675 if (nla_put_u32(skb, NLA_U32, cat_cnt) != 0)
676 goto doi_dump_failure;
677 buf_len -= 3 * NETLBL_LEN_U32;
678 for (tmp = 0;
679 tmp < CIPSO_V4_TAG_MAXCNT &&
680 iter->tags[tmp] != CIPSO_V4_TAG_INVALID;
681 tmp++) {
682 if (buf_len < NETLBL_LEN_U8)
683 goto doi_dump_failure;
684 if (nla_put_u8(skb, NLA_U8, iter->tags[tmp]) != 0)
685 goto doi_dump_failure;
686 buf_len -= NETLBL_LEN_U8;
687 }
688 for (tmp = 0; tmp < iter->map.std->lvl.local_size; tmp++)
689 if (iter->map.std->lvl.local[tmp] !=
690 CIPSO_V4_INV_LVL) {
691 if (buf_len < NETLBL_LEN_U32 + NETLBL_LEN_U8)
692 goto doi_dump_failure;
693 if (nla_put_u32(skb, NLA_U32, tmp) != 0)
694 goto doi_dump_failure;
695 if (nla_put_u8(skb,
696 NLA_U8,
697 iter->map.std->lvl.local[tmp]) != 0)
698 goto doi_dump_failure;
699 buf_len -= NETLBL_LEN_U32 + NETLBL_LEN_U8;
700 }
701 for (tmp = 0; tmp < iter->map.std->cat.local_size; tmp++)
702 if (iter->map.std->cat.local[tmp] !=
703 CIPSO_V4_INV_CAT) {
704 if (buf_len < NETLBL_LEN_U32 + NETLBL_LEN_U16)
705 goto doi_dump_failure;
706 if (nla_put_u32(skb, NLA_U32, tmp) != 0)
707 goto doi_dump_failure;
708 if (nla_put_u16(skb,
709 NLA_U16,
710 iter->map.std->cat.local[tmp]) != 0)
711 goto doi_dump_failure;
712 buf_len -= NETLBL_LEN_U32 + NETLBL_LEN_U16;
713 }
714 break;
715 }
716 rcu_read_unlock();
717
718 return skb;
719 564
720doi_dump_failure: 565doi_walk_return:
721 rcu_read_unlock(); 566 rcu_read_unlock();
722 kfree(skb); 567 *skip_cnt = doi_cnt;
723 return NULL; 568 return ret_val;
724} 569}
725 570
726/** 571/**
@@ -1486,43 +1331,40 @@ socket_setattr_failure:
1486} 1331}
1487 1332
1488/** 1333/**
1489 * cipso_v4_socket_getattr - Get the security attributes from a socket 1334 * cipso_v4_sock_getattr - Get the security attributes from a sock
1490 * @sock: the socket 1335 * @sk: the sock
1491 * @secattr: the security attributes 1336 * @secattr: the security attributes
1492 * 1337 *
1493 * Description: 1338 * Description:
1494 * Query @sock to see if there is a CIPSO option attached to the socket and if 1339 * Query @sk to see if there is a CIPSO option attached to the sock and if
1495 * there is return the CIPSO security attributes in @secattr. Returns zero on 1340 * there is return the CIPSO security attributes in @secattr. This function
1496 * success and negative values on failure. 1341 * requires that @sk be locked, or privately held, but it does not do any
1342 * locking itself. Returns zero on success and negative values on failure.
1497 * 1343 *
1498 */ 1344 */
1499int cipso_v4_socket_getattr(const struct socket *sock, 1345int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
1500 struct netlbl_lsm_secattr *secattr)
1501{ 1346{
1502 int ret_val = -ENOMSG; 1347 int ret_val = -ENOMSG;
1503 struct sock *sk;
1504 struct inet_sock *sk_inet; 1348 struct inet_sock *sk_inet;
1505 unsigned char *cipso_ptr; 1349 unsigned char *cipso_ptr;
1506 u32 doi; 1350 u32 doi;
1507 struct cipso_v4_doi *doi_def; 1351 struct cipso_v4_doi *doi_def;
1508 1352
1509 sk = sock->sk;
1510 lock_sock(sk);
1511 sk_inet = inet_sk(sk); 1353 sk_inet = inet_sk(sk);
1512 if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0) 1354 if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0)
1513 goto socket_getattr_return; 1355 return -ENOMSG;
1514 cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso - 1356 cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso -
1515 sizeof(struct iphdr); 1357 sizeof(struct iphdr);
1516 ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr); 1358 ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr);
1517 if (ret_val == 0) 1359 if (ret_val == 0)
1518 goto socket_getattr_return; 1360 return ret_val;
1519 1361
1520 doi = ntohl(*(u32 *)&cipso_ptr[2]); 1362 doi = ntohl(*(u32 *)&cipso_ptr[2]);
1521 rcu_read_lock(); 1363 rcu_read_lock();
1522 doi_def = cipso_v4_doi_getdef(doi); 1364 doi_def = cipso_v4_doi_getdef(doi);
1523 if (doi_def == NULL) { 1365 if (doi_def == NULL) {
1524 rcu_read_unlock(); 1366 rcu_read_unlock();
1525 goto socket_getattr_return; 1367 return -ENOMSG;
1526 } 1368 }
1527 switch (cipso_ptr[6]) { 1369 switch (cipso_ptr[6]) {
1528 case CIPSO_V4_TAG_RBITMAP: 1370 case CIPSO_V4_TAG_RBITMAP:
@@ -1533,8 +1375,29 @@ int cipso_v4_socket_getattr(const struct socket *sock,
1533 } 1375 }
1534 rcu_read_unlock(); 1376 rcu_read_unlock();
1535 1377
1536socket_getattr_return: 1378 return ret_val;
1537 release_sock(sk); 1379}
1380
1381/**
1382 * cipso_v4_socket_getattr - Get the security attributes from a socket
1383 * @sock: the socket
1384 * @secattr: the security attributes
1385 *
1386 * Description:
1387 * Query @sock to see if there is a CIPSO option attached to the socket and if
1388 * there is return the CIPSO security attributes in @secattr. Returns zero on
1389 * success and negative values on failure.
1390 *
1391 */
1392int cipso_v4_socket_getattr(const struct socket *sock,
1393 struct netlbl_lsm_secattr *secattr)
1394{
1395 int ret_val;
1396
1397 lock_sock(sock->sk);
1398 ret_val = cipso_v4_sock_getattr(sock->sk, secattr);
1399 release_sock(sock->sk);
1400
1538 return ret_val; 1401 return ret_val;
1539} 1402}
1540 1403
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 19b2071ff3..e82a5be894 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -129,6 +129,12 @@ static int sysctl_tcp_congestion_control(ctl_table *table, int __user *name,
129 return ret; 129 return ret;
130} 130}
131 131
132static int __init tcp_congestion_default(void)
133{
134 return tcp_set_default_congestion_control(CONFIG_DEFAULT_TCP_CONG);
135}
136
137late_initcall(tcp_congestion_default);
132 138
133ctl_table ipv4_table[] = { 139ctl_table ipv4_table[] = {
134 { 140 {
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 7ff2e4273a..af0aca1e6b 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -48,7 +48,7 @@ int tcp_register_congestion_control(struct tcp_congestion_ops *ca)
48 printk(KERN_NOTICE "TCP %s already registered\n", ca->name); 48 printk(KERN_NOTICE "TCP %s already registered\n", ca->name);
49 ret = -EEXIST; 49 ret = -EEXIST;
50 } else { 50 } else {
51 list_add_rcu(&ca->list, &tcp_cong_list); 51 list_add_tail_rcu(&ca->list, &tcp_cong_list);
52 printk(KERN_INFO "TCP %s registered\n", ca->name); 52 printk(KERN_INFO "TCP %s registered\n", ca->name);
53 } 53 }
54 spin_unlock(&tcp_cong_list_lock); 54 spin_unlock(&tcp_cong_list_lock);