Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 9 Sep 2017 18:05:20 +0000 (11:05 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 9 Sep 2017 18:05:20 +0000 (11:05 -0700)
Pull networking fixes from David Miller:
 "The iwlwifi firmware compat fix is in here as well as some other
  stuff:

  1) Fix request socket leak introduced by BPF deadlock fix, from Eric
     Dumazet.

  2) Fix VLAN handling with TXQs in mac80211, from Johannes Berg.

  3) Missing __qdisc_drop conversions in prio and qfq schedulers, from
     Gao Feng.

  4) Use after free in netlink nlk groups handling, from Xin Long.

  5) Handle MTU update properly in ipv6 gre tunnels, from Xin Long.

  6) Fix leak of ipv6 fib tables on netns teardown, from Sabrina Dubroca
     with follow-on fix from Eric Dumazet.

  7) Need RCU and preemption disabled during generic XDP data patch,
     from John Fastabend"

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (54 commits)
  bpf: make error reporting in bpf_warn_invalid_xdp_action more clear
  Revert "mdio_bus: Remove unneeded gpiod NULL check"
  bpf: devmap, use cond_resched instead of cpu_relax
  bpf: add support for sockmap detach programs
  net: rcu lock and preempt disable missing around generic xdp
  bpf: don't select potentially stale ri->map from buggy xdp progs
  net: tulip: Constify tulip_tbl
  net: ethernet: ti: netcp_core: no need in netif_napi_del
  davicom: Display proper debug level up to 6
  net: phy: sfp: rename dt properties to match the binding
  dt-binding: net: sfp binding documentation
  dt-bindings: add SFF vendor prefix
  dt-bindings: net: don't confuse with generic PHY property
  ip6_tunnel: fix setting hop_limit value for ipv6 tunnel
  ip_tunnel: fix setting ttl and tos value in collect_md mode
  ipv6: fix typo in fib6_net_exit()
  tcp: fix a request socket leak
  sctp: fix missing wake ups in some situations
  netfilter: xt_hashlimit: fix build error caused by 64bit division
  netfilter: xt_hashlimit: alloc hashtable with right size
  ...

63 files changed:
Documentation/devicetree/bindings/net/ethernet.txt
Documentation/devicetree/bindings/net/sff,sfp.txt [new file with mode: 0644]
Documentation/devicetree/bindings/phy/phy-bindings.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
drivers/isdn/isdnloop/isdnloop.c
drivers/net/ethernet/davicom/dm9000.c
drivers/net/ethernet/dec/tulip/tulip.h
drivers/net/ethernet/dec/tulip/tulip_core.c
drivers/net/ethernet/ti/netcp_core.c
drivers/net/phy/mdio_bus.c
drivers/net/phy/sfp.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
drivers/net/wireless/intel/iwlwifi/fw/file.h
drivers/net/wireless/intel/iwlwifi/mvm/led.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
include/linux/bpf.h
include/linux/skbuff.h
include/net/mac80211.h
include/net/netfilter/nf_conntrack.h
include/net/netfilter/nf_nat.h
include/uapi/linux/bpf.h
kernel/bpf/devmap.c
kernel/bpf/sockmap.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c
net/core/dev.c
net/core/filter.c
net/core/skbuff.c
net/ipv4/ip_tunnel.c
net/ipv4/netfilter/arp_tables.c
net/ipv4/netfilter/ip_tables.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_tunnel.c
net/ipv6/netfilter/ip6_tables.c
net/ipv6/tcp_ipv6.c
net/mac80211/agg-rx.c
net/mac80211/agg-tx.c
net/mac80211/ht.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/mlme.c
net/mac80211/offchannel.c
net/mac80211/tx.c
net/mac80211/util.c
net/netfilter/core.c
net/netfilter/ipvs/ip_vs_proto_sctp.c
net/netfilter/nf_nat_core.c
net/netfilter/xt_hashlimit.c
net/netlink/af_netlink.c
net/rds/send.c
net/sched/cls_api.c
net/sched/sch_prio.c
net/sched/sch_qfq.c
net/sctp/ulpqueue.c
net/tipc/bearer.c
net/wireless/nl80211.c
net/wireless/reg.c
tools/testing/selftests/bpf/test_maps.c

index 7da86f22a13b80843d087fe859d6633de4d8b11d..2974e63ba311aa4d053ee32cd63baea3c415d756 100644 (file)
@@ -1,5 +1,9 @@
 The following properties are common to the Ethernet controllers:
 
+NOTE: All 'phy*' properties documented below are Ethernet specific. For the
+generic PHY 'phys' property, see
+Documentation/devicetree/bindings/phy/phy-bindings.txt.
+
 - local-mac-address: array of 6 bytes, specifies the MAC address that was
   assigned to the network device;
 - mac-address: array of 6 bytes, specifies the MAC address that was last used by
diff --git a/Documentation/devicetree/bindings/net/sff,sfp.txt b/Documentation/devicetree/bindings/net/sff,sfp.txt
new file mode 100644 (file)
index 0000000..60e970c
--- /dev/null
@@ -0,0 +1,76 @@
+Small Form Factor (SFF) Committee Small Form-factor Pluggable (SFP)
+Transceiver
+
+Required properties:
+
+- compatible : must be "sff,sfp"
+
+Optional Properties:
+
+- i2c-bus : phandle of an I2C bus controller for the SFP two wire serial
+  interface
+
+- mod-def0-gpios : GPIO phandle and a specifier of the MOD-DEF0 (AKA Mod_ABS)
+  module presence input gpio signal, active (module absent) high
+
+- los-gpios : GPIO phandle and a specifier of the Receiver Loss of Signal
+  Indication input gpio signal, active (signal lost) high
+
+- tx-fault-gpios : GPIO phandle and a specifier of the Module Transmitter
+  Fault input gpio signal, active (fault condition) high
+
+- tx-disable-gpios : GPIO phandle and a specifier of the Transmitter Disable
+  output gpio signal, active (Tx disable) high
+
+- rate-select0-gpios : GPIO phandle and a specifier of the Rx Signaling Rate
+  Select (AKA RS0) output gpio signal, low: low Rx rate, high: high Rx rate
+
+- rate-select1-gpios : GPIO phandle and a specifier of the Tx Signaling Rate
+  Select (AKA RS1) output gpio signal (SFP+ only), low: low Tx rate, high:
+  high Tx rate
+
+Example #1: Direct serdes to SFP connection
+
+sfp_eth3: sfp-eth3 {
+       compatible = "sff,sfp";
+       i2c-bus = <&sfp_1g_i2c>;
+       los-gpios = <&cpm_gpio2 22 GPIO_ACTIVE_HIGH>;
+       mod-def0-gpios = <&cpm_gpio2 21 GPIO_ACTIVE_LOW>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&cpm_sfp_1g_pins &cps_sfp_1g_pins>;
+       tx-disable-gpios = <&cps_gpio1 24 GPIO_ACTIVE_HIGH>;
+       tx-fault-gpios = <&cpm_gpio2 19 GPIO_ACTIVE_HIGH>;
+};
+
+&cps_emac3 {
+       phy-names = "comphy";
+       phys = <&cps_comphy5 0>;
+       sfp = <&sfp_eth3>;
+};
+
+Example #2: Serdes to PHY to SFP connection
+
+sfp_eth0: sfp-eth0 {
+       compatible = "sff,sfp";
+       i2c-bus = <&sfpp0_i2c>;
+       los-gpios = <&cps_gpio1 28 GPIO_ACTIVE_HIGH>;
+       mod-def0-gpios = <&cps_gpio1 27 GPIO_ACTIVE_LOW>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&cps_sfpp0_pins>;
+       tx-disable-gpios = <&cps_gpio1 29 GPIO_ACTIVE_HIGH>;
+       tx-fault-gpios  = <&cps_gpio1 26 GPIO_ACTIVE_HIGH>;
+};
+
+p0_phy: ethernet-phy@0 {
+       compatible = "ethernet-phy-ieee802.3-c45";
+       pinctrl-names = "default";
+       pinctrl-0 = <&cpm_phy0_pins &cps_phy0_pins>;
+       reg = <0>;
+       interrupt = <&cpm_gpio2 18 IRQ_TYPE_EDGE_FALLING>;
+       sfp = <&sfp_eth0>;
+};
+
+&cpm_eth0 {
+       phy = <&p0_phy>;
+       phy-mode = "10gbase-kr";
+};
index 1293c321754c67014a4bdc4d4165ba517bac398d..a403b81d0679622d0b473edf545898618fc66836 100644 (file)
@@ -34,7 +34,9 @@ PHY user node
 =============
 
 Required Properties:
-phys : the phandle for the PHY device (used by the PHY subsystem)
+phys : the phandle for the PHY device (used by the PHY subsystem; not to be
+       confused with the Ethernet specific 'phy' and 'phy-handle' properties,
+       see Documentation/devicetree/bindings/net/ethernet.txt for these)
 phy-names : the names of the PHY corresponding to the PHYs present in the
            *phys* phandle
 
index 401ed98cab1829f867b9be45af898e0f385308bc..5a79aeb620b3a206434bd45bf2410a7ed47db7cb 100644 (file)
@@ -292,6 +292,7 @@ schindler   Schindler
 seagate        Seagate Technology PLC
 semtech        Semtech Corporation
 sensirion      Sensirion AG
+sff    Small Form Factor Committee
 sgx    SGX Sensortech
 sharp  Sharp Corporation
 si-en  Si-En Technology Ltd.
index 6ffd13466b8cba2256ccb6b0043debf40c9e1eda..e97232646ba15f50b544a4fdc4dd050de0757752 100644 (file)
@@ -409,7 +409,7 @@ isdnloop_sendbuf(int channel, struct sk_buff *skb, isdnloop_card *card)
                return -EINVAL;
        }
        if (len) {
-               if (!(card->flags & (channel) ? ISDNLOOP_FLAGS_B2ACTIVE : ISDNLOOP_FLAGS_B1ACTIVE))
+               if (!(card->flags & (channel ? ISDNLOOP_FLAGS_B2ACTIVE : ISDNLOOP_FLAGS_B1ACTIVE)))
                        return 0;
                if (card->sndcount[channel] > ISDNLOOP_MAX_SQUEUE)
                        return 0;
index 16fe776ddbe592987541de34f8c5de509fb4c2c9..50222b7b81f3e521762fef0c2780e59eca915725 100644 (file)
@@ -65,7 +65,7 @@ MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
  */
 static int debug;
 module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "dm9000 debug level (0-4)");
+MODULE_PARM_DESC(debug, "dm9000 debug level (0-6)");
 
 /* DM9000 register address locking.
  *
index 38431a155f093582c1fd7830d3d9f1944eb40645..06660dbc44b7e7a383bd8f07cc3717d89ed6e3c7 100644 (file)
@@ -515,7 +515,7 @@ void comet_timer(unsigned long data);
 extern int tulip_debug;
 extern const char * const medianame[];
 extern const char tulip_media_cap[];
-extern struct tulip_chip_table tulip_tbl[];
+extern const struct tulip_chip_table tulip_tbl[];
 void oom_timer(unsigned long data);
 extern u8 t21040_csr13[];
 
index 84394b43c0a1f8c742fa52a0872da27535abd6a6..851b6d1f5a42ab893fa16b53b1b5e7f844ec2a71 100644 (file)
@@ -138,7 +138,7 @@ static void tulip_timer(unsigned long data)
  * It is indexed via the values in 'enum chips'
  */
 
-struct tulip_chip_table tulip_tbl[] = {
+const struct tulip_chip_table tulip_tbl[] = {
   { }, /* placeholder for array, slot unused currently */
   { }, /* placeholder for array, slot unused currently */
 
index eb96a69132358b376fd391ed273732fd1de6a175..437d36289786bbbe8f153910ee797b13379b61e3 100644 (file)
@@ -2145,7 +2145,6 @@ static void netcp_delete_interface(struct netcp_device *netcp_device,
 
        of_node_put(netcp->node_interface);
        unregister_netdev(ndev);
-       netif_napi_del(&netcp->rx_napi);
        free_netdev(ndev);
 }
 
index b6f9fa67016831745c5ad43dfe466605182daf71..2df7b62c1a36811e97087ae641a89d06641cef4e 100644 (file)
@@ -399,7 +399,8 @@ error:
        }
 
        /* Put PHYs in RESET to save power */
-       gpiod_set_value_cansleep(bus->reset_gpiod, 1);
+       if (bus->reset_gpiod)
+               gpiod_set_value_cansleep(bus->reset_gpiod, 1);
 
        device_del(&bus->dev);
        return err;
@@ -424,7 +425,8 @@ void mdiobus_unregister(struct mii_bus *bus)
        }
 
        /* Put PHYs in RESET to save power */
-       gpiod_set_value_cansleep(bus->reset_gpiod, 1);
+       if (bus->reset_gpiod)
+               gpiod_set_value_cansleep(bus->reset_gpiod, 1);
 
        device_del(&bus->dev);
 }
index fb2cf4342f48b5894fe5d7a7bfc8356fb7b60b0f..baee371bf767c6dff65b54b8739da6d0f6ba98c1 100644 (file)
@@ -58,11 +58,11 @@ enum {
 };
 
 static const char *gpio_of_names[] = {
-       "moddef0",
+       "mod-def0",
        "los",
        "tx-fault",
        "tx-disable",
-       "rate-select",
+       "rate-select0",
 };
 
 static const enum gpiod_flags gpio_flags[] = {
index f1b60740e02080261d998686a28e27c9ee4ea8a2..53ae3025998999e26f2f06307fe4abd6f6343dc9 100644 (file)
@@ -159,7 +159,8 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
 
        brcmf_feat_firmware_capabilities(ifp);
        memset(&gscan_cfg, 0, sizeof(gscan_cfg));
-       if (drvr->bus_if->chip != BRCM_CC_43430_CHIP_ID)
+       if (drvr->bus_if->chip != BRCM_CC_43430_CHIP_ID &&
+           drvr->bus_if->chip != BRCM_CC_4345_CHIP_ID)
                brcmf_feat_iovar_data_set(ifp, BRCMF_FEAT_GSCAN,
                                          "pfn_gscan_cfg",
                                          &gscan_cfg, sizeof(gscan_cfg));
index 887f6d8fc8a7c65915334af1d3ee9b002ea115ce..279248cd9cfb368e6fc9e81288ae90598145c4b6 100644 (file)
@@ -378,6 +378,7 @@ enum iwl_ucode_tlv_capa {
        IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG        = (__force iwl_ucode_tlv_capa_t)80,
        IWL_UCODE_TLV_CAPA_LQM_SUPPORT                  = (__force iwl_ucode_tlv_capa_t)81,
        IWL_UCODE_TLV_CAPA_TX_POWER_ACK                 = (__force iwl_ucode_tlv_capa_t)84,
+       IWL_UCODE_TLV_CAPA_LED_CMD_SUPPORT              = (__force iwl_ucode_tlv_capa_t)86,
        IWL_UCODE_TLV_CAPA_MLME_OFFLOAD                 = (__force iwl_ucode_tlv_capa_t)96,
 
        NUM_IWL_UCODE_TLV_CAPA
index 005e2e7278a5375ed493b7db8ddeee6a498a022b..b27269504a622f3fff33b2e3736c13720af53e13 100644 (file)
@@ -92,7 +92,8 @@ static void iwl_mvm_send_led_fw_cmd(struct iwl_mvm *mvm, bool on)
 
 static void iwl_mvm_led_set(struct iwl_mvm *mvm, bool on)
 {
-       if (mvm->cfg->device_family >= IWL_DEVICE_FAMILY_8000) {
+       if (fw_has_capa(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_CAPA_LED_CMD_SUPPORT)) {
                iwl_mvm_send_led_fw_cmd(mvm, on);
                return;
        }
index c8852acc14620a8bc6e94df9c92c647feb2fde1d..6467ffac9811e77649ab5c5f650b1e2004f5553d 100644 (file)
@@ -1362,8 +1362,6 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
                                       txi->control.rates,
                                       ARRAY_SIZE(txi->control.rates));
 
-       txi->rate_driver_data[0] = channel;
-
        if (skb->len >= 24 + 8 &&
            ieee80211_is_probe_resp(hdr->frame_control)) {
                /* fake header transmission time */
index 31965f0ef69de64f6f5189c7e1833af3e0f25d74..e8f07573aed96661a91112bfa04a256d6db6d9bb 100644 (file)
@@ -1183,7 +1183,10 @@ static void btc8723b2ant_set_ant_path(struct btc_coexist *btcoexist,
                }
 
                /* fixed internal switch S1->WiFi, S0->BT */
-               btcoexist->btc_write_4byte(btcoexist, 0x948, 0x0);
+               if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT)
+                       btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0);
+               else
+                       btcoexist->btc_write_2byte(btcoexist, 0x948, 0x280);
 
                switch (antpos_type) {
                case BTC_ANT_WIFI_AT_MAIN:
index c1eacd8352a2ba5a1321bc62a4579db314057891..b5e9877d935c4f088a4cf41b5700805aa73f6b42 100644 (file)
@@ -173,6 +173,16 @@ static u8 halbtc_get_wifi_central_chnl(struct btc_coexist *btcoexist)
 
 u8 rtl_get_hwpg_single_ant_path(struct rtl_priv *rtlpriv)
 {
+       struct rtl_mod_params *mod_params = rtlpriv->cfg->mod_params;
+
+       /* override ant_num / ant_path */
+       if (mod_params->ant_sel) {
+               rtlpriv->btcoexist.btc_info.ant_num =
+                       (mod_params->ant_sel == 1 ? ANT_X2 : ANT_X1);
+
+               rtlpriv->btcoexist.btc_info.single_ant_path =
+                       (mod_params->ant_sel == 1 ? 0 : 1);
+       }
        return rtlpriv->btcoexist.btc_info.single_ant_path;
 }
 
@@ -183,6 +193,7 @@ u8 rtl_get_hwpg_bt_type(struct rtl_priv *rtlpriv)
 
 u8 rtl_get_hwpg_ant_num(struct rtl_priv *rtlpriv)
 {
+       struct rtl_mod_params *mod_params = rtlpriv->cfg->mod_params;
        u8 num;
 
        if (rtlpriv->btcoexist.btc_info.ant_num == ANT_X2)
@@ -190,6 +201,10 @@ u8 rtl_get_hwpg_ant_num(struct rtl_priv *rtlpriv)
        else
                num = 1;
 
+       /* override ant_num / ant_path */
+       if (mod_params->ant_sel)
+               num = (mod_params->ant_sel == 1 ? ANT_X2 : ANT_X1) + 1;
+
        return num;
 }
 
@@ -876,7 +891,7 @@ bool exhalbtc_bind_bt_coex_withadapter(void *adapter)
 {
        struct btc_coexist *btcoexist = &gl_bt_coexist;
        struct rtl_priv *rtlpriv = adapter;
-       u8 ant_num = 2, chip_type, single_ant_path = 0;
+       u8 ant_num = 2, chip_type;
 
        if (btcoexist->binded)
                return false;
@@ -911,12 +926,6 @@ bool exhalbtc_bind_bt_coex_withadapter(void *adapter)
        ant_num = rtl_get_hwpg_ant_num(rtlpriv);
        exhalbtc_set_ant_num(rtlpriv, BT_COEX_ANT_TYPE_PG, ant_num);
 
-       /* set default antenna position to main  port */
-       btcoexist->board_info.btdm_ant_pos = BTC_ANTENNA_AT_MAIN_PORT;
-
-       single_ant_path = rtl_get_hwpg_single_ant_path(rtlpriv);
-       exhalbtc_set_single_ant_path(single_ant_path);
-
        if (rtl_get_hwpg_package_type(rtlpriv) == 0)
                btcoexist->board_info.tfbga_package = false;
        else if (rtl_get_hwpg_package_type(rtlpriv) == 1)
index c2cb1b5c094ec3e39cb0ccbe9dc204a1c404cc2f..8390859e79e70b9a07f0948e1efaa5adbfb0c99c 100644 (file)
@@ -385,16 +385,16 @@ static inline void __dev_map_flush(struct bpf_map *map)
 
 #if defined(CONFIG_STREAM_PARSER) && defined(CONFIG_BPF_SYSCALL)
 struct sock  *__sock_map_lookup_elem(struct bpf_map *map, u32 key);
-int sock_map_attach_prog(struct bpf_map *map, struct bpf_prog *prog, u32 type);
+int sock_map_prog(struct bpf_map *map, struct bpf_prog *prog, u32 type);
 #else
 static inline struct sock  *__sock_map_lookup_elem(struct bpf_map *map, u32 key)
 {
        return NULL;
 }
 
-static inline int sock_map_attach_prog(struct bpf_map *map,
-                                      struct bpf_prog *prog,
-                                      u32 type)
+static inline int sock_map_prog(struct bpf_map *map,
+                               struct bpf_prog *prog,
+                               u32 type)
 {
        return -EOPNOTSUPP;
 }
index f751f3b930391d02b7b0f2c2d3852de64b46b920..72299ef00061db1ce70d34b96ae1639ecde08837 100644 (file)
@@ -958,7 +958,7 @@ void kfree_skb(struct sk_buff *skb);
 void kfree_skb_list(struct sk_buff *segs);
 void skb_tx_error(struct sk_buff *skb);
 void consume_skb(struct sk_buff *skb);
-void consume_stateless_skb(struct sk_buff *skb);
+void __consume_stateless_skb(struct sk_buff *skb);
 void  __kfree_skb(struct sk_buff *skb);
 extern struct kmem_cache *skbuff_head_cache;
 
index f8149ca192b430c181406fa9a3e4db8fc0a17252..885690fa39c8d8f4a48f2fa25447646d3d0a7856 100644 (file)
@@ -919,21 +919,10 @@ struct ieee80211_tx_info {
                                unsigned long jiffies;
                        };
                        /* NB: vif can be NULL for injected frames */
-                       union {
-                               /* NB: vif can be NULL for injected frames */
-                               struct ieee80211_vif *vif;
-
-                               /* When packets are enqueued on txq it's easy
-                                * to re-construct the vif pointer. There's no
-                                * more space in tx_info so it can be used to
-                                * store the necessary enqueue time for packet
-                                * sojourn time computation.
-                                */
-                               codel_time_t enqueue_time;
-                       };
+                       struct ieee80211_vif *vif;
                        struct ieee80211_key_conf *hw_key;
                        u32 flags;
-                       /* 4 bytes free */
+                       codel_time_t enqueue_time;
                } control;
                struct {
                        u64 cookie;
index fdc9c64a1c94dda972f0186e0c8224649e2b2d9c..8f3bd30511def05c91870b2f73bba03e4dc1b04a 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/bitops.h>
 #include <linux/compiler.h>
 #include <linux/atomic.h>
-#include <linux/rhashtable.h>
 
 #include <linux/netfilter/nf_conntrack_tcp.h>
 #include <linux/netfilter/nf_conntrack_dccp.h>
@@ -77,7 +76,7 @@ struct nf_conn {
        possible_net_t ct_net;
 
 #if IS_ENABLED(CONFIG_NF_NAT)
-       struct rhlist_head nat_bysource;
+       struct hlist_node       nat_bysource;
 #endif
        /* all members below initialized via memset */
        u8 __nfct_init_offset[0];
index 05c82a1a42679cf336c4ecc2addc30bdaceecbbe..b71701302e6176720a0ac8faf52b48e23bdb2fa9 100644 (file)
@@ -1,6 +1,5 @@
 #ifndef _NF_NAT_H
 #define _NF_NAT_H
-#include <linux/rhashtable.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter/nf_nat.h>
 #include <net/netfilter/nf_conntrack_tuple.h>
index ba848b761cfbf6e90f612e3d9a42c55d657f0ec0..43ab5c402f98f3c2dc15ccc49ec475530a39e401 100644 (file)
@@ -766,8 +766,8 @@ struct bpf_sock {
 
 /* User return codes for XDP prog type.
  * A valid XDP program must return one of these defined values. All other
- * return codes are reserved for future use. Unknown return codes will result
- * in packet drop.
+ * return codes are reserved for future use. Unknown return codes will
+ * result in packet drops and a warning via bpf_warn_invalid_xdp_action().
  */
 enum xdp_action {
        XDP_ABORTED = 0,
index ecf9f99ecc579e315f4651032a8b39415d5b4d81..959c9a07f318b14f6ab4719973f6010de061aadc 100644 (file)
@@ -159,7 +159,7 @@ static void dev_map_free(struct bpf_map *map)
                unsigned long *bitmap = per_cpu_ptr(dtab->flush_needed, cpu);
 
                while (!bitmap_empty(bitmap, dtab->map.max_entries))
-                       cpu_relax();
+                       cond_resched();
        }
 
        for (i = 0; i < dtab->map.max_entries; i++) {
index f6ffde9c6a68cac1472909205083eb3b9c23e8bc..6424ce0e49698abee1da6242a0a8494d8ba0f03f 100644 (file)
@@ -792,7 +792,7 @@ out_progs:
        return err;
 }
 
-int sock_map_attach_prog(struct bpf_map *map, struct bpf_prog *prog, u32 type)
+int sock_map_prog(struct bpf_map *map, struct bpf_prog *prog, u32 type)
 {
        struct bpf_stab *stab = container_of(map, struct bpf_stab, map);
        struct bpf_prog *orig;
index 70ad8e220343c7825c8e331f19c1f65c78fdb796..cb17e1cd1d434dc2e052a2a9fb0aea967fcf4417 100644 (file)
@@ -1096,10 +1096,10 @@ static int bpf_obj_get(const union bpf_attr *attr)
 
 #define BPF_PROG_ATTACH_LAST_FIELD attach_flags
 
-static int sockmap_get_from_fd(const union bpf_attr *attr)
+static int sockmap_get_from_fd(const union bpf_attr *attr, bool attach)
 {
+       struct bpf_prog *prog = NULL;
        int ufd = attr->target_fd;
-       struct bpf_prog *prog;
        struct bpf_map *map;
        struct fd f;
        int err;
@@ -1109,16 +1109,20 @@ static int sockmap_get_from_fd(const union bpf_attr *attr)
        if (IS_ERR(map))
                return PTR_ERR(map);
 
-       prog = bpf_prog_get_type(attr->attach_bpf_fd, BPF_PROG_TYPE_SK_SKB);
-       if (IS_ERR(prog)) {
-               fdput(f);
-               return PTR_ERR(prog);
+       if (attach) {
+               prog = bpf_prog_get_type(attr->attach_bpf_fd,
+                                        BPF_PROG_TYPE_SK_SKB);
+               if (IS_ERR(prog)) {
+                       fdput(f);
+                       return PTR_ERR(prog);
+               }
        }
 
-       err = sock_map_attach_prog(map, prog, attr->attach_type);
+       err = sock_map_prog(map, prog, attr->attach_type);
        if (err) {
                fdput(f);
-               bpf_prog_put(prog);
+               if (prog)
+                       bpf_prog_put(prog);
                return err;
        }
 
@@ -1155,7 +1159,7 @@ static int bpf_prog_attach(const union bpf_attr *attr)
                break;
        case BPF_SK_SKB_STREAM_PARSER:
        case BPF_SK_SKB_STREAM_VERDICT:
-               return sockmap_get_from_fd(attr);
+               return sockmap_get_from_fd(attr, true);
        default:
                return -EINVAL;
        }
@@ -1204,7 +1208,10 @@ static int bpf_prog_detach(const union bpf_attr *attr)
                ret = cgroup_bpf_update(cgrp, NULL, attr->attach_type, false);
                cgroup_put(cgrp);
                break;
-
+       case BPF_SK_SKB_STREAM_PARSER:
+       case BPF_SK_SKB_STREAM_VERDICT:
+               ret = sockmap_get_from_fd(attr, false);
+               break;
        default:
                return -EINVAL;
        }
index d690c7dd1f1a53dd07752308c234f5f7ac44d724..477b6932c3c1f2b9a1639b75f7ec919ba45e422c 100644 (file)
@@ -4203,6 +4203,22 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
                        continue;
                }
 
+               if (insn->imm == BPF_FUNC_redirect_map) {
+                       u64 addr = (unsigned long)prog;
+                       struct bpf_insn r4_ld[] = {
+                               BPF_LD_IMM64(BPF_REG_4, addr),
+                               *insn,
+                       };
+                       cnt = ARRAY_SIZE(r4_ld);
+
+                       new_prog = bpf_patch_insn_data(env, i + delta, r4_ld, cnt);
+                       if (!new_prog)
+                               return -ENOMEM;
+
+                       delta    += cnt - 1;
+                       env->prog = prog = new_prog;
+                       insn      = new_prog->insnsi + i + delta;
+               }
 patch_call_imm:
                fn = prog->aux->ops->get_func_proto(insn->imm);
                /* all functions that have prototype and verifier allowed
index 6f845e4fec175f333b568bfc44ed85a6a400ff6f..fb766d906148e7d1e85a654eaf6048c1cdf49364 100644 (file)
@@ -3981,8 +3981,13 @@ static int netif_rx_internal(struct sk_buff *skb)
        trace_netif_rx(skb);
 
        if (static_key_false(&generic_xdp_needed)) {
-               int ret = do_xdp_generic(rcu_dereference(skb->dev->xdp_prog),
-                                        skb);
+               int ret;
+
+               preempt_disable();
+               rcu_read_lock();
+               ret = do_xdp_generic(rcu_dereference(skb->dev->xdp_prog), skb);
+               rcu_read_unlock();
+               preempt_enable();
 
                /* Consider XDP consuming the packet a success from
                 * the netdev point of view we do not want to count
@@ -4500,18 +4505,20 @@ static int netif_receive_skb_internal(struct sk_buff *skb)
        if (skb_defer_rx_timestamp(skb))
                return NET_RX_SUCCESS;
 
-       rcu_read_lock();
-
        if (static_key_false(&generic_xdp_needed)) {
-               int ret = do_xdp_generic(rcu_dereference(skb->dev->xdp_prog),
-                                        skb);
+               int ret;
 
-               if (ret != XDP_PASS) {
-                       rcu_read_unlock();
+               preempt_disable();
+               rcu_read_lock();
+               ret = do_xdp_generic(rcu_dereference(skb->dev->xdp_prog), skb);
+               rcu_read_unlock();
+               preempt_enable();
+
+               if (ret != XDP_PASS)
                        return NET_RX_DROP;
-               }
        }
 
+       rcu_read_lock();
 #ifdef CONFIG_RPS
        if (static_key_false(&rps_needed)) {
                struct rps_dev_flow voidflow, *rflow = &voidflow;
index 5912c738a7b272e3fb3eb1d66317fe2df9ce0c6d..3a50a9b021e208e40f9ac3846bdb93b9b917ad3d 100644 (file)
@@ -1794,6 +1794,7 @@ struct redirect_info {
        u32 flags;
        struct bpf_map *map;
        struct bpf_map *map_to_flush;
+       const struct bpf_prog *map_owner;
 };
 
 static DEFINE_PER_CPU(struct redirect_info, redirect_info);
@@ -1807,7 +1808,6 @@ BPF_CALL_2(bpf_redirect, u32, ifindex, u64, flags)
 
        ri->ifindex = ifindex;
        ri->flags = flags;
-       ri->map = NULL;
 
        return TC_ACT_REDIRECT;
 }
@@ -2504,6 +2504,7 @@ static int xdp_do_redirect_map(struct net_device *dev, struct xdp_buff *xdp,
                               struct bpf_prog *xdp_prog)
 {
        struct redirect_info *ri = this_cpu_ptr(&redirect_info);
+       const struct bpf_prog *map_owner = ri->map_owner;
        struct bpf_map *map = ri->map;
        u32 index = ri->ifindex;
        struct net_device *fwd;
@@ -2511,6 +2512,15 @@ static int xdp_do_redirect_map(struct net_device *dev, struct xdp_buff *xdp,
 
        ri->ifindex = 0;
        ri->map = NULL;
+       ri->map_owner = NULL;
+
+       /* This is really only caused by a deliberately crappy
+        * BPF program, normally we would never hit that case,
+        * so no need to inform someone via tracepoints either,
+        * just bail out.
+        */
+       if (unlikely(map_owner != xdp_prog))
+               return -EINVAL;
 
        fwd = __dev_map_lookup_elem(map, index);
        if (!fwd) {
@@ -2607,6 +2617,8 @@ BPF_CALL_2(bpf_xdp_redirect, u32, ifindex, u64, flags)
 
        ri->ifindex = ifindex;
        ri->flags = flags;
+       ri->map = NULL;
+       ri->map_owner = NULL;
 
        return XDP_REDIRECT;
 }
@@ -2619,7 +2631,8 @@ static const struct bpf_func_proto bpf_xdp_redirect_proto = {
        .arg2_type      = ARG_ANYTHING,
 };
 
-BPF_CALL_3(bpf_xdp_redirect_map, struct bpf_map *, map, u32, ifindex, u64, flags)
+BPF_CALL_4(bpf_xdp_redirect_map, struct bpf_map *, map, u32, ifindex, u64, flags,
+          const struct bpf_prog *, map_owner)
 {
        struct redirect_info *ri = this_cpu_ptr(&redirect_info);
 
@@ -2629,10 +2642,14 @@ BPF_CALL_3(bpf_xdp_redirect_map, struct bpf_map *, map, u32, ifindex, u64, flags
        ri->ifindex = ifindex;
        ri->flags = flags;
        ri->map = map;
+       ri->map_owner = map_owner;
 
        return XDP_REDIRECT;
 }
 
+/* Note, arg4 is hidden from users and populated by the verifier
+ * with the right pointer.
+ */
 static const struct bpf_func_proto bpf_xdp_redirect_map_proto = {
        .func           = bpf_xdp_redirect_map,
        .gpl_only       = false,
@@ -3592,7 +3609,11 @@ static bool xdp_is_valid_access(int off, int size,
 
 void bpf_warn_invalid_xdp_action(u32 act)
 {
-       WARN_ONCE(1, "Illegal XDP return value %u, expect packet loss\n", act);
+       const u32 act_max = XDP_REDIRECT;
+
+       WARN_ONCE(1, "%s XDP return value %u, expect packet loss!\n",
+                 act > act_max ? "Illegal" : "Driver unsupported",
+                 act);
 }
 EXPORT_SYMBOL_GPL(bpf_warn_invalid_xdp_action);
 
index 68065d7d383fa6bb477ac690a926d9d86db65bc9..16982de649b97b92423a4f9f5eac1e98ca803370 100644 (file)
@@ -710,14 +710,11 @@ EXPORT_SYMBOL(consume_skb);
  *     consume_stateless_skb - free an skbuff, assuming it is stateless
  *     @skb: buffer to free
  *
- *     Works like consume_skb(), but this variant assumes that all the head
- *     states have been already dropped.
+ *     Alike consume_skb(), but this variant assumes that this is the last
+ *     skb reference and all the head states have been already dropped
  */
-void consume_stateless_skb(struct sk_buff *skb)
+void __consume_stateless_skb(struct sk_buff *skb)
 {
-       if (!skb_unref(skb))
-               return;
-
        trace_consume_skb(skb);
        skb_release_data(skb);
        kfree_skbmem(skb);
index 129d1a3616f838c9b487cf2392d1d9eb09dcfa5a..e1856bfa753da40a35a34bf71610ebc22059afc8 100644 (file)
@@ -618,8 +618,8 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, u8 proto)
                ip_rt_put(rt);
                goto tx_dropped;
        }
-       iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, proto, key->tos,
-                     key->ttl, df, !net_eq(tunnel->net, dev_net(dev)));
+       iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, proto, tos, ttl,
+                     df, !net_eq(tunnel->net, dev_net(dev)));
        return;
 tx_error:
        dev->stats.tx_errors++;
index e04457198f939aa2805ebb86f3bfd61a496d363f..9e2770fd00be5eda1a633893c42b59378ab52f17 100644 (file)
@@ -629,6 +629,7 @@ static void get_counters(const struct xt_table_info *t,
 
                        ADD_COUNTER(counters[i], bcnt, pcnt);
                        ++i;
+                       cond_resched();
                }
        }
 }
index 576cba2b57e92753671c67b6df88e2cc67374cde..39286e543ee683fee9ee7d302d860ec3ee0ea104 100644 (file)
@@ -776,6 +776,7 @@ get_counters(const struct xt_table_info *t,
 
                        ADD_COUNTER(counters[i], bcnt, pcnt);
                        ++i; /* macro does multi eval of i */
+                       cond_resched();
                }
        }
 }
index a63486afa7a7e7b4dce88b65bc27cfa872a3ba2f..d9416b5162bc1bdd1acd34fcb4da21cb6b62d0ae 100644 (file)
@@ -1669,9 +1669,9 @@ process:
                 */
                sock_hold(sk);
                refcounted = true;
-               if (tcp_filter(sk, skb))
-                       goto discard_and_relse;
-               nsk = tcp_check_req(sk, skb, req, false);
+               nsk = NULL;
+               if (!tcp_filter(sk, skb))
+                       nsk = tcp_check_req(sk, skb, req, false);
                if (!nsk) {
                        reqsk_put(req);
                        goto discard_and_relse;
index db1c9e78c83c7fb0aba67114c5909c583e618a0a..ef29df8648e4d388547269fe6f972e8ab473419e 100644 (file)
@@ -1397,12 +1397,15 @@ void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len)
                unlock_sock_fast(sk, slow);
        }
 
+       if (!skb_unref(skb))
+               return;
+
        /* In the more common cases we cleared the head states previously,
         * see __udp_queue_rcv_skb().
         */
        if (unlikely(udp_skb_has_head_state(skb)))
                skb_release_head_state(skb);
-       consume_stateless_skb(skb);
+       __consume_stateless_skb(skb);
 }
 EXPORT_SYMBOL_GPL(skb_consume_udp);
 
index a3b5c163325fa3448818c446c7de502eb4f5a9c8..e5308d7cbd75c4fb67861082382122d445cf5b74 100644 (file)
@@ -191,6 +191,12 @@ void rt6_free_pcpu(struct rt6_info *non_pcpu_rt)
 }
 EXPORT_SYMBOL_GPL(rt6_free_pcpu);
 
+static void fib6_free_table(struct fib6_table *table)
+{
+       inetpeer_invalidate_tree(&table->tb6_peers);
+       kfree(table);
+}
+
 static void fib6_link_table(struct net *net, struct fib6_table *tb)
 {
        unsigned int h;
@@ -2022,15 +2028,22 @@ out_timer:
 
 static void fib6_net_exit(struct net *net)
 {
+       unsigned int i;
+
        rt6_ifdown(net, NULL);
        del_timer_sync(&net->ipv6.ip6_fib_timer);
 
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
-       inetpeer_invalidate_tree(&net->ipv6.fib6_local_tbl->tb6_peers);
-       kfree(net->ipv6.fib6_local_tbl);
-#endif
-       inetpeer_invalidate_tree(&net->ipv6.fib6_main_tbl->tb6_peers);
-       kfree(net->ipv6.fib6_main_tbl);
+       for (i = 0; i < FIB6_TABLE_HASHSZ; i++) {
+               struct hlist_head *head = &net->ipv6.fib_table_hash[i];
+               struct hlist_node *tmp;
+               struct fib6_table *tb;
+
+               hlist_for_each_entry_safe(tb, tmp, head, tb6_hlist) {
+                       hlist_del(&tb->tb6_hlist);
+                       fib6_free_table(tb);
+               }
+       }
+
        kfree(net->ipv6.fib_table_hash);
        kfree(net->ipv6.rt6_stats);
        fib6_notifier_exit(net);
index 67ff2aaf5dcbbe9f64482e2a251f061be8007770..b7a72d40933441f835708f55e2d8af371661a5fb 100644 (file)
@@ -432,7 +432,9 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                }
                break;
        case ICMPV6_PKT_TOOBIG:
-               mtu = be32_to_cpu(info) - offset;
+               mtu = be32_to_cpu(info) - offset - t->tun_hlen;
+               if (t->dev->type == ARPHRD_ETHER)
+                       mtu -= ETH_HLEN;
                if (mtu < IPV6_MIN_MTU)
                        mtu = IPV6_MIN_MTU;
                t->dev->mtu = mtu;
index 3a0ba2ae4b0f69659638b3e5521dcf9d4393dc75..10a693a19323a947a9cb36b407421243c17a8009 100644 (file)
@@ -1184,6 +1184,7 @@ route_lookup:
                init_tel_txopt(&opt, encap_limit);
                ipv6_push_frag_opts(skb, &opt.ops, &proto);
        }
+       hop_limit = hop_limit ? : ip6_dst_hoplimit(dst);
 
        /* Calculate max headroom for all the headers and adjust
         * needed_headroom if necessary.
index 54b1e75eded19ac065a4bf923a3370cd999c9f53..01bd3ee5ebc685f1c1735dfe375633d49c2c5437 100644 (file)
@@ -795,6 +795,7 @@ get_counters(const struct xt_table_info *t,
 
                        ADD_COUNTER(counters[i], bcnt, pcnt);
                        ++i;
+                       cond_resched();
                }
        }
 }
index 38f76d8b231e3e5923ad72d05b8d320b6aeb850f..64d94afa427f81fd7a505b1cfd1c0be66c273810 100644 (file)
@@ -1460,9 +1460,9 @@ process:
                }
                sock_hold(sk);
                refcounted = true;
-               if (tcp_filter(sk, skb))
-                       goto discard_and_relse;
-               nsk = tcp_check_req(sk, skb, req, false);
+               nsk = NULL;
+               if (!tcp_filter(sk, skb))
+                       nsk = tcp_check_req(sk, skb, req, false);
                if (!nsk) {
                        reqsk_put(req);
                        goto discard_and_relse;
index 2b36eff5d97ea7c1cef117033c66dd35058ac4e7..2849a1fc41c5dbbe06a7e5c9fbb4ff6276c84394 100644 (file)
@@ -245,10 +245,10 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d
        ieee80211_tx_skb(sdata, skb);
 }
 
-void __ieee80211_start_rx_ba_session(struct sta_info *sta,
-                                    u8 dialog_token, u16 timeout,
-                                    u16 start_seq_num, u16 ba_policy, u16 tid,
-                                    u16 buf_size, bool tx, bool auto_seq)
+void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
+                                     u8 dialog_token, u16 timeout,
+                                     u16 start_seq_num, u16 ba_policy, u16 tid,
+                                     u16 buf_size, bool tx, bool auto_seq)
 {
        struct ieee80211_local *local = sta->sdata->local;
        struct tid_ampdu_rx *tid_agg_rx;
@@ -267,7 +267,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
                ht_dbg(sta->sdata,
                       "STA %pM requests BA session on unsupported tid %d\n",
                       sta->sta.addr, tid);
-               goto end_no_lock;
+               goto end;
        }
 
        if (!sta->sta.ht_cap.ht_supported) {
@@ -275,14 +275,14 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
                       "STA %pM erroneously requests BA session on tid %d w/o QoS\n",
                       sta->sta.addr, tid);
                /* send a response anyway, it's an error case if we get here */
-               goto end_no_lock;
+               goto end;
        }
 
        if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
                ht_dbg(sta->sdata,
                       "Suspend in progress - Denying ADDBA request (%pM tid %d)\n",
                       sta->sta.addr, tid);
-               goto end_no_lock;
+               goto end;
        }
 
        /* sanity check for incoming parameters:
@@ -296,7 +296,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
                ht_dbg_ratelimited(sta->sdata,
                                   "AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n",
                                   sta->sta.addr, tid, ba_policy, buf_size);
-               goto end_no_lock;
+               goto end;
        }
        /* determine default buffer size */
        if (buf_size == 0)
@@ -311,7 +311,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
               buf_size, sta->sta.addr);
 
        /* examine state machine */
-       mutex_lock(&sta->ampdu_mlme.mtx);
+       lockdep_assert_held(&sta->ampdu_mlme.mtx);
 
        if (test_bit(tid, sta->ampdu_mlme.agg_session_valid)) {
                if (sta->ampdu_mlme.tid_rx_token[tid] == dialog_token) {
@@ -415,15 +415,25 @@ end:
                __clear_bit(tid, sta->ampdu_mlme.unexpected_agg);
                sta->ampdu_mlme.tid_rx_token[tid] = dialog_token;
        }
-       mutex_unlock(&sta->ampdu_mlme.mtx);
 
-end_no_lock:
        if (tx)
                ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid,
                                          dialog_token, status, 1, buf_size,
                                          timeout);
 }
 
+void __ieee80211_start_rx_ba_session(struct sta_info *sta,
+                                    u8 dialog_token, u16 timeout,
+                                    u16 start_seq_num, u16 ba_policy, u16 tid,
+                                    u16 buf_size, bool tx, bool auto_seq)
+{
+       mutex_lock(&sta->ampdu_mlme.mtx);
+       ___ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
+                                        start_seq_num, ba_policy, tid,
+                                        buf_size, tx, auto_seq);
+       mutex_unlock(&sta->ampdu_mlme.mtx);
+}
+
 void ieee80211_process_addba_request(struct ieee80211_local *local,
                                     struct sta_info *sta,
                                     struct ieee80211_mgmt *mgmt,
index cbd48762256cb26a4f06efdd3ae91994f99f7a44..bef516ec47f94c19f57da37d80c744bb534deeb4 100644 (file)
@@ -226,7 +226,11 @@ ieee80211_agg_start_txq(struct sta_info *sta, int tid, bool enable)
                clear_bit(IEEE80211_TXQ_AMPDU, &txqi->flags);
 
        clear_bit(IEEE80211_TXQ_STOP, &txqi->flags);
+       local_bh_disable();
+       rcu_read_lock();
        drv_wake_tx_queue(sta->sdata->local, txqi);
+       rcu_read_unlock();
+       local_bh_enable();
 }
 
 /*
@@ -436,7 +440,7 @@ static void sta_addba_resp_timer_expired(unsigned long data)
            test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) {
                rcu_read_unlock();
                ht_dbg(sta->sdata,
-                      "timer expired on %pM tid %d but we are not (or no longer) expecting addBA response there\n",
+                      "timer expired on %pM tid %d not expecting addBA response\n",
                       sta->sta.addr, tid);
                return;
        }
@@ -639,7 +643,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
            time_before(jiffies, sta->ampdu_mlme.last_addba_req_time[tid] +
                        HT_AGG_RETRIES_PERIOD)) {
                ht_dbg(sdata,
-                      "BA request denied - waiting a grace period after %d failed requests on %pM tid %u\n",
+                      "BA request denied - %d failed requests on %pM tid %u\n",
                       sta->ampdu_mlme.addba_req_num[tid], sta->sta.addr, tid);
                ret = -EBUSY;
                goto err_unlock_sta;
index c92df492e8988ee55e5146acb715e5403ff135e3..d6d0b4201e40bf2eadc2ac7051192c7ca5551439 100644 (file)
@@ -300,6 +300,24 @@ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta,
 
        /* stopping might queue the work again - so cancel only afterwards */
        cancel_work_sync(&sta->ampdu_mlme.work);
+
+       /*
+        * In case the tear down is part of a reconfigure due to HW restart
+        * request, it is possible that the low level driver requested to stop
+        * the BA session, so handle it to properly clean tid_tx data.
+        */
+       mutex_lock(&sta->ampdu_mlme.mtx);
+       for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
+               struct tid_ampdu_tx *tid_tx =
+                       rcu_dereference_protected_tid_tx(sta, i);
+
+               if (!tid_tx)
+                       continue;
+
+               if (test_and_clear_bit(HT_AGG_STATE_STOP_CB, &tid_tx->state))
+                       ieee80211_stop_tx_ba_cb(sta, i, tid_tx);
+       }
+       mutex_unlock(&sta->ampdu_mlme.mtx);
 }
 
 void ieee80211_ba_session_work(struct work_struct *work)
@@ -333,9 +351,9 @@ void ieee80211_ba_session_work(struct work_struct *work)
 
                if (test_and_clear_bit(tid,
                                       sta->ampdu_mlme.tid_rx_manage_offl))
-                       __ieee80211_start_rx_ba_session(sta, 0, 0, 0, 1, tid,
-                                                       IEEE80211_MAX_AMPDU_BUF,
-                                                       false, true);
+                       ___ieee80211_start_rx_ba_session(sta, 0, 0, 0, 1, tid,
+                                                        IEEE80211_MAX_AMPDU_BUF,
+                                                        false, true);
 
                if (test_and_clear_bit(tid + IEEE80211_NUM_TIDS,
                                       sta->ampdu_mlme.tid_rx_manage_offl))
index 2197c62a0a6e1166418123964f64d4f8487e88ea..9675814f64dbcc9807e69452e4ad93a4dfe42556 100644 (file)
@@ -1760,6 +1760,10 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
                                     u8 dialog_token, u16 timeout,
                                     u16 start_seq_num, u16 ba_policy, u16 tid,
                                     u16 buf_size, bool tx, bool auto_seq);
+void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
+                                     u8 dialog_token, u16 timeout,
+                                     u16 start_seq_num, u16 ba_policy, u16 tid,
+                                     u16 buf_size, bool tx, bool auto_seq);
 void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta,
                                         enum ieee80211_agg_stop_reason reason);
 void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
index 9228ac73c429921673bf2c058e821a07dcdfec92..f75029abf7286d54708b1739ee5faa89a43fe2ff 100644 (file)
@@ -731,7 +731,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
            sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
            local->ops->wake_tx_queue) {
                /* XXX: for AP_VLAN, actually track AP queues */
-               netif_tx_start_all_queues(dev);
+               if (dev)
+                       netif_tx_start_all_queues(dev);
        } else if (dev) {
                unsigned long flags;
                int n_acs = IEEE80211_NUM_ACS;
@@ -792,6 +793,7 @@ static int ieee80211_open(struct net_device *dev)
 static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                              bool going_down)
 {
+       struct ieee80211_sub_if_data *txq_sdata = sdata;
        struct ieee80211_local *local = sdata->local;
        struct fq *fq = &local->fq;
        unsigned long flags;
@@ -937,6 +939,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 
        switch (sdata->vif.type) {
        case NL80211_IFTYPE_AP_VLAN:
+               txq_sdata = container_of(sdata->bss,
+                                        struct ieee80211_sub_if_data, u.ap);
+
                mutex_lock(&local->mtx);
                list_del(&sdata->u.vlan.list);
                mutex_unlock(&local->mtx);
@@ -1007,8 +1012,17 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
        }
        spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 
-       if (sdata->vif.txq) {
-               struct txq_info *txqi = to_txq_info(sdata->vif.txq);
+       if (txq_sdata->vif.txq) {
+               struct txq_info *txqi = to_txq_info(txq_sdata->vif.txq);
+
+               /*
+                * FIXME FIXME
+                *
+                * We really shouldn't purge the *entire* txqi since that
+                * contains frames for the other AP_VLANs (and possibly
+                * the AP itself) as well, but there's no API in FQ now
+                * to be able to filter.
+                */
 
                spin_lock_bh(&fq->lock);
                ieee80211_txq_purge(local, txqi);
index b588e593b0ec175a72251345174928b724e83838..3b8e2709d8dea14ba4711de7d7d5c6ed5b48473a 100644 (file)
@@ -3155,7 +3155,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
        if (len < 24 + 6)
                return;
 
-       reassoc = ieee80211_is_reassoc_req(mgmt->frame_control);
+       reassoc = ieee80211_is_reassoc_resp(mgmt->frame_control);
        capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
        status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
        aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
index f8e7a8bbc618727bada48c27d59bc01ed5a18498..faf4f60550001df531bd6b808fbafc8b74a28d30 100644 (file)
@@ -707,6 +707,8 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
        if (!cookie)
                return -ENOENT;
 
+       flush_work(&local->hw_roc_start);
+
        mutex_lock(&local->mtx);
        list_for_each_entry_safe(roc, tmp, &local->roc_list, list) {
                if (!mgmt_tx && roc->cookie != cookie)
index 8858f4f185e90953d096ec28debc21f5dd2bc20d..94826680cf2b54e2a6254146856b495d0ba5e861 100644 (file)
@@ -1276,11 +1276,6 @@ static void ieee80211_set_skb_enqueue_time(struct sk_buff *skb)
        IEEE80211_SKB_CB(skb)->control.enqueue_time = codel_get_time();
 }
 
-static void ieee80211_set_skb_vif(struct sk_buff *skb, struct txq_info *txqi)
-{
-       IEEE80211_SKB_CB(skb)->control.vif = txqi->txq.vif;
-}
-
 static u32 codel_skb_len_func(const struct sk_buff *skb)
 {
        return skb->len;
@@ -3414,6 +3409,7 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
        struct ieee80211_tx_info *info;
        struct ieee80211_tx_data tx;
        ieee80211_tx_result r;
+       struct ieee80211_vif *vif;
 
        spin_lock_bh(&fq->lock);
 
@@ -3430,8 +3426,6 @@ begin:
        if (!skb)
                goto out;
 
-       ieee80211_set_skb_vif(skb, txqi);
-
        hdr = (struct ieee80211_hdr *)skb->data;
        info = IEEE80211_SKB_CB(skb);
 
@@ -3488,6 +3482,34 @@ begin:
                }
        }
 
+       switch (tx.sdata->vif.type) {
+       case NL80211_IFTYPE_MONITOR:
+               if (tx.sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
+                       vif = &tx.sdata->vif;
+                       break;
+               }
+               tx.sdata = rcu_dereference(local->monitor_sdata);
+               if (tx.sdata) {
+                       vif = &tx.sdata->vif;
+                       info->hw_queue =
+                               vif->hw_queue[skb_get_queue_mapping(skb)];
+               } else if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL)) {
+                       ieee80211_free_txskb(&local->hw, skb);
+                       goto begin;
+               } else {
+                       vif = NULL;
+               }
+               break;
+       case NL80211_IFTYPE_AP_VLAN:
+               tx.sdata = container_of(tx.sdata->bss,
+                                       struct ieee80211_sub_if_data, u.ap);
+               /* fall through */
+       default:
+               vif = &tx.sdata->vif;
+               break;
+       }
+
+       IEEE80211_SKB_CB(skb)->control.vif = vif;
 out:
        spin_unlock_bh(&fq->lock);
 
index 259698de569ffa6a93c2738f85d6fd6af142eb9a..6aef6793d05236c19afe00a51f4ddc91bc060a39 100644 (file)
@@ -1436,7 +1436,7 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local,
                        WLAN_EID_SSID_LIST,
                        WLAN_EID_CHANNEL_USAGE,
                        WLAN_EID_INTERWORKING,
-                       /* mesh ID can't happen here */
+                       WLAN_EID_MESH_ID,
                        /* 60 GHz can't happen here right now */
                };
                noffset = ieee80211_ie_split(ie, ie_len,
index 04fe25abc5f66e2e892cb8d606846e46d5a0b7f1..52cd2901a097b3b468f1107d9d870260aaff11e3 100644 (file)
@@ -215,7 +215,7 @@ static void *__nf_hook_entries_try_shrink(struct nf_hook_entries __rcu **pp)
        if (skip == hook_entries)
                goto out_assign;
 
-       if (WARN_ON(skip == 0))
+       if (skip == 0)
                return NULL;
 
        hook_entries -= skip;
index e1efa446b305e711514671000d2de58c429ff00d..57c8ee66491eb8a66944afa3250396c36b11b218 100644 (file)
@@ -24,9 +24,13 @@ sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
                if (sh) {
                        sch = skb_header_pointer(skb, iph->len + sizeof(_sctph),
                                                 sizeof(_schunkh), &_schunkh);
-                       if (sch && (sch->type == SCTP_CID_INIT ||
-                                   sysctl_sloppy_sctp(ipvs)))
+                       if (sch) {
+                               if (sch->type == SCTP_CID_ABORT ||
+                                   !(sysctl_sloppy_sctp(ipvs) ||
+                                     sch->type == SCTP_CID_INIT))
+                                       return 1;
                                ports = &sh->source;
+                       }
                }
        } else {
                ports = skb_header_pointer(
index 40573aa6c133f884c88332e68f7b29b802a50c35..f393a7086025f6c5e16032baeed63fa1cffba168 100644 (file)
 #include <net/netfilter/nf_conntrack_zones.h>
 #include <linux/netfilter/nf_nat.h>
 
+static spinlock_t nf_nat_locks[CONNTRACK_LOCKS];
+
 static DEFINE_MUTEX(nf_nat_proto_mutex);
 static const struct nf_nat_l3proto __rcu *nf_nat_l3protos[NFPROTO_NUMPROTO]
                                                __read_mostly;
 static const struct nf_nat_l4proto __rcu **nf_nat_l4protos[NFPROTO_NUMPROTO]
                                                __read_mostly;
 
-struct nf_nat_conn_key {
-       const struct net *net;
-       const struct nf_conntrack_tuple *tuple;
-       const struct nf_conntrack_zone *zone;
-};
-
-static struct rhltable nf_nat_bysource_table;
+static struct hlist_head *nf_nat_bysource __read_mostly;
+static unsigned int nf_nat_htable_size __read_mostly;
+static unsigned int nf_nat_hash_rnd __read_mostly;
 
 inline const struct nf_nat_l3proto *
 __nf_nat_l3proto_find(u8 family)
@@ -118,17 +116,19 @@ int nf_xfrm_me_harder(struct net *net, struct sk_buff *skb, unsigned int family)
 EXPORT_SYMBOL(nf_xfrm_me_harder);
 #endif /* CONFIG_XFRM */
 
-static u32 nf_nat_bysource_hash(const void *data, u32 len, u32 seed)
+/* We keep an extra hash for each conntrack, for fast searching. */
+static unsigned int
+hash_by_src(const struct net *n, const struct nf_conntrack_tuple *tuple)
 {
-       const struct nf_conntrack_tuple *t;
-       const struct nf_conn *ct = data;
+       unsigned int hash;
+
+       get_random_once(&nf_nat_hash_rnd, sizeof(nf_nat_hash_rnd));
 
-       t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
        /* Original src, to ensure we map it consistently if poss. */
+       hash = jhash2((u32 *)&tuple->src, sizeof(tuple->src) / sizeof(u32),
+                     tuple->dst.protonum ^ nf_nat_hash_rnd ^ net_hash_mix(n));
 
-       seed ^= net_hash_mix(nf_ct_net(ct));
-       return jhash2((const u32 *)&t->src, sizeof(t->src) / sizeof(u32),
-                     t->dst.protonum ^ seed);
+       return reciprocal_scale(hash, nf_nat_htable_size);
 }
 
 /* Is this tuple already taken? (not by us) */
@@ -184,28 +184,6 @@ same_src(const struct nf_conn *ct,
                t->src.u.all == tuple->src.u.all);
 }
 
-static int nf_nat_bysource_cmp(struct rhashtable_compare_arg *arg,
-                              const void *obj)
-{
-       const struct nf_nat_conn_key *key = arg->key;
-       const struct nf_conn *ct = obj;
-
-       if (!same_src(ct, key->tuple) ||
-           !net_eq(nf_ct_net(ct), key->net) ||
-           !nf_ct_zone_equal(ct, key->zone, IP_CT_DIR_ORIGINAL))
-               return 1;
-
-       return 0;
-}
-
-static struct rhashtable_params nf_nat_bysource_params = {
-       .head_offset = offsetof(struct nf_conn, nat_bysource),
-       .obj_hashfn = nf_nat_bysource_hash,
-       .obj_cmpfn = nf_nat_bysource_cmp,
-       .nelem_hint = 256,
-       .min_size = 1024,
-};
-
 /* Only called for SRC manip */
 static int
 find_appropriate_src(struct net *net,
@@ -216,26 +194,22 @@ find_appropriate_src(struct net *net,
                     struct nf_conntrack_tuple *result,
                     const struct nf_nat_range *range)
 {
+       unsigned int h = hash_by_src(net, tuple);
        const struct nf_conn *ct;
-       struct nf_nat_conn_key key = {
-               .net = net,
-               .tuple = tuple,
-               .zone = zone
-       };
-       struct rhlist_head *hl, *h;
-
-       hl = rhltable_lookup(&nf_nat_bysource_table, &key,
-                            nf_nat_bysource_params);
-
-       rhl_for_each_entry_rcu(ct, h, hl, nat_bysource) {
-               nf_ct_invert_tuplepr(result,
-                                    &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
-               result->dst = tuple->dst;
 
-               if (in_range(l3proto, l4proto, result, range))
-                       return 1;
+       hlist_for_each_entry_rcu(ct, &nf_nat_bysource[h], nat_bysource) {
+               if (same_src(ct, tuple) &&
+                   net_eq(net, nf_ct_net(ct)) &&
+                   nf_ct_zone_equal(ct, zone, IP_CT_DIR_ORIGINAL)) {
+                       /* Copy source part from reply tuple. */
+                       nf_ct_invert_tuplepr(result,
+                                      &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+                       result->dst = tuple->dst;
+
+                       if (in_range(l3proto, l4proto, result, range))
+                               return 1;
+               }
        }
-
        return 0;
 }
 
@@ -408,6 +382,7 @@ nf_nat_setup_info(struct nf_conn *ct,
                  const struct nf_nat_range *range,
                  enum nf_nat_manip_type maniptype)
 {
+       struct net *net = nf_ct_net(ct);
        struct nf_conntrack_tuple curr_tuple, new_tuple;
 
        /* Can't setup nat info for confirmed ct. */
@@ -416,7 +391,9 @@ nf_nat_setup_info(struct nf_conn *ct,
 
        WARN_ON(maniptype != NF_NAT_MANIP_SRC &&
                maniptype != NF_NAT_MANIP_DST);
-       BUG_ON(nf_nat_initialized(ct, maniptype));
+
+       if (WARN_ON(nf_nat_initialized(ct, maniptype)))
+               return NF_DROP;
 
        /* What we've got will look like inverse of reply. Normally
         * this is what is in the conntrack, except for prior
@@ -447,19 +424,16 @@ nf_nat_setup_info(struct nf_conn *ct,
        }
 
        if (maniptype == NF_NAT_MANIP_SRC) {
-               struct nf_nat_conn_key key = {
-                       .net = nf_ct_net(ct),
-                       .tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
-                       .zone = nf_ct_zone(ct),
-               };
-               int err;
-
-               err = rhltable_insert_key(&nf_nat_bysource_table,
-                                         &key,
-                                         &ct->nat_bysource,
-                                         nf_nat_bysource_params);
-               if (err)
-                       return NF_DROP;
+               unsigned int srchash;
+               spinlock_t *lock;
+
+               srchash = hash_by_src(net,
+                                     &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+               lock = &nf_nat_locks[srchash % ARRAY_SIZE(nf_nat_locks)];
+               spin_lock_bh(lock);
+               hlist_add_head_rcu(&ct->nat_bysource,
+                                  &nf_nat_bysource[srchash]);
+               spin_unlock_bh(lock);
        }
 
        /* It's done. */
@@ -553,6 +527,16 @@ static int nf_nat_proto_remove(struct nf_conn *i, void *data)
        return i->status & IPS_NAT_MASK ? 1 : 0;
 }
 
+static void __nf_nat_cleanup_conntrack(struct nf_conn *ct)
+{
+       unsigned int h;
+
+       h = hash_by_src(nf_ct_net(ct), &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+       spin_lock_bh(&nf_nat_locks[h % ARRAY_SIZE(nf_nat_locks)]);
+       hlist_del_rcu(&ct->nat_bysource);
+       spin_unlock_bh(&nf_nat_locks[h % ARRAY_SIZE(nf_nat_locks)]);
+}
+
 static int nf_nat_proto_clean(struct nf_conn *ct, void *data)
 {
        if (nf_nat_proto_remove(ct, data))
@@ -568,8 +552,7 @@ static int nf_nat_proto_clean(struct nf_conn *ct, void *data)
         * will delete entry from already-freed table.
         */
        clear_bit(IPS_SRC_NAT_DONE_BIT, &ct->status);
-       rhltable_remove(&nf_nat_bysource_table, &ct->nat_bysource,
-                       nf_nat_bysource_params);
+       __nf_nat_cleanup_conntrack(ct);
 
        /* don't delete conntrack.  Although that would make things a lot
         * simpler, we'd end up flushing all conntracks on nat rmmod.
@@ -698,8 +681,7 @@ EXPORT_SYMBOL_GPL(nf_nat_l3proto_unregister);
 static void nf_nat_cleanup_conntrack(struct nf_conn *ct)
 {
        if (ct->status & IPS_SRC_NAT_DONE)
-               rhltable_remove(&nf_nat_bysource_table, &ct->nat_bysource,
-                               nf_nat_bysource_params);
+               __nf_nat_cleanup_conntrack(ct);
 }
 
 static struct nf_ct_ext_type nat_extend __read_mostly = {
@@ -821,19 +803,27 @@ static struct nf_ct_helper_expectfn follow_master_nat = {
 
 static int __init nf_nat_init(void)
 {
-       int ret;
+       int ret, i;
 
-       ret = rhltable_init(&nf_nat_bysource_table, &nf_nat_bysource_params);
-       if (ret)
-               return ret;
+       /* Leave them the same for the moment. */
+       nf_nat_htable_size = nf_conntrack_htable_size;
+       if (nf_nat_htable_size < ARRAY_SIZE(nf_nat_locks))
+               nf_nat_htable_size = ARRAY_SIZE(nf_nat_locks);
+
+       nf_nat_bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size, 0);
+       if (!nf_nat_bysource)
+               return -ENOMEM;
 
        ret = nf_ct_extend_register(&nat_extend);
        if (ret < 0) {
-               rhltable_destroy(&nf_nat_bysource_table);
+               nf_ct_free_hashtable(nf_nat_bysource, nf_nat_htable_size);
                printk(KERN_ERR "nf_nat_core: Unable to register extension\n");
                return ret;
        }
 
+       for (i = 0; i < ARRAY_SIZE(nf_nat_locks); i++)
+               spin_lock_init(&nf_nat_locks[i]);
+
        nf_ct_helper_expectfn_register(&follow_master_nat);
 
        BUG_ON(nfnetlink_parse_nat_setup_hook != NULL);
@@ -863,8 +853,8 @@ static void __exit nf_nat_cleanup(void)
 
        for (i = 0; i < NFPROTO_NUMPROTO; i++)
                kfree(nf_nat_l4protos[i]);
-
-       rhltable_destroy(&nf_nat_bysource_table);
+       synchronize_net();
+       nf_ct_free_hashtable(nf_nat_bysource, nf_nat_htable_size);
 }
 
 MODULE_LICENSE("GPL");
index 10d48234f5f4c759ff03e2b4d262bbd3619594a1..5da8746f7b88ff4c9446f256e542e823a6a561b0 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter/xt_hashlimit.h>
 #include <linux/mutex.h>
+#include <linux/kernel.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
@@ -279,7 +280,7 @@ static int htable_create(struct net *net, struct hashlimit_cfg3 *cfg,
                size = cfg->size;
        } else {
                size = (totalram_pages << PAGE_SHIFT) / 16384 /
-                      sizeof(struct list_head);
+                      sizeof(struct hlist_head);
                if (totalram_pages > 1024 * 1024 * 1024 / PAGE_SIZE)
                        size = 8192;
                if (size < 16)
@@ -287,7 +288,7 @@ static int htable_create(struct net *net, struct hashlimit_cfg3 *cfg,
        }
        /* FIXME: don't use vmalloc() here or anywhere else -HW */
        hinfo = vmalloc(sizeof(struct xt_hashlimit_htable) +
-                       sizeof(struct list_head) * size);
+                       sizeof(struct hlist_head) * size);
        if (hinfo == NULL)
                return -ENOMEM;
        *out_hinfo = hinfo;
@@ -527,12 +528,12 @@ static u64 user2rate(u64 user)
        }
 }
 
-static u64 user2rate_bytes(u64 user)
+static u64 user2rate_bytes(u32 user)
 {
        u64 r;
 
-       r = user ? 0xFFFFFFFFULL / user : 0xFFFFFFFFULL;
-       r = (r - 1) << 4;
+       r = user ? U32_MAX / user : U32_MAX;
+       r = (r - 1) << XT_HASHLIMIT_BYTE_SHIFT;
        return r;
 }
 
@@ -588,7 +589,8 @@ static void rateinfo_init(struct dsthash_ent *dh,
                dh->rateinfo.prev_window = 0;
                dh->rateinfo.current_rate = 0;
                if (hinfo->cfg.mode & XT_HASHLIMIT_BYTES) {
-                       dh->rateinfo.rate = user2rate_bytes(hinfo->cfg.avg);
+                       dh->rateinfo.rate =
+                               user2rate_bytes((u32)hinfo->cfg.avg);
                        if (hinfo->cfg.burst)
                                dh->rateinfo.burst =
                                        hinfo->cfg.burst * dh->rateinfo.rate;
@@ -870,7 +872,7 @@ static int hashlimit_mt_check_common(const struct xt_mtchk_param *par,
 
        /* Check for overflow. */
        if (revision >= 3 && cfg->mode & XT_HASHLIMIT_RATE_MATCH) {
-               if (cfg->avg == 0) {
+               if (cfg->avg == 0 || cfg->avg > U32_MAX) {
                        pr_info("hashlimit invalid rate\n");
                        return -ERANGE;
                }
index 5acee49db90b508cb99660dc0677a44da691640e..327807731b441e8f66bc899cced12edb405687e8 100644 (file)
@@ -691,6 +691,9 @@ static void deferred_put_nlk_sk(struct rcu_head *head)
        struct netlink_sock *nlk = container_of(head, struct netlink_sock, rcu);
        struct sock *sk = &nlk->sk;
 
+       kfree(nlk->groups);
+       nlk->groups = NULL;
+
        if (!refcount_dec_and_test(&sk->sk_refcnt))
                return;
 
@@ -769,9 +772,6 @@ static int netlink_release(struct socket *sock)
                netlink_table_ungrab();
        }
 
-       kfree(nlk->groups);
-       nlk->groups = NULL;
-
        local_bh_disable();
        sock_prot_inuse_add(sock_net(sk), &netlink_proto, -1);
        local_bh_enable();
@@ -955,7 +955,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
        struct net *net = sock_net(sk);
        struct netlink_sock *nlk = nlk_sk(sk);
        struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
-       int err;
+       int err = 0;
        long unsigned int groups = nladdr->nl_groups;
        bool bound;
 
@@ -983,6 +983,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
                        return -EINVAL;
        }
 
+       netlink_lock_table();
        if (nlk->netlink_bind && groups) {
                int group;
 
@@ -993,7 +994,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
                        if (!err)
                                continue;
                        netlink_undo_bind(group, groups, sk);
-                       return err;
+                       goto unlock;
                }
        }
 
@@ -1006,12 +1007,13 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
                        netlink_autobind(sock);
                if (err) {
                        netlink_undo_bind(nlk->ngroups, groups, sk);
-                       return err;
+                       goto unlock;
                }
        }
 
        if (!groups && (nlk->groups == NULL || !(u32)nlk->groups[0]))
-               return 0;
+               goto unlock;
+       netlink_unlock_table();
 
        netlink_table_grab();
        netlink_update_subscriptions(sk, nlk->subscriptions +
@@ -1022,6 +1024,10 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
        netlink_table_ungrab();
 
        return 0;
+
+unlock:
+       netlink_unlock_table();
+       return err;
 }
 
 static int netlink_connect(struct socket *sock, struct sockaddr *addr,
@@ -1079,7 +1085,9 @@ static int netlink_getname(struct socket *sock, struct sockaddr *addr,
                nladdr->nl_groups = netlink_group_mask(nlk->dst_group);
        } else {
                nladdr->nl_pid = nlk->portid;
+               netlink_lock_table();
                nladdr->nl_groups = nlk->groups ? nlk->groups[0] : 0;
+               netlink_unlock_table();
        }
        return 0;
 }
index 058a407430416c259873d7a1d0fd96edeeef504a..b52cdc8ae428819a5853509a06852ec2ebc43a5a 100644 (file)
@@ -428,14 +428,18 @@ over_batch:
         * some work and we will skip our goto
         */
        if (ret == 0) {
+               bool raced;
+
                smp_mb();
+               raced = send_gen != READ_ONCE(cp->cp_send_gen);
+
                if ((test_bit(0, &conn->c_map_queued) ||
-                    !list_empty(&cp->cp_send_queue)) &&
-                       send_gen == READ_ONCE(cp->cp_send_gen)) {
-                       rds_stats_inc(s_send_lock_queue_raced);
+                   !list_empty(&cp->cp_send_queue)) && !raced) {
                        if (batch_count < send_batch_count)
                                goto restart;
                        queue_delayed_work(rds_wq, &cp->cp_send_w, 1);
+               } else if (raced) {
+                       rds_stats_inc(s_send_lock_queue_raced);
                }
        }
 out:
index ea6c65fd5fc5fa31669191470d963bc851822a00..c743f03cfebd1cb274cd0e80046591d38ee56700 100644 (file)
@@ -182,7 +182,7 @@ static struct tcf_chain *tcf_chain_create(struct tcf_block *block,
        list_add_tail(&chain->list, &block->chain_list);
        chain->block = block;
        chain->index = chain_index;
-       chain->refcnt = 1;
+       chain->refcnt = 0;
        return chain;
 }
 
@@ -217,15 +217,15 @@ struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,
        struct tcf_chain *chain;
 
        list_for_each_entry(chain, &block->chain_list, list) {
-               if (chain->index == chain_index) {
-                       chain->refcnt++;
-                       return chain;
-               }
+               if (chain->index == chain_index)
+                       goto incref;
        }
-       if (create)
-               return tcf_chain_create(block, chain_index);
-       else
-               return NULL;
+       chain = create ? tcf_chain_create(block, chain_index) : NULL;
+
+incref:
+       if (chain)
+               chain->refcnt++;
+       return chain;
 }
 EXPORT_SYMBOL(tcf_chain_get);
 
index f31b28f788c008c570a194501227f628bc15643d..2dd6c68ae91eefe2f4e61b40f833f136c7576871 100644 (file)
@@ -80,7 +80,7 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
 
                if (ret & __NET_XMIT_BYPASS)
                        qdisc_qstats_drop(sch);
-               kfree_skb(skb);
+               __qdisc_drop(skb, to_free);
                return ret;
        }
 #endif
index cd661a7f81e6db4252f1b3a9b4da4adae2728248..6ddfd4991108ad9de057a22175d87f667c24f370 100644 (file)
@@ -1215,7 +1215,7 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        if (cl == NULL) {
                if (err & __NET_XMIT_BYPASS)
                        qdisc_qstats_drop(sch);
-               kfree_skb(skb);
+               __qdisc_drop(skb, to_free);
                return err;
        }
        pr_debug("qfq_enqueue: cl = %x\n", cl->common.classid);
index 0225d62a869f8deff10565c4625df0a10464ce87..a71be33f3afeb0aaaef174ee082c4c547aab1e2d 100644 (file)
@@ -265,7 +265,8 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)
                sctp_ulpq_clear_pd(ulpq);
 
        if (queue == &sk->sk_receive_queue && !sp->data_ready_signalled) {
-               sp->data_ready_signalled = 1;
+               if (!sock_owned_by_user(sk))
+                       sp->data_ready_signalled = 1;
                sk->sk_data_ready(sk);
        }
        return 1;
index ac1d66d7e1fdddcfc53e2251e542c0c8e28ef6d8..47ec121574ce4ef95850f688d85b50eff766a710 100644 (file)
@@ -637,7 +637,7 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
                break;
        case NETDEV_UNREGISTER:
        case NETDEV_CHANGENAME:
-               bearer_disable(dev_net(dev), b);
+               bearer_disable(net, b);
                break;
        }
        return NOTIFY_OK;
index 8ce85420ecb0a7e45567c9c576c6bb9691eb267d..0df8023f480bb69feb4cc2d3e0df6ea95f384e1a 100644 (file)
@@ -3791,8 +3791,8 @@ static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
 static void nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
 {
        const struct cfg80211_beacon_data *bcn = &params->beacon;
-       size_t ies_len = bcn->beacon_ies_len;
-       const u8 *ies = bcn->beacon_ies;
+       size_t ies_len = bcn->tail_len;
+       const u8 *ies = bcn->tail;
        const u8 *rates;
        const u8 *cap;
 
index 5fae296a6a583256f9874319dfaa9ee87e977fff..6e94f6934a0e7a47fbac086586701d07c9bb5487 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright 2007      Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2008-2011 Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
+ * Copyright      2017  Intel Deutschland GmbH
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -1483,7 +1484,9 @@ static void reg_process_ht_flags_channel(struct wiphy *wiphy,
 {
        struct ieee80211_supported_band *sband = wiphy->bands[channel->band];
        struct ieee80211_channel *channel_before = NULL, *channel_after = NULL;
+       const struct ieee80211_regdomain *regd;
        unsigned int i;
+       u32 flags;
 
        if (!is_ht40_allowed(channel)) {
                channel->flags |= IEEE80211_CHAN_NO_HT40;
@@ -1503,17 +1506,30 @@ static void reg_process_ht_flags_channel(struct wiphy *wiphy,
                        channel_after = c;
        }
 
+       flags = 0;
+       regd = get_wiphy_regdom(wiphy);
+       if (regd) {
+               const struct ieee80211_reg_rule *reg_rule =
+                       freq_reg_info_regd(MHZ_TO_KHZ(channel->center_freq),
+                                          regd, MHZ_TO_KHZ(20));
+
+               if (!IS_ERR(reg_rule))
+                       flags = reg_rule->flags;
+       }
+
        /*
         * Please note that this assumes target bandwidth is 20 MHz,
         * if that ever changes we also need to change the below logic
         * to include that as well.
         */
-       if (!is_ht40_allowed(channel_before))
+       if (!is_ht40_allowed(channel_before) ||
+           flags & NL80211_RRF_NO_HT40MINUS)
                channel->flags |= IEEE80211_CHAN_NO_HT40MINUS;
        else
                channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
 
-       if (!is_ht40_allowed(channel_after))
+       if (!is_ht40_allowed(channel_after) ||
+           flags & NL80211_RRF_NO_HT40PLUS)
                channel->flags |= IEEE80211_CHAN_NO_HT40PLUS;
        else
                channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
index 4acc772a28c0a72026c583b809f192fb81f97f79..fe3a443a110228efb99bc893d2f0820cd03e6763 100644 (file)
@@ -558,7 +558,7 @@ static void test_sockmap(int tasks, void *data)
                }
        }
 
-       /* Test attaching bad fds */
+       /* Test attaching/detaching bad fds */
        err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_PARSER, 0);
        if (!err) {
                printf("Failed invalid parser prog attach\n");
@@ -571,6 +571,30 @@ static void test_sockmap(int tasks, void *data)
                goto out_sockmap;
        }
 
+       err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0);
+       if (!err) {
+               printf("Failed unknown prog attach\n");
+               goto out_sockmap;
+       }
+
+       err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER);
+       if (err) {
+               printf("Failed empty parser prog detach\n");
+               goto out_sockmap;
+       }
+
+       err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT);
+       if (err) {
+               printf("Failed empty verdict prog detach\n");
+               goto out_sockmap;
+       }
+
+       err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE);
+       if (!err) {
+               printf("Detach invalid prog successful\n");
+               goto out_sockmap;
+       }
+
        /* Load SK_SKB program and Attach */
        err = bpf_prog_load(SOCKMAP_PARSE_PROG,
                            BPF_PROG_TYPE_SK_SKB, &obj, &parse_prog);
@@ -643,6 +667,13 @@ static void test_sockmap(int tasks, void *data)
                goto out_sockmap;
        }
 
+       err = bpf_prog_attach(verdict_prog, map_fd_rx,
+                             __MAX_BPF_ATTACH_TYPE, 0);
+       if (!err) {
+               printf("Attached unknown bpf prog\n");
+               goto out_sockmap;
+       }
+
        /* Test map update elem afterwards fd lives in fd and map_fd */
        for (i = 0; i < 6; i++) {
                err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY);
@@ -809,6 +840,24 @@ static void test_sockmap(int tasks, void *data)
                assert(status == 0);
        }
 
+       err = bpf_prog_detach(map_fd_rx, __MAX_BPF_ATTACH_TYPE);
+       if (!err) {
+               printf("Detached an invalid prog type.\n");
+               goto out_sockmap;
+       }
+
+       err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
+       if (err) {
+               printf("Failed parser prog detach\n");
+               goto out_sockmap;
+       }
+
+       err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
+       if (err) {
+               printf("Failed parser prog detach\n");
+               goto out_sockmap;
+       }
+
        /* Test map close sockets */
        for (i = 0; i < 6; i++)
                close(sfd[i]);