[PATCH nf-next] netfilter:nf_flow_table: add HW stats type support in flowtable

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: wenxu <wenxu@xxxxxxxxx>

The hardware driver offload function will check the hw_stats_type
for the flow action. Add NFTA_FLOWTABLE_HW_STATS_TYPE attr to flowtable
to specify the type of HW stats.

Signed-off-by: wenxu <wenxu@xxxxxxxxx>
---
 include/net/netfilter/nf_flow_table.h    |  2 ++
 include/uapi/linux/netfilter/nf_tables.h |  8 ++++++++
 net/netfilter/nf_flow_table_offload.c    | 11 ++++++++++-
 net/netfilter/nf_tables_api.c            | 31 +++++++++++++++++++++++++++++++
 4 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
index f523ea8..39e1d7e 100644
--- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h
@@ -43,6 +43,7 @@ struct nf_flow_match {
 struct nf_flow_rule {
 	struct nf_flow_match	match;
 	struct flow_rule	*rule;
+	u8			hw_stats_type;
 };
 
 struct nf_flowtable_type {
@@ -72,6 +73,7 @@ struct nf_flowtable {
 	const struct nf_flowtable_type	*type;
 	struct delayed_work		gc_work;
 	unsigned int			flags;
+	u8				hw_stats_type;
 	struct flow_block		flow_block;
 	struct mutex			flow_block_lock; /* Guards flow_block */
 	possible_net_t			net;
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 9c3d2d0..9e08c42 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -10,6 +10,12 @@
 #define NFT_USERDATA_MAXLEN	256
 #define NFT_OSF_MAXGENRELEN	16
 
+#define NFTA_HW_STATS_TYPE_IMMEDIATE (1 << 0)
+#define NFTA_HW_STATS_TYPE_DELAYED (1 << 1)
+
+#define NFTA_HW_STATS_TYPE_ANY (NFTA_HW_STATS_TYPE_IMMEDIATE | \
+			       NFTA_HW_STATS_TYPE_DELAYED)
+
 /**
  * enum nft_registers - nf_tables registers
  *
@@ -1560,6 +1566,7 @@ enum nft_object_attributes {
  * @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32)
  * @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64)
  * @NFTA_FLOWTABLE_FLAGS: flags (NLA_U32)
+ * @NFTA_FLOWTABLE_HW_STATS_TYPE: hw_stats_type (NLA_BITFIELD32)
  */
 enum nft_flowtable_attributes {
 	NFTA_FLOWTABLE_UNSPEC,
@@ -1570,6 +1577,7 @@ enum nft_flowtable_attributes {
 	NFTA_FLOWTABLE_HANDLE,
 	NFTA_FLOWTABLE_PAD,
 	NFTA_FLOWTABLE_FLAGS,
+	NFTA_FLOWTABLE_HW_STATS_TYPE,
 	__NFTA_FLOWTABLE_MAX
 };
 #define NFTA_FLOWTABLE_MAX	(__NFTA_FLOWTABLE_MAX - 1)
diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c
index ad54931..60289a6 100644
--- a/net/netfilter/nf_flow_table_offload.c
+++ b/net/netfilter/nf_flow_table_offload.c
@@ -165,8 +165,16 @@ static void flow_offload_mangle(struct flow_action_entry *entry,
 flow_action_entry_next(struct nf_flow_rule *flow_rule)
 {
 	int i = flow_rule->rule->action.num_entries++;
+	struct flow_action_entry *entry;
+
+	BUILD_BUG_ON(NFTA_HW_STATS_TYPE_ANY != FLOW_ACTION_HW_STATS_ANY);
+	BUILD_BUG_ON(NFTA_HW_STATS_TYPE_IMMEDIATE != FLOW_ACTION_HW_STATS_IMMEDIATE);
+	BUILD_BUG_ON(NFTA_HW_STATS_TYPE_DELAYED != FLOW_ACTION_HW_STATS_DELAYED);
+
+	entry = &flow_rule->rule->action.entries[i];
+	entry->hw_stats_type = flow_rule->hw_stats_type;
 
-	return &flow_rule->rule->action.entries[i];
+	return entry;
 }
 
 static int flow_offload_eth_src(struct net *net,
@@ -602,6 +610,7 @@ int nf_flow_rule_route_ipv6(struct net *net, const struct flow_offload *flow,
 		goto err_flow_match;
 
 	flow_rule->rule->action.num_entries = 0;
+	flow_rule->hw_stats_type = flowtable->hw_stats_type;
 	if (flowtable->type->action(net, flow, dir, flow_rule) < 0)
 		goto err_flow_match;
 
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index f92fb60..27bd6df 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -30,6 +30,7 @@
 static LIST_HEAD(nf_tables_destroy_list);
 static DEFINE_SPINLOCK(nf_tables_destroy_list_lock);
 static u64 table_handle;
+static const u32 nfta_hw_stats_type_allowed = NFTA_HW_STATS_TYPE_ANY;
 
 enum {
 	NFT_VALIDATE_SKIP	= 0,
@@ -6047,6 +6048,9 @@ void nft_unregister_flowtable_type(struct nf_flowtable_type *type)
 	[NFTA_FLOWTABLE_HOOK]		= { .type = NLA_NESTED },
 	[NFTA_FLOWTABLE_HANDLE]		= { .type = NLA_U64 },
 	[NFTA_FLOWTABLE_FLAGS]		= { .type = NLA_U32 },
+	[NFTA_FLOWTABLE_HW_STATS_TYPE]	= { .type = NLA_BITFIELD32,
+					    .validation_data =
+						&nfta_hw_stats_type_allowed },
 };
 
 struct nft_flowtable *nft_flowtable_lookup(const struct nft_table *table,
@@ -6244,6 +6248,15 @@ static int nft_register_flowtable_net_hooks(struct net *net,
 	return err;
 }
 
+static u8 nft_hw_stats_type(const struct nlattr *hw_stats_type_attr)
+{
+	struct nla_bitfield32 hw_stats_type_bf;
+
+	hw_stats_type_bf = nla_get_bitfield32(hw_stats_type_attr);
+
+	return hw_stats_type_bf.value;
+}
+
 static int nf_tables_newflowtable(struct net *net, struct sock *nlsk,
 				  struct sk_buff *skb,
 				  const struct nlmsghdr *nlh,
@@ -6251,6 +6264,7 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk,
 				  struct netlink_ext_ack *extack)
 {
 	const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
+	u8 hw_stats_type = NFTA_HW_STATS_TYPE_ANY;
 	const struct nf_flowtable_type *type;
 	u8 genmask = nft_genmask_next(net);
 	int family = nfmsg->nfgen_family;
@@ -6318,6 +6332,12 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk,
 			goto err3;
 	}
 
+	if ((flowtable->data.flags & NF_FLOWTABLE_HW_OFFLOAD) &&
+	    nla[NFTA_FLOWTABLE_HW_STATS_TYPE])
+		hw_stats_type =
+			nft_hw_stats_type(nla[NFTA_FLOWTABLE_HW_STATS_TYPE]);
+	flowtable->data.hw_stats_type = hw_stats_type;
+
 	write_pnet(&flowtable->data.net, net);
 	flowtable->data.type = type;
 	err = type->init(&flowtable->data);
@@ -6439,6 +6459,17 @@ static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net,
 	    nla_put_be32(skb, NFTA_FLOWTABLE_FLAGS, htonl(flowtable->data.flags)))
 		goto nla_put_failure;
 
+	if (flowtable->data.hw_stats_type != NFTA_HW_STATS_TYPE_ANY) {
+		struct nla_bitfield32 hw_stats_type = {
+			flowtable->data.hw_stats_type,
+			NFTA_HW_STATS_TYPE_ANY,
+		};
+
+		if (nla_put(skb, NFTA_FLOWTABLE_HW_STATS_TYPE,
+			    sizeof(hw_stats_type), &hw_stats_type))
+			goto nla_put_failure;
+	}
+
 	nest = nla_nest_start_noflag(skb, NFTA_FLOWTABLE_HOOK);
 	if (!nest)
 		goto nla_put_failure;
-- 
1.8.3.1




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux