Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville...
authorDavid S. Miller <davem@davemloft.net>
Mon, 31 Mar 2014 20:44:55 +0000 (16:44 -0400)
committerDavid S. Miller <davem@davemloft.net>
Mon, 31 Mar 2014 20:44:55 +0000 (16:44 -0400)
John W. Linville says:

====================
pull request: wireless-next 2014-03-31

Please accept this one last round of general wireless updates for
the 3.15 merge window!

For the Bluetooth bits, Gustavo says:

"Here follow another set of patches to 3.15. This is mostly a bug fix
pull request with the exception of one commit from Marcel which adds
tracking to the current configured LE scan type parameter."

Beyond that, notable bits include some final refactoring of rtl8180
and the addition of the rtl8187se driver, fixes for a number of
problems identified by Dan Carpenter and his static analysis tools,
and a handful of other bits here and there.

Please let me know if there are problems!
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
21 files changed:
Documentation/ABI/testing/sysfs-class-net [new file with mode: 0644]
drivers/net/ethernet/freescale/fec_main.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/qmi_wwan.c
include/linux/netdevice.h
include/net/ip6_route.h
include/uapi/linux/if_link.h
include/uapi/linux/netdevice.h
net/bridge/br_forward.c
net/core/dev.c
net/core/net-sysfs.c
net/core/rtnetlink.c
net/ipv6/icmp.c
net/ipv6/ip6_output.c
net/ipv6/mcast.c
net/ipv6/output_core.c
net/ipv6/ping.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/rds/iw.c
net/sched/sch_generic.c

diff --git a/Documentation/ABI/testing/sysfs-class-net b/Documentation/ABI/testing/sysfs-class-net
new file mode 100644 (file)
index 0000000..d922060
--- /dev/null
@@ -0,0 +1,199 @@
+What:          /sys/class/net/<iface>/addr_assign_type
+Date:          July 2010
+KernelVersion: 3.2
+Contact:       netdev@vger.kernel.org
+Description:
+               Indicates the address assignment type. Possible values are:
+               0: permanent address
+               1: randomly generated
+               2: stolen from another device
+               3: set using dev_set_mac_address
+
+What:          /sys/class/net/<iface>/addr_len
+Date:          April 2005
+KernelVersion: 2.6.12
+Contact:       netdev@vger.kernel.org
+Description:
+               Indicates the hardware address size in bytes.
+               Values vary based on the lower-level protocol used by the
+               interface (Ethernet, FDDI, ATM, IEEE 802.15.4...). See
+               include/uapi/linux/if_*.h for actual values.
+
+What:          /sys/class/net/<iface>/address
+Date:          April 2005
+KernelVersion: 2.6.12
+Contact:       netdev@vger.kernel.org
+Description:
+               Hardware address currently assigned to this interface.
+               Format is a string, e.g: 00:11:22:33:44:55 for an Ethernet MAC
+               address.
+
+What:          /sys/class/net/<iface>/broadcast
+Date:          April 2005
+KernelVersion: 2.6.12
+Contact:       netdev@vger.kernel.org
+Description:
+               Hardware broadcast address for this interface. Format is a
+               string, e.g: ff:ff:ff:ff:ff:ff for an Ethernet broadcast MAC
+               address.
+
+What:          /sys/class/net/<iface>/carrier
+Date:          April 2005
+KernelVersion: 2.6.12
+Contact:       netdev@vger.kernel.org
+Description:
+               Indicates the current physical link state of the interface.
+               Posssible values are:
+               0: physical link is down
+               1: physical link is up
+
+               Note: some special devices, e.g: bonding and team drivers will
+               allow this attribute to be written to force a link state for
+               operating correctly and designating another fallback interface.
+
+What:          /sys/class/net/<iface>/dev_id
+Date:          April 2008
+KernelVersion: 2.6.26
+Contact:       netdev@vger.kernel.org
+Description:
+               Indicates the device unique identifier. Format is an hexadecimal
+               value. This is used to disambiguate interfaces which might be
+               stacked (e.g: VLAN interfaces) but still have the same MAC
+               address as their parent device.
+
+What:          /sys/class/net/<iface>/dormant
+Date:          March 2006
+KernelVersion: 2.6.17
+Contact:       netdev@vger.kernel.org
+Description:
+               Indicates whether the interface is in dormant state. Possible
+               values are:
+               0: interface is not dormant
+               1: interface is dormant
+
+               This attribute can be used by supplicant software to signal that
+               the device is not usable unless some supplicant-based
+               authentication is performed (e.g: 802.1x). 'link_mode' attribute
+               will also reflect the dormant state.
+
+What:          /sys/clas/net/<iface>/duplex
+Date:          October 2009
+KernelVersion: 2.6.33
+Contact:       netdev@vger.kernel.org
+Description:
+               Indicates the interface latest or current duplex value. Possible
+               values are:
+               half: half duplex
+               full: full duplex
+
+               Note: This attribute is only valid for interfaces that implement
+               the ethtool get_settings method (mostly Ethernet).
+
+What:          /sys/class/net/<iface>/flags
+Date:          April 2005
+KernelVersion: 2.6.12
+Contact:       netdev@vger.kernel.org
+Description:
+               Indicates the interface flags as a bitmask in hexadecimal. See
+               include/uapi/linux/if.h for a list of all possible values and
+               the flags semantics.
+
+What:          /sys/class/net/<iface>/ifalias
+Date:          September 2008
+KernelVersion: 2.6.28
+Contact:       netdev@vger.kernel.org
+Description:
+               Indicates/stores an interface alias name as a string. This can
+               be used for system management purposes.
+
+What:          /sys/class/net/<iface>/ifindex
+Date:          April 2005
+KernelVersion: 2.6.12
+Contact:       netdev@vger.kernel.org
+Description:
+               Indicates the system-wide interface unique index identifier as a
+               decimal number. This attribute is used for mapping an interface
+               identifier to an interface name. It is used throughout the
+               networking stack for specifying the interface specific
+               requests/events.
+
+What:          /sys/class/net/<iface>/iflink
+Date:          April 2005
+KernelVersion: 2.6.12
+Contact:       netdev@vger.kernel.org
+Description:
+               Indicates the system-wide interface unique index identifier a
+               the interface is linked to. Format is decimal. This attribute is
+               used to resolve interfaces chaining, linking and stacking.
+               Physical interfaces have the same 'ifindex' and 'iflink' values.
+
+What:          /sys/class/net/<iface>/link_mode
+Date:          March 2006
+KernelVersion: 2.6.17
+Contact:       netdev@vger.kernel.org
+Description:
+               Indicates the interface link mode, as a decimal number. This
+               attribute should be used in conjunction with 'dormant' attribute
+               to determine the interface usability. Possible values:
+               0: default link mode
+               1: dormant link mode
+
+What:          /sys/class/net/<iface>/mtu
+Date:          April 2005
+KernelVersion: 2.6.12
+Contact:       netdev@vger.kernel.org
+Description:
+               Indicates the interface currently configured MTU value, in
+               bytes, and in decimal format. Specific values depends on the
+               lower-level interface protocol used. Ethernet devices will show
+               a 'mtu' attribute value of 1500 unless changed.
+
+What:          /sys/calss/net/<iface>/netdev_group
+Date:          January 2011
+KernelVersion: 2.6.39
+Contact:       netdev@vger.kernel.org
+Description:
+               Indicates the interface network device group, as a decimal
+               integer. Default value is 0 which corresponds to the initial
+               network devices group. The group can be changed to affect
+               routing decisions (see: net/ipv4/fib_rules and
+               net/ipv6/fib6_rules.c).
+
+What:          /sys/class/net/<iface>/operstate
+Date:          March 2006
+KernelVersion: 2.6.17
+Contact:       netdev@vger.kernel.org
+Description:
+               Indicates the interface RFC2863 operational state as a string.
+               Possible values are:
+               "unknown", "notpresent", "down", "lowerlayerdown", "testing",
+               "dormant", "up".
+
+What:          /sys/class/net/<iface>/speed
+Date:          October 2009
+KernelVersion: 2.6.33
+Contact:       netdev@vger.kernel.org
+Description:
+               Indicates the interface latest or current speed value. Value is
+               an integer representing the link speed in Mbits/sec.
+
+               Note: this attribute is only valid for interfaces that implement
+               the ethtool get_settings method (mostly Ethernet ).
+
+What:          /sys/class/net/<iface>/tx_queue_len
+Date:          April 2005
+KernelVersion: 2.6.12
+Contact:       netdev@vger.kernel.org
+Description:
+               Indicates the interface transmit queue len in number of packets,
+               as an integer value. Value depend on the type of interface,
+               Ethernet network adapters have a default value of 1000 unless
+               configured otherwise
+
+What:          /sys/class/net/<iface>/type
+Date:          April 2005
+KernelVersion: 2.6.12
+Contact:       netdev@vger.kernel.org
+Description:
+               Indicates the interface protocol type as a decimal value. See
+               include/uapi/linux/if_arp.h for all possible values.
index e19315eaf2dd65a13bad1f064f856d0e04378dcb..8d69e439f0c518d4b3e46c9ae21d85e4013b7e06 100644 (file)
@@ -1898,10 +1898,11 @@ fec_set_mac_address(struct net_device *ndev, void *p)
        struct fec_enet_private *fep = netdev_priv(ndev);
        struct sockaddr *addr = p;
 
-       if (!is_valid_ether_addr(addr->sa_data))
-               return -EADDRNOTAVAIL;
-
-       memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
+       if (addr) {
+               if (!is_valid_ether_addr(addr->sa_data))
+                       return -EADDRNOTAVAIL;
+               memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
+       }
 
        writel(ndev->dev_addr[3] | (ndev->dev_addr[2] << 8) |
                (ndev->dev_addr[1] << 16) | (ndev->dev_addr[0] << 24),
@@ -2000,6 +2001,8 @@ static int fec_enet_init(struct net_device *ndev)
 
        /* Get the Ethernet address */
        fec_get_mac(ndev);
+       /* make sure MAC we just acquired is programmed into the hw */
+       fec_set_mac_address(ndev, NULL);
 
        /* init the tx & rx ring size */
        fep->tx_ring_size = TX_RING_SIZE;
index bd363b27e8540e3bfe2acc6173adcc8a1952f4b7..9ea4bfe5d31804ed7413ade40ec568a777b9739d 100644 (file)
@@ -625,6 +625,13 @@ static const struct usb_device_id  products[] = {
        .driver_info = 0,
 },
 
+/* Novatel Expedite E371 - handled by qmi_wwan */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(NOVATEL_VENDOR_ID, 0x9011, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+       .driver_info = 0,
+},
+
 /* AnyDATA ADU960S - handled by qmi_wwan */
 {
        USB_DEVICE_AND_INTERFACE_INFO(0x16d5, 0x650a, USB_CLASS_COMM,
index 313cb6cd4848e033bab664788c24c0a88ce55996..e3458e3c44f146653048aba99295670caabd4db5 100644 (file)
@@ -500,6 +500,13 @@ static const struct usb_device_id products[] = {
                                              USB_CDC_PROTO_NONE),
                .driver_info        = (unsigned long)&qmi_wwan_info,
        },
+       {       /* Novatel Expedite E371 */
+               USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0x9011,
+                                             USB_CLASS_COMM,
+                                             USB_CDC_SUBCLASS_ETHERNET,
+                                             USB_CDC_PROTO_NONE),
+               .driver_info        = (unsigned long)&qmi_wwan_info,
+       },
        {       /* Dell Wireless 5800 (Novatel E362) */
                USB_DEVICE_AND_INTERFACE_INFO(0x413C, 0x8195,
                                              USB_CLASS_COMM,
index 06287c110241f47ffa4a546abdf17616a0fd7e83..775cc956ff7874c5949ec707357341137c6fdb1f 100644 (file)
@@ -63,13 +63,6 @@ struct wireless_dev;
 void netdev_set_default_ethtool_ops(struct net_device *dev,
                                    const struct ethtool_ops *ops);
 
-/* hardware address assignment types */
-#define NET_ADDR_PERM          0       /* address is permanent (default) */
-#define NET_ADDR_RANDOM                1       /* address is generated randomly */
-#define NET_ADDR_STOLEN                2       /* address is stolen from other device */
-#define NET_ADDR_SET           3       /* address is set using
-                                        * dev_set_mac_address() */
-
 /* Backlog congestion levels */
 #define NET_RX_SUCCESS         0       /* keep 'em coming, baby */
 #define NET_RX_DROP            1       /* packet dropped */
@@ -1315,6 +1308,9 @@ struct net_device {
        atomic_long_t           rx_dropped;
        atomic_long_t           tx_dropped;
 
+       /* Stats to monitor carrier on<->off transitions */
+       atomic_t                carrier_changes;
+
 #ifdef CONFIG_WIRELESS_EXT
        /* List of functions to handle Wireless Extensions (instead of ioctl).
         * See <net/iw_handler.h> for details. Jean II */
@@ -2018,11 +2014,6 @@ static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen,
        return skb->data + offset;
 }
 
-static inline void *skb_gro_mac_header(struct sk_buff *skb)
-{
-       return NAPI_GRO_CB(skb)->frag0 ?: skb_mac_header(skb);
-}
-
 static inline void *skb_gro_network_header(struct sk_buff *skb)
 {
        return (NAPI_GRO_CB(skb)->frag0 ?: skb->data) +
@@ -2629,6 +2620,7 @@ int dev_get_phys_port_id(struct net_device *dev,
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                        struct netdev_queue *txq);
 int dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
+bool is_skb_forwardable(struct net_device *dev, struct sk_buff *skb);
 
 extern int             netdev_budget;
 
index 00e3f12cb2f94dfd0755581f6c48bc165a469588..3c3bb184eb8f154b61c9f93fd5ea37ffefadeba8 100644 (file)
@@ -51,6 +51,11 @@ static inline unsigned int rt6_flags2srcprefs(int flags)
        return (flags >> 3) & 7;
 }
 
+static inline bool rt6_need_strict(const struct in6_addr *daddr)
+{
+       return ipv6_addr_type(daddr) &
+               (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK);
+}
 
 void ip6_route_input(struct sk_buff *skb);
 
index 16410b6e7819fa93f242665b036812f44fd5fa41..9a7f7ace66494e144c55c08d5bbba085de3a2b7c 100644 (file)
@@ -144,6 +144,7 @@ enum {
        IFLA_NUM_RX_QUEUES,
        IFLA_CARRIER,
        IFLA_PHYS_PORT_ID,
+       IFLA_CARRIER_CHANGES,
        __IFLA_MAX
 };
 
index 6b9500bc2d56a0338b39dbf1b46540edc6ffe141..fdfbd1c17065e33fb45a3e70ebcc6d9cf6891dac 100644 (file)
@@ -49,5 +49,11 @@ enum {
         IF_PORT_100BASEFX
 };
 
+/* hardware address assignment types */
+#define NET_ADDR_PERM          0       /* address is permanent (default) */
+#define NET_ADDR_RANDOM                1       /* address is generated randomly */
+#define NET_ADDR_STOLEN                2       /* address is stolen from other device */
+#define NET_ADDR_SET           3       /* address is set using
+                                        * dev_set_mac_address() */
 
 #endif /* _UAPI_LINUX_NETDEVICE_H */
index d3409e6b5453e3e8f90b26ec51bb398033a865ac..056b67b0e2778fdce7bd80a2bf4ede2d552c0e1d 100644 (file)
@@ -35,16 +35,11 @@ static inline int should_deliver(const struct net_bridge_port *p,
                p->state == BR_STATE_FORWARDING;
 }
 
-static inline unsigned int packet_length(const struct sk_buff *skb)
-{
-       return skb->len - (skb->protocol == htons(ETH_P_8021Q) ? VLAN_HLEN : 0);
-}
-
 int br_dev_queue_push_xmit(struct sk_buff *skb)
 {
        /* ip_fragment doesn't copy the MAC header */
        if (nf_bridge_maybe_copy_header(skb) ||
-           (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb))) {
+           !is_skb_forwardable(skb->dev, skb)) {
                kfree_skb(skb);
        } else {
                skb_push(skb, ETH_HLEN);
@@ -71,7 +66,7 @@ static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
        skb->dev = to->dev;
 
        if (unlikely(netpoll_tx_running(to->br->dev))) {
-               if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb))
+               if (!is_skb_forwardable(skb->dev, skb))
                        kfree_skb(skb);
                else {
                        skb_push(skb, ETH_HLEN);
index cf92139b229c965b0dd29c85ba0d60b941ee7b3f..48d81e4a256e2c06f0018e5d6b9e005ecf942332 100644 (file)
@@ -1640,8 +1640,7 @@ static inline void net_timestamp_set(struct sk_buff *skb)
                        __net_timestamp(SKB);           \
        }                                               \
 
-static inline bool is_skb_forwardable(struct net_device *dev,
-                                     struct sk_buff *skb)
+bool is_skb_forwardable(struct net_device *dev, struct sk_buff *skb)
 {
        unsigned int len;
 
@@ -1660,6 +1659,7 @@ static inline bool is_skb_forwardable(struct net_device *dev,
 
        return false;
 }
+EXPORT_SYMBOL_GPL(is_skb_forwardable);
 
 /**
  * dev_forward_skb - loopback an skb to another netif
@@ -3833,10 +3833,10 @@ static void gro_list_prepare(struct napi_struct *napi, struct sk_buff *skb)
                diffs |= p->vlan_tci ^ skb->vlan_tci;
                if (maclen == ETH_HLEN)
                        diffs |= compare_ether_header(skb_mac_header(p),
-                                                     skb_gro_mac_header(skb));
+                                                     skb_mac_header(skb));
                else if (!diffs)
                        diffs = memcmp(skb_mac_header(p),
-                                      skb_gro_mac_header(skb),
+                                      skb_mac_header(skb),
                                       maclen);
                NAPI_GRO_CB(p)->same_flow = !diffs;
        }
@@ -3859,6 +3859,27 @@ static void skb_gro_reset_offset(struct sk_buff *skb)
        }
 }
 
+static void gro_pull_from_frag0(struct sk_buff *skb, int grow)
+{
+       struct skb_shared_info *pinfo = skb_shinfo(skb);
+
+       BUG_ON(skb->end - skb->tail < grow);
+
+       memcpy(skb_tail_pointer(skb), NAPI_GRO_CB(skb)->frag0, grow);
+
+       skb->data_len -= grow;
+       skb->tail += grow;
+
+       pinfo->frags[0].page_offset += grow;
+       skb_frag_size_sub(&pinfo->frags[0], grow);
+
+       if (unlikely(!skb_frag_size(&pinfo->frags[0]))) {
+               skb_frag_unref(skb, 0);
+               memmove(pinfo->frags, pinfo->frags + 1,
+                       --pinfo->nr_frags * sizeof(pinfo->frags[0]));
+       }
+}
+
 static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
        struct sk_buff **pp = NULL;
@@ -3867,6 +3888,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
        struct list_head *head = &offload_base;
        int same_flow;
        enum gro_result ret;
+       int grow;
 
        if (!(skb->dev->features & NETIF_F_GRO))
                goto normal;
@@ -3874,7 +3896,6 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
        if (skb_is_gso(skb) || skb_has_frag_list(skb))
                goto normal;
 
-       skb_gro_reset_offset(skb);
        gro_list_prepare(napi, skb);
        NAPI_GRO_CB(skb)->csum = skb->csum; /* Needed for CHECKSUM_COMPLETE */
 
@@ -3938,27 +3959,9 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
        ret = GRO_HELD;
 
 pull:
-       if (skb_headlen(skb) < skb_gro_offset(skb)) {
-               int grow = skb_gro_offset(skb) - skb_headlen(skb);
-
-               BUG_ON(skb->end - skb->tail < grow);
-
-               memcpy(skb_tail_pointer(skb), NAPI_GRO_CB(skb)->frag0, grow);
-
-               skb->tail += grow;
-               skb->data_len -= grow;
-
-               skb_shinfo(skb)->frags[0].page_offset += grow;
-               skb_frag_size_sub(&skb_shinfo(skb)->frags[0], grow);
-
-               if (unlikely(!skb_frag_size(&skb_shinfo(skb)->frags[0]))) {
-                       skb_frag_unref(skb, 0);
-                       memmove(skb_shinfo(skb)->frags,
-                               skb_shinfo(skb)->frags + 1,
-                               --skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t));
-               }
-       }
-
+       grow = skb_gro_offset(skb) - skb_headlen(skb);
+       if (grow > 0)
+               gro_pull_from_frag0(skb, grow);
 ok:
        return ret;
 
@@ -4026,6 +4029,8 @@ gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
        trace_napi_gro_receive_entry(skb);
 
+       skb_gro_reset_offset(skb);
+
        return napi_skb_finish(dev_gro_receive(napi, skb), skb);
 }
 EXPORT_SYMBOL(napi_gro_receive);
@@ -4054,12 +4059,16 @@ struct sk_buff *napi_get_frags(struct napi_struct *napi)
 }
 EXPORT_SYMBOL(napi_get_frags);
 
-static gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb,
-                              gro_result_t ret)
+static gro_result_t napi_frags_finish(struct napi_struct *napi,
+                                     struct sk_buff *skb,
+                                     gro_result_t ret)
 {
        switch (ret) {
        case GRO_NORMAL:
-               if (netif_receive_skb_internal(skb))
+       case GRO_HELD:
+               __skb_push(skb, ETH_HLEN);
+               skb->protocol = eth_type_trans(skb, skb->dev);
+               if (ret == GRO_NORMAL && netif_receive_skb_internal(skb))
                        ret = GRO_DROP;
                break;
 
@@ -4068,7 +4077,6 @@ static gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *
                napi_reuse_skb(napi, skb);
                break;
 
-       case GRO_HELD:
        case GRO_MERGED:
                break;
        }
@@ -4076,17 +4084,41 @@ static gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *
        return ret;
 }
 
+/* Upper GRO stack assumes network header starts at gro_offset=0
+ * Drivers could call both napi_gro_frags() and napi_gro_receive()
+ * We copy ethernet header into skb->data to have a common layout.
+ */
 static struct sk_buff *napi_frags_skb(struct napi_struct *napi)
 {
        struct sk_buff *skb = napi->skb;
+       const struct ethhdr *eth;
+       unsigned int hlen = sizeof(*eth);
 
        napi->skb = NULL;
 
-       if (unlikely(!pskb_may_pull(skb, sizeof(struct ethhdr)))) {
-               napi_reuse_skb(napi, skb);
-               return NULL;
+       skb_reset_mac_header(skb);
+       skb_gro_reset_offset(skb);
+
+       eth = skb_gro_header_fast(skb, 0);
+       if (unlikely(skb_gro_header_hard(skb, hlen))) {
+               eth = skb_gro_header_slow(skb, hlen, 0);
+               if (unlikely(!eth)) {
+                       napi_reuse_skb(napi, skb);
+                       return NULL;
+               }
+       } else {
+               gro_pull_from_frag0(skb, hlen);
+               NAPI_GRO_CB(skb)->frag0 += hlen;
+               NAPI_GRO_CB(skb)->frag0_len -= hlen;
        }
-       skb->protocol = eth_type_trans(skb, skb->dev);
+       __skb_pull(skb, hlen);
+
+       /*
+        * This works because the only protocols we care about don't require
+        * special handling.
+        * We'll fix it up properly in napi_frags_finish()
+        */
+       skb->protocol = eth->h_proto;
 
        return skb;
 }
index daed9a64c6f6b350ef4518fc91b8b6718d58624d..46239627848436938cbd1efb743f60ffb0b15289 100644 (file)
@@ -253,6 +253,16 @@ static ssize_t operstate_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(operstate);
 
+static ssize_t carrier_changes_show(struct device *dev,
+                                   struct device_attribute *attr,
+                                   char *buf)
+{
+       struct net_device *netdev = to_net_dev(dev);
+       return sprintf(buf, fmt_dec,
+                      atomic_read(&netdev->carrier_changes));
+}
+static DEVICE_ATTR_RO(carrier_changes);
+
 /* read-write attributes */
 
 static int change_mtu(struct net_device *net, unsigned long new_mtu)
@@ -386,6 +396,7 @@ static struct attribute *net_class_attrs[] = {
        &dev_attr_duplex.attr,
        &dev_attr_dormant.attr,
        &dev_attr_operstate.attr,
+       &dev_attr_carrier_changes.attr,
        &dev_attr_ifalias.attr,
        &dev_attr_carrier.attr,
        &dev_attr_mtu.attr,
index e7c6006bc3eaf72e4a22d729d6d8643bff6bef58..d4ff41739b0f23fcb572905dd34288cb1d8ebd49 100644 (file)
@@ -822,6 +822,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
               + nla_total_size(4) /* IFLA_NUM_RX_QUEUES */
               + nla_total_size(1) /* IFLA_OPERSTATE */
               + nla_total_size(1) /* IFLA_LINKMODE */
+              + nla_total_size(4) /* IFLA_CARRIER_CHANGES */
               + nla_total_size(ext_filter_mask
                                & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */
               + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */
@@ -970,7 +971,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
            (dev->qdisc &&
             nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) ||
            (dev->ifalias &&
-            nla_put_string(skb, IFLA_IFALIAS, dev->ifalias)))
+            nla_put_string(skb, IFLA_IFALIAS, dev->ifalias)) ||
+           nla_put_u32(skb, IFLA_CARRIER_CHANGES,
+                       atomic_read(&dev->carrier_changes)))
                goto nla_put_failure;
 
        if (1) {
@@ -1147,6 +1150,7 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
        [IFLA_NUM_TX_QUEUES]    = { .type = NLA_U32 },
        [IFLA_NUM_RX_QUEUES]    = { .type = NLA_U32 },
        [IFLA_PHYS_PORT_ID]     = { .type = NLA_BINARY, .len = MAX_PHYS_PORT_ID_LEN },
+       [IFLA_CARRIER_CHANGES]  = { .type = NLA_U32 },  /* ignored */
 };
 
 static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
index f2610e15766027ce3a7408862d03f4c427c555ea..7b326529e6a2cba57695697cfff436357c347b2c 100644 (file)
@@ -520,7 +520,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
                              np->tclass, NULL, &fl6, (struct rt6_info *)dst,
                              MSG_DONTWAIT, np->dontfrag);
        if (err) {
-               ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS);
+               ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTERRORS);
                ip6_flush_pending_frames(sk);
        } else {
                err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr,
index 6184dfa4e4d7b4f2080f2b007b743f43768fc212..3284d61577c0f06e9231585fc7a3e93117e40b45 100644 (file)
@@ -1567,8 +1567,8 @@ int ip6_push_pending_frames(struct sock *sk)
        if (proto == IPPROTO_ICMPV6) {
                struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
 
-               ICMP6MSGOUT_INC_STATS_BH(net, idev, icmp6_hdr(skb)->icmp6_type);
-               ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
+               ICMP6MSGOUT_INC_STATS(net, idev, icmp6_hdr(skb)->icmp6_type);
+               ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
        }
 
        err = ip6_local_out(skb);
index e1e47350784bad893c905eecca300388f9b80faa..08b367c6b9cfe2cb268cf7ec603ecc8f5c588a86 100644 (file)
@@ -1620,11 +1620,12 @@ static void mld_sendpack(struct sk_buff *skb)
                      dst_output);
 out:
        if (!err) {
-               ICMP6MSGOUT_INC_STATS_BH(net, idev, ICMPV6_MLD2_REPORT);
-               ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
-               IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_OUTMCAST, payload_len);
-       } else
-               IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS);
+               ICMP6MSGOUT_INC_STATS(net, idev, ICMPV6_MLD2_REPORT);
+               ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
+               IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, payload_len);
+       } else {
+               IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
+       }
 
        rcu_read_unlock();
        return;
index d1b35d377e62de73c0fade1d6464e7a3358ba15a..6313abd53c9d059717113ab1d4763791a6a72312 100644 (file)
@@ -6,24 +6,24 @@
 #include <net/ipv6.h>
 #include <net/ip6_fib.h>
 #include <net/addrconf.h>
+#include <net/secure_seq.h>
 
 void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
 {
        static atomic_t ipv6_fragmentation_id;
+       struct in6_addr addr;
        int old, new;
 
 #if IS_ENABLED(CONFIG_IPV6)
-       if (rt) {
-               struct inet_peer *peer;
-               struct net *net;
-
-               net = dev_net(rt->dst.dev);
-               peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1);
-               if (peer) {
-                       fhdr->identification = htonl(inet_getid(peer, 0));
-                       inet_putpeer(peer);
-                       return;
-               }
+       struct inet_peer *peer;
+       struct net *net;
+
+       net = dev_net(rt->dst.dev);
+       peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1);
+       if (peer) {
+               fhdr->identification = htonl(inet_getid(peer, 0));
+               inet_putpeer(peer);
+               return;
        }
 #endif
        do {
@@ -32,7 +32,10 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
                if (!new)
                        new = 1;
        } while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old);
-       fhdr->identification = htonl(new);
+
+       addr = rt->rt6i_dst.addr;
+       addr.s6_addr32[0] ^= (__force __be32)new;
+       fhdr->identification = htonl(secure_ipv6_id(addr.s6_addr32));
 }
 EXPORT_SYMBOL(ipv6_select_ident);
 
index 587bbdcb22b4c04c0186932d463bce29ca32b38e..bda74291c3e0d09c94ff5961cf393cb7695ee518 100644 (file)
@@ -182,8 +182,8 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                              MSG_DONTWAIT, np->dontfrag);
 
        if (err) {
-               ICMP6_INC_STATS_BH(sock_net(sk), rt->rt6i_idev,
-                                  ICMP6_MIB_OUTERRORS);
+               ICMP6_INC_STATS(sock_net(sk), rt->rt6i_idev,
+                               ICMP6_MIB_OUTERRORS);
                ip6_flush_pending_frames(sk);
        } else {
                err = icmpv6_push_pending_frames(sk, &fl6,
index b93ae6a6a31c2b3bb882f01180aa32c38df2c853..5015c50a5ba7db02b9a8cc842bd0e28b7f3e8782 100644 (file)
@@ -374,12 +374,6 @@ static bool rt6_check_expired(const struct rt6_info *rt)
        return false;
 }
 
-static bool rt6_need_strict(const struct in6_addr *daddr)
-{
-       return ipv6_addr_type(daddr) &
-               (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK);
-}
-
 /* Multipath route selection:
  *   Hash based function using packet header and flowlabel.
  * Adapted from fib_info_hashfn()
index 3277680186b4894a62f3791f3fcca9aa7ed99a23..5ca56cee2dae06830683927658397f6b7a23ecd4 100644 (file)
@@ -39,7 +39,7 @@
 #include <linux/ipsec.h>
 #include <linux/times.h>
 #include <linux/slab.h>
-
+#include <linux/uaccess.h>
 #include <linux/ipv6.h>
 #include <linux/icmpv6.h>
 #include <linux/random.h>
@@ -65,8 +65,6 @@
 #include <net/tcp_memcontrol.h>
 #include <net/busy_poll.h>
 
-#include <asm/uaccess.h>
-
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 
@@ -532,8 +530,8 @@ static struct tcp_md5sig_key *tcp_v6_reqsk_md5_lookup(struct sock *sk,
        return tcp_v6_md5_do_lookup(sk, &inet_rsk(req)->ir_v6_rmt_addr);
 }
 
-static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval,
-                                 int optlen)
+static int tcp_v6_parse_md5_keys(struct sock *sk, char __user *optval,
+                                int optlen)
 {
        struct tcp_md5sig cmd;
        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr;
@@ -717,7 +715,7 @@ struct request_sock_ops tcp6_request_sock_ops __read_mostly = {
        .send_ack       =       tcp_v6_reqsk_send_ack,
        .destructor     =       tcp_v6_reqsk_destructor,
        .send_reset     =       tcp_v6_send_reset,
-       .syn_ack_timeout =      tcp_syn_ack_timeout,
+       .syn_ack_timeout =      tcp_syn_ack_timeout,
 };
 
 #ifdef CONFIG_TCP_MD5SIG
@@ -728,7 +726,7 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
 #endif
 
 static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
-                                u32 tsval, u32 tsecr,
+                                u32 tsval, u32 tsecr, int oif,
                                 struct tcp_md5sig_key *key, int rst, u8 tclass,
                                 u32 label)
 {
@@ -800,8 +798,10 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
        __tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr);
 
        fl6.flowi6_proto = IPPROTO_TCP;
-       if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL)
+       if (rt6_need_strict(&fl6.daddr) || !oif)
                fl6.flowi6_oif = inet6_iif(skb);
+       else
+               fl6.flowi6_oif = oif;
        fl6.fl6_dport = t1->dest;
        fl6.fl6_sport = t1->source;
        security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
@@ -835,6 +835,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
        int genhash;
        struct sock *sk1 = NULL;
 #endif
+       int oif;
 
        if (th->rst)
                return;
@@ -878,7 +879,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
                ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len -
                          (th->doff << 2);
 
-       tcp_v6_send_response(skb, seq, ack_seq, 0, 0, 0, key, 1, 0, 0);
+       oif = sk ? sk->sk_bound_dev_if : 0;
+       tcp_v6_send_response(skb, seq, ack_seq, 0, 0, 0, oif, key, 1, 0, 0);
 
 #ifdef CONFIG_TCP_MD5SIG
 release_sk1:
@@ -890,11 +892,11 @@ release_sk1:
 }
 
 static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
-                           u32 win, u32 tsval, u32 tsecr,
+                           u32 win, u32 tsval, u32 tsecr, int oif,
                            struct tcp_md5sig_key *key, u8 tclass,
                            u32 label)
 {
-       tcp_v6_send_response(skb, seq, ack, win, tsval, tsecr, key, 0, tclass,
+       tcp_v6_send_response(skb, seq, ack, win, tsval, tsecr, oif, key, 0, tclass,
                             label);
 }
 
@@ -906,7 +908,7 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
        tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
                        tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
                        tcp_time_stamp + tcptw->tw_ts_offset,
-                       tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw),
+                       tcptw->tw_ts_recent, tw->tw_bound_dev_if, tcp_twsk_md5_key(tcptw),
                        tw->tw_tclass, (tw->tw_flowlabel << 12));
 
        inet_twsk_put(tw);
@@ -916,7 +918,7 @@ static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
                                  struct request_sock *req)
 {
        tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1,
-                       req->rcv_wnd, tcp_time_stamp, req->ts_recent,
+                       req->rcv_wnd, tcp_time_stamp, req->ts_recent, sk->sk_bound_dev_if,
                        tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr),
                        0, 0);
 }
@@ -1261,7 +1263,8 @@ static struct sock *tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 
 #ifdef CONFIG_TCP_MD5SIG
        /* Copy over the MD5 key from the original socket */
-       if ((key = tcp_v6_md5_do_lookup(sk, &newsk->sk_v6_daddr)) != NULL) {
+       key = tcp_v6_md5_do_lookup(sk, &newsk->sk_v6_daddr);
+       if (key != NULL) {
                /* We're using one, so create a matching key
                 * on the newsk structure. If we fail to get
                 * memory, then we end up not copying the key
@@ -1305,9 +1308,8 @@ static __sum16 tcp_v6_checksum_init(struct sk_buff *skb)
                                              &ipv6_hdr(skb)->saddr,
                                              &ipv6_hdr(skb)->daddr, 0));
 
-       if (skb->len <= 76) {
+       if (skb->len <= 76)
                return __skb_checksum_complete(skb);
-       }
        return 0;
 }
 
@@ -1337,7 +1339,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
                return tcp_v4_do_rcv(sk, skb);
 
 #ifdef CONFIG_TCP_MD5SIG
-       if (tcp_v6_inbound_md5_hash (sk, skb))
+       if (tcp_v6_inbound_md5_hash(sk, skb))
                goto discard;
 #endif
 
@@ -1604,7 +1606,8 @@ do_time_wait:
                break;
        case TCP_TW_RST:
                goto no_tcp_socket;
-       case TCP_TW_SUCCESS:;
+       case TCP_TW_SUCCESS:
+               ;
        }
        goto discard_it;
 }
@@ -1649,7 +1652,7 @@ static void tcp_v6_early_demux(struct sk_buff *skb)
 static struct timewait_sock_ops tcp6_timewait_sock_ops = {
        .twsk_obj_size  = sizeof(struct tcp6_timewait_sock),
        .twsk_unique    = tcp_twsk_unique,
-       .twsk_destructor= tcp_twsk_destructor,
+       .twsk_destructor = tcp_twsk_destructor,
 };
 
 static const struct inet_connection_sock_af_ops ipv6_specific = {
@@ -1683,7 +1686,6 @@ static const struct tcp_sock_af_ops tcp_sock_ipv6_specific = {
 /*
  *     TCP over IPv4 via INET6 API
  */
-
 static const struct inet_connection_sock_af_ops ipv6_mapped = {
        .queue_xmit        = ip_queue_xmit,
        .send_check        = tcp_v4_send_check,
index 7826d46baa7038366872ec412d97ecd94eb1d13f..589935661d667d81b2f6159eb69c237f95329a63 100644 (file)
@@ -239,7 +239,8 @@ static int rds_iw_laddr_check(__be32 addr)
        ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
        /* due to this, we will claim to support IB devices unless we
           check node_type. */
-       if (ret || cm_id->device->node_type != RDMA_NODE_RNIC)
+       if (ret || !cm_id->device ||
+           cm_id->device->node_type != RDMA_NODE_RNIC)
                ret = -EADDRNOTAVAIL;
 
        rdsdebug("addr %pI4 ret %d node type %d\n",
index e82e43b69c335bccbd58e6ba4ef10b56acd8f5a6..e1543b03e39d10c9b952a7ccf454cbd76dd09f09 100644 (file)
@@ -310,6 +310,7 @@ void netif_carrier_on(struct net_device *dev)
        if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state)) {
                if (dev->reg_state == NETREG_UNINITIALIZED)
                        return;
+               atomic_inc(&dev->carrier_changes);
                linkwatch_fire_event(dev);
                if (netif_running(dev))
                        __netdev_watchdog_up(dev);
@@ -328,6 +329,7 @@ void netif_carrier_off(struct net_device *dev)
        if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state)) {
                if (dev->reg_state == NETREG_UNINITIALIZED)
                        return;
+               atomic_inc(&dev->carrier_changes);
                linkwatch_fire_event(dev);
        }
 }