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 487fa5e..97b4233 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 f6c0cd2..fa31d03 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 f55bc50..9c88cec 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;