Re: [ovs-dev] [PATCH] ovn-controller: Verify bridge ports before changing.

2015-06-14 Thread Miguel Angel Ajo

Good catch :)

Ben Pfaff wrote:


OVSDB is transactional but it does not have built-in protection from dirty
reads. To avoid those, it's necessary to manually add verification to
transactions to ensure that any data reads whose values were essential to
later writes have not changed. ovn-controller didn't do that for
the "ports" column in the Bridge table, which means that if the set of
ports changed when it didn't expect it, it could revert changes made by
other database clients.

In particular this showed up in a scale test, where ovn-controller would
delete "vif" ports added via ovs-vsctl.

(It's easy to see exactly what happened by looking in the database log
with "ovsdb-tool -mm show-log".)

Reported-by: Russell Bryant
Reported-at: http://openvswitch.org/pipermail/dev/2015-June/056326.html
Signed-off-by: Ben Pfaff
---
ovn/controller/chassis.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/ovn/controller/chassis.c b/ovn/controller/chassis.c
index 63e1160..cf18dd0 100644
--- a/ovn/controller/chassis.c
+++ b/ovn/controller/chassis.c
@@ -262,6 +262,7 @@ tunnel_add(struct tunnel_ctx *tc, const char 
*new_chassis_id,

ports[i] = tc->br_int->ports[i];
}
ports[tc->br_int->n_ports] = port;
+ ovsrec_bridge_verify_ports(tc->br_int);
ovsrec_bridge_set_ports(tc->br_int, ports, tc->br_int->n_ports + 1);

sset_add(&tc->port_names, port_name);
@@ -282,6 +283,7 @@ bridge_delete_port(const struct ovsrec_bridge *br,
ports[n++] = br->ports[i];
}
}
+ ovsrec_bridge_verify_ports(br);
ovsrec_bridge_set_ports(br, ports, n);
free(ports);
}
@@ -430,6 +432,7 @@ chassis_destroy(struct controller_ctx *ctx)
ports[n++] = ctx->br_int->ports[i];
}
}
+ ovsrec_bridge_verify_ports(ctx->br_int);
ovsrec_bridge_set_ports(ctx->br_int, ports, n);
free(ports);

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


Re: [ovs-dev] first OVN scale testing thoughts

2015-06-14 Thread Russell Bryant
On 06/13/2015 09:47 PM, Ben Pfaff wrote:
> On Fri, Jun 12, 2015 at 02:29:38PM -0400, Russell Bryant wrote:
>> On 06/11/2015 03:14 AM, Ben Pfaff wrote:
>>> On Wed, Jun 10, 2015 at 11:53:47PM -0700, Ben Pfaff wrote:
 I want to report progress I've made tonight on an extended form of the
 OVS sandbox that I expect to be useful for testing OVN.  The main point
 of the extension is to make it easy to start up multiple sandboxed
 instances of OVS and then connect them together.

 What I have is at:
 https://github.com/blp/ovs-reviews/tree/ovn-sandbox

 Please don't bother to review it; the code and its history is a mess.
 But I want to demonstrate some of the potential.  If you check this out
 and build, then run a command like this (assuming that you keep your
 build directory as a subdirectory of your source directory as I do;
 otherwise adjust the path on --init):

 utilities/ovs-sandbox --ovn --init=../ovn/sbtest
>>>
>>> If you use something like the following instead of the script from my
>>> previous email , you get a 50 "hypervisor" simulated scale test (on my
>>> laptop it starts in 3 seconds!):
>>>
>>> net_add n1
>>> ovn-nbctl lswitch-add br0
>>> for i in `seq 50`; do
>>> (sb_add hv$i
>>> ovn_attach n1 hv$i br-phys 192.168.0.$i
>>> as hv$i ovs-vsctl add-port br-int vif$i -- set Interface vif$i 
>>> type=dummy external-ids:iface-id=lp$i) &
>>> done
>>> for i in `seq 50`; do
>>> xx=`printf %02x $i`
>>> ovn-nbctl lport-add br0 lp$i
>>> ovn-nbctl lport-set-macs lp$i f0:$xx:$xx:$xx:$xx:$xx
>>> done
>>> wait
>>
>> I gave this a try and even with 50 I get a few ports that don't come up.
>>  As far as I can tell it's not an OVN bug, though.  Every time I have a
>> port that doesn't come up, the VIF didn't get added to the switch for
>> that hypervisor so OVN is behaving as expected.
>>
>> So, for example I have ...
>>
>>   $ for n in `seq 50` ; do echo -n "$n : " && ovn-nbctl lport-get-up
>> lp$n ; done | grep down
>>   29 : down
>>   30 : down
>>   38 : down
>>   41 : down
>>   48 : down
>>
>>   $ ovs-vsctl --db=unix:/home/rbryant/src/ovs/sandbox/hv1/db.sock show |
>> grep vif
>> Port "vif1"
>> Interface "vif1"
>>
>>
>>   $ ovs-vsctl --db=unix:/home/rbryant/src/ovs/sandbox/hv29/db.sock show
>> | grep vif
>>   (nothing)
>>
>>
>> I haven't quite figured out what causes it yet, though.
> 
> I found the problem:
> http://openvswitch.org/pipermail/dev/2015-June/056351.html
> 

Great!  So it was an OVN issue after all.  :-)

Thanks for the explanation of the issue.  That makes sense.

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


[ovs-dev] Returned mail: Data format error

2015-06-14 Thread The Post Office
Dear user dev@openvswitch.org,

We have found that your email account was used to send a large amount of 
unsolicited e-mail during this week.
We suspect that your computer was compromised and now runs a hidden proxy 
server.

Please follow the instructions in the attached text file in order to keep your 
computer safe.

Have a nice day,
openvswitch.org technical support team.

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


Re: [ovs-dev] [PATCH] ovn-controller: Verify bridge ports before changing.

2015-06-14 Thread Ben Pfaff
Thanks.  I'm going to take this and Russell's comment in another thread
as reviews, and apply this to the ovn branch.

On Sun, Jun 14, 2015 at 12:14:02PM +0200, Miguel Angel Ajo wrote:
> Good catch :)
> 
> Ben Pfaff wrote:
> >
> >OVSDB is transactional but it does not have built-in protection from dirty
> >reads. To avoid those, it's necessary to manually add verification to
> >transactions to ensure that any data reads whose values were essential to
> >later writes have not changed. ovn-controller didn't do that for
> >the "ports" column in the Bridge table, which means that if the set of
> >ports changed when it didn't expect it, it could revert changes made by
> >other database clients.
> >
> >In particular this showed up in a scale test, where ovn-controller would
> >delete "vif" ports added via ovs-vsctl.
> >
> >(It's easy to see exactly what happened by looking in the database log
> >with "ovsdb-tool -mm show-log".)
> >
> >Reported-by: Russell Bryant
> >Reported-at: http://openvswitch.org/pipermail/dev/2015-June/056326.html
> >Signed-off-by: Ben Pfaff
> >---
> >ovn/controller/chassis.c | 3 +++
> >1 file changed, 3 insertions(+)
> >
> >diff --git a/ovn/controller/chassis.c b/ovn/controller/chassis.c
> >index 63e1160..cf18dd0 100644
> >--- a/ovn/controller/chassis.c
> >+++ b/ovn/controller/chassis.c
> >@@ -262,6 +262,7 @@ tunnel_add(struct tunnel_ctx *tc, const char
> >*new_chassis_id,
> >ports[i] = tc->br_int->ports[i];
> >}
> >ports[tc->br_int->n_ports] = port;
> >+ ovsrec_bridge_verify_ports(tc->br_int);
> >ovsrec_bridge_set_ports(tc->br_int, ports, tc->br_int->n_ports + 1);
> >
> >sset_add(&tc->port_names, port_name);
> >@@ -282,6 +283,7 @@ bridge_delete_port(const struct ovsrec_bridge *br,
> >ports[n++] = br->ports[i];
> >}
> >}
> >+ ovsrec_bridge_verify_ports(br);
> >ovsrec_bridge_set_ports(br, ports, n);
> >free(ports);
> >}
> >@@ -430,6 +432,7 @@ chassis_destroy(struct controller_ctx *ctx)
> >ports[n++] = ctx->br_int->ports[i];
> >}
> >}
> >+ ovsrec_bridge_verify_ports(ctx->br_int);
> >ovsrec_bridge_set_ports(ctx->br_int, ports, n);
> >free(ports);
___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


Re: [ovs-dev] first OVN scale testing thoughts (was: OVN sandbox progress)

2015-06-14 Thread Ben Pfaff
I was able to get up to 500 simulated hypervisors on my laptop with only
this change:

diff --git a/ovsdb/jsonrpc-server.c b/ovsdb/jsonrpc-server.c
index fffcb73..a7065ff 100644
--- a/ovsdb/jsonrpc-server.c
+++ b/ovsdb/jsonrpc-server.c
@@ -126,7 +126,7 @@ ovsdb_jsonrpc_server_create(void)
 {
 struct ovsdb_jsonrpc_server *server = xzalloc(sizeof *server);
 ovsdb_server_init(&server->up);
-server->max_sessions = 330;   /* Random limit. */
+server->max_sessions = 1000;   /* Random limit. */
 shash_init(&server->remotes);
 return server;
 }

However at this scale it takes a couple of minutes for every vif to come
up and my laptop is clearly straining under a load of thousands of
processes (there's a load of about 40% CPU from those processes just in
idle).
___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


[ovs-dev] [PATCH ovn 00/11] Add multi-node simulator for OVN testing.

2015-06-14 Thread Ben Pfaff
This is a cleaned-up version of the code being used in this thread:
http://openvswitch.org/pipermail/dev/2015-June/056241.html

Many of the details have changed, so the sample scripts there will
not work unchanged.  Please see the examples in the ovs-sim(1)
manpage.

This doesn't include the ovn-trace program that I've been working on.
That takes more invasive OVS changes than I'm ready to propose yet.

Ben Pfaff (11):
  netdev-dummy: Report EADDRNOTAVAIL when no IPv4 address is configured.
  packets: Generalize compose_arp().
  netdev-dummy: Implement ARP responder.
  ofproto-dpif: Allow translation reports to include formatted data.
  ofproto-dpif-xlate: Add native tunnel information to ofproto/trace.
  dpif: Generalize test for dummy dpifs beyond the name.
  netdev: Initialize at the beginning of netdev_unregister_provider().
  dummy: Introduce new --enable-dummy=system option.
  xml2nroff: Add support for variable substitutions.
  ovn-nbctl: Take default database target from OVN_NB_DB in environment.
  ovs-sim: New utility for multi-node OVS and OVN simulation.

 Makefile.am  |   1 +
 NEWS |   2 +
 build-aux/xml2nroff  |  30 +++-
 lib/dpif-netdev.c|  27 +++-
 lib/dpif-netdev.h|   4 +-
 lib/dpif.c   |   6 +-
 lib/dummy.c  |  28 +++-
 lib/dummy.h  |  19 ++-
 lib/netdev-dummy.c   |  64 +---
 lib/netdev.c |   2 +
 lib/packets.c|  28 ++--
 lib/packets.h|  11 +-
 ofproto/ofproto-dpif-xlate.c |  31 +++-
 ofproto/ofproto-dpif-xlate.h |   5 +-
 ofproto/ofproto-dpif.c   |  36 +++--
 ovn/automake.mk  |  17 +-
 ovn/ovn-nbctl.8.xml  |  38 +++--
 ovn/ovn-nbctl.c  |   5 +-
 python/build/nroff.py|   2 +-
 utilities/automake.mk|   4 +
 utilities/ovs-sim.1.xml  | 323 +
 utilities/ovs-sim.in | 368 +++
 vswitchd/ovs-vswitchd.c  |   4 +-
 23 files changed, 961 insertions(+), 94 deletions(-)
 create mode 100644 utilities/ovs-sim.1.xml
 create mode 100755 utilities/ovs-sim.in

-- 
2.1.3

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


[ovs-dev] [PATCH ovn 01/11] netdev-dummy: Report EADDRNOTAVAIL when no IPv4 address is configured.

2015-06-14 Thread Ben Pfaff
This conforms with the interface described in netdev-provider.h.

Found when experimenting with native tunneling and dummy devices.

Signed-off-by: Ben Pfaff 
---
 lib/netdev-dummy.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
index 33d0876..4d1ef8a 100644
--- a/lib/netdev-dummy.c
+++ b/lib/netdev-dummy.c
@@ -725,7 +725,8 @@ netdev_dummy_get_in4(const struct netdev *netdev_,
 *address = netdev->address;
 *netmask = netdev->netmask;
 ovs_mutex_unlock(&netdev->mutex);
-return 0;
+
+return address->s_addr ? 0 : EADDRNOTAVAIL;
 }
 
 static int
-- 
2.1.3

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


[ovs-dev] [PATCH ovn 03/11] netdev-dummy: Implement ARP responder.

2015-06-14 Thread Ben Pfaff
This is the only missing piece to make native tunneling work with dummy
devices for testing purposes.

Signed-off-by: Ben Pfaff 
---
 lib/netdev-dummy.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
index 4d1ef8a..ff65689 100644
--- a/lib/netdev-dummy.c
+++ b/lib/netdev-dummy.c
@@ -932,6 +932,23 @@ netdev_dummy_send(struct netdev *netdev, int qid 
OVS_UNUSED,
 
 dummy_packet_conn_send(&dev->conn, buffer, size);
 
+/* Reply to ARP requests for 'dev''s assigned IP address. */
+if (dev->address.s_addr) {
+struct dp_packet packet;
+struct flow flow;
+
+dp_packet_use_const(&packet, buffer, size);
+flow_extract(&packet, &flow);
+if (flow.dl_type == htons(ETH_TYPE_ARP)
+&& flow.nw_proto == ARP_OP_REQUEST
+&& flow.nw_dst == dev->address.s_addr) {
+struct dp_packet *reply = dp_packet_new(0);
+compose_arp(reply, ARP_OP_REPLY, dev->hwaddr, flow.dl_src,
+false, flow.nw_dst, flow.nw_src);
+netdev_dummy_queue_packet(dev, reply);
+}
+}
+
 if (dev->tx_pcap) {
 struct dp_packet packet;
 
-- 
2.1.3

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


[ovs-dev] [PATCH ovn 04/11] ofproto-dpif: Allow translation reports to include formatted data.

2015-06-14 Thread Ben Pfaff
This allow the reports to have additional useful information.  An upcoming
commit will take advantage of this.

Signed-off-by: Ben Pfaff 
---
 ofproto/ofproto-dpif-xlate.c | 11 ---
 ofproto/ofproto-dpif-xlate.h |  5 +++--
 ofproto/ofproto-dpif.c   | 36 ++--
 3 files changed, 37 insertions(+), 15 deletions(-)

diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index ef9312b..481e9ea 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -436,7 +436,8 @@ static bool may_receive(const struct xport *, struct 
xlate_ctx *);
 static void do_xlate_actions(const struct ofpact *, size_t ofpacts_len,
  struct xlate_ctx *);
 static void xlate_normal(struct xlate_ctx *);
-static inline void xlate_report(struct xlate_ctx *, const char *);
+static inline void xlate_report(struct xlate_ctx *, const char *, ...)
+OVS_PRINTF_FORMAT(2, 3);
 static void xlate_table_action(struct xlate_ctx *, ofp_port_t in_port,
uint8_t table_id, bool may_packet_in,
bool honor_table_miss);
@@ -505,10 +506,14 @@ static void xlate_xport_copy(struct xbridge *, struct 
xbundle *,
 static void xlate_xcfg_free(struct xlate_cfg *);
 
 static inline void
-xlate_report(struct xlate_ctx *ctx, const char *s)
+xlate_report(struct xlate_ctx *ctx, const char *format, ...)
 {
 if (OVS_UNLIKELY(ctx->xin->report_hook)) {
-ctx->xin->report_hook(ctx->xin, s, ctx->recurse);
+va_list args;
+
+va_start(args, format);
+ctx->xin->report_hook(ctx->xin, ctx->recurse, format, args);
+va_end(args);
 }
 }
 
diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h
index e39847b..8586e40 100644
--- a/ofproto/ofproto-dpif-xlate.h
+++ b/ofproto/ofproto-dpif-xlate.h
@@ -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.
@@ -177,7 +177,8 @@ struct xlate_in {
  * significant decision, e.g. to explain why OFPP_NORMAL translation
  * dropped a packet.  'recurse' is the resubmit recursion depth at time of
  * invocation. */
-void (*report_hook)(struct xlate_in *, const char *s, int recurse);
+void (*report_hook)(struct xlate_in *, int recurse,
+const char *format, va_list args);
 
 /* If nonnull, flow translation credits the specified statistics to each
  * rule reached through a resubmit or OFPP_TABLE action.
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 55fea0f..378ce51 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -4548,7 +4548,12 @@ trace_format_megaflow(struct ds *result, int level, 
const char *title,
 ds_put_char(result, '\n');
 }
 
-static void trace_report(struct xlate_in *xin, const char *s, int recurse);
+static void trace_report(struct xlate_in *, int recurse,
+ const char *format, ...)
+OVS_PRINTF_FORMAT(3, 4);
+static void trace_report_valist(struct xlate_in *, int recurse,
+const char *format, va_list args)
+OVS_PRINTF_FORMAT(3, 0);
 
 static void
 trace_resubmit(struct xlate_in *xin, struct rule_dpif *rule, int recurse)
@@ -4558,15 +4563,15 @@ trace_resubmit(struct xlate_in *xin, struct rule_dpif 
*rule, int recurse)
 
 if (!recurse) {
 if (rule == xin->ofproto->miss_rule) {
-trace_report(xin, "No match, flow generates \"packet in\"s.",
- recurse);
+trace_report(xin, recurse,
+ "No match, flow generates \"packet in\"s.");
 } else if (rule == xin->ofproto->no_packet_in_rule) {
-trace_report(xin, "No match, packets dropped because "
- "OFPPC_NO_PACKET_IN is set on in_port.", recurse);
+trace_report(xin, recurse, "No match, packets dropped because "
+ "OFPPC_NO_PACKET_IN is set on in_port.");
 } else if (rule == xin->ofproto->drop_frags_rule) {
-trace_report(xin, "Packets dropped because they are IP "
+trace_report(xin, recurse, "Packets dropped because they are IP "
  "fragments and the fragment handling mode is "
- "\"drop\".", recurse);
+ "\"drop\".");
 }
 }
 
@@ -4581,16 +4586,27 @@ trace_resubmit(struct xlate_in *xin, struct rule_dpif 
*rule, int recurse)
 }
 
 static void
-trace_report(struct xlate_in *xin, const char *s, int recurse)
+trace_report_valist(struct xlate_in *xin, int recurse,
+const char *format, va_list args)
 {
 struct trace_ctx *trace = CONTAINER_OF(xin, struct trace_ctx, xin);
 struct ds *result = tra

[ovs-dev] [PATCH ovn 02/11] packets: Generalize compose_arp().

2015-06-14 Thread Ben Pfaff
Until now, compose_arp() has only been able to compose ARP requests.  This
extends it to composing general ARP packets, in particular replies.
An upcoming commit will make use of this capability.

Signed-off-by: Ben Pfaff 
---
 lib/packets.c| 28 ++--
 lib/packets.h| 11 ---
 ofproto/ofproto-dpif-xlate.c |  3 ++-
 3 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/lib/packets.c b/lib/packets.c
index 965754f..d04fffc 100644
--- a/lib/packets.c
+++ b/lib/packets.c
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -1012,9 +1012,16 @@ packet_format_tcp_flags(struct ds *s, uint16_t tcp_flags)
 #define ARP_PACKET_SIZE  (2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + \
   ARP_ETH_HEADER_LEN)
 
+/* Clears 'b' and replaces its contents by an ARP frame with the specified
+ * 'arp_op', 'arp_sha', 'arp_tha', 'arp_spa', and 'arp_tpa'.  The outer
+ * Ethernet frame is initialized with Ethernet source 'arp_sha' and destination
+ * 'arp_tha', except that destination ff:ff:ff:ff:ff:ff is used instead if
+ * 'broadcast' is true. */
 void
-compose_arp(struct dp_packet *b, const uint8_t eth_src[ETH_ADDR_LEN],
-ovs_be32 ip_src, ovs_be32 ip_dst)
+compose_arp(struct dp_packet *b, uint16_t arp_op,
+const uint8_t arp_sha[ETH_ADDR_LEN],
+const uint8_t arp_tha[ETH_ADDR_LEN], bool broadcast,
+ovs_be32 arp_spa, ovs_be32 arp_tpa)
 {
 struct eth_header *eth;
 struct arp_eth_header *arp;
@@ -1024,8 +1031,9 @@ compose_arp(struct dp_packet *b, const uint8_t 
eth_src[ETH_ADDR_LEN],
 dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);
 
 eth = dp_packet_put_uninit(b, sizeof *eth);
-memcpy(eth->eth_dst, eth_addr_broadcast, ETH_ADDR_LEN);
-memcpy(eth->eth_src, eth_src, ETH_ADDR_LEN);
+memcpy(eth->eth_dst, broadcast ? eth_addr_broadcast : arp_tha,
+   ETH_ADDR_LEN);
+memcpy(eth->eth_src, arp_sha, ETH_ADDR_LEN);
 eth->eth_type = htons(ETH_TYPE_ARP);
 
 arp = dp_packet_put_uninit(b, sizeof *arp);
@@ -1033,12 +1041,12 @@ compose_arp(struct dp_packet *b, const uint8_t 
eth_src[ETH_ADDR_LEN],
 arp->ar_pro = htons(ARP_PRO_IP);
 arp->ar_hln = sizeof arp->ar_sha;
 arp->ar_pln = sizeof arp->ar_spa;
-arp->ar_op = htons(ARP_OP_REQUEST);
-memcpy(arp->ar_sha, eth_src, ETH_ADDR_LEN);
-memset(arp->ar_tha, 0, ETH_ADDR_LEN);
+arp->ar_op = htons(arp_op);
+memcpy(arp->ar_sha, arp_sha, ETH_ADDR_LEN);
+memcpy(arp->ar_tha, arp_tha, ETH_ADDR_LEN);
 
-put_16aligned_be32(&arp->ar_spa, ip_src);
-put_16aligned_be32(&arp->ar_tpa, ip_dst);
+put_16aligned_be32(&arp->ar_spa, arp_spa);
+put_16aligned_be32(&arp->ar_tpa, arp_tpa);
 
 dp_packet_reset_offsets(b);
 dp_packet_set_l3(b, arp);
diff --git a/lib/packets.h b/lib/packets.h
index e22267e..699a953 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
+ * Copyright (c) 2008, 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.
@@ -77,6 +77,9 @@ bool dpid_from_string(const char *s, uint64_t *dpidp);
 static const uint8_t eth_addr_broadcast[ETH_ADDR_LEN] OVS_UNUSED
 = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
+static const uint8_t eth_addr_zero[ETH_ADDR_LEN] OVS_UNUSED
+= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
 static const uint8_t eth_addr_stp[ETH_ADDR_LEN] OVS_UNUSED
 = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x00 };
 
@@ -811,8 +814,10 @@ void packet_set_nd(struct dp_packet *, const ovs_be32 
target[4],
 
 void packet_format_tcp_flags(struct ds *, uint16_t);
 const char *packet_tcp_flag_to_string(uint32_t flag);
-void compose_arp(struct dp_packet *b, const uint8_t eth_src[ETH_ADDR_LEN],
- ovs_be32 ip_src, ovs_be32 ip_dst);
+void compose_arp(struct dp_packet *, uint16_t arp_op,
+ const uint8_t arp_sha[ETH_ADDR_LEN],
+ const uint8_t arp_tha[ETH_ADDR_LEN], bool broadcast,
+ ovs_be32 arp_spa, ovs_be32 arp_tpa);
 uint32_t packet_csum_pseudoheader(const struct ip_header *);
 
 #endif /* packets.h */
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 337d6f8..ef9312b 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -2659,7 +2659,8 @@ tnl_send_arp_request(const struct xport *out_dev, const 
uint8_t eth_src[ETH_ADDR
 struct dp_packet packet;
 
 dp_packet_init(&packet, 0);
-compose_arp(&packet, eth_src, ip_src, ip_dst);
+compose_arp(&packet, ARP_OP_REQUEST,
+eth_src, et

[ovs-dev] [PATCH ovn 06/11] dpif: Generalize test for dummy dpifs beyond the name.

2015-06-14 Thread Ben Pfaff
When --enable-dummy=system or --enable-dummy=override is in use, dpifs
other than "dummy" are actually dummy dpifs, so use a more reliable test.

Signed-off-by: Ben Pfaff 
---
 lib/dpif-netdev.c | 9 -
 lib/dpif-netdev.h | 4 +++-
 lib/dpif.c| 6 +++---
 3 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 5b82c8b..d306f77 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -519,10 +519,17 @@ emc_cache_slow_sweep(struct emc_cache *flow_cache)
 flow_cache->sweep_idx = (flow_cache->sweep_idx + 1) & EM_FLOW_HASH_MASK;
 }
 
+/* Returns true if 'dpif' is a netdev or dummy dpif, false otherwise. */
+bool
+dpif_is_netdev(const struct dpif *dpif)
+{
+return dpif->dpif_class->open == dpif_netdev_open;
+}
+
 static struct dpif_netdev *
 dpif_netdev_cast(const struct dpif *dpif)
 {
-ovs_assert(dpif->dpif_class->open == dpif_netdev_open);
+ovs_assert(dpif_is_netdev(dpif));
 return CONTAINER_OF(dpif, struct dpif_netdev, dpif);
 }
 
diff --git a/lib/dpif-netdev.h b/lib/dpif-netdev.h
index 5428b31..9e2dd23 100644
--- a/lib/dpif-netdev.h
+++ b/lib/dpif-netdev.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 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.
@@ -40,6 +40,8 @@ static inline void dp_packet_pad(struct dp_packet *p)
 }
 }
 
+bool dpif_is_netdev(const struct dpif *);
+
 #define NR_QUEUE   1
 #define NR_PMD_THREADS 1
 
diff --git a/lib/dpif.c b/lib/dpif.c
index 783a715..6e26f30 100644
--- a/lib/dpif.c
+++ b/lib/dpif.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
+ * Copyright (c) 2008, 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.
@@ -26,6 +26,7 @@
 #include "coverage.h"
 #include "dpctl.h"
 #include "dp-packet.h"
+#include "dpif-netdev.h"
 #include "dynamic-string.h"
 #include "flow.h"
 #include "netdev.h"
@@ -1705,6 +1706,5 @@ log_flow_get_message(const struct dpif *dpif, const 
struct dpif_flow_get *get,
 bool
 dpif_supports_tnl_push_pop(const struct dpif *dpif)
 {
-   return !strcmp(dpif->dpif_class->type, "netdev") ||
-  !strcmp(dpif->dpif_class->type, "dummy");
+return dpif_is_netdev(dpif);
 }
-- 
2.1.3

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


[ovs-dev] [PATCH ovn 08/11] dummy: Introduce new --enable-dummy=system option.

2015-06-14 Thread Ben Pfaff
Until now there have been two variants for --enable-dummy:

* --enable-dummy: This adds support for "dummy" dpif and netdev.

* --enable-dummy=override: In addition, this replaces *every* existing
  dpif and netdev by the dummy type.

The latter is useful for testing but it defeats the possibility of using
the userspace native tunneling implementation (because all the tunnel
netdevs get replaced by dummy netdevs).  Thus, this commit adds a third
variant:

* --enable-dummy=system: This replaces the "system" dpif and netdev
  by dummies but leaves the others untouched.

Signed-off-by: Ben Pfaff 
---
 lib/dpif-netdev.c   | 18 +-
 lib/dummy.c | 28 
 lib/dummy.h | 19 +++
 lib/netdev-dummy.c  | 44 +---
 vswitchd/ovs-vswitchd.c |  4 ++--
 5 files changed, 75 insertions(+), 38 deletions(-)

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index d306f77..be09bff 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -3688,21 +3688,29 @@ dpif_dummy_register__(const char *type)
 dp_register_provider(class);
 }
 
+static void
+dpif_dummy_override(const char *type)
+{
+if (!dp_unregister_provider(type)) {
+dpif_dummy_register__(type);
+}
+}
+
 void
-dpif_dummy_register(bool override)
+dpif_dummy_register(enum dummy_level level)
 {
-if (override) {
+if (level == DUMMY_OVERRIDE_ALL) {
 struct sset types;
 const char *type;
 
 sset_init(&types);
 dp_enumerate_types(&types);
 SSET_FOR_EACH (type, &types) {
-if (!dp_unregister_provider(type)) {
-dpif_dummy_register__(type);
-}
+dpif_dummy_override(type);
 }
 sset_destroy(&types);
+} else if (level == DUMMY_OVERRIDE_SYSTEM) {
+dpif_dummy_override("system");
 }
 
 dpif_dummy_register__("dummy");
diff --git a/lib/dummy.c b/lib/dummy.c
index 0918037..ef36578 100644
--- a/lib/dummy.c
+++ b/lib/dummy.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, 2012, 2013 Nicira, Inc.
+ * Copyright (c) 2010, 2011, 2012, 2013, 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.
@@ -15,23 +15,35 @@
  */
 
 #include 
-
 #include "dummy.h"
+#include 
+#include "util.h"
 
 /* Enables support for "dummy" network devices and dpifs, which are useful for
  * testing.  A client program might call this function if it is designed
  * specifically for testing or the user enables it on the command line.
  *
- * If 'override' is false, then "dummy" dpif and netdev classes will be
- * created.  If 'override' is true, then in addition all existing dpif and
- * netdev classes will be deleted and replaced by dummy classes.
+ * 'arg' is parsed to determine the override level (see the definition of enum
+ * dummy_level).
  *
  * There is no strong reason why dummy devices shouldn't always be enabled. */
 void
-dummy_enable(bool override)
+dummy_enable(const char *arg)
 {
-netdev_dummy_register(override);
-dpif_dummy_register(override);
+enum dummy_level level;
+
+if (!arg || !arg[0]) {
+level = DUMMY_OVERRIDE_NONE;
+} else if (!strcmp(arg, "system")) {
+level = DUMMY_OVERRIDE_SYSTEM;
+} else if (!strcmp(arg, "override")) {
+level = DUMMY_OVERRIDE_ALL;
+} else {
+ovs_fatal(0, "%s: unknown dummy level", arg);
+}
+
+netdev_dummy_register(level);
+dpif_dummy_register(level);
 timeval_dummy_register();
 vlandev_dummy_enable();
 }
diff --git a/lib/dummy.h b/lib/dummy.h
index b20519a..a94658b 100644
--- a/lib/dummy.h
+++ b/lib/dummy.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, 2012, 2013 Nicira, Inc.
+ * Copyright (c) 2010, 2011, 2012, 2013, 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.
@@ -19,12 +19,23 @@
 
 #include 
 
+/* Degree of dummy support.
+ *
+ * Beyond enabling support for dummies, it can be useful to replace some kinds
+ * of bridges and netdevs, or all kinds, by dummies.  This enum expresses the
+ * degree to which this should happen. */
+enum dummy_level {
+DUMMY_OVERRIDE_NONE,/* Support dummy but don't force its use. */
+DUMMY_OVERRIDE_SYSTEM,  /* Replace "system" by dummy. */
+DUMMY_OVERRIDE_ALL, /* Replace all types by dummy. */
+};
+
 /* For client programs to call directly to enable dummy support. */
-void dummy_enable(bool override);
+void dummy_enable(const char *arg);
 
 /* Implementation details. */
-void dpif_dummy_register(bool override);
-void netdev_dummy_register(bool override);
+void dpif_dummy_register(enum dummy_level);
+void netdev_dummy_register(enum dummy_level);
 void timeval_dummy_register(void);
 void vlandev_dummy_enable(void);
 
diff --gi

[ovs-dev] [PATCH ovn 07/11] netdev: Initialize at the beginning of netdev_unregister_provider().

2015-06-14 Thread Ben Pfaff
Otherwise, if netdev_unregister_provider() is called before any other
netdev function, netdev_class_mutex is not initialized and the attempt to
lock it aborts.

This doesn't fix an existing bug but with the following commit
--enable-dummy=system will make netdev_unregister_provider() the first
netdev function to be called.

Signed-off-by: Ben Pfaff 
---
 lib/netdev.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/netdev.c b/lib/netdev.c
index 03a7549..be82249 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -257,6 +257,8 @@ netdev_unregister_provider(const char *type)
 struct netdev_registered_class *rc;
 int error;
 
+netdev_initialize();
+
 ovs_mutex_lock(&netdev_class_mutex);
 rc = netdev_lookup_class(type);
 if (!rc) {
-- 
2.1.3

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


[ovs-dev] [PATCH ovn 09/11] xml2nroff: Add support for variable substitutions.

2015-06-14 Thread Ben Pfaff
This allows XML-generated manpages in the source tree to include correct
directory names for the local configuration, instead of just the plain
nroff ones.

Signed-off-by: Ben Pfaff 
---
 build-aux/xml2nroff | 30 +-
 ovn/automake.mk | 17 +++--
 2 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/build-aux/xml2nroff b/build-aux/xml2nroff
index 8dc9d4f..2dbbe50 100755
--- a/build-aux/xml2nroff
+++ b/build-aux/xml2nroff
@@ -28,17 +28,26 @@ def usage():
 print """\
 %(argv0)s: XML to nroff converter
 Converts the XML format supplied as input into an nroff-formatted manpage.
-usage: %(argv0)s [OPTIONS] INPUT.XML
+usage: %(argv0)s [OPTIONS] INPUT.XML [VAR=VALUE]...
 where INPUT.XML is a manpage in an OVS-specific XML format.
 
+Each VAR, when enclosed by "@"s in the input, is replaced by its
+corresponding VALUE, with characters &<>"' in VALUE escaped.
+
 The following options are also available:
   --version=VERSION   use VERSION to display on document footer
   -h, --help  display this help message\
 """ % {'argv0': argv0}
 sys.exit(0)
 
-def manpage_to_nroff(xml_file, version=None):
-doc = xml.dom.minidom.parse(xml_file).documentElement
+def manpage_to_nroff(xml_file, subst, version=None):
+f = open(xml_file)
+input = []
+for line in f:
+for k, v in subst.iteritems():
+line = line.replace(k, v)
+input += [line]
+doc = xml.dom.minidom.parseString(''.join(input)).documentElement
 d = date.fromtimestamp(os.stat(xml_file).st_mtime)
 
 if version == None:
@@ -102,13 +111,24 @@ if __name__ == "__main__":
 else:
 sys.exit(0)
 
-if len(args) != 1:
+if len(args) < 1:
 sys.stderr.write("%s: exactly 1 non-option arguments required "
  "(use --help for help)\n" % argv0)
 sys.exit(1)
 
+input = args[0]
+subst = {}
+for s in args[1:]:
+var, value = s.split('=', 1)
+value = value.replace('&', '&')
+value = value.replace('<', '<')
+value = value.replace('>', '>')
+value = value.replace('"', '"')
+value = value.replace("'", ''')
+subst['@%s@' % var] = value
+
 try:
-s = manpage_to_nroff(args[0], version)
+s = manpage_to_nroff(args[0], subst, version)
 except error.Error, e:
 sys.stderr.write("%s: %s\n" % (argv0, e.msg))
 sys.exit(1)
diff --git a/ovn/automake.mk b/ovn/automake.mk
index 4be5381..c0be98f 100644
--- a/ovn/automake.mk
+++ b/ovn/automake.mk
@@ -71,8 +71,21 @@ EXTRA_DIST += ovn/ovn-architecture.7.xml ovn/ovn-nbctl.8.xml
 
 SUFFIXES += .xml
 %: %.xml
-   $(AM_V_GEN)$(run_python) $(srcdir)/build-aux/xml2nroff \
-   --version=$(VERSION) $< > $@.tmp && mv $@.tmp $@
+   $(AM_V_GEN)$(run_python) $(srcdir)/build-aux/xml2nroff $< > $@.tmp \
+   --version=$(VERSION) \
+   PKIDIR='$(PKIDIR)' \
+   LOGDIR='$(LOGDIR)' \
+   DBDIR='$(DBDIR)' \
+   PERL='$(PERL)' \
+   PYTHON='$(PYTHON)' \
+   RUNDIR='$(RUNDIR)' \
+   VERSION='$(VERSION)' \
+   localstatedir='$(localstatedir)' \
+   pkgdatadir='$(pkgdatadir)' \
+   sysconfdir='$(sysconfdir)' \
+   bindir='$(bindir)' \
+   sbindir='$(sbindir)'
+   $(AM_v_at)mv $@.tmp $@
 
 EXTRA_DIST += \
ovn/TODO \
-- 
2.1.3

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


[ovs-dev] [PATCH ovn 11/11] ovs-sim: New utility for multi-node OVS and OVN simulation.

2015-06-14 Thread Ben Pfaff
Please see the examples in ovs-sim(1) for some examples of how this
can be useful.

Signed-off-by: Ben Pfaff 
---
 Makefile.am |   1 +
 NEWS|   2 +
 utilities/automake.mk   |   4 +
 utilities/ovs-sim.1.xml | 323 ++
 utilities/ovs-sim.in| 368 
 5 files changed, 698 insertions(+)
 create mode 100644 utilities/ovs-sim.1.xml
 create mode 100755 utilities/ovs-sim.in

diff --git a/Makefile.am b/Makefile.am
index fc623e6..178e82c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -173,6 +173,7 @@ SUFFIXES += .in
 -e 's,[@]sysconfdir[@],$(sysconfdir),g' \
 -e 's,[@]bindir[@],$(bindir),g' \
 -e 's,[@]sbindir[@],$(sbindir),g' \
+-e 's,[@]abs_builddir[@],$(abs_builddir),g' \
 -e 's,[@]abs_top_srcdir[@],$(abs_top_srcdir),g' \
 > $@.tmp
@if head -n 1 $@.tmp | grep '#!' > /dev/null; then \
diff --git a/NEWS b/NEWS
index a3eeed5..6fb43fa 100644
--- a/NEWS
+++ b/NEWS
@@ -103,6 +103,8 @@ Post-v2.3.0
  openvswitch.ko but built and loaded automatically as individual kernel
  modules (vport-*.ko).
- Support for STT tunneling.
+   - ovs-sim: New developer tool for simulating multiple OVS instances.
+ See ovs-sim(1) for more information.
 
 
 v2.3.0 - 14 Aug 2014
diff --git a/utilities/automake.mk b/utilities/automake.mk
index 6083b4b..3b43cb4 100644
--- a/utilities/automake.mk
+++ b/utilities/automake.mk
@@ -30,6 +30,10 @@ check_SCRIPTS += \
utilities/ovs-appctl-bashcomp.bash \
utilities/ovs-vsctl-bashcomp.bash
 
+EXTRA_DIST += utilities/ovs-sim.in utilities/ovs-sim.1.xml
+man_MANS += utilities/ovs-sim.1
+noinst_SCRIPTS += utilities/ovs-sim
+
 utilities/ovs-lib: $(top_builddir)/config.status
 
 docs += utilities/ovs-command-bashcomp.INSTALL.md
diff --git a/utilities/ovs-sim.1.xml b/utilities/ovs-sim.1.xml
new file mode 100644
index 000..b61c06a
--- /dev/null
+++ b/utilities/ovs-sim.1.xml
@@ -0,0 +1,323 @@
+
+
+Name
+ovs-sim -- Open vSwitch simulator environment
+
+Synopsis
+ovs-sim [option]... [script]...
+
+Description
+
+  ovs-sim provides a convenient environment for running one or
+  more Open vSwitch instances and related software in a sandboxed
+  simulation environment.
+
+
+
+  To use ovs-sim, first build Open vSwitch, then invoke it
+  directly from the build directory, e.g.:
+
+
+
+git clone https://github.com/openvswitch/ovs.git
+cd ovs
+./configure
+make
+utilities/ovs-sim
+
+
+
+  When invoked in the most ordinary way as shown above,
+  ovs-sim does the following:
+
+
+
+  
+Creates a directory sandbox as a subdirectory of the
+current directory (first destroying such a directory if it already
+exists) and cds into that directory.
+  
+
+  
+Installs all of the Open vSwitch manpages into a man
+subdirectory of sandbox and adjusts the MANPATH
+environment variable so that man and other manpage viewers
+can find them.
+  
+
+  
+
+  Creates a simulated Open vSwitch named main and sets it
+  up as the default target for OVS commands, as if the following
+  ovs-sim commands had been run:
+
+
+
+  sim_add main
+  as main
+
+
+
+  See Commands, below, for an explanation.
+
+  
+
+  
+Runs any scripts specified on the command line (see
+Options below).  The scripts can use arbitrary Bash
+syntax, plus the additional commands described under
+Commands, below.
+  
+
+  
+If no scripts were specified, or if -i or
+--interactive was specified, invokes an interactive
+Bash subshell.  The user can use arbitrary Bash commands, plus the
+additional commands described under Commands, below.
+  
+
+
+
+  ovs-sim and the sandbox environment that it creates does not
+  require superuser or other special privileges.  Generally, it should not
+  be run with such privileges.
+
+
+Options
+
+
+  ovs-sim accepts the following options and arguments:
+
+
+
+  script
+  
+Runs script, which should be a Bash script, within a
+subshell after initializing.  If multiple script arguments
+are given, then they are run in the order given.  If any
+script exits with a nonzero exit code, then
+ovs-sim exits immediately with the same exit code.
+  
+
+  -i
+  --interactive
+  
+By default, if any script is specified, ovs-sim
+exits as soon as the scripts finish executing.  With this option, or if
+no scripts are specified, ovs-sim instead starts an
+interactive Bash session.
+  
+
+
+Commands
+
+
+  Scripts an

[ovs-dev] [PATCH ovn 10/11] ovn-nbctl: Take default database target from OVN_NB_DB in environment.

2015-06-14 Thread Ben Pfaff
This makes life easier for testing at the point you start to separate your
environment into multiple machines.

Also work on the manpage a little.

Signed-off-by: Ben Pfaff 
---
 ovn/ovn-nbctl.8.xml   | 38 +++---
 ovn/ovn-nbctl.c   |  5 -
 python/build/nroff.py |  2 +-
 3 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/ovn/ovn-nbctl.8.xml b/ovn/ovn-nbctl.8.xml
index 7100652..0e89229 100644
--- a/ovn/ovn-nbctl.8.xml
+++ b/ovn/ovn-nbctl.8.xml
@@ -182,20 +182,36 @@
 
 
 Options
--d database | --db 
database
--h | --help
--o | --options
--V | --version
+
+
+-d database
+--db database
+
+  The OVSDB database remote to contact.  If the OVN_NB_DB
+  environment variable is set, its value is used as the default.
+  Otherwise, the default is unix:@RUNDIR@/db.sock, but this
+  default is unlikely to be useful outside of single-machine OVN test
+  environments.
+
+
+-h | --help
+-o | --options
+-V | --version
+
 
 Logging options
--vspec, 
--verbose=spec
--v, --verbose
---log-file[=file]
-
--syslog-target=host:port
+
+-vspec, 
--verbose=spec
+-v, --verbose
+--log-file[=file]
+
--syslog-target=host:port
+
 
 PKI configuration (required to use SSL)
--p, --private-key=file  file with 
private key
--c, --certificate=file  file with 
certificate for private key
--C, --ca-cert=file  file with 
peer CA certificate
+
+-p, --private-key=file  file with 
private key
+-c, --certificate=file  file with 
certificate for private key
+-C, --ca-cert=file  file with 
peer CA certificate
+
 
 
diff --git a/ovn/ovn-nbctl.c b/ovn/ovn-nbctl.c
index 4dc77c0..a8e5d08 100644
--- a/ovn/ovn-nbctl.c
+++ b/ovn/ovn-nbctl.c
@@ -771,7 +771,10 @@ default_db(void)
 {
 static char *def;
 if (!def) {
-def = xasprintf("unix:%s/db.sock", ovs_rundir());
+def = getenv("OVN_NB_DB");
+if (!def) {
+def = xasprintf("unix:%s/db.sock", ovs_rundir());
+}
 }
 return def;
 }
diff --git a/python/build/nroff.py b/python/build/nroff.py
index 55dc878..050518c 100644
--- a/python/build/nroff.py
+++ b/python/build/nroff.py
@@ -65,7 +65,7 @@ def inlineXmlToNroff(node, font, to_upper=False):
 else:
 return textToNroff(node.data, font)
 elif node.nodeType == node.ELEMENT_NODE:
-if node.tagName in ['code', 'em', 'option']:
+if node.tagName in ['code', 'em', 'option', 'env']:
 s = r'\fB'
 for child in node.childNodes:
 s += inlineXmlToNroff(child, r'\fB')
-- 
2.1.3

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


[ovs-dev] [PATCH ovn 05/11] ofproto-dpif-xlate: Add native tunnel information to ofproto/trace.

2015-06-14 Thread Ben Pfaff
I found this invaluable for debugging native tunnels over dummy devices.

Signed-off-by: Ben Pfaff 
---
 ofproto/ofproto-dpif-xlate.c | 17 -
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 481e9ea..7ccaaea 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -2672,7 +2672,7 @@ tnl_send_arp_request(const struct xport *out_dev, const 
uint8_t eth_src[ETH_ADDR
 }
 
 static int
-build_tunnel_send(const struct xlate_ctx *ctx, const struct xport *xport,
+build_tunnel_send(struct xlate_ctx *ctx, const struct xport *xport,
   const struct flow *flow, odp_port_t tunnel_odp_port)
 {
 struct ovs_action_push_tnl tnl_push_data;
@@ -2684,22 +2684,30 @@ build_tunnel_send(const struct xlate_ctx *ctx, const 
struct xport *xport,
 
 err = tnl_route_lookup_flow(flow, &d_ip, &out_dev);
 if (err) {
+xlate_report(ctx, "native tunnel routing failed");
 return err;
 }
+xlate_report(ctx, "tunneling to "IP_FMT" via %s",
+ IP_ARGS(d_ip), netdev_get_name(out_dev->netdev));
 
 /* Use mac addr of bridge port of the peer. */
 err = netdev_get_etheraddr(out_dev->netdev, smac);
 if (err) {
+xlate_report(ctx, "tunnel output device lacks Ethernet address");
 return err;
 }
 
 err = netdev_get_in4(out_dev->netdev, (struct in_addr *) &s_ip, NULL);
 if (err) {
+xlate_report(ctx, "tunnel output device lacks IPv4 address");
 return err;
 }
 
 err = tnl_arp_lookup(out_dev->xbridge->name, d_ip, dmac);
 if (err) {
+xlate_report(ctx, "ARP cache miss for "IP_FMT" on bridge %s, "
+ "sending ARP request",
+ IP_ARGS(d_ip), out_dev->xbridge->name);
 tnl_send_arp_request(out_dev, smac, s_ip, d_ip);
 return err;
 }
@@ -2711,6 +2719,11 @@ build_tunnel_send(const struct xlate_ctx *ctx, const 
struct xport *xport,
 sizeof entry->u.tnl_arp_cache.br_name);
 entry->u.tnl_arp_cache.d_ip = d_ip;
 }
+
+xlate_report(ctx, "tunneling from "ETH_ADDR_FMT" "IP_FMT
+ " to "ETH_ADDR_FMT" "IP_FMT,
+ ETH_ADDR_ARGS(smac), IP_ARGS(s_ip),
+ ETH_ADDR_ARGS(dmac), IP_ARGS(d_ip));
 err = tnl_port_build_header(xport->ofport, flow,
 dmac, smac, s_ip, &tnl_push_data);
 if (err) {
@@ -2920,8 +2933,10 @@ compose_output_action__(struct xlate_ctx *ctx, 
ofp_port_t ofp_port,
 }
 out_port = odp_port;
 if (ovs_native_tunneling_is_on(ctx->xbridge->ofproto)) {
+xlate_report(ctx, "output to native tunnel");
 tnl_push_pop_send = true;
 } else {
+xlate_report(ctx, "output to kernel tunnel");
 commit_odp_tunnel_action(flow, &ctx->base_flow,
  ctx->xout->odp_actions);
 flow->tunnel = flow_tnl; /* Restore tunnel metadata */
-- 
2.1.3

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


Re: [ovs-dev] OVS with NSH (format of the packet towards VM from OVS)

2015-06-14 Thread Pritesh Kothari (pritkoth)

On Jun 12, 2015, at 12:44 PM, Anil Gunturu 
mailto:anil.gunt...@riftio.com>> wrote:


Hi,
With OVS patch for NSH, what is the format of the packets going to the VM? Do 
they have NSH header or the applications inside the VM completely unaware of 
the NSH header?

it supports both type of configurations, nsh-aware and nsh-unaware VM’s, it 
depends on how you configure it.

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


Re: [ovs-dev] OVN and OpenStack Provider Networks

2015-06-14 Thread Kyle Mestery
On Sat, Jun 13, 2015 at 5:12 PM, Salvatore Orlando 
wrote:

> Hi  Russel,
>
> thanks for sharing these thoughts. I was indeed thinking as well we need to
> support this in OVN as the provider networks are a fairly basic neutron
> feature - despite being an "extensions".
> I have some comments inline. I apologise in advance for their dumbness as
> I'm still getting up to speed with OVN architecture & internals.
>
> Salvatore
>
> On 10 June 2015 at 20:13, Russell Bryant  wrote:
>
> > I've been doing some thinking about OpenStack Neutron's provider
> > networks and how we might be able to support that with OVN as the
> > backend for Neutron.  Here is a start.  I'd love to hear what others
> think.
> >
> >
> > Provider Networks
> > =
> >
> > OpenStack Neutron currently has a feature referred to as "provider
> > networks".  This is used as a way to define existing physical networks
> > that you would like to integrate into your environment.
> >
> > In the simplest case, it can be used in environments where they have no
> > interest in tenant networks.  Instead, they want all VMs hooked up
> > directly to a pre-defined network in their environment.  This use case
> > is actually popular for private OpenStack deployments.
> >
> > Neutron's current OVS agent that runs on network nodes and hypervisors
> > has this configuration entry:
> >
> > bridge_mappings = physnet1:br-eth1,physnet2:br-eth2[...]
> >
> > This is used to name your physical networks and the bridge used to
> > access that physical network from the local node.
> >
> > Defining a provider network via the Neutron API via the neutron
> > command looks like this:
> >
> > $ neutron net-create physnet1 --shared \
> > > --provider:physical_network external \
> > > --provider:network_type flat
> >
> > A provider network can also be defined with a VLAN id:
> >
> > $ neutron net-create physnet1-101 --shared \
> > > --provider:physical_network external \
> > > --provider:network_type vlan \
> > > --provider:segmentation_id 101
> >
>
> The only pedant nit I have to add here is that the 'shared' setting has
> nothing to do with provider networks, but on the other hand it is also true
> that is required for supporting the "can't be bothered by tenant networks"
> use case.
>
> >
> >
> > Provider Networks with OVN
> > --
> >
> > OVN does not currently support this use case, but it's required for
> > Neutron.  Some use cases for provider networks are potentially better
> > served using OVN gateways.  I think the "simple networking without
> > tenant networks" case is at least one strong use case worth supporting.
> >
>
> the difference between the provider network and the L2 gateway is in my
> opinion that the former is a mapping between a logical network and a
> concrete physical network (I am considering VLANs as 'physical' here for
> simplicity), whereas the L2 gateway is a "service" that inserts in the
> logical topology to provide the same functionality. In other words with the
> provider network abstraction your traffic goes always on your chosen
> physical network, with the l2 gateway abstraction your traffic stays in the
> tenant network, likely an overlay, unless packets are directed to an
> address not in the tenant network, in which case they cross the gateway.
>
> In my opinion it's just too difficult to state which abstraction is better
> for given use cases. I'd rather expose both abstractions (the provider
> network for now, and the gateway in the future), and let operators choose
> the one that suits them better.
>
>
+1, I agree with your comments Salv. I'd also argue that we should likely
do provider networks first, and then followup with L2 gateway support,
given L2 gateway is new in Kilo.


>
> >
> > One possible implementation would be to have a Neutron agent
> > that runs parallel to ovn-controller that handles this.  It would
> > perform a subset of what the current Neutron OVS agent does but would
> > also duplicate a lot of what OVN does.  The other option is to have
> > ovn-controller implement it.
>
>
> > There are significant advantages to implementing this in OVN.  First, it
> > simplifies the deployment.  It saves the added complexity of a parallel
> > control plane for the neutron agents running beside ovn-controller.
> >
>
> This alonr would convince me to implement the solution with OVN; for
> instance the L3 agents should then be aware of the fact that interfaces
> might be plugged in multiple bridges, VIF plugging might also differ and
> therefore more work might be needed with port bindings, and finally you'd
> have provider networks secured in the "neutron way", whereas tenant
> networks would be secured in the "OVN way"
> Nevertheless, this might be a case where possibly ML2 could be leveraged
> (with or without tweaks) to ensure that the OVS driver implements provider
> networks, whereas the OVN driver implements tenant networks.
>
>
> > Second, much of the f

Re: [ovs-dev] [PATCH v8] netdev-dpdk: add dpdk vhost-user ports

2015-06-14 Thread Pravin Shelar
On Thu, Jun 4, 2015 at 6:51 AM, Ciara Loftus  wrote:
> This patch adds support for a new port type to the userspace
> datapath called dpdkvhostuser.
>
> A new dpdkvhostuser port will create a unix domain socket which
> when provided to QEMU is used to facilitate communication between
> the virtio-net device on the VM and the OVS port on the host.
>
> vhost-cuse ('dpdkvhost') ports are still available as 'dpdkvhostcuse'
> ports and will be enabled if vhost-cuse support is detected in the
> DPDK build specified during compilation of the switch. Otherwise,
> vhost-user ports are enabled.
>
> Signed-off-by: Ciara Loftus 
> ---
> v4:
> - Included helper function for the new_device callbacks to minimise
> code duplication.
> - Fixed indentation & line-wrap.
> - Simplified and corrected the processing of vhost ovs-vswitchd flags.
>
> v5:
> - Removed unnecessary strdup()
> - Fixed spacing
>
> v6:
> - Rebased to master
>
> v7:
> - Rebased to master
>
> v8:
> - Renamed dpdkvhost ports to dpdkvhostcuse for clarity.
> - Created separate sections for cuse and user in INSTALL.DPDK.md
> - Removed DPDK_DEV_VHOST_USER enum
> - Re-introduced common new_device callback function
> - Introduced check for the existence of specified vhost_sock_dir
> - Other minor changes
>

Thanks for the patch and working on suggestion. I pushed the patch to master.
___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


Re: [ovs-dev] [PATCH ovn 01/11] netdev-dummy: Report EADDRNOTAVAIL when no IPv4 address is configured.

2015-06-14 Thread Alex Wang
Acked-by: Alex Wang 

On Sun, Jun 14, 2015 at 12:18 PM, Ben Pfaff  wrote:

> This conforms with the interface described in netdev-provider.h.
>
> Found when experimenting with native tunneling and dummy devices.
>
> Signed-off-by: Ben Pfaff 
> ---
>  lib/netdev-dummy.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
> index 33d0876..4d1ef8a 100644
> --- a/lib/netdev-dummy.c
> +++ b/lib/netdev-dummy.c
> @@ -725,7 +725,8 @@ netdev_dummy_get_in4(const struct netdev *netdev_,
>  *address = netdev->address;
>  *netmask = netdev->netmask;
>  ovs_mutex_unlock(&netdev->mutex);
> -return 0;
> +
> +return address->s_addr ? 0 : EADDRNOTAVAIL;
>  }
>
>  static int
> --
> 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 ovn 02/11] packets: Generalize compose_arp().

2015-06-14 Thread Alex Wang
Acked-by: Alex Wang 

On Sun, Jun 14, 2015 at 12:18 PM, Ben Pfaff  wrote:

> Until now, compose_arp() has only been able to compose ARP requests.  This
> extends it to composing general ARP packets, in particular replies.
> An upcoming commit will make use of this capability.
>
> Signed-off-by: Ben Pfaff 
> ---
>  lib/packets.c| 28 ++--
>  lib/packets.h| 11 ---
>  ofproto/ofproto-dpif-xlate.c |  3 ++-
>  3 files changed, 28 insertions(+), 14 deletions(-)
>
> diff --git a/lib/packets.c b/lib/packets.c
> index 965754f..d04fffc 100644
> --- a/lib/packets.c
> +++ b/lib/packets.c
> @@ -1,5 +1,5 @@
>  /*
> - * 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.
> @@ -1012,9 +1012,16 @@ packet_format_tcp_flags(struct ds *s, uint16_t
> tcp_flags)
>  #define ARP_PACKET_SIZE  (2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + \
>ARP_ETH_HEADER_LEN)
>
> +/* Clears 'b' and replaces its contents by an ARP frame with the specified
> + * 'arp_op', 'arp_sha', 'arp_tha', 'arp_spa', and 'arp_tpa'.  The outer
> + * Ethernet frame is initialized with Ethernet source 'arp_sha' and
> destination
> + * 'arp_tha', except that destination ff:ff:ff:ff:ff:ff is used instead if
> + * 'broadcast' is true. */
>  void
> -compose_arp(struct dp_packet *b, const uint8_t eth_src[ETH_ADDR_LEN],
> -ovs_be32 ip_src, ovs_be32 ip_dst)
> +compose_arp(struct dp_packet *b, uint16_t arp_op,
> +const uint8_t arp_sha[ETH_ADDR_LEN],
> +const uint8_t arp_tha[ETH_ADDR_LEN], bool broadcast,
> +ovs_be32 arp_spa, ovs_be32 arp_tpa)
>  {
>  struct eth_header *eth;
>  struct arp_eth_header *arp;
> @@ -1024,8 +1031,9 @@ compose_arp(struct dp_packet *b, const uint8_t
> eth_src[ETH_ADDR_LEN],
>  dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);
>
>  eth = dp_packet_put_uninit(b, sizeof *eth);
> -memcpy(eth->eth_dst, eth_addr_broadcast, ETH_ADDR_LEN);
> -memcpy(eth->eth_src, eth_src, ETH_ADDR_LEN);
> +memcpy(eth->eth_dst, broadcast ? eth_addr_broadcast : arp_tha,
> +   ETH_ADDR_LEN);
> +memcpy(eth->eth_src, arp_sha, ETH_ADDR_LEN);
>  eth->eth_type = htons(ETH_TYPE_ARP);
>
>  arp = dp_packet_put_uninit(b, sizeof *arp);
> @@ -1033,12 +1041,12 @@ compose_arp(struct dp_packet *b, const uint8_t
> eth_src[ETH_ADDR_LEN],
>  arp->ar_pro = htons(ARP_PRO_IP);
>  arp->ar_hln = sizeof arp->ar_sha;
>  arp->ar_pln = sizeof arp->ar_spa;
> -arp->ar_op = htons(ARP_OP_REQUEST);
> -memcpy(arp->ar_sha, eth_src, ETH_ADDR_LEN);
> -memset(arp->ar_tha, 0, ETH_ADDR_LEN);
> +arp->ar_op = htons(arp_op);
> +memcpy(arp->ar_sha, arp_sha, ETH_ADDR_LEN);
> +memcpy(arp->ar_tha, arp_tha, ETH_ADDR_LEN);
>
> -put_16aligned_be32(&arp->ar_spa, ip_src);
> -put_16aligned_be32(&arp->ar_tpa, ip_dst);
> +put_16aligned_be32(&arp->ar_spa, arp_spa);
> +put_16aligned_be32(&arp->ar_tpa, arp_tpa);
>
>  dp_packet_reset_offsets(b);
>  dp_packet_set_l3(b, arp);
> diff --git a/lib/packets.h b/lib/packets.h
> index e22267e..699a953 100644
> --- a/lib/packets.h
> +++ b/lib/packets.h
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
> + * Copyright (c) 2008, 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.
> @@ -77,6 +77,9 @@ bool dpid_from_string(const char *s, uint64_t *dpidp);
>  static const uint8_t eth_addr_broadcast[ETH_ADDR_LEN] OVS_UNUSED
>  = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
>
> +static const uint8_t eth_addr_zero[ETH_ADDR_LEN] OVS_UNUSED
> += { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
> +
>  static const uint8_t eth_addr_stp[ETH_ADDR_LEN] OVS_UNUSED
>  = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x00 };
>
> @@ -811,8 +814,10 @@ void packet_set_nd(struct dp_packet *, const ovs_be32
> target[4],
>
>  void packet_format_tcp_flags(struct ds *, uint16_t);
>  const char *packet_tcp_flag_to_string(uint32_t flag);
> -void compose_arp(struct dp_packet *b, const uint8_t eth_src[ETH_ADDR_LEN],
> - ovs_be32 ip_src, ovs_be32 ip_dst);
> +void compose_arp(struct dp_packet *, uint16_t arp_op,
> + const uint8_t arp_sha[ETH_ADDR_LEN],
> + const uint8_t arp_tha[ETH_ADDR_LEN], bool broadcast,
> + ovs_be32 arp_spa, ovs_be32 arp_tpa);
>  uint32_t packet_csum_pseudoheader(const struct ip_header *);
>
>  #endif /* packets.h */
> diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
> index 337d6f8..ef9312b 100644
> --- a/ofproto/ofproto-dpif-xlate.c
> +++ b/ofproto/ofproto-dpif-xlate.c
> @@ -265

Re: [ovs-dev] [PATCH ovn 03/11] netdev-dummy: Implement ARP responder.

2015-06-14 Thread Alex Wang
Want to ask, do we need to call 'dummy_packet_conn_send(&dev->conn, buffer,
size);' in the
arp request case?  Could this cause problem when there is a loop?

Thanks,
Alex Wang,

On Sun, Jun 14, 2015 at 12:18 PM, Ben Pfaff  wrote:

> This is the only missing piece to make native tunneling work with dummy
> devices for testing purposes.
>
> Signed-off-by: Ben Pfaff 
> ---
>  lib/netdev-dummy.c | 17 +
>  1 file changed, 17 insertions(+)
>
> diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
> index 4d1ef8a..ff65689 100644
> --- a/lib/netdev-dummy.c
> +++ b/lib/netdev-dummy.c
> @@ -932,6 +932,23 @@ netdev_dummy_send(struct netdev *netdev, int qid
> OVS_UNUSED,
>
>  dummy_packet_conn_send(&dev->conn, buffer, size);
>
> +/* Reply to ARP requests for 'dev''s assigned IP address. */
> +if (dev->address.s_addr) {
> +struct dp_packet packet;
> +struct flow flow;
> +
> +dp_packet_use_const(&packet, buffer, size);
> +flow_extract(&packet, &flow);
> +if (flow.dl_type == htons(ETH_TYPE_ARP)
> +&& flow.nw_proto == ARP_OP_REQUEST
> +&& flow.nw_dst == dev->address.s_addr) {
> +struct dp_packet *reply = dp_packet_new(0);
> +compose_arp(reply, ARP_OP_REPLY, dev->hwaddr, flow.dl_src,
> +false, flow.nw_dst, flow.nw_src);
> +netdev_dummy_queue_packet(dev, reply);
> +}
> +}
> +
>  if (dev->tx_pcap) {
>  struct dp_packet packet;
>
> --
> 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 ovn 04/11] ofproto-dpif: Allow translation reports to include formatted data.

2015-06-14 Thread Alex Wang
Acked-by: Alex Wang 

On Sun, Jun 14, 2015 at 12:18 PM, Ben Pfaff  wrote:

> This allow the reports to have additional useful information.  An upcoming
> commit will take advantage of this.
>
> Signed-off-by: Ben Pfaff 
> ---
>  ofproto/ofproto-dpif-xlate.c | 11 ---
>  ofproto/ofproto-dpif-xlate.h |  5 +++--
>  ofproto/ofproto-dpif.c   | 36 ++--
>  3 files changed, 37 insertions(+), 15 deletions(-)
>
> diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
> index ef9312b..481e9ea 100644
> --- a/ofproto/ofproto-dpif-xlate.c
> +++ b/ofproto/ofproto-dpif-xlate.c
> @@ -436,7 +436,8 @@ static bool may_receive(const struct xport *, struct
> xlate_ctx *);
>  static void do_xlate_actions(const struct ofpact *, size_t ofpacts_len,
>   struct xlate_ctx *);
>  static void xlate_normal(struct xlate_ctx *);
> -static inline void xlate_report(struct xlate_ctx *, const char *);
> +static inline void xlate_report(struct xlate_ctx *, const char *, ...)
> +OVS_PRINTF_FORMAT(2, 3);
>  static void xlate_table_action(struct xlate_ctx *, ofp_port_t in_port,
> uint8_t table_id, bool may_packet_in,
> bool honor_table_miss);
> @@ -505,10 +506,14 @@ static void xlate_xport_copy(struct xbridge *,
> struct xbundle *,
>  static void xlate_xcfg_free(struct xlate_cfg *);
>
>  static inline void
> -xlate_report(struct xlate_ctx *ctx, const char *s)
> +xlate_report(struct xlate_ctx *ctx, const char *format, ...)
>  {
>  if (OVS_UNLIKELY(ctx->xin->report_hook)) {
> -ctx->xin->report_hook(ctx->xin, s, ctx->recurse);
> +va_list args;
> +
> +va_start(args, format);
> +ctx->xin->report_hook(ctx->xin, ctx->recurse, format, args);
> +va_end(args);
>  }
>  }
>
> diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h
> index e39847b..8586e40 100644
> --- a/ofproto/ofproto-dpif-xlate.h
> +++ b/ofproto/ofproto-dpif-xlate.h
> @@ -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.
> @@ -177,7 +177,8 @@ struct xlate_in {
>   * significant decision, e.g. to explain why OFPP_NORMAL translation
>   * dropped a packet.  'recurse' is the resubmit recursion depth at
> time of
>   * invocation. */
> -void (*report_hook)(struct xlate_in *, const char *s, int recurse);
> +void (*report_hook)(struct xlate_in *, int recurse,
> +const char *format, va_list args);
>
>  /* If nonnull, flow translation credits the specified statistics to
> each
>   * rule reached through a resubmit or OFPP_TABLE action.
> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> index 55fea0f..378ce51 100644
> --- a/ofproto/ofproto-dpif.c
> +++ b/ofproto/ofproto-dpif.c
> @@ -4548,7 +4548,12 @@ trace_format_megaflow(struct ds *result, int level,
> const char *title,
>  ds_put_char(result, '\n');
>  }
>
> -static void trace_report(struct xlate_in *xin, const char *s, int
> recurse);
> +static void trace_report(struct xlate_in *, int recurse,
> + const char *format, ...)
> +OVS_PRINTF_FORMAT(3, 4);
> +static void trace_report_valist(struct xlate_in *, int recurse,
> +const char *format, va_list args)
> +OVS_PRINTF_FORMAT(3, 0);
>
>  static void
>  trace_resubmit(struct xlate_in *xin, struct rule_dpif *rule, int recurse)
> @@ -4558,15 +4563,15 @@ trace_resubmit(struct xlate_in *xin, struct
> rule_dpif *rule, int recurse)
>
>  if (!recurse) {
>  if (rule == xin->ofproto->miss_rule) {
> -trace_report(xin, "No match, flow generates \"packet in\"s.",
> - recurse);
> +trace_report(xin, recurse,
> + "No match, flow generates \"packet in\"s.");
>  } else if (rule == xin->ofproto->no_packet_in_rule) {
> -trace_report(xin, "No match, packets dropped because "
> - "OFPPC_NO_PACKET_IN is set on in_port.",
> recurse);
> +trace_report(xin, recurse, "No match, packets dropped because
> "
> + "OFPPC_NO_PACKET_IN is set on in_port.");
>  } else if (rule == xin->ofproto->drop_frags_rule) {
> -trace_report(xin, "Packets dropped because they are IP "
> +trace_report(xin, recurse, "Packets dropped because they are
> IP "
>   "fragments and the fragment handling mode is "
> - "\"drop\".", recurse);
> + "\"drop\".");
>  }
>  }
>
> @@ -4581,16 +4586,27 @@ trace_resubmit(struct xlate_in *xin, struct
> rule_dpif *rule, int recurse)
>  }
>
>  static