diff options
Diffstat (limited to 'include/net/flow_offload.h')
-rw-r--r-- | include/net/flow_offload.h | 117 |
1 files changed, 115 insertions, 2 deletions
diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index c6f7bd22db60..efd8d47f6997 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h @@ -3,6 +3,7 @@ #include <linux/kernel.h> #include <linux/list.h> +#include <linux/netlink.h> #include <net/flow_dissector.h> #include <linux/rhashtable.h> @@ -68,6 +69,10 @@ struct flow_match_enc_opts { struct flow_dissector_key_enc_opts *key, *mask; }; +struct flow_match_ct { + struct flow_dissector_key_ct *key, *mask; +}; + struct flow_rule; void flow_rule_match_meta(const struct flow_rule *rule, @@ -110,6 +115,8 @@ void flow_rule_match_enc_keyid(const struct flow_rule *rule, struct flow_match_enc_keyid *out); void flow_rule_match_enc_opts(const struct flow_rule *rule, struct flow_match_enc_opts *out); +void flow_rule_match_ct(const struct flow_rule *rule, + struct flow_match_ct *out); enum flow_action_id { FLOW_ACTION_ACCEPT = 0, @@ -135,6 +142,7 @@ enum flow_action_id { FLOW_ACTION_SAMPLE, FLOW_ACTION_POLICE, FLOW_ACTION_CT, + FLOW_ACTION_CT_METADATA, FLOW_ACTION_MPLS_PUSH, FLOW_ACTION_MPLS_POP, FLOW_ACTION_MPLS_MANGLE, @@ -154,10 +162,37 @@ enum flow_action_mangle_base { FLOW_ACT_MANGLE_HDR_TYPE_UDP, }; +enum flow_action_hw_stats_type_bit { + FLOW_ACTION_HW_STATS_TYPE_IMMEDIATE_BIT, + FLOW_ACTION_HW_STATS_TYPE_DELAYED_BIT, +}; + +enum flow_action_hw_stats_type { + FLOW_ACTION_HW_STATS_TYPE_DISABLED = 0, + FLOW_ACTION_HW_STATS_TYPE_IMMEDIATE = + BIT(FLOW_ACTION_HW_STATS_TYPE_IMMEDIATE_BIT), + FLOW_ACTION_HW_STATS_TYPE_DELAYED = + BIT(FLOW_ACTION_HW_STATS_TYPE_DELAYED_BIT), + FLOW_ACTION_HW_STATS_TYPE_ANY = + FLOW_ACTION_HW_STATS_TYPE_IMMEDIATE | + FLOW_ACTION_HW_STATS_TYPE_DELAYED, +}; + typedef void (*action_destr)(void *priv); +struct flow_action_cookie { + u32 cookie_len; + u8 cookie[]; +}; + +struct flow_action_cookie *flow_action_cookie_create(void *data, + unsigned int len, + gfp_t gfp); +void flow_action_cookie_destroy(struct flow_action_cookie *cookie); + struct flow_action_entry { enum flow_action_id id; + enum flow_action_hw_stats_type hw_stats_type; action_destr destructor; void *destructor_priv; union { @@ -196,7 +231,13 @@ struct flow_action_entry { struct { /* FLOW_ACTION_CT */ int action; u16 zone; + struct nf_flowtable *flow_table; } ct; + struct { + unsigned long cookie; + u32 mark; + u32 labels[4]; + } ct_metadata; struct { /* FLOW_ACTION_MPLS_PUSH */ u32 label; __be16 proto; @@ -214,11 +255,12 @@ struct flow_action_entry { u8 ttl; } mpls_mangle; }; + struct flow_action_cookie *cookie; /* user defined action cookie */ }; struct flow_action { unsigned int num_entries; - struct flow_action_entry entries[0]; + struct flow_action_entry entries[]; }; static inline bool flow_action_has_entries(const struct flow_action *action) @@ -238,7 +280,78 @@ static inline bool flow_offload_has_one_action(const struct flow_action *action) } #define flow_action_for_each(__i, __act, __actions) \ - for (__i = 0, __act = &(__actions)->entries[0]; __i < (__actions)->num_entries; __act = &(__actions)->entries[++__i]) + for (__i = 0, __act = &(__actions)->entries[0]; \ + __i < (__actions)->num_entries; \ + __act = &(__actions)->entries[++__i]) + +static inline bool +flow_action_mixed_hw_stats_types_check(const struct flow_action *action, + struct netlink_ext_ack *extack) +{ + const struct flow_action_entry *action_entry; + u8 uninitialized_var(last_hw_stats_type); + int i; + + if (flow_offload_has_one_action(action)) + return true; + + flow_action_for_each(i, action_entry, action) { + if (i && action_entry->hw_stats_type != last_hw_stats_type) { + NL_SET_ERR_MSG_MOD(extack, "Mixing HW stats types for actions is not supported"); + return false; + } + last_hw_stats_type = action_entry->hw_stats_type; + } + return true; +} + +static inline const struct flow_action_entry * +flow_action_first_entry_get(const struct flow_action *action) +{ + WARN_ON(!flow_action_has_entries(action)); + return &action->entries[0]; +} + +static inline bool +__flow_action_hw_stats_types_check(const struct flow_action *action, + struct netlink_ext_ack *extack, + bool check_allow_bit, + enum flow_action_hw_stats_type_bit allow_bit) +{ + const struct flow_action_entry *action_entry; + + if (!flow_action_has_entries(action)) + return true; + if (!flow_action_mixed_hw_stats_types_check(action, extack)) + return false; + action_entry = flow_action_first_entry_get(action); + if (!check_allow_bit && + action_entry->hw_stats_type != FLOW_ACTION_HW_STATS_TYPE_ANY) { + NL_SET_ERR_MSG_MOD(extack, "Driver supports only default HW stats type \"any\""); + return false; + } else if (check_allow_bit && + !(action_entry->hw_stats_type & BIT(allow_bit))) { + NL_SET_ERR_MSG_MOD(extack, "Driver does not support selected HW stats type"); + return false; + } + return true; +} + +static inline bool +flow_action_hw_stats_types_check(const struct flow_action *action, + struct netlink_ext_ack *extack, + enum flow_action_hw_stats_type_bit allow_bit) +{ + return __flow_action_hw_stats_types_check(action, extack, + true, allow_bit); +} + +static inline bool +flow_action_basic_hw_stats_types_check(const struct flow_action *action, + struct netlink_ext_ack *extack) +{ + return __flow_action_hw_stats_types_check(action, extack, false, 0); +} struct flow_rule { struct flow_match match; |