From patchwork Mon Nov 16 06:21:18 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniele Di Proietto X-Patchwork-Id: 544908 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (li376-54.members.linode.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id 5088F14144E for ; Mon, 16 Nov 2015 17:22:22 +1100 (AEDT) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id 667F710539; Sun, 15 Nov 2015 22:21:45 -0800 (PST) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx1e4.cudamail.com (mx1.cudamail.com [69.90.118.67]) by archives.nicira.com (Postfix) with ESMTPS id 4D04410398 for ; Sun, 15 Nov 2015 22:21:42 -0800 (PST) Received: from bar5.cudamail.com (unknown [192.168.21.12]) by mx1e4.cudamail.com (Postfix) with ESMTPS id CE1DB1E00B5 for ; Sun, 15 Nov 2015 23:21:41 -0700 (MST) X-ASG-Debug-ID: 1447654901-09eadd03665096b0001-byXFYA Received: from mx1-pf2.cudamail.com ([192.168.24.2]) by bar5.cudamail.com with ESMTP id 8KjbpAKWy1MD1p8i (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 15 Nov 2015 23:21:41 -0700 (MST) X-Barracuda-Envelope-From: diproiettod@vmware.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.24.2 Received: from unknown (HELO smtp-outbound-2.vmware.com) (208.91.2.13) by mx1-pf2.cudamail.com with ESMTPS (DHE-RSA-AES256-SHA encrypted); 16 Nov 2015 06:21:41 -0000 Received-SPF: pass (mx1-pf2.cudamail.com: SPF record at _spf.vmware.com designates 208.91.2.13 as permitted sender) X-Barracuda-Apparent-Source-IP: 208.91.2.13 X-Barracuda-RBL-IP: 208.91.2.13 Received: from sc9-mailhost2.vmware.com (sc9-mailhost2.vmware.com [10.113.161.72]) by smtp-outbound-2.vmware.com (Postfix) with ESMTP id 584F6287C8 for ; Sun, 15 Nov 2015 22:21:40 -0800 (PST) Received: from sc9-mailhost3.vmware.com (unknown [10.129.192.239]) by sc9-mailhost2.vmware.com (Postfix) with ESMTP id 2F512B0563; Sun, 15 Nov 2015 22:21:40 -0800 (PST) X-CudaMail-Envelope-Sender: diproiettod@vmware.com From: Daniele Di Proietto To: dev@openvswitch.org X-CudaMail-Whitelist-To: dev@openvswitch.org X-CudaMail-MID: CM-E2-1114030515 X-CudaMail-DTE: 111515 X-CudaMail-Originating-IP: 208.91.2.13 Date: Sun, 15 Nov 2015 22:21:18 -0800 X-ASG-Orig-Subj: [##CM-E2-1114030515##][PATCH 07/12] conntrack: Implement dumping to ct_entry. Message-Id: <1447654883-8097-8-git-send-email-diproiettod@vmware.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1447654883-8097-1-git-send-email-diproiettod@vmware.com> References: <1447654883-8097-1-git-send-email-diproiettod@vmware.com> X-Barracuda-Connect: UNKNOWN[192.168.24.2] X-Barracuda-Start-Time: 1447654901 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-ASG-Whitelist: Header =?UTF-8?B?eFwtY3VkYW1haWxcLXdoaXRlbGlzdFwtdG8=?= X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 X-ASG-Whitelist: EmailCat (corporate) Subject: [ovs-dev] [PATCH 07/12] conntrack: Implement dumping to ct_entry. X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" Signed-off-by: Daniele Di Proietto --- lib/conntrack-private.h | 3 ++ lib/conntrack-tcp.c | 34 +++++++++++++ lib/conntrack.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/conntrack.h | 16 +++++++ 4 files changed, 178 insertions(+) diff --git a/lib/conntrack-private.h b/lib/conntrack-private.h index 62e3003..330e6fe 100644 --- a/lib/conntrack-private.h +++ b/lib/conntrack-private.h @@ -21,6 +21,7 @@ #include #include +#include "ct-dpif.h" #include "hmap.h" #include "openvswitch/types.h" #include "packets.h" @@ -69,6 +70,8 @@ struct ct_l4_proto { bool (*valid_new)(struct dp_packet *pkt); enum ct_update_res (*conn_update)(struct conn *conn, struct dp_packet *pkt, bool reply, long long now); + void (*conn_get_protoinfo)(const struct conn *, + struct ct_dpif_protoinfo *); }; extern struct ct_l4_proto ct_proto_tcp; diff --git a/lib/conntrack-tcp.c b/lib/conntrack-tcp.c index 977c691..4fbb0a5 100644 --- a/lib/conntrack-tcp.c +++ b/lib/conntrack-tcp.c @@ -468,8 +468,42 @@ tcp_new_conn(struct dp_packet *pkt, long long now) return &newconn->up; } +static uint8_t +tcp_peer_to_protoinfo_flags(const struct tcp_peer *peer) +{ + uint8_t res = 0; + + if (peer->wscale & CT_WSCALE_FLAG) { + res |= CT_DPIF_TCPF_WINDOW_SCALE; + } + + if (peer->wscale & CT_WSCALE_UNKNOWN) { + res |= CT_DPIF_TCPF_BE_LIBERAL; + } + + return res; +} + +static void +tcp_conn_get_protoinfo(const struct conn *conn_, + struct ct_dpif_protoinfo *protoinfo) +{ + const struct conn_tcp *conn = conn_tcp_cast(conn_); + + protoinfo->proto = IPPROTO_TCP; + protoinfo->tcp.state_orig = conn->peer[0].state; + protoinfo->tcp.state_reply = conn->peer[1].state; + + protoinfo->tcp.wscale_orig = conn->peer[0].wscale & CT_WSCALE_MASK; + protoinfo->tcp.wscale_reply = conn->peer[1].wscale & CT_WSCALE_MASK; + + protoinfo->tcp.flags_orig = tcp_peer_to_protoinfo_flags(&conn->peer[0]); + protoinfo->tcp.flags_reply = tcp_peer_to_protoinfo_flags(&conn->peer[0]); +} + struct ct_l4_proto ct_proto_tcp = { .new_conn = tcp_new_conn, .valid_new = tcp_valid_new, .conn_update = tcp_conn_update, + .conn_get_protoinfo = tcp_conn_get_protoinfo, }; diff --git a/lib/conntrack.c b/lib/conntrack.c index 51332aa..bec5049 100644 --- a/lib/conntrack.c +++ b/lib/conntrack.c @@ -24,6 +24,7 @@ #include "bitmap.h" #include "conntrack-private.h" +#include "ct-dpif.h" #include "dp-packet.h" #include "flow.h" #include "hmap.h" @@ -853,6 +854,130 @@ delete_conn(struct conn *conn) free(conn); } +static void +ct_endpoint_to_ct_dpif_inet_addr(const struct ct_addr *a, + union ct_dpif_inet_addr *b, + ovs_be16 dl_type) +{ + if (dl_type == htons(ETH_TYPE_IP)) { + b->ip = a->ipv4_aligned; + } else if (dl_type == htons(ETH_TYPE_IPV6)){ + b->in6 = a->ipv6_aligned; + } +} + +static void +conn_key_to_tuple(const struct conn_key *key, struct ct_dpif_tuple *tuple) +{ + if (key->dl_type == htons(ETH_TYPE_IP)) { + tuple->l3_type = AF_INET; + } else if (key->dl_type == htons(ETH_TYPE_IPV6)) { + tuple->l3_type = AF_INET6; + } + tuple->ip_proto = key->nw_proto; + ct_endpoint_to_ct_dpif_inet_addr(&key->src.addr, &tuple->src, + key->dl_type); + ct_endpoint_to_ct_dpif_inet_addr(&key->dst.addr, &tuple->dst, + key->dl_type); + + if (key->nw_proto == IPPROTO_ICMP) { + tuple->icmp_id = key->src.port; + /* ICMP type and code are not tracked */ + tuple->icmp_type = 0; + tuple->icmp_code = 0; + } else { + tuple->src_port = key->src.port; + tuple->dst_port = key->dst.port; + } +} + +static void +conn_to_ct_dpif_entry(const struct conn *conn, struct ct_dpif_entry *entry, + long long now) +{ + struct ct_l4_proto *class; + long long expiration; + memset(entry, 0, sizeof *entry); + conn_key_to_tuple(&conn->key, &entry->tuple_orig); + conn_key_to_tuple(&conn->rev_key, &entry->tuple_reply); + + entry->zone = conn->key.zone; + entry->mark = conn->mark; + + memcpy(&entry->labels, &conn->label, sizeof(entry->labels)); + /* Not implemented yet */ + entry->timestamp.start = 0; + entry->timestamp.stop = 0; + + expiration = conn->expiration - now; + entry->timeout = (expiration > 0) ? expiration / 1000: 0; + + class = l4_protos[conn->key.nw_proto]; + if (class->conn_get_protoinfo) { + class->conn_get_protoinfo(conn, &entry->protoinfo); + } +} + +int +conntrack_dump_start(struct conntrack *ct, struct conntrack_dump *dump, + const uint16_t *pzone) +{ + memset(dump, 0, sizeof(*dump)); + if (pzone) { + dump->zone = *pzone; + dump->filter_zone = true; + } + dump->ct = ct; + + return 0; +} + +int +conntrack_dump_next(struct conntrack_dump *dump, struct ct_dpif_entry *entry) +{ + struct conntrack *ct = dump->ct; + long long now = time_msec(); + + while (dump->bucket < CONNTRACK_BUCKETS) { + struct hmap_node *node; + + ct_lock_lock(&ct->locks[dump->bucket]); + for (;;) { + struct conn *conn; + + node = hmap_at_position(&ct->connections[dump->bucket], + &dump->inner_bucket, + &dump->inner_offset); + if (!node) { + break; + } + INIT_CONTAINER(conn, node, node); + if (!dump->filter_zone || conn->key.zone == dump->zone) { + conn_to_ct_dpif_entry(conn, entry, now); + break; + } + /* Else continue, until we find an entry in the appropriate zone + * or the bucket has been scanned completely. */ + } + ct_lock_unlock(&ct->locks[dump->bucket]); + + if (!node) { + dump->inner_bucket = 0; + dump->inner_offset = 0; + dump->bucket++; + } else { + return 0; + } + } + return EOF; +} + +int +conntrack_dump_done(struct conntrack_dump *dump OVS_UNUSED) +{ + return 0; +} + int conntrack_flush(struct conntrack *ct, const uint16_t *zone) { diff --git a/lib/conntrack.h b/lib/conntrack.h index f82857f..210e1da 100644 --- a/lib/conntrack.h +++ b/lib/conntrack.h @@ -69,6 +69,22 @@ int conntrack_execute(struct conntrack *, struct dp_packet **, size_t, const struct ovs_key_ct_labels *setlabel, const char *helper); +struct conntrack_dump { + struct conntrack *ct; + unsigned bucket; + uint32_t inner_bucket; + uint32_t inner_offset; + bool filter_zone; + uint16_t zone; +}; + +struct ct_dpif_entry; + +int conntrack_dump_start(struct conntrack *, struct conntrack_dump *, + const uint16_t *pzone); +int conntrack_dump_next(struct conntrack_dump *, struct ct_dpif_entry *); +int conntrack_dump_done(struct conntrack_dump *); + int conntrack_flush(struct conntrack *, const uint16_t *zone); /* struct ct_lock is a standard mutex or a spinlock when using DPDK */