From patchwork Tue Jun 2 10:09:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gowrishankar Muthukrishnan X-Patchwork-Id: 1302310 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=whitealder.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=DaCEwM+T; dkim-atps=neutral Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49bnq00hpWz9sSg for ; Tue, 2 Jun 2020 20:10:19 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id AB30587775; Tue, 2 Jun 2020 10:10:17 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id XCnFMZ83hqzl; Tue, 2 Jun 2020 10:10:11 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id 28D6586B2B; Tue, 2 Jun 2020 10:10:11 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 16BF4C0865; Tue, 2 Jun 2020 10:10:11 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 64801C016E for ; Tue, 2 Jun 2020 10:10:10 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 2B6CE2047A for ; Tue, 2 Jun 2020 10:10:10 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from silver.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 6o-PEn3JqyxJ for ; Tue, 2 Jun 2020 10:10:06 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) by silver.osuosl.org (Postfix) with ESMTPS id 057CB203B0 for ; Tue, 2 Jun 2020 10:10:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1591092604; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=BuR7SS43bPKmW/RIi6BFYMW0rqtvmOBkmjNSftu9buc=; b=DaCEwM+TL4ABuTBFY5HIFqrLgriDbnB8IlYdFZ2xINd2y3oqIMwY1eUaBaK86uKEUYGKQX zi4GU1tNExcz1/Sj0CeP6Q6ROcB6oMxi9knBS/5LYele+++aevo6wI2CiRAFEqcd/mef+n FBysM64VG/tjvp4f38wEym1L7V024EM= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-492-80CCVfGSPROKpjFBRbs3TQ-1; Tue, 02 Jun 2020 06:10:01 -0400 X-MC-Unique: 80CCVfGSPROKpjFBRbs3TQ-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 3C0FA100A8E9; Tue, 2 Jun 2020 10:10:00 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-111.sin2.redhat.com [10.67.117.111]) by smtp.corp.redhat.com (Postfix) with ESMTP id E1A765D9DD; Tue, 2 Jun 2020 10:09:56 +0000 (UTC) From: Gowrishankar Muthukrishnan To: dev@openvswitch.org Date: Tue, 2 Jun 2020 15:39:43 +0530 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: anju.thomas@ericsson.com, Keshav Gupta , i.maximets@ovn.org Subject: [ovs-dev] [PATCH 1/7] event: add api to manage user defined events X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" User defined notification is helpful in troubleshooting OVS for a particular event to appear as user will define. Based on the type of event, event is handled by a dedicated thread and user is notified in registered socket (jsonrpc) if provided. This patch comprises of below: 1. event API which is central library to define event based on the input file from user (json format). 2. dedicated thread to monitor registered events and issue notification. 3. event macros to hook at counters and functions for evaluating events by above thread. Signed-off-by: Gowrishankar Muthukrishnan --- lib/automake.mk | 2 + lib/event.c | 764 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/event.h | 269 +++++++++++++++++++ vswitchd/bridge.c | 2 + 4 files changed, 1037 insertions(+) create mode 100644 lib/event.c create mode 100644 lib/event.h diff --git a/lib/automake.mk b/lib/automake.mk index 86940cc..f022baa 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -90,6 +90,8 @@ lib_libopenvswitch_la_SOURCES = \ lib/dpif-provider.h \ lib/dpif.c \ lib/dpif.h \ + lib/event.h \ + lib/event.c \ lib/heap.c \ lib/heap.h \ lib/dynamic-string.c \ diff --git a/lib/event.c b/lib/event.c new file mode 100644 index 0000000..77f5396 --- /dev/null +++ b/lib/event.c @@ -0,0 +1,764 @@ +/* + * Copyright (c) 2020 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "event.h" +#include "jsonrpc.h" +#include "openvswitch/poll-loop.h" +#include "openvswitch/shash.h" +#include "openvswitch/vlog.h" +#include "ovs-thread.h" +#include "smap.h" +#include "stream.h" +#include "timeval.h" +#include "unixctl.h" +#include "util.h" + +VLOG_DEFINE_THIS_MODULE(event); + +static bool user_defined_event; +static struct shash events; +static struct shash events_reg; + +static pthread_t event_thread_id; +static struct ovs_mutex event_mutex = OVS_MUTEX_INITIALIZER; + +static bool +handle_conditional_event(struct event *ev) + OVS_REQUIRES(event_mutex) +{ + bool ok; + + switch (ev->def.op) { + case EV_OP_EQ: + ok = (ev->current == ev->def.value); + break; + case EV_OP_NE: + ok = (ev->current != ev->def.value); + break; + case EV_OP_GT: + ok = (ev->current > ev->def.value); + break; + case EV_OP_GE: + ok = (ev->current >= ev->def.value); + break; + case EV_OP_LT: + ok = (ev->current < ev->def.value); + break; + case EV_OP_LE: + ok = (ev->current <= ev->def.value); + break; + case EV_OP_NONE: + default: + ok = false; + } + + if (ok) { + ev->hit++; + } + + return ok; +} + +static bool +handle_message_event(struct event *ev) + OVS_REQUIRES(event_mutex) +{ + if (ev->def.resource == EV_RESOURCE_TIMER) { + if (ev->count >= ev->def.samples) { + stopwatch_get_stats(ev->name, &ev->stats); + ev->count = 0; + ev->hit++; + } + } + return true; +} + +static void * +event_thread(void *args OVS_UNUSED) +{ + for (;;) { + long long int next_refresh; + struct shash_node *node; + struct event *ev; + int error; + bool ok; + + next_refresh = time_msec() + EVENT_POLL_INTERVAL; + do { + ovs_mutex_lock(&event_mutex); + SHASH_FOR_EACH (node, &events) { + ev = (struct event *)node->data; + + if (ev->hit && ev->hit > ev->hit_prev) { + continue; + } + + if (ev->type == EV_CONDITIONAL) { + ok = handle_conditional_event(ev); + } else if (ev->type == EV_MESSAGE) { + ok = handle_message_event(ev); + } else { + continue; + } + + if (ok && ev->notify.cb) { + ovs_mutex_unlock(&event_mutex); + error = ev->notify.cb(ev); + ev->hit_prev = (!error) ? ev->hit: ev->hit_prev; + ovs_mutex_lock(&event_mutex); + } + + } + ovs_mutex_unlock(&event_mutex); + + poll_timer_wait_until(next_refresh); + poll_block(); + } while (time_msec() < next_refresh); + } + + return NULL; +} + +int +event_try_lock(void) +{ + return ovs_mutex_trylock(&event_mutex); +} + +void +event_lock(void) + OVS_ACQUIRES(event_mutex) +{ + return ovs_mutex_lock(&event_mutex); +} + +void +event_unlock(void) + OVS_RELEASES(event_mutex) +{ + ovs_mutex_unlock(&event_mutex); +} + +static int +notify_msg(struct event *ev) + OVS_EXCLUDED(event_mutex) +{ + struct jsonrpc_msg *request; + struct json **str, *data; + int error; + + str = xmalloc(2 * sizeof(*str)); + ovs_mutex_lock(&event_mutex); + str[0] = json_string_create(ev->name); + if (ev->def.resource == EV_RESOURCE_COVERAGE) { + str[1] = json_integer_create(ev->current); + } else if (ev->def.resource == EV_RESOURCE_TIMER) { + str[1] = json_integer_create(ev->stats.pctl_95); + } + ovs_mutex_unlock(&event_mutex); + + data = json_array_create(str, 2); + request = jsonrpc_create_request("ovs_event", data, NULL); + ovs_mutex_lock(&event_mutex); + error = jsonrpc_send(ev->notify.rpc, request); + ovs_mutex_unlock(&event_mutex); + if (error) { + return error; + } + return 0; +} + +static struct shash_node * +event_find(const char *name) + OVS_REQUIRES(event_mutex) +{ + return shash_find(&events, name); +} + +struct event * +event_get(const char *name) + OVS_REQUIRES(event_mutex) +{ + return shash_find_data(&events, name); +} + +uint +event_count(void) + OVS_REQUIRES(event_mutex) +{ + return shash_count(&events); +} + +static void +event_list(struct event **list) + OVS_EXCLUDED(event_mutex) +{ + struct shash_node *node; + uint i = 0; + + if (!list) { + return; + } + + ovs_mutex_lock(&event_mutex); + SHASH_FOR_EACH (node, &events) { + list[i++] = node->data; + } + ovs_mutex_unlock(&event_mutex); +} + +static bool +event_is_defined(struct json *ev_def) + OVS_EXCLUDED(event_mutex) +{ + struct shash_node *node; + struct json *string; + + ovs_assert(ev_def->type == JSON_ARRAY); + + for (int i = 0; i < ev_def->array.n; i++) { + struct json *json; + + json = ev_def->array.elems[i]; + string = shash_find_data(json_object(json), "name"); + + ovs_mutex_lock(&event_mutex); + node = event_find(json_string(string)); + ovs_mutex_unlock(&event_mutex); + + if (node) { + return true; + } + } + return false; +} + +static struct event * +event_delete(const char *name) + OVS_REQUIRES(event_mutex) +{ + struct event *ev; + ev = shash_find_and_delete(&events, name); + if (ev && ev->def.resource == EV_RESOURCE_TIMER) { + if (!stopwatch_count()) { + stopwatch_exit(); + } else { + stopwatch_delete(ev->name); + } + } + return ev; +} + +void +event_register(const char *name, resource_t type) +{ + static resource_t ev_rst[] = {EV_RESOURCE_NONE, + EV_RESOURCE_COVERAGE, + EV_RESOURCE_TIMER}; + static bool events_registry_once = true; + if (events_registry_once) { + events_registry_once = false; + shash_init(&events_reg); + } + + shash_add(&events_reg, name, (void *)&ev_rst[type]); +} + +static int +event_add(struct json *ev_def) + OVS_EXCLUDED(event_mutex) +{ + struct event *ev; + struct shash op_map, def_map; + everr_t everr = EV_ERR_NONE; + + op_t op[] = {EV_OP_NONE, + EV_OP_EQ, + EV_OP_NE, + EV_OP_GT, + EV_OP_GE, + EV_OP_LT, + EV_OP_LE + }; + + char *events_n[EVENT_MAX]; + uint n = 0; + + shash_init(&op_map); + shash_add(&op_map, "none", (void *)&op[0]); + shash_add(&op_map, "eq", (void *)&op[1]); + shash_add(&op_map, "ne", (void *)&op[2]); + shash_add(&op_map, "gt", (void *)&op[3]); + shash_add(&op_map, "ge", (void *)&op[4]); + shash_add(&op_map, "lt", (void *)&op[5]); + shash_add(&op_map, "le", (void *)&op[6]); + + for (int i = 0; i < ev_def->array.n; i++) { + struct shash_node *node; + struct json *string; + struct json *object; + struct json *elem; + char *str; + + shash_init(&def_map); + + elem = ev_def->array.elems[i]; + if (elem->type != JSON_OBJECT) { + everr = EV_PARSE_OBJ_MISSING; + goto error; + } + + string = shash_find_data(json_object(elem), "name"); + if (!string) { + everr = EV_PARSE_NAME_MISSING; + goto error; + } + + ovs_mutex_lock(&event_mutex); + node = event_find(json_string(string)); + ovs_mutex_unlock(&event_mutex); + if (node) { + everr = EV_PARSE_EVENT_EXISTS; + goto error; + } + + ev = xmalloc(sizeof(*ev)); + ev->name = string ? xstrdup(json_string(string)) : NULL; + + string = shash_find_data(json_object(elem), "type"); + if (!string) { + everr = EV_PARSE_TYPE_MISSING; + goto error; + } + + if (!strcmp("conditional", json_string(string))) { + ev->type = EV_CONDITIONAL; + } else if (!strcmp("message", json_string(string))) { + ev->type = EV_MESSAGE; + } else if (!strcmp("none", json_string(string))) { + ev->type = EV_NONE; + } else { + everr = EV_PARSE_INVALID_EVENT; + goto error; + } + + ev->current = 0; + ev->hit = 0; + ev->hit_prev = 0; + ev->notify.stream = NULL; + ev->notify.rpc = NULL; + ev->notify.cb = NULL; + + object = shash_find_data(json_object(elem), "definition"); + if ((!object) | (object->type != JSON_OBJECT)) { + everr = EV_PARSE_DEF_MISSING; + goto error; + } + + SHASH_FOR_EACH (node, json_object(object)) { + const struct json *value = node->data; + unsigned long long *lptr; + + if (value->type == JSON_STRING) { + shash_add(&def_map, node->name, (void *)json_string(value)); + } else if (value->type == JSON_INTEGER) { + lptr = xmalloc(sizeof(unsigned long long)); + *lptr = json_integer(value); + shash_add(&def_map, node->name, (void *)lptr); + } else { + everr = EV_PARSE_INVALID_DEF; + goto error; + } + } + + str = xstrdup(shash_find_data(&def_map, "resource")); + if (!strcmp(str, "coverage_counter")) { + ev->def.resource = EV_RESOURCE_COVERAGE; + } else if (!strcmp(str, "timer")) { + ev->def.resource = EV_RESOURCE_TIMER; + } else if (!strcmp(str, "none")) { + ev->def.resource = EV_RESOURCE_NONE; + } else { + everr = EV_PARSE_INVALID_DEF; + goto error; + } + + if (ev->type == EV_CONDITIONAL) { + str = shash_find_data(&def_map, "match"); + if (!strcmp(str, "exact")) { + ev->def.match = EV_MATCH_EXACT; + } else if (!strcmp(str, "per_min")) { + ev->def.match = EV_MATCH_RATE_MIN; + } else if (!strcmp(str, "per_hour")) { + ev->def.match = EV_MATCH_RATE_HOUR; + } else { + everr = EV_PARSE_INVALID_DEF; + goto error; + } + + str = shash_find_data(&def_map, "op"); + ev->def.op = *(uint *)shash_find_data(&op_map, (const char *)str); + ev->def.value = *(unsigned long long *)shash_find_data( + &def_map, "value"); + + if (!ev->def.match || !ev->def.op || !ev->def.value) { + everr = EV_PARSE_INVALID_DEF; + goto error; + } + } + if (ev->type == EV_MESSAGE) { + str = shash_find_data(&def_map, "unit"); + if (!strcmp(str, "ms")) { + ev->def.unit = EV_UNIT_MS; + } else if (!strcmp(str, "us")) { + ev->def.unit = EV_UNIT_US; + } else { + everr = EV_PARSE_INVALID_DEF; + goto error; + } + + ev->def.samples = *(unsigned long long *)shash_find_data( + &def_map, "samples"); + } + shash_destroy(&def_map); + + string = shash_find_data(json_object(elem), "notify"); + if (string) { + int error; + char *path; + struct stream *stream; + + path = xasprintf("unix:%s", json_string(string)); + error = stream_open_block(stream_open(path, &stream, DSCP_DEFAULT), + -1, &stream); + free(path); + if (error) { + everr = EV_STREAM_OPEN_ERROR; + goto error; + } + + ev->notify.rpc = jsonrpc_open(stream); + ev->notify.stream = stream; + ev->notify.cb = notify_msg; + } + + ovs_mutex_lock(&event_mutex); + shash_add(&events, ev->name, (void *)ev); + ovs_mutex_unlock(&event_mutex); + events_n[n] = ev->name; + ++n; + + if (ev->def.resource == EV_RESOURCE_TIMER) { + unit_t units[4] = {-1, SW_MS, SW_US, SW_NS}; + stopwatch_create(ev->name, units[ev->def.unit]); + } + } + + shash_destroy(&op_map); + if (n) { + return 0; + } + + error: + ovs_mutex_lock(&event_mutex); + for (int i = 0; i < n; i++) { + ev = event_delete(events_n[n]); + if (ev) { + free(ev->name); + } + } + ovs_mutex_unlock(&event_mutex); + return everr; +} + +static void +event_unixctl_define(struct unixctl_conn *conn, int argc OVS_UNUSED, + const char *argv[], void *aux OVS_UNUSED) +{ + struct json *ev_def; + char *reply; + bool ok; + int error; + + ev_def = json_from_file(argv[1]); + if (!ev_def) { + reply = xasprintf("Unable to parse json file\n\n"); + goto cleanup; + } + + if (ev_def->type == JSON_STRING) { + reply = xstrdup(ev_def->string); + goto cleanup; + } + + ok = event_is_defined(ev_def); + if (ok) { + reply = xstrdup("One or more events already set\n"); + goto cleanup; + } + + error = event_add(ev_def); + switch (error) { + case EV_ERR_NONE: + break; + case EV_PARSE_OBJ_MISSING: + reply = xstrdup("Unable to add event (array not found)\n"); + goto cleanup; + case EV_PARSE_NAME_MISSING: + reply = xstrdup("Unable to add event (missing name)\n"); + goto cleanup; + case EV_PARSE_TYPE_MISSING: + reply = xstrdup("Unable to add event (missing type)\n"); + goto cleanup; + case EV_PARSE_DEF_MISSING: + reply = xstrdup("Unable to add event (missing definition)\n"); + goto cleanup; + case EV_PARSE_STREAM_MISSING: + reply = xstrdup("Unable to add event (missing/invalid stream)\n"); + goto cleanup; + case EV_PARSE_EVENT_EXISTS: + reply = xstrdup("Unable to add event (some already exists)\n"); + goto cleanup; + case EV_PARSE_INVALID_EVENT: + reply = xstrdup("Unable to add event (invalid event found)\n"); + goto cleanup; + case EV_PARSE_INVALID_DEF: + reply = xstrdup("Unable to add event (invalid definition)\n"); + goto cleanup; + case EV_STREAM_OPEN_ERROR: + reply = xstrdup("Unable to add event (error in opening stream)\n"); + goto cleanup; + default: + reply = xstrdup("Unable to add event (unknown error)\n"); + goto cleanup; + } + reply = xasprintf("Added event\n"); + + cleanup: + unixctl_command_reply(conn, reply); + free(reply); + json_destroy(ev_def); +} + +static void +event_unixctl_undefine(struct unixctl_conn *conn, int argc OVS_UNUSED, + const char *argv[] OVS_UNUSED, + void *aux OVS_UNUSED) +{ + struct event *ev; + char *reply; + + ovs_mutex_lock(&event_mutex); + ev = event_delete(argv[1]); + ovs_mutex_unlock(&event_mutex); + if (!ev) { + unixctl_command_reply(conn, "Unable to clear event\n"); + return; + } + + free(ev->name); + + reply = xasprintf("Cleared event\n"); + unixctl_command_reply(conn, reply); + free(reply); +} + +static void +event_unixctl_flush(struct unixctl_conn *conn, int argc OVS_UNUSED, + const char *argv[] OVS_UNUSED, + void *aux OVS_UNUSED) +{ + struct shash_node *node; + struct event *ev; + char *reply; + + reply = xasprintf("Deleting all coverage events"); + ovs_mutex_lock(&event_mutex); + SHASH_FOR_EACH (node, &events) { + ev = (struct event *)node->data; + reply = xasprintf("%s\n%s", reply, ev->name); + ev = event_delete(ev->name); + if (!ev) { + reply = xasprintf("%s not_ok!", reply); + } else { + reply = xasprintf("%s ok!", reply); + } + + free(ev->name); + } + ovs_mutex_unlock(&event_mutex); + unixctl_command_reply(conn, reply); + free(reply); +} + +static void +event_unixctl_list(struct unixctl_conn *conn, int argc OVS_UNUSED, + const char *argv[], + void *aux OVS_UNUSED) +{ + struct event **list; + struct shash_node *node; + char *reply; + char *ev_reg = NULL; + uint cnt; + uint i = 0; + char *op[] = {"none", "==", "!=", ">", ">=", "<", "<="}; + char *units[] = {"none", "ms", "us", "ns"}; + int lv[4] = {0,}; + + if (argv[1] && !( + (!strcmp(argv[1], "--all")) || + (!strcmp(argv[1], "--all-timer")) || + (!strcmp(argv[1], "--all-coverage")) + )) { + reply = xasprintf("Invalid option %s\n", argv[1]); + unixctl_command_reply(conn, reply); + free(reply); + return; + } + + if (argv[1]) { + char *rst[] = {"none", "coverage", "timer"}; + resource_t type; + + ev_reg = xasprintf("List of events not yet added:\n"); + + SHASH_FOR_EACH (node, &events_reg) { + if (shash_find(&events, node->name)) { + continue; + } + type = *(resource_t *)node->data; + + if (type == EV_RESOURCE_TIMER && !( + (!strcmp(argv[1], "--all")) || + !(strcmp(argv[1], "--all-timer")) + )) { + continue; + } + + if (type == EV_RESOURCE_COVERAGE && !( + (!strcmp(argv[1], "--all")) || + !(strcmp(argv[1], "--all-coverage")) + )) { + continue; + } + + ev_reg = xasprintf("%s\n%s:", ev_reg, node->name); + ev_reg = xasprintf("%s\n type: %s", ev_reg, rst[type]); + } + } + + ovs_mutex_lock(&event_mutex); + cnt = event_count(); + ovs_mutex_unlock(&event_mutex); + if (!cnt) { + if (!ev_reg) { + unixctl_command_reply(conn, "No event added\n"); + return; + } + unixctl_command_reply(conn, ev_reg); + free(ev_reg); + return; + } + + list = xcalloc(cnt, sizeof(struct event *)); + event_list(list); + + reply = xasprintf("List of events:"); + for (i = 0; i < cnt; i++) { + if (list[i]->def.resource == EV_RESOURCE_COVERAGE) { + lv[1] = list[i]->current; + lv[2] = list[i]->rate_min; + lv[3] = list[i]->rate_hour; + reply = xasprintf("%s\n%s:", reply, list[i]->name); + reply = xasprintf("%s\n resource : coverage", reply); + reply = xasprintf("%s\n current : %llu", reply, + list[i]->current); + reply = xasprintf("%s\n rate_per_min : %u", reply, + list[i]->rate_min); + reply = xasprintf("%s\n rate_per_hour : %u", reply, + list[i]->rate_hour); + reply = xasprintf("%s\n condition : %d %s %llu", reply, + lv[list[i]->def.match], + op[list[i]->def.op], + list[i]->def.value); + reply = xasprintf("%s\n hit count : %lu\n", reply, + list[i]->hit); + } else if (list[i]->def.resource == EV_RESOURCE_TIMER) { + reply = xasprintf("%s\n%s:", reply, list[i]->name); + reply = xasprintf("%s\n resource : timer", reply); + reply = xasprintf("%s\n no_of_samples : %llu", reply, + list[i]->def.samples); + reply = xasprintf("%s\n max duration : %llu (%s)", reply, + list[i]->stats.max, units[list[i]->def.unit]); + reply = xasprintf("%s\n min duration : %llu (%s)",reply, + list[i]->stats.min, units[list[i]->def.unit]); + reply = xasprintf("%s\n 95%% of times : %f (%s)", reply, + list[i]->stats.pctl_95, + units[list[i]->def.unit]); + reply = xasprintf("%s\n hit count : %lu\n", reply, + list[i]->hit); + } else { + reply = xasprintf("%s\n%s: (unknown)", reply, list[i]->name); + } + + } + + if (ev_reg) { + reply = xasprintf("%s\n%s", reply, ev_reg); + free(ev_reg); + } + + unixctl_command_reply(conn, reply); + free(reply); +} + +bool +user_defined_event_enabled(void) +{ + return user_defined_event; +} + +void +event_init(const struct smap *ovs_other_config) +{ + if (smap_get_bool(ovs_other_config, "user_defined_event_enable", false)) { + + static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; + if (ovsthread_once_start(&once)) { + shash_init(&events); + + unixctl_command_register("event/define", "", 1, 1, + event_unixctl_define, NULL); + unixctl_command_register("event/undefine", "", 1, 1, + event_unixctl_undefine, NULL); + unixctl_command_register("event/flush", "", 0, 0, + event_unixctl_flush, NULL); + unixctl_command_register("event/list", + "[--all|-all-coverage|--all-timer]", 0, 1, + event_unixctl_list, NULL); + + event_thread_id = ovs_thread_create("event", event_thread, NULL); + user_defined_event = true; + VLOG_INFO("User defined event support enabled"); + ovsthread_once_done(&once); + } + } else { + VLOG_INFO("User defined event support disbled"); + } +} diff --git a/lib/event.h b/lib/event.h new file mode 100644 index 0000000..592c32f --- /dev/null +++ b/lib/event.h @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2020 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef EVENT_H +#define EVENT_H 1 + +#include "jsonrpc.h" +#include "openvswitch/json.h" +#include "smap.h" +#include "stopwatch.h" +#include "stream.h" + +#define EVENT_MAX 256 +#define EVENT_POLL_INTERVAL 1000 + +typedef enum { + EV_NONE, + EV_CONDITIONAL, + EV_MESSAGE +} event_t; + +typedef enum { + EV_RESOURCE_NONE, + EV_RESOURCE_COVERAGE, + EV_RESOURCE_TIMER +} resource_t; + +typedef enum { + EV_MATCH_NONE, + EV_MATCH_EXACT, + EV_MATCH_RATE_MIN, + EV_MATCH_RATE_HOUR +} match_t; + +typedef enum { + EV_OP_NONE, + EV_OP_EQ, + EV_OP_NE, + EV_OP_GT, + EV_OP_GE, + EV_OP_LT, + EV_OP_LE +} op_t; + +typedef enum { + EV_UNIT_NONE, + EV_UNIT_MS, + EV_UNIT_US +} unit_t; + +#define EV_DEF_COMMON struct {\ + resource_t resource; \ +} + +#define EV_DEF_COND struct { \ + match_t match; \ + op_t op; \ + unsigned long long value;\ +} + +#define EV_DEF_MSG struct { \ + unsigned long long samples;\ + unit_t unit; \ +} + +typedef struct { + EV_DEF_COMMON; + union { + EV_DEF_COND; + EV_DEF_MSG; + }; +} definition_t; + +struct event; + +struct notify { + struct stream *stream; + struct jsonrpc *rpc; + int(*cb)(struct event *ev); +}; + +typedef struct notify notify_t; + +# define EV_RESOURCE struct { \ + unsigned long long current; \ + unsigned int rate_min; \ + unsigned int rate_hour; \ + struct stopwatch_stats stats; \ +} + +struct event { + EV_RESOURCE; + + char *name; + event_t type; + definition_t def; + notify_t notify; + + uint64_t count; + uint64_t hit; + uint64_t hit_prev; +}; + +bool user_defined_event_enabled(void); +void event_init(const struct smap *ovs_other_config); +int event_try_lock(void); +void event_lock(void) OVS_ACQUIRES(event_mutex); +void event_unlock(void) OVS_RELEASES(event_mutex); +void event_register(const char *name, resource_t type); +uint event_count(void) OVS_REQUIRES(event_mutex); +struct event *event_get(const char *name) OVS_REQUIRES(event_mutex); + +typedef enum { + EV_ERR_NONE, + EV_PARSE_OBJ_MISSING, + EV_PARSE_NAME_MISSING, + EV_PARSE_TYPE_MISSING, + EV_PARSE_DEF_MISSING, + EV_PARSE_STREAM_MISSING, + EV_PARSE_EVENT_EXISTS, + EV_PARSE_INVALID_EVENT, + EV_PARSE_INVALID_DEF, + EV_STREAM_OPEN_ERROR +} everr_t; + +#define EVENT_REGISTER(EVENT, TYPE) \ + static bool EVENT##_once = true; \ + if (EVENT##_once) { \ + EVENT##_once = false; \ + event_register(#EVENT, TYPE); \ + } + +#define EVENT_TIMER_START(EVENT) \ + struct event *ev; \ + long long int tsec; \ + event_lock(); \ + ev = event_get(#EVENT); \ + event_unlock(); \ + if (ev != NULL) { \ + if (ev->def.unit == EV_UNIT_US) { \ + tsec = time_usec(); \ + } else { \ + tsec = time_msec(); \ + } \ + stopwatch_start(#EVENT, tsec); \ + } + +#define EVENT_TIMER_STOP(EVENT) \ + if (ev != NULL) { \ + if (ev->def.unit == EV_UNIT_US) { \ + tsec = time_usec(); \ + } else { \ + tsec = time_msec(); \ + } \ + stopwatch_stop(#EVENT, tsec); \ + event_lock(); \ + ev->count++; \ + event_unlock(); \ + } + +#define EVENT_TIMER_START_TRY(EVENT) \ + struct event *ev = NULL; \ + long long int tsec; \ + if (!event_try_lock()) { \ + ev = event_get(#EVENT); \ + event_unlock(); \ + } \ + if (ev != NULL) { \ + if (ev->def.unit == EV_UNIT_US) { \ + tsec = time_usec(); \ + } else { \ + tsec = time_msec(); \ + } \ + stopwatch_start(#EVENT, tsec); \ + } + +#define EVENT_TIMER_STOP_TRY(EVENT) \ + if (!event_try_lock()) { \ + if (ev != NULL) { \ + if (ev->def.unit == EV_UNIT_US) { \ + tsec = time_usec(); \ + } else { \ + tsec = time_msec(); \ + } \ + stopwatch_stop(#EVENT, tsec); \ + ev->count++; \ + } \ + event_unlock(); \ + } + +#define EVENT_FUNC_TIMER(FUNC, ...) \ + if (user_defined_event_enabled()) { \ + EVENT_REGISTER(FUNC, EV_RESOURCE_TIMER);\ + EVENT_TIMER_START(FUNC) \ + FUNC(__VA_ARGS__); \ + EVENT_TIMER_STOP(FUNC) \ + } else { \ + FUNC(__VA_ARGS__); \ + } + +#define EVENT_FUNC_TIMER_TRY(FUNC, ...) \ + if (user_defined_event_enabled()) { \ + EVENT_REGISTER(FUNC, EV_RESOURCE_TIMER);\ + EVENT_TIMER_START_TRY(FUNC) \ + FUNC(__VA_ARGS__); \ + EVENT_TIMER_STOP_TRY(FUNC) \ + } else { \ + FUNC(__VA_ARGS__); \ + } + +#define EVENT_RETFUNC_TIMER(RET, FUNC, ...) \ + if (user_defined_event_enabled()) { \ + EVENT_REGISTER(FUNC, EV_RESOURCE_TIMER);\ + EVENT_TIMER_START(FUNC) \ + RET = FUNC(__VA_ARGS__); \ + EVENT_TIMER_STOP(FUNC) \ + } else { \ + RET = FUNC(__VA_ARGS__); \ + } + +#define EVENT_RETFUNC_TIMER_TRY(RET, FUNC, ...) \ + if (user_defined_event_enabled()) { \ + EVENT_REGISTER(FUNC, EV_RESOURCE_TIMER);\ + EVENT_TIMER_START_TRY(FUNC) \ + RET = FUNC(__VA_ARGS__); \ + EVENT_TIMER_STOP_TRY(FUNC) \ + } else { \ + RET = FUNC(__VA_ARGS__); \ + } + +#define EVENT_COUNTER(NAME, VAR, VALUE) \ + if (user_defined_event_enabled()) { \ + struct event *ev; \ + event_lock(); \ + ev = event_get(#NAME); \ + if (ev != NULL) { \ + ev->VAR = VALUE; \ + } \ + event_unlock(); \ + } + +#define EVENT_COUNTER_TRY(NAME, VAR, VALUE) \ + if (user_defined_event_enabled()) { \ + struct event *ev; \ + const char *name; \ + name = NAME; \ + if (!event_try_lock()) { \ + ev = event_get(name); \ + if (ev != NULL) { \ + ev->VAR = VALUE; \ + } \ + event_unlock(); \ + } \ + } + +#endif /* event.h */ diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index fe73c38..f088ef8 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -29,6 +29,7 @@ #include "dirs.h" #include "dpif.h" #include "dpdk.h" +#include "event.h" #include "hash.h" #include "openvswitch/hmap.h" #include "hmapx.h" @@ -3289,6 +3290,7 @@ bridge_run(void) netdev_set_flow_api_enabled(&cfg->other_config); dpdk_init(&cfg->other_config); userspace_tso_init(&cfg->other_config); + event_init(&cfg->other_config); } /* Initialize the ofproto library. This only needs to run once, but From patchwork Tue Jun 2 10:09:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gowrishankar Muthukrishnan X-Patchwork-Id: 1302311 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.137; helo=fraxinus.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=c5JPMvUc; dkim-atps=neutral Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49bnq33zwpz9sSd for ; Tue, 2 Jun 2020 20:10:23 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 4969C80EAF; Tue, 2 Jun 2020 10:10:21 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id rfGp0qrGX4ra; Tue, 2 Jun 2020 10:10:20 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by fraxinus.osuosl.org (Postfix) with ESMTP id BE92084483; Tue, 2 Jun 2020 10:10:20 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id A5004C0865; Tue, 2 Jun 2020 10:10:20 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 2561AC0865 for ; Tue, 2 Jun 2020 10:10:18 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 0556A86366 for ; Tue, 2 Jun 2020 10:10:18 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id BnM9flJm9IuQ for ; Tue, 2 Jun 2020 10:10:15 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-delivery-1.mimecast.com (us-smtp-2.mimecast.com [207.211.31.81]) by fraxinus.osuosl.org (Postfix) with ESMTPS id 20431862FC for ; Tue, 2 Jun 2020 10:10:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1591092609; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=2F7p9mDHdkR4QMZhAKxrofmae/RMslKMMtHY9pL1jQk=; b=c5JPMvUcDf2BHlzTK6Yl9mrOgeR8WnVhkUzMoVuDCjzOOf1/h9LcrTri3xJoFCw0SKQveL wZ6iOSGc7EH4HD33zAecHZ1WC6x/xJ4kK4hUn992Ii79u9QiqIszX6nUvEmC4JNUEEqArn Fa9vIHONgQG/SzBzIWKwzJugddwan2c= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-109-AA7rd1VhM6-OxeY88cj1Og-1; Tue, 02 Jun 2020 06:10:07 -0400 X-MC-Unique: AA7rd1VhM6-OxeY88cj1Og-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 27DA3100A8E8; Tue, 2 Jun 2020 10:10:06 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-111.sin2.redhat.com [10.67.117.111]) by smtp.corp.redhat.com (Postfix) with ESMTP id C746A5D9DD; Tue, 2 Jun 2020 10:10:00 +0000 (UTC) From: Gowrishankar Muthukrishnan To: dev@openvswitch.org Date: Tue, 2 Jun 2020 15:39:44 +0530 Message-Id: <4649bf8c47b75d7821567a2470dcd9dc20870922.1591091223.git.gmuthukr@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: anju.thomas@ericsson.com, Keshav Gupta , i.maximets@ovn.org Subject: [ovs-dev] [PATCH 2/7] stopwatch: expose required api for event library X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Timer notifications in event library require handling stopwatch across one or more events, so share few required functions. Signed-off-by: Gowrishankar Muthukrishnan --- lib/stopwatch.c | 20 +++++++++++++++++++- lib/stopwatch.h | 9 +++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/stopwatch.c b/lib/stopwatch.c index f560216..0858d72 100644 --- a/lib/stopwatch.c +++ b/lib/stopwatch.c @@ -463,7 +463,7 @@ stopwatch_thread(void *ign OVS_UNUSED) return NULL; } -static void +void stopwatch_exit(void) { struct shash_node *node, *node_next; @@ -526,6 +526,24 @@ stopwatch_create(const char *name, enum stopwatch_units units) } void +stopwatch_delete(const char *name) +{ + ovs_mutex_lock(&stopwatches_lock); + shash_find_and_delete(&stopwatches, name); + ovs_mutex_unlock(&stopwatches_lock); +} + +unsigned int +stopwatch_count(void) +{ + unsigned int n; + ovs_mutex_lock(&stopwatches_lock); + n = shash_count(&stopwatches); + ovs_mutex_unlock(&stopwatches_lock); + return n; +} + +void stopwatch_start(const char *name, unsigned long long ts) { struct stopwatch_packet *pkt = stopwatch_packet_create(OP_START_SAMPLE); diff --git a/lib/stopwatch.h b/lib/stopwatch.h index 91abd64..2f8e56c 100644 --- a/lib/stopwatch.h +++ b/lib/stopwatch.h @@ -56,4 +56,13 @@ bool stopwatch_get_stats(const char *name, struct stopwatch_stats *stats); /* Block until all enqueued samples have been processed. */ void stopwatch_sync(void); +/* Delete stopwatch */ +void stopwatch_delete(const char *name); + +/* Count stopwatches */ +unsigned int stopwatch_count(void); + +/* Exit stopwatch */ +void stopwatch_exit(void); + #endif /* stopwatch.h */ From patchwork Tue Jun 2 10:09:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gowrishankar Muthukrishnan X-Patchwork-Id: 1302312 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.133; helo=hemlock.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=KmA8P1yB; dkim-atps=neutral Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49bnq41qGpz9sSg for ; Tue, 2 Jun 2020 20:10:24 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 74E6B88395; Tue, 2 Jun 2020 10:10:22 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id B0-N700Hugu1; Tue, 2 Jun 2020 10:10:21 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by hemlock.osuosl.org (Postfix) with ESMTP id C1CDB88081; Tue, 2 Jun 2020 10:10:21 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 9CBD3C0894; Tue, 2 Jun 2020 10:10:21 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id AEF2BC0891 for ; Tue, 2 Jun 2020 10:10:20 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 9EA3F83597 for ; Tue, 2 Jun 2020 10:10:20 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id deq4KsdZrZPL for ; Tue, 2 Jun 2020 10:10:20 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) by fraxinus.osuosl.org (Postfix) with ESMTPS id 99A7E80EAF for ; Tue, 2 Jun 2020 10:10:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1591092618; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=b30RpdBOBv1ezahe2zci1Eouq+SnKWDBSFYVhlkvOP4=; b=KmA8P1yBCZLq7yueuJc7M8mRdFtB3QMKlC8rETuMmz//UkqiKFXMOVGnBkD+d53yoZUMXt 5uOuohWNmJDW8U+Qg3EfbCgRSkJpxsnOLce0/UIy+nXuoc4AV/NjhFHOBA4L7lEDqnWCwK zqk0Uj/hg4HXK+S1gSpXPO7ktFpdL6M= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-101-PC7FhSazOAiB8k12rdWBYw-1; Tue, 02 Jun 2020 06:10:15 -0400 X-MC-Unique: PC7FhSazOAiB8k12rdWBYw-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id B68AB835B40; Tue, 2 Jun 2020 10:10:13 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-111.sin2.redhat.com [10.67.117.111]) by smtp.corp.redhat.com (Postfix) with ESMTP id B7D4F5D9EF; Tue, 2 Jun 2020 10:10:06 +0000 (UTC) From: Gowrishankar Muthukrishnan To: dev@openvswitch.org Date: Tue, 2 Jun 2020 15:39:45 +0530 Message-Id: <7a0c5bc220e04ab7e8de6450747afb5db20f0183.1591091223.git.gmuthukr@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: anju.thomas@ericsson.com, Keshav Gupta , i.maximets@ovn.org Subject: [ovs-dev] [PATCH 3/7] dpif: hook timer event api in datapath functions X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" This patch injects timing some important functions as listed below in datapath. This can be expanded but the list is short for now. Signed-off-by: Gowrishankar Muthukrishnan --- lib/dpif-netdev.c | 5 ++++- lib/netdev-dpdk.c | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 51c8885..4db07c4 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -4297,7 +4298,9 @@ dp_netdev_pmd_flush_output_on_port(struct dp_netdev_pmd_thread *pmd, output_cnt = dp_packet_batch_size(&p->output_pkts); ovs_assert(output_cnt > 0); - netdev_send(p->port->netdev, tx_qid, &p->output_pkts, dynamic_txqs); + EVENT_FUNC_TIMER_TRY(netdev_send, + p->port->netdev, + tx_qid, &p->output_pkts, dynamic_txqs); dp_packet_batch_init(&p->output_pkts); /* Update time of the next flush. */ diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c index 44ebf96..3493b05 100644 --- a/lib/netdev-dpdk.c +++ b/lib/netdev-dpdk.c @@ -17,6 +17,7 @@ #include #include "netdev-dpdk.h" +#include #include #include #include @@ -2605,6 +2606,8 @@ __netdev_dpdk_vhost_send(struct netdev *netdev, int qid, unsigned int tx_pkts; tx_pkts = rte_vhost_enqueue_burst(vid, vhost_qid, cur_pkts, cnt); + EVENT_RETFUNC_TIMER_TRY(tx_pkts, rte_vhost_enqueue_burst, + vid, vhost_qid, cur_pkts, cnt); if (OVS_LIKELY(tx_pkts)) { /* Packets have been sent.*/ cnt -= tx_pkts; From patchwork Tue Jun 2 10:09:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gowrishankar Muthukrishnan X-Patchwork-Id: 1302317 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=whitealder.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=hOi7c/1h; dkim-atps=neutral Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49bnqH1d1bz9sSg for ; Tue, 2 Jun 2020 20:10:35 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 8005187842; Tue, 2 Jun 2020 10:10:33 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id elFajooYNSSB; Tue, 2 Jun 2020 10:10:28 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id 7308687863; Tue, 2 Jun 2020 10:10:26 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 564CFC0891; Tue, 2 Jun 2020 10:10:26 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 2F372C016E for ; Tue, 2 Jun 2020 10:10:25 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 1EBE584FFF for ; Tue, 2 Jun 2020 10:10:25 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id m4lSiD5bPe0y for ; Tue, 2 Jun 2020 10:10:24 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) by fraxinus.osuosl.org (Postfix) with ESMTPS id E272186381 for ; Tue, 2 Jun 2020 10:10:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1591092622; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=GyUv0wVwAFR6O17Wc5LmSixJ7s/hj1rbygpRhJCI4TY=; b=hOi7c/1hp4IWOlGpyOPm+uM0zrVe3OspafPjN1B0WpBhfsSqjtdbghSWQJklXAaBsU1x1Q 9AaMvdJgEGHKUDXjAmd+q1kq9MpQMkos/Azk7m0JNnXI4PiuGKyAkfvCyZYw4WV+W7RYjF EqkuPUTjqd03dWpNO40SGmM4O4EtKdA= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-33-zMI8frtFNxGvZrr0hfV0FA-1; Tue, 02 Jun 2020 06:10:21 -0400 X-MC-Unique: zMI8frtFNxGvZrr0hfV0FA-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id F0AA0108BD10; Tue, 2 Jun 2020 10:10:19 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-111.sin2.redhat.com [10.67.117.111]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8585F5D9DD; Tue, 2 Jun 2020 10:10:14 +0000 (UTC) From: Gowrishankar Muthukrishnan To: dev@openvswitch.org Date: Tue, 2 Jun 2020 15:39:46 +0530 Message-Id: <093573848c90e242707e7dfe7474f278f786df50.1591091223.git.gmuthukr@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: anju.thomas@ericsson.com, Keshav Gupta , i.maximets@ovn.org Subject: [ovs-dev] [PATCH 4/7] coverage: support conditional notification from events X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" This patch enables monitoring coverage counters through event API. Signed-off-by: Gowrishankar Muthukrishnan --- lib/coverage.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/coverage.h | 4 ++++ lib/timeval.c | 3 +++ 3 files changed, 68 insertions(+) diff --git a/lib/coverage.c b/lib/coverage.c index a95b6aa..f4c872e 100644 --- a/lib/coverage.c +++ b/lib/coverage.c @@ -25,6 +25,7 @@ #include "unixctl.h" #include "util.h" #include "openvswitch/vlog.h" +#include "event.h" VLOG_DEFINE_THIS_MODULE(coverage); @@ -36,6 +37,7 @@ static size_t allocated_coverage_counters = 0; static struct ovs_mutex coverage_mutex = OVS_MUTEX_INITIALIZER; DEFINE_STATIC_PER_THREAD_DATA(long long int, coverage_clear_time, LLONG_MIN); +DEFINE_STATIC_PER_THREAD_DATA(long long int, coverage_event_time, LLONG_MIN); static long long int coverage_run_time = LLONG_MIN; /* Index counter used to compute the moving average array's index. */ @@ -51,6 +53,7 @@ static bool coverage_read_counter(const char *name, void coverage_counter_register(struct coverage_counter* counter) { + event_register(counter->name, EV_RESOURCE_COVERAGE); if (n_coverage_counters >= allocated_coverage_counters) { coverage_counters = x2nrealloc(coverage_counters, &allocated_coverage_counters, @@ -414,3 +417,61 @@ coverage_read_counter(const char *name, unsigned long long int *count) return false; } + +static void +coverage_event__(bool trylock) +{ + long long int now, *thread_time; + + now = time_msec(); + thread_time = coverage_event_time_get(); + + /* Initialize the coverage_event_time. */ + if (*thread_time == LLONG_MIN) { + *thread_time = now + COVERAGE_EVENT_INTERVAL; + } + + if (now >= *thread_time) { + size_t i; + + if (trylock) { + /* Returns if cannot acquire lock. */ + if (event_try_lock()) { + return; + } + if (ovs_mutex_trylock(&coverage_mutex)) { + event_unlock(); + return; + } + } else { + event_lock(); + ovs_mutex_lock(&coverage_mutex); + } + + for (i = 0; i < n_coverage_counters && event_count(); i++) { + struct coverage_counter *c = coverage_counters[i]; + struct event *ev; + + ev = event_get(c->name); + if (!ev || ev->def.resource != EV_RESOURCE_COVERAGE) { + continue; + } + + ev->current = c->total; + ovs_mutex_unlock(&coverage_mutex); + ev->rate_min = coverage_array_sum(c->min, MIN_AVG_LEN) / 60.0; + ev->rate_hour = coverage_array_sum(c->hr, HR_AVG_LEN) / 3600.0; + ovs_mutex_lock(&coverage_mutex); + } + + ovs_mutex_unlock(&coverage_mutex); + event_unlock(); + *thread_time = now + COVERAGE_EVENT_INTERVAL; + } +} + +void +coverage_try_event(void) +{ + coverage_event__(true); +} diff --git a/lib/coverage.h b/lib/coverage.h index dea990e..4cdf956 100644 --- a/lib/coverage.h +++ b/lib/coverage.h @@ -39,6 +39,9 @@ BUILD_ASSERT_DECL(60000 % COVERAGE_RUN_INTERVAL == 0); #define COVERAGE_CLEAR_INTERVAL 1000 BUILD_ASSERT_DECL(COVERAGE_RUN_INTERVAL % COVERAGE_CLEAR_INTERVAL == 0); +#define COVERAGE_EVENT_INTERVAL 1000 +BUILD_ASSERT_DECL(60000 % COVERAGE_EVENT_INTERVAL == 0); + /* Defines the moving average array length. */ #define MIN_AVG_LEN (60000/COVERAGE_RUN_INTERVAL) #define HR_AVG_LEN 60 @@ -90,5 +93,6 @@ void coverage_log(void); void coverage_clear(void); void coverage_try_clear(void); void coverage_run(void); +void coverage_try_event(void); #endif /* coverage.h */ diff --git a/lib/timeval.c b/lib/timeval.c index 193c7ba..3e3d86f 100644 --- a/lib/timeval.c +++ b/lib/timeval.c @@ -35,6 +35,7 @@ #include "ovs-thread.h" #include "signals.h" #include "seq.h" +#include "stopwatch.h" #include "unixctl.h" #include "util.h" #include "openvswitch/vlog.h" @@ -294,6 +295,8 @@ time_poll(struct pollfd *pollfds, int n_pollfds, HANDLE *handles OVS_UNUSED, time_init(); coverage_clear(); coverage_run(); + coverage_try_event(); + if (*last_wakeup && !thread_is_pmd()) { log_poll_interval(*last_wakeup); } From patchwork Tue Jun 2 10:09:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gowrishankar Muthukrishnan X-Patchwork-Id: 1302323 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.136; helo=silver.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=h1KKsfLe; dkim-atps=neutral Received: from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49bnrh2rHTz9sSd for ; Tue, 2 Jun 2020 20:11:48 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 85B3E20421; Tue, 2 Jun 2020 10:11:46 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from silver.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id KDfX42QFwoFS; Tue, 2 Jun 2020 10:11:40 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by silver.osuosl.org (Postfix) with ESMTP id 74CB8226EA; Tue, 2 Jun 2020 10:10:51 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 567ECC0865; Tue, 2 Jun 2020 10:10:51 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 48EF6C016E for ; Tue, 2 Jun 2020 10:10:49 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 289B022699 for ; Tue, 2 Jun 2020 10:10:49 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from silver.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id O5cLSLSOhB+r for ; Tue, 2 Jun 2020 10:10:38 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-delivery-1.mimecast.com (us-smtp-1.mimecast.com [207.211.31.81]) by silver.osuosl.org (Postfix) with ESMTPS id 637EA22703 for ; Tue, 2 Jun 2020 10:10:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1591092626; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=dUWHZIvUk3lzCumXQF+jOZIUCB0Uthn9kUL/H1uPhN8=; b=h1KKsfLeJUDbdnFnAjbUdmMnrwtEuBwLPG6JVNiH++JiZaPu1yQRym6j/P2diioDb1Zya1 jK6ekCwqa8uw4FGUkmbbPZPDJf8DeawNs7PdboZ1Ln8X8BX3d4NFZD+Et3JMylIolY6/Eg lbBJd2yGeQlOuJTSvXwdwoz8SG7MLG4= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-173-_U7VNvsuNCefd88BG1CusQ-1; Tue, 02 Jun 2020 06:10:24 -0400 X-MC-Unique: _U7VNvsuNCefd88BG1CusQ-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 8AC3C845F29; Tue, 2 Jun 2020 10:10:23 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-111.sin2.redhat.com [10.67.117.111]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8CD3B5D9DD; Tue, 2 Jun 2020 10:10:20 +0000 (UTC) From: Gowrishankar Muthukrishnan To: dev@openvswitch.org Date: Tue, 2 Jun 2020 15:39:47 +0530 Message-Id: <7c6a6e4df394d34eb0962f5099f2f5bb568834e1.1591091223.git.gmuthukr@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: anju.thomas@ericsson.com, Keshav Gupta , i.maximets@ovn.org Subject: [ovs-dev] [PATCH 5/7] event: test daemon to receive notification from event api X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" This is sample tiny daemon which receives event notification from the registered events and displays the message info in the terminal. Signed-off-by: Gowrishankar Muthukrishnan --- utilities/automake.mk | 6 +- utilities/ovs-testeventd.c | 156 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 utilities/ovs-testeventd.c diff --git a/utilities/automake.mk b/utilities/automake.mk index e2e22c3..0d6a648 100644 --- a/utilities/automake.mk +++ b/utilities/automake.mk @@ -3,7 +3,8 @@ bin_PROGRAMS += \ utilities/ovs-testcontroller \ utilities/ovs-dpctl \ utilities/ovs-ofctl \ - utilities/ovs-vsctl + utilities/ovs-vsctl \ + utilities/ovs-testeventd bin_SCRIPTS += utilities/ovs-docker \ utilities/ovs-pki \ utilities/ovs-pcap \ @@ -118,6 +119,9 @@ utilities_ovs_ofctl_LDADD = \ utilities_ovs_vsctl_SOURCES = utilities/ovs-vsctl.c utilities_ovs_vsctl_LDADD = lib/libopenvswitch.la +utilities_ovs_testeventd_SOURCES = utilities/ovs-testeventd.c +utilities_ovs_testeventd_LDADD = lib/libopenvswitch.la + if LINUX noinst_PROGRAMS += utilities/nlmon utilities_nlmon_SOURCES = utilities/nlmon.c diff --git a/utilities/ovs-testeventd.c b/utilities/ovs-testeventd.c new file mode 100644 index 0000000..6d97e37 --- /dev/null +++ b/utilities/ovs-testeventd.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2020 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "stream.h" +#include "jsonrpc.h" +#include "openvswitch/json.h" +#include "openvswitch/poll-loop.h" +#include "util.h" + +static int +handle_rpc(struct jsonrpc *rpc, struct jsonrpc_msg *msg, bool *done) +{ + if (msg->type == JSONRPC_REQUEST) { + struct jsonrpc_msg *reply = NULL; + + if (!strcmp(msg->method, "echo")) { + reply = jsonrpc_create_reply(json_clone(msg->params), msg->id); + } else if (!strcmp(msg->method, "ovs_event")) { + char *params_s = json_to_string(msg->params, 0); + char *id_s = json_to_string(msg->id, 0); + printf("received msg %s(%s), id=%s\n", + msg->method, params_s, id_s); + + struct json *object = json_object_create(); + json_object_put_string(object, "status", "ok"); + reply = jsonrpc_create_reply(object, msg->id); + free(params_s); + free(id_s); + } else { + struct json *error = json_object_create(); + json_object_put_string(error, "error", "unknown method"); + reply = jsonrpc_create_error(error, msg->id); + ovs_error(0, "unknown msg %s", msg->method); + } + + jsonrpc_send(rpc, reply); + return 0; + } else if (msg->type == JSONRPC_NOTIFY) { + if (!strcmp(msg->method, "shutdown")) { + *done = true; + return 0; + } else { + ovs_error(0, "unknown notification %s", msg->method); + return ENOTTY; + } + } else { + ovs_error(0, "unsolicited JSON-RPC reply or error"); + return EPROTO; + } +} + +int main(int argc, char *argv[]) +{ + char *path; + struct pstream *listen; + struct jsonrpc **rpcs; + size_t n_rpcs, allocated_rpcs; + int error; + bool done; + + if (argc != 2) { + printf("USAGE: %s socket_file_to_create\n", argv[0]); + return -1; + } + + path = xasprintf("punix:%s", argv[1]); + error = jsonrpc_pstream_open(path, &listen, 0); + free(path); + + if (error) { + printf("unable to open listening socket"); + return -1; + } + + rpcs = NULL; + done = false; + n_rpcs = allocated_rpcs = 0; + for (;;) { + struct stream *stream; + size_t i; + + error = pstream_accept(listen, &stream); + if (!error) { + if (n_rpcs >= allocated_rpcs) { + rpcs = x2nrealloc(rpcs, &allocated_rpcs, sizeof *rpcs); + } + rpcs[n_rpcs++] = jsonrpc_open(stream); + } else if (error != EAGAIN) { + printf("pstream_accept failed"); + } + + for (i = 0; i < n_rpcs;) { + struct jsonrpc *rpc = rpcs[i]; + struct jsonrpc_msg *msg; + + jsonrpc_run(rpc); + if (!jsonrpc_get_backlog(rpc)) { + error = jsonrpc_recv(rpc, &msg); + if (!error) { + error = handle_rpc(rpc, msg, &done); + jsonrpc_msg_destroy(msg); + } else if (error == EAGAIN) { + error = 0; + } + } + + if (!error) { + error = jsonrpc_get_status(rpc); + } + if (error) { + jsonrpc_close(rpc); + ovs_error(error, "connection closed"); + memmove(&rpcs[i], &rpcs[i + 1], + (n_rpcs - i - 1) * sizeof *rpcs); + n_rpcs--; + } else { + i++; + } + } + + /* Wait for something to do. */ + if (done && !n_rpcs) { + break; + } + pstream_wait(listen); + for (i = 0; i < n_rpcs; i++) { + struct jsonrpc *rpc = rpcs[i]; + + jsonrpc_wait(rpc); + if (!jsonrpc_get_backlog(rpc)) { + jsonrpc_recv_wait(rpc); + } + } + poll_block(); + } + free(rpcs); + pstream_close(listen); + return 0; +} From patchwork Tue Jun 2 10:09:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gowrishankar Muthukrishnan X-Patchwork-Id: 1302322 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.137; helo=fraxinus.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=f08RTTMp; dkim-atps=neutral Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49bnr40VL4z9sSg for ; Tue, 2 Jun 2020 20:11:16 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 98BEE863E3; Tue, 2 Jun 2020 10:11:14 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id QMP-xeDlBFzh; Tue, 2 Jun 2020 10:11:12 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by fraxinus.osuosl.org (Postfix) with ESMTP id 91C0686449; Tue, 2 Jun 2020 10:11:10 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 79726C0893; Tue, 2 Jun 2020 10:11:10 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0918CC016E for ; Tue, 2 Jun 2020 10:11:09 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id F02AA22854 for ; Tue, 2 Jun 2020 10:11:08 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from silver.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id SJsqkCFaM3Nl for ; Tue, 2 Jun 2020 10:10:57 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) by silver.osuosl.org (Postfix) with ESMTPS id 9CC282265B for ; Tue, 2 Jun 2020 10:10:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1591092631; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=++fU+zu+BlEYz78qNBK2fL+mWi51DXscfvaiqYG9XJY=; b=f08RTTMp86VOVXJ2vbgVjMv87paZxNgQFvtzzRRAn9zLsqEnEr0lheL5+26cE/UPHy0RXd 2VaBYyGHrquB99JPAbYCztskMbElqddYj7Sf8pCAYAz/Chz+m8AdhAimMhvsUZmnt8ZrV3 wUDnzj/pgARLPzgU0Q2/7wW0g2ppfvI= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-397-jX0NEgLJNreOmIdJIqgAuw-1; Tue, 02 Jun 2020 06:10:30 -0400 X-MC-Unique: jX0NEgLJNreOmIdJIqgAuw-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id DB5D2872FEC; Tue, 2 Jun 2020 10:10:28 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-111.sin2.redhat.com [10.67.117.111]) by smtp.corp.redhat.com (Postfix) with ESMTP id 176995D9DD; Tue, 2 Jun 2020 10:10:23 +0000 (UTC) From: Gowrishankar Muthukrishnan To: dev@openvswitch.org Date: Tue, 2 Jun 2020 15:39:48 +0530 Message-Id: <31894ba9b1b5484e59ff79d6c755a9cfb675d410.1591091223.git.gmuthukr@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: anju.thomas@ericsson.com, Keshav Gupta , i.maximets@ovn.org Subject: [ovs-dev] [PATCH 6/7] event: documentation notes on event library X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Documentation notes on event library and its usage is included in this patch. Signed-off-by: Gowrishankar Muthukrishnan --- Documentation/automake.mk | 1 + Documentation/topics/index.rst | 1 + Documentation/topics/user-defined-events.rst | 306 +++++++++++++++++++++++++++ 3 files changed, 308 insertions(+) create mode 100644 Documentation/topics/user-defined-events.rst diff --git a/Documentation/automake.mk b/Documentation/automake.mk index f85c432..6dafa58 100644 --- a/Documentation/automake.mk +++ b/Documentation/automake.mk @@ -55,6 +55,7 @@ DOC_SOURCE = \ Documentation/topics/ovsdb-replication.rst \ Documentation/topics/porting.rst \ Documentation/topics/tracing.rst \ + Documentation/topics/user-defined-events.rst \ Documentation/topics/userspace-tso.rst \ Documentation/topics/windows.rst \ Documentation/howto/index.rst \ diff --git a/Documentation/topics/index.rst b/Documentation/topics/index.rst index 08af3a2..9f53aed 100644 --- a/Documentation/topics/index.rst +++ b/Documentation/topics/index.rst @@ -53,3 +53,4 @@ OVS userspace-tso idl-compound-indexes ovs-extensions + user-defined-events diff --git a/Documentation/topics/user-defined-events.rst b/Documentation/topics/user-defined-events.rst new file mode 100644 index 0000000..0c283c2 --- /dev/null +++ b/Documentation/topics/user-defined-events.rst @@ -0,0 +1,306 @@ +.. + Copyright 2020, Red Hat, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); you may + not use this file except in compliance with the License. You may obtain + a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + License for the specific language governing permissions and limitations + under the License. + + Convention for heading levels in Open vSwitch documentation: + + ======= Heading 0 (reserved for the title in a document) + ------- Heading 1 + ~~~~~~~ Heading 2 + +++++++ Heading 3 + ''''''' Heading 4 + + Avoid deeper levels because they do not render well. + +=================================== +User defined events and notification +==================================== + +**Note:** This feature is considered experimental. + + +Events are objects or messages that are used to notify other software +components for a state change. In openvswitch, multiple resources that +are involved in processing packets, undergo various state changes. +Many of these resources are monitored internally by Openvswitch in +various statistical counters for an instance like coverage counters, +perf metric counters etc. When there is poor performance in network I/O +through openvswitch or even to check if any of the resources is not +healthy, sometimes the communication exchange between system operator +and developer is lengthy in terms of: + + - having to rely on CLI but the information sometimes is too much + to connect hotspot dots. + - Debugging tools like gdb is more developer friendly and can not + be used when live traffic is performance oriented. + - Perf like tracing tool can help finding top consumers on system + resources but it is from a system point of view. + +Hence, troubleshooting negotiations kick off between support and engineering +teams by means of various patches and collated logs and processes can +sometimes become tedious. Finally, we lose opportunity to quickly confirm +the root cause for an issue. + +Event library in Openvswitch is to rescue system operator from this +data pollution and provide an abstract view on existing resources +useful for troubleshooting. Here are the advantages in using event +library enable CLI for troubleshooting. + + - Less intrusiveness in enabling event API in runtime across + available resources. + - Operator could engage monitoring application for receiving + event notifications asynchronously. + - It abstracts the way the processing resources could be + diagnosed using readable definition file and it is the input + to populate various events. + - Developer can apply its API in other Openvswitch components to + create useful events for their troubleshooting. For an example, + timer API can be used to measure time taken by one or more + problematic functions. + +Event library is an independent library within Openvswitch which provides +an abstract view of occurrence of an event in the data and control path +to the system operator, in a very less intrusive and asynchronous way. +Event creation and handling is implemented as shown in below figure. + +:: + + +--------------+ + | ovs-appctl | + | event/* | + +------+-------+ + | + [2] | + +--------------------------V---------------------------+ + | | + | +---------------+ | + | | datapath | | + | OVS | resources | | + | daemon +-------|-------+ | + | | resource | + | [3] | updates | + | evaluate | | + | definition ********V******** | + | +------------->* event_FOO * | + | | ***************** | + | event_init() | | + | | | | + | | | | + +---------|--------|-----------------------------------+ + | | + [1] | | [4] + | | + +----V--------|---+ +---------------------+ + | event * |----^--->| user monitor app | + | thread | | | (ovs-testeventd) | + +-----------------+ | +---------------------+ + | + [5] | + event notification + (JSON RPC) + +Event thread +------------ +Event thread is created during the bring up of ovs-vswitchd. Required +resources for the event API is initialized (as [1] in fig) and thread +will enter infinite loop to handle any event which will be registered +by the user. This thread takes care of handling the event definition +for an instance, in case of conditional event to evaluate whether the +event resource value has satisfied the condition defined about it. +If there is notification channel registered (JSONRPC socket) for that +event, then this thread will send corresponding information about the +handled event. If there is no notification channel requested, event is +assumed not handled and further handling will be stopped. + +Event CLI +--------- +Event CLI provisions creation and injection of events inside Openvswitch +through ovs-appctl utility (as [2] in fig). Following commands are +available to the user. + + ovs-appctl event/define + CLI used to create events. + + ovs-appctl event/undefine + CLI used to destroy event. + + ovs-appctl event/flush + CLI used to destroy all events registered in one go. + + ovs-appctl event/list + CLI used to list all registered events and their current status. + +Event types +----------- +Depending the purpose of creating the events, they can be classified into +below supported types. + + - Conditional events + - Message events + +Conditional events +~~~~~~~~~~~~~~~~~ +Conditional events are asynchronous events when there is some condition +associated with the resources under monitoring is satisfied. User defines +what the condition for the event is. Until the condition of state change +is evaluated to true, the event is muted. + +An example definition could be as below. + +:: + { + “name�: “� + “type�: “conditional� + "definition�: { + “resource�: “�, + “match": “per_min�, + “op�: “gt�, + “value�: 200 + } + } + +Message events +~~~~~~~~~~~~~ +Message events are workflow events which are notified to the user +when it is processed in the workflow, where it is injected. As long as +the event is registered in the workflow, processing of that event is +handled by the event library. + +An example definition could be as below. + +:: + { + “name�: “� + “type�: “message� + “definition�: { + “resource�: “� + } + } + +Event resources +--------------- +Any event functions on basis of some input from the resource that it +monitors. So, Event API supports below resources in the datapath for +events to associate with (as [3] in fig). + +coverage counters +function timers + +Coverage counters +~~~~~~~~~~~~~~~~ +Coverage library provisions API to create a counter at some place in +packet flow where that portion of code could be examined for how many +times getting executed and at what rates (in the past 1 min and 1 hour). + +Event API enables conditional events creation and notification from these +counters. + +Example event definition: + +:: + { + “name�: "poll_create_node�, + “type�: "conditional�, + “definition�: { + “resource�: “coverage_counter�, + “match�: “exact�, + “op�: “gt�, + “value�: 10 + }, + “notify�: “/tmp/event.sock� + } + +Timer +~~~~~ +Lots of functions involved in moving packets from one port to the other +and every function has its own instructions. It is useful to find hot +spots through timing functions that are important and critical in packet +processing eg datapath functions for rx/tx, flow lookup and upcall +functions etc. + +Event API enables timing a target function using stopwatch library and +informs the time taken by it as a message events every time the function +is called. + +Example event definition: + +:: + { + “name�: “netdev_send�, + “type�: “message�, + “definition�: { + “resource�: “timer�, + “samples�: 50, + “unit�: “ns� + }, + “notify�: “/tmp/event.sock� + } + +Event definitions +----------------- +Event API recognizes event definitions in JSON format data. Based on +the type of the event and resource that it is associated with, JSON +descriptions will vary. + ++-------------+------------+--------------------------------------------------+ +| **Type** | **Key** | **Description** | ++-------------+------------+--------------------------------------------------+ +| Common | name | Name of the event (in STRING). | +| +------------+--------------------------------------------------+ +| | type | One of the below types (in STRING). | +| | | - conditional | +| | | - message | +| +------------+--------------------------------------------------+ +| | notify | Name of JSON RPC socket (in STRING). | +| +------------+--------------------------------------------------+ +| | definition | Detail on the type (as OBJECT) | ++-------------+------------+--------------------------------------------------+ +| Conditional | resource | One the resources to associate with (as STRING). | +| definition | | - coverage_counter | +| +------------+--------------------------------------------------+ +| | match | One of the types of resource value to evaluate | +| | | (in STRING). | +| | | - exact | +| | | - rate_min | +| | | - rate_hour | +| +------------+--------------------------------------------------+ +| | op | One of the types of operation in evaluation | +| | | (in STRING). | +| | | - eq | +| | | - ne | +| | | - gt | +| | | - ge | +| | | - lt | +| | | - le | +| +------------+--------------------------------------------------+ +| | value | Value to be checked (in INTEGER) | ++-------------+------------+--------------------------------------------------+ +| Message | resource | One the resources to associate with (as STRING). | +| definition | | - timer | +| +------------+--------------------------------------------------+ +| | samples | Number of samples be processed before handling | +| | | message event (in INTEGER). | +| +------------+--------------------------------------------------| +| | unit | Unit of resource value (in STRING). | +| | | All applicable strings. | +| | | - ms | +| | | - us | ++-------------+------------+--------------------------------------------------+ + +Step to enable event API: +------------------------- +:: + ovs-vsctl --no-wait set Open_vSwitch . + other_config:user_defined_event_enable=true + From patchwork Tue Jun 2 10:09:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gowrishankar Muthukrishnan X-Patchwork-Id: 1302321 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=whitealder.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=SxzguZGJ; dkim-atps=neutral Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49bnr34PTBz9sSd for ; Tue, 2 Jun 2020 20:11:15 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 088BB87852; Tue, 2 Jun 2020 10:11:14 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id edMdgO13yJI0; Tue, 2 Jun 2020 10:11:02 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id 8DA2987804; Tue, 2 Jun 2020 10:10:56 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 73956C0865; Tue, 2 Jun 2020 10:10:56 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 115D1C0865 for ; Tue, 2 Jun 2020 10:10:55 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id F03EE86463 for ; Tue, 2 Jun 2020 10:10:54 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 96tXis-6w27I for ; Tue, 2 Jun 2020 10:10:52 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-delivery-1.mimecast.com (us-smtp-1.mimecast.com [205.139.110.61]) by fraxinus.osuosl.org (Postfix) with ESMTPS id C1AFE862E4 for ; Tue, 2 Jun 2020 10:10:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1591092650; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=b3fDoCPvpkysxdMYxG2v+MsJ/anYV9jSxxHK5TvJo5o=; b=SxzguZGJyv9J30laPTTQ8/tdty4JhmQVYPSUwos7jZzv4EE89Nc1/r/enbNRBcqyZDhR1P jLSNnZ4P346sAUWX2u4RSk10aqVTkeRDRKnf4ygsScdWMOh2vHIb5P7ZXj5cOUrXsCjeq2 1QsbPwA+vOQAPumMtGHhQh6XbAMttDA= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-426-c6rsM6tjNLSw2Yp6iW8Bqg-1; Tue, 02 Jun 2020 06:10:33 -0400 X-MC-Unique: c6rsM6tjNLSw2Yp6iW8Bqg-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 417CE1883637; Tue, 2 Jun 2020 10:10:32 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-111.sin2.redhat.com [10.67.117.111]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8E7725D9DD; Tue, 2 Jun 2020 10:10:29 +0000 (UTC) From: Gowrishankar Muthukrishnan To: dev@openvswitch.org Date: Tue, 2 Jun 2020 15:39:49 +0530 Message-Id: <2565e390c582380dd66cf24d68ced20f3dc05f7d.1591091223.git.gmuthukr@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: anju.thomas@ericsson.com, Keshav Gupta , i.maximets@ovn.org Subject: [ovs-dev] [PATCH 7/7] system-event: add event testsuite X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Add iperf3 performance testsuite for checking events. Signed-off-by: Gowrishankar Muthukrishnan --- This is not complete test suite as I would like to get first set of feedbacks on implementation and write unit tests accordingly. This test is to check if event API works expectedly while running some traffic profile. Run ovs-testeventd before test (though not mandatory if "notify:" is removed in json file as test generates). $ sudo sh -c "while true;do ./utilities/ovs-testeventd /tmp/event.sock;done" $ sudo -E PATH=$DPDK_BUILD/app:$PATH make check-event $ for i in `seq 1 4`;do echo test $i; pushd tests/system-event-testsuite.dir/$i > /dev/null; grep 'sender' -A1 -B1 system-event-testsuite.log; cat event_list;popd > /dev/null; done Sample results from my VM (not server :) ): test 1 [ ID] Interval Transfer Bandwidth Retr [ 4] 0.00-10.00 sec 296 MBytes 249 Mbits/sec 837 sender [ 4] 0.00-10.00 sec 294 MBytes 246 Mbits/sec receiver List of events: netdev_send: resource : timer no_of_samples : 50 max duration : 349 (us) min duration : 3 (us) 95% of times : 169.623093 (us) hit count : 10 rte_vhost_enqueue_burst: resource : timer no_of_samples : 50 max duration : 43 (us) min duration : 1 (us) 95% of times : 3.891219 (us) hit count : 10 List of events not yet added: test 2 [ ID] Interval Transfer Bandwidth Retr [ 4] 0.00-10.01 sec 267 MBytes 224 Mbits/sec 31 sender [ 4] 0.00-10.01 sec 266 MBytes 223 Mbits/sec receiver List of events: netdev_send: resource : timer no_of_samples : 50 max duration : 283 (us) min duration : 2 (us) 95% of times : 150.735806 (us) hit count : 10 rte_vhost_enqueue_burst: resource : timer no_of_samples : 50 max duration : 7 (us) min duration : 1 (us) 95% of times : 3.955793 (us) hit count : 10 List of events not yet added: test 3 [ ID] Interval Transfer Bandwidth Retr [ 4] 0.00-10.00 sec 326 MBytes 273 Mbits/sec 599 sender [ 4] 0.00-10.00 sec 323 MBytes 270 Mbits/sec receiver List of events: netdev_send: resource : timer no_of_samples : 50 max duration : 278 (us) min duration : 6 (us) 95% of times : 179.230316 (us) hit count : 10 rte_vhost_enqueue_burst: resource : timer no_of_samples : 50 max duration : 39 (us) min duration : 1 (us) 95% of times : 4.549241 (us) hit count : 10 List of events not yet added: test 4 [ ID] Interval Transfer Bandwidth Retr [ 4] 0.00-10.01 sec 257 MBytes 216 Mbits/sec 75 sender [ 4] 0.00-10.01 sec 256 MBytes 214 Mbits/sec receiver List of events: netdev_send: resource : timer no_of_samples : 50 max duration : 428 (us) min duration : 4 (us) 95% of times : 129.270144 (us) hit count : 11 rte_vhost_enqueue_burst: resource : timer no_of_samples : 50 max duration : 12 (us) min duration : 1 (us) 95% of times : 3.113697 (us) hit count : 11 List of events not yet added: --- tests/automake.mk | 18 +++ tests/system-event.at | 351 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 369 insertions(+) create mode 100644 tests/system-event.at diff --git a/tests/automake.mk b/tests/automake.mk index cbba5b1..ea8f318 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -8,6 +8,7 @@ EXTRA_DIST += \ $(SYSTEM_AFXDP_TESTSUITE_AT) \ $(SYSTEM_OFFLOADS_TESTSUITE_AT) \ $(SYSTEM_DPDK_TESTSUITE_AT) \ + $(SYSTEM_EVENT_TESTSUITE_AT) \ $(OVSDB_CLUSTER_TESTSUITE_AT) \ $(TESTSUITE) \ $(SYSTEM_KMOD_TESTSUITE) \ @@ -16,6 +17,7 @@ EXTRA_DIST += \ $(SYSTEM_AFXDP_TESTSUITE) \ $(SYSTEM_OFFLOADS_TESTSUITE) \ $(SYSTEM_DPDK_TESTSUITE) \ + $(SYSTEM_EVENT_TESTSUITE) \ $(OVSDB_CLUSTER_TESTSUITE) \ tests/atlocal.in \ $(srcdir)/package.m4 \ @@ -184,6 +186,12 @@ SYSTEM_DPDK_TESTSUITE_AT = \ tests/system-dpdk-testsuite.at \ tests/system-dpdk.at +SYSTEM_EVENT_TESTSUITE_AT = \ + tests/system-common-macros.at \ + tests/system-dpdk-macros.at \ + tests/system-dpdk-testsuite.at \ + tests/system-event.at + check_SCRIPTS += tests/atlocal TESTSUITE = $(srcdir)/tests/testsuite @@ -194,6 +202,7 @@ SYSTEM_TSO_TESTSUITE = $(srcdir)/tests/system-tso-testsuite SYSTEM_AFXDP_TESTSUITE = $(srcdir)/tests/system-afxdp-testsuite SYSTEM_OFFLOADS_TESTSUITE = $(srcdir)/tests/system-offloads-testsuite SYSTEM_DPDK_TESTSUITE = $(srcdir)/tests/system-dpdk-testsuite +SYSTEM_EVENT_TESTSUITE = $(srcdir)/tests/system-event-testsuite OVSDB_CLUSTER_TESTSUITE = $(srcdir)/tests/ovsdb-cluster-testsuite DISTCLEANFILES += tests/atconfig tests/atlocal @@ -356,6 +365,10 @@ check-dpdk: all set $(SHELL) '$(SYSTEM_DPDK_TESTSUITE)' -C tests AUTOTEST_PATH='$(AUTOTEST_PATH)'; \ "$$@" $(TESTSUITEFLAGS) -j1 || (test X'$(RECHECK)' = Xyes && "$$@" --recheck) +check-event: all + set $(SHELL) '$(SYSTEM_EVENT_TESTSUITE)' -C tests AUTOTEST_PATH='$(AUTOTEST_PATH)'; \ + "$$@" $(TESTSUITEFLAGS) -j1 || (test X'$(RECHECK)' = Xyes && "$$@" --recheck) + clean-local: test ! -f '$(TESTSUITE)' || $(SHELL) '$(TESTSUITE)' -C tests --clean @@ -401,6 +414,11 @@ $(SYSTEM_DPDK_TESTSUITE): package.m4 $(SYSTEM_TESTSUITE_AT) $(SYSTEM_DPDK_TESTSU $(AM_V_GEN)$(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at $(AM_V_at)mv $@.tmp $@ +$(SYSTEM_EVENT_TESTSUITE): package.m4 $(SYSTEM_TESTSUITE_AT) $(SYSTEM_EVENT_TESTSUITE_AT) $(COMMON_MACROS_AT) + $(AM_V_GEN)$(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at + $(AM_V_at)mv $@.tmp $@ + +$(OVSDB_CLUSTER_TESTSUITE): package.m4 $(OVSDB_CLUSTER_TESTSUITE_AT) $(COMMON_MACROS_AT) $(OVSDB_CLUSTER_TESTSUITE): package.m4 $(OVSDB_CLUSTER_TESTSUITE_AT) $(COMMON_MACROS_AT) $(AM_V_GEN)$(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at $(AM_V_at)mv $@.tmp $@ diff --git a/tests/system-event.at b/tests/system-event.at new file mode 100644 index 0000000..bc9ba1d --- /dev/null +++ b/tests/system-event.at @@ -0,0 +1,351 @@ +m4_define([CONFIGURE_VETH_OFFLOADS], + [AT_CHECK([ethtool -K $1 tx off], [0], [ignore], [ignore])]) + +m4_define([SET_NUMA_NODE], + [ + AT_CHECK([lscpu | awk '/NUMA node\(s\)/ {c=1; while (c++<$(3)) {printf "$1,"}; print "$1"}' > NUMA_NODE]) +]) + +m4_define([CREATE_EVENT_JSON], + [ + AT_CHECK[cat > $abs_top_srcdir/tests/event.json </dev/null 2>/dev/null]) +OVS_DB_START() +AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:userspace-tso-enable=true]) +AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:user_defined_event_enable=true]) +OVS_DPDK_START() +AT_CHECK([grep -c 'Userspace TCP Segmentation Offloading support enabled' \ + ovs-vswitchd.log],[ignore],[dnl +1 +]) + +dnl Find number of sockets +SET_NUMA_NODE([512]) + +dnl Add userspace bridge and attach it to OVS +AT_CHECK([ovs-vsctl add-br br10 -- set bridge br10 datapath_type=netdev]) +AT_CHECK([ovs-vsctl add-port br10 dpdkvhostuserclient0 -- set Interface \ + dpdkvhostuserclient0 \ + type=dpdkvhostuserclient \ + options:vhost-server-path=$OVS_RUNDIR/dpdkvhostclient0], [], + [stdout], [stderr]) +AT_CHECK([ovs-vsctl show], [], [stdout]) + +dnl Set up namespaces +ADD_NAMESPACES(ns1, ns2) + +dnl Add veth device +ADD_VETH(tap1, ns2, br10, "172.31.110.12/24") + +dnl Execute testpmd in background +on_exit "pkill -f -x -9 'tail -f /dev/null'" +AT_CHECK([echo "show device info all" > CMDFILE]) +AT_CHECK([echo "show port 0 tx_offload capabilities" >> CMDFILE]) +tail -f /dev/null | testpmd --socket-mem="$(cat NUMA_NODE)" --no-pci\ + --vdev="net_virtio_user,path=$OVS_RUNDIR/dpdkvhostclient0,server=1" \ + --vdev="net_tap0,iface=tap0" --file-prefix page0 \ + --single-file-segments -- --cmdline-file=CMDFILE \ + -a >$OVS_RUNDIR/testpmd-dpdkvhostuserclient0.log 2>&1 & + +dnl Give settling time to the testpmd processes - NOTE: this is bad form. +sleep 10 + +dnl Move the tap devices to the namespaces +AT_CHECK([ps aux | grep testpmd], [], [stdout], [stderr]) +AT_CHECK([ip link show], [], [stdout], [stderr]) +AT_CHECK([ip link set tap0 netns ns1], [], [stdout], [stderr]) + +AT_CHECK([ip netns exec ns1 ip link show], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns1 ip link show | grep tap0], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns1 ip link set tap0 up], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns1 ip addr add 172.31.110.11/24 dev tap0], [], + [stdout], [stderr]) + +AT_CHECK([ip netns exec ns1 ip link show], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns2 ip link show], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns1 ping -c 4 -I tap0 172.31.110.12], [], [stdout], + [stderr]) + +CREATE_EVENT_JSON() +AT_CHECK([ovs-appctl event/define $abs_top_srcdir/tests/event.json],[],[ignore]) +AT_CHECK([ip netns exec ns2 iperf3 -s -1 -D]) +AT_CHECK([ip netns exec ns1 iperf3 -c 172.31.110.12],[],[stdout]) +AT_CHECK([ovs-appctl event/list --all-timer > event_list]) + +dnl Clean up +AT_CHECK([ovs-vsctl del-port br10 dpdkvhostuserclient0], [], [stdout], [stderr]) + +dnl Clean up the testpmd now +pkill -f -x -9 'tail -f /dev/null' + +AT_FAIL_IF([true]) +OVS_VSWITCHD_STOP() +AT_CLEANUP +dnl -------------------------------------------------------------------------- + +dnl -------------------------------------------------------------------------- +dnl iperf on vhostuser (with userspace-tso) +AT_SETUP([OVS-DPDK - iperf on vhostuser (with userspace-tso)]) +AT_KEYWORDS([dpdk]) +OVS_DPDK_PRE_CHECK() +AT_SKIP_IF([! which testpmd >/dev/null 2>/dev/null]) +OVS_DB_START() +AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:userspace-tso-enable=true]) +AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:user_defined_event_enable=true]) +OVS_DPDK_START() +AT_CHECK([grep -c 'Userspace TCP Segmentation Offloading support enabled' \ + ovs-vswitchd.log],[ignore],[dnl +1 +]) + +dnl Find number of sockets +SET_NUMA_NODE([512]) + +dnl Add userspace bridge and attach it to OVS +AT_CHECK([ovs-vsctl add-br br10 -- set bridge br10 datapath_type=netdev]) +AT_CHECK([ovs-vsctl add-port br10 dpdkvhostuser0 -- set Interface dpdkvhostuser0 \ + type=dpdkvhostuser], [], + [stdout], [stderr]) +AT_CHECK([ovs-vsctl show], [], [stdout]) + +dnl Set up namespaces +ADD_NAMESPACES(ns1, ns2) + +dnl Add veth device +ADD_VETH(tap1, ns2, br10, "172.31.110.12/24") + +dnl Execute testpmd in background +on_exit "pkill -f -x -9 'tail -f /dev/null'" +AT_CHECK([echo "show device info all" > CMDFILE]) +AT_CHECK([echo "show port 0 tx_offload capabilities" >> CMDFILE]) +tail -f /dev/null | testpmd --socket-mem="$(cat NUMA_NODE)" --no-pci\ + --vdev="net_virtio_user,path=$OVS_RUNDIR/dpdkvhostuser0" \ + --vdev="net_tap0,iface=tap0" --file-prefix page0 \ + --single-file-segments -- --cmdline-file=CMDFILE \ + -a >$OVS_RUNDIR/testpmd-dpdkvhostuser0.log 2>&1 & + +dnl Give settling time to the testpmd processes - NOTE: this is bad form. +sleep 10 + +dnl Move the tap devices to the namespaces +AT_CHECK([ps aux | grep testpmd], [], [stdout], [stderr]) +AT_CHECK([ip link show], [], [stdout], [stderr]) +AT_CHECK([ip link set tap0 netns ns1], [], [stdout], [stderr]) + +AT_CHECK([ip netns exec ns1 ip link show], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns1 ip link show | grep tap0], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns1 ip link set tap0 up], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns1 ip addr add 172.31.110.11/24 dev tap0], [], + [stdout], [stderr]) + +AT_CHECK([ip netns exec ns1 ip link show], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns2 ip link show], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns1 ping -c 4 -I tap0 172.31.110.12], [], [stdout], + [stderr]) + +CREATE_EVENT_JSON() +AT_CHECK([ovs-appctl event/define $abs_top_srcdir/tests/event.json],[],[ignore]) +AT_CHECK([ip netns exec ns2 iperf3 -s -1 -D]) +AT_CHECK([ip netns exec ns1 iperf3 -c 172.31.110.12],[],[stdout]) +AT_CHECK([ovs-appctl event/list --all-timer > event_list]) + +dnl Clean up the testpmd now +pkill -f -x -9 'tail -f /dev/null' + +dnl Clean up +AT_CHECK([ovs-vsctl del-port br10 dpdkvhostuser0], [], [stdout], [stderr]) + +AT_FAIL_IF([true]) +OVS_VSWITCHD_STOP() +AT_CLEANUP +dnl -------------------------------------------------------------------------- + +dnl -------------------------------------------------------------------------- +dnl iperf on vhostuserclient (without userspace-tso) +AT_SETUP([OVS-DPDK - iperf on vhostuserclient (without userspace-tso)]) +AT_KEYWORDS([dpdk]) +OVS_DPDK_PRE_CHECK() +AT_SKIP_IF([! which testpmd >/dev/null 2>/dev/null]) +OVS_DB_START() +AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:userspace-tso-enable=false]) +AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:user_defined_event_enable=true]) +OVS_DPDK_START() +AT_CHECK([grep -c 'Userspace TCP Segmentation Offloading support enabled' \ + ovs-vswitchd.log],[ignore],[dnl +0 +]) + +dnl Find number of sockets +SET_NUMA_NODE([512]) + +dnl Add userspace bridge and attach it to OVS +AT_CHECK([ovs-vsctl add-br br10 -- set bridge br10 datapath_type=netdev]) +AT_CHECK([ovs-vsctl add-port br10 dpdkvhostuserclient0 -- set Interface \ + dpdkvhostuserclient0 \ + type=dpdkvhostuserclient \ + options:vhost-server-path=$OVS_RUNDIR/dpdkvhostclient0], [], + [stdout], [stderr]) +AT_CHECK([ovs-vsctl show], [], [stdout]) + +dnl Set up namespaces +ADD_NAMESPACES(ns1, ns2) + +dnl Add veth device +ADD_VETH(tap1, ns2, br10, "172.31.110.12/24") + +dnl Execute testpmd in background +on_exit "pkill -f -x -9 'tail -f /dev/null'" +AT_CHECK([echo "show device info all" > CMDFILE]) +AT_CHECK([echo "show port 0 tx_offload capabilities" >> CMDFILE]) +tail -f /dev/null | testpmd --socket-mem="$(cat NUMA_NODE)" --no-pci\ + --vdev="net_virtio_user,path=$OVS_RUNDIR/dpdkvhostclient0,server=1" \ + --vdev="net_tap0,iface=tap0" --file-prefix page0 \ + --single-file-segments -- --cmdline-file=CMDFILE \ + -a >$OVS_RUNDIR/testpmd-dpdkvhostuserclient0.log 2>&1 & + +dnl Give settling time to the testpmd processes - NOTE: this is bad form. +sleep 10 + +dnl Move the tap devices to the namespaces +AT_CHECK([ps aux | grep testpmd], [], [stdout], [stderr]) +AT_CHECK([ip link show], [], [stdout], [stderr]) +AT_CHECK([ip link set tap0 netns ns1], [], [stdout], [stderr]) + +AT_CHECK([ip netns exec ns1 ip link show], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns1 ip link show | grep tap0], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns1 ip link set tap0 up], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns1 ip addr add 172.31.110.11/24 dev tap0], [], + [stdout], [stderr]) + +AT_CHECK([ip netns exec ns1 ip link show], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns2 ip link show], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns1 ping -c 4 -I tap0 172.31.110.12], [], [stdout], + [stderr]) + +CREATE_EVENT_JSON() +AT_CHECK([ovs-appctl event/define $abs_top_srcdir/tests/event.json],[],[ignore]) +AT_CHECK([ip netns exec ns2 iperf3 -s -1 -D]) +AT_CHECK([ip netns exec ns1 iperf3 -c 172.31.110.12],[],[stdout]) +AT_CHECK([ovs-appctl event/list --all-timer > event_list]) + +dnl Clean up +AT_CHECK([ovs-vsctl del-port br10 dpdkvhostuserclient0], [], [stdout], [stderr]) + +dnl Clean up the testpmd now +pkill -f -x -9 'tail -f /dev/null' + +AT_FAIL_IF([true]) +OVS_VSWITCHD_STOP() +AT_CLEANUP +dnl -------------------------------------------------------------------------- + +dnl -------------------------------------------------------------------------- +dnl iperf on vhostuser (without userspace-tso) +AT_SETUP([OVS-DPDK - iperf on vhostuser (without userspace-tso)]) +AT_KEYWORDS([dpdk]) +OVS_DPDK_PRE_CHECK() +AT_SKIP_IF([! which testpmd >/dev/null 2>/dev/null]) +OVS_DB_START() +AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:userspace-tso-enable=false]) +AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:user_defined_event_enable=true]) +OVS_DPDK_START() +AT_CHECK([grep -c 'Userspace TCP Segmentation Offloading support enabled' \ + ovs-vswitchd.log],[ignore],[dnl +0 +]) + +dnl Find number of sockets +SET_NUMA_NODE([512]) + +dnl Add userspace bridge and attach it to OVS +AT_CHECK([ovs-vsctl add-br br10 -- set bridge br10 datapath_type=netdev]) +AT_CHECK([ovs-vsctl add-port br10 dpdkvhostuser0 -- set Interface dpdkvhostuser0 \ + type=dpdkvhostuser], [], + [stdout], [stderr]) +AT_CHECK([ovs-vsctl show], [], [stdout]) + +dnl Set up namespaces +ADD_NAMESPACES(ns1, ns2) + +dnl Add veth device +ADD_VETH(tap1, ns2, br10, "172.31.110.12/24") + +dnl Execute testpmd in background +on_exit "pkill -f -x -9 'tail -f /dev/null'" +AT_CHECK([echo "show device info all" > CMDFILE]) +AT_CHECK([echo "show port 0 tx_offload capabilities" >> CMDFILE]) +tail -f /dev/null | testpmd --socket-mem="$(cat NUMA_NODE)" --no-pci\ + --vdev="net_virtio_user,path=$OVS_RUNDIR/dpdkvhostuser0" \ + --vdev="net_tap0,iface=tap0" --file-prefix page0 \ + --single-file-segments -- --cmdline-file=CMDFILE \ + -a >$OVS_RUNDIR/testpmd-dpdkvhostuser0.log 2>&1 & + +dnl Give settling time to the testpmd processes - NOTE: this is bad form. +sleep 10 + +dnl Move the tap devices to the namespaces +AT_CHECK([ps aux | grep testpmd], [], [stdout], [stderr]) +AT_CHECK([ip link show], [], [stdout], [stderr]) +AT_CHECK([ip link set tap0 netns ns1], [], [stdout], [stderr]) + +AT_CHECK([ip netns exec ns1 ip link show], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns1 ip link show | grep tap0], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns1 ip link set tap0 up], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns1 ip addr add 172.31.110.11/24 dev tap0], [], + [stdout], [stderr]) + +AT_CHECK([ip netns exec ns1 ip link show], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns2 ip link show], [], [stdout], [stderr]) +AT_CHECK([ip netns exec ns1 ping -c 4 -I tap0 172.31.110.12], [], [stdout], + [stderr]) + +CREATE_EVENT_JSON() +AT_CHECK([ovs-appctl event/define $abs_top_srcdir/tests/event.json],[],[ignore]) +AT_CHECK([ip netns exec ns2 iperf3 -s -1 -D]) +AT_CHECK([ip netns exec ns1 iperf3 -c 172.31.110.12],[],[stdout]) +AT_CHECK([ovs-appctl event/list --all-timer > event_list]) + +dnl Clean up the testpmd now +pkill -f -x -9 'tail -f /dev/null' + +dnl Clean up +AT_CHECK([ovs-vsctl del-port br10 dpdkvhostuser0], [], [stdout], [stderr]) + +AT_FAIL_IF([true]) +OVS_VSWITCHD_STOP() +AT_CLEANUP +dnl -------------------------------------------------------------------------- + +