taprio: validate TCA_TAPRIO_ATTR_FLAGS through policy instead of open-coding
[linux-2.6-microblaze.git] / net / sched / sch_taprio.c
index 31a8252..827cb68 100644 (file)
@@ -40,6 +40,8 @@ static struct static_key_false taprio_have_working_mqprio;
 
 #define TXTIME_ASSIST_IS_ENABLED(flags) ((flags) & TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST)
 #define FULL_OFFLOAD_IS_ENABLED(flags) ((flags) & TCA_TAPRIO_ATTR_FLAG_FULL_OFFLOAD)
+#define TAPRIO_SUPPORTED_FLAGS \
+       (TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST | TCA_TAPRIO_ATTR_FLAG_FULL_OFFLOAD)
 #define TAPRIO_FLAGS_INVALID U32_MAX
 
 struct sched_entry {
@@ -408,19 +410,6 @@ static bool is_valid_interval(struct sk_buff *skb, struct Qdisc *sch)
        return entry;
 }
 
-static bool taprio_flags_valid(u32 flags)
-{
-       /* Make sure no other flag bits are set. */
-       if (flags & ~(TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST |
-                     TCA_TAPRIO_ATTR_FLAG_FULL_OFFLOAD))
-               return false;
-       /* txtime-assist and full offload are mutually exclusive */
-       if ((flags & TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST) &&
-           (flags & TCA_TAPRIO_ATTR_FLAG_FULL_OFFLOAD))
-               return false;
-       return true;
-}
-
 /* This returns the tstamp value set by TCP in terms of the set clock. */
 static ktime_t get_tcp_tstamp(struct taprio_sched *q, struct sk_buff *skb)
 {
@@ -1031,7 +1020,8 @@ static const struct nla_policy taprio_policy[TCA_TAPRIO_ATTR_MAX + 1] = {
        [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME]           =
                NLA_POLICY_FULL_RANGE_SIGNED(NLA_S64, &taprio_cycle_time_range),
        [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION] = { .type = NLA_S64 },
-       [TCA_TAPRIO_ATTR_FLAGS]                      = { .type = NLA_U32 },
+       [TCA_TAPRIO_ATTR_FLAGS]                      =
+               NLA_POLICY_MASK(NLA_U32, TAPRIO_SUPPORTED_FLAGS),
        [TCA_TAPRIO_ATTR_TXTIME_DELAY]               = { .type = NLA_U32 },
        [TCA_TAPRIO_ATTR_TC_ENTRY]                   = { .type = NLA_NESTED },
 };
@@ -1815,33 +1805,6 @@ static int taprio_mqprio_cmp(const struct net_device *dev,
        return 0;
 }
 
-/* The semantics of the 'flags' argument in relation to 'change()'
- * requests, are interpreted following two rules (which are applied in
- * this order): (1) an omitted 'flags' argument is interpreted as
- * zero; (2) the 'flags' of a "running" taprio instance cannot be
- * changed.
- */
-static int taprio_new_flags(const struct nlattr *attr, u32 old,
-                           struct netlink_ext_ack *extack)
-{
-       u32 new = 0;
-
-       if (attr)
-               new = nla_get_u32(attr);
-
-       if (old != TAPRIO_FLAGS_INVALID && old != new) {
-               NL_SET_ERR_MSG_MOD(extack, "Changing 'flags' of a running schedule is not supported");
-               return -EOPNOTSUPP;
-       }
-
-       if (!taprio_flags_valid(new)) {
-               NL_SET_ERR_MSG_MOD(extack, "Specified 'flags' are not valid");
-               return -EINVAL;
-       }
-
-       return new;
-}
-
 static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
                         struct netlink_ext_ack *extack)
 {
@@ -1852,6 +1815,7 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
        struct net_device *dev = qdisc_dev(sch);
        struct tc_mqprio_qopt *mqprio = NULL;
        unsigned long flags;
+       u32 taprio_flags;
        ktime_t start;
        int i, err;
 
@@ -1863,12 +1827,28 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
        if (tb[TCA_TAPRIO_ATTR_PRIOMAP])
                mqprio = nla_data(tb[TCA_TAPRIO_ATTR_PRIOMAP]);
 
-       err = taprio_new_flags(tb[TCA_TAPRIO_ATTR_FLAGS],
-                              q->flags, extack);
-       if (err < 0)
-               return err;
+       /* The semantics of the 'flags' argument in relation to 'change()'
+        * requests, are interpreted following two rules (which are applied in
+        * this order): (1) an omitted 'flags' argument is interpreted as
+        * zero; (2) the 'flags' of a "running" taprio instance cannot be
+        * changed.
+        */
+       taprio_flags = tb[TCA_TAPRIO_ATTR_FLAGS] ? nla_get_u32(tb[TCA_TAPRIO_ATTR_FLAGS]) : 0;
 
-       q->flags = err;
+       /* txtime-assist and full offload are mutually exclusive */
+       if ((taprio_flags & TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST) &&
+           (taprio_flags & TCA_TAPRIO_ATTR_FLAG_FULL_OFFLOAD)) {
+               NL_SET_ERR_MSG_ATTR(extack, tb[TCA_TAPRIO_ATTR_FLAGS],
+                                   "TXTIME_ASSIST and FULL_OFFLOAD are mutually exclusive");
+               return -EINVAL;
+       }
+
+       if (q->flags != TAPRIO_FLAGS_INVALID && q->flags != taprio_flags) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Changing 'flags' of a running schedule is not supported");
+               return -EOPNOTSUPP;
+       }
+       q->flags = taprio_flags;
 
        err = taprio_parse_mqprio_opt(dev, mqprio, extack, q->flags);
        if (err < 0)