diff mbox series

[RFC,4/6] net/sched: act_ct: add support for force flag

Message ID b12a84a87b983d2bdbe710147f5aef5c98ed54db.1548285996.git.mleitner@redhat.com
State RFC
Delegated to: David Miller
Headers show
Series Initial, PoC implementation of sw datapath of tc+CT | expand

Commit Message

Marcelo Ricardo Leitner Jan. 25, 2019, 2:32 a.m. UTC
OvS ct action has this 'force' flag, which basically forces ConnTrack to
consider that this packet, this specific direction, is the original one.

Implement that similarly: if the ct entry is there and the direction is not
the expected one, destroy it and create a new one.

Signed-off-by: Marcelo Ricardo Leitner <mleitner@redhat.com>
---
 include/uapi/linux/tc_act/tc_ct.h |  1 +
 net/sched/act_ct.c                | 16 +++++++++++++++-
 2 files changed, 16 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/include/uapi/linux/tc_act/tc_ct.h b/include/uapi/linux/tc_act/tc_ct.h
index 37b95cda1dedd283b0244a03a20860ba22966dfa..009e53ee83fb3125bc5c4ca86954af3bf6a0287a 100644
--- a/include/uapi/linux/tc_act/tc_ct.h
+++ b/include/uapi/linux/tc_act/tc_ct.h
@@ -25,6 +25,7 @@  enum {
 
 enum {
 	TC_CT_COMMIT,
+	TC_CT_FORCE,
 	__TC_CT_MAX
 };
 #define TC_CT_MAX (__TC_CT_MAX - 1)
diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
index f69509954149a0c8be710916a5289a4448049b5d..8a1b5d6a7cd8360c50011d992368464db213a020 100644
--- a/net/sched/act_ct.c
+++ b/net/sched/act_ct.c
@@ -165,6 +165,7 @@  static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
 		      struct tcf_result *res)
 {
 	struct tcf_ct *p = to_tcf_ct(a);
+	enum ip_conntrack_info ctinfo;
 	struct nf_hook_state state = {
 		.hook = NF_INET_PRE_ROUTING,
 	};
@@ -173,6 +174,8 @@  static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
 	int action, err;
 	int nh_ofs;
 
+	/* Again needs to be here because we need a new ref on the ct. */
+again:
 	spin_lock(&p->tcf_lock);
 
 	tcf_lastuse_update(&p->tcf_tm);
@@ -218,8 +221,19 @@  static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
 	if (err != NF_ACCEPT)
 		goto drop;
 
-	new_ct = (struct nf_conn *)skb_nfct(skb);
+	new_ct = nf_ct_get(skb, &ctinfo);
 	if (new_ct) {
+		/* Force conntrack entry direction. */
+		if (flags & BIT(TC_CT_FORCE) &&
+		    CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) {
+			if (nf_ct_is_confirmed(new_ct))
+				nf_ct_delete(new_ct, 0, 0);
+
+			nf_conntrack_put(&new_ct->ct_general);
+			nf_ct_set(skb, NULL, 0);
+			goto again;
+		}
+
 		if (mark_mask) {
 			new_ct->mark = (new_ct->mark &~ mark_mask) | (mark & mark_mask);
 			if (nf_ct_is_confirmed(new_ct))