[ovs-dev] OVN: RFC add a new JSON-RPC selective monitoring method

2015-08-31 Thread Liran Schour
Following the discussion on overcoming OVN scalability issues by allowing 
clients to monitor only rows that meet specific criteria
(http://openvswitch.org/pipermail/dev/2015-August/059149.html), I propose 
to amend the OVSDB protocol specification (RFC 7047). 

Proposed amendment is to define a new monitor method, monitor_cond, for 
specifying monitoring conditions. Adding a new method allows keeping all 
of the existing client code intact, replacing code only in places that can 
benefit from this new method (e.g. in ovn-controller).

Below is the description for a new JSON-RPC monitor_cond method to be 
added to the OVSDB protocol. (All references are to RFC 7047)

monitor_cond:
-

The "monitor_cond" request enables a client to replicate subsets of tables 
within an OVSDB database by requesting notifications of changes to those 
rows in the table that match all the conditions specified in "where" by 
receiving these rows.

The request object has the following members:

* "method": "monitor_cond"

* "params": [, , ]

* "id": 

The  parameter is used to match subsequent update 
notifications (see below) to this request.
The  object maps the name of the table to an array 
of .

Each  is an object with the following members:
   * "where": [*]   optional
   * "select": optional

 is specified in Section 5.1 in the RFC

 is an object with the following members:

* "initial":   optional
* "insert":optional
* "delete":optional
* "modify":optional

The contents of this object specify how the columns or table are to be 
monitored, as explained
in more detail below.

The response object has the following members:

   *  "result": 
 
   *  "error": null
 
   *  "id": same "id" as request

The  object is described in detail in Section 4.1.6. It 
contains the contents of
the tables for which "initial" rows are selected.  If no tables' initial 
contents are
requested, then "result" is an empty object.

Subsequently, when changes to a specified table that match all the 
conditions in monitor-cond-request are committed, the changes are 
automatically sent to the client using the "update" monitor notification 
(see Section 4.1.6).  This monitoring persists until the JSON-RPC session 
terminates or until the client sends a "monitor_cancel" JSON-RPC request.

Each  specifies one or more conditions and the 
manner in which the rows
that match the conditions are to be monitored.  The circumstances in which 
an "update" notification is sent for a row within the table are determined 
by :

  *  If "initial" is omitted or true, every row in the table that matches 
the conditions is sent as part of the response to the "monitor_cond" 
request.
 
  *  If "insert" is omitted or true, "update" notifications are sent for 
rows newly inserted into the table that match conditions.
 
  *  If "delete" is omitted or true, "update" notifications are sent for 
rows deleted from the table that match conditions.
 
  *  If "modify" is omitted or true, "update" notifications are sent 
whenever a row in the table that matches conditions is modified.

...

I send this specification for review.
Next step will be starting a design discussion for implementing this in 
the ovsdb-server.
___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


Re: [ovs-dev] [PATCH v2 1/2] datapath-windows: Process tunnel filter requests iteratively

2015-08-31 Thread Sorin Vinturis
Hi Nithin,

Please see my answers inline.

Thanks,
Sorin

-Original Message-
From: Nithin Raju [mailto:nit...@vmware.com] 
Sent: Thursday, 27 August, 2015 23:44
To: Sorin Vinturis
Cc: dev@openvswitch.org
Subject: Re: [ovs-dev] [PATCH v2 1/2] datapath-windows: Process tunnel filter 
requests iteratively

> On Jul 20, 2015, at 12:00 PM, Sorin Vinturis 
>  wrote:
> 
> In order to support IRP cancelling mechanism for pending IRPs, all 
> tunnel filter requests, VXLAN create/delete tunnel, need to be 
> processed iteratively.
> 
> Signed-off-by: Sorin Vinturis 

hi Sorin,
I had a question regarding latency of processing the requests. Looks good 
otherwise. A v4 should be good to go.

> -do
> -{
> +do {
> if (!InterlockedCompareExchange(
> (LONG volatile *)&threadCtx->listRequests.numEntries, 0, 0)) {
> OVS_LOG_INFO("Nothing to do... request list is empty."); 
> @@ -1076,38 +1056,25 @@ 
> OvsTunnelFilterRequestListProcess(POVS_TUNFLT_THREAD_CONTEXT threadCtx)
> }
> inTransaction = TRUE;
> 
> -InitializeListHead(&head);
> -OvsTunnelFilterRequestPopList(&threadCtx->listRequests, &head, 
> &count);
> -
> -LIST_FORALL_SAFE(&head, link, next) {
> -request = CONTAINING_RECORD(link, OVS_TUNFLT_REQUEST, entry);
> +while (NULL != (request = OvsTunnelFilterRequestPop(
> +&threadCtx->listRequests))) {

minor: indentation can be improved to:
   while (NULL !=
  (request = OvsTunnelFilterRequestPop(&threadCtx->listRequests))) {
SV: Sure.

> 
> status = OvsTunnelFilterExecuteAction(threadCtx->engineSession,
>   request);
> +
> +/* Complete the IRP with the last operation status. */
> +OvsTunnelFilterCompleteRequest(request, status);
> +
> +OvsFreeMemory(request);
> +request = NULL;
> +
> if (!NT_SUCCESS(status)) {
> -RemoveEntryList(&request->entry);
> -count--;
> -
> -/* Complete the IRP with the failure status. */
> -OvsTunnelFilterCompleteRequest(request->irp,
> -   request->callback,
> -   request->context,
> -   status);
> -OvsFreeMemory(request);
> -request = NULL;
> -} else {
> -error = FALSE;
> +break;
> }
> }
> 

What happens if there are 10 requests to process, and the 5th one fails. You’d 
bail out of processing commit the 4 and go back into calling 
KeWaitForMultipleObjects() in OvsTunnelFilterThreadProc(). What is the trigger 
to processing the remaining 5 request, esp. if they are legitimate requests and 
there’s a good chance that they’ll succeed.
SV: You are right. If there are more requests queued and an error happened to 
one of them, the remaining request would not be processed until another one 
will be received and the request event is signaled. I'll change the code to 
continue with the processing the remaining requests, in case of error, instead 
of breaking.

Also, if you are worried about the number of requests being committed per 
transaction, maybe you should submit them in batches.
SV: No, I am not worried about the number of requests being too large for a 
transaction to handle. I've tested by pushing 2000 of requests on 8 threads and 
the code behaves fine. The threads number could be raised to handle an 
increased number of requests if necessary.

Does KeSetEvent() queue up wakeup events?
SV: No, the KeSetEvent() does not queue up the events.

-- Nithin
___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


Re: [ovs-dev] [PATCH v2 1/2] datapath-windows: Process tunnel filter requests iteratively

2015-08-31 Thread Nithin Raju
hi Sorin,
Looks like you acknowledge my comments. I’ll look forward to the v3. Thanks for 
your patience.

-- Nithin

> On Aug 31, 2015, at 5:08 AM, Sorin Vinturis 
>  wrote:
> 
> Hi Nithin,
> 
> Please see my answers inline.
> 
> Thanks,
> Sorin
> 
> -Original Message-
> From: Nithin Raju [mailto:nit...@vmware.com] 
> Sent: Thursday, 27 August, 2015 23:44
> To: Sorin Vinturis
> Cc: dev@openvswitch.org
> Subject: Re: [ovs-dev] [PATCH v2 1/2] datapath-windows: Process tunnel filter 
> requests iteratively
> 
>> On Jul 20, 2015, at 12:00 PM, Sorin Vinturis 
>>  wrote:
>> 
>> In order to support IRP cancelling mechanism for pending IRPs, all 
>> tunnel filter requests, VXLAN create/delete tunnel, need to be 
>> processed iteratively.
>> 
>> Signed-off-by: Sorin Vinturis 
> 
> hi Sorin,
> I had a question regarding latency of processing the requests. Looks good 
> otherwise. A v4 should be good to go.
> 
>> -do
>> -{
>> +do {
>>if (!InterlockedCompareExchange(
>>(LONG volatile *)&threadCtx->listRequests.numEntries, 0, 0)) {
>>OVS_LOG_INFO("Nothing to do... request list is empty."); 
>> @@ -1076,38 +1056,25 @@ 
>> OvsTunnelFilterRequestListProcess(POVS_TUNFLT_THREAD_CONTEXT threadCtx)
>>}
>>inTransaction = TRUE;
>> 
>> -InitializeListHead(&head);
>> -OvsTunnelFilterRequestPopList(&threadCtx->listRequests, &head, 
>> &count);
>> -
>> -LIST_FORALL_SAFE(&head, link, next) {
>> -request = CONTAINING_RECORD(link, OVS_TUNFLT_REQUEST, entry);
>> +while (NULL != (request = OvsTunnelFilterRequestPop(
>> +&threadCtx->listRequests))) {
> 
> minor: indentation can be improved to:
>   while (NULL !=
>  (request = OvsTunnelFilterRequestPop(&threadCtx->listRequests))) 
> {
> SV: Sure.
> 
>> 
>>status = OvsTunnelFilterExecuteAction(threadCtx->engineSession,
>>  request);
>> +
>> +/* Complete the IRP with the last operation status. */
>> +OvsTunnelFilterCompleteRequest(request, status);
>> +
>> +OvsFreeMemory(request);
>> +request = NULL;
>> +
>>if (!NT_SUCCESS(status)) {
>> -RemoveEntryList(&request->entry);
>> -count--;
>> -
>> -/* Complete the IRP with the failure status. */
>> -OvsTunnelFilterCompleteRequest(request->irp,
>> -   request->callback,
>> -   request->context,
>> -   status);
>> -OvsFreeMemory(request);
>> -request = NULL;
>> -} else {
>> -error = FALSE;
>> +break;
>>}
>>}
>> 
> 
> What happens if there are 10 requests to process, and the 5th one fails. 
> You’d bail out of processing commit the 4 and go back into calling 
> KeWaitForMultipleObjects() in OvsTunnelFilterThreadProc(). What is the 
> trigger to processing the remaining 5 request, esp. if they are legitimate 
> requests and there’s a good chance that they’ll succeed.
> SV: You are right. If there are more requests queued and an error happened to 
> one of them, the remaining request would not be processed until another one 
> will be received and the request event is signaled. I'll change the code to 
> continue with the processing the remaining requests, in case of error, 
> instead of breaking.
> 
> Also, if you are worried about the number of requests being committed per 
> transaction, maybe you should submit them in batches.
> SV: No, I am not worried about the number of requests being too large for a 
> transaction to handle. I've tested by pushing 2000 of requests on 8 threads 
> and the code behaves fine. The threads number could be raised to handle an 
> increased number of requests if necessary.
> 
> Does KeSetEvent() queue up wakeup events?
> SV: No, the KeSetEvent() does not queue up the events.
> 
> -- Nithin

___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


[ovs-dev] [PATCH] ovsdb: Remove misleading OVS_UNUSED from ovsdb_monitor_change_cb().

2015-08-31 Thread Ben Pfaff
This function does use this parameter.

(This does not change any behavior.)

Signed-off-by: Ben Pfaff 
---
 ovsdb/monitor.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ovsdb/monitor.c b/ovsdb/monitor.c
index 133460e..8a64fc1 100644
--- a/ovsdb/monitor.c
+++ b/ovsdb/monitor.c
@@ -779,7 +779,7 @@ ovsdb_monitor_changes_classify(enum ovsdb_monitor_selection 
type,
 static bool
 ovsdb_monitor_change_cb(const struct ovsdb_row *old,
 const struct ovsdb_row *new,
-const unsigned long int *changed OVS_UNUSED,
+const unsigned long int *changed,
 void *aux_)
 {
 struct ovsdb_monitor_aux *aux = aux_;
-- 
2.1.3

___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


[ovs-dev] [PATCH] ovsdb: Update _version more accurately in transaction commit.

2015-08-31 Thread Ben Pfaff
The _version column in each OVSDB row is supposed to be updated whenever
any other column in the row changes.  However, the transaction code was
not careful to do this only when a row actually changed--there were other
cases where a row was considered at transaction commit time and _version
updated even though the row did not actually change.  For example,
ovsdb_txn_adjust_atom_refs() calls find_or_make_txn_row(), which calls
ovsdb_txn_row_modify(), which updates _version, but
ovsdb_txn_adjust_atom_refs() doesn't actually update any data.

One way to fix this would be to carefully consider and adjust all the code
that looks at transaction rows.  However, this seems somewhat error prone
and thus difficult to test.  This commit takes a different approach: it
drops the code that adjusts _version on the fly, instead replacing it by
a final pass over the database at the end of the commit process that checks
for each row whether any columns changed and updates _version at that point
if any did.  That seems pretty foolproof to me.

Reported-by: RishiRaj Maulick 
Reported-at: http://openvswitch.org/pipermail/dev/2015-August/059439.html
Signed-off-by: Ben Pfaff 
---
 ovsdb/transaction.c | 25 ++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/ovsdb/transaction.c b/ovsdb/transaction.c
index 83ddaff..2c85fee 100644
--- a/ovsdb/transaction.c
+++ b/ovsdb/transaction.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
+/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -534,7 +534,6 @@ assess_weak_refs(struct ovsdb_txn *txn, struct 
ovsdb_txn_row *txn_row)
 }
 
 if (datum->n != orig_n) {
-bitmap_set1(txn_row->changed, OVSDB_COL_VERSION);
 bitmap_set1(txn_row->changed, column->index);
 ovsdb_datum_sort_assert(datum, column->type.key.type);
 if (datum->n < column->type.n_min) {
@@ -748,6 +747,21 @@ check_index_uniqueness(struct ovsdb_txn *txn OVS_UNUSED,
 return NULL;
 }
 
+static struct ovsdb_error * OVS_WARN_UNUSED_RESULT
+update_version(struct ovsdb_txn *txn OVS_UNUSED, struct ovsdb_txn_row *txn_row)
+{
+struct ovsdb_table *table = txn_row->table;
+size_t n_columns = shash_count(&table->schema->columns);
+
+if (txn_row->old && txn_row->new
+&& !bitmap_is_all_zeros(txn_row->changed, n_columns)) {
+bitmap_set1(txn_row->changed, OVSDB_COL_VERSION);
+uuid_generate(ovsdb_row_get_version_rw(txn_row->new));
+}
+
+return NULL;
+}
+
 static struct ovsdb_error *
 ovsdb_txn_commit_(struct ovsdb_txn *txn, bool durable)
 {
@@ -801,6 +815,12 @@ ovsdb_txn_commit_(struct ovsdb_txn *txn, bool durable)
 return error;
 }
 
+/* Update _version for rows that changed.  */
+error = for_each_txn_row(txn, update_version);
+if (error) {
+return OVSDB_WRAP_BUG("can't happen", error);
+}
+
 /* Send the commit to each replica. */
 LIST_FOR_EACH (replica, node, &txn->db->replicas) {
 error = (replica->class->commit)(replica, txn, durable);
@@ -915,7 +935,6 @@ ovsdb_txn_row_modify(struct ovsdb_txn *txn, const struct 
ovsdb_row *ro_row_)
 
 rw_row = ovsdb_row_clone(ro_row);
 rw_row->n_refs = ro_row->n_refs;
-uuid_generate(ovsdb_row_get_version_rw(rw_row));
 ovsdb_txn_row_create(txn, table, ro_row, rw_row);
 hmap_replace(&table->rows, &ro_row->hmap_node, &rw_row->hmap_node);
 
-- 
2.1.3

___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


Re: [ovs-dev] Query with respect to OVSDB and vswitchd

2015-08-31 Thread Ben Pfaff
On Mon, Aug 31, 2015 at 09:10:19AM +0530, RishiRaj Maulick wrote:
> Hi ,
> 
> I have been very recently using the OVSDB for one of our projects . I am
> able to create my own schema and operate on it . However to better
> understand things , I was also looking at the behavior of vswitchd on the
> default schema.
> 
> I am confused with the events of things that happened -
> 
> 1) I am monitoring the "Bridge" table through ovsdb-client
> 2) Using ovs-vsctl , whenever I add a bridge ( say br0 ) , on the monitor
> console I see that there are 2 activities - one of which is the initial
> "insert" and the next is an update for the "datapath id " that gets
> allocated by the vswitchd.
> This is understandable. In the update the _version field and the datapath
> id field gets mutated to new values.
> 3) However, if I add a second bridge ( say br1 ) , in the monitor console ,
> apart from the above operations pertaining to the new bridge being added (
> br1 ) , I am also seeing that the entry for the previously added bridge br0
> also gets mutated and the only change is the _version field.
> 
> My understanding of the  _uuid and _version fields is that these are
> maintained by the DB for internal purposes and the ovsdb-client cannot
> mutate these.
> 
> So I wanted to understand , why ( or what is the need ) the change of
> *_version* for all of the existing bridges are required , whenever we are
> adding a new bridge.

It's just a bug.  I sent out a fix.  Will you test it?
http://openvswitch.org/pipermail/dev/2015-August/059445.html

Thanks,

Ben.
___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


Re: [ovs-dev] [PATCH v2 2/2] datapath-windows: Support for IRP cancelling mechanism

2015-08-31 Thread Sorin Vinturis
Hi Nithin,

Please see my answers inline.

-Original Message-
From: Nithin Raju [mailto:nit...@vmware.com] 
Sent: Friday, 28 August, 2015 01:03
To: Sorin Vinturis
Cc: dev@openvswitch.org
Subject: Re: [ovs-dev] [PATCH v2 2/2] datapath-windows: Support for IRP 
cancelling mechanism

hi Sorin,
Looks good overall.

I just one one comment about the patch which I’ve inlined.

How did you test this BTW?
SV: I've tested using instrumentation code.

> VOID
> @@ -1309,7 +1405,7 @@ 
> OvsTunnelFilterThreadUninit(POVS_TUNFLT_THREAD_CONTEXT threadCtx)
>  * 
> --
> 
>  * This function creates a new tunnel filter request and push it to a 
> thread
>  * queue. If the thread stop event is signaled, the request is 
> completed with
> - * STATUS_CANCELLED without pushing it to any queue.
> + * STATUS_REQUEST_ABORTED without pushing it to any queue.
>  * 
> --
> 
>  */
> NTSTATUS
> @@ -1321,7 +1417,7 @@ OvsTunnelFilterQueueRequest(PIRP irp,
> PVOID tunnelContext) {
> POVS_TUNFLT_REQUEST request = NULL;
> -NTSTATUSstatus = STATUS_PENDING;
> +NTSTATUSstatus = STATUS_SUCCESS;
> BOOLEAN error = TRUE;
> UINT64  timeout = 0;
> 
> @@ -1334,8 +1430,8 @@ OvsTunnelFilterQueueRequest(PIRP irp,
>   FALSE,
>   (LARGE_INTEGER *)&timeout)) {
> /* The stop event is signaled. Completed the IRP with
> - * STATUS_CANCELLED. */
> -status = STATUS_CANCELLED;
> + * STATUS_REQUEST_ABORTED. */
> +status = STATUS_REQUEST_ABORTED;
> break;
> }
> 
> @@ -1366,7 +1462,10 @@ OvsTunnelFilterQueueRequest(PIRP irp,
> request->callback = callback;
> request->context = tunnelContext;
> 
> -OvsTunnelFilterThreadPush(request);
> +status = OvsTunnelFilterThreadPush(request);
> +if (!NT_SUCCESS(status)) {
> +break;
> +}
> 
> error = FALSE;
> } while (error);
> @@ -1379,13 +1478,14 @@ OvsTunnelFilterQueueRequest(PIRP irp,
> }
> }
> 
> -return status;
> +/* Return pending to indicate that the IRP will be completed later. */
> +return STATUS_PENDING;

You are returning STATUS_PENDING at the end of the function. You should be 
returning ‘status’.
SV: Correct. Good catch. 

___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


[ovs-dev] [PATCH v3 1/2] datapath-windows: Process tunnel filter requests iteratively

2015-08-31 Thread Sorin Vinturis
In order to support IRP cancelling mechanism for pending IRPs, all
tunnel filter requests, VXLAN create/delete tunnel, need to be
processed iteratively.

Signed-off-by: Sorin Vinturis 
---
 datapath-windows/ovsext/TunnelFilter.c | 103 ++---
 1 file changed, 30 insertions(+), 73 deletions(-)

diff --git a/datapath-windows/ovsext/TunnelFilter.c 
b/datapath-windows/ovsext/TunnelFilter.c
index 00e57c3..6cf9a94 100644
--- a/datapath-windows/ovsext/TunnelFilter.c
+++ b/datapath-windows/ovsext/TunnelFilter.c
@@ -955,38 +955,25 @@ OvsTunnelFilterExecuteAction(HANDLE engineSession,
 
 /*
  * --
- * This function pops the whole request entries from the queue and returns the
- * number of entries through the 'count' parameter. The operation is
- * synchronized using request list spinlock.
+ * This function pops the head item from the requests list while holding
+ * the list's spinlock.
  * --
  */
-VOID
-OvsTunnelFilterRequestPopList(POVS_TUNFLT_REQUEST_LIST listRequests,
-  PLIST_ENTRY head,
-  UINT32 *count)
+POVS_TUNFLT_REQUEST
+OvsTunnelFilterRequestPop(POVS_TUNFLT_REQUEST_LIST listRequests)
 {
+POVS_TUNFLT_REQUEST request = NULL;
+
 NdisAcquireSpinLock(&listRequests->spinlock);
 
 if (!IsListEmpty(&listRequests->head)) {
-PLIST_ENTRY PrevEntry;
-PLIST_ENTRY NextEntry;
-
-NextEntry = listRequests->head.Flink;
-PrevEntry = listRequests->head.Blink;
-
-head->Flink = NextEntry;
-NextEntry->Blink = head;
-
-head->Blink = PrevEntry;
-PrevEntry->Flink = head;
-
-*count = listRequests->numEntries;
-
-InitializeListHead(&listRequests->head);
-listRequests->numEntries = 0;
+request = (POVS_TUNFLT_REQUEST)RemoveHeadList(&listRequests->head);
+listRequests->numEntries--;
 }
 
 NdisReleaseSpinLock(&listRequests->spinlock);
+
+return request;
 }
 
 /*
@@ -1056,16 +1043,10 @@ VOID
 OvsTunnelFilterRequestListProcess(POVS_TUNFLT_THREAD_CONTEXT threadCtx)
 {
 POVS_TUNFLT_REQUEST request = NULL;
-PLIST_ENTRY link = NULL;
-PLIST_ENTRY next = NULL;
-LIST_ENTRY  head;
 NTSTATUSstatus = STATUS_SUCCESS;
-UINT32  count = 0;
 BOOLEAN inTransaction = FALSE;
-BOOLEAN error = TRUE;
 
-do
-{
+do {
 if (!InterlockedCompareExchange(
 (LONG volatile *)&threadCtx->listRequests.numEntries, 0, 0)) {
 OVS_LOG_INFO("Nothing to do... request list is empty.");
@@ -1080,38 +1061,24 @@ 
OvsTunnelFilterRequestListProcess(POVS_TUNFLT_THREAD_CONTEXT threadCtx)
 }
 inTransaction = TRUE;
 
-InitializeListHead(&head);
-OvsTunnelFilterRequestPopList(&threadCtx->listRequests, &head, &count);
-
-LIST_FORALL_SAFE(&head, link, next) {
-request = CONTAINING_RECORD(link, OVS_TUNFLT_REQUEST, entry);
-
-status = OvsTunnelFilterExecuteAction(threadCtx->engineSession,
-  request);
-if (!NT_SUCCESS(status)) {
-RemoveEntryList(&request->entry);
-count--;
-
-/* Complete the IRP with the failure status. */
-OvsTunnelFilterCompleteRequest(request->irp,
-   request->callback,
-   request->context,
-   status);
-OvsFreeMemory(request);
-request = NULL;
-} else {
-error = FALSE;
-}
-}
+while (NULL !=
+(request = OvsTunnelFilterRequestPop(&threadCtx->listRequests))) {
 
-if (error) {
-/* No successful requests were made, so there is no point to commit
- * the transaction. */
-break;
+OvsTunnelFilterExecuteAction(threadCtx->engineSession,
+ request);
+
+/* Complete the IRP with the last operation status. */
+OvsTunnelFilterCompleteRequest(request->irp,
+   request->callback,
+   request->context,
+   status);
+
+OvsFreeMemory(request);
+request = NULL;
 }
 
 status = FwpmTransactionCommit(threadCtx->engineSession);
-if (!NT_SUCCESS(status)){
+if (!NT_SUCCESS(status)) {
 OVS_LOG_ERROR("Failed to commit transaction, status: %x.",
   status);
 break;
@@ -1125,20 +1092,6 @@ 
OvsTunnelFilterRequestListProcess(POVS_TUNFLT_THREAD_CONTEXT threa

[ovs-dev] [PATCH v3 0/2] datapath-windows: IRP cancelling mechanism

2015-08-31 Thread Sorin Vinturis
This patch series adds support for IRP cancelling mechanism to the OVS 
extension.

Sorin Vinturis (2):
  [PATCH v3 1/2] datapath-windows: Process tunnel filter requests iteratively
  [PATCH v3 2/2] datapath-windows: Support for IRP cancelling mechanism

___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


[ovs-dev] [PATCH v3 2/2] datapath-windows: Support for IRP cancelling mechanism

2015-08-31 Thread Sorin Vinturis
Under certain circumstances, we might need to cancel a pending IRP
that has been submitted and not yet responded. This might occur when
the request takes too long to complete or when the process which
initiated the request terminated, leaving the request outstanding.

This patch provides this missing piece by adding support for IRP
cancelling mechanism.

Signed-off-by: Sorin Vinturis 
Reported-by: Sorin Vinturis 
Reported-at: https://github.com/openvswitch/ovs-issues/issues/95

v2: Before pending an IRP, check if it has been cancelled.
---
 datapath-windows/ovsext/Datapath.c |   4 -
 datapath-windows/ovsext/TunnelFilter.c | 198 ++---
 2 files changed, 180 insertions(+), 22 deletions(-)

diff --git a/datapath-windows/ovsext/Datapath.c 
b/datapath-windows/ovsext/Datapath.c
index 8c72533..b7bbf80 100644
--- a/datapath-windows/ovsext/Datapath.c
+++ b/datapath-windows/ovsext/Datapath.c
@@ -918,10 +918,6 @@ done:
 exit:
 /* Should not complete a pending IRP unless proceesing is completed. */
 if (status == STATUS_PENDING) {
-/* STATUS_PENDING is returned by the NL handler when the request is
- * to be processed later, so we mark the IRP as pending and complete
- * it in another thread when the request is processed. */
-IoMarkIrpPending(irp);
 return status;
 }
 return OvsCompleteIrpRequest(irp, (ULONG_PTR)replyLen, status);
diff --git a/datapath-windows/ovsext/TunnelFilter.c 
b/datapath-windows/ovsext/TunnelFilter.c
index 6cf9a94..ec14c64 100644
--- a/datapath-windows/ovsext/TunnelFilter.c
+++ b/datapath-windows/ovsext/TunnelFilter.c
@@ -168,6 +168,10 @@ static VOID 
OvsTunnelFilterThreadStop(POVS_TUNFLT_THREAD_CONTEXT threadCtx,
   BOOLEAN signalEvent);
 static NTSTATUS OvsTunnelFilterThreadInit(POVS_TUNFLT_THREAD_CONTEXT 
threadCtx);
 static VOID OvsTunnelFilterThreadUninit(POVS_TUNFLT_THREAD_CONTEXT 
threadCtx);
+static VOID OvsTunnelFilterSetIrpContext(POVS_TUNFLT_REQUEST_LIST 
listRequests,
+ POVS_TUNFLT_REQUEST request);
+static VOID OvsTunnelFilterCancelIrp(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp);
 
 /*
  * Callout driver global variables
@@ -955,20 +959,49 @@ OvsTunnelFilterExecuteAction(HANDLE engineSession,
 
 /*
  * --
- * This function pops the head item from the requests list while holding
- * the list's spinlock.
+ * This function pops the head request from the queue while holding the
+ * queue lock. If the request has already been cancelled or is about to be
+ * cancelled, the function retrieves the next valid request.
+ *
+ * Returns a pointer to the OVS_TUNFLT_REQUEST_LIST request object retrieved
+ * from the queue.
  * --
  */
 POVS_TUNFLT_REQUEST
 OvsTunnelFilterRequestPop(POVS_TUNFLT_REQUEST_LIST listRequests)
 {
 POVS_TUNFLT_REQUEST request = NULL;
+PLIST_ENTRY link, next, head;
 
 NdisAcquireSpinLock(&listRequests->spinlock);
 
 if (!IsListEmpty(&listRequests->head)) {
-request = (POVS_TUNFLT_REQUEST)RemoveHeadList(&listRequests->head);
-listRequests->numEntries--;
+head = &listRequests->head;
+LIST_FORALL_SAFE(head, link, next) {
+PDRIVER_CANCEL oldCancelRoutine;
+
+request = CONTAINING_RECORD(link, OVS_TUNFLT_REQUEST, entry);
+if (request->irp) {
+oldCancelRoutine = IoSetCancelRoutine(request->irp, NULL);
+if (oldCancelRoutine == NULL) {
+/*
+ * The Cancel routine for the current IRP is running. The
+ * request is to be completed by the Cancel routine. Leave
+ * this request alone and go to the next one.
+ */
+continue;
+} else {
+/*
+ * The Cancel routine cannot run now and cannot already 
have
+ * started to run. This request can be processed.
+ */
+}
+}
+
+RemoveEntryList(&request->entry);
+listRequests->numEntries--;
+break;
+}
 }
 
 NdisReleaseSpinLock(&listRequests->spinlock);
@@ -978,20 +1011,78 @@ OvsTunnelFilterRequestPop(POVS_TUNFLT_REQUEST_LIST 
listRequests)
 
 /*
  * --
- * This function pushes the received request to the list while holding the
- * request list spinlock.
+ * This function pushes the received request to the queue, marks the IRP as
+ * pending and sets its Cancel routine, while holding the queue lock.
+ *
+ * Returns STATUS_CANCELLED if the IRP has already been cancelled. Otherwise,
+ * STATUS_SUCCESS is returne

Re: [ovs-dev] [PATCH] flow: Fix MSVC compile errors.

2015-08-31 Thread Nithin Raju

> On Aug 30, 2015, at 7:40 AM, Ben Pfaff  wrote:
> 
> MSVC doesn't like the change in 'const' between function declaration and
> definition: it reports "formal parameter 2 different from declaration" for
> each of the functions in flow.h corrected by this (commit.  I think it's
> technically wrong about that, standards-wise.)
> 
> MSVC doesn't like an empty-brace initializer.  (I think it's technically
> right about that, standards-wise.)
> 
> This commit attempts to fix both problems, but I have not tested it with
> MSVC.
> 
> CC: Jarno Rajahalme 
> Signed-off-by: Ben Pfaff 

Thanks Ben for the patch.

There seems to be one a change required in netdev-windows.c. I’ll send out a 
patch for that.

Acked-by: Nithin Raju 
Tested-by: Nithin Raju 

thanks,
-- Nithin
___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


[ovs-dev] [PATCH] lib/netdev-windows.c: typo in call to memcpy()

2015-08-31 Thread Nithin Raju
Signed-off-by: Nithin Raju 
---
 lib/netdev-windows.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/netdev-windows.c b/lib/netdev-windows.c
index 51d088a..aef9d2c 100644
--- a/lib/netdev-windows.c
+++ b/lib/netdev-windows.c
@@ -248,7 +248,7 @@ netdev_windows_netdev_from_ofpbuf(struct 
netdev_windows_netdev_info *info,
 info->port_no = nl_attr_get_odp_port(a[OVS_WIN_NETDEV_ATTR_PORT_NO]);
 info->ovs_type = nl_attr_get_u32(a[OVS_WIN_NETDEV_ATTR_TYPE]);
 info->name = nl_attr_get_string(a[OVS_WIN_NETDEV_ATTR_NAME]);
-memcpy(info->mac_address, 
nl_attr_get_unspec(a[OVS_WIN_NETDEV_ATTR_MAC_ADDR],
+memcpy(&info->mac_address, 
nl_attr_get_unspec(a[OVS_WIN_NETDEV_ATTR_MAC_ADDR],
sizeof(info->mac_address)), sizeof(info->mac_address));
 info->mtu = nl_attr_get_u32(a[OVS_WIN_NETDEV_ATTR_MTU]);
 info->ifi_flags = nl_attr_get_u32(a[OVS_WIN_NETDEV_ATTR_IF_FLAGS]);
-- 
1.9.4.msysgit.2

___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


Re: [ovs-dev] [PATCH v3 1/2] datapath-windows: Process tunnel filter requests iteratively

2015-08-31 Thread Nithin Raju

> +while (NULL !=
> +(request = OvsTunnelFilterRequestPop(&threadCtx->listRequests))) 
> {
> 
> -if (error) {
> -/* No successful requests were made, so there is no point to 
> commit
> - * the transaction. */
> -break;
> +OvsTunnelFilterExecuteAction(threadCtx->engineSession,
> + request);

Don’t you need a:
status = ?

> +
> +/* Complete the IRP with the last operation status. */
> +OvsTunnelFilterCompleteRequest(request->irp,
> +   request->callback,
> +   request->context,
> +   status);

-- Nithin
___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


Re: [ovs-dev] [PATCH v2] datapath: check for rx handler register

2015-08-31 Thread Jesse Gross
On Fri, Aug 28, 2015 at 5:52 PM, Flavio Leitner  wrote:
> Red Hat Enterprise Linux 6 has backported the netdev RX
> handler facility so use the netdev_rx_handler_register as
> an indicator.
>
> The handler prototype changed between 2.6.36 and 2.6.39
> since there could be backports in any stage, don't look
> at the kernel version, but at the prototype.
>
> Signed-off-by: Flavio Leitner 

Thanks, applied to master and branch-2.4.
___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


Re: [ovs-dev] [PATCH] flow: Fix MSVC compile errors.

2015-08-31 Thread Ben Pfaff
On Mon, Aug 31, 2015 at 05:56:34PM +, Nithin Raju wrote:
> 
> > On Aug 30, 2015, at 7:40 AM, Ben Pfaff  wrote:
> > 
> > MSVC doesn't like the change in 'const' between function declaration and
> > definition: it reports "formal parameter 2 different from declaration" for
> > each of the functions in flow.h corrected by this (commit.  I think it's
> > technically wrong about that, standards-wise.)
> > 
> > MSVC doesn't like an empty-brace initializer.  (I think it's technically
> > right about that, standards-wise.)
> > 
> > This commit attempts to fix both problems, but I have not tested it with
> > MSVC.
> > 
> > CC: Jarno Rajahalme 
> > Signed-off-by: Ben Pfaff 
> 
> Thanks Ben for the patch.
> 
> There seems to be one a change required in netdev-windows.c. I’ll send out a 
> patch for that.
> 
> Acked-by: Nithin Raju 
> Tested-by: Nithin Raju 

Thanks, I've applied this to master.  I'll look for the netdev-windows.c
patch.
___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


Re: [ovs-dev] [PATCH] lib/netdev-windows.c: typo in call to memcpy()

2015-08-31 Thread Ben Pfaff
On Mon, Aug 31, 2015 at 10:59:28AM -0700, Nithin Raju wrote:
> Signed-off-by: Nithin Raju 

Thanks, applied.
___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


[ovs-dev] [PATCH v4 1/2] datapath-windows: Process tunnel filter requests iteratively

2015-08-31 Thread Sorin Vinturis
In order to support IRP cancelling mechanism for pending IRPs, all
tunnel filter requests, VXLAN create/delete tunnel, need to be
processed iteratively.

Signed-off-by: Sorin Vinturis 
---
 datapath-windows/ovsext/TunnelFilter.c | 103 ++---
 1 file changed, 30 insertions(+), 73 deletions(-)

diff --git a/datapath-windows/ovsext/TunnelFilter.c 
b/datapath-windows/ovsext/TunnelFilter.c
index 00e57c3..6cf9a94 100644
--- a/datapath-windows/ovsext/TunnelFilter.c
+++ b/datapath-windows/ovsext/TunnelFilter.c
@@ -955,38 +955,25 @@ OvsTunnelFilterExecuteAction(HANDLE engineSession,
 
 /*
  * --
- * This function pops the whole request entries from the queue and returns the
- * number of entries through the 'count' parameter. The operation is
- * synchronized using request list spinlock.
+ * This function pops the head item from the requests list while holding
+ * the list's spinlock.
  * --
  */
-VOID
-OvsTunnelFilterRequestPopList(POVS_TUNFLT_REQUEST_LIST listRequests,
-  PLIST_ENTRY head,
-  UINT32 *count)
+POVS_TUNFLT_REQUEST
+OvsTunnelFilterRequestPop(POVS_TUNFLT_REQUEST_LIST listRequests)
 {
+POVS_TUNFLT_REQUEST request = NULL;
+
 NdisAcquireSpinLock(&listRequests->spinlock);
 
 if (!IsListEmpty(&listRequests->head)) {
-PLIST_ENTRY PrevEntry;
-PLIST_ENTRY NextEntry;
-
-NextEntry = listRequests->head.Flink;
-PrevEntry = listRequests->head.Blink;
-
-head->Flink = NextEntry;
-NextEntry->Blink = head;
-
-head->Blink = PrevEntry;
-PrevEntry->Flink = head;
-
-*count = listRequests->numEntries;
-
-InitializeListHead(&listRequests->head);
-listRequests->numEntries = 0;
+request = (POVS_TUNFLT_REQUEST)RemoveHeadList(&listRequests->head);
+listRequests->numEntries--;
 }
 
 NdisReleaseSpinLock(&listRequests->spinlock);
+
+return request;
 }
 
 /*
@@ -1056,16 +1043,10 @@ VOID
 OvsTunnelFilterRequestListProcess(POVS_TUNFLT_THREAD_CONTEXT threadCtx)
 {
 POVS_TUNFLT_REQUEST request = NULL;
-PLIST_ENTRY link = NULL;
-PLIST_ENTRY next = NULL;
-LIST_ENTRY  head;
 NTSTATUSstatus = STATUS_SUCCESS;
-UINT32  count = 0;
 BOOLEAN inTransaction = FALSE;
-BOOLEAN error = TRUE;
 
-do
-{
+do {
 if (!InterlockedCompareExchange(
 (LONG volatile *)&threadCtx->listRequests.numEntries, 0, 0)) {
 OVS_LOG_INFO("Nothing to do... request list is empty.");
@@ -1080,38 +1061,24 @@ 
OvsTunnelFilterRequestListProcess(POVS_TUNFLT_THREAD_CONTEXT threadCtx)
 }
 inTransaction = TRUE;
 
-InitializeListHead(&head);
-OvsTunnelFilterRequestPopList(&threadCtx->listRequests, &head, &count);
-
-LIST_FORALL_SAFE(&head, link, next) {
-request = CONTAINING_RECORD(link, OVS_TUNFLT_REQUEST, entry);
-
-status = OvsTunnelFilterExecuteAction(threadCtx->engineSession,
-  request);
-if (!NT_SUCCESS(status)) {
-RemoveEntryList(&request->entry);
-count--;
-
-/* Complete the IRP with the failure status. */
-OvsTunnelFilterCompleteRequest(request->irp,
-   request->callback,
-   request->context,
-   status);
-OvsFreeMemory(request);
-request = NULL;
-} else {
-error = FALSE;
-}
-}
+while (NULL !=
+(request = OvsTunnelFilterRequestPop(&threadCtx->listRequests))) {
 
-if (error) {
-/* No successful requests were made, so there is no point to commit
- * the transaction. */
-break;
+status = OvsTunnelFilterExecuteAction(threadCtx->engineSession,
+  request);
+
+/* Complete the IRP with the last operation status. */
+OvsTunnelFilterCompleteRequest(request->irp,
+   request->callback,
+   request->context,
+   status);
+
+OvsFreeMemory(request);
+request = NULL;
 }
 
 status = FwpmTransactionCommit(threadCtx->engineSession);
-if (!NT_SUCCESS(status)){
+if (!NT_SUCCESS(status)) {
 OVS_LOG_ERROR("Failed to commit transaction, status: %x.",
   status);
 break;
@@ -1125,20 +1092,6 @@ 
OvsTunnelFilterRequestListProcess(POVS_TUNFLT_TH

Re: [ovs-dev] [PATCH v4 1/2] datapath-windows: Process tunnel filter requests iteratively

2015-08-31 Thread Nithin Raju
> On Aug 31, 2015, at 1:53 PM, Sorin Vinturis 
>  wrote:
> 
> In order to support IRP cancelling mechanism for pending IRPs, all
> tunnel filter requests, VXLAN create/delete tunnel, need to be
> processed iteratively.
> 
> Signed-off-by: Sorin Vinturis 

Acked-by: Nithin Raju 

___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


Re: [ovs-dev] [PATCH v3 2/2] datapath-windows: Support for IRP cancelling mechanism

2015-08-31 Thread Nithin Raju
> On Aug 31, 2015, at 10:46 AM, Sorin Vinturis 
>  wrote:
> 
> Under certain circumstances, we might need to cancel a pending IRP
> that has been submitted and not yet responded. This might occur when
> the request takes too long to complete or when the process which
> initiated the request terminated, leaving the request outstanding.
> 
> This patch provides this missing piece by adding support for IRP
> cancelling mechanism.
> 
> Signed-off-by: Sorin Vinturis 
> Reported-by: Sorin Vinturis 

Acked-by: Nithin Raju 
___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


Re: [ovs-dev] [PATCH v4 1/2] datapath-windows: Process tunnel filter requests iteratively

2015-08-31 Thread Ben Pfaff
On Mon, Aug 31, 2015 at 09:11:05PM +, Nithin Raju wrote:
> > On Aug 31, 2015, at 1:53 PM, Sorin Vinturis 
> >  wrote:
> > 
> > In order to support IRP cancelling mechanism for pending IRPs, all
> > tunnel filter requests, VXLAN create/delete tunnel, need to be
> > processed iteratively.
> > 
> > Signed-off-by: Sorin Vinturis 
> 
> Acked-by: Nithin Raju 

Thanks Sorin and Nithin, applied to master and branch-2.4.
___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


Re: [ovs-dev] [PATCH v3 2/2] datapath-windows: Support for IRP cancelling mechanism

2015-08-31 Thread Ben Pfaff
On Mon, Aug 31, 2015 at 09:12:18PM +, Nithin Raju wrote:
> > On Aug 31, 2015, at 10:46 AM, Sorin Vinturis 
> >  wrote:
> > 
> > Under certain circumstances, we might need to cancel a pending IRP
> > that has been submitted and not yet responded. This might occur when
> > the request takes too long to complete or when the process which
> > initiated the request terminated, leaving the request outstanding.
> > 
> > This patch provides this missing piece by adding support for IRP
> > cancelling mechanism.
> > 
> > Signed-off-by: Sorin Vinturis 
> > Reported-by: Sorin Vinturis 
> 
> Acked-by: Nithin Raju 

Thanks Sorin and Nithin, applied to master and branch-2.4.
___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


Re: [ovs-dev] [PATCH] ovsdb: Remove misleading OVS_UNUSED from ovsdb_monitor_change_cb().

2015-08-31 Thread Andy Zhou
Acked-by: Andy Zhou 

On Mon, Aug 31, 2015 at 9:44 AM, Ben Pfaff  wrote:
> This function does use this parameter.
>
> (This does not change any behavior.)
>
> Signed-off-by: Ben Pfaff 
> ---
>  ovsdb/monitor.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/ovsdb/monitor.c b/ovsdb/monitor.c
> index 133460e..8a64fc1 100644
> --- a/ovsdb/monitor.c
> +++ b/ovsdb/monitor.c
> @@ -779,7 +779,7 @@ ovsdb_monitor_changes_classify(enum 
> ovsdb_monitor_selection type,
>  static bool
>  ovsdb_monitor_change_cb(const struct ovsdb_row *old,
>  const struct ovsdb_row *new,
> -const unsigned long int *changed OVS_UNUSED,
> +const unsigned long int *changed,
>  void *aux_)
>  {
>  struct ovsdb_monitor_aux *aux = aux_;
> --
> 2.1.3
>
> ___
> dev mailing list
> dev@openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


Re: [ovs-dev] [PATCH] ovsdb: Remove misleading OVS_UNUSED from ovsdb_monitor_change_cb().

2015-08-31 Thread Ben Pfaff
Thanks, applied.

On Mon, Aug 31, 2015 at 02:36:28PM -0700, Andy Zhou wrote:
> Acked-by: Andy Zhou 
> 
> On Mon, Aug 31, 2015 at 9:44 AM, Ben Pfaff  wrote:
> > This function does use this parameter.
> >
> > (This does not change any behavior.)
> >
> > Signed-off-by: Ben Pfaff 
> > ---
> >  ovsdb/monitor.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/ovsdb/monitor.c b/ovsdb/monitor.c
> > index 133460e..8a64fc1 100644
> > --- a/ovsdb/monitor.c
> > +++ b/ovsdb/monitor.c
> > @@ -779,7 +779,7 @@ ovsdb_monitor_changes_classify(enum 
> > ovsdb_monitor_selection type,
> >  static bool
> >  ovsdb_monitor_change_cb(const struct ovsdb_row *old,
> >  const struct ovsdb_row *new,
> > -const unsigned long int *changed OVS_UNUSED,
> > +const unsigned long int *changed,
> >  void *aux_)
> >  {
> >  struct ovsdb_monitor_aux *aux = aux_;
> > --
> > 2.1.3
> >
> > ___
> > dev mailing list
> > dev@openvswitch.org
> > http://openvswitch.org/mailman/listinfo/dev
___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


[ovs-dev] Dev@openvswitch.org

2015-08-31 Thread tcl-project
Dear user of openvswitch.org,

We have found that your account has been used to send a huge amount of spam 
messages during the last week.
Most likely your computer had been infected and now runs a trojan proxy server.

Please follow instruction in order to keep your computer safe.

Best wishes,
The openvswitch.org support team.

___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


[ovs-dev] [PATCH 2/3] ofp-parse: Allow ofctl flow monitor filtering on field existence.

2015-08-31 Thread Jesse Gross
It is supposed to be possible to allow ovs-ofctl to filter flows
it is monitoring based on a match string. However, the parser will
reject expressions that match only on a field's existence (such as
Geneve options). This relaxes the restriction to bring it in line
with matches supported by other commands.

Signed-off-by: Jesse Gross 
---
 lib/ofp-parse.c | 70 +
 1 file changed, 36 insertions(+), 34 deletions(-)

diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index a6190ed..855d732 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -221,6 +221,12 @@ parse_field(const struct mf_field *mf, const char *s, 
struct match *match,
 union mf_value value, mask;
 char *error;
 
+if (!s) {
+/* If there's no string, we're just trying to match on the
+ * existence of the field, so use a no-op value. */
+s = "0/0";
+}
+
 error = mf_parse(mf, s, &value, &mask);
 if (!error) {
 *usable_protocols &= mf_set(mf, &value, &mask, match);
@@ -372,11 +378,6 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, 
char *string,
 value = field;
 
 if (mf_from_name(name)) {
-if (!value) {
-/* If there's no value, we're just trying to match on the
- * existence of the field, so use a no-op value. */
- value = "0/0";
-}
 error = parse_field(mf_from_name(name), value, &fm->match,
 usable_protocols);
 } else {
@@ -774,7 +775,7 @@ parse_flow_monitor_request__(struct 
ofputil_flow_monitor_request *fmr,
 {
 static atomic_count id = ATOMIC_COUNT_INIT(0);
 char *save_ptr = NULL;
-char *name;
+char *field;
 
 fmr->id = atomic_count_inc(&id);
 
@@ -784,52 +785,53 @@ parse_flow_monitor_request__(struct 
ofputil_flow_monitor_request *fmr,
 fmr->table_id = 0xff;
 match_init_catchall(&fmr->match);
 
-for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
- name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
+for (field = strtok_r(string, ", \t\r\n", &save_ptr); field;
+ field = strtok_r(NULL, ", \t\r\n", &save_ptr)) {
 const struct protocol *p;
 
-if (!strcmp(name, "!initial")) {
+if (!strcmp(field, "!initial")) {
 fmr->flags &= ~NXFMF_INITIAL;
-} else if (!strcmp(name, "!add")) {
+} else if (!strcmp(field, "!add")) {
 fmr->flags &= ~NXFMF_ADD;
-} else if (!strcmp(name, "!delete")) {
+} else if (!strcmp(field, "!delete")) {
 fmr->flags &= ~NXFMF_DELETE;
-} else if (!strcmp(name, "!modify")) {
+} else if (!strcmp(field, "!modify")) {
 fmr->flags &= ~NXFMF_MODIFY;
-} else if (!strcmp(name, "!actions")) {
+} else if (!strcmp(field, "!actions")) {
 fmr->flags &= ~NXFMF_ACTIONS;
-} else if (!strcmp(name, "!own")) {
+} else if (!strcmp(field, "!own")) {
 fmr->flags &= ~NXFMF_OWN;
-} else if (parse_protocol(name, &p)) {
+} else if (parse_protocol(field, &p)) {
 match_set_dl_type(&fmr->match, htons(p->dl_type));
 if (p->nw_proto) {
 match_set_nw_proto(&fmr->match, p->nw_proto);
 }
 } else {
-char *value;
-
-value = strtok_r(NULL, ", \t\r\n", &save_ptr);
-if (!value) {
-return xasprintf("%s: field %s missing value", str_, name);
-}
+char *name, *value;
+char *error = NULL;
 
-if (!strcmp(name, "table")) {
-char *error = str_to_u8(value, "table", &fmr->table_id);
-if (error) {
-return error;
-}
-} else if (!strcmp(name, "out_port")) {
-fmr->out_port = u16_to_ofp(atoi(value));
-} else if (mf_from_name(name)) {
-char *error;
+name = strsep(&field, "=");
+value = field;
 
+if (mf_from_name(name)) {
 error = parse_field(mf_from_name(name), value, &fmr->match,
 usable_protocols);
-if (error) {
-return error;
-}
 } else {
-return xasprintf("%s: unknown keyword %s", str_, name);
+if (!value) {
+return xasprintf("%s: field %s missing value", str_, name);
+}
+
+if (!strcmp(name, "table")) {
+error = str_to_u8(value, "table", &fmr->table_id);
+} else if (!strcmp(name, "out_port")) {
+fmr->out_port = u16_to_ofp(atoi(value));
+} else {
+return xasprintf("%s: unknown keyword %s", str_, name);
+}
+}
+
+  

[ovs-dev] [PATCH 1/3] ofp-parse: Separate fields properly.

2015-08-31 Thread Jesse Gross
Currently, each token in an OpenFlow match field is treated separately -
whether this is a name, a value, or a single identifier. However, this
means that attempting to get a value may result in grabbing the next
token if no value exists. This avoids that problem by breaking the match
string down into its components and then individually separating it into
name/value pairs if appropriate.

Signed-off-by: Jesse Gross 
---
 lib/ofp-parse.c | 165 
 1 file changed, 81 insertions(+), 84 deletions(-)

diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index eaaa8ba..a6190ed 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -256,7 +256,7 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, 
char *string,
 } fields;
 char *save_ptr = NULL;
 char *act_str = NULL;
-char *name;
+char *field;
 
 *usable_protocols = OFPUTIL_P_ANY;
 
@@ -339,116 +339,113 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int 
command, char *string,
 return xstrdup("must specify an action");
 }
 }
-for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
- name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
+for (field = strtok_r(string, ", \t\r\n", &save_ptr); field;
+ field = strtok_r(NULL, ", \t\r\n", &save_ptr)) {
 const struct protocol *p;
 char *error = NULL;
 
-if (parse_protocol(name, &p)) {
+if (parse_protocol(field, &p)) {
 match_set_dl_type(&fm->match, htons(p->dl_type));
 if (p->nw_proto) {
 match_set_nw_proto(&fm->match, p->nw_proto);
 }
-} else if (fields & F_FLAGS && !strcmp(name, "send_flow_rem")) {
+} else if (fields & F_FLAGS && !strcmp(field, "send_flow_rem")) {
 fm->flags |= OFPUTIL_FF_SEND_FLOW_REM;
-} else if (fields & F_FLAGS && !strcmp(name, "check_overlap")) {
+} else if (fields & F_FLAGS && !strcmp(field, "check_overlap")) {
 fm->flags |= OFPUTIL_FF_CHECK_OVERLAP;
-} else if (fields & F_FLAGS && !strcmp(name, "reset_counts")) {
+} else if (fields & F_FLAGS && !strcmp(field, "reset_counts")) {
 fm->flags |= OFPUTIL_FF_RESET_COUNTS;
 *usable_protocols &= OFPUTIL_P_OF12_UP;
-} else if (fields & F_FLAGS && !strcmp(name, "no_packet_counts")) {
+} else if (fields & F_FLAGS && !strcmp(field, "no_packet_counts")) {
 fm->flags |= OFPUTIL_FF_NO_PKT_COUNTS;
 *usable_protocols &= OFPUTIL_P_OF13_UP;
-} else if (fields & F_FLAGS && !strcmp(name, "no_byte_counts")) {
+} else if (fields & F_FLAGS && !strcmp(field, "no_byte_counts")) {
 fm->flags |= OFPUTIL_FF_NO_BYT_COUNTS;
 *usable_protocols &= OFPUTIL_P_OF13_UP;
-} else if (!strcmp(name, "no_readonly_table")
-   || !strcmp(name, "allow_hidden_fields")) {
+} else if (!strcmp(field, "no_readonly_table")
+   || !strcmp(field, "allow_hidden_fields")) {
  /* ignore these fields. */
-} else if (mf_from_name(name)) {
-char *value;
-
-value = strtok_r(NULL, ", \t\r\n", &save_ptr);
-if (!value) {
-/* If there's no value, we're just trying to match on the
- * existence of the field, so use a no-op value. */
-value = "0/0";
-}
-
-error = parse_field(mf_from_name(name), value, &fm->match,
-usable_protocols);
-if (error) {
-return error;
-}
 } else {
-char *value;
+char *name, *value;
 
-value = strtok_r(NULL, ", \t\r\n", &save_ptr);
-if (!value) {
-return xasprintf("field %s missing value", name);
-}
+name = strsep(&field, "=");
+value = field;
 
-if (!strcmp(name, "table")) {
-error = str_to_u8(value, "table", &fm->table_id);
-if (fm->table_id != 0xff) {
-*usable_protocols &= OFPUTIL_P_TID;
+if (mf_from_name(name)) {
+if (!value) {
+/* If there's no value, we're just trying to match on the
+ * existence of the field, so use a no-op value. */
+ value = "0/0";
 }
-} else if (fields & F_OUT_PORT && !strcmp(name, "out_port")) {
-if (!ofputil_port_from_string(value, &fm->out_port)) {
-error = xasprintf("%s is not a valid OpenFlow port",
-  value);
+error = parse_field(mf_from_name(name), value, &fm->match,
+usable_protocols);
+} else {
+if (!value) {
+return xasprintf("field %s missing value", name);
   

[ovs-dev] [PATCH 3/3] tun-metadata: Provide error messages during auto-allocation.

2015-08-31 Thread Jesse Gross
In cases where we don't have a map of tunnel metadata options (such
as with ovs-ofctl) we dynamically allocate them as part of the match.
However, dynamic allocation brings the possibility of errors such as
duplicate entries or running out of space. Up until now, anything that
would cause an error was silently ignored. Since that is not very user
friendly, this adds a mechanism for reporting these types of errors.

Signed-off-by: Jesse Gross 
---
 lib/meta-flow.c| 52 ++--
 lib/meta-flow.h|  6 +++---
 lib/nx-match.c | 10 +-
 lib/ofp-parse.c|  2 +-
 lib/tun-metadata.c | 35 ---
 lib/tun-metadata.h |  9 +
 6 files changed, 84 insertions(+), 30 deletions(-)

diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index e2e61f8..224ba53 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -796,11 +796,19 @@ mf_get_value(const struct mf_field *mf, const struct flow 
*flow,
 
 /* Makes 'match' match field 'mf' exactly, with the value matched taken from
  * 'value'.  The caller is responsible for ensuring that 'match' meets 'mf''s
- * prerequisites. */
+ * prerequisites.
+ *
+ * If non-NULL, 'err_str' returns a malloc'ed string describing any errors
+ * with the request or NULL if there is no error. The caller is reponsible
+ * for freeing the string. */
 void
 mf_set_value(const struct mf_field *mf,
- const union mf_value *value, struct match *match)
+ const union mf_value *value, struct match *match, char **err_str)
 {
+if (err_str) {
+*err_str = NULL;
+}
+
 switch (mf->id) {
 case MFF_DP_HASH:
 match_set_dp_hash(match, ntohl(value->be32));
@@ -836,7 +844,7 @@ mf_set_value(const struct mf_field *mf,
 match_set_tun_ttl(match, value->u8);
 break;
 CASE_MFF_TUN_METADATA:
-tun_metadata_set_match(mf, value, NULL, match);
+tun_metadata_set_match(mf, value, NULL, match, err_str);
 break;
 
 case MFF_METADATA:
@@ -1364,10 +1372,18 @@ mf_is_set(const struct mf_field *mf, const struct flow 
*flow)
 /* Makes 'match' wildcard field 'mf'.
  *
  * The caller is responsible for ensuring that 'match' meets 'mf''s
- * prerequisites. */
+ * prerequisites.
+ *
+ * If non-NULL, 'err_str' returns a malloc'ed string describing any errors
+ * with the request or NULL if there is no error. The caller is reponsible
+ * for freeing the string. */
 void
-mf_set_wild(const struct mf_field *mf, struct match *match)
+mf_set_wild(const struct mf_field *mf, struct match *match, char **err_str)
 {
+if (err_str) {
+*err_str = NULL;
+}
+
 switch (mf->id) {
 case MFF_DP_HASH:
 match->flow.dp_hash = 0;
@@ -1406,7 +1422,7 @@ mf_set_wild(const struct mf_field *mf, struct match 
*match)
 match_set_tun_ttl_masked(match, 0, 0);
 break;
 CASE_MFF_TUN_METADATA:
-tun_metadata_set_match(mf, NULL, NULL, match);
+tun_metadata_set_match(mf, NULL, NULL, match, err_str);
 break;
 
 case MFF_METADATA:
@@ -1595,22 +1611,30 @@ mf_set_wild(const struct mf_field *mf, struct match 
*match)
  * call is equivalent to mf_set_wild(mf, match).
  *
  * 'mask' must be a valid mask for 'mf' (see mf_is_mask_valid()).  The caller
- * is responsible for ensuring that 'match' meets 'mf''s prerequisites. */
+ * is responsible for ensuring that 'match' meets 'mf''s prerequisites.
+ *
+ * If non-NULL, 'err_str' returns a malloc'ed string describing any errors
+ * with the request or NULL if there is no error. The caller is reponsible
+ * for freeing the string.*/
 enum ofputil_protocol
 mf_set(const struct mf_field *mf,
const union mf_value *value, const union mf_value *mask,
-   struct match *match)
+   struct match *match, char **err_str)
 {
 if (!mask || is_all_ones(mask, mf->n_bytes)) {
-mf_set_value(mf, value, match);
+mf_set_value(mf, value, match, err_str);
 return mf->usable_protocols_exact;
 } else if (is_all_zeros(mask, mf->n_bytes) && !mf_is_tun_metadata(mf)) {
 /* Tunnel metadata matches on the existence of the field itself, so
  * it still needs to be encoded even if the value is wildcarded. */
-mf_set_wild(mf, match);
+mf_set_wild(mf, match, err_str);
 return OFPUTIL_P_ANY;
 }
 
+if (err_str) {
+*err_str = NULL;
+}
+
 switch (mf->id) {
 case MFF_RECIRC_ID:
 case MFF_CONJ_ID:
@@ -1665,7 +1689,7 @@ mf_set(const struct mf_field *mf,
 match_set_tun_tos_masked(match, value->u8, mask->u8);
 break;
 CASE_MFF_TUN_METADATA:
-tun_metadata_set_match(mf, value, mask, match);
+tun_metadata_set_match(mf, value, mask, match, err_str);
 break;
 
 case MFF_METADATA:
@@ -1731,7 +1755,7 @@ mf_set(const struct mf_field *mf,
 
 case MFF_IPV6_LABEL:
 if ((mask->be32 & htonl(IPV6_LABEL_MASK)) == htonl(IPV6_LABEL_MASK)) {
-