diff options
41 files changed, 462 insertions, 398 deletions
diff --git a/drivers/atm/adummy.c b/drivers/atm/adummy.c index 6cc93de0b71d..ac2c10822be0 100644 --- a/drivers/atm/adummy.c +++ b/drivers/atm/adummy.c | |||
| @@ -113,15 +113,13 @@ static int __init adummy_init(void) | |||
| 113 | 113 | ||
| 114 | printk(KERN_ERR "adummy: version %s\n", DRV_VERSION); | 114 | printk(KERN_ERR "adummy: version %s\n", DRV_VERSION); |
| 115 | 115 | ||
| 116 | adummy_dev = (struct adummy_dev *) kmalloc(sizeof(struct adummy_dev), | 116 | adummy_dev = kzalloc(sizeof(struct adummy_dev), |
| 117 | GFP_KERNEL); | 117 | GFP_KERNEL); |
| 118 | if (!adummy_dev) { | 118 | if (!adummy_dev) { |
| 119 | printk(KERN_ERR DEV_LABEL ": kmalloc() failed\n"); | 119 | printk(KERN_ERR DEV_LABEL ": kzalloc() failed\n"); |
| 120 | err = -ENOMEM; | 120 | err = -ENOMEM; |
| 121 | goto out; | 121 | goto out; |
| 122 | } | 122 | } |
| 123 | memset(adummy_dev, 0, sizeof(struct adummy_dev)); | ||
| 124 | |||
| 125 | atm_dev = atm_dev_register(DEV_LABEL, &adummy_ops, -1, NULL); | 123 | atm_dev = atm_dev_register(DEV_LABEL, &adummy_ops, -1, NULL); |
| 126 | if (!atm_dev) { | 124 | if (!atm_dev) { |
| 127 | printk(KERN_ERR DEV_LABEL ": atm_dev_register() failed\n"); | 125 | printk(KERN_ERR DEV_LABEL ": atm_dev_register() failed\n"); |
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index 4521a249dd56..da599e6e9d34 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c | |||
| @@ -915,8 +915,8 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id, | |||
| 915 | 915 | ||
| 916 | /********** make rate (not quite as much fun as Horizon) **********/ | 916 | /********** make rate (not quite as much fun as Horizon) **********/ |
| 917 | 917 | ||
| 918 | static unsigned int make_rate (unsigned int rate, rounding r, | 918 | static int make_rate (unsigned int rate, rounding r, |
| 919 | u16 * bits, unsigned int * actual) { | 919 | u16 * bits, unsigned int * actual) { |
| 920 | unsigned char exp = -1; // hush gcc | 920 | unsigned char exp = -1; // hush gcc |
| 921 | unsigned int man = -1; // hush gcc | 921 | unsigned int man = -1; // hush gcc |
| 922 | 922 | ||
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index 38fc054bd671..5f25e5efefcd 100644 --- a/drivers/atm/firestream.c +++ b/drivers/atm/firestream.c | |||
| @@ -1784,7 +1784,7 @@ static int __devinit fs_init (struct fs_dev *dev) | |||
| 1784 | write_fs (dev, RAM, (1 << (28 - FS155_VPI_BITS - FS155_VCI_BITS)) - 1); | 1784 | write_fs (dev, RAM, (1 << (28 - FS155_VPI_BITS - FS155_VCI_BITS)) - 1); |
| 1785 | dev->nchannels = FS155_NR_CHANNELS; | 1785 | dev->nchannels = FS155_NR_CHANNELS; |
| 1786 | } | 1786 | } |
| 1787 | dev->atm_vccs = kmalloc (dev->nchannels * sizeof (struct atm_vcc *), | 1787 | dev->atm_vccs = kcalloc (dev->nchannels, sizeof (struct atm_vcc *), |
| 1788 | GFP_KERNEL); | 1788 | GFP_KERNEL); |
| 1789 | fs_dprintk (FS_DEBUG_ALLOC, "Alloc atmvccs: %p(%Zd)\n", | 1789 | fs_dprintk (FS_DEBUG_ALLOC, "Alloc atmvccs: %p(%Zd)\n", |
| 1790 | dev->atm_vccs, dev->nchannels * sizeof (struct atm_vcc *)); | 1790 | dev->atm_vccs, dev->nchannels * sizeof (struct atm_vcc *)); |
| @@ -1794,9 +1794,8 @@ static int __devinit fs_init (struct fs_dev *dev) | |||
| 1794 | /* XXX Clean up..... */ | 1794 | /* XXX Clean up..... */ |
| 1795 | return 1; | 1795 | return 1; |
| 1796 | } | 1796 | } |
| 1797 | memset (dev->atm_vccs, 0, dev->nchannels * sizeof (struct atm_vcc *)); | ||
| 1798 | 1797 | ||
| 1799 | dev->tx_inuse = kmalloc (dev->nchannels / 8 /* bits/byte */ , GFP_KERNEL); | 1798 | dev->tx_inuse = kzalloc (dev->nchannels / 8 /* bits/byte */ , GFP_KERNEL); |
| 1800 | fs_dprintk (FS_DEBUG_ALLOC, "Alloc tx_inuse: %p(%d)\n", | 1799 | fs_dprintk (FS_DEBUG_ALLOC, "Alloc tx_inuse: %p(%d)\n", |
| 1801 | dev->atm_vccs, dev->nchannels / 8); | 1800 | dev->atm_vccs, dev->nchannels / 8); |
| 1802 | 1801 | ||
| @@ -1805,8 +1804,6 @@ static int __devinit fs_init (struct fs_dev *dev) | |||
| 1805 | /* XXX Clean up..... */ | 1804 | /* XXX Clean up..... */ |
| 1806 | return 1; | 1805 | return 1; |
| 1807 | } | 1806 | } |
| 1808 | memset (dev->tx_inuse, 0, dev->nchannels / 8); | ||
| 1809 | |||
| 1810 | /* -- RAS1 : FS155 and 50 differ. Default (0) should be OK for both */ | 1807 | /* -- RAS1 : FS155 and 50 differ. Default (0) should be OK for both */ |
| 1811 | /* -- RAS2 : FS50 only: Default is OK. */ | 1808 | /* -- RAS2 : FS50 only: Default is OK. */ |
| 1812 | 1809 | ||
| @@ -1893,14 +1890,11 @@ static int __devinit firestream_init_one (struct pci_dev *pci_dev, | |||
| 1893 | if (pci_enable_device(pci_dev)) | 1890 | if (pci_enable_device(pci_dev)) |
| 1894 | goto err_out; | 1891 | goto err_out; |
| 1895 | 1892 | ||
| 1896 | fs_dev = kmalloc (sizeof (struct fs_dev), GFP_KERNEL); | 1893 | fs_dev = kzalloc (sizeof (struct fs_dev), GFP_KERNEL); |
| 1897 | fs_dprintk (FS_DEBUG_ALLOC, "Alloc fs-dev: %p(%Zd)\n", | 1894 | fs_dprintk (FS_DEBUG_ALLOC, "Alloc fs-dev: %p(%Zd)\n", |
| 1898 | fs_dev, sizeof (struct fs_dev)); | 1895 | fs_dev, sizeof (struct fs_dev)); |
| 1899 | if (!fs_dev) | 1896 | if (!fs_dev) |
| 1900 | goto err_out; | 1897 | goto err_out; |
| 1901 | |||
| 1902 | memset (fs_dev, 0, sizeof (struct fs_dev)); | ||
| 1903 | |||
| 1904 | atm_dev = atm_dev_register("fs", &ops, -1, NULL); | 1898 | atm_dev = atm_dev_register("fs", &ops, -1, NULL); |
| 1905 | if (!atm_dev) | 1899 | if (!atm_dev) |
| 1906 | goto err_out_free_fs_dev; | 1900 | goto err_out_free_fs_dev; |
diff --git a/drivers/atm/he.c b/drivers/atm/he.c index f2511b42dba2..b22a9142b240 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c | |||
| @@ -383,14 +383,12 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) | |||
| 383 | } | 383 | } |
| 384 | pci_set_drvdata(pci_dev, atm_dev); | 384 | pci_set_drvdata(pci_dev, atm_dev); |
| 385 | 385 | ||
| 386 | he_dev = (struct he_dev *) kmalloc(sizeof(struct he_dev), | 386 | he_dev = kzalloc(sizeof(struct he_dev), |
| 387 | GFP_KERNEL); | 387 | GFP_KERNEL); |
| 388 | if (!he_dev) { | 388 | if (!he_dev) { |
| 389 | err = -ENOMEM; | 389 | err = -ENOMEM; |
| 390 | goto init_one_failure; | 390 | goto init_one_failure; |
| 391 | } | 391 | } |
| 392 | memset(he_dev, 0, sizeof(struct he_dev)); | ||
| 393 | |||
| 394 | he_dev->pci_dev = pci_dev; | 392 | he_dev->pci_dev = pci_dev; |
| 395 | he_dev->atm_dev = atm_dev; | 393 | he_dev->atm_dev = atm_dev; |
| 396 | he_dev->atm_dev->dev_data = he_dev; | 394 | he_dev->atm_dev->dev_data = he_dev; |
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c index d1113e845f95..209dba1c70da 100644 --- a/drivers/atm/horizon.c +++ b/drivers/atm/horizon.c | |||
| @@ -2719,7 +2719,7 @@ static int __devinit hrz_probe(struct pci_dev *pci_dev, const struct pci_device_ | |||
| 2719 | goto out_disable; | 2719 | goto out_disable; |
| 2720 | } | 2720 | } |
| 2721 | 2721 | ||
| 2722 | dev = kmalloc(sizeof(hrz_dev), GFP_KERNEL); | 2722 | dev = kzalloc(sizeof(hrz_dev), GFP_KERNEL); |
| 2723 | if (!dev) { | 2723 | if (!dev) { |
| 2724 | // perhaps we should be nice: deregister all adapters and abort? | 2724 | // perhaps we should be nice: deregister all adapters and abort? |
| 2725 | PRINTD(DBG_ERR, "out of memory"); | 2725 | PRINTD(DBG_ERR, "out of memory"); |
| @@ -2727,8 +2727,6 @@ static int __devinit hrz_probe(struct pci_dev *pci_dev, const struct pci_device_ | |||
| 2727 | goto out_release; | 2727 | goto out_release; |
| 2728 | } | 2728 | } |
| 2729 | 2729 | ||
| 2730 | memset(dev, 0, sizeof(hrz_dev)); | ||
| 2731 | |||
| 2732 | pci_set_drvdata(pci_dev, dev); | 2730 | pci_set_drvdata(pci_dev, dev); |
| 2733 | 2731 | ||
| 2734 | // grab IRQ and install handler - move this someplace more sensible | 2732 | // grab IRQ and install handler - move this someplace more sensible |
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index b0369bb20f08..7487f0ad68e9 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c | |||
| @@ -642,11 +642,9 @@ alloc_scq(struct idt77252_dev *card, int class) | |||
| 642 | { | 642 | { |
| 643 | struct scq_info *scq; | 643 | struct scq_info *scq; |
| 644 | 644 | ||
| 645 | scq = (struct scq_info *) kmalloc(sizeof(struct scq_info), GFP_KERNEL); | 645 | scq = kzalloc(sizeof(struct scq_info), GFP_KERNEL); |
| 646 | if (!scq) | 646 | if (!scq) |
| 647 | return NULL; | 647 | return NULL; |
| 648 | memset(scq, 0, sizeof(struct scq_info)); | ||
| 649 | |||
| 650 | scq->base = pci_alloc_consistent(card->pcidev, SCQ_SIZE, | 648 | scq->base = pci_alloc_consistent(card->pcidev, SCQ_SIZE, |
| 651 | &scq->paddr); | 649 | &scq->paddr); |
| 652 | if (scq->base == NULL) { | 650 | if (scq->base == NULL) { |
| @@ -2142,11 +2140,9 @@ idt77252_init_est(struct vc_map *vc, int pcr) | |||
| 2142 | { | 2140 | { |
| 2143 | struct rate_estimator *est; | 2141 | struct rate_estimator *est; |
| 2144 | 2142 | ||
| 2145 | est = kmalloc(sizeof(struct rate_estimator), GFP_KERNEL); | 2143 | est = kzalloc(sizeof(struct rate_estimator), GFP_KERNEL); |
| 2146 | if (!est) | 2144 | if (!est) |
| 2147 | return NULL; | 2145 | return NULL; |
| 2148 | memset(est, 0, sizeof(*est)); | ||
| 2149 | |||
| 2150 | est->maxcps = pcr < 0 ? -pcr : pcr; | 2146 | est->maxcps = pcr < 0 ? -pcr : pcr; |
| 2151 | est->cps = est->maxcps; | 2147 | est->cps = est->maxcps; |
| 2152 | est->avcps = est->cps << 5; | 2148 | est->avcps = est->cps << 5; |
| @@ -2451,14 +2447,12 @@ idt77252_open(struct atm_vcc *vcc) | |||
| 2451 | 2447 | ||
| 2452 | index = VPCI2VC(card, vpi, vci); | 2448 | index = VPCI2VC(card, vpi, vci); |
| 2453 | if (!card->vcs[index]) { | 2449 | if (!card->vcs[index]) { |
| 2454 | card->vcs[index] = kmalloc(sizeof(struct vc_map), GFP_KERNEL); | 2450 | card->vcs[index] = kzalloc(sizeof(struct vc_map), GFP_KERNEL); |
| 2455 | if (!card->vcs[index]) { | 2451 | if (!card->vcs[index]) { |
| 2456 | printk("%s: can't alloc vc in open()\n", card->name); | 2452 | printk("%s: can't alloc vc in open()\n", card->name); |
| 2457 | up(&card->mutex); | 2453 | up(&card->mutex); |
| 2458 | return -ENOMEM; | 2454 | return -ENOMEM; |
| 2459 | } | 2455 | } |
| 2460 | memset(card->vcs[index], 0, sizeof(struct vc_map)); | ||
| 2461 | |||
| 2462 | card->vcs[index]->card = card; | 2456 | card->vcs[index]->card = card; |
| 2463 | card->vcs[index]->index = index; | 2457 | card->vcs[index]->index = index; |
| 2464 | 2458 | ||
| @@ -2926,13 +2920,11 @@ open_card_oam(struct idt77252_dev *card) | |||
| 2926 | for (vci = 3; vci < 5; vci++) { | 2920 | for (vci = 3; vci < 5; vci++) { |
| 2927 | index = VPCI2VC(card, vpi, vci); | 2921 | index = VPCI2VC(card, vpi, vci); |
| 2928 | 2922 | ||
| 2929 | vc = kmalloc(sizeof(struct vc_map), GFP_KERNEL); | 2923 | vc = kzalloc(sizeof(struct vc_map), GFP_KERNEL); |
| 2930 | if (!vc) { | 2924 | if (!vc) { |
| 2931 | printk("%s: can't alloc vc\n", card->name); | 2925 | printk("%s: can't alloc vc\n", card->name); |
| 2932 | return -ENOMEM; | 2926 | return -ENOMEM; |
| 2933 | } | 2927 | } |
| 2934 | memset(vc, 0, sizeof(struct vc_map)); | ||
| 2935 | |||
| 2936 | vc->index = index; | 2928 | vc->index = index; |
| 2937 | card->vcs[index] = vc; | 2929 | card->vcs[index] = vc; |
| 2938 | 2930 | ||
| @@ -2995,12 +2987,11 @@ open_card_ubr0(struct idt77252_dev *card) | |||
| 2995 | { | 2987 | { |
| 2996 | struct vc_map *vc; | 2988 | struct vc_map *vc; |
| 2997 | 2989 | ||
| 2998 | vc = kmalloc(sizeof(struct vc_map), GFP_KERNEL); | 2990 | vc = kzalloc(sizeof(struct vc_map), GFP_KERNEL); |
| 2999 | if (!vc) { | 2991 | if (!vc) { |
| 3000 | printk("%s: can't alloc vc\n", card->name); | 2992 | printk("%s: can't alloc vc\n", card->name); |
| 3001 | return -ENOMEM; | 2993 | return -ENOMEM; |
| 3002 | } | 2994 | } |
| 3003 | memset(vc, 0, sizeof(struct vc_map)); | ||
| 3004 | card->vcs[0] = vc; | 2995 | card->vcs[0] = vc; |
| 3005 | vc->class = SCHED_UBR0; | 2996 | vc->class = SCHED_UBR0; |
| 3006 | 2997 | ||
| @@ -3695,14 +3686,12 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) | |||
| 3695 | goto err_out_disable_pdev; | 3686 | goto err_out_disable_pdev; |
| 3696 | } | 3687 | } |
| 3697 | 3688 | ||
| 3698 | card = kmalloc(sizeof(struct idt77252_dev), GFP_KERNEL); | 3689 | card = kzalloc(sizeof(struct idt77252_dev), GFP_KERNEL); |
| 3699 | if (!card) { | 3690 | if (!card) { |
| 3700 | printk("idt77252-%d: can't allocate private data\n", index); | 3691 | printk("idt77252-%d: can't allocate private data\n", index); |
| 3701 | err = -ENOMEM; | 3692 | err = -ENOMEM; |
| 3702 | goto err_out_disable_pdev; | 3693 | goto err_out_disable_pdev; |
| 3703 | } | 3694 | } |
| 3704 | memset(card, 0, sizeof(struct idt77252_dev)); | ||
| 3705 | |||
| 3706 | card->revision = revision; | 3695 | card->revision = revision; |
| 3707 | card->index = index; | 3696 | card->index = index; |
| 3708 | card->pcidev = pcidev; | 3697 | card->pcidev = pcidev; |
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index fe60a59b7fc0..b9568e10965a 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c | |||
| @@ -1482,16 +1482,10 @@ static inline void vcc_table_deallocate(const struct lanai_dev *lanai) | |||
| 1482 | static inline struct lanai_vcc *new_lanai_vcc(void) | 1482 | static inline struct lanai_vcc *new_lanai_vcc(void) |
| 1483 | { | 1483 | { |
| 1484 | struct lanai_vcc *lvcc; | 1484 | struct lanai_vcc *lvcc; |
| 1485 | lvcc = (struct lanai_vcc *) kmalloc(sizeof(*lvcc), GFP_KERNEL); | 1485 | lvcc = kzalloc(sizeof(*lvcc), GFP_KERNEL); |
| 1486 | if (likely(lvcc != NULL)) { | 1486 | if (likely(lvcc != NULL)) { |
| 1487 | lvcc->vbase = NULL; | ||
| 1488 | lvcc->rx.atmvcc = lvcc->tx.atmvcc = NULL; | ||
| 1489 | lvcc->nref = 0; | ||
| 1490 | memset(&lvcc->stats, 0, sizeof lvcc->stats); | ||
| 1491 | lvcc->rx.buf.start = lvcc->tx.buf.start = NULL; | ||
| 1492 | skb_queue_head_init(&lvcc->tx.backlog); | 1487 | skb_queue_head_init(&lvcc->tx.backlog); |
| 1493 | #ifdef DEBUG | 1488 | #ifdef DEBUG |
| 1494 | lvcc->tx.unqueue = NULL; | ||
| 1495 | lvcc->vci = -1; | 1489 | lvcc->vci = -1; |
| 1496 | #endif | 1490 | #endif |
| 1497 | } | 1491 | } |
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c index 2c65e82f0d6b..083c5d3f2e18 100644 --- a/drivers/atm/zatm.c +++ b/drivers/atm/zatm.c | |||
| @@ -603,9 +603,8 @@ static int start_rx(struct atm_dev *dev) | |||
| 603 | DPRINTK("start_rx\n"); | 603 | DPRINTK("start_rx\n"); |
| 604 | zatm_dev = ZATM_DEV(dev); | 604 | zatm_dev = ZATM_DEV(dev); |
| 605 | size = sizeof(struct atm_vcc *)*zatm_dev->chans; | 605 | size = sizeof(struct atm_vcc *)*zatm_dev->chans; |
| 606 | zatm_dev->rx_map = (struct atm_vcc **) kmalloc(size,GFP_KERNEL); | 606 | zatm_dev->rx_map = kzalloc(size,GFP_KERNEL); |
| 607 | if (!zatm_dev->rx_map) return -ENOMEM; | 607 | if (!zatm_dev->rx_map) return -ENOMEM; |
| 608 | memset(zatm_dev->rx_map,0,size); | ||
| 609 | /* set VPI/VCI split (use all VCIs and give what's left to VPIs) */ | 608 | /* set VPI/VCI split (use all VCIs and give what's left to VPIs) */ |
| 610 | zpokel(zatm_dev,(1 << dev->ci_range.vci_bits)-1,uPD98401_VRR); | 609 | zpokel(zatm_dev,(1 << dev->ci_range.vci_bits)-1,uPD98401_VRR); |
| 611 | /* prepare free buffer pools */ | 610 | /* prepare free buffer pools */ |
| @@ -801,6 +800,7 @@ static int alloc_shaper(struct atm_dev *dev,int *pcr,int min,int max,int ubr) | |||
| 801 | i = m = 1; | 800 | i = m = 1; |
| 802 | zatm_dev->ubr_ref_cnt++; | 801 | zatm_dev->ubr_ref_cnt++; |
| 803 | zatm_dev->ubr = shaper; | 802 | zatm_dev->ubr = shaper; |
| 803 | *pcr = 0; | ||
| 804 | } | 804 | } |
| 805 | else { | 805 | else { |
| 806 | if (min) { | 806 | if (min) { |
| @@ -951,9 +951,8 @@ static int open_tx_first(struct atm_vcc *vcc) | |||
| 951 | skb_queue_head_init(&zatm_vcc->tx_queue); | 951 | skb_queue_head_init(&zatm_vcc->tx_queue); |
| 952 | init_waitqueue_head(&zatm_vcc->tx_wait); | 952 | init_waitqueue_head(&zatm_vcc->tx_wait); |
| 953 | /* initialize ring */ | 953 | /* initialize ring */ |
| 954 | zatm_vcc->ring = kmalloc(RING_SIZE,GFP_KERNEL); | 954 | zatm_vcc->ring = kzalloc(RING_SIZE,GFP_KERNEL); |
| 955 | if (!zatm_vcc->ring) return -ENOMEM; | 955 | if (!zatm_vcc->ring) return -ENOMEM; |
| 956 | memset(zatm_vcc->ring,0,RING_SIZE); | ||
| 957 | loop = zatm_vcc->ring+RING_ENTRIES*RING_WORDS; | 956 | loop = zatm_vcc->ring+RING_ENTRIES*RING_WORDS; |
| 958 | loop[0] = uPD98401_TXPD_V; | 957 | loop[0] = uPD98401_TXPD_V; |
| 959 | loop[1] = loop[2] = 0; | 958 | loop[1] = loop[2] = 0; |
diff --git a/include/linux/in.h b/include/linux/in.h index d79fc75fa7c2..2619859f6e1b 100644 --- a/include/linux/in.h +++ b/include/linux/in.h | |||
| @@ -40,6 +40,7 @@ enum { | |||
| 40 | 40 | ||
| 41 | IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */ | 41 | IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */ |
| 42 | IPPROTO_AH = 51, /* Authentication Header protocol */ | 42 | IPPROTO_AH = 51, /* Authentication Header protocol */ |
| 43 | IPPROTO_BEETPH = 94, /* IP option pseudo header for BEET */ | ||
| 43 | IPPROTO_PIM = 103, /* Protocol Independent Multicast */ | 44 | IPPROTO_PIM = 103, /* Protocol Independent Multicast */ |
| 44 | 45 | ||
| 45 | IPPROTO_COMP = 108, /* Compression Header protocol */ | 46 | IPPROTO_COMP = 108, /* Compression Header protocol */ |
diff --git a/include/linux/ip.h b/include/linux/ip.h index 6b25d36fc54c..ecee9bb27d0e 100644 --- a/include/linux/ip.h +++ b/include/linux/ip.h | |||
| @@ -80,6 +80,8 @@ | |||
| 80 | #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */ | 80 | #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */ |
| 81 | #define IPOPT_TS_PRESPEC 3 /* specified modules only */ | 81 | #define IPOPT_TS_PRESPEC 3 /* specified modules only */ |
| 82 | 82 | ||
| 83 | #define IPV4_BEET_PHMAXLEN 8 | ||
| 84 | |||
| 83 | struct iphdr { | 85 | struct iphdr { |
| 84 | #if defined(__LITTLE_ENDIAN_BITFIELD) | 86 | #if defined(__LITTLE_ENDIAN_BITFIELD) |
| 85 | __u8 ihl:4, | 87 | __u8 ihl:4, |
| @@ -123,4 +125,11 @@ struct ip_comp_hdr { | |||
| 123 | __be16 cpi; | 125 | __be16 cpi; |
| 124 | }; | 126 | }; |
| 125 | 127 | ||
| 128 | struct ip_beet_phdr { | ||
| 129 | __u8 nexthdr; | ||
| 130 | __u8 hdrlen; | ||
| 131 | __u8 padlen; | ||
| 132 | __u8 reserved; | ||
| 133 | }; | ||
| 134 | |||
| 126 | #endif /* _LINUX_IP_H */ | 135 | #endif /* _LINUX_IP_H */ |
diff --git a/include/linux/ipsec.h b/include/linux/ipsec.h index d3c527616b5e..d17a6302a0e9 100644 --- a/include/linux/ipsec.h +++ b/include/linux/ipsec.h | |||
| @@ -12,7 +12,8 @@ | |||
| 12 | enum { | 12 | enum { |
| 13 | IPSEC_MODE_ANY = 0, /* We do not support this for SA */ | 13 | IPSEC_MODE_ANY = 0, /* We do not support this for SA */ |
| 14 | IPSEC_MODE_TRANSPORT = 1, | 14 | IPSEC_MODE_TRANSPORT = 1, |
| 15 | IPSEC_MODE_TUNNEL = 2 | 15 | IPSEC_MODE_TUNNEL = 2, |
| 16 | IPSEC_MODE_BEET = 3 | ||
| 16 | }; | 17 | }; |
| 17 | 18 | ||
| 18 | enum { | 19 | enum { |
diff --git a/include/linux/netfilter_bridge/ebt_mark_t.h b/include/linux/netfilter_bridge/ebt_mark_t.h index 110fec6a40a2..6270f6f33693 100644 --- a/include/linux/netfilter_bridge/ebt_mark_t.h +++ b/include/linux/netfilter_bridge/ebt_mark_t.h | |||
| @@ -1,6 +1,18 @@ | |||
| 1 | #ifndef __LINUX_BRIDGE_EBT_MARK_T_H | 1 | #ifndef __LINUX_BRIDGE_EBT_MARK_T_H |
| 2 | #define __LINUX_BRIDGE_EBT_MARK_T_H | 2 | #define __LINUX_BRIDGE_EBT_MARK_T_H |
| 3 | 3 | ||
| 4 | /* The target member is reused for adding new actions, the | ||
| 5 | * value of the real target is -1 to -NUM_STANDARD_TARGETS. | ||
| 6 | * For backward compatibility, the 4 lsb (2 would be enough, | ||
| 7 | * but let's play it safe) are kept to designate this target. | ||
| 8 | * The remaining bits designate the action. By making the set | ||
| 9 | * action 0xfffffff0, the result will look ok for older | ||
| 10 | * versions. [September 2006] */ | ||
| 11 | #define MARK_SET_VALUE (0xfffffff0) | ||
| 12 | #define MARK_OR_VALUE (0xffffffe0) | ||
| 13 | #define MARK_AND_VALUE (0xffffffd0) | ||
| 14 | #define MARK_XOR_VALUE (0xffffffc0) | ||
| 15 | |||
| 4 | struct ebt_mark_t_info | 16 | struct ebt_mark_t_info |
| 5 | { | 17 | { |
| 6 | unsigned long mark; | 18 | unsigned long mark; |
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h index ce02c984f3ba..5b63a231a76b 100644 --- a/include/linux/netfilter_ipv4.h +++ b/include/linux/netfilter_ipv4.h | |||
| @@ -77,7 +77,7 @@ enum nf_ip_hook_priorities { | |||
| 77 | #define SO_ORIGINAL_DST 80 | 77 | #define SO_ORIGINAL_DST 80 |
| 78 | 78 | ||
| 79 | #ifdef __KERNEL__ | 79 | #ifdef __KERNEL__ |
| 80 | extern int ip_route_me_harder(struct sk_buff **pskb); | 80 | extern int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type); |
| 81 | extern int ip_xfrm_me_harder(struct sk_buff **pskb); | 81 | extern int ip_xfrm_me_harder(struct sk_buff **pskb); |
| 82 | extern unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook, | 82 | extern unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook, |
| 83 | unsigned int dataoff, u_int8_t protocol); | 83 | unsigned int dataoff, u_int8_t protocol); |
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index 430afd058269..8ae7f744917b 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h | |||
| @@ -129,7 +129,8 @@ enum | |||
| 129 | #define XFRM_MODE_TUNNEL 1 | 129 | #define XFRM_MODE_TUNNEL 1 |
| 130 | #define XFRM_MODE_ROUTEOPTIMIZATION 2 | 130 | #define XFRM_MODE_ROUTEOPTIMIZATION 2 |
| 131 | #define XFRM_MODE_IN_TRIGGER 3 | 131 | #define XFRM_MODE_IN_TRIGGER 3 |
| 132 | #define XFRM_MODE_MAX 4 | 132 | #define XFRM_MODE_BEET 4 |
| 133 | #define XFRM_MODE_MAX 5 | ||
| 133 | 134 | ||
| 134 | /* Netlink configuration messages. */ | 135 | /* Netlink configuration messages. */ |
| 135 | enum { | 136 | enum { |
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c index 770c0df972a3..b54306a934e5 100644 --- a/net/bridge/netfilter/ebt_mark.c +++ b/net/bridge/netfilter/ebt_mark.c | |||
| @@ -22,24 +22,37 @@ static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr, | |||
| 22 | const void *data, unsigned int datalen) | 22 | const void *data, unsigned int datalen) |
| 23 | { | 23 | { |
| 24 | struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)data; | 24 | struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)data; |
| 25 | int action = info->target & -16; | ||
| 25 | 26 | ||
| 26 | if ((*pskb)->nfmark != info->mark) | 27 | if (action == MARK_SET_VALUE) |
| 27 | (*pskb)->nfmark = info->mark; | 28 | (*pskb)->nfmark = info->mark; |
| 29 | else if (action == MARK_OR_VALUE) | ||
| 30 | (*pskb)->nfmark |= info->mark; | ||
| 31 | else if (action == MARK_AND_VALUE) | ||
| 32 | (*pskb)->nfmark &= info->mark; | ||
| 33 | else | ||
| 34 | (*pskb)->nfmark ^= info->mark; | ||
| 28 | 35 | ||
| 29 | return info->target; | 36 | return info->target | -16; |
| 30 | } | 37 | } |
| 31 | 38 | ||
| 32 | static int ebt_target_mark_check(const char *tablename, unsigned int hookmask, | 39 | static int ebt_target_mark_check(const char *tablename, unsigned int hookmask, |
| 33 | const struct ebt_entry *e, void *data, unsigned int datalen) | 40 | const struct ebt_entry *e, void *data, unsigned int datalen) |
| 34 | { | 41 | { |
| 35 | struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)data; | 42 | struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)data; |
| 43 | int tmp; | ||
| 36 | 44 | ||
| 37 | if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_t_info))) | 45 | if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_t_info))) |
| 38 | return -EINVAL; | 46 | return -EINVAL; |
| 39 | if (BASE_CHAIN && info->target == EBT_RETURN) | 47 | tmp = info->target | -16; |
| 48 | if (BASE_CHAIN && tmp == EBT_RETURN) | ||
| 40 | return -EINVAL; | 49 | return -EINVAL; |
| 41 | CLEAR_BASE_CHAIN_BIT; | 50 | CLEAR_BASE_CHAIN_BIT; |
| 42 | if (INVALID_TARGET) | 51 | if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) |
| 52 | return -EINVAL; | ||
| 53 | tmp = info->target & -16; | ||
| 54 | if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE && | ||
| 55 | tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE) | ||
| 43 | return -EINVAL; | 56 | return -EINVAL; |
| 44 | return 0; | 57 | return 0; |
| 45 | } | 58 | } |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 8ce8c471d868..b4b478353b27 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
| @@ -344,12 +344,12 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, | |||
| 344 | { | 344 | { |
| 345 | struct neighbour *n; | 345 | struct neighbour *n; |
| 346 | int key_len = tbl->key_len; | 346 | int key_len = tbl->key_len; |
| 347 | u32 hash_val = tbl->hash(pkey, dev) & tbl->hash_mask; | 347 | u32 hash_val = tbl->hash(pkey, dev); |
| 348 | 348 | ||
| 349 | NEIGH_CACHE_STAT_INC(tbl, lookups); | 349 | NEIGH_CACHE_STAT_INC(tbl, lookups); |
| 350 | 350 | ||
| 351 | read_lock_bh(&tbl->lock); | 351 | read_lock_bh(&tbl->lock); |
| 352 | for (n = tbl->hash_buckets[hash_val]; n; n = n->next) { | 352 | for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) { |
| 353 | if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) { | 353 | if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) { |
| 354 | neigh_hold(n); | 354 | neigh_hold(n); |
| 355 | NEIGH_CACHE_STAT_INC(tbl, hits); | 355 | NEIGH_CACHE_STAT_INC(tbl, hits); |
| @@ -364,12 +364,12 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, const void *pkey) | |||
| 364 | { | 364 | { |
| 365 | struct neighbour *n; | 365 | struct neighbour *n; |
| 366 | int key_len = tbl->key_len; | 366 | int key_len = tbl->key_len; |
| 367 | u32 hash_val = tbl->hash(pkey, NULL) & tbl->hash_mask; | 367 | u32 hash_val = tbl->hash(pkey, NULL); |
| 368 | 368 | ||
| 369 | NEIGH_CACHE_STAT_INC(tbl, lookups); | 369 | NEIGH_CACHE_STAT_INC(tbl, lookups); |
| 370 | 370 | ||
| 371 | read_lock_bh(&tbl->lock); | 371 | read_lock_bh(&tbl->lock); |
| 372 | for (n = tbl->hash_buckets[hash_val]; n; n = n->next) { | 372 | for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) { |
| 373 | if (!memcmp(n->primary_key, pkey, key_len)) { | 373 | if (!memcmp(n->primary_key, pkey, key_len)) { |
| 374 | neigh_hold(n); | 374 | neigh_hold(n); |
| 375 | NEIGH_CACHE_STAT_INC(tbl, hits); | 375 | NEIGH_CACHE_STAT_INC(tbl, hits); |
| @@ -1998,12 +1998,12 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | |||
| 1998 | int rc, h, s_h = cb->args[1]; | 1998 | int rc, h, s_h = cb->args[1]; |
| 1999 | int idx, s_idx = idx = cb->args[2]; | 1999 | int idx, s_idx = idx = cb->args[2]; |
| 2000 | 2000 | ||
| 2001 | read_lock_bh(&tbl->lock); | ||
| 2001 | for (h = 0; h <= tbl->hash_mask; h++) { | 2002 | for (h = 0; h <= tbl->hash_mask; h++) { |
| 2002 | if (h < s_h) | 2003 | if (h < s_h) |
| 2003 | continue; | 2004 | continue; |
| 2004 | if (h > s_h) | 2005 | if (h > s_h) |
| 2005 | s_idx = 0; | 2006 | s_idx = 0; |
| 2006 | read_lock_bh(&tbl->lock); | ||
| 2007 | for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next, idx++) { | 2007 | for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next, idx++) { |
| 2008 | if (idx < s_idx) | 2008 | if (idx < s_idx) |
| 2009 | continue; | 2009 | continue; |
| @@ -2016,8 +2016,8 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | |||
| 2016 | goto out; | 2016 | goto out; |
| 2017 | } | 2017 | } |
| 2018 | } | 2018 | } |
| 2019 | read_unlock_bh(&tbl->lock); | ||
| 2020 | } | 2019 | } |
| 2020 | read_unlock_bh(&tbl->lock); | ||
| 2021 | rc = skb->len; | 2021 | rc = skb->len; |
| 2022 | out: | 2022 | out: |
| 2023 | cb->args[1] = h; | 2023 | cb->args[1] = h; |
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index d172a9804448..5572071af735 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig | |||
| @@ -434,6 +434,15 @@ config INET_XFRM_MODE_TUNNEL | |||
| 434 | 434 | ||
| 435 | If unsure, say Y. | 435 | If unsure, say Y. |
| 436 | 436 | ||
| 437 | config INET_XFRM_MODE_BEET | ||
| 438 | tristate "IP: IPsec BEET mode" | ||
| 439 | default y | ||
| 440 | select XFRM | ||
| 441 | ---help--- | ||
| 442 | Support for IPsec BEET mode. | ||
| 443 | |||
| 444 | If unsure, say Y. | ||
| 445 | |||
| 437 | config INET_DIAG | 446 | config INET_DIAG |
| 438 | tristate "INET: socket monitoring interface" | 447 | tristate "INET: socket monitoring interface" |
| 439 | default y | 448 | default y |
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index f66049e28aeb..15645c51520c 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile | |||
| @@ -23,6 +23,7 @@ obj-$(CONFIG_INET_AH) += ah4.o | |||
| 23 | obj-$(CONFIG_INET_ESP) += esp4.o | 23 | obj-$(CONFIG_INET_ESP) += esp4.o |
| 24 | obj-$(CONFIG_INET_IPCOMP) += ipcomp.o | 24 | obj-$(CONFIG_INET_IPCOMP) += ipcomp.o |
| 25 | obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o | 25 | obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o |
| 26 | obj-$(CONFIG_INET_XFRM_MODE_BEET) += xfrm4_mode_beet.o | ||
| 26 | obj-$(CONFIG_INET_TUNNEL) += tunnel4.o | 27 | obj-$(CONFIG_INET_TUNNEL) += tunnel4.o |
| 27 | obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o | 28 | obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o |
| 28 | obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o | 29 | obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o |
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 13b29360d102..b5c205b57669 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
| @@ -253,7 +253,8 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
| 253 | * as per draft-ietf-ipsec-udp-encaps-06, | 253 | * as per draft-ietf-ipsec-udp-encaps-06, |
| 254 | * section 3.1.2 | 254 | * section 3.1.2 |
| 255 | */ | 255 | */ |
| 256 | if (x->props.mode == XFRM_MODE_TRANSPORT) | 256 | if (x->props.mode == XFRM_MODE_TRANSPORT || |
| 257 | x->props.mode == XFRM_MODE_BEET) | ||
| 257 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 258 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
| 258 | } | 259 | } |
| 259 | 260 | ||
| @@ -271,17 +272,28 @@ static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) | |||
| 271 | { | 272 | { |
| 272 | struct esp_data *esp = x->data; | 273 | struct esp_data *esp = x->data; |
| 273 | u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); | 274 | u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); |
| 274 | 275 | int enclen = 0; | |
| 275 | if (x->props.mode == XFRM_MODE_TUNNEL) { | 276 | |
| 276 | mtu = ALIGN(mtu + 2, blksize); | 277 | switch (x->props.mode) { |
| 277 | } else { | 278 | case XFRM_MODE_TUNNEL: |
| 278 | /* The worst case. */ | 279 | mtu = ALIGN(mtu +2, blksize); |
| 280 | break; | ||
| 281 | default: | ||
| 282 | case XFRM_MODE_TRANSPORT: | ||
| 283 | /* The worst case */ | ||
| 279 | mtu = ALIGN(mtu + 2, 4) + blksize - 4; | 284 | mtu = ALIGN(mtu + 2, 4) + blksize - 4; |
| 285 | break; | ||
| 286 | case XFRM_MODE_BEET: | ||
| 287 | /* The worst case. */ | ||
| 288 | enclen = IPV4_BEET_PHMAXLEN; | ||
| 289 | mtu = ALIGN(mtu + enclen + 2, blksize); | ||
| 290 | break; | ||
| 280 | } | 291 | } |
| 292 | |||
| 281 | if (esp->conf.padlen) | 293 | if (esp->conf.padlen) |
| 282 | mtu = ALIGN(mtu, esp->conf.padlen); | 294 | mtu = ALIGN(mtu, esp->conf.padlen); |
| 283 | 295 | ||
| 284 | return mtu + x->props.header_len + esp->auth.icv_trunc_len; | 296 | return mtu + x->props.header_len + esp->auth.icv_trunc_len - enclen; |
| 285 | } | 297 | } |
| 286 | 298 | ||
| 287 | static void esp4_err(struct sk_buff *skb, u32 info) | 299 | static void esp4_err(struct sk_buff *skb, u32 info) |
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 2017d36024d4..3839b706142e 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c | |||
| @@ -206,6 +206,7 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info) | |||
| 206 | static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x) | 206 | static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x) |
| 207 | { | 207 | { |
| 208 | struct xfrm_state *t; | 208 | struct xfrm_state *t; |
| 209 | u8 mode = XFRM_MODE_TUNNEL; | ||
| 209 | 210 | ||
| 210 | t = xfrm_state_alloc(); | 211 | t = xfrm_state_alloc(); |
| 211 | if (t == NULL) | 212 | if (t == NULL) |
| @@ -216,7 +217,9 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x) | |||
| 216 | t->id.daddr.a4 = x->id.daddr.a4; | 217 | t->id.daddr.a4 = x->id.daddr.a4; |
| 217 | memcpy(&t->sel, &x->sel, sizeof(t->sel)); | 218 | memcpy(&t->sel, &x->sel, sizeof(t->sel)); |
| 218 | t->props.family = AF_INET; | 219 | t->props.family = AF_INET; |
| 219 | t->props.mode = XFRM_MODE_TUNNEL; | 220 | if (x->props.mode == XFRM_MODE_BEET) |
| 221 | mode = x->props.mode; | ||
| 222 | t->props.mode = mode; | ||
| 220 | t->props.saddr.a4 = x->props.saddr.a4; | 223 | t->props.saddr.a4 = x->props.saddr.a4; |
| 221 | t->props.flags = x->props.flags; | 224 | t->props.flags = x->props.flags; |
| 222 | 225 | ||
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index 6dee03935f78..1445bb47fea4 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c | |||
| @@ -813,6 +813,16 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb, | |||
| 813 | skb->nh.iph->saddr = cp->vaddr; | 813 | skb->nh.iph->saddr = cp->vaddr; |
| 814 | ip_send_check(skb->nh.iph); | 814 | ip_send_check(skb->nh.iph); |
| 815 | 815 | ||
| 816 | /* For policy routing, packets originating from this | ||
| 817 | * machine itself may be routed differently to packets | ||
| 818 | * passing through. We want this packet to be routed as | ||
| 819 | * if it came from this machine itself. So re-compute | ||
| 820 | * the routing information. | ||
| 821 | */ | ||
| 822 | if (ip_route_me_harder(pskb, RTN_LOCAL) != 0) | ||
| 823 | goto drop; | ||
| 824 | skb = *pskb; | ||
| 825 | |||
| 816 | IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT"); | 826 | IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT"); |
| 817 | 827 | ||
| 818 | ip_vs_out_stats(cp, skb); | 828 | ip_vs_out_stats(cp, skb); |
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index 5ac15379a0cf..e2005c6810a4 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #include <net/ip.h> | 8 | #include <net/ip.h> |
| 9 | 9 | ||
| 10 | /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */ | 10 | /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */ |
| 11 | int ip_route_me_harder(struct sk_buff **pskb) | 11 | int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type) |
| 12 | { | 12 | { |
| 13 | struct iphdr *iph = (*pskb)->nh.iph; | 13 | struct iphdr *iph = (*pskb)->nh.iph; |
| 14 | struct rtable *rt; | 14 | struct rtable *rt; |
| @@ -16,10 +16,13 @@ int ip_route_me_harder(struct sk_buff **pskb) | |||
| 16 | struct dst_entry *odst; | 16 | struct dst_entry *odst; |
| 17 | unsigned int hh_len; | 17 | unsigned int hh_len; |
| 18 | 18 | ||
| 19 | if (addr_type == RTN_UNSPEC) | ||
| 20 | addr_type = inet_addr_type(iph->saddr); | ||
| 21 | |||
| 19 | /* some non-standard hacks like ipt_REJECT.c:send_reset() can cause | 22 | /* some non-standard hacks like ipt_REJECT.c:send_reset() can cause |
| 20 | * packets with foreign saddr to appear on the NF_IP_LOCAL_OUT hook. | 23 | * packets with foreign saddr to appear on the NF_IP_LOCAL_OUT hook. |
| 21 | */ | 24 | */ |
| 22 | if (inet_addr_type(iph->saddr) == RTN_LOCAL) { | 25 | if (addr_type == RTN_LOCAL) { |
| 23 | fl.nl_u.ip4_u.daddr = iph->daddr; | 26 | fl.nl_u.ip4_u.daddr = iph->daddr; |
| 24 | fl.nl_u.ip4_u.saddr = iph->saddr; | 27 | fl.nl_u.ip4_u.saddr = iph->saddr; |
| 25 | fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); | 28 | fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); |
| @@ -156,7 +159,7 @@ static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info) | |||
| 156 | if (!(iph->tos == rt_info->tos | 159 | if (!(iph->tos == rt_info->tos |
| 157 | && iph->daddr == rt_info->daddr | 160 | && iph->daddr == rt_info->daddr |
| 158 | && iph->saddr == rt_info->saddr)) | 161 | && iph->saddr == rt_info->saddr)) |
| 159 | return ip_route_me_harder(pskb); | 162 | return ip_route_me_harder(pskb, RTN_UNSPEC); |
| 160 | } | 163 | } |
| 161 | return 0; | 164 | return 0; |
| 162 | } | 165 | } |
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 021395b67463..d85d2de50449 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c | |||
| @@ -265,7 +265,8 @@ ip_nat_local_fn(unsigned int hooknum, | |||
| 265 | ct->tuplehash[!dir].tuple.src.u.all | 265 | ct->tuplehash[!dir].tuple.src.u.all |
| 266 | #endif | 266 | #endif |
| 267 | ) | 267 | ) |
| 268 | return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; | 268 | if (ip_route_me_harder(pskb, RTN_UNSPEC)) |
| 269 | ret = NF_DROP; | ||
| 269 | } | 270 | } |
| 270 | return ret; | 271 | return ret; |
| 271 | } | 272 | } |
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index fd0c05efed8a..ad0312d0e4fd 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c | |||
| @@ -38,76 +38,16 @@ MODULE_DESCRIPTION("iptables REJECT target module"); | |||
| 38 | #define DEBUGP(format, args...) | 38 | #define DEBUGP(format, args...) |
| 39 | #endif | 39 | #endif |
| 40 | 40 | ||
| 41 | static inline struct rtable *route_reverse(struct sk_buff *skb, | ||
| 42 | struct tcphdr *tcph, int hook) | ||
| 43 | { | ||
| 44 | struct iphdr *iph = skb->nh.iph; | ||
| 45 | struct dst_entry *odst; | ||
| 46 | struct flowi fl = {}; | ||
| 47 | struct rtable *rt; | ||
| 48 | |||
| 49 | /* We don't require ip forwarding to be enabled to be able to | ||
| 50 | * send a RST reply for bridged traffic. */ | ||
| 51 | if (hook != NF_IP_FORWARD | ||
| 52 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
| 53 | || (skb->nf_bridge && skb->nf_bridge->mask & BRNF_BRIDGED) | ||
| 54 | #endif | ||
| 55 | ) { | ||
| 56 | fl.nl_u.ip4_u.daddr = iph->saddr; | ||
| 57 | if (hook == NF_IP_LOCAL_IN) | ||
| 58 | fl.nl_u.ip4_u.saddr = iph->daddr; | ||
| 59 | fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); | ||
| 60 | |||
| 61 | if (ip_route_output_key(&rt, &fl) != 0) | ||
| 62 | return NULL; | ||
| 63 | } else { | ||
| 64 | /* non-local src, find valid iif to satisfy | ||
| 65 | * rp-filter when calling ip_route_input. */ | ||
| 66 | fl.nl_u.ip4_u.daddr = iph->daddr; | ||
| 67 | if (ip_route_output_key(&rt, &fl) != 0) | ||
| 68 | return NULL; | ||
| 69 | |||
| 70 | odst = skb->dst; | ||
| 71 | if (ip_route_input(skb, iph->saddr, iph->daddr, | ||
| 72 | RT_TOS(iph->tos), rt->u.dst.dev) != 0) { | ||
| 73 | dst_release(&rt->u.dst); | ||
| 74 | return NULL; | ||
| 75 | } | ||
| 76 | dst_release(&rt->u.dst); | ||
| 77 | rt = (struct rtable *)skb->dst; | ||
| 78 | skb->dst = odst; | ||
| 79 | |||
| 80 | fl.nl_u.ip4_u.daddr = iph->saddr; | ||
| 81 | fl.nl_u.ip4_u.saddr = iph->daddr; | ||
| 82 | fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); | ||
| 83 | } | ||
| 84 | |||
| 85 | if (rt->u.dst.error) { | ||
| 86 | dst_release(&rt->u.dst); | ||
| 87 | return NULL; | ||
| 88 | } | ||
| 89 | |||
| 90 | fl.proto = IPPROTO_TCP; | ||
| 91 | fl.fl_ip_sport = tcph->dest; | ||
| 92 | fl.fl_ip_dport = tcph->source; | ||
| 93 | security_skb_classify_flow(skb, &fl); | ||
| 94 | |||
| 95 | xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0); | ||
| 96 | |||
| 97 | return rt; | ||
| 98 | } | ||
| 99 | |||
| 100 | /* Send RST reply */ | 41 | /* Send RST reply */ |
| 101 | static void send_reset(struct sk_buff *oldskb, int hook) | 42 | static void send_reset(struct sk_buff *oldskb, int hook) |
| 102 | { | 43 | { |
| 103 | struct sk_buff *nskb; | 44 | struct sk_buff *nskb; |
| 104 | struct iphdr *iph = oldskb->nh.iph; | 45 | struct iphdr *iph = oldskb->nh.iph; |
| 105 | struct tcphdr _otcph, *oth, *tcph; | 46 | struct tcphdr _otcph, *oth, *tcph; |
| 106 | struct rtable *rt; | ||
| 107 | __be16 tmp_port; | 47 | __be16 tmp_port; |
| 108 | __be32 tmp_addr; | 48 | __be32 tmp_addr; |
| 109 | int needs_ack; | 49 | int needs_ack; |
| 110 | int hh_len; | 50 | unsigned int addr_type; |
| 111 | 51 | ||
| 112 | /* IP header checks: fragment. */ | 52 | /* IP header checks: fragment. */ |
| 113 | if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)) | 53 | if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)) |
| @@ -126,23 +66,13 @@ static void send_reset(struct sk_buff *oldskb, int hook) | |||
| 126 | if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP)) | 66 | if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP)) |
| 127 | return; | 67 | return; |
| 128 | 68 | ||
| 129 | if ((rt = route_reverse(oldskb, oth, hook)) == NULL) | ||
| 130 | return; | ||
| 131 | |||
| 132 | hh_len = LL_RESERVED_SPACE(rt->u.dst.dev); | ||
| 133 | |||
| 134 | /* We need a linear, writeable skb. We also need to expand | 69 | /* We need a linear, writeable skb. We also need to expand |
| 135 | headroom in case hh_len of incoming interface < hh_len of | 70 | headroom in case hh_len of incoming interface < hh_len of |
| 136 | outgoing interface */ | 71 | outgoing interface */ |
| 137 | nskb = skb_copy_expand(oldskb, hh_len, skb_tailroom(oldskb), | 72 | nskb = skb_copy_expand(oldskb, LL_MAX_HEADER, skb_tailroom(oldskb), |
| 138 | GFP_ATOMIC); | 73 | GFP_ATOMIC); |
| 139 | if (!nskb) { | 74 | if (!nskb) |
| 140 | dst_release(&rt->u.dst); | ||
| 141 | return; | 75 | return; |
| 142 | } | ||
| 143 | |||
| 144 | dst_release(nskb->dst); | ||
| 145 | nskb->dst = &rt->u.dst; | ||
| 146 | 76 | ||
| 147 | /* This packet will not be the same as the other: clear nf fields */ | 77 | /* This packet will not be the same as the other: clear nf fields */ |
| 148 | nf_reset(nskb); | 78 | nf_reset(nskb); |
| @@ -184,6 +114,21 @@ static void send_reset(struct sk_buff *oldskb, int hook) | |||
| 184 | tcph->window = 0; | 114 | tcph->window = 0; |
| 185 | tcph->urg_ptr = 0; | 115 | tcph->urg_ptr = 0; |
| 186 | 116 | ||
| 117 | /* Set DF, id = 0 */ | ||
| 118 | nskb->nh.iph->frag_off = htons(IP_DF); | ||
| 119 | nskb->nh.iph->id = 0; | ||
| 120 | |||
| 121 | addr_type = RTN_UNSPEC; | ||
| 122 | if (hook != NF_IP_FORWARD | ||
| 123 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
| 124 | || (nskb->nf_bridge && nskb->nf_bridge->mask & BRNF_BRIDGED) | ||
| 125 | #endif | ||
| 126 | ) | ||
| 127 | addr_type = RTN_LOCAL; | ||
| 128 | |||
| 129 | if (ip_route_me_harder(&nskb, addr_type)) | ||
| 130 | goto free_nskb; | ||
| 131 | |||
| 187 | /* Adjust TCP checksum */ | 132 | /* Adjust TCP checksum */ |
| 188 | nskb->ip_summed = CHECKSUM_NONE; | 133 | nskb->ip_summed = CHECKSUM_NONE; |
| 189 | tcph->check = 0; | 134 | tcph->check = 0; |
| @@ -192,12 +137,8 @@ static void send_reset(struct sk_buff *oldskb, int hook) | |||
| 192 | nskb->nh.iph->daddr, | 137 | nskb->nh.iph->daddr, |
| 193 | csum_partial((char *)tcph, | 138 | csum_partial((char *)tcph, |
| 194 | sizeof(struct tcphdr), 0)); | 139 | sizeof(struct tcphdr), 0)); |
| 195 | 140 | /* Adjust IP TTL */ | |
| 196 | /* Adjust IP TTL, DF */ | ||
| 197 | nskb->nh.iph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT); | 141 | nskb->nh.iph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT); |
| 198 | /* Set DF, id = 0 */ | ||
| 199 | nskb->nh.iph->frag_off = htons(IP_DF); | ||
| 200 | nskb->nh.iph->id = 0; | ||
| 201 | 142 | ||
| 202 | /* Adjust IP checksum */ | 143 | /* Adjust IP checksum */ |
| 203 | nskb->nh.iph->check = 0; | 144 | nskb->nh.iph->check = 0; |
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index e62ea2bb9c0a..b91f3582359b 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c | |||
| @@ -157,7 +157,8 @@ ipt_local_hook(unsigned int hook, | |||
| 157 | || (*pskb)->nfmark != nfmark | 157 | || (*pskb)->nfmark != nfmark |
| 158 | #endif | 158 | #endif |
| 159 | || (*pskb)->nh.iph->tos != tos)) | 159 | || (*pskb)->nh.iph->tos != tos)) |
| 160 | return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; | 160 | if (ip_route_me_harder(pskb, RTN_UNSPEC)) |
| 161 | ret = NF_DROP; | ||
| 161 | 162 | ||
| 162 | return ret; | 163 | return ret; |
| 163 | } | 164 | } |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 3f884cea14ff..cf06accbe687 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -2259,7 +2259,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p) | |||
| 2259 | u32 pkts_acked = 0; | 2259 | u32 pkts_acked = 0; |
| 2260 | void (*rtt_sample)(struct sock *sk, u32 usrtt) | 2260 | void (*rtt_sample)(struct sock *sk, u32 usrtt) |
| 2261 | = icsk->icsk_ca_ops->rtt_sample; | 2261 | = icsk->icsk_ca_ops->rtt_sample; |
| 2262 | struct timeval tv; | 2262 | struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }; |
| 2263 | 2263 | ||
| 2264 | while ((skb = skb_peek(&sk->sk_write_queue)) && | 2264 | while ((skb = skb_peek(&sk->sk_write_queue)) && |
| 2265 | skb != sk->sk_send_head) { | 2265 | skb != sk->sk_send_head) { |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 6d6142f9c478..865d75214a9a 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
| @@ -675,6 +675,8 @@ do_append_data: | |||
| 675 | udp_flush_pending_frames(sk); | 675 | udp_flush_pending_frames(sk); |
| 676 | else if (!corkreq) | 676 | else if (!corkreq) |
| 677 | err = udp_push_pending_frames(sk, up); | 677 | err = udp_push_pending_frames(sk, up); |
| 678 | else if (unlikely(skb_queue_empty(&sk->sk_write_queue))) | ||
| 679 | up->pending = 0; | ||
| 678 | release_sock(sk); | 680 | release_sock(sk); |
| 679 | 681 | ||
| 680 | out: | 682 | out: |
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c new file mode 100644 index 000000000000..89cf59ea7bbe --- /dev/null +++ b/net/ipv4/xfrm4_mode_beet.c | |||
| @@ -0,0 +1,139 @@ | |||
| 1 | /* | ||
| 2 | * xfrm4_mode_beet.c - BEET mode encapsulation for IPv4. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2006 Diego Beltrami <diego.beltrami@gmail.com> | ||
| 5 | * Miika Komu <miika@iki.fi> | ||
| 6 | * Herbert Xu <herbert@gondor.apana.org.au> | ||
| 7 | * Abhinav Pathak <abhinav.pathak@hiit.fi> | ||
| 8 | * Jeff Ahrenholz <ahrenholz@gmail.com> | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/init.h> | ||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/skbuff.h> | ||
| 15 | #include <linux/stringify.h> | ||
| 16 | #include <net/dst.h> | ||
| 17 | #include <net/ip.h> | ||
| 18 | #include <net/xfrm.h> | ||
| 19 | |||
| 20 | /* Add encapsulation header. | ||
| 21 | * | ||
| 22 | * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt. | ||
| 23 | * The following fields in it shall be filled in by x->type->output: | ||
| 24 | * tot_len | ||
| 25 | * check | ||
| 26 | * | ||
| 27 | * On exit, skb->h will be set to the start of the payload to be processed | ||
| 28 | * by x->type->output and skb->nh will be set to the top IP header. | ||
| 29 | */ | ||
| 30 | static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) | ||
| 31 | { | ||
| 32 | struct iphdr *iph, *top_iph = NULL; | ||
| 33 | int hdrlen, optlen; | ||
| 34 | |||
| 35 | iph = skb->nh.iph; | ||
| 36 | skb->h.ipiph = iph; | ||
| 37 | |||
| 38 | hdrlen = 0; | ||
| 39 | optlen = iph->ihl * 4 - sizeof(*iph); | ||
| 40 | if (unlikely(optlen)) | ||
| 41 | hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4); | ||
| 42 | |||
| 43 | skb->nh.raw = skb_push(skb, x->props.header_len + hdrlen); | ||
| 44 | top_iph = skb->nh.iph; | ||
| 45 | hdrlen = iph->ihl * 4 - optlen; | ||
| 46 | skb->h.raw += hdrlen; | ||
| 47 | |||
| 48 | memmove(top_iph, iph, hdrlen); | ||
| 49 | if (unlikely(optlen)) { | ||
| 50 | struct ip_beet_phdr *ph; | ||
| 51 | |||
| 52 | BUG_ON(optlen < 0); | ||
| 53 | |||
| 54 | ph = (struct ip_beet_phdr *)skb->h.raw; | ||
| 55 | ph->padlen = 4 - (optlen & 4); | ||
| 56 | ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8; | ||
| 57 | ph->nexthdr = top_iph->protocol; | ||
| 58 | |||
| 59 | top_iph->protocol = IPPROTO_BEETPH; | ||
| 60 | top_iph->ihl = sizeof(struct iphdr) / 4; | ||
| 61 | } | ||
| 62 | |||
| 63 | top_iph->saddr = x->props.saddr.a4; | ||
| 64 | top_iph->daddr = x->id.daddr.a4; | ||
| 65 | |||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb) | ||
| 70 | { | ||
| 71 | struct iphdr *iph = skb->nh.iph; | ||
| 72 | int phlen = 0; | ||
| 73 | int optlen = 0; | ||
| 74 | __u8 ph_nexthdr = 0, protocol = 0; | ||
| 75 | int err = -EINVAL; | ||
| 76 | |||
| 77 | protocol = iph->protocol; | ||
| 78 | |||
| 79 | if (unlikely(iph->protocol == IPPROTO_BEETPH)) { | ||
| 80 | struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 1); | ||
| 81 | |||
| 82 | if (!pskb_may_pull(skb, sizeof(*ph))) | ||
| 83 | goto out; | ||
| 84 | |||
| 85 | phlen = ph->hdrlen * 8; | ||
| 86 | optlen = phlen - ph->padlen - sizeof(*ph); | ||
| 87 | if (optlen < 0 || optlen & 3 || optlen > 250) | ||
| 88 | goto out; | ||
| 89 | |||
| 90 | if (!pskb_may_pull(skb, phlen)) | ||
| 91 | goto out; | ||
| 92 | |||
| 93 | ph_nexthdr = ph->nexthdr; | ||
| 94 | } | ||
| 95 | |||
| 96 | skb_push(skb, sizeof(*iph) - phlen + optlen); | ||
| 97 | memmove(skb->data, skb->nh.raw, sizeof(*iph)); | ||
| 98 | skb->nh.raw = skb->data; | ||
| 99 | |||
| 100 | iph = skb->nh.iph; | ||
| 101 | iph->ihl = (sizeof(*iph) + optlen) / 4; | ||
| 102 | iph->tot_len = htons(skb->len); | ||
| 103 | iph->daddr = x->sel.daddr.a4; | ||
| 104 | iph->saddr = x->sel.saddr.a4; | ||
| 105 | if (ph_nexthdr) | ||
| 106 | iph->protocol = ph_nexthdr; | ||
| 107 | else | ||
| 108 | iph->protocol = protocol; | ||
| 109 | iph->check = 0; | ||
| 110 | iph->check = ip_fast_csum(skb->nh.raw, iph->ihl); | ||
| 111 | err = 0; | ||
| 112 | out: | ||
| 113 | return err; | ||
| 114 | } | ||
| 115 | |||
| 116 | static struct xfrm_mode xfrm4_beet_mode = { | ||
| 117 | .input = xfrm4_beet_input, | ||
| 118 | .output = xfrm4_beet_output, | ||
| 119 | .owner = THIS_MODULE, | ||
| 120 | .encap = XFRM_MODE_BEET, | ||
| 121 | }; | ||
| 122 | |||
| 123 | static int __init xfrm4_beet_init(void) | ||
| 124 | { | ||
| 125 | return xfrm_register_mode(&xfrm4_beet_mode, AF_INET); | ||
| 126 | } | ||
| 127 | |||
| 128 | static void __exit xfrm4_beet_exit(void) | ||
| 129 | { | ||
| 130 | int err; | ||
| 131 | |||
| 132 | err = xfrm_unregister_mode(&xfrm4_beet_mode, AF_INET); | ||
| 133 | BUG_ON(err); | ||
| 134 | } | ||
| 135 | |||
| 136 | module_init(xfrm4_beet_init); | ||
| 137 | module_exit(xfrm4_beet_exit); | ||
| 138 | MODULE_LICENSE("GPL"); | ||
| 139 | MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_BEET); | ||
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index a2d211da2aba..a460e8132b4d 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
| @@ -136,6 +136,16 @@ config INET6_XFRM_MODE_TUNNEL | |||
| 136 | 136 | ||
| 137 | If unsure, say Y. | 137 | If unsure, say Y. |
| 138 | 138 | ||
| 139 | config INET6_XFRM_MODE_BEET | ||
| 140 | tristate "IPv6: IPsec BEET mode" | ||
| 141 | depends on IPV6 | ||
| 142 | default IPV6 | ||
| 143 | select XFRM | ||
| 144 | ---help--- | ||
| 145 | Support for IPsec BEET mode. | ||
| 146 | |||
| 147 | If unsure, say Y. | ||
| 148 | |||
| 139 | config INET6_XFRM_MODE_ROUTEOPTIMIZATION | 149 | config INET6_XFRM_MODE_ROUTEOPTIMIZATION |
| 140 | tristate "IPv6: MIPv6 route optimization mode (EXPERIMENTAL)" | 150 | tristate "IPv6: MIPv6 route optimization mode (EXPERIMENTAL)" |
| 141 | depends on IPV6 && EXPERIMENTAL | 151 | depends on IPV6 && EXPERIMENTAL |
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 0213c6612b58..87274e47fe32 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile | |||
| @@ -26,6 +26,7 @@ obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o | |||
| 26 | obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o | 26 | obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o |
| 27 | obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o | 27 | obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o |
| 28 | obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o | 28 | obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o |
| 29 | obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o | ||
| 29 | obj-$(CONFIG_NETFILTER) += netfilter/ | 30 | obj-$(CONFIG_NETFILTER) += netfilter/ |
| 30 | 31 | ||
| 31 | obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o | 32 | obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o |
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index a2860e35efd7..71f59f18ede8 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
| @@ -199,6 +199,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
| 199 | static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) | 199 | static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) |
| 200 | { | 200 | { |
| 201 | struct xfrm_state *t = NULL; | 201 | struct xfrm_state *t = NULL; |
| 202 | u8 mode = XFRM_MODE_TUNNEL; | ||
| 202 | 203 | ||
| 203 | t = xfrm_state_alloc(); | 204 | t = xfrm_state_alloc(); |
| 204 | if (!t) | 205 | if (!t) |
| @@ -212,7 +213,9 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) | |||
| 212 | memcpy(t->id.daddr.a6, x->id.daddr.a6, sizeof(struct in6_addr)); | 213 | memcpy(t->id.daddr.a6, x->id.daddr.a6, sizeof(struct in6_addr)); |
| 213 | memcpy(&t->sel, &x->sel, sizeof(t->sel)); | 214 | memcpy(&t->sel, &x->sel, sizeof(t->sel)); |
| 214 | t->props.family = AF_INET6; | 215 | t->props.family = AF_INET6; |
| 215 | t->props.mode = XFRM_MODE_TUNNEL; | 216 | if (x->props.mode == XFRM_MODE_BEET) |
| 217 | mode = x->props.mode; | ||
| 218 | t->props.mode = mode; | ||
| 216 | memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr)); | 219 | memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr)); |
| 217 | 220 | ||
| 218 | if (xfrm_init_state(t)) | 221 | if (xfrm_init_state(t)) |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 9662561701d1..e0c3934a7e4b 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -546,7 +546,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 546 | struct in6_addr *daddr, *final_p = NULL, final; | 546 | struct in6_addr *daddr, *final_p = NULL, final; |
| 547 | struct ipv6_txoptions *opt = NULL; | 547 | struct ipv6_txoptions *opt = NULL; |
| 548 | struct ip6_flowlabel *flowlabel = NULL; | 548 | struct ip6_flowlabel *flowlabel = NULL; |
| 549 | struct flowi *fl = &inet->cork.fl; | 549 | struct flowi fl; |
| 550 | struct dst_entry *dst; | 550 | struct dst_entry *dst; |
| 551 | int addr_len = msg->msg_namelen; | 551 | int addr_len = msg->msg_namelen; |
| 552 | int ulen = len; | 552 | int ulen = len; |
| @@ -626,19 +626,19 @@ do_udp_sendmsg: | |||
| 626 | } | 626 | } |
| 627 | ulen += sizeof(struct udphdr); | 627 | ulen += sizeof(struct udphdr); |
| 628 | 628 | ||
| 629 | memset(fl, 0, sizeof(*fl)); | 629 | memset(&fl, 0, sizeof(fl)); |
| 630 | 630 | ||
| 631 | if (sin6) { | 631 | if (sin6) { |
| 632 | if (sin6->sin6_port == 0) | 632 | if (sin6->sin6_port == 0) |
| 633 | return -EINVAL; | 633 | return -EINVAL; |
| 634 | 634 | ||
| 635 | fl->fl_ip_dport = sin6->sin6_port; | 635 | fl.fl_ip_dport = sin6->sin6_port; |
| 636 | daddr = &sin6->sin6_addr; | 636 | daddr = &sin6->sin6_addr; |
| 637 | 637 | ||
| 638 | if (np->sndflow) { | 638 | if (np->sndflow) { |
| 639 | fl->fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; | 639 | fl.fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; |
| 640 | if (fl->fl6_flowlabel&IPV6_FLOWLABEL_MASK) { | 640 | if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) { |
| 641 | flowlabel = fl6_sock_lookup(sk, fl->fl6_flowlabel); | 641 | flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); |
| 642 | if (flowlabel == NULL) | 642 | if (flowlabel == NULL) |
| 643 | return -EINVAL; | 643 | return -EINVAL; |
| 644 | daddr = &flowlabel->dst; | 644 | daddr = &flowlabel->dst; |
| @@ -656,32 +656,32 @@ do_udp_sendmsg: | |||
| 656 | if (addr_len >= sizeof(struct sockaddr_in6) && | 656 | if (addr_len >= sizeof(struct sockaddr_in6) && |
| 657 | sin6->sin6_scope_id && | 657 | sin6->sin6_scope_id && |
| 658 | ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) | 658 | ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) |
| 659 | fl->oif = sin6->sin6_scope_id; | 659 | fl.oif = sin6->sin6_scope_id; |
| 660 | } else { | 660 | } else { |
| 661 | if (sk->sk_state != TCP_ESTABLISHED) | 661 | if (sk->sk_state != TCP_ESTABLISHED) |
| 662 | return -EDESTADDRREQ; | 662 | return -EDESTADDRREQ; |
| 663 | 663 | ||
| 664 | fl->fl_ip_dport = inet->dport; | 664 | fl.fl_ip_dport = inet->dport; |
| 665 | daddr = &np->daddr; | 665 | daddr = &np->daddr; |
| 666 | fl->fl6_flowlabel = np->flow_label; | 666 | fl.fl6_flowlabel = np->flow_label; |
| 667 | connected = 1; | 667 | connected = 1; |
| 668 | } | 668 | } |
| 669 | 669 | ||
| 670 | if (!fl->oif) | 670 | if (!fl.oif) |
| 671 | fl->oif = sk->sk_bound_dev_if; | 671 | fl.oif = sk->sk_bound_dev_if; |
| 672 | 672 | ||
| 673 | if (msg->msg_controllen) { | 673 | if (msg->msg_controllen) { |
| 674 | opt = &opt_space; | 674 | opt = &opt_space; |
| 675 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 675 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
| 676 | opt->tot_len = sizeof(*opt); | 676 | opt->tot_len = sizeof(*opt); |
| 677 | 677 | ||
| 678 | err = datagram_send_ctl(msg, fl, opt, &hlimit, &tclass); | 678 | err = datagram_send_ctl(msg, &fl, opt, &hlimit, &tclass); |
| 679 | if (err < 0) { | 679 | if (err < 0) { |
| 680 | fl6_sock_release(flowlabel); | 680 | fl6_sock_release(flowlabel); |
| 681 | return err; | 681 | return err; |
| 682 | } | 682 | } |
| 683 | if ((fl->fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { | 683 | if ((fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { |
| 684 | flowlabel = fl6_sock_lookup(sk, fl->fl6_flowlabel); | 684 | flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); |
| 685 | if (flowlabel == NULL) | 685 | if (flowlabel == NULL) |
| 686 | return -EINVAL; | 686 | return -EINVAL; |
| 687 | } | 687 | } |
| @@ -695,39 +695,39 @@ do_udp_sendmsg: | |||
| 695 | opt = fl6_merge_options(&opt_space, flowlabel, opt); | 695 | opt = fl6_merge_options(&opt_space, flowlabel, opt); |
| 696 | opt = ipv6_fixup_options(&opt_space, opt); | 696 | opt = ipv6_fixup_options(&opt_space, opt); |
| 697 | 697 | ||
| 698 | fl->proto = IPPROTO_UDP; | 698 | fl.proto = IPPROTO_UDP; |
| 699 | ipv6_addr_copy(&fl->fl6_dst, daddr); | 699 | ipv6_addr_copy(&fl.fl6_dst, daddr); |
| 700 | if (ipv6_addr_any(&fl->fl6_src) && !ipv6_addr_any(&np->saddr)) | 700 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) |
| 701 | ipv6_addr_copy(&fl->fl6_src, &np->saddr); | 701 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); |
| 702 | fl->fl_ip_sport = inet->sport; | 702 | fl.fl_ip_sport = inet->sport; |
| 703 | 703 | ||
| 704 | /* merge ip6_build_xmit from ip6_output */ | 704 | /* merge ip6_build_xmit from ip6_output */ |
| 705 | if (opt && opt->srcrt) { | 705 | if (opt && opt->srcrt) { |
| 706 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | 706 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; |
| 707 | ipv6_addr_copy(&final, &fl->fl6_dst); | 707 | ipv6_addr_copy(&final, &fl.fl6_dst); |
| 708 | ipv6_addr_copy(&fl->fl6_dst, rt0->addr); | 708 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); |
| 709 | final_p = &final; | 709 | final_p = &final; |
| 710 | connected = 0; | 710 | connected = 0; |
| 711 | } | 711 | } |
| 712 | 712 | ||
| 713 | if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst)) { | 713 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) { |
| 714 | fl->oif = np->mcast_oif; | 714 | fl.oif = np->mcast_oif; |
| 715 | connected = 0; | 715 | connected = 0; |
| 716 | } | 716 | } |
| 717 | 717 | ||
| 718 | security_sk_classify_flow(sk, fl); | 718 | security_sk_classify_flow(sk, &fl); |
| 719 | 719 | ||
| 720 | err = ip6_sk_dst_lookup(sk, &dst, fl); | 720 | err = ip6_sk_dst_lookup(sk, &dst, &fl); |
| 721 | if (err) | 721 | if (err) |
| 722 | goto out; | 722 | goto out; |
| 723 | if (final_p) | 723 | if (final_p) |
| 724 | ipv6_addr_copy(&fl->fl6_dst, final_p); | 724 | ipv6_addr_copy(&fl.fl6_dst, final_p); |
| 725 | 725 | ||
| 726 | if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) | 726 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) |
| 727 | goto out; | 727 | goto out; |
| 728 | 728 | ||
| 729 | if (hlimit < 0) { | 729 | if (hlimit < 0) { |
| 730 | if (ipv6_addr_is_multicast(&fl->fl6_dst)) | 730 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) |
| 731 | hlimit = np->mcast_hops; | 731 | hlimit = np->mcast_hops; |
| 732 | else | 732 | else |
| 733 | hlimit = np->hop_limit; | 733 | hlimit = np->hop_limit; |
| @@ -763,21 +763,23 @@ back_from_confirm: | |||
| 763 | do_append_data: | 763 | do_append_data: |
| 764 | up->len += ulen; | 764 | up->len += ulen; |
| 765 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen, | 765 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen, |
| 766 | sizeof(struct udphdr), hlimit, tclass, opt, fl, | 766 | sizeof(struct udphdr), hlimit, tclass, opt, &fl, |
| 767 | (struct rt6_info*)dst, | 767 | (struct rt6_info*)dst, |
| 768 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); | 768 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); |
| 769 | if (err) | 769 | if (err) |
| 770 | udp_v6_flush_pending_frames(sk); | 770 | udp_v6_flush_pending_frames(sk); |
| 771 | else if (!corkreq) | 771 | else if (!corkreq) |
| 772 | err = udp_v6_push_pending_frames(sk, up); | 772 | err = udp_v6_push_pending_frames(sk, up); |
| 773 | else if (unlikely(skb_queue_empty(&sk->sk_write_queue))) | ||
| 774 | up->pending = 0; | ||
| 773 | 775 | ||
| 774 | if (dst) { | 776 | if (dst) { |
| 775 | if (connected) { | 777 | if (connected) { |
| 776 | ip6_dst_store(sk, dst, | 778 | ip6_dst_store(sk, dst, |
| 777 | ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ? | 779 | ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ? |
| 778 | &np->daddr : NULL, | 780 | &np->daddr : NULL, |
| 779 | #ifdef CONFIG_IPV6_SUBTREES | 781 | #ifdef CONFIG_IPV6_SUBTREES |
| 780 | ipv6_addr_equal(&fl->fl6_src, &np->saddr) ? | 782 | ipv6_addr_equal(&fl.fl6_src, &np->saddr) ? |
| 781 | &np->saddr : | 783 | &np->saddr : |
| 782 | #endif | 784 | #endif |
| 783 | NULL); | 785 | NULL); |
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c new file mode 100644 index 000000000000..edcfffa9e87b --- /dev/null +++ b/net/ipv6/xfrm6_mode_beet.c | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | /* | ||
| 2 | * xfrm6_mode_beet.c - BEET mode encapsulation for IPv6. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2006 Diego Beltrami <diego.beltrami@gmail.com> | ||
| 5 | * Miika Komu <miika@iki.fi> | ||
| 6 | * Herbert Xu <herbert@gondor.apana.org.au> | ||
| 7 | * Abhinav Pathak <abhinav.pathak@hiit.fi> | ||
| 8 | * Jeff Ahrenholz <ahrenholz@gmail.com> | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/init.h> | ||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/skbuff.h> | ||
| 15 | #include <linux/stringify.h> | ||
| 16 | #include <net/dsfield.h> | ||
| 17 | #include <net/dst.h> | ||
| 18 | #include <net/inet_ecn.h> | ||
| 19 | #include <net/ipv6.h> | ||
| 20 | #include <net/xfrm.h> | ||
| 21 | |||
| 22 | /* Add encapsulation header. | ||
| 23 | * | ||
| 24 | * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt. | ||
| 25 | * The following fields in it shall be filled in by x->type->output: | ||
| 26 | * payload_len | ||
| 27 | * | ||
| 28 | * On exit, skb->h will be set to the start of the encapsulation header to be | ||
| 29 | * filled in by x->type->output and skb->nh will be set to the nextheader field | ||
| 30 | * of the extension header directly preceding the encapsulation header, or in | ||
| 31 | * its absence, that of the top IP header. The value of skb->data will always | ||
| 32 | * point to the top IP header. | ||
| 33 | */ | ||
| 34 | static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) | ||
| 35 | { | ||
| 36 | struct ipv6hdr *iph, *top_iph; | ||
| 37 | u8 *prevhdr; | ||
| 38 | int hdr_len; | ||
| 39 | |||
| 40 | skb_push(skb, x->props.header_len); | ||
| 41 | iph = skb->nh.ipv6h; | ||
| 42 | |||
| 43 | hdr_len = ip6_find_1stfragopt(skb, &prevhdr); | ||
| 44 | skb->nh.raw = prevhdr - x->props.header_len; | ||
| 45 | skb->h.raw = skb->data + hdr_len; | ||
| 46 | memmove(skb->data, iph, hdr_len); | ||
| 47 | |||
| 48 | skb->nh.raw = skb->data; | ||
| 49 | top_iph = skb->nh.ipv6h; | ||
| 50 | skb->nh.raw = &top_iph->nexthdr; | ||
| 51 | skb->h.ipv6h = top_iph + 1; | ||
| 52 | |||
| 53 | ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); | ||
| 54 | ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); | ||
| 55 | |||
| 56 | return 0; | ||
| 57 | } | ||
| 58 | |||
| 59 | static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) | ||
| 60 | { | ||
| 61 | struct ipv6hdr *ip6h; | ||
| 62 | int size = sizeof(struct ipv6hdr); | ||
| 63 | int err = -EINVAL; | ||
| 64 | |||
| 65 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | ||
| 66 | goto out; | ||
| 67 | |||
| 68 | skb_push(skb, size); | ||
| 69 | memmove(skb->data, skb->nh.raw, size); | ||
| 70 | skb->nh.raw = skb->data; | ||
| 71 | |||
| 72 | skb->mac.raw = memmove(skb->data - skb->mac_len, | ||
| 73 | skb->mac.raw, skb->mac_len); | ||
| 74 | |||
| 75 | ip6h = skb->nh.ipv6h; | ||
| 76 | ip6h->payload_len = htons(skb->len - size); | ||
| 77 | ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *) &x->sel.daddr.a6); | ||
| 78 | ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *) &x->sel.saddr.a6); | ||
| 79 | err = 0; | ||
| 80 | out: | ||
| 81 | return err; | ||
| 82 | } | ||
| 83 | |||
| 84 | static struct xfrm_mode xfrm6_beet_mode = { | ||
| 85 | .input = xfrm6_beet_input, | ||
| 86 | .output = xfrm6_beet_output, | ||
| 87 | .owner = THIS_MODULE, | ||
| 88 | .encap = XFRM_MODE_BEET, | ||
| 89 | }; | ||
| 90 | |||
| 91 | static int __init xfrm6_beet_init(void) | ||
| 92 | { | ||
| 93 | return xfrm_register_mode(&xfrm6_beet_mode, AF_INET6); | ||
| 94 | } | ||
| 95 | |||
| 96 | static void __exit xfrm6_beet_exit(void) | ||
| 97 | { | ||
| 98 | int err; | ||
| 99 | |||
| 100 | err = xfrm_unregister_mode(&xfrm6_beet_mode, AF_INET6); | ||
| 101 | BUG_ON(err); | ||
| 102 | } | ||
| 103 | |||
| 104 | module_init(xfrm6_beet_init); | ||
| 105 | module_exit(xfrm6_beet_exit); | ||
| 106 | MODULE_LICENSE("GPL"); | ||
| 107 | MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_BEET); | ||
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 0a28d2c5c44f..ce94732b8e23 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
| @@ -365,7 +365,7 @@ config NETFILTER_XT_MATCH_MULTIPORT | |||
| 365 | 365 | ||
| 366 | config NETFILTER_XT_MATCH_PHYSDEV | 366 | config NETFILTER_XT_MATCH_PHYSDEV |
| 367 | tristate '"physdev" match support' | 367 | tristate '"physdev" match support' |
| 368 | depends on NETFILTER_XTABLES && BRIDGE_NETFILTER | 368 | depends on NETFILTER_XTABLES && BRIDGE && BRIDGE_NETFILTER |
| 369 | help | 369 | help |
| 370 | Physdev packet matching matches against the physical bridge ports | 370 | Physdev packet matching matches against the physical bridge ports |
| 371 | the IP packet arrived on or will leave by. | 371 | the IP packet arrived on or will leave by. |
diff --git a/net/sched/estimator.c b/net/sched/estimator.c deleted file mode 100644 index 0ebc98e9be2d..000000000000 --- a/net/sched/estimator.c +++ /dev/null | |||
| @@ -1,196 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * net/sched/estimator.c Simple rate estimator. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License | ||
| 6 | * as published by the Free Software Foundation; either version | ||
| 7 | * 2 of the License, or (at your option) any later version. | ||
| 8 | * | ||
| 9 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <asm/uaccess.h> | ||
| 13 | #include <asm/system.h> | ||
| 14 | #include <linux/bitops.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/types.h> | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/jiffies.h> | ||
| 19 | #include <linux/string.h> | ||
| 20 | #include <linux/mm.h> | ||
| 21 | #include <linux/socket.h> | ||
| 22 | #include <linux/sockios.h> | ||
| 23 | #include <linux/in.h> | ||
| 24 | #include <linux/errno.h> | ||
| 25 | #include <linux/interrupt.h> | ||
| 26 | #include <linux/netdevice.h> | ||
| 27 | #include <linux/skbuff.h> | ||
| 28 | #include <linux/rtnetlink.h> | ||
| 29 | #include <linux/init.h> | ||
| 30 | #include <net/sock.h> | ||
| 31 | #include <net/pkt_sched.h> | ||
| 32 | |||
| 33 | /* | ||
| 34 | This code is NOT intended to be used for statistics collection, | ||
| 35 | its purpose is to provide a base for statistical multiplexing | ||
| 36 | for controlled load service. | ||
| 37 | If you need only statistics, run a user level daemon which | ||
| 38 | periodically reads byte counters. | ||
| 39 | |||
| 40 | Unfortunately, rate estimation is not a very easy task. | ||
| 41 | F.e. I did not find a simple way to estimate the current peak rate | ||
| 42 | and even failed to formulate the problem 8)8) | ||
| 43 | |||
| 44 | So I preferred not to built an estimator into the scheduler, | ||
| 45 | but run this task separately. | ||
| 46 | Ideally, it should be kernel thread(s), but for now it runs | ||
| 47 | from timers, which puts apparent top bounds on the number of rated | ||
| 48 | flows, has minimal overhead on small, but is enough | ||
| 49 | to handle controlled load service, sets of aggregates. | ||
| 50 | |||
| 51 | We measure rate over A=(1<<interval) seconds and evaluate EWMA: | ||
| 52 | |||
| 53 | avrate = avrate*(1-W) + rate*W | ||
| 54 | |||
| 55 | where W is chosen as negative power of 2: W = 2^(-ewma_log) | ||
| 56 | |||
| 57 | The resulting time constant is: | ||
| 58 | |||
| 59 | T = A/(-ln(1-W)) | ||
| 60 | |||
| 61 | |||
| 62 | NOTES. | ||
| 63 | |||
| 64 | * The stored value for avbps is scaled by 2^5, so that maximal | ||
| 65 | rate is ~1Gbit, avpps is scaled by 2^10. | ||
| 66 | |||
| 67 | * Minimal interval is HZ/4=250msec (it is the greatest common divisor | ||
| 68 | for HZ=100 and HZ=1024 8)), maximal interval | ||
| 69 | is (HZ*2^EST_MAX_INTERVAL)/4 = 8sec. Shorter intervals | ||
| 70 | are too expensive, longer ones can be implemented | ||
| 71 | at user level painlessly. | ||
| 72 | */ | ||
| 73 | |||
| 74 | #define EST_MAX_INTERVAL 5 | ||
| 75 | |||
| 76 | struct qdisc_estimator | ||
| 77 | { | ||
| 78 | struct qdisc_estimator *next; | ||
| 79 | struct tc_stats *stats; | ||
| 80 | spinlock_t *stats_lock; | ||
| 81 | unsigned interval; | ||
| 82 | int ewma_log; | ||
| 83 | u64 last_bytes; | ||
| 84 | u32 last_packets; | ||
| 85 | u32 avpps; | ||
| 86 | u32 avbps; | ||
| 87 | }; | ||
| 88 | |||
| 89 | struct qdisc_estimator_head | ||
| 90 | { | ||
| 91 | struct timer_list timer; | ||
| 92 | struct qdisc_estimator *list; | ||
| 93 | }; | ||
| 94 | |||
| 95 | static struct qdisc_estimator_head elist[EST_MAX_INTERVAL+1]; | ||
| 96 | |||
| 97 | /* Estimator array lock */ | ||
| 98 | static DEFINE_RWLOCK(est_lock); | ||
| 99 | |||
| 100 | static void est_timer(unsigned long arg) | ||
| 101 | { | ||
| 102 | int idx = (int)arg; | ||
| 103 | struct qdisc_estimator *e; | ||
| 104 | |||
| 105 | read_lock(&est_lock); | ||
| 106 | for (e = elist[idx].list; e; e = e->next) { | ||
| 107 | struct tc_stats *st = e->stats; | ||
| 108 | u64 nbytes; | ||
| 109 | u32 npackets; | ||
| 110 | u32 rate; | ||
| 111 | |||
| 112 | spin_lock(e->stats_lock); | ||
| 113 | nbytes = st->bytes; | ||
| 114 | npackets = st->packets; | ||
| 115 | rate = (nbytes - e->last_bytes)<<(7 - idx); | ||
| 116 | e->last_bytes = nbytes; | ||
| 117 | e->avbps += ((long)rate - (long)e->avbps) >> e->ewma_log; | ||
| 118 | st->bps = (e->avbps+0xF)>>5; | ||
| 119 | |||
| 120 | rate = (npackets - e->last_packets)<<(12 - idx); | ||
| 121 | e->last_packets = npackets; | ||
| 122 | e->avpps += ((long)rate - (long)e->avpps) >> e->ewma_log; | ||
| 123 | e->stats->pps = (e->avpps+0x1FF)>>10; | ||
| 124 | spin_unlock(e->stats_lock); | ||
| 125 | } | ||
| 126 | |||
| 127 | mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4)); | ||
| 128 | read_unlock(&est_lock); | ||
| 129 | } | ||
| 130 | |||
| 131 | int qdisc_new_estimator(struct tc_stats *stats, spinlock_t *stats_lock, struct rtattr *opt) | ||
| 132 | { | ||
| 133 | struct qdisc_estimator *est; | ||
| 134 | struct tc_estimator *parm = RTA_DATA(opt); | ||
| 135 | |||
| 136 | if (RTA_PAYLOAD(opt) < sizeof(*parm)) | ||
| 137 | return -EINVAL; | ||
| 138 | |||
| 139 | if (parm->interval < -2 || parm->interval > 3) | ||
| 140 | return -EINVAL; | ||
| 141 | |||
| 142 | est = kzalloc(sizeof(*est), GFP_KERNEL); | ||
| 143 | if (est == NULL) | ||
| 144 | return -ENOBUFS; | ||
| 145 | |||
| 146 | est->interval = parm->interval + 2; | ||
| 147 | est->stats = stats; | ||
| 148 | est->stats_lock = stats_lock; | ||
| 149 | est->ewma_log = parm->ewma_log; | ||
| 150 | est->last_bytes = stats->bytes; | ||
| 151 | est->avbps = stats->bps<<5; | ||
| 152 | est->last_packets = stats->packets; | ||
| 153 | est->avpps = stats->pps<<10; | ||
| 154 | |||
| 155 | est->next = elist[est->interval].list; | ||
| 156 | if (est->next == NULL) { | ||
| 157 | init_timer(&elist[est->interval].timer); | ||
| 158 | elist[est->interval].timer.data = est->interval; | ||
| 159 | elist[est->interval].timer.expires = jiffies + ((HZ<<est->interval)/4); | ||
| 160 | elist[est->interval].timer.function = est_timer; | ||
| 161 | add_timer(&elist[est->interval].timer); | ||
| 162 | } | ||
| 163 | write_lock_bh(&est_lock); | ||
| 164 | elist[est->interval].list = est; | ||
| 165 | write_unlock_bh(&est_lock); | ||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | |||
| 169 | void qdisc_kill_estimator(struct tc_stats *stats) | ||
| 170 | { | ||
| 171 | int idx; | ||
| 172 | struct qdisc_estimator *est, **pest; | ||
| 173 | |||
| 174 | for (idx=0; idx <= EST_MAX_INTERVAL; idx++) { | ||
| 175 | int killed = 0; | ||
| 176 | pest = &elist[idx].list; | ||
| 177 | while ((est=*pest) != NULL) { | ||
| 178 | if (est->stats != stats) { | ||
| 179 | pest = &est->next; | ||
| 180 | continue; | ||
| 181 | } | ||
| 182 | |||
| 183 | write_lock_bh(&est_lock); | ||
| 184 | *pest = est->next; | ||
| 185 | write_unlock_bh(&est_lock); | ||
| 186 | |||
| 187 | kfree(est); | ||
| 188 | killed++; | ||
| 189 | } | ||
| 190 | if (killed && elist[idx].list == NULL) | ||
| 191 | del_timer(&elist[idx].timer); | ||
| 192 | } | ||
| 193 | } | ||
| 194 | |||
| 195 | EXPORT_SYMBOL(qdisc_kill_estimator); | ||
| 196 | EXPORT_SYMBOL(qdisc_new_estimator); | ||
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 6c058e3660c0..bb3ddd4784b1 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
| @@ -391,7 +391,7 @@ static inline void htb_add_class_to_row(struct htb_sched *q, | |||
| 391 | /* If this triggers, it is a bug in this code, but it need not be fatal */ | 391 | /* If this triggers, it is a bug in this code, but it need not be fatal */ |
| 392 | static void htb_safe_rb_erase(struct rb_node *rb, struct rb_root *root) | 392 | static void htb_safe_rb_erase(struct rb_node *rb, struct rb_root *root) |
| 393 | { | 393 | { |
| 394 | if (!RB_EMPTY_NODE(rb)) { | 394 | if (RB_EMPTY_NODE(rb)) { |
| 395 | WARN_ON(1); | 395 | WARN_ON(1); |
| 396 | } else { | 396 | } else { |
| 397 | rb_erase(rb, root); | 397 | rb_erase(rb, root); |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 693f02eca6d6..53bc8cb5adbc 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
| @@ -1666,8 +1666,9 @@ static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf) | |||
| 1666 | char addr_string[16]; | 1666 | char addr_string[16]; |
| 1667 | 1667 | ||
| 1668 | tipc_printf(TIPC_OUTPUT, "Msg seq number: %u, ", msg_seqno(msg)); | 1668 | tipc_printf(TIPC_OUTPUT, "Msg seq number: %u, ", msg_seqno(msg)); |
| 1669 | tipc_printf(TIPC_OUTPUT, "Outstanding acks: %u\n", (u32)TIPC_SKB_CB(buf)->handle); | 1669 | tipc_printf(TIPC_OUTPUT, "Outstanding acks: %lu\n", |
| 1670 | 1670 | (unsigned long) TIPC_SKB_CB(buf)->handle); | |
| 1671 | |||
| 1671 | n_ptr = l_ptr->owner->next; | 1672 | n_ptr = l_ptr->owner->next; |
| 1672 | tipc_node_lock(n_ptr); | 1673 | tipc_node_lock(n_ptr); |
| 1673 | 1674 | ||
diff --git a/net/xfrm/xfrm_hash.h b/net/xfrm/xfrm_hash.h index 6ac4e4f033ac..d401dc8f05ed 100644 --- a/net/xfrm/xfrm_hash.h +++ b/net/xfrm/xfrm_hash.h | |||
| @@ -41,17 +41,18 @@ static inline unsigned int __xfrm_dst_hash(xfrm_address_t *daddr, xfrm_address_t | |||
| 41 | return (h ^ (h >> 16)) & hmask; | 41 | return (h ^ (h >> 16)) & hmask; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | static inline unsigned __xfrm_src_hash(xfrm_address_t *saddr, | 44 | static inline unsigned __xfrm_src_hash(xfrm_address_t *daddr, |
| 45 | xfrm_address_t *saddr, | ||
| 45 | unsigned short family, | 46 | unsigned short family, |
| 46 | unsigned int hmask) | 47 | unsigned int hmask) |
| 47 | { | 48 | { |
| 48 | unsigned int h = family; | 49 | unsigned int h = family; |
| 49 | switch (family) { | 50 | switch (family) { |
| 50 | case AF_INET: | 51 | case AF_INET: |
| 51 | h ^= __xfrm4_addr_hash(saddr); | 52 | h ^= __xfrm4_daddr_saddr_hash(daddr, saddr); |
| 52 | break; | 53 | break; |
| 53 | case AF_INET6: | 54 | case AF_INET6: |
| 54 | h ^= __xfrm6_addr_hash(saddr); | 55 | h ^= __xfrm6_daddr_saddr_hash(daddr, saddr); |
| 55 | break; | 56 | break; |
| 56 | }; | 57 | }; |
| 57 | return (h ^ (h >> 16)) & hmask; | 58 | return (h ^ (h >> 16)) & hmask; |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index b6e2e79d7261..2a7861661f14 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
| @@ -778,8 +778,9 @@ void xfrm_policy_flush(u8 type) | |||
| 778 | for (dir = 0; dir < XFRM_POLICY_MAX; dir++) { | 778 | for (dir = 0; dir < XFRM_POLICY_MAX; dir++) { |
| 779 | struct xfrm_policy *pol; | 779 | struct xfrm_policy *pol; |
| 780 | struct hlist_node *entry; | 780 | struct hlist_node *entry; |
| 781 | int i; | 781 | int i, killed; |
| 782 | 782 | ||
| 783 | killed = 0; | ||
| 783 | again1: | 784 | again1: |
| 784 | hlist_for_each_entry(pol, entry, | 785 | hlist_for_each_entry(pol, entry, |
| 785 | &xfrm_policy_inexact[dir], bydst) { | 786 | &xfrm_policy_inexact[dir], bydst) { |
| @@ -790,6 +791,7 @@ void xfrm_policy_flush(u8 type) | |||
| 790 | write_unlock_bh(&xfrm_policy_lock); | 791 | write_unlock_bh(&xfrm_policy_lock); |
| 791 | 792 | ||
| 792 | xfrm_policy_kill(pol); | 793 | xfrm_policy_kill(pol); |
| 794 | killed++; | ||
| 793 | 795 | ||
| 794 | write_lock_bh(&xfrm_policy_lock); | 796 | write_lock_bh(&xfrm_policy_lock); |
| 795 | goto again1; | 797 | goto again1; |
| @@ -807,13 +809,14 @@ void xfrm_policy_flush(u8 type) | |||
| 807 | write_unlock_bh(&xfrm_policy_lock); | 809 | write_unlock_bh(&xfrm_policy_lock); |
| 808 | 810 | ||
| 809 | xfrm_policy_kill(pol); | 811 | xfrm_policy_kill(pol); |
| 812 | killed++; | ||
| 810 | 813 | ||
| 811 | write_lock_bh(&xfrm_policy_lock); | 814 | write_lock_bh(&xfrm_policy_lock); |
| 812 | goto again2; | 815 | goto again2; |
| 813 | } | 816 | } |
| 814 | } | 817 | } |
| 815 | 818 | ||
| 816 | xfrm_policy_count[dir] = 0; | 819 | xfrm_policy_count[dir] -= killed; |
| 817 | } | 820 | } |
| 818 | atomic_inc(&flow_cache_genid); | 821 | atomic_inc(&flow_cache_genid); |
| 819 | write_unlock_bh(&xfrm_policy_lock); | 822 | write_unlock_bh(&xfrm_policy_lock); |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index f927b7330f02..39b8bf3a9ded 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
| @@ -63,10 +63,11 @@ static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, | |||
| 63 | return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask); | 63 | return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask); |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | static inline unsigned int xfrm_src_hash(xfrm_address_t *addr, | 66 | static inline unsigned int xfrm_src_hash(xfrm_address_t *daddr, |
| 67 | xfrm_address_t *saddr, | ||
| 67 | unsigned short family) | 68 | unsigned short family) |
| 68 | { | 69 | { |
| 69 | return __xfrm_src_hash(addr, family, xfrm_state_hmask); | 70 | return __xfrm_src_hash(daddr, saddr, family, xfrm_state_hmask); |
| 70 | } | 71 | } |
| 71 | 72 | ||
| 72 | static inline unsigned int | 73 | static inline unsigned int |
| @@ -92,7 +93,8 @@ static void xfrm_hash_transfer(struct hlist_head *list, | |||
| 92 | nhashmask); | 93 | nhashmask); |
| 93 | hlist_add_head(&x->bydst, ndsttable+h); | 94 | hlist_add_head(&x->bydst, ndsttable+h); |
| 94 | 95 | ||
| 95 | h = __xfrm_src_hash(&x->props.saddr, x->props.family, | 96 | h = __xfrm_src_hash(&x->id.daddr, &x->props.saddr, |
| 97 | x->props.family, | ||
| 96 | nhashmask); | 98 | nhashmask); |
| 97 | hlist_add_head(&x->bysrc, nsrctable+h); | 99 | hlist_add_head(&x->bysrc, nsrctable+h); |
| 98 | 100 | ||
| @@ -458,7 +460,7 @@ static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, | |||
| 458 | 460 | ||
| 459 | static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) | 461 | static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) |
| 460 | { | 462 | { |
| 461 | unsigned int h = xfrm_src_hash(saddr, family); | 463 | unsigned int h = xfrm_src_hash(daddr, saddr, family); |
| 462 | struct xfrm_state *x; | 464 | struct xfrm_state *x; |
| 463 | struct hlist_node *entry; | 465 | struct hlist_node *entry; |
| 464 | 466 | ||
| @@ -587,7 +589,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
| 587 | if (km_query(x, tmpl, pol) == 0) { | 589 | if (km_query(x, tmpl, pol) == 0) { |
| 588 | x->km.state = XFRM_STATE_ACQ; | 590 | x->km.state = XFRM_STATE_ACQ; |
| 589 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); | 591 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); |
| 590 | h = xfrm_src_hash(saddr, family); | 592 | h = xfrm_src_hash(daddr, saddr, family); |
| 591 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); | 593 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); |
| 592 | if (x->id.spi) { | 594 | if (x->id.spi) { |
| 593 | h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family); | 595 | h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family); |
| @@ -622,7 +624,7 @@ static void __xfrm_state_insert(struct xfrm_state *x) | |||
| 622 | x->props.reqid, x->props.family); | 624 | x->props.reqid, x->props.family); |
| 623 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); | 625 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); |
| 624 | 626 | ||
| 625 | h = xfrm_src_hash(&x->props.saddr, x->props.family); | 627 | h = xfrm_src_hash(&x->id.daddr, &x->props.saddr, x->props.family); |
| 626 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); | 628 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); |
| 627 | 629 | ||
| 628 | if (x->id.spi) { | 630 | if (x->id.spi) { |
| @@ -748,7 +750,7 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re | |||
| 748 | x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ; | 750 | x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ; |
| 749 | add_timer(&x->timer); | 751 | add_timer(&x->timer); |
| 750 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); | 752 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); |
| 751 | h = xfrm_src_hash(saddr, family); | 753 | h = xfrm_src_hash(daddr, saddr, family); |
| 752 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); | 754 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); |
| 753 | wake_up(&km_waitq); | 755 | wake_up(&km_waitq); |
| 754 | } | 756 | } |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index c59a78d2923a..d54b3a70d5df 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
| @@ -211,6 +211,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, | |||
| 211 | case XFRM_MODE_TRANSPORT: | 211 | case XFRM_MODE_TRANSPORT: |
| 212 | case XFRM_MODE_TUNNEL: | 212 | case XFRM_MODE_TUNNEL: |
| 213 | case XFRM_MODE_ROUTEOPTIMIZATION: | 213 | case XFRM_MODE_ROUTEOPTIMIZATION: |
| 214 | case XFRM_MODE_BEET: | ||
| 214 | break; | 215 | break; |
| 215 | 216 | ||
| 216 | default: | 217 | default: |
