* @NFT_CT_EXPIRATION: relative conntrack expiration time in ms
  * @NFT_CT_HELPER: connection tracking helper assigned to conntrack
  * @NFT_CT_L3PROTOCOL: conntrack layer 3 protocol
- * @NFT_CT_SRC: conntrack layer 3 protocol source (IPv4/IPv6 address)
- * @NFT_CT_DST: conntrack layer 3 protocol destination (IPv4/IPv6 address)
+ * @NFT_CT_SRC: conntrack layer 3 protocol source (IPv4/IPv6 address, deprecated)
+ * @NFT_CT_DST: conntrack layer 3 protocol destination (IPv4/IPv6 address, deprecated)
  * @NFT_CT_PROTOCOL: conntrack layer 4 protocol
  * @NFT_CT_PROTO_SRC: conntrack layer 4 protocol source
  * @NFT_CT_PROTO_DST: conntrack layer 4 protocol destination
  * @NFT_CT_AVGPKT: conntrack average bytes per packet
  * @NFT_CT_ZONE: conntrack zone
  * @NFT_CT_EVENTMASK: ctnetlink events to be generated for this conntrack
+ * @NFT_CT_SRC_IP: conntrack layer 3 protocol source (IPv4 address)
+ * @NFT_CT_DST_IP: conntrack layer 3 protocol destination (IPv4 address)
+ * @NFT_CT_SRC_IP6: conntrack layer 3 protocol source (IPv6 address)
+ * @NFT_CT_DST_IP6: conntrack layer 3 protocol destination (IPv6 address)
  */
 enum nft_ct_keys {
        NFT_CT_STATE,
        NFT_CT_AVGPKT,
        NFT_CT_ZONE,
        NFT_CT_EVENTMASK,
+       NFT_CT_SRC_IP,
+       NFT_CT_DST_IP,
+       NFT_CT_SRC_IP6,
+       NFT_CT_DST_IP6,
 };
 
 /**
 
        case NFT_CT_PROTO_DST:
                nft_reg_store16(dest, (__force u16)tuple->dst.u.all);
                return;
+       case NFT_CT_SRC_IP:
+               if (nf_ct_l3num(ct) != NFPROTO_IPV4)
+                       goto err;
+               *dest = tuple->src.u3.ip;
+               return;
+       case NFT_CT_DST_IP:
+               if (nf_ct_l3num(ct) != NFPROTO_IPV4)
+                       goto err;
+               *dest = tuple->dst.u3.ip;
+               return;
+       case NFT_CT_SRC_IP6:
+               if (nf_ct_l3num(ct) != NFPROTO_IPV6)
+                       goto err;
+               memcpy(dest, tuple->src.u3.ip6, sizeof(struct in6_addr));
+               return;
+       case NFT_CT_DST_IP6:
+               if (nf_ct_l3num(ct) != NFPROTO_IPV6)
+                       goto err;
+               memcpy(dest, tuple->dst.u3.ip6, sizeof(struct in6_addr));
+               return;
        default:
                break;
        }
                        return -EAFNOSUPPORT;
                }
                break;
+       case NFT_CT_SRC_IP:
+       case NFT_CT_DST_IP:
+               if (tb[NFTA_CT_DIRECTION] == NULL)
+                       return -EINVAL;
+
+               len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u3.ip);
+               break;
+       case NFT_CT_SRC_IP6:
+       case NFT_CT_DST_IP6:
+               if (tb[NFTA_CT_DIRECTION] == NULL)
+                       return -EINVAL;
+
+               len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u3.ip6);
+               break;
        case NFT_CT_PROTO_SRC:
        case NFT_CT_PROTO_DST:
                if (tb[NFTA_CT_DIRECTION] == NULL)
        switch (priv->key) {
        case NFT_CT_SRC:
        case NFT_CT_DST:
+       case NFT_CT_SRC_IP:
+       case NFT_CT_DST_IP:
+       case NFT_CT_SRC_IP6:
+       case NFT_CT_DST_IP6:
        case NFT_CT_PROTO_SRC:
        case NFT_CT_PROTO_DST:
                if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))