IPS_HELPER_BIT = 13,
        IPS_HELPER = (1 << IPS_HELPER_BIT),
 
+       /* Conntrack has been offloaded to flow table. */
+       IPS_OFFLOAD_BIT = 14,
+       IPS_OFFLOAD = (1 << IPS_OFFLOAD_BIT),
+
        /* Be careful here, modifying these bits can make things messy,
         * so don't let users modify them directly.
         */
        IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK |
                                 IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING |
-                                IPS_SEQ_ADJUST | IPS_TEMPLATE),
+                                IPS_SEQ_ADJUST | IPS_TEMPLATE | IPS_OFFLOAD),
 
        __IPS_MAX_BIT = 14,
 };
 
        hlist_nulls_for_each_entry_rcu(h, n, head, hnnode) {
                tmp = nf_ct_tuplehash_to_ctrack(h);
 
+               if (test_bit(IPS_OFFLOAD_BIT, &tmp->status))
+                       continue;
+
                if (nf_ct_is_expired(tmp)) {
                        nf_ct_gc_expired(tmp);
                        continue;
        return false;
 }
 
+#define        DAY     (86400 * HZ)
+
+/* Set an arbitrary timeout large enough not to ever expire, this save
+ * us a check for the IPS_OFFLOAD_BIT from the packet path via
+ * nf_ct_is_expired().
+ */
+static void nf_ct_offload_timeout(struct nf_conn *ct)
+{
+       if (nf_ct_expires(ct) < DAY / 2)
+               ct->timeout = nfct_time_stamp + DAY;
+}
+
 static void gc_worker(struct work_struct *work)
 {
        unsigned int min_interval = max(HZ / GC_MAX_BUCKETS_DIV, 1u);
                        tmp = nf_ct_tuplehash_to_ctrack(h);
 
                        scanned++;
+                       if (test_bit(IPS_OFFLOAD_BIT, &tmp->status)) {
+                               nf_ct_offload_timeout(tmp);
+                               continue;
+                       }
+
                        if (nf_ct_is_expired(tmp)) {
                                nf_ct_gc_expired(tmp);
                                expired_count++;
 
                                    .len = NF_CT_LABELS_MAX_SIZE },
 };
 
+static int ctnetlink_flush_iterate(struct nf_conn *ct, void *data)
+{
+       if (test_bit(IPS_OFFLOAD_BIT, &ct->status))
+               return 0;
+
+       return ctnetlink_filter_match(ct, data);
+}
+
 static int ctnetlink_flush_conntrack(struct net *net,
                                     const struct nlattr * const cda[],
                                     u32 portid, int report)
                        return PTR_ERR(filter);
        }
 
-       nf_ct_iterate_cleanup_net(net, ctnetlink_filter_match, filter,
+       nf_ct_iterate_cleanup_net(net, ctnetlink_flush_iterate, filter,
                                  portid, report);
        kfree(filter);
 
 
        ct = nf_ct_tuplehash_to_ctrack(h);
 
+       if (test_bit(IPS_OFFLOAD_BIT, &ct->status)) {
+               nf_ct_put(ct);
+               return -EBUSY;
+       }
+
        if (cda[CTA_ID]) {
                u_int32_t id = ntohl(nla_get_be32(cda[CTA_ID]));
                if (id != (u32)(unsigned long)ct) {
 
 /* Print out the private part of the conntrack. */
 static void tcp_print_conntrack(struct seq_file *s, struct nf_conn *ct)
 {
+       if (test_bit(IPS_OFFLOAD_BIT, &ct->status))
+               return;
+
        seq_printf(s, "%s ", tcp_conntrack_names[ct->proto.tcp.state]);
 }
 #endif
 
        WARN_ON(!l4proto);
 
        ret = -ENOSPC;
-       seq_printf(s, "%-8s %u %-8s %u %ld ",
+       seq_printf(s, "%-8s %u %-8s %u ",
                   l3proto_name(l3proto->l3proto), nf_ct_l3num(ct),
-                  l4proto_name(l4proto->l4proto), nf_ct_protonum(ct),
-                  nf_ct_expires(ct)  / HZ);
+                  l4proto_name(l4proto->l4proto), nf_ct_protonum(ct));
+
+       if (!test_bit(IPS_OFFLOAD_BIT, &ct->status))
+               seq_printf(s, "%ld ", nf_ct_expires(ct)  / HZ);
 
        if (l4proto->print_conntrack)
                l4proto->print_conntrack(s, ct);
        if (seq_print_acct(s, ct, IP_CT_DIR_REPLY))
                goto release;
 
-       if (test_bit(IPS_ASSURED_BIT, &ct->status))
+       if (test_bit(IPS_OFFLOAD_BIT, &ct->status))
+               seq_puts(s, "[OFFLOAD] ");
+       else if (test_bit(IPS_ASSURED_BIT, &ct->status))
                seq_puts(s, "[ASSURED] ");
 
        if (seq_has_overflowed(s))