Message ID | 20230403103440.2895683-6-vladimir.oltean@nxp.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | Add tc-mqprio and tc-taprio support for preemptible traffic classes | expand |
Context | Check | Description |
---|---|---|
netdev/series_format | success | Posting correctly formatted |
netdev/tree_selection | success | Clearly marked for net-next |
netdev/fixes_present | success | Fixes tag not required for -next series |
netdev/header_inline | success | No static functions without inline keyword in header files |
netdev/build_32bit | success | Errors and warnings before: 91 this patch: 91 |
netdev/cc_maintainers | success | CCed 9 of 9 maintainers |
netdev/build_clang | success | Errors and warnings before: 20 this patch: 20 |
netdev/verify_signedoff | success | Signed-off-by tag matches author and committer |
netdev/deprecated_api | success | None detected |
netdev/check_selftest | success | No net selftest shell script |
netdev/verify_fixes | success | No Fixes tag |
netdev/build_allmodconfig_warn | success | Errors and warnings before: 109 this patch: 109 |
netdev/checkpatch | success | total: 0 errors, 0 warnings, 0 checks, 58 lines checked |
netdev/kdoc | success | Errors and warnings before: 0 this patch: 0 |
netdev/source_inline | success | Was 0 now: 0 |
On Mon, Apr 3, 2023 at 6:35 AM Vladimir Oltean <vladimir.oltean@nxp.com> wrote: > > With the multiplexed ndo_setup_tc() model which lacks a first-class > struct netlink_ext_ack * argument, the only way to pass the netlink > extended ACK message down to the device driver is to embed it within the > offload structure. > > Do this for struct tc_mqprio_qopt_offload and struct tc_taprio_qopt_offload. > > Since struct tc_taprio_qopt_offload also contains a tc_mqprio_qopt_offload > structure, and since device drivers might effectively reuse their mqprio > implementation for the mqprio portion of taprio, we make taprio set the > extack in both offload structures to point at the same netlink extack > message. > > In fact, the taprio handling is a bit more tricky, for 2 reasons. > > First is because the offload structure has a longer lifetime than the > extack structure. The driver is supposed to populate the extack > synchronously from ndo_setup_tc() and leave it alone afterwards. > To not have any use-after-free surprises, we zero out the extack pointer > when we leave taprio_enable_offload(). > > The second reason is because taprio does overwrite the extack message on > ndo_setup_tc() error. We need to switch to the weak form of setting an > extack message, which preserves a potential message set by the driver. > > Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> > Reviewed-by: Simon Horman <simon.horman@corigine.com> Acked-by: Jamal Hadi Salim <jhs@mojatatu.com> cheers, jamal > --- > v3->v4: none > v2->v3: patch is new > > include/net/pkt_sched.h | 2 ++ > net/sched/sch_mqprio.c | 5 ++++- > net/sched/sch_taprio.c | 12 ++++++++++-- > 3 files changed, 16 insertions(+), 3 deletions(-) > > diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h > index bb0bd69fb655..b43ed4733455 100644 > --- a/include/net/pkt_sched.h > +++ b/include/net/pkt_sched.h > @@ -166,6 +166,7 @@ struct tc_mqprio_caps { > struct tc_mqprio_qopt_offload { > /* struct tc_mqprio_qopt must always be the first element */ > struct tc_mqprio_qopt qopt; > + struct netlink_ext_ack *extack; > u16 mode; > u16 shaper; > u32 flags; > @@ -193,6 +194,7 @@ struct tc_taprio_sched_entry { > > struct tc_taprio_qopt_offload { > struct tc_mqprio_qopt_offload mqprio; > + struct netlink_ext_ack *extack; > u8 enable; > ktime_t base_time; > u64 cycle_time; > diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c > index 9ee5a9a9b9e9..5287ff60b3f9 100644 > --- a/net/sched/sch_mqprio.c > +++ b/net/sched/sch_mqprio.c > @@ -33,9 +33,12 @@ static int mqprio_enable_offload(struct Qdisc *sch, > const struct tc_mqprio_qopt *qopt, > struct netlink_ext_ack *extack) > { > - struct tc_mqprio_qopt_offload mqprio = {.qopt = *qopt}; > struct mqprio_sched *priv = qdisc_priv(sch); > struct net_device *dev = qdisc_dev(sch); > + struct tc_mqprio_qopt_offload mqprio = { > + .qopt = *qopt, > + .extack = extack, > + }; > int err, i; > > switch (priv->mode) { > diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c > index 1f469861eae3..cbad43019172 100644 > --- a/net/sched/sch_taprio.c > +++ b/net/sched/sch_taprio.c > @@ -1520,7 +1520,9 @@ static int taprio_enable_offload(struct net_device *dev, > return -ENOMEM; > } > offload->enable = 1; > + offload->extack = extack; > mqprio_qopt_reconstruct(dev, &offload->mqprio.qopt); > + offload->mqprio.extack = extack; > taprio_sched_to_offload(dev, sched, offload, &caps); > > for (tc = 0; tc < TC_MAX_QUEUE; tc++) > @@ -1528,14 +1530,20 @@ static int taprio_enable_offload(struct net_device *dev, > > err = ops->ndo_setup_tc(dev, TC_SETUP_QDISC_TAPRIO, offload); > if (err < 0) { > - NL_SET_ERR_MSG(extack, > - "Device failed to setup taprio offload"); > + NL_SET_ERR_MSG_WEAK(extack, > + "Device failed to setup taprio offload"); > goto done; > } > > q->offloaded = true; > > done: > + /* The offload structure may linger around via a reference taken by the > + * device driver, so clear up the netlink extack pointer so that the > + * driver isn't tempted to dereference data which stopped being valid > + */ > + offload->extack = NULL; > + offload->mqprio.extack = NULL; > taprio_offload_free(offload); > > return err; > -- > 2.34.1 >
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index bb0bd69fb655..b43ed4733455 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -166,6 +166,7 @@ struct tc_mqprio_caps { struct tc_mqprio_qopt_offload { /* struct tc_mqprio_qopt must always be the first element */ struct tc_mqprio_qopt qopt; + struct netlink_ext_ack *extack; u16 mode; u16 shaper; u32 flags; @@ -193,6 +194,7 @@ struct tc_taprio_sched_entry { struct tc_taprio_qopt_offload { struct tc_mqprio_qopt_offload mqprio; + struct netlink_ext_ack *extack; u8 enable; ktime_t base_time; u64 cycle_time; diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c index 9ee5a9a9b9e9..5287ff60b3f9 100644 --- a/net/sched/sch_mqprio.c +++ b/net/sched/sch_mqprio.c @@ -33,9 +33,12 @@ static int mqprio_enable_offload(struct Qdisc *sch, const struct tc_mqprio_qopt *qopt, struct netlink_ext_ack *extack) { - struct tc_mqprio_qopt_offload mqprio = {.qopt = *qopt}; struct mqprio_sched *priv = qdisc_priv(sch); struct net_device *dev = qdisc_dev(sch); + struct tc_mqprio_qopt_offload mqprio = { + .qopt = *qopt, + .extack = extack, + }; int err, i; switch (priv->mode) { diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c index 1f469861eae3..cbad43019172 100644 --- a/net/sched/sch_taprio.c +++ b/net/sched/sch_taprio.c @@ -1520,7 +1520,9 @@ static int taprio_enable_offload(struct net_device *dev, return -ENOMEM; } offload->enable = 1; + offload->extack = extack; mqprio_qopt_reconstruct(dev, &offload->mqprio.qopt); + offload->mqprio.extack = extack; taprio_sched_to_offload(dev, sched, offload, &caps); for (tc = 0; tc < TC_MAX_QUEUE; tc++) @@ -1528,14 +1530,20 @@ static int taprio_enable_offload(struct net_device *dev, err = ops->ndo_setup_tc(dev, TC_SETUP_QDISC_TAPRIO, offload); if (err < 0) { - NL_SET_ERR_MSG(extack, - "Device failed to setup taprio offload"); + NL_SET_ERR_MSG_WEAK(extack, + "Device failed to setup taprio offload"); goto done; } q->offloaded = true; done: + /* The offload structure may linger around via a reference taken by the + * device driver, so clear up the netlink extack pointer so that the + * driver isn't tempted to dereference data which stopped being valid + */ + offload->extack = NULL; + offload->mqprio.extack = NULL; taprio_offload_free(offload); return err;