Commit 35d39fec authored by Paul Blakey's avatar Paul Blakey Committed by David S. Miller

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: default avatarPaul Blakey <paulb@nvidia.com>
Reviewed-by: default avatarJamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ed8c8f60
...@@ -1028,4 +1028,15 @@ struct tc_fifo_qopt_offload { ...@@ -1028,4 +1028,15 @@ struct tc_fifo_qopt_offload {
}; };
}; };
#ifdef CONFIG_NET_CLS_ACT
DECLARE_STATIC_KEY_FALSE(tc_skb_ext_tc);
void tc_skb_ext_tc_enable(void);
void tc_skb_ext_tc_disable(void);
#define tc_skb_ext_tc_enabled() static_branch_unlikely(&tc_skb_ext_tc)
#else /* CONFIG_NET_CLS_ACT */
static inline void tc_skb_ext_tc_enable(void) { }
static inline void tc_skb_ext_tc_disable(void) { }
#define tc_skb_ext_tc_enabled() false
#endif
#endif #endif
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <net/genetlink.h> #include <net/genetlink.h>
#include <net/net_namespace.h> #include <net/net_namespace.h>
#include <net/netns/generic.h> #include <net/netns/generic.h>
#include <net/pkt_cls.h>
#include "datapath.h" #include "datapath.h"
#include "flow.h" #include "flow.h"
...@@ -1601,8 +1602,6 @@ static void ovs_dp_reset_user_features(struct sk_buff *skb, ...@@ -1601,8 +1602,6 @@ static void ovs_dp_reset_user_features(struct sk_buff *skb,
dp->user_features = 0; dp->user_features = 0;
} }
DEFINE_STATIC_KEY_FALSE(tc_recirc_sharing_support);
static int ovs_dp_set_upcall_portids(struct datapath *dp, static int ovs_dp_set_upcall_portids(struct datapath *dp,
const struct nlattr *ids) const struct nlattr *ids)
{ {
...@@ -1657,7 +1656,7 @@ u32 ovs_dp_get_upcall_portid(const struct datapath *dp, uint32_t cpu_id) ...@@ -1657,7 +1656,7 @@ u32 ovs_dp_get_upcall_portid(const struct datapath *dp, uint32_t cpu_id)
static int ovs_dp_change(struct datapath *dp, struct nlattr *a[]) static int ovs_dp_change(struct datapath *dp, struct nlattr *a[])
{ {
u32 user_features = 0; u32 user_features = 0, old_features = dp->user_features;
int err; int err;
if (a[OVS_DP_ATTR_USER_FEATURES]) { if (a[OVS_DP_ATTR_USER_FEATURES]) {
...@@ -1696,10 +1695,12 @@ static int ovs_dp_change(struct datapath *dp, struct nlattr *a[]) ...@@ -1696,10 +1695,12 @@ static int ovs_dp_change(struct datapath *dp, struct nlattr *a[])
return err; return err;
} }
if (dp->user_features & OVS_DP_F_TC_RECIRC_SHARING) if ((dp->user_features & OVS_DP_F_TC_RECIRC_SHARING) &&
static_branch_enable(&tc_recirc_sharing_support); !(old_features & OVS_DP_F_TC_RECIRC_SHARING))
else tc_skb_ext_tc_enable();
static_branch_disable(&tc_recirc_sharing_support); else if (!(dp->user_features & OVS_DP_F_TC_RECIRC_SHARING) &&
(old_features & OVS_DP_F_TC_RECIRC_SHARING))
tc_skb_ext_tc_disable();
return 0; return 0;
} }
...@@ -1839,6 +1840,9 @@ static void __dp_destroy(struct datapath *dp) ...@@ -1839,6 +1840,9 @@ static void __dp_destroy(struct datapath *dp)
struct flow_table *table = &dp->table; struct flow_table *table = &dp->table;
int i; int i;
if (dp->user_features & OVS_DP_F_TC_RECIRC_SHARING)
tc_skb_ext_tc_disable();
for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) { for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) {
struct vport *vport; struct vport *vport;
struct hlist_node *n; struct hlist_node *n;
......
...@@ -253,8 +253,6 @@ static inline struct datapath *get_dp(struct net *net, int dp_ifindex) ...@@ -253,8 +253,6 @@ static inline struct datapath *get_dp(struct net *net, int dp_ifindex)
extern struct notifier_block ovs_dp_device_notifier; extern struct notifier_block ovs_dp_device_notifier;
extern struct genl_family dp_vport_genl_family; extern struct genl_family dp_vport_genl_family;
DECLARE_STATIC_KEY_FALSE(tc_recirc_sharing_support);
void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key); void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key);
void ovs_dp_detach_port(struct vport *); void ovs_dp_detach_port(struct vport *);
int ovs_dp_upcall(struct datapath *, struct sk_buff *, int ovs_dp_upcall(struct datapath *, struct sk_buff *,
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <net/mpls.h> #include <net/mpls.h>
#include <net/ndisc.h> #include <net/ndisc.h>
#include <net/nsh.h> #include <net/nsh.h>
#include <net/pkt_cls.h>
#include <net/netfilter/nf_conntrack_zones.h> #include <net/netfilter/nf_conntrack_zones.h>
#include "conntrack.h" #include "conntrack.h"
...@@ -895,7 +896,7 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info, ...@@ -895,7 +896,7 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
key->mac_proto = res; key->mac_proto = res;
#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT) #if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
if (static_branch_unlikely(&tc_recirc_sharing_support)) { if (tc_skb_ext_tc_enabled()) {
tc_ext = skb_ext_find(skb, TC_SKB_EXT); tc_ext = skb_ext_find(skb, TC_SKB_EXT);
key->recirc_id = tc_ext ? tc_ext->chain : 0; key->recirc_id = tc_ext ? tc_ext->chain : 0;
OVS_CB(skb)->mru = tc_ext ? tc_ext->mru : 0; OVS_CB(skb)->mru = tc_ext ? tc_ext->mru : 0;
......
...@@ -49,6 +49,23 @@ static LIST_HEAD(tcf_proto_base); ...@@ -49,6 +49,23 @@ static LIST_HEAD(tcf_proto_base);
/* Protects list of registered TC modules. It is pure SMP lock. */ /* Protects list of registered TC modules. It is pure SMP lock. */
static DEFINE_RWLOCK(cls_mod_lock); static DEFINE_RWLOCK(cls_mod_lock);
#ifdef CONFIG_NET_CLS_ACT
DEFINE_STATIC_KEY_FALSE(tc_skb_ext_tc);
EXPORT_SYMBOL(tc_skb_ext_tc);
void tc_skb_ext_tc_enable(void)
{
static_branch_inc(&tc_skb_ext_tc);
}
EXPORT_SYMBOL(tc_skb_ext_tc_enable);
void tc_skb_ext_tc_disable(void)
{
static_branch_dec(&tc_skb_ext_tc);
}
EXPORT_SYMBOL(tc_skb_ext_tc_disable);
#endif
static u32 destroy_obj_hashfn(const struct tcf_proto *tp) static u32 destroy_obj_hashfn(const struct tcf_proto *tp)
{ {
return jhash_3words(tp->chain->index, tp->prio, return jhash_3words(tp->chain->index, tp->prio,
...@@ -1615,19 +1632,21 @@ int tcf_classify(struct sk_buff *skb, ...@@ -1615,19 +1632,21 @@ int tcf_classify(struct sk_buff *skb,
ret = __tcf_classify(skb, tp, orig_tp, res, compat_mode, ret = __tcf_classify(skb, tp, orig_tp, res, compat_mode,
&last_executed_chain); &last_executed_chain);
/* If we missed on some chain */ if (tc_skb_ext_tc_enabled()) {
if (ret == TC_ACT_UNSPEC && last_executed_chain) { /* If we missed on some chain */
struct tc_skb_cb *cb = tc_skb_cb(skb); if (ret == TC_ACT_UNSPEC && last_executed_chain) {
struct tc_skb_cb *cb = tc_skb_cb(skb);
ext = tc_skb_ext_alloc(skb);
if (WARN_ON_ONCE(!ext)) ext = tc_skb_ext_alloc(skb);
return TC_ACT_SHOT; if (WARN_ON_ONCE(!ext))
ext->chain = last_executed_chain; return TC_ACT_SHOT;
ext->mru = cb->mru; ext->chain = last_executed_chain;
ext->post_ct = cb->post_ct; ext->mru = cb->mru;
ext->post_ct_snat = cb->post_ct_snat; ext->post_ct = cb->post_ct;
ext->post_ct_dnat = cb->post_ct_dnat; ext->post_ct_snat = cb->post_ct_snat;
ext->zone = cb->zone; ext->post_ct_dnat = cb->post_ct_dnat;
ext->zone = cb->zone;
}
} }
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment