diff options
69 files changed, 771 insertions, 404 deletions
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt index 676ecf62491d..4efca560adda 100644 --- a/Documentation/devicetree/bindings/net/cpsw.txt +++ b/Documentation/devicetree/bindings/net/cpsw.txt | |||
@@ -46,6 +46,7 @@ Required properties: | |||
46 | Optional properties: | 46 | Optional properties: |
47 | - dual_emac_res_vlan : Specifies VID to be used to segregate the ports | 47 | - dual_emac_res_vlan : Specifies VID to be used to segregate the ports |
48 | - mac-address : See ethernet.txt file in the same directory | 48 | - mac-address : See ethernet.txt file in the same directory |
49 | - phy-handle : See ethernet.txt file in the same directory | ||
49 | 50 | ||
50 | Note: "ti,hwmods" field is used to fetch the base address and irq | 51 | Note: "ti,hwmods" field is used to fetch the base address and irq |
51 | resources from TI, omap hwmod data base during device registration. | 52 | resources from TI, omap hwmod data base during device registration. |
diff --git a/Documentation/devicetree/bindings/net/smsc-lan87xx.txt b/Documentation/devicetree/bindings/net/smsc-lan87xx.txt new file mode 100644 index 000000000000..974edd5c85cc --- /dev/null +++ b/Documentation/devicetree/bindings/net/smsc-lan87xx.txt | |||
@@ -0,0 +1,24 @@ | |||
1 | SMSC LAN87xx Ethernet PHY | ||
2 | |||
3 | Some boards require special tuning values. Configure them | ||
4 | through an Ethernet OF device node. | ||
5 | |||
6 | Optional properties: | ||
7 | |||
8 | - smsc,disable-energy-detect: | ||
9 | If set, do not enable energy detect mode for the SMSC phy. | ||
10 | default: enable energy detect mode | ||
11 | |||
12 | Examples: | ||
13 | smsc phy with disabled energy detect mode on an am335x based board. | ||
14 | &davinci_mdio { | ||
15 | pinctrl-names = "default", "sleep"; | ||
16 | pinctrl-0 = <&davinci_mdio_default>; | ||
17 | pinctrl-1 = <&davinci_mdio_sleep>; | ||
18 | status = "okay"; | ||
19 | |||
20 | ethernetphy0: ethernet-phy@0 { | ||
21 | reg = <0>; | ||
22 | smsc,disable-energy-detect; | ||
23 | }; | ||
24 | }; | ||
diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c index 18accb0a79cc..c53a53f6efb6 100644 --- a/drivers/isdn/hisax/isdnl2.c +++ b/drivers/isdn/hisax/isdnl2.c | |||
@@ -1247,7 +1247,7 @@ static void | |||
1247 | l2_pull_iqueue(struct FsmInst *fi, int event, void *arg) | 1247 | l2_pull_iqueue(struct FsmInst *fi, int event, void *arg) |
1248 | { | 1248 | { |
1249 | struct PStack *st = fi->userdata; | 1249 | struct PStack *st = fi->userdata; |
1250 | struct sk_buff *skb; | 1250 | struct sk_buff *skb, *nskb; |
1251 | struct Layer2 *l2 = &st->l2; | 1251 | struct Layer2 *l2 = &st->l2; |
1252 | u_char header[MAX_HEADER_LEN]; | 1252 | u_char header[MAX_HEADER_LEN]; |
1253 | int i, hdr_space_needed; | 1253 | int i, hdr_space_needed; |
@@ -1262,14 +1262,10 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg) | |||
1262 | return; | 1262 | return; |
1263 | 1263 | ||
1264 | hdr_space_needed = l2headersize(l2, 0); | 1264 | hdr_space_needed = l2headersize(l2, 0); |
1265 | if (hdr_space_needed > skb_headroom(skb)) { | 1265 | nskb = skb_realloc_headroom(skb, hdr_space_needed); |
1266 | struct sk_buff *orig_skb = skb; | 1266 | if (!nskb) { |
1267 | 1267 | skb_queue_head(&l2->i_queue, skb); | |
1268 | skb = skb_realloc_headroom(skb, hdr_space_needed); | 1268 | return; |
1269 | if (!skb) { | ||
1270 | dev_kfree_skb(orig_skb); | ||
1271 | return; | ||
1272 | } | ||
1273 | } | 1269 | } |
1274 | spin_lock_irqsave(&l2->lock, flags); | 1270 | spin_lock_irqsave(&l2->lock, flags); |
1275 | if (test_bit(FLG_MOD128, &l2->flag)) | 1271 | if (test_bit(FLG_MOD128, &l2->flag)) |
@@ -1282,7 +1278,7 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg) | |||
1282 | p1); | 1278 | p1); |
1283 | dev_kfree_skb(l2->windowar[p1]); | 1279 | dev_kfree_skb(l2->windowar[p1]); |
1284 | } | 1280 | } |
1285 | l2->windowar[p1] = skb_clone(skb, GFP_ATOMIC); | 1281 | l2->windowar[p1] = skb; |
1286 | 1282 | ||
1287 | i = sethdraddr(&st->l2, header, CMD); | 1283 | i = sethdraddr(&st->l2, header, CMD); |
1288 | 1284 | ||
@@ -1295,8 +1291,8 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg) | |||
1295 | l2->vs = (l2->vs + 1) % 8; | 1291 | l2->vs = (l2->vs + 1) % 8; |
1296 | } | 1292 | } |
1297 | spin_unlock_irqrestore(&l2->lock, flags); | 1293 | spin_unlock_irqrestore(&l2->lock, flags); |
1298 | memcpy(skb_push(skb, i), header, i); | 1294 | memcpy(skb_push(nskb, i), header, i); |
1299 | st->l2.l2l1(st, PH_PULL | INDICATION, skb); | 1295 | st->l2.l2l1(st, PH_PULL | INDICATION, nskb); |
1300 | test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag); | 1296 | test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag); |
1301 | if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) { | 1297 | if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) { |
1302 | FsmDelTimer(&st->l2.t203, 13); | 1298 | FsmDelTimer(&st->l2.t203, 13); |
diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c index 949cabb88f1c..5eb380a25903 100644 --- a/drivers/isdn/mISDN/layer2.c +++ b/drivers/isdn/mISDN/layer2.c | |||
@@ -1476,7 +1476,7 @@ static void | |||
1476 | l2_pull_iqueue(struct FsmInst *fi, int event, void *arg) | 1476 | l2_pull_iqueue(struct FsmInst *fi, int event, void *arg) |
1477 | { | 1477 | { |
1478 | struct layer2 *l2 = fi->userdata; | 1478 | struct layer2 *l2 = fi->userdata; |
1479 | struct sk_buff *skb, *nskb, *oskb; | 1479 | struct sk_buff *skb, *nskb; |
1480 | u_char header[MAX_L2HEADER_LEN]; | 1480 | u_char header[MAX_L2HEADER_LEN]; |
1481 | u_int i, p1; | 1481 | u_int i, p1; |
1482 | 1482 | ||
@@ -1486,48 +1486,34 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg) | |||
1486 | skb = skb_dequeue(&l2->i_queue); | 1486 | skb = skb_dequeue(&l2->i_queue); |
1487 | if (!skb) | 1487 | if (!skb) |
1488 | return; | 1488 | return; |
1489 | |||
1490 | if (test_bit(FLG_MOD128, &l2->flag)) | ||
1491 | p1 = (l2->vs - l2->va) % 128; | ||
1492 | else | ||
1493 | p1 = (l2->vs - l2->va) % 8; | ||
1494 | p1 = (p1 + l2->sow) % l2->window; | ||
1495 | if (l2->windowar[p1]) { | ||
1496 | printk(KERN_WARNING "%s: l2 try overwrite ack queue entry %d\n", | ||
1497 | mISDNDevName4ch(&l2->ch), p1); | ||
1498 | dev_kfree_skb(l2->windowar[p1]); | ||
1499 | } | ||
1500 | l2->windowar[p1] = skb; | ||
1501 | i = sethdraddr(l2, header, CMD); | 1489 | i = sethdraddr(l2, header, CMD); |
1502 | if (test_bit(FLG_MOD128, &l2->flag)) { | 1490 | if (test_bit(FLG_MOD128, &l2->flag)) { |
1503 | header[i++] = l2->vs << 1; | 1491 | header[i++] = l2->vs << 1; |
1504 | header[i++] = l2->vr << 1; | 1492 | header[i++] = l2->vr << 1; |
1493 | } else | ||
1494 | header[i++] = (l2->vr << 5) | (l2->vs << 1); | ||
1495 | nskb = skb_realloc_headroom(skb, i); | ||
1496 | if (!nskb) { | ||
1497 | printk(KERN_WARNING "%s: no headroom(%d) copy for IFrame\n", | ||
1498 | mISDNDevName4ch(&l2->ch), i); | ||
1499 | skb_queue_head(&l2->i_queue, skb); | ||
1500 | return; | ||
1501 | } | ||
1502 | if (test_bit(FLG_MOD128, &l2->flag)) { | ||
1503 | p1 = (l2->vs - l2->va) % 128; | ||
1505 | l2->vs = (l2->vs + 1) % 128; | 1504 | l2->vs = (l2->vs + 1) % 128; |
1506 | } else { | 1505 | } else { |
1507 | header[i++] = (l2->vr << 5) | (l2->vs << 1); | 1506 | p1 = (l2->vs - l2->va) % 8; |
1508 | l2->vs = (l2->vs + 1) % 8; | 1507 | l2->vs = (l2->vs + 1) % 8; |
1509 | } | 1508 | } |
1510 | 1509 | p1 = (p1 + l2->sow) % l2->window; | |
1511 | nskb = skb_clone(skb, GFP_ATOMIC); | 1510 | if (l2->windowar[p1]) { |
1512 | p1 = skb_headroom(nskb); | 1511 | printk(KERN_WARNING "%s: l2 try overwrite ack queue entry %d\n", |
1513 | if (p1 >= i) | 1512 | mISDNDevName4ch(&l2->ch), p1); |
1514 | memcpy(skb_push(nskb, i), header, i); | 1513 | dev_kfree_skb(l2->windowar[p1]); |
1515 | else { | ||
1516 | printk(KERN_WARNING | ||
1517 | "%s: L2 pull_iqueue skb header(%d/%d) too short\n", | ||
1518 | mISDNDevName4ch(&l2->ch), i, p1); | ||
1519 | oskb = nskb; | ||
1520 | nskb = mI_alloc_skb(oskb->len + i, GFP_ATOMIC); | ||
1521 | if (!nskb) { | ||
1522 | dev_kfree_skb(oskb); | ||
1523 | printk(KERN_WARNING "%s: no skb mem in %s\n", | ||
1524 | mISDNDevName4ch(&l2->ch), __func__); | ||
1525 | return; | ||
1526 | } | ||
1527 | memcpy(skb_put(nskb, i), header, i); | ||
1528 | memcpy(skb_put(nskb, oskb->len), oskb->data, oskb->len); | ||
1529 | dev_kfree_skb(oskb); | ||
1530 | } | 1514 | } |
1515 | l2->windowar[p1] = skb; | ||
1516 | memcpy(skb_push(nskb, i), header, i); | ||
1531 | l2down(l2, PH_DATA_REQ, l2_newid(l2), nskb); | 1517 | l2down(l2, PH_DATA_REQ, l2_newid(l2), nskb); |
1532 | test_and_clear_bit(FLG_ACK_PEND, &l2->flag); | 1518 | test_and_clear_bit(FLG_ACK_PEND, &l2->flag); |
1533 | if (!test_and_set_bit(FLG_T200_RUN, &l2->flag)) { | 1519 | if (!test_and_set_bit(FLG_T200_RUN, &l2->flag)) { |
diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c index 48ce83e443c2..8d50314ac3eb 100644 --- a/drivers/net/ethernet/allwinner/sun4i-emac.c +++ b/drivers/net/ethernet/allwinner/sun4i-emac.c | |||
@@ -847,21 +847,25 @@ static int emac_probe(struct platform_device *pdev) | |||
847 | if (ndev->irq == -ENXIO) { | 847 | if (ndev->irq == -ENXIO) { |
848 | netdev_err(ndev, "No irq resource\n"); | 848 | netdev_err(ndev, "No irq resource\n"); |
849 | ret = ndev->irq; | 849 | ret = ndev->irq; |
850 | goto out; | 850 | goto out_iounmap; |
851 | } | 851 | } |
852 | 852 | ||
853 | db->clk = devm_clk_get(&pdev->dev, NULL); | 853 | db->clk = devm_clk_get(&pdev->dev, NULL); |
854 | if (IS_ERR(db->clk)) { | 854 | if (IS_ERR(db->clk)) { |
855 | ret = PTR_ERR(db->clk); | 855 | ret = PTR_ERR(db->clk); |
856 | goto out; | 856 | goto out_iounmap; |
857 | } | 857 | } |
858 | 858 | ||
859 | clk_prepare_enable(db->clk); | 859 | ret = clk_prepare_enable(db->clk); |
860 | if (ret) { | ||
861 | dev_err(&pdev->dev, "Error couldn't enable clock (%d)\n", ret); | ||
862 | goto out_iounmap; | ||
863 | } | ||
860 | 864 | ||
861 | ret = sunxi_sram_claim(&pdev->dev); | 865 | ret = sunxi_sram_claim(&pdev->dev); |
862 | if (ret) { | 866 | if (ret) { |
863 | dev_err(&pdev->dev, "Error couldn't map SRAM to device\n"); | 867 | dev_err(&pdev->dev, "Error couldn't map SRAM to device\n"); |
864 | goto out; | 868 | goto out_clk_disable_unprepare; |
865 | } | 869 | } |
866 | 870 | ||
867 | db->phy_node = of_parse_phandle(np, "phy", 0); | 871 | db->phy_node = of_parse_phandle(np, "phy", 0); |
@@ -910,6 +914,10 @@ static int emac_probe(struct platform_device *pdev) | |||
910 | 914 | ||
911 | out_release_sram: | 915 | out_release_sram: |
912 | sunxi_sram_release(&pdev->dev); | 916 | sunxi_sram_release(&pdev->dev); |
917 | out_clk_disable_unprepare: | ||
918 | clk_disable_unprepare(db->clk); | ||
919 | out_iounmap: | ||
920 | iounmap(db->membase); | ||
913 | out: | 921 | out: |
914 | dev_err(db->dev, "not found (%d).\n", ret); | 922 | dev_err(db->dev, "not found (%d).\n", ret); |
915 | 923 | ||
@@ -921,8 +929,12 @@ out: | |||
921 | static int emac_remove(struct platform_device *pdev) | 929 | static int emac_remove(struct platform_device *pdev) |
922 | { | 930 | { |
923 | struct net_device *ndev = platform_get_drvdata(pdev); | 931 | struct net_device *ndev = platform_get_drvdata(pdev); |
932 | struct emac_board_info *db = netdev_priv(ndev); | ||
924 | 933 | ||
925 | unregister_netdev(ndev); | 934 | unregister_netdev(ndev); |
935 | sunxi_sram_release(&pdev->dev); | ||
936 | clk_disable_unprepare(db->clk); | ||
937 | iounmap(db->membase); | ||
926 | free_netdev(ndev); | 938 | free_netdev(ndev); |
927 | 939 | ||
928 | dev_dbg(&pdev->dev, "released and freed device\n"); | 940 | dev_dbg(&pdev->dev, "released and freed device\n"); |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 45512242baea..112f1bc8bcee 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c | |||
@@ -1595,7 +1595,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) | |||
1595 | packet->rdesc_count, 1); | 1595 | packet->rdesc_count, 1); |
1596 | 1596 | ||
1597 | /* Make sure ownership is written to the descriptor */ | 1597 | /* Make sure ownership is written to the descriptor */ |
1598 | dma_wmb(); | 1598 | wmb(); |
1599 | 1599 | ||
1600 | ring->cur = cur_index + 1; | 1600 | ring->cur = cur_index + 1; |
1601 | if (!packet->skb->xmit_more || | 1601 | if (!packet->skb->xmit_more || |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 49f796aaad4f..cff8940e1694 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c | |||
@@ -1811,6 +1811,7 @@ static int xgbe_tx_poll(struct xgbe_channel *channel) | |||
1811 | struct netdev_queue *txq; | 1811 | struct netdev_queue *txq; |
1812 | int processed = 0; | 1812 | int processed = 0; |
1813 | unsigned int tx_packets = 0, tx_bytes = 0; | 1813 | unsigned int tx_packets = 0, tx_bytes = 0; |
1814 | unsigned int cur; | ||
1814 | 1815 | ||
1815 | DBGPR("-->xgbe_tx_poll\n"); | 1816 | DBGPR("-->xgbe_tx_poll\n"); |
1816 | 1817 | ||
@@ -1818,10 +1819,11 @@ static int xgbe_tx_poll(struct xgbe_channel *channel) | |||
1818 | if (!ring) | 1819 | if (!ring) |
1819 | return 0; | 1820 | return 0; |
1820 | 1821 | ||
1822 | cur = ring->cur; | ||
1821 | txq = netdev_get_tx_queue(netdev, channel->queue_index); | 1823 | txq = netdev_get_tx_queue(netdev, channel->queue_index); |
1822 | 1824 | ||
1823 | while ((processed < XGBE_TX_DESC_MAX_PROC) && | 1825 | while ((processed < XGBE_TX_DESC_MAX_PROC) && |
1824 | (ring->dirty != ring->cur)) { | 1826 | (ring->dirty != cur)) { |
1825 | rdata = XGBE_GET_DESC_DATA(ring, ring->dirty); | 1827 | rdata = XGBE_GET_DESC_DATA(ring, ring->dirty); |
1826 | rdesc = rdata->rdesc; | 1828 | rdesc = rdata->rdesc; |
1827 | 1829 | ||
diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index 95af75d35bc5..8b1929e9f698 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c | |||
@@ -2048,7 +2048,7 @@ static void swphy_poll_timer(unsigned long data) | |||
2048 | 2048 | ||
2049 | for (i = 0; i < priv->num_ports; i++) { | 2049 | for (i = 0; i < priv->num_ports; i++) { |
2050 | struct bcm63xx_enetsw_port *port; | 2050 | struct bcm63xx_enetsw_port *port; |
2051 | int val, j, up, advertise, lpa, lpa2, speed, duplex, media; | 2051 | int val, j, up, advertise, lpa, speed, duplex, media; |
2052 | int external_phy = bcm_enet_port_is_rgmii(i); | 2052 | int external_phy = bcm_enet_port_is_rgmii(i); |
2053 | u8 override; | 2053 | u8 override; |
2054 | 2054 | ||
@@ -2091,22 +2091,27 @@ static void swphy_poll_timer(unsigned long data) | |||
2091 | lpa = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id, | 2091 | lpa = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id, |
2092 | MII_LPA); | 2092 | MII_LPA); |
2093 | 2093 | ||
2094 | lpa2 = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id, | ||
2095 | MII_STAT1000); | ||
2096 | |||
2097 | /* figure out media and duplex from advertise and LPA values */ | 2094 | /* figure out media and duplex from advertise and LPA values */ |
2098 | media = mii_nway_result(lpa & advertise); | 2095 | media = mii_nway_result(lpa & advertise); |
2099 | duplex = (media & ADVERTISE_FULL) ? 1 : 0; | 2096 | duplex = (media & ADVERTISE_FULL) ? 1 : 0; |
2100 | if (lpa2 & LPA_1000FULL) | 2097 | |
2101 | duplex = 1; | 2098 | if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)) |
2102 | 2099 | speed = 100; | |
2103 | if (lpa2 & (LPA_1000FULL | LPA_1000HALF)) | 2100 | else |
2104 | speed = 1000; | 2101 | speed = 10; |
2105 | else { | 2102 | |
2106 | if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)) | 2103 | if (val & BMSR_ESTATEN) { |
2107 | speed = 100; | 2104 | advertise = bcmenet_sw_mdio_read(priv, external_phy, |
2108 | else | 2105 | port->phy_id, MII_CTRL1000); |
2109 | speed = 10; | 2106 | |
2107 | lpa = bcmenet_sw_mdio_read(priv, external_phy, | ||
2108 | port->phy_id, MII_STAT1000); | ||
2109 | |||
2110 | if (advertise & (ADVERTISE_1000FULL | ADVERTISE_1000HALF) | ||
2111 | && lpa & (LPA_1000FULL | LPA_1000HALF)) { | ||
2112 | speed = 1000; | ||
2113 | duplex = (lpa & LPA_1000FULL); | ||
2114 | } | ||
2110 | } | 2115 | } |
2111 | 2116 | ||
2112 | dev_info(&priv->pdev->dev, | 2117 | dev_info(&priv->pdev->dev, |
diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig index 9b35d142f47a..8fb84e69c30e 100644 --- a/drivers/net/ethernet/cavium/Kconfig +++ b/drivers/net/ethernet/cavium/Kconfig | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | config NET_VENDOR_CAVIUM | 5 | config NET_VENDOR_CAVIUM |
6 | tristate "Cavium ethernet drivers" | 6 | bool "Cavium ethernet drivers" |
7 | depends on PCI | 7 | depends on PCI |
8 | default y | 8 | default y |
9 | ---help--- | 9 | ---help--- |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 8fd26fdd7705..3f385ffe420f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c | |||
@@ -1406,6 +1406,12 @@ static void i40e_get_ethtool_stats(struct net_device *netdev, | |||
1406 | data[i++] = (i40e_gstrings_veb_stats[j].sizeof_stat == | 1406 | data[i++] = (i40e_gstrings_veb_stats[j].sizeof_stat == |
1407 | sizeof(u64)) ? *(u64 *)p : *(u32 *)p; | 1407 | sizeof(u64)) ? *(u64 *)p : *(u32 *)p; |
1408 | } | 1408 | } |
1409 | for (j = 0; j < I40E_MAX_TRAFFIC_CLASS; j++) { | ||
1410 | data[i++] = veb->tc_stats.tc_tx_packets[j]; | ||
1411 | data[i++] = veb->tc_stats.tc_tx_bytes[j]; | ||
1412 | data[i++] = veb->tc_stats.tc_rx_packets[j]; | ||
1413 | data[i++] = veb->tc_stats.tc_rx_bytes[j]; | ||
1414 | } | ||
1409 | } | 1415 | } |
1410 | for (j = 0; j < I40E_GLOBAL_STATS_LEN; j++) { | 1416 | for (j = 0; j < I40E_GLOBAL_STATS_LEN; j++) { |
1411 | p = (char *)pf + i40e_gstrings_stats[j].stat_offset; | 1417 | p = (char *)pf + i40e_gstrings_stats[j].stat_offset; |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 3e595adfb0bf..b825f978d441 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c | |||
@@ -8154,6 +8154,7 @@ static int i40e_sw_init(struct i40e_pf *pf) | |||
8154 | if (pf->hw.func_caps.vmdq) { | 8154 | if (pf->hw.func_caps.vmdq) { |
8155 | pf->num_vmdq_vsis = I40E_DEFAULT_NUM_VMDQ_VSI; | 8155 | pf->num_vmdq_vsis = I40E_DEFAULT_NUM_VMDQ_VSI; |
8156 | pf->flags |= I40E_FLAG_VMDQ_ENABLED; | 8156 | pf->flags |= I40E_FLAG_VMDQ_ENABLED; |
8157 | pf->num_vmdq_qps = i40e_default_queues_per_vmdq(pf); | ||
8157 | } | 8158 | } |
8158 | 8159 | ||
8159 | #ifdef I40E_FCOE | 8160 | #ifdef I40E_FCOE |
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 603d29df5832..6bf725921e79 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c | |||
@@ -759,11 +759,23 @@ txq_put_data_tso(struct net_device *dev, struct tx_queue *txq, | |||
759 | 759 | ||
760 | desc->l4i_chk = 0; | 760 | desc->l4i_chk = 0; |
761 | desc->byte_cnt = length; | 761 | desc->byte_cnt = length; |
762 | desc->buf_ptr = dma_map_single(dev->dev.parent, data, | 762 | |
763 | length, DMA_TO_DEVICE); | 763 | if (length <= 8 && (uintptr_t)data & 0x7) { |
764 | if (unlikely(dma_mapping_error(dev->dev.parent, desc->buf_ptr))) { | 764 | /* Copy unaligned small data fragment to TSO header data area */ |
765 | WARN(1, "dma_map_single failed!\n"); | 765 | memcpy(txq->tso_hdrs + txq->tx_curr_desc * TSO_HEADER_SIZE, |
766 | return -ENOMEM; | 766 | data, length); |
767 | desc->buf_ptr = txq->tso_hdrs_dma | ||
768 | + txq->tx_curr_desc * TSO_HEADER_SIZE; | ||
769 | } else { | ||
770 | /* Alignment is okay, map buffer and hand off to hardware */ | ||
771 | txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_SINGLE; | ||
772 | desc->buf_ptr = dma_map_single(dev->dev.parent, data, | ||
773 | length, DMA_TO_DEVICE); | ||
774 | if (unlikely(dma_mapping_error(dev->dev.parent, | ||
775 | desc->buf_ptr))) { | ||
776 | WARN(1, "dma_map_single failed!\n"); | ||
777 | return -ENOMEM; | ||
778 | } | ||
767 | } | 779 | } |
768 | 780 | ||
769 | cmd_sts = BUFFER_OWNED_BY_DMA; | 781 | cmd_sts = BUFFER_OWNED_BY_DMA; |
@@ -779,7 +791,8 @@ txq_put_data_tso(struct net_device *dev, struct tx_queue *txq, | |||
779 | } | 791 | } |
780 | 792 | ||
781 | static inline void | 793 | static inline void |
782 | txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length) | 794 | txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length, |
795 | u32 *first_cmd_sts, bool first_desc) | ||
783 | { | 796 | { |
784 | struct mv643xx_eth_private *mp = txq_to_mp(txq); | 797 | struct mv643xx_eth_private *mp = txq_to_mp(txq); |
785 | int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); | 798 | int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); |
@@ -788,6 +801,7 @@ txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length) | |||
788 | int ret; | 801 | int ret; |
789 | u32 cmd_csum = 0; | 802 | u32 cmd_csum = 0; |
790 | u16 l4i_chk = 0; | 803 | u16 l4i_chk = 0; |
804 | u32 cmd_sts; | ||
791 | 805 | ||
792 | tx_index = txq->tx_curr_desc; | 806 | tx_index = txq->tx_curr_desc; |
793 | desc = &txq->tx_desc_area[tx_index]; | 807 | desc = &txq->tx_desc_area[tx_index]; |
@@ -803,9 +817,17 @@ txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length) | |||
803 | desc->byte_cnt = hdr_len; | 817 | desc->byte_cnt = hdr_len; |
804 | desc->buf_ptr = txq->tso_hdrs_dma + | 818 | desc->buf_ptr = txq->tso_hdrs_dma + |
805 | txq->tx_curr_desc * TSO_HEADER_SIZE; | 819 | txq->tx_curr_desc * TSO_HEADER_SIZE; |
806 | desc->cmd_sts = cmd_csum | BUFFER_OWNED_BY_DMA | TX_FIRST_DESC | | 820 | cmd_sts = cmd_csum | BUFFER_OWNED_BY_DMA | TX_FIRST_DESC | |
807 | GEN_CRC; | 821 | GEN_CRC; |
808 | 822 | ||
823 | /* Defer updating the first command descriptor until all | ||
824 | * following descriptors have been written. | ||
825 | */ | ||
826 | if (first_desc) | ||
827 | *first_cmd_sts = cmd_sts; | ||
828 | else | ||
829 | desc->cmd_sts = cmd_sts; | ||
830 | |||
809 | txq->tx_curr_desc++; | 831 | txq->tx_curr_desc++; |
810 | if (txq->tx_curr_desc == txq->tx_ring_size) | 832 | if (txq->tx_curr_desc == txq->tx_ring_size) |
811 | txq->tx_curr_desc = 0; | 833 | txq->tx_curr_desc = 0; |
@@ -819,6 +841,8 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb, | |||
819 | int desc_count = 0; | 841 | int desc_count = 0; |
820 | struct tso_t tso; | 842 | struct tso_t tso; |
821 | int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); | 843 | int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); |
844 | struct tx_desc *first_tx_desc; | ||
845 | u32 first_cmd_sts = 0; | ||
822 | 846 | ||
823 | /* Count needed descriptors */ | 847 | /* Count needed descriptors */ |
824 | if ((txq->tx_desc_count + tso_count_descs(skb)) >= txq->tx_ring_size) { | 848 | if ((txq->tx_desc_count + tso_count_descs(skb)) >= txq->tx_ring_size) { |
@@ -826,11 +850,14 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb, | |||
826 | return -EBUSY; | 850 | return -EBUSY; |
827 | } | 851 | } |
828 | 852 | ||
853 | first_tx_desc = &txq->tx_desc_area[txq->tx_curr_desc]; | ||
854 | |||
829 | /* Initialize the TSO handler, and prepare the first payload */ | 855 | /* Initialize the TSO handler, and prepare the first payload */ |
830 | tso_start(skb, &tso); | 856 | tso_start(skb, &tso); |
831 | 857 | ||
832 | total_len = skb->len - hdr_len; | 858 | total_len = skb->len - hdr_len; |
833 | while (total_len > 0) { | 859 | while (total_len > 0) { |
860 | bool first_desc = (desc_count == 0); | ||
834 | char *hdr; | 861 | char *hdr; |
835 | 862 | ||
836 | data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len); | 863 | data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len); |
@@ -840,7 +867,8 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb, | |||
840 | /* prepare packet headers: MAC + IP + TCP */ | 867 | /* prepare packet headers: MAC + IP + TCP */ |
841 | hdr = txq->tso_hdrs + txq->tx_curr_desc * TSO_HEADER_SIZE; | 868 | hdr = txq->tso_hdrs + txq->tx_curr_desc * TSO_HEADER_SIZE; |
842 | tso_build_hdr(skb, hdr, &tso, data_left, total_len == 0); | 869 | tso_build_hdr(skb, hdr, &tso, data_left, total_len == 0); |
843 | txq_put_hdr_tso(skb, txq, data_left); | 870 | txq_put_hdr_tso(skb, txq, data_left, &first_cmd_sts, |
871 | first_desc); | ||
844 | 872 | ||
845 | while (data_left > 0) { | 873 | while (data_left > 0) { |
846 | int size; | 874 | int size; |
@@ -860,6 +888,10 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb, | |||
860 | __skb_queue_tail(&txq->tx_skb, skb); | 888 | __skb_queue_tail(&txq->tx_skb, skb); |
861 | skb_tx_timestamp(skb); | 889 | skb_tx_timestamp(skb); |
862 | 890 | ||
891 | /* ensure all other descriptors are written before first cmd_sts */ | ||
892 | wmb(); | ||
893 | first_tx_desc->cmd_sts = first_cmd_sts; | ||
894 | |||
863 | /* clear TX_END status */ | 895 | /* clear TX_END status */ |
864 | mp->work_tx_end &= ~(1 << txq->index); | 896 | mp->work_tx_end &= ~(1 << txq->index); |
865 | 897 | ||
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 55d2d8577d07..040fbc1e5508 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/pm_runtime.h> | 31 | #include <linux/pm_runtime.h> |
32 | #include <linux/gpio.h> | 32 | #include <linux/gpio.h> |
33 | #include <linux/of.h> | 33 | #include <linux/of.h> |
34 | #include <linux/of_mdio.h> | ||
34 | #include <linux/of_net.h> | 35 | #include <linux/of_net.h> |
35 | #include <linux/of_device.h> | 36 | #include <linux/of_device.h> |
36 | #include <linux/if_vlan.h> | 37 | #include <linux/if_vlan.h> |
@@ -366,6 +367,7 @@ struct cpsw_priv { | |||
366 | spinlock_t lock; | 367 | spinlock_t lock; |
367 | struct platform_device *pdev; | 368 | struct platform_device *pdev; |
368 | struct net_device *ndev; | 369 | struct net_device *ndev; |
370 | struct device_node *phy_node; | ||
369 | struct napi_struct napi_rx; | 371 | struct napi_struct napi_rx; |
370 | struct napi_struct napi_tx; | 372 | struct napi_struct napi_tx; |
371 | struct device *dev; | 373 | struct device *dev; |
@@ -1146,7 +1148,11 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv) | |||
1146 | cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast, | 1148 | cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast, |
1147 | 1 << slave_port, 0, 0, ALE_MCAST_FWD_2); | 1149 | 1 << slave_port, 0, 0, ALE_MCAST_FWD_2); |
1148 | 1150 | ||
1149 | slave->phy = phy_connect(priv->ndev, slave->data->phy_id, | 1151 | if (priv->phy_node) |
1152 | slave->phy = of_phy_connect(priv->ndev, priv->phy_node, | ||
1153 | &cpsw_adjust_link, 0, slave->data->phy_if); | ||
1154 | else | ||
1155 | slave->phy = phy_connect(priv->ndev, slave->data->phy_id, | ||
1150 | &cpsw_adjust_link, slave->data->phy_if); | 1156 | &cpsw_adjust_link, slave->data->phy_if); |
1151 | if (IS_ERR(slave->phy)) { | 1157 | if (IS_ERR(slave->phy)) { |
1152 | dev_err(priv->dev, "phy %s not found on slave %d\n", | 1158 | dev_err(priv->dev, "phy %s not found on slave %d\n", |
@@ -1934,11 +1940,12 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv, | |||
1934 | slave->port_vlan = data->dual_emac_res_vlan; | 1940 | slave->port_vlan = data->dual_emac_res_vlan; |
1935 | } | 1941 | } |
1936 | 1942 | ||
1937 | static int cpsw_probe_dt(struct cpsw_platform_data *data, | 1943 | static int cpsw_probe_dt(struct cpsw_priv *priv, |
1938 | struct platform_device *pdev) | 1944 | struct platform_device *pdev) |
1939 | { | 1945 | { |
1940 | struct device_node *node = pdev->dev.of_node; | 1946 | struct device_node *node = pdev->dev.of_node; |
1941 | struct device_node *slave_node; | 1947 | struct device_node *slave_node; |
1948 | struct cpsw_platform_data *data = &priv->data; | ||
1942 | int i = 0, ret; | 1949 | int i = 0, ret; |
1943 | u32 prop; | 1950 | u32 prop; |
1944 | 1951 | ||
@@ -2029,6 +2036,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, | |||
2029 | if (strcmp(slave_node->name, "slave")) | 2036 | if (strcmp(slave_node->name, "slave")) |
2030 | continue; | 2037 | continue; |
2031 | 2038 | ||
2039 | priv->phy_node = of_parse_phandle(slave_node, "phy-handle", 0); | ||
2032 | parp = of_get_property(slave_node, "phy_id", &lenp); | 2040 | parp = of_get_property(slave_node, "phy_id", &lenp); |
2033 | if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) { | 2041 | if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) { |
2034 | dev_err(&pdev->dev, "Missing slave[%d] phy_id property\n", i); | 2042 | dev_err(&pdev->dev, "Missing slave[%d] phy_id property\n", i); |
@@ -2044,7 +2052,6 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, | |||
2044 | } | 2052 | } |
2045 | snprintf(slave_data->phy_id, sizeof(slave_data->phy_id), | 2053 | snprintf(slave_data->phy_id, sizeof(slave_data->phy_id), |
2046 | PHY_ID_FMT, mdio->name, phyid); | 2054 | PHY_ID_FMT, mdio->name, phyid); |
2047 | |||
2048 | slave_data->phy_if = of_get_phy_mode(slave_node); | 2055 | slave_data->phy_if = of_get_phy_mode(slave_node); |
2049 | if (slave_data->phy_if < 0) { | 2056 | if (slave_data->phy_if < 0) { |
2050 | dev_err(&pdev->dev, "Missing or malformed slave[%d] phy-mode property\n", | 2057 | dev_err(&pdev->dev, "Missing or malformed slave[%d] phy-mode property\n", |
@@ -2245,7 +2252,7 @@ static int cpsw_probe(struct platform_device *pdev) | |||
2245 | /* Select default pin state */ | 2252 | /* Select default pin state */ |
2246 | pinctrl_pm_select_default_state(&pdev->dev); | 2253 | pinctrl_pm_select_default_state(&pdev->dev); |
2247 | 2254 | ||
2248 | if (cpsw_probe_dt(&priv->data, pdev)) { | 2255 | if (cpsw_probe_dt(priv, pdev)) { |
2249 | dev_err(&pdev->dev, "cpsw: platform data missing\n"); | 2256 | dev_err(&pdev->dev, "cpsw: platform data missing\n"); |
2250 | ret = -ENODEV; | 2257 | ret = -ENODEV; |
2251 | goto clean_runtime_disable_ret; | 2258 | goto clean_runtime_disable_ret; |
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index cde29f8a37bf..445071c163cb 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c | |||
@@ -594,14 +594,12 @@ static struct rtable *geneve_get_rt(struct sk_buff *skb, | |||
594 | rt = ip_route_output_key(geneve->net, fl4); | 594 | rt = ip_route_output_key(geneve->net, fl4); |
595 | if (IS_ERR(rt)) { | 595 | if (IS_ERR(rt)) { |
596 | netdev_dbg(dev, "no route to %pI4\n", &fl4->daddr); | 596 | netdev_dbg(dev, "no route to %pI4\n", &fl4->daddr); |
597 | dev->stats.tx_carrier_errors++; | 597 | return ERR_PTR(-ENETUNREACH); |
598 | return rt; | ||
599 | } | 598 | } |
600 | if (rt->dst.dev == dev) { /* is this necessary? */ | 599 | if (rt->dst.dev == dev) { /* is this necessary? */ |
601 | netdev_dbg(dev, "circular route to %pI4\n", &fl4->daddr); | 600 | netdev_dbg(dev, "circular route to %pI4\n", &fl4->daddr); |
602 | dev->stats.collisions++; | ||
603 | ip_rt_put(rt); | 601 | ip_rt_put(rt); |
604 | return ERR_PTR(-EINVAL); | 602 | return ERR_PTR(-ELOOP); |
605 | } | 603 | } |
606 | return rt; | 604 | return rt; |
607 | } | 605 | } |
@@ -627,12 +625,12 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev) | |||
627 | struct ip_tunnel_info *info = NULL; | 625 | struct ip_tunnel_info *info = NULL; |
628 | struct rtable *rt = NULL; | 626 | struct rtable *rt = NULL; |
629 | const struct iphdr *iip; /* interior IP header */ | 627 | const struct iphdr *iip; /* interior IP header */ |
628 | int err = -EINVAL; | ||
630 | struct flowi4 fl4; | 629 | struct flowi4 fl4; |
631 | __u8 tos, ttl; | 630 | __u8 tos, ttl; |
632 | __be16 sport; | 631 | __be16 sport; |
633 | bool udp_csum; | 632 | bool udp_csum; |
634 | __be16 df; | 633 | __be16 df; |
635 | int err; | ||
636 | 634 | ||
637 | if (geneve->collect_md) { | 635 | if (geneve->collect_md) { |
638 | info = skb_tunnel_info(skb); | 636 | info = skb_tunnel_info(skb); |
@@ -647,7 +645,7 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev) | |||
647 | rt = geneve_get_rt(skb, dev, &fl4, info); | 645 | rt = geneve_get_rt(skb, dev, &fl4, info); |
648 | if (IS_ERR(rt)) { | 646 | if (IS_ERR(rt)) { |
649 | netdev_dbg(dev, "no route to %pI4\n", &fl4.daddr); | 647 | netdev_dbg(dev, "no route to %pI4\n", &fl4.daddr); |
650 | dev->stats.tx_carrier_errors++; | 648 | err = PTR_ERR(rt); |
651 | goto tx_error; | 649 | goto tx_error; |
652 | } | 650 | } |
653 | 651 | ||
@@ -699,10 +697,37 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev) | |||
699 | tx_error: | 697 | tx_error: |
700 | dev_kfree_skb(skb); | 698 | dev_kfree_skb(skb); |
701 | err: | 699 | err: |
702 | dev->stats.tx_errors++; | 700 | if (err == -ELOOP) |
701 | dev->stats.collisions++; | ||
702 | else if (err == -ENETUNREACH) | ||
703 | dev->stats.tx_carrier_errors++; | ||
704 | else | ||
705 | dev->stats.tx_errors++; | ||
703 | return NETDEV_TX_OK; | 706 | return NETDEV_TX_OK; |
704 | } | 707 | } |
705 | 708 | ||
709 | static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) | ||
710 | { | ||
711 | struct ip_tunnel_info *info = skb_tunnel_info(skb); | ||
712 | struct geneve_dev *geneve = netdev_priv(dev); | ||
713 | struct rtable *rt; | ||
714 | struct flowi4 fl4; | ||
715 | |||
716 | if (ip_tunnel_info_af(info) != AF_INET) | ||
717 | return -EINVAL; | ||
718 | |||
719 | rt = geneve_get_rt(skb, dev, &fl4, info); | ||
720 | if (IS_ERR(rt)) | ||
721 | return PTR_ERR(rt); | ||
722 | |||
723 | ip_rt_put(rt); | ||
724 | info->key.u.ipv4.src = fl4.saddr; | ||
725 | info->key.tp_src = udp_flow_src_port(geneve->net, skb, | ||
726 | 1, USHRT_MAX, true); | ||
727 | info->key.tp_dst = geneve->dst_port; | ||
728 | return 0; | ||
729 | } | ||
730 | |||
706 | static const struct net_device_ops geneve_netdev_ops = { | 731 | static const struct net_device_ops geneve_netdev_ops = { |
707 | .ndo_init = geneve_init, | 732 | .ndo_init = geneve_init, |
708 | .ndo_uninit = geneve_uninit, | 733 | .ndo_uninit = geneve_uninit, |
@@ -713,6 +738,7 @@ static const struct net_device_ops geneve_netdev_ops = { | |||
713 | .ndo_change_mtu = eth_change_mtu, | 738 | .ndo_change_mtu = eth_change_mtu, |
714 | .ndo_validate_addr = eth_validate_addr, | 739 | .ndo_validate_addr = eth_validate_addr, |
715 | .ndo_set_mac_address = eth_mac_addr, | 740 | .ndo_set_mac_address = eth_mac_addr, |
741 | .ndo_fill_metadata_dst = geneve_fill_metadata_dst, | ||
716 | }; | 742 | }; |
717 | 743 | ||
718 | static void geneve_get_drvinfo(struct net_device *dev, | 744 | static void geneve_get_drvinfo(struct net_device *dev, |
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 248478c6f6e4..197c93937c2d 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c | |||
@@ -137,7 +137,7 @@ static const struct proto_ops macvtap_socket_ops; | |||
137 | #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \ | 137 | #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \ |
138 | NETIF_F_TSO6 | NETIF_F_UFO) | 138 | NETIF_F_TSO6 | NETIF_F_UFO) |
139 | #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO) | 139 | #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO) |
140 | #define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG) | 140 | #define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG | NETIF_F_FRAGLIST) |
141 | 141 | ||
142 | static struct macvlan_dev *macvtap_get_vlan_rcu(const struct net_device *dev) | 142 | static struct macvlan_dev *macvtap_get_vlan_rcu(const struct net_device *dev) |
143 | { | 143 | { |
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index a7fb66580cee..60994a83a0d6 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig | |||
@@ -141,6 +141,11 @@ config MICREL_PHY | |||
141 | ---help--- | 141 | ---help--- |
142 | Supports the KSZ9021, VSC8201, KS8001 PHYs. | 142 | Supports the KSZ9021, VSC8201, KS8001 PHYs. |
143 | 143 | ||
144 | config DP83848_PHY | ||
145 | tristate "Driver for Texas Instruments DP83848 PHY" | ||
146 | ---help--- | ||
147 | Supports the DP83848 PHY. | ||
148 | |||
144 | config DP83867_PHY | 149 | config DP83867_PHY |
145 | tristate "Drivers for Texas Instruments DP83867 Gigabit PHY" | 150 | tristate "Drivers for Texas Instruments DP83867 Gigabit PHY" |
146 | ---help--- | 151 | ---help--- |
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 7655d47ad8d8..f31a4e25cf15 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile | |||
@@ -26,6 +26,7 @@ obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o | |||
26 | obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o | 26 | obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o |
27 | obj-$(CONFIG_NATIONAL_PHY) += national.o | 27 | obj-$(CONFIG_NATIONAL_PHY) += national.o |
28 | obj-$(CONFIG_DP83640_PHY) += dp83640.o | 28 | obj-$(CONFIG_DP83640_PHY) += dp83640.o |
29 | obj-$(CONFIG_DP83848_PHY) += dp83848.o | ||
29 | obj-$(CONFIG_DP83867_PHY) += dp83867.o | 30 | obj-$(CONFIG_DP83867_PHY) += dp83867.o |
30 | obj-$(CONFIG_STE10XP) += ste10Xp.o | 31 | obj-$(CONFIG_STE10XP) += ste10Xp.o |
31 | obj-$(CONFIG_MICREL_PHY) += micrel.o | 32 | obj-$(CONFIG_MICREL_PHY) += micrel.o |
diff --git a/drivers/net/phy/dp83848.c b/drivers/net/phy/dp83848.c new file mode 100644 index 000000000000..5ce9bef54468 --- /dev/null +++ b/drivers/net/phy/dp83848.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * Driver for the Texas Instruments DP83848 PHY | ||
3 | * | ||
4 | * Copyright (C) 2015 Texas Instruments Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/phy.h> | ||
18 | |||
19 | #define DP83848_PHY_ID 0x20005c90 | ||
20 | |||
21 | /* Registers */ | ||
22 | #define DP83848_MICR 0x11 | ||
23 | #define DP83848_MISR 0x12 | ||
24 | |||
25 | /* MICR Register Fields */ | ||
26 | #define DP83848_MICR_INT_OE BIT(0) /* Interrupt Output Enable */ | ||
27 | #define DP83848_MICR_INTEN BIT(1) /* Interrupt Enable */ | ||
28 | |||
29 | /* MISR Register Fields */ | ||
30 | #define DP83848_MISR_RHF_INT_EN BIT(0) /* Receive Error Counter */ | ||
31 | #define DP83848_MISR_FHF_INT_EN BIT(1) /* False Carrier Counter */ | ||
32 | #define DP83848_MISR_ANC_INT_EN BIT(2) /* Auto-negotiation complete */ | ||
33 | #define DP83848_MISR_DUP_INT_EN BIT(3) /* Duplex Status */ | ||
34 | #define DP83848_MISR_SPD_INT_EN BIT(4) /* Speed status */ | ||
35 | #define DP83848_MISR_LINK_INT_EN BIT(5) /* Link status */ | ||
36 | #define DP83848_MISR_ED_INT_EN BIT(6) /* Energy detect */ | ||
37 | #define DP83848_MISR_LQM_INT_EN BIT(7) /* Link Quality Monitor */ | ||
38 | |||
39 | static int dp83848_ack_interrupt(struct phy_device *phydev) | ||
40 | { | ||
41 | int err = phy_read(phydev, DP83848_MISR); | ||
42 | |||
43 | return err < 0 ? err : 0; | ||
44 | } | ||
45 | |||
46 | static int dp83848_config_intr(struct phy_device *phydev) | ||
47 | { | ||
48 | int err; | ||
49 | |||
50 | if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { | ||
51 | err = phy_write(phydev, DP83848_MICR, | ||
52 | DP83848_MICR_INT_OE | | ||
53 | DP83848_MICR_INTEN); | ||
54 | if (err < 0) | ||
55 | return err; | ||
56 | |||
57 | return phy_write(phydev, DP83848_MISR, | ||
58 | DP83848_MISR_ANC_INT_EN | | ||
59 | DP83848_MISR_DUP_INT_EN | | ||
60 | DP83848_MISR_SPD_INT_EN | | ||
61 | DP83848_MISR_LINK_INT_EN); | ||
62 | } | ||
63 | |||
64 | return phy_write(phydev, DP83848_MICR, 0x0); | ||
65 | } | ||
66 | |||
67 | static struct mdio_device_id __maybe_unused dp83848_tbl[] = { | ||
68 | { DP83848_PHY_ID, 0xfffffff0 }, | ||
69 | { } | ||
70 | }; | ||
71 | MODULE_DEVICE_TABLE(mdio, dp83848_tbl); | ||
72 | |||
73 | static struct phy_driver dp83848_driver[] = { | ||
74 | { | ||
75 | .phy_id = DP83848_PHY_ID, | ||
76 | .phy_id_mask = 0xfffffff0, | ||
77 | .name = "TI DP83848", | ||
78 | .features = PHY_BASIC_FEATURES, | ||
79 | .flags = PHY_HAS_INTERRUPT, | ||
80 | |||
81 | .soft_reset = genphy_soft_reset, | ||
82 | .config_init = genphy_config_init, | ||
83 | .suspend = genphy_suspend, | ||
84 | .resume = genphy_resume, | ||
85 | .config_aneg = genphy_config_aneg, | ||
86 | .read_status = genphy_read_status, | ||
87 | |||
88 | /* IRQ related */ | ||
89 | .ack_interrupt = dp83848_ack_interrupt, | ||
90 | .config_intr = dp83848_config_intr, | ||
91 | |||
92 | .driver = { .owner = THIS_MODULE, }, | ||
93 | }, | ||
94 | }; | ||
95 | module_phy_driver(dp83848_driver); | ||
96 | |||
97 | MODULE_DESCRIPTION("Texas Instruments DP83848 PHY driver"); | ||
98 | MODULE_AUTHOR("Andrew F. Davis <afd@ti.com"); | ||
99 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 499185eaf413..cf6312fafea5 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c | |||
@@ -514,6 +514,27 @@ static int ksz8873mll_read_status(struct phy_device *phydev) | |||
514 | return 0; | 514 | return 0; |
515 | } | 515 | } |
516 | 516 | ||
517 | static int ksz9031_read_status(struct phy_device *phydev) | ||
518 | { | ||
519 | int err; | ||
520 | int regval; | ||
521 | |||
522 | err = genphy_read_status(phydev); | ||
523 | if (err) | ||
524 | return err; | ||
525 | |||
526 | /* Make sure the PHY is not broken. Read idle error count, | ||
527 | * and reset the PHY if it is maxed out. | ||
528 | */ | ||
529 | regval = phy_read(phydev, MII_STAT1000); | ||
530 | if ((regval & 0xFF) == 0xFF) { | ||
531 | phy_init_hw(phydev); | ||
532 | phydev->link = 0; | ||
533 | } | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
517 | static int ksz8873mll_config_aneg(struct phy_device *phydev) | 538 | static int ksz8873mll_config_aneg(struct phy_device *phydev) |
518 | { | 539 | { |
519 | return 0; | 540 | return 0; |
@@ -772,7 +793,7 @@ static struct phy_driver ksphy_driver[] = { | |||
772 | .driver_data = &ksz9021_type, | 793 | .driver_data = &ksz9021_type, |
773 | .config_init = ksz9031_config_init, | 794 | .config_init = ksz9031_config_init, |
774 | .config_aneg = genphy_config_aneg, | 795 | .config_aneg = genphy_config_aneg, |
775 | .read_status = genphy_read_status, | 796 | .read_status = ksz9031_read_status, |
776 | .ack_interrupt = kszphy_ack_interrupt, | 797 | .ack_interrupt = kszphy_ack_interrupt, |
777 | .config_intr = kszphy_config_intr, | 798 | .config_intr = kszphy_config_intr, |
778 | .suspend = genphy_suspend, | 799 | .suspend = genphy_suspend, |
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index 70b08958763a..dc2da8770918 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c | |||
@@ -43,16 +43,25 @@ static int smsc_phy_ack_interrupt(struct phy_device *phydev) | |||
43 | 43 | ||
44 | static int smsc_phy_config_init(struct phy_device *phydev) | 44 | static int smsc_phy_config_init(struct phy_device *phydev) |
45 | { | 45 | { |
46 | int __maybe_unused len; | ||
47 | struct device *dev __maybe_unused = &phydev->dev; | ||
48 | struct device_node *of_node __maybe_unused = dev->of_node; | ||
46 | int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); | 49 | int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); |
50 | int enable_energy = 1; | ||
47 | 51 | ||
48 | if (rc < 0) | 52 | if (rc < 0) |
49 | return rc; | 53 | return rc; |
50 | 54 | ||
51 | /* Enable energy detect mode for this SMSC Transceivers */ | 55 | if (of_find_property(of_node, "smsc,disable-energy-detect", &len)) |
52 | rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, | 56 | enable_energy = 0; |
53 | rc | MII_LAN83C185_EDPWRDOWN); | 57 | |
54 | if (rc < 0) | 58 | if (enable_energy) { |
55 | return rc; | 59 | /* Enable energy detect mode for this SMSC Transceivers */ |
60 | rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, | ||
61 | rc | MII_LAN83C185_EDPWRDOWN); | ||
62 | if (rc < 0) | ||
63 | return rc; | ||
64 | } | ||
56 | 65 | ||
57 | return smsc_phy_ack_interrupt(phydev); | 66 | return smsc_phy_ack_interrupt(phydev); |
58 | } | 67 | } |
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index 2ed75060da50..5e0b43283bce 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c | |||
@@ -589,7 +589,7 @@ static int pppoe_release(struct socket *sock) | |||
589 | 589 | ||
590 | po = pppox_sk(sk); | 590 | po = pppox_sk(sk); |
591 | 591 | ||
592 | if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) { | 592 | if (po->pppoe_dev) { |
593 | dev_put(po->pppoe_dev); | 593 | dev_put(po->pppoe_dev); |
594 | po->pppoe_dev = NULL; | 594 | po->pppoe_dev = NULL; |
595 | } | 595 | } |
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 4752e69de00e..75ae756e93cf 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c | |||
@@ -711,6 +711,10 @@ static const struct usb_device_id products[] = { | |||
711 | {QMI_FIXED_INTF(0x1199, 0x9056, 8)}, /* Sierra Wireless Modem */ | 711 | {QMI_FIXED_INTF(0x1199, 0x9056, 8)}, /* Sierra Wireless Modem */ |
712 | {QMI_FIXED_INTF(0x1199, 0x9057, 8)}, | 712 | {QMI_FIXED_INTF(0x1199, 0x9057, 8)}, |
713 | {QMI_FIXED_INTF(0x1199, 0x9061, 8)}, /* Sierra Wireless Modem */ | 713 | {QMI_FIXED_INTF(0x1199, 0x9061, 8)}, /* Sierra Wireless Modem */ |
714 | {QMI_FIXED_INTF(0x1199, 0x9070, 8)}, /* Sierra Wireless MC74xx/EM74xx */ | ||
715 | {QMI_FIXED_INTF(0x1199, 0x9070, 10)}, /* Sierra Wireless MC74xx/EM74xx */ | ||
716 | {QMI_FIXED_INTF(0x1199, 0x9071, 8)}, /* Sierra Wireless MC74xx/EM74xx */ | ||
717 | {QMI_FIXED_INTF(0x1199, 0x9071, 10)}, /* Sierra Wireless MC74xx/EM74xx */ | ||
714 | {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ | 718 | {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ |
715 | {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)}, /* Alcatel L800MA */ | 719 | {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)}, /* Alcatel L800MA */ |
716 | {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ | 720 | {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ |
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index cf262ccf5047..6369a5734d4c 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
@@ -2360,6 +2360,46 @@ static int vxlan_change_mtu(struct net_device *dev, int new_mtu) | |||
2360 | return 0; | 2360 | return 0; |
2361 | } | 2361 | } |
2362 | 2362 | ||
2363 | static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb, | ||
2364 | struct ip_tunnel_info *info, | ||
2365 | __be16 sport, __be16 dport) | ||
2366 | { | ||
2367 | struct vxlan_dev *vxlan = netdev_priv(dev); | ||
2368 | struct rtable *rt; | ||
2369 | struct flowi4 fl4; | ||
2370 | |||
2371 | memset(&fl4, 0, sizeof(fl4)); | ||
2372 | fl4.flowi4_tos = RT_TOS(info->key.tos); | ||
2373 | fl4.flowi4_mark = skb->mark; | ||
2374 | fl4.flowi4_proto = IPPROTO_UDP; | ||
2375 | fl4.daddr = info->key.u.ipv4.dst; | ||
2376 | |||
2377 | rt = ip_route_output_key(vxlan->net, &fl4); | ||
2378 | if (IS_ERR(rt)) | ||
2379 | return PTR_ERR(rt); | ||
2380 | ip_rt_put(rt); | ||
2381 | |||
2382 | info->key.u.ipv4.src = fl4.saddr; | ||
2383 | info->key.tp_src = sport; | ||
2384 | info->key.tp_dst = dport; | ||
2385 | return 0; | ||
2386 | } | ||
2387 | |||
2388 | static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) | ||
2389 | { | ||
2390 | struct vxlan_dev *vxlan = netdev_priv(dev); | ||
2391 | struct ip_tunnel_info *info = skb_tunnel_info(skb); | ||
2392 | __be16 sport, dport; | ||
2393 | |||
2394 | sport = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min, | ||
2395 | vxlan->cfg.port_max, true); | ||
2396 | dport = info->key.tp_dst ? : vxlan->cfg.dst_port; | ||
2397 | |||
2398 | if (ip_tunnel_info_af(info) == AF_INET) | ||
2399 | return egress_ipv4_tun_info(dev, skb, info, sport, dport); | ||
2400 | return -EINVAL; | ||
2401 | } | ||
2402 | |||
2363 | static const struct net_device_ops vxlan_netdev_ops = { | 2403 | static const struct net_device_ops vxlan_netdev_ops = { |
2364 | .ndo_init = vxlan_init, | 2404 | .ndo_init = vxlan_init, |
2365 | .ndo_uninit = vxlan_uninit, | 2405 | .ndo_uninit = vxlan_uninit, |
@@ -2374,6 +2414,7 @@ static const struct net_device_ops vxlan_netdev_ops = { | |||
2374 | .ndo_fdb_add = vxlan_fdb_add, | 2414 | .ndo_fdb_add = vxlan_fdb_add, |
2375 | .ndo_fdb_del = vxlan_fdb_delete, | 2415 | .ndo_fdb_del = vxlan_fdb_delete, |
2376 | .ndo_fdb_dump = vxlan_fdb_dump, | 2416 | .ndo_fdb_dump = vxlan_fdb_dump, |
2417 | .ndo_fill_metadata_dst = vxlan_fill_metadata_dst, | ||
2377 | }; | 2418 | }; |
2378 | 2419 | ||
2379 | /* Info for udev, that this is a virtual tunnel endpoint */ | 2420 | /* Info for udev, that this is a virtual tunnel endpoint */ |
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 9bf63c27a9b7..441b158d04f7 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c | |||
@@ -1706,19 +1706,19 @@ static void xennet_destroy_queues(struct netfront_info *info) | |||
1706 | } | 1706 | } |
1707 | 1707 | ||
1708 | static int xennet_create_queues(struct netfront_info *info, | 1708 | static int xennet_create_queues(struct netfront_info *info, |
1709 | unsigned int num_queues) | 1709 | unsigned int *num_queues) |
1710 | { | 1710 | { |
1711 | unsigned int i; | 1711 | unsigned int i; |
1712 | int ret; | 1712 | int ret; |
1713 | 1713 | ||
1714 | info->queues = kcalloc(num_queues, sizeof(struct netfront_queue), | 1714 | info->queues = kcalloc(*num_queues, sizeof(struct netfront_queue), |
1715 | GFP_KERNEL); | 1715 | GFP_KERNEL); |
1716 | if (!info->queues) | 1716 | if (!info->queues) |
1717 | return -ENOMEM; | 1717 | return -ENOMEM; |
1718 | 1718 | ||
1719 | rtnl_lock(); | 1719 | rtnl_lock(); |
1720 | 1720 | ||
1721 | for (i = 0; i < num_queues; i++) { | 1721 | for (i = 0; i < *num_queues; i++) { |
1722 | struct netfront_queue *queue = &info->queues[i]; | 1722 | struct netfront_queue *queue = &info->queues[i]; |
1723 | 1723 | ||
1724 | queue->id = i; | 1724 | queue->id = i; |
@@ -1728,7 +1728,7 @@ static int xennet_create_queues(struct netfront_info *info, | |||
1728 | if (ret < 0) { | 1728 | if (ret < 0) { |
1729 | dev_warn(&info->netdev->dev, | 1729 | dev_warn(&info->netdev->dev, |
1730 | "only created %d queues\n", i); | 1730 | "only created %d queues\n", i); |
1731 | num_queues = i; | 1731 | *num_queues = i; |
1732 | break; | 1732 | break; |
1733 | } | 1733 | } |
1734 | 1734 | ||
@@ -1738,11 +1738,11 @@ static int xennet_create_queues(struct netfront_info *info, | |||
1738 | napi_enable(&queue->napi); | 1738 | napi_enable(&queue->napi); |
1739 | } | 1739 | } |
1740 | 1740 | ||
1741 | netif_set_real_num_tx_queues(info->netdev, num_queues); | 1741 | netif_set_real_num_tx_queues(info->netdev, *num_queues); |
1742 | 1742 | ||
1743 | rtnl_unlock(); | 1743 | rtnl_unlock(); |
1744 | 1744 | ||
1745 | if (num_queues == 0) { | 1745 | if (*num_queues == 0) { |
1746 | dev_err(&info->netdev->dev, "no queues\n"); | 1746 | dev_err(&info->netdev->dev, "no queues\n"); |
1747 | return -EINVAL; | 1747 | return -EINVAL; |
1748 | } | 1748 | } |
@@ -1788,7 +1788,7 @@ static int talk_to_netback(struct xenbus_device *dev, | |||
1788 | if (info->queues) | 1788 | if (info->queues) |
1789 | xennet_destroy_queues(info); | 1789 | xennet_destroy_queues(info); |
1790 | 1790 | ||
1791 | err = xennet_create_queues(info, num_queues); | 1791 | err = xennet_create_queues(info, &num_queues); |
1792 | if (err < 0) | 1792 | if (err < 0) |
1793 | goto destroy_ring; | 1793 | goto destroy_ring; |
1794 | 1794 | ||
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index dfaa7b3e9ae9..82c159e0532a 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h | |||
@@ -237,6 +237,10 @@ | |||
237 | #define KASAN_ABI_VERSION 3 | 237 | #define KASAN_ABI_VERSION 3 |
238 | #endif | 238 | #endif |
239 | 239 | ||
240 | #if GCC_VERSION >= 50000 | ||
241 | #define CC_HAVE_BUILTIN_OVERFLOW | ||
242 | #endif | ||
243 | |||
240 | #endif /* gcc version >= 40000 specific checks */ | 244 | #endif /* gcc version >= 40000 specific checks */ |
241 | 245 | ||
242 | #if !defined(__noclone) | 246 | #if !defined(__noclone) |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 773383859bd9..4ac653b7b8ac 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -1055,6 +1055,10 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev, | |||
1055 | * This function is used to pass protocol port error state information | 1055 | * This function is used to pass protocol port error state information |
1056 | * to the switch driver. The switch driver can react to the proto_down | 1056 | * to the switch driver. The switch driver can react to the proto_down |
1057 | * by doing a phys down on the associated switch port. | 1057 | * by doing a phys down on the associated switch port. |
1058 | * int (*ndo_fill_metadata_dst)(struct net_device *dev, struct sk_buff *skb); | ||
1059 | * This function is used to get egress tunnel information for given skb. | ||
1060 | * This is useful for retrieving outer tunnel header parameters while | ||
1061 | * sampling packet. | ||
1058 | * | 1062 | * |
1059 | */ | 1063 | */ |
1060 | struct net_device_ops { | 1064 | struct net_device_ops { |
@@ -1230,6 +1234,8 @@ struct net_device_ops { | |||
1230 | int (*ndo_get_iflink)(const struct net_device *dev); | 1234 | int (*ndo_get_iflink)(const struct net_device *dev); |
1231 | int (*ndo_change_proto_down)(struct net_device *dev, | 1235 | int (*ndo_change_proto_down)(struct net_device *dev, |
1232 | bool proto_down); | 1236 | bool proto_down); |
1237 | int (*ndo_fill_metadata_dst)(struct net_device *dev, | ||
1238 | struct sk_buff *skb); | ||
1233 | }; | 1239 | }; |
1234 | 1240 | ||
1235 | /** | 1241 | /** |
@@ -2210,6 +2216,7 @@ void dev_add_offload(struct packet_offload *po); | |||
2210 | void dev_remove_offload(struct packet_offload *po); | 2216 | void dev_remove_offload(struct packet_offload *po); |
2211 | 2217 | ||
2212 | int dev_get_iflink(const struct net_device *dev); | 2218 | int dev_get_iflink(const struct net_device *dev); |
2219 | int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb); | ||
2213 | struct net_device *__dev_get_by_flags(struct net *net, unsigned short flags, | 2220 | struct net_device *__dev_get_by_flags(struct net *net, unsigned short flags, |
2214 | unsigned short mask); | 2221 | unsigned short mask); |
2215 | struct net_device *dev_get_by_name(struct net *net, const char *name); | 2222 | struct net_device *dev_get_by_name(struct net *net, const char *name); |
diff --git a/include/linux/overflow-arith.h b/include/linux/overflow-arith.h new file mode 100644 index 000000000000..e12ccf854a70 --- /dev/null +++ b/include/linux/overflow-arith.h | |||
@@ -0,0 +1,18 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <linux/kernel.h> | ||
4 | |||
5 | #ifdef CC_HAVE_BUILTIN_OVERFLOW | ||
6 | |||
7 | #define overflow_usub __builtin_usub_overflow | ||
8 | |||
9 | #else | ||
10 | |||
11 | static inline bool overflow_usub(unsigned int a, unsigned int b, | ||
12 | unsigned int *res) | ||
13 | { | ||
14 | *res = a - b; | ||
15 | return *res > a ? true : false; | ||
16 | } | ||
17 | |||
18 | #endif | ||
diff --git a/include/net/dst_metadata.h b/include/net/dst_metadata.h index af9d5382f6cb..ce009710120c 100644 --- a/include/net/dst_metadata.h +++ b/include/net/dst_metadata.h | |||
@@ -60,6 +60,38 @@ static inline struct metadata_dst *tun_rx_dst(int md_size) | |||
60 | return tun_dst; | 60 | return tun_dst; |
61 | } | 61 | } |
62 | 62 | ||
63 | static inline struct metadata_dst *tun_dst_unclone(struct sk_buff *skb) | ||
64 | { | ||
65 | struct metadata_dst *md_dst = skb_metadata_dst(skb); | ||
66 | int md_size = md_dst->u.tun_info.options_len; | ||
67 | struct metadata_dst *new_md; | ||
68 | |||
69 | if (!md_dst) | ||
70 | return ERR_PTR(-EINVAL); | ||
71 | |||
72 | new_md = metadata_dst_alloc(md_size, GFP_ATOMIC); | ||
73 | if (!new_md) | ||
74 | return ERR_PTR(-ENOMEM); | ||
75 | |||
76 | memcpy(&new_md->u.tun_info, &md_dst->u.tun_info, | ||
77 | sizeof(struct ip_tunnel_info) + md_size); | ||
78 | skb_dst_drop(skb); | ||
79 | dst_hold(&new_md->dst); | ||
80 | skb_dst_set(skb, &new_md->dst); | ||
81 | return new_md; | ||
82 | } | ||
83 | |||
84 | static inline struct ip_tunnel_info *skb_tunnel_info_unclone(struct sk_buff *skb) | ||
85 | { | ||
86 | struct metadata_dst *dst; | ||
87 | |||
88 | dst = tun_dst_unclone(skb); | ||
89 | if (IS_ERR(dst)) | ||
90 | return NULL; | ||
91 | |||
92 | return &dst->u.tun_info; | ||
93 | } | ||
94 | |||
63 | static inline struct metadata_dst *ip_tun_rx_dst(struct sk_buff *skb, | 95 | static inline struct metadata_dst *ip_tun_rx_dst(struct sk_buff *skb, |
64 | __be16 flags, | 96 | __be16 flags, |
65 | __be64 tunnel_id, | 97 | __be64 tunnel_id, |
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h index fef125e2d777..28ccedd000f5 100644 --- a/include/uapi/linux/openvswitch.h +++ b/include/uapi/linux/openvswitch.h | |||
@@ -622,7 +622,8 @@ struct ovs_action_hash { | |||
622 | * enum ovs_ct_attr - Attributes for %OVS_ACTION_ATTR_CT action. | 622 | * enum ovs_ct_attr - Attributes for %OVS_ACTION_ATTR_CT action. |
623 | * @OVS_CT_ATTR_COMMIT: If present, commits the connection to the conntrack | 623 | * @OVS_CT_ATTR_COMMIT: If present, commits the connection to the conntrack |
624 | * table. This allows future packets for the same connection to be identified | 624 | * table. This allows future packets for the same connection to be identified |
625 | * as 'established' or 'related'. | 625 | * as 'established' or 'related'. The flow key for the current packet will |
626 | * retain the pre-commit connection state. | ||
626 | * @OVS_CT_ATTR_ZONE: u16 connection tracking zone. | 627 | * @OVS_CT_ATTR_ZONE: u16 connection tracking zone. |
627 | * @OVS_CT_ATTR_MARK: u32 value followed by u32 mask. For each bit set in the | 628 | * @OVS_CT_ATTR_MARK: u32 value followed by u32 mask. For each bit set in the |
628 | * mask, the corresponding bit in the value is copied to the connection | 629 | * mask, the corresponding bit in the value is copied to the connection |
diff --git a/net/core/dev.c b/net/core/dev.c index 1225b4be8ed6..13f49f81ae13 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -99,6 +99,7 @@ | |||
99 | #include <linux/rtnetlink.h> | 99 | #include <linux/rtnetlink.h> |
100 | #include <linux/stat.h> | 100 | #include <linux/stat.h> |
101 | #include <net/dst.h> | 101 | #include <net/dst.h> |
102 | #include <net/dst_metadata.h> | ||
102 | #include <net/pkt_sched.h> | 103 | #include <net/pkt_sched.h> |
103 | #include <net/checksum.h> | 104 | #include <net/checksum.h> |
104 | #include <net/xfrm.h> | 105 | #include <net/xfrm.h> |
@@ -682,6 +683,32 @@ int dev_get_iflink(const struct net_device *dev) | |||
682 | EXPORT_SYMBOL(dev_get_iflink); | 683 | EXPORT_SYMBOL(dev_get_iflink); |
683 | 684 | ||
684 | /** | 685 | /** |
686 | * dev_fill_metadata_dst - Retrieve tunnel egress information. | ||
687 | * @dev: targeted interface | ||
688 | * @skb: The packet. | ||
689 | * | ||
690 | * For better visibility of tunnel traffic OVS needs to retrieve | ||
691 | * egress tunnel information for a packet. Following API allows | ||
692 | * user to get this info. | ||
693 | */ | ||
694 | int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) | ||
695 | { | ||
696 | struct ip_tunnel_info *info; | ||
697 | |||
698 | if (!dev->netdev_ops || !dev->netdev_ops->ndo_fill_metadata_dst) | ||
699 | return -EINVAL; | ||
700 | |||
701 | info = skb_tunnel_info_unclone(skb); | ||
702 | if (!info) | ||
703 | return -ENOMEM; | ||
704 | if (unlikely(!(info->mode & IP_TUNNEL_INFO_TX))) | ||
705 | return -EINVAL; | ||
706 | |||
707 | return dev->netdev_ops->ndo_fill_metadata_dst(dev, skb); | ||
708 | } | ||
709 | EXPORT_SYMBOL_GPL(dev_fill_metadata_dst); | ||
710 | |||
711 | /** | ||
685 | * __dev_get_by_name - find a device by its name | 712 | * __dev_get_by_name - find a device by its name |
686 | * @net: the applicable net namespace | 713 | * @net: the applicable net namespace |
687 | * @name: name to find | 714 | * @name: name to find |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index bd0679d90519..614521437e30 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -498,10 +498,26 @@ static struct sk_buff *gre_handle_offloads(struct sk_buff *skb, | |||
498 | csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE); | 498 | csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE); |
499 | } | 499 | } |
500 | 500 | ||
501 | static struct rtable *gre_get_rt(struct sk_buff *skb, | ||
502 | struct net_device *dev, | ||
503 | struct flowi4 *fl, | ||
504 | const struct ip_tunnel_key *key) | ||
505 | { | ||
506 | struct net *net = dev_net(dev); | ||
507 | |||
508 | memset(fl, 0, sizeof(*fl)); | ||
509 | fl->daddr = key->u.ipv4.dst; | ||
510 | fl->saddr = key->u.ipv4.src; | ||
511 | fl->flowi4_tos = RT_TOS(key->tos); | ||
512 | fl->flowi4_mark = skb->mark; | ||
513 | fl->flowi4_proto = IPPROTO_GRE; | ||
514 | |||
515 | return ip_route_output_key(net, fl); | ||
516 | } | ||
517 | |||
501 | static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev) | 518 | static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev) |
502 | { | 519 | { |
503 | struct ip_tunnel_info *tun_info; | 520 | struct ip_tunnel_info *tun_info; |
504 | struct net *net = dev_net(dev); | ||
505 | const struct ip_tunnel_key *key; | 521 | const struct ip_tunnel_key *key; |
506 | struct flowi4 fl; | 522 | struct flowi4 fl; |
507 | struct rtable *rt; | 523 | struct rtable *rt; |
@@ -516,14 +532,7 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev) | |||
516 | goto err_free_skb; | 532 | goto err_free_skb; |
517 | 533 | ||
518 | key = &tun_info->key; | 534 | key = &tun_info->key; |
519 | memset(&fl, 0, sizeof(fl)); | 535 | rt = gre_get_rt(skb, dev, &fl, key); |
520 | fl.daddr = key->u.ipv4.dst; | ||
521 | fl.saddr = key->u.ipv4.src; | ||
522 | fl.flowi4_tos = RT_TOS(key->tos); | ||
523 | fl.flowi4_mark = skb->mark; | ||
524 | fl.flowi4_proto = IPPROTO_GRE; | ||
525 | |||
526 | rt = ip_route_output_key(net, &fl); | ||
527 | if (IS_ERR(rt)) | 536 | if (IS_ERR(rt)) |
528 | goto err_free_skb; | 537 | goto err_free_skb; |
529 | 538 | ||
@@ -566,6 +575,24 @@ err_free_skb: | |||
566 | dev->stats.tx_dropped++; | 575 | dev->stats.tx_dropped++; |
567 | } | 576 | } |
568 | 577 | ||
578 | static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) | ||
579 | { | ||
580 | struct ip_tunnel_info *info = skb_tunnel_info(skb); | ||
581 | struct rtable *rt; | ||
582 | struct flowi4 fl4; | ||
583 | |||
584 | if (ip_tunnel_info_af(info) != AF_INET) | ||
585 | return -EINVAL; | ||
586 | |||
587 | rt = gre_get_rt(skb, dev, &fl4, &info->key); | ||
588 | if (IS_ERR(rt)) | ||
589 | return PTR_ERR(rt); | ||
590 | |||
591 | ip_rt_put(rt); | ||
592 | info->key.u.ipv4.src = fl4.saddr; | ||
593 | return 0; | ||
594 | } | ||
595 | |||
569 | static netdev_tx_t ipgre_xmit(struct sk_buff *skb, | 596 | static netdev_tx_t ipgre_xmit(struct sk_buff *skb, |
570 | struct net_device *dev) | 597 | struct net_device *dev) |
571 | { | 598 | { |
@@ -1023,6 +1050,7 @@ static const struct net_device_ops gre_tap_netdev_ops = { | |||
1023 | .ndo_change_mtu = ip_tunnel_change_mtu, | 1050 | .ndo_change_mtu = ip_tunnel_change_mtu, |
1024 | .ndo_get_stats64 = ip_tunnel_get_stats64, | 1051 | .ndo_get_stats64 = ip_tunnel_get_stats64, |
1025 | .ndo_get_iflink = ip_tunnel_get_iflink, | 1052 | .ndo_get_iflink = ip_tunnel_get_iflink, |
1053 | .ndo_fill_metadata_dst = gre_fill_metadata_dst, | ||
1026 | }; | 1054 | }; |
1027 | 1055 | ||
1028 | static void ipgre_tap_setup(struct net_device *dev) | 1056 | static void ipgre_tap_setup(struct net_device *dev) |
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 690d27d3f2f9..a35584176535 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -75,6 +75,7 @@ endif # NF_TABLES | |||
75 | 75 | ||
76 | config NF_DUP_IPV4 | 76 | config NF_DUP_IPV4 |
77 | tristate "Netfilter IPv4 packet duplication to alternate destination" | 77 | tristate "Netfilter IPv4 packet duplication to alternate destination" |
78 | depends on !NF_CONNTRACK || NF_CONNTRACK | ||
78 | help | 79 | help |
79 | This option enables the nf_dup_ipv4 core, which duplicates an IPv4 | 80 | This option enables the nf_dup_ipv4 core, which duplicates an IPv4 |
80 | packet to be rerouted to another destination. | 81 | packet to be rerouted to another destination. |
diff --git a/net/ipv4/netfilter/ipt_rpfilter.c b/net/ipv4/netfilter/ipt_rpfilter.c index 74dd6671b66d..78cc64eddfc1 100644 --- a/net/ipv4/netfilter/ipt_rpfilter.c +++ b/net/ipv4/netfilter/ipt_rpfilter.c | |||
@@ -60,9 +60,7 @@ static bool rpfilter_lookup_reverse(struct net *net, struct flowi4 *fl4, | |||
60 | if (FIB_RES_DEV(res) == dev) | 60 | if (FIB_RES_DEV(res) == dev) |
61 | dev_match = true; | 61 | dev_match = true; |
62 | #endif | 62 | #endif |
63 | if (dev_match || flags & XT_RPFILTER_LOOSE) | 63 | return dev_match || flags & XT_RPFILTER_LOOSE; |
64 | return FIB_RES_NH(res).nh_scope <= RT_SCOPE_HOST; | ||
65 | return dev_match; | ||
66 | } | 64 | } |
67 | 65 | ||
68 | static bool rpfilter_is_local(const struct sk_buff *skb) | 66 | static bool rpfilter_is_local(const struct sk_buff *skb) |
diff --git a/net/ipv4/tcp_dctcp.c b/net/ipv4/tcp_dctcp.c index 7092a61c4dc8..7e538f71f5fb 100644 --- a/net/ipv4/tcp_dctcp.c +++ b/net/ipv4/tcp_dctcp.c | |||
@@ -209,7 +209,7 @@ static void dctcp_update_alpha(struct sock *sk, u32 flags) | |||
209 | 209 | ||
210 | /* alpha = (1 - g) * alpha + g * F */ | 210 | /* alpha = (1 - g) * alpha + g * F */ |
211 | 211 | ||
212 | alpha -= alpha >> dctcp_shift_g; | 212 | alpha -= min_not_zero(alpha, alpha >> dctcp_shift_g); |
213 | if (bytes_ecn) { | 213 | if (bytes_ecn) { |
214 | /* If dctcp_shift_g == 1, a 32bit value would overflow | 214 | /* If dctcp_shift_g == 1, a 32bit value would overflow |
215 | * after 8 Mbytes. | 215 | * after 8 Mbytes. |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index f6f7f9b4901b..f4f9793eb025 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -3410,7 +3410,7 @@ static int tcp_xmit_probe_skb(struct sock *sk, int urgent, int mib) | |||
3410 | */ | 3410 | */ |
3411 | tcp_init_nondata_skb(skb, tp->snd_una - !urgent, TCPHDR_ACK); | 3411 | tcp_init_nondata_skb(skb, tp->snd_una - !urgent, TCPHDR_ACK); |
3412 | skb_mstamp_get(&skb->skb_mstamp); | 3412 | skb_mstamp_get(&skb->skb_mstamp); |
3413 | NET_INC_STATS_BH(sock_net(sk), mib); | 3413 | NET_INC_STATS(sock_net(sk), mib); |
3414 | return tcp_transmit_skb(sk, skb, 0, GFP_ATOMIC); | 3414 | return tcp_transmit_skb(sk, skb, 0, GFP_ATOMIC); |
3415 | } | 3415 | } |
3416 | 3416 | ||
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 9f298d0dc9a1..7ee6518afa86 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c | |||
@@ -30,6 +30,8 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb) | |||
30 | 30 | ||
31 | mtu = dst_mtu(skb_dst(skb)); | 31 | mtu = dst_mtu(skb_dst(skb)); |
32 | if (skb->len > mtu) { | 32 | if (skb->len > mtu) { |
33 | skb->protocol = htons(ETH_P_IP); | ||
34 | |||
33 | if (skb->sk) | 35 | if (skb->sk) |
34 | xfrm_local_error(skb, mtu); | 36 | xfrm_local_error(skb, mtu); |
35 | else | 37 | else |
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 9f777ec59a59..ed33abf57abd 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -32,6 +32,7 @@ struct fib6_rule { | |||
32 | struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, | 32 | struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, |
33 | int flags, pol_lookup_t lookup) | 33 | int flags, pol_lookup_t lookup) |
34 | { | 34 | { |
35 | struct rt6_info *rt; | ||
35 | struct fib_lookup_arg arg = { | 36 | struct fib_lookup_arg arg = { |
36 | .lookup_ptr = lookup, | 37 | .lookup_ptr = lookup, |
37 | .flags = FIB_LOOKUP_NOREF, | 38 | .flags = FIB_LOOKUP_NOREF, |
@@ -40,11 +41,21 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, | |||
40 | fib_rules_lookup(net->ipv6.fib6_rules_ops, | 41 | fib_rules_lookup(net->ipv6.fib6_rules_ops, |
41 | flowi6_to_flowi(fl6), flags, &arg); | 42 | flowi6_to_flowi(fl6), flags, &arg); |
42 | 43 | ||
43 | if (arg.result) | 44 | rt = arg.result; |
44 | return arg.result; | ||
45 | 45 | ||
46 | dst_hold(&net->ipv6.ip6_null_entry->dst); | 46 | if (!rt) { |
47 | return &net->ipv6.ip6_null_entry->dst; | 47 | dst_hold(&net->ipv6.ip6_null_entry->dst); |
48 | return &net->ipv6.ip6_null_entry->dst; | ||
49 | } | ||
50 | |||
51 | if (rt->rt6i_flags & RTF_REJECT && | ||
52 | rt->dst.error == -EAGAIN) { | ||
53 | ip6_rt_put(rt); | ||
54 | rt = net->ipv6.ip6_null_entry; | ||
55 | dst_hold(&rt->dst); | ||
56 | } | ||
57 | |||
58 | return &rt->dst; | ||
48 | } | 59 | } |
49 | 60 | ||
50 | static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | 61 | static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 09fddf70cca4..0c7e276c230e 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -286,7 +286,17 @@ struct fib6_table *fib6_get_table(struct net *net, u32 id) | |||
286 | struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, | 286 | struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, |
287 | int flags, pol_lookup_t lookup) | 287 | int flags, pol_lookup_t lookup) |
288 | { | 288 | { |
289 | return (struct dst_entry *) lookup(net, net->ipv6.fib6_main_tbl, fl6, flags); | 289 | struct rt6_info *rt; |
290 | |||
291 | rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, flags); | ||
292 | if (rt->rt6i_flags & RTF_REJECT && | ||
293 | rt->dst.error == -EAGAIN) { | ||
294 | ip6_rt_put(rt); | ||
295 | rt = net->ipv6.ip6_null_entry; | ||
296 | dst_hold(&rt->dst); | ||
297 | } | ||
298 | |||
299 | return &rt->dst; | ||
290 | } | 300 | } |
291 | 301 | ||
292 | static void __net_init fib6_tables_init(struct net *net) | 302 | static void __net_init fib6_tables_init(struct net *net) |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 0c89671e0767..c2650688aca7 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -28,6 +28,7 @@ | |||
28 | 28 | ||
29 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/overflow-arith.h> | ||
31 | #include <linux/string.h> | 32 | #include <linux/string.h> |
32 | #include <linux/socket.h> | 33 | #include <linux/socket.h> |
33 | #include <linux/net.h> | 34 | #include <linux/net.h> |
@@ -596,7 +597,10 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, | |||
596 | if (np->frag_size) | 597 | if (np->frag_size) |
597 | mtu = np->frag_size; | 598 | mtu = np->frag_size; |
598 | } | 599 | } |
599 | mtu -= hlen + sizeof(struct frag_hdr); | 600 | |
601 | if (overflow_usub(mtu, hlen + sizeof(struct frag_hdr), &mtu) || | ||
602 | mtu <= 7) | ||
603 | goto fail_toobig; | ||
600 | 604 | ||
601 | frag_id = ipv6_select_ident(net, &ipv6_hdr(skb)->daddr, | 605 | frag_id = ipv6_select_ident(net, &ipv6_hdr(skb)->daddr, |
602 | &ipv6_hdr(skb)->saddr); | 606 | &ipv6_hdr(skb)->saddr); |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 96833e4b3193..f6a024e141e5 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -58,6 +58,7 @@ endif # NF_TABLES | |||
58 | 58 | ||
59 | config NF_DUP_IPV6 | 59 | config NF_DUP_IPV6 |
60 | tristate "Netfilter IPv6 packet duplication to alternate destination" | 60 | tristate "Netfilter IPv6 packet duplication to alternate destination" |
61 | depends on !NF_CONNTRACK || NF_CONNTRACK | ||
61 | help | 62 | help |
62 | This option enables the nf_dup_ipv6 core, which duplicates an IPv6 | 63 | This option enables the nf_dup_ipv6 core, which duplicates an IPv6 |
63 | packet to be rerouted to another destination. | 64 | packet to be rerouted to another destination. |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index d0619632723a..2701cb3d88e9 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -1171,6 +1171,7 @@ struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk, | |||
1171 | { | 1171 | { |
1172 | struct dst_entry *dst; | 1172 | struct dst_entry *dst; |
1173 | int flags = 0; | 1173 | int flags = 0; |
1174 | bool any_src; | ||
1174 | 1175 | ||
1175 | dst = l3mdev_rt6_dst_by_oif(net, fl6); | 1176 | dst = l3mdev_rt6_dst_by_oif(net, fl6); |
1176 | if (dst) | 1177 | if (dst) |
@@ -1178,11 +1179,12 @@ struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk, | |||
1178 | 1179 | ||
1179 | fl6->flowi6_iif = LOOPBACK_IFINDEX; | 1180 | fl6->flowi6_iif = LOOPBACK_IFINDEX; |
1180 | 1181 | ||
1182 | any_src = ipv6_addr_any(&fl6->saddr); | ||
1181 | if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr) || | 1183 | if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr) || |
1182 | fl6->flowi6_oif) | 1184 | (fl6->flowi6_oif && any_src)) |
1183 | flags |= RT6_LOOKUP_F_IFACE; | 1185 | flags |= RT6_LOOKUP_F_IFACE; |
1184 | 1186 | ||
1185 | if (!ipv6_addr_any(&fl6->saddr)) | 1187 | if (!any_src) |
1186 | flags |= RT6_LOOKUP_F_HAS_SADDR; | 1188 | flags |= RT6_LOOKUP_F_HAS_SADDR; |
1187 | else if (sk) | 1189 | else if (sk) |
1188 | flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs); | 1190 | flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs); |
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 9db067a11b52..4d09ce6fa90e 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
@@ -79,6 +79,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) | |||
79 | 79 | ||
80 | if (!skb->ignore_df && skb->len > mtu) { | 80 | if (!skb->ignore_df && skb->len > mtu) { |
81 | skb->dev = dst->dev; | 81 | skb->dev = dst->dev; |
82 | skb->protocol = htons(ETH_P_IPV6); | ||
82 | 83 | ||
83 | if (xfrm6_local_dontfrag(skb)) | 84 | if (xfrm6_local_dontfrag(skb)) |
84 | xfrm6_local_rxpmtu(skb, mtu); | 85 | xfrm6_local_rxpmtu(skb, mtu); |
@@ -143,6 +144,7 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb) | |||
143 | struct dst_entry *dst = skb_dst(skb); | 144 | struct dst_entry *dst = skb_dst(skb); |
144 | struct xfrm_state *x = dst->xfrm; | 145 | struct xfrm_state *x = dst->xfrm; |
145 | int mtu; | 146 | int mtu; |
147 | bool toobig; | ||
146 | 148 | ||
147 | #ifdef CONFIG_NETFILTER | 149 | #ifdef CONFIG_NETFILTER |
148 | if (!x) { | 150 | if (!x) { |
@@ -151,25 +153,29 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb) | |||
151 | } | 153 | } |
152 | #endif | 154 | #endif |
153 | 155 | ||
156 | if (x->props.mode != XFRM_MODE_TUNNEL) | ||
157 | goto skip_frag; | ||
158 | |||
154 | if (skb->protocol == htons(ETH_P_IPV6)) | 159 | if (skb->protocol == htons(ETH_P_IPV6)) |
155 | mtu = ip6_skb_dst_mtu(skb); | 160 | mtu = ip6_skb_dst_mtu(skb); |
156 | else | 161 | else |
157 | mtu = dst_mtu(skb_dst(skb)); | 162 | mtu = dst_mtu(skb_dst(skb)); |
158 | 163 | ||
159 | if (skb->len > mtu && xfrm6_local_dontfrag(skb)) { | 164 | toobig = skb->len > mtu && !skb_is_gso(skb); |
165 | |||
166 | if (toobig && xfrm6_local_dontfrag(skb)) { | ||
160 | xfrm6_local_rxpmtu(skb, mtu); | 167 | xfrm6_local_rxpmtu(skb, mtu); |
161 | return -EMSGSIZE; | 168 | return -EMSGSIZE; |
162 | } else if (!skb->ignore_df && skb->len > mtu && skb->sk) { | 169 | } else if (!skb->ignore_df && toobig && skb->sk) { |
163 | xfrm_local_error(skb, mtu); | 170 | xfrm_local_error(skb, mtu); |
164 | return -EMSGSIZE; | 171 | return -EMSGSIZE; |
165 | } | 172 | } |
166 | 173 | ||
167 | if (x->props.mode == XFRM_MODE_TUNNEL && | 174 | if (toobig || dst_allfrag(skb_dst(skb))) |
168 | ((skb->len > mtu && !skb_is_gso(skb)) || | ||
169 | dst_allfrag(skb_dst(skb)))) { | ||
170 | return ip6_fragment(net, sk, skb, | 175 | return ip6_fragment(net, sk, skb, |
171 | __xfrm6_output_finish); | 176 | __xfrm6_output_finish); |
172 | } | 177 | |
178 | skip_frag: | ||
173 | return x->outer_mode->afinfo->output_finish(sk, skb); | 179 | return x->outer_mode->afinfo->output_finish(sk, skb); |
174 | } | 180 | } |
175 | 181 | ||
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 08c9c93f3527..2cc5840f943d 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -177,7 +177,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
177 | return; | 177 | return; |
178 | 178 | ||
179 | case IPPROTO_ICMPV6: | 179 | case IPPROTO_ICMPV6: |
180 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 2 - skb->data)) { | 180 | if (!onlyproto && (nh + offset + 2 < skb->data || |
181 | pskb_may_pull(skb, nh + offset + 2 - skb->data))) { | ||
181 | u8 *icmp; | 182 | u8 *icmp; |
182 | 183 | ||
183 | nh = skb_network_header(skb); | 184 | nh = skb_network_header(skb); |
@@ -191,7 +192,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
191 | #if IS_ENABLED(CONFIG_IPV6_MIP6) | 192 | #if IS_ENABLED(CONFIG_IPV6_MIP6) |
192 | case IPPROTO_MH: | 193 | case IPPROTO_MH: |
193 | offset += ipv6_optlen(exthdr); | 194 | offset += ipv6_optlen(exthdr); |
194 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) { | 195 | if (!onlyproto && (nh + offset + 3 < skb->data || |
196 | pskb_may_pull(skb, nh + offset + 3 - skb->data))) { | ||
195 | struct ip6_mh *mh; | 197 | struct ip6_mh *mh; |
196 | 198 | ||
197 | nh = skb_network_header(skb); | 199 | nh = skb_network_header(skb); |
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c index a26c401ef4a4..43964594aa12 100644 --- a/net/irda/irlmp.c +++ b/net/irda/irlmp.c | |||
@@ -1839,7 +1839,7 @@ static void *irlmp_seq_hb_idx(struct irlmp_iter_state *iter, loff_t *off) | |||
1839 | for (element = hashbin_get_first(iter->hashbin); | 1839 | for (element = hashbin_get_first(iter->hashbin); |
1840 | element != NULL; | 1840 | element != NULL; |
1841 | element = hashbin_get_next(iter->hashbin)) { | 1841 | element = hashbin_get_next(iter->hashbin)) { |
1842 | if (!off || *off-- == 0) { | 1842 | if (!off || (*off)-- == 0) { |
1843 | /* NB: hashbin left locked */ | 1843 | /* NB: hashbin left locked */ |
1844 | return element; | 1844 | return element; |
1845 | } | 1845 | } |
diff --git a/net/key/af_key.c b/net/key/af_key.c index 83a70688784b..f9c9ecb0cdd3 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -261,7 +261,7 @@ static int pfkey_broadcast(struct sk_buff *skb, | |||
261 | 261 | ||
262 | err2 = pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk); | 262 | err2 = pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk); |
263 | 263 | ||
264 | /* Error is cleare after succecful sending to at least one | 264 | /* Error is cleared after successful sending to at least one |
265 | * registered KM */ | 265 | * registered KM */ |
266 | if ((broadcast_flags & BROADCAST_REGISTERED) && err) | 266 | if ((broadcast_flags & BROADCAST_REGISTERED) && err) |
267 | err = err2; | 267 | err = err2; |
diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 09e661c3ae58..f39276d1c2d7 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c | |||
@@ -152,6 +152,8 @@ void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg) | |||
152 | #endif | 152 | #endif |
153 | synchronize_net(); | 153 | synchronize_net(); |
154 | nf_queue_nf_hook_drop(net, &entry->ops); | 154 | nf_queue_nf_hook_drop(net, &entry->ops); |
155 | /* other cpu might still process nfqueue verdict that used reg */ | ||
156 | synchronize_net(); | ||
155 | kfree(entry); | 157 | kfree(entry); |
156 | } | 158 | } |
157 | EXPORT_SYMBOL(nf_unregister_net_hook); | 159 | EXPORT_SYMBOL(nf_unregister_net_hook); |
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c index a1fe5377a2b3..5a30ce6e8c90 100644 --- a/net/netfilter/ipset/ip_set_list_set.c +++ b/net/netfilter/ipset/ip_set_list_set.c | |||
@@ -297,7 +297,7 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext, | |||
297 | ip_set_timeout_expired(ext_timeout(n, set)))) | 297 | ip_set_timeout_expired(ext_timeout(n, set)))) |
298 | n = NULL; | 298 | n = NULL; |
299 | 299 | ||
300 | e = kzalloc(set->dsize, GFP_KERNEL); | 300 | e = kzalloc(set->dsize, GFP_ATOMIC); |
301 | if (!e) | 301 | if (!e) |
302 | return -ENOMEM; | 302 | return -ENOMEM; |
303 | e->id = d->id; | 303 | e->id = d->id; |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 0a49a8c7c564..fafe33bdb619 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -2371,7 +2371,7 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname, | |||
2371 | int pos, idx, shift; | 2371 | int pos, idx, shift; |
2372 | 2372 | ||
2373 | err = 0; | 2373 | err = 0; |
2374 | netlink_table_grab(); | 2374 | netlink_lock_table(); |
2375 | for (pos = 0; pos * 8 < nlk->ngroups; pos += sizeof(u32)) { | 2375 | for (pos = 0; pos * 8 < nlk->ngroups; pos += sizeof(u32)) { |
2376 | if (len - pos < sizeof(u32)) | 2376 | if (len - pos < sizeof(u32)) |
2377 | break; | 2377 | break; |
@@ -2386,7 +2386,7 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname, | |||
2386 | } | 2386 | } |
2387 | if (put_user(ALIGN(nlk->ngroups / 8, sizeof(u32)), optlen)) | 2387 | if (put_user(ALIGN(nlk->ngroups / 8, sizeof(u32)), optlen)) |
2388 | err = -EFAULT; | 2388 | err = -EFAULT; |
2389 | netlink_table_ungrab(); | 2389 | netlink_unlock_table(); |
2390 | break; | 2390 | break; |
2391 | } | 2391 | } |
2392 | case NETLINK_CAP_ACK: | 2392 | case NETLINK_CAP_ACK: |
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index c6087233d7fc..221fa8b37a47 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c | |||
@@ -769,7 +769,6 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb, | |||
769 | struct sw_flow_key *key, const struct nlattr *attr, | 769 | struct sw_flow_key *key, const struct nlattr *attr, |
770 | const struct nlattr *actions, int actions_len) | 770 | const struct nlattr *actions, int actions_len) |
771 | { | 771 | { |
772 | struct ip_tunnel_info info; | ||
773 | struct dp_upcall_info upcall; | 772 | struct dp_upcall_info upcall; |
774 | const struct nlattr *a; | 773 | const struct nlattr *a; |
775 | int rem; | 774 | int rem; |
@@ -797,11 +796,9 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb, | |||
797 | if (vport) { | 796 | if (vport) { |
798 | int err; | 797 | int err; |
799 | 798 | ||
800 | upcall.egress_tun_info = &info; | 799 | err = dev_fill_metadata_dst(vport->dev, skb); |
801 | err = ovs_vport_get_egress_tun_info(vport, skb, | 800 | if (!err) |
802 | &upcall); | 801 | upcall.egress_tun_info = skb_tunnel_info(skb); |
803 | if (err) | ||
804 | upcall.egress_tun_info = NULL; | ||
805 | } | 802 | } |
806 | 803 | ||
807 | break; | 804 | break; |
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index 9ed833e9bb7d..bd165ee2bb16 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c | |||
@@ -151,6 +151,8 @@ static void ovs_ct_update_key(const struct sk_buff *skb, | |||
151 | ct = nf_ct_get(skb, &ctinfo); | 151 | ct = nf_ct_get(skb, &ctinfo); |
152 | if (ct) { | 152 | if (ct) { |
153 | state = ovs_ct_get_state(ctinfo); | 153 | state = ovs_ct_get_state(ctinfo); |
154 | if (!nf_ct_is_confirmed(ct)) | ||
155 | state |= OVS_CS_F_NEW; | ||
154 | if (ct->master) | 156 | if (ct->master) |
155 | state |= OVS_CS_F_RELATED; | 157 | state |= OVS_CS_F_RELATED; |
156 | zone = nf_ct_zone(ct); | 158 | zone = nf_ct_zone(ct); |
@@ -222,9 +224,6 @@ static int ovs_ct_set_labels(struct sk_buff *skb, struct sw_flow_key *key, | |||
222 | struct nf_conn *ct; | 224 | struct nf_conn *ct; |
223 | int err; | 225 | int err; |
224 | 226 | ||
225 | if (!IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS)) | ||
226 | return -ENOTSUPP; | ||
227 | |||
228 | /* The connection could be invalid, in which case set_label is no-op.*/ | 227 | /* The connection could be invalid, in which case set_label is no-op.*/ |
229 | ct = nf_ct_get(skb, &ctinfo); | 228 | ct = nf_ct_get(skb, &ctinfo); |
230 | if (!ct) | 229 | if (!ct) |
@@ -377,7 +376,7 @@ static bool skb_nfct_cached(const struct net *net, const struct sk_buff *skb, | |||
377 | return true; | 376 | return true; |
378 | } | 377 | } |
379 | 378 | ||
380 | static int __ovs_ct_lookup(struct net *net, const struct sw_flow_key *key, | 379 | static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key, |
381 | const struct ovs_conntrack_info *info, | 380 | const struct ovs_conntrack_info *info, |
382 | struct sk_buff *skb) | 381 | struct sk_buff *skb) |
383 | { | 382 | { |
@@ -408,6 +407,8 @@ static int __ovs_ct_lookup(struct net *net, const struct sw_flow_key *key, | |||
408 | } | 407 | } |
409 | } | 408 | } |
410 | 409 | ||
410 | ovs_ct_update_key(skb, key, true); | ||
411 | |||
411 | return 0; | 412 | return 0; |
412 | } | 413 | } |
413 | 414 | ||
@@ -430,8 +431,6 @@ static int ovs_ct_lookup(struct net *net, struct sw_flow_key *key, | |||
430 | err = __ovs_ct_lookup(net, key, info, skb); | 431 | err = __ovs_ct_lookup(net, key, info, skb); |
431 | if (err) | 432 | if (err) |
432 | return err; | 433 | return err; |
433 | |||
434 | ovs_ct_update_key(skb, key, true); | ||
435 | } | 434 | } |
436 | 435 | ||
437 | return 0; | 436 | return 0; |
@@ -460,8 +459,6 @@ static int ovs_ct_commit(struct net *net, struct sw_flow_key *key, | |||
460 | if (nf_conntrack_confirm(skb) != NF_ACCEPT) | 459 | if (nf_conntrack_confirm(skb) != NF_ACCEPT) |
461 | return -EINVAL; | 460 | return -EINVAL; |
462 | 461 | ||
463 | ovs_ct_update_key(skb, key, true); | ||
464 | |||
465 | return 0; | 462 | return 0; |
466 | } | 463 | } |
467 | 464 | ||
@@ -587,6 +584,10 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info, | |||
587 | case OVS_CT_ATTR_MARK: { | 584 | case OVS_CT_ATTR_MARK: { |
588 | struct md_mark *mark = nla_data(a); | 585 | struct md_mark *mark = nla_data(a); |
589 | 586 | ||
587 | if (!mark->mask) { | ||
588 | OVS_NLERR(log, "ct_mark mask cannot be 0"); | ||
589 | return -EINVAL; | ||
590 | } | ||
590 | info->mark = *mark; | 591 | info->mark = *mark; |
591 | break; | 592 | break; |
592 | } | 593 | } |
@@ -595,6 +596,10 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info, | |||
595 | case OVS_CT_ATTR_LABELS: { | 596 | case OVS_CT_ATTR_LABELS: { |
596 | struct md_labels *labels = nla_data(a); | 597 | struct md_labels *labels = nla_data(a); |
597 | 598 | ||
599 | if (!labels_nonzero(&labels->mask)) { | ||
600 | OVS_NLERR(log, "ct_labels mask cannot be 0"); | ||
601 | return -EINVAL; | ||
602 | } | ||
598 | info->labels = *labels; | 603 | info->labels = *labels; |
599 | break; | 604 | break; |
600 | } | 605 | } |
@@ -705,11 +710,12 @@ int ovs_ct_action_to_attr(const struct ovs_conntrack_info *ct_info, | |||
705 | if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) && | 710 | if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) && |
706 | nla_put_u16(skb, OVS_CT_ATTR_ZONE, ct_info->zone.id)) | 711 | nla_put_u16(skb, OVS_CT_ATTR_ZONE, ct_info->zone.id)) |
707 | return -EMSGSIZE; | 712 | return -EMSGSIZE; |
708 | if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) && | 713 | if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) && ct_info->mark.mask && |
709 | nla_put(skb, OVS_CT_ATTR_MARK, sizeof(ct_info->mark), | 714 | nla_put(skb, OVS_CT_ATTR_MARK, sizeof(ct_info->mark), |
710 | &ct_info->mark)) | 715 | &ct_info->mark)) |
711 | return -EMSGSIZE; | 716 | return -EMSGSIZE; |
712 | if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) && | 717 | if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) && |
718 | labels_nonzero(&ct_info->labels.mask) && | ||
713 | nla_put(skb, OVS_CT_ATTR_LABELS, sizeof(ct_info->labels), | 719 | nla_put(skb, OVS_CT_ATTR_LABELS, sizeof(ct_info->labels), |
714 | &ct_info->labels)) | 720 | &ct_info->labels)) |
715 | return -EMSGSIZE; | 721 | return -EMSGSIZE; |
diff --git a/net/openvswitch/conntrack.h b/net/openvswitch/conntrack.h index da8714942c95..82e0dfc66028 100644 --- a/net/openvswitch/conntrack.h +++ b/net/openvswitch/conntrack.h | |||
@@ -35,12 +35,9 @@ void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key); | |||
35 | int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb); | 35 | int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb); |
36 | void ovs_ct_free_action(const struct nlattr *a); | 36 | void ovs_ct_free_action(const struct nlattr *a); |
37 | 37 | ||
38 | static inline bool ovs_ct_state_supported(u32 state) | 38 | #define CT_SUPPORTED_MASK (OVS_CS_F_NEW | OVS_CS_F_ESTABLISHED | \ |
39 | { | 39 | OVS_CS_F_RELATED | OVS_CS_F_REPLY_DIR | \ |
40 | return !(state & ~(OVS_CS_F_NEW | OVS_CS_F_ESTABLISHED | | 40 | OVS_CS_F_INVALID | OVS_CS_F_TRACKED) |
41 | OVS_CS_F_RELATED | OVS_CS_F_REPLY_DIR | | ||
42 | OVS_CS_F_INVALID | OVS_CS_F_TRACKED)); | ||
43 | } | ||
44 | #else | 41 | #else |
45 | #include <linux/errno.h> | 42 | #include <linux/errno.h> |
46 | 43 | ||
@@ -53,11 +50,6 @@ static inline bool ovs_ct_verify(struct net *net, int attr) | |||
53 | return false; | 50 | return false; |
54 | } | 51 | } |
55 | 52 | ||
56 | static inline bool ovs_ct_state_supported(u32 state) | ||
57 | { | ||
58 | return false; | ||
59 | } | ||
60 | |||
61 | static inline int ovs_ct_copy_action(struct net *net, const struct nlattr *nla, | 53 | static inline int ovs_ct_copy_action(struct net *net, const struct nlattr *nla, |
62 | const struct sw_flow_key *key, | 54 | const struct sw_flow_key *key, |
63 | struct sw_flow_actions **acts, bool log) | 55 | struct sw_flow_actions **acts, bool log) |
@@ -94,5 +86,7 @@ static inline int ovs_ct_put_key(const struct sw_flow_key *key, | |||
94 | } | 86 | } |
95 | 87 | ||
96 | static inline void ovs_ct_free_action(const struct nlattr *a) { } | 88 | static inline void ovs_ct_free_action(const struct nlattr *a) { } |
89 | |||
90 | #define CT_SUPPORTED_MASK 0 | ||
97 | #endif /* CONFIG_NF_CONNTRACK */ | 91 | #endif /* CONFIG_NF_CONNTRACK */ |
98 | #endif /* ovs_conntrack.h */ | 92 | #endif /* ovs_conntrack.h */ |
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index a75828091e21..5633172b791a 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -489,9 +489,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, | |||
489 | 489 | ||
490 | if (upcall_info->egress_tun_info) { | 490 | if (upcall_info->egress_tun_info) { |
491 | nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_EGRESS_TUN_KEY); | 491 | nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_EGRESS_TUN_KEY); |
492 | err = ovs_nla_put_egress_tunnel_key(user_skb, | 492 | err = ovs_nla_put_tunnel_info(user_skb, |
493 | upcall_info->egress_tun_info, | 493 | upcall_info->egress_tun_info); |
494 | upcall_info->egress_tun_opts); | ||
495 | BUG_ON(err); | 494 | BUG_ON(err); |
496 | nla_nest_end(user_skb, nla); | 495 | nla_nest_end(user_skb, nla); |
497 | } | 496 | } |
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h index f88038a99f44..67bdecd9fdc1 100644 --- a/net/openvswitch/datapath.h +++ b/net/openvswitch/datapath.h | |||
@@ -117,7 +117,6 @@ struct ovs_skb_cb { | |||
117 | */ | 117 | */ |
118 | struct dp_upcall_info { | 118 | struct dp_upcall_info { |
119 | struct ip_tunnel_info *egress_tun_info; | 119 | struct ip_tunnel_info *egress_tun_info; |
120 | const void *egress_tun_opts; | ||
121 | const struct nlattr *userdata; | 120 | const struct nlattr *userdata; |
122 | const struct nlattr *actions; | 121 | const struct nlattr *actions; |
123 | int actions_len; | 122 | int actions_len; |
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index 80e1f09397c0..907d6fd28ede 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c | |||
@@ -764,7 +764,7 @@ static int __ip_tun_to_nlattr(struct sk_buff *skb, | |||
764 | if ((output->tun_flags & TUNNEL_OAM) && | 764 | if ((output->tun_flags & TUNNEL_OAM) && |
765 | nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_OAM)) | 765 | nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_OAM)) |
766 | return -EMSGSIZE; | 766 | return -EMSGSIZE; |
767 | if (tun_opts) { | 767 | if (swkey_tun_opts_len) { |
768 | if (output->tun_flags & TUNNEL_GENEVE_OPT && | 768 | if (output->tun_flags & TUNNEL_GENEVE_OPT && |
769 | nla_put(skb, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS, | 769 | nla_put(skb, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS, |
770 | swkey_tun_opts_len, tun_opts)) | 770 | swkey_tun_opts_len, tun_opts)) |
@@ -798,14 +798,13 @@ static int ip_tun_to_nlattr(struct sk_buff *skb, | |||
798 | return 0; | 798 | return 0; |
799 | } | 799 | } |
800 | 800 | ||
801 | int ovs_nla_put_egress_tunnel_key(struct sk_buff *skb, | 801 | int ovs_nla_put_tunnel_info(struct sk_buff *skb, |
802 | const struct ip_tunnel_info *egress_tun_info, | 802 | struct ip_tunnel_info *tun_info) |
803 | const void *egress_tun_opts) | ||
804 | { | 803 | { |
805 | return __ip_tun_to_nlattr(skb, &egress_tun_info->key, | 804 | return __ip_tun_to_nlattr(skb, &tun_info->key, |
806 | egress_tun_opts, | 805 | ip_tunnel_info_opts(tun_info), |
807 | egress_tun_info->options_len, | 806 | tun_info->options_len, |
808 | ip_tunnel_info_af(egress_tun_info)); | 807 | ip_tunnel_info_af(tun_info)); |
809 | } | 808 | } |
810 | 809 | ||
811 | static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match, | 810 | static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match, |
@@ -866,7 +865,7 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match, | |||
866 | ovs_ct_verify(net, OVS_KEY_ATTR_CT_STATE)) { | 865 | ovs_ct_verify(net, OVS_KEY_ATTR_CT_STATE)) { |
867 | u32 ct_state = nla_get_u32(a[OVS_KEY_ATTR_CT_STATE]); | 866 | u32 ct_state = nla_get_u32(a[OVS_KEY_ATTR_CT_STATE]); |
868 | 867 | ||
869 | if (!is_mask && !ovs_ct_state_supported(ct_state)) { | 868 | if (ct_state & ~CT_SUPPORTED_MASK) { |
870 | OVS_NLERR(log, "ct_state flags %08x unsupported", | 869 | OVS_NLERR(log, "ct_state flags %08x unsupported", |
871 | ct_state); | 870 | ct_state); |
872 | return -EINVAL; | 871 | return -EINVAL; |
@@ -1149,6 +1148,9 @@ static void nlattr_set(struct nlattr *attr, u8 val, | |||
1149 | } else { | 1148 | } else { |
1150 | memset(nla_data(nla), val, nla_len(nla)); | 1149 | memset(nla_data(nla), val, nla_len(nla)); |
1151 | } | 1150 | } |
1151 | |||
1152 | if (nla_type(nla) == OVS_KEY_ATTR_CT_STATE) | ||
1153 | *(u32 *)nla_data(nla) &= CT_SUPPORTED_MASK; | ||
1152 | } | 1154 | } |
1153 | } | 1155 | } |
1154 | 1156 | ||
@@ -2432,11 +2434,7 @@ static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb) | |||
2432 | if (!start) | 2434 | if (!start) |
2433 | return -EMSGSIZE; | 2435 | return -EMSGSIZE; |
2434 | 2436 | ||
2435 | err = ip_tun_to_nlattr(skb, &tun_info->key, | 2437 | err = ovs_nla_put_tunnel_info(skb, tun_info); |
2436 | tun_info->options_len ? | ||
2437 | ip_tunnel_info_opts(tun_info) : NULL, | ||
2438 | tun_info->options_len, | ||
2439 | ip_tunnel_info_af(tun_info)); | ||
2440 | if (err) | 2438 | if (err) |
2441 | return err; | 2439 | return err; |
2442 | nla_nest_end(skb, start); | 2440 | nla_nest_end(skb, start); |
diff --git a/net/openvswitch/flow_netlink.h b/net/openvswitch/flow_netlink.h index 6ca3f0baf449..47dd142eca1c 100644 --- a/net/openvswitch/flow_netlink.h +++ b/net/openvswitch/flow_netlink.h | |||
@@ -55,9 +55,9 @@ int ovs_nla_put_mask(const struct sw_flow *flow, struct sk_buff *skb); | |||
55 | int ovs_nla_get_match(struct net *, struct sw_flow_match *, | 55 | int ovs_nla_get_match(struct net *, struct sw_flow_match *, |
56 | const struct nlattr *key, const struct nlattr *mask, | 56 | const struct nlattr *key, const struct nlattr *mask, |
57 | bool log); | 57 | bool log); |
58 | int ovs_nla_put_egress_tunnel_key(struct sk_buff *, | 58 | |
59 | const struct ip_tunnel_info *, | 59 | int ovs_nla_put_tunnel_info(struct sk_buff *skb, |
60 | const void *egress_tun_opts); | 60 | struct ip_tunnel_info *tun_info); |
61 | 61 | ||
62 | bool ovs_nla_get_ufid(struct sw_flow_id *, const struct nlattr *, bool log); | 62 | bool ovs_nla_get_ufid(struct sw_flow_id *, const struct nlattr *, bool log); |
63 | int ovs_nla_get_identifier(struct sw_flow_id *sfid, const struct nlattr *ufid, | 63 | int ovs_nla_get_identifier(struct sw_flow_id *sfid, const struct nlattr *ufid, |
diff --git a/net/openvswitch/vport-geneve.c b/net/openvswitch/vport-geneve.c index 7a568ca8da54..efb736bb6855 100644 --- a/net/openvswitch/vport-geneve.c +++ b/net/openvswitch/vport-geneve.c | |||
@@ -52,18 +52,6 @@ static int geneve_get_options(const struct vport *vport, | |||
52 | return 0; | 52 | return 0; |
53 | } | 53 | } |
54 | 54 | ||
55 | static int geneve_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, | ||
56 | struct dp_upcall_info *upcall) | ||
57 | { | ||
58 | struct geneve_port *geneve_port = geneve_vport(vport); | ||
59 | struct net *net = ovs_dp_get_net(vport->dp); | ||
60 | __be16 dport = htons(geneve_port->port_no); | ||
61 | __be16 sport = udp_flow_src_port(net, skb, 1, USHRT_MAX, true); | ||
62 | |||
63 | return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp), | ||
64 | skb, IPPROTO_UDP, sport, dport); | ||
65 | } | ||
66 | |||
67 | static struct vport *geneve_tnl_create(const struct vport_parms *parms) | 55 | static struct vport *geneve_tnl_create(const struct vport_parms *parms) |
68 | { | 56 | { |
69 | struct net *net = ovs_dp_get_net(parms->dp); | 57 | struct net *net = ovs_dp_get_net(parms->dp); |
@@ -130,7 +118,6 @@ static struct vport_ops ovs_geneve_vport_ops = { | |||
130 | .get_options = geneve_get_options, | 118 | .get_options = geneve_get_options, |
131 | .send = dev_queue_xmit, | 119 | .send = dev_queue_xmit, |
132 | .owner = THIS_MODULE, | 120 | .owner = THIS_MODULE, |
133 | .get_egress_tun_info = geneve_get_egress_tun_info, | ||
134 | }; | 121 | }; |
135 | 122 | ||
136 | static int __init ovs_geneve_tnl_init(void) | 123 | static int __init ovs_geneve_tnl_init(void) |
diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c index cdb758ab01cf..c3257d78d3d2 100644 --- a/net/openvswitch/vport-gre.c +++ b/net/openvswitch/vport-gre.c | |||
@@ -84,18 +84,10 @@ static struct vport *gre_create(const struct vport_parms *parms) | |||
84 | return ovs_netdev_link(vport, parms->name); | 84 | return ovs_netdev_link(vport, parms->name); |
85 | } | 85 | } |
86 | 86 | ||
87 | static int gre_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, | ||
88 | struct dp_upcall_info *upcall) | ||
89 | { | ||
90 | return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp), | ||
91 | skb, IPPROTO_GRE, 0, 0); | ||
92 | } | ||
93 | |||
94 | static struct vport_ops ovs_gre_vport_ops = { | 87 | static struct vport_ops ovs_gre_vport_ops = { |
95 | .type = OVS_VPORT_TYPE_GRE, | 88 | .type = OVS_VPORT_TYPE_GRE, |
96 | .create = gre_create, | 89 | .create = gre_create, |
97 | .send = dev_queue_xmit, | 90 | .send = dev_queue_xmit, |
98 | .get_egress_tun_info = gre_get_egress_tun_info, | ||
99 | .destroy = ovs_netdev_tunnel_destroy, | 91 | .destroy = ovs_netdev_tunnel_destroy, |
100 | .owner = THIS_MODULE, | 92 | .owner = THIS_MODULE, |
101 | }; | 93 | }; |
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c index 7f0a8bd08857..ec76398a792f 100644 --- a/net/openvswitch/vport-internal_dev.c +++ b/net/openvswitch/vport-internal_dev.c | |||
@@ -106,12 +106,45 @@ static void internal_dev_destructor(struct net_device *dev) | |||
106 | free_netdev(dev); | 106 | free_netdev(dev); |
107 | } | 107 | } |
108 | 108 | ||
109 | static struct rtnl_link_stats64 * | ||
110 | internal_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) | ||
111 | { | ||
112 | int i; | ||
113 | |||
114 | memset(stats, 0, sizeof(*stats)); | ||
115 | stats->rx_errors = dev->stats.rx_errors; | ||
116 | stats->tx_errors = dev->stats.tx_errors; | ||
117 | stats->tx_dropped = dev->stats.tx_dropped; | ||
118 | stats->rx_dropped = dev->stats.rx_dropped; | ||
119 | |||
120 | for_each_possible_cpu(i) { | ||
121 | const struct pcpu_sw_netstats *percpu_stats; | ||
122 | struct pcpu_sw_netstats local_stats; | ||
123 | unsigned int start; | ||
124 | |||
125 | percpu_stats = per_cpu_ptr(dev->tstats, i); | ||
126 | |||
127 | do { | ||
128 | start = u64_stats_fetch_begin_irq(&percpu_stats->syncp); | ||
129 | local_stats = *percpu_stats; | ||
130 | } while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start)); | ||
131 | |||
132 | stats->rx_bytes += local_stats.rx_bytes; | ||
133 | stats->rx_packets += local_stats.rx_packets; | ||
134 | stats->tx_bytes += local_stats.tx_bytes; | ||
135 | stats->tx_packets += local_stats.tx_packets; | ||
136 | } | ||
137 | |||
138 | return stats; | ||
139 | } | ||
140 | |||
109 | static const struct net_device_ops internal_dev_netdev_ops = { | 141 | static const struct net_device_ops internal_dev_netdev_ops = { |
110 | .ndo_open = internal_dev_open, | 142 | .ndo_open = internal_dev_open, |
111 | .ndo_stop = internal_dev_stop, | 143 | .ndo_stop = internal_dev_stop, |
112 | .ndo_start_xmit = internal_dev_xmit, | 144 | .ndo_start_xmit = internal_dev_xmit, |
113 | .ndo_set_mac_address = eth_mac_addr, | 145 | .ndo_set_mac_address = eth_mac_addr, |
114 | .ndo_change_mtu = internal_dev_change_mtu, | 146 | .ndo_change_mtu = internal_dev_change_mtu, |
147 | .ndo_get_stats64 = internal_get_stats, | ||
115 | }; | 148 | }; |
116 | 149 | ||
117 | static struct rtnl_link_ops internal_dev_link_ops __read_mostly = { | 150 | static struct rtnl_link_ops internal_dev_link_ops __read_mostly = { |
@@ -161,6 +194,11 @@ static struct vport *internal_dev_create(const struct vport_parms *parms) | |||
161 | err = -ENOMEM; | 194 | err = -ENOMEM; |
162 | goto error_free_vport; | 195 | goto error_free_vport; |
163 | } | 196 | } |
197 | vport->dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); | ||
198 | if (!vport->dev->tstats) { | ||
199 | err = -ENOMEM; | ||
200 | goto error_free_netdev; | ||
201 | } | ||
164 | 202 | ||
165 | dev_net_set(vport->dev, ovs_dp_get_net(vport->dp)); | 203 | dev_net_set(vport->dev, ovs_dp_get_net(vport->dp)); |
166 | internal_dev = internal_dev_priv(vport->dev); | 204 | internal_dev = internal_dev_priv(vport->dev); |
@@ -173,7 +211,7 @@ static struct vport *internal_dev_create(const struct vport_parms *parms) | |||
173 | rtnl_lock(); | 211 | rtnl_lock(); |
174 | err = register_netdevice(vport->dev); | 212 | err = register_netdevice(vport->dev); |
175 | if (err) | 213 | if (err) |
176 | goto error_free_netdev; | 214 | goto error_unlock; |
177 | 215 | ||
178 | dev_set_promiscuity(vport->dev, 1); | 216 | dev_set_promiscuity(vport->dev, 1); |
179 | rtnl_unlock(); | 217 | rtnl_unlock(); |
@@ -181,8 +219,10 @@ static struct vport *internal_dev_create(const struct vport_parms *parms) | |||
181 | 219 | ||
182 | return vport; | 220 | return vport; |
183 | 221 | ||
184 | error_free_netdev: | 222 | error_unlock: |
185 | rtnl_unlock(); | 223 | rtnl_unlock(); |
224 | free_percpu(vport->dev->tstats); | ||
225 | error_free_netdev: | ||
186 | free_netdev(vport->dev); | 226 | free_netdev(vport->dev); |
187 | error_free_vport: | 227 | error_free_vport: |
188 | ovs_vport_free(vport); | 228 | ovs_vport_free(vport); |
@@ -198,7 +238,7 @@ static void internal_dev_destroy(struct vport *vport) | |||
198 | 238 | ||
199 | /* unregister_netdevice() waits for an RCU grace period. */ | 239 | /* unregister_netdevice() waits for an RCU grace period. */ |
200 | unregister_netdevice(vport->dev); | 240 | unregister_netdevice(vport->dev); |
201 | 241 | free_percpu(vport->dev->tstats); | |
202 | rtnl_unlock(); | 242 | rtnl_unlock(); |
203 | } | 243 | } |
204 | 244 | ||
diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c index 6f700710d413..1605691d9414 100644 --- a/net/openvswitch/vport-vxlan.c +++ b/net/openvswitch/vport-vxlan.c | |||
@@ -146,32 +146,12 @@ static struct vport *vxlan_create(const struct vport_parms *parms) | |||
146 | return ovs_netdev_link(vport, parms->name); | 146 | return ovs_netdev_link(vport, parms->name); |
147 | } | 147 | } |
148 | 148 | ||
149 | static int vxlan_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, | ||
150 | struct dp_upcall_info *upcall) | ||
151 | { | ||
152 | struct vxlan_dev *vxlan = netdev_priv(vport->dev); | ||
153 | struct net *net = ovs_dp_get_net(vport->dp); | ||
154 | unsigned short family = ip_tunnel_info_af(upcall->egress_tun_info); | ||
155 | __be16 dst_port = vxlan_dev_dst_port(vxlan, family); | ||
156 | __be16 src_port; | ||
157 | int port_min; | ||
158 | int port_max; | ||
159 | |||
160 | inet_get_local_port_range(net, &port_min, &port_max); | ||
161 | src_port = udp_flow_src_port(net, skb, 0, 0, true); | ||
162 | |||
163 | return ovs_tunnel_get_egress_info(upcall, net, | ||
164 | skb, IPPROTO_UDP, | ||
165 | src_port, dst_port); | ||
166 | } | ||
167 | |||
168 | static struct vport_ops ovs_vxlan_netdev_vport_ops = { | 149 | static struct vport_ops ovs_vxlan_netdev_vport_ops = { |
169 | .type = OVS_VPORT_TYPE_VXLAN, | 150 | .type = OVS_VPORT_TYPE_VXLAN, |
170 | .create = vxlan_create, | 151 | .create = vxlan_create, |
171 | .destroy = ovs_netdev_tunnel_destroy, | 152 | .destroy = ovs_netdev_tunnel_destroy, |
172 | .get_options = vxlan_get_options, | 153 | .get_options = vxlan_get_options, |
173 | .send = dev_queue_xmit, | 154 | .send = dev_queue_xmit, |
174 | .get_egress_tun_info = vxlan_get_egress_tun_info, | ||
175 | }; | 155 | }; |
176 | 156 | ||
177 | static int __init ovs_vxlan_tnl_init(void) | 157 | static int __init ovs_vxlan_tnl_init(void) |
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index ef19d0b77d13..0ac0fd004d7e 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c | |||
@@ -480,64 +480,6 @@ void ovs_vport_deferred_free(struct vport *vport) | |||
480 | } | 480 | } |
481 | EXPORT_SYMBOL_GPL(ovs_vport_deferred_free); | 481 | EXPORT_SYMBOL_GPL(ovs_vport_deferred_free); |
482 | 482 | ||
483 | int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall, | ||
484 | struct net *net, | ||
485 | struct sk_buff *skb, | ||
486 | u8 ipproto, | ||
487 | __be16 tp_src, | ||
488 | __be16 tp_dst) | ||
489 | { | ||
490 | struct ip_tunnel_info *egress_tun_info = upcall->egress_tun_info; | ||
491 | const struct ip_tunnel_info *tun_info = skb_tunnel_info(skb); | ||
492 | const struct ip_tunnel_key *tun_key; | ||
493 | u32 skb_mark = skb->mark; | ||
494 | struct rtable *rt; | ||
495 | struct flowi4 fl; | ||
496 | |||
497 | if (unlikely(!tun_info)) | ||
498 | return -EINVAL; | ||
499 | if (ip_tunnel_info_af(tun_info) != AF_INET) | ||
500 | return -EINVAL; | ||
501 | |||
502 | tun_key = &tun_info->key; | ||
503 | |||
504 | /* Route lookup to get srouce IP address. | ||
505 | * The process may need to be changed if the corresponding process | ||
506 | * in vports ops changed. | ||
507 | */ | ||
508 | rt = ovs_tunnel_route_lookup(net, tun_key, skb_mark, &fl, ipproto); | ||
509 | if (IS_ERR(rt)) | ||
510 | return PTR_ERR(rt); | ||
511 | |||
512 | ip_rt_put(rt); | ||
513 | |||
514 | /* Generate egress_tun_info based on tun_info, | ||
515 | * saddr, tp_src and tp_dst | ||
516 | */ | ||
517 | ip_tunnel_key_init(&egress_tun_info->key, | ||
518 | fl.saddr, tun_key->u.ipv4.dst, | ||
519 | tun_key->tos, | ||
520 | tun_key->ttl, | ||
521 | tp_src, tp_dst, | ||
522 | tun_key->tun_id, | ||
523 | tun_key->tun_flags); | ||
524 | egress_tun_info->options_len = tun_info->options_len; | ||
525 | egress_tun_info->mode = tun_info->mode; | ||
526 | upcall->egress_tun_opts = ip_tunnel_info_opts(egress_tun_info); | ||
527 | return 0; | ||
528 | } | ||
529 | EXPORT_SYMBOL_GPL(ovs_tunnel_get_egress_info); | ||
530 | |||
531 | int ovs_vport_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, | ||
532 | struct dp_upcall_info *upcall) | ||
533 | { | ||
534 | /* get_egress_tun_info() is only implemented on tunnel ports. */ | ||
535 | if (unlikely(!vport->ops->get_egress_tun_info)) | ||
536 | return -EINVAL; | ||
537 | |||
538 | return vport->ops->get_egress_tun_info(vport, skb, upcall); | ||
539 | } | ||
540 | |||
541 | static unsigned int packet_length(const struct sk_buff *skb) | 483 | static unsigned int packet_length(const struct sk_buff *skb) |
542 | { | 484 | { |
543 | unsigned int length = skb->len - ETH_HLEN; | 485 | unsigned int length = skb->len - ETH_HLEN; |
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h index 885607f28d56..bdfd82a7c064 100644 --- a/net/openvswitch/vport.h +++ b/net/openvswitch/vport.h | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/skbuff.h> | 27 | #include <linux/skbuff.h> |
28 | #include <linux/spinlock.h> | 28 | #include <linux/spinlock.h> |
29 | #include <linux/u64_stats_sync.h> | 29 | #include <linux/u64_stats_sync.h> |
30 | #include <net/route.h> | ||
31 | 30 | ||
32 | #include "datapath.h" | 31 | #include "datapath.h" |
33 | 32 | ||
@@ -53,16 +52,6 @@ int ovs_vport_set_upcall_portids(struct vport *, const struct nlattr *pids); | |||
53 | int ovs_vport_get_upcall_portids(const struct vport *, struct sk_buff *); | 52 | int ovs_vport_get_upcall_portids(const struct vport *, struct sk_buff *); |
54 | u32 ovs_vport_find_upcall_portid(const struct vport *, struct sk_buff *); | 53 | u32 ovs_vport_find_upcall_portid(const struct vport *, struct sk_buff *); |
55 | 54 | ||
56 | int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall, | ||
57 | struct net *net, | ||
58 | struct sk_buff *, | ||
59 | u8 ipproto, | ||
60 | __be16 tp_src, | ||
61 | __be16 tp_dst); | ||
62 | |||
63 | int ovs_vport_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, | ||
64 | struct dp_upcall_info *upcall); | ||
65 | |||
66 | /** | 55 | /** |
67 | * struct vport_portids - array of netlink portids of a vport. | 56 | * struct vport_portids - array of netlink portids of a vport. |
68 | * must be protected by rcu. | 57 | * must be protected by rcu. |
@@ -140,8 +129,6 @@ struct vport_parms { | |||
140 | * have any configuration. | 129 | * have any configuration. |
141 | * @send: Send a packet on the device. | 130 | * @send: Send a packet on the device. |
142 | * zero for dropped packets or negative for error. | 131 | * zero for dropped packets or negative for error. |
143 | * @get_egress_tun_info: Get the egress tunnel 5-tuple and other info for | ||
144 | * a packet. | ||
145 | */ | 132 | */ |
146 | struct vport_ops { | 133 | struct vport_ops { |
147 | enum ovs_vport_type type; | 134 | enum ovs_vport_type type; |
@@ -154,9 +141,6 @@ struct vport_ops { | |||
154 | int (*get_options)(const struct vport *, struct sk_buff *); | 141 | int (*get_options)(const struct vport *, struct sk_buff *); |
155 | 142 | ||
156 | netdev_tx_t (*send) (struct sk_buff *skb); | 143 | netdev_tx_t (*send) (struct sk_buff *skb); |
157 | int (*get_egress_tun_info)(struct vport *, struct sk_buff *, | ||
158 | struct dp_upcall_info *upcall); | ||
159 | |||
160 | struct module *owner; | 144 | struct module *owner; |
161 | struct list_head list; | 145 | struct list_head list; |
162 | }; | 146 | }; |
diff --git a/net/sysctl_net.c b/net/sysctl_net.c index e7000be321b0..ed98c1fc3de1 100644 --- a/net/sysctl_net.c +++ b/net/sysctl_net.c | |||
@@ -94,10 +94,14 @@ __init int net_sysctl_init(void) | |||
94 | goto out; | 94 | goto out; |
95 | ret = register_pernet_subsys(&sysctl_pernet_ops); | 95 | ret = register_pernet_subsys(&sysctl_pernet_ops); |
96 | if (ret) | 96 | if (ret) |
97 | goto out; | 97 | goto out1; |
98 | register_sysctl_root(&net_sysctl_root); | 98 | register_sysctl_root(&net_sysctl_root); |
99 | out: | 99 | out: |
100 | return ret; | 100 | return ret; |
101 | out1: | ||
102 | unregister_sysctl_table(net_header); | ||
103 | net_header = NULL; | ||
104 | goto out; | ||
101 | } | 105 | } |
102 | 106 | ||
103 | struct ctl_table_header *register_net_sysctl(struct net *net, | 107 | struct ctl_table_header *register_net_sysctl(struct net *net, |
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 41042de3ae9b..eadba62afa85 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
@@ -42,7 +42,8 @@ | |||
42 | #include "core.h" | 42 | #include "core.h" |
43 | 43 | ||
44 | #define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */ | 44 | #define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */ |
45 | #define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */ | 45 | #define BCLINK_WIN_DEFAULT 50 /* bcast link window size (default) */ |
46 | #define BCLINK_WIN_MIN 32 /* bcast minimum link window size */ | ||
46 | 47 | ||
47 | const char tipc_bclink_name[] = "broadcast-link"; | 48 | const char tipc_bclink_name[] = "broadcast-link"; |
48 | 49 | ||
@@ -908,9 +909,10 @@ int tipc_bclink_set_queue_limits(struct net *net, u32 limit) | |||
908 | 909 | ||
909 | if (!bcl) | 910 | if (!bcl) |
910 | return -ENOPROTOOPT; | 911 | return -ENOPROTOOPT; |
911 | if ((limit < TIPC_MIN_LINK_WIN) || (limit > TIPC_MAX_LINK_WIN)) | 912 | if (limit < BCLINK_WIN_MIN) |
913 | limit = BCLINK_WIN_MIN; | ||
914 | if (limit > TIPC_MAX_LINK_WIN) | ||
912 | return -EINVAL; | 915 | return -EINVAL; |
913 | |||
914 | tipc_bclink_lock(net); | 916 | tipc_bclink_lock(net); |
915 | tipc_link_set_queue_limits(bcl, limit); | 917 | tipc_link_set_queue_limits(bcl, limit); |
916 | tipc_bclink_unlock(net); | 918 | tipc_bclink_unlock(net); |
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 454f5ec275c8..26d38b3d8760 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c | |||
@@ -121,7 +121,7 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf) | |||
121 | { | 121 | { |
122 | struct sk_buff *head = *headbuf; | 122 | struct sk_buff *head = *headbuf; |
123 | struct sk_buff *frag = *buf; | 123 | struct sk_buff *frag = *buf; |
124 | struct sk_buff *tail; | 124 | struct sk_buff *tail = NULL; |
125 | struct tipc_msg *msg; | 125 | struct tipc_msg *msg; |
126 | u32 fragid; | 126 | u32 fragid; |
127 | int delta; | 127 | int delta; |
@@ -141,9 +141,15 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf) | |||
141 | if (unlikely(skb_unclone(frag, GFP_ATOMIC))) | 141 | if (unlikely(skb_unclone(frag, GFP_ATOMIC))) |
142 | goto err; | 142 | goto err; |
143 | head = *headbuf = frag; | 143 | head = *headbuf = frag; |
144 | skb_frag_list_init(head); | ||
145 | TIPC_SKB_CB(head)->tail = NULL; | ||
146 | *buf = NULL; | 144 | *buf = NULL; |
145 | TIPC_SKB_CB(head)->tail = NULL; | ||
146 | if (skb_is_nonlinear(head)) { | ||
147 | skb_walk_frags(head, tail) { | ||
148 | TIPC_SKB_CB(head)->tail = tail; | ||
149 | } | ||
150 | } else { | ||
151 | skb_frag_list_init(head); | ||
152 | } | ||
147 | return 0; | 153 | return 0; |
148 | } | 154 | } |
149 | 155 | ||
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c index 9bc0b1e515fa..0021c01dec17 100644 --- a/net/tipc/udp_media.c +++ b/net/tipc/udp_media.c | |||
@@ -52,6 +52,8 @@ | |||
52 | /* IANA assigned UDP port */ | 52 | /* IANA assigned UDP port */ |
53 | #define UDP_PORT_DEFAULT 6118 | 53 | #define UDP_PORT_DEFAULT 6118 |
54 | 54 | ||
55 | #define UDP_MIN_HEADROOM 28 | ||
56 | |||
55 | static const struct nla_policy tipc_nl_udp_policy[TIPC_NLA_UDP_MAX + 1] = { | 57 | static const struct nla_policy tipc_nl_udp_policy[TIPC_NLA_UDP_MAX + 1] = { |
56 | [TIPC_NLA_UDP_UNSPEC] = {.type = NLA_UNSPEC}, | 58 | [TIPC_NLA_UDP_UNSPEC] = {.type = NLA_UNSPEC}, |
57 | [TIPC_NLA_UDP_LOCAL] = {.type = NLA_BINARY, | 59 | [TIPC_NLA_UDP_LOCAL] = {.type = NLA_BINARY, |
@@ -156,6 +158,9 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb, | |||
156 | struct sk_buff *clone; | 158 | struct sk_buff *clone; |
157 | struct rtable *rt; | 159 | struct rtable *rt; |
158 | 160 | ||
161 | if (skb_headroom(skb) < UDP_MIN_HEADROOM) | ||
162 | pskb_expand_head(skb, UDP_MIN_HEADROOM, 0, GFP_ATOMIC); | ||
163 | |||
159 | clone = skb_clone(skb, GFP_ATOMIC); | 164 | clone = skb_clone(skb, GFP_ATOMIC); |
160 | skb_set_inner_protocol(clone, htons(ETH_P_TIPC)); | 165 | skb_set_inner_protocol(clone, htons(ETH_P_TIPC)); |
161 | ub = rcu_dereference_rtnl(b->media_ptr); | 166 | ub = rcu_dereference_rtnl(b->media_ptr); |
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index df5fc6b340f1..00e8a349aabc 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c | |||
@@ -1948,13 +1948,13 @@ int __vsock_core_init(const struct vsock_transport *t, struct module *owner) | |||
1948 | err = misc_register(&vsock_device); | 1948 | err = misc_register(&vsock_device); |
1949 | if (err) { | 1949 | if (err) { |
1950 | pr_err("Failed to register misc device\n"); | 1950 | pr_err("Failed to register misc device\n"); |
1951 | return -ENOENT; | 1951 | goto err_reset_transport; |
1952 | } | 1952 | } |
1953 | 1953 | ||
1954 | err = proto_register(&vsock_proto, 1); /* we want our slab */ | 1954 | err = proto_register(&vsock_proto, 1); /* we want our slab */ |
1955 | if (err) { | 1955 | if (err) { |
1956 | pr_err("Cannot register vsock protocol\n"); | 1956 | pr_err("Cannot register vsock protocol\n"); |
1957 | goto err_misc_deregister; | 1957 | goto err_deregister_misc; |
1958 | } | 1958 | } |
1959 | 1959 | ||
1960 | err = sock_register(&vsock_family_ops); | 1960 | err = sock_register(&vsock_family_ops); |
@@ -1969,8 +1969,9 @@ int __vsock_core_init(const struct vsock_transport *t, struct module *owner) | |||
1969 | 1969 | ||
1970 | err_unregister_proto: | 1970 | err_unregister_proto: |
1971 | proto_unregister(&vsock_proto); | 1971 | proto_unregister(&vsock_proto); |
1972 | err_misc_deregister: | 1972 | err_deregister_misc: |
1973 | misc_deregister(&vsock_device); | 1973 | misc_deregister(&vsock_device); |
1974 | err_reset_transport: | ||
1974 | transport = NULL; | 1975 | transport = NULL; |
1975 | err_busy: | 1976 | err_busy: |
1976 | mutex_unlock(&vsock_register_mutex); | 1977 | mutex_unlock(&vsock_register_mutex); |
diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c index 1f63daff3965..7555cad83a75 100644 --- a/net/vmw_vsock/vmci_transport.c +++ b/net/vmw_vsock/vmci_transport.c | |||
@@ -40,13 +40,11 @@ | |||
40 | 40 | ||
41 | static int vmci_transport_recv_dgram_cb(void *data, struct vmci_datagram *dg); | 41 | static int vmci_transport_recv_dgram_cb(void *data, struct vmci_datagram *dg); |
42 | static int vmci_transport_recv_stream_cb(void *data, struct vmci_datagram *dg); | 42 | static int vmci_transport_recv_stream_cb(void *data, struct vmci_datagram *dg); |
43 | static void vmci_transport_peer_attach_cb(u32 sub_id, | ||
44 | const struct vmci_event_data *ed, | ||
45 | void *client_data); | ||
46 | static void vmci_transport_peer_detach_cb(u32 sub_id, | 43 | static void vmci_transport_peer_detach_cb(u32 sub_id, |
47 | const struct vmci_event_data *ed, | 44 | const struct vmci_event_data *ed, |
48 | void *client_data); | 45 | void *client_data); |
49 | static void vmci_transport_recv_pkt_work(struct work_struct *work); | 46 | static void vmci_transport_recv_pkt_work(struct work_struct *work); |
47 | static void vmci_transport_cleanup(struct work_struct *work); | ||
50 | static int vmci_transport_recv_listen(struct sock *sk, | 48 | static int vmci_transport_recv_listen(struct sock *sk, |
51 | struct vmci_transport_packet *pkt); | 49 | struct vmci_transport_packet *pkt); |
52 | static int vmci_transport_recv_connecting_server( | 50 | static int vmci_transport_recv_connecting_server( |
@@ -75,6 +73,10 @@ struct vmci_transport_recv_pkt_info { | |||
75 | struct vmci_transport_packet pkt; | 73 | struct vmci_transport_packet pkt; |
76 | }; | 74 | }; |
77 | 75 | ||
76 | static LIST_HEAD(vmci_transport_cleanup_list); | ||
77 | static DEFINE_SPINLOCK(vmci_transport_cleanup_lock); | ||
78 | static DECLARE_WORK(vmci_transport_cleanup_work, vmci_transport_cleanup); | ||
79 | |||
78 | static struct vmci_handle vmci_transport_stream_handle = { VMCI_INVALID_ID, | 80 | static struct vmci_handle vmci_transport_stream_handle = { VMCI_INVALID_ID, |
79 | VMCI_INVALID_ID }; | 81 | VMCI_INVALID_ID }; |
80 | static u32 vmci_transport_qp_resumed_sub_id = VMCI_INVALID_ID; | 82 | static u32 vmci_transport_qp_resumed_sub_id = VMCI_INVALID_ID; |
@@ -791,44 +793,6 @@ out: | |||
791 | return err; | 793 | return err; |
792 | } | 794 | } |
793 | 795 | ||
794 | static void vmci_transport_peer_attach_cb(u32 sub_id, | ||
795 | const struct vmci_event_data *e_data, | ||
796 | void *client_data) | ||
797 | { | ||
798 | struct sock *sk = client_data; | ||
799 | const struct vmci_event_payload_qp *e_payload; | ||
800 | struct vsock_sock *vsk; | ||
801 | |||
802 | e_payload = vmci_event_data_const_payload(e_data); | ||
803 | |||
804 | vsk = vsock_sk(sk); | ||
805 | |||
806 | /* We don't ask for delayed CBs when we subscribe to this event (we | ||
807 | * pass 0 as flags to vmci_event_subscribe()). VMCI makes no | ||
808 | * guarantees in that case about what context we might be running in, | ||
809 | * so it could be BH or process, blockable or non-blockable. So we | ||
810 | * need to account for all possible contexts here. | ||
811 | */ | ||
812 | local_bh_disable(); | ||
813 | bh_lock_sock(sk); | ||
814 | |||
815 | /* XXX This is lame, we should provide a way to lookup sockets by | ||
816 | * qp_handle. | ||
817 | */ | ||
818 | if (vmci_handle_is_equal(vmci_trans(vsk)->qp_handle, | ||
819 | e_payload->handle)) { | ||
820 | /* XXX This doesn't do anything, but in the future we may want | ||
821 | * to set a flag here to verify the attach really did occur and | ||
822 | * we weren't just sent a datagram claiming it was. | ||
823 | */ | ||
824 | goto out; | ||
825 | } | ||
826 | |||
827 | out: | ||
828 | bh_unlock_sock(sk); | ||
829 | local_bh_enable(); | ||
830 | } | ||
831 | |||
832 | static void vmci_transport_handle_detach(struct sock *sk) | 796 | static void vmci_transport_handle_detach(struct sock *sk) |
833 | { | 797 | { |
834 | struct vsock_sock *vsk; | 798 | struct vsock_sock *vsk; |
@@ -871,28 +835,38 @@ static void vmci_transport_peer_detach_cb(u32 sub_id, | |||
871 | const struct vmci_event_data *e_data, | 835 | const struct vmci_event_data *e_data, |
872 | void *client_data) | 836 | void *client_data) |
873 | { | 837 | { |
874 | struct sock *sk = client_data; | 838 | struct vmci_transport *trans = client_data; |
875 | const struct vmci_event_payload_qp *e_payload; | 839 | const struct vmci_event_payload_qp *e_payload; |
876 | struct vsock_sock *vsk; | ||
877 | 840 | ||
878 | e_payload = vmci_event_data_const_payload(e_data); | 841 | e_payload = vmci_event_data_const_payload(e_data); |
879 | vsk = vsock_sk(sk); | ||
880 | if (vmci_handle_is_invalid(e_payload->handle)) | ||
881 | return; | ||
882 | |||
883 | /* Same rules for locking as for peer_attach_cb(). */ | ||
884 | local_bh_disable(); | ||
885 | bh_lock_sock(sk); | ||
886 | 842 | ||
887 | /* XXX This is lame, we should provide a way to lookup sockets by | 843 | /* XXX This is lame, we should provide a way to lookup sockets by |
888 | * qp_handle. | 844 | * qp_handle. |
889 | */ | 845 | */ |
890 | if (vmci_handle_is_equal(vmci_trans(vsk)->qp_handle, | 846 | if (vmci_handle_is_invalid(e_payload->handle) || |
891 | e_payload->handle)) | 847 | vmci_handle_is_equal(trans->qp_handle, e_payload->handle)) |
892 | vmci_transport_handle_detach(sk); | 848 | return; |
893 | 849 | ||
894 | bh_unlock_sock(sk); | 850 | /* We don't ask for delayed CBs when we subscribe to this event (we |
895 | local_bh_enable(); | 851 | * pass 0 as flags to vmci_event_subscribe()). VMCI makes no |
852 | * guarantees in that case about what context we might be running in, | ||
853 | * so it could be BH or process, blockable or non-blockable. So we | ||
854 | * need to account for all possible contexts here. | ||
855 | */ | ||
856 | spin_lock_bh(&trans->lock); | ||
857 | if (!trans->sk) | ||
858 | goto out; | ||
859 | |||
860 | /* Apart from here, trans->lock is only grabbed as part of sk destruct, | ||
861 | * where trans->sk isn't locked. | ||
862 | */ | ||
863 | bh_lock_sock(trans->sk); | ||
864 | |||
865 | vmci_transport_handle_detach(trans->sk); | ||
866 | |||
867 | bh_unlock_sock(trans->sk); | ||
868 | out: | ||
869 | spin_unlock_bh(&trans->lock); | ||
896 | } | 870 | } |
897 | 871 | ||
898 | static void vmci_transport_qp_resumed_cb(u32 sub_id, | 872 | static void vmci_transport_qp_resumed_cb(u32 sub_id, |
@@ -1181,7 +1155,7 @@ vmci_transport_recv_connecting_server(struct sock *listener, | |||
1181 | */ | 1155 | */ |
1182 | err = vmci_event_subscribe(VMCI_EVENT_QP_PEER_DETACH, | 1156 | err = vmci_event_subscribe(VMCI_EVENT_QP_PEER_DETACH, |
1183 | vmci_transport_peer_detach_cb, | 1157 | vmci_transport_peer_detach_cb, |
1184 | pending, &detach_sub_id); | 1158 | vmci_trans(vpending), &detach_sub_id); |
1185 | if (err < VMCI_SUCCESS) { | 1159 | if (err < VMCI_SUCCESS) { |
1186 | vmci_transport_send_reset(pending, pkt); | 1160 | vmci_transport_send_reset(pending, pkt); |
1187 | err = vmci_transport_error_to_vsock_error(err); | 1161 | err = vmci_transport_error_to_vsock_error(err); |
@@ -1321,7 +1295,6 @@ vmci_transport_recv_connecting_client(struct sock *sk, | |||
1321 | || vmci_trans(vsk)->qpair | 1295 | || vmci_trans(vsk)->qpair |
1322 | || vmci_trans(vsk)->produce_size != 0 | 1296 | || vmci_trans(vsk)->produce_size != 0 |
1323 | || vmci_trans(vsk)->consume_size != 0 | 1297 | || vmci_trans(vsk)->consume_size != 0 |
1324 | || vmci_trans(vsk)->attach_sub_id != VMCI_INVALID_ID | ||
1325 | || vmci_trans(vsk)->detach_sub_id != VMCI_INVALID_ID) { | 1298 | || vmci_trans(vsk)->detach_sub_id != VMCI_INVALID_ID) { |
1326 | skerr = EPROTO; | 1299 | skerr = EPROTO; |
1327 | err = -EINVAL; | 1300 | err = -EINVAL; |
@@ -1389,7 +1362,6 @@ static int vmci_transport_recv_connecting_client_negotiate( | |||
1389 | struct vsock_sock *vsk; | 1362 | struct vsock_sock *vsk; |
1390 | struct vmci_handle handle; | 1363 | struct vmci_handle handle; |
1391 | struct vmci_qp *qpair; | 1364 | struct vmci_qp *qpair; |
1392 | u32 attach_sub_id; | ||
1393 | u32 detach_sub_id; | 1365 | u32 detach_sub_id; |
1394 | bool is_local; | 1366 | bool is_local; |
1395 | u32 flags; | 1367 | u32 flags; |
@@ -1399,7 +1371,6 @@ static int vmci_transport_recv_connecting_client_negotiate( | |||
1399 | 1371 | ||
1400 | vsk = vsock_sk(sk); | 1372 | vsk = vsock_sk(sk); |
1401 | handle = VMCI_INVALID_HANDLE; | 1373 | handle = VMCI_INVALID_HANDLE; |
1402 | attach_sub_id = VMCI_INVALID_ID; | ||
1403 | detach_sub_id = VMCI_INVALID_ID; | 1374 | detach_sub_id = VMCI_INVALID_ID; |
1404 | 1375 | ||
1405 | /* If we have gotten here then we should be past the point where old | 1376 | /* If we have gotten here then we should be past the point where old |
@@ -1444,23 +1415,15 @@ static int vmci_transport_recv_connecting_client_negotiate( | |||
1444 | goto destroy; | 1415 | goto destroy; |
1445 | } | 1416 | } |
1446 | 1417 | ||
1447 | /* Subscribe to attach and detach events first. | 1418 | /* Subscribe to detach events first. |
1448 | * | 1419 | * |
1449 | * XXX We attach once for each queue pair created for now so it is easy | 1420 | * XXX We attach once for each queue pair created for now so it is easy |
1450 | * to find the socket (it's provided), but later we should only | 1421 | * to find the socket (it's provided), but later we should only |
1451 | * subscribe once and add a way to lookup sockets by queue pair handle. | 1422 | * subscribe once and add a way to lookup sockets by queue pair handle. |
1452 | */ | 1423 | */ |
1453 | err = vmci_event_subscribe(VMCI_EVENT_QP_PEER_ATTACH, | ||
1454 | vmci_transport_peer_attach_cb, | ||
1455 | sk, &attach_sub_id); | ||
1456 | if (err < VMCI_SUCCESS) { | ||
1457 | err = vmci_transport_error_to_vsock_error(err); | ||
1458 | goto destroy; | ||
1459 | } | ||
1460 | |||
1461 | err = vmci_event_subscribe(VMCI_EVENT_QP_PEER_DETACH, | 1424 | err = vmci_event_subscribe(VMCI_EVENT_QP_PEER_DETACH, |
1462 | vmci_transport_peer_detach_cb, | 1425 | vmci_transport_peer_detach_cb, |
1463 | sk, &detach_sub_id); | 1426 | vmci_trans(vsk), &detach_sub_id); |
1464 | if (err < VMCI_SUCCESS) { | 1427 | if (err < VMCI_SUCCESS) { |
1465 | err = vmci_transport_error_to_vsock_error(err); | 1428 | err = vmci_transport_error_to_vsock_error(err); |
1466 | goto destroy; | 1429 | goto destroy; |
@@ -1496,7 +1459,6 @@ static int vmci_transport_recv_connecting_client_negotiate( | |||
1496 | vmci_trans(vsk)->produce_size = vmci_trans(vsk)->consume_size = | 1459 | vmci_trans(vsk)->produce_size = vmci_trans(vsk)->consume_size = |
1497 | pkt->u.size; | 1460 | pkt->u.size; |
1498 | 1461 | ||
1499 | vmci_trans(vsk)->attach_sub_id = attach_sub_id; | ||
1500 | vmci_trans(vsk)->detach_sub_id = detach_sub_id; | 1462 | vmci_trans(vsk)->detach_sub_id = detach_sub_id; |
1501 | 1463 | ||
1502 | vmci_trans(vsk)->notify_ops->process_negotiate(sk); | 1464 | vmci_trans(vsk)->notify_ops->process_negotiate(sk); |
@@ -1504,9 +1466,6 @@ static int vmci_transport_recv_connecting_client_negotiate( | |||
1504 | return 0; | 1466 | return 0; |
1505 | 1467 | ||
1506 | destroy: | 1468 | destroy: |
1507 | if (attach_sub_id != VMCI_INVALID_ID) | ||
1508 | vmci_event_unsubscribe(attach_sub_id); | ||
1509 | |||
1510 | if (detach_sub_id != VMCI_INVALID_ID) | 1469 | if (detach_sub_id != VMCI_INVALID_ID) |
1511 | vmci_event_unsubscribe(detach_sub_id); | 1470 | vmci_event_unsubscribe(detach_sub_id); |
1512 | 1471 | ||
@@ -1607,9 +1566,11 @@ static int vmci_transport_socket_init(struct vsock_sock *vsk, | |||
1607 | vmci_trans(vsk)->qp_handle = VMCI_INVALID_HANDLE; | 1566 | vmci_trans(vsk)->qp_handle = VMCI_INVALID_HANDLE; |
1608 | vmci_trans(vsk)->qpair = NULL; | 1567 | vmci_trans(vsk)->qpair = NULL; |
1609 | vmci_trans(vsk)->produce_size = vmci_trans(vsk)->consume_size = 0; | 1568 | vmci_trans(vsk)->produce_size = vmci_trans(vsk)->consume_size = 0; |
1610 | vmci_trans(vsk)->attach_sub_id = vmci_trans(vsk)->detach_sub_id = | 1569 | vmci_trans(vsk)->detach_sub_id = VMCI_INVALID_ID; |
1611 | VMCI_INVALID_ID; | ||
1612 | vmci_trans(vsk)->notify_ops = NULL; | 1570 | vmci_trans(vsk)->notify_ops = NULL; |
1571 | INIT_LIST_HEAD(&vmci_trans(vsk)->elem); | ||
1572 | vmci_trans(vsk)->sk = &vsk->sk; | ||
1573 | spin_lock_init(&vmci_trans(vsk)->lock); | ||
1613 | if (psk) { | 1574 | if (psk) { |
1614 | vmci_trans(vsk)->queue_pair_size = | 1575 | vmci_trans(vsk)->queue_pair_size = |
1615 | vmci_trans(psk)->queue_pair_size; | 1576 | vmci_trans(psk)->queue_pair_size; |
@@ -1629,29 +1590,57 @@ static int vmci_transport_socket_init(struct vsock_sock *vsk, | |||
1629 | return 0; | 1590 | return 0; |
1630 | } | 1591 | } |
1631 | 1592 | ||
1632 | static void vmci_transport_destruct(struct vsock_sock *vsk) | 1593 | static void vmci_transport_free_resources(struct list_head *transport_list) |
1633 | { | 1594 | { |
1634 | if (vmci_trans(vsk)->attach_sub_id != VMCI_INVALID_ID) { | 1595 | while (!list_empty(transport_list)) { |
1635 | vmci_event_unsubscribe(vmci_trans(vsk)->attach_sub_id); | 1596 | struct vmci_transport *transport = |
1636 | vmci_trans(vsk)->attach_sub_id = VMCI_INVALID_ID; | 1597 | list_first_entry(transport_list, struct vmci_transport, |
1637 | } | 1598 | elem); |
1599 | list_del(&transport->elem); | ||
1638 | 1600 | ||
1639 | if (vmci_trans(vsk)->detach_sub_id != VMCI_INVALID_ID) { | 1601 | if (transport->detach_sub_id != VMCI_INVALID_ID) { |
1640 | vmci_event_unsubscribe(vmci_trans(vsk)->detach_sub_id); | 1602 | vmci_event_unsubscribe(transport->detach_sub_id); |
1641 | vmci_trans(vsk)->detach_sub_id = VMCI_INVALID_ID; | 1603 | transport->detach_sub_id = VMCI_INVALID_ID; |
1642 | } | 1604 | } |
1643 | 1605 | ||
1644 | if (!vmci_handle_is_invalid(vmci_trans(vsk)->qp_handle)) { | 1606 | if (!vmci_handle_is_invalid(transport->qp_handle)) { |
1645 | vmci_qpair_detach(&vmci_trans(vsk)->qpair); | 1607 | vmci_qpair_detach(&transport->qpair); |
1646 | vmci_trans(vsk)->qp_handle = VMCI_INVALID_HANDLE; | 1608 | transport->qp_handle = VMCI_INVALID_HANDLE; |
1647 | vmci_trans(vsk)->produce_size = 0; | 1609 | transport->produce_size = 0; |
1648 | vmci_trans(vsk)->consume_size = 0; | 1610 | transport->consume_size = 0; |
1611 | } | ||
1612 | |||
1613 | kfree(transport); | ||
1649 | } | 1614 | } |
1615 | } | ||
1616 | |||
1617 | static void vmci_transport_cleanup(struct work_struct *work) | ||
1618 | { | ||
1619 | LIST_HEAD(pending); | ||
1620 | |||
1621 | spin_lock_bh(&vmci_transport_cleanup_lock); | ||
1622 | list_replace_init(&vmci_transport_cleanup_list, &pending); | ||
1623 | spin_unlock_bh(&vmci_transport_cleanup_lock); | ||
1624 | vmci_transport_free_resources(&pending); | ||
1625 | } | ||
1626 | |||
1627 | static void vmci_transport_destruct(struct vsock_sock *vsk) | ||
1628 | { | ||
1629 | /* Ensure that the detach callback doesn't use the sk/vsk | ||
1630 | * we are about to destruct. | ||
1631 | */ | ||
1632 | spin_lock_bh(&vmci_trans(vsk)->lock); | ||
1633 | vmci_trans(vsk)->sk = NULL; | ||
1634 | spin_unlock_bh(&vmci_trans(vsk)->lock); | ||
1650 | 1635 | ||
1651 | if (vmci_trans(vsk)->notify_ops) | 1636 | if (vmci_trans(vsk)->notify_ops) |
1652 | vmci_trans(vsk)->notify_ops->socket_destruct(vsk); | 1637 | vmci_trans(vsk)->notify_ops->socket_destruct(vsk); |
1653 | 1638 | ||
1654 | kfree(vsk->trans); | 1639 | spin_lock_bh(&vmci_transport_cleanup_lock); |
1640 | list_add(&vmci_trans(vsk)->elem, &vmci_transport_cleanup_list); | ||
1641 | spin_unlock_bh(&vmci_transport_cleanup_lock); | ||
1642 | schedule_work(&vmci_transport_cleanup_work); | ||
1643 | |||
1655 | vsk->trans = NULL; | 1644 | vsk->trans = NULL; |
1656 | } | 1645 | } |
1657 | 1646 | ||
@@ -2146,6 +2135,9 @@ module_init(vmci_transport_init); | |||
2146 | 2135 | ||
2147 | static void __exit vmci_transport_exit(void) | 2136 | static void __exit vmci_transport_exit(void) |
2148 | { | 2137 | { |
2138 | cancel_work_sync(&vmci_transport_cleanup_work); | ||
2139 | vmci_transport_free_resources(&vmci_transport_cleanup_list); | ||
2140 | |||
2149 | if (!vmci_handle_is_invalid(vmci_transport_stream_handle)) { | 2141 | if (!vmci_handle_is_invalid(vmci_transport_stream_handle)) { |
2150 | if (vmci_datagram_destroy_handle( | 2142 | if (vmci_datagram_destroy_handle( |
2151 | vmci_transport_stream_handle) != VMCI_SUCCESS) | 2143 | vmci_transport_stream_handle) != VMCI_SUCCESS) |
@@ -2164,6 +2156,7 @@ module_exit(vmci_transport_exit); | |||
2164 | 2156 | ||
2165 | MODULE_AUTHOR("VMware, Inc."); | 2157 | MODULE_AUTHOR("VMware, Inc."); |
2166 | MODULE_DESCRIPTION("VMCI transport for Virtual Sockets"); | 2158 | MODULE_DESCRIPTION("VMCI transport for Virtual Sockets"); |
2159 | MODULE_VERSION("1.0.2.0-k"); | ||
2167 | MODULE_LICENSE("GPL v2"); | 2160 | MODULE_LICENSE("GPL v2"); |
2168 | MODULE_ALIAS("vmware_vsock"); | 2161 | MODULE_ALIAS("vmware_vsock"); |
2169 | MODULE_ALIAS_NETPROTO(PF_VSOCK); | 2162 | MODULE_ALIAS_NETPROTO(PF_VSOCK); |
diff --git a/net/vmw_vsock/vmci_transport.h b/net/vmw_vsock/vmci_transport.h index ce6c9623d5f0..2ad46f39649f 100644 --- a/net/vmw_vsock/vmci_transport.h +++ b/net/vmw_vsock/vmci_transport.h | |||
@@ -119,10 +119,12 @@ struct vmci_transport { | |||
119 | u64 queue_pair_size; | 119 | u64 queue_pair_size; |
120 | u64 queue_pair_min_size; | 120 | u64 queue_pair_min_size; |
121 | u64 queue_pair_max_size; | 121 | u64 queue_pair_max_size; |
122 | u32 attach_sub_id; | ||
123 | u32 detach_sub_id; | 122 | u32 detach_sub_id; |
124 | union vmci_transport_notify notify; | 123 | union vmci_transport_notify notify; |
125 | struct vmci_transport_notify_ops *notify_ops; | 124 | struct vmci_transport_notify_ops *notify_ops; |
125 | struct list_head elem; | ||
126 | struct sock *sk; | ||
127 | spinlock_t lock; /* protects sk. */ | ||
126 | }; | 128 | }; |
127 | 129 | ||
128 | int vmci_transport_register(void); | 130 | int vmci_transport_register(void); |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index a8de9e300200..24e06a2377f6 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -1928,8 +1928,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1928 | struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; | 1928 | struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; |
1929 | struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL]; | 1929 | struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL]; |
1930 | struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; | 1930 | struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; |
1931 | struct nlattr *et = attrs[XFRMA_ETIMER_THRESH]; | ||
1932 | struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH]; | ||
1931 | 1933 | ||
1932 | if (!lt && !rp && !re) | 1934 | if (!lt && !rp && !re && !et && !rt) |
1933 | return err; | 1935 | return err; |
1934 | 1936 | ||
1935 | /* pedantic mode - thou shalt sayeth replaceth */ | 1937 | /* pedantic mode - thou shalt sayeth replaceth */ |