net: sched: provide notification for graft on root
authorJakub Kicinski <jakub.kicinski@netronome.com>
Mon, 12 Nov 2018 22:58:10 +0000 (14:58 -0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 14 Nov 2018 16:51:27 +0000 (08:51 -0800)
Drivers are currently not notified when a Qdisc is grafted as root.
This requires special casing Qdiscs added with parent = TC_H_ROOT in
the driver.  Also there is no notification sent to the driver when
an existing Qdisc is grafted as root.

Add this very simple notifications, drivers should now be able to
track their Qdisc tree fully.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: John Hurley <john.hurley@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/netdevice.h
include/net/pkt_cls.h
net/sched/sch_api.c

index 487fa5e0e1652da8ea91253c5c3b84ddcb0a8925..97b4233120e4b03e184f18c66b7596be8aae70a4 100644 (file)
@@ -845,6 +845,7 @@ enum tc_setup_type {
        TC_SETUP_QDISC_PRIO,
        TC_SETUP_QDISC_MQ,
        TC_SETUP_QDISC_ETF,
+       TC_SETUP_ROOT_QDISC,
 };
 
 /* These structures hold the attributes of bpf state that are being passed
index f6c0cd29dea40f007e0e444b51594a6531d8b86e..fa31d034231d3ccc256884165c14a6c03c0cb1ee 100644 (file)
@@ -889,4 +889,14 @@ struct tc_prio_qopt_offload {
        };
 };
 
+enum tc_root_command {
+       TC_ROOT_GRAFT,
+};
+
+struct tc_root_qopt_offload {
+       enum tc_root_command command;
+       u32 handle;
+       bool ingress;
+};
+
 #endif
index f55bc50cd0a938a8f5562caa50c24df02bac3080..9c88cec7e8a20f9f30a9f4113e34cf96084ee393 100644 (file)
@@ -860,6 +860,21 @@ void qdisc_offload_graft_helper(struct net_device *dev, struct Qdisc *sch,
 }
 EXPORT_SYMBOL(qdisc_offload_graft_helper);
 
+static void qdisc_offload_graft_root(struct net_device *dev,
+                                    struct Qdisc *new, struct Qdisc *old,
+                                    struct netlink_ext_ack *extack)
+{
+       struct tc_root_qopt_offload graft_offload = {
+               .command        = TC_ROOT_GRAFT,
+               .handle         = new ? new->handle : 0,
+               .ingress        = (new && new->flags & TCQ_F_INGRESS) ||
+                                 (old && old->flags & TCQ_F_INGRESS),
+       };
+
+       qdisc_offload_graft_helper(dev, NULL, new, old,
+                                  TC_SETUP_ROOT_QDISC, &graft_offload, extack);
+}
+
 static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
                         u32 portid, u32 seq, u16 flags, int event)
 {
@@ -1026,6 +1041,8 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
                if (dev->flags & IFF_UP)
                        dev_deactivate(dev);
 
+               qdisc_offload_graft_root(dev, new, old, extack);
+
                if (new && new->ops->attach)
                        goto skip;