* [PATCH net-next v2 01/11] net: dsa: PHY device is mandatory for EEE
From: Vivien Didelot @ 2017-08-01 20:32 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, John Crispin, Vivien Didelot
In-Reply-To: <20170801203241.22294-1-vivien.didelot@savoirfairelinux.com>
The port's PHY and MAC are both implied in EEE. The current code does
not call the PHY operations if the related device is NULL. Change that
by returning -ENODEV if there's no PHY device attached to the interface.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
net/dsa/slave.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 9507bd38cf04..7df55d597740 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -648,6 +648,10 @@ static int dsa_slave_set_eee(struct net_device *dev, struct ethtool_eee *e)
struct dsa_switch *ds = p->dp->ds;
int ret;
+ /* Port's PHY and MAC both need to be EEE capable */
+ if (!p->phy)
+ return -ENODEV;
+
if (!ds->ops->set_eee)
return -EOPNOTSUPP;
@@ -655,10 +659,7 @@ static int dsa_slave_set_eee(struct net_device *dev, struct ethtool_eee *e)
if (ret)
return ret;
- if (p->phy)
- ret = phy_ethtool_set_eee(p->phy, e);
-
- return ret;
+ return phy_ethtool_set_eee(p->phy, e);
}
static int dsa_slave_get_eee(struct net_device *dev, struct ethtool_eee *e)
@@ -667,6 +668,10 @@ static int dsa_slave_get_eee(struct net_device *dev, struct ethtool_eee *e)
struct dsa_switch *ds = p->dp->ds;
int ret;
+ /* Port's PHY and MAC both need to be EEE capable */
+ if (!p->phy)
+ return -ENODEV;
+
if (!ds->ops->get_eee)
return -EOPNOTSUPP;
@@ -674,10 +679,7 @@ static int dsa_slave_get_eee(struct net_device *dev, struct ethtool_eee *e)
if (ret)
return ret;
- if (p->phy)
- ret = phy_ethtool_get_eee(p->phy, e);
-
- return ret;
+ return phy_ethtool_get_eee(p->phy, e);
}
#ifdef CONFIG_NET_POLL_CONTROLLER
--
2.13.3
^ permalink raw reply related
* [PATCH net] tcp: avoid setting cwnd to invalid ssthresh after cwnd reduction states
From: Yuchung Cheng @ 2017-08-01 20:22 UTC (permalink / raw)
To: davem; +Cc: netdev, ncardwell, edumazet, Yuchung Cheng
If the sender switches the congestion control during ECN-triggered
cwnd-reduction state (CA_CWR), upon exiting recovery cwnd is set to
the ssthresh value calculated by the previous congestion control. If
the previous congestion control is BBR that always keep ssthresh
to TCP_INIFINITE_SSTHRESH, cwnd ends up being infinite. The safe
step is to avoid assigning invalid ssthresh value when recovery ends.
Signed-off-by: Yuchung Cheng <ycheng@google.com>
Signed-off-by: Neal Cardwell <ncardwell@google.com>
---
net/ipv4/tcp_input.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 2920e0cb09f8..dad026fcfd09 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2520,8 +2520,8 @@ static inline void tcp_end_cwnd_reduction(struct sock *sk)
return;
/* Reset cwnd to ssthresh in CWR or Recovery (unless it's undone) */
- if (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR ||
- (tp->undo_marker && tp->snd_ssthresh < TCP_INFINITE_SSTHRESH)) {
+ if (tp->snd_ssthresh < TCP_INFINITE_SSTHRESH &&
+ (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR || tp->undo_marker)) {
tp->snd_cwnd = tp->snd_ssthresh;
tp->snd_cwnd_stamp = tcp_jiffies32;
}
--
2.14.0.rc1.383.gd1ce394fe2-goog
^ permalink raw reply related
* (unknown),
From: stef.ryckmans @ 2017-08-01 20:18 UTC (permalink / raw)
To: netdev
[-- Attachment #1: EMAIL_005677859264_netdev.zip --]
[-- Type: application/zip, Size: 2832 bytes --]
^ permalink raw reply
* [Patch net-next] flow_dissector: remove unused functions
From: Cong Wang @ 2017-08-01 20:18 UTC (permalink / raw)
To: netdev; +Cc: tom, Cong Wang
They are introduced by commit f70ea018da06
("net: Add functions to get skb->hash based on flow structures")
but never gets used in tree.
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
include/linux/skbuff.h | 16 ----------------
net/core/flow_dissector.c | 45 ---------------------------------------------
2 files changed, 61 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 4093552be1de..7090519c72dd 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1122,8 +1122,6 @@ static inline __u32 skb_get_hash(struct sk_buff *skb)
return skb->hash;
}
-__u32 __skb_get_hash_flowi6(struct sk_buff *skb, const struct flowi6 *fl6);
-
static inline __u32 skb_get_hash_flowi6(struct sk_buff *skb, const struct flowi6 *fl6)
{
if (!skb->l4_hash && !skb->sw_hash) {
@@ -1136,20 +1134,6 @@ static inline __u32 skb_get_hash_flowi6(struct sk_buff *skb, const struct flowi6
return skb->hash;
}
-__u32 __skb_get_hash_flowi4(struct sk_buff *skb, const struct flowi4 *fl);
-
-static inline __u32 skb_get_hash_flowi4(struct sk_buff *skb, const struct flowi4 *fl4)
-{
- if (!skb->l4_hash && !skb->sw_hash) {
- struct flow_keys keys;
- __u32 hash = __get_hash_from_flowi4(fl4, &keys);
-
- __skb_set_sw_hash(skb, hash, flow_keys_have_l4(&keys));
- }
-
- return skb->hash;
-}
-
__u32 skb_get_hash_perturb(const struct sk_buff *skb, u32 perturb);
static inline __u32 skb_get_hash_raw(const struct sk_buff *skb)
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index fc5fc4594c90..0cc672aba1f0 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -998,51 +998,6 @@ __u32 skb_get_hash_perturb(const struct sk_buff *skb, u32 perturb)
}
EXPORT_SYMBOL(skb_get_hash_perturb);
-__u32 __skb_get_hash_flowi6(struct sk_buff *skb, const struct flowi6 *fl6)
-{
- struct flow_keys keys;
-
- memset(&keys, 0, sizeof(keys));
-
- memcpy(&keys.addrs.v6addrs.src, &fl6->saddr,
- sizeof(keys.addrs.v6addrs.src));
- memcpy(&keys.addrs.v6addrs.dst, &fl6->daddr,
- sizeof(keys.addrs.v6addrs.dst));
- keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
- keys.ports.src = fl6->fl6_sport;
- keys.ports.dst = fl6->fl6_dport;
- keys.keyid.keyid = fl6->fl6_gre_key;
- keys.tags.flow_label = (__force u32)fl6->flowlabel;
- keys.basic.ip_proto = fl6->flowi6_proto;
-
- __skb_set_sw_hash(skb, flow_hash_from_keys(&keys),
- flow_keys_have_l4(&keys));
-
- return skb->hash;
-}
-EXPORT_SYMBOL(__skb_get_hash_flowi6);
-
-__u32 __skb_get_hash_flowi4(struct sk_buff *skb, const struct flowi4 *fl4)
-{
- struct flow_keys keys;
-
- memset(&keys, 0, sizeof(keys));
-
- keys.addrs.v4addrs.src = fl4->saddr;
- keys.addrs.v4addrs.dst = fl4->daddr;
- keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
- keys.ports.src = fl4->fl4_sport;
- keys.ports.dst = fl4->fl4_dport;
- keys.keyid.keyid = fl4->fl4_gre_key;
- keys.basic.ip_proto = fl4->flowi4_proto;
-
- __skb_set_sw_hash(skb, flow_hash_from_keys(&keys),
- flow_keys_have_l4(&keys));
-
- return skb->hash;
-}
-EXPORT_SYMBOL(__skb_get_hash_flowi4);
-
u32 __skb_get_poff(const struct sk_buff *skb, void *data,
const struct flow_keys *keys, int hlen)
{
--
2.13.0
^ permalink raw reply related
* Re: [PATCH net-next 10/11] net: dsa: mv88e6xxx: remove EEE support
From: Vivien Didelot @ 2017-08-01 20:08 UTC (permalink / raw)
To: Andrew Lunn
Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli
In-Reply-To: <87h8xrfdrp.fsf@weeman.i-did-not-set--mail-host-address--so-tickle-me>
Vivien Didelot <vivien.didelot@savoirfairelinux.com> writes:
> Second option is: we keep it KISS and let the driver define its noop,
> but as I explain, it is confusing, especially for the get operation.
In fact we should be good because the DSA layer will call
ds->ops->{g,s}et_mac_eee before phy_ethtool_{g,s}et_eee, so if the DSA
driver didn't touch the ethtool_eee structure, the PHY ops will anyway.
I'm sending a v2 right away.
Thanks,
Vivien
^ permalink raw reply
* [PATCH net] ibmvnic: Initialize SCRQ's during login renegotiation
From: Thomas Falcon @ 2017-08-01 20:04 UTC (permalink / raw)
To: netdev; +Cc: Thomas Falcon
SCRQ resources are freed during renegotiation, but they are not
re-allocated afterwards due to some changes in the initialization
process. Fix that by re-allocating the memory after renegotation.
SCRQ's can also be freed if a server capabilities request fails.
If this were encountered during a device reset for example,
SCRQ's may not be re-allocated. This operation is not necessary
anymore so remove it.
Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
---
drivers/net/ethernet/ibm/ibmvnic.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index a3e6946..c45e8e3 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -111,6 +111,7 @@ static void send_request_map(struct ibmvnic_adapter *, dma_addr_t, __be32, u8);
static void send_request_unmap(struct ibmvnic_adapter *, u8);
static void send_login(struct ibmvnic_adapter *adapter);
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 void release_crq_queue(struct ibmvnic_adapter *);
@@ -651,6 +652,7 @@ static int ibmvnic_login(struct net_device *netdev)
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
unsigned long timeout = msecs_to_jiffies(30000);
struct device *dev = &adapter->vdev->dev;
+ int rc;
do {
if (adapter->renegotiate) {
@@ -664,6 +666,18 @@ static int ibmvnic_login(struct net_device *netdev)
dev_err(dev, "Capabilities query timeout\n");
return -1;
}
+ rc = init_sub_crqs(adapter);
+ if (rc) {
+ dev_err(dev,
+ "Initialization of SCRQ's failed\n");
+ return -1;
+ }
+ rc = init_sub_crq_irqs(adapter);
+ if (rc) {
+ dev_err(dev,
+ "Initialization of SCRQ's irqs failed\n");
+ return -1;
+ }
}
reinit_completion(&adapter->init_done);
@@ -3004,7 +3018,6 @@ static void handle_request_cap_rsp(union ibmvnic_crq *crq,
*req_value,
(long int)be64_to_cpu(crq->request_capability_rsp.
number), name);
- release_sub_crqs(adapter);
*req_value = be64_to_cpu(crq->request_capability_rsp.number);
ibmvnic_send_req_caps(adapter, 1);
return;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH net 4/7] nfp: Initialize RX and TX ring 64-bit stats seqcounts
From: Simon Horman @ 2017-08-01 20:04 UTC (permalink / raw)
To: Florian Fainelli
Cc: netdev, davem, edumazet, Jakub Kicinski, Daniel Borkmann,
open list:NETRONOME ETHERNET DRIVERS, open list
In-Reply-To: <20170801191113.8754-5-f.fainelli@gmail.com>
On Tue, Aug 01, 2017 at 12:11:09PM -0700, Florian Fainelli wrote:
> On 32-bit hosts and with CONFIG_DEBUG_LOCK_ALLOC we should be seeing a
> lockdep splat indicating this seqcount is not correctly initialized, fix
> that.
>
> Fixes: 4c3523623dc0 ("net: add driver for Netronome NFP4000/NFP6000 NIC VFs")
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
FYI, Jakub is on leave this week.
^ permalink raw reply
* Re: [Intel-wired-lan] [PATCH 6/6] [net-next]net: i40e: Enable cloud filters in i40e via tc/flower classifier
From: Shannon Nelson @ 2017-08-01 19:16 UTC (permalink / raw)
To: Amritha Nambiar, intel-wired-lan, jeffrey.t.kirsher
Cc: netdev, mitch.a.williams
In-Reply-To: <150154788503.4135.7051219373661945937.stgit@anamdev.jf.intel.com>
On 7/31/2017 5:38 PM, Amritha Nambiar wrote:
> This patch enables tc-flower based hardware offloads. tc/flower
> filter provided by the kernel is configured as driver specific
> cloud filter. The patch implements functions and admin queue
> commands needed to support cloud filters in the driver and
> adds cloud filters to configure these tc-flower filters.
>
> The only action supported is to redirect packets to a traffic class
> on the same device.
>
> # tc qdisc add dev eth0 ingress
> # ethtool -K eth0 hw-tc-offload on
>
> # tc filter add dev eth0 protocol ip parent ffff:\
> prio 1 flower dst_mac 3c:fd:fe:a0:d6:70 skip_sw indev eth0\
> action mirred ingress redirect dev eth0 tc 0
>
> # tc filter add dev eth0 protocol ip parent ffff:\
> prio 2 flower dst_ip 192.168.3.5/32\
> ip_proto udp dst_port 25 skip_sw indev eth0\
> action mirred ingress redirect dev eth0 tc 1
>
> # tc filter add dev eth0 protocol ipv6 parent ffff:\
> prio 3 flower dst_ip fe8::200:1\
> ip_proto udp dst_port 66 skip_sw indev eth0\
> action mirred ingress redirect dev eth0 tc 2
>
> Delete tc flower filter:
> Example:
>
> # tc filter del dev eth0 parent ffff: prio 3 handle 0x1 flower
> # tc filter del dev eth0 parent ffff:
>
> Flow Director Sideband is disabled while configuring cloud filters
> via tc-flower.
Only while configuring, or the whole time there is a cloud filter? This
is unclear here.
>
> Unsupported matches when cloud filters are added using enhanced
> big buffer cloud filter mode of underlying switch include:
> 1. source port and source IP
> 2. Combined MAC address and IP fields.
> 3. Not specfying L4 port
s/specfying/specifying/
>
> These filter matches can however be used to redirect traffic to
> the main VSI (tc 0) which does not require the enhanced big buffer
> cloud filter support.
>
> Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
> Signed-off-by: Kiran Patil <kiran.patil@intel.com>
> ---
> drivers/net/ethernet/intel/i40e/i40e.h | 46 +
> drivers/net/ethernet/intel/i40e/i40e_common.c | 180 ++++
> drivers/net/ethernet/intel/i40e/i40e_main.c | 952 ++++++++++++++++++++++
> drivers/net/ethernet/intel/i40e/i40e_prototype.h | 17
> 4 files changed, 1193 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
> index 5c0cad5..7288265 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e.h
> +++ b/drivers/net/ethernet/intel/i40e/i40e.h
> @@ -55,6 +55,8 @@
> #include <linux/net_tstamp.h>
> #include <linux/ptp_clock_kernel.h>
> #include <net/pkt_cls.h>
> +#include <net/tc_act/tc_gact.h>
> +#include <net/tc_act/tc_mirred.h>
> #include "i40e_type.h"
> #include "i40e_prototype.h"
> #include "i40e_client.h"
> @@ -252,10 +254,51 @@ struct i40e_fdir_filter {
> u32 fd_id;
> };
>
> +#define I40E_CLOUD_FIELD_OMAC 0x01
> +#define I40E_CLOUD_FIELD_IMAC 0x02
> +#define I40E_CLOUD_FIELD_IVLAN 0x04
> +#define I40E_CLOUD_FIELD_TEN_ID 0x08
> +#define I40E_CLOUD_FIELD_IIP 0x10
> +
> +#define I40E_CLOUD_FILTER_FLAGS_OMAC I40E_CLOUD_FIELD_OMAC
> +#define I40E_CLOUD_FILTER_FLAGS_IMAC I40E_CLOUD_FIELD_IMAC
> +#define I40E_CLOUD_FILTER_FLAGS_IMAC_IVLAN (I40E_CLOUD_FIELD_IMAC | \
> + I40E_CLOUD_FIELD_IVLAN)
> +#define I40E_CLOUD_FILTER_FLAGS_IMAC_TEN_ID (I40E_CLOUD_FIELD_IMAC | \
> + I40E_CLOUD_FIELD_TEN_ID)
> +#define I40E_CLOUD_FILTER_FLAGS_OMAC_TEN_ID_IMAC (I40E_CLOUD_FIELD_OMAC | \
> + I40E_CLOUD_FIELD_IMAC | \
> + I40E_CLOUD_FIELD_TEN_ID)
> +#define I40E_CLOUD_FILTER_FLAGS_IMAC_IVLAN_TEN_ID (I40E_CLOUD_FIELD_IMAC | \
> + I40E_CLOUD_FIELD_IVLAN | \
> + I40E_CLOUD_FIELD_TEN_ID)
> +#define I40E_CLOUD_FILTER_FLAGS_IIP I40E_CLOUD_FIELD_IIP
> +
> struct i40e_cloud_filter {
> struct hlist_node cloud_node;
> /* cloud filter input set follows */
> unsigned long cookie;
> + u8 dst_mac[ETH_ALEN];
> + u8 src_mac[ETH_ALEN];
> + __be16 vlan_id;
> + __be32 dst_ip[4];
> + __be32 src_ip[4];
> + u8 dst_ipv6[16];
> + u8 src_ipv6[16];
> + __be16 dst_port;
> + __be16 src_port;
> + /* matter only when IP based filtering is set */
> + bool is_ipv6;
> + /* IPPROTO value */
> + u8 ip_proto;
> + /* L4 port type: src or destination port */
> +#define I40E_CLOUD_FILTER_PORT_SRC 0x01
> +#define I40E_CLOUD_FILTER_PORT_DEST 0x02
> + u8 port_type;
> + u32 tenant_id;
> + u8 flags;
> +#define I40E_CLOUD_TNL_TYPE_NONE 0xff
> + u8 tunnel_type;
> /* filter control */
> u16 seid;
> };
> @@ -574,6 +617,9 @@ struct i40e_pf {
> u16 phy_led_val;
>
> u16 override_q_count;
> + u16 last_sw_conf_flags;
> + u16 last_sw_conf_valid_flags;
> +
Unnecessary blank line
> };
>
> /**
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
> index d0e8138..bfbe304 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_common.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
> @@ -5269,5 +5269,185 @@ i40e_add_pinfo_to_list(struct i40e_hw *hw,
>
> status = i40e_aq_write_ppp(hw, (void *)sec, sec->data_end,
> track_id, &offset, &info, NULL);
> +
> + return status;
> +}
> +
> +/**
> + * i40e_aq_add_cloud_filters
> + * @hw: pointer to the hardware structure
> + * @seid: VSI seid to add cloud filters from
> + * @filters: Buffer which contains the filters to be added
> + * @filter_count: number of filters contained in the buffer
> + *
> + * Set the cloud filters for a given VSI. The contents of the
> + * i40e_aqc_add_remove_cloud_filters_element_data are filled
> + * in by the caller of the function.
> + *
> + **/
> +enum i40e_status_code i40e_aq_add_cloud_filters(struct i40e_hw *hw,
> + u16 seid,
> + struct i40e_aqc_add_remove_cloud_filters_element_data *filters,
> + u8 filter_count)
> +{
> + struct i40e_aq_desc desc;
> + struct i40e_aqc_add_remove_cloud_filters *cmd =
> + (struct i40e_aqc_add_remove_cloud_filters *)&desc.params.raw;
> + enum i40e_status_code status;
> + u16 buff_len;
> +
> + i40e_fill_default_direct_cmd_desc(&desc,
> + i40e_aqc_opc_add_cloud_filters);
> +
> + buff_len = filter_count * sizeof(*filters);
> + desc.datalen = cpu_to_le16(buff_len);
> + desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
> + cmd->num_filters = filter_count;
> + cmd->seid = cpu_to_le16(seid);
> +
> + status = i40e_asq_send_command(hw, &desc, filters, buff_len, NULL);
> +
> + return status;
> +}
> +
> +/**
> + * i40e_aq_add_cloud_filters_big_buffer
> + * @hw: pointer to the hardware structure
> + * @seid: VSI seid to add cloud filters from
> + * @filters: Buffer which contains the filters in big buffer to be added
> + * @filter_count: number of filters contained in the buffer
> + *
> + * Set the cloud filters for a given VSI. The contents of the
> + * i40e_aqc_add_remove_cloud_filters_element_big_data are filled
> + * in by the caller of the function.
> + *
> + **/
> +i40e_status i40e_aq_add_cloud_filters_big_buffer(struct i40e_hw *hw,
> + u16 seid,
> + struct i40e_aqc_add_remove_cloud_filters_element_big_data *filters,
> + u8 filter_count)
> +{
> + struct i40e_aq_desc desc;
> + struct i40e_aqc_add_remove_cloud_filters *cmd =
> + (struct i40e_aqc_add_remove_cloud_filters *)&desc.params.raw;
> + i40e_status status;
> + u16 buff_len;
> + int i;
> +
> + i40e_fill_default_direct_cmd_desc(&desc,
> + i40e_aqc_opc_add_cloud_filters);
> +
> + buff_len = filter_count * sizeof(*filters);
> + desc.datalen = cpu_to_le16(buff_len);
> + desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
> + cmd->num_filters = filter_count;
> + cmd->seid = cpu_to_le16(seid);
> + cmd->big_buffer_flag = I40E_AQC_ADD_REM_CLOUD_CMD_BIG_BUFFER;
> +
> + for (i = 0; i < filter_count; i++) {
> + u16 tnl_type;
> + u32 ti;
> +
> + tnl_type = (le16_to_cpu(filters[i].element.flags) &
> + I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK) >>
> + I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT;
> + if (tnl_type == I40E_AQC_ADD_CLOUD_TNL_TYPE_GENEVE) {
> + ti = le32_to_cpu(filters[i].element.tenant_id);
> + filters[i].element.tenant_id = cpu_to_le32(ti << 8);
> + }
You might want to add a comment to explain this little hack. I believe
this is for a bit of firmware weirdness?
> + }
> +
> + status = i40e_asq_send_command(hw, &desc, filters, buff_len, NULL);
> +
> + return status;
> +}
> +
> +/**
> + * i40e_aq_remove_cloud_filters
> + * @hw: pointer to the hardware structure
> + * @seid: VSI seid to remove cloud filters from
> + * @filters: Buffer which contains the filters to be removed
> + * @filter_count: number of filters contained in the buffer
> + *
> + * Remove the cloud filters for a given VSI. The contents of the
> + * i40e_aqc_add_remove_cloud_filters_element_data are filled
> + * in by the caller of the function.
> + *
> + **/
> +enum i40e_status_code i40e_aq_remove_cloud_filters(struct i40e_hw *hw,
> + u16 seid,
> + struct i40e_aqc_add_remove_cloud_filters_element_data *filters,
> + u8 filter_count)
> +{
> + struct i40e_aq_desc desc;
> + struct i40e_aqc_add_remove_cloud_filters *cmd =
> + (struct i40e_aqc_add_remove_cloud_filters *)&desc.params.raw;
> + enum i40e_status_code status;
> + u16 buff_len;
> +
> + i40e_fill_default_direct_cmd_desc(&desc,
> + i40e_aqc_opc_remove_cloud_filters);
> +
> + buff_len = filter_count * sizeof(*filters);
> + desc.datalen = cpu_to_le16(buff_len);
> + desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
> + cmd->num_filters = filter_count;
> + cmd->seid = cpu_to_le16(seid);
> +
> + status = i40e_asq_send_command(hw, &desc, filters, buff_len, NULL);
> +
> + return status;
> +}
> +
> +/**
> + * i40e_aq_remove_cloud_filters_big_buffer
> + * @hw: pointer to the hardware structure
> + * @seid: VSI seid to remove cloud filters from
> + * @filters: Buffer which contains the filters in big buffer to be removed
> + * @filter_count: number of filters contained in the buffer
> + *
> + * Remove the cloud filters for a given VSI. The contents of the
> + * i40e_aqc_add_remove_cloud_filters_element_big_data are filled
> + * in by the caller of the function.
> + *
> + **/
> +i40e_status i40e_aq_remove_cloud_filters_big_buffer(
> + struct i40e_hw *hw,
> + u16 seid,
> + struct i40e_aqc_add_remove_cloud_filters_element_big_data *filters,
> + u8 filter_count)
> +{
> + struct i40e_aq_desc desc;
> + struct i40e_aqc_add_remove_cloud_filters *cmd =
> + (struct i40e_aqc_add_remove_cloud_filters *)&desc.params.raw;
> + i40e_status status;
> + u16 buff_len;
> + int i;
> +
> + i40e_fill_default_direct_cmd_desc(&desc,
> + i40e_aqc_opc_remove_cloud_filters);
> +
> + buff_len = filter_count * sizeof(*filters);
> + desc.datalen = cpu_to_le16(buff_len);
> + desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
> + cmd->num_filters = filter_count;
> + cmd->seid = cpu_to_le16(seid);
> + cmd->big_buffer_flag = I40E_AQC_ADD_REM_CLOUD_CMD_BIG_BUFFER;
> +
> + for (i = 0; i < filter_count; i++) {
> + u16 tnl_type;
> + u32 ti;
> +
> + tnl_type = (le16_to_cpu(filters[i].element.flags) &
> + I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK) >>
> + I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT;
> + if (tnl_type == I40E_AQC_ADD_CLOUD_TNL_TYPE_GENEVE) {
> + ti = le32_to_cpu(filters[i].element.tenant_id);
> + filters[i].element.tenant_id = cpu_to_le32(ti << 8);
> + }
Same comment
> + }
> +
> + status = i40e_asq_send_command(hw, &desc, filters, buff_len, NULL);
> +
> return status;
> }
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
> index 93f6fe2..65b284e 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
> @@ -69,6 +69,12 @@ static int i40e_reset(struct i40e_pf *pf);
> static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired);
> static void i40e_fdir_sb_setup(struct i40e_pf *pf);
> static int i40e_veb_get_bw_info(struct i40e_veb *veb);
> +static int i40e_add_del_cloud_filter(struct i40e_vsi *vsi,
> + struct i40e_cloud_filter *filter,
> + bool add);
> +static int i40e_add_del_cloud_filter_big_buf(struct i40e_vsi *vsi,
> + struct i40e_cloud_filter *filter,
> + bool add);
>
> /* i40e_pci_tbl - PCI Device ID Table
> *
> @@ -5482,7 +5488,11 @@ int i40e_set_bw_limit(struct i40e_vsi *vsi, u16 seid, u64 max_tx_rate)
> **/
> static void i40e_remove_queue_channels(struct i40e_vsi *vsi)
Hmmm... I'm looking at net-next code and I don't see this function, or
anything else with "i40e_channel" or "queue_channel". What are you
applying this patch to? Am I missing something?
> {
> + enum i40e_admin_queue_err last_aq_status;
> + struct i40e_cloud_filter *cfilter;
> struct i40e_channel *ch, *ch_tmp;
> + struct i40e_pf *pf = vsi->back;
> + struct hlist_node *node;
> int ret, i;
>
> /* Reset rss size that was stored when reconfiguring rss for
> @@ -5523,6 +5533,29 @@ static void i40e_remove_queue_channels(struct i40e_vsi *vsi)
> "Failed to reset tx rate for ch->seid %u\n",
> ch->seid);
>
> + /* delete cloud filters associated with this channel */
> + hlist_for_each_entry_safe(cfilter, node,
> + &pf->cloud_filter_list, cloud_node) {
> + if (cfilter->seid != ch->seid)
> + continue;
> +
> + hash_del(&cfilter->cloud_node);
> + if (cfilter->dst_port)
> + ret = i40e_add_del_cloud_filter_big_buf(vsi,
> + cfilter,
> + false);
> + else
> + ret = i40e_add_del_cloud_filter(vsi, cfilter,
> + false);
> + last_aq_status = pf->hw.aq.asq_last_status;
> + if (ret)
> + dev_info(&pf->pdev->dev,
> + "fail to delete cloud filter, err %s aq_err %s\n",
> + i40e_stat_str(&pf->hw, ret),
> + i40e_aq_str(&pf->hw, last_aq_status));
> + kfree(cfilter);
> + }
> +
> /* delete VSI from FW */
> ret = i40e_aq_delete_element(&vsi->back->hw, ch->seid,
> NULL);
> @@ -6004,6 +6037,131 @@ static bool i40e_setup_channel(struct i40e_pf *pf, struct i40e_vsi *vsi,
> }
>
> /**
> + * i40e_get_device_capabilities - get device level info about the HW
> + * @pf: the PF struct
> + **/
> +static int i40e_get_device_capabilities(struct i40e_pf *pf)
Since this is almost exactly the same as the original
i40e_get_capabilities(), it would be better to simply add list_type_opc
to i40e_get_capabilities() parameter list
> +{
> + struct i40e_aqc_list_capabilities_element_resp *cap_buf;
> + u16 data_size;
> + int buf_len;
> + int err;
> +
> + buf_len = 40 * sizeof(struct i40e_aqc_list_capabilities_element_resp);
> +
> + /* proceed with query device level capabilities */
> + do {
> + cap_buf = kzalloc(buf_len, GFP_KERNEL);
> + if (!cap_buf)
> + return -ENOMEM;
> +
> + /* this loads the data into the hw struct for us */
> + err = i40e_aq_discover_capabilities(&pf->hw, cap_buf, buf_len,
> + &data_size,
> + i40e_aqc_opc_list_dev_capabilities,
> + NULL);
> + /* data loaded, buffer no longer needed */
> + kfree(cap_buf);
> +
> + if (pf->hw.aq.asq_last_status == I40E_AQ_RC_ENOMEM) {
> + /* retry with a larger buffer */
> + buf_len = data_size;
> + } else if (pf->hw.aq.asq_last_status != I40E_AQ_RC_OK) {
> + dev_dbg(&pf->pdev->dev,
> + "device capability discovery failed, err %s aq_err %s\n",
> + i40e_stat_str(&pf->hw, err),
> + i40e_aq_str(&pf->hw,
> + pf->hw.aq.asq_last_status));
> + return -ENODEV;
> + }
> + } while (err);
> +
> + if (pf->hw.debug_mask & I40E_DEBUG_USER) {
> + dev_info(&pf->pdev->dev,
> + "switch_mode=0x%04x, function_valid=0x%08x\n",
> + pf->hw.dev_caps.switch_mode,
> + pf->hw.dev_caps.valid_functions);
> + dev_info(&pf->pdev->dev,
> + "SR-IOV=%d, num_vfs for all function=%u\n",
> + pf->hw.dev_caps.sr_iov_1_1, pf->hw.dev_caps.num_vfs);
> + dev_info(&pf->pdev->dev,
> + "num_vsis=%u, num_rx:%u, num_tx=%u\n",
> + pf->hw.dev_caps.num_vsis, pf->hw.dev_caps.num_rx_qp,
> + pf->hw.dev_caps.num_tx_qp);
> + }
> + return 0;
> +}
> +
> +/**
> + * i40e_validate_and_set_switch_mode - sets up switch mode correctly
> + * @vsi: ptr to VSI which has PF backing
> + * @l4type: true for TCP ond false for UDP
> + * @port_type: true if port is destination and false if port is source
> + *
> + * Sets up switch mode correctly if it needs to be changed and perform
> + * what are allowed modes.
> + **/
> +static int i40e_validate_and_set_switch_mode(struct i40e_vsi *vsi, bool l4type,
> + bool port_type)
> +{
> + u8 mode;
> + struct i40e_pf *pf = vsi->back;
> + struct i40e_hw *hw = &pf->hw;
> + int ret;
> +
> + ret = i40e_get_device_capabilities(pf);
> + if (ret)
> + return -EINVAL;
> +
> + if (hw->dev_caps.switch_mode) {
> + /* if switch mode is set, support mode2 (non-tunneled for
> + * cloud filter) for now
> + */
> +#define I40E_SWITCH_MODE_MASK 0xF /* largest cloud filter mode is 0x8 */
Why isn't this defined in the appropriate .h file?
> + u32 switch_mode = hw->dev_caps.switch_mode &
> + I40E_SWITCH_MODE_MASK;
> + if (switch_mode >= I40E_NVM_IMAGE_TYPE_MODE1) {
> + if (switch_mode == I40E_NVM_IMAGE_TYPE_MODE2)
> + return 0;
> + dev_err(&pf->pdev->dev,
> + "Invalid switch_mode (%d), only non-tunneled mode for cloud filter is supported\n",
> + hw->dev_caps.switch_mode);
> + return -EINVAL;
> + }
> + }
> +
> + /* port_type: true for destination port and false for source port
> + * For now, supports only destination port type
> + */
> + if (!port_type) {
> + dev_err(&pf->pdev->dev, "src port type not supported\n");
> + return -EINVAL;
> + }
> +
> + /* Set Bit 7 to be valid */
> + mode = I40E_AQ_SET_SWITCH_BIT7_VALID;
> +
> + /* Set L4type to both TCP and UDP support */
> + mode |= I40E_AQ_SET_SWITCH_L4_TYPE_BOTH;
> +
> + /* Set cloud filter mode */
> + mode |= I40E_AQ_SET_SWITCH_MODE_NON_TUNNEL;
> +
> + /* Prep mode field for set_switch_config */
> + ret = i40e_aq_set_switch_config(hw, pf->last_sw_conf_flags,
> + pf->last_sw_conf_valid_flags,
> + mode, NULL);
> + if (ret && hw->aq.asq_last_status != I40E_AQ_RC_ESRCH)
> + dev_err(&pf->pdev->dev,
> + "couldn't set switch config bits, err %s aq_err %s\n",
> + i40e_stat_str(hw, ret),
> + i40e_aq_str(hw,
> + hw->aq.asq_last_status));
> +
> + return ret;
> +}
> +
> +/**
> * i40e_create_queue_channel - function to create channel
> * @vsi: VSI to be configured
> * @ch: ptr to channel (it contains channel specific params)
> @@ -6632,6 +6790,10 @@ static int i40e_setup_tc(struct net_device *netdev, struct tc_to_netdev *tc)
> }
> if (!hw) {
> pf->flags &= ~I40E_FLAG_TC_MQPRIO;
> + if ((pf->hw.func_caps.fd_filters_guaranteed > 0) ||
> + (pf->hw.func_caps.fd_filters_best_effort > 0))
> + pf->flags |= I40E_FLAG_FD_ATR_ENABLED;
> +
> if (tc->type == TC_SETUP_MQPRIO_EXT)
> memcpy(&vsi->mqprio_qopt, tc->mqprio_qopt,
> sizeof(*tc->mqprio_qopt));
> @@ -6682,6 +6844,11 @@ static int i40e_setup_tc(struct net_device *netdev, struct tc_to_netdev *tc)
> sizeof(*tc->mqprio_qopt));
> pf->flags |= I40E_FLAG_TC_MQPRIO;
> pf->flags &= ~I40E_FLAG_DCB_ENABLED;
> + if (pf->flags & I40E_FLAG_FD_ATR_ENABLED) {
> + pf->flags &= ~I40E_FLAG_FD_ATR_ENABLED;
> + dev_info(&pf->pdev->dev,
> + "Disabling ATR in MQPRIO mode\n");
> + }
> break;
> default:
> return -EINVAL;
> @@ -6743,10 +6910,724 @@ static int i40e_setup_tc(struct net_device *netdev, struct tc_to_netdev *tc)
> return ret;
> }
>
> +/**
> + * i40e_set_cld_element - sets cloud filter element data
> + * @filter: cloud filter rule
> + * @cld: ptr to cloud filter element data
> + *
> + * This is helper function to copy data into cloud filter element
> + **/
> +static inline void
> +i40e_set_cld_element(struct i40e_cloud_filter *filter,
> + struct i40e_aqc_add_remove_cloud_filters_element_data *cld)
> +{
> + u8 *dest_ipaddr;
> + u32 ipaddr;
> + int i;
> +
> + memset(cld, 0, sizeof(*cld));
> +
> + ether_addr_copy(cld->outer_mac, filter->dst_mac);
> + ether_addr_copy(cld->inner_mac, filter->src_mac);
> +
> + if (filter->is_ipv6) {
> + dest_ipaddr = (u8 *)&cld->ipaddr.v6.data;
> + for (i = ARRAY_SIZE(filter->dst_ipv6) - 1; i >= 0; i--) {
> + memcpy(dest_ipaddr, &filter->dst_ipv6[i], 1);
> + dest_ipaddr++;
> + }
> + } else {
> + ipaddr = be32_to_cpu(filter->dst_ip[0]);
> + memcpy(&cld->ipaddr.v4.data, &ipaddr, 4);
> + }
> +
> + cld->inner_vlan = cpu_to_le16(ntohs(filter->vlan_id));
> + cld->tenant_id = cpu_to_le32(filter->tenant_id);
> +}
> +
> +/**
> + * i40e_add_del_cloud_filter - Add/del cloud filter
> + * @vsi: pointer to VSI
> + * @filter: cloud filter rule
> + * @add: if true, add, if false, delete
> + *
> + * Add or delete a cloud filter for a specific flow spec.
> + * Returns 0 if the filter were successfully added.
> + **/
> +static int i40e_add_del_cloud_filter(struct i40e_vsi *vsi,
> + struct i40e_cloud_filter *filter, bool add)
> +{
> + struct i40e_aqc_add_remove_cloud_filters_element_data cld_filter;
> + struct i40e_pf *pf = vsi->back;
> + int ret;
> + static const u16 flag_table[128] = {
> + [I40E_CLOUD_FILTER_FLAGS_OMAC] =
> + I40E_AQC_ADD_CLOUD_FILTER_OMAC,
> + [I40E_CLOUD_FILTER_FLAGS_IMAC] =
> + I40E_AQC_ADD_CLOUD_FILTER_IMAC,
> + [I40E_CLOUD_FILTER_FLAGS_IMAC_IVLAN] =
> + I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN,
> + [I40E_CLOUD_FILTER_FLAGS_IMAC_TEN_ID] =
> + I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID,
> + [I40E_CLOUD_FILTER_FLAGS_OMAC_TEN_ID_IMAC] =
> + I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC,
> + [I40E_CLOUD_FILTER_FLAGS_IMAC_IVLAN_TEN_ID] =
> + I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID,
> + [I40E_CLOUD_FILTER_FLAGS_IIP] =
> + I40E_AQC_ADD_CLOUD_FILTER_IIP,
> + };
> +
> + if (filter->flags >= ARRAY_SIZE(flag_table))
> + return I40E_ERR_CONFIG;
> +
> + /* copy element needed to add cloud filter from filter */
> + i40e_set_cld_element(filter, &cld_filter);
> +
> + if (filter->tunnel_type != I40E_CLOUD_TNL_TYPE_NONE)
> + cld_filter.flags = cpu_to_le16(filter->tunnel_type <<
> + I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT);
> +
> + if (filter->is_ipv6)
> + cld_filter.flags |= cpu_to_le16(flag_table[filter->flags] |
> + I40E_AQC_ADD_CLOUD_FLAGS_IPV6);
> + else
> + cld_filter.flags |= cpu_to_le16(flag_table[filter->flags] |
> + I40E_AQC_ADD_CLOUD_FLAGS_IPV4);
> +
> + if (add)
> + ret = i40e_aq_add_cloud_filters(&pf->hw, filter->seid,
> + &cld_filter, 1);
> + else
> + ret = i40e_aq_remove_cloud_filters(&pf->hw, filter->seid,
> + &cld_filter, 1);
> + if (ret)
> + dev_dbg(&pf->pdev->dev,
> + "Failed to %s cloud filter using l4 port %u, err %d aq_err %d\n",
> + add ? "add" : "delete", filter->dst_port, ret,
> + pf->hw.aq.asq_last_status);
> +
> + dev_info(&pf->pdev->dev,
> + "%s cloud filter for VSI: %d\n", add ? "Added" : "Deleted",
> + filter->seid);
If there was an error, this dev_info() is lying to the user.
> + return ret;
> +}
> +
> +/**
> + * i40e_add_del_cloud_filter_big_buf - Add/del cloud filter using big_buf
> + * @vsi: pointer to VSI
> + * @filter: cloud filter rule
> + * @add: if true, add, if false, delete
> + *
> + * Add or delete a cloud filter for a specific flow spec using big buffer.
> + * Returns 0 if the filter were successfully added.
> + **/
> +static int i40e_add_del_cloud_filter_big_buf(struct i40e_vsi *vsi,
> + struct i40e_cloud_filter *filter,
> + bool add)
> +{
> + struct i40e_aqc_add_remove_cloud_filters_element_big_data cld_filter;
> + struct i40e_pf *pf = vsi->back;
> + int ret;
> +
> + /* Both (Outer/Inner) valid mac_addr are not supported */
> + if (is_valid_ether_addr(filter->dst_mac) &&
> + is_valid_ether_addr(filter->src_mac))
> + return -EINVAL;
> +
> + /* Make sure port is specified, otherwise bail out, for channel
> + * specific cloud filter needs 'L4 port' to be non-zero
> + */
> + if (!filter->dst_port)
> + return -EINVAL;
> +
> + /* adding filter using src_port/src_ip is not supported at this stage */
> + if (filter->src_port || filter->src_ip[0])
> + return -EINVAL;
> +
> + /* copy element needed to add cloud filter from filter */
> + i40e_set_cld_element(filter, &cld_filter.element);
> +
> + if (is_valid_ether_addr(filter->dst_mac) ||
> + is_valid_ether_addr(filter->src_mac) ||
> + is_multicast_ether_addr(filter->dst_mac) ||
> + is_multicast_ether_addr(filter->src_mac)) {
> + /* MAC + IP : unsupported mode */
> + if (filter->dst_ip[0])
> + return -EINVAL;
> +
> + /* since we validated that L4 port must be valid before
> + * we get here, start with respective "flags" value
> + * and update if vlan is present or not
> + */
> + cld_filter.element.flags =
> + cpu_to_le16(I40E_AQC_ADD_CLOUD_FILTER_MAC_PORT);
> +
> + if (filter->vlan_id) {
> + cld_filter.element.flags =
> + cpu_to_le16(I40E_AQC_ADD_CLOUD_FILTER_MAC_VLAN_PORT);
> + }
cld_filter.element.flags = cpu_to_le16(filter->vlan_id
? I40E_AQC_ADD_CLOUD_FILTER_MAC_VLAN_PORT;
: I40E_AQC_ADD_CLOUD_FILTER_MAC_PORT);
> +
> + } else if (filter->dst_ip[0] || filter->is_ipv6) {
> + cld_filter.element.flags =
> + cpu_to_le16(I40E_AQC_ADD_CLOUD_FILTER_IP_PORT);
> + if (filter->is_ipv6)
> + cld_filter.element.flags |=
> + cpu_to_le16(I40E_AQC_ADD_CLOUD_FLAGS_IPV6);
> + else
> + cld_filter.element.flags |=
> + cpu_to_le16(I40E_AQC_ADD_CLOUD_FLAGS_IPV4);
cld_filter.element.flags |= cpu_to_le16(filter->is_ipv6
? I40E_AQC_ADD_CLOUD_FLAGS_IPV6
: I40E_AQC_ADD_CLOUD_FLAGS_IPV4);
> + } else {
> + dev_err(&pf->pdev->dev,
> + "either mac or ip has to be valid for cloud filter\n");
> + return -EINVAL;
> + }
> +
> + /* Now copy L4 port in Byte 6..7 in general fields */
> + cld_filter.general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD0] =
> + be16_to_cpu(filter->dst_port);
> +
> + if (add) {
> + bool proto_type, port_type;
> +
> + proto_type = (filter->ip_proto == IPPROTO_TCP) ? true : false;
> + port_type = (filter->port_type & I40E_CLOUD_FILTER_PORT_DEST) ?
> + true : false;
> +
> + /* For now, src port based cloud filter for channel is not
> + * supported
> + */
> + if (!port_type) {
> + dev_err(&pf->pdev->dev,
> + "unsupported port type (src port)\n");
> + return -EOPNOTSUPP;
> + }
> +
> + /* Validate current device switch mode, change if necessary */
> + ret = i40e_validate_and_set_switch_mode(vsi, proto_type,
> + port_type);
> + if (ret) {
> + dev_err(&pf->pdev->dev,
> + "fail to and set switch mode, ret %d\n",
> + ret);
> + return ret;
> + }
> +
> + ret = i40e_aq_add_cloud_filters_big_buffer(&pf->hw,
> + filter->seid,
> + &cld_filter, 1);
> + } else {
> + ret = i40e_aq_remove_cloud_filters_big_buffer(&pf->hw,
> + filter->seid,
> + &cld_filter, 1);
> + }
> +
> + if (ret)
> + dev_dbg(&pf->pdev->dev,
> + "Failed to %s cloud filter(big buffer) err %d aq_err %d\n",
> + add ? "add" : "delete", ret, pf->hw.aq.asq_last_status);
> +
> + dev_info(&pf->pdev->dev,
> + "%s cloud filter for VSI: %d, L4 port: %d\n",
> + add ? "add" : "delete", filter->seid, ntohs(filter->dst_port));
If there was an error, this dev_info is possibly lying to the user.
> +
> + return ret;
> +}
> +
> +/**
> + * i40e_parse_cls_flower - Parse tc flower filters provided by kernel
> + * @vsi: Pointer to VSI
> + * @cls_flower: Pointer to struct tc_cls_flower_offload
> + * @filter: Pointer to cloud filter structure
> + *
> + **/
> +static int i40e_parse_cls_flower(struct i40e_vsi *vsi,
> + struct tc_cls_flower_offload *f,
> + struct i40e_cloud_filter *filter)
> +{
> + struct i40e_pf *pf = vsi->back;
> + u16 addr_type = 0;
> + u8 field_flags = 0;
> +
> + if (f->dissector->used_keys &
> + ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
> + BIT(FLOW_DISSECTOR_KEY_BASIC) |
> + BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
> + BIT(FLOW_DISSECTOR_KEY_VLAN) |
> + BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
> + BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
> + BIT(FLOW_DISSECTOR_KEY_PORTS) |
> + BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) |
> + BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) |
> + BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) |
> + BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) |
> + BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL))) {
> + dev_err(&pf->pdev->dev, "Unsupported key used: 0x%x\n",
> + f->dissector->used_keys);
> + return -EOPNOTSUPP;
> + }
> +
> + if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
> + struct flow_dissector_key_keyid *key =
> + skb_flow_dissector_target(f->dissector,
> + FLOW_DISSECTOR_KEY_ENC_KEYID,
> + f->key);
> +
> + struct flow_dissector_key_keyid *mask =
> + skb_flow_dissector_target(f->dissector,
> + FLOW_DISSECTOR_KEY_ENC_KEYID,
> + f->mask);
> +
> + if (mask->keyid != 0)
> + field_flags |= I40E_CLOUD_FIELD_TEN_ID;
> +
> + filter->tenant_id = be32_to_cpu(key->keyid);
> + }
> +
> + if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
> + struct flow_dissector_key_basic *key =
> + skb_flow_dissector_target(f->dissector,
> + FLOW_DISSECTOR_KEY_BASIC,
> + f->key);
> +
> + filter->ip_proto = key->ip_proto;
> + }
> +
> + if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
> + struct flow_dissector_key_eth_addrs *key =
> + skb_flow_dissector_target(f->dissector,
> + FLOW_DISSECTOR_KEY_ETH_ADDRS,
> + f->key);
> +
> + struct flow_dissector_key_eth_addrs *mask =
> + skb_flow_dissector_target(f->dissector,
> + FLOW_DISSECTOR_KEY_ETH_ADDRS,
> + f->mask);
> +
> + /* use is_broadcast and is_zero to check for all 0xf or 0 */
> + if (!is_zero_ether_addr(mask->dst)) {
> + if (is_broadcast_ether_addr(mask->dst)) {
> + field_flags |= I40E_CLOUD_FIELD_OMAC;
> + } else {
> + dev_err(&pf->pdev->dev, "Bad ether dest mask %pM\n",
> + mask->dst);
> + return I40E_ERR_CONFIG;
> + }
> + }
> +
> + if (!is_zero_ether_addr(mask->src)) {
> + if (is_broadcast_ether_addr(mask->src)) {
> + field_flags |= I40E_CLOUD_FIELD_IMAC;
> + } else {
> + dev_err(&pf->pdev->dev, "Bad ether src mask %pM\n",
> + mask->src);
> + return I40E_ERR_CONFIG;
> + }
> + }
> + ether_addr_copy(filter->dst_mac, key->dst);
> + ether_addr_copy(filter->src_mac, key->src);
> + }
> +
> + if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
> + struct flow_dissector_key_vlan *key =
> + skb_flow_dissector_target(f->dissector,
> + FLOW_DISSECTOR_KEY_VLAN,
> + f->key);
> + struct flow_dissector_key_vlan *mask =
> + skb_flow_dissector_target(f->dissector,
> + FLOW_DISSECTOR_KEY_VLAN,
> + f->mask);
> +
> + if (mask->vlan_id) {
> + if (mask->vlan_id == VLAN_VID_MASK) {
> + field_flags |= I40E_CLOUD_FIELD_IVLAN;
> + } else {
> + dev_err(&pf->pdev->dev, "Bad vlan mask %u\n",
Should this be a %04x rather than %u?
> + mask->vlan_id);
> + return I40E_ERR_CONFIG;
> + }
> + }
> +
> + filter->vlan_id = cpu_to_be16(key->vlan_id);
> + }
> +
> + if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
> + struct flow_dissector_key_control *key =
> + skb_flow_dissector_target(f->dissector,
> + FLOW_DISSECTOR_KEY_CONTROL,
> + f->key);
> +
> + addr_type = key->addr_type;
> + }
> +
> + if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
> + struct flow_dissector_key_ipv4_addrs *key =
> + skb_flow_dissector_target(f->dissector,
> + FLOW_DISSECTOR_KEY_IPV4_ADDRS,
> + f->key);
> + struct flow_dissector_key_ipv4_addrs *mask =
> + skb_flow_dissector_target(f->dissector,
> + FLOW_DISSECTOR_KEY_IPV4_ADDRS,
> + f->mask);
> +
> + if (mask->dst) {
> + if (mask->dst == cpu_to_be32(0xffffffff)) {
> + field_flags |= I40E_CLOUD_FIELD_IIP;
> + } else {
> + dev_err(&pf->pdev->dev, "Bad ip dst mask 0x%08x\n",
> + be32_to_cpu(mask->dst));
> + return I40E_ERR_CONFIG;
> + }
> + }
> +
> + if (mask->src) {
> + if (mask->src == cpu_to_be32(0xffffffff)) {
> + field_flags |= I40E_CLOUD_FIELD_IIP;
> + } else {
> + dev_err(&pf->pdev->dev, "Bad ip src mask 0x%08x\n",
> + be32_to_cpu(mask->dst));
> + return I40E_ERR_CONFIG;
> + }
> + }
> +
> + if (field_flags & I40E_CLOUD_FIELD_TEN_ID) {
> + dev_err(&pf->pdev->dev, "Tenant id not allowed for ip filter\n");
> + return I40E_ERR_CONFIG;
> + }
> + filter->dst_ip[0] = key->dst;
> + filter->src_ip[0] = key->src;
> + }
> +
> + if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
> + struct flow_dissector_key_ipv6_addrs *key =
> + skb_flow_dissector_target(f->dissector,
> + FLOW_DISSECTOR_KEY_IPV6_ADDRS,
> + f->key);
> + struct flow_dissector_key_ipv6_addrs *mask =
> + skb_flow_dissector_target(f->dissector,
> + FLOW_DISSECTOR_KEY_IPV6_ADDRS,
> + f->mask);
> +
> + /* validate mask, make sure it is not IPV6_ADDR_ANY */
> + if (ipv6_addr_any(&mask->dst)) {
> + dev_err(&pf->pdev->dev, "Bad ipv6 dst mask 0x%02x\n",
> + IPV6_ADDR_ANY);
> + return I40E_ERR_CONFIG;
> + }
> +
> + /* validate src and dest IPV6 address, make sure they are not
> + * ANY (0:0:0:0:0:0:0:0) or LOOPBACK (0:0:0:0:0:0:0:1), which
> + * can be represented as ::1
> + */
> + if (ipv6_addr_any(&key->dst) || ipv6_addr_loopback(&key->dst)) {
> + dev_err(&pf->pdev->dev,
> + "Bad ipv6 dst addr is ANY or LOOPBACK\n");
> + return I40E_ERR_CONFIG;
> + }
> + if (ipv6_addr_loopback(&key->src)) {
> + dev_err(&pf->pdev->dev,
> + "Bad ipv6 src addr is ANY or LOOPBACK\n");
> + return I40E_ERR_CONFIG;
> + }
> + memcpy(&filter->src_ipv6, &key->src.s6_addr,
> + ARRAY_SIZE(filter->src_ipv6));
> + memcpy(&filter->dst_ipv6, &key->dst.s6_addr,
> + ARRAY_SIZE(filter->dst_ipv6));
> +
> + /* mark it as IPv6 filter, to be used later */
> + filter->is_ipv6 = true;
> +
> + /* and it is IP[4|6] filter type */
> + field_flags |= I40E_CLOUD_FIELD_IIP;
> + }
> +
> + if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
> + struct flow_dissector_key_ports *key =
> + skb_flow_dissector_target(f->dissector,
> + FLOW_DISSECTOR_KEY_PORTS,
> + f->key);
> + struct flow_dissector_key_ports *mask =
> + skb_flow_dissector_target(f->dissector,
> + FLOW_DISSECTOR_KEY_PORTS,
> + f->mask);
> +
> + if (mask->src) {
> + if (mask->src == cpu_to_be16(0xffff)) {
> + field_flags |= I40E_CLOUD_FIELD_IIP;
> + } else {
> + dev_err(&pf->pdev->dev, "Bad src port mask %u\n",
Should this be a %04x rather than %u?
> + be16_to_cpu(mask->src));
> + return I40E_ERR_CONFIG;
> + }
> + }
> +
> + if (mask->dst) {
> + if (mask->dst == cpu_to_be16(0xffff)) {
> + field_flags |= I40E_CLOUD_FIELD_IIP;
> + } else {
> + dev_err(&pf->pdev->dev, "Bad dst port mask %u\n",
Should this be a %04x rather than %u?
> + be16_to_cpu(mask->dst));
> + return I40E_ERR_CONFIG;
> + }
> + }
> +
> + filter->dst_port = key->dst;
> + filter->src_port = key->src;
> +
> + /* For now, only supports destination port*/
> + filter->port_type |= I40E_CLOUD_FILTER_PORT_DEST;
> +
> + switch (filter->ip_proto) {
> + case IPPROTO_TCP:
> + case IPPROTO_UDP:
> + break;
> + default:
> + dev_err(&pf->pdev->dev,
> + "Only UDP and TCP transport are supported\n");
> + return -EINVAL;
> + }
> + }
> + filter->flags = field_flags;
> + return 0;
> +}
> +
> +/**
> + * i40e_handle_redirect_action: Forward to a traffic class on the device
> + * @vsi: Pointer to VSI
> + * @ifindex: ifindex of the device to forwared to
> + * @tc: traffic class index on the device
> + * @filter: Pointer to cloud filter structure
> + *
> + **/
> +static int i40e_handle_redirect_action(struct i40e_vsi *vsi, int ifindex, u8 tc,
> + struct i40e_cloud_filter *filter)
> +{
> + struct i40e_channel *ch, *ch_tmp;
> +
> + /* redirect to a traffic class on the same device */
> + if (vsi->netdev->ifindex == ifindex) {
> + if (tc == 0) {
> + filter->seid = vsi->seid;
> + return 0;
> + } else if (vsi->tc_config.enabled_tc & BIT(tc)) {
> + if (!filter->dst_port) {
> + dev_err(&vsi->back->pdev->dev,
> + "Specify destination port to redirect to traffic class that is not default\n");
> + return -EINVAL;
> + }
> + if (list_empty(&vsi->ch_list))
> + return -EINVAL;
> + list_for_each_entry_safe(ch, ch_tmp, &vsi->ch_list,
> + list) {
> + if (ch->seid == vsi->tc_seid_map[tc])
> + filter->seid = ch->seid;
> + }
> + return 0;
> + }
> + }
> + return -EINVAL;
> +}
> +
> +/**
> + * i40e_parse_tc_actions - Parse tc actions
> + * @vsi: Pointer to VSI
> + * @cls_flower: Pointer to struct tc_cls_flower_offload
> + * @filter: Pointer to cloud filter structure
> + *
> + **/
> +static int i40e_parse_tc_actions(struct i40e_vsi *vsi, struct tcf_exts *exts,
> + struct i40e_cloud_filter *filter)
> +{
> + const struct tc_action *a;
> + LIST_HEAD(actions);
> + int err;
> +
> + if (tc_no_actions(exts))
> + return -EINVAL;
> +
> + tcf_exts_to_list(exts, &actions);
> + list_for_each_entry(a, &actions, list) {
> + /* Drop action */
> + if (is_tcf_gact_shot(a)) {
> + dev_err(&vsi->back->pdev->dev,
> + "Cloud filters do not support the drop action.\n");
> + return -EOPNOTSUPP;
> + }
> +
> + /* Redirect to a traffic class on the same device */
> + if (!is_tcf_mirred_egress_redirect(a)) {
> + int ifindex = tcf_mirred_ifindex(a);
> + int tc = tcf_mirred_tc(a);
> +
> + err = i40e_handle_redirect_action(vsi, ifindex, tc,
> + filter);
> + if (err == 0)
> + return err;
> + }
> + }
> + return -EINVAL;
> +}
> +
> +/**
> + * i40e_configure_clsflower - Configure tc flower filters
> + * @vsi: Pointer to VSI
> + * @cls_flower: Pointer to struct tc_cls_flower_offload
> + *
> + **/
> +static int i40e_configure_clsflower(struct i40e_vsi *vsi,
> + struct tc_cls_flower_offload *cls_flower)
> +{
> + struct i40e_cloud_filter *filter = NULL;
> + struct i40e_pf *pf = vsi->back;
> + int err = 0;
> +
> + if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) ||
> + test_bit(__I40E_RESET_INTR_RECEIVED, pf->state))
> + return -EBUSY;
> +
> + if (pf->fdir_pf_active_filters ||
> + (!hlist_empty(&pf->fdir_filter_list))) {
> + dev_err(&vsi->back->pdev->dev,
> + "Flow Director Sideband filters exists, turn ntuple off to configure cloud filters\n");
> + return -EINVAL;
> + }
> +
> + if (vsi->back->flags & I40E_FLAG_FD_SB_ENABLED) {
> + dev_err(&vsi->back->pdev->dev,
> + "Disable Flow Director Sideband while configuring Cloud filters via tc-flower\n");
> + vsi->back->flags &= ~I40E_FLAG_FD_SB_ENABLED;
> + }
> +
> + filter = kzalloc(sizeof(*filter), GFP_KERNEL);
> + if (!filter)
> + return -ENOMEM;
> +
> + filter->cookie = cls_flower->cookie;
> +
> + err = i40e_parse_cls_flower(vsi, cls_flower, filter);
> + if (err < 0)
> + goto err;
> +
> + err = i40e_parse_tc_actions(vsi, cls_flower->exts, filter);
> + if (err < 0)
> + goto err;
> +
> + /* Add cloud filter */
> + if (filter->dst_port)
> + err = i40e_add_del_cloud_filter_big_buf(vsi, filter, true);
> + else
> + err = i40e_add_del_cloud_filter(vsi, filter, true);
> +
> + if (err) {
> + dev_err(&pf->pdev->dev,
> + "Failed to add cloud filter, err %s\n",
> + i40e_stat_str(&pf->hw, err));
> + err = i40e_aq_rc_to_posix(err, pf->hw.aq.asq_last_status);
> + goto err;
> + }
> +
> + /* add filter to the ordered list */
> + INIT_HLIST_NODE(&filter->cloud_node);
> +
> + hlist_add_head(&filter->cloud_node, &pf->cloud_filter_list);
> +
> + pf->num_cloud_filters++;
> +
> + return err;
> +err:
> + kfree(filter);
> + return err;
> +}
> +
> +/**
> + * i40e_find_cloud_filter - Find the could filter in the list
> + * @vsi: Pointer to VSI
> + * @cookie: filter specific cookie
> + *
> + **/
> +static struct i40e_cloud_filter *i40e_find_cloud_filter(struct i40e_vsi *vsi,
> + unsigned long *cookie)
> +{
> + struct i40e_cloud_filter *filter = NULL;
> + struct hlist_node *node2;
> +
> + hlist_for_each_entry_safe(filter, node2,
> + &vsi->back->cloud_filter_list, cloud_node)
> + if (!memcmp(cookie, &filter->cookie, sizeof(filter->cookie)))
> + return filter;
> + return NULL;
> +}
> +
> +/**
> + * i40e_delete_clsflower - Remove tc flower filters
> + * @vsi: Pointer to VSI
> + * @cls_flower: Pointer to struct tc_cls_flower_offload
> + *
> + **/
> +static int i40e_delete_clsflower(struct i40e_vsi *vsi,
> + struct tc_cls_flower_offload *cls_flower)
> +{
> + struct i40e_cloud_filter *filter = NULL;
> + struct i40e_pf *pf = vsi->back;
> + int err = 0;
> +
> + filter = i40e_find_cloud_filter(vsi, &cls_flower->cookie);
> +
> + if (!filter)
> + return -EINVAL;
> +
> + hash_del(&filter->cloud_node);
> +
> + if (filter->dst_port)
> + err = i40e_add_del_cloud_filter_big_buf(vsi, filter, false);
> + else
> + err = i40e_add_del_cloud_filter(vsi, filter, false);
> + if (err) {
> + kfree(filter);
> + dev_err(&pf->pdev->dev,
> + "Failed to delete cloud filter, err %s\n",
> + i40e_stat_str(&pf->hw, err));
> + return i40e_aq_rc_to_posix(err, pf->hw.aq.asq_last_status);
Hmmm... okay, maybe those earlier functions are not really lying if they
have this followup to check them.
> + }
> +
> + kfree(filter);
> + pf->num_cloud_filters--;
> +
> + if (!pf->num_cloud_filters) {
> + /* Re-enable FD-SB that was disabled while configuring cloud
> + * filters
> + */
> + if ((pf->hw.func_caps.fd_filters_guaranteed > 0) ||
> + (pf->hw.func_caps.fd_filters_best_effort > 0)) {
> + if (!(pf->flags & I40E_FLAG_MFP_ENABLED &&
> + pf->hw.num_partitions > 1))
> + pf->flags |= I40E_FLAG_FD_SB_ENABLED;
What if FD_SB was disabled for other reasons, like not enough msix
vectors or queues, or some other odd circumstance that turns them off?
> + }
> + }
> +
> + return 0;
> +}
> +
> static int __i40e_setup_tc(struct net_device *netdev, u32 handle,
> u32 chain_index, __be16 proto,
> struct tc_to_netdev *tc)
> {
> + struct i40e_netdev_priv *np = netdev_priv(netdev);
> + struct i40e_vsi *vsi = np->vsi;
> +
> + if (TC_H_MAJ(handle) == TC_H_MAJ(TC_H_INGRESS) &&
> + tc->type == TC_SETUP_CLSFLOWER) {
> + switch (tc->cls_flower->command) {
> + case TC_CLSFLOWER_REPLACE:
> + return i40e_configure_clsflower(vsi, tc->cls_flower);
> + case TC_CLSFLOWER_DESTROY:
> + return i40e_delete_clsflower(vsi, tc->cls_flower);
> + case TC_CLSFLOWER_STATS:
> + return -EOPNOTSUPP;
> + default:
> + return -EINVAL;
> + }
> + }
> +
> return i40e_setup_tc(netdev, tc);
> }
>
> @@ -6948,6 +7829,16 @@ static void i40e_cloud_filter_exit(struct i40e_pf *pf)
> kfree(cfilter);
> }
> pf->num_cloud_filters = 0;
> +
> + /* Re-enable FD-SB that was disabled while configuring cloud
> + * filters
> + */
> + if ((pf->hw.func_caps.fd_filters_guaranteed > 0) ||
> + (pf->hw.func_caps.fd_filters_best_effort > 0)) {
> + if (!(pf->flags & I40E_FLAG_MFP_ENABLED &&
> + pf->hw.num_partitions > 1))
> + pf->flags |= I40E_FLAG_FD_SB_ENABLED;
What if FD_SB was disabled for other reasons, like not enough msix
vectors or queues, or some other odd circumstance that turns them off?
This is getting complex and repetative. Maybe there needs to be a
little function that checks all the FD_SB conditions and can be used
from anywhere needed.
> + }
> }
>
> /**
> @@ -8157,6 +9048,48 @@ static void i40e_fdir_teardown(struct i40e_pf *pf)
> }
>
> /**
> + * i40e_rebuild_cloud_filters - Rebuilds cloud filters for VSIs
> + * @vsi: PF main vsi
> + * @seid: seid of main or channel VSIs
> + *
> + * Rebuilds cloud filters associated with main VSI and channel VSIs if they
> + * existed before reset
> + **/
> +static int i40e_rebuild_cloud_filters(struct i40e_vsi *vsi, u16 seid)
> +{
> + struct i40e_cloud_filter *cfilter;
> + struct i40e_pf *pf = vsi->back;
> + struct hlist_node *node;
> + i40e_status ret;
> +
> + /* Add cloud filters back if they exist */
> + if (hlist_empty(&pf->cloud_filter_list))
> + return 0;
> +
> + hlist_for_each_entry_safe(cfilter, node, &pf->cloud_filter_list,
> + cloud_node) {
> + if (cfilter->seid != seid)
> + continue;
> +
> + if (cfilter->dst_port)
> + ret = i40e_add_del_cloud_filter_big_buf(vsi, cfilter,
> + true);
> + else
> + ret = i40e_add_del_cloud_filter(vsi, cfilter, true);
> +
> + if (ret) {
> + dev_dbg(&pf->pdev->dev,
> + "Failed to rebuild cloud filter, err %s aq_err %s\n",
> + i40e_stat_str(&pf->hw, ret),
> + i40e_aq_str(&pf->hw,
> + pf->hw.aq.asq_last_status));
> + return ret;
> + }
> + }
> + return 0;
> +}
> +
> +/**
> * i40e_rebuild_channels - Rebuilds channel VSIs if they existed before reset
> * @vsi: PF main vsi
> *
> @@ -8193,6 +9126,13 @@ static int i40e_rebuild_channels(struct i40e_vsi *vsi)
> I40E_BW_CREDIT_DIVISOR,
> ch->seid);
> }
> + ret = i40e_rebuild_cloud_filters(vsi, ch->seid);
> + if (ret) {
> + dev_dbg(&vsi->back->pdev->dev,
> + "Failed to rebuild cloud filters for channel VSI %u\n",
> + ch->seid);
> + return ret;
> + }
> }
> return 0;
> }
> @@ -8476,6 +9416,10 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
> goto end_unlock;
> }
>
> + ret = i40e_rebuild_cloud_filters(vsi, vsi->seid);
> + if (ret)
> + goto end_unlock;
> +
> /* PF Main VSI is rebuild by now, go ahead and rebuild channel VSIs
> * for this main VSI if they exist
> */
> @@ -10846,7 +11790,8 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
> netdev->hw_features |= NETIF_F_NTUPLE;
> hw_features = hw_enc_features |
> NETIF_F_HW_VLAN_CTAG_TX |
> - NETIF_F_HW_VLAN_CTAG_RX;
> + NETIF_F_HW_VLAN_CTAG_RX |
> + NETIF_F_HW_TC;
>
> netdev->hw_features |= hw_features;
>
> @@ -12123,8 +13068,10 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
> */
>
> if ((pf->hw.pf_id == 0) &&
> - !(pf->flags & I40E_FLAG_TRUE_PROMISC_SUPPORT))
> + !(pf->flags & I40E_FLAG_TRUE_PROMISC_SUPPORT)) {
> flags = I40E_AQ_SET_SWITCH_CFG_PROMISC;
> + pf->last_sw_conf_flags = flags;
> + }
>
> if (pf->hw.pf_id == 0) {
> u16 valid_flags;
> @@ -12140,6 +13087,7 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
> pf->hw.aq.asq_last_status));
> /* not a fatal problem, just keep going */
> }
> + pf->last_sw_conf_valid_flags = valid_flags;
> }
>
> /* first time setup */
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h
> index 9142d0d..e24f1ce 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h
> +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h
> @@ -283,6 +283,23 @@ i40e_status i40e_aq_query_switch_comp_bw_config(struct i40e_hw *hw,
> struct i40e_asq_cmd_details *cmd_details);
> i40e_status i40e_aq_resume_port_tx(struct i40e_hw *hw,
> struct i40e_asq_cmd_details *cmd_details);
> +i40e_status i40e_aq_add_cloud_filters_big_buffer(struct i40e_hw *hw,
> + u16 seid,
> + struct i40e_aqc_add_remove_cloud_filters_element_big_data *filters,
> + u8 filter_count);
> +enum i40e_status_code i40e_aq_add_cloud_filters(struct i40e_hw *hw,
> + u16 vsi,
> + struct i40e_aqc_add_remove_cloud_filters_element_data *filters,
> + u8 filter_count);
> +
> +enum i40e_status_code i40e_aq_remove_cloud_filters(struct i40e_hw *hw,
> + u16 vsi,
> + struct i40e_aqc_add_remove_cloud_filters_element_data *filters,
> + u8 filter_count);
> +i40e_status i40e_aq_remove_cloud_filters_big_buffer(
> + struct i40e_hw *hw, u16 seid,
> + struct i40e_aqc_add_remove_cloud_filters_element_big_data *filters,
> + u8 filter_count);
> i40e_status i40e_read_lldp_cfg(struct i40e_hw *hw,
> struct i40e_lldp_variables *lldp_cfg);
> /* i40e_common */
>
> _______________________________________________
> Intel-wired-lan mailing list
> Intel-wired-lan@osuosl.org
> https://lists.osuosl.org/mailman/listinfo/intel-wired-lan
>
^ permalink raw reply
* Re: [Intel-wired-lan] [PATCH 5/6] [net-next]net: i40e: Clean up of cloud filters
From: Shannon Nelson @ 2017-08-01 19:16 UTC (permalink / raw)
To: Amritha Nambiar, intel-wired-lan, jeffrey.t.kirsher
Cc: netdev, mitch.a.williams
In-Reply-To: <150154787996.4135.2478207403613749470.stgit@anamdev.jf.intel.com>
On 7/31/2017 5:38 PM, Amritha Nambiar wrote:
> Introduce the cloud filter datastructure and cleanup of cloud
> filters associated with the device.
>
> Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
> ---
> drivers/net/ethernet/intel/i40e/i40e.h | 11 +++++++++++
> drivers/net/ethernet/intel/i40e/i40e_main.c | 27 +++++++++++++++++++++++++++
> 2 files changed, 38 insertions(+)
>
> diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
> index 1391e5d..5c0cad5 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e.h
> +++ b/drivers/net/ethernet/intel/i40e/i40e.h
> @@ -252,6 +252,14 @@ struct i40e_fdir_filter {
> u32 fd_id;
> };
>
> +struct i40e_cloud_filter {
> + struct hlist_node cloud_node;
> + /* cloud filter input set follows */
> + unsigned long cookie;
> + /* filter control */
> + u16 seid;
> +};
This would be cleaner and more readable with the field comments off to
the side rather than in line with the fields.
> +
> #define I40E_ETH_P_LLDP 0x88cc
>
> #define I40E_DCB_PRIO_TYPE_STRICT 0
> @@ -419,6 +427,9 @@ struct i40e_pf {
> struct i40e_udp_port_config udp_ports[I40E_MAX_PF_UDP_OFFLOAD_PORTS];
> u16 pending_udp_bitmap;
>
> + struct hlist_head cloud_filter_list;
> + u16 num_cloud_filters;
> +
> enum i40e_interrupt_policy int_policy;
> u16 rx_itr_default;
> u16 tx_itr_default;
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
> index fdddd74..93f6fe2 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
> @@ -6928,6 +6928,29 @@ static void i40e_fdir_filter_exit(struct i40e_pf *pf)
> }
>
> /**
> + * i40e_cloud_filter_exit - Cleans up the Cloud Filters
> + * @pf: Pointer to PF
> + *
> + * This function destroys the hlist where all the Cloud Filters
> + * filters were saved.
> + **/
> +static void i40e_cloud_filter_exit(struct i40e_pf *pf)
> +{
> + struct i40e_cloud_filter *cfilter;
> + struct hlist_node *node;
> +
> + if (hlist_empty(&pf->cloud_filter_list))
> + return;
Is this check really necessary? Doesn't hlist_for_each_entry_safe()
check for this?
> +
> + hlist_for_each_entry_safe(cfilter, node,
> + &pf->cloud_filter_list, cloud_node) {
> + hlist_del(&cfilter->cloud_node);
> + kfree(cfilter);
> + }
> + pf->num_cloud_filters = 0;
> +}
> +
> +/**
> * i40e_close - Disables a network interface
> * @netdev: network interface device structure
> *
> @@ -12137,6 +12160,7 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
> vsi = i40e_vsi_reinit_setup(pf->vsi[pf->lan_vsi]);
> if (!vsi) {
> dev_info(&pf->pdev->dev, "setup of MAIN VSI failed\n");
> + i40e_cloud_filter_exit(pf);
> i40e_fdir_teardown(pf);
> return -EAGAIN;
> }
> @@ -12961,6 +12985,8 @@ static void i40e_remove(struct pci_dev *pdev)
> if (pf->vsi[pf->lan_vsi])
> i40e_vsi_release(pf->vsi[pf->lan_vsi]);
>
> + i40e_cloud_filter_exit(pf);
> +
> /* remove attached clients */
> if (pf->flags & I40E_FLAG_IWARP_ENABLED) {
> ret_code = i40e_lan_del_device(pf);
> @@ -13170,6 +13196,7 @@ static void i40e_shutdown(struct pci_dev *pdev)
>
> del_timer_sync(&pf->service_timer);
> cancel_work_sync(&pf->service_task);
> + i40e_cloud_filter_exit(pf);
> i40e_fdir_teardown(pf);
>
> /* Client close must be called explicitly here because the timer
>
> _______________________________________________
> Intel-wired-lan mailing list
> Intel-wired-lan@osuosl.org
> https://lists.osuosl.org/mailman/listinfo/intel-wired-lan
>
^ permalink raw reply
* Re: [Intel-wired-lan] [PATCH net-next RFC 0/6] Configure cloud filters in i40e via tc/flower classifier
From: Shannon Nelson @ 2017-08-01 19:16 UTC (permalink / raw)
To: Amritha Nambiar, intel-wired-lan, jeffrey.t.kirsher
Cc: netdev, mitch.a.williams
In-Reply-To: <150154569340.4135.11548126443780491627.stgit@anamdev.jf.intel.com>
If this is an RFC patchset, then all the patches should have RFC in them.
On 7/31/2017 5:36 PM, Amritha Nambiar wrote:
> This patch series enables configuring cloud filters in i40e
> using the tc/flower classifier. The only tc-filter action
> supported is to redirect packets to a traffic class on the
> same device. The tc/mirred:redirect action is extended to
> accept a traffic class to achieve this.
>
> The cloud filters are added for a VSI and are cleaned up when
> the VSI is deleted. The filters that match on L4 ports needs
> enhanced admin queue functions with big buffer support for
> extended general fields in Add/Remove Cloud filters command.
>
> Example:
> # tc qdisc add dev eth0 ingress
>
> # ethtool -K eth0 hw-tc-offload on
>
> # tc filter add dev eth0 protocol ip parent ffff: prio 1 flower\
> dst_ip 192.168.1.1/32 ip_proto udp dst_port 22\
> skip_sw indev eth0 action mirred ingress redirect dev eth0 tc 1
>
> # tc filter show dev eth0 parent ffff:
> filter protocol ip pref 1 flower
> filter protocol ip pref 1 flower handle 0x1
> indev eth0
> eth_type ipv4
> ip_proto udp
> dst_ip 192.168.1.1
> dst_port 22
> skip_sw
> in_hw
> action order 1: mirred (Ingress Redirect to device eth0) stolen tc 1
> index 1 ref 1 bind 1
> ---
>
> Amritha Nambiar (6):
> [net-next]net: sched: act_mirred: Extend redirect action to accept a traffic class
> [net-next]net: i40e: Maintain a mapping of TCs with the VSI seids
> [net-next]net: i40e: Extend set switch config command to accept cloud filter mode
> [net-next]net: i40e: Admin queue definitions for cloud filters
> [net-next]net: i40e: Clean up of cloud filters
> [net-next]net: i40e: Enable cloud filters in i40e via tc/flower classifier
>
>
> drivers/net/ethernet/intel/i40e/i40e.h | 58 +
> drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 132 +++
> drivers/net/ethernet/intel/i40e/i40e_common.c | 184 ++++
> drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 2
> drivers/net/ethernet/intel/i40e/i40e_main.c | 983 +++++++++++++++++++++
> drivers/net/ethernet/intel/i40e/i40e_prototype.h | 19
> drivers/net/ethernet/intel/i40e/i40e_type.h | 9
> include/net/tc_act/tc_mirred.h | 7
> include/uapi/linux/tc_act/tc_mirred.h | 5
> net/sched/act_mirred.c | 17
> 10 files changed, 1408 insertions(+), 8 deletions(-)
>
> --
> _______________________________________________
> Intel-wired-lan mailing list
> Intel-wired-lan@osuosl.org
> https://lists.osuosl.org/mailman/listinfo/intel-wired-lan
>
^ permalink raw reply
* Re: [Intel-wired-lan] [PATCH 4/6] [net-next]net: i40e: Admin queue definitions for cloud filters
From: Shannon Nelson @ 2017-08-01 19:16 UTC (permalink / raw)
To: Amritha Nambiar, intel-wired-lan, jeffrey.t.kirsher
Cc: netdev, mitch.a.williams
In-Reply-To: <150154787489.4135.14606047917479370681.stgit@anamdev.jf.intel.com>
On 7/31/2017 5:37 PM, Amritha Nambiar wrote:
> Add new admin queue definitions and extended fields for cloud
> filter support. Define big buffer for extended general fields
> in Add/Remove Cloud filters command.
>
> Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
> Signed-off-by: Kiran Patil <kiran.patil@intel.com>
> Signed-off-by: Store Laura <laura.stroe@intel.com>
> Signed-off-by: Iremonger Bernard <bernard.iremonger@intel.com>
> Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
> ---
> drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 98 +++++++++++++++++++++
> 1 file changed, 97 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
> index 8bba04c..9f14305 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
> +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
I see that you're changing the i40e version of this, but not the i40evf
version. I understand that these changes are not useful for the VF, but
are you no longer trying to keep the AdminQ definitions consistent
between the two?
> @@ -1358,7 +1358,9 @@ struct i40e_aqc_add_remove_cloud_filters {
> #define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_SHIFT 0
> #define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_MASK (0x3FF << \
> I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_SHIFT)
> - u8 reserved2[4];
> + u8 big_buffer_flag;
> +#define I40E_AQC_ADD_REM_CLOUD_CMD_BIG_BUFFER 1
> + u8 reserved2[3];
> __le32 addr_high;
> __le32 addr_low;
> };
> @@ -1395,6 +1397,13 @@ struct i40e_aqc_add_remove_cloud_filters_element_data {
> #define I40E_AQC_ADD_CLOUD_FILTER_IMAC 0x000A
> #define I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC 0x000B
> #define I40E_AQC_ADD_CLOUD_FILTER_IIP 0x000C
> +/* 0x0010 to 0x0017 is for custom filters */
> +/* flag to be used when adding cloud filter: IP + L4 Port */
> +#define I40E_AQC_ADD_CLOUD_FILTER_IP_PORT 0x0010
> +/* flag to be used when adding cloud filter: Dest MAC + L4 Port */
> +#define I40E_AQC_ADD_CLOUD_FILTER_MAC_PORT 0x0011
> +/* flag to be used when adding cloud filter: Dest MAC + VLAN + L4 Port */
> +#define I40E_AQC_ADD_CLOUD_FILTER_MAC_VLAN_PORT 0x0012
>
> #define I40E_AQC_ADD_CLOUD_FLAGS_TO_QUEUE 0x0080
> #define I40E_AQC_ADD_CLOUD_VNK_SHIFT 6
> @@ -1429,6 +1438,45 @@ struct i40e_aqc_add_remove_cloud_filters_element_data {
> u8 response_reserved[7];
> };
I know you didn't add this struct, but where's the I40E_CHECK_STRUCT_LEN
check?
>
> +/* i40e_aqc_add_remove_cloud_filters_element_big_data is used when
> + * I40E_AQC_ADD_REM_CLOUD_CMD_BIG_BUFFER flag is set.
> + */
> +struct i40e_aqc_add_remove_cloud_filters_element_big_data {
> + struct i40e_aqc_add_remove_cloud_filters_element_data element;
> + u16 general_fields[32];
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD0 0
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1 1
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD2 2
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0 3
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1 4
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2 5
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X12_WORD0 6
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X12_WORD1 7
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X12_WORD2 8
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X13_WORD0 9
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X13_WORD1 10
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X13_WORD2 11
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X14_WORD0 12
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X14_WORD1 13
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X14_WORD2 14
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD0 15
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD1 16
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD2 17
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD3 18
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD4 19
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD5 20
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD6 21
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD7 22
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD0 23
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD1 24
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD2 25
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD3 26
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD4 27
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD5 28
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD6 29
> +#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD7 30
> +};
Needs the I40E_CHECK_STRUCT_LEN to be consistent with the data checking
in the rest of this file.
> +
> struct i40e_aqc_remove_cloud_filters_completion {
> __le16 perfect_ovlan_used;
> __le16 perfect_ovlan_free;
> @@ -1440,6 +1488,54 @@ struct i40e_aqc_remove_cloud_filters_completion {
>
> I40E_CHECK_CMD_LENGTH(i40e_aqc_remove_cloud_filters_completion);
>
> +/* Replace filter Command 0x025F
> + * uses the i40e_aqc_replace_cloud_filters,
> + * and the generic indirect completion structure
> + */
> +struct i40e_filter_data {
> + u8 filter_type;
> + u8 input[3];
> +};
Should have I40E_CHECK_STRUCT_LEN check
> +
> +struct i40e_aqc_replace_cloud_filters_cmd {
> + u8 valid_flags;
> +#define I40E_AQC_REPLACE_L1_FILTER 0x0
> +#define I40E_AQC_REPLACE_CLOUD_FILTER 0x1
> +#define I40E_AQC_GET_CLOUD_FILTERS 0x2
> +#define I40E_AQC_MIRROR_CLOUD_FILTER 0x4
> +#define I40E_AQC_HIGH_PRIORITY_CLOUD_FILTER 0x8
> + u8 old_filter_type;
> + u8 new_filter_type;
> + u8 tr_bit;
> + u8 reserved[4];
> + __le32 addr_high;
> + __le32 addr_low;
> +};
Should have I40E_CHECK_CMD_LENGTH check
> +
> +struct i40e_aqc_replace_cloud_filters_cmd_buf {
> + u8 data[32];
> +/* Filter type INPUT codes*/
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_ENTRIES_MAX 3
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED BIT(7)
> +
> +/* Field Vector offsets */
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_MAC_DA 0
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_ETH 6
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG 7
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_VLAN 8
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_OVLAN 9
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_IVLAN 10
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TUNNLE_KEY 11
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC 12
> +/* big FLU */
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IP_DA 14
> +/* big FLU */
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_OIP_DA 15
> +
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_INNER_VLAN 37
> + struct i40e_filter_data filters[8];
> +};
Should have I40E_CHECK_STRUCT_LEN check
> +
> /* Add Mirror Rule (indirect or direct 0x0260)
> * Delete Mirror Rule (indirect or direct 0x0261)
> * note: some rule types (4,5) do not use an external buffer.
>
> _______________________________________________
> Intel-wired-lan mailing list
> Intel-wired-lan@osuosl.org
> https://lists.osuosl.org/mailman/listinfo/intel-wired-lan
>
^ permalink raw reply
* [PATCH net 5/7] gtp: Initialize 64-bit per-cpu stats correctly
From: Florian Fainelli @ 2017-08-01 19:11 UTC (permalink / raw)
To: netdev
Cc: davem, edumazet, Florian Fainelli, Pablo Neira Ayuso,
Harald Welte, open list:GTP (GPRS Tunneling Protocol), open list
In-Reply-To: <20170801191113.8754-1-f.fainelli@gmail.com>
On 32-bit hosts and with CONFIG_DEBUG_LOCK_ALLOC we should be seeing a
lockdep splat indicating this seqcount is not correctly initialized, fix
that by using netdev_alloc_pcpu_stats() instead of an open coded
allocation.
Fixes: 459aa660eb1d ("gtp: add initial driver for datapath of GPRS Tunneling Protocol (GTP-U)")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/gtp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 1542e837fdfa..f38e32a7ec9c 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -364,7 +364,7 @@ static int gtp_dev_init(struct net_device *dev)
gtp->dev = dev;
- dev->tstats = alloc_percpu(struct pcpu_sw_netstats);
+ dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
if (!dev->tstats)
return -ENOMEM;
--
2.9.3
^ permalink raw reply related
* [PATCH net 1/7] b44: Initialize 64-bit stats seqcount
From: Florian Fainelli @ 2017-08-01 19:11 UTC (permalink / raw)
To: netdev; +Cc: davem, edumazet, Florian Fainelli, Michael Chan, open list
In-Reply-To: <20170801191113.8754-1-f.fainelli@gmail.com>
On 32-bit hosts and with CONFIG_DEBUG_LOCK_ALLOC we should be seeing a
lockdep splat indicating this seqcount is not correctly initialized, fix
that.
Fixes: eeda8585522b ("b44: add 64 bit stats")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/broadcom/b44.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index f411936b744c..a1125d10c825 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -2368,6 +2368,7 @@ static int b44_init_one(struct ssb_device *sdev,
bp->msg_enable = netif_msg_init(b44_debug, B44_DEF_MSG_ENABLE);
spin_lock_init(&bp->lock);
+ u64_stats_init(&bp->hw_stats.syncp);
bp->rx_pending = B44_DEF_RX_RING_PENDING;
bp->tx_pending = B44_DEF_TX_RING_PENDING;
--
2.9.3
^ permalink raw reply related
* [PATCH net 0/7] drivers: net: Fix 64-bit statistics seqcount init
From: Florian Fainelli @ 2017-08-01 19:11 UTC (permalink / raw)
To: netdev; +Cc: davem, edumazet, Florian Fainelli
Hi all,
This patch series fixes a bunch of drivers to have their 64-bit statistics
seqcount cookie be initialized correctly. Most of these drivers (except b44,
gtp) are probably used on 64-bit only hosts and so the lockdep splat might have
never been seen.
Florian Fainelli (7):
b44: Initialize 64-bit stats seqcount
i40e: Initialize 64-bit statistics TX ring seqcount
ixgbe: Initialize 64-bit stats seqcounts
nfp: Initialize RX and TX ring 64-bit stats seqcounts
gtp: Initialize 64-bit per-cpu stats correctly
netvsc: Initialize 64-bit stats seqcount
ipvlan: Fix 64-bit statistics seqcount initialization
drivers/net/ethernet/broadcom/b44.c | 1 +
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 2 ++
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 4 ++++
drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 2 ++
drivers/net/gtp.c | 2 +-
drivers/net/hyperv/netvsc.c | 2 ++
drivers/net/ipvlan/ipvlan_main.c | 2 +-
7 files changed, 13 insertions(+), 2 deletions(-)
--
2.9.3
^ permalink raw reply
* [PATCH net 7/7] ipvlan: Fix 64-bit statistics seqcount initialization
From: Florian Fainelli @ 2017-08-01 19:11 UTC (permalink / raw)
To: netdev
Cc: davem, edumazet, Florian Fainelli, Mahesh Bandewar, Gao Feng,
David Ahern, Matthias Schiffer, Krister Johansen,
Florian Westphal, Sainath Grandhi, open list
In-Reply-To: <20170801191113.8754-1-f.fainelli@gmail.com>
On 32-bit hosts and with CONFIG_DEBUG_LOCK_ALLOC we should be seeing a
lockdep splat indicating this seqcount is not correctly initialized, fix
that by using the proper helper function: netdev_alloc_pcpu_stats().
Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ipvlan/ipvlan_main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index f37e3c1fd4e7..8dab74a81303 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -192,7 +192,7 @@ static int ipvlan_init(struct net_device *dev)
netdev_lockdep_set_classes(dev);
- ipvlan->pcpu_stats = alloc_percpu(struct ipvl_pcpu_stats);
+ ipvlan->pcpu_stats = netdev_alloc_pcpu_stats(struct ipvl_pcpu_stats);
if (!ipvlan->pcpu_stats)
return -ENOMEM;
--
2.9.3
^ permalink raw reply related
* [PATCH net 6/7] netvsc: Initialize 64-bit stats seqcount
From: Florian Fainelli @ 2017-08-01 19:11 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Stephen Hemminger, Haiyang Zhang, open list,
edumazet, open list:Hyper-V CORE AND DRIVERS, davem
In-Reply-To: <20170801191113.8754-1-f.fainelli@gmail.com>
On 32-bit hosts and with CONFIG_DEBUG_LOCK_ALLOC we should be seeing a
lockdep splat indicating this seqcount is not correctly initialized, fix
that. In commit 6c80f3fc2398 ("netvsc: report per-channel stats in
ethtool statistics") netdev_alloc_pcpu_stats() was removed in favor of
open-coding the 64-bits statistics, except that u64_stats_init() was
missed.
Fixes: 6c80f3fc2398 ("netvsc: report per-channel stats in ethtool statistics")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/hyperv/netvsc.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 0a9167dd72fb..96f90c75d1b7 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -1302,6 +1302,8 @@ int netvsc_device_add(struct hv_device *device,
struct netvsc_channel *nvchan = &net_device->chan_table[i];
nvchan->channel = device->channel;
+ u64_stats_init(&nvchan->tx_stats.syncp);
+ u64_stats_init(&nvchan->rx_stats.syncp);
}
/* Enable NAPI handler before init callbacks */
--
2.9.3
^ permalink raw reply related
* [PATCH net 6/7] netvsc: Initialize 64-bit stats seqcount
From: Florian Fainelli @ 2017-08-01 19:11 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Stephen Hemminger, Haiyang Zhang, open list,
edumazet, open list:Hyper-V CORE AND DRIVERS, davem
In-Reply-To: <20170801191113.8754-1-f.fainelli@gmail.com>
On 32-bit hosts and with CONFIG_DEBUG_LOCK_ALLOC we should be seeing a
lockdep splat indicating this seqcount is not correctly initialized, fix
that. In commit 6c80f3fc2398 ("netvsc: report per-channel stats in
ethtool statistics") netdev_alloc_pcpu_stats() was removed in favor of
open-coding the 64-bits statistics, except that u64_stats_init() was
missed.
Fixes: 6c80f3fc2398 ("netvsc: report per-channel stats in ethtool statistics")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/hyperv/netvsc.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 0a9167dd72fb..96f90c75d1b7 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -1302,6 +1302,8 @@ int netvsc_device_add(struct hv_device *device,
struct netvsc_channel *nvchan = &net_device->chan_table[i];
nvchan->channel = device->channel;
+ u64_stats_init(&nvchan->tx_stats.syncp);
+ u64_stats_init(&nvchan->rx_stats.syncp);
}
/* Enable NAPI handler before init callbacks */
--
2.9.3
^ permalink raw reply related
* [PATCH net 4/7] nfp: Initialize RX and TX ring 64-bit stats seqcounts
From: Florian Fainelli @ 2017-08-01 19:11 UTC (permalink / raw)
To: netdev
Cc: davem, edumazet, Florian Fainelli, Jakub Kicinski, Simon Horman,
Daniel Borkmann, open list:NETRONOME ETHERNET DRIVERS, open list
In-Reply-To: <20170801191113.8754-1-f.fainelli@gmail.com>
On 32-bit hosts and with CONFIG_DEBUG_LOCK_ALLOC we should be seeing a
lockdep splat indicating this seqcount is not correctly initialized, fix
that.
Fixes: 4c3523623dc0 ("net: add driver for Netronome NFP4000/NFP6000 NIC VFs")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 18750ff0ede6..4631ca8b8eb2 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -513,6 +513,7 @@ nfp_net_tx_ring_init(struct nfp_net_tx_ring *tx_ring,
tx_ring->idx = idx;
tx_ring->r_vec = r_vec;
tx_ring->is_xdp = is_xdp;
+ u64_stats_init(&tx_ring->r_vec->tx_sync);
tx_ring->qcidx = tx_ring->idx * nn->stride_tx;
tx_ring->qcp_q = nn->tx_bar + NFP_QCP_QUEUE_OFF(tx_ring->qcidx);
@@ -532,6 +533,7 @@ nfp_net_rx_ring_init(struct nfp_net_rx_ring *rx_ring,
rx_ring->idx = idx;
rx_ring->r_vec = r_vec;
+ u64_stats_init(&rx_ring->r_vec->rx_sync);
rx_ring->fl_qcidx = rx_ring->idx * nn->stride_rx;
rx_ring->qcp_fl = nn->rx_bar + NFP_QCP_QUEUE_OFF(rx_ring->fl_qcidx);
--
2.9.3
^ permalink raw reply related
* [PATCH net 3/7] ixgbe: Initialize 64-bit stats seqcounts
From: Florian Fainelli @ 2017-08-01 19:11 UTC (permalink / raw)
To: netdev
Cc: davem, edumazet, Florian Fainelli, Jeff Kirsher,
moderated list:INTEL ETHERNET DRIVERS, open list
In-Reply-To: <20170801191113.8754-1-f.fainelli@gmail.com>
On 32-bit hosts and with CONFIG_DEBUG_LOCK_ALLOC we should be seeing a
lockdep splat indicating this seqcount is not correctly initialized, fix
that.
Fixes: 4197aa7bb818 ("ixgbevf: provide 64 bit statistics")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 084c53582793..032f8ac06357 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -2988,6 +2988,8 @@ int ixgbevf_setup_tx_resources(struct ixgbevf_ring *tx_ring)
if (!tx_ring->tx_buffer_info)
goto err;
+ u64_stats_init(&tx_ring->syncp);
+
/* round up to nearest 4K */
tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc);
tx_ring->size = ALIGN(tx_ring->size, 4096);
@@ -3046,6 +3048,8 @@ int ixgbevf_setup_rx_resources(struct ixgbevf_ring *rx_ring)
if (!rx_ring->rx_buffer_info)
goto err;
+ u64_stats_init(&rx_ring->syncp);
+
/* Round up to nearest 4K */
rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc);
rx_ring->size = ALIGN(rx_ring->size, 4096);
--
2.9.3
^ permalink raw reply related
* [PATCH net 2/7] i40e: Initialize 64-bit statistics TX ring seqcount
From: Florian Fainelli @ 2017-08-01 19:11 UTC (permalink / raw)
To: netdev
Cc: davem, edumazet, Florian Fainelli, Jeff Kirsher,
moderated list:INTEL ETHERNET DRIVERS, open list
In-Reply-To: <20170801191113.8754-1-f.fainelli@gmail.com>
On 32-bit hosts and with CONFIG_DEBUG_LOCK_ALLOC we should be seeing a
lockdep splat indicating this seqcount is not correctly initialized, fix
that.
Fixes: 980e9b118642 ("i40e: Add support for 64 bit netstats")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index b936febc315a..2194960d5855 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -1113,6 +1113,8 @@ int i40e_setup_tx_descriptors(struct i40e_ring *tx_ring)
if (!tx_ring->tx_bi)
goto err;
+ u64_stats_init(&tx_ring->syncp);
+
/* round up to nearest 4K */
tx_ring->size = tx_ring->count * sizeof(struct i40e_tx_desc);
/* add u32 for head writeback, align after this takes care of
--
2.9.3
^ permalink raw reply related
* Re: [PATCH net-next 10/11] net: dsa: mv88e6xxx: remove EEE support
From: Florian Fainelli @ 2017-08-01 18:53 UTC (permalink / raw)
To: Andrew Lunn; +Cc: Vivien Didelot, netdev, linux-kernel, kernel, David S. Miller
In-Reply-To: <20170801172757.GL23157@lunn.ch>
On 08/01/2017 10:27 AM, Andrew Lunn wrote:
>> If the MAC does not support EEE but the PHY does I think you can still
>> allow EEE to be advertised and enabled, you just won't have the MAC be
>> able to leverage the power savings that EEE brings. AFAICT this is still
>> a valid mode whereby the PHY is put in a lower power mode, just not the
>> whole transmit path (MAC + PHY).
>
> Hi Florian
>
> I read a couple of datasheets for a few phys doing EEE. Both said the
> same, the MAC has to indicate to the PHY when low power should be
> entered and existed. The PHY itself does not appear to do anything on
> its own.
Oh you are right, the LPI signal has to come from the MAC for the PHY to
decide how to do the idle signaling, my bad.
>
> It would be good to read the standards about this. But i don't think
> we should tell userspace EEE is enabled, if the PHY has it enabled,
> but the MAC is not capable and hence EEE is not actually being used at
> all.
--
Florian
^ permalink raw reply
* Re: [PATCH v3 net-next 1/4] tcp: ULP infrastructure
From: Tom Herbert @ 2017-08-01 18:27 UTC (permalink / raw)
To: Dave Watson
Cc: Ilya Lesokhin, Aviad Yehezkel, Boris Pismenny, Liran Liss,
Matan Barak, David Miller, Linux Kernel Network Developers,
Herbert Xu, Linux Crypto Mailing List, Hannes Frederic Sowa,
Eric Dumazet, Alexei Starovoitov, Nikos Mavrogiannopoulos,
Fridolín Pokorný
In-Reply-To: <20170731221614.GB93172@dhcp-172-20-173-153.dhcp.thefacebook.com>
On Mon, Jul 31, 2017 at 3:16 PM, Dave Watson <davejwatson@fb.com> wrote:
> On 07/29/17 01:12 PM, Tom Herbert wrote:
>> On Wed, Jun 14, 2017 at 11:37 AM, Dave Watson <davejwatson@fb.com> wrote:
>> > Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP
>> > sockets. Based on a similar infrastructure in tcp_cong. The idea is that any
>> > ULP can add its own logic by changing the TCP proto_ops structure to its own
>> > methods.
>> >
>> > Example usage:
>> >
>> > setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));
>> >
>> One question: is there a good reason why the ULP infrastructure should
>> just be for TCP sockets. For example, I'd really like to be able
>> something like:
>>
>> setsockopt(sock, SOL_SOCKET, SO_ULP, &ulp_param, sizeof(ulp_param));
>>
>> Where ulp_param is a structure containing the ULP name as well as some
>> ULP specific parameters that are passed to init_ulp. ulp_init could
>> determine whether the socket family is appropriate for the ULP being
>> requested.
>
> Using SOL_SOCKET instead seems reasonable to me. I can see how
> ulp_params could have some use, perhaps at a slight loss in clarity.
> TLS needs its own setsockopts anyway though, for renegotiate for
> example.
I'll post the changes shortly. The reason to include parameters with
the setsockopt is so that we can push the ULP and start operations in
one shot.
Tom
^ permalink raw reply
* [iproute PATCH] iplink: Notify user if EEXIST error might be spurious
From: Phil Sutter @ 2017-08-01 17:27 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
Back in the days when RTM_NEWLINK wasn't yet implemented, people had to
rely upon kernel modules to create (virtual) interfaces for them. The
number of those was usually defined via module parameter, and a sane
default value was chosen. Now that iproute2 allows users to instantiate
new interfaces at will, this is no longer required - though for
backwards compatibility reasons, we're stuck with both methods which
collide at the point when one tries to create an interface with a
standard name for a type which exists in a kernel module: The kernel
will load the module, which instantiates the interface and the following
RTM_NEWLINK request will fail since the interface exists already. For
instance:
| # lsmod | grep dummy
| # ip link show | grep dummy0
| # ip link add dummy0 type dummy
| RTNETLINK answers: File exists
| # ip link show | grep -c dummy0
| 1
There is no race-free solution in userspace for this dilemma as far as I
can tell, so try to detect whether a user might have run into this and
notify that the given error message might be irrelevant.
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
ip/iplink.c | 35 ++++++++++++++++++++++++++++++++++-
1 file changed, 34 insertions(+), 1 deletion(-)
diff --git a/ip/iplink.c b/ip/iplink.c
index 5aff2fde38dae..f94fa96668d21 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -867,6 +867,33 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
return ret - argc;
}
+static bool link_name_is_standard(const char *type, const char *name)
+{
+ const struct {
+ const char *type;
+ const char *name;
+ } standard_links[] = {
+ { "dummy", "dummy0" },
+ { "ifb", "ifb0" },
+ { "ifb", "ifb1" },
+ { "bond", "bond0" },
+ { "ipip", "tunl0" },
+ { "gre", "gre0" },
+ { "gretap", "gretap0" },
+ { "vti", "ip_vti0" },
+ { "sit", "sit0" },
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(standard_links); i++) {
+ if (strcmp(type, standard_links[i].type) ||
+ strcmp(name, standard_links[i].name))
+ continue;
+ return true;
+ }
+ return false;
+}
+
static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
{
int len;
@@ -1007,8 +1034,14 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
return -1;
}
- if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) {
+ if (errno == EEXIST &&
+ flags & NLM_F_CREATE &&
+ link_name_is_standard(type, name))
+ fprintf(stderr,
+ "Note: Kernel might have created interface upon module load.\n");
return -2;
+ }
return 0;
}
--
2.13.1
^ permalink raw reply related
* Re: [PATCH net-next 10/11] net: dsa: mv88e6xxx: remove EEE support
From: Andrew Lunn @ 2017-08-01 17:27 UTC (permalink / raw)
To: Florian Fainelli
Cc: Vivien Didelot, netdev, linux-kernel, kernel, David S. Miller
In-Reply-To: <17c26dee-c285-4dd5-1be0-286c0126d4db@gmail.com>
> If the MAC does not support EEE but the PHY does I think you can still
> allow EEE to be advertised and enabled, you just won't have the MAC be
> able to leverage the power savings that EEE brings. AFAICT this is still
> a valid mode whereby the PHY is put in a lower power mode, just not the
> whole transmit path (MAC + PHY).
Hi Florian
I read a couple of datasheets for a few phys doing EEE. Both said the
same, the MAC has to indicate to the PHY when low power should be
entered and existed. The PHY itself does not appear to do anything on
its own.
It would be good to read the standards about this. But i don't think
we should tell userspace EEE is enabled, if the PHY has it enabled,
but the MAC is not capable and hence EEE is not actually being used at
all.
Andrew
^ permalink raw reply
* Re: [PATCH net-next 4/6] tcp: remove header prediction
From: Neal Cardwell @ 2017-08-01 17:23 UTC (permalink / raw)
To: Florian Westphal; +Cc: Netdev, David Miller, Eric Dumazet, Yuchung Cheng
In-Reply-To: <20170730015723.25587-5-fw@strlen.de>
On Sat, Jul 29, 2017 at 9:57 PM, Florian Westphal <fw@strlen.de> wrote:
> @@ -5519,11 +5347,10 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb)
> if (sock_flag(sk, SOCK_KEEPOPEN))
> inet_csk_reset_keepalive_timer(sk, keepalive_time_when(tp));
>
> - if (!tp->rx_opt.snd_wscale)
> - __tcp_fast_path_on(tp, tp->snd_wnd);
> - else
> - tp->pred_flags = 0;
> -
> + if (!sock_flag(sk, SOCK_DEAD)) {
> + sk->sk_state_change(sk);
> + sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT);
> + }
> }
>
This patch hunk seems like it introduces a minor bug. It seems like
after this change, the sk_state_change() and sk_wake_async() calls for
a completed active connection happen twice: once in this new spot
inside tcp_finish_connect() and once in the existing code in
tcp_rcv_synsent_state_process() immediately after it calls
tcp_finish_connect().
I would vote for removing this new code snippet and retaining the old
one, in case there are subtle interactions with
tcp_rcv_fastopen_synack(), which happens in between the new wake-up
location and the old wake-up location.
neal
^ permalink raw reply
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