diff options
-rw-r--r-- | acinclude.m4 | 3 | ||||
-rw-r--r-- | datapath/datapath.c | 38 | ||||
-rw-r--r-- | datapath/datapath.h | 2 | ||||
-rw-r--r-- | datapath/flow.c | 13 | ||||
-rw-r--r-- | datapath/linux/compat/include/linux/static_key.h | 7 |
5 files changed, 58 insertions, 5 deletions
diff --git a/acinclude.m4 b/acinclude.m4 index 84f344da0..3d56510a0 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -631,6 +631,9 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ [OVS_DEFINE([HAVE_UPSTREAM_STATIC_KEY])]) OVS_GREP_IFELSE([$KSRC/include/linux/jump_label.h], [DEFINE_STATIC_KEY_FALSE], [OVS_DEFINE([HAVE_DEFINE_STATIC_KEY])]) + OVS_GREP_IFELSE([$KSRC/include/linux/jump_label.h], + [DECLARE_STATIC_KEY_FALSE], + [OVS_DEFINE([HAVE_DECLARE_STATIC_KEY])]) OVS_GREP_IFELSE([$KSRC/include/linux/etherdevice.h], [eth_hw_addr_random]) OVS_GREP_IFELSE([$KSRC/include/linux/etherdevice.h], [ether_addr_copy]) diff --git a/datapath/datapath.c b/datapath/datapath.c index c8c21d774..009887691 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -1635,10 +1635,34 @@ static void ovs_dp_reset_user_features(struct sk_buff *skb, struct genl_info *in dp->user_features = 0; } -static void ovs_dp_change(struct datapath *dp, struct nlattr *a[]) +DEFINE_STATIC_KEY_FALSE(tc_recirc_sharing_support); + +static int ovs_dp_change(struct datapath *dp, struct nlattr *a[]) { - if (a[OVS_DP_ATTR_USER_FEATURES]) - dp->user_features = nla_get_u32(a[OVS_DP_ATTR_USER_FEATURES]); + u32 user_features = 0; + + if (a[OVS_DP_ATTR_USER_FEATURES]) { + user_features = nla_get_u32(a[OVS_DP_ATTR_USER_FEATURES]); + + if (user_features & ~(OVS_DP_F_VPORT_PIDS | + OVS_DP_F_UNALIGNED | + OVS_DP_F_TC_RECIRC_SHARING)) + return -EOPNOTSUPP; + +#if !IS_ENABLED(CONFIG_NET_TC_SKB_EXT) + if (user_features & OVS_DP_F_TC_RECIRC_SHARING) + return -EOPNOTSUPP; +#endif + } + + dp->user_features = user_features; + + if (dp->user_features & OVS_DP_F_TC_RECIRC_SHARING) + static_branch_enable(&tc_recirc_sharing_support); + else + static_branch_disable(&tc_recirc_sharing_support); + + return 0; } static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) @@ -1700,7 +1724,9 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) parms.port_no = OVSP_LOCAL; parms.upcall_portids = a[OVS_DP_ATTR_UPCALL_PID]; - ovs_dp_change(dp, a); + err = ovs_dp_change(dp, a); + if (err) + goto err_destroy_meters; /* So far only local changes have been made, now need the lock. */ ovs_lock(); @@ -1825,7 +1851,9 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info) if (IS_ERR(dp)) goto err_unlock_free; - ovs_dp_change(dp, info->attrs); + err = ovs_dp_change(dp, info->attrs); + if (err) + goto err_unlock_free; err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid, info->snd_seq, 0, OVS_DP_CMD_GET); diff --git a/datapath/datapath.h b/datapath/datapath.h index f99db1fde..c377e9b24 100644 --- a/datapath/datapath.h +++ b/datapath/datapath.h @@ -251,6 +251,8 @@ extern struct notifier_block ovs_dp_device_notifier; extern struct genl_family dp_vport_genl_family; extern const struct genl_multicast_group ovs_dp_vport_multicast_group; +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_detach_port(struct vport *); int ovs_dp_upcall(struct datapath *, struct sk_buff *, diff --git a/datapath/flow.c b/datapath/flow.c index 6dc7402d5..5a00c238c 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -874,6 +874,9 @@ static int key_extract_mac_proto(struct sk_buff *skb) int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info, struct sk_buff *skb, struct sw_flow_key *key) { +#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT) + struct tc_skb_ext *tc_ext; +#endif int res, err; /* Extract metadata from packet. */ @@ -904,7 +907,17 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info, if (res < 0) return res; key->mac_proto = res; + +#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT) + if (static_branch_unlikely(&tc_recirc_sharing_support)) { + tc_ext = skb_ext_find(skb, TC_SKB_EXT); + key->recirc_id = tc_ext ? tc_ext->chain : 0; + } else { + key->recirc_id = 0; + } +#else key->recirc_id = 0; +#endif err = key_extract(skb, key); if (!err) diff --git a/datapath/linux/compat/include/linux/static_key.h b/datapath/linux/compat/include/linux/static_key.h index 7e43a49e8..432feccb9 100644 --- a/datapath/linux/compat/include/linux/static_key.h +++ b/datapath/linux/compat/include/linux/static_key.h @@ -74,6 +74,13 @@ static inline void rpl_static_key_disable(struct static_key *key) #define static_branch_enable(x) rpl_static_key_enable(&(x)->key) #define static_branch_disable(x) rpl_static_key_disable(&(x)->key) +#ifndef HAVE_DECLARE_STATIC_KEY +#define DECLARE_STATIC_KEY_TRUE(name) \ + extern struct static_key_true name +#define DECLARE_STATIC_KEY_FALSE(name) \ + extern struct static_key_false name +#endif + #endif /* HAVE_UPSTREAM_STATIC_KEY */ #endif /* _STATIC_KEY_WRAPPER_H */ |