Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net/sched: Enable tc skb ext allocation on chain miss only when needed

Currently tc skb extension is used to send miss info from
tc to ovs datapath module, and driver to tc. For the tc to ovs
miss it is currently always allocated even if it will not
be used by ovs datapath (as it depends on a requested feature).

Export the static key which is used by openvswitch module to
guard this code path as well, so it will be skipped if ovs
datapath doesn't need it. Enable this code path once
ovs datapath needs it.

Signed-off-by: Paul Blakey <paulb@nvidia.com>
Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Paul Blakey and committed by
David S. Miller
35d39fec ed8c8f60

+55 -22
+11
include/net/pkt_cls.h
··· 1028 1028 }; 1029 1029 }; 1030 1030 1031 + #ifdef CONFIG_NET_CLS_ACT 1032 + DECLARE_STATIC_KEY_FALSE(tc_skb_ext_tc); 1033 + void tc_skb_ext_tc_enable(void); 1034 + void tc_skb_ext_tc_disable(void); 1035 + #define tc_skb_ext_tc_enabled() static_branch_unlikely(&tc_skb_ext_tc) 1036 + #else /* CONFIG_NET_CLS_ACT */ 1037 + static inline void tc_skb_ext_tc_enable(void) { } 1038 + static inline void tc_skb_ext_tc_disable(void) { } 1039 + #define tc_skb_ext_tc_enabled() false 1040 + #endif 1041 + 1031 1042 #endif
+11 -7
net/openvswitch/datapath.c
··· 37 37 #include <net/genetlink.h> 38 38 #include <net/net_namespace.h> 39 39 #include <net/netns/generic.h> 40 + #include <net/pkt_cls.h> 40 41 41 42 #include "datapath.h" 42 43 #include "flow.h" ··· 1602 1601 dp->user_features = 0; 1603 1602 } 1604 1603 1605 - DEFINE_STATIC_KEY_FALSE(tc_recirc_sharing_support); 1606 - 1607 1604 static int ovs_dp_set_upcall_portids(struct datapath *dp, 1608 1605 const struct nlattr *ids) 1609 1606 { ··· 1656 1657 1657 1658 static int ovs_dp_change(struct datapath *dp, struct nlattr *a[]) 1658 1659 { 1659 - u32 user_features = 0; 1660 + u32 user_features = 0, old_features = dp->user_features; 1660 1661 int err; 1661 1662 1662 1663 if (a[OVS_DP_ATTR_USER_FEATURES]) { ··· 1695 1696 return err; 1696 1697 } 1697 1698 1698 - if (dp->user_features & OVS_DP_F_TC_RECIRC_SHARING) 1699 - static_branch_enable(&tc_recirc_sharing_support); 1700 - else 1701 - static_branch_disable(&tc_recirc_sharing_support); 1699 + if ((dp->user_features & OVS_DP_F_TC_RECIRC_SHARING) && 1700 + !(old_features & OVS_DP_F_TC_RECIRC_SHARING)) 1701 + tc_skb_ext_tc_enable(); 1702 + else if (!(dp->user_features & OVS_DP_F_TC_RECIRC_SHARING) && 1703 + (old_features & OVS_DP_F_TC_RECIRC_SHARING)) 1704 + tc_skb_ext_tc_disable(); 1702 1705 1703 1706 return 0; 1704 1707 } ··· 1839 1838 { 1840 1839 struct flow_table *table = &dp->table; 1841 1840 int i; 1841 + 1842 + if (dp->user_features & OVS_DP_F_TC_RECIRC_SHARING) 1843 + tc_skb_ext_tc_disable(); 1842 1844 1843 1845 for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) { 1844 1846 struct vport *vport;
-2
net/openvswitch/datapath.h
··· 253 253 extern struct notifier_block ovs_dp_device_notifier; 254 254 extern struct genl_family dp_vport_genl_family; 255 255 256 - DECLARE_STATIC_KEY_FALSE(tc_recirc_sharing_support); 257 - 258 256 void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key); 259 257 void ovs_dp_detach_port(struct vport *); 260 258 int ovs_dp_upcall(struct datapath *, struct sk_buff *,
+2 -1
net/openvswitch/flow.c
··· 34 34 #include <net/mpls.h> 35 35 #include <net/ndisc.h> 36 36 #include <net/nsh.h> 37 + #include <net/pkt_cls.h> 37 38 #include <net/netfilter/nf_conntrack_zones.h> 38 39 39 40 #include "conntrack.h" ··· 896 895 key->mac_proto = res; 897 896 898 897 #if IS_ENABLED(CONFIG_NET_TC_SKB_EXT) 899 - if (static_branch_unlikely(&tc_recirc_sharing_support)) { 898 + if (tc_skb_ext_tc_enabled()) { 900 899 tc_ext = skb_ext_find(skb, TC_SKB_EXT); 901 900 key->recirc_id = tc_ext ? tc_ext->chain : 0; 902 901 OVS_CB(skb)->mru = tc_ext ? tc_ext->mru : 0;
+31 -12
net/sched/cls_api.c
··· 49 49 /* Protects list of registered TC modules. It is pure SMP lock. */ 50 50 static DEFINE_RWLOCK(cls_mod_lock); 51 51 52 + #ifdef CONFIG_NET_CLS_ACT 53 + DEFINE_STATIC_KEY_FALSE(tc_skb_ext_tc); 54 + EXPORT_SYMBOL(tc_skb_ext_tc); 55 + 56 + void tc_skb_ext_tc_enable(void) 57 + { 58 + static_branch_inc(&tc_skb_ext_tc); 59 + } 60 + EXPORT_SYMBOL(tc_skb_ext_tc_enable); 61 + 62 + void tc_skb_ext_tc_disable(void) 63 + { 64 + static_branch_dec(&tc_skb_ext_tc); 65 + } 66 + EXPORT_SYMBOL(tc_skb_ext_tc_disable); 67 + #endif 68 + 52 69 static u32 destroy_obj_hashfn(const struct tcf_proto *tp) 53 70 { 54 71 return jhash_3words(tp->chain->index, tp->prio, ··· 1632 1615 ret = __tcf_classify(skb, tp, orig_tp, res, compat_mode, 1633 1616 &last_executed_chain); 1634 1617 1635 - /* If we missed on some chain */ 1636 - if (ret == TC_ACT_UNSPEC && last_executed_chain) { 1637 - struct tc_skb_cb *cb = tc_skb_cb(skb); 1618 + if (tc_skb_ext_tc_enabled()) { 1619 + /* If we missed on some chain */ 1620 + if (ret == TC_ACT_UNSPEC && last_executed_chain) { 1621 + struct tc_skb_cb *cb = tc_skb_cb(skb); 1638 1622 1639 - ext = tc_skb_ext_alloc(skb); 1640 - if (WARN_ON_ONCE(!ext)) 1641 - return TC_ACT_SHOT; 1642 - ext->chain = last_executed_chain; 1643 - ext->mru = cb->mru; 1644 - ext->post_ct = cb->post_ct; 1645 - ext->post_ct_snat = cb->post_ct_snat; 1646 - ext->post_ct_dnat = cb->post_ct_dnat; 1647 - ext->zone = cb->zone; 1623 + ext = tc_skb_ext_alloc(skb); 1624 + if (WARN_ON_ONCE(!ext)) 1625 + return TC_ACT_SHOT; 1626 + ext->chain = last_executed_chain; 1627 + ext->mru = cb->mru; 1628 + ext->post_ct = cb->post_ct; 1629 + ext->post_ct_snat = cb->post_ct_snat; 1630 + ext->post_ct_dnat = cb->post_ct_dnat; 1631 + ext->zone = cb->zone; 1632 + } 1648 1633 } 1649 1634 1650 1635 return ret;