-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'add-new-pcp-and-apptrust-attributes-to-dcbnl'
Daniel Machon says: ==================== Add new PCP and APPTRUST attributes to dcbnl This patch series adds new extension attributes to dcbnl, to support PCP prioritization (and thereby hw offloadable pcp-based queue classification) and per-selector trust and trust order. Additionally, the microchip sparx5 driver has been dcb-enabled to make use of the new attributes to offload PCP, DSCP and Default prio to the switch, and implement trust order of selectors. For pre-RFC discussion see: https://lore.kernel.org/netdev/Yv9VO1DYAxNduw6A@DEN-LT-70577/ For RFC series see: https://lore.kernel.org/netdev/20220915095757.2861822-1-daniel.machon@microchip.com/ In summary: there currently exist no convenient way to offload per-port PCP-based queue classification to hardware. The DCB subsystem offers different ways to prioritize through its APP table, but lacks an option for PCP. Similarly, there is no way to indicate the notion of trust for APP table selectors. This patch series addresses both topics. PCP based queue classification: - 8021Q standardizes the Priority Code Point table (see 6.9.3 of IEEE Std 802.1Q-2018). This patch series makes it possible, to offload the PCP classification to said table. The new PCP selector is not a standard part of the APP managed object, therefore it is encapsulated in a new non-std extension attribute. Selector trust: - ASIC's often has the notion of trust DSCP and trust PCP. The new attribute makes it possible to specify a trust order of app selectors, which drivers can then react on. DCB-enable sparx5 driver: - Now supports offloading of DSCP, PCP and default priority. Only one mapping of protocol:priority is allowed. Consecutive mappings of the same protocol to some new priority, will overwrite the previous. This is to keep a consistent view of the app table and the hardware. - Now supports dscp and pcp trust, by use of the introduced dcbnl_set/getapptrust ops. Sparx5 supports trust orders: [], [dscp], [pcp] and [dscp, pcp]. For now, only DSCP and PCP selectors are supported by the driver, everything else is bounced. Patch #1 introduces a new PCP selector to the APP object, which makes it possible to encode PCP and DEI in the app triplet and offload it to the PCP table of the ASIC. Patch #2 Introduces the new extension attributes DCB_ATTR_DCB_APP_TRUST_TABLE and DCB_ATTR_DCB_APP_TRUST. Trusted selectors are passed in the nested DCB_ATTR_DCB_APP_TRUST_TABLE attribute, and assembled into an array of selectors: u8 selectors[256]; where lower indexes has higher precedence. In the array, selectors are stored consecutively, starting from index zero. With a maximum number of 256 unique selectors, the list has the same maximum size. Patch #3 Sets up the dcbnl ops hook, and adds support for offloading pcp app entries, to the PCP table of the switch. Patch #4 Makes use of the dcbnl_set/getapptrust ops, to set a per-port trust order. Patch #5 Adds support for offloading dscp app entries to the DSCP table of the switch. Patch #6 Adds support for offloading default prio app entries to the switch. ==================== Link: https://lore.kernel.org/r/20221101094834.2726202-1-daniel.machon@microchip.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
- Loading branch information
Showing
11 changed files
with
744 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,310 @@ | ||
// SPDX-License-Identifier: GPL-2.0+ | ||
/* Microchip Sparx5 Switch driver | ||
* | ||
* Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries. | ||
*/ | ||
|
||
#include <net/dcbnl.h> | ||
|
||
#include "sparx5_port.h" | ||
|
||
enum sparx5_dcb_apptrust_values { | ||
SPARX5_DCB_APPTRUST_EMPTY, | ||
SPARX5_DCB_APPTRUST_DSCP, | ||
SPARX5_DCB_APPTRUST_PCP, | ||
SPARX5_DCB_APPTRUST_DSCP_PCP, | ||
__SPARX5_DCB_APPTRUST_MAX | ||
}; | ||
|
||
static const struct sparx5_dcb_apptrust { | ||
u8 selectors[IEEE_8021QAZ_APP_SEL_MAX + 1]; | ||
int nselectors; | ||
} *sparx5_port_apptrust[SPX5_PORTS]; | ||
|
||
static const char *sparx5_dcb_apptrust_names[__SPARX5_DCB_APPTRUST_MAX] = { | ||
[SPARX5_DCB_APPTRUST_EMPTY] = "empty", | ||
[SPARX5_DCB_APPTRUST_DSCP] = "dscp", | ||
[SPARX5_DCB_APPTRUST_PCP] = "pcp", | ||
[SPARX5_DCB_APPTRUST_DSCP_PCP] = "dscp pcp" | ||
}; | ||
|
||
/* Sparx5 supported apptrust policies */ | ||
static const struct sparx5_dcb_apptrust | ||
sparx5_dcb_apptrust_policies[__SPARX5_DCB_APPTRUST_MAX] = { | ||
/* Empty *must* be first */ | ||
[SPARX5_DCB_APPTRUST_EMPTY] = { { 0 }, 0 }, | ||
[SPARX5_DCB_APPTRUST_DSCP] = { { IEEE_8021QAZ_APP_SEL_DSCP }, 1 }, | ||
[SPARX5_DCB_APPTRUST_PCP] = { { DCB_APP_SEL_PCP }, 1 }, | ||
[SPARX5_DCB_APPTRUST_DSCP_PCP] = { { IEEE_8021QAZ_APP_SEL_DSCP, | ||
DCB_APP_SEL_PCP }, 2 }, | ||
}; | ||
|
||
/* Validate app entry. | ||
* | ||
* Check for valid selectors and valid protocol and priority ranges. | ||
*/ | ||
static int sparx5_dcb_app_validate(struct net_device *dev, | ||
const struct dcb_app *app) | ||
{ | ||
int err = 0; | ||
|
||
switch (app->selector) { | ||
/* Default priority checks */ | ||
case IEEE_8021QAZ_APP_SEL_ETHERTYPE: | ||
if (app->protocol != 0) | ||
err = -EINVAL; | ||
else if (app->priority >= SPX5_PRIOS) | ||
err = -ERANGE; | ||
break; | ||
/* Dscp checks */ | ||
case IEEE_8021QAZ_APP_SEL_DSCP: | ||
if (app->protocol >= SPARX5_PORT_QOS_DSCP_COUNT) | ||
err = -EINVAL; | ||
else if (app->priority >= SPX5_PRIOS) | ||
err = -ERANGE; | ||
break; | ||
/* Pcp checks */ | ||
case DCB_APP_SEL_PCP: | ||
if (app->protocol >= SPARX5_PORT_QOS_PCP_DEI_COUNT) | ||
err = -EINVAL; | ||
else if (app->priority >= SPX5_PRIOS) | ||
err = -ERANGE; | ||
break; | ||
default: | ||
err = -EINVAL; | ||
break; | ||
} | ||
|
||
if (err) | ||
netdev_err(dev, "Invalid entry: %d:%d\n", app->protocol, | ||
app->priority); | ||
|
||
return err; | ||
} | ||
|
||
/* Validate apptrust configuration. | ||
* | ||
* Return index of supported apptrust configuration if valid, otherwise return | ||
* error. | ||
*/ | ||
static int sparx5_dcb_apptrust_validate(struct net_device *dev, u8 *selectors, | ||
int nselectors, int *err) | ||
{ | ||
bool match; | ||
int i, ii; | ||
|
||
for (i = 0; i < ARRAY_SIZE(sparx5_dcb_apptrust_policies); i++) { | ||
if (sparx5_dcb_apptrust_policies[i].nselectors != nselectors) | ||
continue; | ||
match = true; | ||
for (ii = 0; ii < nselectors; ii++) { | ||
if (sparx5_dcb_apptrust_policies[i].selectors[ii] != | ||
*(selectors + ii)) { | ||
match = false; | ||
break; | ||
} | ||
} | ||
if (match) | ||
break; | ||
} | ||
|
||
/* Requested trust configuration is not supported */ | ||
if (!match) { | ||
netdev_err(dev, "Valid apptrust configurations are:\n"); | ||
for (i = 0; i < ARRAY_SIZE(sparx5_dcb_apptrust_names); i++) | ||
pr_info("order: %s\n", sparx5_dcb_apptrust_names[i]); | ||
*err = -EOPNOTSUPP; | ||
} | ||
|
||
return i; | ||
} | ||
|
||
static bool sparx5_dcb_apptrust_contains(int portno, u8 selector) | ||
{ | ||
const struct sparx5_dcb_apptrust *conf = sparx5_port_apptrust[portno]; | ||
int i; | ||
|
||
for (i = 0; i < conf->nselectors; i++) | ||
if (conf->selectors[i] == selector) | ||
return true; | ||
|
||
return false; | ||
} | ||
|
||
static int sparx5_dcb_app_update(struct net_device *dev) | ||
{ | ||
struct sparx5_port *port = netdev_priv(dev); | ||
struct sparx5_port_qos_dscp_map *dscp_map; | ||
struct sparx5_port_qos_pcp_map *pcp_map; | ||
struct sparx5_port_qos qos = {0}; | ||
struct dcb_app app_itr = {0}; | ||
int portno = port->portno; | ||
int i; | ||
|
||
dscp_map = &qos.dscp.map; | ||
pcp_map = &qos.pcp.map; | ||
|
||
/* Get default prio. */ | ||
qos.default_prio = dcb_ieee_getapp_default_prio_mask(dev); | ||
if (qos.default_prio) | ||
qos.default_prio = fls(qos.default_prio) - 1; | ||
|
||
/* Get dscp ingress mapping */ | ||
for (i = 0; i < ARRAY_SIZE(dscp_map->map); i++) { | ||
app_itr.selector = IEEE_8021QAZ_APP_SEL_DSCP; | ||
app_itr.protocol = i; | ||
dscp_map->map[i] = dcb_getapp(dev, &app_itr); | ||
} | ||
|
||
/* Get pcp ingress mapping */ | ||
for (i = 0; i < ARRAY_SIZE(pcp_map->map); i++) { | ||
app_itr.selector = DCB_APP_SEL_PCP; | ||
app_itr.protocol = i; | ||
pcp_map->map[i] = dcb_getapp(dev, &app_itr); | ||
} | ||
|
||
/* Enable use of pcp for queue classification ? */ | ||
if (sparx5_dcb_apptrust_contains(portno, DCB_APP_SEL_PCP)) { | ||
qos.pcp.qos_enable = true; | ||
qos.pcp.dp_enable = qos.pcp.qos_enable; | ||
} | ||
|
||
/* Enable use of dscp for queue classification ? */ | ||
if (sparx5_dcb_apptrust_contains(portno, IEEE_8021QAZ_APP_SEL_DSCP)) { | ||
qos.dscp.qos_enable = true; | ||
qos.dscp.dp_enable = qos.dscp.qos_enable; | ||
} | ||
|
||
return sparx5_port_qos_set(port, &qos); | ||
} | ||
|
||
/* Set or delete dscp app entry. | ||
* | ||
* Dscp mapping is global for all ports, so set and delete app entries are | ||
* replicated for each port. | ||
*/ | ||
static int sparx5_dcb_ieee_dscp_setdel_app(struct net_device *dev, | ||
struct dcb_app *app, bool del) | ||
{ | ||
struct sparx5_port *port = netdev_priv(dev); | ||
struct dcb_app apps[SPX5_PORTS]; | ||
struct sparx5_port *port_itr; | ||
int err, i; | ||
|
||
for (i = 0; i < SPX5_PORTS; i++) { | ||
port_itr = port->sparx5->ports[i]; | ||
if (!port_itr) | ||
continue; | ||
memcpy(&apps[i], app, sizeof(struct dcb_app)); | ||
if (del) | ||
err = dcb_ieee_delapp(port_itr->ndev, &apps[i]); | ||
else | ||
err = dcb_ieee_setapp(port_itr->ndev, &apps[i]); | ||
if (err) | ||
return err; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int sparx5_dcb_ieee_setapp(struct net_device *dev, struct dcb_app *app) | ||
{ | ||
struct dcb_app app_itr; | ||
int err = 0; | ||
u8 prio; | ||
|
||
err = sparx5_dcb_app_validate(dev, app); | ||
if (err) | ||
goto out; | ||
|
||
/* Delete current mapping, if it exists */ | ||
prio = dcb_getapp(dev, app); | ||
if (prio) { | ||
app_itr = *app; | ||
app_itr.priority = prio; | ||
dcb_ieee_delapp(dev, &app_itr); | ||
} | ||
|
||
if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) | ||
err = sparx5_dcb_ieee_dscp_setdel_app(dev, app, false); | ||
else | ||
err = dcb_ieee_setapp(dev, app); | ||
|
||
if (err) | ||
goto out; | ||
|
||
sparx5_dcb_app_update(dev); | ||
|
||
out: | ||
return err; | ||
} | ||
|
||
static int sparx5_dcb_ieee_delapp(struct net_device *dev, struct dcb_app *app) | ||
{ | ||
int err; | ||
|
||
if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) | ||
err = sparx5_dcb_ieee_dscp_setdel_app(dev, app, true); | ||
else | ||
err = dcb_ieee_delapp(dev, app); | ||
|
||
if (err < 0) | ||
return err; | ||
|
||
return sparx5_dcb_app_update(dev); | ||
} | ||
|
||
static int sparx5_dcb_setapptrust(struct net_device *dev, u8 *selectors, | ||
int nselectors) | ||
{ | ||
struct sparx5_port *port = netdev_priv(dev); | ||
int err = 0, idx; | ||
|
||
idx = sparx5_dcb_apptrust_validate(dev, selectors, nselectors, &err); | ||
if (err < 0) | ||
return err; | ||
|
||
sparx5_port_apptrust[port->portno] = &sparx5_dcb_apptrust_policies[idx]; | ||
|
||
return sparx5_dcb_app_update(dev); | ||
} | ||
|
||
static int sparx5_dcb_getapptrust(struct net_device *dev, u8 *selectors, | ||
int *nselectors) | ||
{ | ||
struct sparx5_port *port = netdev_priv(dev); | ||
const struct sparx5_dcb_apptrust *trust; | ||
|
||
trust = sparx5_port_apptrust[port->portno]; | ||
|
||
memcpy(selectors, trust->selectors, trust->nselectors); | ||
*nselectors = trust->nselectors; | ||
|
||
return 0; | ||
} | ||
|
||
const struct dcbnl_rtnl_ops sparx5_dcbnl_ops = { | ||
.ieee_setapp = sparx5_dcb_ieee_setapp, | ||
.ieee_delapp = sparx5_dcb_ieee_delapp, | ||
.dcbnl_setapptrust = sparx5_dcb_setapptrust, | ||
.dcbnl_getapptrust = sparx5_dcb_getapptrust, | ||
}; | ||
|
||
int sparx5_dcb_init(struct sparx5 *sparx5) | ||
{ | ||
struct sparx5_port *port; | ||
int i; | ||
|
||
for (i = 0; i < SPX5_PORTS; i++) { | ||
port = sparx5->ports[i]; | ||
if (!port) | ||
continue; | ||
port->ndev->dcbnl_ops = &sparx5_dcbnl_ops; | ||
/* Initialize [dscp, pcp] default trust */ | ||
sparx5_port_apptrust[port->portno] = | ||
&sparx5_dcb_apptrust_policies | ||
[SPARX5_DCB_APPTRUST_DSCP_PCP]; | ||
} | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.