diff mbox

[ovs-dev,patch_v8,5/9] dpdk: Add orig tuple context recovery.

Message ID 1496166573-90065-6-git-send-email-dlu998@gmail.com
State Accepted
Headers show

Commit Message

Darrell Ball May 30, 2017, 5:49 p.m. UTC
This patch adds orig tuple checking and context
recovery; NAT interactions are factored in.
Orig tuple support exists to better handle policy
changes.

Signed-off-by: Darrell Ball <dlu998@gmail.com>
Acked-by: Daniele Di Proietto <diproiettod@ovn.org>
---
 lib/conntrack.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)
diff mbox

Patch

diff --git a/lib/conntrack.c b/lib/conntrack.c
index 616e23b..ed0b16b 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -679,6 +679,72 @@  handle_nat(struct dp_packet *pkt, struct conn *conn,
     }
 }
 
+static bool
+check_orig_tuple(struct conntrack *ct, struct dp_packet *pkt,
+                 struct conn_lookup_ctx *ctx_in, long long now,
+                 unsigned *bucket, struct conn **conn,
+                 const struct nat_action_info_t *nat_action_info)
+    OVS_REQUIRES(ct->buckets[*bucket].lock)
+{
+    if ((ctx_in->key.dl_type == htons(ETH_TYPE_IP) &&
+         !pkt->md.ct_orig_tuple.ipv4.ipv4_proto) ||
+        (ctx_in->key.dl_type == htons(ETH_TYPE_IPV6) &&
+         !pkt->md.ct_orig_tuple.ipv6.ipv6_proto) ||
+        !(pkt->md.ct_state & (CS_SRC_NAT | CS_DST_NAT)) ||
+        nat_action_info){
+        return false;
+    }
+
+    ct_lock_unlock(&ct->buckets[*bucket].lock);
+    struct conn_lookup_ctx ctx;
+    memset(&ctx, 0 , sizeof ctx);
+    ctx.conn = NULL;
+
+    if (ctx_in->key.dl_type == htons(ETH_TYPE_IP)) {
+
+        ctx.key.src.addr.ipv4_aligned = pkt->md.ct_orig_tuple.ipv4.ipv4_src;
+        ctx.key.dst.addr.ipv4_aligned = pkt->md.ct_orig_tuple.ipv4.ipv4_dst;
+
+        if (ctx_in->key.nw_proto == IPPROTO_ICMP) {
+            ctx.key.src.icmp_id = ctx_in->key.src.icmp_id;
+            ctx.key.dst.icmp_id = ctx_in->key.dst.icmp_id;
+            uint16_t src_port = ntohs(pkt->md.ct_orig_tuple.ipv4.src_port);
+            ctx.key.src.icmp_type = (uint8_t) src_port;
+            ctx.key.dst.icmp_type = reverse_icmp_type(ctx.key.src.icmp_type);
+        } else {
+            ctx.key.src.port = pkt->md.ct_orig_tuple.ipv4.src_port;
+            ctx.key.dst.port = pkt->md.ct_orig_tuple.ipv4.dst_port;
+        }
+        ctx.key.nw_proto = pkt->md.ct_orig_tuple.ipv4.ipv4_proto;
+    } else {
+        ctx.key.src.addr.ipv6_aligned = pkt->md.ct_orig_tuple.ipv6.ipv6_src;
+        ctx.key.dst.addr.ipv6_aligned = pkt->md.ct_orig_tuple.ipv6.ipv6_dst;
+
+        if (ctx_in->key.nw_proto == IPPROTO_ICMPV6) {
+            ctx.key.src.icmp_id = ctx_in->key.src.icmp_id;
+            ctx.key.dst.icmp_id = ctx_in->key.dst.icmp_id;
+            uint16_t src_port = ntohs(pkt->md.ct_orig_tuple.ipv6.src_port);
+            ctx.key.src.icmp_type = (uint8_t) src_port;
+            ctx.key.dst.icmp_type = reverse_icmp6_type(ctx.key.src.icmp_type);
+        } else {
+            ctx.key.src.port = pkt->md.ct_orig_tuple.ipv6.src_port;
+            ctx.key.dst.port = pkt->md.ct_orig_tuple.ipv6.dst_port;
+        }
+        ctx.key.nw_proto = pkt->md.ct_orig_tuple.ipv6.ipv6_proto;
+    }
+
+    ctx.key.dl_type = ctx_in->key.dl_type;
+    ctx.key.zone = pkt->md.ct_zone;
+
+    ctx.hash = conn_key_hash(&ctx.key, ct->hash_basis);
+    *bucket = hash_to_bucket(ctx.hash);
+    ct_lock_lock(&ct->buckets[*bucket].lock);
+    conn_key_lookup(&ct->buckets[*bucket], &ctx, now);
+    *conn = ctx.conn;
+
+    return *conn ? true : false;
+}
+
 static void
 process_one(struct conntrack *ct, struct dp_packet *pkt,
             struct conn_lookup_ctx *ctx, uint16_t zone,
@@ -735,6 +801,10 @@  process_one(struct conntrack *ct, struct dp_packet *pkt,
         if (nat_action_info && !create_new_conn) {
             handle_nat(pkt, conn, zone, ctx->reply, ctx->related);
         }
+
+    }else if (check_orig_tuple(ct, pkt, ctx, now, &bucket, &conn,
+                               nat_action_info)) {
+        create_new_conn = conn_update_state(ct, pkt, ctx, &conn, now, bucket);
     } else {
         if (ctx->related) {
             pkt->md.ct_state = CS_INVALID;