* Re: [PATCH net] net: phy: broadcom: Fix auxiliary control register reads
From: David Miller @ 2018-05-23 19:19 UTC (permalink / raw)
To: f.fainelli; +Cc: netdev, jon.mason, andrew, linux-kernel
In-Reply-To: <20180522232227.6355-1-f.fainelli@gmail.com>
From: Florian Fainelli <f.fainelli@gmail.com>
Date: Tue, 22 May 2018 16:22:26 -0700
> We are currently doing auxiliary control register reads with the shadow
> register value 0b111 (0x7) which incidentally is also the selector value
> that should be present in bits [2:0]. Fix this by using the appropriate
> selector mask which is defined (MII_BCM54XX_AUXCTL_SHDWSEL_MASK).
>
> This does not have a functional impact yet because we always access the
> MII_BCM54XX_AUXCTL_SHDWSEL_MISC (0x7) register in the current code.
> This might change at some point though.
>
> Fixes: 5b4e29005123 ("net: phy: broadcom: add bcm54xx_auxctl_read")
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
> David, please queue this for -stable as well, thank you!
Applied and queued up for -stable.
^ permalink raw reply
* Re: [PATCH net-next v5 0/3] fib rule selftest
From: David Miller @ 2018-05-23 19:14 UTC (permalink / raw)
To: roopa; +Cc: netdev, nikolay, dsa, idosch, eric.dumazet
In-Reply-To: <1527023009-13609-1-git-send-email-roopa@cumulusnetworks.com>
From: Roopa Prabhu <roopa@cumulusnetworks.com>
Date: Tue, 22 May 2018 14:03:26 -0700
> From: Roopa Prabhu <roopa@cumulusnetworks.com>
>
> This series adds a new test to test fib rules.
> ip route get is used to test fib rule matches.
> This series also extends ip route get to match on
> sport and dport to test recent support of sport
> and dport fib rule match.
...
Looks good, series applied, thanks.
^ permalink raw reply
* Re: [PATCH net] net: ipv4: add missing RTA_TABLE to rtm_ipv4_policy
From: David Miller @ 2018-05-23 19:04 UTC (permalink / raw)
To: roopa; +Cc: netdev, eric.dumazet
In-Reply-To: <1527021891-6837-1-git-send-email-roopa@cumulusnetworks.com>
From: Roopa Prabhu <roopa@cumulusnetworks.com>
Date: Tue, 22 May 2018 13:44:51 -0700
> From: Roopa Prabhu <roopa@cumulusnetworks.com>
>
> Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Applied and queued up for -stable.
Please provide an appropriate Fixes: tag next time.
^ permalink raw reply
* Re: [PATCH V4 8/8] dt-bindings: stm32: add compatible for syscon
From: Rob Herring @ 2018-05-23 19:03 UTC (permalink / raw)
To: Christophe Roullier
Cc: mark.rutland, mcoquelin.stm32, alexandre.torgue, peppe.cavallaro,
devicetree, linux-arm-kernel, netdev, andrew
In-Reply-To: <1527090479-5263-9-git-send-email-christophe.roullier@st.com>
On Wed, May 23, 2018 at 05:47:59PM +0200, Christophe Roullier wrote:
> This patch describes syscon DT bindings.
>
> Signed-off-by: Christophe Roullier <christophe.roullier@st.com>
> ---
> Documentation/devicetree/bindings/arm/stm32.txt | 10 ----------
> .../devicetree/bindings/arm/stm32/stm32-syscon.txt | 14 ++++++++++++++
> Documentation/devicetree/bindings/arm/stm32/stm32.txt | 10 ++++++++++
> 3 files changed, 24 insertions(+), 10 deletions(-)
> delete mode 100644 Documentation/devicetree/bindings/arm/stm32.txt
> create mode 100644 Documentation/devicetree/bindings/arm/stm32/stm32-syscon.txt
> create mode 100644 Documentation/devicetree/bindings/arm/stm32/stm32.txt
In the future, use the -M option so file moves don't show any diff.
Reviewed-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* Re: [net-next] i40iw/i40e: Remove link dependency on i40e
From: David Miller @ 2018-05-23 19:00 UTC (permalink / raw)
To: jeffrey.t.kirsher
Cc: dledford, jgg, sindhu.devale, netdev, linux-rdma, nhorman,
sassmann, jogreene, shiraz.saleem
In-Reply-To: <20180522203831.20624-1-jeffrey.t.kirsher@intel.com>
From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Tue, 22 May 2018 13:38:31 -0700
> From: Sindhu Devale <sindhu.devale@intel.com>
>
> Currently i40iw is dependent on i40e symbols
> i40e_register_client and i40e_unregister_client due to
> which i40iw cannot be loaded without i40e being loaded.
>
> This patch allows RDMA driver to build and load without
> linking to LAN driver and without LAN driver being loaded
> first. Once the LAN driver is loaded, the RDMA driver
> is notified through the netdevice notifiers to register
> as client to the LAN driver. Add function pointers to IDC
> register/unregister in the private VSI structure. This
> allows a RDMA driver to build without linking to i40e.
>
> Signed-off-by: Sindhu Devale <sindhu.devale@intel.com>
> Signed-off-by: Shiraz Saleem <shiraz.saleem@intel.com>
> Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
If two drivers depend upon eachother, and a change to one can create
an incompatibility with the other, by definition they must be upgraded
together.
This doesn't even get into recompiling or anything like that, it's a
simple fact of life.
I'm not applying this sorry.
^ permalink raw reply
* Re: [net-next PATCH v2 1/4] net: Refactor XPS for CPUs and Rx queues
From: Nambiar, Amritha @ 2018-05-23 18:59 UTC (permalink / raw)
To: Tom Herbert
Cc: Linux Kernel Network Developers, David S. Miller, Alexander Duyck,
Sridhar Samudrala, Eric Dumazet, Hannes Frederic Sowa
In-Reply-To: <CALx6S37VqLRGUXD5OCbXCL4Fheb7e+JjtDPa8vvXM7bWBWNw-w@mail.gmail.com>
On 5/17/2018 9:08 PM, Tom Herbert wrote:
> On Tue, May 15, 2018 at 6:26 PM, Amritha Nambiar
> <amritha.nambiar@intel.com> wrote:
>> Refactor XPS code to support Tx queue selection based on
>> CPU map or Rx queue map.
>>
>> Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
>> ---
>> include/linux/cpumask.h | 11 ++
>> include/linux/netdevice.h | 72 +++++++++++++++-
>> net/core/dev.c | 208 +++++++++++++++++++++++++++++----------------
>> net/core/net-sysfs.c | 4 -
>> 4 files changed, 215 insertions(+), 80 deletions(-)
>>
>> diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
>> index bf53d89..57f20a0 100644
>> --- a/include/linux/cpumask.h
>> +++ b/include/linux/cpumask.h
>> @@ -115,12 +115,17 @@ extern struct cpumask __cpu_active_mask;
>> #define cpu_active(cpu) ((cpu) == 0)
>> #endif
>>
>> -/* verify cpu argument to cpumask_* operators */
>> -static inline unsigned int cpumask_check(unsigned int cpu)
>> +static inline void cpu_max_bits_warn(unsigned int cpu, unsigned int bits)
>> {
>> #ifdef CONFIG_DEBUG_PER_CPU_MAPS
>> - WARN_ON_ONCE(cpu >= nr_cpumask_bits);
>> + WARN_ON_ONCE(cpu >= bits);
>> #endif /* CONFIG_DEBUG_PER_CPU_MAPS */
>> +}
>> +
>> +/* verify cpu argument to cpumask_* operators */
>> +static inline unsigned int cpumask_check(unsigned int cpu)
>> +{
>> + cpu_max_bits_warn(cpu, nr_cpumask_bits);
>> return cpu;
>> }
>>
>> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
>> index 03ed492..c2eeb36 100644
>> --- a/include/linux/netdevice.h
>> +++ b/include/linux/netdevice.h
>> @@ -730,10 +730,21 @@ struct xps_map {
>> */
>> struct xps_dev_maps {
>> struct rcu_head rcu;
>> - struct xps_map __rcu *cpu_map[0];
>> + struct xps_map __rcu *attr_map[0];
>> };
>> -#define XPS_DEV_MAPS_SIZE(_tcs) (sizeof(struct xps_dev_maps) + \
>> +
>> +#define XPS_CPU_DEV_MAPS_SIZE(_tcs) (sizeof(struct xps_dev_maps) + \
>> (nr_cpu_ids * (_tcs) * sizeof(struct xps_map *)))
>> +
>> +#define XPS_RXQ_DEV_MAPS_SIZE(_tcs, _rxqs) (sizeof(struct xps_dev_maps) +\
>> + (_rxqs * (_tcs) * sizeof(struct xps_map *)))
>> +
>> +enum xps_map_type {
>> + XPS_MAP_RXQS,
>> + XPS_MAP_CPUS,
>> + __XPS_MAP_MAX
>> +};
>> +
>> #endif /* CONFIG_XPS */
>>
>> #define TC_MAX_QUEUE 16
>> @@ -1891,7 +1902,7 @@ struct net_device {
>> int watchdog_timeo;
>>
>> #ifdef CONFIG_XPS
>> - struct xps_dev_maps __rcu *xps_maps;
>> + struct xps_dev_maps __rcu *xps_maps[__XPS_MAP_MAX];
>> #endif
>> #ifdef CONFIG_NET_CLS_ACT
>> struct mini_Qdisc __rcu *miniq_egress;
>> @@ -3229,6 +3240,61 @@ static inline void netif_wake_subqueue(struct net_device *dev, u16 queue_index)
>> #ifdef CONFIG_XPS
>> int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
>> u16 index);
>> +int __netif_set_xps_queue(struct net_device *dev, const unsigned long *mask,
>> + u16 index, enum xps_map_type type);
>> +
>> +static inline bool attr_test_mask(unsigned long j, const unsigned long *mask,
>> + unsigned int nr_bits)
>> +{
>> + cpu_max_bits_warn(j, nr_bits);
>> + return test_bit(j, mask);
>> +}
>> +
>> +static inline bool attr_test_online(unsigned long j,
>> + const unsigned long *online_mask,
>> + unsigned int nr_bits)
>> +{
>> + cpu_max_bits_warn(j, nr_bits);
>> +
>> + if (online_mask)
>> + return test_bit(j, online_mask);
>> +
>> + if (j >= 0 && j < nr_bits)
>> + return true;
>> +
>> + return false;
>> +}
>> +
>> +static inline unsigned int attrmask_next(int n, const unsigned long *srcp,
>> + unsigned int nr_bits)
>> +{
>> + /* -1 is a legal arg here. */
>> + if (n != -1)
>> + cpu_max_bits_warn(n, nr_bits);
>> +
>> + if (srcp)
>> + return find_next_bit(srcp, nr_bits, n + 1);
>> +
>> + return n + 1;
>> +}
>> +
>> +static inline int attrmask_next_and(int n, const unsigned long *src1p,
>> + const unsigned long *src2p,
>> + unsigned int nr_bits)
>> +{
>> + /* -1 is a legal arg here. */
>> + if (n != -1)
>> + cpu_max_bits_warn(n, nr_bits);
>> +
>> + if (src1p && src2p)
>> + return find_next_and_bit(src1p, src2p, nr_bits, n + 1);
>> + else if (src1p)
>> + return find_next_bit(src1p, nr_bits, n + 1);
>> + else if (src2p)
>> + return find_next_bit(src2p, nr_bits, n + 1);
>> +
>> + return n + 1;
>> +}
>> #else
>> static inline int netif_set_xps_queue(struct net_device *dev,
>> const struct cpumask *mask,
>> diff --git a/net/core/dev.c b/net/core/dev.c
>> index 9f43901..7e5dfdb 100644
>> --- a/net/core/dev.c
>> +++ b/net/core/dev.c
>> @@ -2092,7 +2092,7 @@ static bool remove_xps_queue(struct xps_dev_maps *dev_maps,
>> int pos;
>>
>> if (dev_maps)
>> - map = xmap_dereference(dev_maps->cpu_map[tci]);
>> + map = xmap_dereference(dev_maps->attr_map[tci]);
>> if (!map)
>> return false;
>>
>> @@ -2105,7 +2105,7 @@ static bool remove_xps_queue(struct xps_dev_maps *dev_maps,
>> break;
>> }
>>
>> - RCU_INIT_POINTER(dev_maps->cpu_map[tci], NULL);
>> + RCU_INIT_POINTER(dev_maps->attr_map[tci], NULL);
>> kfree_rcu(map, rcu);
>> return false;
>> }
>> @@ -2125,7 +2125,7 @@ static bool remove_xps_queue_cpu(struct net_device *dev,
>> int i, j;
>>
>> for (i = count, j = offset; i--; j++) {
>> - if (!remove_xps_queue(dev_maps, cpu, j))
>> + if (!remove_xps_queue(dev_maps, tci, j))
>> break;
>> }
>>
>> @@ -2138,30 +2138,47 @@ static bool remove_xps_queue_cpu(struct net_device *dev,
>> static void netif_reset_xps_queues(struct net_device *dev, u16 offset,
>> u16 count)
>> {
>> + const unsigned long *possible_mask = NULL;
>> + enum xps_map_type type = XPS_MAP_RXQS;
>> struct xps_dev_maps *dev_maps;
>> - int cpu, i;
>> bool active = false;
>> + unsigned int nr_ids;
>> + int i, j;
>>
>> mutex_lock(&xps_map_mutex);
>> - dev_maps = xmap_dereference(dev->xps_maps);
>>
>> - if (!dev_maps)
>> - goto out_no_maps;
>> + while (type < __XPS_MAP_MAX) {
>> + dev_maps = xmap_dereference(dev->xps_maps[type]);
>> + if (!dev_maps)
>> + goto out_no_maps;
>> +
>> + if (type == XPS_MAP_CPUS) {
>> + if (num_possible_cpus() > 1)
>> + possible_mask = cpumask_bits(cpu_possible_mask);
>> + nr_ids = nr_cpu_ids;
>> + } else if (type == XPS_MAP_RXQS) {
>> + nr_ids = dev->num_rx_queues;
>> + }
> type is an enum so this should be a switch
Will fix in v3.
>
>>
>> - for_each_possible_cpu(cpu)
>> - active |= remove_xps_queue_cpu(dev, dev_maps, cpu,
>> - offset, count);
>> + for (j = -1; j = attrmask_next(j, possible_mask, nr_ids),
>> + j < nr_ids;)
>> + active |= remove_xps_queue_cpu(dev, dev_maps, j, offset,
>> + count);
>> + if (!active) {
>> + RCU_INIT_POINTER(dev->xps_maps[type], NULL);
>> + kfree_rcu(dev_maps, rcu);
>> + }
>>
>> - if (!active) {
>> - RCU_INIT_POINTER(dev->xps_maps, NULL);
>> - kfree_rcu(dev_maps, rcu);
>> + if (type == XPS_MAP_CPUS) {
>> + for (i = offset + (count - 1); count--; i--)
>> + netdev_queue_numa_node_write(
>> + netdev_get_tx_queue(dev, i),
>> + NUMA_NO_NODE);
>> + }
>> +out_no_maps:
>> + type++;
>> }
>>
>> - for (i = offset + (count - 1); count--; i--)
>> - netdev_queue_numa_node_write(netdev_get_tx_queue(dev, i),
>> - NUMA_NO_NODE);
>> -
>> -out_no_maps:
>> mutex_unlock(&xps_map_mutex);
>> }
>>
>> @@ -2170,11 +2187,11 @@ static void netif_reset_xps_queues_gt(struct net_device *dev, u16 index)
>> netif_reset_xps_queues(dev, index, dev->num_tx_queues - index);
>> }
>>
>> -static struct xps_map *expand_xps_map(struct xps_map *map,
>> - int cpu, u16 index)
>> +static struct xps_map *expand_xps_map(struct xps_map *map, int attr_index,
>> + u16 index, enum xps_map_type type)
>> {
>> - struct xps_map *new_map;
>> int alloc_len = XPS_MIN_MAP_ALLOC;
>> + struct xps_map *new_map = NULL;
>> int i, pos;
>>
>> for (pos = 0; map && pos < map->len; pos++) {
>> @@ -2183,7 +2200,7 @@ static struct xps_map *expand_xps_map(struct xps_map *map,
>> return map;
>> }
>>
>> - /* Need to add queue to this CPU's existing map */
>> + /* Need to add tx-queue to this CPU's/rx-queue's existing map */
>> if (map) {
>> if (pos < map->alloc_len)
>> return map;
>> @@ -2191,9 +2208,14 @@ static struct xps_map *expand_xps_map(struct xps_map *map,
>> alloc_len = map->alloc_len * 2;
>> }
>>
>> - /* Need to allocate new map to store queue on this CPU's map */
>> - new_map = kzalloc_node(XPS_MAP_SIZE(alloc_len), GFP_KERNEL,
>> - cpu_to_node(cpu));
>> + /* Need to allocate new map to store tx-queue on this CPU's/rx-queue's
>> + * map
>> + */
>> + if (type == XPS_MAP_RXQS)
>> + new_map = kzalloc(XPS_MAP_SIZE(alloc_len), GFP_KERNEL);
>> + else if (type == XPS_MAP_CPUS)
>> + new_map = kzalloc_node(XPS_MAP_SIZE(alloc_len), GFP_KERNEL,
>> + cpu_to_node(attr_index));
> switch here also
Will fix in v3.
>
>> if (!new_map)
>> return NULL;
>>
>> @@ -2205,14 +2227,16 @@ static struct xps_map *expand_xps_map(struct xps_map *map,
>> return new_map;
>> }
>>
>> -int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
>> - u16 index)
>> +int __netif_set_xps_queue(struct net_device *dev, const unsigned long *mask,
>> + u16 index, enum xps_map_type type)
>> {
>> + const unsigned long *online_mask = NULL, *possible_mask = NULL;
>> struct xps_dev_maps *dev_maps, *new_dev_maps = NULL;
>> - int i, cpu, tci, numa_node_id = -2;
>> + int i, j, tci, numa_node_id = -2;
>> int maps_sz, num_tc = 1, tc = 0;
>> struct xps_map *map, *new_map;
>> bool active = false;
>> + unsigned int nr_ids;
>>
>> if (dev->num_tc) {
>> num_tc = dev->num_tc;
>> @@ -2221,16 +2245,33 @@ int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
>> return -EINVAL;
>> }
>>
>> - maps_sz = XPS_DEV_MAPS_SIZE(num_tc);
>> + switch (type) {
>> + case XPS_MAP_RXQS:
>> + maps_sz = XPS_RXQ_DEV_MAPS_SIZE(num_tc, dev->num_rx_queues);
>> + dev_maps = xmap_dereference(dev->xps_maps[XPS_MAP_RXQS]);
>> + nr_ids = dev->num_rx_queues;
>> + break;
>> + case XPS_MAP_CPUS:
>> + maps_sz = XPS_CPU_DEV_MAPS_SIZE(num_tc);
>> + if (num_possible_cpus() > 1) {
>> + online_mask = cpumask_bits(cpu_online_mask);
>> + possible_mask = cpumask_bits(cpu_possible_mask);
>> + }
>> + dev_maps = xmap_dereference(dev->xps_maps[XPS_MAP_CPUS]);
>> + nr_ids = nr_cpu_ids;
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> +
>> if (maps_sz < L1_CACHE_BYTES)
>> maps_sz = L1_CACHE_BYTES;
>>
>> mutex_lock(&xps_map_mutex);
>>
>> - dev_maps = xmap_dereference(dev->xps_maps);
>> -
>> /* allocate memory for queue storage */
>> - for_each_cpu_and(cpu, cpu_online_mask, mask) {
>> + for (j = -1; j = attrmask_next_and(j, online_mask, mask, nr_ids),
>> + j < nr_ids;) {
>> if (!new_dev_maps)
>> new_dev_maps = kzalloc(maps_sz, GFP_KERNEL);
>> if (!new_dev_maps) {
>> @@ -2238,73 +2279,81 @@ int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
>> return -ENOMEM;
>> }
>>
>> - tci = cpu * num_tc + tc;
>> - map = dev_maps ? xmap_dereference(dev_maps->cpu_map[tci]) :
>> + tci = j * num_tc + tc;
>> + map = dev_maps ? xmap_dereference(dev_maps->attr_map[tci]) :
>> NULL;
>>
>> - map = expand_xps_map(map, cpu, index);
>> + map = expand_xps_map(map, j, index, type);
>> if (!map)
>> goto error;
>>
>> - RCU_INIT_POINTER(new_dev_maps->cpu_map[tci], map);
>> + RCU_INIT_POINTER(new_dev_maps->attr_map[tci], map);
>> }
>>
>> if (!new_dev_maps)
>> goto out_no_new_maps;
>>
>> - for_each_possible_cpu(cpu) {
>> + for (j = -1; j = attrmask_next(j, possible_mask, nr_ids),
>> + j < nr_ids;) {
>> /* copy maps belonging to foreign traffic classes */
>> - for (i = tc, tci = cpu * num_tc; dev_maps && i--; tci++) {
>> + for (i = tc, tci = j * num_tc; dev_maps && i--; tci++) {
>> /* fill in the new device map from the old device map */
>> - map = xmap_dereference(dev_maps->cpu_map[tci]);
>> - RCU_INIT_POINTER(new_dev_maps->cpu_map[tci], map);
>> + map = xmap_dereference(dev_maps->attr_map[tci]);
>> + RCU_INIT_POINTER(new_dev_maps->attr_map[tci], map);
>> }
>>
>> /* We need to explicitly update tci as prevous loop
>> * could break out early if dev_maps is NULL.
>> */
>> - tci = cpu * num_tc + tc;
>> + tci = j * num_tc + tc;
>>
>> - if (cpumask_test_cpu(cpu, mask) && cpu_online(cpu)) {
>> - /* add queue to CPU maps */
>> + if (attr_test_mask(j, mask, nr_ids) &&
>> + attr_test_online(j, online_mask, nr_ids)) {
>> + /* add tx-queue to CPU/rx-queue maps */
>> int pos = 0;
>>
>> - map = xmap_dereference(new_dev_maps->cpu_map[tci]);
>> + map = xmap_dereference(new_dev_maps->attr_map[tci]);
>> while ((pos < map->len) && (map->queues[pos] != index))
>> pos++;
>>
>> if (pos == map->len)
>> map->queues[map->len++] = index;
>> #ifdef CONFIG_NUMA
>> - if (numa_node_id == -2)
>> - numa_node_id = cpu_to_node(cpu);
>> - else if (numa_node_id != cpu_to_node(cpu))
>> - numa_node_id = -1;
>> + if (type == XPS_MAP_CPUS) {
>> + if (numa_node_id == -2)
>> + numa_node_id = cpu_to_node(j);
>> + else if (numa_node_id != cpu_to_node(j))
>> + numa_node_id = -1;
>> + }
>> #endif
>> } else if (dev_maps) {
>> /* fill in the new device map from the old device map */
>> - map = xmap_dereference(dev_maps->cpu_map[tci]);
>> - RCU_INIT_POINTER(new_dev_maps->cpu_map[tci], map);
>> + map = xmap_dereference(dev_maps->attr_map[tci]);
>> + RCU_INIT_POINTER(new_dev_maps->attr_map[tci], map);
>> }
>>
>> /* copy maps belonging to foreign traffic classes */
>> for (i = num_tc - tc, tci++; dev_maps && --i; tci++) {
>> /* fill in the new device map from the old device map */
>> - map = xmap_dereference(dev_maps->cpu_map[tci]);
>> - RCU_INIT_POINTER(new_dev_maps->cpu_map[tci], map);
>> + map = xmap_dereference(dev_maps->attr_map[tci]);
>> + RCU_INIT_POINTER(new_dev_maps->attr_map[tci], map);
>> }
>> }
>>
>> - rcu_assign_pointer(dev->xps_maps, new_dev_maps);
>> + if (type == XPS_MAP_RXQS)
>> + rcu_assign_pointer(dev->xps_maps[XPS_MAP_RXQS], new_dev_maps);
>> + else if (type == XPS_MAP_CPUS)
>> + rcu_assign_pointer(dev->xps_maps[XPS_MAP_CPUS], new_dev_maps);
>>
>> /* Cleanup old maps */
>> if (!dev_maps)
>> goto out_no_old_maps;
>>
>> - for_each_possible_cpu(cpu) {
>> - for (i = num_tc, tci = cpu * num_tc; i--; tci++) {
>> - new_map = xmap_dereference(new_dev_maps->cpu_map[tci]);
>> - map = xmap_dereference(dev_maps->cpu_map[tci]);
>> + for (j = -1; j = attrmask_next(j, possible_mask, nr_ids),
>> + j < nr_ids;) {
>> + for (i = num_tc, tci = j * num_tc; i--; tci++) {
>> + new_map = xmap_dereference(new_dev_maps->attr_map[tci]);
>> + map = xmap_dereference(dev_maps->attr_map[tci]);
>> if (map && map != new_map)
>> kfree_rcu(map, rcu);
>> }
>> @@ -2317,19 +2366,23 @@ int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
>> active = true;
>>
>> out_no_new_maps:
>> - /* update Tx queue numa node */
>> - netdev_queue_numa_node_write(netdev_get_tx_queue(dev, index),
>> - (numa_node_id >= 0) ? numa_node_id :
>> - NUMA_NO_NODE);
>> + if (type == XPS_MAP_CPUS) {
>> + /* update Tx queue numa node */
>> + netdev_queue_numa_node_write(netdev_get_tx_queue(dev, index),
>> + (numa_node_id >= 0) ?
>> + numa_node_id : NUMA_NO_NODE);
>> + }
>>
>> if (!dev_maps)
>> goto out_no_maps;
>>
>> - /* removes queue from unused CPUs */
>> - for_each_possible_cpu(cpu) {
>> - for (i = tc, tci = cpu * num_tc; i--; tci++)
>> + /* removes tx-queue from unused CPUs/rx-queues */
>> + for (j = -1; j = attrmask_next(j, possible_mask, nr_ids),
>> + j < nr_ids;) {
>> + for (i = tc, tci = j * num_tc; i--; tci++)
>> active |= remove_xps_queue(dev_maps, tci, index);
>> - if (!cpumask_test_cpu(cpu, mask) || !cpu_online(cpu))
>> + if (!attr_test_mask(j, mask, nr_ids) ||
>> + !attr_test_online(j, online_mask, nr_ids))
>> active |= remove_xps_queue(dev_maps, tci, index);
>> for (i = num_tc - tc, tci++; --i; tci++)
>> active |= remove_xps_queue(dev_maps, tci, index);
>> @@ -2337,7 +2390,10 @@ int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
>>
>> /* free map if not active */
>> if (!active) {
>> - RCU_INIT_POINTER(dev->xps_maps, NULL);
>> + if (type == XPS_MAP_RXQS)
>> + RCU_INIT_POINTER(dev->xps_maps[XPS_MAP_RXQS], NULL);
>> + else if (type == XPS_MAP_CPUS)
>> + RCU_INIT_POINTER(dev->xps_maps[XPS_MAP_CPUS], NULL);
>> kfree_rcu(dev_maps, rcu);
>> }
>>
>> @@ -2347,11 +2403,12 @@ int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
>> return 0;
>> error:
>> /* remove any maps that we added */
>> - for_each_possible_cpu(cpu) {
>> - for (i = num_tc, tci = cpu * num_tc; i--; tci++) {
>> - new_map = xmap_dereference(new_dev_maps->cpu_map[tci]);
>> + for (j = -1; j = attrmask_next(j, possible_mask, nr_ids),
>> + j < nr_ids;) {
>> + for (i = num_tc, tci = j * num_tc; i--; tci++) {
>> + new_map = xmap_dereference(new_dev_maps->attr_map[tci]);
>> map = dev_maps ?
>> - xmap_dereference(dev_maps->cpu_map[tci]) :
>> + xmap_dereference(dev_maps->attr_map[tci]) :
>> NULL;
>> if (new_map && new_map != map)
>> kfree(new_map);
>> @@ -2363,6 +2420,13 @@ int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
>> kfree(new_dev_maps);
>> return -ENOMEM;
>> }
>> +
>> +int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
>> + u16 index)
>> +{
>> + return __netif_set_xps_queue(dev, cpumask_bits(mask), index,
>> + XPS_MAP_CPUS);
>> +}
>> EXPORT_SYMBOL(netif_set_xps_queue);
>>
>> #endif
>> @@ -3402,7 +3466,7 @@ static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
>> int queue_index = -1;
>>
>> rcu_read_lock();
>> - dev_maps = rcu_dereference(dev->xps_maps);
>> + dev_maps = rcu_dereference(dev->xps_maps[XPS_MAP_CPUS]);
>> if (dev_maps) {
>> unsigned int tci = skb->sender_cpu - 1;
>>
>> @@ -3411,7 +3475,7 @@ static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
>> tci += netdev_get_prio_tc_map(dev, skb->priority);
>> }
>>
>> - map = rcu_dereference(dev_maps->cpu_map[tci]);
>> + map = rcu_dereference(dev_maps->attr_map[tci]);
>> if (map) {
>> if (map->len == 1)
>> queue_index = map->queues[0];
>> diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
>> index c476f07..d7abd33 100644
>> --- a/net/core/net-sysfs.c
>> +++ b/net/core/net-sysfs.c
>> @@ -1227,13 +1227,13 @@ static ssize_t xps_cpus_show(struct netdev_queue *queue,
>> }
>>
>> rcu_read_lock();
>> - dev_maps = rcu_dereference(dev->xps_maps);
>> + dev_maps = rcu_dereference(dev->xps_maps[XPS_MAP_CPUS]);
>> if (dev_maps) {
>> for_each_possible_cpu(cpu) {
>> int i, tci = cpu * num_tc + tc;
>> struct xps_map *map;
>>
>> - map = rcu_dereference(dev_maps->cpu_map[tci]);
>> + map = rcu_dereference(dev_maps->attr_map[tci]);
>> if (!map)
>> continue;
>>
>>
^ permalink raw reply
* Re: [PATCH net-next] hv_netvsc: Add handlers for ethtool get/set msg level
From: David Miller @ 2018-05-23 18:59 UTC (permalink / raw)
To: haiyangz, haiyangz
Cc: netdev, kys, sthemmin, olaf, vkuznets, devel, linux-kernel
In-Reply-To: <20180522182934.31515-1-haiyangz@linuxonhyperv.com>
From: Haiyang Zhang <haiyangz@linuxonhyperv.com>
Date: Tue, 22 May 2018 11:29:34 -0700
> From: Haiyang Zhang <haiyangz@microsoft.com>
>
> The handlers for ethtool get/set msg level are missing from netvsc.
> This patch adds them.
>
> Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Applied.
^ permalink raw reply
* Re: [PATCH net] ibmvnic: Only do H_EOI for mobility events
From: David Miller @ 2018-05-23 18:54 UTC (permalink / raw)
To: nfont; +Cc: netdev, jallen, tlfalcon
In-Reply-To: <152700607013.58815.10070919641026174502.stgit@ltcalpine2-lp14.aus.stglabs.ibm.com>
From: Nathan Fontenot <nfont@linux.vnet.ibm.com>
Date: Tue, 22 May 2018 11:21:10 -0500
> When enabling the sub-CRQ IRQ a previous update sent a H_EOI prior
> to the enablement to clear any pending interrupts that may be present
> across a partition migration. This fixed a firmware bug where a
> migration could erroneously indicate that a H_EOI was pending.
>
> The H_EOI should only be sent when enabling during a mobility
> event though. Doing so at other time could wrong and can produce
> extra driver output when IRQs are enabled when doing TX completion.
>
> Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>
Applied, thanks.
^ permalink raw reply
* [PATCH iproute2-next] ip route: print RTA_CACHEINFO if it exists
From: dsahern @ 2018-05-23 18:53 UTC (permalink / raw)
To: netdev, stephen; +Cc: David Ahern
From: David Ahern <dsahern@gmail.com>
RTA_CACHEINFO can be sent for non-cloned routes. If the attribute is
present print it. Allows route dumps to print expires times for example
which can exist on FIB entries.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
ip/iproute.c | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/ip/iproute.c b/ip/iproute.c
index 56dd9f25e38e..647c170b1d10 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -899,17 +899,13 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
rta_getattr_u32(tb[RTA_UID]));
if (r->rtm_family == AF_INET) {
- if (r->rtm_flags & RTM_F_CLONED) {
- print_cache_flags(fp, r->rtm_flags);
+ print_cache_flags(fp, r->rtm_flags);
- if (tb[RTA_CACHEINFO])
- print_rta_cacheinfo(fp, RTA_DATA(tb[RTA_CACHEINFO]));
- }
+ if (tb[RTA_CACHEINFO])
+ print_rta_cacheinfo(fp, RTA_DATA(tb[RTA_CACHEINFO]));
} else if (r->rtm_family == AF_INET6) {
- if (r->rtm_flags & RTM_F_CLONED) {
- if (tb[RTA_CACHEINFO])
- print_rta_cacheinfo(fp, RTA_DATA(tb[RTA_CACHEINFO]));
- }
+ if (tb[RTA_CACHEINFO])
+ print_rta_cacheinfo(fp, RTA_DATA(tb[RTA_CACHEINFO]));
}
if (tb[RTA_METRICS])
--
2.11.0
^ permalink raw reply related
* Re: [PATCH][V2] net: vxge: fix spelling mistake in macro VXGE_HW_ERR_PRIVILAGED_OPEARATION
From: David Miller @ 2018-05-23 18:50 UTC (permalink / raw)
To: colin.king; +Cc: jdmason, netdev, kernel-janitors, linux-kernel
In-Reply-To: <20180522161809.30299-1-colin.king@canonical.com>
From: Colin King <colin.king@canonical.com>
Date: Tue, 22 May 2018 17:18:09 +0100
> From: Colin Ian King <colin.king@canonical.com>
>
> Rename VXGE_HW_ERR_PRIVILAGED_OPEARATION to VXGE_HW_ERR_PRIVILEGED_OPERATION
> to fix spelling mistake.
>
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
> ---
> V2: PRIVILAGED -> PRIVILEGED, thanks to Edward Cree for spotting that mistake
Applied to net-next, thanks Colin.
^ permalink raw reply
* [PATCH iproute2] ip route: Print expires as signed int
From: dsahern @ 2018-05-23 18:50 UTC (permalink / raw)
To: netdev, stephen; +Cc: David Ahern
From: David Ahern <dsahern@gmail.com>
rta_expires is a signed int; print it as one.
Fixes: 663c3cb23103f ("iproute: implement JSON and color output")
Signed-off-by: David Ahern <dsahern@gmail.com>
---
ip/iproute.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ip/iproute.c b/ip/iproute.c
index 56dd9f25e38e..cbc43e2b691a 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -463,8 +463,8 @@ static void print_rta_cacheinfo(FILE *fp, const struct rta_cacheinfo *ci)
hz = get_user_hz();
if (ci->rta_expires != 0)
- print_uint(PRINT_ANY, "expires",
- "expires %usec ", ci->rta_expires/hz);
+ print_int(PRINT_ANY, "expires",
+ "expires %dsec ", ci->rta_expires/hz);
if (ci->rta_error != 0)
print_uint(PRINT_ANY, "error",
"error %u ", ci->rta_error);
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 7/8] ibmvnic: Set resetting state at earliest possible point
From: Thomas Falcon @ 2018-05-23 18:38 UTC (permalink / raw)
To: netdev; +Cc: nfont, jallen, linuxppc-dev, Thomas Falcon
In-Reply-To: <1527100682-23099-1-git-send-email-tlfalcon@linux.vnet.ibm.com>
Set device resetting state at the earliest possible point: as soon as a
reset is successfully scheduled. The reset state is toggled off when
all resets have been processed to completion.
Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
---
drivers/net/ethernet/ibm/ibmvnic.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index f26e1f8..ee51deb 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -1919,7 +1919,6 @@ static void __ibmvnic_reset(struct work_struct *work)
netdev = adapter->netdev;
mutex_lock(&adapter->reset_lock);
- adapter->resetting = true;
reset_state = adapter->state;
rwi = get_next_rwi(adapter);
@@ -1994,7 +1993,7 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
rwi->reset_reason = reason;
list_add_tail(&rwi->list, &adapter->rwi_list);
mutex_unlock(&adapter->rwi_lock);
-
+ adapter->resetting = true;
netdev_dbg(adapter->netdev, "Scheduling reset (reason %d)\n", reason);
schedule_work(&adapter->ibmvnic_reset);
--
2.7.5
^ permalink raw reply related
* [PATCH net-next 8/8] ibmvnic: Introduce hard reset recovery
From: Thomas Falcon @ 2018-05-23 18:38 UTC (permalink / raw)
To: netdev; +Cc: nfont, jallen, linuxppc-dev, Thomas Falcon
In-Reply-To: <1527100682-23099-1-git-send-email-tlfalcon@linux.vnet.ibm.com>
Introduce a recovery hard reset to handle reset failure as a result of
change of device context following a transport event, such as a
backing device failover or partition migration. These operations reset
the device context to its initial state. If this occurs during a reset,
any initialization commands are likely to fail with an invalid state
error as backing device firmware requests reinitialization.
When this happens, make one more attempt by performing a hard reset,
which frees any resources currently allocated and performs device
initialization. If a transport event occurs during a device reset, a
flag is set which will trigger a new hard reset following the
completionof the current reset event.
Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
---
drivers/net/ethernet/ibm/ibmvnic.c | 101 +++++++++++++++++++++++++++++++++++--
drivers/net/ethernet/ibm/ibmvnic.h | 1 +
2 files changed, 98 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index ee51deb..09f8e6b 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -1878,6 +1878,85 @@ static int do_reset(struct ibmvnic_adapter *adapter,
return 0;
}
+static int do_hard_reset(struct ibmvnic_adapter *adapter,
+ struct ibmvnic_rwi *rwi, u32 reset_state)
+{
+ struct net_device *netdev = adapter->netdev;
+ int rc;
+
+ netdev_dbg(adapter->netdev, "Hard resetting driver (%d)\n",
+ rwi->reset_reason);
+
+ netif_carrier_off(netdev);
+ adapter->reset_reason = rwi->reset_reason;
+
+ ibmvnic_cleanup(netdev);
+ release_resources(adapter);
+ release_sub_crqs(adapter, 0);
+ release_crq_queue(adapter);
+
+ /* remove the closed state so when we call open it appears
+ * we are coming from the probed state.
+ */
+ adapter->state = VNIC_PROBED;
+
+ rc = init_crq_queue(adapter);
+ if (rc) {
+ netdev_err(adapter->netdev,
+ "Couldn't initialize crq. rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = ibmvnic_init(adapter);
+ if (rc)
+ return rc;
+
+ /* If the adapter was in PROBE state prior to the reset,
+ * exit here.
+ */
+ if (reset_state == VNIC_PROBED)
+ return 0;
+
+ rc = ibmvnic_login(netdev);
+ if (rc) {
+ adapter->state = VNIC_PROBED;
+ return 0;
+ }
+ /* netif_set_real_num_xx_queues needs to take rtnl lock here
+ * unless wait_for_reset is set, in which case the rtnl lock
+ * has already been taken before initializing the reset
+ */
+ if (!adapter->wait_for_reset) {
+ rtnl_lock();
+ rc = init_resources(adapter);
+ rtnl_unlock();
+ } else {
+ rc = init_resources(adapter);
+ }
+ if (rc)
+ return rc;
+
+ ibmvnic_disable_irqs(adapter);
+ adapter->state = VNIC_CLOSED;
+
+ if (reset_state == VNIC_CLOSED)
+ return 0;
+
+ rc = __ibmvnic_open(netdev);
+ if (rc) {
+ if (list_empty(&adapter->rwi_list))
+ adapter->state = VNIC_CLOSED;
+ else
+ adapter->state = reset_state;
+
+ return 0;
+ }
+
+ netif_carrier_on(netdev);
+
+ return 0;
+}
+
static struct ibmvnic_rwi *get_next_rwi(struct ibmvnic_adapter *adapter)
{
struct ibmvnic_rwi *rwi;
@@ -1923,9 +2002,15 @@ static void __ibmvnic_reset(struct work_struct *work)
rwi = get_next_rwi(adapter);
while (rwi) {
- rc = do_reset(adapter, rwi, reset_state);
+ if (adapter->force_reset_recovery) {
+ adapter->force_reset_recovery = false;
+ rc = do_hard_reset(adapter, rwi, reset_state);
+ } else {
+ rc = do_reset(adapter, rwi, reset_state);
+ }
kfree(rwi);
- if (rc && rc != IBMVNIC_INIT_FAILED)
+ if (rc && rc != IBMVNIC_INIT_FAILED &&
+ !adapter->force_reset_recovery)
break;
rwi = get_next_rwi(adapter);
@@ -1951,9 +2036,9 @@ static void __ibmvnic_reset(struct work_struct *work)
static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
enum ibmvnic_reset_reason reason)
{
+ struct list_head *entry, *tmp_entry;
struct ibmvnic_rwi *rwi, *tmp;
struct net_device *netdev = adapter->netdev;
- struct list_head *entry;
int ret;
if (adapter->state == VNIC_REMOVING ||
@@ -1989,7 +2074,13 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
ret = ENOMEM;
goto err;
}
-
+ /* if we just received a transport event,
+ * flush reset queue and process this reset
+ */
+ if (adapter->force_reset_recovery && !list_empty(&adapter->rwi_list)) {
+ list_for_each_safe(entry, tmp_entry, &adapter->rwi_list)
+ list_del(entry);
+ }
rwi->reset_reason = reason;
list_add_tail(&rwi->list, &adapter->rwi_list);
mutex_unlock(&adapter->rwi_lock);
@@ -4271,6 +4362,8 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
case IBMVNIC_CRQ_XPORT_EVENT:
netif_carrier_off(netdev);
adapter->crq.active = false;
+ if (adapter->resetting)
+ adapter->force_reset_recovery = true;
if (gen_crq->cmd == IBMVNIC_PARTITION_MIGRATED) {
dev_info(dev, "Migrated, re-enabling adapter\n");
ibmvnic_reset(adapter, VNIC_RESET_MOBILITY);
diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h
index edfc312..f9fb780 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.h
+++ b/drivers/net/ethernet/ibm/ibmvnic.h
@@ -1109,6 +1109,7 @@ struct ibmvnic_adapter {
bool mac_change_pending;
bool failover_pending;
+ bool force_reset_recovery;
struct ibmvnic_tunables desired;
struct ibmvnic_tunables fallback;
--
2.7.5
^ permalink raw reply related
* [PATCH net-next 6/8] ibmvnic: Create separate initialization routine for resets
From: Thomas Falcon @ 2018-05-23 18:38 UTC (permalink / raw)
To: netdev; +Cc: nfont, jallen, linuxppc-dev, Thomas Falcon
In-Reply-To: <1527100682-23099-1-git-send-email-tlfalcon@linux.vnet.ibm.com>
Instead of having one initialization routine for all cases, create
a separate, simpler function for standard initialization, such as during
device probe. Use the original initialization function to handle
device reset scenarios. The goal of this patch is to avoid having
a single, cluttered init function to handle all possible
scenarios.
Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
---
drivers/net/ethernet/ibm/ibmvnic.c | 48 ++++++++++++++++++++++++++++++++++++--
1 file changed, 46 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index b1bbd5b..f26e1f8 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -116,6 +116,7 @@ static void send_cap_queries(struct ibmvnic_adapter *adapter);
static int init_sub_crqs(struct ibmvnic_adapter *);
static int init_sub_crq_irqs(struct ibmvnic_adapter *adapter);
static int ibmvnic_init(struct ibmvnic_adapter *);
+static int ibmvnic_reset_init(struct ibmvnic_adapter *);
static void release_crq_queue(struct ibmvnic_adapter *);
static int __ibmvnic_set_mac(struct net_device *netdev, struct sockaddr *p);
static int init_crq_queue(struct ibmvnic_adapter *adapter);
@@ -1807,7 +1808,7 @@ static int do_reset(struct ibmvnic_adapter *adapter,
return rc;
}
- rc = ibmvnic_init(adapter);
+ rc = ibmvnic_reset_init(adapter);
if (rc)
return IBMVNIC_INIT_FAILED;
@@ -4571,7 +4572,7 @@ static int init_crq_queue(struct ibmvnic_adapter *adapter)
return retrc;
}
-static int ibmvnic_init(struct ibmvnic_adapter *adapter)
+static int ibmvnic_reset_init(struct ibmvnic_adapter *adapter)
{
struct device *dev = &adapter->vdev->dev;
unsigned long timeout = msecs_to_jiffies(30000);
@@ -4630,6 +4631,49 @@ static int ibmvnic_init(struct ibmvnic_adapter *adapter)
return rc;
}
+static int ibmvnic_init(struct ibmvnic_adapter *adapter)
+{
+ struct device *dev = &adapter->vdev->dev;
+ unsigned long timeout = msecs_to_jiffies(30000);
+ int rc;
+
+ adapter->from_passive_init = false;
+
+ init_completion(&adapter->init_done);
+ adapter->init_done_rc = 0;
+ ibmvnic_send_crq_init(adapter);
+ if (!wait_for_completion_timeout(&adapter->init_done, timeout)) {
+ dev_err(dev, "Initialization sequence timed out\n");
+ return -1;
+ }
+
+ if (adapter->init_done_rc) {
+ release_crq_queue(adapter);
+ return adapter->init_done_rc;
+ }
+
+ if (adapter->from_passive_init) {
+ adapter->state = VNIC_OPEN;
+ adapter->from_passive_init = false;
+ return -1;
+ }
+
+ rc = init_sub_crqs(adapter);
+ if (rc) {
+ dev_err(dev, "Initialization of sub crqs failed\n");
+ release_crq_queue(adapter);
+ return rc;
+ }
+
+ rc = init_sub_crq_irqs(adapter);
+ if (rc) {
+ dev_err(dev, "Failed to initialize sub crq irqs\n");
+ release_crq_queue(adapter);
+ }
+
+ return rc;
+}
+
static struct device_attribute dev_attr_failover;
static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
--
2.7.5
^ permalink raw reply related
* [PATCH net-next 5/8] ibmvnic: Handle error case when setting link state
From: Thomas Falcon @ 2018-05-23 18:37 UTC (permalink / raw)
To: netdev; +Cc: nfont, jallen, linuxppc-dev, Thomas Falcon
In-Reply-To: <1527100682-23099-1-git-send-email-tlfalcon@linux.vnet.ibm.com>
If setting the link state is not successful, print a warning
with the resulting return code and return it to be handled
by the caller.
Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
---
drivers/net/ethernet/ibm/ibmvnic.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index f1f744e..b1bbd5b 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -929,6 +929,10 @@ static int set_link_state(struct ibmvnic_adapter *adapter, u8 link_state)
/* Partuial success, delay and re-send */
mdelay(1000);
resend = true;
+ } else if (adapter->init_done_rc) {
+ netdev_warn(netdev, "Unable to set link state, rc=%d\n",
+ adapter->init_done_rc);
+ return adapter->init_done_rc;
}
} while (resend);
--
2.7.5
^ permalink raw reply related
* [PATCH net-next 4/8] ibmvnic: Return error code if init interrupted by transport event
From: Thomas Falcon @ 2018-05-23 18:37 UTC (permalink / raw)
To: netdev; +Cc: nfont, jallen, linuxppc-dev, Thomas Falcon
In-Reply-To: <1527100682-23099-1-git-send-email-tlfalcon@linux.vnet.ibm.com>
If device init is interrupted by a failover, set the init return
code so that it can be checked and handled appropriately by the
init routine.
Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
---
drivers/net/ethernet/ibm/ibmvnic.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 7083519..f1f744e 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4249,7 +4249,10 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
dev_info(dev, "Partner initialized\n");
adapter->from_passive_init = true;
adapter->failover_pending = false;
- complete(&adapter->init_done);
+ if (!completion_done(&adapter->init_done)) {
+ complete(&adapter->init_done);
+ adapter->init_done_rc = -EIO;
+ }
ibmvnic_reset(adapter, VNIC_RESET_FAILOVER);
break;
case IBMVNIC_CRQ_INIT_COMPLETE:
--
2.7.5
^ permalink raw reply related
* [PATCH net-next 3/8] ibmvnic: Check CRQ command return codes
From: Thomas Falcon @ 2018-05-23 18:37 UTC (permalink / raw)
To: netdev; +Cc: nfont, jallen, linuxppc-dev, Thomas Falcon
In-Reply-To: <1527100682-23099-1-git-send-email-tlfalcon@linux.vnet.ibm.com>
Check whether CRQ command is successful before awaiting a response
from the management partition. If the command was not successful, the
driver may hang waiting for a response that will never come.
Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
---
drivers/net/ethernet/ibm/ibmvnic.c | 51 +++++++++++++++++++++++++++-----------
1 file changed, 37 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index e6a081c..7083519 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -109,8 +109,8 @@ static union sub_crq *ibmvnic_next_scrq(struct ibmvnic_adapter *,
struct ibmvnic_sub_crq_queue *);
static int ibmvnic_poll(struct napi_struct *napi, int data);
static void send_map_query(struct ibmvnic_adapter *adapter);
-static void send_request_map(struct ibmvnic_adapter *, dma_addr_t, __be32, u8);
-static void send_request_unmap(struct ibmvnic_adapter *, u8);
+static int send_request_map(struct ibmvnic_adapter *, dma_addr_t, __be32, u8);
+static int send_request_unmap(struct ibmvnic_adapter *, u8);
static int send_login(struct ibmvnic_adapter *adapter);
static void send_cap_queries(struct ibmvnic_adapter *adapter);
static int init_sub_crqs(struct ibmvnic_adapter *);
@@ -172,6 +172,7 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,
struct ibmvnic_long_term_buff *ltb, int size)
{
struct device *dev = &adapter->vdev->dev;
+ int rc;
ltb->size = size;
ltb->buff = dma_alloc_coherent(dev, ltb->size, <b->addr,
@@ -185,8 +186,12 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,
adapter->map_id++;
init_completion(&adapter->fw_done);
- send_request_map(adapter, ltb->addr,
- ltb->size, ltb->map_id);
+ rc = send_request_map(adapter, ltb->addr,
+ ltb->size, ltb->map_id);
+ if (rc) {
+ dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
+ return rc;
+ }
wait_for_completion(&adapter->fw_done);
if (adapter->fw_done_rc) {
@@ -215,10 +220,14 @@ static void free_long_term_buff(struct ibmvnic_adapter *adapter,
static int reset_long_term_buff(struct ibmvnic_adapter *adapter,
struct ibmvnic_long_term_buff *ltb)
{
+ int rc;
+
memset(ltb->buff, 0, ltb->size);
init_completion(&adapter->fw_done);
- send_request_map(adapter, ltb->addr, ltb->size, ltb->map_id);
+ rc = send_request_map(adapter, ltb->addr, ltb->size, ltb->map_id);
+ if (rc)
+ return rc;
wait_for_completion(&adapter->fw_done);
if (adapter->fw_done_rc) {
@@ -952,6 +961,7 @@ static int ibmvnic_get_vpd(struct ibmvnic_adapter *adapter)
struct device *dev = &adapter->vdev->dev;
union ibmvnic_crq crq;
int len = 0;
+ int rc;
if (adapter->vpd->buff)
len = adapter->vpd->len;
@@ -959,7 +969,9 @@ static int ibmvnic_get_vpd(struct ibmvnic_adapter *adapter)
init_completion(&adapter->fw_done);
crq.get_vpd_size.first = IBMVNIC_CRQ_CMD;
crq.get_vpd_size.cmd = GET_VPD_SIZE;
- ibmvnic_send_crq(adapter, &crq);
+ rc = ibmvnic_send_crq(adapter, &crq);
+ if (rc)
+ return rc;
wait_for_completion(&adapter->fw_done);
if (!adapter->vpd->len)
@@ -992,7 +1004,12 @@ static int ibmvnic_get_vpd(struct ibmvnic_adapter *adapter)
crq.get_vpd.cmd = GET_VPD;
crq.get_vpd.ioba = cpu_to_be32(adapter->vpd->dma_addr);
crq.get_vpd.len = cpu_to_be32((u32)adapter->vpd->len);
- ibmvnic_send_crq(adapter, &crq);
+ rc = ibmvnic_send_crq(adapter, &crq);
+ if (rc) {
+ kfree(adapter->vpd->buff);
+ adapter->vpd->buff = NULL;
+ return rc;
+ }
wait_for_completion(&adapter->fw_done);
return 0;
@@ -1691,6 +1708,7 @@ static int __ibmvnic_set_mac(struct net_device *netdev, struct sockaddr *p)
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
struct sockaddr *addr = p;
union ibmvnic_crq crq;
+ int rc;
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
@@ -1701,7 +1719,9 @@ static int __ibmvnic_set_mac(struct net_device *netdev, struct sockaddr *p)
ether_addr_copy(&crq.change_mac_addr.mac_addr[0], addr->sa_data);
init_completion(&adapter->fw_done);
- ibmvnic_send_crq(adapter, &crq);
+ rc = ibmvnic_send_crq(adapter, &crq);
+ if (rc)
+ return rc;
wait_for_completion(&adapter->fw_done);
/* netdev->dev_addr is changed in handle_change_mac_rsp function */
return adapter->fw_done_rc ? -EIO : 0;
@@ -2365,6 +2385,7 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev,
struct ibmvnic_adapter *adapter = netdev_priv(dev);
union ibmvnic_crq crq;
int i, j;
+ int rc;
memset(&crq, 0, sizeof(crq));
crq.request_statistics.first = IBMVNIC_CRQ_CMD;
@@ -2375,7 +2396,9 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev,
/* Wait for data to be written */
init_completion(&adapter->stats_done);
- ibmvnic_send_crq(adapter, &crq);
+ rc = ibmvnic_send_crq(adapter, &crq);
+ if (rc)
+ return;
wait_for_completion(&adapter->stats_done);
for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++)
@@ -3377,8 +3400,8 @@ static int send_login(struct ibmvnic_adapter *adapter)
return -1;
}
-static void send_request_map(struct ibmvnic_adapter *adapter, dma_addr_t addr,
- u32 len, u8 map_id)
+static int send_request_map(struct ibmvnic_adapter *adapter, dma_addr_t addr,
+ u32 len, u8 map_id)
{
union ibmvnic_crq crq;
@@ -3388,10 +3411,10 @@ static void send_request_map(struct ibmvnic_adapter *adapter, dma_addr_t addr,
crq.request_map.map_id = map_id;
crq.request_map.ioba = cpu_to_be32(addr);
crq.request_map.len = cpu_to_be32(len);
- ibmvnic_send_crq(adapter, &crq);
+ return ibmvnic_send_crq(adapter, &crq);
}
-static void send_request_unmap(struct ibmvnic_adapter *adapter, u8 map_id)
+static int send_request_unmap(struct ibmvnic_adapter *adapter, u8 map_id)
{
union ibmvnic_crq crq;
@@ -3399,7 +3422,7 @@ static void send_request_unmap(struct ibmvnic_adapter *adapter, u8 map_id)
crq.request_unmap.first = IBMVNIC_CRQ_CMD;
crq.request_unmap.cmd = REQUEST_UNMAP;
crq.request_unmap.map_id = map_id;
- ibmvnic_send_crq(adapter, &crq);
+ return ibmvnic_send_crq(adapter, &crq);
}
static void send_map_query(struct ibmvnic_adapter *adapter)
--
2.7.5
^ permalink raw reply related
* [PATCH net-next 2/8] ibmvnic: Introduce active CRQ state
From: Thomas Falcon @ 2018-05-23 18:37 UTC (permalink / raw)
To: netdev; +Cc: nfont, jallen, linuxppc-dev, Thomas Falcon
In-Reply-To: <1527100682-23099-1-git-send-email-tlfalcon@linux.vnet.ibm.com>
Introduce an "active" state for a IBM vNIC Command-Response Queue. A CRQ
is considered active once it has initialized or linked with its partner by
sending an initialization request and getting a successful response back
from the management partition. Until this has happened, do not allow CRQ
commands to be sent other than the initialization request.
This change will avoid a protocol error in case of a device transport
event occurring during a initialization. When the driver receives a
transport event notification indicating that the backing hardware
has changed and needs reinitialization, any further commands other
than the initialization handshake with the VIOS management partition
will result in an invalid state error. Instead of sending a command
that will be returned with an error, print a warning and return an
error that will be handled by the caller.
Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
---
drivers/net/ethernet/ibm/ibmvnic.c | 10 ++++++++++
drivers/net/ethernet/ibm/ibmvnic.h | 1 +
2 files changed, 11 insertions(+)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index eabc1e4..e6a081c 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -3147,6 +3147,12 @@ static int ibmvnic_send_crq(struct ibmvnic_adapter *adapter,
(unsigned long int)cpu_to_be64(u64_crq[0]),
(unsigned long int)cpu_to_be64(u64_crq[1]));
+ if (!adapter->crq.active &&
+ crq->generic.first != IBMVNIC_CRQ_INIT_CMD) {
+ dev_warn(dev, "Invalid request detected while CRQ is inactive, possible device state change during reset\n");
+ return -EINVAL;
+ }
+
/* Make sure the hypervisor sees the complete request */
mb();
@@ -4225,6 +4231,7 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
break;
case IBMVNIC_CRQ_INIT_COMPLETE:
dev_info(dev, "Partner initialization complete\n");
+ adapter->crq.active = true;
send_version_xchg(adapter);
break;
default:
@@ -4233,6 +4240,7 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
return;
case IBMVNIC_CRQ_XPORT_EVENT:
netif_carrier_off(netdev);
+ adapter->crq.active = false;
if (gen_crq->cmd == IBMVNIC_PARTITION_MIGRATED) {
dev_info(dev, "Migrated, re-enabling adapter\n");
ibmvnic_reset(adapter, VNIC_RESET_MOBILITY);
@@ -4420,6 +4428,7 @@ static int ibmvnic_reset_crq(struct ibmvnic_adapter *adapter)
/* Clean out the queue */
memset(crq->msgs, 0, PAGE_SIZE);
crq->cur = 0;
+ crq->active = false;
/* And re-open it again */
rc = plpar_hcall_norets(H_REG_CRQ, vdev->unit_address,
@@ -4454,6 +4463,7 @@ static void release_crq_queue(struct ibmvnic_adapter *adapter)
DMA_BIDIRECTIONAL);
free_page((unsigned long)crq->msgs);
crq->msgs = NULL;
+ crq->active = false;
}
static int init_crq_queue(struct ibmvnic_adapter *adapter)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h
index 22391e8..edfc312 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.h
+++ b/drivers/net/ethernet/ibm/ibmvnic.h
@@ -865,6 +865,7 @@ struct ibmvnic_crq_queue {
int size, cur;
dma_addr_t msg_token;
spinlock_t lock;
+ bool active;
};
union sub_crq {
--
2.7.5
^ permalink raw reply related
* [PATCH net-next 1/8] ibmvnic: Mark NAPI flag as disabled when released
From: Thomas Falcon @ 2018-05-23 18:37 UTC (permalink / raw)
To: netdev; +Cc: nfont, jallen, linuxppc-dev, Thomas Falcon
In-Reply-To: <1527100682-23099-1-git-send-email-tlfalcon@linux.vnet.ibm.com>
Set adapter NAPI state as disabled if they are removed. This will allow
them to be enabled again if reallocated in case of a hard reset.
Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
---
drivers/net/ethernet/ibm/ibmvnic.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 4bb4646..eabc1e4 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -789,6 +789,7 @@ static void release_napi(struct ibmvnic_adapter *adapter)
kfree(adapter->napi);
adapter->napi = NULL;
adapter->num_active_rx_napi = 0;
+ adapter->napi_enabled = false;
}
static int ibmvnic_login(struct net_device *netdev)
--
2.7.5
^ permalink raw reply related
* [PATCH net-next 0/8] ibmvnic: Failover hardening
From: Thomas Falcon @ 2018-05-23 18:37 UTC (permalink / raw)
To: netdev; +Cc: nfont, jallen, linuxppc-dev, Thomas Falcon
Introduce additional transport event hardening to handle
events during device reset. In the driver's current state,
if a transport event is received during device reset, it can
cause the device to become unresponsive as invalid operations
are processed as the backing device context changes. After
a transport event, the device expects a request to begin the
initialization process. If the driver is still processing
a previously queued device reset in this state, it is likely
to fail as firmware will reject any commands other than the
one to initialize the client driver's Command-Response Queue.
Instead of failing and becoming dormant, the driver will make
one more attempt to recover and continue operation. This is
achieved by setting a state flag, which if true will direct
the driver to clean up all allocated resources and perform
a hard reset in an attempt to bring the driver back to an
operational state.
Thomas Falcon (8):
ibmvnic: Mark NAPI flag as disabled when released
ibmvnic: Introduce active CRQ state
ibmvnic: Check CRQ command return codes
ibmvnic: Return error code if init interrupted by transport event
ibmvnic: Handle error case when setting link state
ibmvnic: Create separate initialization routine for resets
ibmvnic: Set resetting state at earliest possible point
ibmvnic: Introduce hard reset recovery
drivers/net/ethernet/ibm/ibmvnic.c | 223 +++++++++++++++++++++++++++++++++----
drivers/net/ethernet/ibm/ibmvnic.h | 2 +
2 files changed, 202 insertions(+), 23 deletions(-)
--
2.7.5
^ permalink raw reply
* Re: [PATCH net-next v2 0/2] udp gso fixes
From: David Miller @ 2018-05-23 18:49 UTC (permalink / raw)
To: willemdebruijn.kernel; +Cc: netdev, willemb
In-Reply-To: <20180522153440.204128-1-willemdebruijn.kernel@gmail.com>
From: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Date: Tue, 22 May 2018 11:34:38 -0400
> From: Willem de Bruijn <willemb@google.com>
>
> A few small fixes:
> - disallow segmentation with XFRM
> - do not leak gso packets into the ingress path
>
> Changes
> v1 -> v2
> - fix build failure in team.c
> - drop scatter-gather fix:
> this is now fixed by commit 113f99c33585 ("net: test tailroom
> before appending to linear skb"). After this patch gso skbs are
> built non-linear regardless of NETIF_F_SG and skb_segment builds
> linear segs.
Series applied, thanks.
^ permalink raw reply
* Re: pull-request: wireless-drivers 2018-05-22
From: David Miller @ 2018-05-23 18:46 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <87603fg3yc.fsf@kamboji.qca.qualcomm.com>
From: Kalle Valo <kvalo@codeaurora.org>
Date: Tue, 22 May 2018 17:28:11 +0300
> here's a pull request to net tree for 4.17. Please let me know if you
> have any problems.
Pulled, thanks Kalle.
^ permalink raw reply
* Re: [PATCH net-next v15 4/7] sch_cake: Add NAT awareness to packet classifier
From: David Miller @ 2018-05-23 18:44 UTC (permalink / raw)
To: toke; +Cc: netdev, cake, netfilter-devel
In-Reply-To: <152699745846.21931.4558451708304709296.stgit@alrua-kau>
From: Toke Høiland-Jørgensen <toke@toke.dk>
Date: Tue, 22 May 2018 15:57:38 +0200
> When CAKE is deployed on a gateway that also performs NAT (which is a
> common deployment mode), the host fairness mechanism cannot distinguish
> internal hosts from each other, and so fails to work correctly.
>
> To fix this, we add an optional NAT awareness mode, which will query the
> kernel conntrack mechanism to obtain the pre-NAT addresses for each packet
> and use that in the flow and host hashing.
>
> When the shaper is enabled and the host is already performing NAT, the cost
> of this lookup is negligible. However, in unlimited mode with no NAT being
> performed, there is a significant CPU cost at higher bandwidths. For this
> reason, the feature is turned off by default.
>
> Cc: netfilter-devel@vger.kernel.org
> Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
This is really pushing the limits of what a packet scheduler can
require for correct operation. And this creates an incredibly
ugly dependency.
I'd much rather you do something NAT method agnostic, like save
or compute the necessary information on ingress and then later
use it on egress.
Because what you have here will completely break when someone does NAT
using eBPF, act_nat, or similar.
There is even skb->rxhash, be creative :-)
^ permalink raw reply
* [PATCH 17/18] netfilter: nfnetlink_queue: resolve clash for unconfirmed conntracks
From: Pablo Neira Ayuso @ 2018-05-23 18:42 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <20180523184254.22599-1-pablo@netfilter.org>
In nfqueue, two consecutive skbuffs may race to create the conntrack
entry. Hence, the one that loses the race gets dropped due to clash in
the insertion into the hashes from the nf_conntrack_confirm() path.
This patch adds a new nf_conntrack_update() function which searches for
possible clashes and resolve them. NAT mangling for the packet losing
race is corrected by using the conntrack information that won race.
In order to avoid direct module dependencies with conntrack and NAT, the
nf_ct_hook and nf_nat_hook structures are used for this purpose.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/linux/netfilter.h | 5 +++
net/netfilter/nf_conntrack_core.c | 77 +++++++++++++++++++++++++++++++++++++++
net/netfilter/nf_nat_core.c | 41 +++++++++++++--------
net/netfilter/nfnetlink_queue.c | 28 ++++++++++++--
4 files changed, 132 insertions(+), 19 deletions(-)
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index e8d09dc028f6..04551af2ff23 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -324,11 +324,15 @@ int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry);
struct nf_conn;
enum nf_nat_manip_type;
struct nlattr;
+enum ip_conntrack_dir;
struct nf_nat_hook {
int (*parse_nat_setup)(struct nf_conn *ct, enum nf_nat_manip_type manip,
const struct nlattr *attr);
void (*decode_session)(struct sk_buff *skb, struct flowi *fl);
+ unsigned int (*manip_pkt)(struct sk_buff *skb, struct nf_conn *ct,
+ enum nf_nat_manip_type mtype,
+ enum ip_conntrack_dir dir);
};
extern struct nf_nat_hook __rcu *nf_nat_hook;
@@ -392,6 +396,7 @@ struct nf_conn;
enum ip_conntrack_info;
struct nf_ct_hook {
+ int (*update)(struct net *net, struct sk_buff *skb);
void (*destroy)(struct nf_conntrack *);
};
extern struct nf_ct_hook __rcu *nf_ct_hook;
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 8d109d750073..3465da2a98bd 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1607,6 +1607,82 @@ static void nf_conntrack_attach(struct sk_buff *nskb, const struct sk_buff *skb)
nf_conntrack_get(skb_nfct(nskb));
}
+static int nf_conntrack_update(struct net *net, struct sk_buff *skb)
+{
+ const struct nf_conntrack_l3proto *l3proto;
+ const struct nf_conntrack_l4proto *l4proto;
+ struct nf_conntrack_tuple_hash *h;
+ struct nf_conntrack_tuple tuple;
+ enum ip_conntrack_info ctinfo;
+ struct nf_nat_hook *nat_hook;
+ unsigned int dataoff, status;
+ struct nf_conn *ct;
+ u16 l3num;
+ u8 l4num;
+
+ ct = nf_ct_get(skb, &ctinfo);
+ if (!ct || nf_ct_is_confirmed(ct))
+ return 0;
+
+ l3num = nf_ct_l3num(ct);
+ l3proto = nf_ct_l3proto_find_get(l3num);
+
+ if (l3proto->get_l4proto(skb, skb_network_offset(skb), &dataoff,
+ &l4num) <= 0)
+ return -1;
+
+ l4proto = nf_ct_l4proto_find_get(l3num, l4num);
+
+ if (!nf_ct_get_tuple(skb, skb_network_offset(skb), dataoff, l3num,
+ l4num, net, &tuple, l3proto, l4proto))
+ return -1;
+
+ if (ct->status & IPS_SRC_NAT) {
+ memcpy(tuple.src.u3.all,
+ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.all,
+ sizeof(tuple.src.u3.all));
+ tuple.src.u.all =
+ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all;
+ }
+
+ if (ct->status & IPS_DST_NAT) {
+ memcpy(tuple.dst.u3.all,
+ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.all,
+ sizeof(tuple.dst.u3.all));
+ tuple.dst.u.all =
+ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.all;
+ }
+
+ h = nf_conntrack_find_get(net, nf_ct_zone(ct), &tuple);
+ if (!h)
+ return 0;
+
+ /* Store status bits of the conntrack that is clashing to re-do NAT
+ * mangling according to what it has been done already to this packet.
+ */
+ status = ct->status;
+
+ nf_ct_put(ct);
+ ct = nf_ct_tuplehash_to_ctrack(h);
+ nf_ct_set(skb, ct, ctinfo);
+
+ nat_hook = rcu_dereference(nf_nat_hook);
+ if (!nat_hook)
+ return 0;
+
+ if (status & IPS_SRC_NAT &&
+ nat_hook->manip_pkt(skb, ct, NF_NAT_MANIP_SRC,
+ IP_CT_DIR_ORIGINAL) == NF_DROP)
+ return -1;
+
+ if (status & IPS_DST_NAT &&
+ nat_hook->manip_pkt(skb, ct, NF_NAT_MANIP_DST,
+ IP_CT_DIR_ORIGINAL) == NF_DROP)
+ return -1;
+
+ return 0;
+}
+
/* Bring out ya dead! */
static struct nf_conn *
get_next_corpse(int (*iter)(struct nf_conn *i, void *data),
@@ -2126,6 +2202,7 @@ int nf_conntrack_init_start(void)
}
static struct nf_ct_hook nf_conntrack_hook = {
+ .update = nf_conntrack_update,
.destroy = destroy_conntrack,
};
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index f4d264676cfe..821f8d835f7a 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -493,17 +493,36 @@ nf_nat_alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
}
EXPORT_SYMBOL_GPL(nf_nat_alloc_null_binding);
+static unsigned int nf_nat_manip_pkt(struct sk_buff *skb, struct nf_conn *ct,
+ enum nf_nat_manip_type mtype,
+ enum ip_conntrack_dir dir)
+{
+ const struct nf_nat_l3proto *l3proto;
+ const struct nf_nat_l4proto *l4proto;
+ struct nf_conntrack_tuple target;
+
+ /* We are aiming to look like inverse of other direction. */
+ nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
+
+ l3proto = __nf_nat_l3proto_find(target.src.l3num);
+ l4proto = __nf_nat_l4proto_find(target.src.l3num,
+ target.dst.protonum);
+ if (!l3proto->manip_pkt(skb, 0, l4proto, &target, mtype))
+ return NF_DROP;
+
+ return NF_ACCEPT;
+}
+
/* Do packet manipulations according to nf_nat_setup_info. */
unsigned int nf_nat_packet(struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int hooknum,
struct sk_buff *skb)
{
- const struct nf_nat_l3proto *l3proto;
- const struct nf_nat_l4proto *l4proto;
+ enum nf_nat_manip_type mtype = HOOK2MANIP(hooknum);
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+ unsigned int verdict = NF_ACCEPT;
unsigned long statusbit;
- enum nf_nat_manip_type mtype = HOOK2MANIP(hooknum);
if (mtype == NF_NAT_MANIP_SRC)
statusbit = IPS_SRC_NAT;
@@ -515,19 +534,10 @@ unsigned int nf_nat_packet(struct nf_conn *ct,
statusbit ^= IPS_NAT_MASK;
/* Non-atomic: these bits don't change. */
- if (ct->status & statusbit) {
- struct nf_conntrack_tuple target;
-
- /* We are aiming to look like inverse of other direction. */
- nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
+ if (ct->status & statusbit)
+ verdict = nf_nat_manip_pkt(skb, ct, mtype, dir);
- l3proto = __nf_nat_l3proto_find(target.src.l3num);
- l4proto = __nf_nat_l4proto_find(target.src.l3num,
- target.dst.protonum);
- if (!l3proto->manip_pkt(skb, 0, l4proto, &target, mtype))
- return NF_DROP;
- }
- return NF_ACCEPT;
+ return verdict;
}
EXPORT_SYMBOL_GPL(nf_nat_packet);
@@ -1031,6 +1041,7 @@ struct nf_nat_hook nat_hook = {
#ifdef CONFIG_XFRM
.decode_session = __nf_nat_decode_session,
#endif
+ .manip_pkt = nf_nat_manip_pkt,
};
static int __init nf_nat_init(void)
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 74a04638ef03..2c173042ac0e 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -227,6 +227,25 @@ find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id)
return entry;
}
+static void nfqnl_reinject(struct nf_queue_entry *entry, unsigned int verdict)
+{
+ struct nf_ct_hook *ct_hook;
+ int err;
+
+ if (verdict == NF_ACCEPT ||
+ verdict == NF_STOP) {
+ rcu_read_lock();
+ ct_hook = rcu_dereference(nf_ct_hook);
+ if (ct_hook) {
+ err = ct_hook->update(entry->state.net, entry->skb);
+ if (err < 0)
+ verdict = NF_DROP;
+ }
+ rcu_read_unlock();
+ }
+ nf_reinject(entry, verdict);
+}
+
static void
nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data)
{
@@ -237,7 +256,7 @@ nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data)
if (!cmpfn || cmpfn(entry, data)) {
list_del(&entry->list);
queue->queue_total--;
- nf_reinject(entry, NF_DROP);
+ nfqnl_reinject(entry, NF_DROP);
}
}
spin_unlock_bh(&queue->lock);
@@ -686,7 +705,7 @@ __nfqnl_enqueue_packet(struct net *net, struct nfqnl_instance *queue,
err_out_unlock:
spin_unlock_bh(&queue->lock);
if (failopen)
- nf_reinject(entry, NF_ACCEPT);
+ nfqnl_reinject(entry, NF_ACCEPT);
err_out:
return err;
}
@@ -1085,7 +1104,8 @@ static int nfqnl_recv_verdict_batch(struct net *net, struct sock *ctnl,
list_for_each_entry_safe(entry, tmp, &batch_list, list) {
if (nfqa[NFQA_MARK])
entry->skb->mark = ntohl(nla_get_be32(nfqa[NFQA_MARK]));
- nf_reinject(entry, verdict);
+
+ nfqnl_reinject(entry, verdict);
}
return 0;
}
@@ -1208,7 +1228,7 @@ static int nfqnl_recv_verdict(struct net *net, struct sock *ctnl,
if (nfqa[NFQA_MARK])
entry->skb->mark = ntohl(nla_get_be32(nfqa[NFQA_MARK]));
- nf_reinject(entry, verdict);
+ nfqnl_reinject(entry, verdict);
return 0;
}
--
2.11.0
^ permalink raw reply related
* [PATCH 18/18] netfilter: nf_tables: remove nft_af_info.
From: Pablo Neira Ayuso @ 2018-05-23 18:42 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <20180523184254.22599-1-pablo@netfilter.org>
From: Taehee Yoo <ap420073@gmail.com>
The struct nft_af_info was removed.
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netns/nftables.h | 2 --
1 file changed, 2 deletions(-)
diff --git a/include/net/netns/nftables.h b/include/net/netns/nftables.h
index 48134353411d..29c3851b486a 100644
--- a/include/net/netns/nftables.h
+++ b/include/net/netns/nftables.h
@@ -4,8 +4,6 @@
#include <linux/list.h>
-struct nft_af_info;
-
struct netns_nftables {
struct list_head tables;
struct list_head commit_list;
--
2.11.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox