<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:syn="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/">
  <channel rdf:about="http://blog.gmane.org/gmane.network.openvswitch.devel">
    <title>gmane.network.openvswitch.devel</title>
    <link>http://blog.gmane.org/gmane.network.openvswitch.devel</link>
    <description/>
    <syn:updatePeriod>hourly</syn:updatePeriod>
    <syn:updateFrequency>1</syn:updateFrequency>
    <syn:updateBase>1901-01-01T00:00+00:00</syn:updateBase>
    <items>
      <rdf:Seq>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20793"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20780"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20775"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20764"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20762"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20755"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20749"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20740"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20737"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20736"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20735"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20731"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20729"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20724"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20723"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20722"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20719"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20718"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20711"/>
        <rdf:li rdf:resource="http://comments.gmane.org/gmane.network.openvswitch.devel/20707"/>
      </rdf:Seq>
    </items>
    <image rdf:resource="http://gmane.org/img/gmane-25t.png"/>
    <textinput rdf:resource=""/>
  </channel>
  <image rdf:about="http://gmane.org/img/gmane-25t.png">
    <title>Gmane</title>
    <url>http://gmane.org/img/gmane-25t.png</url>
    <link>http://gmane.org</link>
  </image>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20793">
    <title>[PATCH v9 0/6] Add packet recirculation</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20793</link>
    <description>&lt;pre&gt;Recirculation is a technique to allow a frame to re-enter
frame processing. This is intended to be used after actions
have been applied to the frame with modify the frame in
some way that makes it possible for richer processing to occur.

An example is and indeed targeted use case is MPLS. If an MPLS frame has an
mpls_pop action applied with the IPv4 ethernet type then it becomes
possible to decode the IPv4 portion of the frame. This may be used to
construct a facet that modifies the IPv4 portion of the frame. This is not
possible prior to the mpls_pop action as the contents of the frame after
the MPLS stack is not known to be IPv4.


Design:

* New recirculation action.

  ovs-vswitchd adds a recirculation action to the end of a list of
  datapath actions for a flow when the actions are truncated because
  insufficient flow match information is available to add the next
  OpenFlow action.  The recirculation action is preceded by an action
  to set the skb_mark to an id which can be used to scope a facet lookup
  of a recirculated packet.

  e.g.  pop_mpls(0x0800),dec_ttl becomes pop_mpls(0x800),set(skb_mark(id)),recirculate

* Datapath behaviour

  Then the datapath encounters a recirculate action it:
  + Recalculates the flow key based on the packet
    which will typically have been modified by previous actions
  + As the recirculate action is preceded by a set(skb_mark(id)) action,
    the new match key will now include skb_mark=id.
  + Performs a lookup using the new match key
  + Processes the packet if a facet matches the key or;
  + Makes an upcall if necessary

* No facet behaviour

  + Loop:
    1) translate actions
    2) If there is a recirculate action, execute packet
       and go back to 1) for remaining actions.


Base/Pre-requisites:

This series applies to the git master branch on openvswtich.org
and doees not have any pre-requisites.


Availability:

For reference this series is available in git at:

git://github.com/horms/openvswitch.git devel/mpls-recirculate.v9


TODO:

* Conclude discussion with Jesse Gross on weather or not packets
  are not output by do_execute_actions() if an output action precedes
  a recirculate action.
* Review of fproto/ofproto-dpif.c by Jesse Gross (and Ben Pfaff?)


Change Log:

v9
* As suggested by Jesse Gross
- Follow the convention on other code that when passing around
  a void pointer and casting it, the variable named with an underscore
  is the void pointer.
- Move extraction of userspace data into execute_actions().
  Previously it was in the userspace callback passed to execute_actions().
- Remove ovs_assert() calls from execute_actions().
  They seem unnecessary at best.
- Reduce the number of new parameters added to functions,
  in many cases to zero, by using the skb_priority, skb_mark
  and tunnel elements of struct flow.
- Add patch to make use of execute_actions() to execute controller actions

v8
* For a learn action recirculate regardless of the value of
  ctx-&amp;gt;may_learn in do_xlate_actions(). Previously recirculation
  only occurred if ctx-&amp;gt;may_learn was true. That is a bug as it causes
  revalidation to fail. Flagged by the tests developed as part of a patch
  to allow multiple MPLS push and poop actions.
* Update tests removing unnecessary dl_type pre-requisite

v7
* Rebase
* Add skb_priority, skb_mark and tun_key parameters to dp_netdev_port_input()
  This allows the skb_priority, skb_mark and tun_key  to be passed from
  dpif_netdev_execute() to honour corresponding set actions.
* Recirculate on reg load and move, stack push and pop,
  multipath, bundle, and learn actions.
* Add tests

v6
* Rearange patches so as only to add self-contained working chages
* Create execute_actions() in lib/execute-actions.c
  - This moves makes much more action execution code than before
    from the user-spcace datapath into common library code.
* Add set skb_priority support to execute_set_action()
* Add set tunnel support to execute_set_action()
* Support revalidation of facets for recirculated packets
* Address other elements Jesse's review, as noted in
  per-patch changelogs


v5
* Correct declaration of facet_find_by_id to match definition:
  ovs_be32 -&amp;gt; uint32_t.
* Enhancements to recirculation id code:
  - Allow efficient lookup of facets by their recirculation id
  - Add RECIRCULATION_ID_DUMMY which may be used in cases
    where no facet it used. It is an arbitrary valid id.
  - Also add recirculated element to action_xlate_ctx()
    to use to detect if a recirculation action was added during
    translation. The previous scheme of checking if recirculation_id
    was not RECIRCULATION_ID_NONE is broken for cases where
    the context is initialised with a recirculation_id other than
    RECIRCULATION_ID_NONE. E.g. when RECIRCULATION_ID_DUMMY is used.
  - Avoid id collision

rfc4:
* Allow recirculation without facets in ovs-vswitchd
  - Handle flow miss without facet
  - Packet out
* Minor enhancement to recirculation id management: Add RECIRCULATE_ID_NONE
  to use instead of using 0 directly.
* Correct calculation of facet-&amp;gt;recirculation_ofpacts and
  facet-&amp;gt;recirculation_ofpacts_len in subfacet_make_actions()
  in the case of more than one level of recirculation.

rfc3
* Use IS_ERR_OR_NULL()
* Handle facet consistency checking by constructing a chain of facets
  from the given facet, to its recirculation parent and then its parent
  until the topmost facet.  If there is no recirculation  the chain will
  be of length one. If there is one recirculation action then the chain
  will be of length two. And so on.

  The topmost facet in the chain can is used to lookup the rule to be
  verified. The chain is then walked from top to bottom, translating
  actions up to the end or the first recirculation action that is
  encountered, whichever comes first. As the code walks down the chain
  it updates the actions that are executed to start of the actions to
  be executed to be just after the end of the actions executed in the
  previous facet in the chain. This is similar to the way that facets
  are created when a recirculation action is encountered.

rfc2
* As suggested by Jesse Gross
  - Update for changes to ovs_dp_process_received_packet()
    to no longer check if OVS_CB(skb)-&amp;gt;flow is pre-initialised.
  - Do not add spurious printk debugging to ovs_execute_actions()
  - Do not add spurious debugging messages to commit_set_nw_action()
  - Correct typo in comment above commit_odp_actions().
  - Do not execute recirculation in ovs-vswitchd, rather allow
    the datapath to make an upcall when a recirculation action
    is encountered on execute.
    + This implicitly breaks support for recirculation without facets,
      so for now force all misses of MPLS frames to be handled with
      a facet; and treat handling of recirculation for packet_out as
      a todo item.
  - Use skb_mark for recirculation_id in match. This avoids
    both expanding the match and including a recirculation_id parameter
    with the recirculation action: set_skb_mark should be used before
    the recirculation action.
  - Tidy up ownership of skb in ovs_execute_actions

rfc1
* Initial post


Patch List and Diffstat:

Simon Horman (5):
  Add execute_actions
  Add set skb_mark support to execute_set_action
  Add set skb_priority support to execute_set_action
  Add set tunnel support to execute_set_action
  Add packet recirculation

 datapath/actions.c          |   9 +-
 datapath/datapath.c         | 105 ++++---
 datapath/datapath.h         |   2 +-
 include/linux/openvswitch.h |   4 +
 lib/automake.mk             |   2 +
 lib/dpif-netdev.c           | 254 +++++-----------
 lib/execute-actions.c       | 225 ++++++++++++++
 lib/execute-actions.h       |  34 +++
 lib/flow.h                  |   4 +
 lib/odp-util.c              |  17 +-
 lib/odp-util.h              |   4 +
 ofproto/ofproto-dpif.c      | 703 +++++++++++++++++++++++++++++++++++++++-----
 tests/ofproto-dpif.at       | 214 ++++++++++++--
 13 files changed, 1257 insertions(+), 320 deletions(-)
 create mode 100644 lib/execute-actions.c
 create mode 100644 lib/execute-actions.h

&lt;/pre&gt;</description>
    <dc:creator>Simon Horman</dc:creator>
    <dc:date>2013-05-22T07:08:04</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20780">
    <title>[PATCH] netdev: New function netdev_ref().</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20780</link>
    <description>&lt;pre&gt;I suspect that this makes it easier to make sure that a netdev stays open
as long as needed in some cases where a module needs access to a netdev
opened by some higher-level module.

CC: Ethan Jackson &amp;lt;ethan-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
Signed-off-by: Ben Pfaff &amp;lt;blp-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
---
 lib/netdev.c |   11 +++++++++++
 lib/netdev.h |    1 +
 2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/lib/netdev.c b/lib/netdev.c
index 5c2e9f5..5aae01c 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -277,6 +277,17 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; netdev_open(const char *name, const char *type, struct netdev **netdevp)
     return 0;
 }
 
+/* Returns a reference to 'netdev_' for the caller to own. */
+struct netdev *
+netdev_ref(const struct netdev *netdev_)
+{
+    struct netdev *netdev = CONST_CAST(struct netdev *, netdev_);
+
+    ovs_assert(netdev-&amp;gt;ref_cnt &amp;gt; 0);
+    netdev-&amp;gt;ref_cnt++;
+    return netdev;
+}
+
 /* Reconfigures the device 'netdev' with 'args'.  'args' may be empty
  * or NULL if none are needed. */
 int
diff --git a/lib/netdev.h b/lib/netdev.h
index c7f3c1d..b1cc319 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -110,6 +110,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; bool netdev_is_reserved_name(const char *name);
 
 /* Open and close. */
 int netdev_open(const char *name, const char *type, struct netdev **);
+struct netdev *netdev_ref(const struct netdev *);
 void netdev_close(struct netdev *);
 
 void netdev_parse_name(const char *netdev_name, char **name, char **type);
&lt;/pre&gt;</description>
    <dc:creator>Ben Pfaff</dc:creator>
    <dc:date>2013-05-21T22:42:44</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20775">
    <title>[PATCH] lib/dpif-netdev.c: Remove redundant call toflow_extract</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20775</link>
    <description>&lt;pre&gt;This commit removes the redundant call to flow_extract in dpif_netdev_execute,
since in the next line, the call to dpif_netdev_flow_from_nlattrs will reset
the flow variable.

Signed-off-by: Alex Wang &amp;lt;alexw-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
---
 lib/dpif-netdev.c |    1 -
 1 file changed, 1 deletion(-)

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 78bdedb..4ad2823 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -941,7 +941,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; dpif_netdev_execute(struct dpif *dpif, const struct dpif_execute *execute)
     ofpbuf_reserve(&amp;amp;copy, DP_NETDEV_HEADROOM);
     ofpbuf_put(&amp;amp;copy, execute-&amp;gt;packet-&amp;gt;data, execute-&amp;gt;packet-&amp;gt;size);
 
-    flow_extract(&amp;amp;copy, 0, 0, NULL, -1, &amp;amp;key);
     error = dpif_netdev_flow_from_nlattrs(execute-&amp;gt;key, execute-&amp;gt;key_len,
                                           &amp;amp;key);
     if (!error) {
&lt;/pre&gt;</description>
    <dc:creator>Alex Wang</dc:creator>
    <dc:date>2013-05-21T18:33:58</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20764">
    <title>my code for review is now available from github</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20764</link>
    <description>&lt;pre&gt;As an organizational tool for developers who might be interested in
reviewing my code, I've now posted all my outstanding unreviewed (or
review in progress) code as branches in the github repository visible on
the web at:
        https://github.com/blp/ovs-reviews/branches

This is an experiment to see whether it helps to get my code reviewed
more promptly.  For now, I plan to keep the repository up-to-date as I
post new patch series, apply feedback, and merge code into the master
repository.  If the experiment is successful, then I'll continue to do
this indefinitely.

You can clone the repository via:
        git://github.com/blp/ovs-reviews.git
or
        https://github.com/blp/ovs-reviews.git
and probably other ways too.
&lt;/pre&gt;</description>
    <dc:creator>Ben Pfaff</dc:creator>
    <dc:date>2013-05-21T15:44:27</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20762">
    <title>bounce for mail to yamt-bO972TJMBWD+G+EEi5ephHgSJqDPrsil&lt; at &gt;public.gmane.org</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20762</link>
    <description>&lt;pre&gt;I don't know where else to send this so I'll hope that Yamamoto-san
reads ovs-dev.

----- Forwarded message from Mail Delivery Subsystem &amp;lt;mailer-daemon-gM/Ye1E23mwN+BqQ9rBEUg&amp;lt; at &amp;gt;public.gmane.org&amp;gt; -----

Date: Tue, 21 May 2013 15:02:22 +0000
From: Mail Delivery Subsystem &amp;lt;mailer-daemon-gM/Ye1E23mwN+BqQ9rBEUg&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
To: blp-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org
Subject: Delivery Status Notification (Failure)

Delivery to the following recipient failed permanently:

     yamt-bO972TJMBWD+G+EEi5ephHgSJqDPrsil&amp;lt; at &amp;gt;public.gmane.org

Technical details of permanent failure: 
Google tried to deliver your message, but it was rejected by the server for the recipient domain outbounds9.ga.obsmtp.com by outbounds9.ga.obsmtp.com. [74.125.148.12].

The error that the other server returned was:
550 MX record points to an invalid IP for domain:mwd.biglobe.ne.jp - psmtp

----- Original message -----

X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=google.com; s=20120113;
        h=date:from:to:cc:subject:message-id:references:mime-version
         :content-type:content-disposition:in-reply-to:user-agent
         :x-gm-message-state;
        bh=Q+j5KMI90/8eT9tOqD1ugjtWmrDlEWUF8d1CYwV2EoQ=;
        b=SmMwqT1QCYhZHSkpIF2jx81OV+0UBzggtykXb0KnEmPAP9Ob/yAhConn4RpYsO5gZK
         Bmy2MXlH/UjlUwH9/lYvoSKKTtsBuX1+duNOgnuytVgoQSiJV81MCIDkgVN5fgTHkMS8
         56S+GedPtlcmPpj+QXy2sd2uOsZg2v+IJb8F19BRQKaeIeiSsKf27WIbDKxdId790oBo
         nDxs1SW8J/lHXxxaOHQRSB/O3x0ugRDrHaBZvCzu7nk7jEkr8OpoVqP110Isq1VMf2kG
         fciMIuwwCNbQjVEhv4uzNE2519WVY2au3lIBWqybIeBIuSXlyIedNOoGcOz2LiNLdvbF
         PUkQ==
X-Received: by 10.68.196.231 with SMTP id ip7mr3119262pbc.61.1369148532301;
        Tue, 21 May 2013 08:02:12 -0700 (PDT)
X-Received: by 10.68.196.231 with SMTP id ip7mr3119252pbc.61.1369148532221;
        Tue, 21 May 2013 08:02:12 -0700 (PDT)
Return-Path: &amp;lt;blp-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
Received: from nicira.com (c-50-131-104-186.hsd1.ca.comcast.net. [50.131.104.186])
        by mx.google.com with ESMTPSA id vu10sm3048518pbc.27.2013.05.21.08.02.10
        for &amp;lt;multiple recipients&amp;gt;
        (version=TLSv1.2 cipher=RC4-SHA bits=128/128);
        Tue, 21 May 2013 08:02:11 -0700 (PDT)
Date: Tue, 21 May 2013 08:02:07 -0700
From: Ben Pfaff &amp;lt;blp-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
To: yamt-bO972TJMBWD+G+EEi5ephHgSJqDPrsil&amp;lt; at &amp;gt;public.gmane.org
Cc: dev-yBygre7rU0TnMu66kgdUjQ&amp;lt; at &amp;gt;public.gmane.org
Subject: Re: [ovs-dev] [PATCH 10/13] acinclude.m4: update a comment for
 NetBSD support
Message-ID: &amp;lt;20130521150207.GE17017-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
References: &amp;lt;1369126205-25292-1-git-send-email-yamt-bO972TJMBWD+G+EEi5ephHgSJqDPrsil&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
 &amp;lt;1369126205-25292-11-git-send-email-yamt-bO972TJMBWD+G+EEi5ephHgSJqDPrsil&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: &amp;lt;1369126205-25292-11-git-send-email-yamt-bO972TJMBWD+G+EEi5ephHgSJqDPrsil&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
User-Agent: Mutt/1.5.21 (2010-09-15)
X-Gm-Message-State: ALoCoQkipTk1jCELVyF3YDDdTRNxLmde2YTTFFfkEGd38tFYKXurOq197x7EUcAOiiCxh3JqDaWwOjCXJ0DYASqo1XFzrfkUUGCV1J8/+QVfJr+89VsDTtZMACrcU0t3TWRrPR1drdfSr3ZTF3HPfNg/QJczD3Q/RiW4nK1x/BKwCzuxaboeAfA=

On Tue, May 21, 2013 at 05:50:02PM +0900, yamt-bO972TJMBWD+G+EEi5ephHgSJqDPrsil&amp;lt; at &amp;gt;public.gmane.org wrote:

Applied, thanks.

----- End forwarded message -----
&lt;/pre&gt;</description>
    <dc:creator>Ben Pfaff</dc:creator>
    <dc:date>2013-05-21T15:05:02</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20755">
    <title>Thanks, Dad</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20755</link>
    <description>&lt;pre&gt;您的电子邮件客户端无法读取此电子邮件。
请到这里在线查看：
http://link.m10.mian-dan.com/rhd/m2a6295084C5d0425f6c5ac3876112268f3e0cc748e45S7f82L6e57N3b33


要停止接收这些电子邮件：http://link.m10.mian-dan.com/rhu/m2a6295084C5d0425f6c5ac3876112268f3e0cc748e45L6e57N3b82
&lt;/pre&gt;</description>
    <dc:creator>Aurabuy</dc:creator>
    <dc:date>2013-05-21T12:30:23</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20749">
    <title>[PATCH 00/13] NetBSD support</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20749</link>
    <description>&lt;pre&gt;From: YAMAMOTO Takashi &amp;lt;yamt-bO972TJMBWD+G+EEi5ephHgSJqDPrsil&amp;lt; at &amp;gt;public.gmane.org&amp;gt;

NetBSD support patch set rebased today

YAMAMOTO Takashi (13):
  don't forget to define HAVE_BACKTRACE
  add minimal NetBSD support
  keep "kernel name" for each netdev
  netdev-bsd: NetBSD: keep a AF_LINK socket open
  missing ifdef netbsd guard for af_link_sock
  implement set_etheraddr for NetBSD
  implement get_stats for NetBSD
  some NetBSD related documentation changes
  implement get_next_hop for NetBSD
  acinclude.m4: update a comment for NetBSD support
  factor out a function to extract stats from if_data to netdev_stats.
  testsuite: update a comment
  INSTALL: update for NetBSD

 INSTALL               |  18 +--
 INSTALL.userspace     |  20 ++-
 acinclude.m4          |   5 +-
 lib/command-line.c    |   4 +-
 lib/command-line.h    |   2 +-
 lib/netdev-bsd.c      | 365 ++++++++++++++++++++++++++++++++++++++++++++------
 lib/netdev-provider.h |   2 +-
 lib/netdev.c          |   2 +-
 m4/openvswitch.m4     |   4 +-
 tests/ofproto.at      |   2 +-
 10 files changed, 360 insertions(+), 64 deletions(-)

&lt;/pre&gt;</description>
    <dc:creator>yamt-bO972TJMBWD+G+EEi5ephHgSJqDPrsil&lt; at &gt;public.gmane.org</dc:creator>
    <dc:date>2013-05-21T08:49:52</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20740">
    <title>[PATCH] ofproto-dpif: Don't configure BFD on missingofports.</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20740</link>
    <description>&lt;pre&gt;This was causing ovs-vswitchd to core occasionally, even when BFD
wasn't turned on.

Bug #17162.
Signed-off-by: Ethan Jackson &amp;lt;ethan-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
---
 ofproto/ofproto.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 28df181..ca1dc89 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -812,6 +812,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; ofproto_port_set_bfd(struct ofproto *ofproto, uint16_t ofp_port,
     if (!ofport) {
         VLOG_WARN("%s: cannot configure bfd on nonexistent port %"PRIu16,
                   ofproto-&amp;gt;name, ofp_port);
+        return;
     }
 
     error = (ofproto-&amp;gt;ofproto_class-&amp;gt;set_bfd
&lt;/pre&gt;</description>
    <dc:creator>Ethan Jackson</dc:creator>
    <dc:date>2013-05-21T02:10:02</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20737">
    <title>[PATCH 1/2] ofp-util: New functionofputil_port_to_string().</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20737</link>
    <description>&lt;pre&gt;This function is more convenient than ofputil_format_port() when a "struct
ds" is not already in use.  This commit converts one caller for which this
was already true, and the following commit will add another.

Signed-off-by: Ben Pfaff &amp;lt;blp-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
---
 lib/ofp-util.c |   32 ++++++++++++++++++++++----------
 lib/ofp-util.h |    2 ++
 2 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index b4ff09b..e5502e1 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -4135,14 +4135,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; ofputil_port_from_string(const char *s, uint16_t *portp)
             *portp = port32;
             return true;
         } else if (port32 &amp;lt;= OFPP_LAST_RESV) {
-            struct ds msg;
+            char name[OFP_MAX_PORT_NAME_LEN];
 
-            ds_init(&amp;amp;msg);
-            ofputil_format_port(port32, &amp;amp;msg);
+            ofputil_port_to_string(port32, name, sizeof name);
             VLOG_WARN_ONCE("referring to port %s as %u is deprecated for "
                            "compatibility with future versions of OpenFlow",
-                           ds_cstr(&amp;amp;msg), port32);
-            ds_destroy(&amp;amp;msg);
+                           name, port32);
 
             *portp = port32;
             return true;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -4183,18 +4181,32 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; ofputil_port_from_string(const char *s, uint16_t *portp)
 void
 ofputil_format_port(uint16_t port, struct ds *s)
 {
-    const char *name;
+    char name[OFP_MAX_PORT_NAME_LEN];
 
+    ofputil_port_to_string(port, name, sizeof name);
+    ds_put_cstr(s, name);
+}
+
+/* Puts in the 'bufsize' byte in 'buf' a null-terminated string representation
+ * of OpenFlow port number 'port'.  Most ports are represented as just the port
+ * number, but special ports, e.g. OFPP_LOCAL, are represented by name,
+ * e.g. "LOCAL". */
+void
+ofputil_port_to_string(uint16_t port,
+                       char namebuf[OFP_MAX_PORT_NAME_LEN], size_t bufsize)
+{
     switch (port) {
-#define OFPUTIL_NAMED_PORT(NAME) case OFPP_##NAME: name = #NAME; break;
+#define OFPUTIL_NAMED_PORT(NAME)                                \
+        case OFPP_##NAME:                                       \
+            ovs_strlcpy(namebuf, #NAME, bufsize);                   \
+            break;
         OFPUTIL_NAMED_PORTS
 #undef OFPUTIL_NAMED_PORT
 
     default:
-        ds_put_format(s, "%"PRIu16, port);
-        return;
+        snprintf(namebuf, bufsize, "%"PRIu16, port);
+        break;
     }
-    ds_put_cstr(s, name);
 }
 
 /* Given a buffer 'b' that contains an array of OpenFlow ports of type
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index 4d0d8ad..bf9c315 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -37,6 +37,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; ovs_be32 ofputil_port_to_ofp11(uint16_t ofp10_port);
 enum ofperr ofputil_check_output_port(uint16_t ofp_port, int max_ports);
 bool ofputil_port_from_string(const char *, uint16_t *portp);
 void ofputil_format_port(uint16_t port, struct ds *);
+void ofputil_port_to_string(uint16_t port, char namebuf[OFP_MAX_PORT_NAME_LEN],
+                            size_t bufsize);
 
 /* Converting OFPFW10_NW_SRC_MASK and OFPFW10_NW_DST_MASK wildcard bit counts
  * to and from IP bitmasks. */
&lt;/pre&gt;</description>
    <dc:creator>Ben Pfaff</dc:creator>
    <dc:date>2013-05-21T00:14:44</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20736">
    <title>[PATCH] cfm: Implement "demand mode".</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20736</link>
    <description>&lt;pre&gt;The new CFM "demand mode" (named after BFD's demand mode) uses
data traffic to indicate interface liveness.  It's helpful on
heavily congested networks where CCMs may be dropped.

Signed-off-by: Ethan Jackson &amp;lt;ethan-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
---
 lib/cfm.c              |   49 +++++++++++++++++++++++++++++++++++++++++-------
 lib/cfm.h              |    4 +++-
 ofproto/ofproto-dpif.c |    2 +-
 vswitchd/bridge.c      |    1 +
 vswitchd/vswitch.xml   |   37 ++++++++++++++++++++++++++++++++++++
 5 files changed, 84 insertions(+), 9 deletions(-)

diff --git a/lib/cfm.c b/lib/cfm.c
index d232b34..9df404e 100644
--- a/lib/cfm.c
+++ b/lib/cfm.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -26,6 +26,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 #include "flow.h"
 #include "hash.h"
 #include "hmap.h"
+#include "netdev.h"
 #include "ofpbuf.h"
 #include "packets.h"
 #include "poll-loop.h"
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -81,12 +82,16 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct ccm {
 BUILD_ASSERT_DECL(CCM_LEN == sizeof(struct ccm));
 
 struct cfm {
-    char *name;                 /* Name of this CFM object. */
+    const char *name;           /* Name of this CFM object. */
     struct hmap_node hmap_node; /* Node in all_cfms list. */
 
+    const struct netdev *netdev;
+    uint64_t rx_packets;        /* Packets received by 'netdev'. */
+
     uint64_t mpid;
     bool check_tnl_key;    /* Verify the tunnel key of inbound packets? */
     bool extended;         /* Extended mode. */
+    bool demand;           /* Demand mode. */
     bool booted;           /* A full fault interval has occured. */
     enum cfm_fault_reason fault;  /* Connectivity fault status. */
     enum cfm_fault_reason recv_fault;  /* Bit mask of faults occuring on
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -143,6 +148,18 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct hmap all_cfms = HMAP_INITIALIZER(&amp;amp;all_cfms);
 static unixctl_cb_func cfm_unixctl_show;
 static unixctl_cb_func cfm_unixctl_set_fault;
 
+static uint64_t
+cfm_rx_packets(const struct cfm *cfm)
+{
+    struct netdev_stats stats;
+
+    if (!netdev_get_stats(cfm-&amp;gt;netdev, &amp;amp;stats)) {
+        return stats.rx_packets;
+    } else {
+        return 0;
+    }
+}
+
 static const uint8_t *
 cfm_ccm_addr(const struct cfm *cfm)
 {
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -287,12 +304,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; cfm_init(void)
 /* Allocates a 'cfm' object called 'name'.  'cfm' should be initialized by
  * cfm_configure() before use. */
 struct cfm *
-cfm_create(const char *name)
+cfm_create(const struct netdev *netdev)
 {
     struct cfm *cfm;
 
     cfm = xzalloc(sizeof *cfm);
-    cfm-&amp;gt;name = xstrdup(name);
+    cfm-&amp;gt;name = netdev_get_name(netdev);
+    cfm-&amp;gt;netdev = netdev;
     hmap_init(&amp;amp;cfm-&amp;gt;remote_mps);
     cfm_generate_maid(cfm);
     hmap_insert(&amp;amp;all_cfms, &amp;amp;cfm-&amp;gt;hmap_node, hash_string(cfm-&amp;gt;name, 0));
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -320,7 +338,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; cfm_destroy(struct cfm *cfm)
     hmap_destroy(&amp;amp;cfm-&amp;gt;remote_mps);
     hmap_remove(&amp;amp;all_cfms, &amp;amp;cfm-&amp;gt;hmap_node);
     free(cfm-&amp;gt;rmps_array);
-    free(cfm-&amp;gt;name);
     free(cfm);
 }
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -332,6 +349,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; cfm_run(struct cfm *cfm)
         long long int interval = cfm_fault_interval(cfm);
         struct remote_mp *rmp, *rmp_next;
         bool old_cfm_fault = cfm-&amp;gt;fault;
+        bool demand_override;
 
         cfm-&amp;gt;fault = cfm-&amp;gt;recv_fault;
         cfm-&amp;gt;recv_fault = 0;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -373,14 +391,23 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; cfm_run(struct cfm *cfm)
         }
         cfm-&amp;gt;health_interval++;
 
-        HMAP_FOR_EACH_SAFE (rmp, rmp_next, node, &amp;amp;cfm-&amp;gt;remote_mps) {
+        demand_override = false;
+        if (cfm-&amp;gt;demand) {
+            uint64_t rx_packets = cfm_rx_packets(cfm);
+            demand_override = hmap_count(&amp;amp;cfm-&amp;gt;remote_mps) == 1
+                &amp;amp;&amp;amp; rx_packets &amp;gt; cfm-&amp;gt;rx_packets;
+            cfm-&amp;gt;rx_packets = rx_packets;
+        }
 
+        HMAP_FOR_EACH_SAFE (rmp, rmp_next, node, &amp;amp;cfm-&amp;gt;remote_mps) {
             if (!rmp-&amp;gt;recv) {
                 VLOG_INFO("%s: Received no CCM from RMP %"PRIu64" in the last"
                           " %lldms", cfm-&amp;gt;name, rmp-&amp;gt;mpid,
                           time_msec() - rmp-&amp;gt;last_rx);
-                hmap_remove(&amp;amp;cfm-&amp;gt;remote_mps, &amp;amp;rmp-&amp;gt;node);
-                free(rmp);
+                if (!demand_override) {
+                    hmap_remove(&amp;amp;cfm-&amp;gt;remote_mps, &amp;amp;rmp-&amp;gt;node);
+                    free(rmp);
+                }
             } else {
                 rmp-&amp;gt;recv = false;
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -518,6 +545,14 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; cfm_configure(struct cfm *cfm, const struct cfm_settings *s)
         interval_ms = MIN(s-&amp;gt;interval, UINT16_MAX);
     }
 
+    if (cfm-&amp;gt;extended &amp;amp;&amp;amp; s-&amp;gt;demand) {
+        interval_ms = MAX(interval_ms, 500);
+        if (!cfm-&amp;gt;demand) {
+            cfm-&amp;gt;demand = true;
+            cfm-&amp;gt;rx_packets = cfm_rx_packets(cfm);
+        }
+    }
+
     if (interval != cfm-&amp;gt;ccm_interval || interval_ms != cfm-&amp;gt;ccm_interval_ms) {
         cfm-&amp;gt;ccm_interval = interval;
         cfm-&amp;gt;ccm_interval_ms = interval_ms;
diff --git a/lib/cfm.h b/lib/cfm.h
index 8bb6778..eec9704 100644
--- a/lib/cfm.h
+++ b/lib/cfm.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -23,6 +23,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 
 struct flow;
 struct ofpbuf;
+struct netdev;
 
 #define CFM_RANDOM_VLAN UINT16_MAX
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -53,6 +54,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct cfm_settings {
     uint64_t mpid;              /* The MPID of this CFM. */
     int interval;               /* The requested transmission interval. */
     bool extended;              /* Run in extended mode. */
+    bool demand;                /* Run in demand mode. */
     bool opup;                  /* Operational State. */
     uint16_t ccm_vlan;          /* CCM Vlan tag. Zero if none.
                                    CFM_RANDOM_VLAN if random. */
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -62,7 +64,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct cfm_settings {
 };
 
 void cfm_init(void);
-struct cfm *cfm_create(const char *name);
+struct cfm *cfm_create(const struct netdev *);
 void cfm_destroy(struct cfm *);
 void cfm_run(struct cfm *);
 bool cfm_should_send_ccm(struct cfm *);
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 5cc56d1..b84e2c0 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1973,7 +1973,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; set_cfm(struct ofport *ofport_, const struct cfm_settings *s)
 
             ofproto = ofproto_dpif_cast(ofport-&amp;gt;up.ofproto);
             ofproto-&amp;gt;backer-&amp;gt;need_revalidate = REV_RECONFIGURE;
-            ofport-&amp;gt;cfm = cfm_create(netdev_get_name(ofport-&amp;gt;up.netdev));
+            ofport-&amp;gt;cfm = cfm_create(ofport-&amp;gt;up.netdev);
         }
 
         if (cfm_configure(ofport-&amp;gt;cfm, s)) {
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index e10036c..f067c9d 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -3691,6 +3691,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; iface_configure_cfm(struct iface *iface)
 
     s.extended = smap_get_bool(&amp;amp;iface-&amp;gt;cfg-&amp;gt;other_config, "cfm_extended",
                                false);
+    s.demand = smap_get_bool(&amp;amp;iface-&amp;gt;cfg-&amp;gt;other_config, "cfm_demand", false);
 
     opstate_str = smap_get(&amp;amp;iface-&amp;gt;cfg-&amp;gt;other_config, "cfm_opstate");
     s.opup = !opstate_str || !strcasecmp("up", opstate_str);
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 4396779..47b13d2 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2000,6 +2000,43 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
         compatibility with 802.1ag compliant implementations.  Defaults to
         &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;.
       &amp;lt;/column&amp;gt;
+
+      &amp;lt;column name="other_config" key="cfm_demand" type='{"type": "boolean"}'&amp;gt;
+        &amp;lt;p&amp;gt;
+          When &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, and
+          &amp;lt;ref column="other_config" key="cfm_extended"/&amp;gt; is true, the CFM
+          module operates in demand mode.  When in demand mode, traffic
+          received on the &amp;lt;ref table="Interface"/&amp;gt; is used to indicate
+          liveness.  CCMs are still transmitted and received, but if the
+          &amp;lt;ref table="Interface"/&amp;gt; is receiving traffic, their absence does not
+          cause a connectivity fault.
+        &amp;lt;/p&amp;gt;
+
+        &amp;lt;p&amp;gt;
+            Demand mode has a couple of caveats:
+          &amp;lt;ul&amp;gt;
+            &amp;lt;li&amp;gt;
+              To ensure that ovs-vswitchd has enough time to pull statistics
+              from the datapath, the minimum
+              &amp;lt;ref column="other_config" key="cfm_interval"/&amp;gt; is 500ms.
+            &amp;lt;/li&amp;gt;
+
+            &amp;lt;li&amp;gt;
+              To avoid ambiguity, demand mode disables itself when there are
+              multiple remote maintenance points.
+            &amp;lt;/li&amp;gt;
+
+            &amp;lt;li&amp;gt;
+              If the &amp;lt;ref table="Interface"/&amp;gt; is heavily congested, CCMs
+              containing the &amp;lt;ref column="other_config" key="cfm_opstate"/&amp;gt;
+              status may be dropped causing changes in the operational state to
+              be delayed.  Similarly, if CCMs containing the RDI bit are not
+              received, unidirectional link failures may not be detected.
+            &amp;lt;/li&amp;gt;
+          &amp;lt;/ul&amp;gt;
+        &amp;lt;/p&amp;gt;
+      &amp;lt;/column&amp;gt;
+
       &amp;lt;column name="other_config" key="cfm_opstate"
               type='{"type": "string", "enum": ["set", ["down", "up"]]}'&amp;gt;
         When &amp;lt;code&amp;gt;down&amp;lt;/code&amp;gt;, the CFM module marks all CCMs it generates as
&lt;/pre&gt;</description>
    <dc:creator>Ethan Jackson</dc:creator>
    <dc:date>2013-05-20T22:57:56</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20735">
    <title>[PATCH v2] gre: Restructure tunneling.</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20735</link>
    <description>&lt;pre&gt;Following patch restructures ovs tunneling and gre vport
implementation to make ovs tunneling more in sync with
upstream kernel tunneling.  Doing this tunneling code is
simplified as most of protocol processing on send and
recv is pushed to kernel tunneling.  For external ovs
module the code is moved to kernel compatibility code.

Signed-off-by: Pravin B Shelar &amp;lt;pshelar-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
---
v1-v2:
 - Fix Modules path for ip_tunnels_core.c
---
 datapath/compat.h                              |    6 +
 datapath/linux/Modules.mk                      |    6 +
 datapath/linux/compat/gre.c                    |  360 ++++++++++++++++++++++++
 datapath/linux/compat/gso.c                    |  166 +++++++++++
 datapath/linux/compat/gso.h                    |   46 +++
 datapath/linux/compat/include/linux/err.h      |    9 +
 datapath/linux/compat/include/linux/if_ether.h |    4 +
 datapath/linux/compat/include/net/gre.h        |  109 +++++++
 datapath/linux/compat/include/net/ip_tunnels.h |   52 ++++
 datapath/linux/compat/ip_tunnels_core.c        |   78 +++++
 datapath/tunnel.c                              |   12 +-
 datapath/tunnel.h                              |    8 +-
 datapath/vport-gre.c                           |  331 ++++++++++------------
 13 files changed, 998 insertions(+), 189 deletions(-)
 create mode 100644 datapath/linux/compat/gre.c
 create mode 100644 datapath/linux/compat/gso.c
 create mode 100644 datapath/linux/compat/gso.h
 create mode 100644 datapath/linux/compat/include/net/gre.h
 create mode 100644 datapath/linux/compat/include/net/ip_tunnels.h
 create mode 100644 datapath/linux/compat/ip_tunnels_core.c

diff --git a/datapath/compat.h b/datapath/compat.h
index c7fd225..6095323 100644
--- a/datapath/compat.h
+++ b/datapath/compat.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -93,5 +93,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static inline void skb_set_mark(struct sk_buff *skb, u32 mark)
 skb-&amp;gt;mark = mark;
 }
 #endif /* after 2.6.20 */
+#if LINUX_VERSION_CODE &amp;gt;= KERNEL_VERSION(2,6,36)
+#define rt_dst(rt) (rt-&amp;gt;dst)
+#else
+#define rt_dst(rt) (rt-&amp;gt;u.dst)
+#endif
+
 
 #endif /* compat.h */
diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk
index 1434a2d..a62d444 100644
--- a/datapath/linux/Modules.mk
+++ b/datapath/linux/Modules.mk
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -3,8 +3,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; openvswitch_sources += \
 linux/compat/dev-openvswitch.c \
 linux/compat/exthdrs_core.c \
 linux/compat/flex_array.c \
+linux/compat/gre.c \
+linux/compat/gso.c \
 linux/compat/genetlink-openvswitch.c \
 linux/compat/ip_output-openvswitch.c \
+linux/compat/ip_tunnels_core.c \
 linux/compat/kmemdup.c \
 linux/compat/netdevice.c \
 linux/compat/net_namespace.c \
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -13,6 +16,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; openvswitch_sources += \
 linux/compat/time.c\
 linux/compat/workqueue.c
 openvswitch_headers += \
+linux/compat/gso.h \
 linux/compat/include/asm/percpu.h \
 linux/compat/include/linux/compiler.h \
 linux/compat/include/linux/compiler-gcc.h \
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -61,8 +65,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; openvswitch_headers += \
 linux/compat/include/net/checksum.h \
 linux/compat/include/net/dst.h \
 linux/compat/include/net/genetlink.h \
+linux/compat/include/net/gre.h \
 linux/compat/include/net/inet_frag.h \
 linux/compat/include/net/ip.h \
+linux/compat/include/net/ip_tunnels.h \
 linux/compat/include/net/ipv6.h \
 linux/compat/include/net/net_namespace.h \
 linux/compat/include/net/netlink.h \
diff --git a/datapath/linux/compat/gre.c b/datapath/linux/compat/gre.c
new file mode 100644
index 0000000..2c091c8
--- /dev/null
+++ b/datapath/linux/compat/gre.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,360 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/*
+ * Copyright (c) 2007-2013 Nicira, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#include &amp;lt;linux/module.h&amp;gt;
+#include &amp;lt;linux/if.h&amp;gt;
+#include &amp;lt;linux/if_tunnel.h&amp;gt;
+#include &amp;lt;linux/icmp.h&amp;gt;
+#include &amp;lt;linux/in.h&amp;gt;
+#include &amp;lt;linux/ip.h&amp;gt;
+#include &amp;lt;linux/kernel.h&amp;gt;
+#include &amp;lt;linux/kmod.h&amp;gt;
+#include &amp;lt;linux/netdevice.h&amp;gt;
+#include &amp;lt;linux/skbuff.h&amp;gt;
+#include &amp;lt;linux/spinlock.h&amp;gt;
+
+#include &amp;lt;net/gre.h&amp;gt;
+#include &amp;lt;net/icmp.h&amp;gt;
+#include &amp;lt;net/protocol.h&amp;gt;
+#include &amp;lt;net/route.h&amp;gt;
+#include &amp;lt;net/xfrm.h&amp;gt;
+
+#include "gso.h"
+
+static struct gre_cisco_protocol __rcu *gre_cisco_proto;
+
+static int gre_handle_csum_offloads(struct sk_buff *skb, bool gre_csum)
+{
+if (skb-&amp;gt;ip_summed == CHECKSUM_PARTIAL &amp;amp;&amp;amp; gre_csum) {
+int err;
+
+err = skb_checksum_help(skb);
+return err;
+} else if (skb-&amp;gt;ip_summed != CHECKSUM_PARTIAL)
+skb-&amp;gt;ip_summed = CHECKSUM_NONE;
+return 0;
+}
+
+static void gre_csum_fix(struct sk_buff *skb)
+{
+struct gre_base_hdr *greh;
+__be32 *options;
+int gre_offset = skb_transport_offset(skb);
+
+greh = (struct gre_base_hdr *)skb_transport_header(skb);
+options = ((__be32 *)greh + 1);
+
+*options = 0;
+*(__sum16 *)options = csum_fold(skb_checksum(skb, gre_offset,
+     skb-&amp;gt;len - gre_offset, 0));
+}
+
+struct sk_buff *gre_handle_offloads(struct sk_buff *skb, bool gre_csum)
+{
+int err;
+
+skb_reset_inner_headers(skb);
+
+if (skb_is_gso(skb)) {
+if (gre_csum)
+OVS_GSO_CB(skb)-&amp;gt;fix_segment = gre_csum_fix;
+} else {
+err = gre_handle_csum_offloads(skb, gre_csum);
+if (err)
+goto error;
+
+}
+return skb;
+error:
+kfree_skb(skb);
+return ERR_PTR(err);
+}
+
+static bool is_gre_gso(struct sk_buff *skb)
+{
+return skb_is_gso(skb);
+}
+
+void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
+      int hdr_len)
+{
+struct gre_base_hdr *greh;
+
+__skb_push(skb, hdr_len);
+
+greh = (struct gre_base_hdr *)skb-&amp;gt;data;
+greh-&amp;gt;flags = tnl_flags_to_gre_flags(tpi-&amp;gt;flags);
+greh-&amp;gt;protocol = tpi-&amp;gt;proto;
+
+if (tpi-&amp;gt;flags&amp;amp;(TUNNEL_KEY|TUNNEL_CSUM|TUNNEL_SEQ)) {
+__be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4);
+
+if (tpi-&amp;gt;flags&amp;amp;TUNNEL_SEQ) {
+*ptr = tpi-&amp;gt;seq;
+ptr--;
+}
+if (tpi-&amp;gt;flags&amp;amp;TUNNEL_KEY) {
+*ptr = tpi-&amp;gt;key;
+ptr--;
+}
+if (tpi-&amp;gt;flags&amp;amp;TUNNEL_CSUM &amp;amp;&amp;amp; !is_gre_gso(skb)) {
+*(__sum16 *)ptr = 0;
+*(__sum16 *)ptr = csum_fold(skb_checksum(skb, 0,
+skb-&amp;gt;len, 0));
+}
+}
+}
+
+static __sum16 check_checksum(struct sk_buff *skb)
+{
+__sum16 csum = 0;
+
+switch (skb-&amp;gt;ip_summed) {
+case CHECKSUM_COMPLETE:
+csum = csum_fold(skb-&amp;gt;csum);
+
+if (!csum)
+break;
+/* Fall through. */
+
+case CHECKSUM_NONE:
+skb-&amp;gt;csum = 0;
+csum = __skb_checksum_complete(skb);
+skb-&amp;gt;ip_summed = CHECKSUM_COMPLETE;
+break;
+}
+
+return csum;
+}
+
+static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
+    bool *csum_err)
+{
+unsigned int ip_hlen = ip_hdrlen(skb);
+struct gre_base_hdr *greh;
+__be32 *options;
+int hdr_len;
+
+if (unlikely(!pskb_may_pull(skb, sizeof(struct gre_base_hdr))))
+return -EINVAL;
+
+greh = (struct gre_base_hdr *)(skb_network_header(skb) + ip_hlen);
+if (unlikely(greh-&amp;gt;flags &amp;amp; (GRE_VERSION | GRE_ROUTING)))
+return -EINVAL;
+
+tpi-&amp;gt;flags = gre_flags_to_tnl_flags(greh-&amp;gt;flags);
+hdr_len = ip_gre_calc_hlen(tpi-&amp;gt;flags);
+
+if (!pskb_may_pull(skb, hdr_len))
+return -EINVAL;
+
+greh = (struct gre_base_hdr *)(skb_network_header(skb) + ip_hlen);
+tpi-&amp;gt;proto = greh-&amp;gt;protocol;
+
+options = (__be32 *)(greh + 1);
+if (greh-&amp;gt;flags &amp;amp; GRE_CSUM) {
+if (check_checksum(skb)) {
+*csum_err = true;
+return -EINVAL;
+}
+options++;
+}
+
+if (greh-&amp;gt;flags &amp;amp; GRE_KEY) {
+tpi-&amp;gt;key = *options;
+options++;
+} else
+tpi-&amp;gt;key = 0;
+
+if (unlikely(greh-&amp;gt;flags &amp;amp; GRE_SEQ)) {
+tpi-&amp;gt;seq = *options;
+options++;
+} else
+tpi-&amp;gt;seq = 0;
+
+/* WCCP version 1 and 2 protocol decoding.
+ * - Change protocol to IP
+ * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
+ */
+if (greh-&amp;gt;flags == 0 &amp;amp;&amp;amp; tpi-&amp;gt;proto == htons(ETH_P_WCCP)) {
+tpi-&amp;gt;proto = htons(ETH_P_IP);
+if ((*(u8 *)options &amp;amp; 0xF0) != 0x40) {
+hdr_len += 4;
+if (!pskb_may_pull(skb, hdr_len))
+return -EINVAL;
+}
+}
+return 0;
+}
+
+static int gre_cisco_rcv(struct sk_buff *skb)
+{
+struct tnl_ptk_info tpi;
+bool csum_err = false;
+struct gre_cisco_protocol *proto;
+
+rcu_read_lock();
+proto = rcu_dereference(gre_cisco_proto);
+if (!proto)
+goto drop;
+
+if (parse_gre_header(skb, &amp;amp;tpi, &amp;amp;csum_err) &amp;lt; 0)
+goto drop;
+proto-&amp;gt;handler(skb, &amp;amp;tpi);
+rcu_read_unlock();
+return 0;
+
+drop:
+rcu_read_unlock();
+kfree_skb(skb);
+return 0;
+}
+
+static const struct gre_protocol ipgre_protocol = {
+.handler=gre_cisco_rcv,
+};
+
+#if LINUX_VERSION_CODE &amp;lt; KERNEL_VERSION(2,6,37)
+static const struct gre_protocol __rcu *gre_proto[GREPROTO_MAX] __read_mostly;
+
+int gre_add_protocol(const struct gre_protocol *proto, u8 version)
+{
+if (version &amp;gt;= GREPROTO_MAX)
+return -EINVAL;
+
+return (cmpxchg((const struct gre_protocol **)&amp;amp;gre_proto[version], NULL, proto) == NULL) ?
+0 : -EBUSY;
+}
+
+int gre_del_protocol(const struct gre_protocol *proto, u8 version)
+{
+int ret;
+
+if (version &amp;gt;= GREPROTO_MAX)
+return -EINVAL;
+
+ret = (cmpxchg((const struct gre_protocol **)&amp;amp;gre_proto[version], proto, NULL) == proto) ?
+0 : -EBUSY;
+
+if (ret)
+return ret;
+
+synchronize_net();
+return 0;
+}
+
+static int gre_rcv(struct sk_buff *skb)
+{
+const struct gre_protocol *proto;
+u8 ver;
+int ret;
+
+if (!pskb_may_pull(skb, 12))
+goto drop;
+
+ver = skb-&amp;gt;data[1]&amp;amp;0x7f;
+if (ver &amp;gt;= GREPROTO_MAX)
+goto drop;
+
+rcu_read_lock();
+proto = rcu_dereference(gre_proto[ver]);
+if (!proto || !proto-&amp;gt;handler)
+goto drop_unlock;
+ret = proto-&amp;gt;handler(skb);
+rcu_read_unlock();
+return ret;
+
+drop_unlock:
+rcu_read_unlock();
+drop:
+kfree_skb(skb);
+return NET_RX_DROP;
+}
+
+static const struct net_protocol net_gre_protocol = {
+.handler     = gre_rcv,
+#if LINUX_VERSION_CODE &amp;gt;= KERNEL_VERSION(2,6,32)
+.netns_ok    = 1,
+#endif
+};
+#endif
+
+static int gre_compat_init(void)
+{
+int err;
+
+#if LINUX_VERSION_CODE &amp;lt; KERNEL_VERSION(2,6,37)
+if (inet_add_protocol(&amp;amp;net_gre_protocol, IPPROTO_GRE) &amp;lt; 0) {
+pr_err("can't add protocol\n");
+return -EAGAIN;
+}
+#endif
+err = gre_add_protocol(&amp;amp;ipgre_protocol, GREPROTO_CISCO);
+if (err) {
+pr_warn("cannot register gre protocol handler\n");
+
+#if LINUX_VERSION_CODE &amp;lt; KERNEL_VERSION(2,6,37)
+inet_del_protocol(&amp;amp;net_gre_protocol, IPPROTO_GRE);
+#endif
+}
+
+return err;
+}
+
+static int gre_compat_exit(void)
+{
+int ret;
+
+ret = gre_del_protocol(&amp;amp;ipgre_protocol, GREPROTO_CISCO);
+if (ret)
+return ret;
+
+#if LINUX_VERSION_CODE &amp;lt; KERNEL_VERSION(2,6,37)
+ret = inet_del_protocol(&amp;amp;net_gre_protocol, IPPROTO_GRE);
+if (ret)
+return ret;
+#endif
+return 0;
+}
+
+int gre_cisco_register(struct gre_cisco_protocol *newp)
+{
+int err;
+
+err = gre_compat_init();
+if (err)
+return err;
+
+return (cmpxchg((struct gre_cisco_protocol **)&amp;amp;gre_cisco_proto, NULL, newp) == NULL) ?
+0 : -EBUSY;
+}
+
+int gre_cisco_unregister(struct gre_cisco_protocol *proto)
+{
+int ret;
+
+ret = (cmpxchg((struct gre_cisco_protocol **)&amp;amp;gre_cisco_proto, proto, NULL) == proto) ?
+0 : -EINVAL;
+
+if (ret)
+return ret;
+
+synchronize_net();
+ret = gre_compat_exit();
+return ret;
+}
diff --git a/datapath/linux/compat/gso.c b/datapath/linux/compat/gso.c
new file mode 100644
index 0000000..f6a4ad3
--- /dev/null
+++ b/datapath/linux/compat/gso.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,166 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/*
+ * Copyright (c) 2007-2013 Nicira, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#include &amp;lt;linux/module.h&amp;gt;
+#include &amp;lt;linux/if.h&amp;gt;
+#include &amp;lt;linux/if_tunnel.h&amp;gt;
+#include &amp;lt;linux/icmp.h&amp;gt;
+#include &amp;lt;linux/in.h&amp;gt;
+#include &amp;lt;linux/ip.h&amp;gt;
+#include &amp;lt;linux/kernel.h&amp;gt;
+#include &amp;lt;linux/kmod.h&amp;gt;
+#include &amp;lt;linux/netdevice.h&amp;gt;
+#include &amp;lt;linux/skbuff.h&amp;gt;
+#include &amp;lt;linux/spinlock.h&amp;gt;
+
+#include &amp;lt;net/gre.h&amp;gt;
+#include &amp;lt;net/icmp.h&amp;gt;
+#include &amp;lt;net/protocol.h&amp;gt;
+#include &amp;lt;net/route.h&amp;gt;
+#include &amp;lt;net/xfrm.h&amp;gt;
+
+#include "gso.h"
+
+static __be16 skb_network_protocol(struct sk_buff *skb)
+{
+__be16 type = skb-&amp;gt;protocol;
+int vlan_depth = ETH_HLEN;
+
+while (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) {
+struct vlan_hdr *vh;
+
+if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN)))
+return 0;
+
+vh = (struct vlan_hdr *)(skb-&amp;gt;data + vlan_depth);
+type = vh-&amp;gt;h_vlan_encapsulated_proto;
+vlan_depth += VLAN_HLEN;
+}
+
+return type;
+}
+
+static struct sk_buff *tnl_skb_gso_segment(struct sk_buff *skb,
+   netdev_features_t features,
+   bool tx_path)
+{
+struct iphdr *iph= ip_hdr(skb);
+int tnl_hlen= skb_inner_network_offset(skb);
+struct sk_buff *skb1= skb;
+struct sk_buff *segs;
+
+__skb_pull(skb, tnl_hlen);
+skb_reset_mac_header(skb);
+skb_reset_network_header(skb);
+skb_reset_transport_header(skb);
+skb-&amp;gt;protocol = skb_network_protocol(skb);
+
+segs = __skb_gso_segment(skb, 0, true);
+if (!segs || IS_ERR(segs))
+goto free;
+
+skb = segs;
+while (skb) {
+__skb_push(skb, tnl_hlen);
+skb_reset_mac_header(skb);
+skb_reset_network_header(skb);
+skb_set_transport_header(skb, sizeof(struct iphdr));
+skb-&amp;gt;mac_len = 0;
+
+memcpy(ip_hdr(skb), iph, tnl_hlen);
+if (OVS_GSO_CB(skb)-&amp;gt;fix_segment)
+OVS_GSO_CB(skb)-&amp;gt;fix_segment(skb);
+skb = skb-&amp;gt;next;
+}
+free:
+consume_skb(skb1);
+return segs;
+}
+
+static bool need_linearize(const struct sk_buff *skb)
+{
+int i;
+
+if (unlikely(skb_shinfo(skb)-&amp;gt;frag_list))
+return true;
+
+/*
+ * Generally speaking we should linearize if there are paged frags.
+ * However, if all of the refcounts are 1 we know nobody else can
+ * change them from underneath us and we can skip the linearization.
+ */
+for (i = 0; i &amp;lt; skb_shinfo(skb)-&amp;gt;nr_frags; i++)
+if (unlikely(page_count(skb_frag_page(&amp;amp;skb_shinfo(skb)-&amp;gt;frags[i])) &amp;gt; 1))
+return true;
+
+return false;
+}
+
+int ip_local_out(struct sk_buff *skb)
+{
+struct dst_entry *dst = skb_dst(skb);
+int ret = NETDEV_TX_OK;
+
+if (skb_is_gso(skb)) {
+skb = tnl_skb_gso_segment(skb, 0, true);
+if (!skb || IS_ERR(skb))
+return 0;
+}  else if (skb-&amp;gt;ip_summed == CHECKSUM_PARTIAL) {
+int err;
+
+if (unlikely(need_linearize(skb))) {
+err = __skb_linearize(skb);
+if (unlikely(err))
+return 0;
+}
+
+err = skb_checksum_help(skb);
+if (unlikely(err))
+return 0;
+}
+
+while (skb) {
+struct sk_buff *next_skb = skb-&amp;gt;next;
+int err;
+
+if (next_skb)
+skb_dst_set(skb, dst_clone(dst));
+else
+skb_dst_set(skb, dst);
+
+skb-&amp;gt;next = NULL;
+
+/*
+ * Allow our local IP stack to fragment the outer packet even
+ * if the DF bit is set as a last resort.  We also need to
+ * force selection of an IP ID here because Linux will
+ * otherwise leave it at 0 if the packet originally had DF set.
+ */
+
+skb-&amp;gt;local_df = 1;
+memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+
+#undef ip_local_out
+err = ip_local_out(skb);
+if (unlikely(net_xmit_eval(err)))
+ret = err;
+
+skb = next_skb;
+}
+return ret;
+}
diff --git a/datapath/linux/compat/gso.h b/datapath/linux/compat/gso.h
new file mode 100644
index 0000000..3157041
--- /dev/null
+++ b/datapath/linux/compat/gso.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,46 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+#ifndef __LINUX_GSO_WRAPPER_H
+#define __LINUX_GSO_WRAPPER_H
+
+#include &amp;lt;linux/skbuff.h&amp;gt;
+#include &amp;lt;net/protocol.h&amp;gt;
+
+#include "datapath.h"
+
+struct ovs_gso_cb {
+struct ovs_skb_cb dp_cb;
+sk_buff_data_tinner_network_header;
+void (*fix_segment)(struct sk_buff *);
+};
+#define OVS_GSO_CB(skb) ((struct ovs_gso_cb *)(skb)-&amp;gt;cb)
+
+#define skb_inner_network_header rpl_skb_inner_network_header
+
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
+static inline unsigned char *skb_inner_network_header(const struct sk_buff *skb)
+{
+return skb-&amp;gt;head + OVS_GSO_CB(skb)-&amp;gt;inner_network_header;
+}
+#else
+static inline unsigned char *skb_inner_network_header(const struct sk_buff *skb)
+{
+return OVS_GSO_CB(skb)-&amp;gt;inner_network_header;
+}
+#endif
+
+#define skb_inner_network_offset rpl_skb_inner_network_offset
+static inline int skb_inner_network_offset(const struct sk_buff *skb)
+{
+return skb_inner_network_header(skb) - skb-&amp;gt;data;
+}
+
+#define skb_reset_inner_headers rpl_skb_reset_inner_headers
+static inline void skb_reset_inner_headers(struct sk_buff *skb)
+{
+BUILD_BUG_ON(sizeof(struct ovs_gso_cb) &amp;gt; 48);
+OVS_GSO_CB(skb)-&amp;gt;inner_network_header = skb-&amp;gt;network_header;
+OVS_GSO_CB(skb)-&amp;gt;fix_segment = NULL;
+}
+
+#define ip_local_out rpl_ip_local_out
+int ip_local_out(struct sk_buff *skb);
+#endif
diff --git a/datapath/linux/compat/include/linux/err.h b/datapath/linux/compat/include/linux/err.h
index 50faf2a..d640298 100644
--- a/datapath/linux/compat/include/linux/err.h
+++ b/datapath/linux/compat/include/linux/err.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -18,4 +18,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static inline void *ERR_CAST(const void *ptr)
 }
 #endif /* HAVE_ERR_CAST */
 
+#ifndef IS_ERR_VALUE
+#define IS_ERR_VALUE(x) unlikely((x) &amp;gt;= (unsigned long)-MAX_ERRNO)
+static inline long __must_check IS_ERR_OR_NULL(const void *ptr)
+{
+return !ptr || IS_ERR_VALUE((unsigned long)ptr);
+}
+#endif
+
+
 #endif
diff --git a/datapath/linux/compat/include/linux/if_ether.h b/datapath/linux/compat/include/linux/if_ether.h
index 85b0d22..e22ea96 100644
--- a/datapath/linux/compat/include/linux/if_ether.h
+++ b/datapath/linux/compat/include/linux/if_ether.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -20,4 +20,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 #define ETH_P_802_3_MIN        0x0600
 #endif
 
+#ifndef ETH_P_8021AD
+#define ETH_P_8021AD    0x88A8          /* 802.1ad Service VLAN         */
+#endif
+
 #endif
diff --git a/datapath/linux/compat/include/net/gre.h b/datapath/linux/compat/include/net/gre.h
new file mode 100644
index 0000000..16dc54e
--- /dev/null
+++ b/datapath/linux/compat/include/net/gre.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,109 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+#ifndef __LINUX_GRE_WRAPPER_H
+#define __LINUX_GRE_WRAPPER_H
+
+#include &amp;lt;linux/skbuff.h&amp;gt;
+#include &amp;lt;net/ip_tunnels.h&amp;gt;
+
+#if LINUX_VERSION_CODE &amp;gt; KERNEL_VERSION(2,6,37)
+#include_next &amp;lt;net/gre.h&amp;gt;
+
+#else /* LINUX_VERSION_CODE &amp;lt;= KERNEL_VERSION(2,6,37) */
+
+#define GREPROTO_CISCO0
+#define GREPROTO_PPTP1
+#define GREPROTO_MAX2
+#define GRE_IP_PROTO_MAX2
+
+struct gre_protocol {
+int  (*handler)(struct sk_buff *skb);
+void (*err_handler)(struct sk_buff *skb, u32 info);
+};
+
+int gre_add_protocol(const struct gre_protocol *proto, u8 version);
+int gre_del_protocol(const struct gre_protocol *proto, u8 version);
+
+#endif
+
+#define GRE_IP_PROTO_MAX2
+
+struct gre_base_hdr {
+__be16 flags;
+__be16 protocol;
+};
+#define GRE_HEADER_SECTION 4
+
+#define MAX_GRE_PROTO_PRIORITY 255
+struct gre_cisco_protocol {
+int (*handler)(struct sk_buff *skb, const struct tnl_ptk_info *tpi);
+int (*err_handler)(struct sk_buff *skb, u32 info,
+   const struct tnl_ptk_info *tpi);
+u8 priority;
+};
+
+#define gre_build_header rpl_gre_build_header
+void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
+      int hdr_len);
+
+#define gre_handle_offloads rpl_gre_handle_offloads
+struct sk_buff *gre_handle_offloads(struct sk_buff *skb, bool gre_csum);
+
+int gre_cisco_register(struct gre_cisco_protocol *proto);
+int gre_cisco_unregister(struct gre_cisco_protocol *proto);
+
+static inline int ip_gre_calc_hlen(__be16 o_flags)
+{
+int addend = 4;
+
+if (o_flags&amp;amp;TUNNEL_CSUM)
+addend += 4;
+if (o_flags&amp;amp;TUNNEL_KEY)
+addend += 4;
+if (o_flags&amp;amp;TUNNEL_SEQ)
+addend += 4;
+return addend;
+}
+
+static inline __be16 gre_flags_to_tnl_flags(__be16 flags)
+{
+__be16 tflags = 0;
+
+if (flags &amp;amp; GRE_CSUM)
+tflags |= TUNNEL_CSUM;
+if (flags &amp;amp; GRE_ROUTING)
+tflags |= TUNNEL_ROUTING;
+if (flags &amp;amp; GRE_KEY)
+tflags |= TUNNEL_KEY;
+if (flags &amp;amp; GRE_SEQ)
+tflags |= TUNNEL_SEQ;
+if (flags &amp;amp; GRE_STRICT)
+tflags |= TUNNEL_STRICT;
+if (flags &amp;amp; GRE_REC)
+tflags |= TUNNEL_REC;
+if (flags &amp;amp; GRE_VERSION)
+tflags |= TUNNEL_VERSION;
+
+return tflags;
+}
+
+static inline __be16 tnl_flags_to_gre_flags(__be16 tflags)
+{
+__be16 flags = 0;
+
+if (tflags &amp;amp; TUNNEL_CSUM)
+flags |= GRE_CSUM;
+if (tflags &amp;amp; TUNNEL_ROUTING)
+flags |= GRE_ROUTING;
+if (tflags &amp;amp; TUNNEL_KEY)
+flags |= GRE_KEY;
+if (tflags &amp;amp; TUNNEL_SEQ)
+flags |= GRE_SEQ;
+if (tflags &amp;amp; TUNNEL_STRICT)
+flags |= GRE_STRICT;
+if (tflags &amp;amp; TUNNEL_REC)
+flags |= GRE_REC;
+if (tflags &amp;amp; TUNNEL_VERSION)
+flags |= GRE_VERSION;
+
+return flags;
+}
+#endif
diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h
new file mode 100644
index 0000000..cb53d21
--- /dev/null
+++ b/datapath/linux/compat/include/net/ip_tunnels.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,52 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+#ifndef __NET_IP_TUNNELS_WRAPPER_H
+#define __NET_IP_TUNNELS_WRAPPER_H 1
+
+#include &amp;lt;linux/if_tunnel.h&amp;gt;
+#include &amp;lt;linux/netdevice.h&amp;gt;
+#include &amp;lt;linux/skbuff.h&amp;gt;
+#include &amp;lt;linux/types.h&amp;gt;
+#include &amp;lt;net/dsfield.h&amp;gt;
+#include &amp;lt;net/flow.h&amp;gt;
+#include &amp;lt;net/inet_ecn.h&amp;gt;
+#include &amp;lt;net/ip.h&amp;gt;
+#include &amp;lt;net/rtnetlink.h&amp;gt;
+
+#define TUNNEL_CSUM__cpu_to_be16(0x01)
+#define TUNNEL_ROUTING__cpu_to_be16(0x02)
+#define TUNNEL_KEY__cpu_to_be16(0x04)
+#define TUNNEL_SEQ__cpu_to_be16(0x08)
+#define TUNNEL_STRICT__cpu_to_be16(0x10)
+#define TUNNEL_REC__cpu_to_be16(0x20)
+#define TUNNEL_VERSION__cpu_to_be16(0x40)
+#define TUNNEL_NO_KEY__cpu_to_be16(0x80)
+
+struct tnl_ptk_info {
+__be16 flags;
+__be16 proto;
+__be32 key;
+__be32 seq;
+};
+
+#define PACKET_RCVD0
+#define PACKET_REJECT1
+
+static inline void tunnel_ip_select_ident(struct sk_buff *skb,
+  const struct iphdr  *old_iph,
+  struct dst_entry *dst)
+{
+struct iphdr *iph = ip_hdr(skb);
+
+/* Use inner packet iph-id if possible. */
+if (skb-&amp;gt;protocol == htons(ETH_P_IP) &amp;amp;&amp;amp; old_iph-&amp;gt;id)
+iph-&amp;gt;id = old_iph-&amp;gt;id;
+else
+__ip_select_ident(iph, dst,
+(skb_shinfo(skb)-&amp;gt;gso_segs ?: 1) - 1);
+}
+
+int iptunnel_xmit(struct net *net, struct rtable *rt,
+  struct sk_buff *skb,
+  __be32 src, __be32 dst, __u8 proto,
+  __u8 tos, __u8 ttl, __be16 df);
+
+#endif /* __NET_IP_TUNNELS_H */
diff --git a/datapath/linux/compat/ip_tunnels_core.c b/datapath/linux/compat/ip_tunnels_core.c
new file mode 100644
index 0000000..67eee41
--- /dev/null
+++ b/datapath/linux/compat/ip_tunnels_core.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,78 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/*
+ * Copyright (c) 2007-2013 Nicira, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include &amp;lt;linux/in.h&amp;gt;
+#include &amp;lt;linux/in_route.h&amp;gt;
+#include &amp;lt;linux/inetdevice.h&amp;gt;
+#include &amp;lt;linux/jhash.h&amp;gt;
+#include &amp;lt;linux/list.h&amp;gt;
+#include &amp;lt;linux/kernel.h&amp;gt;
+#include &amp;lt;linux/version.h&amp;gt;
+#include &amp;lt;linux/workqueue.h&amp;gt;
+#include &amp;lt;linux/rculist.h&amp;gt;
+#include &amp;lt;net/ip_tunnels.h&amp;gt;
+#include &amp;lt;net/route.h&amp;gt;
+#include &amp;lt;net/xfrm.h&amp;gt;
+
+#include "gso.h"
+#include "compat.h"
+
+int iptunnel_xmit(struct net *net, struct rtable *rt,
+  struct sk_buff *skb,
+  __be32 src, __be32 dst, __u8 proto,
+  __u8 tos, __u8 ttl, __be16 df)
+{
+int pkt_len = skb-&amp;gt;len;
+struct iphdr *iph;
+int err;
+
+nf_reset(skb);
+secpath_reset(skb);
+skb_clear_rxhash(skb);
+skb_dst_drop(skb);
+skb_dst_set(skb, &amp;amp;rt_dst(rt));
+#if 0
+/* Do not clear ovs-callback.  It will be done in gso code. */
+memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+#endif
+
+/* Push down and install the IP header. */
+__skb_push(skb, sizeof(struct iphdr));
+skb_reset_network_header(skb);
+
+iph = ip_hdr(skb);
+
+iph-&amp;gt;version=4;
+iph-&amp;gt;ihl=sizeof(struct iphdr) &amp;gt;&amp;gt; 2;
+iph-&amp;gt;frag_off=df;
+iph-&amp;gt;protocol=proto;
+iph-&amp;gt;tos=tos;
+iph-&amp;gt;daddr=dst;
+iph-&amp;gt;saddr=src;
+iph-&amp;gt;ttl=ttl;
+tunnel_ip_select_ident(skb,
+       (const struct iphdr *)skb_inner_network_header(skb),
+       &amp;amp;rt_dst(rt));
+
+err = ip_local_out(skb);
+if (unlikely(net_xmit_eval(err)))
+pkt_len = 0;
+return pkt_len;
+}
diff --git a/datapath/tunnel.c b/datapath/tunnel.c
index 8c93e18..1275055 100644
--- a/datapath/tunnel.c
+++ b/datapath/tunnel.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -37,12 +37,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 #include "vlan.h"
 #include "vport.h"
 
-#if LINUX_VERSION_CODE &amp;gt;= KERNEL_VERSION(2,6,36)
-#define rt_dst(rt) (rt-&amp;gt;dst)
-#else
-#define rt_dst(rt) (rt-&amp;gt;u.dst)
-#endif
-
 /**
  *ovs_tnl_rcv - ingress point for generic tunnel code
  *
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -85,9 +79,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void ovs_tnl_rcv(struct vport *vport, struct sk_buff *skb,
 ovs_vport_receive(vport, skb, tun_key);
 }
 
-static struct rtable *find_route(struct net *net,
-__be32 *saddr, __be32 daddr, u8 ipproto,
-u8 tos, u32 skb_mark)
+struct rtable *find_route(struct net *net,
+  __be32 *saddr, __be32 daddr, u8 ipproto,
+  u8 tos, u32 skb_mark)
 {
 struct rtable *rt;
 /* Tunnel configuration keeps DSCP part of TOS bits, But Linux
diff --git a/datapath/tunnel.h b/datapath/tunnel.h
index 89c4e16..2ba7467 100644
--- a/datapath/tunnel.h
+++ b/datapath/tunnel.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -26,6 +26,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 #include "flow.h"
 #include "vport.h"
 
+struct rtable *find_route(struct net *net,
+  __be32 *saddr, __be32 daddr, u8 ipproto,
+  u8 tos, u32 skb_mark);
+
+u16 ovs_tnl_get_src_port(struct sk_buff *skb);
 
 int ovs_tnl_send(struct vport *vport, struct sk_buff *skb,
  u8 ipproto, int tunnel_hlen,
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -35,7 +40,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int ovs_tnl_send(struct vport *vport, struct sk_buff *skb,
 
 void ovs_tnl_rcv(struct vport *vport, struct sk_buff *skb,
  struct ovs_key_ipv4_tunnel *tun_key);
-u16 ovs_tnl_get_src_port(struct sk_buff *skb);
 
 static inline void tnl_tun_key_init(struct ovs_key_ipv4_tunnel *tun_key,
     const struct iphdr *iph, __be64 tun_id, u32 tun_flags)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -52,4 +56,4 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static inline void tnl_tun_key_init(struct ovs_key_ipv4_tunnel *tun_key,
        sizeof(*tun_key) - OVS_TUNNEL_KEY_SIZE);
 }
 
-#endif /* tunnel.h */
+#endif /* TUNNEL_H */
diff --git a/datapath/vport-gre.c b/datapath/vport-gre.c
index add17d9..f551976 100644
--- a/datapath/vport-gre.c
+++ b/datapath/vport-gre.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -24,26 +24,29 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 #include &amp;lt;linux/if_tunnel.h&amp;gt;
 #include &amp;lt;linux/if_vlan.h&amp;gt;
 #include &amp;lt;linux/in.h&amp;gt;
+#include &amp;lt;linux/if_vlan.h&amp;gt;
+#include &amp;lt;linux/in.h&amp;gt;
+#include &amp;lt;linux/in_route.h&amp;gt;
+#include &amp;lt;linux/inetdevice.h&amp;gt;
+#include &amp;lt;linux/jhash.h&amp;gt;
+#include &amp;lt;linux/list.h&amp;gt;
+#include &amp;lt;linux/kernel.h&amp;gt;
+#include &amp;lt;linux/workqueue.h&amp;gt;
+#include &amp;lt;linux/rculist.h&amp;gt;
+#include &amp;lt;net/route.h&amp;gt;
+#include &amp;lt;net/xfrm.h&amp;gt;
+
 
 #include &amp;lt;net/icmp.h&amp;gt;
 #include &amp;lt;net/ip.h&amp;gt;
+#include &amp;lt;net/ip_tunnels.h&amp;gt;
+#include &amp;lt;net/gre.h&amp;gt;
 #include &amp;lt;net/protocol.h&amp;gt;
 
 #include "datapath.h"
 #include "tunnel.h"
 #include "vport.h"
 
-/*
- * The GRE header is composed of a series of sections: a base and then a variable
- * number of options.
- */
-#define GRE_HEADER_SECTION 4
-
-struct gre_base_hdr {
-__be16 flags;
-__be16 protocol;
-};
-
 static int gre_hdr_len(const struct ovs_key_ipv4_tunnel *tun_key)
 {
 int len = GRE_HEADER_SECTION;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -55,19 +58,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int gre_hdr_len(const struct ovs_key_ipv4_tunnel *tun_key)
 return len;
 }
 
-static int gre64_hdr_len(const struct ovs_key_ipv4_tunnel *tun_key)
-{
-/* Set key for GRE64 tunnels, even when key if is zero. */
-int len = GRE_HEADER_SECTION +/* GRE Hdr */
-  GRE_HEADER_SECTION +/* GRE Key */
-  GRE_HEADER_SECTION;/* GRE SEQ */
-
-if (tun_key-&amp;gt;tun_flags &amp;amp; OVS_TNL_F_CSUM)
-len += GRE_HEADER_SECTION;
-
-return len;
-}
-
 /* Returns the least-significant 32 bits of a __be64. */
 static __be32 be64_get_low32(__be64 x)
 {
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -78,61 +68,35 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static __be32 be64_get_low32(__be64 x)
 #endif
 }
 
-static __be32 be64_get_high32(__be64 x)
+static __be16 ovs_tnl_flags_to_gre_flags(u16 tun_flags)
 {
-#ifdef __BIG_ENDIAN
-return (__force __be32)((__force u64)x &amp;gt;&amp;gt; 32);
-#else
-return (__force __be32)x;
-#endif
+__be16 flags = 0;
+if (tun_flags &amp;amp; OVS_TNL_F_CSUM)
+flags |= TUNNEL_CSUM;
+if (tun_flags &amp;amp; OVS_TNL_F_KEY)
+flags |= TUNNEL_KEY;
+return flags;
 }
 
-static void __gre_build_header(struct sk_buff *skb,
-       int tunnel_hlen,
-       bool is_gre64)
+static struct sk_buff *__build_header(const struct vport *vport,
+      struct sk_buff *skb,
+      int tunnel_hlen,
+      __be32 seq, __be16 gre64_flag)
 {
 const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)-&amp;gt;tun_key;
-__be32 *options = (__be32 *)(skb_network_header(skb) + tunnel_hlen
-- GRE_HEADER_SECTION);
-struct gre_base_hdr *greh = (struct gre_base_hdr *) skb_transport_header(skb);
-greh-&amp;gt;protocol = htons(ETH_P_TEB);
-greh-&amp;gt;flags = 0;
-
-/* Work backwards over the options so the checksum is last. */
-if (tun_key-&amp;gt;tun_flags &amp;amp; OVS_TNL_F_KEY || is_gre64) {
-greh-&amp;gt;flags |= GRE_KEY;
-if (is_gre64) {
-/* Set higher 32 bits to seq. */
-*options = be64_get_high32(tun_key-&amp;gt;tun_id);
-options--;
-greh-&amp;gt;flags |= GRE_SEQ;
-}
-*options = be64_get_low32(tun_key-&amp;gt;tun_id);
-options--;
-}
+struct tnl_ptk_info tpi;
 
-if (tun_key-&amp;gt;tun_flags &amp;amp; OVS_TNL_F_CSUM) {
-greh-&amp;gt;flags |= GRE_CSUM;
-*options = 0;
-*(__sum16 *)options = csum_fold(skb_checksum(skb,
-skb_transport_offset(skb),
-skb-&amp;gt;len - skb_transport_offset(skb),
-0));
-}
-}
+skb = gre_handle_offloads(skb, (tun_key-&amp;gt;tun_flags &amp;amp; OVS_TNL_F_CSUM));
+if (IS_ERR(skb))
+return NULL;
 
-static void gre_build_header(const struct vport *vport,
-     struct sk_buff *skb,
-     int tunnel_hlen)
-{
-__gre_build_header(skb, tunnel_hlen, false);
-}
+tpi.flags = ovs_tnl_flags_to_gre_flags(tun_key-&amp;gt;tun_flags) | gre64_flag;
+tpi.proto = htons(ETH_P_TEB);
+tpi.key = be64_get_low32(tun_key-&amp;gt;tun_id);
+tpi.seq = seq;
+gre_build_header(skb, &amp;amp;tpi, tunnel_hlen);
 
-static void gre64_build_header(const struct vport *vport,
-       struct sk_buff *skb,
-       int tunnel_hlen)
-{
-__gre_build_header(skb, tunnel_hlen, true);
+return skb;
 }
 
 static __be64 key_to_tunnel_id(__be32 key, __be32 seq)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -144,120 +108,45 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static __be64 key_to_tunnel_id(__be32 key, __be32 seq)
 #endif
 }
 
-static int parse_header(struct iphdr *iph, __be16 *flags, __be64 *tun_id,
-bool *is_gre64)
+static int _parse_header(const struct tnl_ptk_info *tpi, u32 *tnl_flags,
+ __be64 *tun_id)
 {
-/* IP and ICMP protocol handlers check that the IHL is valid. */
-struct gre_base_hdr *greh = (struct gre_base_hdr *)((u8 *)iph + (iph-&amp;gt;ihl &amp;lt;&amp;lt; 2));
-__be32 *options = (__be32 *)(greh + 1);
-int hdr_len;
-
-*flags = greh-&amp;gt;flags;
-
-if (unlikely(greh-&amp;gt;flags &amp;amp; (GRE_VERSION | GRE_ROUTING)))
-return -EINVAL;
-
-if (unlikely(greh-&amp;gt;protocol != htons(ETH_P_TEB)))
-return -EINVAL;
-
-hdr_len = GRE_HEADER_SECTION;
+int hdr_len = GRE_HEADER_SECTION;
 
-if (greh-&amp;gt;flags &amp;amp; GRE_CSUM) {
+*tnl_flags = 0;
+if (tpi-&amp;gt;flags &amp;amp; TUNNEL_CSUM) {
 hdr_len += GRE_HEADER_SECTION;
-options++;
+*tnl_flags |= OVS_TNL_F_CSUM;
 }
 
-if (greh-&amp;gt;flags &amp;amp; GRE_KEY) {
-__be32 seq;
-__be32 gre_key;
-
-gre_key = *options;
+if (tpi-&amp;gt;flags &amp;amp; TUNNEL_KEY) {
 hdr_len += GRE_HEADER_SECTION;
-options++;
-
-if (greh-&amp;gt;flags &amp;amp; GRE_SEQ) {
-seq = *options;
-*is_gre64 = true;
-} else {
-seq = 0;
-*is_gre64 = false;
-}
-*tun_id = key_to_tunnel_id(gre_key, seq);
+*tun_id = key_to_tunnel_id(tpi-&amp;gt;key, tpi-&amp;gt;seq);
+*tnl_flags |= OVS_TNL_F_KEY;
 } else {
 *tun_id = 0;
-/* Ignore GRE seq if there is no key present. */
-*is_gre64 = false;
 }
 
-if (greh-&amp;gt;flags &amp;amp; GRE_SEQ)
+if (tpi-&amp;gt;flags &amp;amp; TUNNEL_SEQ)
 hdr_len += GRE_HEADER_SECTION;
 
 return hdr_len;
 }
 
-static bool check_checksum(struct sk_buff *skb)
-{
-struct iphdr *iph = ip_hdr(skb);
-struct gre_base_hdr *greh = (struct gre_base_hdr *)(iph + 1);
-__sum16 csum = 0;
-
-if (greh-&amp;gt;flags &amp;amp; GRE_CSUM) {
-switch (skb-&amp;gt;ip_summed) {
-case CHECKSUM_COMPLETE:
-csum = csum_fold(skb-&amp;gt;csum);
-
-if (!csum)
-break;
-/* Fall through. */
-
-case CHECKSUM_NONE:
-skb-&amp;gt;csum = 0;
-csum = __skb_checksum_complete(skb);
-skb-&amp;gt;ip_summed = CHECKSUM_COMPLETE;
-break;
-}
-}
-
-return (csum == 0);
-}
-
-static u32 gre_flags_to_tunnel_flags(__be16 gre_flags, bool is_gre64)
-{
-u32 tunnel_flags = 0;
-
-if (gre_flags &amp;amp; GRE_KEY || is_gre64)
-tunnel_flags = OVS_TNL_F_KEY;
-
-if (gre_flags &amp;amp; GRE_CSUM)
-tunnel_flags |= OVS_TNL_F_CSUM;
-
-return tunnel_flags;
-}
-
 /* Called with rcu_read_lock and BH disabled. */
-static int gre_rcv(struct sk_buff *skb)
+static int gre_rcv(struct sk_buff *skb,
+   const struct tnl_ptk_info *tpi)
 {
 struct ovs_net *ovs_net;
 struct vport *vport;
 int hdr_len;
-struct iphdr *iph;
 struct ovs_key_ipv4_tunnel tun_key;
-__be16 gre_flags;
 u32 tnl_flags;
 __be64 key;
-bool is_gre64;
-
-if (unlikely(!pskb_may_pull(skb, sizeof(struct gre_base_hdr) + ETH_HLEN)))
-goto error;
-if (unlikely(!check_checksum(skb)))
-goto error;
-
-hdr_len = parse_header(ip_hdr(skb), &amp;amp;gre_flags, &amp;amp;key, &amp;amp;is_gre64);
-if (unlikely(hdr_len &amp;lt; 0))
-goto error;
 
+hdr_len = _parse_header(tpi, &amp;amp;tnl_flags, &amp;amp;key);
 ovs_net = net_generic(dev_net(skb-&amp;gt;dev), ovs_net_id);
-if (is_gre64)
+if (tpi-&amp;gt;flags &amp;amp; TUNNEL_SEQ)
 vport = rcu_dereference(ovs_net-&amp;gt;vport_net.gre64_vport);
 else
 vport = rcu_dereference(ovs_net-&amp;gt;vport_net.gre_vport);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -267,26 +156,22 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int gre_rcv(struct sk_buff *skb)
 if (unlikely(!pskb_may_pull(skb, hdr_len + ETH_HLEN)))
 goto error;
 
-iph = ip_hdr(skb);
-tnl_flags = gre_flags_to_tunnel_flags(gre_flags, is_gre64);
-tnl_tun_key_init(&amp;amp;tun_key, iph, key, tnl_flags);
+tnl_tun_key_init(&amp;amp;tun_key, ip_hdr(skb), key, tnl_flags);
 
 __skb_pull(skb, hdr_len);
 skb_postpull_rcsum(skb, skb_transport_header(skb), hdr_len + ETH_HLEN);
 
 ovs_tnl_rcv(vport, skb, &amp;amp;tun_key);
-return 0;
+return PACKET_RCVD;
 
 error:
 kfree_skb(skb);
-return 0;
+return PACKET_RCVD;
 }
 
-static const struct net_protocol gre_protocol_handlers = {
-.handler=gre_rcv,
-#if LINUX_VERSION_CODE &amp;gt;= KERNEL_VERSION(2,6,32)
-.netns_ok=1,
-#endif
+static struct gre_cisco_protocol gre_protocol = {
+.handler= gre_rcv,
+.priority= 1,
 };
 
 static int gre_ports;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -298,7 +183,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int gre_init(void)
 if (gre_ports &amp;gt; 1)
 return 0;
 
-err = inet_add_protocol(&amp;amp;gre_protocol_handlers, IPPROTO_GRE);
+err = gre_cisco_register(&amp;amp;gre_protocol);
 if (err)
 pr_warn("cannot register gre protocol handler\n");
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -311,7 +196,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void gre_exit(void)
 if (gre_ports &amp;gt; 0)
 return;
 
-inet_del_protocol(&amp;amp;gre_protocol_handlers, IPPROTO_GRE);
+gre_cisco_unregister(&amp;amp;gre_protocol);
 }
 
 static const char *gre_get_name(const struct vport *vport)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -361,7 +246,72 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void gre_tnl_destroy(struct vport *vport)
 gre_exit();
 }
 
-static int gre_tnl_send(struct vport *vport, struct sk_buff *skb)
+static int __send(struct vport *vport, struct sk_buff *skb,
+  int tunnel_hlen,
+  __be32 seq, __be16 gre64_flag)
+{
+struct net *net = ovs_dp_get_net(vport-&amp;gt;dp);
+struct rtable *rt;
+int min_headroom;
+__be16 df;
+__be32 saddr;
+int err;
+
+forward_ip_summed(skb, true);
+
+/* Route lookup */
+saddr = OVS_CB(skb)-&amp;gt;tun_key-&amp;gt;ipv4_src;
+rt = find_route(ovs_dp_get_net(vport-&amp;gt;dp),
+&amp;amp;saddr,
+OVS_CB(skb)-&amp;gt;tun_key-&amp;gt;ipv4_dst,
+IPPROTO_GRE,
+OVS_CB(skb)-&amp;gt;tun_key-&amp;gt;ipv4_tos,
+skb_get_mark(skb));
+if (IS_ERR(rt)) {
+err = PTR_ERR(rt);
+goto error;
+}
+
+min_headroom = LL_RESERVED_SPACE(rt_dst(rt).dev) + rt_dst(rt).header_len
++ tunnel_hlen
++ (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0);
+
+if (skb_headroom(skb) &amp;lt; min_headroom || skb_header_cloned(skb)) {
+int head_delta = SKB_DATA_ALIGN(min_headroom -
+skb_headroom(skb) +
+16);
+err = pskb_expand_head(skb, max_t(int, head_delta, 0),
+0, GFP_ATOMIC);
+if (unlikely(err))
+goto err_free_rt;
+}
+
+if (unlikely(vlan_deaccel_tag(skb))) {
+err = -ENOMEM;
+goto err_free_rt;
+}
+
+/* Push Tunnel header. */
+skb = __build_header(vport, skb, tunnel_hlen, seq, gre64_flag);
+if (unlikely(!skb)) {
+err = 0;
+goto err_free_rt;
+}
+
+df = OVS_CB(skb)-&amp;gt;tun_key-&amp;gt;tun_flags &amp;amp; OVS_TNL_F_DONT_FRAGMENT ?
+htons(IP_DF) : 0;
+
+return iptunnel_xmit(net, rt, skb, saddr,
+     OVS_CB(skb)-&amp;gt;tun_key-&amp;gt;ipv4_dst, IPPROTO_GRE,
+     OVS_CB(skb)-&amp;gt;tun_key-&amp;gt;ipv4_tos,
+     OVS_CB(skb)-&amp;gt;tun_key-&amp;gt;ipv4_ttl, df);
+err_free_rt:
+ip_rt_put(rt);
+error:
+return err;
+}
+
+static int gre_send(struct vport *vport, struct sk_buff *skb)
 {
 int hlen;
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -369,7 +319,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int gre_tnl_send(struct vport *vport, struct sk_buff *skb)
 return -EINVAL;
 
 hlen = gre_hdr_len(OVS_CB(skb)-&amp;gt;tun_key);
-return ovs_tnl_send(vport, skb, IPPROTO_GRE, hlen, gre_build_header);
+
+return __send(vport, skb, hlen, 0, 0);
 }
 
 const struct vport_ops ovs_gre_vport_ops = {
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -377,7 +328,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; const struct vport_ops ovs_gre_vport_ops = {
 .create= gre_create,
 .destroy= gre_tnl_destroy,
 .get_name= gre_get_name,
-.send= gre_tnl_send,
+.send= gre_send,
 };
 
 /* GRE64 vport. */
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -422,15 +373,39 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void gre64_tnl_destroy(struct vport *vport)
 gre_exit();
 }
 
-static int gre64_tnl_send(struct vport *vport, struct sk_buff *skb)
+static int gre64_hdr_len(const struct ovs_key_ipv4_tunnel *tun_key)
+{
+/* Set key for GRE64 tunnels, even when key if is zero. */
+int len = GRE_HEADER_SECTION +/* GRE Hdr */
+GRE_HEADER_SECTION +/* GRE Key */
+GRE_HEADER_SECTION;/* GRE SEQ */
+
+if (tun_key-&amp;gt;tun_flags &amp;amp; OVS_TNL_F_CSUM)
+len += GRE_HEADER_SECTION;
+
+return len;
+}
+
+static __be32 be64_get_high32(__be64 x)
+{
+#ifdef __BIG_ENDIAN
+return (__force __be32)((__force u64)x &amp;gt;&amp;gt; 32);
+#else
+return (__force __be32)x;
+#endif
+}
+
+static int gre64_send(struct vport *vport, struct sk_buff *skb)
 {
 int hlen;
+__be32 seq;
 
 if (unlikely(!OVS_CB(skb)-&amp;gt;tun_key))
 return -EINVAL;
 
 hlen = gre64_hdr_len(OVS_CB(skb)-&amp;gt;tun_key);
-return ovs_tnl_send(vport, skb, IPPROTO_GRE, hlen, gre64_build_header);
+seq = be64_get_high32(OVS_CB(skb)-&amp;gt;tun_key-&amp;gt;tun_id);
+return __send(vport, skb, hlen, seq, TUNNEL_SEQ);
 }
 
 const struct vport_ops ovs_gre64_vport_ops = {
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -438,5 +413,5 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; const struct vport_ops ovs_gre64_vport_ops = {
 .create= gre64_create,
 .destroy= gre64_tnl_destroy,
 .get_name= gre_get_name,
-.send= gre64_tnl_send,
+.send= gre64_send,
 };
&lt;/pre&gt;</description>
    <dc:creator>Pravin B Shelar</dc:creator>
    <dc:date>2013-05-20T21:33:52</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20731">
    <title>[PATCH] ofp-util: Make ofputil_port_from_ofp11() returnOFPP_NONE on error.</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20731</link>
    <description>&lt;pre&gt;This makes life easier for a few callers, and it agrees with a general
principle that a function should fill in its output parameters whether it
succeeds or not.

CC: Jarno Rajahalme &amp;lt;jarno.rajahalme-OYasijW0DpE&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
Signed-off-by: Ben Pfaff &amp;lt;blp-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
---
 lib/meta-flow.c |   12 +++---------
 lib/ofp-util.c  |    3 ++-
 2 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index c59d82a..54bc4c2 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1203,9 +1203,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; mf_set_value(const struct mf_field *mf,
 
     case MFF_IN_PORT_OXM: {
         uint16_t port;
-        if (ofputil_port_from_ofp11(value-&amp;gt;be32, &amp;amp;port)) {
-            port = OFPP_NONE;
-        }
+        ofputil_port_from_ofp11(value-&amp;gt;be32, &amp;amp;port);
         match_set_in_port(match, port);
         break;
     }
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1395,9 +1393,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; mf_set_flow_value(const struct mf_field *mf,
 
     case MFF_IN_PORT_OXM: {
         uint16_t port;
-        if (ofputil_port_from_ofp11(value-&amp;gt;be32, &amp;amp;port)) {
-            port = OFPP_NONE;
-        }
+        ofputil_port_from_ofp11(value-&amp;gt;be32, &amp;amp;port);
         flow-&amp;gt;in_port = port;
         break;
     }
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2481,9 +2477,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; mf_format(const struct mf_field *mf,
     case MFS_OFP_PORT_OXM:
         if (!mask) {
             uint16_t port;
-            if (ofputil_port_from_ofp11(value-&amp;gt;be32, &amp;amp;port)) {
-                port = OFPP_NONE;
-            }
+            ofputil_port_from_ofp11(value-&amp;gt;be32, &amp;amp;port);
             ofputil_format_port(port, s);
             break;
         }
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 2ca0077..b4ff09b 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -4029,7 +4029,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; ofputil_frag_handling_from_string(const char *s, enum ofp_config_flags *flags)
 /* Converts the OpenFlow 1.1+ port number 'ofp11_port' into an OpenFlow 1.0
  * port number and stores the latter in '*ofp10_port', for the purpose of
  * decoding OpenFlow 1.1+ protocol messages.  Returns 0 if successful,
- * otherwise an OFPERR_* number.
+ * otherwise an OFPERR_* number.  On error, stores OFPP_NONE in '*ofp10_port'.
  *
  * See the definition of OFP11_MAX for an explanation of the mapping. */
 enum ofperr
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -4044,6 +4044,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; ofputil_port_from_ofp11(ovs_be32 ofp11_port, uint16_t *ofp10_port)
         *ofp10_port = ofp11_port_h - OFPP11_OFFSET;
         return 0;
     } else {
+        *ofp10_port = OFPP_NONE;
         VLOG_WARN_RL(&amp;amp;bad_ofmsg_rl, "port %"PRIu32" is outside the supported "
                      "range 0 through %d or 0x%"PRIx32" through 0x%"PRIx32,
                      ofp11_port_h, OFPP_MAX - 1,
&lt;/pre&gt;</description>
    <dc:creator>Ben Pfaff</dc:creator>
    <dc:date>2013-05-20T18:31:19</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20729">
    <title>[PATCH 1/2] ofproto/ofproto-dpif.c: Re-implement theofproto/trace command</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20729</link>
    <description>&lt;pre&gt;Since the use of single datapath, all bridges belonging to the same type of
datapath will use the same (single) datapath. This causes confusion in the
current 'ofproto/trace' command. Especially, when given the unrelated
'bridge' and 'in_port' combination, the current implementation will still
be able to process and give misleading output. Thusly, this patch changes
the 'ofproto/trace' command syntax to formats shown as follow.

ofproto/trace [datapath] odp_flow [-generate|packet]
ofproto/trace bridge br_flow [-generate|packet]

Also, this patch updates the tests and the manpages accordingly.

Co-authored-by: Ben Pfaff &amp;lt;blp-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
Signed-off-by: Alex Wang &amp;lt;alexw-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
---
 ofproto/ofproto-dpif.c      |  155 ++++++++++++++++++++++---------------------
 ofproto/ofproto-unixctl.man |  138 +++++++++++++++++++++++---------------
 tests/learn.at              |   16 ++---
 tests/ofproto-dpif.at       |   76 ++++++++++-----------
 tests/tunnel.at             |   52 +++++++--------
 5 files changed, 233 insertions(+), 204 deletions(-)

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index c4f7d25..a77f339 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -8128,7 +8128,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void
 ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
                       void *aux OVS_UNUSED)
 {
-    const char *dpname = argv[1];
+    const struct dpif_backer *backer;
     struct ofproto_dpif *ofproto;
     struct ofpbuf odp_key;
     struct ofpbuf *packet;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -8138,101 +8138,102 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
     char *s;
 
     packet = NULL;
-    ofpbuf_init(&amp;amp;odp_key, 0);
+    backer = NULL;
     ds_init(&amp;amp;result);
+    ofpbuf_init(&amp;amp;odp_key, 0);
 
-    ofproto = ofproto_dpif_lookup(dpname);
-    if (!ofproto) {
-        unixctl_command_reply_error(conn, "Unknown ofproto (use ofproto/list "
-                                    "for help)");
-        goto exit;
+    /* Handle "-generate" or a hex string as the last argument. */
+    if (!strcmp(argv[argc - 1], "-generate")) {
+        packet = ofpbuf_new(0);
+        argc--;
+    } else {
+        const char *error = eth_from_hex(argv[argc - 1], &amp;amp;packet);
+        if (!error) {
+            argc--;
+        } else if (argc == 4) {
+            /* The 3-argument form must end in "-generate' or a hex string. */
+            unixctl_command_reply_error(conn, error);
+            goto exit;
+        }
     }
-    if (argc == 3 || (argc == 4 &amp;amp;&amp;amp; !strcmp(argv[3], "-generate"))) {
-        /* ofproto/trace dpname flow [-generate] */
-        const char *flow_s = argv[2];
-        const char *generate_s = argv[3];
 
-        /* Allow 'flow_s' to be either a datapath flow or an OpenFlow-like
-         * flow.  We guess which type it is based on whether 'flow_s' contains
-         * an '(', since a datapath flow always contains '(') but an
-         * OpenFlow-like flow should not (in fact it's allowed but I believe
-         * that's not documented anywhere).
-         *
-         * An alternative would be to try to parse 'flow_s' both ways, but then
-         * it would be tricky giving a sensible error message.  After all, do
-         * you just say "syntax error" or do you present both error messages?
-         * Both choices seem lousy. */
-        if (strchr(flow_s, '(')) {
-            int error;
-
-            /* Convert string to datapath key. */
-            ofpbuf_init(&amp;amp;odp_key, 0);
-            error = odp_flow_key_from_string(flow_s, NULL, &amp;amp;odp_key);
-            if (error) {
-                unixctl_command_reply_error(conn, "Bad flow syntax");
-                goto exit;
+    /* Parse the flow and determine whether a datapath or
+     * bridge is specified. If function odp_flow_key_from_string()
+     * returns 0, the flow is a odp_flow. If function
+     * parse_ofp_exact_flow() returns 0, the flow is a br_flow. */
+    if (!odp_flow_key_from_string(argv[argc - 1], NULL, &amp;amp;odp_key)) {
+        /* If the odp_flow is the second argument,
+         * the datapath name is the first argument. */
+        if (argc == 3) {
+            const char *dp_type;
+            if (!strncmp(argv[1], "ovs-", 4)) {
+                dp_type = argv[1] + 4;
+            } else {
+                dp_type = argv[1];
             }
-
-            /* The user might have specified the wrong ofproto but within the
-             * same backer.  That's OK, ofproto_receive() can find the right
-             * one for us. */
-            if (ofproto_receive(ofproto-&amp;gt;backer, NULL, odp_key.data,
-                                odp_key.size, &amp;amp;flow, NULL, &amp;amp;ofproto, NULL,
-                                &amp;amp;initial_vals)) {
-                unixctl_command_reply_error(conn, "Invalid flow");
+            backer = shash_find_data(&amp;amp;all_dpif_backers, dp_type);
+            if (!backer) {
+                unixctl_command_reply_error(conn, "Cannot find datapath "
+                               "of this name");
                 goto exit;
             }
-            ds_put_format(&amp;amp;result, "Bridge: %s\n", ofproto-&amp;gt;up.name);
         } else {
-            char *error_s;
-
-            error_s = parse_ofp_exact_flow(&amp;amp;flow, argv[2]);
-            if (error_s) {
-                unixctl_command_reply_error(conn, error_s);
-                free(error_s);
+            /* No datapath name specified, so there should be only one
+             * datapath. */
+            struct shash_node *node;
+            if (shash_count(&amp;amp;all_dpif_backers) != 1) {
+                unixctl_command_reply_error(conn, "Must specify datapath "
+                         "name, there is more than one type of datapath");
                 goto exit;
             }
-
-            initial_vals.vlan_tci = flow.vlan_tci;
+            node = shash_first(&amp;amp;all_dpif_backers);
+            backer = node-&amp;gt;data;
         }
 
-        /* Generate a packet, if requested. */
-        if (generate_s) {
-            packet = ofpbuf_new(0);
-            flow_compose(packet, &amp;amp;flow);
+        /* Extract the ofproto_dpif object from the ofproto_receive()
+         * function. */
+        if (ofproto_receive(backer, NULL, odp_key.data,
+                            odp_key.size, &amp;amp;flow, NULL, &amp;amp;ofproto, NULL,
+                            &amp;amp;initial_vals)) {
+            unixctl_command_reply_error(conn, "Invalid datapath flow");
+            goto exit;
         }
-    } else if (argc == 7) {
-        /* ofproto/trace dpname priority tun_id in_port mark packet */
-        const char *priority_s = argv[2];
-        const char *tun_id_s = argv[3];
-        const char *in_port_s = argv[4];
-        const char *mark_s = argv[5];
-        const char *packet_s = argv[6];
-        uint32_t in_port = atoi(in_port_s);
-        ovs_be64 tun_id = htonll(strtoull(tun_id_s, NULL, 0));
-        uint32_t priority = atoi(priority_s);
-        uint32_t mark = atoi(mark_s);
-        const char *msg;
-
-        msg = eth_from_hex(packet_s, &amp;amp;packet);
-        if (msg) {
-            unixctl_command_reply_error(conn, msg);
+        ds_put_format(&amp;amp;result, "Bridge: %s\n", ofproto-&amp;gt;up.name);
+    } else if (!parse_ofp_exact_flow(&amp;amp;flow, argv[argc - 1])) {
+        if (argc != 3) {
+            unixctl_command_reply_error(conn, "Must specify bridge name");
             goto exit;
         }
 
-        ds_put_cstr(&amp;amp;result, "Packet: ");
-        s = ofp_packet_to_string(packet-&amp;gt;data, packet-&amp;gt;size);
-        ds_put_cstr(&amp;amp;result, s);
-        free(s);
-
-        flow_extract(packet, priority, mark, NULL, in_port, &amp;amp;flow);
-        flow.tunnel.tun_id = tun_id;
+        ofproto = ofproto_dpif_lookup(argv[1]);
+        if (!ofproto) {
+            unixctl_command_reply_error(conn, "Unknown bridge name");
+            goto exit;
+        }
         initial_vals.vlan_tci = flow.vlan_tci;
     } else {
-        unixctl_command_reply_error(conn, "Bad command syntax");
+        unixctl_command_reply_error(conn, "Bad flow syntax");
         goto exit;
     }
 
+    /* Generate a packet, if requested. */
+    if (packet) {
+        if (!packet-&amp;gt;size) {
+            flow_compose(packet, &amp;amp;flow);
+        } else {
+            ds_put_cstr(&amp;amp;result, "Packet: ");
+            s = ofp_packet_to_string(packet-&amp;gt;data, packet-&amp;gt;size);
+            ds_put_cstr(&amp;amp;result, s);
+            free(s);
+
+            /* Use the metadata from the flow and the packet argument
+             * to reconstruct the flow. */
+            flow_extract(packet, flow.skb_priority, flow.skb_mark, NULL,
+                         flow.in_port, &amp;amp;flow);
+            initial_vals.vlan_tci = flow.vlan_tci;
+        }
+    }
+
     ofproto_trace(ofproto, &amp;amp;flow, packet, &amp;amp;initial_vals, &amp;amp;result);
     unixctl_command_reply(conn, ds_cstr(&amp;amp;result));
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -8661,8 +8662,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; ofproto_dpif_unixctl_init(void)
 
     unixctl_command_register(
         "ofproto/trace",
-        "bridge {priority tun_id in_port mark packet | odp_flow [-generate]}",
-        2, 6, ofproto_unixctl_trace, NULL);
+        "[dp_name]|bridge odp_flow|br_flow [-generate|packet]",
+        1, 3, ofproto_unixctl_trace, NULL);
     unixctl_command_register("fdb/flush", "[bridge]", 0, 1,
                              ofproto_unixctl_fdb_flush, NULL);
     unixctl_command_register("fdb/show", "bridge", 1, 1,
diff --git a/ofproto/ofproto-unixctl.man b/ofproto/ofproto-unixctl.man
index 8890343..8141de9 100644
--- a/ofproto/ofproto-unixctl.man
+++ b/ofproto/ofproto-unixctl.man
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -6,70 +6,98 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; These commands manage the core OpenFlow switch implementation (called
 Lists the names of the running ofproto instances.  These are the names
 that may be used on \fBofproto/trace\fR.
 .
-.IP "\fBofproto/trace \fIswitch priority tun_id in_port mark packet\fR"
-.IQ "\fBofproto/trace \fIswitch flow \fB\-generate\fR"
-Traces the path of an imaginary packet through \fIswitch\fR.  Both
-forms require \fIswitch\fR, the switch on which the packet arrived
-(one of those listed by \fBofproto/list\fR).  The first form specifies
-a packet's contents explicitly:
+.IP "\fBofproto/trace\fR [\fIdpname\fR] \fIodp_flow\fR [\fB\-generate \fR| \
+\fIpacket\fR]"
+.IQ "\fBofproto/trace\fR \fIbridge\fR \fIbr_flow\fR \
+[\fB\-generate \fR| \fIpacket\fR]"
+Traces the path of an imaginary packet through \fIswitch\fR and
+reports the path that it took.  The packet's headers (e.g. source and
+destination) and metadata (e.g. input port), together called its
+``flow,'' are usually all that matter for this purpose.  You can
+specify the flow in the following ways:
+.
 .RS
-.IP "\fIpriority\fR"
-Packet QoS priority. Use \fB0\fR if QoS is not setup.
-.IP "\fItun_id\fR"
-The tunnel ID on which the packet arrived.  Use
-\fB0\fR if the packet did not arrive through a tunnel.
-.IP "\fIin_port\fR"
-The OpenFlow port on which the packet arrived.  Use \fB65534\fR if the
-packet arrived on \fBOFPP_LOCAL\fR, the local port.
-.IP "\fImark\fR"
-SKB mark of the packet. Use \fB0\fR if Netfilter marks are not used.
-.IP "\fIpacket\fR"
-A sequence of hex digits specifying the packet's contents.  An
-Ethernet frame is at least 14 bytes long, so there must be at least 28
-hex digits.  Obviously, it is inconvenient to type in the hex digits
-by hand, so the \fBovs\-pcap\fR(1) and \fBovs\-tcpundump\fR(1)
-utilities provide easier ways.
+.IP "\fIdpname\fR \fIodp_flow\fR"
+\fIodp_flow\fR is a flow in the form printed by \fBovs\-dpctl\fR(8)'s
+\fBdump\-flows\fR command.  If all of your bridges have the same type,
+which is the common case, then you can omit \fIdpname\fR, but if you
+have bridges of different types (say, both \fBovs-netdev\fR and
+\fBovs-system\fR), then you need to specify a \fIdpname\fR to disambiguate.
+.
+.IP "\fIbridge\fR \fIbr_flow\fR"
+\fIbr_flow\fR is a flow in the form similar to that accepted by
+\fBovs\-ofctl\fR(8)'s \fBadd\-flow\fR command.  (This is not an
+OpenFlow flow: besides other differences, it never contains
+wildcards.)  \fIbridge\fR names of the bridge through which
+\fIbr_flow\fR should be traced.
 .RE
+.
 .IP
-The second form specifies the packet's contents implicitly:
+Most commonly, one specifies only a flow, using one of the forms
+above, but sometimes one might need to specify an actual packet
+instead of just a flow:
+.
 .RS
-.IP "\fIflow\fR"
-A flow in one of two forms: either the form printed by
-\fBovs\-dpctl\fR(8)'s \fBdump\-flows\fR command, or in a format
-similar to that accepted by \fBovs\-ofctl\fR(8)'s \fBadd\-flow\fR
-command.  This is not an OpenFlow flow: besides other differences, it
-never contains wildcards.  \fB\*(PN\fR generates an arbitrary packet
-that has the specified \fIflow\fR.
-.RE
+.IP "Side effects."
+Some actions have side effects.  For example, the \fBnormal\fR action
+can update the MAC learning table, and the \fBlearn\fR action can
+change OpenFlow tables.  \fBofproto/trace\fR only performs side
+effects when a packet is specified.  If you want side effects to take
+place, then you must supply a packet.
+.
 .IP
-\fB\*(PN\fR will respond with extensive information on how the packet
-would be handled if it were to be received.  The packet will not
-actually be sent, but side effects such as MAC learning will occur.
+(Output actions are obviously side effects too, but
+\fBofproto/trace\fR never executes them, even when one specifies a
+packet.)
 .
-.IP "\fBofproto/trace \fIswitch flow\fR"
-Traces the path of a packet in an imaginary flow through
-\fIswitch\fR.  The arguments are:
-.RS
-.IP "\fIswitch\fR"
-The switch on which the packet arrived (one of those listed by
-\fBofproto/list\fR).
-.IP "\fIflow\fR"
-A flow in one of two forms: either the form printed by
-\fBovs\-dpctl\fR(8)'s \fBdump\-flows\fR command, or in a format
-similar to that accepted by \fBovs\-ofctl\fR(8)'s \fBadd\-flow\fR
-command.  This is not an OpenFlow flow: besides other differences, it
-never contains wildcards.
+.IP "Incomplete information."
+Most of the time, Open vSwitch can figure out everything about the
+path of a packet using just the flow, but in some special
+circumstances it needs to look at parts of the packet that are not
+included in the flow.  When this is the case, and you do not supply a
+packet, then \fBofproto/trace\fR will tell you it needs a packet.
 .RE
+.
 .IP
-\fB\*(PN\fR will respond with extensive information on how a packet
-in \fIflow\fR would be handled if it were received by
-\fIswitch\fR.  No packet will actually be sent.  Some side effects may
-occur, but MAC learning in particular will not.
+If you wish to include a packet as part of the \fBofproto/trace\fR
+operation, there are two ways to do it:
+.
+.RS
+.IP \fB\-generate\fR
+This option, added to one of the ways to specify a flow already
+described, causes Open vSwitch to internally generate a packet with
+the flow described and then to use that packet.  If your goal is to
+execute side effects, then \fB\-generate\fR is the easiest way to do
+it, but \fB\-generate\fR is not a good way to fill in incomplete
+information, because it generates packets based on only the flow
+information, which means that the packets really do not have any more
+information than the flow.
+.
+.IP \fIpacket\fR
+This form supplies an explicit \fIpacket\fR as a sequence of hex
+digits.  An Ethernet frame is at least 14 bytes long, so there must be
+at least 28 hex digits.  Obviously, it is inconvenient to type in the
+hex digits by hand, so the \fBovs\-pcap\fR(1) and
+\fBovs\-tcpundump\fR(1) utilities provide easier ways.
 .IP
-This form of \fBofproto/trace\fR cannot determine the complete set of
-datapath actions in some corner cases.  If the results say that this
-is the case, rerun \fBofproto/trace\fR supplying a packet in the flow
-to get complete results.
+With this form, packet headers are extracted directly from
+\fIpacket\fR, so the \fIodp_flow\fR or \fIbr_flow\fR should specify
+only metadata. The metadata can be:
+.RS
+.IP \fIskb_priority\fR
+Packet QoS priority.
+.IP \fIskb_mark\fR
+SKB mark of the packet.
+.IP \fItun_id\fR
+The tunnel ID on which the packet arrived.
+.IP \fIin_port\fR
+The port on which the packet arrived.
+.RE
+.
+The in_port value is kernel datapath port number for the first format
+and OpenFlow port number for the second format. The numbering of these
+two types of port usually differs and there is no relationship.
+.RE
 .IP "\fBofproto/self\-check\fR [\fIswitch\fR]"
 Runs an internal consistency check on \fIswitch\fR, if specified,
 otherwise on all ofproto instances, and responds with a brief summary
diff --git a/tests/learn.at b/tests/learn.at
index 5eb3e5d..cd9983e 100644
--- a/tests/learn.at
+++ b/tests/learn.at
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -75,7 +75,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
 # Trace an ARP packet arriving on port 3, to create a MAC learning entry.
 flow="in_port(3),eth(src=50:54:00:00:00:05,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=192.168.0.1,tip=192.168.0.2,op=1,sha=50:54:00:00:00:05,tha=00:00:00:00:00:00)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
 
 expected="1,2,100"
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -92,7 +92,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; NXST_FLOW reply:
 
 # Trace a packet arrival destined for the learned MAC.
 # (This will also learn a MAC.)
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:06,dst=50:54:00:00:00:05),eth_type(0x0806),arp(sip=192.168.0.2,tip=192.168.0.1,op=2,sha=50:54:00:00:00:06,tha=50:54:00:00:00:05)' -generate], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:06,dst=50:54:00:00:00:05),eth_type(0x0806),arp(sip=192.168.0.2,tip=192.168.0.1,op=2,sha=50:54:00:00:00:06,tha=50:54:00:00:00:05)' -generate], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [Datapath actions: 3
 ])
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -106,7 +106,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; NXST_FLOW reply:
 
 # Trace a packet arrival that updates the first learned MAC entry.
 flow="in_port(2),eth(src=50:54:00:00:00:05,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=192.168.0.1,tip=192.168.0.2,op=1,sha=50:54:00:00:00:05,tha=00:00:00:00:00:00)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
 
 expected="1,3,100"
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -147,7 +147,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
 # Trace an ICMP packet arriving on port 3, to create a MAC learning entry.
 flow="in_port(3),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
 
 expected="1,2,100"
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -166,7 +166,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; NXST_FLOW reply:
 # disappear as long as we refresh it every second.
 for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25; do
     ovs-appctl time/warp 1000
-    AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
+    AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
 
     # Check that the entry is there.
     AT_CHECK([ovs-ofctl dump-flows br0 table=1], [0], [stdout])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -209,7 +209,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([[ovs-ofctl add-flow br0 'table=0 tcp actions=learn(table=1, hard_timeo
 
 # Trace a TCPv4 packet arriving on port 3.
 flow="in_port(3),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:06),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=6,tos=0,ttl=64,frag=no),tcp(src=40000,dst=80)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
 
 expected="1,2,100"
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -237,7 +237,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([[ovs-ofctl add-flow br0 'table=0 tcp6 actions=learn(table=1, hard_time
 
 # Trace a TCPv6 packet arriving on port 3.
 flow="in_port(3),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:06),eth_type(0x86dd),ipv6(src=fec0::2,dst=fec0::1,label=0,proto=6,tclass=0,hlimit=255,frag=no),tcp(src=40000,dst=80)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
 
 expected="1,2,100"
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -296,7 +296,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_SETUP([learning action - fin_timeout feature])
 OVS_VSWITCHD_START(
     [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1])
 AT_CHECK([[ovs-ofctl add-flow br0 'actions=learn(fin_hard_timeout=10, fin_idle_timeout=5, NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], output:NXM_OF_IN_PORT[])']])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=192.168.0.1,tip=192.168.0.2,op=1,sha=50:54:00:00:00:05,tha=00:00:00:00:00:00)' -generate], [0], [ignore])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=192.168.0.1,tip=192.168.0.2,op=1,sha=50:54:00:00:00:05,tha=00:00:00:00:00:00)' -generate], [0], [ignore])
 AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip], [0],
 [NXST_FLOW reply:
  table=1, dl_dst=50:54:00:00:00:05 actions=fin_timeout(idle_timeout=5,hard_timeout=10),output:1
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 1fdbac3..6a46ddb 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -62,7 +62,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=15,reg0=0x10,reg1=0x11,reg2=0x12,reg3=0x13,reg4=0x14,reg5=0x15,reg6=0x16
 
 ])
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(90),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(90),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: 20,21,22,33
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -81,7 +81,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=5            actions=pop:NXM_NX_REG3[[]],output:NXM_NX_REG3[[]]
 
 ])
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(90),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(90),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: 33,22,21,20
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -102,7 +102,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=7 actions=load:0x110000ff-&amp;gt;NXM_NX_REG0[[]],output:NXM_NX_REG0[[]]
 in_port=8 actions=1,9,load:9-&amp;gt;NXM_OF_IN_PORT[[]],1,9
 ])
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: 9,55,10,55,66,11,77,88,9,1
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -117,24 +117,24 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; table=0 in_port=1 action=dec_ttl,output:2,resubmit(1,1),output:4
 table=1 in_port=1 action=dec_ttl,output:3
 ])
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=2,frag=no)' -generate], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=2,frag=no)' -generate], [0], [stdout])
 AT_CHECK([tail -3 stdout], [0],
   [Datapath actions: set(ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=1,frag=no)),2,4
 This flow is handled by the userspace slow path because it:
 - Sends "packet-in" messages to the OpenFlow controller.
 ])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=3,frag=no)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=3,frag=no)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=2,frag=no)),2,set(ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=1,frag=no)),3,4
 ])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=10,tclass=0x70,hlimit=128,frag=no)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=10,tclass=0x70,hlimit=128,frag=no)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(ipv6(src=::1,dst=::2,label=0,proto=10,tclass=0x70,hlimit=127,frag=no)),2,set(ipv6(src=::1,dst=::2,label=0,proto=10,tclass=0x70,hlimit=126,frag=no)),3,4
 ])
 
 AT_CAPTURE_FILE([ofctl_monitor.log])
 AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl --detach --no-chdir --pidfile 2&amp;gt; ofctl_monitor.log])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=2,frag=no)' -generate], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=2,frag=no)' -generate], [0], [stdout])
 OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
 AT_CHECK([cat ofctl_monitor.log], [0], [dnl
 NXT_PACKET_IN (xid=0x0): table_id=1 total_len=42 in_port=1 (via invalid_ttl) data_len=42 (unbuffered)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -174,7 +174,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([ovs-vsctl -- \
         --id=&amp;lt; at &amp;gt;newqos create QoS type=linux-htb queues=1=&amp;lt; at &amp;gt;q1,2=&amp;lt; at &amp;gt;q2 --\
         --id=&amp;lt; at &amp;gt;q1 create Queue dscp=1 --\
         --id=&amp;lt; at &amp;gt;q2 create Queue dscp=2], [0], [ignore])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(9),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=1.1.1.1,dst=2.2.2.2,proto=1,tos=0xff,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(9),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=1.1.1.1,dst=2.2.2.2,proto=1,tos=0xff,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: dnl
 100,dnl
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -204,7 +204,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 AT_CHECK([ovs-ofctl mod-port br0 5 noforward])
 AT_CHECK([ovs-ofctl mod-port br0 6 noflood])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(100),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(100),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
 AT_CHECK([tail -1 stdout \
 | sed -e 's/Datapath actions: //' | tr ',' '\n' | sort], [0], [dnl
 1
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -214,7 +214,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([tail -1 stdout \
 7
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
 AT_CHECK([tail -1 stdout \
 | sed -e 's/Datapath actions: //' | tr ',' '\n' | sort], [0], [dnl
 100
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -224,7 +224,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([tail -1 stdout \
 7
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(2),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
 AT_CHECK([tail -1 stdout \
 | sed -e 's/Datapath actions: //' | tr ',' '\n' | sort], [0], [dnl
 1
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -235,12 +235,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([tail -1 stdout \
 7
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(3),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(3),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: 100,1,2,4,6,7
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(4),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(4),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(skb_priority(0x1)),100,1,2,set(skb_priority(0x2)),3,set(skb_priority(0x1)),6,7
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -760,7 +760,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; do
   echo "----------------------------------------------------------------------"
   echo "in_port=$in_port vlan=$vlan pcp=$pcp"
 
-  AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+  AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
   actual=`tail -1 stdout | sed 's/Datapath actions: //'`
 
   AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -804,7 +804,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; do
   AT_CHECK([ovs-ofctl set-frags br0 $mode])
   for type in no first later; do
     eval flow=\$${type}_flow exp_output=\$$type
-    AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+    AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
     AT_CHECK_UNQUOTED([tail -1 stdout], [0], [Datapath actions: $exp_output
 ])
   done
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -821,15 +821,15 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=2 actions=output:12,resubmit:1,output:12
 in_port=3 actions=output:13,resubmit:2,output:14
 ])
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: 10
 ])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: 12,10
 ])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(3),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(3),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: 13,12,10
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -852,13 +852,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=2 actions=output:1
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
 flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 2,3
 ])
 
 flow="in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 1,3
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -882,13 +882,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=2 actions=output:1
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
 flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 2,3
 ])
 
 flow="in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 1
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -931,13 +931,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=2 actions=output:1
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
 flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 2,3
 ])
 
 flow="in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 1
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -960,19 +960,19 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=1, actions=output:2
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
 flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 2
 ])
 
 flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=10,pcp=0),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0))"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 2
 ])
 
 flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=11,pcp=0),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0))"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 2,3
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -996,13 +996,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=2 actions=output:1
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
 flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: push_vlan(vid=17,pcp=0),2,pop_vlan,3
 ])
 
 flow="in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 1,3
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1024,7 +1024,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=2 actions=mod_vlan_vid:17,output:1
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
 flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
 
 expected="2,push_vlan(vid=12,pcp=0),1,2,100"
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1033,7 +1033,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; mv stdout expout
 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
 
 flow="in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
 
 expected="push_vlan(vid=17,pcp=0),1,pop_vlan,push_vlan(vid=12,pcp=0),1,2,100"
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1063,7 +1063,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; arp='eth_type(0x0806),arp(sip=192.168.0.1,tip=192.168.0.2,op=1,sha=50:54:00:00:0
 
 # Trace an ARP packet arriving on p3, to create a MAC learning entry.
 OFPROTO_TRACE(
-  [br0],
+  [ovs-dummy],
   [in_port(3),eth(src=50:54:00:00:00:05,dst=ff:ff:ff:ff:ff:ff),$arp],
   [-generate],
   [1,2,100])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1077,7 +1077,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/[[0-9]]\{1,\}$/?/'], [0], [d
 # Trace a packet arrival destined for the learned MAC.
 # (This will also learn a MAC.)
 OFPROTO_TRACE(
-  [br0],
+  [ovs-dummy],
   [in_port(1),eth(src=50:54:00:00:00:06,dst=50:54:00:00:00:05),$arp],
   [-generate],
   [3])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1091,7 +1091,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/[[0-9]]\{1,\}$/?/'], [0], [d
 
 # Trace a packet arrival that updates the first learned MAC entry.
 OFPROTO_TRACE(
-  [br0],
+  [ovs-dummy],
   [in_port(2),eth(src=50:54:00:00:00:05,dst=ff:ff:ff:ff:ff:ff),$arp],
   [-generate],
   [1,3,100])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1113,12 +1113,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK(
 
 # Trace some packet arrivals in br1 to create MAC learning entries there too.
 OFPROTO_TRACE(
-  [br1],
+  [ovs-dummy],
   [in_port(4),eth(src=50:54:00:00:00:06,dst=ff:ff:ff:ff:ff:ff),$arp],
   [-generate],
   [5,101])
 OFPROTO_TRACE(
-  [br1],
+  [ovs-dummy],
   [in_port(5),eth(src=50:54:00:00:00:07,dst=ff:ff:ff:ff:ff:ff),$arp],
   [-generate],
   [4,101])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1159,7 +1159,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([ovs-appctl time/stop])
 # Trace 10 ARP packets arriving on p3, to create MAC learning entries.
 for i in 0 1 2 3 4 5 6 7 8 9; do
     OFPROTO_TRACE(
-      [br0],
+      [ovs-dummy],
       [in_port(3),eth(src=50:54:00:00:00:0$i,dst=ff:ff:ff:ff:ff:ff),$arp],
       [-generate],
       [1,2,100])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1184,7 +1184,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/ *[[0-9]]\{1,\}$//' | sort],
 
 # Trace another ARP packet on another MAC.
 OFPROTO_TRACE(
-  [br0],
+  [ovs-dummy],
   [in_port(3),eth(src=50:54:00:00:00:10,dst=ff:ff:ff:ff:ff:ff),$arp],
   [-generate],
   [1,2,100])
diff --git a/tests/tunnel.at b/tests/tunnel.at
index 2369bd2..c69be44 100644
--- a/tests/tunnel.at
+++ b/tests/tunnel.at
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -26,13 +26,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; br0 (dummy&amp;lt; at &amp;gt;ovs-dummy):
 ])
 
 dnl remote_ip
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=1.2.3.4,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=1.2.3.4,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x0,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df))),1
 ])
 
 dnl local_ip, remote_ip
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x0,src=2.2.2.2,dst=1.1.1.1,tos=0x0,ttl=64,flags(df))),1
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -51,18 +51,18 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; br0 (dummy&amp;lt; at &amp;gt;ovs-dummy):
 p2 2/1: (gre: csum=true, df_default=false, local_ip=2.2.2.3, remote_ip=1.1.1.1, ttl=1)
 p3 3/64: (gre64: remote_ip=2.2.2.2)
 ])
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x0,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df))),1
 ])
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.3,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.3,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x0,src=2.2.2.3,dst=1.1.1.1,tos=0x0,ttl=1,flags(csum))),1
 ])
 
 dnl nonexistent tunnel
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=5.5.5.5,dst=6.6.6.6,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [2], [ignore], [dnl
-Invalid flow
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=5.5.5.5,dst=6.6.6.6,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [2], [ignore], [dnl
+Invalid datapath flow
 ovs-appctl: ovs-vswitchd: server returned an error
 ])
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -91,25 +91,25 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; br0 (dummy&amp;lt; at &amp;gt;ovs-dummy):
 ])
 
 dnl Tunnel CE and encapsulated packet CE
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=3,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=3,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: 2
 ])
 
 dnl Tunnel CE and encapsulated packet ECT(1)
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=1,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=1,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0x3,ttl=64,frag=no)),2
 ])
 
 dnl Tunnel CE and encapsulated packet ECT(2)
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=2,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=2,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0x3,ttl=64,frag=no)),2
 ])
 
 dnl Tunnel CE and encapsulated packet Non-ECT
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: drop
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -139,13 +139,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; br0 (dummy&amp;lt; at &amp;gt;ovs-dummy):
 ])
 
 dnl Basic
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=4,ttl=128,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=4,ttl=128,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x5,src=2.2.2.2,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1
 ])
 
 dnl ECN
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=1,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=1,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x5,src=2.2.2.2,dst=1.1.1.1,tos=0x1,ttl=64,flags(df,key))),1
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -175,19 +175,19 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; br0 (dummy&amp;lt; at &amp;gt;ovs-dummy):
 ])
 
 dnl Basic
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=4,ttl=128,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=4,ttl=128,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x0,src=0.0.0.0,dst=1.1.1.1,tos=0x4,ttl=128,flags(df))),1
 ])
 
 dnl ECN
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=5,ttl=128,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=5,ttl=128,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x0,src=0.0.0.0,dst=1.1.1.1,tos=0x5,ttl=128,flags(df))),1
 ])
 
 dnl non-IP
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0806),arp(sip=1.2.3.4,tip=5.6.7.8,op=1,sha=00:0f:10:11:12:13,tha=00:14:15:16:17:18)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0806),arp(sip=1.2.3.4,tip=5.6.7.8,op=1,sha=00:0f:10:11:12:13,tha=00:14:15:16:17:18)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x0,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df))),1
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -222,7 +222,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; br0 (dummy&amp;lt; at &amp;gt;ovs-dummy):
 p4 4/1: (gre: key=flow, remote_ip=4.4.4.4)
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(100),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(100),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [Datapath actions: dnl
 set(tunnel(tun_id=0x1,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1,dnl
 set(tunnel(tun_id=0x2,src=0.0.0.0,dst=2.2.2.2,tos=0x0,ttl=64,flags(df,key))),1,dnl
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -257,29 +257,29 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; br0 (dummy&amp;lt; at &amp;gt;ovs-dummy):
 p3 3/1: (gre: out_key=5, remote_ip=1.1.1.1)
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x1,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x1,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [Datapath actions: dnl
 set(tunnel(tun_id=0x1,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1,dnl
 set(tunnel(tun_id=0x3,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1,dnl
 set(tunnel(tun_id=0x5,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x2,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x2,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [Datapath actions: dnl
 set(tunnel(tun_id=0x3,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1,dnl
 set(tunnel(tun_id=0x1,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1,dnl
 set(tunnel(tun_id=0x5,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [Datapath actions: dnl
 set(tunnel(tun_id=0x5,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1,dnl
 set(tunnel(tun_id=0x1,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1,dnl
 set(tunnel(tun_id=0x3,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0xf,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [2], [ignore], [dnl
-Invalid flow
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0xf,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [2], [ignore], [dnl
+Invalid datapath flow
 ovs-appctl: ovs-vswitchd: server returned an error
 ])
 OVS_VSWITCHD_STOP(["/receive tunnel port not found/d"])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -315,22 +315,22 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; br0 (dummy&amp;lt; at &amp;gt;ovs-dummy):
 p5 5/5: (dummy)
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x2,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x2,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [dnl
 Datapath actions: 3
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x3,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x3,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [dnl
 Datapath actions: 4,3,set(tunnel(tun_id=0x3,src=0.0.0.0,dst=3.3.3.3,tos=0x0,ttl=64,flags(df,key))),1,5
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x3,src=3.3.3.3,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x3,src=3.3.3.3,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [dnl
 Datapath actions: 4,3,5
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [dnl
 - Sends "packet-in" messages to the OpenFlow controller.
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -433,7 +433,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=4 actions=set_field:2.2.2.2-&amp;gt;tun_dst,output:4
 in_port=5 actions=set_field:5-&amp;gt;tun_id
 ])
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(90),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(90),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x2a,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1,set(tunnel(tun_id=0x2a,src=0.0.0.0,dst=3.3.3.3,tos=0x0,ttl=64,flags(df,key))),1,set(tunnel(tun_id=0x2a,src=1.1.1.1,dst=4.4.4.4,tos=0x0,ttl=64,flags(df,key))),1,set(tunnel(tun_id=0x3,src=0.0.0.0,dst=2.2.2.2,tos=0x0,ttl=64,flags(df,key))),1
 ])
&lt;/pre&gt;</description>
    <dc:creator>Alex Wang</dc:creator>
    <dc:date>2013-05-20T18:36:05</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20724">
    <title>[PATCH 2/2] tests/ofproto-dpif.at: Add tests for theofproto/trace command</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20724</link>
    <description>&lt;pre&gt;Two testcases are added to the testsuite, which test the new
command syntax and the corresponding corner cases.

Signed-off-by: Alex Wang &amp;lt;alexw-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
---
 tests/ofproto-dpif.at |  256 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 256 insertions(+)

diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 6a46ddb..ff007cd 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1044,6 +1044,262 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
+# Two testcases below are for the ofproto/trace command
+# The first one tests all correct syntax:
+# ofproto/trace [dp_name] odp_flow [-generate|packet]
+# ofproto/trace br_name br_flow [-generate|packet]
+AT_SETUP([ofproto-dpif - ofproto/trace command 1])
+OVS_VSWITCHD_START([set bridge br0 fail-mode=standalone])
+ADD_OF_PORTS([br0], 1, 2, 3)
+
+AT_DATA([flows.txt], [dnl
+in_port=1 actions=output:2
+in_port=2 actions=output:1
+])
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+odp_flow="in_port(1)"
+br_flow="in_port=1"
+# Test command: ofproto/trace odp_flow
+AT_CHECK([ovs-appctl ofproto/trace "$odp_flow"], [0], [stdout])
+AT_CHECK([tail -1 stdout], [0], [dnl
+Datapath actions: 2
+])
+
+# Test command: ofproto/trace dp_name odp_flow
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$odp_flow"], [0], [stdout])
+AT_CHECK([tail -1 stdout], [0], [dnl
+Datapath actions: 2
+])
+# Test commmand: ofproto/trace br_name br_flow
+AT_CHECK([ovs-appctl ofproto/trace br0 "$br_flow"], [0], [stdout])
+AT_CHECK([tail -1 stdout], [0], [dnl
+Datapath actions: 2
+])
+
+# Delete the inserted flows
+AT_CHECK([ovs-ofctl del-flows br0 "in_port=1"], [0], [stdout])
+AT_CHECK([ovs-ofctl del-flows br0 "in_port=2"], [0], [stdout])
+
+# This section beflow tests the [-generate] option
+odp_flow="in_port(3),eth(src=50:54:00:00:00:05,dst=ff:ff:ff:ff:ff:ff)"
+br_flow="arp,metadata=0,in_port=3,vlan_tci=0x0000,dl_src=50:54:00:00:00:05,dl_dst=ff:ff:ff:ff:ff:ff"
+
+# Test command: ofproto/trace odp_flow
+AT_CHECK([ovs-appctl ofproto/trace "$odp_flow"], [0], [stdout])
+# Check for no MAC learning entry
+AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/[[0-9]]\{1,\}$/?/'], [0], [dnl
+ port  VLAN  MAC                Age
+])
+
+# Test command: ofproto/trace br_name br_flow
+AT_CHECK([ovs-appctl ofproto/trace br0 "$br_flow"], [0], [stdout])
+# Check for no MAC learning entry
+AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/[[0-9]]\{1,\}$/?/'], [0], [dnl
+ port  VLAN  MAC                Age
+])
+
+# Test command: ofproto/trace odp_flow -generate
+AT_CHECK([ovs-appctl ofproto/trace "$odp_flow" -generate], [0], [stdout])
+# Check for the MAC learning entry
+AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/[[0-9]]\{1,\}$/?/'], [0], [dnl
+ port  VLAN  MAC                Age
+    3     0  50:54:00:00:00:05    ?
+])
+
+# Test command: ofproto/trace dp_name odp_flow -generate
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy \
+  "in_port(1),eth(src=50:54:00:00:00:06,dst=50:54:00:00:00:05)" \
+  -generate], [0], [stdout])
+# Check for both MAC learning entries
+AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/[[0-9]]\{1,\}$/?/'], [0], [dnl
+ port  VLAN  MAC                Age
+    3     0  50:54:00:00:00:05    ?
+    1     0  50:54:00:00:00:06    ?
+])
+
+# Test command: ofproto/trace br_name br_flow -generate
+AT_CHECK([ovs-appctl ofproto/trace br0 \
+  "in_port=2,dl_src=50:54:00:00:00:07,dl_dst=50:54:00:00:00:06" \
+  -generate], [0], [stdout])
+# Check for both MAC learning entries.
+AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/[[0-9]]\{1,\}$/?/'], [0], [dnl
+ port  VLAN  MAC                Age
+    3     0  50:54:00:00:00:05    ?
+    1     0  50:54:00:00:00:06    ?
+    2     0  50:54:00:00:00:07    ?
+])
+
+# This section beflow tests the [packet] option
+# The ovs-tcpundump of packets between port1 and port2
+pkt1to2="50540000000250540000000108064500001C000100004001F98CC0A80001C0A800020800F7FF00000000"
+pkt2to1="50540000000150540000000208064500001C000100004001F98CC0A80002C0A800010800F7FF00000000"
+
+# Construct the MAC learning table
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy \
+  "in_port(1),eth(src=50:54:00:00:00:01,dst=ff:ff:ff:ff:ff:ff)" \
+  -generate], [0], [stdout])
+
+# Construct the MAC learning table
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy \
+  "in_port(2),eth(src=50:54:00:00:00:02,dst=ff:ff:ff:ff:ff:ff)" \
+  -generate], [0], [stdout])
+
+# Test command: ofproto/trace odp_flow packet
+AT_CHECK([ovs-appctl ofproto/trace \
+  "in_port(1),skb_priority(1),skb_mark(2)" "$pkt1to2"], [0], [stdout])
+AT_CHECK([tail -1 stdout], [0], [dnl
+Datapath actions: 2
+])
+AT_CHECK([head -n 3 stdout], [0], [dnl
+Bridge: br0
+Packet: arp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:01,dl_dst=50:54:00:00:00:02,arp_spa=0.0.0.0,arp_tpa=0.0.0.0,arp_sha=00:00:00:00:00:00,arp_tha=00:00:00:00:00:00
+Flow: skb_mark=0x2,skb_priority=0x1,arp,metadata=0,in_port=1,vlan_tci=0x0000,dl_src=50:54:00:00:00:01,dl_dst=50:54:00:00:00:02,arp_spa=0.0.0.0,arp_tpa=0.0.0.0,arp_sha=00:00:00:00:00:00,arp_tha=00:00:00:00:00:00
+])
+
+# Test command: ofproto/trace dp_name odp_flow packet
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy \
+  "in_port(1),skb_priority(1),skb_mark(2)" "$pkt1to2"], [0], [stdout])
+AT_CHECK([tail -1 stdout], [0], [dnl
+Datapath actions: 2
+])
+AT_CHECK([head -n 3 stdout], [0], [dnl
+Bridge: br0
+Packet: arp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:01,dl_dst=50:54:00:00:00:02,arp_spa=0.0.0.0,arp_tpa=0.0.0.0,arp_sha=00:00:00:00:00:00,arp_tha=00:00:00:00:00:00
+Flow: skb_mark=0x2,skb_priority=0x1,arp,metadata=0,in_port=1,vlan_tci=0x0000,dl_src=50:54:00:00:00:01,dl_dst=50:54:00:00:00:02,arp_spa=0.0.0.0,arp_tpa=0.0.0.0,arp_sha=00:00:00:00:00:00,arp_tha=00:00:00:00:00:00
+])
+
+# Test command: ofproto/trace br_name br_flow packet
+AT_CHECK([ovs-appctl ofproto/trace br0 \
+  "in_port=2,skb_priority=2,skb_mark=1" "$pkt2to1"], [0], [stdout],[stderr])
+AT_CHECK([tail -1 stdout], [0], [dnl
+Datapath actions: set(skb_mark(0)),1
+])
+AT_CHECK([head -n 2 stdout], [0], [dnl
+Packet: arp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:02,dl_dst=50:54:00:00:00:01,arp_spa=0.0.0.0,arp_tpa=0.0.0.0,arp_sha=00:00:00:00:00:00,arp_tha=00:00:00:00:00:00
+Flow: skb_mark=0x1,skb_priority=0x2,arp,metadata=0,in_port=2,vlan_tci=0x0000,dl_src=50:54:00:00:00:02,dl_dst=50:54:00:00:00:01,arp_spa=0.0.0.0,arp_tpa=0.0.0.0,arp_sha=00:00:00:00:00:00,arp_tha=00:00:00:00:00:00
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+# The second test tests the corner cases
+AT_SETUP([ofproto-dpif - ofproto/trace command 2])
+OVS_VSWITCHD_START
+ADD_OF_PORTS([br0], 1, 2)
+
+# Define flows
+odp_flow="in_port(1),eth(src=50:54:00:00:00:01,dst=50:54:00:00:00:02)"
+br_flow="in_port=1,dl_src=50:54:00:00:00:01,dl_dst=50:54:00:00:00:02"
+# Define options
+generate="-generate"
+pkt="50540000000250540000000108064500001C000100004001F98CC0A80001C0A800020800F7FF00000000"
+
+# Test incorrect command: ofproto/trace wrong_name odp_flow [-generate|packet]
+m4_foreach(
+[option],
+[[],
+["$generate"],
+["$pkt"]],
+[AT_CHECK([ovs-appctl ofproto/trace wrong_name "$odp_flow" option],
+  [2], [], [stderr])
+AT_CHECK([tail -2 stderr], [0], [dnl
+Cannot find datapath of this name
+ovs-appctl: ovs-vswitchd: server returned an error
+])])
+
+# Test incorrect command: ofproto/trace empty_string odp_flow [-generate|packet]
+m4_foreach(
+[option],
+[[],
+["$generate"],
+["$pkt"]],
+[AT_CHECK([ovs-appctl ofproto/trace "" "$odp_flow" option],
+  [2], [], [stderr])
+AT_CHECK([tail -2 stderr], [0], [dnl
+Cannot find datapath of this name
+ovs-appctl: ovs-vswitchd: server returned an error
+])])
+
+# Test incorrect command: ofproto/trace nonexist_dp_name odp_flow [-generate|packet]
+m4_foreach(
+[option],
+[[],
+["$generate"],
+["$pkt"]],
+[AT_CHECK([ovs-appctl ofproto/trace ovs-system "$odp_flow" option],
+  [2], [], [stderr])
+AT_CHECK([tail -2 stderr], [0], [dnl
+Cannot find datapath of this name
+ovs-appctl: ovs-vswitchd: server returned an error
+])])
+
+# Test incorrect command: ofproto/trace br_name odp_flow [-generate|packet]
+m4_foreach(
+[option],
+[[],
+["$generate"],
+["$pkt"]],
+[AT_CHECK([ovs-appctl ofproto/trace br0 "$odp_flow" option],
+  [2], [], [stderr])
+AT_CHECK([tail -2 stderr], [0], [dnl
+Cannot find datapath of this name
+ovs-appctl: ovs-vswitchd: server returned an error
+])])
+
+# Test incorrect command: ofproto/trace dp_name br_flow [-generate|packet]
+m4_foreach(
+[option],
+[[],
+["$generate"],
+["$pkt"]],
+[AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$br_flow" option],
+  [2], [], [stderr])
+AT_CHECK([tail -2 stderr], [0], [dnl
+Unknown bridge name
+ovs-appctl: ovs-vswitchd: server returned an error
+])])
+
+# Test incorrect command: ofproto/trace br_flow [-generate|packet]
+m4_foreach(
+[option],
+[[],
+["$generate"],
+["$pkt"]],
+[AT_CHECK([ovs-appctl ofproto/trace "$br_flow" option],
+  [2], [], [stderr])
+AT_CHECK([tail -2 stderr], [0], [dnl
+Must specify bridge name
+ovs-appctl: ovs-vswitchd: server returned an error
+])])
+
+# Test incorrect command: ofproto/trace dp_name odp_flow garbage_option
+AT_CHECK([ovs-appctl ofproto/trace \
+  ovs-dummy "$odp_flow" garbage_option],
+  [2], [stdout],[stderr])
+AT_CHECK([tail -2 stderr], [0], [dnl
+Trailing garbage in packet data
+ovs-appctl: ovs-vswitchd: server returned an error
+])
+
+# Test incorrect command: ofproto/trace with 4 arguments
+AT_CHECK([ovs-appctl ofproto/trace \
+  arg1, arg2, arg3, arg4], [2], [stdout],[stderr])
+AT_CHECK([tail -2 stderr], [0], [dnl
+"ofproto/trace" command takes at most 3 arguments
+ovs-appctl: ovs-vswitchd: server returned an error
+])
+
+# Test incorrect command: ofproto/trace with 0 argument
+AT_CHECK([ovs-appctl ofproto/trace ], [2], [stdout],[stderr])
+AT_CHECK([tail -2 stderr], [0], [dnl
+"ofproto/trace" command requires at least 1 arguments
+ovs-appctl: ovs-vswitchd: server returned an error
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 m4_define([OFPROTO_TRACE],
   [flow="$2"
    AT_CHECK([ovs-appctl ofproto/trace $1 "$flow" $3], [0], [stdout])
&lt;/pre&gt;</description>
    <dc:creator>Alex Wang</dc:creator>
    <dc:date>2013-05-20T18:17:51</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20723">
    <title>[PATCH 1/2] ofproto/ofproto-dpif.c: Re-implement theofproto/trace command</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20723</link>
    <description>&lt;pre&gt;Since the use of single datapath, all bridges belonging to the same type of
datapath will use the same (single) datapath. This causes confusion in the
current 'ofproto/trace' command. Especially, when given the unrelated
'bridge' and 'in_port' combination, the current implementation will still
be able to process and give misleading output. Thusly, this patch changes
the 'ofproto/trace' command syntax to formats shown as follow.

ofproto/trace [datapath] odp_flow [-generate|packet]
ofproto/trace bridge br_flow [-generate|packet]

Also, this patch updates the tests and the manpages accordingly.

Co-authored-by: Ben Pfaff &amp;lt;blp-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
Signed-off-by: Alex Wang &amp;lt;alexw-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
---
 ofproto/ofproto-dpif.c      |  159 ++++++++++++++++++++++---------------------
 ofproto/ofproto-unixctl.man |  138 ++++++++++++++++++++++---------------
 tests/learn.at              |   16 ++---
 tests/ofproto-dpif.at       |   76 ++++++++++-----------
 tests/tunnel.at             |   52 +++++++-------
 5 files changed, 235 insertions(+), 206 deletions(-)

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index c4f7d25..abac2d7 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -3686,8 +3686,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; handle_flow_miss_without_facet(struct flow_miss *miss,
         dpif_flow_stats_extract(&amp;amp;miss-&amp;gt;flow, packet, now, &amp;amp;stats);
         rule_credit_stats(rule, &amp;amp;stats);
 
-        action_xlate_ctx_init(&amp;amp;ctx, ofproto, &amp;amp;miss-&amp;gt;flow, &amp;amp;miss-&amp;gt;initial_vals,
-                              rule, stats.tcp_flags, packet);
+        action_xlate_ctx_init(&amp;amp;ctx, ofproto, &amp;amp;miss-&amp;gt;flow,
+                              &amp;amp;miss-&amp;gt;initial_vals, rule, 0, packet);
         ctx.resubmit_stats = &amp;amp;stats;
         xlate_actions(&amp;amp;ctx, rule-&amp;gt;up.ofpacts, rule-&amp;gt;up.ofpacts_len,
                       &amp;amp;odp_actions);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -8128,7 +8128,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void
 ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
                       void *aux OVS_UNUSED)
 {
-    const char *dpname = argv[1];
+    const struct dpif_backer *backer;
     struct ofproto_dpif *ofproto;
     struct ofpbuf odp_key;
     struct ofpbuf *packet;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -8138,101 +8138,102 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
     char *s;
 
     packet = NULL;
-    ofpbuf_init(&amp;amp;odp_key, 0);
+    backer = NULL;
     ds_init(&amp;amp;result);
+    ofpbuf_init(&amp;amp;odp_key, 0);
 
-    ofproto = ofproto_dpif_lookup(dpname);
-    if (!ofproto) {
-        unixctl_command_reply_error(conn, "Unknown ofproto (use ofproto/list "
-                                    "for help)");
-        goto exit;
+    /* Handle "-generate" or a hex string as the last argument. */
+    if (!strcmp(argv[argc - 1], "-generate")) {
+        packet = ofpbuf_new(0);
+        argc--;
+    } else {
+        const char *error = eth_from_hex(argv[argc - 1], &amp;amp;packet);
+        if (!error) {
+            argc--;
+        } else if (argc == 4) {
+            /* The 3-argument form must end in "-generate' or a hex string. */
+            unixctl_command_reply_error(conn, error);
+            goto exit;
+        }
     }
-    if (argc == 3 || (argc == 4 &amp;amp;&amp;amp; !strcmp(argv[3], "-generate"))) {
-        /* ofproto/trace dpname flow [-generate] */
-        const char *flow_s = argv[2];
-        const char *generate_s = argv[3];
 
-        /* Allow 'flow_s' to be either a datapath flow or an OpenFlow-like
-         * flow.  We guess which type it is based on whether 'flow_s' contains
-         * an '(', since a datapath flow always contains '(') but an
-         * OpenFlow-like flow should not (in fact it's allowed but I believe
-         * that's not documented anywhere).
-         *
-         * An alternative would be to try to parse 'flow_s' both ways, but then
-         * it would be tricky giving a sensible error message.  After all, do
-         * you just say "syntax error" or do you present both error messages?
-         * Both choices seem lousy. */
-        if (strchr(flow_s, '(')) {
-            int error;
-
-            /* Convert string to datapath key. */
-            ofpbuf_init(&amp;amp;odp_key, 0);
-            error = odp_flow_key_from_string(flow_s, NULL, &amp;amp;odp_key);
-            if (error) {
-                unixctl_command_reply_error(conn, "Bad flow syntax");
-                goto exit;
+    /* Parse the flow and determine whether a datapath or
+     * bridge is specified. If function odp_flow_key_from_string()
+     * returns 0, the flow is a odp_flow. If function
+     * parse_ofp_exact_flow() returns 0, the flow is a br_flow. */
+    if (!odp_flow_key_from_string(argv[argc - 1], NULL, &amp;amp;odp_key)) {
+        /* If the odp_flow is the second argument,
+         * the datapath name is the first argument. */
+        if (argc == 3) {
+            const char *dp_type;
+            if (!strncmp(argv[1], "ovs-", 4)) {
+                dp_type = argv[1] + 4;
+            } else {
+                dp_type = argv[1];
             }
-
-            /* The user might have specified the wrong ofproto but within the
-             * same backer.  That's OK, ofproto_receive() can find the right
-             * one for us. */
-            if (ofproto_receive(ofproto-&amp;gt;backer, NULL, odp_key.data,
-                                odp_key.size, &amp;amp;flow, NULL, &amp;amp;ofproto, NULL,
-                                &amp;amp;initial_vals)) {
-                unixctl_command_reply_error(conn, "Invalid flow");
+            backer = shash_find_data(&amp;amp;all_dpif_backers, dp_type);
+            if (!backer) {
+                unixctl_command_reply_error(conn, "Cannot find datapath "
+                               "of this name");
                 goto exit;
             }
-            ds_put_format(&amp;amp;result, "Bridge: %s\n", ofproto-&amp;gt;up.name);
         } else {
-            char *error_s;
-
-            error_s = parse_ofp_exact_flow(&amp;amp;flow, argv[2]);
-            if (error_s) {
-                unixctl_command_reply_error(conn, error_s);
-                free(error_s);
+            /* No datapath name specified, so there should be only one
+             * datapath. */
+            struct shash_node *node;
+            if (shash_count(&amp;amp;all_dpif_backers) != 1) {
+                unixctl_command_reply_error(conn, "Must specify datapath "
+                         "name, there is more than one type of datapath");
                 goto exit;
             }
-
-            initial_vals.vlan_tci = flow.vlan_tci;
+            node = shash_first(&amp;amp;all_dpif_backers);
+            backer = node-&amp;gt;data;
         }
 
-        /* Generate a packet, if requested. */
-        if (generate_s) {
-            packet = ofpbuf_new(0);
-            flow_compose(packet, &amp;amp;flow);
+        /* Extract the ofproto_dpif object from the ofproto_receive()
+         * function. */
+        if (ofproto_receive(backer, NULL, odp_key.data,
+                            odp_key.size, &amp;amp;flow, NULL, &amp;amp;ofproto, NULL,
+                            &amp;amp;initial_vals)) {
+            unixctl_command_reply_error(conn, "Invalid datapath flow");
+            goto exit;
         }
-    } else if (argc == 7) {
-        /* ofproto/trace dpname priority tun_id in_port mark packet */
-        const char *priority_s = argv[2];
-        const char *tun_id_s = argv[3];
-        const char *in_port_s = argv[4];
-        const char *mark_s = argv[5];
-        const char *packet_s = argv[6];
-        uint32_t in_port = atoi(in_port_s);
-        ovs_be64 tun_id = htonll(strtoull(tun_id_s, NULL, 0));
-        uint32_t priority = atoi(priority_s);
-        uint32_t mark = atoi(mark_s);
-        const char *msg;
-
-        msg = eth_from_hex(packet_s, &amp;amp;packet);
-        if (msg) {
-            unixctl_command_reply_error(conn, msg);
+        ds_put_format(&amp;amp;result, "Bridge: %s\n", ofproto-&amp;gt;up.name);
+    } else if (!parse_ofp_exact_flow(&amp;amp;flow, argv[argc - 1])) {
+        if (argc != 3) {
+            unixctl_command_reply_error(conn, "Must specify bridge name");
             goto exit;
         }
 
-        ds_put_cstr(&amp;amp;result, "Packet: ");
-        s = ofp_packet_to_string(packet-&amp;gt;data, packet-&amp;gt;size);
-        ds_put_cstr(&amp;amp;result, s);
-        free(s);
-
-        flow_extract(packet, priority, mark, NULL, in_port, &amp;amp;flow);
-        flow.tunnel.tun_id = tun_id;
+        ofproto = ofproto_dpif_lookup(argv[1]);
+        if (!ofproto) {
+            unixctl_command_reply_error(conn, "Unknown bridge name");
+            goto exit;
+        }
         initial_vals.vlan_tci = flow.vlan_tci;
     } else {
-        unixctl_command_reply_error(conn, "Bad command syntax");
+        unixctl_command_reply_error(conn, "Bad flow syntax");
         goto exit;
     }
 
+    /* Generate a packet, if requested. */
+    if (packet) {
+        if (!packet-&amp;gt;size) {
+            flow_compose(packet, &amp;amp;flow);
+        } else {
+            ds_put_cstr(&amp;amp;result, "Packet: ");
+            s = ofp_packet_to_string(packet-&amp;gt;data, packet-&amp;gt;size);
+            ds_put_cstr(&amp;amp;result, s);
+            free(s);
+
+            /* Use the metadata from the flow and the packet argument
+             * to reconstruct the flow. */
+            flow_extract(packet, flow.skb_priority, flow.skb_mark, NULL,
+                         flow.in_port, &amp;amp;flow);
+            initial_vals.vlan_tci = flow.vlan_tci;
+        }
+    }
+
     ofproto_trace(ofproto, &amp;amp;flow, packet, &amp;amp;initial_vals, &amp;amp;result);
     unixctl_command_reply(conn, ds_cstr(&amp;amp;result));
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -8661,8 +8662,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; ofproto_dpif_unixctl_init(void)
 
     unixctl_command_register(
         "ofproto/trace",
-        "bridge {priority tun_id in_port mark packet | odp_flow [-generate]}",
-        2, 6, ofproto_unixctl_trace, NULL);
+        "[dp_name]|bridge odp_flow|br_flow [-generate|packet]",
+        1, 3, ofproto_unixctl_trace, NULL);
     unixctl_command_register("fdb/flush", "[bridge]", 0, 1,
                              ofproto_unixctl_fdb_flush, NULL);
     unixctl_command_register("fdb/show", "bridge", 1, 1,
diff --git a/ofproto/ofproto-unixctl.man b/ofproto/ofproto-unixctl.man
index 8890343..8141de9 100644
--- a/ofproto/ofproto-unixctl.man
+++ b/ofproto/ofproto-unixctl.man
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -6,70 +6,98 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; These commands manage the core OpenFlow switch implementation (called
 Lists the names of the running ofproto instances.  These are the names
 that may be used on \fBofproto/trace\fR.
 .
-.IP "\fBofproto/trace \fIswitch priority tun_id in_port mark packet\fR"
-.IQ "\fBofproto/trace \fIswitch flow \fB\-generate\fR"
-Traces the path of an imaginary packet through \fIswitch\fR.  Both
-forms require \fIswitch\fR, the switch on which the packet arrived
-(one of those listed by \fBofproto/list\fR).  The first form specifies
-a packet's contents explicitly:
+.IP "\fBofproto/trace\fR [\fIdpname\fR] \fIodp_flow\fR [\fB\-generate \fR| \
+\fIpacket\fR]"
+.IQ "\fBofproto/trace\fR \fIbridge\fR \fIbr_flow\fR \
+[\fB\-generate \fR| \fIpacket\fR]"
+Traces the path of an imaginary packet through \fIswitch\fR and
+reports the path that it took.  The packet's headers (e.g. source and
+destination) and metadata (e.g. input port), together called its
+``flow,'' are usually all that matter for this purpose.  You can
+specify the flow in the following ways:
+.
 .RS
-.IP "\fIpriority\fR"
-Packet QoS priority. Use \fB0\fR if QoS is not setup.
-.IP "\fItun_id\fR"
-The tunnel ID on which the packet arrived.  Use
-\fB0\fR if the packet did not arrive through a tunnel.
-.IP "\fIin_port\fR"
-The OpenFlow port on which the packet arrived.  Use \fB65534\fR if the
-packet arrived on \fBOFPP_LOCAL\fR, the local port.
-.IP "\fImark\fR"
-SKB mark of the packet. Use \fB0\fR if Netfilter marks are not used.
-.IP "\fIpacket\fR"
-A sequence of hex digits specifying the packet's contents.  An
-Ethernet frame is at least 14 bytes long, so there must be at least 28
-hex digits.  Obviously, it is inconvenient to type in the hex digits
-by hand, so the \fBovs\-pcap\fR(1) and \fBovs\-tcpundump\fR(1)
-utilities provide easier ways.
+.IP "\fIdpname\fR \fIodp_flow\fR"
+\fIodp_flow\fR is a flow in the form printed by \fBovs\-dpctl\fR(8)'s
+\fBdump\-flows\fR command.  If all of your bridges have the same type,
+which is the common case, then you can omit \fIdpname\fR, but if you
+have bridges of different types (say, both \fBovs-netdev\fR and
+\fBovs-system\fR), then you need to specify a \fIdpname\fR to disambiguate.
+.
+.IP "\fIbridge\fR \fIbr_flow\fR"
+\fIbr_flow\fR is a flow in the form similar to that accepted by
+\fBovs\-ofctl\fR(8)'s \fBadd\-flow\fR command.  (This is not an
+OpenFlow flow: besides other differences, it never contains
+wildcards.)  \fIbridge\fR names of the bridge through which
+\fIbr_flow\fR should be traced.
 .RE
+.
 .IP
-The second form specifies the packet's contents implicitly:
+Most commonly, one specifies only a flow, using one of the forms
+above, but sometimes one might need to specify an actual packet
+instead of just a flow:
+.
 .RS
-.IP "\fIflow\fR"
-A flow in one of two forms: either the form printed by
-\fBovs\-dpctl\fR(8)'s \fBdump\-flows\fR command, or in a format
-similar to that accepted by \fBovs\-ofctl\fR(8)'s \fBadd\-flow\fR
-command.  This is not an OpenFlow flow: besides other differences, it
-never contains wildcards.  \fB\*(PN\fR generates an arbitrary packet
-that has the specified \fIflow\fR.
-.RE
+.IP "Side effects."
+Some actions have side effects.  For example, the \fBnormal\fR action
+can update the MAC learning table, and the \fBlearn\fR action can
+change OpenFlow tables.  \fBofproto/trace\fR only performs side
+effects when a packet is specified.  If you want side effects to take
+place, then you must supply a packet.
+.
 .IP
-\fB\*(PN\fR will respond with extensive information on how the packet
-would be handled if it were to be received.  The packet will not
-actually be sent, but side effects such as MAC learning will occur.
+(Output actions are obviously side effects too, but
+\fBofproto/trace\fR never executes them, even when one specifies a
+packet.)
 .
-.IP "\fBofproto/trace \fIswitch flow\fR"
-Traces the path of a packet in an imaginary flow through
-\fIswitch\fR.  The arguments are:
-.RS
-.IP "\fIswitch\fR"
-The switch on which the packet arrived (one of those listed by
-\fBofproto/list\fR).
-.IP "\fIflow\fR"
-A flow in one of two forms: either the form printed by
-\fBovs\-dpctl\fR(8)'s \fBdump\-flows\fR command, or in a format
-similar to that accepted by \fBovs\-ofctl\fR(8)'s \fBadd\-flow\fR
-command.  This is not an OpenFlow flow: besides other differences, it
-never contains wildcards.
+.IP "Incomplete information."
+Most of the time, Open vSwitch can figure out everything about the
+path of a packet using just the flow, but in some special
+circumstances it needs to look at parts of the packet that are not
+included in the flow.  When this is the case, and you do not supply a
+packet, then \fBofproto/trace\fR will tell you it needs a packet.
 .RE
+.
 .IP
-\fB\*(PN\fR will respond with extensive information on how a packet
-in \fIflow\fR would be handled if it were received by
-\fIswitch\fR.  No packet will actually be sent.  Some side effects may
-occur, but MAC learning in particular will not.
+If you wish to include a packet as part of the \fBofproto/trace\fR
+operation, there are two ways to do it:
+.
+.RS
+.IP \fB\-generate\fR
+This option, added to one of the ways to specify a flow already
+described, causes Open vSwitch to internally generate a packet with
+the flow described and then to use that packet.  If your goal is to
+execute side effects, then \fB\-generate\fR is the easiest way to do
+it, but \fB\-generate\fR is not a good way to fill in incomplete
+information, because it generates packets based on only the flow
+information, which means that the packets really do not have any more
+information than the flow.
+.
+.IP \fIpacket\fR
+This form supplies an explicit \fIpacket\fR as a sequence of hex
+digits.  An Ethernet frame is at least 14 bytes long, so there must be
+at least 28 hex digits.  Obviously, it is inconvenient to type in the
+hex digits by hand, so the \fBovs\-pcap\fR(1) and
+\fBovs\-tcpundump\fR(1) utilities provide easier ways.
 .IP
-This form of \fBofproto/trace\fR cannot determine the complete set of
-datapath actions in some corner cases.  If the results say that this
-is the case, rerun \fBofproto/trace\fR supplying a packet in the flow
-to get complete results.
+With this form, packet headers are extracted directly from
+\fIpacket\fR, so the \fIodp_flow\fR or \fIbr_flow\fR should specify
+only metadata. The metadata can be:
+.RS
+.IP \fIskb_priority\fR
+Packet QoS priority.
+.IP \fIskb_mark\fR
+SKB mark of the packet.
+.IP \fItun_id\fR
+The tunnel ID on which the packet arrived.
+.IP \fIin_port\fR
+The port on which the packet arrived.
+.RE
+.
+The in_port value is kernel datapath port number for the first format
+and OpenFlow port number for the second format. The numbering of these
+two types of port usually differs and there is no relationship.
+.RE
 .IP "\fBofproto/self\-check\fR [\fIswitch\fR]"
 Runs an internal consistency check on \fIswitch\fR, if specified,
 otherwise on all ofproto instances, and responds with a brief summary
diff --git a/tests/learn.at b/tests/learn.at
index 5eb3e5d..cd9983e 100644
--- a/tests/learn.at
+++ b/tests/learn.at
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -75,7 +75,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
 # Trace an ARP packet arriving on port 3, to create a MAC learning entry.
 flow="in_port(3),eth(src=50:54:00:00:00:05,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=192.168.0.1,tip=192.168.0.2,op=1,sha=50:54:00:00:00:05,tha=00:00:00:00:00:00)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
 
 expected="1,2,100"
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -92,7 +92,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; NXST_FLOW reply:
 
 # Trace a packet arrival destined for the learned MAC.
 # (This will also learn a MAC.)
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:06,dst=50:54:00:00:00:05),eth_type(0x0806),arp(sip=192.168.0.2,tip=192.168.0.1,op=2,sha=50:54:00:00:00:06,tha=50:54:00:00:00:05)' -generate], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:06,dst=50:54:00:00:00:05),eth_type(0x0806),arp(sip=192.168.0.2,tip=192.168.0.1,op=2,sha=50:54:00:00:00:06,tha=50:54:00:00:00:05)' -generate], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [Datapath actions: 3
 ])
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -106,7 +106,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; NXST_FLOW reply:
 
 # Trace a packet arrival that updates the first learned MAC entry.
 flow="in_port(2),eth(src=50:54:00:00:00:05,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=192.168.0.1,tip=192.168.0.2,op=1,sha=50:54:00:00:00:05,tha=00:00:00:00:00:00)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
 
 expected="1,3,100"
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -147,7 +147,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
 # Trace an ICMP packet arriving on port 3, to create a MAC learning entry.
 flow="in_port(3),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
 
 expected="1,2,100"
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -166,7 +166,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; NXST_FLOW reply:
 # disappear as long as we refresh it every second.
 for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25; do
     ovs-appctl time/warp 1000
-    AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
+    AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
 
     # Check that the entry is there.
     AT_CHECK([ovs-ofctl dump-flows br0 table=1], [0], [stdout])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -209,7 +209,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([[ovs-ofctl add-flow br0 'table=0 tcp actions=learn(table=1, hard_timeo
 
 # Trace a TCPv4 packet arriving on port 3.
 flow="in_port(3),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:06),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=6,tos=0,ttl=64,frag=no),tcp(src=40000,dst=80)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
 
 expected="1,2,100"
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -237,7 +237,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([[ovs-ofctl add-flow br0 'table=0 tcp6 actions=learn(table=1, hard_time
 
 # Trace a TCPv6 packet arriving on port 3.
 flow="in_port(3),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:06),eth_type(0x86dd),ipv6(src=fec0::2,dst=fec0::1,label=0,proto=6,tclass=0,hlimit=255,frag=no),tcp(src=40000,dst=80)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow" -generate], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow" -generate], [0], [stdout])
 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
 
 expected="1,2,100"
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -296,7 +296,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_SETUP([learning action - fin_timeout feature])
 OVS_VSWITCHD_START(
     [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1])
 AT_CHECK([[ovs-ofctl add-flow br0 'actions=learn(fin_hard_timeout=10, fin_idle_timeout=5, NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], output:NXM_OF_IN_PORT[])']])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=192.168.0.1,tip=192.168.0.2,op=1,sha=50:54:00:00:00:05,tha=00:00:00:00:00:00)' -generate], [0], [ignore])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=192.168.0.1,tip=192.168.0.2,op=1,sha=50:54:00:00:00:05,tha=00:00:00:00:00:00)' -generate], [0], [ignore])
 AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip], [0],
 [NXST_FLOW reply:
  table=1, dl_dst=50:54:00:00:00:05 actions=fin_timeout(idle_timeout=5,hard_timeout=10),output:1
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 1fdbac3..6a46ddb 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -62,7 +62,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=15,reg0=0x10,reg1=0x11,reg2=0x12,reg3=0x13,reg4=0x14,reg5=0x15,reg6=0x16
 
 ])
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(90),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(90),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: 20,21,22,33
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -81,7 +81,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=5            actions=pop:NXM_NX_REG3[[]],output:NXM_NX_REG3[[]]
 
 ])
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(90),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(90),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: 33,22,21,20
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -102,7 +102,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=7 actions=load:0x110000ff-&amp;gt;NXM_NX_REG0[[]],output:NXM_NX_REG0[[]]
 in_port=8 actions=1,9,load:9-&amp;gt;NXM_OF_IN_PORT[[]],1,9
 ])
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: 9,55,10,55,66,11,77,88,9,1
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -117,24 +117,24 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; table=0 in_port=1 action=dec_ttl,output:2,resubmit(1,1),output:4
 table=1 in_port=1 action=dec_ttl,output:3
 ])
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=2,frag=no)' -generate], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=2,frag=no)' -generate], [0], [stdout])
 AT_CHECK([tail -3 stdout], [0],
   [Datapath actions: set(ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=1,frag=no)),2,4
 This flow is handled by the userspace slow path because it:
 - Sends "packet-in" messages to the OpenFlow controller.
 ])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=3,frag=no)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=3,frag=no)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=2,frag=no)),2,set(ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=1,frag=no)),3,4
 ])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=10,tclass=0x70,hlimit=128,frag=no)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=10,tclass=0x70,hlimit=128,frag=no)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(ipv6(src=::1,dst=::2,label=0,proto=10,tclass=0x70,hlimit=127,frag=no)),2,set(ipv6(src=::1,dst=::2,label=0,proto=10,tclass=0x70,hlimit=126,frag=no)),3,4
 ])
 
 AT_CAPTURE_FILE([ofctl_monitor.log])
 AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl --detach --no-chdir --pidfile 2&amp;gt; ofctl_monitor.log])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=2,frag=no)' -generate], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=2,frag=no)' -generate], [0], [stdout])
 OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
 AT_CHECK([cat ofctl_monitor.log], [0], [dnl
 NXT_PACKET_IN (xid=0x0): table_id=1 total_len=42 in_port=1 (via invalid_ttl) data_len=42 (unbuffered)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -174,7 +174,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([ovs-vsctl -- \
         --id=&amp;lt; at &amp;gt;newqos create QoS type=linux-htb queues=1=&amp;lt; at &amp;gt;q1,2=&amp;lt; at &amp;gt;q2 --\
         --id=&amp;lt; at &amp;gt;q1 create Queue dscp=1 --\
         --id=&amp;lt; at &amp;gt;q2 create Queue dscp=2], [0], [ignore])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(9),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=1.1.1.1,dst=2.2.2.2,proto=1,tos=0xff,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(9),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=1.1.1.1,dst=2.2.2.2,proto=1,tos=0xff,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: dnl
 100,dnl
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -204,7 +204,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 AT_CHECK([ovs-ofctl mod-port br0 5 noforward])
 AT_CHECK([ovs-ofctl mod-port br0 6 noflood])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(100),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(100),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
 AT_CHECK([tail -1 stdout \
 | sed -e 's/Datapath actions: //' | tr ',' '\n' | sort], [0], [dnl
 1
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -214,7 +214,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([tail -1 stdout \
 7
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
 AT_CHECK([tail -1 stdout \
 | sed -e 's/Datapath actions: //' | tr ',' '\n' | sort], [0], [dnl
 100
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -224,7 +224,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([tail -1 stdout \
 7
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(2),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
 AT_CHECK([tail -1 stdout \
 | sed -e 's/Datapath actions: //' | tr ',' '\n' | sort], [0], [dnl
 1
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -235,12 +235,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([tail -1 stdout \
 7
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(3),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(3),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: 100,1,2,4,6,7
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(4),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(4),eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:02),eth_type(0x0900)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(skb_priority(0x1)),100,1,2,set(skb_priority(0x2)),3,set(skb_priority(0x1)),6,7
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -760,7 +760,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; do
   echo "----------------------------------------------------------------------"
   echo "in_port=$in_port vlan=$vlan pcp=$pcp"
 
-  AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+  AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
   actual=`tail -1 stdout | sed 's/Datapath actions: //'`
 
   AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -804,7 +804,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; do
   AT_CHECK([ovs-ofctl set-frags br0 $mode])
   for type in no first later; do
     eval flow=\$${type}_flow exp_output=\$$type
-    AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+    AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
     AT_CHECK_UNQUOTED([tail -1 stdout], [0], [Datapath actions: $exp_output
 ])
   done
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -821,15 +821,15 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=2 actions=output:12,resubmit:1,output:12
 in_port=3 actions=output:13,resubmit:2,output:14
 ])
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: 10
 ])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: 12,10
 ])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(3),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(3),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: 13,12,10
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -852,13 +852,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=2 actions=output:1
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
 flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 2,3
 ])
 
 flow="in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 1,3
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -882,13 +882,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=2 actions=output:1
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
 flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 2,3
 ])
 
 flow="in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 1
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -931,13 +931,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=2 actions=output:1
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
 flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 2,3
 ])
 
 flow="in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 1
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -960,19 +960,19 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=1, actions=output:2
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
 flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 2
 ])
 
 flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=10,pcp=0),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0))"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 2
 ])
 
 flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=11,pcp=0),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0))"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 2,3
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -996,13 +996,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=2 actions=output:1
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
 flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: push_vlan(vid=17,pcp=0),2,pop_vlan,3
 ])
 
 flow="in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 AT_CHECK_UNQUOTED([tail -1 stdout], [0],
   [Datapath actions: 1,3
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1024,7 +1024,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=2 actions=mod_vlan_vid:17,output:1
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
 flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
 
 expected="2,push_vlan(vid=12,pcp=0),1,2,100"
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1033,7 +1033,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; mv stdout expout
 AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
 
 flow="in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
-AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
 actual=`tail -1 stdout | sed 's/Datapath actions: //'`
 
 expected="push_vlan(vid=17,pcp=0),1,pop_vlan,push_vlan(vid=12,pcp=0),1,2,100"
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1063,7 +1063,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; arp='eth_type(0x0806),arp(sip=192.168.0.1,tip=192.168.0.2,op=1,sha=50:54:00:00:0
 
 # Trace an ARP packet arriving on p3, to create a MAC learning entry.
 OFPROTO_TRACE(
-  [br0],
+  [ovs-dummy],
   [in_port(3),eth(src=50:54:00:00:00:05,dst=ff:ff:ff:ff:ff:ff),$arp],
   [-generate],
   [1,2,100])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1077,7 +1077,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/[[0-9]]\{1,\}$/?/'], [0], [d
 # Trace a packet arrival destined for the learned MAC.
 # (This will also learn a MAC.)
 OFPROTO_TRACE(
-  [br0],
+  [ovs-dummy],
   [in_port(1),eth(src=50:54:00:00:00:06,dst=50:54:00:00:00:05),$arp],
   [-generate],
   [3])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1091,7 +1091,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/[[0-9]]\{1,\}$/?/'], [0], [d
 
 # Trace a packet arrival that updates the first learned MAC entry.
 OFPROTO_TRACE(
-  [br0],
+  [ovs-dummy],
   [in_port(2),eth(src=50:54:00:00:00:05,dst=ff:ff:ff:ff:ff:ff),$arp],
   [-generate],
   [1,3,100])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1113,12 +1113,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK(
 
 # Trace some packet arrivals in br1 to create MAC learning entries there too.
 OFPROTO_TRACE(
-  [br1],
+  [ovs-dummy],
   [in_port(4),eth(src=50:54:00:00:00:06,dst=ff:ff:ff:ff:ff:ff),$arp],
   [-generate],
   [5,101])
 OFPROTO_TRACE(
-  [br1],
+  [ovs-dummy],
   [in_port(5),eth(src=50:54:00:00:00:07,dst=ff:ff:ff:ff:ff:ff),$arp],
   [-generate],
   [4,101])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1159,7 +1159,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK([ovs-appctl time/stop])
 # Trace 10 ARP packets arriving on p3, to create MAC learning entries.
 for i in 0 1 2 3 4 5 6 7 8 9; do
     OFPROTO_TRACE(
-      [br0],
+      [ovs-dummy],
       [in_port(3),eth(src=50:54:00:00:00:0$i,dst=ff:ff:ff:ff:ff:ff),$arp],
       [-generate],
       [1,2,100])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1184,7 +1184,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/ *[[0-9]]\{1,\}$//' | sort],
 
 # Trace another ARP packet on another MAC.
 OFPROTO_TRACE(
-  [br0],
+  [ovs-dummy],
   [in_port(3),eth(src=50:54:00:00:00:10,dst=ff:ff:ff:ff:ff:ff),$arp],
   [-generate],
   [1,2,100])
diff --git a/tests/tunnel.at b/tests/tunnel.at
index 2369bd2..c69be44 100644
--- a/tests/tunnel.at
+++ b/tests/tunnel.at
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -26,13 +26,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; br0 (dummy&amp;lt; at &amp;gt;ovs-dummy):
 ])
 
 dnl remote_ip
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=1.2.3.4,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=1.2.3.4,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x0,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df))),1
 ])
 
 dnl local_ip, remote_ip
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x0,src=2.2.2.2,dst=1.1.1.1,tos=0x0,ttl=64,flags(df))),1
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -51,18 +51,18 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; br0 (dummy&amp;lt; at &amp;gt;ovs-dummy):
 p2 2/1: (gre: csum=true, df_default=false, local_ip=2.2.2.3, remote_ip=1.1.1.1, ttl=1)
 p3 3/64: (gre64: remote_ip=2.2.2.2)
 ])
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x0,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df))),1
 ])
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.3,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.3,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x0,src=2.2.2.3,dst=1.1.1.1,tos=0x0,ttl=1,flags(csum))),1
 ])
 
 dnl nonexistent tunnel
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=5.5.5.5,dst=6.6.6.6,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [2], [ignore], [dnl
-Invalid flow
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=5.5.5.5,dst=6.6.6.6,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [2], [ignore], [dnl
+Invalid datapath flow
 ovs-appctl: ovs-vswitchd: server returned an error
 ])
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -91,25 +91,25 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; br0 (dummy&amp;lt; at &amp;gt;ovs-dummy):
 ])
 
 dnl Tunnel CE and encapsulated packet CE
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=3,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=3,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: 2
 ])
 
 dnl Tunnel CE and encapsulated packet ECT(1)
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=1,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=1,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0x3,ttl=64,frag=no)),2
 ])
 
 dnl Tunnel CE and encapsulated packet ECT(2)
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=2,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=2,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0x3,ttl=64,frag=no)),2
 ])
 
 dnl Tunnel CE and encapsulated packet Non-ECT
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: drop
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -139,13 +139,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; br0 (dummy&amp;lt; at &amp;gt;ovs-dummy):
 ])
 
 dnl Basic
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=4,ttl=128,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=4,ttl=128,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x5,src=2.2.2.2,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1
 ])
 
 dnl ECN
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=1,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=1,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x5,src=2.2.2.2,dst=1.1.1.1,tos=0x1,ttl=64,flags(df,key))),1
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -175,19 +175,19 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; br0 (dummy&amp;lt; at &amp;gt;ovs-dummy):
 ])
 
 dnl Basic
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=4,ttl=128,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=4,ttl=128,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x0,src=0.0.0.0,dst=1.1.1.1,tos=0x4,ttl=128,flags(df))),1
 ])
 
 dnl ECN
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=5,ttl=128,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=5,ttl=128,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x0,src=0.0.0.0,dst=1.1.1.1,tos=0x5,ttl=128,flags(df))),1
 ])
 
 dnl non-IP
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0806),arp(sip=1.2.3.4,tip=5.6.7.8,op=1,sha=00:0f:10:11:12:13,tha=00:14:15:16:17:18)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0806),arp(sip=1.2.3.4,tip=5.6.7.8,op=1,sha=00:0f:10:11:12:13,tha=00:14:15:16:17:18)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x0,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df))),1
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -222,7 +222,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; br0 (dummy&amp;lt; at &amp;gt;ovs-dummy):
 p4 4/1: (gre: key=flow, remote_ip=4.4.4.4)
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(100),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(100),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [Datapath actions: dnl
 set(tunnel(tun_id=0x1,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1,dnl
 set(tunnel(tun_id=0x2,src=0.0.0.0,dst=2.2.2.2,tos=0x0,ttl=64,flags(df,key))),1,dnl
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -257,29 +257,29 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; br0 (dummy&amp;lt; at &amp;gt;ovs-dummy):
 p3 3/1: (gre: out_key=5, remote_ip=1.1.1.1)
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x1,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x1,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [Datapath actions: dnl
 set(tunnel(tun_id=0x1,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1,dnl
 set(tunnel(tun_id=0x3,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1,dnl
 set(tunnel(tun_id=0x5,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x2,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x2,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [Datapath actions: dnl
 set(tunnel(tun_id=0x3,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1,dnl
 set(tunnel(tun_id=0x1,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1,dnl
 set(tunnel(tun_id=0x5,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [Datapath actions: dnl
 set(tunnel(tun_id=0x5,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1,dnl
 set(tunnel(tun_id=0x1,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1,dnl
 set(tunnel(tun_id=0x3,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0xf,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [2], [ignore], [dnl
-Invalid flow
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0xf,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [2], [ignore], [dnl
+Invalid datapath flow
 ovs-appctl: ovs-vswitchd: server returned an error
 ])
 OVS_VSWITCHD_STOP(["/receive tunnel port not found/d"])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -315,22 +315,22 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; br0 (dummy&amp;lt; at &amp;gt;ovs-dummy):
 p5 5/5: (dummy)
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x2,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x2,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [dnl
 Datapath actions: 3
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x3,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x3,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [dnl
 Datapath actions: 4,3,set(tunnel(tun_id=0x3,src=0.0.0.0,dst=3.3.3.3,tos=0x0,ttl=64,flags(df,key))),1,5
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x3,src=3.3.3.3,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x3,src=3.3.3.3,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [dnl
 Datapath actions: 4,3,5
 ])
 
-AT_CHECK([ovs-appctl ofproto/trace br0 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0], [dnl
 - Sends "packet-in" messages to the OpenFlow controller.
 ])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -433,7 +433,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; in_port=4 actions=set_field:2.2.2.2-&amp;gt;tun_dst,output:4
 in_port=5 actions=set_field:5-&amp;gt;tun_id
 ])
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(90),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(90),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: set(tunnel(tun_id=0x2a,src=0.0.0.0,dst=1.1.1.1,tos=0x0,ttl=64,flags(df,key))),1,set(tunnel(tun_id=0x2a,src=0.0.0.0,dst=3.3.3.3,tos=0x0,ttl=64,flags(df,key))),1,set(tunnel(tun_id=0x2a,src=1.1.1.1,dst=4.4.4.4,tos=0x0,ttl=64,flags(df,key))),1,set(tunnel(tun_id=0x3,src=0.0.0.0,dst=2.2.2.2,tos=0x0,ttl=64,flags(df,key))),1
 ])
&lt;/pre&gt;</description>
    <dc:creator>Alex Wang</dc:creator>
    <dc:date>2013-05-20T18:17:28</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20722">
    <title>[PATCH] gre: Restructure tunneling.</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20722</link>
    <description>&lt;pre&gt;Following patch restructure ovs tunneling and gre vport
implementation to make ovs tunneling more in sync with
upstream kernel tunneling.  Doing this tunneling code is
simplified as most of protocol processing on send and
recv is pushed to kernel tunneling.  For external ovs
module the code is moved to kernel compatibility code.

Signed-off-by: Pravin B Shelar &amp;lt;pshelar-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
---
 datapath/compat.h                              |    6 +
 datapath/linux/Modules.mk                      |    6 +
 datapath/linux/compat/gre.c                    |  360 ++++++++++++++++++++++++
 datapath/linux/compat/gso.c                    |  166 +++++++++++
 datapath/linux/compat/gso.h                    |   46 +++
 datapath/linux/compat/include/linux/err.h      |    9 +
 datapath/linux/compat/include/linux/if_ether.h |    4 +
 datapath/linux/compat/include/net/gre.h        |  109 +++++++
 datapath/linux/compat/include/net/ip_tunnels.h |   52 ++++
 datapath/linux/compat/ip_tunnels_core.c        |   78 +++++
 datapath/tunnel.c                              |   12 +-
 datapath/tunnel.h                              |    8 +-
 datapath/vport-gre.c                           |  331 ++++++++++------------
 13 files changed, 998 insertions(+), 189 deletions(-)
 create mode 100644 datapath/linux/compat/gre.c
 create mode 100644 datapath/linux/compat/gso.c
 create mode 100644 datapath/linux/compat/gso.h
 create mode 100644 datapath/linux/compat/include/net/gre.h
 create mode 100644 datapath/linux/compat/include/net/ip_tunnels.h
 create mode 100644 datapath/linux/compat/ip_tunnels_core.c

diff --git a/datapath/compat.h b/datapath/compat.h
index c7fd225..6095323 100644
--- a/datapath/compat.h
+++ b/datapath/compat.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -93,5 +93,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static inline void skb_set_mark(struct sk_buff *skb, u32 mark)
 skb-&amp;gt;mark = mark;
 }
 #endif /* after 2.6.20 */
+#if LINUX_VERSION_CODE &amp;gt;= KERNEL_VERSION(2,6,36)
+#define rt_dst(rt) (rt-&amp;gt;dst)
+#else
+#define rt_dst(rt) (rt-&amp;gt;u.dst)
+#endif
+
 
 #endif /* compat.h */
diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk
index 1434a2d..bbda6c0 100644
--- a/datapath/linux/Modules.mk
+++ b/datapath/linux/Modules.mk
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -3,8 +3,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; openvswitch_sources += \
 linux/compat/dev-openvswitch.c \
 linux/compat/exthdrs_core.c \
 linux/compat/flex_array.c \
+linux/compat/gre.c \
+linux/compat/gso.c \
 linux/compat/genetlink-openvswitch.c \
 linux/compat/ip_output-openvswitch.c \
+datapath/linux/compat/ip_tunnels_core.c \
 linux/compat/kmemdup.c \
 linux/compat/netdevice.c \
 linux/compat/net_namespace.c \
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -13,6 +16,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; openvswitch_sources += \
 linux/compat/time.c\
 linux/compat/workqueue.c
 openvswitch_headers += \
+linux/compat/gso.h \
 linux/compat/include/asm/percpu.h \
 linux/compat/include/linux/compiler.h \
 linux/compat/include/linux/compiler-gcc.h \
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -61,8 +65,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; openvswitch_headers += \
 linux/compat/include/net/checksum.h \
 linux/compat/include/net/dst.h \
 linux/compat/include/net/genetlink.h \
+linux/compat/include/net/gre.h \
 linux/compat/include/net/inet_frag.h \
 linux/compat/include/net/ip.h \
+linux/compat/include/net/ip_tunnels.h \
 linux/compat/include/net/ipv6.h \
 linux/compat/include/net/net_namespace.h \
 linux/compat/include/net/netlink.h \
diff --git a/datapath/linux/compat/gre.c b/datapath/linux/compat/gre.c
new file mode 100644
index 0000000..2c091c8
--- /dev/null
+++ b/datapath/linux/compat/gre.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,360 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/*
+ * Copyright (c) 2007-2013 Nicira, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#include &amp;lt;linux/module.h&amp;gt;
+#include &amp;lt;linux/if.h&amp;gt;
+#include &amp;lt;linux/if_tunnel.h&amp;gt;
+#include &amp;lt;linux/icmp.h&amp;gt;
+#include &amp;lt;linux/in.h&amp;gt;
+#include &amp;lt;linux/ip.h&amp;gt;
+#include &amp;lt;linux/kernel.h&amp;gt;
+#include &amp;lt;linux/kmod.h&amp;gt;
+#include &amp;lt;linux/netdevice.h&amp;gt;
+#include &amp;lt;linux/skbuff.h&amp;gt;
+#include &amp;lt;linux/spinlock.h&amp;gt;
+
+#include &amp;lt;net/gre.h&amp;gt;
+#include &amp;lt;net/icmp.h&amp;gt;
+#include &amp;lt;net/protocol.h&amp;gt;
+#include &amp;lt;net/route.h&amp;gt;
+#include &amp;lt;net/xfrm.h&amp;gt;
+
+#include "gso.h"
+
+static struct gre_cisco_protocol __rcu *gre_cisco_proto;
+
+static int gre_handle_csum_offloads(struct sk_buff *skb, bool gre_csum)
+{
+if (skb-&amp;gt;ip_summed == CHECKSUM_PARTIAL &amp;amp;&amp;amp; gre_csum) {
+int err;
+
+err = skb_checksum_help(skb);
+return err;
+} else if (skb-&amp;gt;ip_summed != CHECKSUM_PARTIAL)
+skb-&amp;gt;ip_summed = CHECKSUM_NONE;
+return 0;
+}
+
+static void gre_csum_fix(struct sk_buff *skb)
+{
+struct gre_base_hdr *greh;
+__be32 *options;
+int gre_offset = skb_transport_offset(skb);
+
+greh = (struct gre_base_hdr *)skb_transport_header(skb);
+options = ((__be32 *)greh + 1);
+
+*options = 0;
+*(__sum16 *)options = csum_fold(skb_checksum(skb, gre_offset,
+     skb-&amp;gt;len - gre_offset, 0));
+}
+
+struct sk_buff *gre_handle_offloads(struct sk_buff *skb, bool gre_csum)
+{
+int err;
+
+skb_reset_inner_headers(skb);
+
+if (skb_is_gso(skb)) {
+if (gre_csum)
+OVS_GSO_CB(skb)-&amp;gt;fix_segment = gre_csum_fix;
+} else {
+err = gre_handle_csum_offloads(skb, gre_csum);
+if (err)
+goto error;
+
+}
+return skb;
+error:
+kfree_skb(skb);
+return ERR_PTR(err);
+}
+
+static bool is_gre_gso(struct sk_buff *skb)
+{
+return skb_is_gso(skb);
+}
+
+void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
+      int hdr_len)
+{
+struct gre_base_hdr *greh;
+
+__skb_push(skb, hdr_len);
+
+greh = (struct gre_base_hdr *)skb-&amp;gt;data;
+greh-&amp;gt;flags = tnl_flags_to_gre_flags(tpi-&amp;gt;flags);
+greh-&amp;gt;protocol = tpi-&amp;gt;proto;
+
+if (tpi-&amp;gt;flags&amp;amp;(TUNNEL_KEY|TUNNEL_CSUM|TUNNEL_SEQ)) {
+__be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4);
+
+if (tpi-&amp;gt;flags&amp;amp;TUNNEL_SEQ) {
+*ptr = tpi-&amp;gt;seq;
+ptr--;
+}
+if (tpi-&amp;gt;flags&amp;amp;TUNNEL_KEY) {
+*ptr = tpi-&amp;gt;key;
+ptr--;
+}
+if (tpi-&amp;gt;flags&amp;amp;TUNNEL_CSUM &amp;amp;&amp;amp; !is_gre_gso(skb)) {
+*(__sum16 *)ptr = 0;
+*(__sum16 *)ptr = csum_fold(skb_checksum(skb, 0,
+skb-&amp;gt;len, 0));
+}
+}
+}
+
+static __sum16 check_checksum(struct sk_buff *skb)
+{
+__sum16 csum = 0;
+
+switch (skb-&amp;gt;ip_summed) {
+case CHECKSUM_COMPLETE:
+csum = csum_fold(skb-&amp;gt;csum);
+
+if (!csum)
+break;
+/* Fall through. */
+
+case CHECKSUM_NONE:
+skb-&amp;gt;csum = 0;
+csum = __skb_checksum_complete(skb);
+skb-&amp;gt;ip_summed = CHECKSUM_COMPLETE;
+break;
+}
+
+return csum;
+}
+
+static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
+    bool *csum_err)
+{
+unsigned int ip_hlen = ip_hdrlen(skb);
+struct gre_base_hdr *greh;
+__be32 *options;
+int hdr_len;
+
+if (unlikely(!pskb_may_pull(skb, sizeof(struct gre_base_hdr))))
+return -EINVAL;
+
+greh = (struct gre_base_hdr *)(skb_network_header(skb) + ip_hlen);
+if (unlikely(greh-&amp;gt;flags &amp;amp; (GRE_VERSION | GRE_ROUTING)))
+return -EINVAL;
+
+tpi-&amp;gt;flags = gre_flags_to_tnl_flags(greh-&amp;gt;flags);
+hdr_len = ip_gre_calc_hlen(tpi-&amp;gt;flags);
+
+if (!pskb_may_pull(skb, hdr_len))
+return -EINVAL;
+
+greh = (struct gre_base_hdr *)(skb_network_header(skb) + ip_hlen);
+tpi-&amp;gt;proto = greh-&amp;gt;protocol;
+
+options = (__be32 *)(greh + 1);
+if (greh-&amp;gt;flags &amp;amp; GRE_CSUM) {
+if (check_checksum(skb)) {
+*csum_err = true;
+return -EINVAL;
+}
+options++;
+}
+
+if (greh-&amp;gt;flags &amp;amp; GRE_KEY) {
+tpi-&amp;gt;key = *options;
+options++;
+} else
+tpi-&amp;gt;key = 0;
+
+if (unlikely(greh-&amp;gt;flags &amp;amp; GRE_SEQ)) {
+tpi-&amp;gt;seq = *options;
+options++;
+} else
+tpi-&amp;gt;seq = 0;
+
+/* WCCP version 1 and 2 protocol decoding.
+ * - Change protocol to IP
+ * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
+ */
+if (greh-&amp;gt;flags == 0 &amp;amp;&amp;amp; tpi-&amp;gt;proto == htons(ETH_P_WCCP)) {
+tpi-&amp;gt;proto = htons(ETH_P_IP);
+if ((*(u8 *)options &amp;amp; 0xF0) != 0x40) {
+hdr_len += 4;
+if (!pskb_may_pull(skb, hdr_len))
+return -EINVAL;
+}
+}
+return 0;
+}
+
+static int gre_cisco_rcv(struct sk_buff *skb)
+{
+struct tnl_ptk_info tpi;
+bool csum_err = false;
+struct gre_cisco_protocol *proto;
+
+rcu_read_lock();
+proto = rcu_dereference(gre_cisco_proto);
+if (!proto)
+goto drop;
+
+if (parse_gre_header(skb, &amp;amp;tpi, &amp;amp;csum_err) &amp;lt; 0)
+goto drop;
+proto-&amp;gt;handler(skb, &amp;amp;tpi);
+rcu_read_unlock();
+return 0;
+
+drop:
+rcu_read_unlock();
+kfree_skb(skb);
+return 0;
+}
+
+static const struct gre_protocol ipgre_protocol = {
+.handler=gre_cisco_rcv,
+};
+
+#if LINUX_VERSION_CODE &amp;lt; KERNEL_VERSION(2,6,37)
+static const struct gre_protocol __rcu *gre_proto[GREPROTO_MAX] __read_mostly;
+
+int gre_add_protocol(const struct gre_protocol *proto, u8 version)
+{
+if (version &amp;gt;= GREPROTO_MAX)
+return -EINVAL;
+
+return (cmpxchg((const struct gre_protocol **)&amp;amp;gre_proto[version], NULL, proto) == NULL) ?
+0 : -EBUSY;
+}
+
+int gre_del_protocol(const struct gre_protocol *proto, u8 version)
+{
+int ret;
+
+if (version &amp;gt;= GREPROTO_MAX)
+return -EINVAL;
+
+ret = (cmpxchg((const struct gre_protocol **)&amp;amp;gre_proto[version], proto, NULL) == proto) ?
+0 : -EBUSY;
+
+if (ret)
+return ret;
+
+synchronize_net();
+return 0;
+}
+
+static int gre_rcv(struct sk_buff *skb)
+{
+const struct gre_protocol *proto;
+u8 ver;
+int ret;
+
+if (!pskb_may_pull(skb, 12))
+goto drop;
+
+ver = skb-&amp;gt;data[1]&amp;amp;0x7f;
+if (ver &amp;gt;= GREPROTO_MAX)
+goto drop;
+
+rcu_read_lock();
+proto = rcu_dereference(gre_proto[ver]);
+if (!proto || !proto-&amp;gt;handler)
+goto drop_unlock;
+ret = proto-&amp;gt;handler(skb);
+rcu_read_unlock();
+return ret;
+
+drop_unlock:
+rcu_read_unlock();
+drop:
+kfree_skb(skb);
+return NET_RX_DROP;
+}
+
+static const struct net_protocol net_gre_protocol = {
+.handler     = gre_rcv,
+#if LINUX_VERSION_CODE &amp;gt;= KERNEL_VERSION(2,6,32)
+.netns_ok    = 1,
+#endif
+};
+#endif
+
+static int gre_compat_init(void)
+{
+int err;
+
+#if LINUX_VERSION_CODE &amp;lt; KERNEL_VERSION(2,6,37)
+if (inet_add_protocol(&amp;amp;net_gre_protocol, IPPROTO_GRE) &amp;lt; 0) {
+pr_err("can't add protocol\n");
+return -EAGAIN;
+}
+#endif
+err = gre_add_protocol(&amp;amp;ipgre_protocol, GREPROTO_CISCO);
+if (err) {
+pr_warn("cannot register gre protocol handler\n");
+
+#if LINUX_VERSION_CODE &amp;lt; KERNEL_VERSION(2,6,37)
+inet_del_protocol(&amp;amp;net_gre_protocol, IPPROTO_GRE);
+#endif
+}
+
+return err;
+}
+
+static int gre_compat_exit(void)
+{
+int ret;
+
+ret = gre_del_protocol(&amp;amp;ipgre_protocol, GREPROTO_CISCO);
+if (ret)
+return ret;
+
+#if LINUX_VERSION_CODE &amp;lt; KERNEL_VERSION(2,6,37)
+ret = inet_del_protocol(&amp;amp;net_gre_protocol, IPPROTO_GRE);
+if (ret)
+return ret;
+#endif
+return 0;
+}
+
+int gre_cisco_register(struct gre_cisco_protocol *newp)
+{
+int err;
+
+err = gre_compat_init();
+if (err)
+return err;
+
+return (cmpxchg((struct gre_cisco_protocol **)&amp;amp;gre_cisco_proto, NULL, newp) == NULL) ?
+0 : -EBUSY;
+}
+
+int gre_cisco_unregister(struct gre_cisco_protocol *proto)
+{
+int ret;
+
+ret = (cmpxchg((struct gre_cisco_protocol **)&amp;amp;gre_cisco_proto, proto, NULL) == proto) ?
+0 : -EINVAL;
+
+if (ret)
+return ret;
+
+synchronize_net();
+ret = gre_compat_exit();
+return ret;
+}
diff --git a/datapath/linux/compat/gso.c b/datapath/linux/compat/gso.c
new file mode 100644
index 0000000..f6a4ad3
--- /dev/null
+++ b/datapath/linux/compat/gso.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,166 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/*
+ * Copyright (c) 2007-2013 Nicira, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#include &amp;lt;linux/module.h&amp;gt;
+#include &amp;lt;linux/if.h&amp;gt;
+#include &amp;lt;linux/if_tunnel.h&amp;gt;
+#include &amp;lt;linux/icmp.h&amp;gt;
+#include &amp;lt;linux/in.h&amp;gt;
+#include &amp;lt;linux/ip.h&amp;gt;
+#include &amp;lt;linux/kernel.h&amp;gt;
+#include &amp;lt;linux/kmod.h&amp;gt;
+#include &amp;lt;linux/netdevice.h&amp;gt;
+#include &amp;lt;linux/skbuff.h&amp;gt;
+#include &amp;lt;linux/spinlock.h&amp;gt;
+
+#include &amp;lt;net/gre.h&amp;gt;
+#include &amp;lt;net/icmp.h&amp;gt;
+#include &amp;lt;net/protocol.h&amp;gt;
+#include &amp;lt;net/route.h&amp;gt;
+#include &amp;lt;net/xfrm.h&amp;gt;
+
+#include "gso.h"
+
+static __be16 skb_network_protocol(struct sk_buff *skb)
+{
+__be16 type = skb-&amp;gt;protocol;
+int vlan_depth = ETH_HLEN;
+
+while (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) {
+struct vlan_hdr *vh;
+
+if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN)))
+return 0;
+
+vh = (struct vlan_hdr *)(skb-&amp;gt;data + vlan_depth);
+type = vh-&amp;gt;h_vlan_encapsulated_proto;
+vlan_depth += VLAN_HLEN;
+}
+
+return type;
+}
+
+static struct sk_buff *tnl_skb_gso_segment(struct sk_buff *skb,
+   netdev_features_t features,
+   bool tx_path)
+{
+struct iphdr *iph= ip_hdr(skb);
+int tnl_hlen= skb_inner_network_offset(skb);
+struct sk_buff *skb1= skb;
+struct sk_buff *segs;
+
+__skb_pull(skb, tnl_hlen);
+skb_reset_mac_header(skb);
+skb_reset_network_header(skb);
+skb_reset_transport_header(skb);
+skb-&amp;gt;protocol = skb_network_protocol(skb);
+
+segs = __skb_gso_segment(skb, 0, true);
+if (!segs || IS_ERR(segs))
+goto free;
+
+skb = segs;
+while (skb) {
+__skb_push(skb, tnl_hlen);
+skb_reset_mac_header(skb);
+skb_reset_network_header(skb);
+skb_set_transport_header(skb, sizeof(struct iphdr));
+skb-&amp;gt;mac_len = 0;
+
+memcpy(ip_hdr(skb), iph, tnl_hlen);
+if (OVS_GSO_CB(skb)-&amp;gt;fix_segment)
+OVS_GSO_CB(skb)-&amp;gt;fix_segment(skb);
+skb = skb-&amp;gt;next;
+}
+free:
+consume_skb(skb1);
+return segs;
+}
+
+static bool need_linearize(const struct sk_buff *skb)
+{
+int i;
+
+if (unlikely(skb_shinfo(skb)-&amp;gt;frag_list))
+return true;
+
+/*
+ * Generally speaking we should linearize if there are paged frags.
+ * However, if all of the refcounts are 1 we know nobody else can
+ * change them from underneath us and we can skip the linearization.
+ */
+for (i = 0; i &amp;lt; skb_shinfo(skb)-&amp;gt;nr_frags; i++)
+if (unlikely(page_count(skb_frag_page(&amp;amp;skb_shinfo(skb)-&amp;gt;frags[i])) &amp;gt; 1))
+return true;
+
+return false;
+}
+
+int ip_local_out(struct sk_buff *skb)
+{
+struct dst_entry *dst = skb_dst(skb);
+int ret = NETDEV_TX_OK;
+
+if (skb_is_gso(skb)) {
+skb = tnl_skb_gso_segment(skb, 0, true);
+if (!skb || IS_ERR(skb))
+return 0;
+}  else if (skb-&amp;gt;ip_summed == CHECKSUM_PARTIAL) {
+int err;
+
+if (unlikely(need_linearize(skb))) {
+err = __skb_linearize(skb);
+if (unlikely(err))
+return 0;
+}
+
+err = skb_checksum_help(skb);
+if (unlikely(err))
+return 0;
+}
+
+while (skb) {
+struct sk_buff *next_skb = skb-&amp;gt;next;
+int err;
+
+if (next_skb)
+skb_dst_set(skb, dst_clone(dst));
+else
+skb_dst_set(skb, dst);
+
+skb-&amp;gt;next = NULL;
+
+/*
+ * Allow our local IP stack to fragment the outer packet even
+ * if the DF bit is set as a last resort.  We also need to
+ * force selection of an IP ID here because Linux will
+ * otherwise leave it at 0 if the packet originally had DF set.
+ */
+
+skb-&amp;gt;local_df = 1;
+memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+
+#undef ip_local_out
+err = ip_local_out(skb);
+if (unlikely(net_xmit_eval(err)))
+ret = err;
+
+skb = next_skb;
+}
+return ret;
+}
diff --git a/datapath/linux/compat/gso.h b/datapath/linux/compat/gso.h
new file mode 100644
index 0000000..3157041
--- /dev/null
+++ b/datapath/linux/compat/gso.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,46 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+#ifndef __LINUX_GSO_WRAPPER_H
+#define __LINUX_GSO_WRAPPER_H
+
+#include &amp;lt;linux/skbuff.h&amp;gt;
+#include &amp;lt;net/protocol.h&amp;gt;
+
+#include "datapath.h"
+
+struct ovs_gso_cb {
+struct ovs_skb_cb dp_cb;
+sk_buff_data_tinner_network_header;
+void (*fix_segment)(struct sk_buff *);
+};
+#define OVS_GSO_CB(skb) ((struct ovs_gso_cb *)(skb)-&amp;gt;cb)
+
+#define skb_inner_network_header rpl_skb_inner_network_header
+
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
+static inline unsigned char *skb_inner_network_header(const struct sk_buff *skb)
+{
+return skb-&amp;gt;head + OVS_GSO_CB(skb)-&amp;gt;inner_network_header;
+}
+#else
+static inline unsigned char *skb_inner_network_header(const struct sk_buff *skb)
+{
+return OVS_GSO_CB(skb)-&amp;gt;inner_network_header;
+}
+#endif
+
+#define skb_inner_network_offset rpl_skb_inner_network_offset
+static inline int skb_inner_network_offset(const struct sk_buff *skb)
+{
+return skb_inner_network_header(skb) - skb-&amp;gt;data;
+}
+
+#define skb_reset_inner_headers rpl_skb_reset_inner_headers
+static inline void skb_reset_inner_headers(struct sk_buff *skb)
+{
+BUILD_BUG_ON(sizeof(struct ovs_gso_cb) &amp;gt; 48);
+OVS_GSO_CB(skb)-&amp;gt;inner_network_header = skb-&amp;gt;network_header;
+OVS_GSO_CB(skb)-&amp;gt;fix_segment = NULL;
+}
+
+#define ip_local_out rpl_ip_local_out
+int ip_local_out(struct sk_buff *skb);
+#endif
diff --git a/datapath/linux/compat/include/linux/err.h b/datapath/linux/compat/include/linux/err.h
index 50faf2a..d640298 100644
--- a/datapath/linux/compat/include/linux/err.h
+++ b/datapath/linux/compat/include/linux/err.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -18,4 +18,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static inline void *ERR_CAST(const void *ptr)
 }
 #endif /* HAVE_ERR_CAST */
 
+#ifndef IS_ERR_VALUE
+#define IS_ERR_VALUE(x) unlikely((x) &amp;gt;= (unsigned long)-MAX_ERRNO)
+static inline long __must_check IS_ERR_OR_NULL(const void *ptr)
+{
+return !ptr || IS_ERR_VALUE((unsigned long)ptr);
+}
+#endif
+
+
 #endif
diff --git a/datapath/linux/compat/include/linux/if_ether.h b/datapath/linux/compat/include/linux/if_ether.h
index 85b0d22..e22ea96 100644
--- a/datapath/linux/compat/include/linux/if_ether.h
+++ b/datapath/linux/compat/include/linux/if_ether.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -20,4 +20,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 #define ETH_P_802_3_MIN        0x0600
 #endif
 
+#ifndef ETH_P_8021AD
+#define ETH_P_8021AD    0x88A8          /* 802.1ad Service VLAN         */
+#endif
+
 #endif
diff --git a/datapath/linux/compat/include/net/gre.h b/datapath/linux/compat/include/net/gre.h
new file mode 100644
index 0000000..16dc54e
--- /dev/null
+++ b/datapath/linux/compat/include/net/gre.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,109 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+#ifndef __LINUX_GRE_WRAPPER_H
+#define __LINUX_GRE_WRAPPER_H
+
+#include &amp;lt;linux/skbuff.h&amp;gt;
+#include &amp;lt;net/ip_tunnels.h&amp;gt;
+
+#if LINUX_VERSION_CODE &amp;gt; KERNEL_VERSION(2,6,37)
+#include_next &amp;lt;net/gre.h&amp;gt;
+
+#else /* LINUX_VERSION_CODE &amp;lt;= KERNEL_VERSION(2,6,37) */
+
+#define GREPROTO_CISCO0
+#define GREPROTO_PPTP1
+#define GREPROTO_MAX2
+#define GRE_IP_PROTO_MAX2
+
+struct gre_protocol {
+int  (*handler)(struct sk_buff *skb);
+void (*err_handler)(struct sk_buff *skb, u32 info);
+};
+
+int gre_add_protocol(const struct gre_protocol *proto, u8 version);
+int gre_del_protocol(const struct gre_protocol *proto, u8 version);
+
+#endif
+
+#define GRE_IP_PROTO_MAX2
+
+struct gre_base_hdr {
+__be16 flags;
+__be16 protocol;
+};
+#define GRE_HEADER_SECTION 4
+
+#define MAX_GRE_PROTO_PRIORITY 255
+struct gre_cisco_protocol {
+int (*handler)(struct sk_buff *skb, const struct tnl_ptk_info *tpi);
+int (*err_handler)(struct sk_buff *skb, u32 info,
+   const struct tnl_ptk_info *tpi);
+u8 priority;
+};
+
+#define gre_build_header rpl_gre_build_header
+void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
+      int hdr_len);
+
+#define gre_handle_offloads rpl_gre_handle_offloads
+struct sk_buff *gre_handle_offloads(struct sk_buff *skb, bool gre_csum);
+
+int gre_cisco_register(struct gre_cisco_protocol *proto);
+int gre_cisco_unregister(struct gre_cisco_protocol *proto);
+
+static inline int ip_gre_calc_hlen(__be16 o_flags)
+{
+int addend = 4;
+
+if (o_flags&amp;amp;TUNNEL_CSUM)
+addend += 4;
+if (o_flags&amp;amp;TUNNEL_KEY)
+addend += 4;
+if (o_flags&amp;amp;TUNNEL_SEQ)
+addend += 4;
+return addend;
+}
+
+static inline __be16 gre_flags_to_tnl_flags(__be16 flags)
+{
+__be16 tflags = 0;
+
+if (flags &amp;amp; GRE_CSUM)
+tflags |= TUNNEL_CSUM;
+if (flags &amp;amp; GRE_ROUTING)
+tflags |= TUNNEL_ROUTING;
+if (flags &amp;amp; GRE_KEY)
+tflags |= TUNNEL_KEY;
+if (flags &amp;amp; GRE_SEQ)
+tflags |= TUNNEL_SEQ;
+if (flags &amp;amp; GRE_STRICT)
+tflags |= TUNNEL_STRICT;
+if (flags &amp;amp; GRE_REC)
+tflags |= TUNNEL_REC;
+if (flags &amp;amp; GRE_VERSION)
+tflags |= TUNNEL_VERSION;
+
+return tflags;
+}
+
+static inline __be16 tnl_flags_to_gre_flags(__be16 tflags)
+{
+__be16 flags = 0;
+
+if (tflags &amp;amp; TUNNEL_CSUM)
+flags |= GRE_CSUM;
+if (tflags &amp;amp; TUNNEL_ROUTING)
+flags |= GRE_ROUTING;
+if (tflags &amp;amp; TUNNEL_KEY)
+flags |= GRE_KEY;
+if (tflags &amp;amp; TUNNEL_SEQ)
+flags |= GRE_SEQ;
+if (tflags &amp;amp; TUNNEL_STRICT)
+flags |= GRE_STRICT;
+if (tflags &amp;amp; TUNNEL_REC)
+flags |= GRE_REC;
+if (tflags &amp;amp; TUNNEL_VERSION)
+flags |= GRE_VERSION;
+
+return flags;
+}
+#endif
diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h
new file mode 100644
index 0000000..cb53d21
--- /dev/null
+++ b/datapath/linux/compat/include/net/ip_tunnels.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,52 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+#ifndef __NET_IP_TUNNELS_WRAPPER_H
+#define __NET_IP_TUNNELS_WRAPPER_H 1
+
+#include &amp;lt;linux/if_tunnel.h&amp;gt;
+#include &amp;lt;linux/netdevice.h&amp;gt;
+#include &amp;lt;linux/skbuff.h&amp;gt;
+#include &amp;lt;linux/types.h&amp;gt;
+#include &amp;lt;net/dsfield.h&amp;gt;
+#include &amp;lt;net/flow.h&amp;gt;
+#include &amp;lt;net/inet_ecn.h&amp;gt;
+#include &amp;lt;net/ip.h&amp;gt;
+#include &amp;lt;net/rtnetlink.h&amp;gt;
+
+#define TUNNEL_CSUM__cpu_to_be16(0x01)
+#define TUNNEL_ROUTING__cpu_to_be16(0x02)
+#define TUNNEL_KEY__cpu_to_be16(0x04)
+#define TUNNEL_SEQ__cpu_to_be16(0x08)
+#define TUNNEL_STRICT__cpu_to_be16(0x10)
+#define TUNNEL_REC__cpu_to_be16(0x20)
+#define TUNNEL_VERSION__cpu_to_be16(0x40)
+#define TUNNEL_NO_KEY__cpu_to_be16(0x80)
+
+struct tnl_ptk_info {
+__be16 flags;
+__be16 proto;
+__be32 key;
+__be32 seq;
+};
+
+#define PACKET_RCVD0
+#define PACKET_REJECT1
+
+static inline void tunnel_ip_select_ident(struct sk_buff *skb,
+  const struct iphdr  *old_iph,
+  struct dst_entry *dst)
+{
+struct iphdr *iph = ip_hdr(skb);
+
+/* Use inner packet iph-id if possible. */
+if (skb-&amp;gt;protocol == htons(ETH_P_IP) &amp;amp;&amp;amp; old_iph-&amp;gt;id)
+iph-&amp;gt;id = old_iph-&amp;gt;id;
+else
+__ip_select_ident(iph, dst,
+(skb_shinfo(skb)-&amp;gt;gso_segs ?: 1) - 1);
+}
+
+int iptunnel_xmit(struct net *net, struct rtable *rt,
+  struct sk_buff *skb,
+  __be32 src, __be32 dst, __u8 proto,
+  __u8 tos, __u8 ttl, __be16 df);
+
+#endif /* __NET_IP_TUNNELS_H */
diff --git a/datapath/linux/compat/ip_tunnels_core.c b/datapath/linux/compat/ip_tunnels_core.c
new file mode 100644
index 0000000..67eee41
--- /dev/null
+++ b/datapath/linux/compat/ip_tunnels_core.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,78 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/*
+ * Copyright (c) 2007-2013 Nicira, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include &amp;lt;linux/in.h&amp;gt;
+#include &amp;lt;linux/in_route.h&amp;gt;
+#include &amp;lt;linux/inetdevice.h&amp;gt;
+#include &amp;lt;linux/jhash.h&amp;gt;
+#include &amp;lt;linux/list.h&amp;gt;
+#include &amp;lt;linux/kernel.h&amp;gt;
+#include &amp;lt;linux/version.h&amp;gt;
+#include &amp;lt;linux/workqueue.h&amp;gt;
+#include &amp;lt;linux/rculist.h&amp;gt;
+#include &amp;lt;net/ip_tunnels.h&amp;gt;
+#include &amp;lt;net/route.h&amp;gt;
+#include &amp;lt;net/xfrm.h&amp;gt;
+
+#include "gso.h"
+#include "compat.h"
+
+int iptunnel_xmit(struct net *net, struct rtable *rt,
+  struct sk_buff *skb,
+  __be32 src, __be32 dst, __u8 proto,
+  __u8 tos, __u8 ttl, __be16 df)
+{
+int pkt_len = skb-&amp;gt;len;
+struct iphdr *iph;
+int err;
+
+nf_reset(skb);
+secpath_reset(skb);
+skb_clear_rxhash(skb);
+skb_dst_drop(skb);
+skb_dst_set(skb, &amp;amp;rt_dst(rt));
+#if 0
+/* Do not clear ovs-callback.  It will be done in gso code. */
+memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+#endif
+
+/* Push down and install the IP header. */
+__skb_push(skb, sizeof(struct iphdr));
+skb_reset_network_header(skb);
+
+iph = ip_hdr(skb);
+
+iph-&amp;gt;version=4;
+iph-&amp;gt;ihl=sizeof(struct iphdr) &amp;gt;&amp;gt; 2;
+iph-&amp;gt;frag_off=df;
+iph-&amp;gt;protocol=proto;
+iph-&amp;gt;tos=tos;
+iph-&amp;gt;daddr=dst;
+iph-&amp;gt;saddr=src;
+iph-&amp;gt;ttl=ttl;
+tunnel_ip_select_ident(skb,
+       (const struct iphdr *)skb_inner_network_header(skb),
+       &amp;amp;rt_dst(rt));
+
+err = ip_local_out(skb);
+if (unlikely(net_xmit_eval(err)))
+pkt_len = 0;
+return pkt_len;
+}
diff --git a/datapath/tunnel.c b/datapath/tunnel.c
index 8c93e18..1275055 100644
--- a/datapath/tunnel.c
+++ b/datapath/tunnel.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -37,12 +37,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 #include "vlan.h"
 #include "vport.h"
 
-#if LINUX_VERSION_CODE &amp;gt;= KERNEL_VERSION(2,6,36)
-#define rt_dst(rt) (rt-&amp;gt;dst)
-#else
-#define rt_dst(rt) (rt-&amp;gt;u.dst)
-#endif
-
 /**
  *ovs_tnl_rcv - ingress point for generic tunnel code
  *
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -85,9 +79,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void ovs_tnl_rcv(struct vport *vport, struct sk_buff *skb,
 ovs_vport_receive(vport, skb, tun_key);
 }
 
-static struct rtable *find_route(struct net *net,
-__be32 *saddr, __be32 daddr, u8 ipproto,
-u8 tos, u32 skb_mark)
+struct rtable *find_route(struct net *net,
+  __be32 *saddr, __be32 daddr, u8 ipproto,
+  u8 tos, u32 skb_mark)
 {
 struct rtable *rt;
 /* Tunnel configuration keeps DSCP part of TOS bits, But Linux
diff --git a/datapath/tunnel.h b/datapath/tunnel.h
index 89c4e16..2ba7467 100644
--- a/datapath/tunnel.h
+++ b/datapath/tunnel.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -26,6 +26,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 #include "flow.h"
 #include "vport.h"
 
+struct rtable *find_route(struct net *net,
+  __be32 *saddr, __be32 daddr, u8 ipproto,
+  u8 tos, u32 skb_mark);
+
+u16 ovs_tnl_get_src_port(struct sk_buff *skb);
 
 int ovs_tnl_send(struct vport *vport, struct sk_buff *skb,
  u8 ipproto, int tunnel_hlen,
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -35,7 +40,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int ovs_tnl_send(struct vport *vport, struct sk_buff *skb,
 
 void ovs_tnl_rcv(struct vport *vport, struct sk_buff *skb,
  struct ovs_key_ipv4_tunnel *tun_key);
-u16 ovs_tnl_get_src_port(struct sk_buff *skb);
 
 static inline void tnl_tun_key_init(struct ovs_key_ipv4_tunnel *tun_key,
     const struct iphdr *iph, __be64 tun_id, u32 tun_flags)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -52,4 +56,4 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static inline void tnl_tun_key_init(struct ovs_key_ipv4_tunnel *tun_key,
        sizeof(*tun_key) - OVS_TUNNEL_KEY_SIZE);
 }
 
-#endif /* tunnel.h */
+#endif /* TUNNEL_H */
diff --git a/datapath/vport-gre.c b/datapath/vport-gre.c
index add17d9..f551976 100644
--- a/datapath/vport-gre.c
+++ b/datapath/vport-gre.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -24,26 +24,29 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 #include &amp;lt;linux/if_tunnel.h&amp;gt;
 #include &amp;lt;linux/if_vlan.h&amp;gt;
 #include &amp;lt;linux/in.h&amp;gt;
+#include &amp;lt;linux/if_vlan.h&amp;gt;
+#include &amp;lt;linux/in.h&amp;gt;
+#include &amp;lt;linux/in_route.h&amp;gt;
+#include &amp;lt;linux/inetdevice.h&amp;gt;
+#include &amp;lt;linux/jhash.h&amp;gt;
+#include &amp;lt;linux/list.h&amp;gt;
+#include &amp;lt;linux/kernel.h&amp;gt;
+#include &amp;lt;linux/workqueue.h&amp;gt;
+#include &amp;lt;linux/rculist.h&amp;gt;
+#include &amp;lt;net/route.h&amp;gt;
+#include &amp;lt;net/xfrm.h&amp;gt;
+
 
 #include &amp;lt;net/icmp.h&amp;gt;
 #include &amp;lt;net/ip.h&amp;gt;
+#include &amp;lt;net/ip_tunnels.h&amp;gt;
+#include &amp;lt;net/gre.h&amp;gt;
 #include &amp;lt;net/protocol.h&amp;gt;
 
 #include "datapath.h"
 #include "tunnel.h"
 #include "vport.h"
 
-/*
- * The GRE header is composed of a series of sections: a base and then a variable
- * number of options.
- */
-#define GRE_HEADER_SECTION 4
-
-struct gre_base_hdr {
-__be16 flags;
-__be16 protocol;
-};
-
 static int gre_hdr_len(const struct ovs_key_ipv4_tunnel *tun_key)
 {
 int len = GRE_HEADER_SECTION;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -55,19 +58,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int gre_hdr_len(const struct ovs_key_ipv4_tunnel *tun_key)
 return len;
 }
 
-static int gre64_hdr_len(const struct ovs_key_ipv4_tunnel *tun_key)
-{
-/* Set key for GRE64 tunnels, even when key if is zero. */
-int len = GRE_HEADER_SECTION +/* GRE Hdr */
-  GRE_HEADER_SECTION +/* GRE Key */
-  GRE_HEADER_SECTION;/* GRE SEQ */
-
-if (tun_key-&amp;gt;tun_flags &amp;amp; OVS_TNL_F_CSUM)
-len += GRE_HEADER_SECTION;
-
-return len;
-}
-
 /* Returns the least-significant 32 bits of a __be64. */
 static __be32 be64_get_low32(__be64 x)
 {
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -78,61 +68,35 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static __be32 be64_get_low32(__be64 x)
 #endif
 }
 
-static __be32 be64_get_high32(__be64 x)
+static __be16 ovs_tnl_flags_to_gre_flags(u16 tun_flags)
 {
-#ifdef __BIG_ENDIAN
-return (__force __be32)((__force u64)x &amp;gt;&amp;gt; 32);
-#else
-return (__force __be32)x;
-#endif
+__be16 flags = 0;
+if (tun_flags &amp;amp; OVS_TNL_F_CSUM)
+flags |= TUNNEL_CSUM;
+if (tun_flags &amp;amp; OVS_TNL_F_KEY)
+flags |= TUNNEL_KEY;
+return flags;
 }
 
-static void __gre_build_header(struct sk_buff *skb,
-       int tunnel_hlen,
-       bool is_gre64)
+static struct sk_buff *__build_header(const struct vport *vport,
+      struct sk_buff *skb,
+      int tunnel_hlen,
+      __be32 seq, __be16 gre64_flag)
 {
 const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)-&amp;gt;tun_key;
-__be32 *options = (__be32 *)(skb_network_header(skb) + tunnel_hlen
-- GRE_HEADER_SECTION);
-struct gre_base_hdr *greh = (struct gre_base_hdr *) skb_transport_header(skb);
-greh-&amp;gt;protocol = htons(ETH_P_TEB);
-greh-&amp;gt;flags = 0;
-
-/* Work backwards over the options so the checksum is last. */
-if (tun_key-&amp;gt;tun_flags &amp;amp; OVS_TNL_F_KEY || is_gre64) {
-greh-&amp;gt;flags |= GRE_KEY;
-if (is_gre64) {
-/* Set higher 32 bits to seq. */
-*options = be64_get_high32(tun_key-&amp;gt;tun_id);
-options--;
-greh-&amp;gt;flags |= GRE_SEQ;
-}
-*options = be64_get_low32(tun_key-&amp;gt;tun_id);
-options--;
-}
+struct tnl_ptk_info tpi;
 
-if (tun_key-&amp;gt;tun_flags &amp;amp; OVS_TNL_F_CSUM) {
-greh-&amp;gt;flags |= GRE_CSUM;
-*options = 0;
-*(__sum16 *)options = csum_fold(skb_checksum(skb,
-skb_transport_offset(skb),
-skb-&amp;gt;len - skb_transport_offset(skb),
-0));
-}
-}
+skb = gre_handle_offloads(skb, (tun_key-&amp;gt;tun_flags &amp;amp; OVS_TNL_F_CSUM));
+if (IS_ERR(skb))
+return NULL;
 
-static void gre_build_header(const struct vport *vport,
-     struct sk_buff *skb,
-     int tunnel_hlen)
-{
-__gre_build_header(skb, tunnel_hlen, false);
-}
+tpi.flags = ovs_tnl_flags_to_gre_flags(tun_key-&amp;gt;tun_flags) | gre64_flag;
+tpi.proto = htons(ETH_P_TEB);
+tpi.key = be64_get_low32(tun_key-&amp;gt;tun_id);
+tpi.seq = seq;
+gre_build_header(skb, &amp;amp;tpi, tunnel_hlen);
 
-static void gre64_build_header(const struct vport *vport,
-       struct sk_buff *skb,
-       int tunnel_hlen)
-{
-__gre_build_header(skb, tunnel_hlen, true);
+return skb;
 }
 
 static __be64 key_to_tunnel_id(__be32 key, __be32 seq)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -144,120 +108,45 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static __be64 key_to_tunnel_id(__be32 key, __be32 seq)
 #endif
 }
 
-static int parse_header(struct iphdr *iph, __be16 *flags, __be64 *tun_id,
-bool *is_gre64)
+static int _parse_header(const struct tnl_ptk_info *tpi, u32 *tnl_flags,
+ __be64 *tun_id)
 {
-/* IP and ICMP protocol handlers check that the IHL is valid. */
-struct gre_base_hdr *greh = (struct gre_base_hdr *)((u8 *)iph + (iph-&amp;gt;ihl &amp;lt;&amp;lt; 2));
-__be32 *options = (__be32 *)(greh + 1);
-int hdr_len;
-
-*flags = greh-&amp;gt;flags;
-
-if (unlikely(greh-&amp;gt;flags &amp;amp; (GRE_VERSION | GRE_ROUTING)))
-return -EINVAL;
-
-if (unlikely(greh-&amp;gt;protocol != htons(ETH_P_TEB)))
-return -EINVAL;
-
-hdr_len = GRE_HEADER_SECTION;
+int hdr_len = GRE_HEADER_SECTION;
 
-if (greh-&amp;gt;flags &amp;amp; GRE_CSUM) {
+*tnl_flags = 0;
+if (tpi-&amp;gt;flags &amp;amp; TUNNEL_CSUM) {
 hdr_len += GRE_HEADER_SECTION;
-options++;
+*tnl_flags |= OVS_TNL_F_CSUM;
 }
 
-if (greh-&amp;gt;flags &amp;amp; GRE_KEY) {
-__be32 seq;
-__be32 gre_key;
-
-gre_key = *options;
+if (tpi-&amp;gt;flags &amp;amp; TUNNEL_KEY) {
 hdr_len += GRE_HEADER_SECTION;
-options++;
-
-if (greh-&amp;gt;flags &amp;amp; GRE_SEQ) {
-seq = *options;
-*is_gre64 = true;
-} else {
-seq = 0;
-*is_gre64 = false;
-}
-*tun_id = key_to_tunnel_id(gre_key, seq);
+*tun_id = key_to_tunnel_id(tpi-&amp;gt;key, tpi-&amp;gt;seq);
+*tnl_flags |= OVS_TNL_F_KEY;
 } else {
 *tun_id = 0;
-/* Ignore GRE seq if there is no key present. */
-*is_gre64 = false;
 }
 
-if (greh-&amp;gt;flags &amp;amp; GRE_SEQ)
+if (tpi-&amp;gt;flags &amp;amp; TUNNEL_SEQ)
 hdr_len += GRE_HEADER_SECTION;
 
 return hdr_len;
 }
 
-static bool check_checksum(struct sk_buff *skb)
-{
-struct iphdr *iph = ip_hdr(skb);
-struct gre_base_hdr *greh = (struct gre_base_hdr *)(iph + 1);
-__sum16 csum = 0;
-
-if (greh-&amp;gt;flags &amp;amp; GRE_CSUM) {
-switch (skb-&amp;gt;ip_summed) {
-case CHECKSUM_COMPLETE:
-csum = csum_fold(skb-&amp;gt;csum);
-
-if (!csum)
-break;
-/* Fall through. */
-
-case CHECKSUM_NONE:
-skb-&amp;gt;csum = 0;
-csum = __skb_checksum_complete(skb);
-skb-&amp;gt;ip_summed = CHECKSUM_COMPLETE;
-break;
-}
-}
-
-return (csum == 0);
-}
-
-static u32 gre_flags_to_tunnel_flags(__be16 gre_flags, bool is_gre64)
-{
-u32 tunnel_flags = 0;
-
-if (gre_flags &amp;amp; GRE_KEY || is_gre64)
-tunnel_flags = OVS_TNL_F_KEY;
-
-if (gre_flags &amp;amp; GRE_CSUM)
-tunnel_flags |= OVS_TNL_F_CSUM;
-
-return tunnel_flags;
-}
-
 /* Called with rcu_read_lock and BH disabled. */
-static int gre_rcv(struct sk_buff *skb)
+static int gre_rcv(struct sk_buff *skb,
+   const struct tnl_ptk_info *tpi)
 {
 struct ovs_net *ovs_net;
 struct vport *vport;
 int hdr_len;
-struct iphdr *iph;
 struct ovs_key_ipv4_tunnel tun_key;
-__be16 gre_flags;
 u32 tnl_flags;
 __be64 key;
-bool is_gre64;
-
-if (unlikely(!pskb_may_pull(skb, sizeof(struct gre_base_hdr) + ETH_HLEN)))
-goto error;
-if (unlikely(!check_checksum(skb)))
-goto error;
-
-hdr_len = parse_header(ip_hdr(skb), &amp;amp;gre_flags, &amp;amp;key, &amp;amp;is_gre64);
-if (unlikely(hdr_len &amp;lt; 0))
-goto error;
 
+hdr_len = _parse_header(tpi, &amp;amp;tnl_flags, &amp;amp;key);
 ovs_net = net_generic(dev_net(skb-&amp;gt;dev), ovs_net_id);
-if (is_gre64)
+if (tpi-&amp;gt;flags &amp;amp; TUNNEL_SEQ)
 vport = rcu_dereference(ovs_net-&amp;gt;vport_net.gre64_vport);
 else
 vport = rcu_dereference(ovs_net-&amp;gt;vport_net.gre_vport);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -267,26 +156,22 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int gre_rcv(struct sk_buff *skb)
 if (unlikely(!pskb_may_pull(skb, hdr_len + ETH_HLEN)))
 goto error;
 
-iph = ip_hdr(skb);
-tnl_flags = gre_flags_to_tunnel_flags(gre_flags, is_gre64);
-tnl_tun_key_init(&amp;amp;tun_key, iph, key, tnl_flags);
+tnl_tun_key_init(&amp;amp;tun_key, ip_hdr(skb), key, tnl_flags);
 
 __skb_pull(skb, hdr_len);
 skb_postpull_rcsum(skb, skb_transport_header(skb), hdr_len + ETH_HLEN);
 
 ovs_tnl_rcv(vport, skb, &amp;amp;tun_key);
-return 0;
+return PACKET_RCVD;
 
 error:
 kfree_skb(skb);
-return 0;
+return PACKET_RCVD;
 }
 
-static const struct net_protocol gre_protocol_handlers = {
-.handler=gre_rcv,
-#if LINUX_VERSION_CODE &amp;gt;= KERNEL_VERSION(2,6,32)
-.netns_ok=1,
-#endif
+static struct gre_cisco_protocol gre_protocol = {
+.handler= gre_rcv,
+.priority= 1,
 };
 
 static int gre_ports;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -298,7 +183,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int gre_init(void)
 if (gre_ports &amp;gt; 1)
 return 0;
 
-err = inet_add_protocol(&amp;amp;gre_protocol_handlers, IPPROTO_GRE);
+err = gre_cisco_register(&amp;amp;gre_protocol);
 if (err)
 pr_warn("cannot register gre protocol handler\n");
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -311,7 +196,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void gre_exit(void)
 if (gre_ports &amp;gt; 0)
 return;
 
-inet_del_protocol(&amp;amp;gre_protocol_handlers, IPPROTO_GRE);
+gre_cisco_unregister(&amp;amp;gre_protocol);
 }
 
 static const char *gre_get_name(const struct vport *vport)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -361,7 +246,72 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void gre_tnl_destroy(struct vport *vport)
 gre_exit();
 }
 
-static int gre_tnl_send(struct vport *vport, struct sk_buff *skb)
+static int __send(struct vport *vport, struct sk_buff *skb,
+  int tunnel_hlen,
+  __be32 seq, __be16 gre64_flag)
+{
+struct net *net = ovs_dp_get_net(vport-&amp;gt;dp);
+struct rtable *rt;
+int min_headroom;
+__be16 df;
+__be32 saddr;
+int err;
+
+forward_ip_summed(skb, true);
+
+/* Route lookup */
+saddr = OVS_CB(skb)-&amp;gt;tun_key-&amp;gt;ipv4_src;
+rt = find_route(ovs_dp_get_net(vport-&amp;gt;dp),
+&amp;amp;saddr,
+OVS_CB(skb)-&amp;gt;tun_key-&amp;gt;ipv4_dst,
+IPPROTO_GRE,
+OVS_CB(skb)-&amp;gt;tun_key-&amp;gt;ipv4_tos,
+skb_get_mark(skb));
+if (IS_ERR(rt)) {
+err = PTR_ERR(rt);
+goto error;
+}
+
+min_headroom = LL_RESERVED_SPACE(rt_dst(rt).dev) + rt_dst(rt).header_len
++ tunnel_hlen
++ (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0);
+
+if (skb_headroom(skb) &amp;lt; min_headroom || skb_header_cloned(skb)) {
+int head_delta = SKB_DATA_ALIGN(min_headroom -
+skb_headroom(skb) +
+16);
+err = pskb_expand_head(skb, max_t(int, head_delta, 0),
+0, GFP_ATOMIC);
+if (unlikely(err))
+goto err_free_rt;
+}
+
+if (unlikely(vlan_deaccel_tag(skb))) {
+err = -ENOMEM;
+goto err_free_rt;
+}
+
+/* Push Tunnel header. */
+skb = __build_header(vport, skb, tunnel_hlen, seq, gre64_flag);
+if (unlikely(!skb)) {
+err = 0;
+goto err_free_rt;
+}
+
+df = OVS_CB(skb)-&amp;gt;tun_key-&amp;gt;tun_flags &amp;amp; OVS_TNL_F_DONT_FRAGMENT ?
+htons(IP_DF) : 0;
+
+return iptunnel_xmit(net, rt, skb, saddr,
+     OVS_CB(skb)-&amp;gt;tun_key-&amp;gt;ipv4_dst, IPPROTO_GRE,
+     OVS_CB(skb)-&amp;gt;tun_key-&amp;gt;ipv4_tos,
+     OVS_CB(skb)-&amp;gt;tun_key-&amp;gt;ipv4_ttl, df);
+err_free_rt:
+ip_rt_put(rt);
+error:
+return err;
+}
+
+static int gre_send(struct vport *vport, struct sk_buff *skb)
 {
 int hlen;
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -369,7 +319,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int gre_tnl_send(struct vport *vport, struct sk_buff *skb)
 return -EINVAL;
 
 hlen = gre_hdr_len(OVS_CB(skb)-&amp;gt;tun_key);
-return ovs_tnl_send(vport, skb, IPPROTO_GRE, hlen, gre_build_header);
+
+return __send(vport, skb, hlen, 0, 0);
 }
 
 const struct vport_ops ovs_gre_vport_ops = {
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -377,7 +328,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; const struct vport_ops ovs_gre_vport_ops = {
 .create= gre_create,
 .destroy= gre_tnl_destroy,
 .get_name= gre_get_name,
-.send= gre_tnl_send,
+.send= gre_send,
 };
 
 /* GRE64 vport. */
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -422,15 +373,39 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void gre64_tnl_destroy(struct vport *vport)
 gre_exit();
 }
 
-static int gre64_tnl_send(struct vport *vport, struct sk_buff *skb)
+static int gre64_hdr_len(const struct ovs_key_ipv4_tunnel *tun_key)
+{
+/* Set key for GRE64 tunnels, even when key if is zero. */
+int len = GRE_HEADER_SECTION +/* GRE Hdr */
+GRE_HEADER_SECTION +/* GRE Key */
+GRE_HEADER_SECTION;/* GRE SEQ */
+
+if (tun_key-&amp;gt;tun_flags &amp;amp; OVS_TNL_F_CSUM)
+len += GRE_HEADER_SECTION;
+
+return len;
+}
+
+static __be32 be64_get_high32(__be64 x)
+{
+#ifdef __BIG_ENDIAN
+return (__force __be32)((__force u64)x &amp;gt;&amp;gt; 32);
+#else
+return (__force __be32)x;
+#endif
+}
+
+static int gre64_send(struct vport *vport, struct sk_buff *skb)
 {
 int hlen;
+__be32 seq;
 
 if (unlikely(!OVS_CB(skb)-&amp;gt;tun_key))
 return -EINVAL;
 
 hlen = gre64_hdr_len(OVS_CB(skb)-&amp;gt;tun_key);
-return ovs_tnl_send(vport, skb, IPPROTO_GRE, hlen, gre64_build_header);
+seq = be64_get_high32(OVS_CB(skb)-&amp;gt;tun_key-&amp;gt;tun_id);
+return __send(vport, skb, hlen, seq, TUNNEL_SEQ);
 }
 
 const struct vport_ops ovs_gre64_vport_ops = {
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -438,5 +413,5 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; const struct vport_ops ovs_gre64_vport_ops = {
 .create= gre64_create,
 .destroy= gre64_tnl_destroy,
 .get_name= gre_get_name,
-.send= gre64_tnl_send,
+.send= gre64_send,
 };
&lt;/pre&gt;</description>
    <dc:creator>Pravin B Shelar</dc:creator>
    <dc:date>2013-05-20T17:56:58</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20719">
    <title>[PATCH 1/2] ovs-vswitchd: An option to enable/disablepacket processing from datapath.</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20719</link>
    <description>&lt;pre&gt;This commit provides an option to enable or disable packet processing
coming from the datapath.

This option is useful during Open vSwitch upgrades. Typically we want
to restart openvswitch, add the openflow flows and then start packet
processing. The next commit will use these commands in Open vSwitch
startup scripts.

Bug #16086.
Signed-off-by: Gurucharan Shetty &amp;lt;gshetty-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
---
 ofproto/ofproto-dpif.c |   21 ++++++++++++++++++++-
 vswitchd/bridge.c      |    7 +++++++
 vswitchd/vswitch.xml   |    9 +++++++++
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index c4f7d25..a31b186 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -72,6 +72,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; COVERAGE_DEFINE(facet_suppress);
  * flow translation. */
 #define MAX_RESUBMIT_RECURSION 64
 
+extern bool recv_set_enable;
+
 /* Number of implemented OpenFlow tables. */
 enum { N_TABLES = 255 };
 enum { TBL_INTERNAL = N_TABLES - 1 };    /* Used for internal hidden rules. */
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -671,6 +673,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct dpif_backer {
     struct tag_set revalidate_set; /* Revalidate only matching facets. */
 
     struct hmap drop_keys; /* Set of dropped odp keys. */
+    bool recv_set_enable; /* Enables or disables receiving packets. */
 };
 
 /* All existing ofproto_backer instances, indexed by ofproto-&amp;gt;up.type. */
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -937,6 +940,21 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; type_run(const char *type)
 
     dpif_run(backer-&amp;gt;dpif);
 
+    /* Enable or disable receiving packets on 'dpif' based on user
+     * configuration. */
+    if (backer-&amp;gt;recv_set_enable != recv_set_enable) {
+        backer-&amp;gt;recv_set_enable = recv_set_enable;
+        error = dpif_recv_set(backer-&amp;gt;dpif, recv_set_enable);
+        if (error) {
+            VLOG_ERR("Failed to %s receiving packets in dpif",
+                     recv_set_enable ? "enable" : "disable");
+            return error;
+        }
+        if (recv_set_enable) {
+            backer-&amp;gt;need_revalidate = REV_RECONFIGURE;
+        }
+    }
+
     /* The most natural place to push facet statistics is when they're pulled
      * from the datapath.  However, when there are many flows in the datapath,
      * this expensive operation can occur so frequently, that it reduces our
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1331,7 +1349,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; open_dpif_backer(const char *type, struct dpif_backer **backerp)
 
     shash_add(&amp;amp;all_dpif_backers, type, backer);
 
-    error = dpif_recv_set(backer-&amp;gt;dpif, true);
+    backer-&amp;gt;recv_set_enable = recv_set_enable;
+    error = dpif_recv_set(backer-&amp;gt;dpif, recv_set_enable);
     if (error) {
         VLOG_ERR("failed to listen on datapath of type %s: %s",
                  type, strerror(error));
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index e10036c..80e22fb 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -183,6 +183,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static long long int iface_stats_timer = LLONG_MIN;
 #define OFP_PORT_ACTION_WINDOW 10
 static bool reconfiguring = false;
 
+/* The default value of true enables receving packets on 'dpif'. */
+bool recv_set_enable = true;
+
 static void add_del_bridges(const struct ovsrec_open_vswitch *);
 static void bridge_update_ofprotos(void);
 static void bridge_create(const struct ovsrec_bridge *);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2321,6 +2324,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; bridge_run(void)
      * returns immediately. */
     bridge_init_ofproto(cfg);
 
+    /* Enables or disables receiving packets on 'dpif'. */
+    recv_set_enable = smap_get_bool(&amp;amp;cfg-&amp;gt;other_config,
+                                    "dpif-packet-receive", true);
+
     /* Let each datapath type do the work that it needs to do. */
     sset_init(&amp;amp;types);
     ofproto_enumerate_types(&amp;amp;types);
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 4396779..fa033f6 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -104,6 +104,15 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
           column or to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to explicitly disable it.
         &amp;lt;/column&amp;gt;
 
+        &amp;lt;column name="other_config" key="dpif-packet-receive"
+                type='{"type": "boolean"}'&amp;gt;
+          Packets are received from the datapath by default. Set this value to
+          &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; to stop receiving packets from the datapath and
+          &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; to start receiving packets. This option is useful
+          during openvswitch upgrades and is used to restore flows before
+          processing the packets.
+        &amp;lt;/column&amp;gt;
+
         &amp;lt;column name="statistics" key="cpu"
                 type='{"type": "integer", "minInteger": 1}'&amp;gt;
           &amp;lt;p&amp;gt;
&lt;/pre&gt;</description>
    <dc:creator>Gurucharan Shetty</dc:creator>
    <dc:date>2013-05-20T06:53:14</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20718">
    <title>[PATCH] ovs-xapi-sync: Handle multiple xs-network-uuidsfor xs 6.1.</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20718</link>
    <description>&lt;pre&gt;For xenservers with version less than 6.1, interface reconfiguration
happened through interface-reconfigure scripts in this repo. In cases
where there were multiple xs-network-uuids for a single bridge,
interface-reconfigure script would add the network uuid associated
with the non-VLAN network as the first record. ovs-xapi-sync would
just blindly use the first record to create the bridge-id

But it looks like for xenserver 6.1, interface-reconfigure script
is no longer used and xenserver natively writes the xs-network-uuids.
So, in ovs-xapi-sync we no longer can copy the first value in
xs-network-uuids as bridge-id. This commit fetches the PIF record
for each xs-network-uuids and the network that does not have a VLAN
associated with it is copied over to bridge-id.

Bug #17090.
Signed-off-by: Gurucharan Shetty &amp;lt;gshetty-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
---
 .../usr_share_openvswitch_scripts_ovs-xapi-sync    |   22 ++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync b/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync
index cb35e7a..e14b319 100755
--- a/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync
+++ b/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -88,6 +88,25 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; def get_network_by_bridge(br_name):
 
     return None
 
+# There are possibilities when multiple xs-network-uuids are set for a bridge.
+# In cases like that, we should choose the bridge-id whose PIF does not have a
+# VLAN associated with it.
+def get_single_bridge_id(bridge_ids, default=None):
+    if not init_session():
+        vlog.warn("Failed to get single bridge id from %s because"
+                  "XAPI session could not be initialized" % bridge_ids)
+        return default
+
+    for bridge_id in bridge_ids:
+       recs = session.xenapi.network.get_all_records_where('field "uuid"="%s"' % bridge_id)
+       if recs:
+           pifs = recs.values()[0]['PIFs']
+           for pif in pifs:
+               rec = session.xenapi.PIF.get_record(pif)
+               if rec['VLAN'] == '-1':
+                   return bridge_id
+
+    return default
 
 # By default, the "bridge-id" external id in the Bridge table is the
 # same as "xs-network-uuids".  This may be overridden by defining a
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -286,6 +305,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; def main():
             bridge_id = nbd
             if bridge_id is None:
                 bridge_id = row.external_ids.get("xs-network-uuids")
+                if bridge_id and len(bridge_id.split(";")) &amp;gt; 1:
+                    bridge_ids = bridge_id.split(";")
+                    bridge_id = get_single_bridge_id(bridge_ids, bridge_ids[0])
 
             if bridge_id is not None:
                 set_external_id(row, "bridge-id", bridge_id.split(";")[0])
&lt;/pre&gt;</description>
    <dc:creator>Gurucharan Shetty</dc:creator>
    <dc:date>2013-05-20T14:56:16</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20711">
    <title>[PATCH] ofproto/ofproto-dpif.c: Fix a typo in functionheader</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20711</link>
    <description>&lt;pre&gt;There is a typo in the "bundle_add_port()" function header.

This patch fixes it.

Signed-off-by: Alex Wang &amp;lt;alexw-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
---
 ofproto/ofproto-dpif.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index c4f7d25..5cc56d1 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2472,7 +2472,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; bundle_del_port(struct ofport_dpif *port)
 }
 
 static bool
-bundle_add_port(struct ofbundle *bundle, uint32_t ofp_port,
+bundle_add_port(struct ofbundle *bundle, uint16_t ofp_port,
                 struct lacp_slave_settings *lacp)
 {
     struct ofport_dpif *port;
&lt;/pre&gt;</description>
    <dc:creator>Alex Wang</dc:creator>
    <dc:date>2013-05-19T04:33:25</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20707">
    <title>[PATCH] netdev-dummy: Remove FreeBSD dependency.</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20707</link>
    <description>&lt;pre&gt;There's no particular reason that netdev_dummy_register() has to care about
the particular OS, except that the tests like to use the special Linux-only
tunnel vport types.  But that can be done better, I think, by just always
registering them from netdev_dummy_register() and making that function
idempotent, so that calling it twice under Linux has no additional effect.
This commit implements that solution.

CC: Ed Maste &amp;lt;emaste-h+KGxgPPiopAfugRpC6u6w&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
Signed-off-by: Ben Pfaff &amp;lt;blp-l0M0P4e3n4LQT0dZR+AlfA&amp;lt; at &amp;gt;public.gmane.org&amp;gt;
---
 lib/netdev-dummy.c |   10 +---------
 lib/netdev-vport.c |    8 ++++++--
 2 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
index 908fef2..14b286b 100644
--- a/lib/netdev-dummy.c
+++ b/lib/netdev-dummy.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -36,12 +36,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 
 VLOG_DEFINE_THIS_MODULE(netdev_dummy);
 
-#ifdef __FreeBSD__
-#define FREE_BSD 1
-#else
-#define FREE_BSD 0
-#endif
-
 struct netdev_dummy {
     struct netdev up;
     uint8_t hwaddr[ETH_ADDR_LEN];
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -553,7 +547,5 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; netdev_dummy_register(bool override)
     }
     netdev_register_provider(&amp;amp;dummy_class);
 
-    if (FREE_BSD) {
-        netdev_vport_tunnel_register();
-    }
+    netdev_vport_tunnel_register();
 }
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 38fc996..6eee8a7 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -685,11 +685,15 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; netdev_vport_tunnel_register(void)
         TUNNEL_CLASS("vxlan", "vxlan_system"),
         TUNNEL_CLASS("lisp", "lisp_system")
     };
+    static bool inited;
 
     int i;
 
-    for (i = 0; i &amp;lt; ARRAY_SIZE(vport_classes); i++) {
-        netdev_register_provider(&amp;amp;vport_classes[i].netdev_class);
+    if (!inited) {
+        inited = true;
+        for (i = 0; i &amp;lt; ARRAY_SIZE(vport_classes); i++) {
+            netdev_register_provider(&amp;amp;vport_classes[i].netdev_class);
+        }
     }
 }
 
&lt;/pre&gt;</description>
    <dc:creator>Ben Pfaff</dc:creator>
    <dc:date>2013-05-17T22:57:20</dc:date>
  </item>
  <item rdf:about="http://comments.gmane.org/gmane.network.openvswitch.devel/20704">
    <title>[oftest v3 0/5] add support for OFTest</title>
    <link>http://comments.gmane.org/gmane.network.openvswitch.devel/20704</link>
    <description>&lt;pre&gt;This is the latest version of the oftest series.  The first version
was posted Oct. 25, 2012.  The second version was posted Feb. 1, 2013.
The only difference between v2 and v3 is considerable work rebasing
due to the restructuring of the netdev library interface.

Ben Pfaff (5):
  netdev-dummy: Limit receive queue length to 100 packets.
  netdev-dummy: Factor some netdev_dummy_receive() code out into new
    function.
  netdev-dummy: Drop "nobody listened" reply from netdev-dummy/receive.
  netdev-dummy: Add "pstream" option for connecting a dummy to a
    process.
  tests: Add support for running OFTest.

 Makefile.am           |    1 +
 NEWS                  |    2 +
 README-OFTest         |   77 ++++++++++++++
 lib/netdev-dummy.c    |  267 +++++++++++++++++++++++++++++++++++++++++++++---
 tests/automake.mk     |    6 +
 tests/ofproto-dpif.at |   24 ++---
 tests/run-oftest      |   94 +++++++++++++++++
 7 files changed, 438 insertions(+), 33 deletions(-)
 create mode 100644 README-OFTest
 create mode 100755 tests/run-oftest

&lt;/pre&gt;</description>
    <dc:creator>Ben Pfaff</dc:creator>
    <dc:date>2013-05-17T22:23:45</dc:date>
  </item>
  <textinput rdf:about="http://search.gmane.org/?group=$group=gmane.network.openvswitch.devel">
    <title>Search Engine</title>
    <description>Search the mailing list at Gmane</description>
    <name>query</name>
    <link>http://search.gmane.org/?group=$group=gmane.network.openvswitch.devel</link>
  </textinput>
</rdf:RDF>
