From patchwork Fri Jul 6 02:23:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Darrell Ball X-Patchwork-Id: 940246 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="tynQl8w5"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41MJSv0tfXz9s4Z for ; Fri, 6 Jul 2018 12:24:14 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 765BDD2E; Fri, 6 Jul 2018 02:24:03 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 9E85CD0E for ; Fri, 6 Jul 2018 02:24:00 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f195.google.com (mail-pf0-f195.google.com [209.85.192.195]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 8BB5A79F for ; Fri, 6 Jul 2018 02:23:59 +0000 (UTC) Received: by mail-pf0-f195.google.com with SMTP id b17-v6so7037823pfi.0 for ; Thu, 05 Jul 2018 19:23:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=AOyhfdnxizZpvqcQaccSOFRUvGshif6Z3atEvD8YF9U=; b=tynQl8w5RMBZSXu+7cL+XlRd6Mt1eblRahxiYHdLSCBsVzA8bJzgdyPljsZXlNvt0F ZQjKNSMB7PM2dKPzkauoQuvb/pAznJ3+R5mLOLRjGRXetT8dG5ahNhcJtO7umAlyfHZA 9VbwJ3bURQmr/Z9WyqbVkAWA5YShUWCPYzjLJRZizYo9Escb0EbptVV9QxBRw6YCe3Dn WzzU+Ewc1dZXxJawIeMg1gKgBvQKIrARFYkBLkAY9Ev8bzBALRvXqZmvJZFFnblyiHLB udEIdNZZXlaKT9LbLXmM2vrYievQ9aYm6EFDBGC/NlOWi2L41lMfslfFITya8u36jquY fp4g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=AOyhfdnxizZpvqcQaccSOFRUvGshif6Z3atEvD8YF9U=; b=gCcDPcv80x7E7YuEa1iUa9oZsoLVpeZrJj6RbJiuEKToV7ykS5WBIiE7irSXQhseDS dpRsGmj/WuMLOabfVMVIUqIKk2F9hsPDRXt+3EQM8DKKJP0zXEr9jH7MOsWm+uImc5B0 B+u9c54EGITnzvmFddkELLsKrWoCIuJPrmRftxSoWVXmr9xAAz+TicR/xYjuzGft5yds HR1bUd4+cLqxN0qOn4ffISmnEbOsmxKaVtKqbwCZGoBtvgh0W37w5HxYkhxSRnz/nxWw yKSk0CrCtMX+JKRiWf0f1tpMrAahi8hmsws/2QWKf1gBBxbLaHfTcq9Hsz2XFcNR0Gn0 tgUg== X-Gm-Message-State: APt69E3nnoGTzNjW7wb+T0T74xbtBSZLMaheX5D2mm5kk2c/98tPNGVW nq8T2fa+tVQBDtFhLPzokz4= X-Google-Smtp-Source: AAOMgpd2eWl0YchCBDp821Ofc96DRQRe4viknWTK2wYA5xCZfzEHvUAl5qEBxyK4QUoyyy/HLzxwQQ== X-Received: by 2002:a63:7454:: with SMTP id e20-v6mr3152277pgn.410.1530843839006; Thu, 05 Jul 2018 19:23:59 -0700 (PDT) Received: from ubuntu.localdomain ([208.91.2.1]) by smtp.gmail.com with ESMTPSA id g124-v6sm11540339pfb.5.2018.07.05.19.23.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 05 Jul 2018 19:23:57 -0700 (PDT) From: Darrell Ball To: dlu998@gmail.com, dev@openvswitch.org Date: Thu, 5 Jul 2018 19:23:46 -0700 Message-Id: <1530843826-13160-1-git-send-email-dlu998@gmail.com> X-Mailer: git-send-email 1.9.1 MIME-Version: 1.0 X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] =?utf-8?b?W+KAnXBhdGNoX3Yy4oCdXSBjb25udHJhY2s6IFN1cHBv?= =?utf-8?q?rt_global_invalid_packet_stats=2E?= X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Only standard sanity failures, which are normally rare, are tracked. Signed-off-by: Darrell Ball --- NEWS | 2 + lib/conntrack.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++--- lib/conntrack.h | 15 +++++++ lib/ct-dpif.c | 27 +++++++++++++ lib/ct-dpif.h | 15 +++++++ lib/dpctl.c | 66 ++++++++++++++++++++++++++++++ lib/dpctl.man | 3 +- lib/dpif-netdev.c | 29 +++++++++++++ lib/dpif-netlink.c | 1 + lib/dpif-provider.h | 6 +++ 10 files changed, 272 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index cd15a33..84b0b8d 100644 --- a/NEWS +++ b/NEWS @@ -40,6 +40,8 @@ Post-v2.9.0 ovs-appctl dpif-netdev/pmd-perf-show * Supervision of PMD performance metrics and logging of suspicious iterations + * ovs-appctl dpctl/ct-stats-show now prints global conntrack invalid + marked sanity failure packet statistics. - ERSPAN: * Implemented ERSPAN protocol (draft-foschiano-erspan-00.txt) for both kernel datapath and userspace datapath. diff --git a/lib/conntrack.c b/lib/conntrack.c index 97fd46a..30fd506 100644 --- a/lib/conntrack.c +++ b/lib/conntrack.c @@ -226,6 +226,27 @@ long long ct_timeout_val[] = { * are accepted; this is for CT_CONN_TYPE_DEFAULT connections. */ #define DEFAULT_N_CONN_LIMIT 3000000 +/* IPv4 sanity invalid packets. */ +static atomic_count min_hdr_err_v4; +static atomic_count size_err_v4; +static atomic_count cksum_err_v4; +static atomic_count fragment_v4; + +/* IPv6 sanity invalid packets. */ +static atomic_count min_hdr_err_v6; +static atomic_count hdr_parse_err_v6; +static atomic_count fragment_v6; + +/* L4 sanity invalid packets. */ +static atomic_count hdr_size_err_tcp; +static atomic_count size_err_tcp; +static atomic_count cksum_err_tcp; +static atomic_count hdr_size_err_udp; +static atomic_count size_err_udp; +static atomic_count cksum_err_udp; +static atomic_count cksum_err_icmp; +static atomic_count cksum_err_icmp6; + /* Does a member by member comparison of two conn_keys; this * function must be kept in sync with struct conn_key; returns 0 * if the keys are equal or 1 if the keys are not equal. */ @@ -337,6 +358,22 @@ conntrack_init(struct conntrack *ct) ct->hash_basis = random_uint32(); atomic_count_init(&ct->n_conn, 0); atomic_init(&ct->n_conn_limit, DEFAULT_N_CONN_LIMIT); + atomic_count_init(&min_hdr_err_v4, 0); + atomic_count_init(&size_err_v4, 0); + atomic_count_init(&cksum_err_v4, 0); + atomic_count_init(&fragment_v4, 0); + atomic_count_init(&min_hdr_err_v6, 0); + atomic_count_init(&hdr_parse_err_v6, 0); + atomic_count_init(&fragment_v6, 0); + atomic_count_init(&hdr_size_err_tcp, 0); + atomic_count_init(&size_err_tcp, 0); + atomic_count_init(&cksum_err_tcp, 0); + atomic_count_init(&hdr_size_err_udp, 0); + atomic_count_init(&size_err_udp, 0); + atomic_count_init(&cksum_err_udp, 0); + atomic_count_init(&cksum_err_icmp, 0); + atomic_count_init(&cksum_err_icmp6, 0); + latch_init(&ct->clean_thread_exit); ct->clean_thread = ovs_thread_create("ct_clean", clean_thread_main, ct); } @@ -1504,6 +1541,7 @@ extract_l3_ipv4(struct conn_key *key, const void *data, size_t size, const char **new_data, bool validate_checksum) { if (OVS_UNLIKELY(size < IP_HEADER_LEN)) { + atomic_count_inc(&min_hdr_err_v4); return false; } @@ -1511,18 +1549,22 @@ extract_l3_ipv4(struct conn_key *key, const void *data, size_t size, size_t ip_len = IP_IHL(ip->ip_ihl_ver) * 4; if (OVS_UNLIKELY(ip_len < IP_HEADER_LEN)) { + atomic_count_inc(&min_hdr_err_v4); return false; } if (OVS_UNLIKELY(size < ip_len)) { + atomic_count_inc(&size_err_v4); return false; } if (IP_IS_FRAGMENT(ip->ip_frag_off)) { + atomic_count_inc(&fragment_v4); return false; } if (validate_checksum && csum(data, ip_len) != 0) { + atomic_count_inc(&cksum_err_v4); return false; } @@ -1547,6 +1589,7 @@ extract_l3_ipv6(struct conn_key *key, const void *data, size_t size, const struct ovs_16aligned_ip6_hdr *ip6 = data; if (OVS_UNLIKELY(size < sizeof *ip6)) { + atomic_count_inc(&min_hdr_err_v6); return false; } @@ -1556,10 +1599,12 @@ extract_l3_ipv6(struct conn_key *key, const void *data, size_t size, uint8_t nw_frag = 0; if (!parse_ipv6_ext_hdrs(&data, &size, &nw_proto, &nw_frag)) { + atomic_count_inc(&hdr_parse_err_v6); return false; } if (nw_frag) { + atomic_count_inc(&fragment_v4); return false; } @@ -1599,15 +1644,21 @@ check_l4_tcp(const struct conn_key *key, const void *data, size_t size, { const struct tcp_header *tcp = data; if (size < sizeof *tcp) { + atomic_count_inc(&hdr_size_err_tcp); return false; } size_t tcp_len = TCP_OFFSET(tcp->tcp_ctl) * 4; if (OVS_UNLIKELY(tcp_len < TCP_HEADER_LEN || tcp_len > size)) { + atomic_count_inc(&size_err_tcp); return false; } - return validate_checksum ? checksum_valid(key, data, size, l3) : true; + if (validate_checksum && !checksum_valid(key, data, size, l3)) { + atomic_count_inc(&cksum_err_tcp); + return false; + } + return true; } static inline bool @@ -1616,30 +1667,44 @@ check_l4_udp(const struct conn_key *key, const void *data, size_t size, { const struct udp_header *udp = data; if (size < sizeof *udp) { + atomic_count_inc(&hdr_size_err_udp); return false; } size_t udp_len = ntohs(udp->udp_len); if (OVS_UNLIKELY(udp_len < UDP_HEADER_LEN || udp_len > size)) { + atomic_count_inc(&size_err_udp); return false; } /* Validation must be skipped if checksum is 0 on IPv4 packets */ - return (udp->udp_csum == 0 && key->dl_type == htons(ETH_TYPE_IP)) - || (validate_checksum ? checksum_valid(key, data, size, l3) : true); + if (!(udp->udp_csum == 0 && key->dl_type == htons(ETH_TYPE_IP)) && + (validate_checksum && !checksum_valid(key, data, size, l3))) { + atomic_count_inc(&cksum_err_udp); + return false; + } + return true; } static inline bool check_l4_icmp(const void *data, size_t size, bool validate_checksum) { - return validate_checksum ? csum(data, size) == 0 : true; + if (validate_checksum && csum(data, size) != 0) { + atomic_count_inc(&cksum_err_icmp); + return false; + } + return true; } static inline bool check_l4_icmp6(const struct conn_key *key, const void *data, size_t size, const void *l3, bool validate_checksum) { - return validate_checksum ? checksum_valid(key, data, size, l3) : true; + if (validate_checksum && !checksum_valid(key, data, size, l3)) { + atomic_count_inc(&cksum_err_icmp6); + return false; + } + return true; } static inline bool @@ -1950,6 +2015,7 @@ conn_key_extract(struct conntrack *ct, struct dp_packet *pkt, ovs_be16 dl_type, bool hwol_bad_l3_csum = dp_packet_ip_checksum_bad(pkt); if (hwol_bad_l3_csum) { ok = false; + atomic_count_inc(&cksum_err_v4); } else { bool hwol_good_l3_csum = dp_packet_ip_checksum_valid(pkt); /* Validate the checksum only when hwol is not supported. */ @@ -2598,6 +2664,44 @@ conntrack_get_nconns(struct conntrack *ct, uint32_t *nconns) return 0; } +/* Reports stats for invalid marked packets due to standard packet + * sanity failures. */ +int +conntrack_get_invl_stats(unsigned int *ct_min_hdr_err_v4, + unsigned int *ct_size_err_v4, + unsigned int *ct_cksum_err_v4, + unsigned int *ct_fragment_v4, + unsigned int *ct_min_hdr_err_v6, + unsigned int *ct_hdr_parse_err_v6, + unsigned int *ct_fragment_v6, + unsigned int *ct_hdr_size_err_tcp, + unsigned int *ct_size_err_tcp, + unsigned int *ct_cksum_err_tcp, + unsigned int *ct_hdr_size_err_udp, + unsigned int *ct_size_err_udp, + unsigned int *ct_cksum_err_udp, + unsigned int *ct_cksum_err_icmp, + unsigned int *ct_cksum_err_icmp6) +{ + *ct_min_hdr_err_v4 = atomic_count_get(&min_hdr_err_v4); + *ct_size_err_v4 = atomic_count_get(&size_err_v4); + *ct_cksum_err_v4 = atomic_count_get(&cksum_err_v4); + *ct_fragment_v4 = atomic_count_get(&fragment_v4); + *ct_min_hdr_err_v6 = atomic_count_get(&min_hdr_err_v6); + *ct_hdr_parse_err_v6 = atomic_count_get(&hdr_parse_err_v6); + *ct_fragment_v6 = atomic_count_get(&fragment_v6); + *ct_hdr_size_err_tcp = atomic_count_get(&hdr_size_err_tcp); + *ct_size_err_tcp = atomic_count_get(&size_err_tcp); + *ct_cksum_err_tcp = atomic_count_get(&cksum_err_tcp); + *ct_hdr_size_err_udp = atomic_count_get(&hdr_size_err_udp); + *ct_size_err_udp = atomic_count_get(&size_err_udp); + *ct_cksum_err_udp = atomic_count_get(&cksum_err_udp); + *ct_cksum_err_icmp = atomic_count_get(&cksum_err_icmp); + *ct_cksum_err_icmp6 = atomic_count_get(&cksum_err_icmp6); + + return 0; +} + /* This function must be called with the ct->resources read lock taken. */ static struct alg_exp_node * expectation_lookup(struct hmap *alg_expectations, const struct conn_key *key, diff --git a/lib/conntrack.h b/lib/conntrack.h index e3a5dcc..0fa9a7e 100644 --- a/lib/conntrack.h +++ b/lib/conntrack.h @@ -122,6 +122,21 @@ int conntrack_flush_tuple(struct conntrack *, const struct ct_dpif_tuple *, int conntrack_set_maxconns(struct conntrack *ct, uint32_t maxconns); int conntrack_get_maxconns(struct conntrack *ct, uint32_t *maxconns); int conntrack_get_nconns(struct conntrack *ct, uint32_t *nconns); +int conntrack_get_invl_stats(unsigned int *ct_min_hdr_err_v4, + unsigned int *ct_size_err_v4, + unsigned int *ct_cksum_err_v4, + unsigned int *fragment_v4, + unsigned int *ct_min_hdr_err_v6, + unsigned int *ct_hdr_parse_err_v6, + unsigned int *fragment_v6, + unsigned int *ct_hdr_size_err_tcp, + unsigned int *ct_size_err_tcp, + unsigned int *ct_cksum_err_tcp, + unsigned int *ct_hdr_size_err_udp, + unsigned int *ct_size_err_udp, + unsigned int *ct_cksum_err_udp, + unsigned int *ct_cksum_err_icmp, + unsigned int *ct_cksum_err_icmp6); /* 'struct ct_lock' is a wrapper for an adaptive mutex. It's useful to try * different types of locks (e.g. spinlocks) */ diff --git a/lib/ct-dpif.c b/lib/ct-dpif.c index 5fa3a97..e4de7de 100644 --- a/lib/ct-dpif.c +++ b/lib/ct-dpif.c @@ -164,6 +164,33 @@ ct_dpif_get_nconns(struct dpif *dpif, uint32_t *nconns) : EOPNOTSUPP); } +int +ct_dpif_get_invl_stats(struct dpif *dpif, unsigned int *min_hdr_err_v4, + unsigned int *size_err_v4, + unsigned int *cksum_err_v4, + unsigned int *fragment_v4, + unsigned int *min_hdr_err_v6, + unsigned int *hdr_parse_err_v6, + unsigned int *fragment_v6, + unsigned int *hdr_size_err_tcp, + unsigned int *size_err_tcp, + unsigned int *cksum_err_tcp, + unsigned int *hdr_size_err_udp, + unsigned int *size_err_udp, + unsigned int *cksum_err_udp, + unsigned int *cksum_err_icmp, + unsigned int *cksum_err_icmp6) +{ + return (dpif->dpif_class->ct_get_invl_stats + ? dpif->dpif_class->ct_get_invl_stats(dpif, min_hdr_err_v4, + size_err_v4, cksum_err_v4, fragment_v4, min_hdr_err_v6, + hdr_parse_err_v6, fragment_v6, hdr_size_err_tcp, + size_err_tcp, cksum_err_tcp, hdr_size_err_udp, + size_err_udp, cksum_err_udp, cksum_err_icmp, + cksum_err_icmp6) + : EOPNOTSUPP); +} + void ct_dpif_entry_uninit(struct ct_dpif_entry *entry) { diff --git a/lib/ct-dpif.h b/lib/ct-dpif.h index 09e7698..13beb0b 100644 --- a/lib/ct-dpif.h +++ b/lib/ct-dpif.h @@ -200,6 +200,21 @@ int ct_dpif_flush(struct dpif *, const uint16_t *zone, int ct_dpif_set_maxconns(struct dpif *dpif, uint32_t maxconns); int ct_dpif_get_maxconns(struct dpif *dpif, uint32_t *maxconns); int ct_dpif_get_nconns(struct dpif *dpif, uint32_t *nconns); +int ct_dpif_get_invl_stats(struct dpif *dpif, unsigned int *min_hdr_err_v4, + unsigned int *size_err_v4, + unsigned int *cksum_err_v4, + unsigned int *fragment_v4, + unsigned int *min_hdr_err_v6, + unsigned int *hdr_parse_err_v6, + unsigned int *fragment_v6, + unsigned int *hdr_size_err_tcp, + unsigned int *size_err_tcp, + unsigned int *cksum_err_tcp, + unsigned int *hdr_size_err_udp, + unsigned int *size_err_udp, + unsigned int *cksum_err_udp, + unsigned int *cksum_err_icmp, + unsigned int *cksum_err_icmp6); void ct_dpif_entry_uninit(struct ct_dpif_entry *); void ct_dpif_format_entry(const struct ct_dpif_entry *, struct ds *, bool verbose, bool print_stats); diff --git a/lib/dpctl.c b/lib/dpctl.c index 4f1e443..45f82fd 100644 --- a/lib/dpctl.c +++ b/lib/dpctl.c @@ -1381,6 +1381,71 @@ error: return error; } +/* Prints nothing for unsupported datapath types. */ +static void +ct_print_invalid_stats(struct dpctl_params *dpctl_p, struct dpif *dpif) +{ + if (dpif) { + unsigned int min_hdr_err_v4; + unsigned int size_err_v4; + unsigned int cksum_err_v4; + unsigned int fragment_v4; + unsigned int min_hdr_err_v6; + unsigned int hdr_parse_err_v6; + unsigned int fragment_v6; + unsigned int hdr_size_err_tcp; + unsigned int size_err_tcp; + unsigned int cksum_err_tcp; + unsigned int hdr_size_err_udp; + unsigned int size_err_udp; + unsigned int cksum_err_udp; + unsigned int cksum_err_icmp; + unsigned int cksum_err_icmp6; + int error = ct_dpif_get_invl_stats(dpif, &min_hdr_err_v4, &size_err_v4, + &cksum_err_v4, &fragment_v4, + &min_hdr_err_v6, &hdr_parse_err_v6, + &fragment_v6, &hdr_size_err_tcp, + &size_err_tcp, &cksum_err_tcp, + &hdr_size_err_udp, &size_err_udp, + &cksum_err_udp, &cksum_err_icmp, + &cksum_err_icmp6); + + if (!error) { + dpctl_print(dpctl_p, "\nConnTracker Invalid Sanity Stats:\n"); + dpctl_print(dpctl_p, "v4 minimum header errors: %u\n", + min_hdr_err_v4); + dpctl_print(dpctl_p, "v4 packet size errors: %u\n", + size_err_v4); + dpctl_print(dpctl_p, "v4 checksum errors: %u\n", + cksum_err_v4); + dpctl_print(dpctl_p, "v4 fragments: %u\n", + fragment_v4); + dpctl_print(dpctl_p, "v6 minimum header errors: %u\n", + min_hdr_err_v6); + dpctl_print(dpctl_p, "v6 parse errors: %u\n", + hdr_parse_err_v6); + dpctl_print(dpctl_p, "v6 fragments: %u\n", + fragment_v6); + dpctl_print(dpctl_p, "tcp header size errors: %u\n", + cksum_err_tcp); + dpctl_print(dpctl_p, "tcp size errors: %u\n", + cksum_err_tcp); + dpctl_print(dpctl_p, "tcp checksum errors: %u\n", + cksum_err_tcp); + dpctl_print(dpctl_p, "udp header size errors: %u\n", + cksum_err_tcp); + dpctl_print(dpctl_p, "udp size errors: %u\n", + cksum_err_tcp); + dpctl_print(dpctl_p, "udp checksum errors: %u\n", + cksum_err_udp); + dpctl_print(dpctl_p, "icmp checksum errors: %u\n", + cksum_err_icmp); + dpctl_print(dpctl_p, "icmp6 checksum errors: %u\n", + cksum_err_icmp6); + } + } +} + static int dpctl_ct_stats_show(int argc, const char *argv[], struct dpctl_params *dpctl_p) @@ -1514,6 +1579,7 @@ dpctl_ct_stats_show(int argc, const char *argv[], } ct_dpif_dump_done(dump); + ct_print_invalid_stats(dpctl_p, dpif); dpif_close(dpif); return error; } diff --git a/lib/dpctl.man b/lib/dpctl.man index 5d987e6..4f62397 100644 --- a/lib/dpctl.man +++ b/lib/dpctl.man @@ -244,7 +244,8 @@ An example of an IPv6 TCP \fIct-tuple\fR: Displays the number of connections grouped by protocol used by \fIdp\fR. If \fBzone=\fIzone\fR is specified, numbers refer to the connections in \fIzone\fR. With \fB\-\-more\fR, groups by connection state for each -protocol. +protocol. Prints global invalid packet stats for the userspace connection +tracker; typically, a rule is in place to drop invalid flagged packets. . .TP \*(DX\fBct\-bkts\fR [\fIdp\fR] [\fBgt=\fIthreshold\fR] diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 9390fff..f19d32b 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -6044,6 +6044,34 @@ dpif_netdev_ct_get_nconns(struct dpif *dpif, uint32_t *nconns) return conntrack_get_nconns(&dp->conntrack, nconns); } +static int +dpif_netdev_ct_get_invl_stats(struct dpif *dpif OVS_UNUSED, + unsigned int *ct_min_hdr_err_v4, + unsigned int *ct_size_err_v4, + unsigned int *ct_cksum_err_v4, + unsigned int *ct_fragment_v4, + unsigned int *ct_min_hdr_err_v6, + unsigned int *ct_hdr_parse_err_v6, + unsigned int *ct_fragment_v6, + unsigned int *ct_hdr_size_err_tcp, + unsigned int *ct_size_err_tcp, + unsigned int *ct_cksum_err_tcp, + unsigned int *ct_hdr_size_err_udp, + unsigned int *ct_size_err_udp, + unsigned int *ct_cksum_err_udp, + unsigned int *ct_cksum_err_icmp, + unsigned int *ct_cksum_err_icmp6) +{ + return conntrack_get_invl_stats(ct_min_hdr_err_v4, ct_size_err_v4, + ct_cksum_err_v4, ct_fragment_v4, + ct_min_hdr_err_v6, ct_hdr_parse_err_v6, + ct_fragment_v6, ct_hdr_size_err_tcp, + ct_size_err_tcp, ct_cksum_err_tcp, + ct_hdr_size_err_udp, ct_size_err_udp, + ct_cksum_err_udp, ct_cksum_err_icmp, + ct_cksum_err_icmp6); +} + const struct dpif_class dpif_netdev_class = { "netdev", dpif_netdev_init, @@ -6092,6 +6120,7 @@ const struct dpif_class dpif_netdev_class = { dpif_netdev_ct_set_maxconns, dpif_netdev_ct_get_maxconns, dpif_netdev_ct_get_nconns, + dpif_netdev_ct_get_invl_stats, dpif_netdev_meter_get_features, dpif_netdev_meter_set, dpif_netdev_meter_get, diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index aa9bbd9..6d07d15 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -3006,6 +3006,7 @@ const struct dpif_class dpif_netlink_class = { NULL, /* ct_set_maxconns */ NULL, /* ct_get_maxconns */ NULL, /* ct_get_nconns */ + NULL, /* ct_get_invl_stats */ dpif_netlink_meter_get_features, dpif_netlink_meter_set, dpif_netlink_meter_get, diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h index 62b3598..1692ac7 100644 --- a/lib/dpif-provider.h +++ b/lib/dpif-provider.h @@ -443,6 +443,12 @@ struct dpif_class { int (*ct_get_maxconns)(struct dpif *, uint32_t *maxconns); /* Get number of connections tracked. */ int (*ct_get_nconns)(struct dpif *, uint32_t *nconns); + int (*ct_get_invl_stats)(struct dpif *, unsigned int *, + unsigned int *, unsigned int *, unsigned int *, + unsigned int *, unsigned int *, unsigned int *, + unsigned int *, unsigned int *, unsigned int *, + unsigned int *, unsigned int *, unsigned int *, + unsigned int *, unsigned int *); /* Meters */