Netdev List
 help / color / mirror / Atom feed
* Re: [Intel-wired-lan] [PATCH 3/4] [next-queue]net: i40e: Enable mqprio full offload mode in the i40e driver for configuring TCs and queue mapping
From: Alexander Duyck @ 2017-05-24 22:05 UTC (permalink / raw)
  To: Amritha Nambiar; +Cc: intel-wired-lan, Netdev
In-Reply-To: <149524191318.11022.8959648104747338042.stgit@anamdev.jf.intel.com>

On Fri, May 19, 2017 at 5:58 PM, Amritha Nambiar
<amritha.nambiar@intel.com> wrote:
> The i40e driver is modified to enable the new mqprio hardware
> offload mode and factor the TCs and queue configuration by
> creating channel VSIs. In this mode, the priority to traffic
> class mapping and the user specified queue ranges are used
> to configure the traffic classes when the 'hw' option is set
> to 2.
>
> Example:
> # tc qdisc add dev eth0 root mqprio num_tc 4\
>   map 0 0 0 0 1 2 2 3 queues 2@0 2@2 1@4 1@5 hw 2
>
> # tc qdisc show dev eth0
> qdisc mqprio 8038: root  tc 4 map 0 0 0 0 1 2 2 3 0 0 0 0 0 0 0 0
>              queues:(0:1) (2:3) (4:4) (5:5)
>
> The HW channels created are removed and all the queue configuration
> is set to default when the qdisc is detached from the root of the
> device.
>
> #tc qdisc del dev eth0 root
>
> This patch also disables setting up channels via ethtool (ethtool -L)
> when the TCs are confgured using mqprio scheduler.
>
> Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
> ---
>  drivers/net/ethernet/intel/i40e/i40e.h         |    4
>  drivers/net/ethernet/intel/i40e/i40e_ethtool.c |    6
>  drivers/net/ethernet/intel/i40e/i40e_main.c    |  311 ++++++++++++++++++++++--
>  3 files changed, 292 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
> index 0915b02..a62f65a 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e.h
> +++ b/drivers/net/ethernet/intel/i40e/i40e.h
> @@ -54,6 +54,8 @@
>  #include <linux/clocksource.h>
>  #include <linux/net_tstamp.h>
>  #include <linux/ptp_clock_kernel.h>
> +#include <net/pkt_cls.h>
> +
>  #include "i40e_type.h"
>  #include "i40e_prototype.h"
>  #include "i40e_client.h"
> @@ -685,6 +687,7 @@ struct i40e_vsi {
>         enum i40e_vsi_type type;  /* VSI type, e.g., LAN, FCoE, etc */
>         s16 vf_id;              /* Virtual function ID for SRIOV VSIs */
>
> +       struct tc_mqprio_qopt_offload mqprio_qopt; /* queue parameters */
>         struct i40e_tc_configuration tc_config;
>         struct i40e_aqc_vsi_properties_data info;
>
> @@ -710,6 +713,7 @@ struct i40e_vsi {
>         u16 cnt_q_avail; /* num of queues available for channel usage */
>         u16 orig_rss_size;
>         u16 current_rss_size;
> +       bool reconfig_rss;
>
>         /* keeps track of next_base_queue to be used for channel setup */
>         atomic_t next_base_queue;
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
> index 3d58762..ab52979 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
> @@ -3841,6 +3841,12 @@ static int i40e_set_channels(struct net_device *dev,
>         if (vsi->type != I40E_VSI_MAIN)
>                 return -EINVAL;
>
> +       /* We do not support setting channels via ethtool when TCs are
> +        * configured through mqprio
> +        */
> +       if (pf->flags & I40E_FLAG_TC_MQPRIO)
> +               return -EINVAL;
> +
>         /* verify they are not requesting separate vectors */
>         if (!count || ch->rx_count || ch->tx_count)
>                 return -EINVAL;
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
> index e1bea45..7f61d4f 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
> @@ -68,6 +68,7 @@ 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_vsi_config_rss(struct i40e_vsi *vsi);
>
>  /* i40e_pci_tbl - PCI Device ID Table
>   *
> @@ -1560,6 +1561,105 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
>  }
>
>  /**
> + * i40e_vsi_setup_queue_map_mqprio - Prepares VSI tc_config to have queue
> + * configurations based on MQPRIO options.
> + * @vsi: the VSI being configured,
> + * @ctxt: VSI context structure
> + * @enabled_tc: number of traffic classes to enable
> + **/
> +static int i40e_vsi_setup_queue_map_mqprio(struct i40e_vsi *vsi,
> +                                          struct i40e_vsi_context *ctxt,
> +                                          u8 enabled_tc)
> +{
> +       u8 netdev_tc = 0, offset = 0;
> +       u16 qcount = 0, max_qcount, qmap, sections = 0;
> +       int i, override_q, pow, num_qps, ret;
> +
> +       if (vsi->type != I40E_VSI_MAIN)
> +               return -EINVAL;
> +
> +       sections = I40E_AQ_VSI_PROP_QUEUE_MAP_VALID;
> +       sections |= I40E_AQ_VSI_PROP_SCHED_VALID;
> +
> +       vsi->tc_config.numtc = vsi->mqprio_qopt.qopt.num_tc;
> +       vsi->tc_config.enabled_tc = enabled_tc ? enabled_tc : 1;
> +
> +       num_qps = vsi->mqprio_qopt.qopt.count[0];
> +
> +       /* find the next higher power-of-2 of num queue pairs */
> +       pow = ilog2(num_qps);
> +       if (!is_power_of_2(num_qps))
> +               pow++;
> +
> +       qmap = (offset << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
> +               (pow << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT);
> +
> +       /* Setup queue offset/count for all TCs for given VSI */
> +       max_qcount = vsi->mqprio_qopt.qopt.count[0];
> +
> +       for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
> +               /* See if the given TC is enabled for the given VSI */
> +               if (vsi->tc_config.enabled_tc & BIT(i)) {
> +                       offset = vsi->mqprio_qopt.qopt.offset[i];
> +                       qcount = vsi->mqprio_qopt.qopt.count[i];
> +
> +                       if (qcount > max_qcount)
> +                               max_qcount = qcount;
> +
> +                       vsi->tc_config.tc_info[i].qoffset = offset;
> +                       vsi->tc_config.tc_info[i].qcount = qcount;
> +                       vsi->tc_config.tc_info[i].netdev_tc = netdev_tc++;
> +
> +               } else {
> +                       /* TC is not enabled so set the offset to
> +                        * default queue and allocate one queue
> +                        * for the given TC.
> +                        */
> +                       vsi->tc_config.tc_info[i].qoffset = 0;
> +                       vsi->tc_config.tc_info[i].qcount = 1;
> +                       vsi->tc_config.tc_info[i].netdev_tc = 0;
> +               }
> +       }
> +
> +       /* Set actual Tx/Rx queue pairs */
> +       vsi->num_queue_pairs = offset + qcount;
> +
> +       /* Setup queue TC[0].qmap for given VSI context */
> +       ctxt->info.tc_mapping[0] = cpu_to_le16(qmap);
> +
> +       ctxt->info.mapping_flags |=
> +                                       cpu_to_le16(I40E_AQ_VSI_QUE_MAP_CONTIG);
> +
> +       ctxt->info.queue_mapping[0] = cpu_to_le16(vsi->base_queue);
> +       ctxt->info.valid_sections |= cpu_to_le16(sections);
> +
> +       /* Reconfigure RSS for main VSI with max queue count */
> +       vsi->rss_size = max_qcount;
> +
> +       ret = i40e_vsi_config_rss(vsi);
> +       if (ret) {
> +               dev_info(&vsi->back->pdev->dev,
> +                        "Failed to reconfig rss for num_queues (%u)\n",
> +                        max_qcount);
> +               return ret;
> +       }
> +       vsi->reconfig_rss = true;
> +       dev_dbg(&vsi->back->pdev->dev,
> +               "Reconfigured rss with num_queues (%u)\n", max_qcount);
> +
> +       /* Find queue count available for channel VSIs and starting offset
> +        * for channel VSIs
> +        */
> +       override_q = vsi->mqprio_qopt.qopt.count[0];
> +       if (override_q && (override_q < vsi->num_queue_pairs)) {
> +               vsi->cnt_q_avail = vsi->num_queue_pairs - override_q;
> +               atomic_set(&vsi->next_base_queue, override_q);
> +       }
> +
> +       return 0;
> +}
> +
> +/**
>   * i40e_vsi_setup_queue_map - Setup a VSI queue map based on enabled_tc
>   * @vsi: the VSI being setup
>   * @ctxt: VSI context structure
> @@ -1597,7 +1697,7 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
>                         numtc = 1;
>                 }
>         } else {
> -               /* At least TC0 is enabled in case of non-DCB case */
> +               /* At least TC0 is enabled in non-DCB, non-MQPRIO case */
>                 numtc = 1;
>         }
>
> @@ -3150,6 +3250,7 @@ static void i40e_vsi_config_dcb_rings(struct i40e_vsi *vsi)
>                         rx_ring->dcb_tc = 0;
>                         tx_ring->dcb_tc = 0;
>                 }
> +               return;
>         }
>
>         for (n = 0; n < I40E_MAX_TRAFFIC_CLASS; n++) {
> @@ -4777,6 +4878,25 @@ static u8 i40e_dcb_get_enabled_tc(struct i40e_dcbx_config *dcbcfg)
>  }
>
>  /**
> + * i40e_mqprio_get_enabled_tc - Get enabled traffic classes
> + * @pf: PF being queried
> + *
> + * Query the current MQPRIO configuration and return the number of
> + * traffic classes enabled.
> + **/
> +static u8 i40e_mqprio_get_enabled_tc(struct i40e_pf *pf)
> +{
> +       struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
> +       u8 num_tc = vsi->mqprio_qopt.qopt.num_tc;
> +       u8 enabled_tc = 1, i;
> +
> +       for (i = 1; i < num_tc; i++)
> +               enabled_tc |= BIT(i);
> +
> +       return enabled_tc;
> +}
> +
> +/**
>   * i40e_pf_get_num_tc - Get enabled traffic classes for PF
>   * @pf: PF being queried
>   *
> @@ -4789,7 +4909,10 @@ static u8 i40e_pf_get_num_tc(struct i40e_pf *pf)
>         u8 num_tc = 0;
>         struct i40e_dcbx_config *dcbcfg = &hw->local_dcbx_config;
>
> -       /* If DCB is not enabled then always in single TC */
> +       if (pf->flags & I40E_FLAG_TC_MQPRIO)
> +               return pf->vsi[pf->lan_vsi]->mqprio_qopt.qopt.num_tc;
> +
> +       /* If neither MQPRIO nor DCB is enabled, then always in single TC */
>         if (!(pf->flags & I40E_FLAG_DCB_ENABLED))
>                 return 1;
>
> @@ -4818,7 +4941,12 @@ static u8 i40e_pf_get_num_tc(struct i40e_pf *pf)
>   **/
>  static u8 i40e_pf_get_tc_map(struct i40e_pf *pf)
>  {
> -       /* If DCB is not enabled for this PF then just return default TC */
> +       if (pf->flags & I40E_FLAG_TC_MQPRIO)
> +               return i40e_mqprio_get_enabled_tc(pf);
> +
> +       /* If neither MQPRIO nor DCB is enabled for this PF then just return
> +        * default TC
> +        */
>         if (!(pf->flags & I40E_FLAG_DCB_ENABLED))
>                 return I40E_DEFAULT_TRAFFIC_CLASS;
>
> @@ -4912,6 +5040,10 @@ static int i40e_vsi_configure_bw_alloc(struct i40e_vsi *vsi, u8 enabled_tc,
>         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
>                 bw_data.tc_bw_credits[i] = bw_share[i];
>
> +       if ((vsi->back->flags & I40E_FLAG_TC_MQPRIO) ||
> +           !vsi->mqprio_qopt.qopt.hw)
> +               return 0;
> +
>         ret = i40e_aq_config_vsi_tc_bw(&vsi->back->hw, vsi->seid, &bw_data,
>                                        NULL);
>         if (ret) {
> @@ -4970,6 +5102,9 @@ static void i40e_vsi_config_netdev_tc(struct i40e_vsi *vsi, u8 enabled_tc)
>                                         vsi->tc_config.tc_info[i].qoffset);
>         }
>
> +       if (pf->flags & I40E_FLAG_TC_MQPRIO)
> +               return;
> +
>         /* Assign UP2TC map for the VSI */
>         for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
>                 /* Get the actual TC# for the UP */
> @@ -5020,7 +5155,8 @@ static int i40e_vsi_config_tc(struct i40e_vsi *vsi, u8 enabled_tc)
>         int i;
>
>         /* Check if enabled_tc is same as existing or new TCs */
> -       if (vsi->tc_config.enabled_tc == enabled_tc)
> +       if (vsi->tc_config.enabled_tc == enabled_tc &&
> +           vsi->mqprio_qopt.qopt.hw != TC_MQPRIO_HW_OFFLOAD)
>                 return ret;
>
>         /* Enable ETS TCs with equal BW Share for now across all VSIs */
> @@ -5043,7 +5179,30 @@ static int i40e_vsi_config_tc(struct i40e_vsi *vsi, u8 enabled_tc)
>         ctxt.vf_num = 0;
>         ctxt.uplink_seid = vsi->uplink_seid;
>         ctxt.info = vsi->info;
> -       i40e_vsi_setup_queue_map(vsi, &ctxt, enabled_tc, false);
> +
> +       if (vsi->back->flags & I40E_FLAG_TC_MQPRIO) {
> +               ret = i40e_vsi_setup_queue_map_mqprio(vsi, &ctxt, enabled_tc);
> +               if (ret)
> +                       goto out;
> +
> +       } else {
> +               i40e_vsi_setup_queue_map(vsi, &ctxt, enabled_tc, false);
> +       }
> +
> +       /* On destroying the qdisc, reset vsi->rss_size, as number of enabled
> +        * queues changed.
> +        */
> +       if (!vsi->mqprio_qopt.qopt.hw && vsi->reconfig_rss) {
> +               vsi->rss_size = min_t(int, vsi->back->alloc_rss_size,
> +                                     vsi->num_queue_pairs);
> +               ret = i40e_vsi_config_rss(vsi);
> +               if (ret) {
> +                       dev_info(&vsi->back->pdev->dev,
> +                                "Failed to reconfig rss for num_queues\n");
> +                       return ret;
> +               }
> +               vsi->reconfig_rss = false;
> +       }
>
>         if (vsi->back->flags & I40E_FLAG_IWARP_ENABLED) {
>                 ctxt.info.valid_sections |=
> @@ -5051,7 +5210,9 @@ static int i40e_vsi_config_tc(struct i40e_vsi *vsi, u8 enabled_tc)
>                 ctxt.info.queueing_opt_flags |= I40E_AQ_VSI_QUE_OPT_TCP_ENA;
>         }
>
> -       /* Update the VSI after updating the VSI queue-mapping information */
> +       /* Update the VSI after updating the VSI queue-mapping
> +        * information
> +        */
>         ret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL);
>         if (ret) {
>                 dev_info(&vsi->back->pdev->dev,
> @@ -6168,48 +6329,142 @@ void i40e_down(struct i40e_vsi *vsi)
>  }
>
>  /**
> + * i40e_validate_mqprio_queue_mapping - validate queue mapping info
> + * @vsi: the VSI being configured
> + * @mqprio_qopt: queue parametrs
> + **/
> +int i40e_validate_mqprio_queue_mapping(struct i40e_vsi *vsi,
> +                               struct tc_mqprio_qopt_offload *mqprio_qopt)

So I see a few issues with this. From what I can tell this can be
static. Second is that it is triggering a check in checkpatch for
unaligned parameters.

I would recommend using the gcc coding style if needed so that you
could move the "static int" into a separate line if needed in order to
avoid issues with the line being too long. In addition you might look
at reducing the length of the function name if you still have issues
with being over 80 characters. Maybe something like
i40e_validate_mqprio_qopt instead of calling out the mapping and all
that since it seems like most of this is just about validating the
qopt fields provided in the mqprio_qopt structure anyway.

> +{
> +       int i;
> +
> +       if ((mqprio_qopt->qopt.offset[0] != 0) ||
> +           (mqprio_qopt->qopt.num_tc < 1))
> +               return -EINVAL;
> +
> +       for (i = 0; ; i++) {
> +               if (!mqprio_qopt->qopt.count[i])
> +                       return -EINVAL;
> +
> +               if (mqprio_qopt->min_rate[i] || mqprio_qopt->max_rate[i])
> +                       return -EINVAL;
> +
> +               if (i >= mqprio_qopt->qopt.num_tc - 1)
> +                       break;
> +
> +               if (mqprio_qopt->qopt.offset[i + 1] !=
> +                   (mqprio_qopt->qopt.offset[i] + mqprio_qopt->qopt.count[i]))
> +                       return -EINVAL;
> +       }
> +
> +       if (vsi->num_queue_pairs <
> +           (mqprio_qopt->qopt.offset[i] + mqprio_qopt->qopt.count[i])) {
> +               return -EINVAL;
> +       }
> +
> +       return 0;
> +}
> +
> +/**
>   * i40e_setup_tc - configure multiple traffic classes
>   * @netdev: net device to configure
> - * @tc: number of traffic classes to enable
> + * @tc: pointer to struct tc_to_netdev
>   **/
> -static int i40e_setup_tc(struct net_device *netdev, u8 tc)
> +static int i40e_setup_tc(struct net_device *netdev, struct tc_to_netdev *tc)
>  {
>         struct i40e_netdev_priv *np = netdev_priv(netdev);
>         struct i40e_vsi *vsi = np->vsi;
>         struct i40e_pf *pf = vsi->back;
> -       u8 enabled_tc = 0;
> +       u8 enabled_tc = 0, num_tc = 0, hw = 0;
>         int ret = -EINVAL;
>         int i;
>
> -       /* Check if DCB enabled to continue */
> -       if (!(pf->flags & I40E_FLAG_DCB_ENABLED)) {
> -               netdev_info(netdev, "DCB is not enabled for adapter\n");
> -               goto exit;
> +       if (tc->type == TC_SETUP_MQPRIO) {
> +               hw = tc->mqprio->hw;
> +               num_tc = tc->mqprio->num_tc;
> +       } else if (tc->type == TC_SETUP_MQPRIO_EXT) {
> +               hw = tc->mqprio_qopt->qopt.hw;
> +               num_tc = tc->mqprio_qopt->qopt.num_tc;
>         }
>
> -       /* Check if MFP enabled */
> -       if (pf->flags & I40E_FLAG_MFP_ENABLED) {
> -               netdev_info(netdev, "Configuring TC not supported in MFP mode\n");
> -               goto exit;
> +       if (!hw) {
> +               pf->flags &= ~I40E_FLAG_TC_MQPRIO;
> +               if (tc->type == TC_SETUP_MQPRIO_EXT)
> +                       memcpy(&vsi->mqprio_qopt, tc->mqprio_qopt,
> +                              sizeof(*tc->mqprio_qopt));
> +               goto config_tc;
>         }
>
> -       /* Check whether tc count is within enabled limit */
> -       if (tc > i40e_pf_get_num_tc(pf)) {
> -               netdev_info(netdev, "TC count greater than enabled on link for adapter\n");
> -               goto exit;
> +       switch (hw) {
> +       case TC_MQPRIO_HW_OFFLOAD_TCS:
> +               pf->flags &= ~I40E_FLAG_TC_MQPRIO;
> +               /* Check if DCB enabled to continue */
> +               if (!(pf->flags & I40E_FLAG_DCB_ENABLED)) {
> +                       netdev_info(netdev,
> +                                   "DCB is not enabled for adapter\n");
> +                       goto exit;
> +               }
> +
> +               /* Check if MFP enabled */
> +               if (pf->flags & I40E_FLAG_MFP_ENABLED) {
> +                       netdev_info(netdev,
> +                                   "Configuring TC not supported in MFP mode\n");
> +                       goto exit;
> +               }
> +
> +               /* Check whether tc count is within enabled limit */
> +               if (num_tc > i40e_pf_get_num_tc(pf)) {
> +                       netdev_info(netdev,
> +                                   "TC count greater than enabled on link for adapter\n");
> +                       goto exit;
> +               }
> +               break;
> +       case TC_MQPRIO_HW_OFFLOAD:
> +               if (pf->flags & I40E_FLAG_DCB_ENABLED) {
> +                       netdev_info(netdev,
> +                                   "Full offload of TC Mqprio options is not supported when DCB is enabled\n");
> +                       goto exit;
> +               }
> +
> +               /* Check if MFP enabled */
> +               if (pf->flags & I40E_FLAG_MFP_ENABLED) {
> +                       netdev_info(netdev,
> +                                   "Configuring TC not supported in MFP mode\n");
> +                       goto exit;
> +               }
> +
> +               ret = i40e_validate_mqprio_queue_mapping(vsi,
> +                                                        tc->mqprio_qopt);
> +               if (ret)
> +                       goto exit;
> +
> +               memcpy(&vsi->mqprio_qopt, tc->mqprio_qopt,
> +                      sizeof(*tc->mqprio_qopt));
> +
> +               pf->flags |= I40E_FLAG_TC_MQPRIO;
> +               pf->flags &= ~I40E_FLAG_DCB_ENABLED;
> +
> +               break;
> +       default:
> +               return -EINVAL;
>         }
>
> +config_tc:
>         /* Generate TC map for number of tc requested */
> -       for (i = 0; i < tc; i++)
> +       for (i = 0; i < num_tc; i++)
>                 enabled_tc |= BIT(i);
>
>         /* Requesting same TC configuration as already enabled */
> -       if (enabled_tc == vsi->tc_config.enabled_tc)
> +       if (enabled_tc == vsi->tc_config.enabled_tc &&
> +           hw != TC_MQPRIO_HW_OFFLOAD)
>                 return 0;
>
>         /* Quiesce VSI queues */
>         i40e_quiesce_vsi(vsi);
>
> +       if (!hw && !(pf->flags & I40E_FLAG_TC_MQPRIO))
> +               i40e_remove_queue_channel(vsi);
> +
>         /* Configure VSI for enabled TCs */
>         ret = i40e_vsi_config_tc(vsi, enabled_tc);
>         if (ret) {
> @@ -6229,8 +6484,11 @@ static int i40e_setup_tc(struct net_device *netdev, u8 tc)
>
>         /* Unquiesce VSI */
>         i40e_unquiesce_vsi(vsi);
> +       return ret;
>
>  exit:
> +       /* Reset the configuration data */
> +       memset(&vsi->tc_config, 0, sizeof(vsi->tc_config));
>         i40e_unquiesce_vsi(vsi);
>         return ret;
>  }
> @@ -6238,12 +6496,7 @@ static int i40e_setup_tc(struct net_device *netdev, u8 tc)
>  static int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
>                            struct tc_to_netdev *tc)
>  {
> -       if (tc->type != TC_SETUP_MQPRIO)
> -               return -EINVAL;
> -
> -       tc->mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
> -
> -       return i40e_setup_tc(netdev, tc->mqprio->num_tc);
> +       return i40e_setup_tc(netdev, tc);
>  }
>
>  /**
>
> _______________________________________________
> Intel-wired-lan mailing list
> Intel-wired-lan@osuosl.org
> https://lists.osuosl.org/mailman/listinfo/intel-wired-lan

^ permalink raw reply

* [PATCH] arp: fixed -Wuninitialized compiler warning
From: Ihar Hrachyshka @ 2017-05-24 22:19 UTC (permalink / raw)
  To: davem, ja; +Cc: Ihar Hrachyshka, netdev

Commit 7d472a59c0e5ec117220a05de6b370447fb6cb66 ("arp: always override
existing neigh entries with gratuitous ARP") introduced a compiler
warning:

net/ipv4/arp.c:880:35: warning: 'addr_type' may be used uninitialized in
this function [-Wmaybe-uninitialized]

While the code logic seems to be correct and doesn't allow the variable
to be used uninitialized, and the warning is not consistently
reproducible, it's still worth fixing it for other people not to waste
time looking at the warning in case it pops up in the build environment.
Yes, compiler is probably at fault, but we will need to accommodate.

Fixes: 7d472a59c0e5ec117220a05de6b370447fb6cb66
Signed-off-by: Ihar Hrachyshka <ihrachys@redhat.com>
---
 net/ipv4/arp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index ae96e6f..e9f3386 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -863,8 +863,8 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
 
 	n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
 
+	addr_type = -1;
 	if (n || IN_DEV_ARP_ACCEPT(in_dev)) {
-		addr_type = -1;
 		is_garp = arp_is_garp(net, dev, &addr_type, arp->ar_op,
 				      sip, tip, sha, tha);
 	}
-- 
2.9.4

^ permalink raw reply related

* [PATCH net] sky2: Do not deadlock on sky2_hw_down
From: Joshua Emele @ 2017-05-24 22:43 UTC (permalink / raw)
  To: netdev; +Cc: Joshua Emele, Mirko Lindner, Stephen Hemminger, linux-kernel

From: Joshua Emele <jemele@google.com>

The sky2_hw_down uses sky2_tx_complete to free pending frames stuck in
the HW queue. Because sky2_hw_down can be called from a process context,
the call to u64_stats_update_begin can result in deadlock.

Because the statistics do not require update as part of the sky2_hw_down
sequence, prevent the update to avoid the deadlock.

[18198.003900] inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage.
[18198.009931] ifconfig/11604 [HC0[0]:SC0[0]:HE1:SE1] takes:
[18198.015348]  (&syncp->seq#2){+.?...}, at: [<805ed440>] sky2_hw_down+0x370/0x428
[18198.022827] {IN-SOFTIRQ-W} state was registered at:
[18198.027723]   [<801729a0>] lock_acquire+0x78/0x98
[18198.032484]   [<805ed048>] sky2_tx_complete+0x1a8/0x230
[18198.037760]   [<805f2718>] sky2_poll+0x7cc/0xfa8
[18198.042425]   [<807692f8>] net_rx_action+0x200/0x330
[18198.047447]   [<80129f64>] __do_softirq+0x130/0x31c
[18198.052369]   [<8012a4a0>] irq_exit+0xc8/0x13c
[18198.056836]   [<8017e398>] __handle_domain_irq+0x84/0xf8
[18198.062180]   [<80101564>] gic_handle_irq+0x58/0xb8
[18198.067086]   [<8010d838>] __irq_usr+0x58/0x80
[18198.071557]   [<76e178ae>] 0x76e178ae
[18198.075247] irq event stamp: 2109
[18198.078568] hardirqs last  enabled at (2109): [<8012a2cc>] __local_bh_enable_ip+0x90/0x110
[18198.086860] hardirqs last disabled at (2107): [<8012a27c>] __local_bh_enable_ip+0x40/0x110
[18198.095150] softirqs last  enabled at (2108): [<805ed368>] sky2_hw_down+0x298/0x428
[18198.102832] softirqs last disabled at (2106): [<805ed284>] sky2_hw_down+0x1b4/0x428
[18198.110515]
               other info that might help us debug this:
[18198.117048]  Possible unsafe locking scenario:

[18198.122974]        CPU0
[18198.125425]        ----
[18198.127876]   lock(&syncp->seq#2);
[18198.131332]   <Interrupt>
[18198.133955]     lock(&syncp->seq#2);
[18198.137585]
                *** DEADLOCK ***

[18198.143517] 1 lock held by ifconfig/11604:
[18198.147618]  #0:  (rtnl_mutex){+.+.+.}, at: [<8077e874>] rtnl_lock+0x18/0x20
[18198.154772]
               stack backtrace:
[18198.159143] CPU: 1 PID: 11604 Comm: ifconfig Not tainted 4.8.17 #1
[18198.165331] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
[18198.171864] Backtrace:
[18198.174353] [<8010c634>] (dump_backtrace) from [<8010c828>] (show_stack+0x18/0x1c)
[18198.181931]  r6:60070093 r5:00000000 r4:80e23248 r3:00000000
[18198.187682] [<8010c810>] (show_stack) from [<8041edc4>] (dump_stack+0xb4/0xe8)
[18198.194924] [<8041ed10>] (dump_stack) from [<801700cc>] (print_usage_bug+0x1dc/0x2d0)
[18198.202762]  r10:edec55c0 r9:80bd1178 r8:81649598 r7:00000006 r6:edec5a90 r5:80fb09f4
[18198.210686]  r4:edec55c0 r3:00000002
[18198.214311] [<8016fef0>] (print_usage_bug) from [<80170348>] (mark_lock+0x188/0x6c4)
[18198.222059]  r9:00000000 r8:00000004 r7:edec55c0 r6:00000006 r5:edec5a90 r4:8016f44c
[18198.229903] [<801701c0>] (mark_lock) from [<801714ac>] (__lock_acquire+0xb90/0x1c70)
[18198.237653]  r10:edec55c0 r9:00000000 r8:edec5aa4 r7:00000004 r6:00000001 r5:00000000
[18198.245573]  r4:000001cd r3:00000001
[18198.249192] [<8017091c>] (__lock_acquire) from [<801729a0>] (lock_acquire+0x78/0x98)
[18198.256940]  r10:00000001 r9:000006d0 r8:00000000 r7:00000001 r6:805ed440 r5:60070013
[18198.264860]  r4:00000000
[18198.267428] [<80172928>] (lock_acquire) from [<805ed048>] (sky2_tx_complete+0x1a8/0x230)
[18198.275523]  r7:ee2d9dfc r6:00000000 r5:ee2d9dc0 r4:00000000
[18198.281266] [<805ecea0>] (sky2_tx_complete) from [<805ed440>] (sky2_hw_down+0x370/0x428)
[18198.289360]  r10:ee2cac00 r9:000006d0 r8:ee2d9dc0 r7:f0d40aa8 r6:00000001 r5:00000d48
[18198.297281]  r4:00000000
[18198.299850] [<805ed0d0>] (sky2_hw_down) from [<805efed8>] (sky2_close+0xac/0x11c)
[18198.307337]  r10:ee838600 r9:00000000 r8:00000000 r7:00001003 r6:ee2d9dc0 r5:00000000
[18198.315258]  r4:ee2cac00
[18198.317830] [<805efe2c>] (sky2_close) from [<8076a310>] (__dev_close_many+0xc4/0x118)
[18198.325664]  r7:00001003 r6:00001042 r5:eb047df8 r4:ee2d9800
[18198.331404] [<8076a24c>] (__dev_close_many) from [<8076ab24>] (__dev_close+0x30/0x48)
[18198.339240]  r5:00000001 r4:ee2d9800
[18198.342866] [<8076aaf4>] (__dev_close) from [<8076dbac>] (__dev_change_flags+0x90/0x154)
[18198.350970] [<8076db1c>] (__dev_change_flags) from [<8076dc90>] (dev_change_flags+0x20/0x50)
[18198.359412]  r8:00000000 r7:00008914 r6:00001003 r5:ee2d9948 r4:ee2d9800 r3:00000014
[18198.367264] [<8076dc70>] (dev_change_flags) from [<807f06d0>] (devinet_ioctl+0x724/0x818)
[18198.375448]  r8:ffffffff r7:00008914 r6:ee2cae0c r5:7ed799ac r4:eb047e80 r3:00000014
[18198.383291] [<807effac>] (devinet_ioctl) from [<807f2e98>] (inet_ioctl+0x19c/0x1c8)
[18198.390951]  r10:edfc3b80 r9:eb046000 r8:00000004 r7:ee724b40 r6:7ed799ac r5:ee724b60
[18198.398872]  r4:00008914
[18198.401446] [<807f2cfc>] (inet_ioctl) from [<8074a234>] (sock_ioctl+0x158/0x300)
[18198.408860] [<8074a0dc>] (sock_ioctl) from [<80239770>] (do_vfs_ioctl+0x98/0xa3c)
[18198.416348]  r7:8023a150 r6:00000004 r5:ee724b60 r4:7ed799ac
[18198.422087] [<802396d8>] (do_vfs_ioctl) from [<8023a150>] (SyS_ioctl+0x3c/0x64)
[18198.429401]  r10:00000000 r9:eb046000 r8:00000004 r7:00008914 r6:edfc3b80 r5:7ed799ac
[18198.437326]  r4:edfc3b80
[18198.439895] [<8023a114>] (SyS_ioctl) from [<80107ee0>] (ret_fast_syscall+0x0/0x1c)
[18198.447469]  r8:80108084 r7:00000036 r6:00000004 r5:7ed799ac r4:7ed79b20 r3:31687465

Signed-off-by: Joshua Emele <jemele@google.com>
---
 drivers/net/ethernet/marvell/sky2.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 1145cde2274a..8016307939bd 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -2012,7 +2012,8 @@ static netdev_tx_t sky2_xmit_frame(struct sk_buff *skb,
  *     looks at the tail of the queue of FIFO (tx_cons), not
  *     the head (tx_prod)
  */
-static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
+static void sky2_tx_complete(struct sky2_port *sky2, u16 done,
+			     bool update_stats)
 {
 	struct net_device *dev = sky2->netdev;
 	u16 idx;
@@ -2046,10 +2047,12 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
 
 	netdev_completed_queue(dev, pkts_compl, bytes_compl);
 
-	u64_stats_update_begin(&sky2->tx_stats.syncp);
-	sky2->tx_stats.packets += pkts_compl;
-	sky2->tx_stats.bytes += bytes_compl;
-	u64_stats_update_end(&sky2->tx_stats.syncp);
+	if (likely(update_stats)) {
+		u64_stats_update_begin(&sky2->tx_stats.syncp);
+		sky2->tx_stats.packets += pkts_compl;
+		sky2->tx_stats.bytes += bytes_compl;
+		u64_stats_update_end(&sky2->tx_stats.syncp);
+	}
 }
 
 static void sky2_tx_reset(struct sky2_hw *hw, unsigned port)
@@ -2120,7 +2123,7 @@ static void sky2_hw_down(struct sky2_port *sky2)
 	sky2_tx_reset(hw, port);
 
 	/* Free any pending frames stuck in HW queue */
-	sky2_tx_complete(sky2, sky2->tx_prod);
+	sky2_tx_complete(sky2, sky2->tx_prod, false);
 }
 
 /* Network shutdown */
@@ -2635,7 +2638,7 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
 	struct sky2_port *sky2 = netdev_priv(dev);
 
 	if (netif_running(dev)) {
-		sky2_tx_complete(sky2, last);
+		sky2_tx_complete(sky2, last, true);
 
 		/* Wake unless it's detached, and called e.g. from sky2_close() */
 		if (tx_avail(sky2) > MAX_SKB_TX_LE + 4)
-- 
2.13.0.219.gdb65acc882-goog

^ permalink raw reply related

* [PATCH 0/2] Replace driver's usage of hard-coded device IDs to #defines
From: Myron Stowe @ 2017-05-24 22:47 UTC (permalink / raw)
  To: linux-pci, netdev; +Cc: bhelgaas, saeedm, noaos, tariqt

Noa Osherovich introduced a series of new Mellanox device ID definitions to
help differentiate specific controllers that needed INTx masking quirks [1].

Bjorn Helgaas followed on, using the device ID definitions Noa provided to
replace hard-coded values within the mxl4 ID table [2].
    
This patch continues along similar lines, adding a few additional Mellanox
device ID definitions and converting the net/mlx5e driver's mlx5 ID table to
use the defines so tools like 'grep' and 'cscope' can be used to help
identify relationships with other aspects (such as INTx masking).


[1]  7254383341b PCI: Add Mellanox device IDs
     d76d2fe05fd PCI: Convert Mellanox broken INTx quirks to be for listed
                 devices only

[2]  c19e4b9037f net/mlx4_core: Use device ID defines


Myron Stowe (2):
      PCI: Add Mellanox device IDs
      net/mlx5e: Use device ID defines


 drivers/net/ethernet/mellanox/mlx5/core/main.c |   12 ++++++------
 include/linux/pci_ids.h                        |    3 +++
 2 files changed, 9 insertions(+), 6 deletions(-)

^ permalink raw reply

* [PATCH 1/2] PCI: Add Mellanox device IDs
From: Myron Stowe @ 2017-05-24 22:47 UTC (permalink / raw)
  To: linux-pci, netdev; +Cc: bhelgaas, saeedm, noaos, tariqt
In-Reply-To: <20170524224734.24221.33787.stgit@amt.stowe>

Add Mellanox device IDs for controllers covered by the mlx5 driver.

Signed-off-by: Myron Stowe <myron.stowe@redhat.com>
---
 include/linux/pci_ids.h |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 5f6b71d..5626d5a 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2266,6 +2266,9 @@
 #define PCI_DEVICE_ID_MELLANOX_CONNECTIB	0x1011
 #define PCI_DEVICE_ID_MELLANOX_CONNECTX4	0x1013
 #define PCI_DEVICE_ID_MELLANOX_CONNECTX4_LX	0x1015
+#define PCI_DEVICE_ID_MELLANOX_CONNECTX5	0x1017
+#define PCI_DEVICE_ID_MELLANOX_CONNECTX5_EX	0x1019
+#define PCI_DEVICE_ID_MELLANOX_CONNECTX6	0x101b
 #define PCI_DEVICE_ID_MELLANOX_TAVOR		0x5a44
 #define PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE	0x5a46
 #define PCI_DEVICE_ID_MELLANOX_SINAI_OLD	0x5e8c

^ permalink raw reply related

* [PATCH 2/2] net/mlx5e: Use device ID defines
From: Myron Stowe @ 2017-05-24 22:47 UTC (permalink / raw)
  To: linux-pci, netdev; +Cc: bhelgaas, saeedm, noaos, tariqt
In-Reply-To: <20170524224734.24221.33787.stgit@amt.stowe>

Use Mellanox device ID definitions in the mlx5 ID table so tools such as
'grep' and 'cscope' can be used to help find related aspects.

No functional change intended.

Signed-off-by: Myron Stowe <myron.stowe@redhat.com>
---
 drivers/net/ethernet/mellanox/mlx5/core/main.c |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index 0c123d5..98642eb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -1508,17 +1508,17 @@ static void shutdown(struct pci_dev *pdev)
 }
 
 static const struct pci_device_id mlx5_core_pci_table[] = {
-	{ PCI_VDEVICE(MELLANOX, 0x1011) },			/* Connect-IB */
+	{ PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_CONNECTIB) },
 	{ PCI_VDEVICE(MELLANOX, 0x1012), MLX5_PCI_DEV_IS_VF},	/* Connect-IB VF */
-	{ PCI_VDEVICE(MELLANOX, 0x1013) },			/* ConnectX-4 */
+	{ PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_CONNECTX4) },
 	{ PCI_VDEVICE(MELLANOX, 0x1014), MLX5_PCI_DEV_IS_VF},	/* ConnectX-4 VF */
-	{ PCI_VDEVICE(MELLANOX, 0x1015) },			/* ConnectX-4LX */
+	{ PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_CONNECTX4_LX) },
 	{ PCI_VDEVICE(MELLANOX, 0x1016), MLX5_PCI_DEV_IS_VF},	/* ConnectX-4LX VF */
-	{ PCI_VDEVICE(MELLANOX, 0x1017) },			/* ConnectX-5, PCIe 3.0 */
+	{ PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_CONNECTX5) },
 	{ PCI_VDEVICE(MELLANOX, 0x1018), MLX5_PCI_DEV_IS_VF},	/* ConnectX-5 VF */
-	{ PCI_VDEVICE(MELLANOX, 0x1019) },			/* ConnectX-5 Ex */
+	{ PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_CONNECTX5_EX) },
 	{ PCI_VDEVICE(MELLANOX, 0x101a), MLX5_PCI_DEV_IS_VF},	/* ConnectX-5 Ex VF */
-	{ PCI_VDEVICE(MELLANOX, 0x101b) },			/* ConnectX-6 */
+	{ PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_CONNECTX6) },
 	{ PCI_VDEVICE(MELLANOX, 0x101c), MLX5_PCI_DEV_IS_VF},	/* ConnectX-6 VF */
 	{ 0, }
 };

^ permalink raw reply related

* [PATCH net v2 0/5] Various BPF fixes
From: Daniel Borkmann @ 2017-05-24 23:05 UTC (permalink / raw)
  To: davem; +Cc: alexei.starovoitov, netdev, Daniel Borkmann

Follow-up to fix incorrect pruning when alignment tracking is
in use and to properly clear regs after call to not leave stale
data behind, also a fix that adds bpf_clone_redirect to the
bpf_helper_changes_pkt_data helper and exposes correct map_flags
for lpm map into fdinfo. For details, please see individual
patches.

Thanks!

v1 -> v2:
  - Reworked first patch so that env->strict_alignment is the
    final indicator on whether we have to deal with strict
    alignment rather than having CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
    checks on various locations, so only checking env->strict_alignment
    is sufficient after that. Thanks for spotting, Dave!
  - Added patch 3 and 4.
  - Rest as is.

Daniel Borkmann (5):
  bpf: fix incorrect pruning decision when alignment must be tracked
  bpf: properly reset caller saved regs after helper call and ld_abs/ind
  bpf: add bpf_clone_redirect to bpf_helper_changes_pkt_data
  bpf: fix wrong exposure of map_flags into fdinfo for lpm
  bpf: add various verifier test cases

 include/linux/filter.h                      |  10 ++
 kernel/bpf/arraymap.c                       |   1 +
 kernel/bpf/lpm_trie.c                       |   1 +
 kernel/bpf/stackmap.c                       |   1 +
 kernel/bpf/verifier.c                       |  56 +++----
 net/core/filter.c                           |   1 +
 tools/include/linux/filter.h                |  10 ++
 tools/testing/selftests/bpf/test_verifier.c | 239 +++++++++++++++++++++++++++-
 8 files changed, 285 insertions(+), 34 deletions(-)

-- 
1.9.3

^ permalink raw reply

* [PATCH net v2 1/5] bpf: fix incorrect pruning decision when alignment must be tracked
From: Daniel Borkmann @ 2017-05-24 23:05 UTC (permalink / raw)
  To: davem; +Cc: alexei.starovoitov, netdev, Daniel Borkmann
In-Reply-To: <cover.1495665905.git.daniel@iogearbox.net>

Currently, when we enforce alignment tracking on direct packet access,
the verifier lets the following program pass despite doing a packet
write with unaligned access:

  0: (61) r2 = *(u32 *)(r1 +76)
  1: (61) r3 = *(u32 *)(r1 +80)
  2: (61) r7 = *(u32 *)(r1 +8)
  3: (bf) r0 = r2
  4: (07) r0 += 14
  5: (25) if r7 > 0x1 goto pc+4
   R0=pkt(id=0,off=14,r=0) R1=ctx R2=pkt(id=0,off=0,r=0)
   R3=pkt_end R7=inv,min_value=0,max_value=1 R10=fp
  6: (2d) if r0 > r3 goto pc+1
   R0=pkt(id=0,off=14,r=14) R1=ctx R2=pkt(id=0,off=0,r=14)
   R3=pkt_end R7=inv,min_value=0,max_value=1 R10=fp
  7: (63) *(u32 *)(r0 -4) = r0
  8: (b7) r0 = 0
  9: (95) exit

  from 6 to 8:
   R0=pkt(id=0,off=14,r=0) R1=ctx R2=pkt(id=0,off=0,r=0)
   R3=pkt_end R7=inv,min_value=0,max_value=1 R10=fp
  8: (b7) r0 = 0
  9: (95) exit

  from 5 to 10:
   R0=pkt(id=0,off=14,r=0) R1=ctx R2=pkt(id=0,off=0,r=0)
   R3=pkt_end R7=inv,min_value=2 R10=fp
  10: (07) r0 += 1
  11: (05) goto pc-6
  6: safe                           <----- here, wrongly found safe
  processed 15 insns

However, if we enforce a pruning mismatch by adding state into r8
which is then being mismatched in states_equal(), we find that for
the otherwise same program, the verifier detects a misaligned packet
access when actually walking that path:

  0: (61) r2 = *(u32 *)(r1 +76)
  1: (61) r3 = *(u32 *)(r1 +80)
  2: (61) r7 = *(u32 *)(r1 +8)
  3: (b7) r8 = 1
  4: (bf) r0 = r2
  5: (07) r0 += 14
  6: (25) if r7 > 0x1 goto pc+4
   R0=pkt(id=0,off=14,r=0) R1=ctx R2=pkt(id=0,off=0,r=0)
   R3=pkt_end R7=inv,min_value=0,max_value=1
   R8=imm1,min_value=1,max_value=1,min_align=1 R10=fp
  7: (2d) if r0 > r3 goto pc+1
   R0=pkt(id=0,off=14,r=14) R1=ctx R2=pkt(id=0,off=0,r=14)
   R3=pkt_end R7=inv,min_value=0,max_value=1
   R8=imm1,min_value=1,max_value=1,min_align=1 R10=fp
  8: (63) *(u32 *)(r0 -4) = r0
  9: (b7) r0 = 0
  10: (95) exit

  from 7 to 9:
   R0=pkt(id=0,off=14,r=0) R1=ctx R2=pkt(id=0,off=0,r=0)
   R3=pkt_end R7=inv,min_value=0,max_value=1
   R8=imm1,min_value=1,max_value=1,min_align=1 R10=fp
  9: (b7) r0 = 0
  10: (95) exit

  from 6 to 11:
   R0=pkt(id=0,off=14,r=0) R1=ctx R2=pkt(id=0,off=0,r=0)
   R3=pkt_end R7=inv,min_value=2
   R8=imm1,min_value=1,max_value=1,min_align=1 R10=fp
  11: (07) r0 += 1
  12: (b7) r8 = 0
  13: (05) goto pc-7                <----- mismatch due to r8
  7: (2d) if r0 > r3 goto pc+1
   R0=pkt(id=0,off=15,r=15) R1=ctx R2=pkt(id=0,off=0,r=15)
   R3=pkt_end R7=inv,min_value=2
   R8=imm0,min_value=0,max_value=0,min_align=2147483648 R10=fp
  8: (63) *(u32 *)(r0 -4) = r0
  misaligned packet access off 2+15+-4 size 4

The reason why we fail to see it in states_equal() is that the
third test in compare_ptrs_to_packet() ...

  if (old->off <= cur->off &&
      old->off >= old->range && cur->off >= cur->range)
          return true;

... will let the above pass. The situation we run into is that
old->off <= cur->off (14 <= 15), meaning that prior walked paths
went with smaller offset, which was later used in the packet
access after successful packet range check and found to be safe
already.

For example: Given is R0=pkt(id=0,off=0,r=0). Adding offset 14
as in above program to it, results in R0=pkt(id=0,off=14,r=0)
before the packet range test. Now, testing this against R3=pkt_end
with 'if r0 > r3 goto out' will transform R0 into R0=pkt(id=0,off=14,r=14)
for the case when we're within bounds. A write into the packet
at offset *(u32 *)(r0 -4), that is, 2 + 14 -4, is valid and
aligned (2 is for NET_IP_ALIGN). After processing this with
all fall-through paths, we later on check paths from branches.
When the above skb->mark test is true, then we jump near the
end of the program, perform r0 += 1, and jump back to the
'if r0 > r3 goto out' test we've visited earlier already. This
time, R0 is of type R0=pkt(id=0,off=15,r=0), and we'll prune
that part because this time we'll have a larger safe packet
range, and we already found that with off=14 all further insn
were already safe, so it's safe as well with a larger off.
However, the problem is that the subsequent write into the packet
with 2 + 15 -4 is then unaligned, and not caught by the alignment
tracking. Note that min_align, aux_off, and aux_off_align were
all 0 in this example.

Since we cannot tell at this time what kind of packet access was
performed in the prior walk and what minimal requirements it has
(we might do so in the future, but that requires more complexity),
fix it to disable this pruning case for strict alignment for now,
and let the verifier do check such paths instead. With that applied,
the test cases pass and reject the program due to misalignment.

Fixes: d1174416747d ("bpf: Track alignment of register values in the verifier.")
Reference: http://patchwork.ozlabs.org/patch/761909/
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
 kernel/bpf/verifier.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index c72cd41..e37e06b 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -843,9 +843,6 @@ static int check_ptr_alignment(struct bpf_verifier_env *env,
 {
 	bool strict = env->strict_alignment;
 
-	if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))
-		strict = true;
-
 	switch (reg->type) {
 	case PTR_TO_PACKET:
 		return check_pkt_ptr_alignment(reg, off, size, strict);
@@ -2696,7 +2693,8 @@ static int check_cfg(struct bpf_verifier_env *env)
 /* the following conditions reduce the number of explored insns
  * from ~140k to ~80k for ultra large programs that use a lot of ptr_to_packet
  */
-static bool compare_ptrs_to_packet(struct bpf_reg_state *old,
+static bool compare_ptrs_to_packet(struct bpf_verifier_env *env,
+				   struct bpf_reg_state *old,
 				   struct bpf_reg_state *cur)
 {
 	if (old->id != cur->id)
@@ -2739,7 +2737,7 @@ static bool compare_ptrs_to_packet(struct bpf_reg_state *old,
 	 * 'if (R4 > data_end)' and all further insn were already good with r=20,
 	 * so they will be good with r=30 and we can prune the search.
 	 */
-	if (old->off <= cur->off &&
+	if (!env->strict_alignment && old->off <= cur->off &&
 	    old->off >= old->range && cur->off >= cur->range)
 		return true;
 
@@ -2810,7 +2808,7 @@ static bool states_equal(struct bpf_verifier_env *env,
 			continue;
 
 		if (rold->type == PTR_TO_PACKET && rcur->type == PTR_TO_PACKET &&
-		    compare_ptrs_to_packet(rold, rcur))
+		    compare_ptrs_to_packet(env, rold, rcur))
 			continue;
 
 		return false;
@@ -3588,10 +3586,10 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr)
 	} else {
 		log_level = 0;
 	}
-	if (attr->prog_flags & BPF_F_STRICT_ALIGNMENT)
+
+	env->strict_alignment = !!(attr->prog_flags & BPF_F_STRICT_ALIGNMENT);
+	if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))
 		env->strict_alignment = true;
-	else
-		env->strict_alignment = false;
 
 	ret = replace_map_fd_with_map_ptr(env);
 	if (ret < 0)
@@ -3697,7 +3695,10 @@ int bpf_analyzer(struct bpf_prog *prog, const struct bpf_ext_analyzer_ops *ops,
 	mutex_lock(&bpf_verifier_lock);
 
 	log_level = 0;
+
 	env->strict_alignment = false;
+	if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))
+		env->strict_alignment = true;
 
 	env->explored_states = kcalloc(env->prog->len,
 				       sizeof(struct bpf_verifier_state_list *),
-- 
1.9.3

^ permalink raw reply related

* [PATCH net v2 2/5] bpf: properly reset caller saved regs after helper call and ld_abs/ind
From: Daniel Borkmann @ 2017-05-24 23:05 UTC (permalink / raw)
  To: davem; +Cc: alexei.starovoitov, netdev, Daniel Borkmann
In-Reply-To: <cover.1495665905.git.daniel@iogearbox.net>

Currently, after performing helper calls, we clear all caller saved
registers, that is r0 - r5 and fill r0 depending on struct bpf_func_proto
specification. The way we reset these regs can affect pruning decisions
in later paths, since we only reset register's imm to 0 and type to
NOT_INIT. However, we leave out clearing of other variables such as id,
min_value, max_value, etc, which can later on lead to pruning mismatches
due to stale data.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
 kernel/bpf/verifier.c | 37 ++++++++++++++++---------------------
 1 file changed, 16 insertions(+), 21 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index e37e06b..339c8a1 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -463,19 +463,22 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,
 	BPF_REG_0, BPF_REG_1, BPF_REG_2, BPF_REG_3, BPF_REG_4, BPF_REG_5
 };
 
+static void mark_reg_not_init(struct bpf_reg_state *regs, u32 regno)
+{
+	BUG_ON(regno >= MAX_BPF_REG);
+
+	memset(&regs[regno], 0, sizeof(regs[regno]));
+	regs[regno].type = NOT_INIT;
+	regs[regno].min_value = BPF_REGISTER_MIN_RANGE;
+	regs[regno].max_value = BPF_REGISTER_MAX_RANGE;
+}
+
 static void init_reg_state(struct bpf_reg_state *regs)
 {
 	int i;
 
-	for (i = 0; i < MAX_BPF_REG; i++) {
-		regs[i].type = NOT_INIT;
-		regs[i].imm = 0;
-		regs[i].min_value = BPF_REGISTER_MIN_RANGE;
-		regs[i].max_value = BPF_REGISTER_MAX_RANGE;
-		regs[i].min_align = 0;
-		regs[i].aux_off = 0;
-		regs[i].aux_off_align = 0;
-	}
+	for (i = 0; i < MAX_BPF_REG; i++)
+		mark_reg_not_init(regs, i);
 
 	/* frame pointer */
 	regs[BPF_REG_FP].type = FRAME_PTR;
@@ -1346,7 +1349,6 @@ static int check_call(struct bpf_verifier_env *env, int func_id, int insn_idx)
 	struct bpf_verifier_state *state = &env->cur_state;
 	const struct bpf_func_proto *fn = NULL;
 	struct bpf_reg_state *regs = state->regs;
-	struct bpf_reg_state *reg;
 	struct bpf_call_arg_meta meta;
 	bool changes_data;
 	int i, err;
@@ -1413,11 +1415,8 @@ static int check_call(struct bpf_verifier_env *env, int func_id, int insn_idx)
 	}
 
 	/* reset caller saved regs */
-	for (i = 0; i < CALLER_SAVED_REGS; i++) {
-		reg = regs + caller_saved[i];
-		reg->type = NOT_INIT;
-		reg->imm = 0;
-	}
+	for (i = 0; i < CALLER_SAVED_REGS; i++)
+		mark_reg_not_init(regs, caller_saved[i]);
 
 	/* update return register */
 	if (fn->ret_type == RET_INTEGER) {
@@ -2445,7 +2444,6 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
 {
 	struct bpf_reg_state *regs = env->cur_state.regs;
 	u8 mode = BPF_MODE(insn->code);
-	struct bpf_reg_state *reg;
 	int i, err;
 
 	if (!may_access_skb(env->prog->type)) {
@@ -2478,11 +2476,8 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
 	}
 
 	/* reset caller saved regs to unreadable */
-	for (i = 0; i < CALLER_SAVED_REGS; i++) {
-		reg = regs + caller_saved[i];
-		reg->type = NOT_INIT;
-		reg->imm = 0;
-	}
+	for (i = 0; i < CALLER_SAVED_REGS; i++)
+		mark_reg_not_init(regs, caller_saved[i]);
 
 	/* mark destination R0 register as readable, since it contains
 	 * the value fetched from the packet
-- 
1.9.3

^ permalink raw reply related

* [PATCH net v2 3/5] bpf: add bpf_clone_redirect to bpf_helper_changes_pkt_data
From: Daniel Borkmann @ 2017-05-24 23:05 UTC (permalink / raw)
  To: davem; +Cc: alexei.starovoitov, netdev, Daniel Borkmann
In-Reply-To: <cover.1495665905.git.daniel@iogearbox.net>

The bpf_clone_redirect() still needs to be listed in
bpf_helper_changes_pkt_data() since we call into
bpf_try_make_head_writable() from there, thus we need
to invalidate prior pkt regs as well.

Fixes: 36bbef52c7eb ("bpf: direct packet write and access for helpers for clsact progs")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
 net/core/filter.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/core/filter.c b/net/core/filter.c
index a253a61..a6bb95f 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -2281,6 +2281,7 @@ bool bpf_helper_changes_pkt_data(void *func)
 	    func == bpf_skb_change_head ||
 	    func == bpf_skb_change_tail ||
 	    func == bpf_skb_pull_data ||
+	    func == bpf_clone_redirect ||
 	    func == bpf_l3_csum_replace ||
 	    func == bpf_l4_csum_replace ||
 	    func == bpf_xdp_adjust_head)
-- 
1.9.3

^ permalink raw reply related

* [PATCH net v2 4/5] bpf: fix wrong exposure of map_flags into fdinfo for lpm
From: Daniel Borkmann @ 2017-05-24 23:05 UTC (permalink / raw)
  To: davem; +Cc: alexei.starovoitov, netdev, Daniel Borkmann
In-Reply-To: <cover.1495665905.git.daniel@iogearbox.net>

trie_alloc() always needs to have BPF_F_NO_PREALLOC passed in via
attr->map_flags, since it does not support preallocation yet. We
check the flag, but we never copy the flag into trie->map.map_flags,
which is later on exposed into fdinfo and used by loaders such as
iproute2. Latter uses this in bpf_map_selfcheck_pinned() to test
whether a pinned map has the same spec as the one from the BPF obj
file and if not, bails out, which is currently the case for lpm
since it exposes always 0 as flags.

Also copy over flags in array_map_alloc() and stack_map_alloc().
They always have to be 0 right now, but we should make sure to not
miss to copy them over at a later point in time when we add actual
flags for them to use.

Fixes: b95a5c4db09b ("bpf: add a longest prefix match trie map implementation")
Reported-by: Jarno Rajahalme <jarno@covalent.io>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
 kernel/bpf/arraymap.c | 1 +
 kernel/bpf/lpm_trie.c | 1 +
 kernel/bpf/stackmap.c | 1 +
 3 files changed, 3 insertions(+)

diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index 5e00b23..172dc8e 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -86,6 +86,7 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
 	array->map.key_size = attr->key_size;
 	array->map.value_size = attr->value_size;
 	array->map.max_entries = attr->max_entries;
+	array->map.map_flags = attr->map_flags;
 	array->elem_size = elem_size;
 
 	if (!percpu)
diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c
index 39cfafd..b09185f 100644
--- a/kernel/bpf/lpm_trie.c
+++ b/kernel/bpf/lpm_trie.c
@@ -432,6 +432,7 @@ static struct bpf_map *trie_alloc(union bpf_attr *attr)
 	trie->map.key_size = attr->key_size;
 	trie->map.value_size = attr->value_size;
 	trie->map.max_entries = attr->max_entries;
+	trie->map.map_flags = attr->map_flags;
 	trie->data_size = attr->key_size -
 			  offsetof(struct bpf_lpm_trie_key, data);
 	trie->max_prefixlen = trie->data_size * 8;
diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c
index 4dfd6f2..31147d7 100644
--- a/kernel/bpf/stackmap.c
+++ b/kernel/bpf/stackmap.c
@@ -88,6 +88,7 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr)
 	smap->map.key_size = attr->key_size;
 	smap->map.value_size = value_size;
 	smap->map.max_entries = attr->max_entries;
+	smap->map.map_flags = attr->map_flags;
 	smap->n_buckets = n_buckets;
 	smap->map.pages = round_up(cost, PAGE_SIZE) >> PAGE_SHIFT;
 
-- 
1.9.3

^ permalink raw reply related

* [PATCH net v2 5/5] bpf: add various verifier test cases
From: Daniel Borkmann @ 2017-05-24 23:05 UTC (permalink / raw)
  To: davem; +Cc: alexei.starovoitov, netdev, Daniel Borkmann
In-Reply-To: <cover.1495665905.git.daniel@iogearbox.net>

This patch adds various verifier test cases:

1) A test case for the pruning issue when tracking alignment
   is used.
2) Various PTR_TO_MAP_VALUE_OR_NULL tests to make sure pointer
   arithmetic turns such register into UNKNOWN_VALUE type.
3) Test cases for the special treatment of LD_ABS/LD_IND to
   make sure verifier doesn't break calling convention here.
   Latter is needed, since f.e. arm64 JIT uses r1 - r5 for
   storing temporary data, so they really must be marked as
   NOT_INIT.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
 include/linux/filter.h                      |  10 ++
 tools/include/linux/filter.h                |  10 ++
 tools/testing/selftests/bpf/test_verifier.c | 239 +++++++++++++++++++++++++++-
 3 files changed, 255 insertions(+), 4 deletions(-)

diff --git a/include/linux/filter.h b/include/linux/filter.h
index 56197f8..62d948f 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -272,6 +272,16 @@
 		.off   = OFF,					\
 		.imm   = IMM })
 
+/* Unconditional jumps, goto pc + off16 */
+
+#define BPF_JMP_A(OFF)						\
+	((struct bpf_insn) {					\
+		.code  = BPF_JMP | BPF_JA,			\
+		.dst_reg = 0,					\
+		.src_reg = 0,					\
+		.off   = OFF,					\
+		.imm   = 0 })
+
 /* Function call */
 
 #define BPF_EMIT_CALL(FUNC)					\
diff --git a/tools/include/linux/filter.h b/tools/include/linux/filter.h
index 390d7c9..4ce25d4 100644
--- a/tools/include/linux/filter.h
+++ b/tools/include/linux/filter.h
@@ -208,6 +208,16 @@
 		.off   = OFF,					\
 		.imm   = IMM })
 
+/* Unconditional jumps, goto pc + off16 */
+
+#define BPF_JMP_A(OFF)						\
+	((struct bpf_insn) {					\
+		.code  = BPF_JMP | BPF_JA,			\
+		.dst_reg = 0,					\
+		.src_reg = 0,					\
+		.off   = OFF,					\
+		.imm   = 0 })
+
 /* Function call */
 
 #define BPF_EMIT_CALL(FUNC)					\
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 3773562..cabb19b 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -49,6 +49,7 @@
 #define MAX_NR_MAPS	4
 
 #define F_NEEDS_EFFICIENT_UNALIGNED_ACCESS	(1 << 0)
+#define F_LOAD_WITH_STRICT_ALIGNMENT		(1 << 1)
 
 struct bpf_test {
 	const char *descr;
@@ -2615,6 +2616,30 @@ struct test_val {
 		.prog_type = BPF_PROG_TYPE_SCHED_CLS,
 	},
 	{
+		"direct packet access: test17 (pruning, alignment)",
+		.insns = {
+			BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+				    offsetof(struct __sk_buff, data)),
+			BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
+				    offsetof(struct __sk_buff, data_end)),
+			BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
+				    offsetof(struct __sk_buff, mark)),
+			BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+			BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 14),
+			BPF_JMP_IMM(BPF_JGT, BPF_REG_7, 1, 4),
+			BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
+			BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, -4),
+			BPF_MOV64_IMM(BPF_REG_0, 0),
+			BPF_EXIT_INSN(),
+			BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
+			BPF_JMP_A(-6),
+		},
+		.errstr = "misaligned packet access off 2+15+-4 size 4",
+		.result = REJECT,
+		.prog_type = BPF_PROG_TYPE_SCHED_CLS,
+		.flags = F_LOAD_WITH_STRICT_ALIGNMENT,
+	},
+	{
 		"helper access to packet: test1, valid packet_ptr range",
 		.insns = {
 			BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
@@ -3341,6 +3366,70 @@ struct test_val {
 		.prog_type = BPF_PROG_TYPE_SCHED_CLS
 	},
 	{
+		"alu ops on ptr_to_map_value_or_null, 1",
+		.insns = {
+			BPF_MOV64_IMM(BPF_REG_1, 10),
+			BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
+			BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+			BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+			BPF_LD_MAP_FD(BPF_REG_1, 0),
+			BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+				     BPF_FUNC_map_lookup_elem),
+			BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
+			BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -2),
+			BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 2),
+			BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
+			BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
+			BPF_EXIT_INSN(),
+		},
+		.fixup_map1 = { 4 },
+		.errstr = "R4 invalid mem access",
+		.result = REJECT,
+		.prog_type = BPF_PROG_TYPE_SCHED_CLS
+	},
+	{
+		"alu ops on ptr_to_map_value_or_null, 2",
+		.insns = {
+			BPF_MOV64_IMM(BPF_REG_1, 10),
+			BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
+			BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+			BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+			BPF_LD_MAP_FD(BPF_REG_1, 0),
+			BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+				     BPF_FUNC_map_lookup_elem),
+			BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
+			BPF_ALU64_IMM(BPF_AND, BPF_REG_4, -1),
+			BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
+			BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
+			BPF_EXIT_INSN(),
+		},
+		.fixup_map1 = { 4 },
+		.errstr = "R4 invalid mem access",
+		.result = REJECT,
+		.prog_type = BPF_PROG_TYPE_SCHED_CLS
+	},
+	{
+		"alu ops on ptr_to_map_value_or_null, 3",
+		.insns = {
+			BPF_MOV64_IMM(BPF_REG_1, 10),
+			BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
+			BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+			BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+			BPF_LD_MAP_FD(BPF_REG_1, 0),
+			BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+				     BPF_FUNC_map_lookup_elem),
+			BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
+			BPF_ALU64_IMM(BPF_LSH, BPF_REG_4, 1),
+			BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
+			BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
+			BPF_EXIT_INSN(),
+		},
+		.fixup_map1 = { 4 },
+		.errstr = "R4 invalid mem access",
+		.result = REJECT,
+		.prog_type = BPF_PROG_TYPE_SCHED_CLS
+	},
+	{
 		"invalid memory access with multiple map_lookup_elem calls",
 		.insns = {
 			BPF_MOV64_IMM(BPF_REG_1, 10),
@@ -4937,7 +5026,149 @@ struct test_val {
 		.fixup_map_in_map = { 3 },
 		.errstr = "R1 type=map_value_or_null expected=map_ptr",
 		.result = REJECT,
-	}
+	},
+	{
+		"ld_abs: check calling conv, r1",
+		.insns = {
+			BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+			BPF_MOV64_IMM(BPF_REG_1, 0),
+			BPF_LD_ABS(BPF_W, -0x200000),
+			BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
+			BPF_EXIT_INSN(),
+		},
+		.errstr = "R1 !read_ok",
+		.result = REJECT,
+	},
+	{
+		"ld_abs: check calling conv, r2",
+		.insns = {
+			BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+			BPF_MOV64_IMM(BPF_REG_2, 0),
+			BPF_LD_ABS(BPF_W, -0x200000),
+			BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+			BPF_EXIT_INSN(),
+		},
+		.errstr = "R2 !read_ok",
+		.result = REJECT,
+	},
+	{
+		"ld_abs: check calling conv, r3",
+		.insns = {
+			BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+			BPF_MOV64_IMM(BPF_REG_3, 0),
+			BPF_LD_ABS(BPF_W, -0x200000),
+			BPF_MOV64_REG(BPF_REG_0, BPF_REG_3),
+			BPF_EXIT_INSN(),
+		},
+		.errstr = "R3 !read_ok",
+		.result = REJECT,
+	},
+	{
+		"ld_abs: check calling conv, r4",
+		.insns = {
+			BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+			BPF_MOV64_IMM(BPF_REG_4, 0),
+			BPF_LD_ABS(BPF_W, -0x200000),
+			BPF_MOV64_REG(BPF_REG_0, BPF_REG_4),
+			BPF_EXIT_INSN(),
+		},
+		.errstr = "R4 !read_ok",
+		.result = REJECT,
+	},
+	{
+		"ld_abs: check calling conv, r5",
+		.insns = {
+			BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+			BPF_MOV64_IMM(BPF_REG_5, 0),
+			BPF_LD_ABS(BPF_W, -0x200000),
+			BPF_MOV64_REG(BPF_REG_0, BPF_REG_5),
+			BPF_EXIT_INSN(),
+		},
+		.errstr = "R5 !read_ok",
+		.result = REJECT,
+	},
+	{
+		"ld_abs: check calling conv, r7",
+		.insns = {
+			BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+			BPF_MOV64_IMM(BPF_REG_7, 0),
+			BPF_LD_ABS(BPF_W, -0x200000),
+			BPF_MOV64_REG(BPF_REG_0, BPF_REG_7),
+			BPF_EXIT_INSN(),
+		},
+		.result = ACCEPT,
+	},
+	{
+		"ld_ind: check calling conv, r1",
+		.insns = {
+			BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+			BPF_MOV64_IMM(BPF_REG_1, 1),
+			BPF_LD_IND(BPF_W, BPF_REG_1, -0x200000),
+			BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
+			BPF_EXIT_INSN(),
+		},
+		.errstr = "R1 !read_ok",
+		.result = REJECT,
+	},
+	{
+		"ld_ind: check calling conv, r2",
+		.insns = {
+			BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+			BPF_MOV64_IMM(BPF_REG_2, 1),
+			BPF_LD_IND(BPF_W, BPF_REG_2, -0x200000),
+			BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+			BPF_EXIT_INSN(),
+		},
+		.errstr = "R2 !read_ok",
+		.result = REJECT,
+	},
+	{
+		"ld_ind: check calling conv, r3",
+		.insns = {
+			BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+			BPF_MOV64_IMM(BPF_REG_3, 1),
+			BPF_LD_IND(BPF_W, BPF_REG_3, -0x200000),
+			BPF_MOV64_REG(BPF_REG_0, BPF_REG_3),
+			BPF_EXIT_INSN(),
+		},
+		.errstr = "R3 !read_ok",
+		.result = REJECT,
+	},
+	{
+		"ld_ind: check calling conv, r4",
+		.insns = {
+			BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+			BPF_MOV64_IMM(BPF_REG_4, 1),
+			BPF_LD_IND(BPF_W, BPF_REG_4, -0x200000),
+			BPF_MOV64_REG(BPF_REG_0, BPF_REG_4),
+			BPF_EXIT_INSN(),
+		},
+		.errstr = "R4 !read_ok",
+		.result = REJECT,
+	},
+	{
+		"ld_ind: check calling conv, r5",
+		.insns = {
+			BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+			BPF_MOV64_IMM(BPF_REG_5, 1),
+			BPF_LD_IND(BPF_W, BPF_REG_5, -0x200000),
+			BPF_MOV64_REG(BPF_REG_0, BPF_REG_5),
+			BPF_EXIT_INSN(),
+		},
+		.errstr = "R5 !read_ok",
+		.result = REJECT,
+	},
+	{
+		"ld_ind: check calling conv, r7",
+		.insns = {
+			BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+			BPF_MOV64_IMM(BPF_REG_7, 1),
+			BPF_LD_IND(BPF_W, BPF_REG_7, -0x200000),
+			BPF_MOV64_REG(BPF_REG_0, BPF_REG_7),
+			BPF_EXIT_INSN(),
+		},
+		.result = ACCEPT,
+	},
 };
 
 static int probe_filter_length(const struct bpf_insn *fp)
@@ -5059,9 +5290,9 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
 
 	do_test_fixup(test, prog, map_fds);
 
-	fd_prog = bpf_load_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
-				   prog, prog_len, "GPL", 0, bpf_vlog,
-				   sizeof(bpf_vlog));
+	fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
+				     prog, prog_len, test->flags & F_LOAD_WITH_STRICT_ALIGNMENT,
+				     "GPL", 0, bpf_vlog, sizeof(bpf_vlog));
 
 	expected_ret = unpriv && test->result_unpriv != UNDEF ?
 		       test->result_unpriv : test->result;
-- 
1.9.3

^ permalink raw reply related

* Re: [PATCH net-next 3/3] net: sysfs: Document PHY device sysfs attributes
From: Florian Fainelli @ 2017-05-24 23:07 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: netdev, davem
In-Reply-To: <20170524201018.GH1788@lunn.ch>

Hi Andrew,

On 05/24/2017 01:10 PM, Andrew Lunn wrote:
>> +What:		/sys/class/mdio_bus/<bus>/<device>/phy_interface
>> +Date:		February 2014
>> +KernelVersion:	3.15
>> +Contact:	netdev@vger.kernel.org
>> +Description:
>> +		String value indicating the PHY interface, possible
>> +		values are in include/linux/phy.h function phy_modes.
> 
> Hi Florian
> 
> Does this suggest that these strings should be moved to
> include/uapi/linux/phy.h?

Humm, I suppose we could do that, although I am not sure ally sure what
we would be putting in there (at least for now).
-- 
Florian

^ permalink raw reply

* linux-next: manual merge of the net-next tree with the net tree
From: Stephen Rothwell @ 2017-05-24 23:34 UTC (permalink / raw)
  To: David Miller, Networking
  Cc: Linux-Next Mailing List, Linux Kernel Mailing List, Andrew Lunn

Hi all,

Today's linux-next merge of the net-next tree got a conflict in:

  drivers/net/phy/marvell.c

between commit:

  f2899788353c ("net: phy: marvell: Limit errata to 88m1101")

from the net tree and commit:

  0c3439bc7773 ("net: phy: Marvell: checkpatch - Comments")

from the net-next tree.

I fixed it up (I just used the former version) and can carry the fix as
necessary. This is now fixed as far as linux-next is concerned, but any
non trivial conflicts should be mentioned to your upstream maintainer
when your tree is submitted for merging.  You may also want to consider
cooperating with the maintainer of the conflicting tree to minimise any
particularly complex conflicts.

-- 
Cheers,
Stephen Rothwell

^ permalink raw reply

* [PATCH] test_bpf: Add a couple of tests for BPF_JSGE.
From: David Daney @ 2017-05-24 23:35 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, netdev, linux-kernel; +Cc: David Daney

Some JITs can optimize comparisons with zero.  Add a couple of
BPF_JSGE tests against immediate zero.

Signed-off-by: David Daney <david.daney@cavium.com>
---
 lib/test_bpf.c | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/lib/test_bpf.c b/lib/test_bpf.c
index 889bc31..be88cba 100644
--- a/lib/test_bpf.c
+++ b/lib/test_bpf.c
@@ -4504,6 +4504,44 @@ static struct bpf_test tests[] = {
 		{ },
 		{ { 0, 1 } },
 	},
+	{
+		"JMP_JSGE_K: Signed jump: value walk 1",
+		.u.insns_int = {
+			BPF_ALU32_IMM(BPF_MOV, R0, 0),
+			BPF_LD_IMM64(R1, -3),
+			BPF_JMP_IMM(BPF_JSGE, R1, 0, 6),
+			BPF_ALU64_IMM(BPF_ADD, R1, 1),
+			BPF_JMP_IMM(BPF_JSGE, R1, 0, 4),
+			BPF_ALU64_IMM(BPF_ADD, R1, 1),
+			BPF_JMP_IMM(BPF_JSGE, R1, 0, 2),
+			BPF_ALU64_IMM(BPF_ADD, R1, 1),
+			BPF_JMP_IMM(BPF_JSGE, R1, 0, 1),
+			BPF_EXIT_INSN(),		/* bad exit */
+			BPF_ALU32_IMM(BPF_MOV, R0, 1),	/* good exit */
+			BPF_EXIT_INSN(),
+		},
+		INTERNAL,
+		{ },
+		{ { 0, 1 } },
+	},
+	{
+		"JMP_JSGE_K: Signed jump: value walk 2",
+		.u.insns_int = {
+			BPF_ALU32_IMM(BPF_MOV, R0, 0),
+			BPF_LD_IMM64(R1, -3),
+			BPF_JMP_IMM(BPF_JSGE, R1, 0, 4),
+			BPF_ALU64_IMM(BPF_ADD, R1, 2),
+			BPF_JMP_IMM(BPF_JSGE, R1, 0, 2),
+			BPF_ALU64_IMM(BPF_ADD, R1, 2),
+			BPF_JMP_IMM(BPF_JSGE, R1, 0, 1),
+			BPF_EXIT_INSN(),		/* bad exit */
+			BPF_ALU32_IMM(BPF_MOV, R0, 1),	/* good exit */
+			BPF_EXIT_INSN(),
+		},
+		INTERNAL,
+		{ },
+		{ { 0, 1 } },
+	},
 	/* BPF_JMP | BPF_JGT | BPF_K */
 	{
 		"JMP_JGT_K: if (3 > 2) return 1",
-- 
2.9.4

^ permalink raw reply related

* Re: [PATCH] test_bpf: Add a couple of tests for BPF_JSGE.
From: Daniel Borkmann @ 2017-05-24 23:52 UTC (permalink / raw)
  To: David Daney, Alexei Starovoitov, netdev, linux-kernel
In-Reply-To: <20170524233549.18388-1-david.daney@cavium.com>

On 05/25/2017 01:35 AM, David Daney wrote:
> Some JITs can optimize comparisons with zero.  Add a couple of
> BPF_JSGE tests against immediate zero.
>
> Signed-off-by: David Daney <david.daney@cavium.com>

Thanks for the tests!

Acked-by: Daniel Borkmann <daniel@iogearbox.net>

^ permalink raw reply

* Re: [PATCH 0/2] Replace driver's usage of hard-coded device IDs to #defines
From: David Miller @ 2017-05-25  0:02 UTC (permalink / raw)
  To: myron.stowe; +Cc: linux-pci, netdev, bhelgaas, saeedm, noaos, tariqt
In-Reply-To: <20170524224734.24221.33787.stgit@amt.stowe>

From: Myron Stowe <myron.stowe@redhat.com>
Date: Wed, 24 May 2017 16:47:34 -0600

> Noa Osherovich introduced a series of new Mellanox device ID definitions to
> help differentiate specific controllers that needed INTx masking quirks [1].
> 
> Bjorn Helgaas followed on, using the device ID definitions Noa provided to
> replace hard-coded values within the mxl4 ID table [2].
>     
> This patch continues along similar lines, adding a few additional Mellanox
> device ID definitions and converting the net/mlx5e driver's mlx5 ID table to
> use the defines so tools like 'grep' and 'cscope' can be used to help
> identify relationships with other aspects (such as INTx masking).

If you're adding pci_ids.h defines, it's only valid to do so if you
actually use the defines in more than one location.

This patch series is not doing that.

^ permalink raw reply

* Re: [PATCH net-next 3/3] net: sysfs: Document PHY device sysfs attributes
From: Florian Fainelli @ 2017-05-25  0:03 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: netdev, davem
In-Reply-To: <00fd6fec-29a2-9a54-085b-95f775610d3b@gmail.com>

On 05/24/2017 04:07 PM, Florian Fainelli wrote:
> Hi Andrew,
> 
> On 05/24/2017 01:10 PM, Andrew Lunn wrote:
>>> +What:		/sys/class/mdio_bus/<bus>/<device>/phy_interface
>>> +Date:		February 2014
>>> +KernelVersion:	3.15
>>> +Contact:	netdev@vger.kernel.org
>>> +Description:
>>> +		String value indicating the PHY interface, possible
>>> +		values are in include/linux/phy.h function phy_modes.
>>
>> Hi Florian
>>
>> Does this suggest that these strings should be moved to
>> include/uapi/linux/phy.h?
> 
> Humm, I suppose we could do that, although I am not sure ally sure what
> we would be putting in there (at least for now).

I actually prefer to put the possible values in the sysfs documentation
files instead of in a UAPI header. Will submit a v2.
-- 
Florian

^ permalink raw reply

* Re: [PATCH net-next 1/8] net: ipv4: refactor __ip_route_output_key_hash
From: David Ahern @ 2017-05-25  1:10 UTC (permalink / raw)
  To: Rosen, Rami, Roopa Prabhu, davem@davemloft.net
  Cc: netdev@vger.kernel.org, nikolay@cumulusnetworks.com
In-Reply-To: <9B0331B6EBBD0E4684FBFAEDA55776F93D54F8DF@HASMSX110.ger.corp.intel.com>

On 5/24/17 1:33 PM, Rosen, Rami wrote:
> Hi, Rupa /David Ahern,
> 
> First, thanks for this patch set!
> 
> Second, it seems to me that something might be incorrect here.
> 
> You have these additions in this patch  (1/8):
> ...
> +struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *flp,
> +					    const struct sk_buff *skb,
> +					    struct fib_result *res);
> ...
> +struct rtable *ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
> +					const struct sk_buff *skb)
> +{
> +	struct fib_result res;
> +	struct rtable *rth;
> +
> +	res.tclassid	= 0;
> +	res.fi		= NULL;
> +	res.table	= NULL;
> +
> +	rcu_read_lock();
> +	rth = ip_route_output_key_hash_rcu(net, fl4, &res, mp_hash);
>  	rcu_read_unlock();
> +
>  	return rth;
>  }
> -EXPORT_SYMBOL_GPL(__ip_route_output_key_hash);
> +EXPORT_SYMBOL_GPL(ip_route_output_key_hash);
>  
> 
> So the third parameter to ip_route_output_key_hash_rcu() should be skb*, and the fourth parameter should be fib_result *. However, you do not pass the skb parameter 
> when calling ip_route_output_key_hash_rcu() in 
> ip_route_output_key_hash()  (in fact you don't use it at all),  and you pass mp_hash as the fourth parameter.

Yep, it's a problem with the forward port of the first round of patches.

Roopa: in include/net/route.h, __ip_route_output_key_hash should be
removed as well.

^ permalink raw reply

* Re: Deleting a dynamic mac entry..
From: Toshiaki Makita @ 2017-05-25  1:11 UTC (permalink / raw)
  To: Manohar Kumar; +Cc: netdev, bridge
In-Reply-To: <CA+N+6-xtSgQ4eDN7SBMg43WXEc=6quPNE4L1-3xjLuTMte0DSA@mail.gmail.com>

On 2017/05/25 3:05, Manohar Kumar wrote:
> Thanks, Toshiaki.
> 
> What is the right way to set the default_pvid using the bridge command
> ? I tried this, which fails..
> 
> root@net-3:~# ip link set dev vxlan0 name untagged type vlan id 0
> RTNETLINK answers: Operation not supported
> root@net-3:~#
> 
> All the interfaces in the bridge are untagged.

# ip link set br0 down
# echo 0 > /sys/class/net/br0/bridge/default_pvid


Toshiaki Makita

^ permalink raw reply

* Re: [PATCH net-next 1/8] net: ipv4: refactor __ip_route_output_key_hash
From: kbuild test robot @ 2017-05-25  1:30 UTC (permalink / raw)
  To: Roopa Prabhu; +Cc: kbuild-all, davem, netdev, dsahern, nikolay
In-Reply-To: <1495649951-30417-2-git-send-email-roopa@cumulusnetworks.com>

[-- Attachment #1: Type: text/plain, Size: 5778 bytes --]

Hi David,

[auto build test ERROR on net-next/master]

url:    https://github.com/0day-ci/linux/commits/Roopa-Prabhu/net-extend-RTM_GETROUTE-to-return-fib-result/20170525-053253
config: cris-etrax-100lx_v2_defconfig (attached as .config)
compiler: cris-linux-gcc (GCC) 6.2.0
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=cris 

Note: the linux-review/Roopa-Prabhu/net-extend-RTM_GETROUTE-to-return-fib-result/20170525-053253 HEAD 083c4ee9e124d0acf29d159ced8a22cb41665a7a builds fine.
      It only hurts bisectibility.

All error/warnings (new ones prefixed by >>):

   In file included from include/net/route.h:31:0,
                    from include/net/lwtunnel.h:8,
                    from include/net/ip_tunnels.h:17,
                    from include/net/dst_metadata.h:5,
                    from net/ipv4/route.c:94:
   net/ipv4/route.c: In function 'ip_route_output_key_hash_rcu':
>> include/net/ip_fib.h:167:32: error: 'res' is a pointer; did you mean to use '->'?
    #define FIB_RES_NH(res)  ((res).fi->fib_nh[0])
                                   ^
                                      ->
>> include/net/ip_fib.h:196:28: note: in expansion of macro 'FIB_RES_NH'
    #define FIB_RES_DEV(res)  (FIB_RES_NH(res).nh_dev)
                               ^~~~~~~~~~
>> net/ipv4/route.c:2399:35: note: in expansion of macro 'FIB_RES_DEV'
      dev_out = l3mdev_master_dev_rcu(FIB_RES_DEV(res)) ? :
                                      ^~~~~~~~~~~
   net/ipv4/route.c: In function 'ip_route_output_key_hash':
>> net/ipv4/route.c:2430:53: error: 'mp_hash' undeclared (first use in this function)
     rth = ip_route_output_key_hash_rcu(net, fl4, &res, mp_hash);
                                                        ^~~~~~~
   net/ipv4/route.c:2430:53: note: each undeclared identifier is reported only once for each function it appears in
>> net/ipv4/route.c:2430:47: error: passing argument 3 of 'ip_route_output_key_hash_rcu' from incompatible pointer type [-Werror=incompatible-pointer-types]
     rth = ip_route_output_key_hash_rcu(net, fl4, &res, mp_hash);
                                                  ^
   net/ipv4/route.c:2249:16: note: expected 'const struct sk_buff *' but argument is of type 'struct fib_result *'
    struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4,
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
   In file included from include/net/route.h:31:0,
                    from include/net/lwtunnel.h:8,
                    from include/net/ip_tunnels.h:17,
                    from include/net/dst_metadata.h:5,
                    from net//ipv4/route.c:94:
   net//ipv4/route.c: In function 'ip_route_output_key_hash_rcu':
>> include/net/ip_fib.h:167:32: error: 'res' is a pointer; did you mean to use '->'?
    #define FIB_RES_NH(res)  ((res).fi->fib_nh[0])
                                   ^
                                      ->
>> include/net/ip_fib.h:196:28: note: in expansion of macro 'FIB_RES_NH'
    #define FIB_RES_DEV(res)  (FIB_RES_NH(res).nh_dev)
                               ^~~~~~~~~~
   net//ipv4/route.c:2399:35: note: in expansion of macro 'FIB_RES_DEV'
      dev_out = l3mdev_master_dev_rcu(FIB_RES_DEV(res)) ? :
                                      ^~~~~~~~~~~
   net//ipv4/route.c: In function 'ip_route_output_key_hash':
   net//ipv4/route.c:2430:53: error: 'mp_hash' undeclared (first use in this function)
     rth = ip_route_output_key_hash_rcu(net, fl4, &res, mp_hash);
                                                        ^~~~~~~
   net//ipv4/route.c:2430:53: note: each undeclared identifier is reported only once for each function it appears in
   net//ipv4/route.c:2430:47: error: passing argument 3 of 'ip_route_output_key_hash_rcu' from incompatible pointer type [-Werror=incompatible-pointer-types]
     rth = ip_route_output_key_hash_rcu(net, fl4, &res, mp_hash);
                                                  ^
   net//ipv4/route.c:2249:16: note: expected 'const struct sk_buff *' but argument is of type 'struct fib_result *'
    struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4,
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/mp_hash +2430 net/ipv4/route.c

  2393					fl4->saddr = res->fi->fib_prefsrc;
  2394				else
  2395					fl4->saddr = fl4->daddr;
  2396			}
  2397	
  2398			/* L3 master device is the loopback for that domain */
> 2399			dev_out = l3mdev_master_dev_rcu(FIB_RES_DEV(res)) ? :
  2400				net->loopback_dev;
  2401			fl4->flowi4_oif = dev_out->ifindex;
  2402			flags |= RTCF_LOCAL;
  2403			goto make_route;
  2404		}
  2405	
  2406		fib_select_path(net, res, fl4, skb);
  2407	
  2408		dev_out = FIB_RES_DEV(*res);
  2409		fl4->flowi4_oif = dev_out->ifindex;
  2410	
  2411	
  2412	make_route:
  2413		rth = __mkroute_output(res, fl4, orig_oif, dev_out, flags);
  2414	
  2415	out:
  2416		return rth;
  2417	}
  2418	
  2419	struct rtable *ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
  2420						const struct sk_buff *skb)
  2421	{
  2422		struct fib_result res;
  2423		struct rtable *rth;
  2424	
  2425		res.tclassid	= 0;
  2426		res.fi		= NULL;
  2427		res.table	= NULL;
  2428	
  2429		rcu_read_lock();
> 2430		rth = ip_route_output_key_hash_rcu(net, fl4, &res, mp_hash);
  2431		rcu_read_unlock();
  2432	
  2433		return rth;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 8682 bytes --]

^ permalink raw reply

* Re: [PATCH net-next 7/8] net: ipv4: RTM_GETROUTE: return matched fib result when requested
From: David Ahern @ 2017-05-25  2:16 UTC (permalink / raw)
  To: Roopa Prabhu, davem; +Cc: netdev, nikolay
In-Reply-To: <1495649951-30417-8-git-send-email-roopa@cumulusnetworks.com>

On 5/24/17 12:19 PM, Roopa Prabhu wrote:

> @@ -2746,8 +2748,15 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
>  	if (rtm->rtm_flags & RTM_F_LOOKUP_TABLE)
>  		table_id = rt->rt_table_id;
>  
> -	err = rt_fill_info(net, dst, src, table_id, &fl4, skb,
> -			   NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, rt);
> +	if (rtm->rtm_flags & RTM_F_FIB_MATCH)
> +		err = fib_dump_info(skb, NETLINK_CB(in_skb).portid,
> +				    nlh->nlmsg_seq, RTM_NEWROUTE, table_id,
> +				    rt->rt_type, res.prefix, res.prefixlen,
> +				    fl4.flowi4_tos, res.fi, 0);

I like this part -- much simpler than duplicating the attributes which
is where I was headed.

^ permalink raw reply

* [PATCH net-next] ibmvnic: Enable TSO support
From: Thomas Falcon @ 2017-05-25  2:29 UTC (permalink / raw)
  To: netdev; +Cc: Thomas Falcon, Nathan Fontenot, John Allen

Enable TSO in the ibmvnic driver. Scatter-gather is also enabled,
though there currently is no support for scatter-gather in
vNIC-compatible hardware, resulting in forced linearization
of all fragmented SKB's. Though not ideal, given the throughput
improvement gained by enabling TSO, it has been decided
that this is an acceptable tradeoff.

The feature is also enabled by a module parameter.
This parameter is necessary because TSO can not easily be
enabled or disabled in firmware without reinitializing the driver.

CC: Nathan Fontenot <nfont@linux.vnet.ibm.com>
CC: John Allen <jallen@linux.vnet.ibm.com>
Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
---
 drivers/net/ethernet/ibm/ibmvnic.c | 39 +++++++++++++++++++++++++++++++++++---
 1 file changed, 36 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index abe2b6e..64e8d50 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -81,6 +81,11 @@
 static const char ibmvnic_driver_name[] = "ibmvnic";
 static const char ibmvnic_driver_string[] = "IBM System i/p Virtual NIC Driver";
 
+static int large_send_offload;
+module_param(large_send_offload, bool, 0644);
+MODULE_PARM_DESC(large_send_offload,
+		 "Determines whether large send offload is enabled");
+
 MODULE_AUTHOR("Santiago Leon <santi_leon@yahoo.com>");
 MODULE_DESCRIPTION("IBM System i/p Virtual NIC Driver");
 MODULE_LICENSE("GPL");
@@ -1025,6 +1030,17 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
 		goto out;
 	}
 
+	/* All scatter-gather SKB's will be linearized for the time being, but
+	 * scatter-gather is only enabled if the user wishes to use TSO.
+	 */
+	if (skb_shinfo(skb)->nr_frags && __skb_linearize(skb)) {
+		dev_kfree_skb_any(skb);
+		tx_send_failed++;
+		tx_dropped++;
+		ret = NETDEV_TX_OK;
+		goto out;
+	}
+
 	tx_pool = &adapter->tx_pool[queue_num];
 	tx_scrq = adapter->tx_scrq[queue_num];
 	txq = netdev_get_tx_queue(netdev, skb_get_queue_mapping(skb));
@@ -1082,6 +1098,11 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
 		tx_crq.v1.flags1 |= IBMVNIC_TX_CHKSUM_OFFLOAD;
 		hdrs += 2;
 	}
+	if (skb_is_gso(skb)) {
+		tx_crq.v1.flags1 |= IBMVNIC_TX_LSO;
+		tx_crq.v1.mss = cpu_to_be16(skb_shinfo(skb)->gso_size);
+		hdrs += 2;
+	}
 	/* determine if l2/3/4 headers are sent to firmware */
 	if ((*hdrs >> 7) & 1 &&
 	    (skb->protocol == htons(ETH_P_IP) ||
@@ -2629,10 +2650,10 @@ static void handle_query_ip_offload_rsp(struct ibmvnic_adapter *adapter)
 	adapter->ip_offload_ctrl.udp_ipv4_chksum = buf->udp_ipv4_chksum;
 	adapter->ip_offload_ctrl.tcp_ipv6_chksum = buf->tcp_ipv6_chksum;
 	adapter->ip_offload_ctrl.udp_ipv6_chksum = buf->udp_ipv6_chksum;
+	adapter->ip_offload_ctrl.large_tx_ipv4 = buf->large_tx_ipv4;
+	adapter->ip_offload_ctrl.large_tx_ipv6 = buf->large_tx_ipv6;
 
-	/* large_tx/rx disabled for now, additional features needed */
-	adapter->ip_offload_ctrl.large_tx_ipv4 = 0;
-	adapter->ip_offload_ctrl.large_tx_ipv6 = 0;
+	/* large_rx disabled for now, additional features needed */
 	adapter->ip_offload_ctrl.large_rx_ipv4 = 0;
 	adapter->ip_offload_ctrl.large_rx_ipv6 = 0;
 
@@ -2648,6 +2669,18 @@ static void handle_query_ip_offload_rsp(struct ibmvnic_adapter *adapter)
 	    (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)))
 		adapter->netdev->features |= NETIF_F_RXCSUM;
 
+	if (large_send_offload) {
+		/* Scatter-gather is not currently supported by firmware.
+		 * It will only be enabled to support TSO operations.
+		 */
+		adapter->netdev->features = NETIF_F_SG;
+
+		if (buf->large_tx_ipv4)
+			adapter->netdev->features |= NETIF_F_TSO;
+		if (buf->large_tx_ipv6)
+			adapter->netdev->features |= NETIF_F_TSO6;
+	}
+
 	memset(&crq, 0, sizeof(crq));
 	crq.control_ip_offload.first = IBMVNIC_CRQ_CMD;
 	crq.control_ip_offload.cmd = CONTROL_IP_OFFLOAD;
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH net-next 2/2] be2net: Update the driver version to 11.4.0.0
From: Suresh Reddy @ 2017-05-25  2:24 UTC (permalink / raw)
  To: netdev; +Cc: Suresh Reddy
In-Reply-To: <1495679079-12025-1-git-send-email-suresh.reddy@broadcom.com>

Signed-off-by: Suresh Reddy <suresh.reddy@broadcom.com>
---
 drivers/net/ethernet/emulex/benet/be.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 5056624..674cf9d 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -37,7 +37,7 @@
 #include "be_hw.h"
 #include "be_roce.h"
 
-#define DRV_VER			"11.1.0.0"
+#define DRV_VER			"11.4.0.0"
 #define DRV_NAME		"be2net"
 #define BE_NAME			"Emulex BladeEngine2"
 #define BE3_NAME		"Emulex BladeEngine3"
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH net-next 0/2] be2net: patch-set
From: Suresh Reddy @ 2017-05-25  2:24 UTC (permalink / raw)
  To: netdev; +Cc: Suresh Reddy
In-Reply-To: <Suresh.Reddy@broadcom.com>

Hi Dave, Please consider applying these two patches to net-next

Suresh Reddy (2):
  be2net: Fix UE detection logic for BE3
  be2net: Update the driver version to 11.4.0.0

 drivers/net/ethernet/emulex/benet/be.h      |  2 +-
 drivers/net/ethernet/emulex/benet/be_hw.h   |  3 +++
 drivers/net/ethernet/emulex/benet/be_main.c | 27 +++++++++++++++++++--------
 3 files changed, 23 insertions(+), 9 deletions(-)

-- 
1.8.3.1

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox