From: Alexander Lobakin <alexandr.lobakin@intel.com>
To: intel-wired-lan@osuosl.org
Subject: [Intel-wired-lan] [PATCH net-next 17/19] iecm: implement cloud filters
Date: Fri, 28 Jan 2022 20:38:09 +0100 [thread overview]
Message-ID: <20220128193809.30521-1-alexandr.lobakin@intel.com> (raw)
In-Reply-To: <20220128001009.721392-18-alan.brady@intel.com>
From: Alan Brady <alan.brady@intel.com>
Date: Thu, 27 Jan 2022 16:10:07 -0800
> This gives iecm the ability to deal with cloud filters and other traffic
> classes.
>
> Signed-off-by: Phani Burra <phani.r.burra@intel.com>
> Signed-off-by: Joshua Hay <joshua.a.hay@intel.com>
> Signed-off-by: Madhu Chittim <madhu.chittim@intel.com>
> Signed-off-by: Pavan Kumar Linga <pavan.kumar.linga@intel.com>
> Signed-off-by: Alan Brady <alan.brady@intel.com>
> ---
> drivers/net/ethernet/intel/iecm/iecm_lib.c | 900 +++++++++++++++++-
> .../net/ethernet/intel/iecm/iecm_virtchnl.c | 68 ++
> drivers/net/ethernet/intel/include/iecm.h | 25 +
> 3 files changed, 992 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/intel/iecm/iecm_lib.c b/drivers/net/ethernet/intel/iecm/iecm_lib.c
> index 35c0cbc42ebe..d11413cb438c 100644
> --- a/drivers/net/ethernet/intel/iecm/iecm_lib.c
> +++ b/drivers/net/ethernet/intel/iecm/iecm_lib.c
> @@ -43,9 +43,16 @@ static int iecm_get_vport_index(struct iecm_adapter *adapter,
> */
> bool iecm_is_feature_ena(struct iecm_vport *vport, netdev_features_t feature)
> {
> + struct iecm_channel_config *ch_config;
> bool ena;
>
> switch (feature) {
> + case NETIF_F_HW_TC:
> + ch_config = &vport->adapter->config_data.ch_config;
> + ena = (vport->netdev->features & feature) &&
> + (ch_config->num_tc > IECM_START_CHNL_TC) &&
> + (ch_config->tc_running);
> + break;
> default:
> ena = vport->netdev->features & feature;
> break;
> @@ -53,6 +60,23 @@ bool iecm_is_feature_ena(struct iecm_vport *vport, netdev_features_t feature)
> return ena;
> }
>
> +/**
> + * iecm_is_adq_v2_ena - Determine whether ADQ V2 is enabled
> + * @vport: virtual port struct
> + *
> + * This function returns true based on negotiated capability ADQ_V2
> + * if set and ADQ enabled
> + */
> +static bool iecm_is_adq_v2_ena(struct iecm_vport *vport)
> +{
> + /* iecm_is_feature_ena tells if the netdev flag is set and adq is
> + * enabled
> + */
> + return (iecm_is_feature_ena(vport, NETIF_F_HW_TC) &&
> + iecm_is_cap_ena(vport->adapter, IECM_OTHER_CAPS,
> + VIRTCHNL2_CAP_ADQ));
The outermost braces are redundant.
> +}
> +
> /**
> * iecm_is_vlan_cap_ena - Check if VLAN capability is enabled
> * @adapter: pointer to adapter
> @@ -946,6 +970,28 @@ static int iecm_get_free_slot(void *array, int size, int curr)
> return next;
> }
>
> +/**
> + * iecm_remove_cloud_filters - Remove all cloud filters
> + * @vport: vport structure
> + */
> +static void iecm_remove_cloud_filters(struct iecm_vport *vport)
> +{
> + struct iecm_adapter *adapter = vport->adapter;
> + struct iecm_cloud_filter_config *cf_config;
> +
> + cf_config = &adapter->config_data.cf_config;
> + if (!list_empty(&cf_config->cloud_filter_list)) {
> + struct iecm_cloud_filter *cf;
> +
> + spin_lock_bh(&adapter->cloud_filter_list_lock);
> + list_for_each_entry(cf, &cf_config->cloud_filter_list, list) {
> + cf->remove = true;
> + }
One-liner, braces are redundant.
> + spin_unlock_bh(&adapter->cloud_filter_list_lock);
> + iecm_send_add_del_cloud_filter_msg(vport, false);
> + }
if (list_empty())
return;
-1 level.
> +}
> +
> /**
> * iecm_remove_vlan_filters - Remove all vlan filters
> * @vport: vport structure
> @@ -1044,8 +1090,14 @@ static void iecm_vport_stop(struct iecm_vport *vport)
> if (test_and_clear_bit(__IECM_DEL_QUEUES,
> vport->adapter->flags))
> iecm_send_delete_queues_msg(vport);
> - if (!test_bit(__IECM_REL_RES_IN_PROG, adapter->flags))
> + /* In function reset/rmmod path we call unregister_netdev which
> + * internally calls delete cloud filters. We remove cloud filters only
> + * when the interface goes down
> + */
> + if (!test_bit(__IECM_REL_RES_IN_PROG, adapter->flags)) {
> + iecm_remove_cloud_filters(vport);
> iecm_remove_vlan_filters(vport);
> + }
>
> iecm_remove_fdir_filters(vport);
>
> @@ -1258,6 +1310,28 @@ static void iecm_restore_vlans(struct iecm_vport *vport)
> iecm_set_all_vlans(vport);
> }
>
> +/**
> + * iecm_restore_cloud_filters - Restore cloud filters
> + * @vport: vport structure
> + */
> +static void iecm_restore_cloud_filters(struct iecm_vport *vport)
> +{
> + struct iecm_adapter *adapter = vport->adapter;
> + struct iecm_cloud_filter_config *cf_config;
> +
> + cf_config = &adapter->config_data.cf_config;
> + if (!list_empty(&cf_config->cloud_filter_list)) {
> + struct iecm_cloud_filter *cf;
> +
> + spin_lock_bh(&adapter->cloud_filter_list_lock);
> + list_for_each_entry(cf, &cf_config->cloud_filter_list, list) {
> + cf->add = true;
> + }
Same here for braces.
> + spin_unlock_bh(&adapter->cloud_filter_list_lock);
> + iecm_send_add_del_cloud_filter_msg(vport, true);
> + }
Same here for reducing indent level.
> +}
> +
> /**
> * iecm_restore_fdir_filters - Restore all Flow Director filters
> * @vport: vport structure
> @@ -1302,6 +1376,10 @@ static void iecm_restore_features(struct iecm_vport *vport)
> dev_info(&adapter->pdev->dev, "Failed to restore promiscuous settings\n");
> }
>
> + /* Restore cloud filters if ADQ is enabled */
> + if (iecm_is_feature_ena(vport, NETIF_F_HW_TC))
> + iecm_restore_cloud_filters(vport);
> +
> if (iecm_is_cap_ena(adapter, IECM_OTHER_CAPS, VIRTCHNL2_CAP_FDIR))
> iecm_restore_fdir_filters(vport);
> }
> @@ -2088,6 +2166,8 @@ int iecm_probe(struct pci_dev *pdev,
> spin_lock_init(&adapter->vlan_list_lock);
> spin_lock_init(&adapter->adv_rss_list_lock);
> spin_lock_init(&adapter->fdir_fltr_list_lock);
> + INIT_LIST_HEAD(&adapter->config_data.cf_config.cloud_filter_list);
> + INIT_LIST_HEAD(&adapter->config_data.cf_config.block_cb_list);
> INIT_LIST_HEAD(&adapter->config_data.mac_filter_list);
> INIT_LIST_HEAD(&adapter->config_data.vlan_filter_list);
> INIT_LIST_HEAD(&adapter->config_data.adv_rss_list);
> @@ -2389,6 +2469,810 @@ static int iecm_offload_txtime(struct iecm_vport *vport,
> return -EOPNOTSUPP;
> }
>
> +/**
> + * iecm_is_vlan_tc_filter_allowed - allowed to add tc-filter using VLAN
> + * @vport: vport structure
> + * @vlan: VLAN to verify
> + *
> + * Using specified "vlan" ID, there must be active VLAN filter in VF's
> + * MAC-VLAN filter list.
> + */
> +static bool
> +iecm_is_vlan_tc_filter_allowed(struct iecm_vport *vport,
> + struct iecm_vlan *vlan)
> +{
> + struct iecm_vlan_filter *f;
> + bool allowed;
> +
> + spin_lock_bh(&vport->adapter->vlan_list_lock);
> + f = iecm_find_vlan(vport, vlan);
> + allowed = (f && !f->add && !f->remove);
Redundant braces here.
> + spin_unlock_bh(&vport->adapter->vlan_list_lock);
> + return allowed;
> +}
> +
> +/**
> + * iecm_is_mac_tc_filter_allowed - allowed to add tc-filter using MAC addr
> + * @vport: vport structure
> + * @macaddr: MAC address
> + *
> + * Using specified MAC address, there must be active MAC filter in
> + * MAC filter list.
> + */
> +static bool
> +iecm_is_mac_tc_filter_allowed(struct iecm_vport *vport, const u8 *macaddr)
> +{
> + struct iecm_adapter *adapter = vport->adapter;
> + struct iecm_mac_filter *f;
> + bool allowed;
> +
> + spin_lock_bh(&adapter->mac_filter_list_lock);
> + f = iecm_find_mac_filter(vport, macaddr);
> + allowed = (f && !f->add && !f->remove);
Same here.
> + spin_unlock_bh(&adapter->mac_filter_list_lock);
> + return allowed;
> +}
> +
> +/**
> + * iecm_parse_keyid - Parse keyid
> + * @rule: Flow rule structure
> + * @field_flags: Cloud filter flags
> + */
> +static void iecm_parse_keyid(struct flow_rule *rule, u8 *field_flags)
> +{
> + struct flow_match_enc_keyid match;
> +
> + flow_rule_match_enc_keyid(rule, &match);
> +
> + if (match.mask->keyid != 0)
> + *field_flags |= IECM_CLOUD_FIELD_TEN_ID;
> +}
> +
> +/**
> + * iecm_parse_flow_type - Parse flow type based on L2 and L3 protocols
> + * @vport: vport structure
> + * @rule: rule from user
> + * @cf: Structure for the virtchnl filter
> + * @filter: Structure for the cloud filter
> + *
> + * Return 0 on success, negative on failure
> + */
> +static int
> +iecm_parse_flow_type(struct iecm_vport *vport,
> + struct flow_rule *rule, struct virtchnl_filter *cf,
> + struct iecm_cloud_filter *filter)
> +{
> + struct iecm_adapter *adapter = vport->adapter;
> + enum virtchnl_flow_type flow_type;
> + struct flow_match_basic match;
> + u16 n_proto_mask = 0;
> + u16 n_proto_key = 0;
> + u16 n_proto = 0;
> + u8 ip_proto = 0;
> +
> + flow_rule_match_basic(rule, &match);
> +
> + n_proto_key = ntohs(match.key->n_proto);
> + n_proto_mask = ntohs(match.mask->n_proto);
> +
> + if (n_proto_key == ETH_P_ALL) {
> + n_proto_key = 0;
> + n_proto_mask = 0;
> + }
n_proto_key = ntohs();
if (n_proto_key != ETH_P_ALL)
n_proto_mask = ntohs();
> + n_proto = n_proto_key & n_proto_mask;
> + if (n_proto != ETH_P_IP && n_proto != ETH_P_IPV6)
> + return -EINVAL;
> +
> + if (iecm_is_cap_ena(adapter, IECM_OTHER_CAPS, VIRTCHNL2_CAP_ADQ)) {
> + if (match.key->ip_proto != IPPROTO_TCP &&
> + match.key->ip_proto != IPPROTO_UDP) {
> + dev_err(&adapter->pdev->dev,
> + "Only TCP or UDP transport is supported\n");
> + return -EINVAL;
> + }
> + } else if (match.key->ip_proto != IPPROTO_TCP) {
> + dev_err(&adapter->pdev->dev,
> + "Only TCP transport is supported\n");
> + return -EINVAL;
> + }
> + ip_proto = match.key->ip_proto;
> +
> + /* determine VIRTCHNL flow_type based on L3 and L4 protocol */
> + if (n_proto == ETH_P_IP)
> + flow_type = (ip_proto == IPPROTO_TCP) ?
> + VIRTCHNL_TCP_V4_FLOW :
> + VIRTCHNL_UDP_V4_FLOW;
> + else
> + flow_type = (ip_proto == IPPROTO_TCP) ?
> + VIRTCHNL_TCP_V6_FLOW :
> + VIRTCHNL_UDP_V6_FLOW;
> + cf->flow_type = flow_type;
> + filter->f.flow_type = flow_type;
> +
> + return 0;
> +}
> +
> +/**
> + * iecm_parse_ether_header - Parse ethernet header fields
> + * @vport: vport structure
> + * @field_flags: Cloud filter flags
> + * @d_spec: Virtchnl structure for L4 specs
> + * @m_spec: Virtchnl structure for L4 specs
> + * @rule: Flow rule structure
> + *
> + * Return 0 on success, negative on failure
> + */
> +static int
> +iecm_parse_ether_header(struct iecm_vport *vport, u8 *field_flags,
> + struct virtchnl_l4_spec *d_spec,
> + struct virtchnl_l4_spec *m_spec,
> + struct flow_rule *rule)
> +{
> + struct iecm_adapter *adapter = vport->adapter;
> + struct flow_match_eth_addrs match;
> + bool adv_adq_ena;
> +
> + adv_adq_ena = iecm_is_cap_ena(adapter, IECM_OTHER_CAPS,
> + VIRTCHNL2_CAP_ADQ);
> +
> + flow_rule_match_eth_addrs(rule, &match);
> +
> + /* use is_broadcast and is_zero to check for all 0xf or 0 */
> + if (!is_zero_ether_addr(match.mask->dst)) {
> + if (adv_adq_ena || is_broadcast_ether_addr(match.mask->dst)) {
> + *field_flags |= IECM_CLOUD_FIELD_OMAC;
> + } else {
> + dev_err(&adapter->pdev->dev, "Bad ether dest mask %pM\n",
> + match.mask->dst);
> + return -EINVAL;
> + }
> + }
> +
> + if (!is_zero_ether_addr(match.mask->src)) {
> + if (adv_adq_ena || is_broadcast_ether_addr(match.mask->src)) {
> + *field_flags |= IECM_CLOUD_FIELD_IMAC;
> + } else {
> + dev_err(&adapter->pdev->dev, "Bad ether src mask %pM\n",
> + match.mask->src);
> + return -EINVAL;
> + }
> + }
> +
> + if (!is_zero_ether_addr(match.key->dst)) {
> + if (!iecm_is_mac_tc_filter_allowed(adapter->vports[0],
> + match.key->dst)) {
> + dev_err(&adapter->pdev->dev,
> + "Dest MAC %pM doesn't belong to this device\n",
> + match.key->dst);
> + return -EINVAL;
> + }
> +
> + if (is_valid_ether_addr(match.key->dst) ||
> + is_multicast_ether_addr(match.key->dst)) {
> + /* set the mask if a valid dst_mac address */
> + if (adv_adq_ena)
> + ether_addr_copy(m_spec->dst_mac,
> + match.mask->dst);
> + else
> + eth_broadcast_addr(m_spec->dst_mac);
> + ether_addr_copy(d_spec->dst_mac,
> + match.key->dst);
> + }
> + }
> +
> + if (!is_zero_ether_addr(match.key->src))
> + if (is_valid_ether_addr(match.key->src) ||
> + is_multicast_ether_addr(match.key->src)) {
> + /* set the mask if a valid src_mac address */
> + if (adv_adq_ena) {
> + ether_addr_copy(m_spec->src_mac,
> + match.mask->src);
> + } else {
> + eth_broadcast_addr(m_spec->src_mac);
> + }
> + ether_addr_copy(d_spec->src_mac,
> + match.key->src);
> + }
All previous ifs had braces, and it way okay since we have multiple
nested if-elses, but here we don't have them.
Please either add them here or remove all the way above to keep the
code style consistent.
> + return 0;
> +}
> +
> +/**
> + * iecm_parse_vlan_header - Parse vlan header fields
> + * @vport: vport structure
> + * @field_flags: Cloud filter flags
> + * @d_spec: Virtchnl structure for L4 specs
> + * @m_spec: Virtchnl structure for L4 specs
> + * @rule: Flow rule structure
> + *
> + * Return 0 on success, negative on failure
> + */
> +static int
> +iecm_parse_vlan_header(struct iecm_vport *vport, u8 *field_flags,
> + struct virtchnl_l4_spec *d_spec,
> + struct virtchnl_l4_spec *m_spec,
> + struct flow_rule *rule)
> +{
> + struct iecm_adapter *adapter = vport->adapter;
> + struct flow_match_vlan match;
> +
> + flow_rule_match_vlan(rule, &match);
> + if (match.mask->vlan_id) {
> + u16 vid = match.key->vlan_id & VLAN_VID_MASK;
> + struct iecm_vlan vlan;
> +
> + vlan = IECM_VLAN(vid, ETH_P_8021Q);
> +
> + if (match.mask->vlan_id != VLAN_VID_MASK) {
> + dev_err(&adapter->pdev->dev, "Bad vlan mask %u\n",
> + match.mask->vlan_id);
> + return -EINVAL;
> + }
> + if (!iecm_is_vlan_tc_filter_allowed(vport, &vlan)) {
> + dev_err(&adapter->pdev->dev,
> + "VLAN %u doesn't belong to this VF\n",
> + vid);
> + return -EINVAL;
> + }
> + *field_flags |= IECM_CLOUD_FIELD_IVLAN;
> + m_spec->vlan_id = cpu_to_be16(match.mask->vlan_id);
> + d_spec->vlan_id = cpu_to_be16(match.key->vlan_id);
> + }
if (!vlan_id)
return 0;
-1 level.
> + return 0;
> +}
> +
> +/**
> + * iecm_parse_ipv4_header - Parse ipv4 header fields
> + * @vport: vport structure
> + * @field_flags: Cloud filter flags
> + * @d_spec: Virtchnl structure for L4 specs
> + * @m_spec: Virtchnl structure for L4 specs
> + * @rule: Flow rule structure
> + *
> + * Return 0 on success, negative on failure
> + */
> +static int
> +iecm_parse_ipv4_header(struct iecm_vport *vport, u8 *field_flags,
> + struct virtchnl_l4_spec *d_spec,
> + struct virtchnl_l4_spec *m_spec,
> + struct flow_rule *rule)
> +{
> + struct iecm_adapter *adapter = vport->adapter;
> + struct flow_match_ipv4_addrs match;
> + bool adv_adq_ena;
> +
> + adv_adq_ena = iecm_is_cap_ena(adapter, IECM_OTHER_CAPS,
> + VIRTCHNL2_CAP_ADQ);
> +
> + flow_rule_match_ipv4_addrs(rule, &match);
> +
> + if (*field_flags & IECM_CLOUD_FIELD_TEN_ID) {
> + dev_info(&adapter->pdev->dev,
> + "Tenant id not allowed for ip filter\n");
> + return -EINVAL;
> + }
> +
> + if (match.mask->dst) {
> + if (adv_adq_ena || match.mask->dst == cpu_to_be32(0xffffffff)) {
> + *field_flags |= IECM_CLOUD_FIELD_IIP;
> + } else {
> + dev_err(&adapter->pdev->dev, "Bad ip dst mask 0x%08x\n",
> + be32_to_cpu(match.mask->dst));
> + return -EINVAL;
> + }
> + }
> +
> + if (match.mask->src) {
> + if (adv_adq_ena || match.mask->src == cpu_to_be32(0xffffffff)) {
> + *field_flags |= IECM_CLOUD_FIELD_IIP;
> + } else {
> + dev_err(&adapter->pdev->dev, "Bad ip src mask 0x%08x\n",
> + be32_to_cpu(match.mask->dst));
> + return -EINVAL;
> + }
> + }
> +
> + if (match.key->dst) {
> + if (adv_adq_ena)
> + m_spec->dst_ip[0] = match.mask->dst;
> + else
> + m_spec->dst_ip[0] = cpu_to_be32(0xffffffff);
> + d_spec->dst_ip[0] = match.key->dst;
> + }
> +
> + if (match.key->src) {
> + if (adv_adq_ena)
> + m_spec->src_ip[0] = match.mask->src;
> + else
> + m_spec->src_ip[0] = cpu_to_be32(0xffffffff);
> + d_spec->src_ip[0] = match.key->src;
> + }
> + return 0;
> +}
> +
> +/**
> + * iecm_parse_ipv6_header - Parse ipv6 header fields
> + * @vport: vport structure
> + * @field_flags: Cloud filter flags
> + * @d_spec: Virtchnl structure for L4 specs
> + * @m_spec: Virtchnl structure for L4 specs
> + * @rule: Flow rule structure
> + *
> + * Return 0 on success, negative on failure
> + */
> +static int
> +iecm_parse_ipv6_header(struct iecm_vport *vport, u8 *field_flags,
> + struct virtchnl_l4_spec *d_spec,
> + struct virtchnl_l4_spec *m_spec,
> + struct flow_rule *rule)
> +{
> + struct iecm_adapter *adapter = vport->adapter;
> + struct flow_match_ipv6_addrs match;
> + int i;
> +
> + flow_rule_match_ipv6_addrs(rule, &match);
> +
> + /* validate mask, make sure it is not IPV6_ADDR_ANY */
> + if (ipv6_addr_any(&match.mask->dst)) {
> + dev_err(&adapter->pdev->dev, "Bad ipv6 dst mask 0x%02x\n",
> + IPV6_ADDR_ANY);
> + return -EINVAL;
> + }
> +
> + /* src and dest IPv6 address should not be LOOPBACK
> + * (0:0:0:0:0:0:0:1) which can be represented as ::1
> + */
> + if (ipv6_addr_loopback(&match.key->dst) ||
> + ipv6_addr_loopback(&match.key->src)) {
> + dev_err(&adapter->pdev->dev,
> + "ipv6 addr should not be loopback\n");
> + return -EINVAL;
> + }
> +
> + if (!ipv6_addr_any(&match.mask->dst) ||
> + !ipv6_addr_any(&match.mask->src))
> + *field_flags |= IECM_CLOUD_FIELD_IIP;
> +
> + /* copy dest IPv6 mask and address */
> + if (iecm_is_cap_ena(adapter, IECM_OTHER_CAPS, VIRTCHNL2_CAP_ADQ)) {
> + memcpy(&m_spec->dst_ip, &match.mask->dst.s6_addr32,
> + sizeof(m_spec->dst_ip));
> + } else {
> + for (i = 0; i < 4; i++)
> + m_spec->dst_ip[i] = cpu_to_be32(0xffffffff);
> + }
One-liners, no braces needed for both `if` and `else`.
> + memcpy(&d_spec->dst_ip, &match.key->dst.s6_addr32,
> + sizeof(d_spec->dst_ip));
> +
> + /* copy source IPv6 mask and address */
> + if (iecm_is_cap_ena(adapter, IECM_OTHER_CAPS, VIRTCHNL2_CAP_ADQ)) {
> + memcpy(&m_spec->src_ip, &match.mask->src.s6_addr32,
> + sizeof(m_spec->src_ip));
> + } else {
> + for (i = 0; i < 4; i++)
> + m_spec->src_ip[i] = cpu_to_be32(0xffffffff);
> + }
Same here.
> + memcpy(&d_spec->src_ip, &match.key->src.s6_addr32,
> + sizeof(d_spec->src_ip));
> +
> + return 0;
> +}
> +
> +/**
> + * iecm_parse_l4_header - Parse l4 header fields
> + * @vport: vport structure
> + * @d_spec: Virtchnl structure for L4 specs
> + * @m_spec: Virtchnl structure for L4 specs
> + * @rule: Flow rule structure
> + *
> + * Return 0 on success, negative on failure
> + */
> +static int
> +iecm_parse_l4_header(struct iecm_vport *vport,
> + struct virtchnl_l4_spec *d_spec,
> + struct virtchnl_l4_spec *m_spec,
> + struct flow_rule *rule)
> +{
> + struct iecm_adapter *adapter = vport->adapter;
> + struct flow_match_ports match;
> +
> + flow_rule_match_ports(rule, &match);
> +
> + if (match.key->dst) {
> + if (iecm_is_cap_ena(adapter, IECM_OTHER_CAPS,
> + VIRTCHNL2_CAP_ADQ) ||
> + match.mask->dst == cpu_to_be16(0xffff)) {
> + m_spec->dst_port = match.mask->dst;
> + d_spec->dst_port = match.key->dst;
> + } else {
> + dev_err(&adapter->pdev->dev, "Bad dst port mask %u\n",
> + be16_to_cpu(match.mask->dst));
> + return -EINVAL;
> + }
> + }
> +
> + if (match.key->src) {
> + if (iecm_is_cap_ena(adapter, IECM_OTHER_CAPS,
> + VIRTCHNL2_CAP_ADQ) ||
> + match.mask->src == cpu_to_be16(0xffff)) {
> + m_spec->src_port = match.mask->src;
> + d_spec->src_port = match.key->src;
> + } else {
> + dev_err(&adapter->pdev->dev, "Bad src port mask %u\n",
> + be16_to_cpu(match.mask->src));
> + return -EINVAL;
> + }
> + }
> + return 0;
> +}
> +
> +/**
> + * iecm_parse_cls_flower - Parse tc flower filters provided by kernel
> + * @vport: vport structure
> + * @f: pointer to struct flow_cls_offload
> + * @filter: pointer to cloud filter structure
> + */
> +static int iecm_parse_cls_flower(struct iecm_vport *vport,
> + struct flow_cls_offload *f,
> + struct iecm_cloud_filter *filter)
> +{
> + struct flow_rule *rule = flow_cls_offload_flow_rule(f);
> + struct iecm_adapter *adapter = vport->adapter;
> + struct virtchnl_l4_spec *d_spec, *m_spec;
> + struct virtchnl_filter *cf = &filter->f;
> + struct flow_dissector *dissector;
> + u8 field_flags = 0;
> + u16 addr_type = 0;
> + int err;
> +
> + dissector = rule->match.dissector;
> + if (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_ENC_KEYID) |
> + BIT(FLOW_DISSECTOR_KEY_PORTS))) {
> + dev_err(&adapter->pdev->dev, "Unsupported key used: 0x%x\n",
> + dissector->used_keys);
> + return -EOPNOTSUPP;
> + }
> + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID))
> + iecm_parse_keyid(rule, &field_flags);
> +
> + /* even though following code refers as "tcp_sec", it is not
> + * just for TCP but a generic struct representing
> + * L2, L3 + L4 fields if specified
> + */
> + m_spec = &cf->mask.tcp_spec;
> + d_spec = &cf->data.tcp_spec;
> +
> + /* determine flow type, TCP/UDP_V4[6]_FLOW based on
> + * L2 proto (aka ETH proto) and L3 proto (aka IP_PROTO)
> + */
> + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
> + err = iecm_parse_flow_type(vport, rule, cf, filter);
> + if (err)
> + return err;
> + }
> +
> + /* process Ethernet header fields */
> + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
> + err = iecm_parse_ether_header(vport, &field_flags,
> + d_spec, m_spec, rule);
> + if (err)
> + return err;
> + }
> +
> + /* process VLAN header for single VLAN (type could be S/C-tag) */
> + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
> + err = iecm_parse_vlan_header(vport, &field_flags,
> + d_spec, m_spec, rule);
> + if (err)
> + return err;
> + }
> +
> + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
> + struct flow_match_control match;
> +
> + flow_rule_match_control(rule, &match);
> + addr_type = match.key->addr_type;
> + }
> +
> + /* process IPv4 header */
> + if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
> + err = iecm_parse_ipv4_header(vport, &field_flags,
> + d_spec, m_spec, rule);
> + if (err)
> + return err;
> + }
> +
> + /* process IPv6 header */
> + if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
> + err = iecm_parse_ipv6_header(vport, &field_flags,
> + d_spec, m_spec, rule);
> + if (err)
> + return err;
> + }
> +
> + /* process L4 header, supported L4 protocols are TCP and UDP */
> + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
> + err = iecm_parse_l4_header(vport, d_spec, m_spec, rule);
> + if (err)
> + return err;
> + }
> + cf->field_flags = field_flags;
> +
> + return 0;
> +}
> +
> +/**
> + * iecm_handle_tclass - Forward to a traffic class on the device
> + * @vport: vport structure
> + * @tc: traffic class index on the device
> + * @filter: pointer to cloud filter structure
> + *
> + * Return 0 on success, negative on failure
> + */
> +static int iecm_handle_tclass(struct iecm_vport *vport, int tc,
> + struct iecm_cloud_filter *filter)
> +{
> + struct iecm_adapter *adapter = vport->adapter;
> +
> + if (tc == 0)
> + return 0;
> + if ((!iecm_is_adq_v2_ena(vport)) &&
> + !filter->f.data.tcp_spec.dst_port) {
> + dev_err(&adapter->pdev->dev,
> + "Specify destination port to redirect to traffic class other than TC0\n");
> + return -EINVAL;
> + }
> + /* redirect to a traffic class on the same device */
> + filter->f.action = VIRTCHNL_ACTION_TC_REDIRECT;
> + filter->f.action_meta = tc;
> + return 0;
> +}
> +
> +/* iecm_find_cf - Find the cloud filter in the list
> + * @vport: vport structure
> + * @cookie: filter specific cookie
> + *
> + * Returns pointer to the filter object or NULL. Must be called while holding
> + * cloud_filter_list_lock.
> + */
> +static struct iecm_cloud_filter *iecm_find_cf(struct iecm_vport *vport,
> + unsigned long *cookie)
> +{
> + struct iecm_adapter *adapter = vport->adapter;
> + struct iecm_cloud_filter *filter = NULL;
> +
> + if (!cookie)
> + return NULL;
> +
> + list_for_each_entry(filter,
> + &adapter->config_data.cf_config.cloud_filter_list,
> + list) {
> + if (!memcmp(cookie, &filter->cookie, sizeof(filter->cookie)))
> + return filter;
> + }
Redundant braces round single statement.
> + return NULL;
> +}
> +
> +/**
> + * iecm_configure_clsflower - Add tc flower filters
> + * @vport: vport structure
> + * @cls_flower: Pointer to struct flow_cls_offload
> + *
> + * Return 0 on success, negative on failure
> + */
> +static int iecm_configure_clsflower(struct iecm_vport *vport,
> + struct flow_cls_offload *cls_flower)
> +{
> + struct iecm_adapter *adapter = vport->adapter;
> + struct iecm_user_config_data *config_data;
> + struct iecm_cloud_filter *filter = NULL;
> + int err;
> + int tc;
> +
> + config_data = &adapter->config_data;
> + tc = tc_classid_to_hwtc(vport->netdev, cls_flower->classid);
> + if (tc < 0) {
> + dev_err(&adapter->pdev->dev, "Invalid traffic class\n");
> + return -EINVAL;
> + }
> +
> +#define IECM_MAX_CLOUD_ADQ_FILTERS 128
> +
> + if (config_data->cf_config.num_cloud_filters >=
> + IECM_MAX_CLOUD_ADQ_FILTERS) {
> + dev_err(&adapter->pdev->dev,
> + "Unable to add filter (action is forward to TC), reached max allowed filters (%u)\n",
> + IECM_MAX_CLOUD_ADQ_FILTERS);
> + return -ENOSPC;
> + }
> +
> + /* bail out here if filter already exists */
> + spin_lock_bh(&adapter->cloud_filter_list_lock);
> + filter = iecm_find_cf(vport, &cls_flower->cookie);
> + if (filter) {
> + filter->remove = false;
> + dev_err(&adapter->pdev->dev, "Failed to add TC Flower filter, it already exists\n");
> + spin_unlock_bh(&adapter->cloud_filter_list_lock);
> + return -EEXIST;
> + }
> + spin_unlock_bh(&adapter->cloud_filter_list_lock);
> +
> + filter = kzalloc(sizeof(*filter), GFP_KERNEL);
> + if (!filter)
> + return -ENOMEM;
> +
> + filter->cookie = cls_flower->cookie;
> +
> + /* set the mask to all zeroes to begin with */
> + memset(&filter->f.mask.tcp_spec, 0, sizeof(struct virtchnl_l4_spec));
> +
> + /* start out with flow type and eth type IPv4 to begin with */
> + filter->f.flow_type = VIRTCHNL_TCP_V4_FLOW;
> + err = iecm_parse_cls_flower(vport, cls_flower, filter);
> + if (err)
> + goto error;
> +
> + err = iecm_handle_tclass(vport, tc, filter);
> + if (err)
> + goto error;
> +
> + /* add filter to the list */
> + spin_lock_bh(&adapter->cloud_filter_list_lock);
> + list_add_tail(&filter->list, &config_data->cf_config.cloud_filter_list);
> + filter->add = true;
> + spin_unlock_bh(&adapter->cloud_filter_list_lock);
> + err = iecm_send_add_del_cloud_filter_msg(vport, true);
> + spin_lock_bh(&adapter->cloud_filter_list_lock);
> + /* We have to find it again in case another thread has already
> + * deleted and kfreed it.
> + */
> + filter = iecm_find_cf(vport, &cls_flower->cookie);
> + if (filter && err) {
> + list_del(&filter->list);
> + spin_unlock_bh(&adapter->cloud_filter_list_lock);
> + goto error;
> + }
> + spin_unlock_bh(&adapter->cloud_filter_list_lock);
> +
> + config_data->cf_config.num_cloud_filters++;
> +error:
> + if (err)
> + kfree(filter);
> + return err;
> +}
> +
> +/**
> + * iecm_delete_clsflower - Remove tc flower filters
> + * @vport: vport structure
> + * @cls_flower: Pointer to struct flow_cls_offload
> + *
> + * Return 0 on success, negative on failure
> + */
> +static int iecm_delete_clsflower(struct iecm_vport *vport,
> + struct flow_cls_offload *cls_flower)
> +{
> + struct iecm_adapter *adapter = vport->adapter;
> + struct iecm_cloud_filter *filter = NULL;
> + int err = 0;
> +
> + spin_lock_bh(&adapter->cloud_filter_list_lock);
> + filter = iecm_find_cf(vport, &cls_flower->cookie);
> + if (filter) {
> + filter->remove = true;
> + adapter->config_data.cf_config.num_cloud_filters--;
> + } else if (adapter->config_data.cf_config.num_cloud_filters) {
> + /* "num_cloud_filters" can become zero if egress qdisc is
> + * detached as per design, driver deletes related filters
> + * when qdisc is detached to avoid stale filters, hence
> + * num_cloud_filters can become zero. But since netdev
> + * layer doesn't know that filters are deleted by driver
> + * implictly when egress qdisc is deleted, it sees filters
> + * being present and "in_hw". User can request delete
> + * of specific filter of detach ingress qdisc - in either of
> + * those operation, filter(s) won't be found in driver cache,
> + * hence instead of returning, let this function return SUCCESS
> + * Returning of err as -EINVAL is only applicable when
> + * unable to find filter and num_cloud_filters is non-zero
> + */
> + err = -EINVAL;
> + }
> + spin_unlock_bh(&adapter->cloud_filter_list_lock);
> +
> + if (filter) {
> + err = iecm_send_add_del_cloud_filter_msg(vport, false);
> + spin_lock_bh(&adapter->cloud_filter_list_lock);
> + /* It can happen that asynchronously the filter was already
> + * deleted from the list. Make sure it's still there and marked
> + * for remove under spinlock before actually trying to delete
> + * from list.
> + */
> + filter = iecm_find_cf(vport, &cls_flower->cookie);
> + if (filter) {
> + list_del(&filter->list);
> + kfree(filter);
> + }
> + spin_unlock_bh(&adapter->cloud_filter_list_lock);
> + }
if (!filter)
return err;
err = ...
-1 level.
> + return err;
> +}
> +
> +/**
> + * iecm_setup_tc_cls_flower - flower classifier offloads
> + * @vport: vport structure
> + * @cls_flower: pointer to struct flow_cls_offload
> + *
> + * Return 0 on success, negative on failure
> + */
> +static int iecm_setup_tc_cls_flower(struct iecm_vport *vport,
> + struct flow_cls_offload *cls_flower)
> +{
> + if (cls_flower->common.chain_index)
> + return -EOPNOTSUPP;
> +
> + switch (cls_flower->command) {
> + case FLOW_CLS_REPLACE:
> + return iecm_configure_clsflower(vport, cls_flower);
> + case FLOW_CLS_DESTROY:
> + return iecm_delete_clsflower(vport, cls_flower);
> + case FLOW_CLS_STATS:
> + return -EOPNOTSUPP;
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +/**
> + * iecm_setup_tc_block_cb - block callback for tc
> + * @type: type of offload
> + * @type_data: offload data
> + * @cb_priv: Private adapter structure
> + *
> + * This function is the block callback for traffic classes
> + * Return 0 on success, negative on failure
> + **/
> +static int iecm_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
> + void *cb_priv)
> +{
> + switch (type) {
> + case TC_SETUP_CLSFLOWER:
> + return iecm_setup_tc_cls_flower((struct iecm_vport *)cb_priv,
> + (struct flow_cls_offload *)
> + type_data);
Just dereference them in separate variables and they will fit into
one line. There shouldn't be any spaces or line breaks after a cast.
> + default:
> + return -EOPNOTSUPP;
> + }
> +}
> +
> +/**
> + * iecm_del_all_cloud_filters - delete all cloud filters on the traffic classes
> + * @vport: vport structure
> + *
> + * This function will loop through the list of cloud filters and deletes them.
> + **/
> +static void iecm_del_all_cloud_filters(struct iecm_vport *vport)
> +{
> + struct iecm_adapter *adapter = vport->adapter;
> + struct iecm_cloud_filter_config *cf_config;
> + struct iecm_cloud_filter *cf, *cftmp;
> +
> + cf_config = &adapter->config_data.cf_config;
> + spin_lock_bh(&adapter->cloud_filter_list_lock);
> + list_for_each_entry_safe(cf, cftmp,
> + &cf_config->cloud_filter_list,
> + list) {
> + list_del(&cf->list);
> + kfree(cf);
> + cf_config->num_cloud_filters--;
> + }
> + spin_unlock_bh(&adapter->cloud_filter_list_lock);
> +}
> +
> /**
> * iecm_validate_tx_bandwidth - validate the max Tx bandwidth
> * @vport: vport structure
> @@ -2596,6 +3480,7 @@ static int __iecm_setup_tc(struct iecm_vport *vport, void *type_data)
> netif_tx_stop_all_queues(netdev);
> netif_tx_disable(netdev);
> ret = iecm_send_disable_channels_msg(vport);
> + iecm_del_all_cloud_filters(vport);
> netif_tx_start_all_queues(netdev);
> if (!test_bit(__IECM_REL_RES_IN_PROG, adapter->flags) &&
> !ret) {
> @@ -2709,8 +3594,10 @@ static int iecm_setup_tc(struct net_device *netdev, enum tc_setup_type type,
> {
> struct iecm_vport *vport = iecm_netdev_to_vport(netdev);
> struct iecm_adapter *adapter = vport->adapter;
> + struct iecm_cloud_filter_config *cf_config;
> int err = 0;
>
> + cf_config = &adapter->config_data.cf_config;
> switch (type) {
> case TC_SETUP_QDISC_ETF:
> if (iecm_is_queue_model_split(vport->txq_model))
> @@ -2720,6 +3607,17 @@ static int iecm_setup_tc(struct net_device *netdev, enum tc_setup_type type,
> type_data);
> break;
> case TC_SETUP_BLOCK:
> + if (iecm_is_cap_ena(adapter, IECM_BASE_CAPS,
> + VIRTCHNL2_CAP_ADQ) ||
> + iecm_is_cap_ena(adapter, IECM_OTHER_CAPS,
> + VIRTCHNL2_CAP_ADQ)) {
> + err =
> + flow_block_cb_setup_simple((struct flow_block_offload *)
> + type_data,
> + &cf_config->block_cb_list,
> + iecm_setup_tc_block_cb,
> + vport, vport, true);
> + }
Invert the condition, and there'll be no line wraps (esp. if you
assign casted @type_data into a separate var).
> break;
> case TC_SETUP_QDISC_MQPRIO:
> if (iecm_is_cap_ena(adapter, IECM_BASE_CAPS,
> diff --git a/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c b/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c
> index 5601846b4674..94af45c36866 100644
> --- a/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c
> +++ b/drivers/net/ethernet/intel/iecm/iecm_virtchnl.c
> @@ -2731,6 +2731,74 @@ static int iecm_send_insert_vlan_msg(struct iecm_vport *vport, bool ena)
> return err;
> }
>
> +/**
> + * iecm_send_add_del_cloud_filter_msg: Send add/del cloud filter message
> + * @vport: vport structure
> + * @add: True to add, false to delete cloud filter
> + *
> + * Request the CP/PF to add/del cloud filters as specified by the user via
> + * tc tool
> + *
> + * Return 0 on success, negative on failure
> + **/
> +int iecm_send_add_del_cloud_filter_msg(struct iecm_vport *vport, bool add)
> +{
> + struct iecm_adapter *adapter = vport->adapter;
> + struct iecm_cloud_filter_config *cf_config;
> + struct iecm_cloud_filter *cf;
> + struct virtchnl_filter f;
> + int len = 0, err = 0;
> +
> + cf_config = &adapter->config_data.cf_config;
> +
> + while (true) {
> + bool process_fltr = false;
> +
> + spin_lock_bh(&adapter->cloud_filter_list_lock);
> + list_for_each_entry(cf, &cf_config->cloud_filter_list, list) {
> + if (add && cf->add) {
> + process_fltr = true;
> + cf->add = false;
> + f = cf->f;
> + break;
> + } else if (!add && cf->remove) {
> + process_fltr = true;
> + cf->remove = false;
> + f = cf->f;
> + break;
> + }
> + }
Redundant braces.
> + spin_unlock_bh(&adapter->cloud_filter_list_lock);
> +
> + /* Don't send mailbox message when there are no filters to add/del */
> + if (!process_fltr)
> + goto error;
> +
> + if (add) {
> + err = iecm_send_mb_msg(adapter, VIRTCHNL_OP_ADD_CLOUD_FILTER,
> + len, (u8 *)&f);
> + if (err)
> + goto error;
> +
> + err = iecm_wait_for_event(adapter, IECM_VC_ADD_CLOUD_FILTER,
> + IECM_VC_ADD_CLOUD_FILTER_ERR);
> + } else {
> + err = iecm_send_mb_msg(adapter, VIRTCHNL_OP_DEL_CLOUD_FILTER,
> + len, (u8 *)&f);
> + if (err)
> + goto error;
> +
> + err =
> + iecm_min_wait_for_event(adapter, IECM_VC_DEL_CLOUD_FILTER,
> + IECM_VC_DEL_CLOUD_FILTER_ERR);
Too long lines here.
> + }
> + if (err)
> + break;
> + }
> +error:
> + return err;
> +}
> +
> /**
> * iecm_send_add_fdir_filter_msg: Send add Flow Director filter message
> * @vport: vport structure
> diff --git a/drivers/net/ethernet/intel/include/iecm.h b/drivers/net/ethernet/intel/include/iecm.h
> index b0785684cc63..0aab41cf982c 100644
> --- a/drivers/net/ethernet/intel/include/iecm.h
> +++ b/drivers/net/ethernet/intel/include/iecm.h
> @@ -403,6 +403,28 @@ enum iecm_user_flags {
> __IECM_USER_FLAGS_NBITS,
> };
>
> +#define IECM_CLOUD_FIELD_OMAC BIT(0)
> +#define IECM_CLOUD_FIELD_IMAC BIT(1)
> +#define IECM_CLOUD_FIELD_IVLAN BIT(2)
> +#define IECM_CLOUD_FIELD_TEN_ID BIT(3)
> +#define IECM_CLOUD_FIELD_IIP BIT(4)
> +
> +#define IECM_START_CHNL_TC 1
> +
> +struct iecm_cloud_filter {
> + struct list_head list;
> + struct virtchnl_filter f;
> + unsigned long cookie;
> + bool remove; /* filter needs to be deleted */
> + bool add; /* filter needs to be added */
> +};
> +
> +struct iecm_cloud_filter_config {
> + struct list_head block_cb_list; /* need to pass this to stack */
> + struct list_head cloud_filter_list;
> + u16 num_cloud_filters;
> +};
> +
> struct iecm_channel_config {
> struct virtchnl_channel_info ch_info[VIRTCHNL_MAX_ADQ_V2_CHANNELS];
> bool tc_running;
> @@ -536,6 +558,7 @@ struct iecm_ptype_state {
> bool outer_frag;
> u8 tunnel_state;
> };
> +
Please move this newline into the patch where iecm_ptype_state was
introduced, it doesn't belong here.
> /* User defined configuration values */
> struct iecm_user_config_data {
> u32 num_req_tx_qs; /* user requested TX queues through ethtool */
> @@ -550,6 +573,7 @@ struct iecm_user_config_data {
> struct list_head vlan_filter_list;
> struct list_head adv_rss_list;
> struct iecm_fdir_fltr_config fdir_config;
> + struct iecm_cloud_filter_config cf_config;
> struct iecm_channel_config ch_config;
> };
>
> @@ -853,6 +877,7 @@ void iecm_set_ethtool_ops(struct net_device *netdev);
> void iecm_vport_set_hsplit(struct iecm_vport *vport, bool ena);
> void iecm_add_del_ether_addrs(struct iecm_vport *vport, bool add, bool async);
> int iecm_set_promiscuous(struct iecm_adapter *adapter);
> +int iecm_send_add_del_cloud_filter_msg(struct iecm_vport *vport, bool add);
> int iecm_send_add_fdir_filter_msg(struct iecm_vport *vport);
> int iecm_send_del_fdir_filter_msg(struct iecm_vport *vport);
> int iecm_get_fdir_fltr_entry(struct iecm_vport *vport,
> --
> 2.33.0
Thanks,
Al
next prev parent reply other threads:[~2022-01-28 19:38 UTC|newest]
Thread overview: 83+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-01-28 0:09 [Intel-wired-lan] [PATCH net-next 00/19] Add iecm and idpf Alan Brady
2022-01-28 0:09 ` [Intel-wired-lan] [PATCH net-next 01/19] virtchnl: Add new virtchnl2 ops Alan Brady
2022-02-02 22:13 ` Brady, Alan
2022-01-28 0:09 ` [Intel-wired-lan] [PATCH net-next 02/19] iecm: add basic module init and documentation Alan Brady
2022-01-28 11:56 ` Alexander Lobakin
2022-02-02 22:15 ` Brady, Alan
2022-02-01 19:44 ` Shannon Nelson
2022-02-03 3:08 ` Brady, Alan
2022-01-28 0:09 ` [Intel-wired-lan] [PATCH net-next 03/19] iecm: add probe and remove Alan Brady
2022-02-01 20:02 ` Shannon Nelson
2022-02-03 3:13 ` Brady, Alan
2022-01-28 0:09 ` [Intel-wired-lan] [PATCH net-next 04/19] iecm: add api_init and controlq init Alan Brady
2022-01-28 12:09 ` Alexander Lobakin
2022-02-02 22:16 ` Brady, Alan
2022-02-01 21:26 ` Shannon Nelson
2022-02-03 3:24 ` Brady, Alan
2022-02-03 3:40 ` Brady, Alan
2022-02-03 5:26 ` Shannon Nelson
2022-02-03 13:13 ` Alexander Lobakin
2022-01-28 0:09 ` [Intel-wired-lan] [PATCH net-next 05/19] iecm: add vport alloc and virtchnl messages Alan Brady
2022-01-28 4:19 ` kernel test robot
2022-01-28 12:39 ` Alexander Lobakin
2022-02-02 22:23 ` Brady, Alan
2022-01-28 12:32 ` Alexander Lobakin
2022-02-02 22:21 ` Brady, Alan
2022-02-03 13:23 ` Alexander Lobakin
2022-01-28 0:09 ` [Intel-wired-lan] [PATCH net-next 06/19] iecm: add virtchnl messages for queues Alan Brady
2022-01-28 13:03 ` Alexander Lobakin
2022-02-02 22:48 ` Brady, Alan
2022-02-03 10:08 ` Maciej Fijalkowski
2022-02-03 14:09 ` Alexander Lobakin
2022-01-28 0:09 ` [Intel-wired-lan] [PATCH net-next 07/19] iecm: finish virtchnl messages Alan Brady
2022-01-28 13:19 ` Alexander Lobakin
2022-02-02 23:06 ` Brady, Alan
2022-02-03 15:05 ` Alexander Lobakin
2022-02-03 15:16 ` Maciej Fijalkowski
2022-01-28 0:09 ` [Intel-wired-lan] [PATCH net-next 08/19] iecm: add interrupts and configure netdev Alan Brady
2022-01-28 13:34 ` Alexander Lobakin
2022-02-02 23:17 ` Brady, Alan
2022-02-03 15:55 ` Alexander Lobakin
2022-01-28 0:09 ` [Intel-wired-lan] [PATCH net-next 09/19] iecm: alloc vport TX resources Alan Brady
2022-02-02 23:45 ` Brady, Alan
2022-02-03 17:56 ` Alexander Lobakin
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 10/19] iecm: alloc vport RX resources Alan Brady
2022-01-28 14:16 ` Alexander Lobakin
2022-02-03 0:13 ` Brady, Alan
2022-02-03 18:29 ` Alexander Lobakin
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 11/19] iecm: add start_xmit and set_rx_mode Alan Brady
2022-01-28 16:35 ` Alexander Lobakin
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 12/19] iecm: finish netdev_ops Alan Brady
2022-01-28 17:06 ` Alexander Lobakin
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 13/19] iecm: implement splitq napi_poll Alan Brady
2022-01-28 5:21 ` kernel test robot
2022-01-28 17:44 ` Alexander Lobakin
2022-02-03 1:15 ` Brady, Alan
2022-01-28 17:38 ` Alexander Lobakin
2022-02-03 1:07 ` Brady, Alan
2022-02-04 11:50 ` Alexander Lobakin
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 14/19] iecm: implement singleq napi_poll Alan Brady
2022-01-28 17:57 ` Alexander Lobakin
2022-02-03 1:45 ` Brady, Alan
2022-02-03 19:05 ` Alexander Lobakin
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 15/19] iecm: implement ethtool callbacks Alan Brady
2022-01-28 18:13 ` Alexander Lobakin
2022-02-03 2:13 ` Brady, Alan
2022-02-03 19:54 ` Alexander Lobakin
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 16/19] iecm: implement flow director Alan Brady
2022-01-28 19:04 ` Alexander Lobakin
2022-02-03 2:41 ` Brady, Alan
2022-02-04 10:08 ` Alexander Lobakin
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 17/19] iecm: implement cloud filters Alan Brady
2022-01-28 19:38 ` Alexander Lobakin [this message]
2022-02-03 2:53 ` Brady, Alan
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 18/19] iecm: add advanced rss Alan Brady
2022-01-28 19:53 ` Alexander Lobakin
2022-02-03 2:55 ` Brady, Alan
2022-02-03 10:46 ` Maciej Fijalkowski
2022-02-04 10:22 ` Alexander Lobakin
2022-01-28 0:10 ` [Intel-wired-lan] [PATCH net-next 19/19] idpf: introduce idpf driver Alan Brady
2022-01-28 20:08 ` Alexander Lobakin
2022-02-03 3:07 ` Brady, Alan
2022-02-04 10:35 ` Alexander Lobakin
2022-02-04 12:05 ` [Intel-wired-lan] [PATCH net-next 00/19] Add iecm and idpf Alexander Lobakin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220128193809.30521-1-alexandr.lobakin@intel.com \
--to=alexandr.lobakin@intel.com \
--cc=intel-wired-lan@osuosl.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox