diff options
37 files changed, 401 insertions, 217 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index dc280bc8eba2..6c884ef1b069 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
| @@ -2536,7 +2536,7 @@ config S6GMAC | |||
| 2536 | source "drivers/net/stmmac/Kconfig" | 2536 | source "drivers/net/stmmac/Kconfig" |
| 2537 | 2537 | ||
| 2538 | config PCH_GBE | 2538 | config PCH_GBE |
| 2539 | tristate "PCH Gigabit Ethernet" | 2539 | tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GbE" |
| 2540 | depends on PCI | 2540 | depends on PCI |
| 2541 | select MII | 2541 | select MII |
| 2542 | ---help--- | 2542 | ---help--- |
| @@ -2548,6 +2548,12 @@ config PCH_GBE | |||
| 2548 | to Gigabit Ethernet. | 2548 | to Gigabit Ethernet. |
| 2549 | This driver enables Gigabit Ethernet function. | 2549 | This driver enables Gigabit Ethernet function. |
| 2550 | 2550 | ||
| 2551 | This driver also can be used for OKI SEMICONDUCTOR IOH(Input/ | ||
| 2552 | Output Hub), ML7223. | ||
| 2553 | ML7223 IOH is for MP(Media Phone) use. | ||
| 2554 | ML7223 is companion chip for Intel Atom E6xx series. | ||
| 2555 | ML7223 is completely compatible for Intel EG20T PCH. | ||
| 2556 | |||
| 2551 | endif # NETDEV_1000 | 2557 | endif # NETDEV_1000 |
| 2552 | 2558 | ||
| 2553 | # | 2559 | # |
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index a0b4743d7224..41bbc32123f8 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h | |||
| @@ -212,7 +212,7 @@ struct be_rx_stats { | |||
| 212 | 212 | ||
| 213 | struct be_rx_compl_info { | 213 | struct be_rx_compl_info { |
| 214 | u32 rss_hash; | 214 | u32 rss_hash; |
| 215 | u16 vid; | 215 | u16 vlan_tag; |
| 216 | u16 pkt_size; | 216 | u16 pkt_size; |
| 217 | u16 rxq_idx; | 217 | u16 rxq_idx; |
| 218 | u16 mac_id; | 218 | u16 mac_id; |
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 0fc06d363806..5fedc27c8839 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c | |||
| @@ -133,7 +133,7 @@ static void be_async_grp5_pvid_state_process(struct be_adapter *adapter, | |||
| 133 | struct be_async_event_grp5_pvid_state *evt) | 133 | struct be_async_event_grp5_pvid_state *evt) |
| 134 | { | 134 | { |
| 135 | if (evt->enabled) | 135 | if (evt->enabled) |
| 136 | adapter->pvid = evt->tag; | 136 | adapter->pvid = le16_to_cpu(evt->tag); |
| 137 | else | 137 | else |
| 138 | adapter->pvid = 0; | 138 | adapter->pvid = 0; |
| 139 | } | 139 | } |
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 7b19931acba1..3fb4a1f465e1 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c | |||
| @@ -1017,7 +1017,8 @@ static void be_rx_compl_process(struct be_adapter *adapter, | |||
| 1017 | kfree_skb(skb); | 1017 | kfree_skb(skb); |
| 1018 | return; | 1018 | return; |
| 1019 | } | 1019 | } |
| 1020 | vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, rxcp->vid); | 1020 | vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, |
| 1021 | rxcp->vlan_tag); | ||
| 1021 | } else { | 1022 | } else { |
| 1022 | netif_receive_skb(skb); | 1023 | netif_receive_skb(skb); |
| 1023 | } | 1024 | } |
| @@ -1077,7 +1078,8 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, | |||
| 1077 | if (likely(!rxcp->vlanf)) | 1078 | if (likely(!rxcp->vlanf)) |
| 1078 | napi_gro_frags(&eq_obj->napi); | 1079 | napi_gro_frags(&eq_obj->napi); |
| 1079 | else | 1080 | else |
| 1080 | vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, rxcp->vid); | 1081 | vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, |
| 1082 | rxcp->vlan_tag); | ||
| 1081 | } | 1083 | } |
| 1082 | 1084 | ||
| 1083 | static void be_parse_rx_compl_v1(struct be_adapter *adapter, | 1085 | static void be_parse_rx_compl_v1(struct be_adapter *adapter, |
| @@ -1106,9 +1108,9 @@ static void be_parse_rx_compl_v1(struct be_adapter *adapter, | |||
| 1106 | AMAP_GET_BITS(struct amap_eth_rx_compl_v1, rsshash, rxcp); | 1108 | AMAP_GET_BITS(struct amap_eth_rx_compl_v1, rsshash, rxcp); |
| 1107 | if (rxcp->vlanf) { | 1109 | if (rxcp->vlanf) { |
| 1108 | rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtm, | 1110 | rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtm, |
| 1109 | compl); | 1111 | compl); |
| 1110 | rxcp->vid = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vlan_tag, | 1112 | rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vlan_tag, |
| 1111 | compl); | 1113 | compl); |
| 1112 | } | 1114 | } |
| 1113 | } | 1115 | } |
| 1114 | 1116 | ||
| @@ -1138,9 +1140,9 @@ static void be_parse_rx_compl_v0(struct be_adapter *adapter, | |||
| 1138 | AMAP_GET_BITS(struct amap_eth_rx_compl_v0, rsshash, rxcp); | 1140 | AMAP_GET_BITS(struct amap_eth_rx_compl_v0, rsshash, rxcp); |
| 1139 | if (rxcp->vlanf) { | 1141 | if (rxcp->vlanf) { |
| 1140 | rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtm, | 1142 | rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtm, |
| 1141 | compl); | 1143 | compl); |
| 1142 | rxcp->vid = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vlan_tag, | 1144 | rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vlan_tag, |
| 1143 | compl); | 1145 | compl); |
| 1144 | } | 1146 | } |
| 1145 | } | 1147 | } |
| 1146 | 1148 | ||
| @@ -1170,10 +1172,11 @@ static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo) | |||
| 1170 | rxcp->vlanf = 0; | 1172 | rxcp->vlanf = 0; |
| 1171 | 1173 | ||
| 1172 | if (!lancer_chip(adapter)) | 1174 | if (!lancer_chip(adapter)) |
| 1173 | rxcp->vid = swab16(rxcp->vid); | 1175 | rxcp->vlan_tag = swab16(rxcp->vlan_tag); |
| 1174 | 1176 | ||
| 1175 | if ((adapter->pvid == rxcp->vid) && | 1177 | if (((adapter->pvid & VLAN_VID_MASK) == |
| 1176 | !adapter->vlan_tag[rxcp->vid]) | 1178 | (rxcp->vlan_tag & VLAN_VID_MASK)) && |
| 1179 | !adapter->vlan_tag[rxcp->vlan_tag]) | ||
| 1177 | rxcp->vlanf = 0; | 1180 | rxcp->vlanf = 0; |
| 1178 | } | 1181 | } |
| 1179 | 1182 | ||
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index b423965a78d1..1b49df6b2470 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c | |||
| @@ -583,7 +583,9 @@ static int slcan_open(struct tty_struct *tty) | |||
| 583 | /* Done. We have linked the TTY line to a channel. */ | 583 | /* Done. We have linked the TTY line to a channel. */ |
| 584 | rtnl_unlock(); | 584 | rtnl_unlock(); |
| 585 | tty->receive_room = 65536; /* We don't flow control */ | 585 | tty->receive_room = 65536; /* We don't flow control */ |
| 586 | return sl->dev->base_addr; | 586 | |
| 587 | /* TTY layer expects 0 on success */ | ||
| 588 | return 0; | ||
| 587 | 589 | ||
| 588 | err_free_chan: | 590 | err_free_chan: |
| 589 | sl->tty = NULL; | 591 | sl->tty = NULL; |
diff --git a/drivers/net/ehea/ehea_ethtool.c b/drivers/net/ehea/ehea_ethtool.c index 1df5f40c646d..7f642aef5e82 100644 --- a/drivers/net/ehea/ehea_ethtool.c +++ b/drivers/net/ehea/ehea_ethtool.c | |||
| @@ -68,15 +68,20 @@ static int ehea_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
| 68 | } | 68 | } |
| 69 | ethtool_cmd_speed_set(cmd, speed); | 69 | ethtool_cmd_speed_set(cmd, speed); |
| 70 | 70 | ||
| 71 | cmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_1000baseT_Full | 71 | if (cmd->speed == SPEED_10000) { |
| 72 | | SUPPORTED_100baseT_Full | SUPPORTED_100baseT_Half | 72 | cmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); |
| 73 | | SUPPORTED_10baseT_Full | SUPPORTED_10baseT_Half | 73 | cmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE); |
| 74 | | SUPPORTED_Autoneg | SUPPORTED_FIBRE); | 74 | cmd->port = PORT_FIBRE; |
| 75 | 75 | } else { | |
| 76 | cmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_Autoneg | 76 | cmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full |
| 77 | | ADVERTISED_FIBRE); | 77 | | SUPPORTED_100baseT_Half | SUPPORTED_10baseT_Full |
| 78 | | SUPPORTED_10baseT_Half | SUPPORTED_Autoneg | ||
| 79 | | SUPPORTED_TP); | ||
| 80 | cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | ||
| 81 | | ADVERTISED_TP); | ||
| 82 | cmd->port = PORT_TP; | ||
| 83 | } | ||
| 78 | 84 | ||
| 79 | cmd->port = PORT_FIBRE; | ||
| 80 | cmd->autoneg = port->autoneg == 1 ? AUTONEG_ENABLE : AUTONEG_DISABLE; | 85 | cmd->autoneg = port->autoneg == 1 ? AUTONEG_ENABLE : AUTONEG_DISABLE; |
| 81 | 86 | ||
| 82 | return 0; | 87 | return 0; |
diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c index f3e4b0adae93..c2476fd96573 100644 --- a/drivers/net/pch_gbe/pch_gbe_main.c +++ b/drivers/net/pch_gbe/pch_gbe_main.c | |||
| @@ -34,6 +34,10 @@ const char pch_driver_version[] = DRV_VERSION; | |||
| 34 | #define PCH_GBE_COPYBREAK_DEFAULT 256 | 34 | #define PCH_GBE_COPYBREAK_DEFAULT 256 |
| 35 | #define PCH_GBE_PCI_BAR 1 | 35 | #define PCH_GBE_PCI_BAR 1 |
| 36 | 36 | ||
| 37 | /* Macros for ML7223 */ | ||
| 38 | #define PCI_VENDOR_ID_ROHM 0x10db | ||
| 39 | #define PCI_DEVICE_ID_ROHM_ML7223_GBE 0x8013 | ||
| 40 | |||
| 37 | #define PCH_GBE_TX_WEIGHT 64 | 41 | #define PCH_GBE_TX_WEIGHT 64 |
| 38 | #define PCH_GBE_RX_WEIGHT 64 | 42 | #define PCH_GBE_RX_WEIGHT 64 |
| 39 | #define PCH_GBE_RX_BUFFER_WRITE 16 | 43 | #define PCH_GBE_RX_BUFFER_WRITE 16 |
| @@ -43,8 +47,7 @@ const char pch_driver_version[] = DRV_VERSION; | |||
| 43 | 47 | ||
| 44 | #define PCH_GBE_MAC_RGMII_CTRL_SETTING ( \ | 48 | #define PCH_GBE_MAC_RGMII_CTRL_SETTING ( \ |
| 45 | PCH_GBE_CHIP_TYPE_INTERNAL | \ | 49 | PCH_GBE_CHIP_TYPE_INTERNAL | \ |
| 46 | PCH_GBE_RGMII_MODE_RGMII | \ | 50 | PCH_GBE_RGMII_MODE_RGMII \ |
| 47 | PCH_GBE_CRS_SEL \ | ||
| 48 | ) | 51 | ) |
| 49 | 52 | ||
| 50 | /* Ethertype field values */ | 53 | /* Ethertype field values */ |
| @@ -1495,12 +1498,11 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter, | |||
| 1495 | /* Write meta date of skb */ | 1498 | /* Write meta date of skb */ |
| 1496 | skb_put(skb, length); | 1499 | skb_put(skb, length); |
| 1497 | skb->protocol = eth_type_trans(skb, netdev); | 1500 | skb->protocol = eth_type_trans(skb, netdev); |
| 1498 | if ((tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK) == | 1501 | if (tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK) |
| 1499 | PCH_GBE_RXD_ACC_STAT_TCPIPOK) { | ||
| 1500 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
| 1501 | } else { | ||
| 1502 | skb->ip_summed = CHECKSUM_NONE; | 1502 | skb->ip_summed = CHECKSUM_NONE; |
| 1503 | } | 1503 | else |
| 1504 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
| 1505 | |||
| 1504 | napi_gro_receive(&adapter->napi, skb); | 1506 | napi_gro_receive(&adapter->napi, skb); |
| 1505 | (*work_done)++; | 1507 | (*work_done)++; |
| 1506 | pr_debug("Receive skb->ip_summed: %d length: %d\n", | 1508 | pr_debug("Receive skb->ip_summed: %d length: %d\n", |
| @@ -2442,6 +2444,13 @@ static DEFINE_PCI_DEVICE_TABLE(pch_gbe_pcidev_id) = { | |||
| 2442 | .class = (PCI_CLASS_NETWORK_ETHERNET << 8), | 2444 | .class = (PCI_CLASS_NETWORK_ETHERNET << 8), |
| 2443 | .class_mask = (0xFFFF00) | 2445 | .class_mask = (0xFFFF00) |
| 2444 | }, | 2446 | }, |
| 2447 | {.vendor = PCI_VENDOR_ID_ROHM, | ||
| 2448 | .device = PCI_DEVICE_ID_ROHM_ML7223_GBE, | ||
| 2449 | .subvendor = PCI_ANY_ID, | ||
| 2450 | .subdevice = PCI_ANY_ID, | ||
| 2451 | .class = (PCI_CLASS_NETWORK_ETHERNET << 8), | ||
| 2452 | .class_mask = (0xFFFF00) | ||
| 2453 | }, | ||
| 2445 | /* required last entry */ | 2454 | /* required last entry */ |
| 2446 | {0} | 2455 | {0} |
| 2447 | }; | 2456 | }; |
diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 86cbb9ea2f26..8ec1a9a0bb9a 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c | |||
| @@ -853,7 +853,9 @@ static int slip_open(struct tty_struct *tty) | |||
| 853 | /* Done. We have linked the TTY line to a channel. */ | 853 | /* Done. We have linked the TTY line to a channel. */ |
| 854 | rtnl_unlock(); | 854 | rtnl_unlock(); |
| 855 | tty->receive_room = 65536; /* We don't flow control */ | 855 | tty->receive_room = 65536; /* We don't flow control */ |
| 856 | return sl->dev->base_addr; | 856 | |
| 857 | /* TTY layer expects 0 on success */ | ||
| 858 | return 0; | ||
| 857 | 859 | ||
| 858 | err_free_bufs: | 860 | err_free_bufs: |
| 859 | sl_free_bufs(sl); | 861 | sl_free_bufs(sl); |
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index a301479ecc60..c924ea2bce07 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c | |||
| @@ -567,7 +567,7 @@ static const struct usb_device_id products [] = { | |||
| 567 | { | 567 | { |
| 568 | USB_DEVICE_AND_INTERFACE_INFO(0x1004, 0x61aa, USB_CLASS_COMM, | 568 | USB_DEVICE_AND_INTERFACE_INFO(0x1004, 0x61aa, USB_CLASS_COMM, |
| 569 | USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), | 569 | USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), |
| 570 | .driver_info = 0, | 570 | .driver_info = (unsigned long)&wwan_info, |
| 571 | }, | 571 | }, |
| 572 | 572 | ||
| 573 | /* | 573 | /* |
diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 7d42f9a2c068..81126ff85e05 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c | |||
| @@ -65,6 +65,7 @@ | |||
| 65 | #define IPHETH_USBINTF_PROTO 1 | 65 | #define IPHETH_USBINTF_PROTO 1 |
| 66 | 66 | ||
| 67 | #define IPHETH_BUF_SIZE 1516 | 67 | #define IPHETH_BUF_SIZE 1516 |
| 68 | #define IPHETH_IP_ALIGN 2 /* padding at front of URB */ | ||
| 68 | #define IPHETH_TX_TIMEOUT (5 * HZ) | 69 | #define IPHETH_TX_TIMEOUT (5 * HZ) |
| 69 | 70 | ||
| 70 | #define IPHETH_INTFNUM 2 | 71 | #define IPHETH_INTFNUM 2 |
| @@ -202,18 +203,21 @@ static void ipheth_rcvbulk_callback(struct urb *urb) | |||
| 202 | return; | 203 | return; |
| 203 | } | 204 | } |
| 204 | 205 | ||
| 205 | len = urb->actual_length; | 206 | if (urb->actual_length <= IPHETH_IP_ALIGN) { |
| 206 | buf = urb->transfer_buffer; | 207 | dev->net->stats.rx_length_errors++; |
| 208 | return; | ||
| 209 | } | ||
| 210 | len = urb->actual_length - IPHETH_IP_ALIGN; | ||
| 211 | buf = urb->transfer_buffer + IPHETH_IP_ALIGN; | ||
| 207 | 212 | ||
| 208 | skb = dev_alloc_skb(NET_IP_ALIGN + len); | 213 | skb = dev_alloc_skb(len); |
| 209 | if (!skb) { | 214 | if (!skb) { |
| 210 | err("%s: dev_alloc_skb: -ENOMEM", __func__); | 215 | err("%s: dev_alloc_skb: -ENOMEM", __func__); |
| 211 | dev->net->stats.rx_dropped++; | 216 | dev->net->stats.rx_dropped++; |
| 212 | return; | 217 | return; |
| 213 | } | 218 | } |
| 214 | 219 | ||
| 215 | skb_reserve(skb, NET_IP_ALIGN); | 220 | memcpy(skb_put(skb, len), buf, len); |
| 216 | memcpy(skb_put(skb, len), buf + NET_IP_ALIGN, len - NET_IP_ALIGN); | ||
| 217 | skb->dev = dev->net; | 221 | skb->dev = dev->net; |
| 218 | skb->protocol = eth_type_trans(skb, dev->net); | 222 | skb->protocol = eth_type_trans(skb, dev->net); |
| 219 | 223 | ||
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 7a494f79c88f..c0da23096160 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c | |||
| @@ -178,6 +178,7 @@ static void | |||
| 178 | vmxnet3_process_events(struct vmxnet3_adapter *adapter) | 178 | vmxnet3_process_events(struct vmxnet3_adapter *adapter) |
| 179 | { | 179 | { |
| 180 | int i; | 180 | int i; |
| 181 | unsigned long flags; | ||
| 181 | u32 events = le32_to_cpu(adapter->shared->ecr); | 182 | u32 events = le32_to_cpu(adapter->shared->ecr); |
| 182 | if (!events) | 183 | if (!events) |
| 183 | return; | 184 | return; |
| @@ -190,10 +191,10 @@ vmxnet3_process_events(struct vmxnet3_adapter *adapter) | |||
| 190 | 191 | ||
| 191 | /* Check if there is an error on xmit/recv queues */ | 192 | /* Check if there is an error on xmit/recv queues */ |
| 192 | if (events & (VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR)) { | 193 | if (events & (VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR)) { |
| 193 | spin_lock(&adapter->cmd_lock); | 194 | spin_lock_irqsave(&adapter->cmd_lock, flags); |
| 194 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, | 195 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, |
| 195 | VMXNET3_CMD_GET_QUEUE_STATUS); | 196 | VMXNET3_CMD_GET_QUEUE_STATUS); |
| 196 | spin_unlock(&adapter->cmd_lock); | 197 | spin_unlock_irqrestore(&adapter->cmd_lock, flags); |
| 197 | 198 | ||
| 198 | for (i = 0; i < adapter->num_tx_queues; i++) | 199 | for (i = 0; i < adapter->num_tx_queues; i++) |
| 199 | if (adapter->tqd_start[i].status.stopped) | 200 | if (adapter->tqd_start[i].status.stopped) |
| @@ -2720,13 +2721,14 @@ static void | |||
| 2720 | vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter) | 2721 | vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter) |
| 2721 | { | 2722 | { |
| 2722 | u32 cfg; | 2723 | u32 cfg; |
| 2724 | unsigned long flags; | ||
| 2723 | 2725 | ||
| 2724 | /* intr settings */ | 2726 | /* intr settings */ |
| 2725 | spin_lock(&adapter->cmd_lock); | 2727 | spin_lock_irqsave(&adapter->cmd_lock, flags); |
| 2726 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, | 2728 | VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, |
| 2727 | VMXNET3_CMD_GET_CONF_INTR); | 2729 | VMXNET3_CMD_GET_CONF_INTR); |
| 2728 | cfg = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD); | 2730 | cfg = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD); |
| 2729 | spin_unlock(&adapter->cmd_lock); | 2731 | spin_unlock_irqrestore(&adapter->cmd_lock, flags); |
| 2730 | adapter->intr.type = cfg & 0x3; | 2732 | adapter->intr.type = cfg & 0x3; |
| 2731 | adapter->intr.mask_mode = (cfg >> 2) & 0x3; | 2733 | adapter->intr.mask_mode = (cfg >> 2) & 0x3; |
| 2732 | 2734 | ||
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index e0b7f139aa88..9d1f510ab6d0 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h | |||
| @@ -788,6 +788,7 @@ struct ip_vs_app { | |||
| 788 | /* IPVS in network namespace */ | 788 | /* IPVS in network namespace */ |
| 789 | struct netns_ipvs { | 789 | struct netns_ipvs { |
| 790 | int gen; /* Generation */ | 790 | int gen; /* Generation */ |
| 791 | int enable; /* enable like nf_hooks do */ | ||
| 791 | /* | 792 | /* |
| 792 | * Hash table: for real service lookups | 793 | * Hash table: for real service lookups |
| 793 | */ | 794 | */ |
| @@ -1086,6 +1087,22 @@ ip_vs_control_add(struct ip_vs_conn *cp, struct ip_vs_conn *ctl_cp) | |||
| 1086 | atomic_inc(&ctl_cp->n_control); | 1087 | atomic_inc(&ctl_cp->n_control); |
| 1087 | } | 1088 | } |
| 1088 | 1089 | ||
| 1090 | /* | ||
| 1091 | * IPVS netns init & cleanup functions | ||
| 1092 | */ | ||
| 1093 | extern int __ip_vs_estimator_init(struct net *net); | ||
| 1094 | extern int __ip_vs_control_init(struct net *net); | ||
| 1095 | extern int __ip_vs_protocol_init(struct net *net); | ||
| 1096 | extern int __ip_vs_app_init(struct net *net); | ||
| 1097 | extern int __ip_vs_conn_init(struct net *net); | ||
| 1098 | extern int __ip_vs_sync_init(struct net *net); | ||
| 1099 | extern void __ip_vs_conn_cleanup(struct net *net); | ||
| 1100 | extern void __ip_vs_app_cleanup(struct net *net); | ||
| 1101 | extern void __ip_vs_protocol_cleanup(struct net *net); | ||
| 1102 | extern void __ip_vs_control_cleanup(struct net *net); | ||
| 1103 | extern void __ip_vs_estimator_cleanup(struct net *net); | ||
| 1104 | extern void __ip_vs_sync_cleanup(struct net *net); | ||
| 1105 | extern void __ip_vs_service_cleanup(struct net *net); | ||
| 1089 | 1106 | ||
| 1090 | /* | 1107 | /* |
| 1091 | * IPVS application functions | 1108 | * IPVS application functions |
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 1cdd4b7b2861..b203e14d26b7 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
| @@ -324,6 +324,7 @@ struct xfrm_state_afinfo { | |||
| 324 | int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n); | 324 | int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n); |
| 325 | int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n); | 325 | int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n); |
| 326 | int (*output)(struct sk_buff *skb); | 326 | int (*output)(struct sk_buff *skb); |
| 327 | int (*output_finish)(struct sk_buff *skb); | ||
| 327 | int (*extract_input)(struct xfrm_state *x, | 328 | int (*extract_input)(struct xfrm_state *x, |
| 328 | struct sk_buff *skb); | 329 | struct sk_buff *skb); |
| 329 | int (*extract_output)(struct xfrm_state *x, | 330 | int (*extract_output)(struct xfrm_state *x, |
| @@ -1463,6 +1464,7 @@ static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi) | |||
| 1463 | extern int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb); | 1464 | extern int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb); |
| 1464 | extern int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb); | 1465 | extern int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb); |
| 1465 | extern int xfrm4_output(struct sk_buff *skb); | 1466 | extern int xfrm4_output(struct sk_buff *skb); |
| 1467 | extern int xfrm4_output_finish(struct sk_buff *skb); | ||
| 1466 | extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family); | 1468 | extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family); |
| 1467 | extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family); | 1469 | extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family); |
| 1468 | extern int xfrm6_extract_header(struct sk_buff *skb); | 1470 | extern int xfrm6_extract_header(struct sk_buff *skb); |
| @@ -1479,6 +1481,7 @@ extern __be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *sad | |||
| 1479 | extern int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb); | 1481 | extern int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb); |
| 1480 | extern int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb); | 1482 | extern int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb); |
| 1481 | extern int xfrm6_output(struct sk_buff *skb); | 1483 | extern int xfrm6_output(struct sk_buff *skb); |
| 1484 | extern int xfrm6_output_finish(struct sk_buff *skb); | ||
| 1482 | extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb, | 1485 | extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb, |
| 1483 | u8 **prevhdr); | 1486 | u8 **prevhdr); |
| 1484 | 1487 | ||
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 718d635d3379..b2274d1fd605 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
| @@ -119,6 +119,9 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) | |||
| 119 | 119 | ||
| 120 | grp->nr_vlans--; | 120 | grp->nr_vlans--; |
| 121 | 121 | ||
| 122 | if (vlan->flags & VLAN_FLAG_GVRP) | ||
| 123 | vlan_gvrp_request_leave(dev); | ||
| 124 | |||
| 122 | vlan_group_set_device(grp, vlan_id, NULL); | 125 | vlan_group_set_device(grp, vlan_id, NULL); |
| 123 | /* Because unregister_netdevice_queue() makes sure at least one rcu | 126 | /* Because unregister_netdevice_queue() makes sure at least one rcu |
| 124 | * grace period is respected before device freeing, | 127 | * grace period is respected before device freeing, |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index d174c312b7f1..58f8010e1aef 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
| @@ -314,9 +314,6 @@ static int vlan_dev_stop(struct net_device *dev) | |||
| 314 | struct vlan_dev_info *vlan = vlan_dev_info(dev); | 314 | struct vlan_dev_info *vlan = vlan_dev_info(dev); |
| 315 | struct net_device *real_dev = vlan->real_dev; | 315 | struct net_device *real_dev = vlan->real_dev; |
| 316 | 316 | ||
| 317 | if (vlan->flags & VLAN_FLAG_GVRP) | ||
| 318 | vlan_gvrp_request_leave(dev); | ||
| 319 | |||
| 320 | dev_mc_unsync(real_dev, dev); | 317 | dev_mc_unsync(real_dev, dev); |
| 321 | dev_uc_unsync(real_dev, dev); | 318 | dev_uc_unsync(real_dev, dev); |
| 322 | if (dev->flags & IFF_ALLMULTI) | 319 | if (dev->flags & IFF_ALLMULTI) |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 893669caa8de..1a92b369c820 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
| @@ -1766,7 +1766,7 @@ static int compat_table_info(const struct ebt_table_info *info, | |||
| 1766 | 1766 | ||
| 1767 | newinfo->entries_size = size; | 1767 | newinfo->entries_size = size; |
| 1768 | 1768 | ||
| 1769 | xt_compat_init_offsets(AF_INET, info->nentries); | 1769 | xt_compat_init_offsets(NFPROTO_BRIDGE, info->nentries); |
| 1770 | return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info, | 1770 | return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info, |
| 1771 | entries, newinfo); | 1771 | entries, newinfo); |
| 1772 | } | 1772 | } |
| @@ -1882,7 +1882,7 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, | |||
| 1882 | struct xt_match *match; | 1882 | struct xt_match *match; |
| 1883 | struct xt_target *wt; | 1883 | struct xt_target *wt; |
| 1884 | void *dst = NULL; | 1884 | void *dst = NULL; |
| 1885 | int off, pad = 0, ret = 0; | 1885 | int off, pad = 0; |
| 1886 | unsigned int size_kern, entry_offset, match_size = mwt->match_size; | 1886 | unsigned int size_kern, entry_offset, match_size = mwt->match_size; |
| 1887 | 1887 | ||
| 1888 | strlcpy(name, mwt->u.name, sizeof(name)); | 1888 | strlcpy(name, mwt->u.name, sizeof(name)); |
| @@ -1935,13 +1935,6 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, | |||
| 1935 | break; | 1935 | break; |
| 1936 | } | 1936 | } |
| 1937 | 1937 | ||
| 1938 | if (!dst) { | ||
| 1939 | ret = xt_compat_add_offset(NFPROTO_BRIDGE, entry_offset, | ||
| 1940 | off + ebt_compat_entry_padsize()); | ||
| 1941 | if (ret < 0) | ||
| 1942 | return ret; | ||
| 1943 | } | ||
| 1944 | |||
| 1945 | state->buf_kern_offset += match_size + off; | 1938 | state->buf_kern_offset += match_size + off; |
| 1946 | state->buf_user_offset += match_size; | 1939 | state->buf_user_offset += match_size; |
| 1947 | pad = XT_ALIGN(size_kern) - size_kern; | 1940 | pad = XT_ALIGN(size_kern) - size_kern; |
| @@ -2016,50 +2009,6 @@ static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32, | |||
| 2016 | return growth; | 2009 | return growth; |
| 2017 | } | 2010 | } |
| 2018 | 2011 | ||
| 2019 | #define EBT_COMPAT_WATCHER_ITERATE(e, fn, args...) \ | ||
| 2020 | ({ \ | ||
| 2021 | unsigned int __i; \ | ||
| 2022 | int __ret = 0; \ | ||
| 2023 | struct compat_ebt_entry_mwt *__watcher; \ | ||
| 2024 | \ | ||
| 2025 | for (__i = e->watchers_offset; \ | ||
| 2026 | __i < (e)->target_offset; \ | ||
| 2027 | __i += __watcher->watcher_size + \ | ||
| 2028 | sizeof(struct compat_ebt_entry_mwt)) { \ | ||
| 2029 | __watcher = (void *)(e) + __i; \ | ||
| 2030 | __ret = fn(__watcher , ## args); \ | ||
| 2031 | if (__ret != 0) \ | ||
| 2032 | break; \ | ||
| 2033 | } \ | ||
| 2034 | if (__ret == 0) { \ | ||
| 2035 | if (__i != (e)->target_offset) \ | ||
| 2036 | __ret = -EINVAL; \ | ||
| 2037 | } \ | ||
| 2038 | __ret; \ | ||
| 2039 | }) | ||
| 2040 | |||
| 2041 | #define EBT_COMPAT_MATCH_ITERATE(e, fn, args...) \ | ||
| 2042 | ({ \ | ||
| 2043 | unsigned int __i; \ | ||
| 2044 | int __ret = 0; \ | ||
| 2045 | struct compat_ebt_entry_mwt *__match; \ | ||
| 2046 | \ | ||
| 2047 | for (__i = sizeof(struct ebt_entry); \ | ||
| 2048 | __i < (e)->watchers_offset; \ | ||
| 2049 | __i += __match->match_size + \ | ||
| 2050 | sizeof(struct compat_ebt_entry_mwt)) { \ | ||
| 2051 | __match = (void *)(e) + __i; \ | ||
| 2052 | __ret = fn(__match , ## args); \ | ||
| 2053 | if (__ret != 0) \ | ||
| 2054 | break; \ | ||
| 2055 | } \ | ||
| 2056 | if (__ret == 0) { \ | ||
| 2057 | if (__i != (e)->watchers_offset) \ | ||
| 2058 | __ret = -EINVAL; \ | ||
| 2059 | } \ | ||
| 2060 | __ret; \ | ||
| 2061 | }) | ||
| 2062 | |||
| 2063 | /* called for all ebt_entry structures. */ | 2012 | /* called for all ebt_entry structures. */ |
| 2064 | static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, | 2013 | static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, |
| 2065 | unsigned int *total, | 2014 | unsigned int *total, |
| @@ -2132,6 +2081,14 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, | |||
| 2132 | } | 2081 | } |
| 2133 | } | 2082 | } |
| 2134 | 2083 | ||
| 2084 | if (state->buf_kern_start == NULL) { | ||
| 2085 | unsigned int offset = buf_start - (char *) base; | ||
| 2086 | |||
| 2087 | ret = xt_compat_add_offset(NFPROTO_BRIDGE, offset, new_offset); | ||
| 2088 | if (ret < 0) | ||
| 2089 | return ret; | ||
| 2090 | } | ||
| 2091 | |||
| 2135 | startoff = state->buf_user_offset - startoff; | 2092 | startoff = state->buf_user_offset - startoff; |
| 2136 | 2093 | ||
| 2137 | BUG_ON(*total < startoff); | 2094 | BUG_ON(*total < startoff); |
| @@ -2240,6 +2197,7 @@ static int compat_do_replace(struct net *net, void __user *user, | |||
| 2240 | 2197 | ||
| 2241 | xt_compat_lock(NFPROTO_BRIDGE); | 2198 | xt_compat_lock(NFPROTO_BRIDGE); |
| 2242 | 2199 | ||
| 2200 | xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries); | ||
| 2243 | ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); | 2201 | ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); |
| 2244 | if (ret < 0) | 2202 | if (ret < 0) |
| 2245 | goto out_unlock; | 2203 | goto out_unlock; |
diff --git a/net/core/dev.c b/net/core/dev.c index 44ef8f8998ca..75898a32c038 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -1284,11 +1284,13 @@ static int dev_close_many(struct list_head *head) | |||
| 1284 | */ | 1284 | */ |
| 1285 | int dev_close(struct net_device *dev) | 1285 | int dev_close(struct net_device *dev) |
| 1286 | { | 1286 | { |
| 1287 | LIST_HEAD(single); | 1287 | if (dev->flags & IFF_UP) { |
| 1288 | LIST_HEAD(single); | ||
| 1288 | 1289 | ||
| 1289 | list_add(&dev->unreg_list, &single); | 1290 | list_add(&dev->unreg_list, &single); |
| 1290 | dev_close_many(&single); | 1291 | dev_close_many(&single); |
| 1291 | list_del(&single); | 1292 | list_del(&single); |
| 1293 | } | ||
| 1292 | return 0; | 1294 | return 0; |
| 1293 | } | 1295 | } |
| 1294 | EXPORT_SYMBOL(dev_close); | 1296 | EXPORT_SYMBOL(dev_close); |
diff --git a/net/dccp/options.c b/net/dccp/options.c index f06ffcfc8d71..4b2ab657ac8e 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c | |||
| @@ -123,6 +123,8 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, | |||
| 123 | case DCCPO_CHANGE_L ... DCCPO_CONFIRM_R: | 123 | case DCCPO_CHANGE_L ... DCCPO_CONFIRM_R: |
| 124 | if (pkt_type == DCCP_PKT_DATA) /* RFC 4340, 6 */ | 124 | if (pkt_type == DCCP_PKT_DATA) /* RFC 4340, 6 */ |
| 125 | break; | 125 | break; |
| 126 | if (len == 0) | ||
| 127 | goto out_invalid_option; | ||
| 126 | rc = dccp_feat_parse_options(sk, dreq, mandatory, opt, | 128 | rc = dccp_feat_parse_options(sk, dreq, mandatory, opt, |
| 127 | *value, value + 1, len - 1); | 129 | *value, value + 1, len - 1); |
| 128 | if (rc) | 130 | if (rc) |
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index 34340c9c95fa..f376b05cca81 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c | |||
| @@ -93,6 +93,7 @@ struct bictcp { | |||
| 93 | u32 ack_cnt; /* number of acks */ | 93 | u32 ack_cnt; /* number of acks */ |
| 94 | u32 tcp_cwnd; /* estimated tcp cwnd */ | 94 | u32 tcp_cwnd; /* estimated tcp cwnd */ |
| 95 | #define ACK_RATIO_SHIFT 4 | 95 | #define ACK_RATIO_SHIFT 4 |
| 96 | #define ACK_RATIO_LIMIT (32u << ACK_RATIO_SHIFT) | ||
| 96 | u16 delayed_ack; /* estimate the ratio of Packets/ACKs << 4 */ | 97 | u16 delayed_ack; /* estimate the ratio of Packets/ACKs << 4 */ |
| 97 | u8 sample_cnt; /* number of samples to decide curr_rtt */ | 98 | u8 sample_cnt; /* number of samples to decide curr_rtt */ |
| 98 | u8 found; /* the exit point is found? */ | 99 | u8 found; /* the exit point is found? */ |
| @@ -398,8 +399,12 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us) | |||
| 398 | u32 delay; | 399 | u32 delay; |
| 399 | 400 | ||
| 400 | if (icsk->icsk_ca_state == TCP_CA_Open) { | 401 | if (icsk->icsk_ca_state == TCP_CA_Open) { |
| 401 | cnt -= ca->delayed_ack >> ACK_RATIO_SHIFT; | 402 | u32 ratio = ca->delayed_ack; |
| 402 | ca->delayed_ack += cnt; | 403 | |
| 404 | ratio -= ca->delayed_ack >> ACK_RATIO_SHIFT; | ||
| 405 | ratio += cnt; | ||
| 406 | |||
| 407 | ca->delayed_ack = min(ratio, ACK_RATIO_LIMIT); | ||
| 403 | } | 408 | } |
| 404 | 409 | ||
| 405 | /* Some calls are for duplicates without timetamps */ | 410 | /* Some calls are for duplicates without timetamps */ |
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 571aa96a175c..2d51840e53a1 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c | |||
| @@ -69,7 +69,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb) | |||
| 69 | } | 69 | } |
| 70 | EXPORT_SYMBOL(xfrm4_prepare_output); | 70 | EXPORT_SYMBOL(xfrm4_prepare_output); |
| 71 | 71 | ||
| 72 | static int xfrm4_output_finish(struct sk_buff *skb) | 72 | int xfrm4_output_finish(struct sk_buff *skb) |
| 73 | { | 73 | { |
| 74 | #ifdef CONFIG_NETFILTER | 74 | #ifdef CONFIG_NETFILTER |
| 75 | if (!skb_dst(skb)->xfrm) { | 75 | if (!skb_dst(skb)->xfrm) { |
| @@ -86,7 +86,11 @@ static int xfrm4_output_finish(struct sk_buff *skb) | |||
| 86 | 86 | ||
| 87 | int xfrm4_output(struct sk_buff *skb) | 87 | int xfrm4_output(struct sk_buff *skb) |
| 88 | { | 88 | { |
| 89 | struct dst_entry *dst = skb_dst(skb); | ||
| 90 | struct xfrm_state *x = dst->xfrm; | ||
| 91 | |||
| 89 | return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, | 92 | return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, |
| 90 | NULL, skb_dst(skb)->dev, xfrm4_output_finish, | 93 | NULL, dst->dev, |
| 94 | x->outer_mode->afinfo->output_finish, | ||
| 91 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | 95 | !(IPCB(skb)->flags & IPSKB_REROUTED)); |
| 92 | } | 96 | } |
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index ea983ae96ae6..d9ac0a0058b5 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c | |||
| @@ -78,6 +78,7 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = { | |||
| 78 | .init_tempsel = __xfrm4_init_tempsel, | 78 | .init_tempsel = __xfrm4_init_tempsel, |
| 79 | .init_temprop = xfrm4_init_temprop, | 79 | .init_temprop = xfrm4_init_temprop, |
| 80 | .output = xfrm4_output, | 80 | .output = xfrm4_output, |
| 81 | .output_finish = xfrm4_output_finish, | ||
| 81 | .extract_input = xfrm4_extract_input, | 82 | .extract_input = xfrm4_extract_input, |
| 82 | .extract_output = xfrm4_extract_output, | 83 | .extract_output = xfrm4_extract_output, |
| 83 | .transport_finish = xfrm4_transport_finish, | 84 | .transport_finish = xfrm4_transport_finish, |
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index 28e74488a329..a5a4c5dd5396 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
| @@ -45,6 +45,8 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
| 45 | int tcphoff, needs_ack; | 45 | int tcphoff, needs_ack; |
| 46 | const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); | 46 | const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); |
| 47 | struct ipv6hdr *ip6h; | 47 | struct ipv6hdr *ip6h; |
| 48 | #define DEFAULT_TOS_VALUE 0x0U | ||
| 49 | const __u8 tclass = DEFAULT_TOS_VALUE; | ||
| 48 | struct dst_entry *dst = NULL; | 50 | struct dst_entry *dst = NULL; |
| 49 | u8 proto; | 51 | u8 proto; |
| 50 | struct flowi6 fl6; | 52 | struct flowi6 fl6; |
| @@ -124,7 +126,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
| 124 | skb_put(nskb, sizeof(struct ipv6hdr)); | 126 | skb_put(nskb, sizeof(struct ipv6hdr)); |
| 125 | skb_reset_network_header(nskb); | 127 | skb_reset_network_header(nskb); |
| 126 | ip6h = ipv6_hdr(nskb); | 128 | ip6h = ipv6_hdr(nskb); |
| 127 | ip6h->version = 6; | 129 | *(__be32 *)ip6h = htonl(0x60000000 | (tclass << 20)); |
| 128 | ip6h->hop_limit = ip6_dst_hoplimit(dst); | 130 | ip6h->hop_limit = ip6_dst_hoplimit(dst); |
| 129 | ip6h->nexthdr = IPPROTO_TCP; | 131 | ip6h->nexthdr = IPPROTO_TCP; |
| 130 | ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr); | 132 | ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr); |
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 8e688b3de9ab..49a91c5f5623 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
| @@ -79,7 +79,7 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb) | |||
| 79 | } | 79 | } |
| 80 | EXPORT_SYMBOL(xfrm6_prepare_output); | 80 | EXPORT_SYMBOL(xfrm6_prepare_output); |
| 81 | 81 | ||
| 82 | static int xfrm6_output_finish(struct sk_buff *skb) | 82 | int xfrm6_output_finish(struct sk_buff *skb) |
| 83 | { | 83 | { |
| 84 | #ifdef CONFIG_NETFILTER | 84 | #ifdef CONFIG_NETFILTER |
| 85 | IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; | 85 | IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; |
| @@ -97,9 +97,9 @@ static int __xfrm6_output(struct sk_buff *skb) | |||
| 97 | if ((x && x->props.mode == XFRM_MODE_TUNNEL) && | 97 | if ((x && x->props.mode == XFRM_MODE_TUNNEL) && |
| 98 | ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || | 98 | ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || |
| 99 | dst_allfrag(skb_dst(skb)))) { | 99 | dst_allfrag(skb_dst(skb)))) { |
| 100 | return ip6_fragment(skb, xfrm6_output_finish); | 100 | return ip6_fragment(skb, x->outer_mode->afinfo->output_finish); |
| 101 | } | 101 | } |
| 102 | return xfrm6_output_finish(skb); | 102 | return x->outer_mode->afinfo->output_finish(skb); |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | int xfrm6_output(struct sk_buff *skb) | 105 | int xfrm6_output(struct sk_buff *skb) |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index afe941e9415c..248f0b2a7ee9 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
| @@ -178,6 +178,7 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = { | |||
| 178 | .tmpl_sort = __xfrm6_tmpl_sort, | 178 | .tmpl_sort = __xfrm6_tmpl_sort, |
| 179 | .state_sort = __xfrm6_state_sort, | 179 | .state_sort = __xfrm6_state_sort, |
| 180 | .output = xfrm6_output, | 180 | .output = xfrm6_output, |
| 181 | .output_finish = xfrm6_output_finish, | ||
| 181 | .extract_input = xfrm6_extract_input, | 182 | .extract_input = xfrm6_extract_input, |
| 182 | .extract_output = xfrm6_extract_output, | 183 | .extract_output = xfrm6_extract_output, |
| 183 | .transport_finish = xfrm6_transport_finish, | 184 | .transport_finish = xfrm6_transport_finish, |
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c index 2dc6de13ac18..51f3af7c4743 100644 --- a/net/netfilter/ipvs/ip_vs_app.c +++ b/net/netfilter/ipvs/ip_vs_app.c | |||
| @@ -576,7 +576,7 @@ static const struct file_operations ip_vs_app_fops = { | |||
| 576 | }; | 576 | }; |
| 577 | #endif | 577 | #endif |
| 578 | 578 | ||
| 579 | static int __net_init __ip_vs_app_init(struct net *net) | 579 | int __net_init __ip_vs_app_init(struct net *net) |
| 580 | { | 580 | { |
| 581 | struct netns_ipvs *ipvs = net_ipvs(net); | 581 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 582 | 582 | ||
| @@ -585,26 +585,17 @@ static int __net_init __ip_vs_app_init(struct net *net) | |||
| 585 | return 0; | 585 | return 0; |
| 586 | } | 586 | } |
| 587 | 587 | ||
| 588 | static void __net_exit __ip_vs_app_cleanup(struct net *net) | 588 | void __net_exit __ip_vs_app_cleanup(struct net *net) |
| 589 | { | 589 | { |
| 590 | proc_net_remove(net, "ip_vs_app"); | 590 | proc_net_remove(net, "ip_vs_app"); |
| 591 | } | 591 | } |
| 592 | 592 | ||
| 593 | static struct pernet_operations ip_vs_app_ops = { | ||
| 594 | .init = __ip_vs_app_init, | ||
| 595 | .exit = __ip_vs_app_cleanup, | ||
| 596 | }; | ||
| 597 | |||
| 598 | int __init ip_vs_app_init(void) | 593 | int __init ip_vs_app_init(void) |
| 599 | { | 594 | { |
| 600 | int rv; | 595 | return 0; |
| 601 | |||
| 602 | rv = register_pernet_subsys(&ip_vs_app_ops); | ||
| 603 | return rv; | ||
| 604 | } | 596 | } |
| 605 | 597 | ||
| 606 | 598 | ||
| 607 | void ip_vs_app_cleanup(void) | 599 | void ip_vs_app_cleanup(void) |
| 608 | { | 600 | { |
| 609 | unregister_pernet_subsys(&ip_vs_app_ops); | ||
| 610 | } | 601 | } |
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index c97bd45975be..d3fd91bbba49 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c | |||
| @@ -1258,22 +1258,17 @@ int __net_init __ip_vs_conn_init(struct net *net) | |||
| 1258 | return 0; | 1258 | return 0; |
| 1259 | } | 1259 | } |
| 1260 | 1260 | ||
| 1261 | static void __net_exit __ip_vs_conn_cleanup(struct net *net) | 1261 | void __net_exit __ip_vs_conn_cleanup(struct net *net) |
| 1262 | { | 1262 | { |
| 1263 | /* flush all the connection entries first */ | 1263 | /* flush all the connection entries first */ |
| 1264 | ip_vs_conn_flush(net); | 1264 | ip_vs_conn_flush(net); |
| 1265 | proc_net_remove(net, "ip_vs_conn"); | 1265 | proc_net_remove(net, "ip_vs_conn"); |
| 1266 | proc_net_remove(net, "ip_vs_conn_sync"); | 1266 | proc_net_remove(net, "ip_vs_conn_sync"); |
| 1267 | } | 1267 | } |
| 1268 | static struct pernet_operations ipvs_conn_ops = { | ||
| 1269 | .init = __ip_vs_conn_init, | ||
| 1270 | .exit = __ip_vs_conn_cleanup, | ||
| 1271 | }; | ||
| 1272 | 1268 | ||
| 1273 | int __init ip_vs_conn_init(void) | 1269 | int __init ip_vs_conn_init(void) |
| 1274 | { | 1270 | { |
| 1275 | int idx; | 1271 | int idx; |
| 1276 | int retc; | ||
| 1277 | 1272 | ||
| 1278 | /* Compute size and mask */ | 1273 | /* Compute size and mask */ |
| 1279 | ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits; | 1274 | ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits; |
| @@ -1309,17 +1304,14 @@ int __init ip_vs_conn_init(void) | |||
| 1309 | rwlock_init(&__ip_vs_conntbl_lock_array[idx].l); | 1304 | rwlock_init(&__ip_vs_conntbl_lock_array[idx].l); |
| 1310 | } | 1305 | } |
| 1311 | 1306 | ||
| 1312 | retc = register_pernet_subsys(&ipvs_conn_ops); | ||
| 1313 | |||
| 1314 | /* calculate the random value for connection hash */ | 1307 | /* calculate the random value for connection hash */ |
| 1315 | get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd)); | 1308 | get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd)); |
| 1316 | 1309 | ||
| 1317 | return retc; | 1310 | return 0; |
| 1318 | } | 1311 | } |
| 1319 | 1312 | ||
| 1320 | void ip_vs_conn_cleanup(void) | 1313 | void ip_vs_conn_cleanup(void) |
| 1321 | { | 1314 | { |
| 1322 | unregister_pernet_subsys(&ipvs_conn_ops); | ||
| 1323 | /* Release the empty cache */ | 1315 | /* Release the empty cache */ |
| 1324 | kmem_cache_destroy(ip_vs_conn_cachep); | 1316 | kmem_cache_destroy(ip_vs_conn_cachep); |
| 1325 | vfree(ip_vs_conn_tab); | 1317 | vfree(ip_vs_conn_tab); |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 07accf6b2401..a74dae6c5dbc 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
| @@ -1113,6 +1113,9 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) | |||
| 1113 | return NF_ACCEPT; | 1113 | return NF_ACCEPT; |
| 1114 | 1114 | ||
| 1115 | net = skb_net(skb); | 1115 | net = skb_net(skb); |
| 1116 | if (!net_ipvs(net)->enable) | ||
| 1117 | return NF_ACCEPT; | ||
| 1118 | |||
| 1116 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); | 1119 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); |
| 1117 | #ifdef CONFIG_IP_VS_IPV6 | 1120 | #ifdef CONFIG_IP_VS_IPV6 |
| 1118 | if (af == AF_INET6) { | 1121 | if (af == AF_INET6) { |
| @@ -1343,6 +1346,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
| 1343 | return NF_ACCEPT; /* The packet looks wrong, ignore */ | 1346 | return NF_ACCEPT; /* The packet looks wrong, ignore */ |
| 1344 | 1347 | ||
| 1345 | net = skb_net(skb); | 1348 | net = skb_net(skb); |
| 1349 | |||
| 1346 | pd = ip_vs_proto_data_get(net, cih->protocol); | 1350 | pd = ip_vs_proto_data_get(net, cih->protocol); |
| 1347 | if (!pd) | 1351 | if (!pd) |
| 1348 | return NF_ACCEPT; | 1352 | return NF_ACCEPT; |
| @@ -1529,6 +1533,11 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) | |||
| 1529 | IP_VS_DBG_ADDR(af, &iph.daddr), hooknum); | 1533 | IP_VS_DBG_ADDR(af, &iph.daddr), hooknum); |
| 1530 | return NF_ACCEPT; | 1534 | return NF_ACCEPT; |
| 1531 | } | 1535 | } |
| 1536 | /* ipvs enabled in this netns ? */ | ||
| 1537 | net = skb_net(skb); | ||
| 1538 | if (!net_ipvs(net)->enable) | ||
| 1539 | return NF_ACCEPT; | ||
| 1540 | |||
| 1532 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); | 1541 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); |
| 1533 | 1542 | ||
| 1534 | /* Bad... Do not break raw sockets */ | 1543 | /* Bad... Do not break raw sockets */ |
| @@ -1562,7 +1571,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) | |||
| 1562 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); | 1571 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); |
| 1563 | } | 1572 | } |
| 1564 | 1573 | ||
| 1565 | net = skb_net(skb); | ||
| 1566 | /* Protocol supported? */ | 1574 | /* Protocol supported? */ |
| 1567 | pd = ip_vs_proto_data_get(net, iph.protocol); | 1575 | pd = ip_vs_proto_data_get(net, iph.protocol); |
| 1568 | if (unlikely(!pd)) | 1576 | if (unlikely(!pd)) |
| @@ -1588,7 +1596,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) | |||
| 1588 | } | 1596 | } |
| 1589 | 1597 | ||
| 1590 | IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet"); | 1598 | IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet"); |
| 1591 | net = skb_net(skb); | ||
| 1592 | ipvs = net_ipvs(net); | 1599 | ipvs = net_ipvs(net); |
| 1593 | /* Check the server status */ | 1600 | /* Check the server status */ |
| 1594 | if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) { | 1601 | if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) { |
| @@ -1743,10 +1750,16 @@ ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb, | |||
| 1743 | int (*okfn)(struct sk_buff *)) | 1750 | int (*okfn)(struct sk_buff *)) |
| 1744 | { | 1751 | { |
| 1745 | int r; | 1752 | int r; |
| 1753 | struct net *net; | ||
| 1746 | 1754 | ||
| 1747 | if (ip_hdr(skb)->protocol != IPPROTO_ICMP) | 1755 | if (ip_hdr(skb)->protocol != IPPROTO_ICMP) |
| 1748 | return NF_ACCEPT; | 1756 | return NF_ACCEPT; |
| 1749 | 1757 | ||
| 1758 | /* ipvs enabled in this netns ? */ | ||
| 1759 | net = skb_net(skb); | ||
| 1760 | if (!net_ipvs(net)->enable) | ||
| 1761 | return NF_ACCEPT; | ||
| 1762 | |||
| 1750 | return ip_vs_in_icmp(skb, &r, hooknum); | 1763 | return ip_vs_in_icmp(skb, &r, hooknum); |
| 1751 | } | 1764 | } |
| 1752 | 1765 | ||
| @@ -1757,10 +1770,16 @@ ip_vs_forward_icmp_v6(unsigned int hooknum, struct sk_buff *skb, | |||
| 1757 | int (*okfn)(struct sk_buff *)) | 1770 | int (*okfn)(struct sk_buff *)) |
| 1758 | { | 1771 | { |
| 1759 | int r; | 1772 | int r; |
| 1773 | struct net *net; | ||
| 1760 | 1774 | ||
| 1761 | if (ipv6_hdr(skb)->nexthdr != IPPROTO_ICMPV6) | 1775 | if (ipv6_hdr(skb)->nexthdr != IPPROTO_ICMPV6) |
| 1762 | return NF_ACCEPT; | 1776 | return NF_ACCEPT; |
| 1763 | 1777 | ||
| 1778 | /* ipvs enabled in this netns ? */ | ||
| 1779 | net = skb_net(skb); | ||
| 1780 | if (!net_ipvs(net)->enable) | ||
| 1781 | return NF_ACCEPT; | ||
| 1782 | |||
| 1764 | return ip_vs_in_icmp_v6(skb, &r, hooknum); | 1783 | return ip_vs_in_icmp_v6(skb, &r, hooknum); |
| 1765 | } | 1784 | } |
| 1766 | #endif | 1785 | #endif |
| @@ -1884,19 +1903,70 @@ static int __net_init __ip_vs_init(struct net *net) | |||
| 1884 | pr_err("%s(): no memory.\n", __func__); | 1903 | pr_err("%s(): no memory.\n", __func__); |
| 1885 | return -ENOMEM; | 1904 | return -ENOMEM; |
| 1886 | } | 1905 | } |
| 1906 | /* Hold the beast until a service is registerd */ | ||
| 1907 | ipvs->enable = 0; | ||
| 1887 | ipvs->net = net; | 1908 | ipvs->net = net; |
| 1888 | /* Counters used for creating unique names */ | 1909 | /* Counters used for creating unique names */ |
| 1889 | ipvs->gen = atomic_read(&ipvs_netns_cnt); | 1910 | ipvs->gen = atomic_read(&ipvs_netns_cnt); |
| 1890 | atomic_inc(&ipvs_netns_cnt); | 1911 | atomic_inc(&ipvs_netns_cnt); |
| 1891 | net->ipvs = ipvs; | 1912 | net->ipvs = ipvs; |
| 1913 | |||
| 1914 | if (__ip_vs_estimator_init(net) < 0) | ||
| 1915 | goto estimator_fail; | ||
| 1916 | |||
| 1917 | if (__ip_vs_control_init(net) < 0) | ||
| 1918 | goto control_fail; | ||
| 1919 | |||
| 1920 | if (__ip_vs_protocol_init(net) < 0) | ||
| 1921 | goto protocol_fail; | ||
| 1922 | |||
| 1923 | if (__ip_vs_app_init(net) < 0) | ||
| 1924 | goto app_fail; | ||
| 1925 | |||
| 1926 | if (__ip_vs_conn_init(net) < 0) | ||
| 1927 | goto conn_fail; | ||
| 1928 | |||
| 1929 | if (__ip_vs_sync_init(net) < 0) | ||
| 1930 | goto sync_fail; | ||
| 1931 | |||
| 1892 | printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n", | 1932 | printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n", |
| 1893 | sizeof(struct netns_ipvs), ipvs->gen); | 1933 | sizeof(struct netns_ipvs), ipvs->gen); |
| 1894 | return 0; | 1934 | return 0; |
| 1935 | /* | ||
| 1936 | * Error handling | ||
| 1937 | */ | ||
| 1938 | |||
| 1939 | sync_fail: | ||
| 1940 | __ip_vs_conn_cleanup(net); | ||
| 1941 | conn_fail: | ||
| 1942 | __ip_vs_app_cleanup(net); | ||
| 1943 | app_fail: | ||
| 1944 | __ip_vs_protocol_cleanup(net); | ||
| 1945 | protocol_fail: | ||
| 1946 | __ip_vs_control_cleanup(net); | ||
| 1947 | control_fail: | ||
| 1948 | __ip_vs_estimator_cleanup(net); | ||
| 1949 | estimator_fail: | ||
| 1950 | return -ENOMEM; | ||
| 1895 | } | 1951 | } |
| 1896 | 1952 | ||
| 1897 | static void __net_exit __ip_vs_cleanup(struct net *net) | 1953 | static void __net_exit __ip_vs_cleanup(struct net *net) |
| 1898 | { | 1954 | { |
| 1899 | IP_VS_DBG(10, "ipvs netns %d released\n", net_ipvs(net)->gen); | 1955 | __ip_vs_service_cleanup(net); /* ip_vs_flush() with locks */ |
| 1956 | __ip_vs_conn_cleanup(net); | ||
| 1957 | __ip_vs_app_cleanup(net); | ||
| 1958 | __ip_vs_protocol_cleanup(net); | ||
| 1959 | __ip_vs_control_cleanup(net); | ||
| 1960 | __ip_vs_estimator_cleanup(net); | ||
| 1961 | IP_VS_DBG(2, "ipvs netns %d released\n", net_ipvs(net)->gen); | ||
| 1962 | } | ||
| 1963 | |||
| 1964 | static void __net_exit __ip_vs_dev_cleanup(struct net *net) | ||
| 1965 | { | ||
| 1966 | EnterFunction(2); | ||
| 1967 | net_ipvs(net)->enable = 0; /* Disable packet reception */ | ||
| 1968 | __ip_vs_sync_cleanup(net); | ||
| 1969 | LeaveFunction(2); | ||
| 1900 | } | 1970 | } |
| 1901 | 1971 | ||
| 1902 | static struct pernet_operations ipvs_core_ops = { | 1972 | static struct pernet_operations ipvs_core_ops = { |
| @@ -1906,6 +1976,10 @@ static struct pernet_operations ipvs_core_ops = { | |||
| 1906 | .size = sizeof(struct netns_ipvs), | 1976 | .size = sizeof(struct netns_ipvs), |
| 1907 | }; | 1977 | }; |
| 1908 | 1978 | ||
| 1979 | static struct pernet_operations ipvs_core_dev_ops = { | ||
| 1980 | .exit = __ip_vs_dev_cleanup, | ||
| 1981 | }; | ||
| 1982 | |||
| 1909 | /* | 1983 | /* |
| 1910 | * Initialize IP Virtual Server | 1984 | * Initialize IP Virtual Server |
| 1911 | */ | 1985 | */ |
| @@ -1913,10 +1987,6 @@ static int __init ip_vs_init(void) | |||
| 1913 | { | 1987 | { |
| 1914 | int ret; | 1988 | int ret; |
| 1915 | 1989 | ||
| 1916 | ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */ | ||
| 1917 | if (ret < 0) | ||
| 1918 | return ret; | ||
| 1919 | |||
| 1920 | ip_vs_estimator_init(); | 1990 | ip_vs_estimator_init(); |
| 1921 | ret = ip_vs_control_init(); | 1991 | ret = ip_vs_control_init(); |
| 1922 | if (ret < 0) { | 1992 | if (ret < 0) { |
| @@ -1944,15 +2014,28 @@ static int __init ip_vs_init(void) | |||
| 1944 | goto cleanup_conn; | 2014 | goto cleanup_conn; |
| 1945 | } | 2015 | } |
| 1946 | 2016 | ||
| 2017 | ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */ | ||
| 2018 | if (ret < 0) | ||
| 2019 | goto cleanup_sync; | ||
| 2020 | |||
| 2021 | ret = register_pernet_device(&ipvs_core_dev_ops); | ||
| 2022 | if (ret < 0) | ||
| 2023 | goto cleanup_sub; | ||
| 2024 | |||
| 1947 | ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); | 2025 | ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); |
| 1948 | if (ret < 0) { | 2026 | if (ret < 0) { |
| 1949 | pr_err("can't register hooks.\n"); | 2027 | pr_err("can't register hooks.\n"); |
| 1950 | goto cleanup_sync; | 2028 | goto cleanup_dev; |
| 1951 | } | 2029 | } |
| 1952 | 2030 | ||
| 1953 | pr_info("ipvs loaded.\n"); | 2031 | pr_info("ipvs loaded.\n"); |
| 2032 | |||
| 1954 | return ret; | 2033 | return ret; |
| 1955 | 2034 | ||
| 2035 | cleanup_dev: | ||
| 2036 | unregister_pernet_device(&ipvs_core_dev_ops); | ||
| 2037 | cleanup_sub: | ||
| 2038 | unregister_pernet_subsys(&ipvs_core_ops); | ||
| 1956 | cleanup_sync: | 2039 | cleanup_sync: |
| 1957 | ip_vs_sync_cleanup(); | 2040 | ip_vs_sync_cleanup(); |
| 1958 | cleanup_conn: | 2041 | cleanup_conn: |
| @@ -1964,20 +2047,20 @@ cleanup_sync: | |||
| 1964 | ip_vs_control_cleanup(); | 2047 | ip_vs_control_cleanup(); |
| 1965 | cleanup_estimator: | 2048 | cleanup_estimator: |
| 1966 | ip_vs_estimator_cleanup(); | 2049 | ip_vs_estimator_cleanup(); |
| 1967 | unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ | ||
| 1968 | return ret; | 2050 | return ret; |
| 1969 | } | 2051 | } |
| 1970 | 2052 | ||
| 1971 | static void __exit ip_vs_cleanup(void) | 2053 | static void __exit ip_vs_cleanup(void) |
| 1972 | { | 2054 | { |
| 1973 | nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); | 2055 | nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); |
| 2056 | unregister_pernet_device(&ipvs_core_dev_ops); | ||
| 2057 | unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ | ||
| 1974 | ip_vs_sync_cleanup(); | 2058 | ip_vs_sync_cleanup(); |
| 1975 | ip_vs_conn_cleanup(); | 2059 | ip_vs_conn_cleanup(); |
| 1976 | ip_vs_app_cleanup(); | 2060 | ip_vs_app_cleanup(); |
| 1977 | ip_vs_protocol_cleanup(); | 2061 | ip_vs_protocol_cleanup(); |
| 1978 | ip_vs_control_cleanup(); | 2062 | ip_vs_control_cleanup(); |
| 1979 | ip_vs_estimator_cleanup(); | 2063 | ip_vs_estimator_cleanup(); |
| 1980 | unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ | ||
| 1981 | pr_info("ipvs unloaded.\n"); | 2064 | pr_info("ipvs unloaded.\n"); |
| 1982 | } | 2065 | } |
| 1983 | 2066 | ||
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 9930f340908a..89842f06931d 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
| @@ -69,6 +69,11 @@ int ip_vs_get_debug_level(void) | |||
| 69 | } | 69 | } |
| 70 | #endif | 70 | #endif |
| 71 | 71 | ||
| 72 | |||
| 73 | /* Protos */ | ||
| 74 | static void __ip_vs_del_service(struct ip_vs_service *svc); | ||
| 75 | |||
| 76 | |||
| 72 | #ifdef CONFIG_IP_VS_IPV6 | 77 | #ifdef CONFIG_IP_VS_IPV6 |
| 73 | /* Taken from rt6_fill_node() in net/ipv6/route.c, is there a better way? */ | 78 | /* Taken from rt6_fill_node() in net/ipv6/route.c, is there a better way? */ |
| 74 | static int __ip_vs_addr_is_local_v6(struct net *net, | 79 | static int __ip_vs_addr_is_local_v6(struct net *net, |
| @@ -1214,6 +1219,8 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u, | |||
| 1214 | write_unlock_bh(&__ip_vs_svc_lock); | 1219 | write_unlock_bh(&__ip_vs_svc_lock); |
| 1215 | 1220 | ||
| 1216 | *svc_p = svc; | 1221 | *svc_p = svc; |
| 1222 | /* Now there is a service - full throttle */ | ||
| 1223 | ipvs->enable = 1; | ||
| 1217 | return 0; | 1224 | return 0; |
| 1218 | 1225 | ||
| 1219 | 1226 | ||
| @@ -1472,6 +1479,84 @@ static int ip_vs_flush(struct net *net) | |||
| 1472 | return 0; | 1479 | return 0; |
| 1473 | } | 1480 | } |
| 1474 | 1481 | ||
| 1482 | /* | ||
| 1483 | * Delete service by {netns} in the service table. | ||
| 1484 | * Called by __ip_vs_cleanup() | ||
| 1485 | */ | ||
| 1486 | void __ip_vs_service_cleanup(struct net *net) | ||
| 1487 | { | ||
| 1488 | EnterFunction(2); | ||
| 1489 | /* Check for "full" addressed entries */ | ||
| 1490 | mutex_lock(&__ip_vs_mutex); | ||
| 1491 | ip_vs_flush(net); | ||
| 1492 | mutex_unlock(&__ip_vs_mutex); | ||
| 1493 | LeaveFunction(2); | ||
| 1494 | } | ||
| 1495 | /* | ||
| 1496 | * Release dst hold by dst_cache | ||
| 1497 | */ | ||
| 1498 | static inline void | ||
| 1499 | __ip_vs_dev_reset(struct ip_vs_dest *dest, struct net_device *dev) | ||
| 1500 | { | ||
| 1501 | spin_lock_bh(&dest->dst_lock); | ||
| 1502 | if (dest->dst_cache && dest->dst_cache->dev == dev) { | ||
| 1503 | IP_VS_DBG_BUF(3, "Reset dev:%s dest %s:%u ,dest->refcnt=%d\n", | ||
| 1504 | dev->name, | ||
| 1505 | IP_VS_DBG_ADDR(dest->af, &dest->addr), | ||
| 1506 | ntohs(dest->port), | ||
| 1507 | atomic_read(&dest->refcnt)); | ||
| 1508 | ip_vs_dst_reset(dest); | ||
| 1509 | } | ||
| 1510 | spin_unlock_bh(&dest->dst_lock); | ||
| 1511 | |||
| 1512 | } | ||
| 1513 | /* | ||
| 1514 | * Netdev event receiver | ||
| 1515 | * Currently only NETDEV_UNREGISTER is handled, i.e. if we hold a reference to | ||
| 1516 | * a device that is "unregister" it must be released. | ||
| 1517 | */ | ||
| 1518 | static int ip_vs_dst_event(struct notifier_block *this, unsigned long event, | ||
| 1519 | void *ptr) | ||
| 1520 | { | ||
| 1521 | struct net_device *dev = ptr; | ||
| 1522 | struct net *net = dev_net(dev); | ||
| 1523 | struct ip_vs_service *svc; | ||
| 1524 | struct ip_vs_dest *dest; | ||
| 1525 | unsigned int idx; | ||
| 1526 | |||
| 1527 | if (event != NETDEV_UNREGISTER) | ||
| 1528 | return NOTIFY_DONE; | ||
| 1529 | IP_VS_DBG(3, "%s() dev=%s\n", __func__, dev->name); | ||
| 1530 | EnterFunction(2); | ||
| 1531 | mutex_lock(&__ip_vs_mutex); | ||
| 1532 | for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { | ||
| 1533 | list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { | ||
| 1534 | if (net_eq(svc->net, net)) { | ||
| 1535 | list_for_each_entry(dest, &svc->destinations, | ||
| 1536 | n_list) { | ||
| 1537 | __ip_vs_dev_reset(dest, dev); | ||
| 1538 | } | ||
| 1539 | } | ||
| 1540 | } | ||
| 1541 | |||
| 1542 | list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { | ||
| 1543 | if (net_eq(svc->net, net)) { | ||
| 1544 | list_for_each_entry(dest, &svc->destinations, | ||
| 1545 | n_list) { | ||
| 1546 | __ip_vs_dev_reset(dest, dev); | ||
| 1547 | } | ||
| 1548 | } | ||
| 1549 | |||
| 1550 | } | ||
| 1551 | } | ||
| 1552 | |||
| 1553 | list_for_each_entry(dest, &net_ipvs(net)->dest_trash, n_list) { | ||
| 1554 | __ip_vs_dev_reset(dest, dev); | ||
| 1555 | } | ||
| 1556 | mutex_unlock(&__ip_vs_mutex); | ||
| 1557 | LeaveFunction(2); | ||
| 1558 | return NOTIFY_DONE; | ||
| 1559 | } | ||
| 1475 | 1560 | ||
| 1476 | /* | 1561 | /* |
| 1477 | * Zero counters in a service or all services | 1562 | * Zero counters in a service or all services |
| @@ -3585,6 +3670,10 @@ void __net_init __ip_vs_control_cleanup_sysctl(struct net *net) { } | |||
| 3585 | 3670 | ||
| 3586 | #endif | 3671 | #endif |
| 3587 | 3672 | ||
| 3673 | static struct notifier_block ip_vs_dst_notifier = { | ||
| 3674 | .notifier_call = ip_vs_dst_event, | ||
| 3675 | }; | ||
| 3676 | |||
| 3588 | int __net_init __ip_vs_control_init(struct net *net) | 3677 | int __net_init __ip_vs_control_init(struct net *net) |
| 3589 | { | 3678 | { |
| 3590 | int idx; | 3679 | int idx; |
| @@ -3623,7 +3712,7 @@ err: | |||
| 3623 | return -ENOMEM; | 3712 | return -ENOMEM; |
| 3624 | } | 3713 | } |
| 3625 | 3714 | ||
| 3626 | static void __net_exit __ip_vs_control_cleanup(struct net *net) | 3715 | void __net_exit __ip_vs_control_cleanup(struct net *net) |
| 3627 | { | 3716 | { |
| 3628 | struct netns_ipvs *ipvs = net_ipvs(net); | 3717 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 3629 | 3718 | ||
| @@ -3636,11 +3725,6 @@ static void __net_exit __ip_vs_control_cleanup(struct net *net) | |||
| 3636 | free_percpu(ipvs->tot_stats.cpustats); | 3725 | free_percpu(ipvs->tot_stats.cpustats); |
| 3637 | } | 3726 | } |
| 3638 | 3727 | ||
| 3639 | static struct pernet_operations ipvs_control_ops = { | ||
| 3640 | .init = __ip_vs_control_init, | ||
| 3641 | .exit = __ip_vs_control_cleanup, | ||
| 3642 | }; | ||
| 3643 | |||
| 3644 | int __init ip_vs_control_init(void) | 3728 | int __init ip_vs_control_init(void) |
| 3645 | { | 3729 | { |
| 3646 | int idx; | 3730 | int idx; |
| @@ -3654,33 +3738,32 @@ int __init ip_vs_control_init(void) | |||
| 3654 | INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]); | 3738 | INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]); |
| 3655 | } | 3739 | } |
| 3656 | 3740 | ||
| 3657 | ret = register_pernet_subsys(&ipvs_control_ops); | ||
| 3658 | if (ret) { | ||
| 3659 | pr_err("cannot register namespace.\n"); | ||
| 3660 | goto err; | ||
| 3661 | } | ||
| 3662 | |||
| 3663 | smp_wmb(); /* Do we really need it now ? */ | 3741 | smp_wmb(); /* Do we really need it now ? */ |
| 3664 | 3742 | ||
| 3665 | ret = nf_register_sockopt(&ip_vs_sockopts); | 3743 | ret = nf_register_sockopt(&ip_vs_sockopts); |
| 3666 | if (ret) { | 3744 | if (ret) { |
| 3667 | pr_err("cannot register sockopt.\n"); | 3745 | pr_err("cannot register sockopt.\n"); |
| 3668 | goto err_net; | 3746 | goto err_sock; |
| 3669 | } | 3747 | } |
| 3670 | 3748 | ||
| 3671 | ret = ip_vs_genl_register(); | 3749 | ret = ip_vs_genl_register(); |
| 3672 | if (ret) { | 3750 | if (ret) { |
| 3673 | pr_err("cannot register Generic Netlink interface.\n"); | 3751 | pr_err("cannot register Generic Netlink interface.\n"); |
| 3674 | nf_unregister_sockopt(&ip_vs_sockopts); | 3752 | goto err_genl; |
| 3675 | goto err_net; | ||
| 3676 | } | 3753 | } |
| 3677 | 3754 | ||
| 3755 | ret = register_netdevice_notifier(&ip_vs_dst_notifier); | ||
| 3756 | if (ret < 0) | ||
| 3757 | goto err_notf; | ||
| 3758 | |||
| 3678 | LeaveFunction(2); | 3759 | LeaveFunction(2); |
| 3679 | return 0; | 3760 | return 0; |
| 3680 | 3761 | ||
| 3681 | err_net: | 3762 | err_notf: |
| 3682 | unregister_pernet_subsys(&ipvs_control_ops); | 3763 | ip_vs_genl_unregister(); |
| 3683 | err: | 3764 | err_genl: |
| 3765 | nf_unregister_sockopt(&ip_vs_sockopts); | ||
| 3766 | err_sock: | ||
| 3684 | return ret; | 3767 | return ret; |
| 3685 | } | 3768 | } |
| 3686 | 3769 | ||
| @@ -3688,7 +3771,6 @@ err: | |||
| 3688 | void ip_vs_control_cleanup(void) | 3771 | void ip_vs_control_cleanup(void) |
| 3689 | { | 3772 | { |
| 3690 | EnterFunction(2); | 3773 | EnterFunction(2); |
| 3691 | unregister_pernet_subsys(&ipvs_control_ops); | ||
| 3692 | ip_vs_genl_unregister(); | 3774 | ip_vs_genl_unregister(); |
| 3693 | nf_unregister_sockopt(&ip_vs_sockopts); | 3775 | nf_unregister_sockopt(&ip_vs_sockopts); |
| 3694 | LeaveFunction(2); | 3776 | LeaveFunction(2); |
diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c index 8c8766ca56ad..508cce98777c 100644 --- a/net/netfilter/ipvs/ip_vs_est.c +++ b/net/netfilter/ipvs/ip_vs_est.c | |||
| @@ -192,7 +192,7 @@ void ip_vs_read_estimator(struct ip_vs_stats_user *dst, | |||
| 192 | dst->outbps = (e->outbps + 0xF) >> 5; | 192 | dst->outbps = (e->outbps + 0xF) >> 5; |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | static int __net_init __ip_vs_estimator_init(struct net *net) | 195 | int __net_init __ip_vs_estimator_init(struct net *net) |
| 196 | { | 196 | { |
| 197 | struct netns_ipvs *ipvs = net_ipvs(net); | 197 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 198 | 198 | ||
| @@ -203,24 +203,16 @@ static int __net_init __ip_vs_estimator_init(struct net *net) | |||
| 203 | return 0; | 203 | return 0; |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | static void __net_exit __ip_vs_estimator_exit(struct net *net) | 206 | void __net_exit __ip_vs_estimator_cleanup(struct net *net) |
| 207 | { | 207 | { |
| 208 | del_timer_sync(&net_ipvs(net)->est_timer); | 208 | del_timer_sync(&net_ipvs(net)->est_timer); |
| 209 | } | 209 | } |
| 210 | static struct pernet_operations ip_vs_app_ops = { | ||
| 211 | .init = __ip_vs_estimator_init, | ||
| 212 | .exit = __ip_vs_estimator_exit, | ||
| 213 | }; | ||
| 214 | 210 | ||
| 215 | int __init ip_vs_estimator_init(void) | 211 | int __init ip_vs_estimator_init(void) |
| 216 | { | 212 | { |
| 217 | int rv; | 213 | return 0; |
| 218 | |||
| 219 | rv = register_pernet_subsys(&ip_vs_app_ops); | ||
| 220 | return rv; | ||
| 221 | } | 214 | } |
| 222 | 215 | ||
| 223 | void ip_vs_estimator_cleanup(void) | 216 | void ip_vs_estimator_cleanup(void) |
| 224 | { | 217 | { |
| 225 | unregister_pernet_subsys(&ip_vs_app_ops); | ||
| 226 | } | 218 | } |
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c index 17484a4416ef..eb86028536fc 100644 --- a/net/netfilter/ipvs/ip_vs_proto.c +++ b/net/netfilter/ipvs/ip_vs_proto.c | |||
| @@ -316,7 +316,7 @@ ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp, | |||
| 316 | /* | 316 | /* |
| 317 | * per network name-space init | 317 | * per network name-space init |
| 318 | */ | 318 | */ |
| 319 | static int __net_init __ip_vs_protocol_init(struct net *net) | 319 | int __net_init __ip_vs_protocol_init(struct net *net) |
| 320 | { | 320 | { |
| 321 | #ifdef CONFIG_IP_VS_PROTO_TCP | 321 | #ifdef CONFIG_IP_VS_PROTO_TCP |
| 322 | register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp); | 322 | register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp); |
| @@ -336,7 +336,7 @@ static int __net_init __ip_vs_protocol_init(struct net *net) | |||
| 336 | return 0; | 336 | return 0; |
| 337 | } | 337 | } |
| 338 | 338 | ||
| 339 | static void __net_exit __ip_vs_protocol_cleanup(struct net *net) | 339 | void __net_exit __ip_vs_protocol_cleanup(struct net *net) |
| 340 | { | 340 | { |
| 341 | struct netns_ipvs *ipvs = net_ipvs(net); | 341 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 342 | struct ip_vs_proto_data *pd; | 342 | struct ip_vs_proto_data *pd; |
| @@ -349,11 +349,6 @@ static void __net_exit __ip_vs_protocol_cleanup(struct net *net) | |||
| 349 | } | 349 | } |
| 350 | } | 350 | } |
| 351 | 351 | ||
| 352 | static struct pernet_operations ipvs_proto_ops = { | ||
| 353 | .init = __ip_vs_protocol_init, | ||
| 354 | .exit = __ip_vs_protocol_cleanup, | ||
| 355 | }; | ||
| 356 | |||
| 357 | int __init ip_vs_protocol_init(void) | 352 | int __init ip_vs_protocol_init(void) |
| 358 | { | 353 | { |
| 359 | char protocols[64]; | 354 | char protocols[64]; |
| @@ -382,7 +377,6 @@ int __init ip_vs_protocol_init(void) | |||
| 382 | REGISTER_PROTOCOL(&ip_vs_protocol_esp); | 377 | REGISTER_PROTOCOL(&ip_vs_protocol_esp); |
| 383 | #endif | 378 | #endif |
| 384 | pr_info("Registered protocols (%s)\n", &protocols[2]); | 379 | pr_info("Registered protocols (%s)\n", &protocols[2]); |
| 385 | return register_pernet_subsys(&ipvs_proto_ops); | ||
| 386 | 380 | ||
| 387 | return 0; | 381 | return 0; |
| 388 | } | 382 | } |
| @@ -393,7 +387,6 @@ void ip_vs_protocol_cleanup(void) | |||
| 393 | struct ip_vs_protocol *pp; | 387 | struct ip_vs_protocol *pp; |
| 394 | int i; | 388 | int i; |
| 395 | 389 | ||
| 396 | unregister_pernet_subsys(&ipvs_proto_ops); | ||
| 397 | /* unregister all the ipvs protocols */ | 390 | /* unregister all the ipvs protocols */ |
| 398 | for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) { | 391 | for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) { |
| 399 | while ((pp = ip_vs_proto_table[i]) != NULL) | 392 | while ((pp = ip_vs_proto_table[i]) != NULL) |
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 3e7961e85e9c..e292e5bddc70 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c | |||
| @@ -1303,13 +1303,18 @@ static struct socket *make_send_sock(struct net *net) | |||
| 1303 | struct socket *sock; | 1303 | struct socket *sock; |
| 1304 | int result; | 1304 | int result; |
| 1305 | 1305 | ||
| 1306 | /* First create a socket */ | 1306 | /* First create a socket move it to right name space later */ |
| 1307 | result = __sock_create(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock, 1); | 1307 | result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock); |
| 1308 | if (result < 0) { | 1308 | if (result < 0) { |
| 1309 | pr_err("Error during creation of socket; terminating\n"); | 1309 | pr_err("Error during creation of socket; terminating\n"); |
| 1310 | return ERR_PTR(result); | 1310 | return ERR_PTR(result); |
| 1311 | } | 1311 | } |
| 1312 | 1312 | /* | |
| 1313 | * Kernel sockets that are a part of a namespace, should not | ||
| 1314 | * hold a reference to a namespace in order to allow to stop it. | ||
| 1315 | * After sk_change_net should be released using sk_release_kernel. | ||
| 1316 | */ | ||
| 1317 | sk_change_net(sock->sk, net); | ||
| 1313 | result = set_mcast_if(sock->sk, ipvs->master_mcast_ifn); | 1318 | result = set_mcast_if(sock->sk, ipvs->master_mcast_ifn); |
| 1314 | if (result < 0) { | 1319 | if (result < 0) { |
| 1315 | pr_err("Error setting outbound mcast interface\n"); | 1320 | pr_err("Error setting outbound mcast interface\n"); |
| @@ -1334,8 +1339,8 @@ static struct socket *make_send_sock(struct net *net) | |||
| 1334 | 1339 | ||
| 1335 | return sock; | 1340 | return sock; |
| 1336 | 1341 | ||
| 1337 | error: | 1342 | error: |
| 1338 | sock_release(sock); | 1343 | sk_release_kernel(sock->sk); |
| 1339 | return ERR_PTR(result); | 1344 | return ERR_PTR(result); |
| 1340 | } | 1345 | } |
| 1341 | 1346 | ||
| @@ -1350,12 +1355,17 @@ static struct socket *make_receive_sock(struct net *net) | |||
| 1350 | int result; | 1355 | int result; |
| 1351 | 1356 | ||
| 1352 | /* First create a socket */ | 1357 | /* First create a socket */ |
| 1353 | result = __sock_create(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock, 1); | 1358 | result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock); |
| 1354 | if (result < 0) { | 1359 | if (result < 0) { |
| 1355 | pr_err("Error during creation of socket; terminating\n"); | 1360 | pr_err("Error during creation of socket; terminating\n"); |
| 1356 | return ERR_PTR(result); | 1361 | return ERR_PTR(result); |
| 1357 | } | 1362 | } |
| 1358 | 1363 | /* | |
| 1364 | * Kernel sockets that are a part of a namespace, should not | ||
| 1365 | * hold a reference to a namespace in order to allow to stop it. | ||
| 1366 | * After sk_change_net should be released using sk_release_kernel. | ||
| 1367 | */ | ||
| 1368 | sk_change_net(sock->sk, net); | ||
| 1359 | /* it is equivalent to the REUSEADDR option in user-space */ | 1369 | /* it is equivalent to the REUSEADDR option in user-space */ |
| 1360 | sock->sk->sk_reuse = 1; | 1370 | sock->sk->sk_reuse = 1; |
| 1361 | 1371 | ||
| @@ -1377,8 +1387,8 @@ static struct socket *make_receive_sock(struct net *net) | |||
| 1377 | 1387 | ||
| 1378 | return sock; | 1388 | return sock; |
| 1379 | 1389 | ||
| 1380 | error: | 1390 | error: |
| 1381 | sock_release(sock); | 1391 | sk_release_kernel(sock->sk); |
| 1382 | return ERR_PTR(result); | 1392 | return ERR_PTR(result); |
| 1383 | } | 1393 | } |
| 1384 | 1394 | ||
| @@ -1473,7 +1483,7 @@ static int sync_thread_master(void *data) | |||
| 1473 | ip_vs_sync_buff_release(sb); | 1483 | ip_vs_sync_buff_release(sb); |
| 1474 | 1484 | ||
| 1475 | /* release the sending multicast socket */ | 1485 | /* release the sending multicast socket */ |
| 1476 | sock_release(tinfo->sock); | 1486 | sk_release_kernel(tinfo->sock->sk); |
| 1477 | kfree(tinfo); | 1487 | kfree(tinfo); |
| 1478 | 1488 | ||
| 1479 | return 0; | 1489 | return 0; |
| @@ -1513,7 +1523,7 @@ static int sync_thread_backup(void *data) | |||
| 1513 | } | 1523 | } |
| 1514 | 1524 | ||
| 1515 | /* release the sending multicast socket */ | 1525 | /* release the sending multicast socket */ |
| 1516 | sock_release(tinfo->sock); | 1526 | sk_release_kernel(tinfo->sock->sk); |
| 1517 | kfree(tinfo->buf); | 1527 | kfree(tinfo->buf); |
| 1518 | kfree(tinfo); | 1528 | kfree(tinfo); |
| 1519 | 1529 | ||
| @@ -1601,7 +1611,7 @@ outtinfo: | |||
| 1601 | outbuf: | 1611 | outbuf: |
| 1602 | kfree(buf); | 1612 | kfree(buf); |
| 1603 | outsocket: | 1613 | outsocket: |
| 1604 | sock_release(sock); | 1614 | sk_release_kernel(sock->sk); |
| 1605 | out: | 1615 | out: |
| 1606 | return result; | 1616 | return result; |
| 1607 | } | 1617 | } |
| @@ -1610,6 +1620,7 @@ out: | |||
| 1610 | int stop_sync_thread(struct net *net, int state) | 1620 | int stop_sync_thread(struct net *net, int state) |
| 1611 | { | 1621 | { |
| 1612 | struct netns_ipvs *ipvs = net_ipvs(net); | 1622 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 1623 | int retc = -EINVAL; | ||
| 1613 | 1624 | ||
| 1614 | IP_VS_DBG(7, "%s(): pid %d\n", __func__, task_pid_nr(current)); | 1625 | IP_VS_DBG(7, "%s(): pid %d\n", __func__, task_pid_nr(current)); |
| 1615 | 1626 | ||
| @@ -1629,7 +1640,7 @@ int stop_sync_thread(struct net *net, int state) | |||
| 1629 | spin_lock_bh(&ipvs->sync_lock); | 1640 | spin_lock_bh(&ipvs->sync_lock); |
| 1630 | ipvs->sync_state &= ~IP_VS_STATE_MASTER; | 1641 | ipvs->sync_state &= ~IP_VS_STATE_MASTER; |
| 1631 | spin_unlock_bh(&ipvs->sync_lock); | 1642 | spin_unlock_bh(&ipvs->sync_lock); |
| 1632 | kthread_stop(ipvs->master_thread); | 1643 | retc = kthread_stop(ipvs->master_thread); |
| 1633 | ipvs->master_thread = NULL; | 1644 | ipvs->master_thread = NULL; |
| 1634 | } else if (state == IP_VS_STATE_BACKUP) { | 1645 | } else if (state == IP_VS_STATE_BACKUP) { |
| 1635 | if (!ipvs->backup_thread) | 1646 | if (!ipvs->backup_thread) |
| @@ -1639,22 +1650,20 @@ int stop_sync_thread(struct net *net, int state) | |||
| 1639 | task_pid_nr(ipvs->backup_thread)); | 1650 | task_pid_nr(ipvs->backup_thread)); |
| 1640 | 1651 | ||
| 1641 | ipvs->sync_state &= ~IP_VS_STATE_BACKUP; | 1652 | ipvs->sync_state &= ~IP_VS_STATE_BACKUP; |
| 1642 | kthread_stop(ipvs->backup_thread); | 1653 | retc = kthread_stop(ipvs->backup_thread); |
| 1643 | ipvs->backup_thread = NULL; | 1654 | ipvs->backup_thread = NULL; |
| 1644 | } else { | ||
| 1645 | return -EINVAL; | ||
| 1646 | } | 1655 | } |
| 1647 | 1656 | ||
| 1648 | /* decrease the module use count */ | 1657 | /* decrease the module use count */ |
| 1649 | ip_vs_use_count_dec(); | 1658 | ip_vs_use_count_dec(); |
| 1650 | 1659 | ||
| 1651 | return 0; | 1660 | return retc; |
| 1652 | } | 1661 | } |
| 1653 | 1662 | ||
| 1654 | /* | 1663 | /* |
| 1655 | * Initialize data struct for each netns | 1664 | * Initialize data struct for each netns |
| 1656 | */ | 1665 | */ |
| 1657 | static int __net_init __ip_vs_sync_init(struct net *net) | 1666 | int __net_init __ip_vs_sync_init(struct net *net) |
| 1658 | { | 1667 | { |
| 1659 | struct netns_ipvs *ipvs = net_ipvs(net); | 1668 | struct netns_ipvs *ipvs = net_ipvs(net); |
| 1660 | 1669 | ||
| @@ -1668,24 +1677,24 @@ static int __net_init __ip_vs_sync_init(struct net *net) | |||
| 1668 | return 0; | 1677 | return 0; |
| 1669 | } | 1678 | } |
| 1670 | 1679 | ||
| 1671 | static void __ip_vs_sync_cleanup(struct net *net) | 1680 | void __ip_vs_sync_cleanup(struct net *net) |
| 1672 | { | 1681 | { |
| 1673 | stop_sync_thread(net, IP_VS_STATE_MASTER); | 1682 | int retc; |
| 1674 | stop_sync_thread(net, IP_VS_STATE_BACKUP); | ||
| 1675 | } | ||
| 1676 | 1683 | ||
| 1677 | static struct pernet_operations ipvs_sync_ops = { | 1684 | retc = stop_sync_thread(net, IP_VS_STATE_MASTER); |
| 1678 | .init = __ip_vs_sync_init, | 1685 | if (retc && retc != -ESRCH) |
| 1679 | .exit = __ip_vs_sync_cleanup, | 1686 | pr_err("Failed to stop Master Daemon\n"); |
| 1680 | }; | ||
| 1681 | 1687 | ||
| 1688 | retc = stop_sync_thread(net, IP_VS_STATE_BACKUP); | ||
| 1689 | if (retc && retc != -ESRCH) | ||
| 1690 | pr_err("Failed to stop Backup Daemon\n"); | ||
| 1691 | } | ||
| 1682 | 1692 | ||
| 1683 | int __init ip_vs_sync_init(void) | 1693 | int __init ip_vs_sync_init(void) |
| 1684 | { | 1694 | { |
| 1685 | return register_pernet_subsys(&ipvs_sync_ops); | 1695 | return 0; |
| 1686 | } | 1696 | } |
| 1687 | 1697 | ||
| 1688 | void ip_vs_sync_cleanup(void) | 1698 | void ip_vs_sync_cleanup(void) |
| 1689 | { | 1699 | { |
| 1690 | unregister_pernet_subsys(&ipvs_sync_ops); | ||
| 1691 | } | 1700 | } |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 30bf8a167fc8..482e90c61850 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
| @@ -1334,6 +1334,7 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, | |||
| 1334 | struct nf_conn *ct; | 1334 | struct nf_conn *ct; |
| 1335 | int err = -EINVAL; | 1335 | int err = -EINVAL; |
| 1336 | struct nf_conntrack_helper *helper; | 1336 | struct nf_conntrack_helper *helper; |
| 1337 | struct nf_conn_tstamp *tstamp; | ||
| 1337 | 1338 | ||
| 1338 | ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC); | 1339 | ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC); |
| 1339 | if (IS_ERR(ct)) | 1340 | if (IS_ERR(ct)) |
| @@ -1451,6 +1452,9 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, | |||
| 1451 | __set_bit(IPS_EXPECTED_BIT, &ct->status); | 1452 | __set_bit(IPS_EXPECTED_BIT, &ct->status); |
| 1452 | ct->master = master_ct; | 1453 | ct->master = master_ct; |
| 1453 | } | 1454 | } |
| 1455 | tstamp = nf_conn_tstamp_find(ct); | ||
| 1456 | if (tstamp) | ||
| 1457 | tstamp->start = ktime_to_ns(ktime_get_real()); | ||
| 1454 | 1458 | ||
| 1455 | add_timer(&ct->timeout); | 1459 | add_timer(&ct->timeout); |
| 1456 | nf_conntrack_hash_insert(ct); | 1460 | nf_conntrack_hash_insert(ct); |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 52959efca858..b0869fe3633b 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
| @@ -455,6 +455,7 @@ void xt_compat_flush_offsets(u_int8_t af) | |||
| 455 | vfree(xt[af].compat_tab); | 455 | vfree(xt[af].compat_tab); |
| 456 | xt[af].compat_tab = NULL; | 456 | xt[af].compat_tab = NULL; |
| 457 | xt[af].number = 0; | 457 | xt[af].number = 0; |
| 458 | xt[af].cur = 0; | ||
| 458 | } | 459 | } |
| 459 | } | 460 | } |
| 460 | EXPORT_SYMBOL_GPL(xt_compat_flush_offsets); | 461 | EXPORT_SYMBOL_GPL(xt_compat_flush_offsets); |
| @@ -473,8 +474,7 @@ int xt_compat_calc_jump(u_int8_t af, unsigned int offset) | |||
| 473 | else | 474 | else |
| 474 | return mid ? tmp[mid - 1].delta : 0; | 475 | return mid ? tmp[mid - 1].delta : 0; |
| 475 | } | 476 | } |
| 476 | WARN_ON_ONCE(1); | 477 | return left ? tmp[left - 1].delta : 0; |
| 477 | return 0; | ||
| 478 | } | 478 | } |
| 479 | EXPORT_SYMBOL_GPL(xt_compat_calc_jump); | 479 | EXPORT_SYMBOL_GPL(xt_compat_calc_jump); |
| 480 | 480 | ||
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c index 0a229191e55b..ae8271652efa 100644 --- a/net/netfilter/xt_DSCP.c +++ b/net/netfilter/xt_DSCP.c | |||
| @@ -99,7 +99,7 @@ tos_tg6(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 99 | u_int8_t orig, nv; | 99 | u_int8_t orig, nv; |
| 100 | 100 | ||
| 101 | orig = ipv6_get_dsfield(iph); | 101 | orig = ipv6_get_dsfield(iph); |
| 102 | nv = (orig & info->tos_mask) ^ info->tos_value; | 102 | nv = (orig & ~info->tos_mask) ^ info->tos_value; |
| 103 | 103 | ||
| 104 | if (orig != nv) { | 104 | if (orig != nv) { |
| 105 | if (!skb_make_writable(skb, sizeof(struct iphdr))) | 105 | if (!skb_make_writable(skb, sizeof(struct iphdr))) |
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c index 481a86fdc409..61805d7b38aa 100644 --- a/net/netfilter/xt_conntrack.c +++ b/net/netfilter/xt_conntrack.c | |||
| @@ -272,11 +272,6 @@ static int conntrack_mt_check(const struct xt_mtchk_param *par) | |||
| 272 | { | 272 | { |
| 273 | int ret; | 273 | int ret; |
| 274 | 274 | ||
| 275 | if (strcmp(par->table, "raw") == 0) { | ||
| 276 | pr_info("state is undetermined at the time of raw table\n"); | ||
| 277 | return -EINVAL; | ||
| 278 | } | ||
| 279 | |||
| 280 | ret = nf_ct_l3proto_try_module_get(par->family); | 275 | ret = nf_ct_l3proto_try_module_get(par->family); |
| 281 | if (ret < 0) | 276 | if (ret < 0) |
| 282 | pr_info("cannot load conntrack support for proto=%u\n", | 277 | pr_info("cannot load conntrack support for proto=%u\n", |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 00bcb88386c2..9bec2e8a838c 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
| @@ -1407,6 +1407,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, | |||
| 1407 | struct net *net = xp_net(policy); | 1407 | struct net *net = xp_net(policy); |
| 1408 | unsigned long now = jiffies; | 1408 | unsigned long now = jiffies; |
| 1409 | struct net_device *dev; | 1409 | struct net_device *dev; |
| 1410 | struct xfrm_mode *inner_mode; | ||
| 1410 | struct dst_entry *dst_prev = NULL; | 1411 | struct dst_entry *dst_prev = NULL; |
| 1411 | struct dst_entry *dst0 = NULL; | 1412 | struct dst_entry *dst0 = NULL; |
| 1412 | int i = 0; | 1413 | int i = 0; |
| @@ -1437,6 +1438,17 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, | |||
| 1437 | goto put_states; | 1438 | goto put_states; |
| 1438 | } | 1439 | } |
| 1439 | 1440 | ||
| 1441 | if (xfrm[i]->sel.family == AF_UNSPEC) { | ||
| 1442 | inner_mode = xfrm_ip2inner_mode(xfrm[i], | ||
| 1443 | xfrm_af2proto(family)); | ||
| 1444 | if (!inner_mode) { | ||
| 1445 | err = -EAFNOSUPPORT; | ||
| 1446 | dst_release(dst); | ||
| 1447 | goto put_states; | ||
| 1448 | } | ||
| 1449 | } else | ||
| 1450 | inner_mode = xfrm[i]->inner_mode; | ||
| 1451 | |||
| 1440 | if (!dst_prev) | 1452 | if (!dst_prev) |
| 1441 | dst0 = dst1; | 1453 | dst0 = dst1; |
| 1442 | else { | 1454 | else { |
| @@ -1465,7 +1477,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, | |||
| 1465 | dst1->lastuse = now; | 1477 | dst1->lastuse = now; |
| 1466 | 1478 | ||
| 1467 | dst1->input = dst_discard; | 1479 | dst1->input = dst_discard; |
| 1468 | dst1->output = xfrm[i]->outer_mode->afinfo->output; | 1480 | dst1->output = inner_mode->afinfo->output; |
| 1469 | 1481 | ||
| 1470 | dst1->next = dst_prev; | 1482 | dst1->next = dst_prev; |
| 1471 | dst_prev = dst1; | 1483 | dst_prev = dst1; |
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index e8a781422feb..47f1b8638df9 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c | |||
| @@ -535,6 +535,9 @@ int xfrm_init_replay(struct xfrm_state *x) | |||
| 535 | replay_esn->bmp_len * sizeof(__u32) * 8) | 535 | replay_esn->bmp_len * sizeof(__u32) * 8) |
| 536 | return -EINVAL; | 536 | return -EINVAL; |
| 537 | 537 | ||
| 538 | if ((x->props.flags & XFRM_STATE_ESN) && replay_esn->replay_window == 0) | ||
| 539 | return -EINVAL; | ||
| 540 | |||
| 538 | if ((x->props.flags & XFRM_STATE_ESN) && x->replay_esn) | 541 | if ((x->props.flags & XFRM_STATE_ESN) && x->replay_esn) |
| 539 | x->repl = &xfrm_replay_esn; | 542 | x->repl = &xfrm_replay_esn; |
| 540 | else | 543 | else |
