Merge commit '559eb2308b4d616590aba34bb8f4dd7f12ae4587'
authorGiuseppe Lettieri <g.lettieri@iet.unipi.it>
Fri, 5 Jul 2013 17:36:43 +0000 (19:36 +0200)
committerGiuseppe Lettieri <g.lettieri@iet.unipi.it>
Fri, 5 Jul 2013 17:36:43 +0000 (19:36 +0200)
Conflicts:
Makefile.am

165 files changed:
AUTHORS
FAQ
INSTALL
INSTALL.Debian
INSTALL.RHEL
INSTALL.XenServer
Makefile.am
NEWS
README
WHY-OVS
acinclude.m4
configure.ac
datapath/Modules.mk
datapath/datapath.c
datapath/datapath.h
datapath/dp_notify.c
datapath/flow.c
datapath/genl_exec.c [deleted file]
datapath/genl_exec.h [deleted file]
datapath/linux/Modules.mk
datapath/linux/compat/include/asm/percpu.h
datapath/linux/compat/include/linux/genetlink.h [deleted file]
datapath/linux/compat/include/linux/if_tunnel.h [new file with mode: 0644]
datapath/linux/compat/include/linux/netdevice.h
datapath/linux/compat/include/linux/workqueue.h
datapath/linux/compat/include/net/netlink.h
datapath/linux/compat/netdevice.c
datapath/linux/compat/workqueue.c
datapath/vport-gre.c
datapath/vport-internal_dev.c
datapath/vport-netdev.c
datapath/vport-netdev.h
datapath/vport.c
datapath/vport.h
debian/changelog
debian/control
debian/openvswitch-switch.init
debian/openvswitch-switch.postinst
debian/rules
include/linux/openvswitch.h
include/openflow/nicira-ext.h
lib/daemon.c
lib/daemon.h
lib/dpif-linux.c
lib/dpif-netdev.c
lib/dynamic-string.c
lib/hmap.h
lib/json.c
lib/list.c
lib/match.c
lib/memory.c
lib/meta-flow.c
lib/meta-flow.h
lib/netdev-bsd.c
lib/netdev-linux.c
lib/netdev-vport.c
lib/netlink-socket.c
lib/nx-match.c
lib/odp-util.c
lib/odp-util.h
lib/ofp-actions.c
lib/ofp-actions.h
lib/ofp-parse.c
lib/ofp-util.c
lib/ofp-util.def
lib/process.c
lib/route-table-bsd.c
lib/route-table.h
lib/sflow.h
lib/signals.c
lib/signals.h
lib/smap.c
lib/socket-util.c
lib/socket-util.h
lib/sset.c
lib/sset.h
lib/stream-provider.h
lib/stream-ssl.c
lib/stream-tcp.c
lib/stream.c
lib/stream.h
lib/table.c
lib/timeval.c
lib/timeval.h
lib/util.c
lib/util.h
lib/vlog.h
lib/worker.c
m4/ax_check_openssl.m4 [new file with mode: 0644]
m4/openvswitch.m4
ofproto/.gitignore
ofproto/automake.mk
ofproto/ipfix-gen-entities [new file with mode: 0755]
ofproto/ipfix.xml [new file with mode: 0644]
ofproto/ofproto-dpif-ipfix.c [new file with mode: 0644]
ofproto/ofproto-dpif-ipfix.h [new file with mode: 0644]
ofproto/ofproto-dpif-sflow.c
ofproto/ofproto-dpif.c
ofproto/ofproto-provider.h
ofproto/ofproto.c
ofproto/ofproto.h
ofproto/tunnel.c
ovsdb/jsonrpc-server.c
ovsdb/jsonrpc-server.h
ovsdb/ovsdb-client.c
ovsdb/ovsdb-server.1.in
ovsdb/ovsdb-server.c
ovsdb/ovsdb-tool.c
python/ovs/db/idl.py
python/ovs/poller.py
python/ovs/socket_util.py
python/ovs/vlog.py
rhel/etc_init.d_openvswitch
tests/.gitignore
tests/automake.mk
tests/choose-port.pl [deleted file]
tests/lacp.at
tests/odp.at
tests/ofp-actions.at
tests/ofproto-dpif.at
tests/ofproto-macros.at
tests/ofproto.at
tests/ovs-ofctl.at
tests/ovs-vsctl.at
tests/ovs-vswitchd.at [new file with mode: 0644]
tests/ovsdb-execution.at
tests/ovsdb-idl.at
tests/ovsdb-monitor.at
tests/ovsdb-server.at
tests/ovsdb-tool.at
tests/ovsdb-trigger.at
tests/test-jsonrpc.c
tests/test-netflow.c
tests/test-ovsdb.c
tests/test-sflow.c
tests/test-util.c
tests/testsuite.at
tests/tunnel.at
tutorial/.gitignore [new file with mode: 0644]
tutorial/Tutorial [new file with mode: 0644]
tutorial/automake.mk [new file with mode: 0644]
tutorial/ovs-sandbox [new file with mode: 0755]
tutorial/t-setup [new file with mode: 0755]
tutorial/t-stage0 [new file with mode: 0755]
tutorial/t-stage1 [new file with mode: 0755]
tutorial/t-stage2 [new file with mode: 0755]
tutorial/t-stage3 [new file with mode: 0755]
tutorial/t-stage4 [new file with mode: 0755]
utilities/ovs-benchmark.c
utilities/ovs-controller.c
utilities/ovs-ctl.in
utilities/ovs-dpctl.c
utilities/ovs-lib.in
utilities/ovs-ofctl.8.in
utilities/ovs-ofctl.c
utilities/ovs-pki.in
utilities/ovs-vsctl.8.in
utilities/ovs-vsctl.c
vswitchd/bridge.c
vswitchd/ovs-vswitchd.c
vswitchd/system-stats.c
vswitchd/vswitch.gv
vswitchd/vswitch.ovsschema
vswitchd/vswitch.pic
vswitchd/vswitch.xml

diff --git a/AUTHORS b/AUTHORS
index 2ca0c2b..593776d 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -3,10 +3,12 @@ signed off on commits in the Open vSwitch version control repository.
 
 Aaron Rosen             arosen@clemson.edu
 Alexey I. Froloff       raorn@altlinux.org
+Alex Wang               alexw@nicira.com
 Andrew Evans            aevans@nicira.com
 Andrew Lambeth          wal@nicira.com
 Andy Southgate          andy.southgate@citrix.com
 Andy Zhou               azhou@nicira.com
+Ansis Atteka            aatteka@nicira.com
 Anupam Chanda           achanda@nicira.com
 Arun Sharma             arun.sharma@calsoftinc.com
 Ben Pfaff               blp@nicira.com
@@ -25,6 +27,7 @@ David Erickson          derickso@stanford.edu
 David S. Miller         davem@davemloft.net
 Devendra Naga           devendra.aaru@gmail.com
 Dominic Curran          dominic.curran@citrix.com
+Duffie Cooley           dcooley@nicira.com
 Ed Maste                emaste at freebsd.org
 Edward Tomasz NapieraÅ‚a trasz@freebsd.org
 Ethan Jackson           ethan@nicira.com
@@ -90,6 +93,7 @@ Yasuhito Takamiya       yasuhito@gmail.com
 Yu Zhiguo               yuzg@cn.fujitsu.com
 Zoltan Kiss             zoltan.kiss@citrix.com
 Zhi Yong Wu             zwu.kernel@gmail.com
+Zang MingJie            zealot0630@gmail.com
 
 The following additional people are mentioned in commit logs as having
 provided helpful bug reports or suggestions.
@@ -101,7 +105,9 @@ Alan Shieh              ashieh@nicira.com
 Alban Browaeys          prahal@yahoo.com
 Alex Yip                alex@nicira.com
 Alexey I. Froloff       raorn@altlinux.org
+Amar Padmanabhan        amar@nicira.com
 Amey Bhide              abhide@nicira.com
+Amre Shakimov           ashakimov@vmware.com
 André Ruß               andre.russ@hybris.com
 Andreas Beckmann        debian@abeckmann.de
 Atzm Watanabe           atzm@stratosphere.co.jp
@@ -118,7 +124,7 @@ Cedric Hobbs            cedric@nicira.com
 Dave Walker             DaveWalker@ubuntu.com
 David Palma             palma@onesource.pt
 Derek Cormier           derek.cormier@lab.ntt.co.jp
-Duffie Cooley           dcooley@nicira.com
+Dhaval Badiani          dbadiani@vmware.com
 DK Moon                 dkmoon@nicira.com
 Edwin Chiu              echiu@nicira.com
 Eivind Bulie Haanaes
@@ -135,6 +141,7 @@ Hassan Khan             hassan.khan@seecs.edu.pk
 Hector Oron             hector.oron@gmail.com
 Henrik Amren            henrik@nicira.com
 Hiroshi Tanaka          htanaka@nicira.com
+Hiroshi Miyata          miyahiro.dazu@gmail.com
 Igor Ganichev           iganichev@nicira.com
 Jacob Cherkas           jcherkas@nicira.com
 Jad Naous               jnaous@gmail.com
@@ -197,6 +204,7 @@ Vishal Swarankar        vishal.swarnkar@gmail.com
 Vjekoslav Brajkovic     balkan@cs.washington.edu
 Voravit T.              voravit@kth.se
 YAMAMOTO Takashi        yamamoto@valinux.co.jp
+Yeming Zhao             zhaoyeming@gmail.com
 Yongqiang Liu           liuyq7809@gmail.com
 kk yap                  yapkke@stanford.edu
 likunyun                kunyunli@hotmail.com
diff --git a/FAQ b/FAQ
index 7488112..1f0f841 100644 (file)
--- a/FAQ
+++ b/FAQ
@@ -9,12 +9,13 @@ General
 Q: What is Open vSwitch?
 
 A: Open vSwitch is a production quality open source software switch
-   designed to be used as a vswitch in virtualized server environments.  A
-   vswitch forwards traffic between different VMs on the same physical host
-   and also forwards traffic between VMs and the physical network.  Open
-   vSwitch supports standard management interfaces (e.g. sFlow, NetFlow,
-   RSPAN, CLI), and is open to programmatic extension and control using
-   OpenFlow and the OVSDB management protocol.
+   designed to be used as a vswitch in virtualized server
+   environments.  A vswitch forwards traffic between different VMs on
+   the same physical host and also forwards traffic between VMs and
+   the physical network.  Open vSwitch supports standard management
+   interfaces (e.g. sFlow, NetFlow, IPFIX, RSPAN, CLI), and is open to
+   programmatic extension and control using OpenFlow and the OVSDB
+   management protocol.
 
    Open vSwitch as designed to be compatible with modern switching
    chipsets.  This means that it can be ported to existing high-fanout
@@ -125,7 +126,7 @@ A: All official releases have been through a comprehensive testing
    LTS release, we will provide an updated release that includes the
    fix.  Releases that are not LTS may not be fixed and may just be
    supplanted by the next major release.  The current LTS release is
-   1.4.x.
+   1.9.x.
 
 Q: What Linux kernel versions does each Open vSwitch release work with?
 
@@ -153,6 +154,11 @@ A: The following table lists the Linux kernel versions against which the
    It should build against almost any kernel, certainly against 2.6.18
    and later.
 
+Q: What Linux kernel versions does IPFIX flow monitoring work with?
+
+A: IPFIX flow monitoring requires the Linux kernel module from Open
+   vSwitch version 1.10.90 or later.
+
 Q: Should userspace or kernel be upgraded first to minimize downtime?
 
    In general, the Open vSwitch userspace should be used with the
@@ -319,6 +325,43 @@ A: No.  ERSPAN is an undocumented proprietary protocol.  As an
    alternative, Open vSwitch supports mirroring to a GRE tunnel (see
    above).
 
+Q: How do I connect two bridges?
+
+A: First, why do you want to do this?  Two connected bridges are not
+   much different from a single bridge, so you might as well just have
+   a single bridge with all your ports on it.
+
+   If you still want to connect two bridges, you can use a pair of
+   patch ports.  The following example creates bridges br0 and br1,
+   adds eth0 and tap0 to br0, adds tap1 to br1, and then connects br0
+   and br1 with a pair of patch ports.
+
+       ovs-vsctl add-br br0
+       ovs-vsctl add-port br0 eth0
+       ovs-vsctl add-port br0 tap0
+       ovs-vsctl add-br br1
+       ovs-vsctl add-port br1 tap1
+       ovs-vsctl \
+           -- add-port br0 patch0 \
+           -- set interface patch0 type=patch options:peer=patch1 \
+           -- add-port br1 patch1 \
+           -- set interface patch1 type=patch options:peer=patch0
+
+   Bridges connected with patch ports are much like a single bridge.
+   For instance, if the example above also added eth1 to br1, and both
+   eth0 and eth1 happened to be connected to the same next-hop switch,
+   then you could loop your network just as you would if you added
+   eth0 and eth1 to the same bridge (see the "Configuration Problems"
+   section below for more information).
+
+   If you are using Open vSwitch 1.9 or an earlier version, then you
+   need to be using the kernel module bundled with Open vSwitch rather
+   than the one that is integrated into Linux 3.3 and later, because
+   Open vSwitch 1.9 and earlier versions need kernel support for patch
+   ports.  This also means that in Open vSwitch 1.9 and earlier, patch
+   ports will not work with the userspace datapath, only with the
+   kernel module.
+
 Q: Why are there so many different ways to dump flows?
 
 A: Open vSwitch uses different kinds of flows for different purposes:
@@ -773,6 +816,21 @@ A: It is to be expected that the VMs can't access each other.  VLANs
    the machines you are trying to access are not on VLAN 9 (or 10) and
    that the Internet is not available on VLAN 9 (or 10).
 
+Q: I added a pair of VMs on the same VLAN, like this:
+
+       ovs-vsctl add-br br0
+       ovs-vsctl add-port br0 eth0
+       ovs-vsctl add-port br0 tap0 tag=9
+       ovs-vsctl add-port br0 tap1 tag=9
+
+    The VMs can access each other, but not the external network or the
+    Internet.
+
+A: It seems likely that the machines you are trying to access in the
+   external network are not on VLAN 9 and that the Internet is not
+   available on VLAN 9.  Also, ensure VLAN 9 is set up as an allowed
+   trunk VLAN on the upstream switch port to which eth0 is connected.
+
 Q: Can I configure an IP address on a VLAN?
 
 A: Yes.  Use an "internal port" configured as an access port.  For
@@ -832,8 +890,43 @@ A: Do you have a controller configured on br0 (as the commands above
    can refer to the answer there for more information.
 
 
-Controllers
------------
+VXLANs
+-----
+
+Q: What's a VXLAN?
+
+A: VXLAN stands for Virtual eXtensible Local Area Network, and is a means
+   to solve the scaling challenges of VLAN networks in a multi-tenant
+   environment. VXLAN is an overlay network which transports an L2 network
+   over an existing L3 network. For more information on VXLAN, please see
+   the IETF draft available here:
+
+   http://tools.ietf.org/html/draft-mahalingam-dutt-dcops-vxlan-03
+
+Q: How much of the VXLAN protocol does Open vSwitch currently support?
+
+A: Open vSwitch currently supports the framing format for packets on the
+   wire. There is currently no support for the multicast aspects of VXLAN.
+   To get around the lack of multicast support, it is possible to
+   pre-provision MAC to IP address mappings either manually or from a
+   controller.
+
+Q: What destination UDP port does the VXLAN implementation in Open vSwitch
+   use?
+
+A: By default, Open vSwitch will use the assigned IANA port for VXLAN, which
+   is 4789. However, it is possible to configure the destination UDP port
+   manually on a per-VXLAN tunnel basis. An example of this configuration is
+   provided below.
+
+   ovs-vsctl add-br br0
+   ovs-vsctl add-port br0 vxlan1 -- set interface vxlan1
+       type=vxlan options:remote_ip=192.168.1.2 options:key=flow
+       options:dst_port=8472
+
+
+Using OpenFlow (Manually or Via Controller)
+-------------------------------------------
 
 Q: What versions of OpenFlow does Open vSwitch support?
 
@@ -1094,6 +1187,23 @@ A: To debug network behavior problems, trace the path of a packet,
    problem.  If not, then follow the ARP reply back to the origin, in
    reverse.
 
+Q: How do I make a flow drop packets?
+
+A: An empty set of actions causes a packet to be dropped.  You can
+   specify an empty set of actions with "actions=" on the ovs-ofctl
+   command line.  For example:
+
+       ovs-ofctl add-flow br0 priority=65535,actions=
+
+   would cause every packet entering switch br0 to be dropped.
+
+   You can write "drop" explicitly if you like.  The effect is the
+   same.  Thus, the following command also causes every packet
+   entering switch br0 to be dropped:
+
+       ovs-ofctl add-flow br0 priority=65535,actions=drop
+
+
 Contact 
 -------
 
diff --git a/INSTALL b/INSTALL
index 5d62a90..a78ded0 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -16,13 +16,11 @@ Build Requirements
 To compile the userspace programs in the Open vSwitch distribution,
 you will need the following software:
 
-    - A make program, e.g. GNU make.  BSD make should also work.
+    - GNU make.
 
     - The GNU C compiler.  We generally test with version 4.1, 4.2, or
       4.3.
 
-    - pkg-config.  We test with version 0.22.
-
     - libssl, from OpenSSL, is optional but recommended if you plan to
       connect the Open vSwitch to an OpenFlow controller.  libssl is
       required to establish confidentiality and authenticity in the
@@ -192,15 +190,16 @@ Prerequisites section, follow the procedure below to build.
    additional environment variables.  For a full list, invoke
    configure with the --help option.
 
-3. Run make in the top source directory:
+3. Run GNU make in the top source directory, e.g.:
 
       % make
 
-   On FreeBSD you may need to use GNU make (gmake) or NetBSD make
-   (bmake) instead of the native make.
+   or if GNU make is installed as "gmake":
+
+      % gmake
 
    For improved warnings if you installed "sparse" (see
-   "Prerequisites"), add C=1 to the "make" command line.
+   "Prerequisites"), add C=1 to the command line.
 
 4. Consider running the testsuite.  Refer to "Running the Testsuite"
    below, for instructions.
index 62f4c19..f7456c5 100644 (file)
@@ -72,12 +72,8 @@ packages.
 
 You must be superuser to install Debian packages.
 
-1. Start by installing the "openvswitch-switch" and
-   "openvswitch-common" packages.  These packages include the core
-   userspace components of the switch.
-
-2. Install an Open vSwitch kernel module.  There are multiple ways to
-   do this.  In order of increasing manual effort, these are:
+1. Start by installing an Open vSwitch kernel module.  There are multiple ways
+   to do this.  In order of increasing manual effort, these are:
 
        * Use a Linux kernel 3.3 or later, which has an integrated Open
         vSwitch kernel module.
@@ -113,6 +109,10 @@ You must be superuser to install Debian packages.
 
        * Build and install the kernel module by hand.
 
+2. Install the "openvswitch-switch" and "openvswitch-common" packages.
+   These packages include the core userspace components of the switch.
+
+
 Open vSwitch .deb packages not mentioned above are rarely useful.
 Please refer to their individual package descriptions to find out
 whether any of them are useful to you.
index eaa2e7c..a698fae 100644 (file)
@@ -101,6 +101,12 @@ RHEL.  On RHEL 5, the default RPM source directory is
     in this example: "kmod-openvswitch", "kmod-openvswitch-debug", and
     "kmod-openvswitch-kdump".
 
+A RHEL host has default firewall rules that prevent any Open vSwitch tunnel
+traffic from passing through. If a user configures Open vSwitch tunnels like
+GRE, VXLAN, LISP etc., they will either have to manually add iptables firewall
+rules to allow the tunnel traffic or add it through a startup script (Please
+refer to the "enable-protocol" command in the ovs-ctl(8) manpage).
+
 Red Hat Network Scripts Integration
 -----------------------------------
 
index 7a4dd76..e31788a 100644 (file)
@@ -158,7 +158,10 @@ command.  The plugin script does roughly the following:
         * If XAPI is configured for a manager, configures the OVS
           manager to match with "ovs-vsctl set-manager".
 
-The Open vSwitch boot sequence only configures an OVS configuration
+Notes
+-----
+
+* The Open vSwitch boot sequence only configures an OVS configuration
 database manager.  There is no way to directly configure an OpenFlow
 controller on XenServer and, as a consequence of the step above that
 deletes all of the bridges at boot time, controller configuration only
@@ -166,6 +169,14 @@ persists until XenServer reboot.  The configuration database manager
 can, however, configure controllers for bridges.  See the BUGS section
 of ovs-controller(8) for more information on this topic.
 
+* The Open vSwitch startup script automatically adds a firewall rule
+to allow GRE traffic. This rule is needed for the XenServer feature
+called "Cross-Host Internal Networks" (CHIN) that uses GRE. If a user
+configures tunnels other than GRE (ex: VXLAN, LISP), they will have
+to either manually add a iptables firewall rule to allow the tunnel traffic
+or add it through a startup script (Please refer to the "enable-protocol"
+command in the ovs-ctl(8) manpage).
+
 Reporting Bugs
 --------------
 
index 5dce7aa..b15a9a4 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
 #
 # Copying and distribution of this file, with or without modification,
 # are permitted in any medium without royalty provided the copyright
@@ -260,3 +260,4 @@ include xenserver/automake.mk
 include python/automake.mk
 include python/compat/automake.mk
 include planetlab/automake.mk
+include tutorial/automake.mk
diff --git a/NEWS b/NEWS
index cbbe06b..3a7123b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,11 @@
-post-v1.10.0
+post-v1.11.0
 ---------------------
+
+
+v1.11.0 - xx xxx xxxx
+---------------------
+    - The "tutorial" directory contains a new tutorial for some advanced
+      Open vSwitch features.
     - Stable bond mode has been removed.
     - The autopath action has been removed.
     - New support for the data encapsulation format of the LISP tunnel
@@ -12,9 +18,13 @@ post-v1.10.0
         NXM fields.
     - ovs-dpctl:
       * New debugging commands "add-flow", "mod-flow", "del-flow".
+    - New syslog format, prefixed with "ovs|", to be easier to filter.
+    - RHEL: Removes the default firewall rule that allowed GRE traffic to
+      pass through. Any users that relied on this automatic firewall hole
+      will have to manually configure it. The ovs-ctl(8) manpage documents
+      the "enable-protocol" command that can be used as an alternative.
 
-
-v1.10.0 - xx xxx xxxx
+v1.10.0 - 01 May 2013
 ---------------------
     - Bridge compatibility support has been removed.  Any uses that
       rely on ovs-brcompatd will have to stick with Open vSwitch 1.9.x
@@ -76,6 +86,7 @@ v1.10.0 - xx xxx xxxx
         retire that meaning of ANY in favor of the OpenFlow 1.1 meaning.
     - Patch ports no longer require kernel support, so they now work
       with FreeBSD and the kernel module built into Linux 3.3 and later.
+    - New "sample" action.
 
 
 v1.9.0 - 26 Feb 2013
diff --git a/README b/README
index f6ffa84..a57bb62 100644 (file)
--- a/README
+++ b/README
@@ -103,6 +103,9 @@ For answers to common questions, read FAQ.
 
 To learn how to set up SSL support for Open vSwitch, read INSTALL.SSL.
 
+To learn about some advanced features of the Open vSwitch software
+switch, read the tutorial in tutorial/Tutorial.
+
 Each Open vSwitch userspace program is accompanied by a manpage.  Many
 of the manpages are customized to your configuration as part of the
 build process, so we recommend building Open vSwitch before reading
diff --git a/WHY-OVS b/WHY-OVS
index e8c6f75..f5f47ff 100644 (file)
--- a/WHY-OVS
+++ b/WHY-OVS
@@ -21,7 +21,7 @@ vSwitch cope with the above requirements.
   migratable between different hosts.  This may include traditional
   "soft state" (such as an entry in an L2 learning table), L3 forwarding
   state, policy routing state, ACLs, QoS policy, monitoring
-  configuration (e.g. NetFlow, sFlow), etc.
+  configuration (e.g. NetFlow, IPFIX, sFlow), etc.
 
   Open vSwitch has support for both configuring and migrating both slow
   (configuration) and fast network state between instances.  For
@@ -38,13 +38,14 @@ vSwitch cope with the above requirements.
   environments, and so forth.
 
   Open vSwitch supports a number of features that allow a network
-  control system to respond and adapt as the environment changes.  This
-  includes simple accounting and visibility support such as NetFlow and
-  sFlow.  But perhaps more useful, Open vSwitch supports a network state
-  database (OVSDB) that supports remote triggers.  Therefore, a piece of
-  orchestration software can "watch" various aspects of the network and
-  respond if/when they change.  This is used heavily today, for example,
-  to respond to and track VM migrations.
+  control system to respond and adapt as the environment changes.
+  This includes simple accounting and visibility support such as
+  NetFlow, IPFIX, and sFlow.  But perhaps more useful, Open vSwitch
+  supports a network state database (OVSDB) that supports remote
+  triggers.  Therefore, a piece of orchestration software can "watch"
+  various aspects of the network and respond if/when they change.
+  This is used heavily today, for example, to respond to and track VM
+  migrations.
 
   Open vSwitch also supports OpenFlow as a method of exporting remote
   access to control traffic.  There are a number of uses for this
index 19a47dd..34634a2 100644 (file)
@@ -224,6 +224,8 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
   OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [dev_disable_lro])
   OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [dev_get_stats])
   OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [dev_get_by_index_rcu])
+  OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [__skb_gso_segment])
+  OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [can_checksum_protocol])
 
   OVS_GREP_IFELSE([$KSRC/include/linux/rcupdate.h], [rcu_read_lock_held], [],
                   [OVS_GREP_IFELSE([$KSRC/include/linux/rtnetlink.h],
@@ -268,11 +270,19 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
 
   OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [NLA_NUL_STRING])
   OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_get_be16])
+  OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_put_be16])
+  OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_put_be32])
+  OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_put_be64])
   OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_find_nested])
 
   OVS_GREP_IFELSE([$KSRC/include/linux/if_vlan.h], [ADD_ALL_VLANS_CMD],
                   [OVS_DEFINE([HAVE_VLAN_BUG_WORKAROUND])])
 
+  OVS_GREP_IFELSE([$KSRC/include/linux/percpu.h], [this_cpu_ptr])
+
+  OVS_GREP_IFELSE([$KSRC/include/linux/openvswitch.h], [openvswitch_handle_frame_hook],
+                  [OVS_DEFINE([HAVE_RHEL_OVS_HOOK])])
+
   OVS_CHECK_LOG2_H
 
   if cmp -s datapath/linux/kcompat.h.new \
@@ -478,13 +488,23 @@ AC_DEFUN([OVS_CHECK_SPARSE_TARGET],
    AC_SUBST([SPARSEFLAGS])
    AC_SUBST([CGCCFLAGS])])
 
+dnl OVS_SPARSE_EXTRA_INCLUDES
+dnl
+dnl The cgcc script from "sparse" does not search gcc's default
+dnl search path. Get the default search path from GCC and pass
+dnl them to sparse.
+AC_DEFUN([OVS_SPARSE_EXTRA_INCLUDES],
+    AC_SUBST([SPARSE_EXTRA_INCLUDES],
+           [`$CC -v -E - </dev/null 2>&1 >/dev/null | sed -n -e '/^#include.*search.*starts.*here:/,/^End.*of.*search.*list\./s/^ \(.*\)/-I \1/p' |grep -v /usr/lib | grep -x -v '\-I /usr/include' | tr \\\n ' ' `] ))
+
 dnl OVS_ENABLE_SPARSE
 AC_DEFUN([OVS_ENABLE_SPARSE],
   [AC_REQUIRE([OVS_CHECK_SPARSE_TARGET])
    AC_REQUIRE([OVS_CHECK_MAKE_IF])
+   AC_REQUIRE([OVS_SPARSE_EXTRA_INCLUDES])
    : ${SPARSE=sparse}
    AC_SUBST([SPARSE])
    AC_CONFIG_COMMANDS_PRE(
      [if test $ovs_cv_gnu_make_if = yes; then
-        CC='$(if $(C),REAL_CC="'"$CC"'" CHECK="$(SPARSE) -I $(top_srcdir)/include/sparse $(SPARSEFLAGS)" cgcc $(CGCCFLAGS),'"$CC"')'
+        CC='$(if $(C),REAL_CC="'"$CC"'" CHECK="$(SPARSE) -I $(top_srcdir)/include/sparse $(SPARSEFLAGS) $(SPARSE_EXTRA_INCLUDES) " cgcc $(CGCCFLAGS),'"$CC"')'
       fi])])
index 79fb46e..bbb6dea 100644 (file)
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 AC_PREREQ(2.64)
-AC_INIT(openvswitch, 1.10.90, ovs-bugs@openvswitch.org)
+AC_INIT(openvswitch, 1.11.90, ovs-bugs@openvswitch.org)
 AC_CONFIG_SRCDIR([datapath/datapath.c])
 AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_AUX_DIR([build-aux])
@@ -60,8 +60,8 @@ OVS_CHECK_IF_DL
 OVS_CHECK_STRTOK_R
 AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec, struct stat.st_mtimensec],
   [], [], [[#include <sys/stat.h>]])
-AC_CHECK_FUNCS([mlockall strnlen strsignal getloadavg statvfs setmntent])
-AC_CHECK_HEADERS([mntent.h sys/statvfs.h linux/types.h linux/if_ether.h execinfo.h])
+AC_CHECK_FUNCS([mlockall strnlen strsignal getloadavg statvfs getmntent_r])
+AC_CHECK_HEADERS([mntent.h sys/statvfs.h linux/types.h linux/if_ether.h])
 
 OVS_CHECK_PKIDIR
 OVS_CHECK_RUNDIR
index 9941123..2ce8888 100644 (file)
@@ -12,7 +12,6 @@ openvswitch_sources = \
        datapath.c \
        dp_notify.c \
        flow.c \
-       genl_exec.c \
        tunnel.c \
        vlan.c \
        vport.c \
@@ -27,7 +26,6 @@ openvswitch_headers = \
        compat.h \
        datapath.h \
        flow.h \
-       genl_exec.h \
        tunnel.h \
        vlan.h \
        vport.h \
index 9cd4b0e..42af315 100644 (file)
@@ -48,6 +48,8 @@
 #include <linux/openvswitch.h>
 #include <linux/rculist.h>
 #include <linux/dmi.h>
+#include <linux/genetlink.h>
+#include <net/genetlink.h>
 #include <net/genetlink.h>
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 #include "checksum.h"
 #include "datapath.h"
 #include "flow.h"
-#include "genl_exec.h"
 #include "vlan.h"
 #include "tunnel.h"
 #include "vport-internal_dev.h"
+#include "vport-netdev.h"
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) || \
     LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)
@@ -81,20 +83,42 @@ static void ovs_notify(struct sk_buff *skb, struct genl_info *info,
 /**
  * DOC: Locking:
  *
- * Writes to device state (add/remove datapath, port, set operations on vports,
- * etc.) are protected by RTNL.
- *
- * Writes to other state (flow table modifications, set miscellaneous datapath
- * parameters, etc.) are protected by genl_mutex.  The RTNL lock nests inside
- * genl_mutex.
+ * All writes e.g. Writes to device state (add/remove datapath, port, set
+ * operations on vports, etc.), Writes to other state (flow table
+ * modifications, set miscellaneous datapath parameters, etc.) are protected
+ * by ovs_lock.
  *
  * Reads are protected by RCU.
  *
  * There are a few special cases (mostly stats) that have their own
  * synchronization but they nest under all of above and don't interact with
  * each other.
+ *
+ * The RTNL lock nests inside ovs_mutex.
  */
 
+static DEFINE_MUTEX(ovs_mutex);
+
+void ovs_lock(void)
+{
+       mutex_lock(&ovs_mutex);
+}
+
+void ovs_unlock(void)
+{
+       mutex_unlock(&ovs_mutex);
+}
+
+#ifdef CONFIG_LOCKDEP
+int lockdep_ovsl_is_held(void)
+{
+       if (debug_locks)
+               return lockdep_is_held(&ovs_mutex);
+       else
+               return 1;
+}
+#endif
+
 static struct vport *new_vport(const struct vport_parms *);
 static int queue_gso_packets(struct net *, int dp_ifindex, struct sk_buff *,
                             const struct dp_upcall_info *);
@@ -102,7 +126,7 @@ static int queue_userspace_packet(struct net *, int dp_ifindex,
                                  struct sk_buff *,
                                  const struct dp_upcall_info *);
 
-/* Must be called with rcu_read_lock, genl_mutex, or RTNL lock. */
+/* Must be called with rcu_read_lock or ovs_mutex. */
 static struct datapath *get_dp(struct net *net, int dp_ifindex)
 {
        struct datapath *dp = NULL;
@@ -120,10 +144,10 @@ static struct datapath *get_dp(struct net *net, int dp_ifindex)
        return dp;
 }
 
-/* Must be called with rcu_read_lock or RTNL lock. */
+/* Must be called with rcu_read_lock or ovs_mutex. */
 const char *ovs_dp_name(const struct datapath *dp)
 {
-       struct vport *vport = ovs_vport_rtnl_rcu(dp, OVSP_LOCAL);
+       struct vport *vport = ovs_vport_ovsl_rcu(dp, OVSP_LOCAL);
        return vport->ops->get_name(vport);
 }
 
@@ -136,7 +160,7 @@ static int get_dpifindex(struct datapath *dp)
 
        local = ovs_vport_rcu(dp, OVSP_LOCAL);
        if (local)
-               ifindex = local->ops->get_ifindex(local);
+               ifindex = netdev_vport_priv(local)->dev->ifindex;
        else
                ifindex = 0;
 
@@ -175,7 +199,7 @@ struct vport *ovs_lookup_vport(const struct datapath *dp, u16 port_no)
        return NULL;
 }
 
-/* Called with RTNL lock and genl_lock. */
+/* Called with ovs_mutex. */
 static struct vport *new_vport(const struct vport_parms *parms)
 {
        struct vport *vport;
@@ -190,10 +214,9 @@ static struct vport *new_vport(const struct vport_parms *parms)
        return vport;
 }
 
-/* Called with RTNL lock. */
 void ovs_dp_detach_port(struct vport *p)
 {
-       ASSERT_RTNL();
+       ASSERT_OVSL();
 
        /* First drop references to device. */
        hlist_del_rcu(&p->dp_hash_node);
@@ -440,13 +463,13 @@ out:
        return err;
 }
 
-/* Called with genl_mutex. */
+/* Called with ovs_mutex. */
 static int flush_flows(struct datapath *dp)
 {
        struct flow_table *old_table;
        struct flow_table *new_table;
 
-       old_table = genl_dereference(dp->table);
+       old_table = ovsl_dereference(dp->table);
        new_table = ovs_flow_tbl_alloc(TBL_MIN_BUCKETS);
        if (!new_table)
                return -ENOMEM;
@@ -947,7 +970,7 @@ static struct genl_ops dp_packet_genl_ops[] = {
 static void get_dp_stats(struct datapath *dp, struct ovs_dp_stats *stats)
 {
        int i;
-       struct flow_table *table = genl_dereference(dp->table);
+       struct flow_table *table = ovsl_dereference(dp->table);
 
        stats->n_flows = ovs_flow_tbl_count(table);
 
@@ -1092,7 +1115,7 @@ static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts)
                + nla_total_size(acts->actions_len); /* OVS_FLOW_ATTR_ACTIONS */
 }
 
-/* Called with genl_lock. */
+/* Called with ovs_mutex. */
 static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
                                  struct sk_buff *skb, u32 portid,
                                  u32 seq, u32 flags, u8 cmd)
@@ -1107,8 +1130,7 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
        u8 tcp_flags;
        int err;
 
-       sf_acts = rcu_dereference_protected(flow->sf_acts,
-                                           lockdep_genl_is_held());
+       sf_acts = ovsl_dereference(flow->sf_acts);
 
        ovs_header = genlmsg_put(skb, portid, seq, &dp_flow_genl_family, flags, cmd);
        if (!ovs_header)
@@ -1181,8 +1203,7 @@ static struct sk_buff *ovs_flow_cmd_alloc_info(struct sw_flow *flow)
 {
        const struct sw_flow_actions *sf_acts;
 
-       sf_acts = rcu_dereference_protected(flow->sf_acts,
-                                           lockdep_genl_is_held());
+       sf_acts = ovsl_dereference(flow->sf_acts);
 
        return genlmsg_new(ovs_flow_cmd_msg_size(sf_acts), GFP_KERNEL);
 }
@@ -1239,18 +1260,19 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
                goto error;
        }
 
+       ovs_lock();
        dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
        error = -ENODEV;
        if (!dp)
-               goto err_kfree;
+               goto err_unlock_ovs;
 
-       table = genl_dereference(dp->table);
+       table = ovsl_dereference(dp->table);
        flow = ovs_flow_tbl_lookup(table, &key, key_len);
        if (!flow) {
                /* Bail out if we're not allowed to create a new flow. */
                error = -ENOENT;
                if (info->genlhdr->cmd == OVS_FLOW_CMD_SET)
-                       goto err_kfree;
+                       goto err_unlock_ovs;
 
                /* Expand table, if necessary, to make room. */
                if (ovs_flow_tbl_need_to_expand(table)) {
@@ -1260,7 +1282,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
                        if (!IS_ERR(new_table)) {
                                rcu_assign_pointer(dp->table, new_table);
                                ovs_flow_tbl_deferred_destroy(table);
-                               table = genl_dereference(dp->table);
+                               table = ovsl_dereference(dp->table);
                        }
                }
 
@@ -1268,7 +1290,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
                flow = ovs_flow_alloc();
                if (IS_ERR(flow)) {
                        error = PTR_ERR(flow);
-                       goto err_kfree;
+                       goto err_unlock_ovs;
                }
                clear_stats(flow);
 
@@ -1293,11 +1315,10 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
                error = -EEXIST;
                if (info->genlhdr->cmd == OVS_FLOW_CMD_NEW &&
                    info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL))
-                       goto err_kfree;
+                       goto err_unlock_ovs;
 
                /* Update actions. */
-               old_acts = rcu_dereference_protected(flow->sf_acts,
-                                                    lockdep_genl_is_held());
+               old_acts = ovsl_dereference(flow->sf_acts);
                rcu_assign_pointer(flow->sf_acts, acts);
                ovs_flow_deferred_free_acts(old_acts);
 
@@ -1311,6 +1332,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
                        spin_unlock_bh(&flow->lock);
                }
        }
+       ovs_unlock();
 
        if (!IS_ERR(reply))
                ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
@@ -1319,6 +1341,8 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
                                ovs_dp_flow_multicast_group.id, PTR_ERR(reply));
        return 0;
 
+err_unlock_ovs:
+       ovs_unlock();
 err_kfree:
        kfree(acts);
 error:
@@ -1343,21 +1367,32 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
        if (err)
                return err;
 
+       ovs_lock();
        dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
-       if (!dp)
-               return -ENODEV;
+       if (!dp) {
+               err = -ENODEV;
+               goto unlock;
+       }
 
-       table = genl_dereference(dp->table);
+       table = ovsl_dereference(dp->table);
        flow = ovs_flow_tbl_lookup(table, &key, key_len);
-       if (!flow)
-               return -ENOENT;
+       if (!flow) {
+               err = -ENOENT;
+               goto unlock;
+       }
 
        reply = ovs_flow_cmd_build_info(flow, dp, info->snd_portid,
                                        info->snd_seq, OVS_FLOW_CMD_NEW);
-       if (IS_ERR(reply))
-               return PTR_ERR(reply);
+       if (IS_ERR(reply)) {
+               err = PTR_ERR(reply);
+               goto unlock;
+       }
 
+       ovs_unlock();
        return genlmsg_reply(reply, info);
+unlock:
+       ovs_unlock();
+       return err;
 }
 
 static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
@@ -1372,25 +1407,33 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
        int err;
        int key_len;
 
+       ovs_lock();
        dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
-       if (!dp)
-               return -ENODEV;
-
-       if (!a[OVS_FLOW_ATTR_KEY])
-               return flush_flows(dp);
+       if (!dp) {
+               err = -ENODEV;
+               goto unlock;
+       }
 
+       if (!a[OVS_FLOW_ATTR_KEY]) {
+               err = flush_flows(dp);
+               goto unlock;
+       }
        err = ovs_flow_from_nlattrs(&key, &key_len, a[OVS_FLOW_ATTR_KEY]);
        if (err)
-               return err;
+               goto unlock;
 
-       table = genl_dereference(dp->table);
+       table = ovsl_dereference(dp->table);
        flow = ovs_flow_tbl_lookup(table, &key, key_len);
-       if (!flow)
-               return -ENOENT;
+       if (!flow) {
+               err = -ENOENT;
+               goto unlock;
+       }
 
        reply = ovs_flow_cmd_alloc_info(flow);
-       if (!reply)
-               return -ENOMEM;
+       if (!reply) {
+               err = -ENOMEM;
+               goto unlock;
+       }
 
        ovs_flow_tbl_remove(table, flow);
 
@@ -1399,9 +1442,13 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
        BUG_ON(err < 0);
 
        ovs_flow_deferred_free(flow);
+       ovs_unlock();
 
        ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
        return 0;
+unlock:
+       ovs_unlock();
+       return err;
 }
 
 static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
@@ -1410,11 +1457,14 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
        struct datapath *dp;
        struct flow_table *table;
 
+       ovs_lock();
        dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
-       if (!dp)
+       if (!dp) {
+               ovs_unlock();
                return -ENODEV;
+       }
 
-       table = genl_dereference(dp->table);
+       table = ovsl_dereference(dp->table);
 
        for (;;) {
                struct sw_flow *flow;
@@ -1435,6 +1485,7 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
                cb->args[0] = bucket;
                cb->args[1] = obj;
        }
+       ovs_unlock();
        return skb->len;
 }
 
@@ -1547,7 +1598,7 @@ static int ovs_dp_cmd_validate(struct nlattr *a[OVS_DP_ATTR_MAX + 1])
        return CHECK_NUL_STRING(a[OVS_DP_ATTR_NAME], IFNAMSIZ - 1);
 }
 
-/* Called with genl_mutex and optionally with RTNL lock also. */
+/* Called with ovs_mutex. */
 static struct datapath *lookup_datapath(struct net *net,
                                        struct ovs_header *ovs_header,
                                        struct nlattr *a[OVS_DP_ATTR_MAX + 1])
@@ -1585,12 +1636,12 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
        if (err)
                goto err;
 
-       rtnl_lock();
+       ovs_lock();
 
        err = -ENOMEM;
        dp = kzalloc(sizeof(*dp), GFP_KERNEL);
        if (dp == NULL)
-               goto err_unlock_rtnl;
+               goto err_unlock_ovs;
 
        ovs_dp_set_net(dp, hold_net(sock_net(skb->sk)));
 
@@ -1642,35 +1693,33 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
        ovs_net = net_generic(ovs_dp_get_net(dp), ovs_net_id);
        list_add_tail(&dp->list_node, &ovs_net->dps);
 
-       rtnl_unlock();
+       ovs_unlock();
 
        ovs_notify(reply, info, &ovs_dp_datapath_multicast_group);
        return 0;
 
 err_destroy_local_port:
-       ovs_dp_detach_port(ovs_vport_rtnl(dp, OVSP_LOCAL));
+       ovs_dp_detach_port(ovs_vport_ovsl(dp, OVSP_LOCAL));
 err_destroy_ports_array:
        kfree(dp->ports);
 err_destroy_percpu:
        free_percpu(dp->stats_percpu);
 err_destroy_table:
-       ovs_flow_tbl_destroy(genl_dereference(dp->table));
+       ovs_flow_tbl_destroy(ovsl_dereference(dp->table));
 err_free_dp:
        release_net(ovs_dp_get_net(dp));
        kfree(dp);
-err_unlock_rtnl:
-       rtnl_unlock();
+err_unlock_ovs:
+       ovs_unlock();
 err:
        return err;
 }
 
-/* Called with genl_mutex. */
+/* Called with ovs_mutex. */
 static void __dp_destroy(struct datapath *dp)
 {
        int i;
 
-       rtnl_lock();
-
        for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) {
                struct vport *vport;
                struct hlist_node *n;
@@ -1681,14 +1730,11 @@ static void __dp_destroy(struct datapath *dp)
        }
 
        list_del(&dp->list_node);
-       ovs_dp_detach_port(ovs_vport_rtnl(dp, OVSP_LOCAL));
 
-       /* rtnl_unlock() will wait until all the references to devices that
-        * are pending unregistration have been dropped.  We do it here to
-        * ensure that any internal devices (which contain DP pointers) are
-        * fully destroyed before freeing the datapath.
-        */
-       rtnl_unlock();
+       /* OVSP_LOCAL is datapath internal port. We need to make sure that
+        * all port in datapath are destroyed first before freeing datapath.
+        */
+       ovs_dp_detach_port(ovs_vport_ovsl(dp, OVSP_LOCAL));
 
        call_rcu(&dp->rcu, destroy_dp_rcu);
 }
@@ -1703,22 +1749,27 @@ static int ovs_dp_cmd_del(struct sk_buff *skb, struct genl_info *info)
        if (err)
                return err;
 
+       ovs_lock();
        dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
        err = PTR_ERR(dp);
        if (IS_ERR(dp))
-               return err;
+               goto unlock;
 
        reply = ovs_dp_cmd_build_info(dp, info->snd_portid,
                                      info->snd_seq, OVS_DP_CMD_DEL);
        err = PTR_ERR(reply);
        if (IS_ERR(reply))
-               return err;
+               goto unlock;
 
        __dp_destroy(dp);
+       ovs_unlock();
 
        ovs_notify(reply, info, &ovs_dp_datapath_multicast_group);
 
        return 0;
+unlock:
+       ovs_unlock();
+       return err;
 }
 
 static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info)
@@ -1731,9 +1782,11 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info)
        if (err)
                return err;
 
+       ovs_lock();
        dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
+       err = PTR_ERR(dp);
        if (IS_ERR(dp))
-               return PTR_ERR(dp);
+               goto unlock;
 
        reply = ovs_dp_cmd_build_info(dp, info->snd_portid,
                                      info->snd_seq, OVS_DP_CMD_NEW);
@@ -1741,12 +1794,17 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info)
                err = PTR_ERR(reply);
                netlink_set_err(GENL_SOCK(sock_net(skb->sk)), 0,
                                ovs_dp_datapath_multicast_group.id, err);
-               return 0;
+               err = 0;
+               goto unlock;
        }
 
+       ovs_unlock();
        ovs_notify(reply, info, &ovs_dp_datapath_multicast_group);
 
        return 0;
+unlock:
+       ovs_unlock();
+       return err;
 }
 
 static int ovs_dp_cmd_get(struct sk_buff *skb, struct genl_info *info)
@@ -1759,16 +1817,26 @@ static int ovs_dp_cmd_get(struct sk_buff *skb, struct genl_info *info)
        if (err)
                return err;
 
+       ovs_lock();
        dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
-       if (IS_ERR(dp))
-               return PTR_ERR(dp);
+       if (IS_ERR(dp)) {
+               err = PTR_ERR(dp);
+               goto unlock;
+       }
 
        reply = ovs_dp_cmd_build_info(dp, info->snd_portid,
                                      info->snd_seq, OVS_DP_CMD_NEW);
-       if (IS_ERR(reply))
-               return PTR_ERR(reply);
+       if (IS_ERR(reply)) {
+               err = PTR_ERR(reply);
+               goto unlock;
+       }
 
+       ovs_unlock();
        return genlmsg_reply(reply, info);
+
+unlock:
+       ovs_unlock();
+       return err;
 }
 
 static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
@@ -1778,6 +1846,7 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
        int skip = cb->args[0];
        int i = 0;
 
+       ovs_lock();
        list_for_each_entry(dp, &ovs_net->dps, list_node) {
                if (i >= skip &&
                    ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB(cb->skb).portid,
@@ -1786,6 +1855,7 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
                        break;
                i++;
        }
+       ovs_unlock();
 
        cb->args[0] = i;
 
@@ -1842,7 +1912,7 @@ struct genl_multicast_group ovs_dp_vport_multicast_group = {
        .name = OVS_VPORT_MCGROUP
 };
 
-/* Called with RTNL lock or RCU read lock. */
+/* Called with ovs_mutex or RCU read lock. */
 static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
                                   u32 portid, u32 seq, u32 flags, u8 cmd)
 {
@@ -1881,7 +1951,7 @@ error:
        return err;
 }
 
-/* Called with RTNL lock or RCU read lock. */
+/* Called with ovs_mutex or RCU read lock. */
 struct sk_buff *ovs_vport_cmd_build_info(struct vport *vport, u32 portid,
                                         u32 seq, u8 cmd)
 {
@@ -1903,7 +1973,7 @@ static int ovs_vport_cmd_validate(struct nlattr *a[OVS_VPORT_ATTR_MAX + 1])
        return CHECK_NUL_STRING(a[OVS_VPORT_ATTR_NAME], IFNAMSIZ - 1);
 }
 
-/* Called with RTNL lock or RCU read lock. */
+/* Called with ovs_mutex or RCU read lock. */
 static struct vport *lookup_vport(struct net *net,
                                  struct ovs_header *ovs_header,
                                  struct nlattr *a[OVS_VPORT_ATTR_MAX + 1])
@@ -1929,7 +1999,7 @@ static struct vport *lookup_vport(struct net *net,
                if (!dp)
                        return ERR_PTR(-ENODEV);
 
-               vport = ovs_vport_rtnl_rcu(dp, port_no);
+               vport = ovs_vport_ovsl_rcu(dp, port_no);
                if (!vport)
                        return ERR_PTR(-ENODEV);
                return vport;
@@ -1957,7 +2027,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
        if (err)
                goto exit;
 
-       rtnl_lock();
+       ovs_lock();
        dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
        err = -ENODEV;
        if (!dp)
@@ -1970,7 +2040,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
                if (port_no >= DP_MAX_PORTS)
                        goto exit_unlock;
 
-               vport = ovs_vport_rtnl(dp, port_no);
+               vport = ovs_vport_ovsl(dp, port_no);
                err = -EBUSY;
                if (vport)
                        goto exit_unlock;
@@ -1980,7 +2050,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
                                err = -EFBIG;
                                goto exit_unlock;
                        }
-                       vport = ovs_vport_rtnl(dp, port_no);
+                       vport = ovs_vport_ovsl(dp, port_no);
                        if (!vport)
                                break;
                }
@@ -2013,7 +2083,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
        ovs_notify(reply, info, &ovs_dp_vport_multicast_group);
 
 exit_unlock:
-       rtnl_unlock();
+       ovs_unlock();
 exit:
        return err;
 }
@@ -2029,16 +2099,17 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
        if (err)
                goto exit;
 
-       rtnl_lock();
+       ovs_lock();
        vport = lookup_vport(sock_net(skb->sk), info->userhdr, a);
        err = PTR_ERR(vport);
        if (IS_ERR(vport))
                goto exit_unlock;
 
-       err = 0;
        if (a[OVS_VPORT_ATTR_TYPE] &&
-           nla_get_u32(a[OVS_VPORT_ATTR_TYPE]) != vport->ops->type)
+           nla_get_u32(a[OVS_VPORT_ATTR_TYPE]) != vport->ops->type) {
                err = -EINVAL;
+               goto exit_unlock;
+       }
 
        reply = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
        if (!reply) {
@@ -2046,10 +2117,11 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
                goto exit_unlock;
        }
 
-       if (!err && a[OVS_VPORT_ATTR_OPTIONS])
+       if (a[OVS_VPORT_ATTR_OPTIONS]) {
                err = ovs_vport_set_options(vport, a[OVS_VPORT_ATTR_OPTIONS]);
-       if (err)
-               goto exit_free;
+               if (err)
+                       goto exit_free;
+       }
 
        if (a[OVS_VPORT_ATTR_STATS])
                ovs_vport_set_stats(vport, nla_data(a[OVS_VPORT_ATTR_STATS]));
@@ -2061,15 +2133,14 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
                                      info->snd_seq, 0, OVS_VPORT_CMD_NEW);
        BUG_ON(err < 0);
 
+       ovs_unlock();
        ovs_notify(reply, info, &ovs_dp_vport_multicast_group);
-
-       rtnl_unlock();
        return 0;
 
 exit_free:
        kfree_skb(reply);
 exit_unlock:
-       rtnl_unlock();
+       ovs_unlock();
 exit:
        return err;
 }
@@ -2085,7 +2156,7 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
        if (err)
                goto exit;
 
-       rtnl_lock();
+       ovs_lock();
        vport = lookup_vport(sock_net(skb->sk), info->userhdr, a);
        err = PTR_ERR(vport);
        if (IS_ERR(vport))
@@ -2108,7 +2179,7 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
        ovs_notify(reply, info, &ovs_dp_vport_multicast_group);
 
 exit_unlock:
-       rtnl_unlock();
+       ovs_unlock();
 exit:
        return err;
 }
@@ -2269,17 +2340,18 @@ error:
        return err;
 }
 
-static int __rehash_flow_table(void *dummy)
+static void rehash_flow_table(struct work_struct *work)
 {
        struct datapath *dp;
        struct net *net;
 
+       ovs_lock();
        rtnl_lock();
        for_each_net(net) {
                struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
 
                list_for_each_entry(dp, &ovs_net->dps, list_node) {
-                       struct flow_table *old_table = genl_dereference(dp->table);
+                       struct flow_table *old_table = ovsl_dereference(dp->table);
                        struct flow_table *new_table;
 
                        new_table = ovs_flow_tbl_rehash(old_table);
@@ -2290,39 +2362,30 @@ static int __rehash_flow_table(void *dummy)
                }
        }
        rtnl_unlock();
-       return 0;
-}
-
-static void rehash_flow_table(struct work_struct *work)
-{
-       genl_exec(__rehash_flow_table, NULL);
+       ovs_unlock();
        schedule_delayed_work(&rehash_flow_wq, REHASH_FLOW_INTERVAL);
 }
 
-static int dp_destroy_all(void *data)
-{
-       struct datapath *dp, *dp_next;
-       struct ovs_net *ovs_net = data;
-
-       list_for_each_entry_safe(dp, dp_next, &ovs_net->dps, list_node)
-               __dp_destroy(dp);
-
-       return 0;
-}
-
 static int __net_init ovs_init_net(struct net *net)
 {
        struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
 
        INIT_LIST_HEAD(&ovs_net->dps);
+       INIT_WORK(&ovs_net->dp_notify_work, ovs_dp_notify_wq);
        return 0;
 }
 
 static void __net_exit ovs_exit_net(struct net *net)
 {
+       struct datapath *dp, *dp_next;
        struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
 
-       genl_exec(dp_destroy_all, ovs_net);
+       ovs_lock();
+       list_for_each_entry_safe(dp, dp_next, &ovs_net->dps, list_node)
+               __dp_destroy(dp);
+       ovs_unlock();
+
+       cancel_work_sync(&ovs_net->dp_notify_work);
 }
 
 static struct pernet_operations ovs_net_ops = {
@@ -2341,13 +2404,9 @@ static int __init dp_init(void)
        pr_info("Open vSwitch switching datapath %s, built "__DATE__" "__TIME__"\n",
                VERSION);
 
-       err = genl_exec_init();
-       if (err)
-               goto error;
-
        err = ovs_workqueues_init();
        if (err)
-               goto error_genl_exec;
+               goto error;
 
        err = ovs_flow_init();
        if (err)
@@ -2383,8 +2442,6 @@ error_flow_exit:
        ovs_flow_exit();
 error_wq:
        ovs_workqueues_exit();
-error_genl_exec:
-       genl_exec_exit();
 error:
        return err;
 }
@@ -2399,7 +2456,6 @@ static void dp_cleanup(void)
        ovs_vport_exit();
        ovs_flow_exit();
        ovs_workqueues_exit();
-       genl_exec_exit();
 }
 
 module_init(dp_init);
index 9bc98fb..ad59a3a 100644 (file)
@@ -61,10 +61,9 @@ struct dp_stats_percpu {
  * struct datapath - datapath for flow-based packet switching
  * @rcu: RCU callback head for deferred destruction.
  * @list_node: Element in global 'dps' list.
- * @n_flows: Number of flows currently in flow table.
- * @table: Current flow table.  Protected by genl_lock and RCU.
+ * @table: Current flow table.  Protected by ovs_mutex and RCU.
  * @ports: Hash table for ports.  %OVSP_LOCAL port always exists.  Protected by
- * RTNL and RCU.
+ * ovs_mutex and RCU.
  * @stats_percpu: Per-CPU datapath statistics.
  * @net: Reference to net namespace.
  *
@@ -142,9 +141,22 @@ struct dp_upcall_info {
 struct ovs_net {
        struct list_head dps;
        struct vport_net vport_net;
+       struct work_struct dp_notify_work;
 };
 
 extern int ovs_net_id;
+void ovs_lock(void);
+void ovs_unlock(void);
+
+#ifdef CONFIG_LOCKDEP
+int lockdep_ovsl_is_held(void);
+#else
+#define lockdep_ovsl_is_held() 1
+#endif
+
+#define ASSERT_OVSL()          WARN_ON(unlikely(!lockdep_ovsl_is_held()))
+#define ovsl_dereference(p)                                    \
+       rcu_dereference_protected(p, lockdep_ovsl_is_held())
 
 static inline struct net *ovs_dp_get_net(struct datapath *dp)
 {
@@ -164,15 +176,15 @@ static inline struct vport *ovs_vport_rcu(const struct datapath *dp, int port_no
        return ovs_lookup_vport(dp, port_no);
 }
 
-static inline struct vport *ovs_vport_rtnl_rcu(const struct datapath *dp, int port_no)
+static inline struct vport *ovs_vport_ovsl_rcu(const struct datapath *dp, int port_no)
 {
-       WARN_ON_ONCE(!rcu_read_lock_held() && !rtnl_is_locked());
+       WARN_ON_ONCE(!rcu_read_lock_held() && !lockdep_ovsl_is_held());
        return ovs_lookup_vport(dp, port_no);
 }
 
-static inline struct vport *ovs_vport_rtnl(const struct datapath *dp, int port_no)
+static inline struct vport *ovs_vport_ovsl(const struct datapath *dp, int port_no)
 {
-       ASSERT_RTNL();
+       ASSERT_OVSL();
        return ovs_lookup_vport(dp, port_no);
 }
 
@@ -189,4 +201,5 @@ struct sk_buff *ovs_vport_cmd_build_info(struct vport *, u32 portid, u32 seq,
                                         u8 cmd);
 
 int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb);
+void ovs_dp_notify_wq(struct work_struct *work);
 #endif /* datapath.h */
index c9eeafe..ec573a5 100644 (file)
 #include "vport-internal_dev.h"
 #include "vport-netdev.h"
 
+static void dp_detach_port_notify(struct vport *vport)
+{
+       struct sk_buff *notify;
+       struct datapath *dp;
+
+       dp = vport->dp;
+       notify = ovs_vport_cmd_build_info(vport, 0, 0,
+                                         OVS_VPORT_CMD_DEL);
+       ovs_dp_detach_port(vport);
+       if (IS_ERR(notify)) {
+               netlink_set_err(GENL_SOCK(ovs_dp_get_net(dp)), 0,
+                               ovs_dp_vport_multicast_group.id,
+                               PTR_ERR(notify));
+               return;
+       }
+
+       genlmsg_multicast_netns(ovs_dp_get_net(dp), notify, 0,
+                               ovs_dp_vport_multicast_group.id,
+                               GFP_KERNEL);
+}
+
+void ovs_dp_notify_wq(struct work_struct *work)
+{
+       struct ovs_net *ovs_net = container_of(work, struct ovs_net, dp_notify_work);
+       struct datapath *dp;
+
+       ovs_lock();
+       list_for_each_entry(dp, &ovs_net->dps, list_node) {
+               int i;
+
+               for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) {
+                       struct vport *vport;
+                       struct hlist_node *n;
+
+                       hlist_for_each_entry_safe(vport, n, &dp->ports[i], dp_hash_node) {
+                               struct netdev_vport *netdev_vport;
+
+                               if (vport->ops->type != OVS_VPORT_TYPE_NETDEV)
+                                       continue;
+
+                               netdev_vport = netdev_vport_priv(vport);
+                               if (netdev_vport->dev->reg_state == NETREG_UNREGISTERED ||
+                                   netdev_vport->dev->reg_state == NETREG_UNREGISTERING)
+                                       dp_detach_port_notify(vport);
+                       }
+               }
+       }
+       ovs_unlock();
+}
+
 static int dp_device_event(struct notifier_block *unused, unsigned long event,
                           void *ptr)
 {
+       struct ovs_net *ovs_net;
        struct net_device *dev = ptr;
-       struct vport *vport;
+       struct vport *vport = NULL;
 
-       if (ovs_is_internal_dev(dev))
-               vport = ovs_internal_dev_get_vport(dev);
-       else
+       if (!ovs_is_internal_dev(dev))
                vport = ovs_netdev_get_vport(dev);
 
        if (!vport)
                return NOTIFY_DONE;
 
-       switch (event) {
-       case NETDEV_UNREGISTER:
-               if (!ovs_is_internal_dev(dev)) {
-                       struct sk_buff *notify;
-                       struct datapath *dp = vport->dp;
-
-                       notify = ovs_vport_cmd_build_info(vport, 0, 0,
-                                                         OVS_VPORT_CMD_DEL);
-                       ovs_dp_detach_port(vport);
-                       if (IS_ERR(notify)) {
-                               netlink_set_err(GENL_SOCK(ovs_dp_get_net(dp)), 0,
-                                               ovs_dp_vport_multicast_group.id,
-                                               PTR_ERR(notify));
-                               break;
-                       }
-
-                       genlmsg_multicast_netns(ovs_dp_get_net(dp), notify, 0,
-                                               ovs_dp_vport_multicast_group.id,
-                                               GFP_KERNEL);
-               }
-               break;
-
+       if (event == NETDEV_UNREGISTER) {
+               ovs_net = net_generic(dev_net(dev), ovs_net_id);
+               queue_work(&ovs_net->dp_notify_work);
        }
 
        return NOTIFY_DONE;
index 841e8be..3ce926e 100644 (file)
@@ -1265,9 +1265,9 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
 
 /**
  * ovs_flow_metadata_from_nlattrs - parses Netlink attributes into a flow key.
- * @in_port: receives the extracted input port.
- * @tun_id: receives the extracted tunnel ID.
- * @key: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
+ * @flow: Receives extracted in_port, priority, tun_key and skb_mark.
+ * @key_len: Length of key in @flow.  Used for calculating flow hash.
+ * @attr: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
  * sequence.
  *
  * This parses a series of Netlink attributes that form a flow key, which must
diff --git a/datapath/genl_exec.c b/datapath/genl_exec.c
deleted file mode 100644 (file)
index ba8dfc0..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (c) 2007-2012 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 <linux/version.h>
-#include <linux/completion.h>
-#include <net/genetlink.h>
-#include "genl_exec.h"
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
-
-static DEFINE_MUTEX(genl_exec_lock);
-
-static genl_exec_func_t         genl_exec_function;
-static int              genl_exec_function_ret;
-static void            *genl_exec_data;
-static struct completion done;
-
-static struct sk_buff *genlmsg_skb;
-
-static int genl_exec_cmd(struct sk_buff *dummy, struct genl_info *dummy2)
-{
-       genl_exec_function_ret = genl_exec_function(genl_exec_data);
-       complete(&done);
-       return 0;
-}
-
-enum exec_cmd {
-       GENL_EXEC_UNSPEC,
-       GENL_EXEC_RUN,
-};
-
-static struct genl_family genl_exec_family = {
-       .id = GENL_ID_GENERATE,
-       .name = "ovs_genl_exec",
-       .version = 1,
-};
-
-static struct genl_ops genl_exec_ops[] = {
-       {
-        .cmd = GENL_EXEC_RUN,
-        .doit = genl_exec_cmd,
-        .flags = CAP_NET_ADMIN,
-       },
-};
-
-int genl_exec_init(void)
-{
-       int err;
-
-       err = genl_register_family_with_ops(&genl_exec_family,
-                       genl_exec_ops, ARRAY_SIZE(genl_exec_ops));
-
-       if (err)
-               return err;
-
-       genlmsg_skb = genlmsg_new(0, GFP_KERNEL);
-       if (!genlmsg_skb) {
-               genl_unregister_family(&genl_exec_family);
-               return -ENOMEM;
-       }
-       return 0;
-}
-
-void genl_exec_exit(void)
-{
-       kfree_skb(genlmsg_skb);
-       genl_unregister_family(&genl_exec_family);
-}
-
-/* genl_lock() is not exported from older kernel.
- * Following function allows any function to be executed with
- * genl_mutex held. */
-
-int genl_exec(genl_exec_func_t func, void *data)
-{
-       int ret;
-
-       mutex_lock(&genl_exec_lock);
-
-       init_completion(&done);
-       skb_get(genlmsg_skb);
-       genlmsg_put(genlmsg_skb, 0, 0, &genl_exec_family,
-                   NLM_F_REQUEST, GENL_EXEC_RUN);
-
-       genl_exec_function = func;
-       genl_exec_data = data;
-
-       /* There is no need to send msg to current namespace. */
-       ret = genlmsg_unicast(&init_net, genlmsg_skb, 0);
-
-       if (!ret) {
-               wait_for_completion(&done);
-               ret = genl_exec_function_ret;
-       } else {
-               pr_err("genl_exec send error %d\n", ret);
-       }
-
-       /* Wait for genetlink to kfree skb. */
-       while (skb_shared(genlmsg_skb))
-               cpu_relax();
-
-       genlmsg_skb->data = genlmsg_skb->head;
-       skb_reset_tail_pointer(genlmsg_skb);
-
-       mutex_unlock(&genl_exec_lock);
-
-       return ret;
-}
-
-#else
-
-int genl_exec(genl_exec_func_t func, void *data)
-{
-       int ret;
-
-       genl_lock();
-       ret = func(data);
-       genl_unlock();
-       return ret;
-}
-
-int genl_exec_init(void)
-{
-       return 0;
-}
-
-void genl_exec_exit(void)
-{
-}
-#endif
diff --git a/datapath/genl_exec.h b/datapath/genl_exec.h
deleted file mode 100644 (file)
index 834de8e..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2007-2012 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
- */
-
-#ifndef GENL_EXEC_H
-#define GENL_EXEC_H 1
-
-typedef int (*genl_exec_func_t)(void *data);
-int genl_exec(genl_exec_func_t func, void *data);
-int genl_exec_init(void);
-void genl_exec_exit(void);
-
-#endif /* genl_exec.h */
index 4324336..1434a2d 100644 (file)
@@ -21,12 +21,12 @@ openvswitch_headers += \
        linux/compat/include/linux/err.h \
        linux/compat/include/linux/etherdevice.h \
        linux/compat/include/linux/flex_array.h \
-       linux/compat/include/linux/genetlink.h \
        linux/compat/include/linux/icmp.h \
        linux/compat/include/linux/icmpv6.h \
        linux/compat/include/linux/if.h \
        linux/compat/include/linux/if_arp.h \
        linux/compat/include/linux/if_ether.h \
+       linux/compat/include/linux/if_tunnel.h \
        linux/compat/include/linux/if_vlan.h \
        linux/compat/include/linux/in.h \
        linux/compat/include/linux/inetdevice.h \
index 404b937..65bce08 100644 (file)
@@ -3,7 +3,7 @@
 
 #include_next <asm/percpu.h>
 
-#ifndef this_cpu_ptr
+#if !defined this_cpu_ptr && !defined HAVE_THIS_CPU_PTR
 #define this_cpu_ptr(ptr) per_cpu_ptr(ptr, smp_processor_id())
 #endif
 
diff --git a/datapath/linux/compat/include/linux/genetlink.h b/datapath/linux/compat/include/linux/genetlink.h
deleted file mode 100644 (file)
index 8b894be..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef __GENETLINK_WRAPPER_H
-#define __GENETLINK_WRAPPER_H 1
-
-#include <linux/version.h>
-#include_next <linux/genetlink.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
-#ifdef CONFIG_PROVE_LOCKING
-static inline int lockdep_genl_is_held(void)
-{
-       return 1;
-}
-#endif
-#endif
-
-#ifndef genl_dereference
-#include <linux/rcupdate.h>
-
-#define genl_dereference(p)                                    \
-       rcu_dereference_protected(p, lockdep_genl_is_held())
-#endif
-
-#endif /* linux/genetlink.h wrapper */
diff --git a/datapath/linux/compat/include/linux/if_tunnel.h b/datapath/linux/compat/include/linux/if_tunnel.h
new file mode 100644 (file)
index 0000000..96ab702
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _IF_TUNNEL_WRAPPER_H_
+#define _IF_TUNNEL_WRAPPER_H_
+
+#include <linux/version.h>
+#include_next <linux/if_tunnel.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)
+
+#include <linux/u64_stats_sync.h>
+
+struct pcpu_tstats {
+       u64     rx_packets;
+       u64     rx_bytes;
+       u64     tx_packets;
+       u64     tx_bytes;
+       struct u64_stats_sync   syncp;
+};
+#endif
+
+#endif /* _IF_TUNNEL_WRAPPER_H_ */
index 71aad87..f8240df 100644 (file)
@@ -158,7 +158,7 @@ static inline int rpl_netif_needs_gso(struct sk_buff *skb, int features)
 typedef u32 netdev_features_t;
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0)
+#ifndef HAVE___SKB_GSO_SEGMENT
 static inline struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
                                                netdev_features_t features,
                                                bool tx_path)
index cb48863..b2de545 100644 (file)
@@ -68,5 +68,7 @@ int cancel_delayed_work_sync(struct delayed_work *dwork);
        } while (0)
 
 extern void flush_scheduled_work(void);
+extern void queue_work(struct work_struct *work);
+extern bool cancel_work_sync(struct work_struct *work);
 
 #endif
index 9616ea9..308cd69 100644 (file)
@@ -85,15 +85,21 @@ static inline __be64 nla_get_be64(const struct nlattr *nla)
 }
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
+#ifndef HAVE_NLA_PUT_BE16
 static inline int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value)
 {
        return nla_put(skb, attrtype, sizeof(__be16), &value);
 }
+#endif
+
+#ifndef HAVE_NLA_PUT_BE32
 static inline int nla_put_be32(struct sk_buff *skb, int attrtype, __be32 value)
 {
        return nla_put(skb, attrtype, sizeof(__be32), &value);
 }
+#endif
+
+#ifndef HAVE_NLA_PUT_BE64
 static inline int nla_put_be64(struct sk_buff *skb, int attrtype, __be64 value)
 {
        return nla_put(skb, attrtype, sizeof(__be64), &value);
index 9e92eeb..d26fb5e 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/if_vlan.h>
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
+#ifndef HAVE_CAN_CHECKSUM_PROTOCOL
 static bool can_checksum_protocol(unsigned long features, __be16 protocol)
 {
        return  ((features & NETIF_F_GEN_CSUM) ||
@@ -12,6 +13,7 @@ static bool can_checksum_protocol(unsigned long features, __be16 protocol)
                ((features & NETIF_F_FCOE_CRC) &&
                                protocol == htons(ETH_P_FCOE)));
 }
+#endif
 
 static inline int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
 {
index 9934f1a..cdb3615 100644 (file)
@@ -29,20 +29,31 @@ static wait_queue_head_t more_work;
 static struct task_struct *workq_thread;
 static struct work_struct *current_work;
 
-static void queue_work(struct work_struct *work)
+static void add_work_to_ovs_wq(struct work_struct *work)
+{
+       list_add_tail(&work->entry, &workq);
+       wake_up(&more_work);
+}
+static void __queue_work(struct work_struct *work)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&wq_lock, flags);
-       list_add_tail(&work->entry, &workq);
-       wake_up(&more_work);
+       add_work_to_ovs_wq(work);
        spin_unlock_irqrestore(&wq_lock, flags);
 }
 
+void queue_work(struct work_struct *work)
+{
+       if (test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work)))
+               return;
+       __queue_work(work);
+}
+
 static void _delayed_work_timer_fn(unsigned long __data)
 {
        struct delayed_work *dwork = (struct delayed_work *)__data;
-       queue_work(&dwork->work);
+       __queue_work(&dwork->work);
 }
 
 static void __queue_delayed_work(struct delayed_work *dwork,
@@ -67,7 +78,7 @@ int schedule_delayed_work(struct delayed_work *dwork, unsigned long delay)
                return 0;
 
        if (delay == 0)
-               queue_work(&dwork->work);
+               __queue_work(&dwork->work);
        else
                __queue_delayed_work(dwork, delay);
 
@@ -96,8 +107,7 @@ static void workqueue_barrier(struct work_struct *work)
        else {
                INIT_WORK(&barr.work, wq_barrier_func);
                init_completion(&barr.done);
-               list_add(&barr.work.entry, &workq);
-               wake_up(&more_work);
+               add_work_to_ovs_wq(&barr.work);
                need_barrier = true;
        }
        spin_unlock_irq(&wq_lock);
@@ -152,6 +162,11 @@ int cancel_delayed_work_sync(struct delayed_work *dwork)
        return __cancel_work_timer(&dwork->work, &dwork->timer);
 }
 
+bool cancel_work_sync(struct work_struct *work)
+{
+       return __cancel_work_timer(work, NULL);
+}
+
 static void run_workqueue(void)
 {
        spin_lock_irq(&wq_lock);
index 40b96cf..a29d2e8 100644 (file)
@@ -331,7 +331,7 @@ static struct vport *gre_create(const struct vport_parms *parms)
        struct vport *vport;
 
        ovs_net = net_generic(net, ovs_net_id);
-       if (rtnl_dereference(ovs_net->vport_net.gre_vport))
+       if (ovsl_dereference(ovs_net->vport_net.gre_vport))
                return ERR_PTR(-EEXIST);
 
        vport = ovs_tnl_create(parms, &ovs_gre_vport_ops, &gre_tnl_ops);
@@ -376,7 +376,7 @@ static struct vport *gre64_create(const struct vport_parms *parms)
        struct vport *vport;
 
        ovs_net = net_generic(net, ovs_net_id);
-       if (rtnl_dereference(ovs_net->vport_net.gre64_vport))
+       if (ovsl_dereference(ovs_net->vport_net.gre64_vport))
                return ERR_PTR(-EEXIST);
 
        vport = ovs_tnl_create(parms, &ovs_gre64_vport_ops, &gre64_tnl_ops);
index 003e880..1e8c304 100644 (file)
@@ -228,16 +228,19 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
        if (vport->port_no == OVSP_LOCAL)
                netdev_vport->dev->features |= NETIF_F_NETNS_LOCAL;
 
+       rtnl_lock();
        err = register_netdevice(netdev_vport->dev);
        if (err)
                goto error_free_netdev;
 
        dev_set_promiscuity(netdev_vport->dev, 1);
+       rtnl_unlock();
        netif_start_queue(netdev_vport->dev);
 
        return vport;
 
 error_free_netdev:
+       rtnl_unlock();
        free_netdev(netdev_vport->dev);
 error_free_vport:
        ovs_vport_free(vport);
@@ -250,10 +253,13 @@ static void internal_dev_destroy(struct vport *vport)
        struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
 
        netif_stop_queue(netdev_vport->dev);
+       rtnl_lock();
        dev_set_promiscuity(netdev_vport->dev, -1);
 
        /* unregister_netdevice() waits for an RCU grace period. */
        unregister_netdevice(netdev_vport->dev);
+
+       rtnl_unlock();
 }
 
 static int internal_dev_recv(struct vport *vport, struct sk_buff *skb)
@@ -292,7 +298,6 @@ const struct vport_ops ovs_internal_vport_ops = {
        .create         = internal_dev_create,
        .destroy        = internal_dev_destroy,
        .get_name       = ovs_netdev_get_name,
-       .get_ifindex    = ovs_netdev_get_ifindex,
        .send           = internal_dev_recv,
 };
 
index 727194e..4558079 100644 (file)
@@ -45,6 +45,12 @@ MODULE_PARM_DESC(vlan_tso, "Enable TSO for VLAN packets");
 #define vlan_tso true
 #endif
 
+#ifdef HAVE_RHEL_OVS_HOOK
+static atomic_t nr_bridges = ATOMIC_INIT(0);
+
+extern struct sk_buff *(*openvswitch_handle_frame_hook)(struct sk_buff *skb);
+#endif
+
 static void netdev_port_receive(struct vport *vport, struct sk_buff *skb);
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
@@ -63,7 +69,8 @@ static rx_handler_result_t netdev_frame_hook(struct sk_buff **pskb)
 
        return RX_HANDLER_CONSUMED;
 }
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) || \
+      defined HAVE_RHEL_OVS_HOOK
 /* Called with rcu_read_lock and bottom-halves disabled. */
 static struct sk_buff *netdev_frame_hook(struct sk_buff *skb)
 {
@@ -105,7 +112,8 @@ static int netdev_frame_hook(struct net_bridge_port *p, struct sk_buff **pskb)
 #error
 #endif
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) || \
+    defined HAVE_RHEL_OVS_HOOK
 static int netdev_init(void) { return 0; }
 static void netdev_exit(void) { }
 #else
@@ -152,19 +160,31 @@ static struct vport *netdev_create(const struct vport_parms *parms)
                goto error_put;
        }
 
+       rtnl_lock();
+#ifdef HAVE_RHEL_OVS_HOOK
+       rcu_assign_pointer(netdev_vport->dev->ax25_ptr, vport);
+       atomic_inc(&nr_bridges);
+       rcu_assign_pointer(openvswitch_handle_frame_hook, netdev_frame_hook);
+#else
        err = netdev_rx_handler_register(netdev_vport->dev, netdev_frame_hook,
                                         vport);
        if (err)
-               goto error_put;
+               goto error_unlock;
+#endif
 
        dev_set_promiscuity(netdev_vport->dev, 1);
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
        dev_disable_lro(netdev_vport->dev);
 #endif
        netdev_vport->dev->priv_flags |= IFF_OVS_DATAPATH;
+       rtnl_unlock();
 
        return vport;
 
+#ifndef HAVE_RHEL_OVS_HOOK
+error_unlock:
+#endif
+       rtnl_unlock();
 error_put:
        dev_put(netdev_vport->dev);
 error_free_vport:
@@ -178,6 +198,12 @@ static void free_port_rcu(struct rcu_head *rcu)
        struct netdev_vport *netdev_vport = container_of(rcu,
                                        struct netdev_vport, rcu);
 
+#ifdef HAVE_RHEL_OVS_HOOK
+       rcu_assign_pointer(netdev_vport->dev->ax25_ptr, NULL);
+
+       if (atomic_dec_and_test(&nr_bridges))
+               rcu_assign_pointer(openvswitch_handle_frame_hook, NULL);
+#endif
        dev_put(netdev_vport->dev);
        ovs_vport_free(vport_from_priv(netdev_vport));
 }
@@ -186,9 +212,11 @@ static void netdev_destroy(struct vport *vport)
 {
        struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
 
+       rtnl_lock();
        netdev_vport->dev->priv_flags &= ~IFF_OVS_DATAPATH;
        netdev_rx_handler_unregister(netdev_vport->dev);
        dev_set_promiscuity(netdev_vport->dev, -1);
+       rtnl_unlock();
 
        call_rcu(&netdev_vport->rcu, free_port_rcu);
 }
@@ -199,12 +227,6 @@ const char *ovs_netdev_get_name(const struct vport *vport)
        return netdev_vport->dev->name;
 }
 
-int ovs_netdev_get_ifindex(const struct vport *vport)
-{
-       const struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
-       return netdev_vport->dev->ifindex;
-}
-
 /* Must be called with rcu_read_lock. */
 static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
 {
@@ -345,13 +367,18 @@ error:
 /* Returns null if this device is not attached to a datapath. */
 struct vport *ovs_netdev_get_vport(struct net_device *dev)
 {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) || \
+    defined HAVE_RHEL_OVS_HOOK
 #if IFF_OVS_DATAPATH != 0
        if (likely(dev->priv_flags & IFF_OVS_DATAPATH))
 #else
        if (likely(rcu_access_pointer(dev->rx_handler) == netdev_frame_hook))
 #endif
+#ifdef HAVE_RHEL_OVS_HOOK
+               return (struct vport *)rcu_dereference_rtnl(dev->ax25_ptr);
+#else
                return (struct vport *)rcu_dereference_rtnl(dev->rx_handler_data);
+#endif
        else
                return NULL;
 #else
@@ -367,11 +394,11 @@ const struct vport_ops ovs_netdev_vport_ops = {
        .create         = netdev_create,
        .destroy        = netdev_destroy,
        .get_name       = ovs_netdev_get_name,
-       .get_ifindex    = ovs_netdev_get_ifindex,
        .send           = netdev_send,
 };
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) && \
+    !defined HAVE_RHEL_OVS_HOOK
 /*
  * Enforces, mutual exclusion with the Linux bridge module, by declaring and
  * exporting br_should_route_hook.  Because the bridge module also exports the
index 6478079..a3cb3a3 100644 (file)
@@ -40,6 +40,5 @@ netdev_vport_priv(const struct vport *vport)
 
 const char *ovs_netdev_get_name(const struct vport *);
 const char *ovs_netdev_get_config(const struct vport *);
-int ovs_netdev_get_ifindex(const struct vport *);
 
 #endif /* vport_netdev.h */
index e9e1444..03446da 100644 (file)
@@ -50,7 +50,7 @@ static const struct vport_ops *base_vport_ops_list[] = {
 static const struct vport_ops **vport_ops_list;
 static int n_vport_types;
 
-/* Protected by RCU read lock for reading, RTNL lock for writing. */
+/* Protected by RCU read lock for reading, ovs_mutex for writing. */
 static struct hlist_head *dev_table;
 #define VPORT_HASH_BUCKETS 1024
 
@@ -133,7 +133,7 @@ static struct hlist_head *hash_bucket(struct net *net, const char *name)
  *
  * @name: name of port to find
  *
- * Must be called with RTNL or RCU read lock.
+ * Must be called with ovs or RCU read lock.
  */
 struct vport *ovs_vport_locate(struct net *net, const char *name)
 {
@@ -181,7 +181,7 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,
        vport->ops = ops;
        INIT_HLIST_NODE(&vport->dp_hash_node);
 
-       vport->percpu_stats = alloc_percpu(struct vport_percpu_stats);
+       vport->percpu_stats = alloc_percpu(struct pcpu_tstats);
        if (!vport->percpu_stats) {
                kfree(vport);
                return ERR_PTR(-ENOMEM);
@@ -214,7 +214,7 @@ void ovs_vport_free(struct vport *vport)
  * @parms: Information about new vport.
  *
  * Creates a new vport with the specified configuration (which is dependent on
- * device type).  RTNL lock must be held.
+ * device type).  ovs_mutex must be held.
  */
 struct vport *ovs_vport_add(const struct vport_parms *parms)
 {
@@ -222,8 +222,6 @@ struct vport *ovs_vport_add(const struct vport_parms *parms)
        int err = 0;
        int i;
 
-       ASSERT_RTNL();
-
        for (i = 0; i < n_vport_types; i++) {
                if (vport_ops_list[i]->type == parms->type) {
                        struct hlist_head *bucket;
@@ -254,12 +252,10 @@ out:
  * @port: New configuration.
  *
  * Modifies an existing device with the specified configuration (which is
- * dependent on device type).  RTNL lock must be held.
+ * dependent on device type).  ovs_mutex must be held.
  */
 int ovs_vport_set_options(struct vport *vport, struct nlattr *options)
 {
-       ASSERT_RTNL();
-
        if (!vport->ops->set_options)
                return -EOPNOTSUPP;
        return vport->ops->set_options(vport, options);
@@ -271,14 +267,13 @@ int ovs_vport_set_options(struct vport *vport, struct nlattr *options)
  * @vport: vport to delete.
  *
  * Detaches @vport from its datapath and destroys it.  It is possible to fail
- * for reasons such as lack of memory.  RTNL lock must be held.
+ * for reasons such as lack of memory.  ovs_mutex must be held.
  */
 void ovs_vport_del(struct vport *vport)
 {
-       ASSERT_RTNL();
+       ASSERT_OVSL();
 
        hlist_del_rcu(&vport->hash_node);
-
        vport->ops->destroy(vport);
 }
 
@@ -293,12 +288,10 @@ void ovs_vport_del(struct vport *vport)
  * support setting the stats, in which case the result will always be
  * -EOPNOTSUPP.
  *
- * Must be called with RTNL lock.
+ * Must be called with ovs_mutex.
  */
 void ovs_vport_set_stats(struct vport *vport, struct ovs_vport_stats *stats)
 {
-       ASSERT_RTNL();
-
        spin_lock_bh(&vport->stats_lock);
        vport->offset_stats = *stats;
        spin_unlock_bh(&vport->stats_lock);
@@ -312,7 +305,7 @@ void ovs_vport_set_stats(struct vport *vport, struct ovs_vport_stats *stats)
  *
  * Retrieves transmit, receive, and error stats for the given device.
  *
- * Must be called with RTNL lock or rcu_read_lock.
+ * Must be called with ovs_mutex or rcu_read_lock.
  */
 void ovs_vport_get_stats(struct vport *vport, struct ovs_vport_stats *stats)
 {
@@ -341,16 +334,16 @@ void ovs_vport_get_stats(struct vport *vport, struct ovs_vport_stats *stats)
        spin_unlock_bh(&vport->stats_lock);
 
        for_each_possible_cpu(i) {
-               const struct vport_percpu_stats *percpu_stats;
-               struct vport_percpu_stats local_stats;
+               const struct pcpu_tstats *percpu_stats;
+               struct pcpu_tstats local_stats;
                unsigned int start;
 
                percpu_stats = per_cpu_ptr(vport->percpu_stats, i);
 
                do {
-                       start = u64_stats_fetch_begin_bh(&percpu_stats->sync);
+                       start = u64_stats_fetch_begin_bh(&percpu_stats->syncp);
                        local_stats = *percpu_stats;
-               } while (u64_stats_fetch_retry_bh(&percpu_stats->sync, start));
+               } while (u64_stats_fetch_retry_bh(&percpu_stats->syncp, start));
 
                stats->rx_bytes         += local_stats.rx_bytes;
                stats->rx_packets       += local_stats.rx_packets;
@@ -373,7 +366,7 @@ void ovs_vport_get_stats(struct vport *vport, struct ovs_vport_stats *stats)
  * negative error code if a real error occurred.  If an error occurs, @skb is
  * left unmodified.
  *
- * Must be called with RTNL lock or rcu_read_lock.
+ * Must be called with ovs_mutex or rcu_read_lock.
  */
 int ovs_vport_get_options(const struct vport *vport, struct sk_buff *skb)
 {
@@ -409,13 +402,13 @@ int ovs_vport_get_options(const struct vport *vport, struct sk_buff *skb)
  */
 void ovs_vport_receive(struct vport *vport, struct sk_buff *skb)
 {
-       struct vport_percpu_stats *stats;
+       struct pcpu_tstats *stats;
 
        stats = this_cpu_ptr(vport->percpu_stats);
-       u64_stats_update_begin(&stats->sync);
+       u64_stats_update_begin(&stats->syncp);
        stats->rx_packets++;
        stats->rx_bytes += skb->len;
-       u64_stats_update_end(&stats->sync);
+       u64_stats_update_end(&stats->syncp);
 
        if (!(vport->ops->flags & VPORT_F_TUN_ID))
                OVS_CB(skb)->tun_key = NULL;
@@ -429,7 +422,7 @@ void ovs_vport_receive(struct vport *vport, struct sk_buff *skb)
  * @vport: vport on which to send the packet
  * @skb: skb to send
  *
- * Sends the given packet and returns the length of data sent.  Either RTNL
+ * Sends the given packet and returns the length of data sent.  Either ovs
  * lock or rcu_read_lock must be held.
  */
 int ovs_vport_send(struct vport *vport, struct sk_buff *skb)
@@ -437,14 +430,14 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb)
        int sent = vport->ops->send(vport, skb);
 
        if (likely(sent)) {
-               struct vport_percpu_stats *stats;
+               struct pcpu_tstats *stats;
 
                stats = this_cpu_ptr(vport->percpu_stats);
 
-               u64_stats_update_begin(&stats->sync);
+               u64_stats_update_begin(&stats->syncp);
                stats->tx_packets++;
                stats->tx_bytes += sent;
-               u64_stats_update_end(&stats->sync);
+               u64_stats_update_end(&stats->syncp);
        }
        return sent;
 }
index 074c6ee..7233e4f 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef VPORT_H
 #define VPORT_H 1
 
+#include <linux/if_tunnel.h>
 #include <linux/list.h>
 #include <linux/netlink.h>
 #include <linux/openvswitch.h>
@@ -53,14 +54,6 @@ int ovs_vport_send(struct vport *, struct sk_buff *);
 
 /* The following definitions are for implementers of vport devices: */
 
-struct vport_percpu_stats {
-       u64 rx_bytes;
-       u64 rx_packets;
-       u64 tx_bytes;
-       u64 tx_packets;
-       struct u64_stats_sync sync;
-};
-
 struct vport_err_stats {
        u64 rx_dropped;
        u64 rx_errors;
@@ -72,9 +65,6 @@ struct vport_err_stats {
  * struct vport - one port within a datapath
  * @rcu: RCU callback head for deferred destruction.
  * @dp: Datapath to which this port belongs.
- * @linkname: The name of the link from /sys/class/net/<datapath>/brif to this
- * &struct vport.  (We keep this around so that we can delete it if the
- * device gets renamed.)  Set to the null string when no link exists.
  * @upcall_portid: The Netlink port to use for packets received on this port that
  * miss the flow table.
  * @port_no: Index into @dp's @ports array.
@@ -90,7 +80,6 @@ struct vport_err_stats {
 struct vport {
        struct rcu_head rcu;
        struct datapath *dp;
-       char linkname[IFNAMSIZ];
        u32 upcall_portid;
        u16 port_no;
 
@@ -98,7 +87,7 @@ struct vport {
        struct hlist_node dp_hash_node;
        const struct vport_ops *ops;
 
-       struct vport_percpu_stats __percpu *percpu_stats;
+       struct pcpu_tstats __percpu *percpu_stats;
 
        spinlock_t stats_lock;
        struct vport_err_stats err_stats;
@@ -150,7 +139,6 @@ struct vport_parms {
  * have any configuration.
  * @get_name: Get the device's name.
  * @get_config: Get the device's configuration.
- * @get_ifindex: Get the system interface index associated with the device.
  * May be null if the device does not have an ifindex.
  * @send: Send a packet on the device.  Returns the length of the packet sent.
  */
@@ -162,17 +150,17 @@ struct vport_ops {
        int (*init)(void);
        void (*exit)(void);
 
-       /* Called with RTNL lock. */
+       /* Called with ovs_mutex. */
        struct vport *(*create)(const struct vport_parms *);
        void (*destroy)(struct vport *);
 
        int (*set_options)(struct vport *, struct nlattr *);
        int (*get_options)(const struct vport *, struct sk_buff *);
 
-       /* Called with rcu_read_lock or RTNL lock. */
+       /* Called with rcu_read_lock or ovs_mutex. */
        const char *(*get_name)(const struct vport *);
        void (*get_config)(const struct vport *, void *);
-       int (*get_ifindex)(const struct vport *);
+
        int (*send)(struct vport *, struct sk_buff *);
 };
 
index 18b0281..f601020 100644 (file)
@@ -1,9 +1,34 @@
-openvswitch (1.10.90-1) unstable; urgency=low
+openvswitch (1.11.90-1) unstable; urgency=low
    [ Open vSwitch team ]
    * New upstream version
      - Nothing yet!  Try NEWS...
 
- -- Open vSwitch team <dev@openvswitch.org>  Mon, 04 Feb 2013 21:52:34 -0700
+ -- Open vSwitch team <dev@openvswitch.org>  Mon, 29 Apr 2013 14:30:34 -0700
+
+openvswitch (1.11.0-1) unstable; urgency=low
+   [ Open vSwitch team ]
+   * New upstream version
+    - The "tutorial" directory contains a new tutorial for some advanced
+      Open vSwitch features.
+    - Stable bond mode has been removed.
+    - The autopath action has been removed.
+    - New support for the data encapsulation format of the LISP tunnel
+      protocol (RFC 6830).  An external control plane or manual flow
+      setup is required for EID-to-RLOC mapping.
+    - OpenFlow:
+      * The "dec_mpls_ttl" and "set_mpls_ttl" actions from OpenFlow
+        1.1 and later are now implemented.
+      * New "stack" extension for use in actions, to push and pop from
+        NXM fields.
+    - ovs-dpctl:
+      * New debugging commands "add-flow", "mod-flow", "del-flow".
+    - New syslog format, prefixed with "ovs|", to be easier to filter.
+    - RHEL: Removes the default firewall rule that allowed GRE traffic to
+      pass through. Any users that relied on this automatic firewall hole
+      will have to manually configure it. The ovs-ctl(8) manpage documents
+      the "enable-protocol" command that can be used as an alternative.
+
+ -- Open vSwitch team <dev@openvswitch.org>  Mon, 29 Apr 2013 14:30:34 -0700
 
 openvswitch (1.10.0-1) unstable; urgency=low
    [ Open vSwitch team ]
@@ -59,7 +84,7 @@ openvswitch (1.10.0-1) unstable; urgency=low
     - Patch ports no longer require kernel support, so they now work
       with FreeBSD and the kernel module built into Linux 3.3 and later.
 
- -- Open vSwitch team <dev@openvswitch.org>  Mon, 04 Feb 2013 21:52:34 -0700
+ -- Open vSwitch team <dev@openvswitch.org>  Wed, 01 May 2013 14:28:21 -0700
 
 openvswitch (1.9.0-1) unstable; urgency=low
    [ Open vSwitch team ]
index acf47b9..fe58b31 100644 (file)
@@ -5,7 +5,7 @@ Maintainer: Open vSwitch developers <dev@openvswitch.org>
 Uploaders: Ben Pfaff <pfaffben@debian.org>, Simon Horman <horms@debian.org>
 Build-Depends:
  debhelper (>= 8), autoconf (>= 2.64), automake (>= 1.10) | automake1.10, 
- libssl-dev, pkg-config (>= 0.21), bzip2, openssl,
+ libssl-dev, bzip2, openssl,
  python-all (>= 2.6.6-3~), procps, python-qt4,
  python-zopeinterface, python-twisted-conch
 Standards-Version: 3.9.3
@@ -16,13 +16,13 @@ Architecture: all
 Depends: module-assistant, bzip2, debhelper (>= 5.0.37), ${misc:Depends}
 Suggests: openvswitch-switch
 Description: Open vSwitch datapath module source - module-assistant version
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  This package provides the Open vSwitch datapath module source code
  that is needed by openvswitch-switch.  The kernel module can be built
@@ -33,13 +33,13 @@ Package: openvswitch-datapath-dkms
 Architecture: all
 Depends: dkms (>= 1.95), make, libc6-dev, ${misc:Depends}, ${python:Depends}
 Description: Open vSwitch datapath module source - DKMS version
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  This package provides the Open vSwitch datapath module source code
  that is needed by openvswitch-switch.  DKMS can built the kernel
@@ -52,13 +52,13 @@ Depends:
  python (>= 2.7) | python-argparse
 Suggests: ethtool
 Description: Open vSwitch common components
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  openvswitch-common provides components required by both openvswitch-switch
  and openvswitch-controller.
@@ -68,34 +68,34 @@ Architecture: linux-any
 Suggests: openvswitch-datapath-module
 Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends}, openvswitch-common (= ${binary:Version}), module-init-tools, procps, uuid-runtime, netbase
 Description: Open vSwitch switch implementations
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  openvswitch-switch provides the userspace components and utilities for
- the Open vSwitch kernel-based switch.  
+ the Open vSwitch kernel-based switch.
 
 Package: openvswitch-ipsec
 Architecture: linux-any
 Depends:
  ${shlibs:Depends}, ${misc:Depends}, python,
- ipsec-tools (>=0.8~alpha20101208), 
+ ipsec-tools (>=0.8~alpha20101208),
  racoon (>=0.8~alpha20101208),
  openvswitch-common (= ${binary:Version}),
  openvswitch-switch (= ${binary:Version}),
  python-openvswitch (= ${source:Version})
 Description: Open vSwitch GRE-over-IPsec support
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  The ovs-monitor-ipsec script provides support for encrypting GRE
  tunnels with IPsec.
@@ -106,13 +106,13 @@ Depends:
  ${misc:Depends}, openvswitch-common (>= ${source:Version}),
  openvswitch-common (<< ${source:Version}.1~)
 Description: Open vSwitch public key infrastructure dependency package
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  openvswitch-pki provides PKI (public key infrastructure) support for
  Open vSwitch switches and controllers, reducing the risk of
@@ -124,13 +124,13 @@ Depends:
  ${shlibs:Depends}, openvswitch-common (= ${binary:Version}),
  openvswitch-pki (= ${source:Version}), ${misc:Depends}
 Description: Open vSwitch controller implementation
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  The Open vSwitch controller enables OpenFlow switches that connect to it
  to act as MAC-learning Ethernet switches.
@@ -144,13 +144,13 @@ Depends:
  openvswitch-controller (= ${binary:Version}),
  openvswitch-switch (= ${binary:Version})
 Description: Debug symbols for Open vSwitch packages
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  This package contains the debug symbols for all the other openvswitch-*
  packages.  Install it to debug one of them or to examine a core dump
@@ -161,13 +161,13 @@ Architecture: all
 Section: python
 Depends: ${misc:Depends}, ${python:Depends}
 Description: Python bindings for Open vSwitch
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  This package contains the full Python bindings for Open vSwitch database.
 
@@ -176,13 +176,13 @@ Architecture: all
 Section: utils
 Depends: ${python:Depends}, python-openvswitch, ${misc:Depends}
 Description: Open vSwitch graphical monitoring tool
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  This package is a GUI tool for monitoring and troubleshooting local
  or remote Open vSwitch installations.  It presents GUI tables that
@@ -194,13 +194,13 @@ Package: openvswitch-test
 Architecture: all
 Depends: ${misc:Depends}, ${python:Depends}, python-twisted-web, python (>= 2.7) | python-argparse
 Description: Open vSwitch test package
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  This package contains utilities that are useful to diagnose
  performance and connectivity issues in Open vSwitch setup.
index d84c1b6..84aa450 100755 (executable)
@@ -75,10 +75,35 @@ stop () {
 }
 
 restart () {
-    # OVS_RESTART_SAVE_FLOWS can be set by package postinst script.
-    if [ "$OVS_RESTART_SAVE_FLOWS" = "yes" ] || \
-       [ "$1" = "--save-flows=yes" ]; then
+    # OVS_FORCE_RELOAD_KMOD can be set by package postinst script.
+    if [ "$1" = "--save-flows=yes" ] || \
+        [ "${OVS_FORCE_RELOAD_KMOD}" = "no" ]; then
         start restart
+    elif [ "${OVS_FORCE_RELOAD_KMOD}" = "yes" ]; then
+        depmod -a
+
+        if [ -e /sys/module/openvswitch ]; then
+            LOADED_SRCVERSION=`cat /sys/module/openvswitch/srcversion`
+            LOADED_VERSION=`cat /sys/module/openvswitch/version`
+        elif [ -e /sys/module/openvswitch_mod ]; then
+            LOADED_SRCVERSION=`cat /sys/module/openvswitch_mod/srcversion`
+            LOADED_VERSION=`cat /sys/module/openvswitch_mod/version`
+        fi
+        SRCVERSION=`modinfo -F srcversion openvswitch 2>/dev/null`
+        VERSION=`modinfo -F version openvswitch 2>/dev/null`
+
+        ovs_ctl_log "Package upgrading:\n"\
+                    "Loaded version: ${LOADED_VERSION} ${LOADED_SRCVERSION}.\n"\
+                    "Version on disk: ${VERSION} ${SRCVERSION}."
+
+        # If the kernel module was previously loaded and it is different than
+        # the kernel module on disk, then do a 'force-reload-kmod'.
+        if [ -n "${LOADED_SRCVERSION}" ] && [ -n "${SRCVERSION}" ] && \
+            [ "${SRCVERSION}" != "${LOADED_SRCVERSION}" ]; then
+            start force-reload-kmod
+        else
+            start restart
+        fi
     else
         stop
         start
index ac6ed65..2464572 100755 (executable)
@@ -49,9 +49,10 @@ esac
 OVS_MISSING_KMOD_OK=yes
 export OVS_MISSING_KMOD_OK
 
-# Save and restore openflow flows during a package upgrade.
-OVS_RESTART_SAVE_FLOWS=yes
-export OVS_RESTART_SAVE_FLOWS
+# force-reload-kmod during upgrade. If a user wants to override this,
+# they can set the variable OVS_FORCE_RELOAD_KMOD=no while installing.
+[ -z "${OVS_FORCE_RELOAD_KMOD}" ] && OVS_FORCE_RELOAD_KMOD=yes || true
+export OVS_FORCE_RELOAD_KMOD
 
 #DEBHELPER#
 
index 51a2e51..d34bdb3 100755 (executable)
@@ -22,6 +22,7 @@ PARALLEL =
 endif
 MAKEFLAGS += $(PARALLEL)
 
+CFLAGS += -g
 ifneq (,$(filter noopt,$(DEB_BUILD_OPTIONS)))
 CFLAGS += -O0
 else
index bd2f05f..e890fd8 100644 (file)
@@ -287,7 +287,9 @@ enum ovs_key_attr {
        OVS_KEY_ATTR_IPV4_TUNNEL,  /* struct ovs_key_ipv4_tunnel */
 #endif
 
-       OVS_KEY_ATTR_MPLS = 62, /* struct ovs_key_mpls */
+       OVS_KEY_ATTR_MPLS = 62, /* array of struct ovs_key_mpls.
+                                * The implementation may restrict
+                                * the accepted length of the array. */
        __OVS_KEY_ATTR_MAX
 };
 
@@ -330,7 +332,7 @@ struct ovs_key_ethernet {
 };
 
 struct ovs_key_mpls {
-       __be32 mpls_top_lse;
+       __be32 mpls_lse;
 };
 
 struct ovs_key_ipv4 {
index 54fc4f9..c80ff95 100644 (file)
@@ -312,6 +312,7 @@ enum nx_action_subtype {
     NXAST_DEC_MPLS_TTL,         /* struct nx_action_header */
     NXAST_STACK_PUSH,           /* struct nx_action_stack */
     NXAST_STACK_POP,            /* struct nx_action_stack */
+    NXAST_SAMPLE,               /* struct nx_action_sample */
 };
 
 /* Header for Nicira-defined actions. */
@@ -2233,4 +2234,29 @@ struct nx_action_mpls_ttl {
 };
 OFP_ASSERT(sizeof(struct nx_action_mpls_ttl) == 16);
 
+/* Action structure for NXAST_SAMPLE.
+ *
+ * Samples matching packets with the given probability and sends them
+ * each to the set of collectors identified with the given ID.  The
+ * probability is expressed as a number of packets to be sampled out
+ * of USHRT_MAX packets, and must be >0.
+ *
+ * When sending packet samples to IPFIX collectors, the IPFIX flow
+ * record sent for each sampled packet is associated with the given
+ * observation domain ID and observation point ID.  Each IPFIX flow
+ * record contain the sampled packet's headers when executing this
+ * rule.  If a sampled packet's headers are modified by previous
+ * actions in the flow, those modified headers are sent. */
+struct nx_action_sample {
+    ovs_be16 type;                  /* OFPAT_VENDOR. */
+    ovs_be16 len;                   /* Length is 24. */
+    ovs_be32 vendor;                /* NX_VENDOR_ID. */
+    ovs_be16 subtype;               /* NXAST_SAMPLE. */
+    ovs_be16 probability;           /* Fraction of packets to sample. */
+    ovs_be32 collector_set_id;      /* ID of collector set in OVSDB. */
+    ovs_be32 obs_domain_id;         /* ID of sampling observation domain. */
+    ovs_be32 obs_point_id;          /* ID of sampling observation point. */
+};
+OFP_ASSERT(sizeof(struct nx_action_sample) == 24);
+
 #endif /* openflow/nicira-ext.h */
index e7ee56c..e12bc14 100644 (file)
@@ -163,6 +163,26 @@ daemon_save_fd(int fd)
     save_fds[fd] = true;
 }
 
+/* Unregisters pidfile from being unlinked when the program terminates via
+* exit() or a fatal signal. */
+void
+remove_pidfile_from_unlink(void)
+{
+    if (pidfile) {
+        fatal_signal_remove_file_to_unlink(pidfile);
+    }
+}
+
+/* Registers pidfile to be unlinked when the program terminates via exit() or a
+ * fatal signal. */
+void
+add_pidfile_to_unlink(void)
+{
+    if (pidfile) {
+        fatal_signal_add_file_to_unlink(pidfile);
+    }
+}
+
 /* If a pidfile has been configured, creates it and stores the running
  * process's pid in it.  Ensures that the pidfile will be deleted when the
  * process exits. */
@@ -240,8 +260,6 @@ make_pidfile(void)
     pidfile_dev = s.st_dev;
     pidfile_ino = s.st_ino;
     free(tmpfile);
-    free(pidfile);
-    pidfile = NULL;
 }
 
 /* If configured with set_pidfile() or set_detach(), creates the pid file and
@@ -529,6 +547,11 @@ daemonize_start(void)
 void
 daemonize_complete(void)
 {
+    if (pidfile) {
+        free(pidfile);
+        pidfile = NULL;
+    }
+
     if (!detached) {
         detached = true;
 
index 8cbcfaf..14436f3 100644 (file)
@@ -65,6 +65,8 @@ void set_detach(void);
 bool get_detach(void);
 void daemon_set_monitor(void);
 void daemon_save_fd(int fd);
+void remove_pidfile_from_unlink(void);
+void add_pidfile_to_unlink(void);
 void daemonize(void);
 void daemonize_start(void);
 void daemonize_complete(void);
index 7293063..ac20ae7 100644 (file)
@@ -312,7 +312,7 @@ add_channel(struct dpif_linux *dpif, uint32_t port_no, struct nl_sock *sock)
         int new_size = port_no + 1;
         int i;
 
-        if (new_size > 65535) {
+        if (new_size > MAX_PORTS) {
             VLOG_WARN_RL(&error_rl, "%s: datapath port %"PRIu32" too big",
                          dpif_name(&dpif->dpif), port_no);
             return EFBIG;
@@ -337,6 +337,7 @@ add_channel(struct dpif_linux *dpif, uint32_t port_no, struct nl_sock *sock)
         return errno;
     }
 
+    nl_sock_destroy(dpif->channels[port_no].sock);
     dpif->channels[port_no].sock = sock;
     dpif->channels[port_no].last_poll = LLONG_MIN;
 
@@ -358,6 +359,7 @@ del_channel(struct dpif_linux *dpif, uint32_t port_no)
     }
 
     epoll_ctl(dpif->epoll_fd, EPOLL_CTL_DEL, nl_sock_fd(ch->sock), NULL);
+    dpif->event_offset = dpif->n_events = 0;
 
     nl_sock_destroy(ch->sock);
     ch->sock = NULL;
@@ -793,7 +795,7 @@ static void
 dpif_linux_init_flow_put(struct dpif *dpif_, const struct dpif_flow_put *put,
                          struct dpif_linux_flow *request)
 {
-    static struct nlattr dummy_action;
+    static const struct nlattr dummy_action;
 
     struct dpif_linux *dpif = dpif_linux_cast(dpif_);
 
@@ -804,7 +806,9 @@ dpif_linux_init_flow_put(struct dpif *dpif_, const struct dpif_flow_put *put,
     request->key = put->key;
     request->key_len = put->key_len;
     /* Ensure that OVS_FLOW_ATTR_ACTIONS will always be included. */
-    request->actions = put->actions ? put->actions : &dummy_action;
+    request->actions = (put->actions
+                        ? put->actions
+                        : CONST_CAST(struct nlattr *, &dummy_action));
     request->actions_len = put->actions_len;
     if (put->flags & DPIF_FP_ZERO_STATS) {
         request->clear = true;
index 185fe19..b945052 100644 (file)
@@ -420,7 +420,7 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
     port->type = xstrdup(type);
 
     error = netdev_get_mtu(netdev, &mtu);
-    if (!error) {
+    if (!error && mtu > max_mtu) {
         max_mtu = mtu;
     }
 
@@ -501,7 +501,6 @@ static int
 do_del_port(struct dp_netdev *dp, uint32_t port_no)
 {
     struct dp_netdev_port *port;
-    char *name;
     int error;
 
     error = get_port_by_number(dp, port_no, &port);
@@ -513,11 +512,8 @@ do_del_port(struct dp_netdev *dp, uint32_t port_no)
     dp->ports[port->port_no] = NULL;
     dp->serial++;
 
-    name = xstrdup(netdev_vport_get_dpif_port(port->netdev));
     netdev_close(port->netdev);
     free(port->type);
-
-    free(name);
     free(port);
 
     return 0;
index bd1cf45..c373601 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -184,21 +184,21 @@ ds_put_printable(struct ds *ds, const char *s, size_t n)
 }
 
 /* Writes the current time to 'string' based on 'template'.
- * The current time is either localtime or UTC based on 'utc'. */
+ * The current time is either local time or UTC based on 'utc'. */
 void
 ds_put_strftime(struct ds *ds, const char *template, bool utc)
 {
-    const struct tm *tm;
+    struct tm tm;
     time_t now = time_wall();
     if (utc) {
-        tm = gmtime(&now);
+        gmtime_r(&now, &tm);
     } else {
-        tm = localtime(&now);
+        localtime_r(&now, &tm);
     }
 
     for (;;) {
         size_t avail = ds->string ? ds->allocated - ds->length + 1 : 0;
-        size_t used = strftime(&ds->string[ds->length], avail, template, tm);
+        size_t used = strftime(&ds->string[ds->length], avail, template, &tm);
         if (used) {
             ds->length += used;
             return;
index 2867bfa..9b6d8c7 100644 (file)
@@ -65,7 +65,8 @@ struct hmap {
 };
 
 /* Initializer for an empty hash map. */
-#define HMAP_INITIALIZER(HMAP) { &(HMAP)->one, NULL, 0, 0 }
+#define HMAP_INITIALIZER(HMAP) \
+    { (struct hmap_node **const) &(HMAP)->one, NULL, 0, 0 }
 
 /* Initialization. */
 void hmap_init(struct hmap *);
index 06a9a42..af385c6 100644 (file)
@@ -620,11 +620,11 @@ json_lex_number(struct json_parser *p)
     significand = 0;
     if (*cp == '0') {
         cp++;
-        if (isdigit(*cp)) {
+        if (isdigit((unsigned char) *cp)) {
             json_error(p, "leading zeros not allowed");
             return;
         }
-    } else if (isdigit(*cp)) {
+    } else if (isdigit((unsigned char) *cp)) {
         do {
             if (significand <= ULLONG_MAX / 10) {
                 significand = significand * 10 + (*cp - '0');
@@ -635,7 +635,7 @@ json_lex_number(struct json_parser *p)
                 }
             }
             cp++;
-        } while (isdigit(*cp));
+        } while (isdigit((unsigned char) *cp));
     } else {
         json_error(p, "'-' must be followed by digit");
         return;
@@ -644,7 +644,7 @@ json_lex_number(struct json_parser *p)
     /* Optional fraction. */
     if (*cp == '.') {
         cp++;
-        if (!isdigit(*cp)) {
+        if (!isdigit((unsigned char) *cp)) {
             json_error(p, "decimal point must be followed by digit");
             return;
         }
@@ -656,7 +656,7 @@ json_lex_number(struct json_parser *p)
                 imprecise = true;
             }
             cp++;
-        } while (isdigit(*cp));
+        } while (isdigit((unsigned char) *cp));
     }
 
     /* Optional exponent. */
@@ -672,7 +672,7 @@ json_lex_number(struct json_parser *p)
             cp++;
         }
 
-        if (!isdigit(*cp)) {
+        if (!isdigit((unsigned char) *cp)) {
             json_error(p, "exponent must contain at least one digit");
             return;
         }
@@ -685,7 +685,7 @@ json_lex_number(struct json_parser *p)
             }
             exponent = exponent * 10 + (*cp - '0');
             cp++;
-        } while (isdigit(*cp));
+        } while (isdigit((unsigned char) *cp));
 
         if (negative_exponent) {
             pow10 -= exponent;
index fd06b81..227546e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -46,8 +46,9 @@ list_insert(struct list *before, struct list *elem)
 void
 list_splice(struct list *before, struct list *first, struct list *last)
 {
-    if (first == last)
+    if (first == last) {
         return;
+    }
     last = last->prev;
 
     /* Cleanly remove 'first'...'last' from its current list. */
@@ -160,8 +161,9 @@ list_size(const struct list *list)
     const struct list *e;
     size_t cnt = 0;
 
-    for (e = list->next; e != list; e = e->next)
+    for (e = list->next; e != list; e = e->next) {
         cnt++;
+    }
     return cnt;
 }
 
index 2aa4e89..fc3c540 100644 (file)
@@ -98,6 +98,8 @@ match_wc_init(struct match *match, const struct flow *flow)
                (flow->dl_type == htons(ETH_TYPE_RARP))) {
         memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
         memset(&wc->masks.nw_dst, 0xff, sizeof wc->masks.nw_dst);
+    } else if (eth_type_mpls(flow->dl_type)) {
+        memset(&wc->masks.mpls_lse, 0xff, sizeof wc->masks.mpls_lse);
     }
 
     if (flow->dl_type == htons(ETH_TYPE_ARP) ||
@@ -818,24 +820,6 @@ format_flow_tunnel(struct ds *s, const struct match *match)
     }
 }
 
-static void
-flow_format_mpls(const struct flow *flow, struct ds *s)
-{
-    if (flow->dl_type == htons(ETH_TYPE_MPLS)) {
-        ds_put_cstr(s, "mpls");
-    } else if (flow->dl_type == htons(ETH_TYPE_MPLS_MCAST)) {
-        ds_put_cstr(s, "mplsm");
-    } else {
-        return;
-    }
-
-    ds_put_format(s, "(label:%"PRIu32",tc:%d,ttl:%d,bos:%d),",
-                  mpls_lse_to_label(flow->mpls_lse),
-                  mpls_lse_to_tc(flow->mpls_lse),
-                  mpls_lse_to_ttl(flow->mpls_lse),
-                  mpls_lse_to_bos(flow->mpls_lse));
-}
-
 /* Appends a string representation of 'match' to 's'.  If 'priority' is
  * different from OFP_DEFAULT_PRIORITY, includes it in 's'. */
 void
@@ -901,8 +885,10 @@ match_format(const struct match *match, struct ds *s, unsigned int priority)
             ds_put_cstr(s, "arp,");
         } else if (f->dl_type == htons(ETH_TYPE_RARP)) {
             ds_put_cstr(s, "rarp,");
-        } else if (f->mpls_depth) {
-            flow_format_mpls(f, s);
+        } else if (f->dl_type == htons(ETH_TYPE_MPLS)) {
+            ds_put_cstr(s, "mpls,");
+        } else if (f->dl_type == htons(ETH_TYPE_MPLS_MCAST)) {
+            ds_put_cstr(s, "mplsm,");
         } else {
             skip_type = false;
         }
@@ -1019,6 +1005,10 @@ match_format(const struct match *match, struct ds *s, unsigned int priority)
         ds_put_format(s, "mpls_tc=%"PRIu8",",
                  mpls_lse_to_tc(f->mpls_lse));
     }
+    if (wc->masks.mpls_lse & htonl(MPLS_TTL_MASK)) {
+        ds_put_format(s, "mpls_ttl=%"PRIu8",",
+                 mpls_lse_to_ttl(f->mpls_lse));
+    }
     if (wc->masks.mpls_lse & htonl(MPLS_BOS_MASK)) {
         ds_put_format(s, "mpls_bos=%"PRIu8",",
                  mpls_lse_to_bos(f->mpls_lse));
index 1babfe9..1137390 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Nicira, Inc.
+ * Copyright (c) 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -138,7 +138,9 @@ memory_report(const struct simap *usage)
     compose_report(usage, &s);
 
     if (want_report) {
-        VLOG_INFO("%s", ds_cstr(&s));
+        if (s.length) {
+            VLOG_INFO("%s", ds_cstr(&s));
+        }
         want_report = false;
     }
     if (n_conns) {
index 6f7a3aa..9296faa 100644 (file)
@@ -359,6 +359,15 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
         MFP_IP_ANY,
         true,
         NXM_OF_IP_TOS, "NXM_OF_IP_TOS",
+        NXM_OF_IP_TOS, "NXM_OF_IP_TOS",
+    }, {
+        MFF_IP_DSCP_SHIFTED, "nw_tos_shifted", NULL,
+        MF_FIELD_SIZES(u8),
+        MFM_NONE,
+        MFS_DECIMAL,
+        MFP_IP_ANY,
+        true,
+        OXM_OF_IP_DSCP, "OXM_OF_IP_DSCP",
         OXM_OF_IP_DSCP, "OXM_OF_IP_DSCP",
     }, {
         MFF_IP_ECN, "nw_ecn", NULL,
@@ -733,6 +742,7 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
     case MFF_IP_PROTO:
         return !wc->masks.nw_proto;
     case MFF_IP_DSCP:
+    case MFF_IP_DSCP_SHIFTED:
         return !(wc->masks.nw_tos & IP_DSCP_MASK);
     case MFF_IP_ECN:
         return !(wc->masks.nw_tos & IP_ECN_MASK);
@@ -916,6 +926,8 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
 
     case MFF_IP_DSCP:
         return !(value->u8 & ~IP_DSCP_MASK);
+    case MFF_IP_DSCP_SHIFTED:
+        return !(value->u8 & (~IP_DSCP_MASK >> 2));
     case MFF_IP_ECN:
         return !(value->u8 & ~IP_ECN_MASK);
     case MFF_IP_FRAG:
@@ -1065,6 +1077,10 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
         value->u8 = flow->nw_tos & IP_DSCP_MASK;
         break;
 
+    case MFF_IP_DSCP_SHIFTED:
+        value->u8 = flow->nw_tos >> 2;
+        break;
+
     case MFF_IP_ECN:
         value->u8 = flow->nw_tos & IP_ECN_MASK;
         break;
@@ -1244,6 +1260,10 @@ mf_set_value(const struct mf_field *mf,
         match_set_nw_dscp(match, value->u8);
         break;
 
+    case MFF_IP_DSCP_SHIFTED:
+        match_set_nw_dscp(match, value->u8 << 2);
+        break;
+
     case MFF_IP_ECN:
         match_set_nw_ecn(match, value->u8);
         break;
@@ -1424,6 +1444,11 @@ mf_set_flow_value(const struct mf_field *mf,
         flow->nw_tos |= value->u8 & IP_DSCP_MASK;
         break;
 
+    case MFF_IP_DSCP_SHIFTED:
+        flow->nw_tos &= ~IP_DSCP_MASK;
+        flow->nw_tos |= value->u8 << 2;
+        break;
+
     case MFF_IP_ECN:
         flow->nw_tos &= ~IP_ECN_MASK;
         flow->nw_tos |= value->u8 & IP_ECN_MASK;
@@ -1624,6 +1649,7 @@ mf_set_wild(const struct mf_field *mf, struct match *match)
         break;
 
     case MFF_IP_DSCP:
+    case MFF_IP_DSCP_SHIFTED:
         match->wc.masks.nw_tos &= ~IP_DSCP_MASK;
         match->flow.nw_tos &= ~IP_DSCP_MASK;
         break;
@@ -1726,6 +1752,7 @@ mf_set(const struct mf_field *mf,
     case MFF_IP_PROTO:
     case MFF_IP_TTL:
     case MFF_IP_DSCP:
+    case MFF_IP_DSCP_SHIFTED:
     case MFF_IP_ECN:
     case MFF_ARP_OP:
     case MFF_ICMPV4_TYPE:
@@ -1956,6 +1983,10 @@ mf_random_value(const struct mf_field *mf, union mf_value *value)
         value->u8 &= IP_DSCP_MASK;
         break;
 
+    case MFF_IP_DSCP_SHIFTED:
+        value->u8 &= IP_DSCP_MASK >> 2;
+        break;
+
     case MFF_IP_ECN:
         value->u8 &= IP_ECN_MASK;
         break;
index 57f6df5..9577a10 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -91,8 +91,18 @@ enum mf_field_id {
     MFF_IPV6_DST,               /* ipv6 */
     MFF_IPV6_LABEL,             /* be32 */
 
+    /* The IPv4/IPv6 DSCP field has two different views:
+     *
+     *   - MFF_IP_DSCP has the DSCP in bits 2-7, their bit positions in the
+     *     IPv4 and IPv6 "traffic class" field, as used in OpenFlow 1.0 and 1.1
+     *     flow format and in NXM's NXM_OF_IP_TOS
+     *
+     *   - MFF_IP_DSCP has the DSCP in bits 0-5, shifted right two bits from
+     *     their positions in the IPv4 and IPv6 "traffic class" field, as used
+     *     in OpenFlow 1.2+ OXM's OXM_OF_IP_DSCP. */
     MFF_IP_PROTO,               /* u8 (used for IPv4 or IPv6) */
     MFF_IP_DSCP,                /* u8 (used for IPv4 or IPv6) */
+    MFF_IP_DSCP_SHIFTED,        /* u8 (used for IPv4 or IPv6) (OF1.2 compat) */
     MFF_IP_ECN,                 /* u8 (used for IPv4 or IPv6) */
     MFF_IP_TTL,                 /* u8 (used for IPv4 or IPv6) */
     MFF_IP_FRAG,                /* u8 (used for IPv4 or IPv6) */
index f46eee8..e3461b8 100644 (file)
@@ -1037,7 +1037,7 @@ netdev_bsd_get_features(const struct netdev *netdev,
     media_list = xcalloc(ifmr.ifm_count, sizeof(int));
     ifmr.ifm_ulist = media_list;
 
-    if (!IFM_TYPE(ifmr.ifm_current) & IFM_ETHER) {
+    if (IFM_TYPE(ifmr.ifm_current) != IFM_ETHER) {
         VLOG_DBG_RL(&rl, "%s: doesn't appear to be ethernet",
                     netdev_get_name(netdev));
         error = EINVAL;
index c0e0c40..722b88b 100644 (file)
@@ -139,6 +139,8 @@ struct tc {
                                  * Written only by TC implementation. */
 };
 
+#define TC_INITIALIZER(TC, OPS) { OPS, HMAP_INITIALIZER(&(TC)->queues) }
+
 /* One traffic control queue.
  *
  * Each TC implementation subclasses this with whatever additional data it
@@ -311,7 +313,7 @@ static const struct tc_ops tc_ops_hfsc;
 static const struct tc_ops tc_ops_default;
 static const struct tc_ops tc_ops_other;
 
-static const struct tc_ops *tcs[] = {
+static const struct tc_ops *const tcs[] = {
     &tc_ops_htb,                /* Hierarchy token bucket (see tc-htb(8)). */
     &tc_ops_hfsc,               /* Hierarchical fair service curve. */
     &tc_ops_default,            /* Default qdisc (see tc-pfifo_fast(8)). */
@@ -1851,7 +1853,7 @@ static int
 netdev_linux_get_qos_types(const struct netdev *netdev OVS_UNUSED,
                            struct sset *types)
 {
-    const struct tc_ops **opsp;
+    const struct tc_ops *const *opsp;
 
     for (opsp = tcs; *opsp != NULL; opsp++) {
         const struct tc_ops *ops = *opsp;
@@ -1865,7 +1867,7 @@ netdev_linux_get_qos_types(const struct netdev *netdev OVS_UNUSED,
 static const struct tc_ops *
 tc_lookup_ovs_name(const char *name)
 {
-    const struct tc_ops **opsp;
+    const struct tc_ops *const *opsp;
 
     for (opsp = tcs; *opsp != NULL; opsp++) {
         const struct tc_ops *ops = *opsp;
@@ -1879,7 +1881,7 @@ tc_lookup_ovs_name(const char *name)
 static const struct tc_ops *
 tc_lookup_linux_name(const char *name)
 {
-    const struct tc_ops **opsp;
+    const struct tc_ops *const *opsp;
 
     for (opsp = tcs; *opsp != NULL; opsp++) {
         const struct tc_ops *ops = *opsp;
@@ -3559,13 +3561,11 @@ default_install__(struct netdev *netdev)
 {
     struct netdev_dev_linux *netdev_dev =
                                 netdev_dev_linux_cast(netdev_get_dev(netdev));
-    static struct tc *tc;
+    static const struct tc tc = TC_INITIALIZER(&tc, &tc_ops_default);
 
-    if (!tc) {
-        tc = xmalloc(sizeof *tc);
-        tc_init(tc, &tc_ops_default);
-    }
-    netdev_dev->tc = tc;
+    /* Nothing but a tc class implementation is allowed to write to a tc.  This
+     * class never does that, so we can legitimately use a const tc object. */
+    netdev_dev->tc = CONST_CAST(struct tc *, &tc);
 }
 
 static int
@@ -3608,13 +3608,11 @@ other_tc_load(struct netdev *netdev, struct ofpbuf *nlmsg OVS_UNUSED)
 {
     struct netdev_dev_linux *netdev_dev =
                                 netdev_dev_linux_cast(netdev_get_dev(netdev));
-    static struct tc *tc;
+    static const struct tc tc = TC_INITIALIZER(&tc, &tc_ops_other);
 
-    if (!tc) {
-        tc = xmalloc(sizeof *tc);
-        tc_init(tc, &tc_ops_other);
-    }
-    netdev_dev->tc = tc;
+    /* Nothing but a tc class implementation is allowed to write to a tc.  This
+     * class never does that, so we can legitimately use a const tc object. */
+    netdev_dev->tc = CONST_CAST(struct tc *, &tc);
     return 0;
 }
 
index 4aa8bb0..08169a1 100644 (file)
@@ -41,9 +41,7 @@
 
 VLOG_DEFINE_THIS_MODULE(netdev_vport);
 
-/* Default to the OTV port, per the VXLAN IETF draft. */
-#define VXLAN_DST_PORT 8472
-
+#define VXLAN_DST_PORT 4789
 #define LISP_DST_PORT 4341
 
 #define DEFAULT_TTL 64
index e6b10a1..fbb1724 100644 (file)
@@ -59,8 +59,7 @@ static void log_nlmsg(const char *function, int error,
 \f
 /* Netlink sockets. */
 
-struct nl_sock
-{
+struct nl_sock {
     int fd;
     uint32_t next_seq;
     uint32_t pid;
@@ -111,10 +110,7 @@ nl_sock_create(int protocol, struct nl_sock **sockp)
     }
 
     *sockp = NULL;
-    sock = malloc(sizeof *sock);
-    if (sock == NULL) {
-        return ENOMEM;
-    }
+    sock = xmalloc(sizeof *sock);
 
     sock->fd = socket(AF_NETLINK, SOCK_RAW, protocol);
     if (sock->fd < 0) {
@@ -130,7 +126,7 @@ nl_sock_create(int protocol, struct nl_sock **sockp)
                    &rcvbuf, sizeof rcvbuf)) {
         /* Only root can use SO_RCVBUFFORCE.  Everyone else gets EPERM.
          * Warn only if the failure is therefore unexpected. */
-        if (errno != EPERM || !getuid()) {
+        if (errno != EPERM) {
             VLOG_WARN_RL(&rl, "setting %d-byte socket receive buffer failed "
                          "(%s)", rcvbuf, strerror(errno));
         }
index bfead68..b328f02 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -517,8 +517,11 @@ nxm_put_ip(struct ofpbuf *b, const struct match *match,
     nxm_put_frag(b, match);
 
     if (match->wc.masks.nw_tos & IP_DSCP_MASK) {
-        nxm_put_8(b, oxm ? OXM_OF_IP_DSCP : NXM_OF_IP_TOS,
-                  flow->nw_tos & IP_DSCP_MASK);
+        if (oxm) {
+            nxm_put_8(b, OXM_OF_IP_DSCP, flow->nw_tos >> 2);
+        } else {
+            nxm_put_8(b, NXM_OF_IP_TOS, flow->nw_tos & IP_DSCP_MASK);
+        }
     }
 
     if (match->wc.masks.nw_tos & IP_ECN_MASK) {
index 751c1c9..ae09267 100644 (file)
@@ -262,43 +262,60 @@ format_odp_userspace_action(struct ds *ds, const struct nlattr *attr)
                   nl_attr_get_u32(a[OVS_USERSPACE_ATTR_PID]));
 
     userdata_attr = a[OVS_USERSPACE_ATTR_USERDATA];
-    if (userdata_attr && nl_attr_get_size(userdata_attr) == sizeof(uint64_t)) {
-        uint64_t userdata = nl_attr_get_u64(a[OVS_USERSPACE_ATTR_USERDATA]);
-        union user_action_cookie cookie;
-
-        memcpy(&cookie, &userdata, sizeof cookie);
-
-        switch (cookie.type) {
-        case USER_ACTION_COOKIE_SFLOW:
-            ds_put_format(ds, ",sFlow("
-                          "vid=%"PRIu16",pcp=%"PRIu8",output=%"PRIu32")",
-                          vlan_tci_to_vid(cookie.sflow.vlan_tci),
-                          vlan_tci_to_pcp(cookie.sflow.vlan_tci),
-                          cookie.sflow.output);
-            break;
 
-        case USER_ACTION_COOKIE_SLOW_PATH:
-            ds_put_cstr(ds, ",slow_path(");
-            format_flags(ds, slow_path_reason_to_string,
-                         cookie.slow_path.reason, ',');
-            ds_put_format(ds, ")");
-            break;
+    if (userdata_attr) {
+        const uint8_t *userdata = nl_attr_get(userdata_attr);
+        size_t userdata_len = nl_attr_get_size(userdata_attr);
+        bool userdata_unspec = true;
+        union user_action_cookie cookie;
 
-        case USER_ACTION_COOKIE_UNSPEC:
-        default:
-            ds_put_format(ds, ",userdata=0x%"PRIx64, userdata);
-            break;
+        if (userdata_len >= sizeof cookie.type
+            && userdata_len <= sizeof cookie) {
+
+            memset(&cookie, 0, sizeof cookie);
+            memcpy(&cookie, userdata, userdata_len);
+
+            userdata_unspec = false;
+
+            if (userdata_len == sizeof cookie.sflow
+                && cookie.type == USER_ACTION_COOKIE_SFLOW) {
+                ds_put_format(ds, ",sFlow("
+                              "vid=%"PRIu16",pcp=%"PRIu8",output=%"PRIu32")",
+                              vlan_tci_to_vid(cookie.sflow.vlan_tci),
+                              vlan_tci_to_pcp(cookie.sflow.vlan_tci),
+                              cookie.sflow.output);
+            } else if (userdata_len == sizeof cookie.slow_path
+                       && cookie.type == USER_ACTION_COOKIE_SLOW_PATH) {
+                ds_put_cstr(ds, ",slow_path(");
+                format_flags(ds, slow_path_reason_to_string,
+                             cookie.slow_path.reason, ',');
+                ds_put_format(ds, ")");
+            } else if (userdata_len == sizeof cookie.flow_sample
+                       && cookie.type == USER_ACTION_COOKIE_FLOW_SAMPLE) {
+                ds_put_format(ds, ",flow_sample(probability=%"PRIu16
+                              ",collector_set_id=%"PRIu32
+                              ",obs_domain_id=%"PRIu32
+                              ",obs_point_id=%"PRIu32")",
+                              cookie.flow_sample.probability,
+                              cookie.flow_sample.collector_set_id,
+                              cookie.flow_sample.obs_domain_id,
+                              cookie.flow_sample.obs_point_id);
+            } else if (userdata_len == sizeof cookie.ipfix
+                       && cookie.type == USER_ACTION_COOKIE_IPFIX) {
+                ds_put_format(ds, ",ipfix");
+            } else {
+                userdata_unspec = true;
+            }
         }
-    } else if (userdata_attr) {
-        const uint8_t *userdata = nl_attr_get(userdata_attr);
-        size_t len = nl_attr_get_size(userdata_attr);
-        size_t i;
 
-        ds_put_format(ds, ",userdata(");
-        for (i = 0; i < len; i++) {
-            ds_put_format(ds, "%02x", userdata[i]);
+        if (userdata_unspec) {
+            size_t i;
+            ds_put_format(ds, ",userdata(");
+            for (i = 0; i < userdata_len; i++) {
+                ds_put_format(ds, "%02x", userdata[i]);
+            }
+            ds_put_char(ds, ')');
         }
-        ds_put_char(ds, ')');
     }
 
     ds_put_char(ds, ')');
@@ -456,7 +473,10 @@ parse_odp_action(const char *s, const struct simap *port_names,
     {
         unsigned long long int pid;
         unsigned long long int output;
-        char userdata_s[32];
+        unsigned long long int probability;
+        unsigned long long int collector_set_id;
+        unsigned long long int obs_domain_id;
+        unsigned long long int obs_point_id;
         int vid, pcp;
         int n = -1;
 
@@ -477,7 +497,8 @@ parse_odp_action(const char *s, const struct simap *port_names,
             cookie.type = USER_ACTION_COOKIE_SFLOW;
             cookie.sflow.vlan_tci = htons(tci);
             cookie.sflow.output = output;
-            odp_put_userspace_action(pid, &cookie, sizeof cookie, actions);
+            odp_put_userspace_action(pid, &cookie, sizeof cookie.sflow,
+                                     actions);
             return n;
         } else if (sscanf(s, "userspace(pid=%lli,slow_path%n", &pid, &n) > 0
                    && n > 0) {
@@ -499,15 +520,30 @@ parse_odp_action(const char *s, const struct simap *port_names,
             }
             n++;
 
-            odp_put_userspace_action(pid, &cookie, sizeof cookie, actions);
+            odp_put_userspace_action(pid, &cookie, sizeof cookie.slow_path,
+                                     actions);
             return n;
-        } else if (sscanf(s, "userspace(pid=%lli,userdata="
-                          "%31[x0123456789abcdefABCDEF])%n", &pid, userdata_s,
-                          &n) > 0 && n > 0) {
-            uint64_t userdata;
+        } else if (sscanf(s, "userspace(pid=%lli,flow_sample(probability=%lli,"
+                          "collector_set_id=%lli,obs_domain_id=%lli,"
+                          "obs_point_id=%lli))%n",
+                          &pid, &probability, &collector_set_id,
+                          &obs_domain_id, &obs_point_id, &n) > 0 && n > 0) {
+            union user_action_cookie cookie;
 
-            userdata = strtoull(userdata_s, NULL, 0);
-            odp_put_userspace_action(pid, &userdata, sizeof(userdata),
+            cookie.type = USER_ACTION_COOKIE_FLOW_SAMPLE;
+            cookie.flow_sample.probability = probability;
+            cookie.flow_sample.collector_set_id = collector_set_id;
+            cookie.flow_sample.obs_domain_id = obs_domain_id;
+            cookie.flow_sample.obs_point_id = obs_point_id;
+            odp_put_userspace_action(pid, &cookie, sizeof cookie.flow_sample,
+                                     actions);
+            return n;
+        } else if (sscanf(s, "userspace(pid=%lli,ipfix)%n", &pid, &n) > 0
+                   && n > 0) {
+            union user_action_cookie cookie;
+
+            cookie.type = USER_ACTION_COOKIE_IPFIX;
+            odp_put_userspace_action(pid, &cookie, sizeof cookie.ipfix,
                                      actions);
             return n;
         } else if (sscanf(s, "userspace(pid=%lli,userdata(%n", &pid, &n) > 0
@@ -906,7 +942,7 @@ format_odp_key_attr(const struct nlattr *a, struct ds *ds)
     case OVS_KEY_ATTR_MPLS: {
         const struct ovs_key_mpls *mpls_key = nl_attr_get(a);
         ds_put_char(ds, '(');
-        format_mpls_lse(ds, mpls_key->mpls_top_lse);
+        format_mpls_lse(ds, mpls_key->mpls_lse);
         ds_put_char(ds, ')');
         break;
     }
@@ -1231,7 +1267,7 @@ parse_odp_key_attr(const char *s, const struct simap *port_names,
 
             mpls = nl_msg_put_unspec_uninit(key, OVS_KEY_ATTR_MPLS,
                                             sizeof *mpls);
-            mpls->mpls_top_lse = mpls_lse_from_components(label, tc, ttl, bos);
+            mpls->mpls_lse = mpls_lse_from_components(label, tc, ttl, bos);
             return n;
         }
     }
@@ -1594,7 +1630,7 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow,
 
         mpls_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_MPLS,
                                             sizeof *mpls_key);
-        mpls_key->mpls_top_lse = flow->mpls_lse;
+        mpls_key->mpls_lse = flow->mpls_lse;
     }
 
     if (is_ip_any(flow) && !(flow->nw_frag & FLOW_NW_FRAG_LATER)) {
@@ -2161,13 +2197,12 @@ void
 commit_odp_tunnel_action(const struct flow *flow, struct flow *base,
                          struct ofpbuf *odp_actions)
 {
-    if (!memcmp(&base->tunnel, &flow->tunnel, sizeof base->tunnel)) {
-        return;
-    }
-    memcpy(&base->tunnel, &flow->tunnel, sizeof base->tunnel);
-
     /* A valid IPV4_TUNNEL must have non-zero ip_dst. */
     if (flow->tunnel.ip_dst) {
+        if (!memcmp(&base->tunnel, &flow->tunnel, sizeof base->tunnel)) {
+            return;
+        }
+        memcpy(&base->tunnel, &flow->tunnel, sizeof base->tunnel);
         odp_put_tunnel_action(&base->tunnel, odp_actions);
     }
 }
@@ -2250,7 +2285,7 @@ commit_mpls_action(const struct flow *flow, struct flow *base,
     } else {
         struct ovs_key_mpls mpls_key;
 
-        mpls_key.mpls_top_lse = flow->mpls_lse;
+        mpls_key.mpls_lse = flow->mpls_lse;
         commit_set_action(odp_actions, OVS_KEY_ATTR_MPLS,
                           &mpls_key, sizeof(mpls_key));
     }
index ad0fb30..0b34383 100644 (file)
@@ -127,8 +127,10 @@ void commit_odp_actions(const struct flow *, struct flow *base,
 
 enum user_action_cookie_type {
     USER_ACTION_COOKIE_UNSPEC,
-    USER_ACTION_COOKIE_SFLOW,        /* Packet for sFlow sampling. */
-    USER_ACTION_COOKIE_SLOW_PATH     /* Userspace must process this flow. */
+    USER_ACTION_COOKIE_SFLOW,        /* Packet for per-bridge sFlow sampling. */
+    USER_ACTION_COOKIE_SLOW_PATH,    /* Userspace must process this flow. */
+    USER_ACTION_COOKIE_FLOW_SAMPLE,  /* Packet for per-flow sampling. */
+    USER_ACTION_COOKIE_IPFIX,        /* Packet for per-bridge IPFIX sampling. */
 };
 
 /* user_action_cookie is passed as argument to OVS_ACTION_ATTR_USERSPACE.
@@ -147,8 +149,20 @@ union user_action_cookie {
         uint16_t unused;
         uint32_t reason;        /* enum slow_path_reason. */
     } slow_path;
+
+    struct {
+        uint16_t type;          /* USER_ACTION_COOKIE_FLOW_SAMPLE. */
+        uint16_t probability;   /* Sampling probability. */
+        uint32_t collector_set_id; /* ID of IPFIX collector set. */
+        uint32_t obs_domain_id; /* Observation Domain ID. */
+        uint32_t obs_point_id;  /* Observation Point ID. */
+    } flow_sample;
+
+    struct {
+        uint16_t type;          /* USER_ACTION_COOKIE_IPFIX. */
+    } ipfix;
 };
-BUILD_ASSERT_DECL(sizeof(union user_action_cookie) == 8);
+BUILD_ASSERT_DECL(sizeof(union user_action_cookie) == 16);
 
 size_t odp_put_userspace_action(uint32_t pid,
                                 const void *userdata, size_t userdata_size,
index d405d2d..068699f 100644 (file)
@@ -217,6 +217,25 @@ dec_ttl_cnt_ids_from_openflow(const struct nx_action_cnt_ids *nac_ids,
     return 0;
 }
 
+static enum ofperr
+sample_from_openflow(const struct nx_action_sample *nas,
+                     struct ofpbuf *out)
+{
+    struct ofpact_sample *sample;
+
+    sample = ofpact_put_SAMPLE(out);
+    sample->probability = ntohs(nas->probability);
+    sample->collector_set_id = ntohl(nas->collector_set_id);
+    sample->obs_domain_id = ntohl(nas->obs_domain_id);
+    sample->obs_point_id = ntohl(nas->obs_point_id);
+
+    if (sample->probability == 0) {
+        return OFPERR_OFPBAC_BAD_ARGUMENT;
+    }
+
+    return 0;
+}
+
 static enum ofperr
 decode_nxast_action(const union ofp_action *a, enum ofputil_action_code *code)
 {
@@ -434,6 +453,11 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code,
         ofpact_put_POP_MPLS(out)->ethertype = nxapm->ethertype;
         break;
     }
+
+    case OFPUTIL_NXAST_SAMPLE:
+        error = sample_from_openflow(
+            (const struct nx_action_sample *) a, out);
+        break;
     }
 
     return error;
@@ -1199,6 +1223,9 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports,
         *dl_type = ofpact_get_POP_MPLS(a)->ethertype;
         return 0;
 
+    case OFPACT_SAMPLE:
+        return 0;
+
     case OFPACT_CLEAR_ACTIONS:
     case OFPACT_WRITE_METADATA:
     case OFPACT_GOTO_TABLE:
@@ -1393,6 +1420,19 @@ ofpact_fin_timeout_to_nxast(const struct ofpact_fin_timeout *fin_timeout,
     naft->fin_hard_timeout = htons(fin_timeout->fin_hard_timeout);
 }
 
+static void
+ofpact_sample_to_nxast(const struct ofpact_sample *os,
+                       struct ofpbuf *out)
+{
+    struct nx_action_sample *nas;
+
+    nas = ofputil_put_NXAST_SAMPLE(out);
+    nas->probability = htons(os->probability);
+    nas->collector_set_id = htonl(os->collector_set_id);
+    nas->obs_domain_id = htonl(os->obs_domain_id);
+    nas->obs_point_id = htonl(os->obs_point_id);
+}
+
 static void
 ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out)
 {
@@ -1489,6 +1529,10 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out)
             ofpact_get_POP_MPLS(a)->ethertype;
         break;
 
+    case OFPACT_SAMPLE:
+        ofpact_sample_to_nxast(ofpact_get_SAMPLE(a), out);
+        break;
+
     case OFPACT_OUTPUT:
     case OFPACT_ENQUEUE:
     case OFPACT_SET_VLAN_VID:
@@ -1621,6 +1665,7 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out)
     case OFPACT_EXIT:
     case OFPACT_PUSH_MPLS:
     case OFPACT_POP_MPLS:
+    case OFPACT_SAMPLE:
         ofpact_to_nxast(a, out);
         break;
     }
@@ -1784,6 +1829,7 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out)
     case OFPACT_MULTIPATH:
     case OFPACT_NOTE:
     case OFPACT_EXIT:
+    case OFPACT_SAMPLE:
         ofpact_to_nxast(a, out);
         break;
     }
@@ -1912,6 +1958,7 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, uint16_t port)
     case OFPACT_EXIT:
     case OFPACT_PUSH_MPLS:
     case OFPACT_POP_MPLS:
+    case OFPACT_SAMPLE:
     case OFPACT_CLEAR_ACTIONS:
     case OFPACT_GOTO_TABLE:
     default:
@@ -2003,6 +2050,7 @@ ofpact_format(const struct ofpact *a, struct ds *s)
     const struct ofpact_controller *controller;
     const struct ofpact_metadata *metadata;
     const struct ofpact_tunnel *tunnel;
+    const struct ofpact_sample *sample;
     uint16_t port;
 
     switch (a->type) {
@@ -2204,6 +2252,15 @@ ofpact_format(const struct ofpact *a, struct ds *s)
         ds_put_cstr(s, "exit");
         break;
 
+    case OFPACT_SAMPLE:
+        sample = ofpact_get_SAMPLE(a);
+        ds_put_format(
+            s, "sample(probability=%"PRIu16",collector_set_id=%"PRIu32
+            ",obs_domain_id=%"PRIu32",obs_point_id=%"PRIu32")",
+            sample->probability, sample->collector_set_id,
+            sample->obs_domain_id, sample->obs_point_id);
+        break;
+
     case OFPACT_CLEAR_ACTIONS:
         ds_put_format(s, "%s",
                       ofpact_instruction_name_from_type(
index 0189c8a..ffceb05 100644 (file)
@@ -94,6 +94,7 @@
     /* Other. */                                                    \
     DEFINE_OFPACT(NOTE,            ofpact_note,          data)      \
     DEFINE_OFPACT(EXIT,            ofpact_null,          ofpact)    \
+    DEFINE_OFPACT(SAMPLE,          ofpact_sample,        ofpact)    \
                                                                     \
     /* Instructions */                                              \
     /* XXX Write-Actions */                                         \
@@ -441,6 +442,17 @@ struct ofpact_note {
     uint8_t data[];
 };
 
+/* OFPACT_SAMPLE.
+ *
+ * Used for NXAST_SAMPLE. */
+struct ofpact_sample {
+    struct ofpact ofpact;
+    uint16_t probability;  // Always >0.
+    uint32_t collector_set_id;
+    uint32_t obs_domain_id;
+    uint32_t obs_point_id;
+};
+
 /* OFPACT_DEC_TTL.
  *
  * Used for OFPAT11_DEC_NW_TTL, NXAST_DEC_TTL and NXAST_DEC_TTL_CNT_IDS. */
index e8abc9f..295c038 100644 (file)
@@ -389,6 +389,34 @@ parse_metadata(struct ofpbuf *b, char *arg)
     om->metadata = htonll(str_to_u64(arg));
 }
 
+static void
+parse_sample(struct ofpbuf *b, char *arg)
+{
+    struct ofpact_sample *os = ofpact_put_SAMPLE(b);
+    char *key, *value;
+
+    while (ofputil_parse_key_value(&arg, &key, &value)) {
+        if (!strcmp(key, "probability")) {
+            os->probability = str_to_u16(value, "probability");
+            if (os->probability == 0) {
+                ovs_fatal(0, "invalid probability value \"%s\"", value);
+            }
+        } else if (!strcmp(key, "collector_set_id")) {
+            os->collector_set_id = str_to_u32(value);
+        } else if (!strcmp(key, "obs_domain_id")) {
+            os->obs_domain_id = str_to_u32(value);
+        } else if (!strcmp(key, "obs_point_id")) {
+            os->obs_point_id = str_to_u32(value);
+        } else {
+            ovs_fatal(0, "invalid key \"%s\" in \"sample\" argument",
+                      key);
+        }
+    }
+    if (os->probability == 0) {
+        ovs_fatal(0, "non-zero \"probability\" must be specified on sample");
+    }
+}
+
 static void
 parse_named_action(enum ofputil_action_code code, const struct flow *flow,
                    char *arg, struct ofpbuf *ofpacts)
@@ -591,12 +619,17 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
         ofpact_put_POP_MPLS(ofpacts)->ethertype =
             htons(str_to_u16(arg, "pop_mpls"));
         break;
+
     case OFPUTIL_NXAST_STACK_PUSH:
         nxm_parse_stack_action(ofpact_put_STACK_PUSH(ofpacts), arg);
         break;
     case OFPUTIL_NXAST_STACK_POP:
         nxm_parse_stack_action(ofpact_put_STACK_POP(ofpacts), arg);
         break;
+
+    case OFPUTIL_NXAST_SAMPLE:
+        parse_sample(ofpacts, arg);
+        break;
     }
 }
 
index 6b78f84..42c3613 100644 (file)
@@ -922,7 +922,7 @@ ofputil_version_from_string(const char *s)
 }
 
 static bool
-is_delimiter(char c)
+is_delimiter(unsigned char c)
 {
     return isspace(c) || c == ',';
 }
index b7dde48..d88d420 100644 (file)
@@ -71,6 +71,7 @@ NXAST_ACTION(NXAST_SET_MPLS_TTL,    nx_action_mpls_ttl,     0, "set_mpls_ttl")
 NXAST_ACTION(NXAST_DEC_MPLS_TTL,    nx_action_header,       0, "dec_mpls_ttl")
 NXAST_ACTION(NXAST_PUSH_MPLS,       nx_action_push_mpls,    0, "push_mpls")
 NXAST_ACTION(NXAST_POP_MPLS,        nx_action_pop_mpls,     0, "pop_mpls")
+NXAST_ACTION(NXAST_SAMPLE,          nx_action_sample,       0, "sample")
 
 #undef OFPAT10_ACTION
 #undef OFPAT11_ACTION
index 795a136..9fe742c 100644 (file)
@@ -640,7 +640,7 @@ sigchld_is_blocked(void)
 {
     sigset_t sigs;
 
-    xsigprocmask(SIG_SETMASK, NULL, &sigs);
+    xpthread_sigmask(SIG_SETMASK, NULL, &sigs);
     return sigismember(&sigs, SIGCHLD);
 }
 
@@ -651,11 +651,11 @@ block_sigchld(sigset_t *oldsigs)
 
     sigemptyset(&sigchld);
     sigaddset(&sigchld, SIGCHLD);
-    xsigprocmask(SIG_BLOCK, &sigchld, oldsigs);
+    xpthread_sigmask(SIG_BLOCK, &sigchld, oldsigs);
 }
 
 static void
 unblock_sigchld(const sigset_t *oldsigs)
 {
-    xsigprocmask(SIG_SETMASK, oldsigs, NULL);
+    xpthread_sigmask(SIG_SETMASK, oldsigs, NULL);
 }
index eb4a168..38cd2c9 100644 (file)
@@ -97,7 +97,13 @@ route_table_get_name(ovs_be32 ip, char name[IFNAMSIZ])
                 name[namelen] = '\0';
                 return true;
             }
+#if defined(__FreeBSD__)
             sa = (struct sockaddr *)((char *)sa + SA_SIZE(sa));
+#elif defined(__NetBSD__)
+            sa = (struct sockaddr *)((char *)sa + RT_ROUNDUP(sa->sa_len));
+#else
+#error unimplemented
+#endif
         }
     }
     return false;
index 804cb3f..6403b6d 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef ROUTE_TABLE_H
 #define ROUTE_TABLE_H 1
 
+#include <sys/types.h>
 #include <sys/socket.h>
 #include <net/if.h>
 #include <stdbool.h>
index 8ea9693..0d1f2b9 100644 (file)
@@ -8,6 +8,13 @@
 #ifndef SFLOW_H
 #define SFLOW_H 1
 
+typedef enum {
+    SFL_DSCLASS_IFINDEX = 0,
+    SFL_DSCLASS_VLAN = 1,
+    SFL_DSCLASS_PHYSICAL_ENTITY = 2,
+    SFL_DSCLASS_LOGICAL_ENTITY = 3
+} SFL_DSCLASS;
+
 enum SFLAddress_type {
     SFLADDRESSTYPE_IP_V4 = 1,
     SFLADDRESSTYPE_IP_V6 = 2
index 06c2e75..f31bc52 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -168,9 +168,10 @@ xsigaction(int signum, const struct sigaction *new, struct sigaction *old)
 }
 
 void
-xsigprocmask(int how, const sigset_t *new, sigset_t *old)
+xpthread_sigmask(int how, const sigset_t *new, sigset_t *old)
 {
-    if (sigprocmask(how, new, old)) {
-        VLOG_FATAL("sigprocmask failed (%s)", strerror(errno));
+    int error = pthread_sigmask(how, new, old);
+    if (error) {
+        VLOG_FATAL("pthread_sigmask failed (%s)", strerror(error));
     }
 }
index ac96b0f..641bcbb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2011 Nicira, Inc.
+ * Copyright (c) 2008, 2011, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,6 +31,6 @@ void signal_wait(struct signal *);
 const char *signal_name(int signum);
 
 void xsigaction(int signum, const struct sigaction *, struct sigaction *old);
-void xsigprocmask(int how, const sigset_t *, sigset_t *old);
+void xpthread_sigmask(int how, const sigset_t *, sigset_t *old);
 
 #endif /* signals.h */
index 54b339f..0d75733 100644 (file)
@@ -15,6 +15,8 @@
 #include <config.h>
 #include "smap.h"
 
+#include <strings.h>
+
 #include "hash.h"
 #include "json.h"
 
index 9fea7bd..906b970 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -178,30 +178,57 @@ lookup_ipv6(const char *host_name, struct in6_addr *addr)
  * successful, otherwise a positive errno value.
  *
  * Most Open vSwitch code should not use this because it causes deadlocks:
- * gethostbyname() sends out a DNS request but that starts a new flow for which
+ * getaddrinfo() sends out a DNS request but that starts a new flow for which
  * OVS must set up a flow, but it can't because it's waiting for a DNS reply.
  * The synchronous lookup also delays other activity.  (Of course we can solve
  * this but it doesn't seem worthwhile quite yet.)  */
 int
 lookup_hostname(const char *host_name, struct in_addr *addr)
 {
-    struct hostent *h;
+    struct addrinfo *result;
+    struct addrinfo hints;
 
     if (inet_aton(host_name, addr)) {
         return 0;
     }
 
-    h = gethostbyname(host_name);
-    if (h) {
-        *addr = *(struct in_addr *) h->h_addr;
+    memset(&hints, 0, sizeof hints);
+    hints.ai_family = AF_INET;
+
+    switch (getaddrinfo(host_name, NULL, &hints, &result)) {
+    case 0:
+        *addr = ((struct sockaddr_in *) result->ai_addr)->sin_addr;
+        freeaddrinfo(result);
         return 0;
-    }
 
-    return (h_errno == HOST_NOT_FOUND ? ENOENT
-            : h_errno == TRY_AGAIN ? EAGAIN
-            : h_errno == NO_RECOVERY ? EIO
-            : h_errno == NO_ADDRESS ? ENXIO
-            : EINVAL);
+    case EAI_ADDRFAMILY:
+    case EAI_NONAME:
+    case EAI_SERVICE:
+        return ENOENT;
+
+    case EAI_AGAIN:
+        return EAGAIN;
+
+    case EAI_BADFLAGS:
+    case EAI_FAMILY:
+    case EAI_SOCKTYPE:
+        return EINVAL;
+
+    case EAI_FAIL:
+        return EIO;
+
+    case EAI_MEMORY:
+        return ENOMEM;
+
+    case EAI_NODATA:
+        return ENXIO;
+
+    case EAI_SYSTEM:
+        return errno;
+
+    default:
+        return EPROTO;
+    }
 }
 
 int
@@ -684,6 +711,7 @@ int
 inet_open_passive(int style, const char *target, int default_port,
                   struct sockaddr_in *sinp, uint8_t dscp)
 {
+    bool kernel_chooses_port;
     struct sockaddr_in sin;
     int fd = 0, error;
     unsigned int yes = 1;
@@ -733,9 +761,10 @@ inet_open_passive(int style, const char *target, int default_port,
         goto error;
     }
 
-    if (sinp) {
+    kernel_chooses_port = sin.sin_port == htons(0);
+    if (sinp || kernel_chooses_port) {
         socklen_t sin_len = sizeof sin;
-        if (getsockname(fd, (struct sockaddr *) &sin, &sin_len) < 0){
+        if (getsockname(fd, (struct sockaddr *) &sin, &sin_len) < 0) {
             error = errno;
             VLOG_ERR("%s: getsockname: %s", target, strerror(error));
             goto error;
@@ -745,7 +774,13 @@ inet_open_passive(int style, const char *target, int default_port,
             VLOG_ERR("%s: getsockname: invalid socket name", target);
             goto error;
         }
-        *sinp = sin;
+        if (sinp) {
+            *sinp = sin;
+        }
+        if (kernel_chooses_port) {
+            VLOG_INFO("%s: listening on port %"PRIu16,
+                      target, ntohs(sin.sin_port));
+        }
     }
 
     return fd;
index 5bf8529..96aad5d 100644 (file)
@@ -23,6 +23,7 @@
 #include <netinet/in.h>
 #include <stdbool.h>
 #include "openvswitch/types.h"
+#include <netinet/in_systm.h>
 #include <netinet/ip.h>
 
 int set_nonblocking(int fd);
index c5b616f..443538d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -268,3 +268,37 @@ sset_at_position(const struct sset *set, uint32_t *bucketp, uint32_t *offsetp)
     hmap_node = hmap_at_position(&set->map, bucketp, offsetp);
     return SSET_NODE_FROM_HMAP_NODE(hmap_node);
 }
+
+static int
+compare_string_pointers(const void *a_, const void *b_)
+{
+    const char *const *a = a_;
+    const char *const *b = b_;
+
+    return strcmp(*a, *b);
+}
+
+/* Returns a null-terminated array of pointers to the strings in 'set', sorted
+ * alphabetically.  The caller must free the returned array when it is no
+ * longer needed, but the strings in the array belong to 'set' and thus must
+ * not be modified or freed. */
+const char **
+sset_sort(const struct sset *set)
+{
+    size_t n = sset_count(set);
+    const char **array;
+    const char *s;
+    size_t i;
+
+    array = xmalloc(sizeof *array * (n + 1));
+    i = 0;
+    SSET_FOR_EACH (s, set) {
+        array[i++] = s;
+    }
+    ovs_assert(i == n);
+    array[n] = NULL;
+
+    qsort(array, n, sizeof *array, compare_string_pointers);
+
+    return array;
+}
index 327074c..625cea9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -79,6 +79,8 @@ struct sset_node *sset_at_position(const struct sset *,
           ? (NEXT) = SSET_NEXT(SSET, NAME), true    \
           : false);                                 \
          (NAME) = (NEXT))
+
+const char **sset_sort(const struct sset *);
 \f
 /* Implementation helper macros. */
 
index 1db3735..43c63e8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, 2012 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -139,9 +139,11 @@ struct stream_class {
 struct pstream {
     const struct pstream_class *class;
     char *name;
+    ovs_be16 bound_port;
 };
 
 void pstream_init(struct pstream *, const struct pstream_class *, const char *name);
+void pstream_set_bound_port(struct pstream *, ovs_be16 bound_port);
 static inline void pstream_assert_class(const struct pstream *pstream,
                                         const struct pstream_class *class)
 {
index 23c5591..ddf65a3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -808,6 +808,7 @@ pssl_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp,
 
     pssl = xmalloc(sizeof *pssl);
     pstream_init(&pssl->pstream, &pssl_pstream_class, bound_name);
+    pstream_set_bound_port(&pssl->pstream, sin.sin_port);
     pssl->fd = fd;
     *pstreamp = &pssl->pstream;
     return 0;
index 0384c42..1767fe4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -108,6 +108,7 @@ ptcp_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp,
 {
     struct sockaddr_in sin;
     char bound_name[128];
+    int error;
     int fd;
 
     fd = inet_open_passive(SOCK_STREAM, suffix, -1, &sin, dscp);
@@ -117,8 +118,12 @@ ptcp_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp,
 
     sprintf(bound_name, "ptcp:%"PRIu16":"IP_FMT,
             ntohs(sin.sin_port), IP_ARGS(sin.sin_addr.s_addr));
-    return new_fd_pstream(bound_name, fd, ptcp_accept, set_dscp, NULL,
-                          pstreamp);
+    error = new_fd_pstream(bound_name, fd, ptcp_accept, set_dscp, NULL,
+                           pstreamp);
+    if (!error) {
+        pstream_set_bound_port(*pstreamp, sin.sin_port);
+    }
+    return error;
 }
 
 static int
index 0c6a8c1..da089ae 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -621,6 +621,14 @@ pstream_set_dscp(struct pstream *pstream, uint8_t dscp)
     }
     return 0;
 }
+
+/* Returns the transport port on which 'pstream' is listening, or 0 if the
+ * concept doesn't apply. */
+ovs_be16
+pstream_get_bound_port(const struct pstream *pstream)
+{
+    return pstream->bound_port;
+}
 \f
 /* Initializes 'stream' as a new stream named 'name', implemented via 'class'.
  * The initial connection status, supplied as 'connect_status', is interpreted
@@ -681,9 +689,16 @@ void
 pstream_init(struct pstream *pstream, const struct pstream_class *class,
             const char *name)
 {
+    memset(pstream, 0, sizeof *pstream);
     pstream->class = class;
     pstream->name = xstrdup(name);
 }
+
+void
+pstream_set_bound_port(struct pstream *pstream, ovs_be16 port)
+{
+    pstream->bound_port = port;
+}
 \f
 static int
 count_fields(const char *s_)
index d2f2ebb..aa3fa9d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, 2011 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -66,6 +66,8 @@ int pstream_accept(struct pstream *, struct stream **);
 int pstream_accept_block(struct pstream *, struct stream **);
 void pstream_wait(struct pstream *);
 int pstream_set_dscp(struct pstream *, uint8_t dscp);
+
+ovs_be16 pstream_get_bound_port(const struct pstream *);
 \f
 /* Convenience functions. */
 
index 15bcec8..266c410 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -222,7 +222,8 @@ static void
 table_format_timestamp__(char *s, size_t size)
 {
     time_t now = time_wall();
-    strftime(s, size, "%Y-%m-%d %H:%M:%S", gmtime(&now));
+    struct tm tm;
+    strftime(s, size, "%Y-%m-%d %H:%M:%S", gmtime_r(&now, &tm));
 }
 
 static void
index 6e41514..f687c96 100644 (file)
@@ -37,7 +37,7 @@
 
 /* backtrace() from <execinfo.h> is really useful, but it is not signal safe
  * everywhere, such as on x86-64.  */
-#if HAVE_EXECINFO_H && !defined __x86_64__
+#if HAVE_BACKTRACE && !defined __x86_64__
 #  define USE_BACKTRACE 1
 #  include <execinfo.h>
 #else
@@ -454,13 +454,13 @@ block_sigalrm(sigset_t *oldsigs)
     sigset_t sigalrm;
     sigemptyset(&sigalrm);
     sigaddset(&sigalrm, SIGALRM);
-    xsigprocmask(SIG_BLOCK, &sigalrm, oldsigs);
+    xpthread_sigmask(SIG_BLOCK, &sigalrm, oldsigs);
 }
 
 static void
 unblock_sigalrm(const sigset_t *oldsigs)
 {
-    xsigprocmask(SIG_SETMASK, oldsigs, NULL);
+    xpthread_sigmask(SIG_SETMASK, oldsigs, NULL);
 }
 
 long long int
index 72cf498..b74fe12 100644 (file)
@@ -70,7 +70,6 @@ void time_wall_timespec(struct timespec *);
 void time_alarm(unsigned int secs);
 int time_poll(struct pollfd *, int n_pollfds, long long int timeout_when,
               int *elapsed);
-bool time_cached(void);
 
 long long int timespec_to_msec(const struct timespec *);
 long long int timeval_to_msec(const struct timeval *);
index cbaffa7..cd4019e 100644 (file)
@@ -843,7 +843,7 @@ raw_ctz(uint32_t n)
 #endif
 
 /* Returns the number of 1-bits in 'x', between 0 and 32 inclusive. */
-int
+unsigned int
 popcount(uint32_t x)
 {
     /* In my testing, this implementation is over twice as fast as any other
index b944ec7..4f6a201 100644 (file)
@@ -265,7 +265,7 @@ ctz(uint32_t n)
 
 int log_2_floor(uint32_t);
 int log_2_ceil(uint32_t);
-int popcount(uint32_t);
+unsigned int popcount(uint32_t);
 
 /* Returns the rightmost 1-bit in 'x' (e.g. 01011000 => 00001000), or 0 if 'x'
  * is 0. */
index ab746c8..c7ab206 100644 (file)
@@ -52,7 +52,7 @@ enum vlog_level vlog_get_level_val(const char *name);
 
 /* Facilities that we can log to. */
 #define VLOG_FACILITIES                                                 \
-    VLOG_FACILITY(SYSLOG, "%05N|%c%T|%p|%m")                            \
+    VLOG_FACILITY(SYSLOG, "ovs|%05N|%c%T|%p|%m")                            \
     VLOG_FACILITY(CONSOLE, "%D{%Y-%m-%dT%H:%M:%SZ}|%05N|%c%T|%p|%m")    \
     VLOG_FACILITY(FILE, "%D{%Y-%m-%dT%H:%M:%SZ}|%05N|%c%T|%p|%m")
 enum vlog_facility {
index ce4a53b..4c947a4 100644 (file)
@@ -101,6 +101,9 @@ worker_start(void)
     xset_nonblocking(work_fds[0]);
     xset_nonblocking(work_fds[1]);
 
+    /* Don't let the worker process own the responsibility to delete
+     * the pidfile.  Register it again after the fork. */
+    remove_pidfile_from_unlink();
     if (!fork_and_clean_up()) {
         /* In child (worker) process. */
         daemonize_post_detach();
@@ -110,6 +113,7 @@ worker_start(void)
     }
 
     /* In parent (main) process. */
+    add_pidfile_to_unlink();
     close(work_fds[1]);
     client_sock = work_fds[0];
     rxbuf_init(&client_rx);
diff --git a/m4/ax_check_openssl.m4 b/m4/ax_check_openssl.m4
new file mode 100644 (file)
index 0000000..2d543e6
--- /dev/null
@@ -0,0 +1,124 @@
+# ===========================================================================
+#     http://www.gnu.org/software/autoconf-archive/ax_check_openssl.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CHECK_OPENSSL([action-if-found[, action-if-not-found]])
+#
+# DESCRIPTION
+#
+#   Look for OpenSSL in a number of default spots, or in a user-selected
+#   spot (via --with-openssl).  Sets
+#
+#     SSL_INCLUDES to the include directives required
+#     SSL_LIBS to the -l directives required
+#     SSL_LDFLAGS to the -L or -R flags required
+#
+#   and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately
+#
+#   This macro sets SSL_INCLUDES such that source files should use the
+#   openssl/ directory in include directives:
+#
+#     #include <openssl/hmac.h>
+#
+# LICENSE
+#
+#   Copyright (c) 2009,2010 Zmanda Inc. <http://www.zmanda.com/>
+#   Copyright (c) 2009,2010 Dustin J. Mitchell <dustin@zmanda.com>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 8
+
+AU_ALIAS([CHECK_SSL], [AX_CHECK_OPENSSL])
+AC_DEFUN([AX_CHECK_OPENSSL], [
+    found=false
+    AC_ARG_WITH([openssl],
+        [AS_HELP_STRING([--with-openssl=DIR],
+            [root of the OpenSSL directory])],
+        [
+            case "$withval" in
+            "" | y | ye | yes | n | no)
+            AC_MSG_ERROR([Invalid --with-openssl value])
+              ;;
+            *) ssldirs="$withval"
+              ;;
+            esac
+        ], [
+            # if pkg-config is installed and openssl has installed a .pc file,
+            # then use that information and don't search ssldirs
+            AC_PATH_PROG([PKG_CONFIG], [pkg-config])
+            if test x"$PKG_CONFIG" != x""; then
+                SSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null`
+                if test $? = 0; then
+                    SSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null`
+                    SSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null`
+                    found=true
+                fi
+            fi
+
+            # no such luck; use some default ssldirs
+            if ! $found; then
+                ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr"
+            fi
+        ]
+        )
+
+
+    # note that we #include <openssl/foo.h>, so the OpenSSL headers have to be in
+    # an 'openssl' subdirectory
+
+    if ! $found; then
+        SSL_INCLUDES=
+        for ssldir in $ssldirs; do
+            AC_MSG_CHECKING([for openssl/ssl.h in $ssldir])
+            if test -f "$ssldir/include/openssl/ssl.h"; then
+                SSL_INCLUDES="-I$ssldir/include"
+                SSL_LDFLAGS="-L$ssldir/lib"
+                SSL_LIBS="-lssl -lcrypto"
+                found=true
+                AC_MSG_RESULT([yes])
+                break
+            else
+                AC_MSG_RESULT([no])
+            fi
+        done
+
+        # if the file wasn't found, well, go ahead and try the link anyway -- maybe
+        # it will just work!
+    fi
+
+    # try the preprocessor and linker with our new flags,
+    # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS
+
+    AC_MSG_CHECKING([whether compiling and linking against OpenSSL works])
+    echo "Trying link with SSL_LDFLAGS=$SSL_LDFLAGS;" \
+        "SSL_LIBS=$SSL_LIBS; SSL_INCLUDES=$SSL_INCLUDES" >&AS_MESSAGE_LOG_FD
+
+    save_LIBS="$LIBS"
+    save_LDFLAGS="$LDFLAGS"
+    save_CPPFLAGS="$CPPFLAGS"
+    LDFLAGS="$LDFLAGS $SSL_LDFLAGS"
+    LIBS="$SSL_LIBS $LIBS"
+    CPPFLAGS="$SSL_INCLUDES $CPPFLAGS"
+    AC_LINK_IFELSE(
+        [AC_LANG_PROGRAM([#include <openssl/ssl.h>], [SSL_new(NULL)])],
+        [
+            AC_MSG_RESULT([yes])
+            $1
+        ], [
+            AC_MSG_RESULT([no])
+            $2
+        ])
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+
+    AC_SUBST([SSL_INCLUDES])
+    AC_SUBST([SSL_LIBS])
+    AC_SUBST([SSL_LDFLAGS])
+])
index 59cc933..ac0c7d5 100644 (file)
@@ -99,8 +99,7 @@ AC_DEFUN([OVS_CHECK_OPENSSL],
      [ssl=check])
 
    if test "$ssl" != false; then
-       m4_ifndef([PKG_CHECK_MODULES], [m4_fatal([Please install pkg-config.])])
-       PKG_CHECK_MODULES([SSL], [openssl],
+       AX_CHECK_OPENSSL(
          [HAVE_OPENSSL=yes],
          [HAVE_OPENSSL=no
           if test "$ssl" = check; then
@@ -168,10 +167,9 @@ AC_DEFUN([OVS_CHECK_DBDIR],
      [DBDIR='${sysconfdir}/${PACKAGE}'])
    AC_SUBST([DBDIR])])
 
-dnl Defines HAVE_BACKTRACE if backtrace() is declared in <execinfo.h>
-dnl and exists in libc.
+dnl Defines HAVE_BACKTRACE if backtrace() is found.
 AC_DEFUN([OVS_CHECK_BACKTRACE],
-  [AC_CHECK_HEADER([execinfo.h], [AC_CHECK_FUNCS([backtrace])])])
+  [AC_SEARCH_LIBS([backtrace], [execinfo ubacktrace])])
 
 dnl Checks for __malloc_hook, etc., supported by glibc.
 AC_DEFUN([OVS_CHECK_MALLOC_HOOKS],
index b336cc7..cd10be1 100644 (file)
@@ -1,2 +1,3 @@
 /Makefile
 /Makefile.in
+/ipfix-entities.def
index 69f014f..e4ea41d 100644 (file)
@@ -23,6 +23,8 @@ ofproto_libofproto_a_SOURCES = \
        ofproto/ofproto-dpif.c \
        ofproto/ofproto-dpif-governor.c \
        ofproto/ofproto-dpif-governor.h \
+       ofproto/ofproto-dpif-ipfix.c \
+       ofproto/ofproto-dpif-ipfix.h \
        ofproto/ofproto-dpif-sflow.c \
        ofproto/ofproto-dpif-sflow.h \
        ofproto/ofproto-provider.h \
@@ -33,4 +35,18 @@ ofproto_libofproto_a_SOURCES = \
        ofproto/tunnel.c \
        ofproto/tunnel.h
 
+# Distribute this generated file in order not to require Python at
+# build time if ofproto/ipfix.xml is not modified.
+ofproto_libofproto_a_SOURCES += ofproto/ipfix-entities.def
+
+BUILT_SOURCES += ofproto/ipfix-entities.def
+
+CLEANFILES += ofproto/ipfix-entities.def
+
 MAN_FRAGMENTS += ofproto/ofproto-unixctl.man ofproto/ofproto-dpif-unixctl.man
+
+# IPFIX entity definition macros generation from IANA's XML definition.
+EXTRA_DIST += ofproto/ipfix.xml
+dist_noinst_SCRIPTS = ofproto/ipfix-gen-entities
+ofproto/ipfix-entities.def: ofproto/ipfix.xml ofproto/ipfix-gen-entities
+       $(run_python) $(srcdir)/ofproto/ipfix-gen-entities $< > $@
diff --git a/ofproto/ipfix-gen-entities b/ofproto/ipfix-gen-entities
new file mode 100755 (executable)
index 0000000..4d4e0de
--- /dev/null
@@ -0,0 +1,140 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2012 Nicira, Inc.
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.  This file is offered as-is,
+# without warranty of any kind.
+
+import getopt
+import re
+import sys
+import xml.sax
+import xml.sax.handler
+
+class IpfixEntityHandler(xml.sax.handler.ContentHandler):
+
+    RECORD_FIELDS = ['name', 'dataType', 'elementId', 'status']
+
+    # Cf. RFC 5101, Section 6.
+    DATA_TYPE_SIZE = {
+        'unsigned8': 1,
+        'unsigned16': 2,
+        'unsigned32': 4,
+        'unsigned64': 8,
+        'signed8': 1,
+        'signed16': 2,
+        'signed32': 4,
+        'signed64': 8,
+        'float32': 4,
+        'float64': 8,
+        'boolean': 1,  # Not clear.
+        'macAddress': 6,
+        'octetArray': 0,  # Not clear.
+        'string': 0,  # Not clear.
+        'dateTimeSeconds': 4,
+        'dateTimeMilliseconds': 8,
+        'dateTimeMicroseconds': 8,
+        'dateTimeNanoseconds': 8,
+        'ipv4Address': 4,
+        'ipv6Address': 16,
+        }
+
+    def __init__(self):
+        self.current_field_name = None
+        self.current_field_value = []
+        self.current_record = dict()
+
+    def startDocument(self):
+        print """\
+/* IPFIX entities. */
+#ifndef IPFIX_ENTITY
+#define IPFIX_ENTITY(ENUM, ID, SIZE, NAME)
+#endif
+"""
+
+    def endDocument(self):
+        print """
+#undef IPFIX_ENTITY"""
+
+    def startElement(self, name, attrs):
+        if name in self.RECORD_FIELDS:
+            self.current_field_name = name
+        else:
+            self.current_field_name = None
+        self.current_field_value = []
+
+    @staticmethod
+    def camelcase_to_uppercase(s):
+        return re.sub('(.)([A-Z]+)', r'\1_\2', s).upper()
+
+    def endElement(self, name):
+        if self.current_field_name is not None:
+            self.current_record[self.current_field_name] = ''.join(
+                self.current_field_value).strip()
+        elif (name == 'record'
+              and self.current_record.get('status') == 'current'
+              and 'dataType' in self.current_record):
+
+            self.current_record['enumName'] = self.camelcase_to_uppercase(
+                self.current_record['name'])
+            self.current_record['dataTypeSize'] = self.DATA_TYPE_SIZE.get(
+                self.current_record['dataType'], 0)
+
+            print 'IPFIX_ENTITY(%(enumName)s, %(elementId)s, ' \
+                  '%(dataTypeSize)i, %(name)s)' % self.current_record
+            self.current_record.clear()
+
+    def characters(self, content):
+        if self.current_field_name is not None:
+            self.current_field_value.append(content)
+
+def print_ipfix_entity_macros(xml_file):
+    xml.sax.parse(xml_file, IpfixEntityHandler())
+
+def usage(name):
+    print """\
+%(name)s: IPFIX entity definition generator
+Prints C macros defining IPFIX entities from the standard IANA file at
+<http://www.iana.org/assignments/ipfix/ipfix.xml>
+usage: %(name)s [OPTIONS] XML
+where XML is the standard IANA XML file defining IPFIX entities
+
+The following options are also available:
+  -h, --help                  display this help message
+  -V, --version               display version information\
+""" % {'name': name}
+    sys.exit(0)
+
+if __name__ == '__main__':
+#    try:
+        try:
+            options, args = getopt.gnu_getopt(sys.argv[1:], 'hV',
+                                              ['help', 'version'])
+        except getopt.GetoptError, geo:
+            sys.stderr.write('%s: %s\n' % (sys.argv[0], geo.msg))
+            sys.exit(1)
+
+        for key, value in options:
+            if key in ['-h', '--help']:
+                usage()
+            elif key in ['-V', '--version']:
+                print 'ipfix-gen-entities (Open vSwitch)'
+            else:
+                sys.exit(0)
+
+        if len(args) != 1:
+            sys.stderr.write('%s: exactly 1 non-option arguments required '
+                             '(use --help for help)\n' % sys.argv[0])
+            sys.exit(1)
+
+        print_ipfix_entity_macros(args[0])
+
+#    except Exception, e:
+#        sys.stderr.write('%s: %s\n' % (sys.argv[0], e))
+#        sys.exit(1)
+
+# Local variables:
+# mode: python
+# End:
diff --git a/ofproto/ipfix.xml b/ofproto/ipfix.xml
new file mode 100644 (file)
index 0000000..845722f
--- /dev/null
@@ -0,0 +1,8752 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<?xml-stylesheet type="text/xsl" href="ipfix.xsl"?>
+<?oxygen RNGSchema="ipfix.rng" type="xml"?>
+<registry xmlns="http://www.iana.org/assignments" id="ipfix">
+  <title>IP Flow Information Export (IPFIX) Entities</title>
+  <created>2007-05-10</created>
+  <updated>2012-12-05</updated>
+  <note>For the IPFIX schema, please see <xref type="uri" data="http://www.iana.org/assignments/xml-registry/schema/ipfix.xsd"/>.</note>
+
+  <registry id="ipfix-information-elements">
+    <title>IPFIX Information Elements</title>
+    <registration_rule>Expert Review</registration_rule>
+    <expert>Primary expert - Nevil Brownlee and Secondary expert - Juergen Quittek</expert>
+    <xref type="rfc" data="rfc5102"/>
+    <note>Values 0-127: NFv9-compatible</note>
+    <record>
+      <name>Reserved</name>
+      <elementId>0</elementId>
+      <status>current</status>
+      <description/>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>octetDeltaCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>deltaCounter</dataTypeSemantics>
+      <elementId>1</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The number of octets since the previous report (if any)
+         in incoming packets for this Flow at the Observation Point.
+         The number of octets includes IP header(s) and IP payload.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>packetDeltaCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>deltaCounter</dataTypeSemantics>
+      <elementId>2</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The number of incoming packets since the previous report
+         (if any) for this Flow at the Observation Point.
+         </paragraph>
+      </description>
+      <units>packets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>deltaFlowCount</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>deltaCounter</dataTypeSemantics>
+      <elementId>3</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The conservative count of Original Flows contributing
+          to this Aggregated Flow; may be distributed via any of the methods
+          expressed by the valueDistributionMethod Information Element.
+        </paragraph>
+      </description>
+      <xref type="draft" data="RFC-ietf-ipfix-a9n-08"/>
+    </record>
+
+    <record>
+      <name>protocolIdentifier</name>
+      <dataType>unsigned8</dataType>
+      <group>ipHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>4</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The value of the protocol number in the IP packet header.
+         The protocol number identifies the IP packet payload type.
+         Protocol numbers are defined in the IANA Protocol Numbers
+         registry.
+            </paragraph>
+        <paragraph>
+         In Internet Protocol version 4 (IPv4), this is carried in the
+         Protocol field.  In Internet Protocol version 6 (IPv6), this
+         is carried in the Next Header field in the last extension
+         header of the packet.
+            </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the specification of the IPv4
+          protocol field.
+          See <xref type="rfc" data="rfc2460"/> for the specification of the
+          IPv6 protocol field.
+          See the list of protocol numbers assigned by IANA at <xref type="registry" data="protocol-numbers"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>ipClassOfService</name>
+      <dataType>unsigned8</dataType>
+      <group>ipHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>5</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         For IPv4 packets, this is the value of the TOS field in
+         the IPv4 packet header.  For IPv6 packets, this is the
+         value of the Traffic Class field in the IPv6 packet header.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc1812"/> (Section 5.3.2) and <xref type="rfc" data="rfc791"/> for the definition of the IPv4 TOS field.
+          See <xref type="rfc" data="rfc2460"/> for the definition of the IPv6
+          Traffic Class field.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>tcpControlBits</name>
+      <dataType>unsigned8</dataType>
+      <group>minMax</group>
+      <dataTypeSemantics>flags</dataTypeSemantics>
+      <elementId>6</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         TCP control bits observed for packets of this Flow.
+         The information is encoded in a set of bit fields.
+         For each TCP control bit, there is a bit in this
+         set.  A bit is set to 1 if any observed packet of this
+         Flow has the corresponding TCP control bit set to 1.
+         A value of 0 for a bit indicates that the corresponding
+         bit was not set in any of the observed packets
+         of this Flow.
+         </paragraph>
+        <artwork>
+          0     1     2     3     4     5     6     7
+      +-----+-----+-----+-----+-----+-----+-----+-----+
+      |  Reserved | URG | ACK | PSH | RST | SYN | FIN |
+      +-----+-----+-----+-----+-----+-----+-----+-----+
+
+      Reserved:  Reserved for future use by TCP.  Must be zero.
+           URG:  Urgent Pointer field significant
+           ACK:  Acknowledgment field significant
+           PSH:  Push Function
+           RST:  Reset the connection
+           SYN:  Synchronize sequence numbers
+           FIN:  No more data from sender
+         </artwork>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc793"/> for the definition of the TCP
+          control bits in the TCP header.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>sourceTransportPort</name>
+      <dataType>unsigned16</dataType>
+      <group>transportHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>7</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The source port identifier in the transport header.
+         For the transport protocols UDP, TCP, and SCTP, this is the
+         source port number given in the respective header.  This
+         field MAY also be used for future transport protocols that
+         have 16-bit source port identifiers.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc768"/> for the definition of the UDP
+          source port field.
+          See <xref type="rfc" data="rfc793"/> for the definition of the TCP
+          source port field.
+          See <xref type="rfc" data="rfc4960"/> for the definition of SCTP.
+        </paragraph>
+        <paragraph>
+          Additional information on defined UDP and TCP port numbers can be
+          found at <xref type="registry" data="port-numbers"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>sourceIPv4Address</name>
+      <dataType>ipv4Address</dataType>
+      <group>ipHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>8</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The IPv4 source address in the IP packet header.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the definition of the IPv4
+          source address field.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>sourceIPv4PrefixLength</name>
+      <dataType>unsigned8</dataType>
+      <group>ipHeader</group>
+      <elementId>9</elementId>
+      <applicability>option</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The number of contiguous bits that are relevant in the
+         sourceIPv4Prefix Information Element.
+         </paragraph>
+      </description>
+      <units>bits</units>
+      <range>0-32</range>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>ingressInterface</name>
+      <dataType>unsigned32</dataType>
+      <group>scope</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>10</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           The index of the IP interface where packets of this Flow
+           are being received.  The value matches the value of managed
+           object 'ifIndex' as defined in RFC 2863.
+           Note that ifIndex values are not assigned statically to an
+           interface and that the interfaces may be renumbered every
+           time the device's management system is re-initialized, as
+           specified in RFC 2863.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc2863"/> for the definition of the
+          ifIndex object.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>destinationTransportPort</name>
+      <dataType>unsigned16</dataType>
+      <group>transportHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>11</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The destination port identifier in the transport header.
+         For the transport protocols UDP, TCP, and SCTP, this is the
+         destination port number given in the respective header.
+         This field MAY also be used for future transport protocols
+         that have 16-bit destination port identifiers.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc768"/> for the definition of the UDP
+          destination port field.
+          See <xref type="rfc" data="rfc793"/> for the definition of the TCP
+          destination port field.
+          See <xref type="rfc" data="rfc4960"/> for the definition of SCTP.
+        </paragraph>
+        <paragraph>
+          Additional information on defined UDP and TCP port numbers can be
+          found at <xref type="registry" data="port-numbers"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>destinationIPv4Address</name>
+      <dataType>ipv4Address</dataType>
+      <group>ipHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>12</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The IPv4 destination address in the IP packet header.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the definition of the IPv4
+          destination address field.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>destinationIPv4PrefixLength</name>
+      <dataType>unsigned8</dataType>
+      <group>ipHeader</group>
+      <elementId>13</elementId>
+      <applicability>option</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The number of contiguous bits that are relevant in the
+         destinationIPv4Prefix Information Element.
+         </paragraph>
+      </description>
+      <units>bits</units>
+      <range>0-32</range>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>egressInterface</name>
+      <dataType>unsigned32</dataType>
+      <group>scope</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>14</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           The index of the IP interface where packets of
+           this Flow are being sent.  The value matches the value of
+           managed object 'ifIndex' as defined in RFC 2863.
+           Note that ifIndex values are not assigned statically to an
+           interface and that the interfaces may be renumbered every
+           time the device's management system is re-initialized, as
+           specified in RFC 2863.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc2863"/> for the definition of the
+          ifIndex object.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>ipNextHopIPv4Address</name>
+      <dataType>ipv4Address</dataType>
+      <group>derived</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>15</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The IPv4 address of the next IPv4 hop.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>bgpSourceAsNumber</name>
+      <dataType>unsigned32</dataType>
+      <group>derived</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>16</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The autonomous system (AS) number of the source IP address.
+         If AS path information for this Flow is only available as
+         an unordered AS set (and not as an ordered AS sequence),
+         then the value of this Information Element is 0.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc4271"/> for a description of BGP-4, and
+          see <xref type="rfc" data="rfc1930"/> for the definition of the AS
+          number.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>bgpDestinationAsNumber</name>
+      <dataType>unsigned32</dataType>
+      <group>derived</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>17</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The autonomous system (AS) number of the destination IP
+         address.  If AS path information for this Flow is only
+         available as an unordered AS set (and not as an ordered AS
+         sequence), then the value of this Information Element is 0.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc4271"/> for a description of BGP-4, and
+          see <xref type="rfc" data="rfc1930"/> for the definition of the AS
+          number.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>bgpNextHopIPv4Address</name>
+      <dataType>ipv4Address</dataType>
+      <group>derived</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>18</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The IPv4 address of the next (adjacent) BGP hop.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc4271"/> for a description of BGP-4.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>postMCastPacketDeltaCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>deltaCounter</dataTypeSemantics>
+      <elementId>19</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The number of outgoing multicast packets since the
+         previous report (if any) sent for packets of this Flow
+         by a multicast daemon within the Observation Domain.
+         This property cannot necessarily be observed at the
+         Observation Point, but may be retrieved by other means.
+         </paragraph>
+      </description>
+      <units>packets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>postMCastOctetDeltaCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>deltaCounter</dataTypeSemantics>
+      <elementId>20</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The number of octets since the previous report (if any)
+         in outgoing multicast packets sent for packets of this
+         Flow by a multicast daemon within the Observation Domain.
+         This property cannot necessarily be observed at the
+         Observation Point, but may be retrieved by other means.
+         The number of octets includes IP header(s) and IP payload.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowEndSysUpTime</name>
+      <dataType>unsigned32</dataType>
+      <group>timestamp</group>
+      <elementId>21</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The relative timestamp of the last packet of this Flow.
+         It indicates the number of milliseconds since the
+         last (re-)initialization of the IPFIX Device (sysUpTime).
+         </paragraph>
+      </description>
+      <units>milliseconds</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowStartSysUpTime</name>
+      <dataType>unsigned32</dataType>
+      <group>timestamp</group>
+      <elementId>22</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The relative timestamp of the first packet of this Flow.
+         It indicates the number of milliseconds since the
+         last (re-)initialization of the IPFIX Device (sysUpTime).
+         </paragraph>
+      </description>
+      <units>milliseconds</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>postOctetDeltaCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>deltaCounter</dataTypeSemantics>
+      <elementId>23</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The definition of this Information Element is identical
+         to the definition of Information Element
+         'octetDeltaCount', except that it reports a
+         potentially modified value caused by a middlebox
+         function after the packet passed the Observation Point.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>postPacketDeltaCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>deltaCounter</dataTypeSemantics>
+      <elementId>24</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The definition of this Information Element is identical
+         to the definition of Information Element
+         'packetDeltaCount', except that it reports a
+         potentially modified value caused by a middlebox
+         function after the packet passed the Observation Point.
+         </paragraph>
+      </description>
+      <units>packets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>minimumIpTotalLength</name>
+      <dataType>unsigned64</dataType>
+      <group>minMax</group>
+      <elementId>25</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         Length of the smallest packet observed for this Flow.
+         The packet length includes the IP header(s) length and
+         the IP payload length.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the specification of the IPv4
+          total length.
+          See <xref type="rfc" data="rfc2460"/> for the specification of the
+          IPv6 payload length.
+          See <xref type="rfc" data="rfc2675"/> for the specification of the
+          IPv6 jumbo payload length.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>maximumIpTotalLength</name>
+      <dataType>unsigned64</dataType>
+      <group>minMax</group>
+      <elementId>26</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         Length of the largest packet observed for this Flow.
+         The packet length includes the IP header(s) length and
+         the IP payload length.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the specification of the IPv4
+          total length.
+          See <xref type="rfc" data="rfc2460"/> for the specification of the
+          IPv6 payload length.
+          See <xref type="rfc" data="rfc2675"/> for the specification of the
+          IPv6 jumbo payload length.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>sourceIPv6Address</name>
+      <dataType>ipv6Address</dataType>
+      <group>ipHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>27</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The IPv6 source address in the IP packet header.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc2460"/> for the definition of the Source
+          Address field in the IPv6 header.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>destinationIPv6Address</name>
+      <dataType>ipv6Address</dataType>
+      <group>ipHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>28</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The IPv6 destination address in the IP packet header.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc2460"/> for the definition of the
+          Destination Address field in the IPv6 header.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>sourceIPv6PrefixLength</name>
+      <dataType>unsigned8</dataType>
+      <group>ipHeader</group>
+      <elementId>29</elementId>
+      <applicability>option</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The number of contiguous bits that are relevant in the
+         sourceIPv6Prefix Information Element.
+         </paragraph>
+      </description>
+      <units>bits</units>
+      <range>0-128</range>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>destinationIPv6PrefixLength</name>
+      <dataType>unsigned8</dataType>
+      <group>ipHeader</group>
+      <elementId>30</elementId>
+      <applicability>option</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The number of contiguous bits that are relevant in the
+         destinationIPv6Prefix Information Element.
+         </paragraph>
+      </description>
+      <units>bits</units>
+      <range>0-128</range>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowLabelIPv6</name>
+      <dataType>unsigned32</dataType>
+      <group>ipHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>31</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The value of the IPv6 Flow Label field in the IP packet header.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc2460"/> for the definition of the
+          Flow Label field in the IPv6 packet header.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>icmpTypeCodeIPv4</name>
+      <dataType>unsigned16</dataType>
+      <group>transportHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>32</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         Type and Code of the IPv4 ICMP message.  The combination of
+         both values is reported as (ICMP type * 256) + ICMP code.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc792"/> for the definition of the IPv4
+          ICMP type and code fields.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>igmpType</name>
+      <dataType>unsigned8</dataType>
+      <group>transportHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>33</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The type field of the IGMP message.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3376"/> for the definition of the IGMP
+          type field.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <elementId>34-35</elementId>
+      <reserved/>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowActiveTimeout</name>
+      <dataType>unsigned16</dataType>
+      <group>misc</group>
+      <elementId>36</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The number of seconds after which an active Flow is timed out
+         anyway, even if there is still a continuous flow of packets.
+         </paragraph>
+      </description>
+      <units>seconds</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowIdleTimeout</name>
+      <dataType>unsigned16</dataType>
+      <group>misc</group>
+      <elementId>37</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+          A Flow is considered to be timed out if no packets belonging
+          to the Flow have been observed for the number of seconds
+          specified by this field.
+         </paragraph>
+      </description>
+      <units>seconds</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <elementId>38-39</elementId>
+      <reserved/>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>exportedOctetTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>processCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>40</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           The total number of octets that the Exporting Process
+           has sent since the Exporting Process (re-)initialization
+           to a particular Collecting Process.
+           The value of this Information Element is calculated by
+           summing up the IPFIX Message Header length values of all
+           IPFIX Messages that were successfully sent to the Collecting
+           Process.  The reported number excludes octets in the IPFIX
+           Message that carries the counter value.
+           If this Information Element is sent to a particular
+           Collecting Process, then by default it specifies the number
+           of octets sent to this Collecting Process.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>exportedMessageTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>processCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>41</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           The total number of IPFIX Messages that the Exporting Process
+           has sent since the Exporting Process (re-)initialization to
+           a particular Collecting Process.
+           The reported number excludes the IPFIX Message that carries
+           the counter value.
+           If this Information Element is sent to a particular
+           Collecting Process, then by default it specifies the number
+           of IPFIX Messages sent to this Collecting Process.
+         </paragraph>
+      </description>
+      <units>messages</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>exportedFlowRecordTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>processCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>42</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           The total number of Flow Records that the Exporting
+           Process has sent as Data Records since the Exporting
+           Process (re-)initialization to a particular Collecting
+           Process.  The reported number excludes Flow Records in
+           the IPFIX Message that carries the counter value.
+           If this Information Element is sent to a particular
+           Collecting Process, then by default it specifies the number
+           of Flow Records sent to this process.
+         </paragraph>
+      </description>
+      <units>flows</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <elementId>43</elementId>
+      <reserved/>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>sourceIPv4Prefix</name>
+      <dataType>ipv4Address</dataType>
+      <group>ipHeader</group>
+      <elementId>44</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         IPv4 source address prefix.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>destinationIPv4Prefix</name>
+      <dataType>ipv4Address</dataType>
+      <group>ipHeader</group>
+      <elementId>45</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph> IPv4 destination address prefix. </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsTopLabelType</name>
+      <dataType>unsigned8</dataType>
+      <group>derived</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>46</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         This field identifies the control protocol that allocated the
+         top-of-stack label.  Values for this field are listed in the 
+         MPLS label type registry. See 
+         <xref type="uri" data="http://www.iana.org/assignments/ipfix/ipfix.xml#ipfix-mpls-label-type"/>
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3031"/> for the MPLS label structure.
+          See <xref type="rfc" data="rfc4364"/> for the association of MPLS
+          labels with Virtual Private Networks (VPNs).
+          See <xref type="rfc" data="rfc4271"/> for BGP and BGP routing.
+          See <xref type="rfc" data="rfc5036"/> for Label Distribution Protocol
+          (LDP).
+          See the list of MPLS label types assigned by IANA at <xref type="registry" data="mpls-label-values"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsTopLabelIPv4Address</name>
+      <dataType>ipv4Address</dataType>
+      <group>derived</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>47</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           The IPv4 address of the system that the MPLS top label will
+           cause this Flow to be forwarded to.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3031"/> for the association between MPLS
+          labels and IP addresses.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <elementId>48-51</elementId>
+      <reserved/>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>minimumTTL</name>
+      <dataType>unsigned8</dataType>
+      <group>minMax</group>
+      <elementId>52</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           Minimum TTL value observed for any packet in this Flow.
+         </paragraph>
+      </description>
+      <units>hops</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the definition of the IPv4
+          Time to Live field.
+          See <xref type="rfc" data="rfc2460"/> for the definition of the IPv6
+          Hop Limit field.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>maximumTTL</name>
+      <dataType>unsigned8</dataType>
+      <group>minMax</group>
+      <elementId>53</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           Maximum TTL value observed for any packet in this Flow.
+         </paragraph>
+      </description>
+      <units>hops</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the definition of the IPv4
+          Time to Live field.
+          See <xref type="rfc" data="rfc2460"/> for the definition of the IPv6
+          Hop Limit field.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>fragmentIdentification</name>
+      <dataType>unsigned32</dataType>
+      <group>ipHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>54</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The value of the Identification field
+         in the IPv4 packet header or in the IPv6 Fragment header,
+         respectively.  The value is 0 for IPv6 if there is
+         no fragment header.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the definition of the IPv4
+          Identification field.
+          See <xref type="rfc" data="rfc2460"/> for the definition of the
+          Identification field in the IPv6 Fragment header.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>postIpClassOfService</name>
+      <dataType>unsigned8</dataType>
+      <group>ipHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>55</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The definition of this Information Element is identical
+         to the definition of Information Element
+         'ipClassOfService', except that it reports a
+         potentially modified value caused by a middlebox
+         function after the packet passed the Observation Point.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the definition of the IPv4
+          TOS field.
+          See <xref type="rfc" data="rfc2460"/> for the definition of the IPv6
+          Traffic Class field.
+          See <xref type="rfc" data="rfc3234"/> for the definition of
+          middleboxes.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>sourceMacAddress</name>
+      <dataType>macAddress</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>56</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           The IEEE 802 source MAC address field.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>See IEEE.802-3.2002.</paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>postDestinationMacAddress</name>
+      <dataType>macAddress</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>57</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The definition of this Information Element is identical
+         to the definition of Information Element
+         'destinationMacAddress', except that it reports a
+         potentially modified value caused by a middlebox
+         function after the packet passed the Observation Point.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>See IEEE.802-3.2002.</paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>vlanId</name>
+      <dataType>unsigned16</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>58</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Virtual LAN identifier associated with ingress interface. For dot1q vlans, see 243
+          dot1qVlanId.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>See IEEE.802-1Q.2003.</paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>postVlanId</name>
+      <dataType>unsigned16</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>59</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Virtual LAN identifier associated with egress interface. For postdot1q vlans, see 254 postDot1qVlanId.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>See IEEE.802-1Q.2003.</paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>ipVersion</name>
+      <dataType>unsigned8</dataType>
+      <group>ipHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>60</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The IP version field in the IP packet header.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the definition of the version
+          field in the IPv4 packet header.
+          See <xref type="rfc" data="rfc2460"/> for the definition of the
+          version field in the IPv6 packet header.
+          Additional information on defined version numbers can be found at
+          <xref type="registry" data="version-numbers"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowDirection</name>
+      <dataType>unsigned8</dataType>
+      <group>misc</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>61</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The direction of the Flow observed at the Observation
+         Point.  There are only two values defined.
+         </paragraph>
+        <artwork>
+         0x00: ingress flow
+         0x01: egress flow
+         </artwork>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>ipNextHopIPv6Address</name>
+      <dataType>ipv6Address</dataType>
+      <group>derived</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>62</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The IPv6 address of the next IPv6 hop.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>bgpNextHopIPv6Address</name>
+      <dataType>ipv6Address</dataType>
+      <group>derived</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>63</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The IPv6 address of the next (adjacent) BGP hop.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc4271"/> for a description of BGP-4.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>ipv6ExtensionHeaders</name>
+      <dataType>unsigned32</dataType>
+      <group>minMax</group>
+      <dataTypeSemantics>flags</dataTypeSemantics>
+      <elementId>64</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         IPv6 extension headers observed in packets of this Flow.
+         The information is encoded in a set of bit fields.  For
+         each IPv6 option header, there is a bit in this set.
+         The bit is set to 1 if any observed packet of this Flow
+         contains the corresponding IPv6 extension header.
+         Otherwise, if no observed packet of this Flow contained
+         the respective IPv6 extension header, the value of the
+         corresponding bit is 0.
+         </paragraph>
+        <artwork>
+              0     1     2     3     4     5     6     7
+          +-----+-----+-----+-----+-----+-----+-----+-----+
+          | DST | HOP | Res | UNK |FRA0 | RH  |FRA1 | Res |  ...
+          +-----+-----+-----+-----+-----+-----+-----+-----+
+
+              8     9    10    11    12    13    14    15
+          +-----+-----+-----+-----+-----+-----+-----+-----+
+      ... |           Reserved    | MOB | ESP | AH  | PAY | ...
+          +-----+-----+-----+-----+-----+-----+-----+-----+
+
+             16    17    18    19    20    21    22    23
+          +-----+-----+-----+-----+-----+-----+-----+-----+
+      ... |                  Reserved                     | ...
+          +-----+-----+-----+-----+-----+-----+-----+-----+
+             24    25    26    27    28    29    30    31
+          +-----+-----+-----+-----+-----+-----+-----+-----+
+      ... |                  Reserved                     |
+          +-----+-----+-----+-----+-----+-----+-----+-----+
+
+        Bit    IPv6 Option   Description
+       0, DST      60       Destination option header
+       1, HOP       0       Hop-by-hop option header
+       2, Res               Reserved
+       3, UNK               Unknown Layer 4 header
+                            (compressed, encrypted, not supported)
+       4, FRA0     44       Fragment header - first fragment
+       5, RH       43       Routing header
+       6, FRA1     44       Fragmentation header - not first fragment
+       7, Res               Reserved
+      8 to 11               Reserved
+      12, MOB     135       IPv6 mobility [RFC3775]
+      13, ESP      50       Encrypted security payload
+      14, AH       51       Authentication Header
+      15, PAY     108       Payload compression header
+      16 to 31              Reserved
+         </artwork>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc2460"/> for the general definition of
+          IPv6 extension headers and for the specification of the hop-by-hop
+          options header, the routing header, the fragment header, and the
+          destination options header.
+          See <xref type="rfc" data="rfc4302"/> for the specification of the
+          authentication header.
+          See <xref type="rfc" data="rfc4303"/> for the specification of the
+          encapsulating security payload.
+  
+          The diagram provided in <xref type="rfc" data="rfc5102"/> is incorrect.  
+          The diagram in this registry is taken from Errata 1738. See <xref type="rfc-errata" data="1738"/>       
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <elementId>65-69</elementId>
+      <reserved/>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsTopLabelStackSection</name>
+      <dataType>octetArray</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>70</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The Label, Exp, and S fields from the top MPLS label
+         stack entry, i.e., from the last label that was pushed.
+         </paragraph>
+        <paragraph>
+         The size of this Information Element is 3 octets.
+         </paragraph>
+        <artwork>
+       0                   1                   2
+       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                Label                  | Exp |S|
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+      Label:  Label Value, 20 bits
+      Exp:    Experimental Use, 3 bits
+      S:      Bottom of Stack, 1 bit
+         </artwork>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3032"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsLabelStackSection2</name>
+      <dataType>octetArray</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>71</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The Label, Exp, and S fields from the label stack entry that
+         was pushed immediately before the label stack entry that would
+         be reported by mplsTopLabelStackSection.  See the definition of
+         mplsTopLabelStackSection for further details.
+         </paragraph>
+        <paragraph>
+         The size of this Information Element is 3 octets.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3032"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsLabelStackSection3</name>
+      <dataType>octetArray</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>72</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The Label, Exp, and S fields from the label stack entry that
+         was pushed immediately before the label stack entry that would
+         be reported by mplsLabelStackSection2.  See the definition of
+         mplsTopLabelStackSection for further details.
+         </paragraph>
+        <paragraph>
+         The size of this Information Element is 3 octets.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3032"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsLabelStackSection4</name>
+      <dataType>octetArray</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>73</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The Label, Exp, and S fields from the label stack entry that
+         was pushed immediately before the label stack entry that would
+         be reported by mplsLabelStackSection3.  See the definition of
+         mplsTopLabelStackSection for further details.
+         </paragraph>
+        <paragraph>
+         The size of this Information Element is 3 octets.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3032"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsLabelStackSection5</name>
+      <dataType>octetArray</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>74</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The Label, Exp, and S fields from the label stack entry that
+         was pushed immediately before the label stack entry that would
+         be reported by mplsLabelStackSection4.  See the definition of
+         mplsTopLabelStackSection for further details.
+         </paragraph>
+        <paragraph>
+         The size of this Information Element is 3 octets.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3032"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsLabelStackSection6</name>
+      <dataType>octetArray</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>75</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The Label, Exp, and S fields from the label stack entry that
+         was pushed immediately before the label stack entry that would
+         be reported by mplsLabelStackSection5.  See the definition of
+         mplsTopLabelStackSection for further details.
+         </paragraph>
+        <paragraph>
+         The size of this Information Element is 3 octets.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3032"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsLabelStackSection7</name>
+      <dataType>octetArray</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>76</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The Label, Exp, and S fields from the label stack entry that
+         was pushed immediately before the label stack entry that would
+         be reported by mplsLabelStackSection6.  See the definition of
+         mplsTopLabelStackSection for further details.
+         </paragraph>
+        <paragraph>
+         The size of this Information Element is 3 octets.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3032"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsLabelStackSection8</name>
+      <dataType>octetArray</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>77</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The Label, Exp, and S fields from the label stack entry that
+         was pushed immediately before the label stack entry that would
+         be reported by mplsLabelStackSection7.  See the definition of
+         mplsTopLabelStackSection for further details.
+         </paragraph>
+        <paragraph>
+         The size of this Information Element is 3 octets.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3032"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsLabelStackSection9</name>
+      <dataType>octetArray</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>78</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The Label, Exp, and S fields from the label stack entry that
+         was pushed immediately before the label stack entry that would
+         be reported by mplsLabelStackSection8.  See the definition of
+         mplsTopLabelStackSection for further details.
+         </paragraph>
+        <paragraph>
+         The size of this Information Element is 3 octets.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3032"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsLabelStackSection10</name>
+      <dataType>octetArray</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>79</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The Label, Exp, and S fields from the label stack entry that
+         was pushed immediately before the label stack entry that would
+         be reported by mplsLabelStackSection9.  See the definition of
+         mplsTopLabelStackSection for further details.
+         </paragraph>
+        <paragraph>
+         The size of this Information Element is 3 octets.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3032"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>destinationMacAddress</name>
+      <dataType>macAddress</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>80</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           The IEEE 802 destination MAC address field.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See IEEE.802-3.2002.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>postSourceMacAddress</name>
+      <dataType>macAddress</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>81</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The definition of this Information Element is identical
+         to the definition of Information Element
+         'sourceMacAddress', except that it reports a
+         potentially modified value caused by a middlebox
+         function after the packet passed the Observation Point.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See IEEE.802-3.2002.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>interfaceName</name>
+      <dataType>string</dataType>
+      <elementId>82</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          A short name uniquely describing an interface, eg "Eth1/0".
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc2863"/> for the definition of the ifName object.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record> 
+    
+    <record>
+      <name>interfaceDescription</name>
+      <dataType>string</dataType>
+      <elementId>83</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The description of an interface, eg "FastEthernet 1/0" or "ISP 
+          connection".
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc2863"/> for the definition of the ifDescr object.
+        </paragraph>
+      </references>
+      <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <elementId>84</elementId>
+      <reserved/>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>octetTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>85</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The total number of octets in incoming packets
+         for this Flow at the Observation Point since the Metering
+         Process (re-)initialization for this Observation Point.  The
+         number of octets includes IP header(s) and IP payload.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>packetTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>86</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The total number of incoming packets for this Flow
+         at the Observation Point since the Metering Process
+         (re-)initialization for this Observation Point.
+         </paragraph>
+      </description>
+      <units>packets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <elementId>87</elementId>
+      <reserved/>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>fragmentOffset</name>
+      <dataType>unsigned16</dataType>
+      <group>ipHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>88</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The value of the IP fragment offset field in the
+         IPv4 packet header or the IPv6 Fragment header,
+         respectively.  The value is 0 for IPv6 if there is
+         no fragment header.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the specification of the
+          fragment offset in the IPv4 header.
+          See <xref type="rfc" data="rfc2460"/> for the specification of the
+          fragment offset in the IPv6 Fragment header.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+        <elementId>89</elementId>
+      <reserved/>   
+    </record>
+
+    <record>
+      <name>mplsVpnRouteDistinguisher</name>
+      <dataType>octetArray</dataType>
+      <group>derived</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>90</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The value of the VPN route distinguisher of a corresponding
+         entry in a VPN routing and forwarding table.  Route
+         distinguisher ensures that the same address can be used in
+         several different MPLS VPNs and that it is possible for BGP to
+         carry several completely different routes to that address, one
+         for each VPN.  According to RFC 4364, the size of
+         mplsVpnRouteDistinguisher is 8 octets.  However, in RFC 4382 an
+         octet string with flexible length was chosen for representing a
+         VPN route distinguisher by object MplsL3VpnRouteDistinguisher.
+         This choice was made in order to be open to future changes of
+         the size.  This idea was adopted when choosing octetArray as
+         abstract data type for this Information Element.  The maximum
+         length of this Information Element is 256 octets.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc4364"/> for the specification of the
+          route distinguisher.  See <xref type="rfc" data="rfc4382"/> for the
+          specification of the MPLS/BGP Layer 3 Virtual Private Network (VPN)
+          Management Information Base.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsTopLabelPrefixLength</name>
+      <dataType>unsigned8</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>91</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The prefix length of the subnet of the mplsTopLabelIPv4Address that
+          the MPLS top label will cause the Flow to be forwarded to.
+        </paragraph>
+      </description>
+      <units>bits</units>
+      <range>0-32</range>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3031"/> for the association between 
+          MPLS labels and prefix lengths.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record> 
+    <record>
+      <elementId>92-93</elementId>
+      <reserved/>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>applicationDescription</name>
+      <dataType>string</dataType>
+      <elementId>94</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Specifies the description of an application.
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc6759"/>
+    </record>
+
+    <record>
+      <name>applicationId</name>
+      <dataType>octetArray</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>95</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Specifies an Application ID per <xref type="rfc" data="rfc6759"/>.
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See section 4 of <xref type="rfc" data="rfc6759"/> for the applicationId Information Element Specification.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc6759"/>
+    </record>
+
+    <record>
+      <name>applicationName</name>
+      <dataType>string</dataType>
+      <elementId>96</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Specifies the name of an application.
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc6759"/>
+    </record>
+
+    <record>
+      <elementId>97</elementId>
+      <reserved/>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>postIpDiffServCodePoint</name>
+      <dataType>unsigned8</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>98</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The definition of this Information Element is identical to the 
+          definition of Information Element 'ipDiffServCodePoint', except 
+          that it reports a potentially modified value caused by a 
+          middlebox function after the packet passed the Observation 
+          Point.
+        </paragraph>
+      </description>
+      <range>0-63</range>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3260"/> for the definition of the Differentiated 
+          Services Field.  See section 5.3.2 of <xref type="rfc" data="rfc1812"/> and 
+          <xref type="rfc" data="rfc791"/> for the definition of the IPv4 TOS field.  See 
+          <xref type="rfc" data="rfc2460"/> for the definition of the IPv6 Traffic Class 
+          field.  See the IPFIX Information Model <xref type="rfc" data="rfc5102"/> for the 
+          'ipDiffServCodePoint' specification.  
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>multicastReplicationFactor</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>99</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The amount of multicast replication that's applied to a traffic 
+          stream.
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc1112"/> for the specification of reserved IPv4 
+          multicast addresses.  See <xref type="rfc" data="rfc4291"/> for the 
+          specification of reserved IPv6 multicast addresses. 
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+    
+    <record>  
+      <elementId>100</elementId>
+      <reserved/>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>classificationEngineId</name>
+      <dataType>unsigned8</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>101</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          A unique identifier for the engine that determined the
+          Selector ID. Thus, the Classification Engine ID defines
+          the context for the Selector ID. The Classification
+          Engine can be considered a specific registry for
+          application assignments.
+        </paragraph>
+        <paragraph>
+          Values for this field are listed in the Classification
+          Engine IDs registry. See 
+          <xref type="uri" data="http://www.iana.org/assignments/ipfix/ipfix.xml#classification-engine-ids"/>
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc6759"/>
+    </record>
+
+    <record>  
+      <elementId>102-127</elementId>
+      <reserved/>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>bgpNextAdjacentAsNumber</name>
+      <dataType>unsigned32</dataType>
+      <group>derived</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>128</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The autonomous system (AS) number of the first AS in the AS
+         path to the destination IP address.  The path is deduced
+         by looking up the destination IP address of the Flow in the
+         BGP routing information base.  If AS path information for
+         this Flow is only available as an unordered AS set (and not
+         as an ordered AS sequence), then the value of this Information
+         Element is 0.
+       </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc4271"/> for a description of BGP-4, and
+          see <xref type="rfc" data="rfc1930"/> for the definition of the AS
+          number.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>bgpPrevAdjacentAsNumber</name>
+      <dataType>unsigned32</dataType>
+      <group>derived</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>129</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The autonomous system (AS) number of the last AS in the AS
+         path from the source IP address.  The path is deduced
+         by looking up the source IP address of the Flow in the BGP
+         routing information base.  If AS path information for this
+         Flow is only available as an unordered AS set (and not as
+         an ordered AS sequence), then the value of this Information
+         Element is 0.  In case of BGP asymmetry, the
+         bgpPrevAdjacentAsNumber might not be able to report the correct
+         value.
+       </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc4271"/> for a description of BGP-4, and
+          see <xref type="rfc" data="rfc1930"/> for the definition of the AS
+          number.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>exporterIPv4Address</name>
+      <dataType>ipv4Address</dataType>
+      <group>config</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>130</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The IPv4 address used by the Exporting Process.  This is used
+         by the Collector to identify the Exporter in cases where the
+         identity of the Exporter may have been obscured by the use of
+         a proxy.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>exporterIPv6Address</name>
+      <dataType>ipv6Address</dataType>
+      <group>config</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>131</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The IPv6 address used by the Exporting Process.  This is used
+         by the Collector to identify the Exporter in cases where the
+         identity of the Exporter may have been obscured by the use of
+         a proxy.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>droppedOctetDeltaCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>deltaCounter</dataTypeSemantics>
+      <elementId>132</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The number of octets since the previous report (if any)
+         in packets of this Flow dropped by packet treatment.
+         The number of octets includes IP header(s) and IP payload.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>droppedPacketDeltaCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>deltaCounter</dataTypeSemantics>
+      <elementId>133</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The number of packets since the previous report (if any)
+         of this Flow dropped by packet treatment.
+         </paragraph>
+      </description>
+      <units>packets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>droppedOctetTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>134</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The total number of octets in packets of this Flow dropped
+         by packet treatment since the Metering Process
+         (re-)initialization for this Observation Point.
+         The number of octets includes IP header(s) and IP payload.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>droppedPacketTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>135</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The number of packets of this Flow dropped by packet
+         treatment since the Metering Process
+         (re-)initialization for this Observation Point.
+         </paragraph>
+      </description>
+      <units>packets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowEndReason</name>
+      <dataType>unsigned8</dataType>
+      <group>misc</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>136</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The reason for Flow termination.  The range of values includes
+         the following:
+         </paragraph>
+        <artwork>
+      0x01: idle timeout
+            The Flow was terminated because it was considered to be
+            idle.
+      0x02: active timeout
+            The Flow was terminated for reporting purposes while it was
+            still active, for example, after the maximum lifetime of
+            unreported Flows was reached.
+      0x03: end of Flow detected
+            The Flow was terminated because the Metering Process
+            detected signals indicating the end of the Flow,
+            for example, the TCP FIN flag.
+      0x04: forced end
+            The Flow was terminated because of some external event,
+            for example, a shutdown of the Metering Process initiated
+            by a network management application.
+      0x05: lack of resources
+            The Flow was terminated because of lack of resources
+            available to the Metering Process and/or the Exporting
+            Process.
+         </artwork>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>commonPropertiesId</name>
+      <dataType>unsigned64</dataType>
+      <group>scope</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>137</elementId>
+      <applicability>option</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           An identifier of a set of common properties that is
+           unique per Observation Domain and Transport Session.
+           Typically, this Information Element is used to link to
+           information reported in separate Data Records.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>observationPointId</name>
+      <dataType>unsigned32</dataType>
+      <group>scope</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>138</elementId>
+      <applicability>option</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         An identifier of an Observation Point that is unique per
+         Observation Domain.  It is RECOMMENDED that this identifier is
+         also unique per IPFIX Device.  Typically, this Information
+         Element is used for limiting the scope of other Information
+         Elements.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>icmpTypeCodeIPv6</name>
+      <dataType>unsigned16</dataType>
+      <group>transportHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>139</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         Type and Code of the IPv6 ICMP message.  The combination of
+         both values is reported as (ICMP type * 256) + ICMP code.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc4443"/> for the definition of the IPv6
+          ICMP type and code fields.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsTopLabelIPv6Address</name>
+      <dataType>ipv6Address</dataType>
+      <group>derived</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>140</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           The IPv6 address of the system that the MPLS top label will
+           cause this Flow to be forwarded to.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3031"/> for the association between MPLS
+          labels and IP addresses.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>lineCardId</name>
+      <dataType>unsigned32</dataType>
+      <group>scope</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>141</elementId>
+      <applicability>option</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           An identifier of a line card that is unique per IPFIX
+           Device hosting an Observation Point.  Typically, this
+           Information Element is used for limiting the scope
+           of other Information Elements.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>portId</name>
+      <dataType>unsigned32</dataType>
+      <group>scope</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>142</elementId>
+      <applicability>option</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           An identifier of a line port that is unique per IPFIX
+           Device hosting an Observation Point.  Typically, this
+           Information Element is used for limiting the scope
+           of other Information Elements.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>meteringProcessId</name>
+      <dataType>unsigned32</dataType>
+      <group>scope</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>143</elementId>
+      <applicability>option</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           An identifier of a Metering Process that is unique per
+           IPFIX Device.  Typically, this Information Element is used
+           for limiting the scope of other Information Elements.
+           Note that process identifiers are typically assigned
+           dynamically.
+           The Metering Process may be re-started with a different ID.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>exportingProcessId</name>
+      <dataType>unsigned32</dataType>
+      <group>scope</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>144</elementId>
+      <applicability>option</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           An identifier of an Exporting Process that is unique per
+           IPFIX Device.  Typically, this Information Element is used
+           for limiting the scope of other Information Elements.
+           Note that process identifiers are typically assigned
+           dynamically.  The Exporting Process may be re-started
+           with a different ID.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>templateId</name>
+      <dataType>unsigned16</dataType>
+      <group>scope</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>145</elementId>
+      <applicability>option</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           An identifier of a Template that is locally unique within a
+           combination of a Transport session and an Observation Domain.
+         </paragraph>
+        <paragraph>
+           Template IDs 0-255 are reserved for Template Sets, Options
+           Template Sets, and other reserved Sets yet to be created.
+           Template IDs of Data Sets are numbered from 256 to 65535.
+         </paragraph>
+        <paragraph>
+           Typically, this Information Element is used for limiting
+           the scope of other Information Elements.
+           Note that after a re-start of the Exporting Process Template
+           identifiers may be re-assigned.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>wlanChannelId</name>
+      <dataType>unsigned8</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>146</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           The identifier of the 802.11 (Wi-Fi) channel used.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See IEEE.802-11.1999.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>wlanSSID</name>
+      <dataType>string</dataType>
+      <group>subIpHeader</group>
+      <elementId>147</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           The Service Set IDentifier (SSID) identifying an 802.11
+           (Wi-Fi) network used.  According to IEEE.802-11.1999, the
+           SSID is encoded into a string of up to 32 characters.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See IEEE.802-11.1999.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowId</name>
+      <dataType>unsigned64</dataType>
+      <group>scope</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>148</elementId>
+      <applicability>option</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           An identifier of a Flow that is unique within an Observation
+           Domain.  This Information Element can be used to distinguish
+           between different Flows if Flow Keys such as IP addresses and
+           port numbers are not reported or are reported in separate
+           records.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>observationDomainId</name>
+      <dataType>unsigned32</dataType>
+      <group>scope</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>149</elementId>
+      <applicability>option</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           An identifier of an Observation Domain that is locally
+           unique to an Exporting Process.  The Exporting Process uses
+           the Observation Domain ID to uniquely identify to the
+           Collecting Process the Observation Domain where Flows
+           were metered.  It is RECOMMENDED that this identifier is
+           also unique per IPFIX Device.
+         </paragraph>
+        <paragraph>
+           A value of 0 indicates that no specific Observation Domain
+           is identified by this Information Element.
+         </paragraph>
+        <paragraph>
+           Typically, this Information Element is used for limiting
+           the scope of other Information Elements.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowStartSeconds</name>
+      <dataType>dateTimeSeconds</dataType>
+      <group>timestamp</group>
+      <elementId>150</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The absolute timestamp of the first packet of this Flow.
+         </paragraph>
+      </description>
+      <units>seconds</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowEndSeconds</name>
+      <dataType>dateTimeSeconds</dataType>
+      <group>timestamp</group>
+      <elementId>151</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The absolute timestamp of the last packet of this Flow.
+         </paragraph>
+      </description>
+      <units>seconds</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowStartMilliseconds</name>
+      <dataType>dateTimeMilliseconds</dataType>
+      <group>timestamp</group>
+      <elementId>152</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The absolute timestamp of the first packet of this Flow.
+         </paragraph>
+      </description>
+      <units>milliseconds</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowEndMilliseconds</name>
+      <dataType>dateTimeMilliseconds</dataType>
+      <group>timestamp</group>
+      <elementId>153</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The absolute timestamp of the last packet of this Flow.
+         </paragraph>
+      </description>
+      <units>milliseconds</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowStartMicroseconds</name>
+      <dataType>dateTimeMicroseconds</dataType>
+      <group>timestamp</group>
+      <elementId>154</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The absolute timestamp of the first packet of this Flow.
+         </paragraph>
+      </description>
+      <units>microseconds</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowEndMicroseconds</name>
+      <dataType>dateTimeMicroseconds</dataType>
+      <group>timestamp</group>
+      <elementId>155</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The absolute timestamp of the last packet of this Flow.
+         </paragraph>
+      </description>
+      <units>microseconds</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowStartNanoseconds</name>
+      <dataType>dateTimeNanoseconds</dataType>
+      <group>timestamp</group>
+      <elementId>156</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The absolute timestamp of the first packet of this Flow.
+         </paragraph>
+      </description>
+      <units>nanoseconds</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowEndNanoseconds</name>
+      <dataType>dateTimeNanoseconds</dataType>
+      <group>timestamp</group>
+      <elementId>157</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The absolute timestamp of the last packet of this Flow.
+         </paragraph>
+      </description>
+      <units>nanoseconds</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowStartDeltaMicroseconds</name>
+      <dataType>unsigned32</dataType>
+      <group>timestamp</group>
+      <elementId>158</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         This is a relative timestamp only valid within the scope
+         of a single IPFIX Message.  It contains the negative time
+         offset of the first observed packet of this Flow relative
+         to the export time specified in the IPFIX Message Header.
+         </paragraph>
+      </description>
+      <units>microseconds</units>
+      <references>
+        <paragraph>
+          See the <xref type="rfc" data="rfc5101">IPFIX protocol
+            specification</xref> for the definition of the IPFIX Message Header.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowEndDeltaMicroseconds</name>
+      <dataType>unsigned32</dataType>
+      <group>timestamp</group>
+      <elementId>159</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         This is a relative timestamp only valid within the scope
+         of a single IPFIX Message.  It contains the negative time
+         offset of the last observed packet of this Flow relative
+         to the export time specified in the IPFIX Message Header.
+         </paragraph>
+      </description>
+      <units>microseconds</units>
+      <references>
+        <paragraph>
+          See the <xref type="rfc" data="rfc5101">IPFIX protocol
+            specification</xref> for the definition of the IPFIX Message Header.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>systemInitTimeMilliseconds</name>
+      <dataType>dateTimeMilliseconds</dataType>
+      <group>timestamp</group>
+      <elementId>160</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The absolute timestamp of the last (re-)initialization of the
+         IPFIX Device.
+         </paragraph>
+      </description>
+      <units>milliseconds</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowDurationMilliseconds</name>
+      <dataType>unsigned32</dataType>
+      <group>misc</group>
+      <elementId>161</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The difference in time between the first observed packet
+         of this Flow and the last observed packet of this Flow.
+         </paragraph>
+      </description>
+      <units>milliseconds</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowDurationMicroseconds</name>
+      <dataType>unsigned32</dataType>
+      <group>misc</group>
+      <elementId>162</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The difference in time between the first observed packet
+         of this Flow and the last observed packet of this Flow.
+         </paragraph>
+      </description>
+      <units>microseconds</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>observedFlowTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>processCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>163</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The total number of Flows observed in the Observation Domain
+         since the Metering Process (re-)initialization for this
+         Observation Point.
+         </paragraph>
+      </description>
+      <units>flows</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>ignoredPacketTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>processCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>164</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+            The total number of observed IP packets that the
+            Metering Process did not process since the
+            (re-)initialization of the Metering Process.
+         </paragraph>
+      </description>
+      <units>packets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>ignoredOctetTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>processCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>165</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+            The total number of octets in observed IP packets
+            (including the IP header) that the Metering Process
+            did not process since the (re-)initialization of the
+            Metering Process.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>notSentFlowTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>processCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>166</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+            The total number of Flow Records that were generated by the
+            Metering Process and dropped by the Metering Process or
+            by the Exporting Process instead of being sent to the
+            Collecting Process.  There are several potential reasons for
+            this including resource shortage and special Flow export
+            policies.
+         </paragraph>
+      </description>
+      <units>flows</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>notSentPacketTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>processCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>167</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+            The total number of packets in Flow Records that were
+            generated by the Metering Process and dropped
+            by the Metering Process or by the Exporting Process
+            instead of being sent to the Collecting Process.
+            There are several potential reasons for this including
+            resource shortage and special Flow export policies.
+         </paragraph>
+      </description>
+      <units>packets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>notSentOctetTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>processCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>168</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+            The total number of octets in packets in Flow Records
+            that were generated by the Metering Process and
+            dropped by the Metering Process or by the Exporting
+            Process instead of being sent to the Collecting Process.
+            There are several potential reasons for this including
+            resource shortage and special Flow export policies.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>destinationIPv6Prefix</name>
+      <dataType>ipv6Address</dataType>
+      <group>ipHeader</group>
+      <elementId>169</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph> IPv6 destination address prefix. </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>sourceIPv6Prefix</name>
+      <dataType>ipv6Address</dataType>
+      <group>ipHeader</group>
+      <elementId>170</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         IPv6 source address prefix.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>postOctetTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>171</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The definition of this Information Element is identical
+         to the definition of Information Element
+         'octetTotalCount', except that it reports a
+         potentially modified value caused by a middlebox
+         function after the packet passed the Observation Point.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>postPacketTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>172</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The definition of this Information Element is identical
+         to the definition of Information Element
+         'packetTotalCount', except that it reports a
+         potentially modified value caused by a middlebox
+         function after the packet passed the Observation Point.
+         </paragraph>
+      </description>
+      <units>packets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>flowKeyIndicator</name>
+      <dataType>unsigned64</dataType>
+      <group>config</group>
+      <dataTypeSemantics>flags</dataTypeSemantics>
+      <elementId>173</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         This set of bit fields is used for marking the Information
+         Elements of a Data Record that serve as Flow Key.  Each bit
+         represents an Information Element in the Data Record with
+         the n-th bit representing the n-th Information Element.
+         A bit set to value 1 indicates that the corresponding
+         Information Element is a Flow Key of the reported Flow.
+         A bit set to value 0 indicates that this is not the case.
+         </paragraph>
+        <paragraph>
+         If the Data Record contains more than 64 Information Elements,
+         the corresponding Template SHOULD be designed such that all
+         Flow Keys are among the first 64 Information Elements, because
+         the flowKeyIndicator only contains 64 bits.  If the Data Record
+         contains less than 64 Information Elements, then the bits in
+         the flowKeyIndicator for which no corresponding Information
+         Element exists MUST have the value 0.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>postMCastPacketTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>174</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The total number of outgoing multicast packets sent for
+         packets of this Flow by a multicast daemon within the
+         Observation Domain since the Metering Process
+         (re-)initialization.  This property cannot necessarily
+         be observed at the Observation Point, but may be retrieved
+         by other means.
+         </paragraph>
+      </description>
+      <units>packets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>postMCastOctetTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>175</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The total number of octets in outgoing multicast packets
+         sent for packets of this Flow by a multicast daemon in the
+         Observation Domain since the Metering Process
+         (re-)initialization.  This property cannot necessarily be
+         observed at the Observation Point, but may be retrieved by
+         other means.
+         The number of octets includes IP header(s) and IP payload.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>icmpTypeIPv4</name>
+      <dataType>unsigned8</dataType>
+      <group>transportHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>176</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         Type of the IPv4 ICMP message.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc792"/> for the definition of the IPv4
+          ICMP type field.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>icmpCodeIPv4</name>
+      <dataType>unsigned8</dataType>
+      <group>transportHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>177</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         Code of the IPv4 ICMP message.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc792"/> for the definition of the IPv4
+          ICMP code field.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>icmpTypeIPv6</name>
+      <dataType>unsigned8</dataType>
+      <group>transportHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>178</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         Type of the IPv6 ICMP message.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc4443"/> for the definition of the IPv6
+          ICMP type field.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>icmpCodeIPv6</name>
+      <dataType>unsigned8</dataType>
+      <group>transportHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>179</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         Code of the IPv6 ICMP message.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc4443"/> for the definition of the IPv6
+          ICMP code field.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>udpSourcePort</name>
+      <dataType>unsigned16</dataType>
+      <group>transportHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>180</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The source port identifier in the UDP header.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc768"/> for the definition of the UDP
+          source port field.
+          Additional information on defined UDP port numbers can be found at
+          <xref type="registry" data="port-numbers"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>udpDestinationPort</name>
+      <dataType>unsigned16</dataType>
+      <group>transportHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>181</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The destination port identifier in the UDP header.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc768"/> for the definition of the UDP
+          destination port field.
+          Additional information on defined UDP port numbers can be found at
+          <xref type="registry" data="port-numbers"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>tcpSourcePort</name>
+      <dataType>unsigned16</dataType>
+      <group>transportHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>182</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The source port identifier in the TCP header.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc793"/> for the definition of the TCP
+          source port field.
+          Additional information on defined TCP port numbers can be found at
+          <xref type="registry" data="port-numbers"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>tcpDestinationPort</name>
+      <dataType>unsigned16</dataType>
+      <group>transportHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>183</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The destination port identifier in the TCP header.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc793"/> for the definition of the TCP
+          destination port field.
+          Additional information on defined TCP port numbers can be found at
+          <xref type="registry" data="port-numbers"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>tcpSequenceNumber</name>
+      <dataType>unsigned32</dataType>
+      <group>transportHeader</group>
+      <elementId>184</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The sequence number in the TCP header.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc793"/> for the definition of the TCP
+          sequence number.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>tcpAcknowledgementNumber</name>
+      <dataType>unsigned32</dataType>
+      <group>transportHeader</group>
+      <elementId>185</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The acknowledgement number in the TCP header.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc793"/> for the definition of the TCP
+          acknowledgement number.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>tcpWindowSize</name>
+      <dataType>unsigned16</dataType>
+      <group>transportHeader</group>
+      <elementId>186</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The window field in the TCP header.
+         If the TCP window scale is supported,
+         then TCP window scale must be known
+         to fully interpret the value of this information.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc793"/> for the definition of the TCP
+          window field.
+          See <xref type="rfc" data="rfc1323"/> for the definition of the TCP
+          window scale.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>tcpUrgentPointer</name>
+      <dataType>unsigned16</dataType>
+      <group>transportHeader</group>
+      <elementId>187</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The urgent pointer in the TCP header.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc793"/> for the definition of the TCP
+          urgent pointer.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>tcpHeaderLength</name>
+      <dataType>unsigned8</dataType>
+      <group>transportHeader</group>
+      <elementId>188</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The length of the TCP header.  Note that the value of this
+         Information Element is different from the value of the Data
+         Offset field in the TCP header.  The Data Offset field
+         indicates the length of the TCP header in units of 4 octets.
+         This Information Elements specifies the length of the TCP
+         header in units of octets.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc793"/> for the definition of the TCP
+          header.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>ipHeaderLength</name>
+      <dataType>unsigned8</dataType>
+      <group>ipHeader</group>
+      <elementId>189</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The length of the IP header.  For IPv6, the value of this
+         Information Element is 40.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the definition of the IPv4
+          header.
+          See <xref type="rfc" data="rfc2460"/> for the definition of the IPv6
+          header.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>totalLengthIPv4</name>
+      <dataType>unsigned16</dataType>
+      <group>ipHeader</group>
+      <elementId>190</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The total length of the IPv4 packet.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the specification of the IPv4
+          total length.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>payloadLengthIPv6</name>
+      <dataType>unsigned16</dataType>
+      <group>ipHeader</group>
+      <elementId>191</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         This Information Element reports the value of the Payload
+         Length field in the IPv6 header.  Note that IPv6 extension
+         headers belong to the payload.  Also note that in case of a
+         jumbo payload option the value of the Payload Length field in
+         the IPv6 header is zero and so will be the value reported
+         by this Information Element.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc2460"/> for the specification of the IPv6
+          payload length.
+          See <xref type="rfc" data="rfc2675"/> for the specification of the IPv6
+          jumbo payload option.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>ipTTL</name>
+      <dataType>unsigned8</dataType>
+      <group>ipHeader</group>
+      <elementId>192</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         For IPv4, the value of the Information Element matches
+         the value of the Time to Live (TTL) field in the IPv4 packet
+         header.  For IPv6, the value of the Information Element
+         matches the value of the Hop Limit field in the IPv6
+         packet header.
+         </paragraph>
+      </description>
+      <units>hops</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the definition of the IPv4
+          Time to Live field.
+          See <xref type="rfc" data="rfc2675"/> for the definition of the IPv6
+          Hop Limit field.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>nextHeaderIPv6</name>
+      <dataType>unsigned8</dataType>
+      <group>ipHeader</group>
+      <elementId>193</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The value of the Next Header field of the IPv6 header.
+         The value identifies the type of the following IPv6
+         extension header or of the following IP payload.
+         Valid values are defined in the IANA
+         Protocol Numbers registry.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc2460"/> for the definition of the IPv6
+          Next Header field.
+          See the list of protocol numbers assigned by IANA at <xref type="registry" data="protocol-numbers"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsPayloadLength</name>
+      <dataType>unsigned32</dataType>
+      <group>subIpHeader</group>
+      <elementId>194</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The size of the MPLS packet without the label stack.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3031"/> for the specification of MPLS
+          packets.
+          See <xref type="rfc" data="rfc3032"/> for the specification of the
+          MPLS label stack.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>ipDiffServCodePoint</name>
+      <dataType>unsigned8</dataType>
+      <group>ipHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>195</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The value of a Differentiated Services Code Point (DSCP)
+         encoded in the Differentiated Services field.  The
+         Differentiated Services field spans the most significant
+         6 bits of the IPv4 TOS field or the IPv6 Traffic Class
+         field, respectively.
+         </paragraph>
+        <paragraph>
+         This Information Element encodes only the 6 bits of the
+         Differentiated Services field.  Therefore, its value may
+         range from 0 to 63.
+         </paragraph>
+      </description>
+      <range>0-63</range>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3260"/> for the definition of the
+          Differentiated Services field.
+          See <xref type="rfc" data="rfc1812"/> (Section 5.3.2) and <xref type="rfc" data="rfc791"/> for the definition of the IPv4 TOS field.
+          See <xref type="rfc" data="rfc2460"/> for the definition of the IPv6
+          Traffic Class field.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>ipPrecedence</name>
+      <dataType>unsigned8</dataType>
+      <group>ipHeader</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>196</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The value of the IP Precedence.  The IP Precedence value
+         is encoded in the first 3 bits of the IPv4 TOS field
+         or the IPv6 Traffic Class field, respectively.
+         </paragraph>
+        <paragraph>
+         This Information Element encodes only these 3 bits.
+         Therefore, its value may range from 0 to 7.
+         </paragraph>
+      </description>
+      <range>0-7</range>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc1812"/> (Section 5.3.3) and <xref type="rfc" data="rfc791"/> for the definition of the IP Precedence.
+          See <xref type="rfc" data="rfc1812"/> (Section 5.3.2) and <xref type="rfc" data="rfc791"/> for the definition of the IPv4 TOS field.
+          See <xref type="rfc" data="rfc2460"/> for the definition of the IPv6
+          Traffic Class field.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>fragmentFlags</name>
+      <dataType>unsigned8</dataType>
+      <group>ipHeader</group>
+      <dataTypeSemantics>flags</dataTypeSemantics>
+      <elementId>197</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           Fragmentation properties indicated by flags in the IPv4
+           packet header or the IPv6 Fragment header, respectively.
+         </paragraph>
+        <artwork>
+
+         Bit 0:    (RS) Reserved.
+                   The value of this bit MUST be 0 until specified
+                   otherwise.
+         Bit 1:    (DF) 0 = May Fragment,  1 = Don't Fragment.
+                   Corresponds to the value of the DF flag in the
+                   IPv4 header.  Will always be 0 for IPv6 unless
+                   a "don't fragment" feature is introduced to IPv6.
+         Bit 2:    (MF) 0 = Last Fragment, 1 = More Fragments.
+                   Corresponds to the MF flag in the IPv4 header
+                   or to the M flag in the IPv6 Fragment header,
+                   respectively.  The value is 0 for IPv6 if there
+                   is no fragment header.
+         Bits 3-7: (DC) Don't Care.
+                   The values of these bits are irrelevant.
+
+             0   1   2   3   4   5   6   7
+           +---+---+---+---+---+---+---+---+
+           | R | D | M | D | D | D | D | D |
+           | S | F | F | C | C | C | C | C |
+           +---+---+---+---+---+---+---+---+
+         </artwork>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the specification of the IPv4
+          fragment flags.
+          See <xref type="rfc" data="rfc2460"/> for the specification of the
+          IPv6 Fragment header.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>octetDeltaSumOfSquares</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <elementId>198</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The sum of the squared numbers of octets per incoming
+         packet since the previous report (if any) for this
+         Flow at the Observation Point.
+         The number of octets includes IP header(s) and IP payload.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>octetTotalSumOfSquares</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <elementId>199</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The total sum of the squared numbers of octets in incoming
+         packets for this Flow at the Observation Point since the
+         Metering Process (re-)initialization for this Observation
+         Point.  The number of octets includes IP header(s) and IP
+         payload.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsTopLabelTTL</name>
+      <dataType>unsigned8</dataType>
+      <group>subIpHeader</group>
+      <elementId>200</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The TTL field from the top MPLS label stack entry,
+         i.e., the last label that was pushed.
+         </paragraph>
+      </description>
+      <units>hops</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3032"/> for the specification of the TTL
+          field.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsLabelStackLength</name>
+      <dataType>unsigned32</dataType>
+      <group>subIpHeader</group>
+      <elementId>201</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The length of the MPLS label stack in units of octets.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3032"/> for the specification of the
+          MPLS label stack.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsLabelStackDepth</name>
+      <dataType>unsigned32</dataType>
+      <group>subIpHeader</group>
+      <elementId>202</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The number of labels in the MPLS label stack.
+         </paragraph>
+      </description>
+      <units>label stack entries</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3032"/> for the specification of the
+          MPLS label stack.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>mplsTopLabelExp</name>
+      <dataType>unsigned8</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>flags</dataTypeSemantics>
+      <elementId>203</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The Exp field from the top MPLS label stack entry,
+         i.e., the last label that was pushed.
+         </paragraph>
+        <artwork>
+         Bits 0-4:  Don't Care, value is irrelevant.
+         Bits 5-7:  MPLS Exp field.
+
+             0   1   2   3   4   5   6   7
+           +---+---+---+---+---+---+---+---+
+           |     don't care    |    Exp    |
+           +---+---+---+---+---+---+---+---+
+         </artwork>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3032"/> for the specification of the
+          Exp field.
+          See <xref type="rfc" data="rfc3270"/> for usage of the Exp field.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>ipPayloadLength</name>
+      <dataType>unsigned32</dataType>
+      <group>derived</group>
+      <elementId>204</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The effective length of the IP payload.
+         </paragraph>
+        <paragraph>
+         For IPv4 packets, the value of this Information Element is
+         the difference between the total length of the IPv4 packet
+         (as reported by Information Element totalLengthIPv4) and the
+         length of the IPv4 header (as reported by Information Element
+         headerLengthIPv4).
+         </paragraph>
+        <paragraph>
+         For IPv6, the value of the Payload Length field
+         in the IPv6 header is reported except in the case that
+         the value of this field is zero and that there is a valid
+         jumbo payload option.  In this case, the value of the
+         Jumbo Payload Length field in the jumbo payload option
+         is reported.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the specification of IPv4
+          packets.
+          See <xref type="rfc" data="rfc2460"/> for the specification of the
+          IPv6 payload length.
+          See <xref type="rfc" data="rfc2675"/> for the specification of the
+          IPv6 jumbo payload length.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>udpMessageLength</name>
+      <dataType>unsigned16</dataType>
+      <group>transportHeader</group>
+      <elementId>205</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The value of the Length field in the UDP header.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc768"/> for the specification of the UDP
+          header.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>isMulticast</name>
+      <dataType>unsigned8</dataType>
+      <group>ipHeader</group>
+      <dataTypeSemantics>flags</dataTypeSemantics>
+      <elementId>206</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           If the IP destination address is not a reserved multicast
+           address, then the value of all bits of the octet (including
+           the reserved ones) is zero.
+         </paragraph>
+        <paragraph>
+           The first bit of this octet is set to 1 if the Version
+           field of the IP header has the value 4 and if the
+           Destination Address field contains a reserved multicast
+           address in the range from 224.0.0.0 to 239.255.255.255.
+           Otherwise, this bit is set to 0.
+         </paragraph>
+        <paragraph>
+           The second and third bits of this octet are reserved for
+           future use.
+         </paragraph>
+        <paragraph>
+           The remaining bits of the octet are only set to values
+           other than zero if the IP Destination Address is a
+           reserved IPv6 multicast address.  Then the fourth bit
+           of the octet is set to the value of the T flag in the
+           IPv6 multicast address and the remaining four bits are
+           set to the value of the scope field in the IPv6
+           multicast address.
+         </paragraph>
+        <artwork>
+             0      1      2      3      4      5      6      7
+          +------+------+------+------+------+------+------+------+
+          |   IPv6 multicast scope    |  T   | RES. | RES. | MCv4 |
+          +------+------+------+------+------+------+------+------+
+
+          Bits 0-3:  set to value of multicast scope if IPv6 multicast
+          Bit  4:    set to value of T flag, if IPv6 multicast
+          Bits 5-6:  reserved for future use
+          Bit  7:    set to 1 if IPv4 multicast
+         </artwork>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc1112"/> for the specification of
+          reserved IPv4 multicast addresses.
+          See <xref type="rfc" data="rfc4291"/> for the specification of
+          reserved IPv6 multicast addresses and the definition of the T flag and
+          the IPv6 multicast scope.
+          The diagram provided in <xref type="rfc" data="rfc5102"/> is incorrect.  
+          The diagram in this registry is taken from Errata 1736. See <xref type="rfc-errata" data="1736"/>
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>ipv4IHL</name>
+      <dataType>unsigned8</dataType>
+      <group>ipHeader</group>
+      <elementId>207</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The value of the Internet Header Length (IHL) field in
+         the IPv4 header.  It specifies the length of the header
+         in units of 4 octets.  Please note that its unit is
+         different from most of the other Information Elements
+         reporting length values.
+         </paragraph>
+      </description>
+      <units>4 octets</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the specification of the IPv4
+          header.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>ipv4Options</name>
+      <dataType>unsigned32</dataType>
+      <group>minMax</group>
+      <dataTypeSemantics>flags</dataTypeSemantics>
+      <elementId>208</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         IPv4 options in packets of this Flow.
+         The information is encoded in a set of bit fields.  For
+         each valid IPv4 option type, there is a bit in this set.
+         The bit is set to 1 if any observed packet of this Flow
+         contains the corresponding IPv4 option type.  Otherwise,
+         if no observed packet of this Flow contained the
+         respective IPv4 option type, the value of the
+         corresponding bit is 0.
+         </paragraph>
+        <paragraph>
+         The list of valid IPv4 options is maintained by IANA.
+         Note that for identifying an option not just the 5-bit
+         Option Number, but all 8 bits of the Option Type need to
+         match one of the IPv4 options specified at
+         http://www.iana.org/assignments/ip-parameters.
+         </paragraph>
+        <paragraph>
+         Options are mapped to bits according to their option numbers.
+         Option number X is mapped to bit X.
+         The mapping is illustrated by the figure below.
+         </paragraph>
+        <artwork>
+           0      1      2      3      4      5      6      7
+       +------+------+------+------+------+------+------+------+
+   ... |  RR  |CIPSO |E-SEC |  TS  | LSR  |  SEC | NOP  | EOOL |
+       +------+------+------+------+------+------+------+------+
+
+           8      9     10     11     12     13     14     15
+       +------+------+------+------+------+------+------+------+
+   ... |ENCODE| VISA | FINN | MTUR | MTUP | ZSU  | SSR  | SID  | ...
+       +------+------+------+------+------+------+------+------+
+
+          16     17     18     19     20     21     22     23
+       +------+------+------+------+------+------+------+------+
+   ... | DPS  |NSAPA | SDB  |RTRALT|ADDEXT|  TR  | EIP  |IMITD | ...
+       +------+------+------+------+------+------+------+------+
+
+          24     25     26     27     28     29     30     31
+       +------+------+------+------+------+------+------+------+
+       |      | EXP  |   to be assigned by IANA  |  QS  | UMP  | ...
+       +------+------+------+------+------+------+------+------+
+
+           Type   Option
+       Bit Value  Name    Reference
+       ---+-----+-------+------------------------------------
+        0     7   RR      Record Route, RFC 791
+        1   134   CIPSO   Commercial Security
+        2   133   E-SEC   Extended Security, RFC 1108
+        3    68   TS      Time Stamp, RFC 791
+        4   131   LSR     Loose Source Route, RFC791
+        5   130   SEC     Security, RFC 1108
+        6     1   NOP     No Operation, RFC 791
+        7     0   EOOL    End of Options List, RFC 791
+        8    15   ENCODE
+        9   142   VISA    Experimental Access Control
+       10   205   FINN    Experimental Flow Control
+       11    12   MTUR    (obsoleted) MTU Reply, RFC 1191
+       12    11   MTUP    (obsoleted) MTU Probe, RFC 1191
+       13    10   ZSU     Experimental Measurement
+       14   137   SSR     Strict Source Route, RFC 791
+       15   136   SID     Stream ID, RFC 791
+       16   151   DPS     Dynamic Packet State
+       17   150   NSAPA   NSAP Address
+       18   149   SDB     Selective Directed Broadcast
+       19   147   ADDEXT  Address Extension
+       20   148   RTRALT  Router Alert, RFC 2113
+       21    82   TR      Traceroute, RFC 3193
+       22   145   EIP     Extended Internet Protocol, RFC 1385
+       23   144   IMITD   IMI Traffic Descriptor
+       25    30   EXP     RFC3692-style Experiment
+       25    94   EXP     RFC3692-style Experiment
+       25   158   EXP     RFC3692-style Experiment
+       25   222   EXP     RFC3692-style Experiment
+       30    25   QS      Quick-Start
+       31   152   UMP     Upstream Multicast Pkt.
+       ...  ...   ...     Further options numbers
+                          may be assigned by IANA
+
+         </artwork>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the definition of IPv4
+          options.
+          See the list of IPv4 option numbers assigned by IANA at <xref type="registry" data="ip-parameters"/>.
+          The diagram provided in <xref type="rfc" data="rfc5102"/> is incorrect.  
+          The diagram in this registry is taken from Errata 1737. See <xref type="rfc-errata" data="1737"/>   
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>tcpOptions</name>
+      <dataType>unsigned64</dataType>
+      <group>minMax</group>
+      <dataTypeSemantics>flags</dataTypeSemantics>
+      <elementId>209</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+        TCP options in packets of this Flow.
+        The information is encoded in a set of bit fields.  For
+        each TCP option, there is a bit in this set.
+        The bit is set to 1 if any observed packet of this Flow
+        contains the corresponding TCP option.
+        Otherwise, if no observed packet of this Flow contained
+        the respective TCP option, the value of the
+        corresponding bit is 0.
+         </paragraph>
+        <paragraph>
+         Options are mapped to bits according to their option
+         numbers.  Option number X is mapped to bit X.
+         TCP option numbers are maintained by IANA.
+         </paragraph>
+        <artwork>
+              0     1     2     3     4     5     6     7
+          +-----+-----+-----+-----+-----+-----+-----+-----+
+          |   7 |   6 |   5 |   4 |   3 |   2 |   1 |   0 |  ...
+          +-----+-----+-----+-----+-----+-----+-----+-----+
+
+              8     9    10    11    12    13    14    15
+          +-----+-----+-----+-----+-----+-----+-----+-----+
+      ... |  15 |  14 |  13 |  12 |  11 |  10 |   9 |   8 |...
+          +-----+-----+-----+-----+-----+-----+-----+-----+
+
+             16    17    18    19    20    21    22    23
+          +-----+-----+-----+-----+-----+-----+-----+-----+
+      ... |  23 |  22 |  21 |  20 |  19 |  18 |  17 |  16 |...
+          +-----+-----+-----+-----+-----+-----+-----+-----+
+
+                                . . .
+
+             56    57    58    59    60    61    62    63
+          +-----+-----+-----+-----+-----+-----+-----+-----+
+      ... |  63 |  62 |  61 |  60 |  59 |  58 |  57 |  56 |
+          +-----+-----+-----+-----+-----+-----+-----+-----+
+         </artwork>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc793"/> for the definition of TCP
+          options.
+          See the list of TCP option numbers assigned by IANA at <xref type="registry" data="tcp-parameters"/>.
+          The diagram provided in <xref type="rfc" data="rfc5102"/> is incorrect.  
+          The diagram in this registry is taken from Errata 1739. See <xref type="rfc-errata" data="1739"/>
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>paddingOctets</name>
+      <dataType>octetArray</dataType>
+      <group>padding</group>
+      <elementId>210</elementId>
+      <applicability>option</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           The value of this Information Element is always a sequence of
+           0x00 values.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>collectorIPv4Address</name>
+      <dataType>ipv4Address</dataType>
+      <group>config</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>211</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         An IPv4 address to which the Exporting Process sends Flow
+         information.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>collectorIPv6Address</name>
+      <dataType>ipv6Address</dataType>
+      <group>config</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>212</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         An IPv6 address to which the Exporting Process sends Flow
+         information.
+         </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>exportInterface</name>
+      <dataType>unsigned32</dataType>
+      <group>config</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>213</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           The index of the interface from which IPFIX Messages sent
+           by the Exporting Process to a Collector leave the IPFIX
+           Device.  The value matches the value of
+           managed object 'ifIndex' as defined in RFC 2863.
+           Note that ifIndex values are not assigned statically to an
+           interface and that the interfaces may be renumbered every
+           time the device's management system is re-initialized, as
+           specified in RFC 2863.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc2863"/> for the definition of the
+          ifIndex object.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>exportProtocolVersion</name>
+      <dataType>unsigned8</dataType>
+      <group>config</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>214</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+           The protocol version used by the Exporting Process for
+           sending Flow information.  The protocol version is given
+           by the value of the Version Number field in the Message
+           Header.
+         </paragraph>
+        <paragraph>
+           The protocol version is 10 for IPFIX and 9 for NetFlow
+           version 9.
+           A value of 0 indicates that no export protocol is in use.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See the <xref type="rfc" data="rfc5101">IPFIX protocol
+            specification</xref> for the definition of the IPFIX Message Header.
+          See <xref type="rfc" data="rfc3954"/> for the definition of the
+          NetFlow version 9 message header.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>exportTransportProtocol</name>
+      <dataType>unsigned8</dataType>
+      <group>config</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>215</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The value of the protocol number used by the Exporting Process
+         for sending Flow information.
+         The protocol number identifies the IP packet payload type.
+         Protocol numbers are defined in the IANA Protocol Numbers
+         registry.
+         </paragraph>
+        <paragraph>
+         In Internet Protocol version 4 (IPv4), this is carried in the
+         Protocol field.  In Internet Protocol version 6 (IPv6), this
+         is carried in the Next Header field in the last extension
+         header of the packet.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the specification of the IPv4
+          protocol field.
+          See <xref type="rfc" data="rfc2460"/> for the specification of the
+          IPv6 protocol field.
+          See the list of protocol numbers assigned by IANA at <xref type="registry" data="protocol-numbers"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>collectorTransportPort</name>
+      <dataType>unsigned16</dataType>
+      <group>config</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>216</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The destination port identifier to which the Exporting
+         Process sends Flow information.  For the transport protocols
+         UDP, TCP, and SCTP, this is the destination port number.
+         This field MAY also be used for future transport protocols
+         that have 16-bit source port identifiers.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc768"/> for the definition of the UDP
+          destination port field.
+          See <xref type="rfc" data="rfc793"/> for the definition of the TCP
+          destination port field.
+          See <xref type="rfc" data="rfc4960"/> for the definition of SCTP.
+        </paragraph>
+        <paragraph>
+          Additional information on defined UDP and TCP port numbers can be
+          found at <xref type="registry" data="port-numbers"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>exporterTransportPort</name>
+      <dataType>unsigned16</dataType>
+      <group>config</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>217</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The source port identifier from which the Exporting
+         Process sends Flow information.  For the transport protocols
+         UDP, TCP, and SCTP, this is the source port number.
+         This field MAY also be used for future transport protocols
+         that have 16-bit source port identifiers.  This field may
+         be useful for distinguishing multiple Exporting Processes
+         that use the same IP address.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc768"/> for the definition of the UDP
+          source port field.
+          See <xref type="rfc" data="rfc793"/> for the definition of the TCP
+          source port field.
+          See <xref type="rfc" data="rfc4960"/> for the definition of SCTP.
+        </paragraph>
+        <paragraph>
+          Additional information on defined UDP and TCP port numbers can be
+          found at <xref type="registry" data="port-numbers"/>.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>tcpSynTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>218</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The total number of packets of this Flow with
+          TCP "Synchronize sequence numbers" (SYN) flag set.
+         </paragraph>
+      </description>
+      <units>packets</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc793"/> for the definition of the TCP SYN
+          flag.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>tcpFinTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>219</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The total number of packets of this Flow with
+          TCP "No more data from sender" (FIN) flag set.
+         </paragraph>
+      </description>
+      <units>packets</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc793"/> for the definition of the TCP FIN
+          flag.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>tcpRstTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>220</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The total number of packets of this Flow with
+          TCP "Reset the connection" (RST) flag set.
+         </paragraph>
+      </description>
+      <units>packets</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc793"/> for the definition of the TCP RST
+          flag.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>tcpPshTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>221</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The total number of packets of this Flow with
+          TCP "Push Function" (PSH) flag set.
+         </paragraph>
+      </description>
+      <units>packets</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc793"/> for the definition of the TCP PSH
+          flag.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>tcpAckTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>222</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The total number of packets of this Flow with
+          TCP "Acknowledgment field significant" (ACK) flag set.
+         </paragraph>
+      </description>
+      <units>packets</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc793"/> for the definition of the TCP ACK
+          flag.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>tcpUrgTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <group>flowCounter</group>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>223</elementId>
+      <applicability>data</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The total number of packets of this Flow with
+          TCP "Urgent Pointer field significant" (URG) flag set.
+         </paragraph>
+      </description>
+      <units>packets</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc793"/> for the definition of the TCP URG
+          flag.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>ipTotalLength</name>
+      <dataType>unsigned64</dataType>
+      <group>ipHeader</group>
+      <elementId>224</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The total length of the IP packet.
+         </paragraph>
+      </description>
+      <units>octets</units>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the specification of the IPv4
+          total length.
+          See <xref type="rfc" data="rfc2460"/> for the specification of the
+          IPv6 payload length.
+          See <xref type="rfc" data="rfc2675"/> for the specification of the
+          IPv6 jumbo payload length.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>postNATSourceIPv4Address</name>
+      <dataType>ipv4Address</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>225</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The definition of this Information Element is identical to the 
+          definition of Information Element 'sourceIPv4Address', except 
+          that it reports a modified value caused by a NAT middlebox 
+          function after the packet passed the Observation Point.
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the definition of the IPv4 source 
+          address field.  See <xref type="rfc" data="rfc3022"/> for the definition of 
+          NAT.  See <xref type="rfc" data="rfc3234"/> for the definition of middleboxes. 
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>   
+    <record>
+      <name>postNATDestinationIPv4Address</name>
+      <dataType>ipv4Address</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>226</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The definition of this Information Element is identical to the 
+          definition of Information Element 'destinationIPv4Address', 
+          except that it reports a modified value caused by a NAT 
+          middlebox function after the packet passed the Observation 
+          Point.
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc791"/> for the definition of the IPv4 destination 
+          address field.  See <xref type="rfc" data="rfc3022"/> for the definition of 
+          NAT.  See <xref type="rfc" data="rfc3234"/> for the definition of middleboxes. 
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>postNAPTSourceTransportPort</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>227</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The definition of this Information Element is identical to the 
+          definition of Information Element 'sourceTransportPort', except 
+          that it reports a modified value caused by a Network Address 
+          Port Translation (NAPT) middlebox function after the packet 
+          passed the Observation Point.
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc768"/> for the definition of the UDP source port 
+          field.  See <xref type="rfc" data="rfc793"/> for the definition of the TCP 
+          source port field.  See <xref type="rfc" data="rfc4960"/> for the definition of 
+          SCTP.     
+          See <xref type="rfc" data="rfc3022"/> for the definition of NAPT.  See <xref type="rfc" data="rfc3234"/> for the definition of middleboxes. 
+          Additional information on defined UDP and TCP port numbers can 
+          be found at http://www.iana.org/assignments/port-numbers.   
+         </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>postNAPTDestinationTransportPort</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>228</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The definition of this Information Element is identical to the 
+          definition of Information Element 'destinationTransportPort', 
+          except that it reports a modified value caused by a Network 
+          Address Port Translation (NAPT) middlebox function after the 
+          packet passed the Observation Point. 
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          See <xref type="rfc" data="rfc768"/> for the definition of the UDP source port 
+          field.  See <xref type="rfc" data="rfc793"/> for the definition of the TCP 
+          source port field.  See <xref type="rfc" data="rfc4960"/> for the definition of 
+          SCTP.     
+          See <xref type="rfc" data="rfc3022"/> for the definition of NAPT.  See <xref type="rfc" data="rfc3234"/> for the definition of middleboxes. 
+          Additional information on defined UDP and TCP port numbers can 
+          be found at http://www.iana.org/assignments/port-numbers.   
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>natOriginatingAddressRealm</name>
+      <dataType>unsigned8</dataType>
+      <dataTypeSemantics>flags</dataTypeSemantics>
+      <elementId>229</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Indicates whether the session was created because traffic 
+          originated in the private or public address realm. 
+          postNATSourceIPv4Address, postNATDestinationIPv4Address, 
+          postNAPTSourceTransportPort, and 
+          postNAPTDestinationTransportPort are qualified with the address 
+          realm in perspective. 
+        </paragraph>
+       <paragraph>
+          The allowed values are: 
+          </paragraph>
+        <paragraph>
+          Private: 1 
+        </paragraph>
+        <paragraph>
+          Public:  2
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          See <xref type="rfc" data="rfc3022"/> for the definition of NAT.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>  
+    <record>
+      <name>natEvent</name>
+      <dataType>unsigned8</dataType>
+      <elementId>230</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Indicates a NAT event. The allowed values are: 
+        </paragraph>
+        <paragraph>
+          1 - Create event.
+        </paragraph>
+        <paragraph>
+          2 - Delete event.
+        </paragraph>
+        <paragraph>
+          3 - Pool exhausted. 
+        </paragraph>
+        <paragraph>
+          A Create event is generated when a NAT translation is created, 
+          whether dynamically or statically.  A Delete event is generated 
+          when a NAT translation is deleted. 
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          See <xref type="rfc" data="rfc3022"/> for the definition of NAT.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>  
+    <record>
+      <name>initiatorOctets</name>
+      <dataType>unsigned64</dataType>
+      <elementId>231</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The total number of layer 4 payload bytes in a flow from the 
+          initiator.  The initiator is the device which triggered the 
+          session creation, and remains the same for the life of the 
+          session.  
+        </paragraph>
+      </description>
+      <units>octets</units>
+      <references>
+        <paragraph>         
+          See #298, initiatorPackets.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>  
+    <record>
+      <name>responderOctets</name>
+      <dataType>unsigned64</dataType>
+      <elementId>232</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The total number of layer 4 payload bytes in a flow from the 
+          responder.  The responder is the device which replies to the 
+          initiator, and remains the same for the life of the session. 
+        </paragraph>
+      </description>
+      <units>octets</units>
+      <references>      
+        <paragraph>         
+          See #299, responderPackets.
+        </paragraph>
+      </references>
+
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>firewallEvent</name>
+      <dataType>unsigned8</dataType>
+      <elementId>233</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Indicates a firewall event.  The allowed values are: 
+        </paragraph>
+        <paragraph>
+          0 - Ignore (invalid) 
+          </paragraph>
+        <paragraph>
+          1 - Flow Created 
+        </paragraph>
+        <paragraph>
+          2 - Flow Deleted 
+        </paragraph>
+        <paragraph>
+          3 - Flow Denied
+        </paragraph>
+        <paragraph>
+          4 - Flow Alert 
+        </paragraph>
+        <paragraph>
+          5 - Flow Update 
+        </paragraph>
+      </description>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>ingressVRFID</name>
+      <dataType>unsigned32</dataType>
+      <elementId>234</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          An unique identifier of the VRFname where the packets of this 
+          flow are being received.  This identifier is unique per Metering 
+          Process 
+        </paragraph>
+      </description>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>egressVRFID</name>
+      <dataType>unsigned32</dataType>
+      <elementId>235</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          An unique identifier of the VRFname where the packets of this 
+          flow are being sent.  This identifier is unique per Metering 
+          Process 
+        </paragraph>
+      </description>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>VRFname</name>
+      <dataType>string</dataType>
+      <elementId>236</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The name of a VPN Routing and Forwarding table (VRF). 
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          See <xref type="rfc" data="rfc4364"/> for the definition of VRF.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>postMplsTopLabelExp</name>
+      <dataType>unsigned8</dataType>
+      <group>subIpHeader</group>
+      <dataTypeSemantics>flags</dataTypeSemantics>
+      <elementId>237</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The definition of this Information Element is identical to the
+         definition of Information Element 'mplsTopLabelExp', except
+         that it reports a potentially modified value caused by a
+         middlebox function after the packet passed the Observation
+         Point.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc3032"/> for the specification of the Exp
+          field.
+          See <xref type="rfc" data="rfc3270"/> for usage of the Exp field.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>tcpWindowScale</name>
+      <dataType>unsigned16</dataType>
+      <group>transportHeader</group>
+      <elementId>238</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>
+         The scale of the window field in the TCP header.
+         </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See <xref type="rfc" data="rfc1323"/> for the definition of the TCP
+          window scale.
+        </paragraph>
+      </references>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <name>biflowDirection</name>
+      <dataType>unsigned8</dataType>
+      <group>misc</group>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>239</elementId>
+      <applicability>all</applicability>
+      <status>current</status>
+      <description>
+        <paragraph>A description of the direction assignment method used to
+          assign the Biflow Source and Destination.  This Information Element
+          MAY be present in a Flow Data Record, or applied to all flows exported
+          from an Exporting Process or Observation Domain using IPFIX Options.
+          If this Information Element is not present in a Flow Record or
+          associated with a Biflow via scope, it is assumed that the
+          configuration of the direction assignment method is done out-of-band.
+          Note that when using IPFIX Options to apply this Information Element
+          to all flows within an Observation Domain or from an Exporting
+          Process, the Option SHOULD be sent reliably.  If reliable transport is
+          not available (i.e., when using UDP), this Information Element SHOULD
+          appear in each Flow Record.  This field may take the following
+          values:</paragraph>
+        <artwork>
+ +-------+------------------+----------------------------------------+
+ | Value | Name             | Description                            |
+ +-------+------------------+----------------------------------------+
+ | 0x00  | arbitrary        | Direction was assigned arbitrarily.    |
+ | 0x01  | initiator        | The Biflow Source is the flow          |
+ |       |                  | initiator, as determined by the        |
+ |       |                  | Metering Process' best effort to       |
+ |       |                  | detect the initiator.                  |
+ | 0x02  | reverseInitiator | The Biflow Destination is the flow     |
+ |       |                  | initiator, as determined by the        |
+ |       |                  | Metering Process' best effort to       |
+ |       |                  | detect the initiator.  This value is   |
+ |       |                  | provided for the convenience of        |
+ |       |                  | Exporting Processes to revise an       |
+ |       |                  | initiator estimate without re-encoding |
+ |       |                  | the Biflow Record.                     |
+ | 0x03  | perimeter        | The Biflow Source is the endpoint      |
+ |       |                  | outside of a defined perimeter.  The   |
+ |       |                  | perimeter's definition is implicit in  |
+ |       |                  | the set of Biflow Source and Biflow    |
+ |       |                  | Destination addresses exported in the  |
+ |       |                  | Biflow Records.                        |
+ +-------+------------------+----------------------------------------+
+        </artwork>
+      </description>
+      <xref type="rfc" data="rfc5103"/>
+    </record>
+
+    <record>
+      <name>ethernetHeaderLength</name>
+      <dataType>unsigned8</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>240</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The difference between the length of an Ethernet frame (minus the 
+          FCS) and the length of its MAC Client Data section (including any 
+          padding) as defined in section 3.1 of [IEEE.802-3.2005].  It does 
+          not include the Preamble, SFD and Extension field lengths.  
+        </paragraph>
+      </description>
+      <units>octets</units>
+      <references>
+        <paragraph>         
+          [IEEE.802-3.2005] 
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>ethernetPayloadLength</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>241</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The length of the MAC Client Data section (including any padding) 
+          of a frame as defined in section 3.1 of [IEEE.802-3.2005].  
+        </paragraph>
+      </description>
+      <units>octets</units>
+      <references>
+        <paragraph>         
+          [IEEE.802-3.2005] 
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>   
+    <record>
+      <name>ethernetTotalLength</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>242</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The total length of the Ethernet frame (excluding the Preamble, 
+          SFD, Extension and FCS fields) as described in section 3.1 of 
+          [IEEE.802-3.2005]. 
+        </paragraph>
+      </description>
+      <units>octets</units>
+      <references>
+        <paragraph>         
+          [IEEE.802-3.2005] 
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record> 
+    <record>
+      <name>dot1qVlanId</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>243</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The value of the 12-bit VLAN Identifier portion of the Tag 
+          Control Information field of an Ethernet frame as described in 
+          section 3.5.5 of [IEEE.802-3.2005].  The structure and semantics 
+          within the Tag Control Information field are defined in IEEE 
+          P802.1Q.  In case of a QinQ frame, it represents the outer tag's 
+          VLAN identifier and in case of an IEEE 802.1ad frame it 
+          represents the Service VLAN identifier in the S-TAG Tag Control 
+          Information (TCI) field as described in [IEEE.802-1ad.2005]. 
+        </paragraph>
+      </description>
+      <units>octets</units>
+      <references>
+        <paragraph>         
+          [IEEE.802-3.2005] 
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record> 
+    <record>
+      <name>dot1qPriority</name>
+      <dataType>unsigned8</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>244</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The value of the 3-bit User Priority portion of the Tag Control 
+          Information field of an Ethernet frame as described in section 
+          3.5.5 of [IEEE.802-3.2005].  The structure and semantics within 
+          the Tag Control Information field are defined in IEEE P802.1Q.  
+          In case of a QinQ frame, it represents the outer tag's 3-bit 
+          Class of Service (CoS) identifier and in case of an IEEE 802.1ad 
+          frame it represents the 3-bit Priority Code Point (PCP) portion 
+          of the S-TAG Tag Control Information (TCI) field as described in 
+          [IEEE.802-1ad.2005].
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          [IEEE.802-3.2005] 
+          [IEEE.802-1ad.2005] 
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record> 
+    <record>
+      <name>dot1qCustomerVlanId</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>245</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          In case of a QinQ frame, it represents the inner tag's (*) VLAN 
+          identifier and in case of an IEEE 802.1ad frame it represents the 
+          Customer VLAN identifier in the C-TAG Tag Control Information 
+          (TCI) field as described in [IEEE.802-1ad.2005]. 
+          (*) Note: the 801.2Q tag directly following the outer one. 
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          [IEEE.802-1ad.2005] 
+          [IEEE.802-1Q.2003]
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record> 
+    <record>
+      <name>dot1qCustomerPriority</name>
+      <dataType>unsigned8</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>246</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          In case of a QinQ frame, it represents the inner tag's (*) Class 
+          of Service (CoS) identifier and in case of an IEEE 802.1ad frame 
+          it represents the 3-bit Priority Code Point (PCP) portion of the 
+          C-TAG Tag Control Information (TCI) field as described in 
+          [IEEE.802-1ad.2005]. 
+          (*) Note: the 801.2Q tag directly following the outer one. 
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          [IEEE.802-1ad.2005] 
+          [IEEE.802-1Q.2003]
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record> 
+    <record>
+      <name>metroEvcId</name>
+      <dataType>string</dataType>
+      <elementId>247</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The EVC Service Attribute which uniquely identifies the Ethernet 
+          Virtual Connection (EVC) within a Metro Ethernet Network, as 
+          defined in section 6.2 of MEF 10.1.  The MetroEVCID is encoded in 
+          a string of up to 100 characters.  
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          MEF 10.1 (Ethernet Services Attributes Phase 2) 
+          MEF16 (Ethernet Local Management Interface) 
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record> 
+    <record>
+      <name>metroEvcType</name>
+      <dataType>unsigned8</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>248</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The 3-bit EVC Service Attribute which identifies the type of 
+          service provided by an EVC. 
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          MEF 10.1 (Ethernet Services Attributes Phase 2)  
+          MEF16 (Ethernet Local Management Interface) 
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record> 
+    <record>
+      <name>pseudoWireId</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>249</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          A 32-bit non-zero connection identifier, which together with the 
+          pseudoWireType, identifies the Pseudo Wire (PW) as defined in RFC 
+          4447 [RFC4447]. 
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          See <xref type="rfc" data="rfc4447"/> for pseudowire definitions.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record> 
+    <record>
+      <name>pseudoWireType</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>250</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The value of this information element identifies the type of MPLS 
+          Pseudo Wire (PW) as defined in RFC 4446.
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          See <xref type="rfc" data="rfc4446"/> for the pseudowire type definition, and 
+          http://www.iana.org/assignments/pwe3-parameters for the IANA 
+          Pseudowire Types Registry.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record> 
+    <record>
+      <name>pseudoWireControlWord</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>251</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The 32-bit Preferred Pseudo Wire (PW) MPLS Control Word as 
+          defined in Section 3 of <xref type="rfc" data="rfc4385"/>. 
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          See <xref type="rfc" data="rfc4385"/> for the Pseudo Wire Control Word 
+          definition.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>ingressPhysicalInterface</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>252</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The index of a networking device's physical interface (example, a 
+          switch port) where packets of this flow are being received. 
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          See <xref type="rfc" data="rfc2863"/> for the definition of the ifIndex object.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>egressPhysicalInterface</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>253</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The index of a networking device's physical interface (example, a 
+          switch port) where packets of this flow are being sent. 
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          See <xref type="rfc" data="rfc2863"/> for the definition of the ifIndex object.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>postDot1qVlanId</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>254</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The definition of this Information Element is identical to the 
+          definition of Information Element 'dot1qVlanId', except that it 
+          reports a potentially modified value caused by a middlebox 
+          function after the packet passed the Observation Point.  
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          [IEEE.802-3.2005] 
+          [IEEE.802-1ad.2005] 
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>postDot1qCustomerVlanId</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>255</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The definition of this Information Element is identical to the 
+          definition of Information Element 'dot1qCustomerVlanId', except 
+          that it reports a potentially modified value caused by a 
+          middlebox function after the packet passed the Observation Point. 
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          [IEEE.802-1ad.2005] 
+          [IEEE.802-1Q.2003]
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record> 
+    <record>
+      <name>ethernetType</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>256</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The Ethernet type field of an Ethernet frame that identifies the 
+          MAC client protocol carried in the payload as defined in 
+          paragraph 1.4.349 of [IEEE.802-3.2005]. 
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          [IEEE.802-3.2005] 
+          Ethertype registry available at 
+          http://standards.ieee.org/regauth/ethertype/eth.txt 
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>postIpPrecedence</name>
+      <dataType>unsigned8</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>257</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The definition of this Information Element is identical to the         
+          definition of Information Element 'ipPrecedence', except that 
+          it reports a potentially modified value caused by a middlebox
+          function after the packet passed the Observation Point.
+        </paragraph>
+      </description>
+      <range>0-7</range>
+      <references>
+        <paragraph>         
+          See <xref type="rfc" data="rfc1812"/> (Section 5.3.3) and 
+          <xref type="rfc" data="rfc791"/> for the definition of the
+          IP Precedence. See <xref type="rfc" data="rfc1812"/> 
+          (Section 5.3.2) and <xref type="rfc" data="rfc791"/> for the
+          definition of the IPv4 TOS field. See 
+          <xref type="rfc" data="rfc2460"/> for the definition of the 
+          IPv6 Traffic Class field. 
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>collectionTimeMilliseconds</name>
+      <dataType>dateTimeMilliseconds</dataType>
+      <elementId>258</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The absolute timestamp at which the data within the
+          scope containing this Information Element was received by a
+          Collecting Process.  This Information Element SHOULD be bound to
+          its containing IPFIX Message via IPFIX Options and the
+          messageScope Information Element, as defined below.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5655"/>
+    </record>
+
+    <record>
+      <name>exportSctpStreamId</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>259</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The value of the SCTP Stream Identifier used by the
+          Exporting Process for exporting IPFIX Message data.  This is
+          carried in the Stream Identifier field of the header of the SCTP
+          DATA chunk containing the IPFIX Message(s).
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5655"/>
+    </record>
+
+    <record>
+      <name>maxExportSeconds</name>
+      <dataType>dateTimeSeconds</dataType>
+      <elementId>260</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The absolute Export Time of the latest IPFIX Message
+          within the scope containing this Information Element.  This
+          Information Element SHOULD be bound to its containing IPFIX
+          Transport Session via IPFIX Options and the sessionScope
+          Information Element.
+        </paragraph>
+      </description>
+      <units>seconds</units>
+      <xref type="rfc" data="rfc5655"/>
+    </record>
+
+    <record>
+      <name>maxFlowEndSeconds</name>
+      <dataType>dateTimeSeconds</dataType>
+      <elementId>261</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The latest absolute timestamp of the last packet
+          within any Flow within the scope containing this Information
+          Element, rounded up to the second if necessary.  This Information
+          Element SHOULD be bound to its containing IPFIX Transport Session
+          via IPFIX Options and the sessionScope Information Element.
+        </paragraph>
+      </description>
+      <units>seconds</units>
+      <xref type="rfc" data="rfc5655"/>
+    </record>
+
+    <record>
+      <name>messageMD5Checksum</name>
+      <dataType>octetArray</dataType>
+      <elementId>262</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The MD5 checksum of the IPFIX Message containing this
+          record.  This Information Element SHOULD be bound to its
+          containing IPFIX Message via an options record and the
+          messageScope Information Element, as defined below, and SHOULD
+          appear only once in a given IPFIX Message.  To calculate the value
+          of this Information Element, first buffer the containing IPFIX
+          Message, setting the value of this Information Element to all
+          zeroes.  Then calculate the MD5 checksum of the resulting buffer
+          as defined in [RFC1321], place the resulting value in this
+          Information Element, and export the buffered message.  This
+          Information Element is intended as a simple checksum only;
+          therefore collision resistance and algorithm agility are not
+          required, and MD5 is an appropriate message digest.
+          
+          This Information Element has a fixed length of 16 octets.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5655"/>
+      <xref type="rfc" data="rfc1321"/>
+    </record>
+
+    <record>
+      <name>messageScope</name>
+      <dataType>unsigned8</dataType>
+      <elementId>263</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The presence of this Information Element as scope in
+          an Options Template signifies that the options described by the
+          Template apply to the IPFIX Message that contains them.  It is
+          defined for general purpose message scoping of options, and
+          proposed specifically to allow the attachment a checksum to a
+          message via IPFIX Options.  The value of this Information Element
+          MUST be written as 0 by the File Writer or Exporting Process.  The
+          value of this Information Element MUST be ignored by the File
+          Reader or the Collecting Process.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5655"/>
+    </record>
+
+    <record>
+      <name>minExportSeconds</name>
+      <dataType>dateTimeSeconds</dataType>
+      <elementId>264</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The absolute Export Time of the earliest IPFIX Message
+          within the scope containing this Information Element.  This
+          Information Element SHOULD be bound to its containing IPFIX
+          Transport Session via an options record and the sessionScope
+          Information Element.
+        </paragraph>
+      </description>
+      <units>seconds</units>
+      <xref type="rfc" data="rfc5655"/>
+    </record>
+
+    <record>
+      <name>minFlowStartSeconds</name>
+      <dataType>dateTimeSeconds</dataType>
+      <elementId>265</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The earliest absolute timestamp of the first packet
+          within any Flow within the scope containing this Information
+          Element, rounded down to the second if necessary.  This
+          Information Element SHOULD be bound to its containing IPFIX
+          Transport Session via an options record and the sessionScope
+          Information Element.
+        </paragraph>
+      </description>
+      <units>seconds</units>
+      <xref type="rfc" data="rfc5655"/>
+    </record>
+
+    <record>
+      <name>opaqueOctets</name>
+      <dataType>octetArray</dataType>
+      <elementId>266</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element is used to encapsulate non-
+          IPFIX data into an IPFIX Message stream, for the purpose of
+          allowing a non-IPFIX data processor to store a data stream inline
+          within an IPFIX File.  A Collecting Process or File Writer MUST
+          NOT try to interpret this binary data.  This Information Element
+          differs from paddingOctets as its contents are meaningful in some
+          non-IPFIX context, while the contents of paddingOctets MUST be
+          0x00 and are intended only for Information Element alignment.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5655"/>
+    </record>
+
+    <record>
+      <name>sessionScope</name>
+      <dataType>unsigned8</dataType>
+      <elementId>267</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The presence of this Information Element as scope in
+          an Options Template signifies that the options described by the
+          Template apply to the IPFIX Transport Session that contains them.
+          Note that as all options are implicitly scoped to Transport
+          Session and Observation Domain, this Information Element is
+          equivalent to a "null" scope.  It is defined for general purpose
+          session scoping of options, and proposed specifically to allow the
+          attachment of time window to an IPFIX File via IPFIX Options.  The
+          value of this Information Element MUST be written as 0 by the File
+          Writer or Exporting Process.  The value of this Information
+          Element MUST be ignored by the File Reader or the Collecting
+          Process.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5655"/>
+    </record>
+
+    <record>
+      <name>maxFlowEndMicroseconds</name>
+      <dataType>dateTimeMicroseconds</dataType>
+      <elementId>268</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The latest absolute timestamp of the last packet
+          within any Flow within the scope containing this Information
+          Element, rounded up to the microsecond if necessary.  This
+          Information Element SHOULD be bound to its containing IPFIX
+          Transport Session via IPFIX Options and the sessionScope
+          Information Element.  This Information Element SHOULD be used only
+          in Transport Sessions containing Flow Records with microsecond-
+          precision (or better) timestamp Information Elements.
+        </paragraph>
+      </description>
+      <units>microseconds</units>
+      <xref type="rfc" data="rfc5655"/>
+    </record>
+
+    <record>
+      <name>maxFlowEndMilliseconds</name>
+      <dataType>dateTimeMilliseconds</dataType>
+      <elementId>269</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The latest absolute timestamp of the last packet
+          within any Flow within the scope containing this Information
+          Element, rounded up to the millisecond if necessary.  This
+          Information Element SHOULD be bound to its containing IPFIX
+          Transport Session via IPFIX Options and the sessionScope
+          Information Element.  This Information Element SHOULD be used only
+          in Transport Sessions containing Flow Records with millisecond-
+          precision (or better) timestamp Information Elements.
+        </paragraph>
+      </description>
+      <units>milliseconds</units>
+      <xref type="rfc" data="rfc5655"/>
+    </record>
+
+    <record>
+      <name>maxFlowEndNanoseconds</name>
+      <dataType>dateTimeNanoseconds</dataType>
+      <elementId>270</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The latest absolute timestamp of the last packet
+          within any Flow within the scope containing this Information
+          Element.  This Information Element SHOULD be bound to its
+          containing IPFIX Transport Session via IPFIX Options and the
+          sessionScope Information Element.  This Information Element SHOULD
+          be used only in Transport Sessions containing Flow Records with
+          nanosecond-precision timestamp Information Elements.
+        </paragraph>
+      </description>
+      <units>nanoseconds</units>
+      <xref type="rfc" data="rfc5655"/>
+    </record>
+
+    <record>
+      <name>minFlowStartMicroseconds</name>
+      <dataType>dateTimeMicroseconds</dataType>
+      <elementId>271</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The earliest absolute timestamp of the first packet
+          within any Flow within the scope containing this Information
+          Element, rounded down to the microsecond if necessary.  This
+          Information Element SHOULD be bound to its containing IPFIX
+          Transport Session via an options record and the sessionScope
+          Information Element.  This Information Element SHOULD be used only
+          in Transport Sessions containing Flow Records with microsecond-
+          precision (or better) timestamp Information Elements.
+        </paragraph>
+      </description>
+      <units>microseconds</units>
+      <xref type="rfc" data="rfc5655"/>
+    </record>
+
+    <record>
+      <name>minFlowStartMilliseconds</name>
+      <dataType>dateTimeMilliseconds</dataType>
+      <elementId>272</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The earliest absolute timestamp of the first packet
+          within any Flow within the scope containing this Information
+          Element, rounded down to the millisecond if necessary.  This
+          Information Element SHOULD be bound to its containing IPFIX
+          Transport Session via an options record and the sessionScope
+          Information Element.  This Information Element SHOULD be used only
+          in Transport Sessions containing Flow Records with millisecond-
+          precision (or better) timestamp Information Elements.
+        </paragraph>
+      </description>
+      <units>milliseconds</units>
+      <xref type="rfc" data="rfc5655"/>
+    </record>
+
+    <record>
+      <name>minFlowStartNanoseconds</name>
+      <dataType>dateTimeNanoseconds</dataType>
+      <elementId>273</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The earliest absolute timestamp of the first packet
+          within any Flow within the scope containing this Information
+          Element.  This Information Element SHOULD be bound to its
+          containing IPFIX Transport Session via an options record and the
+          sessionScope Information Element.  This Information Element SHOULD
+          be used only in Transport Sessions containing Flow Records with
+          nanosecond-precision timestamp Information Elements.
+        </paragraph>
+      </description>
+      <units>nanoseconds</units>
+      <xref type="rfc" data="rfc5655"/>
+    </record>
+
+    <record>
+      <name>collectorCertificate</name>
+      <dataType>octetArray</dataType>
+      <elementId>274</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The full X.509 certificate, encoded in ASN.1 DER
+          format, used by the Collector when IPFIX Messages were transmitted
+          using TLS or DTLS.  This Information Element SHOULD be bound to
+          its containing IPFIX Transport Session via an options record and
+          the sessionScope Information Element, or to its containing IPFIX
+          Message via an options record and the messageScope Information
+          Element.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5655"/>
+    </record>
+
+    <record>
+      <name>exporterCertificate</name>
+      <dataType>octetArray</dataType>
+      <elementId>275</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The full X.509 certificate, encoded in ASN.1 DER
+          format, used by the Collector when IPFIX Messages were transmitted
+          using TLS or DTLS.  This Information Element SHOULD be bound to
+          its containing IPFIX Transport Session via an options record and
+          the sessionScope Information Element, or to its containing IPFIX
+          Message via an options record and the messageScope Information
+          Element.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5655"/>
+    </record>
+
+    <record>
+      <name>dataRecordsReliability</name>
+      <dataType>boolean</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>276</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The export reliability of Data Records, within this SCTP 
+          stream, for the element(s) in the Options Template 
+          scope.  A typical example of an element for which the 
+          export reliability will be reported is the templateID, 
+          as specified in the Data Records Reliability Options 
+          Template.  A value of 'True' means that the Exporting 
+          Process MUST send any Data Records associated with the 
+          element(s) reliably within this SCTP stream.  A value of 
+          'False' means that the Exporting Process MAY send any 
+          Data Records associated with the element(s) unreliably 
+          within this SCTP stream.     
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc6526"/>
+    </record>
+    <record date="2010-09-16">
+      <name>observationPointType</name>
+      <dataType>unsigned8</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>277</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Type of observation point. Values assigned to date are:
+        </paragraph>
+          <paragraph>
+          1. Physical port
+          </paragraph>
+            <paragraph>
+          2. Port channel
+            </paragraph>
+              <paragraph>
+          3. Vlan.
+        </paragraph>
+      </description>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+    <record date="2010-10-19">
+      <name>connectionCountNew</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>deltaCounter</dataTypeSemantics>
+      <elementId>278</elementId>
+       <status>current</status>
+       <description>
+         <paragraph>This information element counts the number of TCP or UDP
+         connections which were opened during the observation period. The
+         observation period may be specified by the flow start and end timestamps.
+         </paragraph>
+       </description>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record date="2010-10-19">
+      <name>connectionSumDuration</name>
+      <dataType>unsigned64</dataType>
+      <elementId>279</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>This information element aggregates the total time in
+          seconds for all of the TCP or UDP connections which were in use during
+          the observation period. For example if there are 5 concurrent
+          connections each for 10 seconds, the value would be 50 s.
+        </paragraph>
+      </description>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record date="2010-10-19">
+      <name>connectionTransactionId</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>280</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>This information element identifies a transaction within a
+          connection. A transaction is a meaningful exchange of application data
+          between two network devices or a client and server. A transactionId is
+          assigned the first time a flow is reported, so that later reports for
+          the same flow will have the same transactionId. A different
+          transactionId is used for each transaction within a TCP or UDP
+          connection. The identifiers need not be sequential.
+        </paragraph>
+      </description>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record date="2010-10-19">
+      <name>postNATSourceIPv6Address</name>
+      <dataType>ipv6Address</dataType>
+      <elementId>281</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>The definition of this Information Element is identical to
+          the definition of Information Element 'sourceIPv6Address', except that
+          it reports a modified value caused by a NAT64 middlebox function after
+          the packet passed the Observation Point.
+          
+          See [RFC2460] for the definition of the Source Address field in the IPv6
+          header. See [RFC3234] for the definition of middleboxes. See
+          http://tools.ietf.org/html/draft-ietf-behave-v6v4-xlate-stateful-12 for
+          nat64 specification.
+        </paragraph>
+      </description>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record date="2010-10-19">
+      <name>postNATDestinationIPv6Address</name>
+      <dataType>ipv6Address</dataType>
+      <elementId>282</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>The definition of this Information Element is identical to
+          the definition of Information Element 'destinationIPv6Address', except
+          that it reports a modified value caused by a NAT64 middlebox function
+          after the packet passed the Observation Point.
+          
+          See [RFC2460] for the definition of the Destination Address field in the
+          IPv6 header. See [RFC3234] for the definition of middleboxes. See
+          http://tools.ietf.org/html/draft-ietf-behave-v6v4-xlate-stateful-12 for
+          nat64 specification.
+        </paragraph>
+      </description>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+    
+    <record date="2011-02-10">
+      <name>natPoolId</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>283</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>Locally unique identifier of a NAT pool.
+        </paragraph>
+      </description>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+    
+    <record date="2011-02-10">
+      <name>natPoolName</name>
+      <dataType>string</dataType>
+      <elementId>284</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>The name of a NAT pool identified by a natPoolID.
+        </paragraph>
+      </description>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>anonymizationFlags</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>flags</dataTypeSemantics>
+      <elementId>285</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>A flag word describing specialized modifications to
+          the anonymization policy in effect for the anonymization technique
+          applied to a referenced Information Element within a referenced
+          Template.  When flags are clear (0), the normal policy (as
+          described by anonymizationTechnique) applies without modification.
+        </paragraph>
+        <artwork>
+          MSB   14  13  12  11  10   9   8   7   6   5   4   3   2   1  LSB
+          +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+          |                Reserved                       |LOR|PmA|   SC  |
+          +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+          
+          anonymizationFlags IE
+          
+          +--------+----------+-----------------------------------------------+
+          | bit(s) | name     | description                                   |
+          | (LSB = |          |                                               |
+          | 0)     |          |                                               |
+          +--------+----------+-----------------------------------------------+
+          | 0-1    | SC       | Stability Class: see the Stability Class      |
+          |        |          | table below, and section Section 5.1.         | 
+          | 2      | PmA      | Perimeter Anonymization: when set (1),        |
+          |        |          | source- Information Elements as described in  |
+          |        |          | [RFC5103] are interpreted as external         |
+          |        |          | addresses, and destination- Information       |
+          |        |          | Elements as described in [RFC5103] are        |
+          |        |          | interpreted as internal addresses, for the    |
+          |        |          | purposes of associating                       |
+          |        |          | anonymizationTechnique to Information         |
+          |        |          | Elements only; see Section 7.2.2 for details. |
+          |        |          | This bit MUST NOT be set when associated with |
+          |        |          | a non-endpoint (i.e., source- or              |
+          |        |          | destination-) Information Element.  SHOULD be |
+          |        |          | consistent within a record (i.e., if a        |
+          |        |          | source- Information Element has this flag     |
+          |        |          | set, the corresponding destination- element   |
+          |        |          | SHOULD have this flag set, and vice-versa.)   |
+          | 3      | LOR      | Low-Order Unchanged: when set (1), the        |
+          |        |          | low-order bits of the anonymized Information  |
+          |        |          | Element contain real data.  This modification |
+          |        |          | is intended for the anonymization of          |
+          |        |          | network-level addresses while leaving         |
+          |        |          | host-level addresses intact in order to       |
+          |        |          | preserve host level-structure, which could    |
+          |        |          | otherwise be used to reverse anonymization.   |
+          |        |          | MUST NOT be set when associated with a        |
+          |        |          | truncation-based anonymizationTechnique.      |
+          | 4-15   | Reserved | Reserved for future use: SHOULD be cleared    |
+          |        |          | (0) by the Exporting Process and MUST be      |
+          |        |          | ignored by the Collecting Process.            |
+          +--------+----------+-----------------------------------------------+
+        </artwork>
+        <paragraph>
+          The Stability Class portion of this flags word describes the
+          stability class of the anonymization technique applied to a
+          referenced Information Element within a referenced Template.
+          Stability classes refer to the stability of the parameters of the
+          anonymization technique, and therefore the comparability of the
+          mapping between the real and anonymized values over time.  This
+          determines which anonymized datasets may be compared with each
+          other.  Values are as follows:
+          </paragraph>
+          <artwork>
+            +-----+-----+-------------------------------------------------------+
+            | Bit | Bit | Description                                           |
+            | 1   | 0   |                                                       |
+            +-----+-----+-------------------------------------------------------+
+            | 0   | 0   | Undefined: the Exporting Process makes no             |
+            |     |     | representation as to how stable the mapping is, or    |
+            |     |     | over what time period values of this field will       |
+            |     |     | remain comparable; while the Collecting Process MAY   |
+            |     |     | assume Session level stability, Session level         |
+            |     |     | stability is not guaranteed.  Processes SHOULD assume |
+            |     |     | this is the case in the absence of stability class    |
+            |     |     | information; this is the default stability class.     |
+            | 0   | 1   | Session: the Exporting Process will ensure that the   |
+            |     |     | parameters of the anonymization technique are stable  |
+            |     |     | during the Transport Session.  All the values of the  |
+            |     |     | described Information Element for each Record         |
+            |     |     | described by the referenced Template within the       |
+            |     |     | Transport Session are comparable.  The Exporting      |
+            |     |     | Process SHOULD endeavour to ensure at least this      |
+            |     |     | stability class.                                      |
+            | 1   | 0   | Exporter-Collector Pair: the Exporting Process will   |
+            |     |     | ensure that the parameters of the anonymization       |
+            |     |     | technique are stable across Transport Sessions over   |
+            |     |     | time with the given Collecting Process, but may use   |
+            |     |     | different parameters for different Collecting         |
+            |     |     | Processes.  Data exported to different Collecting     |
+            |     |     | Processes are not comparable.                         |
+            | 1   | 1   | Stable: the Exporting Process will ensure that the    |
+            |     |     | parameters of the anonymization technique are stable  |
+            |     |     | across Transport Sessions over time, regardless of    |
+            |     |     | the Collecting Process to which it is sent.           |
+            +-----+-----+-------------------------------------------------------+
+          </artwork>
+      </description>
+      <xref type="rfc" data="rfc6235"/>
+    </record>
+
+    <record>
+      <name>anonymizationTechnique</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>286</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          A description of the anonymization technique applied
+          to a referenced Information Element within a referenced Template.
+          Each technique may be applicable only to certain Information
+          Elements and recommended only for certain Infomation Elements;
+          these restrictions are noted in the table below.
+        </paragraph>
+        <artwork>
+          +-------+---------------------------+-----------------+-------------+
+          | Value | Description               | Applicable to   | Recommended |
+          |       |                           |                 | for         |
+          +-------+---------------------------+-----------------+-------------+
+          | 0     | Undefined: the Exporting  | all             | all         |
+          |       | Process makes no          |                 |             |
+          |       | representation as to      |                 |             |
+          |       | whether the defined field |                 |             |
+          |       | is anonymized or not.     |                 |             |
+          |       | While the Collecting      |                 |             |
+          |       | Process MAY assume that   |                 |             |
+          |       | the field is not          |                 |             |
+          |       | anonymized, it is not     |                 |             |
+          |       | guaranteed not to be.     |                 |             |
+          |       | This is the default       |                 |             |
+          |       | anonymization technique.  |                 |             |
+          | 1     | None: the values exported | all             | all         |
+          |       | are real.                 |                 |             |
+          | 2     | Precision                 | all             | all         |
+          |       | Degradation/Truncation:   |                 |             |
+          |       | the values exported are   |                 |             |
+          |       | anonymized using simple   |                 |             |
+          |       | precision degradation or  |                 |             |
+          |       | truncation.  The new      |                 |             |
+          |       | precision or number of    |                 |             |
+          |       | truncated bits is         |                 |             |
+          |       | implicit in the exported  |                 |             |
+          |       | data, and can be deduced  |                 |             |
+          |       | by the Collecting         |                 |             |
+          |       | Process.                  |                 |             |
+          | 3     | Binning: the values       | all             | all         |
+          |       | exported are anonymized   |                 |             |
+          |       | into bins.                |                 |             |
+          | 4     | Enumeration: the values   | all             | timestamps  |
+          |       | exported are anonymized   |                 |             |
+          |       | by enumeration.           |                 |             |
+          | 5     | Permutation: the values   | all             | identifiers |
+          |       | exported are anonymized   |                 |             |
+          |       | by permutation.           |                 |             |
+          | 6     | Structured Permutation:   | addresses       |             |
+          |       | the values exported are   |                 |             |
+          |       | anonymized by             |                 |             |
+          |       | permutation, preserving   |                 |             |
+          |       | bit-level structure as    |                 |             |
+          |       | appropriate; this         |                 |             |
+          |       | represents                |                 |             |
+          |       | prefix-preserving IP      |                 |             |
+          |       | address anonymization or  |                 |             |
+          |       | structured MAC address    |                 |             |
+          |       | anonymization.            |                 |             |
+          | 7     | Reverse Truncation: the   | addresses       |             |
+          |       | values exported are       |                 |             |
+          |       | anonymized using reverse  |                 |             |
+          |       | truncation.  The number   |                 |             |
+          |       | of truncated bits is      |                 |             |
+          |       | implicit in the exported  |                 |             |
+          |       | data, and can be deduced  |                 |             |
+          |       | by the Collecting         |                 |             |
+          |       | Process.                  |                 |             |
+          | 8     | Noise: the values         | non-identifiers | counters    |
+          |       | exported are anonymized   |                 |             |
+          |       | by adding random noise to |                 |             |
+          |       | each value.               |                 |             |
+          | 9     | Offset: the values        | all             | timestamps  |
+          |       | exported are anonymized   |                 |             |
+          |       | by adding a single offset |                 |             |
+          |       | to all values.            |                 |             |
+          +-------+---------------------------+-----------------+-------------+ 
+        </artwork>
+      </description>
+      <xref type="rfc" data="rfc6235"/>
+    </record>
+
+    <record>
+      <name>informationElementIndex</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>287</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>A zero-based index of an Information Element
+          referenced by informationElementId within a Template referenced by
+          templateId; used to disambiguate scope for templates containing
+          multiple identical Information Elements.</paragraph>
+      </description>
+      <xref type="rfc" data="rfc6235"/>
+    </record>
+
+    <record>
+      <name>p2pTechnology
+      </name>
+      <dataType>string</dataType>
+      <elementId>288</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>Specifies if the Application ID is based on peer-to-peer
+          technology. 
+        </paragraph>
+        <paragraph>
+          Possible values are: { "yes", "y", 1 }, 
+          { "no", "n", 2 } and { "unassigned", "u", 0 }.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc6759"/>
+    </record>
+
+    <record>
+      <name>tunnelTechnology
+      </name>
+      <dataType>string</dataType>
+      <elementId>289</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>Specifies if the Application ID is used as a tunnel technology.
+        </paragraph>
+        <paragraph>
+          Possible values are: { "yes", "y", 1 }, { "no", "n", 2 } and 
+          { "unassigned", "u", 0 }.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc6759"/>
+    </record>
+
+    <record>
+      <name>encryptedTechnology
+      </name>
+      <dataType>string</dataType>
+      <elementId>290</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>Specifies if the Application ID is an encrypted networking
+          protocol. 
+        </paragraph>
+        <paragraph>Possible values are: { "yes", "y", 1 }, 
+          { "no", "n", 2 } and { "unassigned", "u", 0 }.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc6759"/>
+    </record>
+
+    <record>
+    <name>basicList</name>
+    <dataType>basicList</dataType>
+    <dataTypeSemantics>list</dataTypeSemantics>
+    <elementId>291</elementId>
+    <status>current</status>
+    <description>
+      <paragraph>
+        Specifies a generic Information Element with a basicList abstract
+        data type.  For example, a list of port numbers, a list of
+        interface indexes, etc.
+      </paragraph>
+    </description>
+    <xref type="rfc" data="rfc6313"/>
+    </record>
+
+    <record>
+      <name>subTemplateList</name>
+      <dataType>subTemplateList</dataType>
+      <dataTypeSemantics>list</dataTypeSemantics>
+      <elementId>292</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Specifies a generic Information Element with a subTemplateList
+          abstract data type.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc6313"/>
+    </record>
+
+    <record>
+      <name>subTemplateMultiList</name>
+      <dataType>subTemplateMultiList</dataType>
+      <dataTypeSemantics>list</dataTypeSemantics>
+      <elementId>293</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Specifies a generic Information Element with a
+          subTemplateMultiList abstract data type.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc6313"/>
+    </record>
+
+    <record>
+      <name>bgpValidityState</name>
+      <dataType>unsigned8</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>294</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This element describes the "validity state" of the BGP route correspondent source or destination IP address. If the "validity state" for this Flow is only available, then the value of this Information Element is 255.
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          See <xref type="rfc" data="rfc4271"/> for a description of BGP-4, 
+          <xref type="draft" data="draft-ietf-sidr-pfx-validate"/> for the
+          definition of "validity states" and 
+          <xref type="draft" data="draft-ietf-sidr-origin-validation-signaling"/> 
+          for the encoding of those "validity states". 
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>IPSecSPI</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>295</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          IPSec Security Parameters Index (SPI).
+        </paragraph>
+      </description>
+      <range>0x0-0xFFFFFFFF</range>
+      <references>
+        <paragraph>         
+          See <xref type="rfc" data="rfc2401"/> for the definition of SPI.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>greKey</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>296</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          GRE key, which is used for identifying an individual traffic flow within a tunnel.
+        </paragraph>
+      </description>
+      <range>0x0-0xFFFFFFFF</range>
+      <references>
+        <paragraph>         
+          See <xref type="rfc" data="rfc1701"/> for the definition of GRE and the GRE Key.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>natType</name>
+      <dataType>unsigned8</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>297</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The type of NAT treatment:
+        </paragraph>
+        <paragraph>
+          0 unknown
+        </paragraph>
+        <paragraph>
+          1 NAT44 translated
+        </paragraph>
+        <paragraph>
+          2 NAT64 translated
+        </paragraph>
+        <paragraph>
+          3 NAT46 translated
+        </paragraph>
+        <paragraph>
+          4 IPv4--&gt;IPv4 (no NAT)
+        </paragraph>
+        <paragraph>
+          5 NAT66 translated
+        </paragraph>
+        <paragraph>
+          6 IPv6--&gt;IPv6 (no NAT)
+        </paragraph>
+      </description>
+      <range/>
+      <references>
+        <paragraph>         
+          See <xref type="rfc" data="rfc3022"/> for the definition of NAT.
+          See <xref type="rfc" data="rfc1631"/> for the definition of NAT44.
+          See <xref type="rfc" data="rfc6144"/> for the definition of NAT64.
+          See <xref type="rfc" data="rfc6146"/> for the definition of NAT46.
+          See <xref type="rfc" data="rfc6296"/> for the definition of NAT66.
+          See <xref type="rfc" data="rfc791"/> for the definition of IPv4.
+          See <xref type="rfc" data="rfc2460"/> for the definition of IPv6.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>initiatorPackets</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>298</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The total number of layer 4 packets in a flow from the
+          initiator. The initiator is the device which triggered the
+          session creation, and remains the same for the life of the
+          session.
+        </paragraph>
+      </description>
+      <units>packets</units>
+      <references>
+        <paragraph>         
+          See #231, initiatorOctets.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+    
+    <record>
+      <name>responderPackets</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>299</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The total number of layer 4 packets in a flow from the
+          responder. The responder is the device which replies to the
+          initiator, and remains the same for the life of the session.
+        </paragraph>
+      </description>
+      <units>packets</units>
+      <references>
+        <paragraph>         
+          See #232, responderOctets.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>observationDomainName</name>
+      <dataType>string</dataType>
+      <elementId>300</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The name of an observation domain identified by an
+          observationDomainId.
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>         
+          See #149, observationDomainId.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+    
+    <record>
+      <name>selectionSequenceId</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>301</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          From all the packets observed at an Observation Point, a subset of
+          the packets is selected by a sequence of one or more Selectors.
+          The selectionSequenceId is a unique value per Observation Domain,
+          specifying the Observation Point and the sequence of Selectors
+          through which the packets are selected.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>selectorId</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>302</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The Selector ID is the unique ID identifying a Primitive Selector.
+          Each Primitive Selector must have a unique ID in the Observation
+          Domain.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+      <xref type="rfc-errata" data="2052"/>
+    </record>
+
+    <record>
+      <name>informationElementId</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>303</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element contains the ID of another Information
+          Element.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>selectorAlgorithm</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>304</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element identifies the packet selection methods
+          (e.g., Filtering, Sampling) that are applied by the Selection
+          Process.
+          
+          Most of these methods have parameters.  Further Information
+          Elements are needed to fully specify packet selection with these
+          methods and all their parameters.
+          
+          The methods listed below are defined in [RFC5475].  For their parameters, Information Elements are defined in
+          the information model document.  The names of these Information
+          Elements are listed for each method identifier.
+          
+          Further method identifiers may be added to the list below.  It
+          might be necessary to define new Information Elements to specify
+          their parameters.
+          The selectorAlgorithm registry is maintained by IANA.  New
+          assignments for the registry will be administered by IANA, and
+          are subject to Expert Review [RFC5226].
+          
+          The registry can be updated when specifications of the new
+          method(s) and any new Information Elements are provided.
+          
+          The group of experts must double check the selectorAlgorithm
+          definitions and Information Elements with already defined
+          selectorAlgorithms and Information Elements for completeness,
+          accuracy, and redundancy.  Those experts will initially be drawn
+          from the Working Group Chairs and document editors of the IPFIX
+          and PSAMP Working Groups.
+          
+          The following packet selection methods identifiers are defined
+          here:
+          </paragraph>
+        <paragraph>
+          http://www.iana.org/assignments/psamp-parameters/psamp-parameters.xhtml
+        </paragraph>
+        <paragraph>
+          There is a broad variety of possible parameters that could be used
+          for Property match Filtering (5) but currently there are no agreed
+          parameters specified.        
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>samplingPacketInterval</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>305</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the number of packets that are
+          consecutively sampled.  A value of 100 means that 100
+          consecutive packets are sampled.
+          
+          For example, this Information Element may be used to describe the
+          configuration of a systematic count-based Sampling Selector.
+        </paragraph>
+      </description>
+      <units>packets</units>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>samplingPacketSpace</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>306</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the number of packets between
+          two "samplingPacketInterval"s.  A value of 100 means that the next
+          interval starts 100 packets (which are not sampled) after the
+          current "samplingPacketInterval" is over.
+          
+          For example, this Information Element may be used to describe the
+          configuration of a systematic count-based Sampling Selector.
+        </paragraph>
+      </description>
+      <units>packets</units>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>samplingTimeInterval</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>307</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the time interval in
+          microseconds during which all arriving packets are sampled.
+          
+          For example, this Information Element may be used to describe the
+          configuration of a systematic time-based Sampling Selector.
+        </paragraph>
+      </description>
+      <units>microseconds</units>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>samplingTimeSpace</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>308</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the time interval in
+          microseconds between two "samplingTimeInterval"s.  A value of 100
+          means that the next interval starts 100 microseconds (during which
+          no packets are sampled) after the current "samplingTimeInterval"
+          is over.
+          
+          For example, this Information Element may used to describe the
+          configuration of a systematic time-based Sampling Selector.
+        </paragraph>
+      </description>
+      <units>microseconds</units>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>samplingSize</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>309</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the number of elements taken
+          from the parent Population for random Sampling methods.
+          
+          For example, this Information Element may be used to describe the
+          configuration of a random n-out-of-N Sampling Selector.
+        </paragraph>
+      </description>
+      <units>packets</units>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>samplingPopulation</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>310</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the number of elements in the
+          parent Population for random Sampling methods.
+          
+          For example, this Information Element may be used to describe the
+          configuration of a random n-out-of-N Sampling Selector.
+        </paragraph>
+      </description>
+      <units>packets</units>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>samplingProbability</name>
+      <dataType>float64</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>311</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the probability that a packet
+          is sampled, expressed as a value between 0 and 1.  The probability
+          is equal for every packet.  A value of 0 means no packet was
+          sampled since the probability is 0.
+          
+          For example, this Information Element may be used to describe the
+          configuration of a uniform probabilistic Sampling Selector.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>dataLinkFrameSize</name>
+      <dataType>unsigned16</dataType>
+      <elementId>312</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the length of the selected data
+          link frame.
+          
+          The data link layer is defined in [ISO/IEC 7498-1:1994].
+        </paragraph>
+      </description>
+      <xref type="draft" data="draft-ietf-ipfix-data-link-layer-monitoring"/>
+    </record>
+
+    <record>
+      <name>ipHeaderPacketSection</name>
+      <dataType>octetArray</dataType>
+      <elementId>313</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element, which may have a variable length,
+          carries a series of octets from the start of the IP header of a
+          sampled packet.
+          
+          With sufficient length, this element also reports octets from the
+          IP payload, subject to [RFC2804].  See the Security Considerations
+          section.
+          
+          The size of the exported section may be constrained due to
+          limitations in the IPFIX protocol.
+          
+          The data for this field MUST NOT be padded.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>ipPayloadPacketSection</name>
+      <dataType>octetArray</dataType>
+      <elementId>314</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element, which may have a variable length,
+          carries a series of octets from the start of the IP payload of a
+          sampled packet.
+          
+          The IPv4 payload is that part of the packet that follows the IPv4
+          header and any options, which [RFC0791] refers to as "data" or
+          "data octets". For example, see the examples in [RFC0791], APPENDIX A.
+          
+          The IPv6 payload is the rest of the packet following the 40 octet
+          IPv6 header.  Note that any extension headers present are
+          considered part of the payload.  See [RFC2460] for the IPv6
+          specification.
+          
+          The size of the exported section may be constrained due to
+          limitations in the IPFIX protocol.
+          
+          The data for this field MUST NOT be padded.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>dataLinkFrameSection</name>
+      <dataType>octetArray</dataType>
+      <elementId>315</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element carries n octets from the data link frame
+          of a selected frame, starting sectionOffset octets into the frame.
+          
+          The sectionObservedOctets expresses how much data was observed,
+          while the remainder is padding.
+          
+          When the sectionObservedOctets field corresponding to this
+          Information Element exists, this Information Element MAY have a
+          fixed length and MAY be padded, or MAY have a variable length.
+          
+          When the sectionObservedOctets field corresponding to this
+          Information Element does not exist, this Information Element
+          SHOULD have a variable length and MUST NOT be padded.  In this
+          case, the size of the exported section may be constrained due to
+          limitations in the IPFIX protocol.
+          
+          Further Information Elements, i.e., dataLinkFrameType and
+          dataLinkFrameSize are needed to specify the data link type and the
+          size of the data link frame of this Information Element.  A set of
+          these Information Elements MAY be contained in a structured data
+          type, as expressed in <xref type="rfc" data="rfc6313"/>.  Or a set of these Information
+          Elements MAY be contained in one Flow Record as shown in Appendix
+          C of <xref type="draft" data="draft-ietf-ipfix-data-link-layer-monitoring"/>.
+          
+          The data link layer is defined in [ISO/IEC 7498-1:1994].
+        </paragraph>
+      </description>
+      <xref type="draft" data="draft-ietf-ipfix-data-link-layer-monitoring"/>
+    </record>
+
+    <record>
+      <name>mplsLabelStackSection</name>
+      <dataType>octetArray</dataType>
+      <elementId>316</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element, which may have a variable length,
+          carries the first n octets from the MPLS label stack of a sampled
+          packet.
+          
+          With sufficient length, this element also reports octets from the
+          MPLS payload, subject to [RFC2804].  See the Security
+          Considerations section.
+          
+          See [RFC3031] for the specification of MPLS packets.
+          
+          See [RFC3032] for the specification of the MPLS label stack.
+          
+          The size of the exported section may be constrained due to
+          limitations in the IPFIX protocol.
+          
+          The data for this field MUST NOT be padded.          
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>mplsPayloadPacketSection</name>
+      <dataType>octetArray</dataType>
+      <elementId>317</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element, which may have a variable length,
+          carries the first n octets from the MPLS payload of a sampled
+          packet, being data that follows immediately after the MPLS label
+          stack.
+          
+          See [RFC3031] for the specification of MPLS packets.
+          
+          See [RFC3032] for the specification of the MPLS label stack.
+          
+          The size of the exported section may be constrained due to
+          limitations in the IPFIX protocol.
+          
+          The data for this field MUST NOT be padded.          
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>selectorIdTotalPktsObserved</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>318</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the total number of packets
+          observed by a Selector, for a specific value of SelectorId.
+          
+          This Information Element should be used in an Options Template
+          scoped to the observation to which it refers.  See Section 3.4.2.1
+          of the IPFIX protocol document [RFC5101].      
+        </paragraph>
+      </description>
+      <units>packets</units>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>selectorIdTotalPktsSelected</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>319</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the total number of packets
+          selected by a Selector, for a specific value of SelectorId.
+          
+          This Information Element should be used in an Options Template
+          scoped to the observation to which it refers.  See Section 3.4.2.1
+          of the IPFIX protocol document [RFC5101].
+        </paragraph>
+      </description>
+      <units>packets</units>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>absoluteError</name>
+      <dataType>float64</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>320</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the maximum possible
+          measurement error of the reported value for a given Information
+          Element.  The absoluteError has the same unit as the Information
+          Element with which it is associated.  The real value of the metric can
+          differ by absoluteError (positive or negative) from the measured
+          value.
+          
+          This Information Element provides only the error for measured
+          values.  If an Information Element contains an estimated value
+          (from Sampling), the confidence boundaries and confidence level
+          have to be provided instead, using the upperCILimit, lowerCILimit, 
+          and confidenceLevel Information Elements.
+          
+          This Information Element should be used in an Options Template
+          scoped to the observation to which it refers.  See Section 3.4.2.1
+          of the IPFIX protocol document [RFC5101].   
+        </paragraph>
+      </description>
+      <units>The units of the Information Element for which the error is specified.</units>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>relativeError</name>
+      <dataType>float64</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>321</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the maximum possible positive
+          or negative error ratio for the reported value for a given
+          Information Element as percentage of the measured value.  The real
+          value of the metric can differ by relativeError percent (positive
+          or negative) from the measured value.
+          
+          This Information Element provides only the error for measured
+          values.  If an Information Element contains an estimated value
+          (from Sampling), the confidence boundaries and confidence level
+          have to be provided instead, using the upperCILimit, lowerCILimit, 
+          and confidenceLevel Information Elements.
+          
+          This Information Element should be used in an Options Template
+          scoped to the observation to which it refers.  See Section 3.4.2.1
+          of the IPFIX protocol document [RFC5101]. 
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>observationTimeSeconds</name>
+      <dataType>dateTimeSeconds</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>322</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the absolute time in seconds of
+          an observation.
+        </paragraph>
+      </description>
+      <units>seconds</units>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>observationTimeMilliseconds</name>
+      <dataType>dateTimeMilliseconds</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>323</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the absolute time in
+          milliseconds of an observation.
+        </paragraph>
+      </description>
+      <units>milliseconds</units>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>observationTimeMicroseconds</name>
+      <dataType>dateTimeMicroseconds</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>324</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the absolute time in
+          microseconds of an observation.
+        </paragraph>
+      </description>
+      <units>microseconds</units>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>observationTimeNanoseconds</name>
+      <dataType>dateTimeNanoseconds</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>325</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the absolute time in
+          nanoseconds of an observation.
+        </paragraph>
+      </description>
+      <units>nanoseconds</units>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>digestHashValue</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>326</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the value from the digest hash
+          function.
+          
+          See also Sections 6.2, 3.8 and 7.1 of [RFC5475].
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>hashIPPayloadOffset</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>327</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the IP payload offset used by a
+          Hash-based Selection Selector.
+          
+          See also Sections 6.2, 3.8 and 7.1 of [RFC5475].
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>hashIPPayloadSize</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>328</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the IP payload size used by a
+          Hash-based Selection Selector.  See also Sections 6.2, 3.8 and 7.1 of
+          [RFC5475].
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>hashOutputRangeMin</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>329</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the value for the beginning of
+          a hash function's potential output range.
+          
+          See also Sections 6.2, 3.8 and 7.1 of [RFC5475].
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>hashOutputRangeMax</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>330</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the value for the end of a hash
+          function's potential output range.
+          
+          See also Sections 6.2, 3.8 and 7.1 of [RFC5475].
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>hashSelectedRangeMin</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>331</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the value for the beginning of
+          a hash function's selected range.
+          
+          See also Sections 6.2, 3.8 and 7.1 of [RFC5475].
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>hashSelectedRangeMax</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>332</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the value for the end of a hash
+          function's selected range.
+          
+          See also Sections 6.2, 3.8 and 7.1 of [RFC5475].
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>hashDigestOutput</name>
+      <dataType>boolean</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>333</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element contains a boolean value that is TRUE if
+          the output from this hash Selector has been configured to be
+          included in the packet report as a packet digest, else FALSE.
+          
+          See also Sections 6.2, 3.8 and 7.1 of [RFC5475].
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>hashInitialiserValue</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>334</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the initialiser value to the
+          hash function.
+          
+          See also Sections 6.2, 3.8 and 7.1 of [RFC5475].
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>selectorName</name>
+      <dataType>string</dataType>
+      <elementId>335</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The name of a selector identified by a selectorID.  Globally 
+          unique per Metering Process. 
+        </paragraph>
+      </description>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>upperCILimit</name>
+      <dataType>float64</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>336</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the upper limit of a confidence
+          interval.  It is used to provide an accuracy statement for an
+          estimated value.  The confidence limits define the range in which
+          the real value is assumed to be with a certain probability p.
+          Confidence limits always need to be associated with a confidence
+          level that defines this probability p.  Please note that a
+          confidence interval only provides a probability that the real
+          value lies within the limits.  That means the real value can lie
+          outside the confidence limits.
+          
+          The upperCILimit, lowerCILimit, and confidenceLevel Information
+          Elements should all be used in an Options Template scoped to the
+          observation to which they refer.  See Section 3.4.2.1 of the IPFIX
+          protocol document [RFC5101].
+          
+          Note that the upperCILimit, lowerCILimit, and confidenceLevel are
+          all required to specify confidence, and should be disregarded
+          unless all three are specified together.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>lowerCILimit</name>
+      <dataType>float64</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>337</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the lower limit of a confidence
+          interval.  For further information, see the description of
+          upperCILimit.
+          
+          The upperCILimit, lowerCILimit, and confidenceLevel Information
+          Elements should all be used in an Options Template scoped to the
+          observation to which they refer.  See Section 3.4.2.1 of the IPFIX
+          protocol document [RFC5101].
+          
+          Note that the upperCILimit, lowerCILimit, and confidenceLevel are
+          all required to specify confidence, and should be disregarded
+          unless all three are specified together.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record>
+
+    <record>
+      <name>confidenceLevel</name>
+      <dataType>float64</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>338</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          This Information Element specifies the confidence level.  It is
+          used to provide an accuracy statement for estimated values.  The
+          confidence level provides the probability p with which the real
+          value lies within a given range.  A confidence level always needs
+          to be associated with confidence limits that define the range in
+          which the real value is assumed to be.
+          
+          The upperCILimit, lowerCILimit, and confidenceLevel Information
+          Elements should all be used in an Options Template scoped to the
+          observation to which they refer.  See Section 3.4.2.1 of the IPFIX
+          protocol document [RFC5101].
+          
+          Note that the upperCILimit, lowerCILimit, and confidenceLevel are
+          all required to specify confidence, and should be disregarded
+          unless all three are specified together.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5477"/>
+    </record> 
+    <record>
+      <name>informationElementDataType</name>
+      <dataType>unsigned8</dataType>
+      <elementId>339</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          A description of the abstract data type of an IPFIX
+          information element.These are taken from the abstract data types
+          defined in section 3.1 of the IPFIX Information Model [RFC5102];
+          see that section for more information on the types described
+          in the informationElementDataType sub-registry.
+          
+          These types are registered in the IANA IPFIX Information Element
+          Data Type subregistry.  This subregistry is intended to assign
+          numbers for type names, not to provide a mechanism for adding data
+          types to the IPFIX Protocol, and as such requires a Standards
+          Action [RFC5226] to modify.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <name>informationElementDescription</name>
+      <dataType>string</dataType>
+      <elementId>340</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          A UTF-8 [RFC3629] encoded Unicode string containing a
+          human-readable description of an Information Element.  The content
+          of the informationElementDescription MAY be annotated with one or
+          more language tags [RFC4646], encoded in-line [RFC2482] within the
+          UTF-8 string, in order to specify the language in which the
+          description is written.  Description text in multiple languages
+          MAY tag each section with its own language tag; in this case, the
+          description information in each language SHOULD have equivalent
+          meaning.  In the absence of any language tag, the "i-default"
+          [RFC2277] language SHOULD be assumed.  See the Security
+          Considerations section for notes on string handling for
+          Information Element type records.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <name>informationElementName</name>
+      <dataType>string</dataType>
+      <elementId>341</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          A UTF-8 [RFC3629] encoded Unicode string containing
+          the name of an Information Element, intended as a simple
+          identifier.  See the Security Considerations section for notes on
+          string handling for Information Element type records
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <name>informationElementRangeBegin</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>342</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Contains the inclusive low end of the range of
+          acceptable values for an Information Element.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <name>informationElementRangeEnd</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>343</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Contains the inclusive high end of the range of
+          acceptable values for an Information Element.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <name>informationElementSemantics</name>
+      <dataType>unsigned8</dataType>
+      <elementId>344</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          A description of the semantics of an IPFIX Information
+          Element.  These are taken from the data type semantics defined in
+          section 3.2 of the IPFIX Information Model [RFC5102]; see that
+          section for more information on the types defined in the informationElementSemantics sub-registry.  This
+          field may take the values in Table ; the special value 0x00
+          (default) is used to note that no semantics apply to the field; it
+          cannot be manipulated by a Collecting Process or File Reader that
+          does not understand it a priori.
+               
+          These semantics are registered in the IANA IPFIX Information
+          Element Semantics subregistry.  This subregistry is intended to
+          assign numbers for semantics names, not to provide a mechanism for
+          adding semantics to the IPFIX Protocol, and as such requires a
+          Standards Action [RFC5226] to modify.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <name>informationElementUnits</name>
+      <dataType>unsigned16</dataType>
+      <elementId>345</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          A description of the units of an IPFIX Information
+          Element.  These correspond to the units implicitly defined in the
+          Information Element definitions in section 5 of the IPFIX
+          Information Model [RFC5102]; see that section for more information
+          on the types described in the informationElementsUnits sub-registry.  This field may take the values in
+          Table 3 below; the special value 0x00 (none) is used to note that
+          the field is unitless.
+          
+          These types are registered in the IANA IPFIX Information Element
+          Units subregistry; new types may be added on a First Come First
+          Served [RFC5226] basis.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <name>privateEnterpriseNumber</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>346</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          A private enterprise number, as assigned by IANA.
+          Within the context of an Information Element Type record, this
+          element can be used along with the informationElementId element to
+          scope properties to a specific Information Element.  To export
+          type information about an IANA-assigned Information Element, set
+          the privateEnterpriseNumber to 0, or do not export the
+          privateEnterpriseNumber in the type record.  To export type
+          information about an enterprise-specific Information Element,
+          export the enterprise number in privateEnterpriseNumber, and
+          export the Information Element number with the Enterprise bit
+          cleared in informationElementId.  The Enterprise bit in the
+          associated informationElementId Information Element MUST be
+          ignored by the Collecting Process.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <name>virtualStationInterfaceId</name>
+      <dataType>octetArray</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>347</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Instance Identifier of the interface to a Virtual Station. A Virtual 
+          Station is an end station instance: it can be a virtual machine or a 
+          physical host.
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See IEEE 802.1Qbg for the definition of Virtual Station Interface ID.         
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>virtualStationInterfaceName</name>
+      <dataType>string</dataType>
+      <elementId>348</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Name of the interface to a Virtual Station. A Virtual Station is an end station 
+          instance: it can be a virtual machine or a physical host.
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See IEEE 802.1Qbg for the definition of Virtual Station Interface.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>virtualStationUUID</name>
+      <dataType>octetArray</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>349</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Unique Identifier of a Virtual Station. A Virtual Station is an end station 
+          instance: it can be a virtual machine or a physical host.
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See IEEE 802.1Qbg for the definition of Virtual Station.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>virtualStationName</name>
+      <dataType>string</dataType>
+      <elementId>350</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Name of a Virtual Station. A Virtual Station is an end station 
+          instance: it can be a virtual machine or a physical host.
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See IEEE 802.1Qbg for the definition of Virtual Station.
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>layer2SegmentId</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>351</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Identifier of a layer 2 network segment in an overlay network. 
+          The most significant byte identifies the layer 2 network 
+          overlay network encapsulation type:
+        </paragraph>
+        <paragraph>
+          0x00 reserved
+        </paragraph>
+        <paragraph>
+          0x01 VxLAN
+        </paragraph>
+        <paragraph>
+          0x02 NVGRE
+        </paragraph>
+        <paragraph>
+          The three lowest significant bytes
+          hold the value of the layer 2
+          overlay network segment identifier.
+        </paragraph>
+        <paragraph>
+          For example:
+        </paragraph>
+        <paragraph>
+          - a 24 bit segment ID VXLAN Network
+          Identifier (VNI)
+        </paragraph>
+        <paragraph>
+          - a 24 bit Tenant Network Identifier
+          (TNI) for NVGRE
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>
+          See VxLAN RFC at http://tools.ietf.org/html/draft-mahalingam-dutt-dcops-vxlan-00
+        </paragraph>
+        <paragraph>
+          See NVGRE RFC at http://tools.ietf.org/html/draft-sridharan-virtualization-nvgre-00
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record> 
+    <record>
+      <name>layer2OctetDeltaCount</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>deltaCounter</dataTypeSemantics>
+      <elementId>352</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The number of layer 2 octets since the previous report (if any) in
+          incoming packets for this Flow at the Observation Point.  The
+          number of octets includes layer 2 header(s) and layer 2 payload.
+          # memo: layer 2 version of octetDeltaCount (field #1)
+        </paragraph>
+      </description>
+      <units>octets</units>
+      <references>
+        <paragraph>
+          <xref type="draft" data="draft-kashima-ipfix-data-link-layer-monitoring"/>
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>layer2OctetTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>353</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>      
+          The total number of layer 2 octets in incoming packets for this
+          Flow at the Observation Point since the Metering Process
+          (re-)initialization for this Observation Point.  The number of
+          octets includes layer 2 header(s) and layer 2 payload.
+          # memo: layer 2 version of octetTotalCount (field #85)
+        </paragraph>
+      </description>
+      <units>octets</units>
+      <references>
+        <paragraph>
+          <xref type="draft" data="draft-kashima-ipfix-data-link-layer-monitoring"/>
+        </paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>ingressUnicastPacketTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>354</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>      
+          The total number of incoming unicast packets metered at the 
+          Observation Point since the Metering Process (re-)initialization 
+          for this Observation Point.
+        </paragraph>
+      </description>
+      <units>packets</units>
+      <references><paragraph/></references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>ingressMulticastPacketTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>355</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>      
+          The total number of incoming multicast packets metered at the 
+          Observation Point since the Metering Process (re-)initialization 
+          for this Observation Point.
+        </paragraph>
+      </description>
+      <units>packets</units>
+      <references><paragraph/></references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>ingressBroadcastPacketTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>356</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>      
+          The total number of incoming broadcast packets metered at the 
+          Observation Point since the Metering Process (re-)initialization 
+          for this Observation Point.
+        </paragraph>
+      </description>
+      <units>packets</units>
+      <references><paragraph/></references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>egressUnicastPacketTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>357</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>      
+          The total number of incoming unicast packets metered at the 
+          Observation Point since the Metering Process (re-)initialization 
+          for this Observation Point.
+        </paragraph>
+      </description>
+      <units>packets</units>
+      <references><paragraph/></references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>egressBroadcastPacketTotalCount</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>358</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>      
+          The total number of incoming broadcast packets metered at the 
+          Observation Point since the Metering Process (re-)initialization 
+          for this Observation Point.
+        </paragraph>
+      </description>
+      <units>packets</units>
+      <references><paragraph/></references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>monitoringIntervalStartMilliSeconds</name>
+      <dataType>dateTimeMilliseconds</dataType>
+      <elementId>359</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>      
+          The absolute timestamp at which the monitoring interval
+          started.
+          A Monitoring interval is the period of time during which the Metering
+          Process is running.
+        </paragraph>
+      </description>
+      <units>milliseconds</units>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>monitoringIntervalEndMilliSeconds</name>
+      <dataType>dateTimeMilliseconds</dataType>
+      <elementId>360</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>      
+          The absolute timestamp at which the monitoring interval ended.
+          A Monitoring interval is the period of time during which the Metering
+          Process is running.
+        </paragraph>
+      </description>
+      <units>milliseconds</units>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>portRangeStart</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>361</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>      
+          The port number identifying the start of a range of ports. A value 
+          of zero indicates that the range start is not specified, ie the
+          range is defined in some other way.
+        </paragraph>
+        <paragraph>
+          Additional information on defined TCP port numbers can be found at 
+          http://www.iana.org/assignments/service-names-port-numbers.
+        </paragraph>
+      </description>
+      <references><paragraph/></references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>portRangeEnd</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>362</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>      
+          The port number identifying the end of a range of ports. A value 
+          of zero indicates that the range end is not specified, ie the
+          range is defined in some other way.
+        </paragraph>
+        <paragraph>
+          Additional information on defined TCP port numbers can be found at 
+          http://www.iana.org/assignments/service-names-port-numbers.
+        </paragraph>
+      </description>
+      <references><paragraph/></references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>portRangeStepSize</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>363</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>      
+          The step size in a port range. The default step size is 1,
+          which indicates contiguous ports. A value of zero indicates 
+          that the step size is not specified, ie the range is defined 
+          in some other way.
+        </paragraph>
+      </description>
+      <references><paragraph/></references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>portRangeNumPorts</name>
+      <dataType>unsigned16</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>364</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>      
+          The number of ports in a port range. A value of zero indicates 
+          that the number of ports is not specified, ie the range is defined 
+          in some other way.
+        </paragraph>
+      </description>
+      <references><paragraph/></references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>staMacAddress</name>
+      <dataType>macAddress</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>365</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>      
+          The IEEE 802 MAC address of a wireless station (STA).
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>See section 1.4 of RFC5415 for the definition of STA.</paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>staIPv4Address</name>
+      <dataType>ipv4Address</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>366</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>      
+          The IPv4 address of a wireless station (STA).
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>See section 1.4 of RFC5415 for the definition of STA.</paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>wtpMacAddress</name>
+      <dataType>macAddress</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>367</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>      
+          The IEEE 802 MAC address of a wireless access point (WTP).
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>See section 1.4 of RFC5415 for the definition of WTP.</paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>ingressInterfaceType</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>368</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>      
+          The type of interface where packets of this Flow are being received.
+          The value matches the value of managed object 'ifType' as defined in 
+          http://www.iana.org/assignments/ianaiftype-mib/ianaiftype-mib
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>http://www.iana.org/assignments/ianaiftype-mib/ianaiftype-mib</paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>egressInterfaceType</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>identifier</dataTypeSemantics>
+      <elementId>369</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>      
+          The type of interface where packets of this Flow are being sent.
+          The value matches the value of managed object 'ifType' as defined in 
+          http://www.iana.org/assignments/ianaiftype-mib/ianaiftype-mib
+        </paragraph>
+      </description>
+      <references>
+        <paragraph>http://www.iana.org/assignments/ianaiftype-mib/ianaiftype-mib</paragraph>
+      </references>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>rtpSequenceNumber</name>
+      <dataType>unsigned16</dataType>
+      <elementId>370</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The RTP sequence number per RFC3550.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc3550"/>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>userName</name>
+      <dataType>string</dataType>
+      <elementId>371</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          User name associated with the flow.
+        </paragraph>
+      </description>
+     <xref type="person" data="ipfix-iana_at_cisco.com"/>
+    </record>
+
+    <record>
+      <name>applicationCategoryName</name>
+      <dataType>string</dataType>
+      <elementId>372</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          An attribute that provides a first level categorization for
+          each Application ID.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc6759"/>
+    </record>
+
+    <record>
+      <name>applicationSubCategoryName</name>
+      <dataType>string</dataType>
+      <elementId>373</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          An attribute that provides a second level categorization
+          for each Application ID.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc6759"/>
+    </record>
+
+    <record>
+      <name>applicationGroupName</name>
+      <dataType>string</dataType>
+      <elementId>374</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          An attribute that groups multiple Application IDs that
+          belong to the same networking application.
+        </paragraph>
+      </description>
+      <xref type="rfc" data="rfc6759"/>
+    </record>
+    
+    <record>
+      <name>originalFlowsPresent</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>deltaCounter</dataTypeSemantics>
+      <elementId>375</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The non-conservative count of Original Flows
+          contributing to this Aggregated Flow.  Non-conservative counts
+          need not sum to the original count on re-aggregation.
+        </paragraph>
+      </description>
+      <xref type="draft" data="RFC-ietf-ipfix-a9n-08"/>
+    </record>
+    
+    <record>
+      <name>originalFlowsInitiated</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>deltaCounter</dataTypeSemantics>
+      <elementId>376</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The conservative count of Original Flows whose first
+          packet is represented within this Aggregated Flow.  Conservative
+          counts must sum to the original count on re-aggregation.
+        </paragraph>
+      </description>
+      <xref type="draft" data="RFC-ietf-ipfix-a9n-08"/>
+    </record>
+    
+    <record>
+      <name>originalFlowsCompleted</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>deltaCounter</dataTypeSemantics>
+      <elementId>377</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The conservative count of Original Flows whose last
+          packet is represented within this Aggregated Flow.  Conservative
+          counts must sum to the original count on re-aggregation.
+        </paragraph>
+      </description>
+      <xref type="draft" data="RFC-ietf-ipfix-a9n-08"/>
+    </record>
+    
+    <record>
+      <name>distinctCountOfSourceIPAddress</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>378</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The count of distinct source IP address values for
+          Original Flows contributing to this Aggregated Flow, without
+          regard to IP version.  This Information Element is preferred to
+          the IP-version-specific counters, unless it is important to
+          separate the counts by version.
+        </paragraph>
+      </description>
+      <xref type="draft" data="RFC-ietf-ipfix-a9n-08"/>
+    </record>
+    
+    <record>
+      <name>distinctCountOfDestinationIPAddress</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>379</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The count of distinct destination IP address values
+          for Original Flows contributing to this Aggregated Flow, without
+          regard to IP version.  This Information Element is preferred to
+          the version-specific counters below, unless it is important to
+          separate the counts by version.
+        </paragraph>
+      </description>
+      <xref type="draft" data="RFC-ietf-ipfix-a9n-08"/>
+    </record>
+    
+    <record>
+      <name>distinctCountOfSourceIPv4Address</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>380</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The count of distinct source IPv4 address values for
+          Original Flows contributing to this Aggregated Flow.
+        </paragraph>
+      </description>
+      <xref type="draft" data="RFC-ietf-ipfix-a9n-08"/>
+    </record>
+    
+    <record>
+      <name>distinctCountOfDestinationIPv4Address</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>381</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The count of distinct destination IPv4 address values
+          for Original Flows contributing to this Aggregated Flow.
+        </paragraph>
+      </description>
+      <xref type="draft" data="RFC-ietf-ipfix-a9n-08"/>
+    </record>
+    
+    <record>
+      <name>distinctCountOfSourceIPv6Address</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>382</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The count of distinct source IPv6 address values for
+          Original Flows contributing to this Aggregated Flow.
+        </paragraph>
+      </description>
+      <xref type="draft" data="RFC-ietf-ipfix-a9n-08"/>
+    </record>
+    
+    <record>
+      <name>distinctCountOfDestinationIPv6Address</name>
+      <dataType>unsigned64</dataType>
+      <dataTypeSemantics>totalCounter</dataTypeSemantics>
+      <elementId>383</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          The count of distinct destination IPv6 address values
+          for Original Flows contributing to this Aggregated Flow.
+        </paragraph>
+      </description>
+      <xref type="draft" data="RFC-ietf-ipfix-a9n-08"/>
+    </record>
+
+    <record>
+      <name>valueDistributionMethod</name>
+      <dataType>unsigned8</dataType>
+      <elementId>384</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          A description of the method used to distribute the
+          counters from Contributing Flows into the Aggregated Flow records
+          described by an associated scope, generally a Template.  The
+          method is deemed to apply to all the non-key Information Elements
+          in the referenced scope for which value distribution is a valid
+          operation; if the originalFlowsInitiated and/or
+          originalFlowsCompleted Information Elements appear in the
+          Template, they are not subject to this distribution method, as
+          they each infer their own distribution method.  This is intended
+          to be a complete set of possible value distribution methods; it is
+          encoded as follows:
+          </paragraph>
+            <artwork>
+          +-------+-----------------------------------------------------------+
+          | Value | Description                                               |
+          +-------+-----------------------------------------------------------+
+          | 0     | Unspecified: The counters for an Original Flow are        |
+          |       | explicitly not distributed according to any other method  |
+          |       | defined for this Information Element; use for arbitrary   |
+          |       | distribution, or distribution algorithms not described by |
+          |       | any other codepoint.                                      |
+          |       | --------------------------------------------------------- |
+          |       |                                                           |
+          | 1     | Start Interval: The counters for an Original Flow are     |
+          |       | added to the counters of the appropriate Aggregated Flow  |
+          |       | containing the start time of the Original Flow.  This     |
+          |       | should be assumed the default if value distribution       |
+          |       | information is not available at a Collecting Process for  |
+          |       | an Aggregated Flow.                                       |
+          |       | --------------------------------------------------------- |
+          |       |                                                           |
+          | 2     | End Interval: The counters for an Original Flow are added |
+          |       | to the counters of the appropriate Aggregated Flow        |
+          |       | containing the end time of the Original Flow.             |
+          |       | --------------------------------------------------------- |
+          |       |                                                           |
+          | 3     | Mid Interval: The counters for an Original Flow are added |
+          |       | to the counters of a single appropriate Aggregated Flow   |
+          |       | containing some timestamp between start and end time of   |
+          |       | the Original Flow.                                        |
+          |       | --------------------------------------------------------- |
+          |       |                                                           |
+          | 4     | Simple Uniform Distribution: Each counter for an Original |
+          |       | Flow is divided by the number of time intervals the       |
+          |       | Original Flow covers (i.e., of appropriate Aggregated     |
+          |       | Flows sharing the same Flow Key), and this number is      |
+          |       | added to each corresponding counter in each Aggregated    |
+          |       | Flow.                                                     |
+          |       | --------------------------------------------------------- |
+          |       |                                                           |
+          | 5     | Proportional Uniform Distribution: Each counter for an    |
+          |       | Original Flow is divided by the number of time units the  |
+          |       | Original Flow covers, to derive a mean count rate.  This  |
+          |       | mean count rate is then multiplied by the number of time  |
+          |       | units in the intersection of the duration of the Original |
+          |       | Flow and the time interval of each Aggregated Flow.  This |
+          |       | is like simple uniform distribution, but accounts for the |
+          |       | fractional portions of a time interval covered by an      |
+          |       | Original Flow in the first and last time interval.        |
+          |       | --------------------------------------------------------- |
+          |       |                                                           |
+          | 6     | Simulated Process: Each counter of the Original Flow is   |
+          |       | distributed among the intervals of the Aggregated Flows   |
+          |       | according to some function the Intermediate Aggregation   |
+          |       | Process uses based upon properties of Flows presumed to   |
+          |       | be like the Original Flow.  This is essentially an        |
+          |       | assertion that the Intermediate Aggregation Process has   |
+          |       | no direct packet timing information but is nevertheless   |
+          |       | not using one of the other simpler distribution methods.  |
+          |       | The Intermediate Aggregation Process specifically makes   |
+          |       | no assertion as to the correctness of the simulation.     |
+          |       | --------------------------------------------------------- |
+          |       |                                                           |
+          | 7     | Direct: The Intermediate Aggregation Process has access   |
+          |       | to the original packet timings from the packets making up |
+          |       | the Original Flow, and uses these to distribute or        |
+          |       | recalculate the counters.                                 |
+          +-------+-----------------------------------------------------------+
+            </artwork>
+      </description>
+      <xref type="draft" data="RFC-ietf-ipfix-a9n-08"/>
+    </record>
+
+    <record>
+      <name>rfc3550JitterMeanMilliseconds</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>385</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Interarrival jitter as defined in section 6.4.1 of <xref type="rfc" data="rfc3550"/>, 
+          measured in milliseconds.
+        </paragraph>
+      </description>
+      <units>milliseconds</units>
+      <xref type="rfc" data="rfc3550"/>
+    </record>
+    
+    <record>
+      <name>rfc3550JitterMeanMicroseconds</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>386</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Interarrival jitter as defined in section 6.4.1 of <xref type="rfc" data="rfc3550"/>, 
+          measured in microseconds.
+        </paragraph>
+      </description>
+      <units>microseconds</units>
+      <xref type="rfc" data="rfc3550"/>
+    </record>
+    
+    <record>
+      <name>rfc3550JitterMeanNanoseconds</name>
+      <dataType>unsigned32</dataType>
+      <dataTypeSemantics>quantity</dataTypeSemantics>
+      <elementId>387</elementId>
+      <status>current</status>
+      <description>
+        <paragraph>
+          Interarrival jitter as defined in section 6.4.1 of <xref type="rfc" data="rfc3550"/>, 
+          measured in nanoseconds.
+        </paragraph>
+      </description>
+      <units>nanoseconds</units>
+      <xref type="rfc" data="rfc3550"/>
+    </record>
+
+
+    <record>
+      <elementId>388-32767</elementId>
+      <unassigned/>
+    </record>
+    
+    
+    <registry id="ipfix-mpls-label-type">
+      <title>IPFIX MPLS label type (Value 46)</title>
+      <registration_rule>Expert Review</registration_rule>
+      <expert>Primary expert - Nevil Brownlee and Secondary expert - Juergen Quittek</expert>
+      <xref type="rfc" data="rfc5102"/>
+      
+      <record>
+        <value>1</value>
+        <description>TE-MIDPT: Any TE tunnel mid-point or tail label</description>
+        <xref type="rfc" data="rfc5102"/>
+      </record>
+
+      <record>
+        <value>2</value>
+        <description>Pseudowire: Any PWE3 or Cisco AToM based label</description>
+        <xref type="rfc" data="rfc5102"/>
+      </record>
+
+      <record>
+        <value>3</value>
+        <description>VPN: Any label associated with VPN</description>
+        <xref type="rfc" data="rfc5102"/>
+      </record>
+
+      <record>
+        <value>4</value>
+        <description>BGP: Any label associated with BGP or BGP routing</description>
+        <xref type="rfc" data="rfc5102"/>
+      </record>
+
+      <record>
+        <value>5</value>
+        <description>LDP: Any label associated with dynamically assigned labels using LDP</description>
+        <xref type="rfc" data="rfc5102"/>
+      </record>
+
+      <record>
+        <value>6-255</value>
+        <description>Unassigned</description>
+        <xref type="rfc" data="rfc5102"/>
+      </record>
+    </registry>
+    
+    
+    
+    <registry id="classification-engine-ids">
+      <title>Classification Engine IDs (Value 101)</title>
+      <registration_rule>Expert Review</registration_rule>
+      <expert>Primary expert - Nevil Brownlee and Secondary expert - Juergen Quittek</expert>
+      <xref type="rfc" data="rfc6759"/>
+      
+      <record>
+        <value>0</value>
+        <description>Invalid.</description>
+        <length/>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+
+      <record>
+        <value>1</value>
+        <description>IANA-L3: The Assigned Internet Protocol Number (layer 3 (L3)) is exported in the Selector ID. See http://www.iana.org/assignments/protocol-numbers.
+        </description>
+        <length>1</length>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+
+      <record>
+        <value>2</value>
+        <description>PANA-L3: Proprietary layer 3 definition. An enterprise can export its own layer 3 protocol numbers. The Selector ID has a global significance for all devices from the same enterprise.
+        </description>
+        <length>1</length>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+
+      <record>
+        <value>3</value>
+        <description>IANA-L4: The IANA layer 4 (L4) well-known port
+          number is exported in the Selector ID. See [http://www.iana.org/assignments/service-names-port-numbers]. Note: as an IPFIX flow is unidirectional,
+          it contains the destination port in a flow from
+          the client to the server.
+        </description>
+        <length>2</length>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+
+      <record>
+        <value>4</value>
+        <description>PANA-L4: Proprietary layer 4 definition. An
+          enterprise can export its own layer 4 port
+          numbers. The Selector ID has global significance
+          for devices from the same enterprise. Example:
+          IPFIX had the port 4739 pre-assigned in the IETF
+          draft for years. While waiting for the RFC and its
+          associated IANA registration, the Selector ID 4739
+          was used with this PANA-L4.
+        </description>
+        <length>2</length>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+
+      <record>
+        <value>5</value>
+        <description>Reserved</description>
+        <length/>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+
+      <record>
+        <value>6</value>
+        <description>USER-Defined: The Selector ID represents
+          applications defined by the user (using CLI, GUI,
+          etc.) based on the methods described in section 2.
+          The Selector ID has a local significance per
+          device.
+        </description>
+        <length>3</length>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+
+      <record>
+        <value>7</value>
+        <description>Reserved</description>
+        <length/>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+
+      <record>
+        <value>8</value>
+        <description>Reserved</description>
+        <length/>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+
+      <record>
+        <value>9</value>
+        <description>Reserved</description>
+        <length/>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+
+      <record>
+        <value>10</value>
+        <description>Reserved</description>
+        <length/>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+
+      <record>
+        <value>11</value>
+        <description>Reserved</description>
+        <length/>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+
+      <record>
+        <value>12</value>
+        <description>PANA-L2: Proprietary layer 2 (L2) definition.  An
+          enterprise can export its own layer 2 identifiers.
+          The Selector ID represents the enterprise's unique
+          global layer 2 applications. The Selector ID has a
+          global significance for all devices from the same
+          enterprise. Examples include Cisco Subnetwork
+          Access Protocol (SNAP).
+        </description>
+        <length>5</length>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+      
+      <record>
+        <value>13</value>
+        <description>PANA-L7: Proprietary layer 7 definition. The
+          Selector ID represents the enterprise's unique
+          global ID for the layer 7 applications. The
+          Selector ID has a global significance for all
+          devices from the same enterprise. This
+          Classification Engine Id is used when the
+          application registry is owned by the Exporter
+          manufacturer (referred to as the "enterprise" in
+          this document).
+        </description>
+        <length>3</length>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+      
+      <record>
+        <value>14</value>
+        <description>Reserved</description>
+        <length/>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+      
+      <record>
+        <value>15</value>
+        <description>Reserved</description>
+        <length/>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+      
+      <record>
+        <value>16</value>
+        <description>Reserved</description>
+        <length/>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+      
+      <record>
+        <value>17</value>
+        <description>Reserved</description>
+        <length/>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+
+      <record>
+        <value>18</value>
+        <description>ETHERTYPE: The Selector ID represents the well-
+          known Ethertype. See http://standards.ieee.org/develop/regauth/ethertype/eth.txt. 
+          Note that the Ethertype is usually expressed in 
+          hexadecimal. However, the corresponding decimal 
+          value is used in this Selector ID.
+        </description>
+        <length>2</length>
+        <xref type="rfc" data="rfc6759"/>
+      </record>
+
+      <record>
+        <value>19</value>
+        <description>LLC: The Selector ID represents the well-known
+          IEEE 802.2 Link Layer Control (LLC) Destination
+          Service Access Point (DSAP). 
+          See http://standards.ieee.org/develop/regauth/llc/public.html. 
+          Note that LLC DSAP is usually expressed in 
+          hexadecimal. However, the corresponding decimal 
+          value is used in this Selector ID.
+        </description>
+        <length>1</length>
+        <xref type="rfc" data="rfc6759"/>
+      </record>    
+      
+      <record>
+        <value>20</value>
+        <description>PANA-L7-PEN: Proprietary layer 7 definition,
+          including a Private Enterprise Number (PEN) 
+          [http://www.iana.org/assignments/enterprise-numbers]
+          to identify that the application registry being
+          used is not owned by the Exporter manufacturer or to identify the
+          original enterprise in the case of a mediator or
+          3rd party device. The Selector ID represents the
+          enterprise unique global ID for the layer 7
+          applications. The Selector ID has a global
+          significance for all devices from the same
+          enterprise.
+          </description>
+        <length>3</length>
+      <xref type="rfc" data="rfc6759"/>
+      </record>
+    
+    </registry>
+    
+  </registry>
+  
+  
+  
+  <registry id="ipfix-version-numbers">
+    <title>IPFIX Version Numbers</title>
+    <xref type="rfc" data="rfc5101"/>
+    <registration_rule>Standards Action</registration_rule>
+    
+    <record>
+      <value>0</value>
+      <description>Reserved</description>
+    </record>
+
+    <record>
+      <value>1-8</value>
+      <description>Reserved (historic)</description>
+    </record>
+
+    <record>
+      <value>9</value>
+      <description>Cisco Systems NetFlow Version 9 (historic)</description>
+      <xref type="rfc" data="rfc3954"/>
+    </record>
+
+    <record>
+      <value>10</value>
+      <description>IPFIX as documented in RFC5101</description>
+      <xref type="rfc" data="rfc5101"/>
+    </record>
+
+    <record>
+      <value>11-65535</value>
+      <description>Unassigned</description>
+    </record>
+    
+  </registry>
+  
+  
+  
+  <registry id="ipfix-set-ids">
+    <title>IPFIX Set IDs</title>
+    <xref type="rfc" data="rfc5101"/>
+    <registration_rule>Standards Action</registration_rule>
+    
+    <record>
+      <value>0-1</value>
+      <description>Not used (historic)</description>
+      <xref type="rfc" data="rfc3954"/>
+    </record>
+
+    <record>
+      <value>2</value>
+      <description>Template Set</description>
+      <xref type="rfc" data="rfc5101"/>
+    </record>
+
+    <record>
+      <value>3</value>
+      <description>Option Template Set</description>
+      <xref type="rfc" data="rfc5101"/>
+    </record>
+
+    <record>
+      <value>4-255</value>
+      <description>Unassigned</description>
+      <xref type="rfc" data="rfc5101"/>
+    </record>
+
+    <record>
+      <value>256-65535</value>
+      <description>Reserved for Data Sets</description>
+      <xref type="rfc" data="rfc5101"/>
+    </record>
+    
+  </registry>
+  
+  
+  
+  <registry id="ipfix-information-element-data-types">
+    <title>IPFIX Information Element Data Types</title>
+    <xref type="rfc" data="rfc5610"/>
+    <registration_rule>Standards Action</registration_rule>
+
+    
+    
+    <record>
+      <value>0</value>
+      <description>octetArray</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>1</value>
+      <description>unsigned8</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>2</value>
+      <description>unsigned16</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>3</value>
+      <description>unsigned32</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>4</value>
+      <description>unsigned64</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>5</value>
+      <description>signed8</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>6</value>
+      <description>signed16</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>7</value>
+      <description>signed32</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>8</value>
+      <description>signed64</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>9</value>
+      <description>float32</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>10</value>
+      <description>float64</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>11</value>
+      <description>boolean</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>12</value>
+      <description>macAddress</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>13</value>
+      <description>string</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>14</value>
+      <description>dateTimeSeconds</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>15</value>
+      <description>dateTimeMilliseconds</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>16</value>
+      <description>dateTimeMicroseconds</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>17</value>
+      <description>dateTimeNanoseconds</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>18</value>
+      <description>ipv4Address</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>19</value>
+      <description>ipv6Address</description>
+      <xref type="rfc" data="rfc5102"/>
+    </record>
+
+    <record>
+      <value>20</value>
+      <description>basicList</description>
+      <xref type="rfc" data="rfc6313"/>
+    </record>
+
+    <record>
+      <value>21</value>
+      <description>subTemplateList</description>
+      <xref type="rfc" data="rfc6313"/>
+    </record>
+
+    <record>
+      <value>22</value>
+      <description>subTemplateMultiList</description>
+      <xref type="rfc" data="rfc6313"/>
+    </record>
+
+    <record>
+      <value>23-255</value>
+      <description>Unassigned</description>
+    </record>
+    
+  </registry>
+  
+  
+  
+  <registry id="ipfix-information-element-semantics">
+    <title>IPFIX Information Element Semantics</title>
+    <xref type="rfc" data="rfc5610"/>
+    <registration_rule>Standards Action</registration_rule>
+    
+    
+    
+    <record>
+      <value>0</value>
+      <description>default</description>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>1</value>
+      <description>quantity</description>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>2</value>
+      <description>totalCounter</description>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>3</value>
+      <description>deltaCounter</description>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>4</value>
+      <description>identifier</description>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>5</value>
+      <description>flags</description>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>6</value>
+      <description>list</description>
+      <xref type="rfc" data="rfc6313"/>
+    </record>
+
+    <record>
+      <value>7-255</value>
+      <description>Unassigned</description>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+    
+  </registry>
+  
+  
+  
+  <registry id="ipfix-information-element-units">
+    <title>IPFIX Information Element Units</title>
+    <xref type="rfc" data="rfc5610"/>
+    <registration_rule>Expert Review</registration_rule>
+    
+    <record>
+      <value>0</value>
+      <description>none</description>
+      <comments/>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>1</value>
+      <description>bits</description>
+      <comments/>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>2</value>
+      <description>octets</description>
+      <comments/>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>3</value>
+      <description>packets</description>
+      <comments/>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>4</value>
+      <description>flows</description>
+      <comments/>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>5</value>
+      <description>seconds</description>
+      <comments/>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>6</value>
+      <description>milliseconds</description>
+      <comments/>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>7</value>
+      <description>microseconds</description>
+      <comments/>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>8</value>
+      <description>nanoseconds</description>
+      <comments/>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>9</value>
+      <description>4-octet words</description>
+      <comments>for IPv4 header length</comments>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>10</value>
+      <description>messages</description>
+      <comments>for reliability reporting</comments>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>11</value>
+      <description>hops</description>
+      <comments>for TTL</comments>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>12</value>
+      <description>entries</description>
+      <comments>for MPLS label stack</comments>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+
+    <record>
+      <value>13-65535</value>
+      <description>Unassigned</description>
+      <comments/>
+      <xref type="rfc" data="rfc5610"/>
+    </record>
+    
+  </registry>
+  
+  
+  
+  <registry id="ipfix-structured-data-types-semantics">
+    <title>IPFIX Structured Data Types Semantics</title>
+    <xref type="rfc" data="rfc6313"/>
+    <registration_rule>Standards Action</registration_rule>
+    
+    <record>
+      <value>0x00</value>
+      <name>noneOf</name>
+      <description>The "noneOf" structured data type semantic specifies
+        that none of the elements are actual properties of the Data
+        Record.
+      </description>
+      <xref type="rfc" data="rfc6313"/>
+    </record>
+
+    <record>
+      <value>0x01</value>
+      <name>exactlyOneOf</name>
+      <description>The "exactlyOneOf" structured data type semantic
+        specifies that only a single element from the structured data is
+        an actual property of the Data Record.  This is equivalent to a
+        logical XOR operation.
+      </description>
+      <xref type="rfc" data="rfc6313"/>
+    </record>
+
+    <record>
+      <value>0x02</value>
+      <name>oneOrMoreOf</name>
+      <description>The "oneOrMoreOf" structured data type semantic
+        specifies that one or more elements from the list in the
+        structured data are actual properties of the Data Record.  This is
+        equivalent to a logical OR operation.
+      </description>
+      <xref type="rfc" data="rfc6313"/>
+    </record>
+
+    <record>
+      <value>0x03</value>
+      <name>allOf</name>
+      <description>The "allOf" structured data type semantic specifies
+        that all of the list elements from the structured data are actual
+        properties of the Data Record.
+      </description>
+      <xref type="rfc" data="rfc6313"/>
+    </record>
+
+    <record>
+      <value>0x04</value>
+      <name>ordered</name>
+      <description>The "ordered" structured data type semantic specifies
+        that elements from the list in the structured data are ordered.
+      </description>
+      <xref type="rfc" data="rfc6313"/>
+    </record>
+
+    <record>
+      <value>0x05-0xFE</value>
+      <name/>
+      <description>unassigned
+      </description>
+    </record>
+
+    <record>
+      <value>0xFF</value>
+      <name>undefined</name>
+      <description>The "undefined" structured data type semantic
+        specifies that the semantic of the list elements is not specified and
+        that, if a semantic exists, then it is up to the Collecting
+        Process to draw its own conclusions.  The "undefined" structured
+        data type semantic is the default structured data type semantic.
+      </description>
+      <xref type="rfc" data="rfc6313"/>
+    </record>
+    
+  </registry>
+  
+  <people>
+    <person id="ipfix-iana_at_cisco.com">
+      <name>ipfix-iana at cisco.com</name>
+      <uri>mailto:ipfix-iana&amp;cisco.com</uri>
+      <updated>2012-09-20</updated>
+    </person>
+  </people>
+  
+</registry>
diff --git a/ofproto/ofproto-dpif-ipfix.c b/ofproto/ofproto-dpif-ipfix.c
new file mode 100644 (file)
index 0000000..9de8b1c
--- /dev/null
@@ -0,0 +1,848 @@
+/*
+ * Copyright (c) 2012 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+#include "ofproto-dpif-ipfix.h"
+#include "byte-order.h"
+#include "collectors.h"
+#include "flow.h"
+#include "hash.h"
+#include "hmap.h"
+#include "ofpbuf.h"
+#include "ofproto.h"
+#include "packets.h"
+#include "sset.h"
+#include "util.h"
+#include "timeval.h"
+#include "util.h"
+#include "vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(ipfix);
+
+static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
+
+/* Cf. IETF RFC 5101 Section 10.3.4. */
+#define IPFIX_DEFAULT_COLLECTOR_PORT 4739
+
+struct dpif_ipfix_exporter {
+    struct collectors *collectors;
+    uint32_t seq_number;
+    time_t last_template_set_time;
+};
+
+struct dpif_ipfix_bridge_exporter {
+    struct dpif_ipfix_exporter exporter;
+    struct ofproto_ipfix_bridge_exporter_options *options;
+    uint32_t probability;
+};
+
+struct dpif_ipfix_flow_exporter {
+    struct dpif_ipfix_exporter exporter;
+    struct ofproto_ipfix_flow_exporter_options *options;
+};
+
+struct dpif_ipfix_flow_exporter_map_node {
+    struct hmap_node node;
+    struct dpif_ipfix_flow_exporter exporter;
+};
+
+struct dpif_ipfix {
+    struct dpif_ipfix_bridge_exporter bridge_exporter;
+    struct hmap flow_exporter_map;  /* dpif_ipfix_flow_exporter_map_nodes. */
+};
+
+#define IPFIX_VERSION 0x000a
+
+/* When using UDP, IPFIX Template Records must be re-sent regularly.
+ * The standard default interval is 10 minutes (600 seconds).
+ * Cf. IETF RFC 5101 Section 10.3.6. */
+#define IPFIX_TEMPLATE_INTERVAL 600
+
+/* Cf. IETF RFC 5101 Section 3.1. */
+struct ipfix_header {
+    ovs_be16 version;  /* IPFIX_VERSION. */
+    ovs_be16 length;  /* Length in bytes including this header. */
+    ovs_be32 export_time;  /* Seconds since the epoch. */
+    ovs_be32 seq_number;  /* Message sequence number. */
+    ovs_be32 obs_domain_id;  /* Observation Domain ID. */
+} __attribute__((packed));
+BUILD_ASSERT_DECL(sizeof(struct ipfix_header) == 16);
+
+#define IPFIX_SET_ID_TEMPLATE 2
+#define IPFIX_SET_ID_OPTION_TEMPLATE 3
+
+/* Cf. IETF RFC 5101 Section 3.3.2. */
+struct ipfix_set_header {
+    ovs_be16 set_id;  /* IPFIX_SET_ID_* or valid template ID for Data Sets. */
+    ovs_be16 length;  /* Length of the set in bytes including header. */
+} __attribute__((packed));
+BUILD_ASSERT_DECL(sizeof(struct ipfix_set_header) == 4);
+
+/* Alternatives for templates at each layer.  A template is defined by
+ * a combination of one value for each layer. */
+enum ipfix_proto_l2 {
+    IPFIX_PROTO_L2_ETH = 0,  /* No VLAN. */
+    IPFIX_PROTO_L2_VLAN,
+    NUM_IPFIX_PROTO_L2
+};
+enum ipfix_proto_l3 {
+    IPFIX_PROTO_L3_UNKNOWN = 0,
+    IPFIX_PROTO_L3_IPV4,
+    IPFIX_PROTO_L3_IPV6,
+    NUM_IPFIX_PROTO_L3
+};
+enum ipfix_proto_l4 {
+    IPFIX_PROTO_L4_UNKNOWN = 0,
+    IPFIX_PROTO_L4_TCP_UDP,
+    NUM_IPFIX_PROTO_L4
+};
+
+/* Any Template ID > 255 is usable for Template Records. */
+#define IPFIX_TEMPLATE_ID_MIN 256
+
+/* Cf. IETF RFC 5101 Section 3.4.1. */
+struct ipfix_template_record_header {
+    ovs_be16 template_id;
+    ovs_be16 field_count;
+} __attribute__((packed));
+BUILD_ASSERT_DECL(sizeof(struct ipfix_template_record_header) == 4);
+
+enum ipfix_entity_id {
+#define IPFIX_ENTITY(ENUM, ID, SIZE, NAME)  IPFIX_ENTITY_ID_##ENUM = ID,
+#include "ofproto/ipfix-entities.def"
+};
+
+enum ipfix_entity_size {
+#define IPFIX_ENTITY(ENUM, ID, SIZE, NAME)  IPFIX_ENTITY_SIZE_##ENUM = SIZE,
+#include "ofproto/ipfix-entities.def"
+};
+
+struct ipfix_template_field_specifier {
+    ovs_be16 element_id;  /* IPFIX_ENTITY_ID_*. */
+    ovs_be16 field_length;  /* Length of the field's value, in bytes. */
+    /* No Enterprise ID, since only standard element IDs are specified. */
+} __attribute__((packed));
+BUILD_ASSERT_DECL(sizeof(struct ipfix_template_field_specifier) == 4);
+
+/* Part of data record for common metadata and Ethernet entities. */
+struct ipfix_data_record_common {
+    ovs_be32 observation_point_id;  /* OBSERVATION_POINT_ID */
+    ovs_be64 packet_delta_count;  /* PACKET_DELTA_COUNT */
+    ovs_be64 layer2_octet_delta_count;  /* LAYER2_OCTET_DELTA_COUNT */
+    uint8_t source_mac_address[6];  /* SOURCE_MAC_ADDRESS */
+    uint8_t destination_mac_address[6];  /* DESTINATION_MAC_ADDRESS */
+    ovs_be16 ethernet_type;  /* ETHERNET_TYPE */
+    ovs_be16 ethernet_total_length;  /* ETHERNET_TOTAL_LENGTH */
+    uint8_t ethernet_header_length;  /* ETHERNET_HEADER_LENGTH */
+} __attribute__((packed));
+BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_common) == 37);
+
+/* Part of data record for VLAN entities. */
+struct ipfix_data_record_vlan {
+    ovs_be16 vlan_id;  /* VLAN_ID */
+    ovs_be16 dot1q_vlan_id;  /* DOT1Q_VLAN_ID */
+    uint8_t dot1q_priority;  /* DOT1Q_PRIORITY */
+} __attribute__((packed));
+BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_vlan) == 5);
+
+/* Part of data record for IP entities. */
+struct ipfix_data_record_ip {
+    uint8_t ip_version;  /* IP_VERSION */
+    uint8_t ip_ttl;  /* IP_TTL */
+    uint8_t protocol_identifier;  /* PROTOCOL_IDENTIFIER */
+    uint8_t ip_diff_serv_code_point;  /* IP_DIFF_SERV_CODE_POINT */
+    uint8_t ip_precedence;  /* IP_PRECEDENCE */
+    uint8_t ip_class_of_service;  /* IP_CLASS_OF_SERVICE */
+} __attribute__((packed));
+BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_ip) == 6);
+
+/* Part of data record for IPv4 entities. */
+struct ipfix_data_record_ipv4 {
+    ovs_be32 source_ipv4_address;  /* SOURCE_IPV4_ADDRESS */
+    ovs_be32 destination_ipv4_address;  /* DESTINATION_IPV4_ADDRESS */
+} __attribute__((packed));
+BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_ipv4) == 8);
+
+/* Part of data record for IPv4 entities. */
+struct ipfix_data_record_ipv6 {
+    uint8_t source_ipv6_address[16];  /* SOURCE_IPV6_ADDRESS */
+    uint8_t destination_ipv6_address[16];  /* DESTINATION_IPV6_ADDRESS */
+    ovs_be32 flow_label_ipv6;  /* FLOW_LABEL_IPV6 */
+} __attribute__((packed));
+BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_ipv6) == 36);
+
+/* Part of data record for TCP/UDP entities. */
+struct ipfix_data_record_tcpudp {
+    ovs_be16 source_transport_port;  /* SOURCE_TRANSPORT_PORT */
+    ovs_be16 destination_transport_port;  /* DESTINATION_TRANSPORT_PORT */
+} __attribute__((packed));
+BUILD_ASSERT_DECL(sizeof(struct ipfix_data_record_tcpudp) == 4);
+
+static bool
+ofproto_ipfix_bridge_exporter_options_equal(
+    const struct ofproto_ipfix_bridge_exporter_options *a,
+    const struct ofproto_ipfix_bridge_exporter_options *b)
+{
+    return (a->obs_domain_id == b->obs_domain_id
+            && a->obs_point_id == b->obs_point_id
+            && a->sampling_rate == b->sampling_rate
+            && sset_equals(&a->targets, &b->targets));
+}
+
+static struct ofproto_ipfix_bridge_exporter_options *
+ofproto_ipfix_bridge_exporter_options_clone(
+    const struct ofproto_ipfix_bridge_exporter_options *old)
+{
+    struct ofproto_ipfix_bridge_exporter_options *new =
+        xmemdup(old, sizeof *old);
+    sset_clone(&new->targets, &old->targets);
+    return new;
+}
+
+static void
+ofproto_ipfix_bridge_exporter_options_destroy(
+    struct ofproto_ipfix_bridge_exporter_options *options)
+{
+    if (options) {
+        sset_destroy(&options->targets);
+        free(options);
+    }
+}
+
+static bool
+ofproto_ipfix_flow_exporter_options_equal(
+    const struct ofproto_ipfix_flow_exporter_options *a,
+    const struct ofproto_ipfix_flow_exporter_options *b)
+{
+    return (a->collector_set_id == b->collector_set_id
+            && sset_equals(&a->targets, &b->targets));
+}
+
+static struct ofproto_ipfix_flow_exporter_options *
+ofproto_ipfix_flow_exporter_options_clone(
+    const struct ofproto_ipfix_flow_exporter_options *old)
+{
+    struct ofproto_ipfix_flow_exporter_options *new =
+        xmemdup(old, sizeof *old);
+    sset_clone(&new->targets, &old->targets);
+    return new;
+}
+
+static void
+ofproto_ipfix_flow_exporter_options_destroy(
+    struct ofproto_ipfix_flow_exporter_options *options)
+{
+    if (options) {
+        sset_destroy(&options->targets);
+        free(options);
+    }
+}
+
+static void
+dpif_ipfix_exporter_clear(struct dpif_ipfix_exporter *exporter)
+{
+    collectors_destroy(exporter->collectors);
+    exporter->collectors = NULL;
+    exporter->seq_number = 1;
+    exporter->last_template_set_time = TIME_MIN;
+}
+
+static bool
+dpif_ipfix_exporter_set_options(struct dpif_ipfix_exporter *exporter,
+                                const struct sset *targets)
+{
+    collectors_destroy(exporter->collectors);
+    collectors_create(targets, IPFIX_DEFAULT_COLLECTOR_PORT,
+                      &exporter->collectors);
+    if (exporter->collectors == NULL) {
+        VLOG_WARN_RL(&rl, "no collectors could be initialized, "
+                     "IPFIX exporter disabled");
+        dpif_ipfix_exporter_clear(exporter);
+        return false;
+    }
+    return true;
+}
+
+static void
+dpif_ipfix_bridge_exporter_clear(struct dpif_ipfix_bridge_exporter *exporter)
+{
+    dpif_ipfix_exporter_clear(&exporter->exporter);
+    ofproto_ipfix_bridge_exporter_options_destroy(exporter->options);
+    exporter->options = NULL;
+    exporter->probability = 0;
+}
+
+static void
+dpif_ipfix_bridge_exporter_set_options(
+    struct dpif_ipfix_bridge_exporter *exporter,
+    const struct ofproto_ipfix_bridge_exporter_options *options)
+{
+    bool options_changed;
+
+    if (!options || sset_is_empty(&options->targets)) {
+        /* No point in doing any work if there are no targets. */
+        dpif_ipfix_bridge_exporter_clear(exporter);
+        return;
+    }
+
+    options_changed = (
+        !exporter->options
+        || !ofproto_ipfix_bridge_exporter_options_equal(
+            options, exporter->options));
+
+    /* Configure collectors if options have changed or if we're
+     * shortchanged in collectors (which indicates that opening one or
+     * more of the configured collectors failed, so that we should
+     * retry). */
+    if (options_changed
+        || collectors_count(exporter->exporter.collectors)
+            < sset_count(&options->targets)) {
+        if (!dpif_ipfix_exporter_set_options(&exporter->exporter,
+                                             &options->targets)) {
+            return;
+        }
+    }
+
+    /* Avoid reconfiguring if options didn't change. */
+    if (!options_changed) {
+        return;
+    }
+
+    ofproto_ipfix_bridge_exporter_options_destroy(exporter->options);
+    exporter->options = ofproto_ipfix_bridge_exporter_options_clone(options);
+    exporter->probability =
+        MAX(1, UINT32_MAX / exporter->options->sampling_rate);
+}
+
+static struct dpif_ipfix_flow_exporter_map_node*
+dpif_ipfix_find_flow_exporter_map_node(
+    const struct dpif_ipfix *di, const uint32_t collector_set_id)
+{
+    struct dpif_ipfix_flow_exporter_map_node *exporter_node;
+
+    HMAP_FOR_EACH_WITH_HASH (exporter_node, node,
+                             hash_int(collector_set_id, 0),
+                             &di->flow_exporter_map) {
+        if (exporter_node->exporter.options->collector_set_id
+            == collector_set_id) {
+            return exporter_node;
+        }
+    }
+
+    return NULL;
+}
+
+static void
+dpif_ipfix_flow_exporter_clear(struct dpif_ipfix_flow_exporter *exporter)
+{
+    dpif_ipfix_exporter_clear(&exporter->exporter);
+    ofproto_ipfix_flow_exporter_options_destroy(exporter->options);
+    exporter->options = NULL;
+}
+
+static bool
+dpif_ipfix_flow_exporter_set_options(
+    struct dpif_ipfix_flow_exporter *exporter,
+    const struct ofproto_ipfix_flow_exporter_options *options)
+{
+    bool options_changed;
+
+    if (sset_is_empty(&options->targets)) {
+        /* No point in doing any work if there are no targets. */
+        dpif_ipfix_flow_exporter_clear(exporter);
+        return true;
+    }
+
+    options_changed = (
+        !exporter->options
+        || !ofproto_ipfix_flow_exporter_options_equal(
+            options, exporter->options));
+
+    /* Configure collectors if options have changed or if we're
+     * shortchanged in collectors (which indicates that opening one or
+     * more of the configured collectors failed, so that we should
+     * retry). */
+    if (options_changed
+        || collectors_count(exporter->exporter.collectors)
+            < sset_count(&options->targets)) {
+        if (!dpif_ipfix_exporter_set_options(&exporter->exporter,
+                                             &options->targets)) {
+            return false;
+        }
+    }
+
+    /* Avoid reconfiguring if options didn't change. */
+    if (!options_changed) {
+        return true;
+    }
+
+    ofproto_ipfix_flow_exporter_options_destroy(exporter->options);
+    exporter->options = ofproto_ipfix_flow_exporter_options_clone(options);
+
+    return true;
+}
+
+void
+dpif_ipfix_set_options(
+    struct dpif_ipfix *di,
+    const struct ofproto_ipfix_bridge_exporter_options *bridge_exporter_options,
+    const struct ofproto_ipfix_flow_exporter_options *flow_exporters_options,
+    size_t n_flow_exporters_options)
+{
+    int i;
+    struct ofproto_ipfix_flow_exporter_options *options;
+    struct dpif_ipfix_flow_exporter_map_node *node, *next;
+    size_t n_broken_flow_exporters_options = 0;
+
+    dpif_ipfix_bridge_exporter_set_options(&di->bridge_exporter,
+                                           bridge_exporter_options);
+
+    /* Add new flow exporters and update current flow exporters. */
+    options = (struct ofproto_ipfix_flow_exporter_options *)
+        flow_exporters_options;
+    for (i = 0; i < n_flow_exporters_options; i++) {
+        node = dpif_ipfix_find_flow_exporter_map_node(
+            di, options->collector_set_id);
+        if (!node) {
+            node = xzalloc(sizeof *node);
+            dpif_ipfix_exporter_clear(&node->exporter.exporter);
+            hmap_insert(&di->flow_exporter_map, &node->node,
+                        hash_int(options->collector_set_id, 0));
+        }
+        if (!dpif_ipfix_flow_exporter_set_options(&node->exporter, options)) {
+            n_broken_flow_exporters_options++;
+        }
+        options++;
+    }
+
+    ovs_assert(hmap_count(&di->flow_exporter_map) >=
+               (n_flow_exporters_options - n_broken_flow_exporters_options));
+
+    /* Remove dropped flow exporters, if any needs to be removed. */
+    if (hmap_count(&di->flow_exporter_map) > n_flow_exporters_options) {
+        HMAP_FOR_EACH_SAFE (node, next, node, &di->flow_exporter_map) {
+            /* This is slow but doesn't take any extra memory, and
+             * this table is not supposed to contain many rows anyway. */
+            options = (struct ofproto_ipfix_flow_exporter_options *)
+                flow_exporters_options;
+            for (i = 0; i < n_flow_exporters_options; i++) {
+              if (node->exporter.options->collector_set_id
+                  == options->collector_set_id) {
+                  break;
+              }
+              options++;
+            }
+            if (i == n_flow_exporters_options) {  // Not found.
+                hmap_remove(&di->flow_exporter_map, &node->node);
+                dpif_ipfix_flow_exporter_clear(&node->exporter);
+                free(node);
+            }
+        }
+    }
+
+    ovs_assert(hmap_count(&di->flow_exporter_map) ==
+               (n_flow_exporters_options - n_broken_flow_exporters_options));
+}
+
+struct dpif_ipfix *
+dpif_ipfix_create(void)
+{
+    struct dpif_ipfix *di;
+    di = xzalloc(sizeof *di);
+    dpif_ipfix_exporter_clear(&di->bridge_exporter.exporter);
+    hmap_init(&di->flow_exporter_map);
+    return di;
+}
+
+uint32_t
+dpif_ipfix_get_bridge_exporter_probability(const struct dpif_ipfix *di)
+{
+    return di->bridge_exporter.probability;
+}
+
+static void
+dpif_ipfix_clear(struct dpif_ipfix *di)
+{
+    struct dpif_ipfix_flow_exporter_map_node *node, *next;
+
+    dpif_ipfix_bridge_exporter_clear(&di->bridge_exporter);
+
+    HMAP_FOR_EACH_SAFE (node, next, node, &di->flow_exporter_map) {
+        hmap_remove(&di->flow_exporter_map, &node->node);
+        dpif_ipfix_flow_exporter_clear(&node->exporter);
+        free(node);
+    }
+}
+
+void
+dpif_ipfix_destroy(struct dpif_ipfix *di)
+{
+    if (di) {
+        dpif_ipfix_clear(di);
+        hmap_destroy(&di->flow_exporter_map);
+        free(di);
+    }
+}
+
+static void
+ipfix_init_header(uint32_t seq_number, uint32_t obs_domain_id,
+                  struct ofpbuf *msg)
+{
+    struct ipfix_header *hdr;
+
+    hdr = ofpbuf_put_zeros(msg, sizeof *hdr);
+    hdr->version = htons(IPFIX_VERSION);
+    hdr->length = htons(sizeof *hdr);  /* Updated in ipfix_send_msg. */
+    hdr->export_time = htonl(time_wall());
+    hdr->seq_number = htonl(seq_number);
+    hdr->obs_domain_id = htonl(obs_domain_id);
+}
+
+static void
+ipfix_send_msg(const struct collectors *collectors, struct ofpbuf *msg)
+{
+    struct ipfix_header *hdr;
+
+    /* Adjust the length in the header. */
+    hdr = msg->data;
+    hdr->length = htons(msg->size);
+
+    collectors_send(collectors, msg->data, msg->size);
+    msg->size = 0;
+}
+
+static uint16_t
+ipfix_get_template_id(enum ipfix_proto_l2 l2, enum ipfix_proto_l3 l3,
+                      enum ipfix_proto_l4 l4)
+{
+    uint16_t template_id;
+    template_id = l2;
+    template_id = template_id * NUM_IPFIX_PROTO_L3 + l3;
+    template_id = template_id * NUM_IPFIX_PROTO_L4 + l4;
+    return IPFIX_TEMPLATE_ID_MIN + template_id;
+}
+
+static void
+ipfix_define_template_entity(enum ipfix_entity_id id,
+                             enum ipfix_entity_size size, struct ofpbuf *msg)
+{
+    struct ipfix_template_field_specifier *field;
+
+    field = ofpbuf_put_zeros(msg, sizeof *field);
+    field->element_id = htons(id);
+    field->field_length = htons(size);
+}
+
+static uint16_t
+ipfix_define_template_fields(enum ipfix_proto_l2 l2, enum ipfix_proto_l3 l3,
+                             enum ipfix_proto_l4 l4, struct ofpbuf *msg)
+{
+    uint16_t count = 0;
+
+#define DEF(ID) \
+    { \
+        ipfix_define_template_entity(IPFIX_ENTITY_ID_##ID, \
+                                     IPFIX_ENTITY_SIZE_##ID, msg); \
+        count++; \
+    }
+
+    DEF(OBSERVATION_POINT_ID);
+    DEF(PACKET_DELTA_COUNT);
+    DEF(LAYER2_OCTET_DELTA_COUNT);
+
+    /* Common Ethernet entities. */
+    DEF(SOURCE_MAC_ADDRESS);
+    DEF(DESTINATION_MAC_ADDRESS);
+    DEF(ETHERNET_TYPE);
+    DEF(ETHERNET_TOTAL_LENGTH);
+    DEF(ETHERNET_HEADER_LENGTH);
+
+    if (l2 == IPFIX_PROTO_L2_VLAN) {
+        DEF(VLAN_ID);
+        DEF(DOT1Q_VLAN_ID);
+        DEF(DOT1Q_PRIORITY);
+    }
+
+    if (l3 != IPFIX_PROTO_L3_UNKNOWN) {
+        DEF(IP_VERSION);
+        DEF(IP_TTL);
+        DEF(PROTOCOL_IDENTIFIER);
+        DEF(IP_DIFF_SERV_CODE_POINT);
+        DEF(IP_PRECEDENCE);
+        DEF(IP_CLASS_OF_SERVICE);
+
+        if (l3 == IPFIX_PROTO_L3_IPV4) {
+            DEF(SOURCE_IPV4_ADDRESS);
+            DEF(DESTINATION_IPV4_ADDRESS);
+        } else {  /* l3 == IPFIX_PROTO_L3_IPV6 */
+            DEF(SOURCE_IPV6_ADDRESS);
+            DEF(DESTINATION_IPV6_ADDRESS);
+            DEF(FLOW_LABEL_IPV6);
+        }
+    }
+
+    if (l4 != IPFIX_PROTO_L4_UNKNOWN) {
+        DEF(SOURCE_TRANSPORT_PORT);
+        DEF(DESTINATION_TRANSPORT_PORT);
+    }
+
+#undef DEF
+
+    return count;
+}
+
+static void
+ipfix_send_template_msg(struct dpif_ipfix_exporter *exporter,
+                        uint32_t obs_domain_id)
+{
+    uint64_t msg_stub[DIV_ROUND_UP(1500, 8)];
+    struct ofpbuf msg;
+    size_t set_hdr_offset, tmpl_hdr_offset;
+    struct ipfix_set_header *set_hdr;
+    struct ipfix_template_record_header *tmpl_hdr;
+    uint16_t field_count;
+    enum ipfix_proto_l2 l2;
+    enum ipfix_proto_l3 l3;
+    enum ipfix_proto_l4 l4;
+
+    ofpbuf_use_stub(&msg, msg_stub, sizeof msg_stub);
+
+    ipfix_init_header(exporter->seq_number, obs_domain_id, &msg);
+    set_hdr_offset = msg.size;
+
+    /* Add a Template Set. */
+    set_hdr = ofpbuf_put_zeros(&msg, sizeof *set_hdr);
+    set_hdr->set_id = htons(IPFIX_SET_ID_TEMPLATE);
+
+    /* Define one template for each possible combination of
+     * protocols. */
+    for (l2 = 0; l2 < NUM_IPFIX_PROTO_L2; l2++) {
+        for (l3 = 0; l3 < NUM_IPFIX_PROTO_L3; l3++) {
+            for (l4 = 0; l4 < NUM_IPFIX_PROTO_L4; l4++) {
+                if (l3 == IPFIX_PROTO_L3_UNKNOWN &&
+                    l4 != IPFIX_PROTO_L4_UNKNOWN) {
+                    continue;
+                }
+                tmpl_hdr_offset = msg.size;
+                tmpl_hdr = ofpbuf_put_zeros(&msg, sizeof *tmpl_hdr);
+                tmpl_hdr->template_id = htons(
+                    ipfix_get_template_id(l2, l3, l4));
+                field_count = ipfix_define_template_fields(l2, l3, l4, &msg);
+                tmpl_hdr = (struct ipfix_template_record_header*)
+                    ((uint8_t*)msg.data + tmpl_hdr_offset);
+                tmpl_hdr->field_count = htons(field_count);
+            }
+        }
+    }
+
+    set_hdr = (struct ipfix_set_header*)((uint8_t*)msg.data + set_hdr_offset);
+    set_hdr->length = htons(msg.size - set_hdr_offset);
+
+    /* TODO: Add Options Template Sets, at least to define a Flow Keys
+     * Option Template. */
+
+    ipfix_send_msg(exporter->collectors, &msg);
+
+    ofpbuf_uninit(&msg);
+}
+
+static void
+ipfix_send_data_msg(struct dpif_ipfix_exporter *exporter, struct ofpbuf *packet,
+                    const struct flow *flow, uint64_t packet_delta_count,
+                    uint32_t obs_domain_id, uint32_t obs_point_id)
+{
+    uint64_t msg_stub[DIV_ROUND_UP(1500, 8)];
+    struct ofpbuf msg;
+    size_t set_hdr_offset;
+    struct ipfix_set_header *set_hdr;
+    enum ipfix_proto_l2 l2;
+    enum ipfix_proto_l3 l3;
+    enum ipfix_proto_l4 l4;
+
+    ofpbuf_use_stub(&msg, msg_stub, sizeof msg_stub);
+
+    ipfix_init_header(exporter->seq_number, obs_domain_id, &msg);
+    exporter->seq_number++;
+    set_hdr_offset = msg.size;
+
+    /* Choose the right template ID matching the protocols in the
+     * sampled packet. */
+    l2 = (flow->vlan_tci == 0) ? IPFIX_PROTO_L2_ETH : IPFIX_PROTO_L2_VLAN;
+
+    switch(ntohs(flow->dl_type)) {
+    case ETH_TYPE_IP:
+        l3 = IPFIX_PROTO_L3_IPV4;
+        break;
+    case ETH_TYPE_IPV6:
+        l3 = IPFIX_PROTO_L3_IPV6;
+        break;
+    default:
+        l3 = IPFIX_PROTO_L3_UNKNOWN;
+    }
+
+    l4 = IPFIX_PROTO_L4_UNKNOWN;
+    if (l3 != IPFIX_PROTO_L3_UNKNOWN) {
+        switch(flow->nw_proto) {
+        case IPPROTO_TCP:  /* TCP */
+        case IPPROTO_UDP:  /* UDP */
+            l4 = IPFIX_PROTO_L4_TCP_UDP;
+            break;
+        }
+    }
+
+    /* Add a Data Set. */
+    set_hdr = ofpbuf_put_zeros(&msg, sizeof *set_hdr);
+    set_hdr->set_id = htons(ipfix_get_template_id(l2, l3, l4));
+
+    /* The fields defined in the ipfix_data_record_* structs and sent
+     * below must match exactly the templates defined in
+     * ipfix_define_template_fields. */
+
+    /* Common Ethernet entities. */
+    {
+        struct ipfix_data_record_common *data_common;
+        uint16_t ethernet_total_length;
+        uint8_t ethernet_header_length;
+        uint64_t layer2_octet_delta_count;
+
+        ethernet_total_length = packet->size;
+        ethernet_header_length = (l2 == IPFIX_PROTO_L2_VLAN)
+            ? VLAN_ETH_HEADER_LEN : ETH_HEADER_LEN;
+
+        /* Calculate the total matched octet count by considering as
+         * an approximation that all matched packets have the same
+         * length. */
+        layer2_octet_delta_count = packet_delta_count * ethernet_total_length;
+
+        data_common = ofpbuf_put_zeros(&msg, sizeof *data_common);
+        data_common->observation_point_id = htonl(obs_point_id);
+        data_common->packet_delta_count = htonll(packet_delta_count);
+        data_common->layer2_octet_delta_count =
+            htonll(layer2_octet_delta_count);
+        memcpy(data_common->source_mac_address, flow->dl_src,
+               sizeof flow->dl_src);
+        memcpy(data_common->destination_mac_address, flow->dl_dst,
+               sizeof flow->dl_dst);
+        data_common->ethernet_type = flow->dl_type;
+        data_common->ethernet_total_length = htons(ethernet_total_length);
+        data_common->ethernet_header_length = ethernet_header_length;
+    }
+
+    if (l2 == IPFIX_PROTO_L2_VLAN) {
+        struct ipfix_data_record_vlan *data_vlan;
+        uint16_t vlan_id = vlan_tci_to_vid(flow->vlan_tci);
+        uint8_t priority = vlan_tci_to_pcp(flow->vlan_tci);
+
+        data_vlan = ofpbuf_put_zeros(&msg, sizeof *data_vlan);
+        data_vlan->vlan_id = htons(vlan_id);
+        data_vlan->dot1q_vlan_id = htons(vlan_id);
+        data_vlan->dot1q_priority = priority;
+    }
+
+    if (l3 != IPFIX_PROTO_L3_UNKNOWN) {
+        struct ipfix_data_record_ip *data_ip;
+
+        data_ip = ofpbuf_put_zeros(&msg, sizeof *data_ip);
+        data_ip->ip_version = (l3 == IPFIX_PROTO_L3_IPV4) ? 4 : 6;
+        data_ip->ip_ttl = flow->nw_ttl;
+        data_ip->protocol_identifier = flow->nw_proto;
+        data_ip->ip_diff_serv_code_point = flow->nw_tos >> 2;
+        data_ip->ip_precedence = flow->nw_tos >> 5;
+        data_ip->ip_class_of_service = flow->nw_tos;
+
+        if (l3 == IPFIX_PROTO_L3_IPV4) {
+            struct ipfix_data_record_ipv4 *data_ipv4;
+            data_ipv4 = ofpbuf_put_zeros(&msg, sizeof *data_ipv4);
+            data_ipv4->source_ipv4_address = flow->nw_src;
+            data_ipv4->destination_ipv4_address = flow->nw_dst;
+        } else {  /* l3 == IPFIX_PROTO_L3_IPV6 */
+            struct ipfix_data_record_ipv6 *data_ipv6;
+
+            data_ipv6 = ofpbuf_put_zeros(&msg, sizeof *data_ipv6);
+            memcpy(data_ipv6->source_ipv6_address, &flow->ipv6_src,
+                   sizeof flow->ipv6_src);
+            memcpy(data_ipv6->destination_ipv6_address, &flow->ipv6_dst,
+                   sizeof flow->ipv6_dst);
+            data_ipv6->flow_label_ipv6 = flow->ipv6_label;
+        }
+    }
+
+    if (l4 != IPFIX_PROTO_L4_UNKNOWN) {
+        struct ipfix_data_record_tcpudp *data_tcpudp;
+
+        data_tcpudp = ofpbuf_put_zeros(&msg, sizeof *data_tcpudp);
+        data_tcpudp->source_transport_port = flow->tp_src;
+        data_tcpudp->destination_transport_port = flow->tp_dst;
+    }
+
+    set_hdr = (struct ipfix_set_header*)((uint8_t*)msg.data + set_hdr_offset);
+    set_hdr->length = htons(msg.size - set_hdr_offset);
+
+    ipfix_send_msg(exporter->collectors, &msg);
+
+    ofpbuf_uninit(&msg);
+}
+
+static void
+dpif_ipfix_sample(struct dpif_ipfix_exporter *exporter,
+                  struct ofpbuf *packet, const struct flow *flow,
+                  uint64_t packet_delta_count, uint32_t obs_domain_id,
+                  uint32_t obs_point_id)
+{
+    time_t now = time_wall();
+    if ((exporter->last_template_set_time + IPFIX_TEMPLATE_INTERVAL) <= now) {
+        ipfix_send_template_msg(exporter, obs_domain_id);
+        exporter->last_template_set_time = now;
+    }
+
+    ipfix_send_data_msg(exporter, packet, flow, packet_delta_count,
+                        obs_domain_id, obs_point_id);
+}
+
+void
+dpif_ipfix_bridge_sample(struct dpif_ipfix *di, struct ofpbuf *packet,
+                         const struct flow *flow)
+{
+    /* Use the sampling probability as an approximation of the number
+     * of matched packets. */
+    uint64_t packet_delta_count = UINT32_MAX / di->bridge_exporter.probability;
+
+    dpif_ipfix_sample(&di->bridge_exporter.exporter, packet, flow,
+                      packet_delta_count,
+                      di->bridge_exporter.options->obs_domain_id,
+                      di->bridge_exporter.options->obs_point_id);
+}
+
+void
+dpif_ipfix_flow_sample(struct dpif_ipfix *di, struct ofpbuf *packet,
+                       const struct flow *flow, uint32_t collector_set_id,
+                       uint16_t probability, uint32_t obs_domain_id,
+                       uint32_t obs_point_id)
+{
+    struct dpif_ipfix_flow_exporter_map_node *node;
+    /* Use the sampling probability as an approximation of the number
+     * of matched packets. */
+    uint64_t packet_delta_count = USHRT_MAX / probability;
+
+    node = dpif_ipfix_find_flow_exporter_map_node(di, collector_set_id);
+
+    if (!node) {
+        return;
+    }
+
+    dpif_ipfix_sample(&node->exporter.exporter, packet, flow,
+                      packet_delta_count, obs_domain_id, obs_point_id);
+}
diff --git a/ofproto/ofproto-dpif-ipfix.h b/ofproto/ofproto-dpif-ipfix.h
new file mode 100644 (file)
index 0000000..26b02f1
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OFPROTO_DPIF_IPFIX_H
+#define OFPROTO_DPIF_IPFIX_H 1
+
+#include <stddef.h>
+#include <stdint.h>
+
+struct flow;
+struct ofpbuf;
+struct ofproto_ipfix_bridge_exporter_options;
+struct ofproto_ipfix_flow_exporter_options;
+
+struct dpif_ipfix *dpif_ipfix_create(void);
+uint32_t dpif_ipfix_get_bridge_exporter_probability(const struct dpif_ipfix *);
+void dpif_ipfix_destroy(struct dpif_ipfix *);
+void dpif_ipfix_set_options(
+    struct dpif_ipfix *,
+    const struct ofproto_ipfix_bridge_exporter_options *,
+    const struct ofproto_ipfix_flow_exporter_options *, size_t);
+
+void dpif_ipfix_bridge_sample(struct dpif_ipfix *, struct ofpbuf *,
+                              const struct flow *);
+void dpif_ipfix_flow_sample(struct dpif_ipfix *, struct ofpbuf *,
+                            const struct flow *, uint32_t, uint16_t, uint32_t,
+                            uint32_t);
+
+#endif /* ofproto/ofproto-dpif-ipfix.h */
index 69362ab..9ad0eaf 100644 (file)
@@ -341,39 +341,32 @@ dpif_sflow_add_poller(struct dpif_sflow *ds, struct dpif_sflow_port *dsp)
     sfl_poller_set_bridgePort(poller, dsp->odp_port);
 }
 
-static void
-dpif_sflow_add_sampler(struct dpif_sflow *ds, struct dpif_sflow_port *dsp)
-{
-    SFLSampler *sampler = sfl_agent_addSampler(ds->sflow_agent, &dsp->dsi);
-    sfl_sampler_set_sFlowFsPacketSamplingRate(sampler, ds->options->sampling_rate);
-    sfl_sampler_set_sFlowFsMaximumHeaderSize(sampler, ds->options->header_len);
-    sfl_sampler_set_sFlowFsReceiver(sampler, RECEIVER_INDEX);
-}
-
 void
 dpif_sflow_add_port(struct dpif_sflow *ds, struct ofport *ofport,
                     uint32_t odp_port)
 {
     struct dpif_sflow_port *dsp;
-    uint32_t ifindex;
+    int ifindex;
 
     dpif_sflow_del_port(ds, odp_port);
 
-    /* Add to table of ports. */
-    dsp = xmalloc(sizeof *dsp);
     ifindex = netdev_get_ifindex(ofport->netdev);
+
     if (ifindex <= 0) {
-        ifindex = (ds->sflow_agent->subId << 16) + odp_port;
+        /* Not an ifindex port, so do not add a cross-reference to it here */
+        return;
     }
+
+    /* Add to table of ports. */
+    dsp = xmalloc(sizeof *dsp);
     dsp->ofport = ofport;
     dsp->odp_port = odp_port;
-    SFL_DS_SET(dsp->dsi, 0, ifindex, 0);
+    SFL_DS_SET(dsp->dsi, SFL_DSCLASS_IFINDEX, ifindex, 0);
     hmap_insert(&ds->ports, &dsp->hmap_node, hash_int(odp_port, 0));
 
-    /* Add poller and sampler. */
+    /* Add poller. */
     if (ds->sflow_agent) {
         dpif_sflow_add_poller(ds, dsp);
-        dpif_sflow_add_sampler(ds, dsp);
     }
 }
 
@@ -406,6 +399,9 @@ dpif_sflow_set_options(struct dpif_sflow *ds,
     SFLReceiver *receiver;
     SFLAddress agentIP;
     time_t now;
+    SFLDataSource_instance dsi;
+    uint32_t dsIndex;
+    SFLSampler *sampler;
 
     if (sset_is_empty(&options->targets) || !options->sampling_rate) {
         /* No point in doing any work if there are no targets or nothing to
@@ -473,10 +469,20 @@ dpif_sflow_set_options(struct dpif_sflow *ds,
     /* Set the sampling_rate down in the datapath. */
     ds->probability = MAX(1, UINT32_MAX / ds->options->sampling_rate);
 
-    /* Add samplers and pollers for the currently known ports. */
+    /* Add a single sampler for the bridge. This appears as a PHYSICAL_ENTITY
+       because it is associated with the hypervisor, and interacts with the server
+       hardware directly.  The sub_id is used to distinguish this sampler from
+       others on other bridges within the same agent. */
+    dsIndex = 1000 + options->sub_id;
+    SFL_DS_SET(dsi, SFL_DSCLASS_PHYSICAL_ENTITY, dsIndex, 0);
+    sampler = sfl_agent_addSampler(ds->sflow_agent, &dsi);
+    sfl_sampler_set_sFlowFsPacketSamplingRate(sampler, ds->options->sampling_rate);
+    sfl_sampler_set_sFlowFsMaximumHeaderSize(sampler, ds->options->header_len);
+    sfl_sampler_set_sFlowFsReceiver(sampler, RECEIVER_INDEX);
+
+    /* Add pollers for the currently known ifindex-ports */
     HMAP_FOR_EACH (dsp, hmap_node, &ds->ports) {
         dpif_sflow_add_poller(ds, dsp);
-        dpif_sflow_add_sampler(ds, dsp);
     }
 }
 
@@ -499,43 +505,35 @@ dpif_sflow_received(struct dpif_sflow *ds, struct ofpbuf *packet,
     SFLFlow_sample_element switchElem;
     SFLSampler *sampler;
     struct dpif_sflow_port *in_dsp;
-    struct netdev_stats stats;
     ovs_be16 vlan_tci;
-    int error;
 
-    /* Build a flow sample */
-    memset(&fs, 0, sizeof fs);
-
-    in_dsp = dpif_sflow_find_port(ds, odp_in_port);
-    if (!in_dsp) {
+    sampler = ds->sflow_agent->samplers;
+    if (!sampler) {
         return;
     }
-    fs.input = SFL_DS_INDEX(in_dsp->dsi);
 
-    error = ofproto_port_get_stats(in_dsp->ofport, &stats);
-    if (error) {
-        VLOG_WARN_RL(&rl, "netdev get-stats error %s", strerror(error));
-        return;
-    }
-    fs.sample_pool = stats.rx_packets;
+    /* Build a flow sample. */
+    memset(&fs, 0, sizeof fs);
 
-    /* We are going to give it to the sampler that represents this input port.
-     * By implementing "ingress-only" sampling like this we ensure that we
-     * never have to offer the same sample to more than one sampler. */
-    sampler = sfl_agent_getSamplerByIfIndex(ds->sflow_agent, fs.input);
-    if (!sampler) {
-        VLOG_WARN_RL(&rl, "no sampler for input ifIndex (%"PRIu32")",
-                     fs.input);
-        return;
+    /* Look up the input ifIndex if this port has one. Otherwise just
+     * leave it as 0 (meaning 'unknown') and continue. */
+    in_dsp = dpif_sflow_find_port(ds, odp_in_port);
+    if (in_dsp) {
+        fs.input = SFL_DS_INDEX(in_dsp->dsi);
     }
 
+    /* Make the assumption that the random number generator in the datapath converges
+     * to the configured mean, and just increment the samplePool by the configured
+     * sampling rate every time. */
+    sampler->samplePool += sfl_sampler_get_sFlowFsPacketSamplingRate(sampler);
+
     /* Sampled header. */
     memset(&hdrElem, 0, sizeof hdrElem);
     hdrElem.tag = SFLFLOW_HEADER;
     header = &hdrElem.flowType.header;
     header->header_protocol = SFLHEADER_ETHERNET_ISO8023;
     /* The frame_length should include the Ethernet FCS (4 bytes),
-       but it has already been stripped,  so we need to add 4 here. */
+     * but it has already been stripped,  so we need to add 4 here. */
     header->frame_length = packet->size + 4;
     /* Ethernet FCS stripped off. */
     header->stripped = 4;
index 47830c1..89a4668 100644 (file)
@@ -46,6 +46,7 @@
 #include "ofp-parse.h"
 #include "ofp-print.h"
 #include "ofproto-dpif-governor.h"
+#include "ofproto-dpif-ipfix.h"
 #include "ofproto-dpif-sflow.h"
 #include "poll-loop.h"
 #include "simap.h"
@@ -325,7 +326,8 @@ static void xlate_table_action(struct action_xlate_ctx *, uint16_t in_port,
 static size_t put_userspace_action(const struct ofproto_dpif *,
                                    struct ofpbuf *odp_actions,
                                    const struct flow *,
-                                   const union user_action_cookie *);
+                                   const union user_action_cookie *,
+                                   const size_t);
 
 static void compose_slow_path(const struct ofproto_dpif *, const struct flow *,
                               enum slow_path_reason,
@@ -695,6 +697,7 @@ struct ofproto_dpif {
     /* Bridging. */
     struct netflow *netflow;
     struct dpif_sflow *sflow;
+    struct dpif_ipfix *ipfix;
     struct hmap bundles;        /* Contains "struct ofbundle"s. */
     struct mac_learning *ml;
     struct ofmirror *mirrors[MAX_MIRRORS];
@@ -820,6 +823,9 @@ static int send_packet(const struct ofport_dpif *, struct ofpbuf *packet);
 static size_t compose_sflow_action(const struct ofproto_dpif *,
                                    struct ofpbuf *odp_actions,
                                    const struct flow *, uint32_t odp_port);
+static void compose_ipfix_action(const struct ofproto_dpif *,
+                                 struct ofpbuf *odp_actions,
+                                 const struct flow *);
 static void add_mirror_actions(struct action_xlate_ctx *ctx,
                                const struct flow *flow);
 /* Global variables. */
@@ -1349,6 +1355,7 @@ construct(struct ofproto *ofproto_)
 
     ofproto->netflow = NULL;
     ofproto->sflow = NULL;
+    ofproto->ipfix = NULL;
     ofproto->stp = NULL;
     hmap_init(&ofproto->bundles);
     ofproto->ml = mac_learning_create(MAC_ENTRY_DEFAULT_IDLE_TIME);
@@ -1782,7 +1789,11 @@ port_construct(struct ofport *port_)
     port->carrier_seq = netdev_get_carrier_resets(netdev);
 
     if (netdev_vport_is_patch(netdev)) {
-        /* XXX By bailing out here, we don't do required sFlow work. */
+        /* By bailing out here, we don't submit the port to the sFlow module
+        * to be considered for counter polling export.  This is correct
+        * because the patch port represents an interface that sFlow considers
+        * to be "internal" to the switch as a whole, and therefore not an
+        * candidate for counter polling. */
         port->odp_port = OVSP_NONE;
         return 0;
     }
@@ -1913,6 +1924,32 @@ set_sflow(struct ofproto *ofproto_,
     return 0;
 }
 
+static int
+set_ipfix(
+    struct ofproto *ofproto_,
+    const struct ofproto_ipfix_bridge_exporter_options *bridge_exporter_options,
+    const struct ofproto_ipfix_flow_exporter_options *flow_exporters_options,
+    size_t n_flow_exporters_options)
+{
+    struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
+    struct dpif_ipfix *di = ofproto->ipfix;
+
+    if (bridge_exporter_options || flow_exporters_options) {
+        if (!di) {
+            di = ofproto->ipfix = dpif_ipfix_create();
+        }
+        dpif_ipfix_set_options(
+            di, bridge_exporter_options, flow_exporters_options,
+            n_flow_exporters_options);
+    } else {
+        if (di) {
+            dpif_ipfix_destroy(di);
+            ofproto->ipfix = NULL;
+        }
+    }
+    return 0;
+}
+
 static int
 set_cfm(struct ofport *ofport_, const struct cfm_settings *s)
 {
@@ -4006,9 +4043,11 @@ handle_miss_upcalls(struct dpif_backer *backer, struct dpif_upcall *upcalls,
     hmap_destroy(&todo);
 }
 
-static enum { SFLOW_UPCALL, MISS_UPCALL, BAD_UPCALL }
+static enum { SFLOW_UPCALL, MISS_UPCALL, BAD_UPCALL, FLOW_SAMPLE_UPCALL,
+              IPFIX_UPCALL }
 classify_upcall(const struct dpif_upcall *upcall)
 {
+    size_t userdata_len;
     union user_action_cookie cookie;
 
     /* First look at the upcall type. */
@@ -4030,23 +4069,30 @@ classify_upcall(const struct dpif_upcall *upcall)
         VLOG_WARN_RL(&rl, "action upcall missing cookie");
         return BAD_UPCALL;
     }
-    if (nl_attr_get_size(upcall->userdata) != sizeof(cookie)) {
+    userdata_len = nl_attr_get_size(upcall->userdata);
+    if (userdata_len < sizeof cookie.type
+        || userdata_len > sizeof cookie) {
         VLOG_WARN_RL(&rl, "action upcall cookie has unexpected size %zu",
-                     nl_attr_get_size(upcall->userdata));
+                     userdata_len);
         return BAD_UPCALL;
     }
-    memcpy(&cookie, nl_attr_get(upcall->userdata), sizeof(cookie));
-    switch (cookie.type) {
-    case USER_ACTION_COOKIE_SFLOW:
+    memset(&cookie, 0, sizeof cookie);
+    memcpy(&cookie, nl_attr_get(upcall->userdata), userdata_len);
+    if (userdata_len == sizeof cookie.sflow
+        && cookie.type == USER_ACTION_COOKIE_SFLOW) {
         return SFLOW_UPCALL;
-
-    case USER_ACTION_COOKIE_SLOW_PATH:
+    } else if (userdata_len == sizeof cookie.slow_path
+               && cookie.type == USER_ACTION_COOKIE_SLOW_PATH) {
         return MISS_UPCALL;
-
-    case USER_ACTION_COOKIE_UNSPEC:
-    default:
-        VLOG_WARN_RL(&rl, "invalid user cookie : 0x%"PRIx64,
-                     nl_attr_get_u64(upcall->userdata));
+    } else if (userdata_len == sizeof cookie.flow_sample
+               && cookie.type == USER_ACTION_COOKIE_FLOW_SAMPLE) {
+        return FLOW_SAMPLE_UPCALL;
+    } else if (userdata_len == sizeof cookie.ipfix
+               && cookie.type == USER_ACTION_COOKIE_IPFIX) {
+        return IPFIX_UPCALL;
+    } else {
+        VLOG_WARN_RL(&rl, "invalid user cookie of type %"PRIu16
+                     " and size %zu", cookie.type, userdata_len);
         return BAD_UPCALL;
     }
 }
@@ -4066,11 +4112,56 @@ handle_sflow_upcall(struct dpif_backer *backer,
         return;
     }
 
-    memcpy(&cookie, nl_attr_get(upcall->userdata), sizeof(cookie));
+    memset(&cookie, 0, sizeof cookie);
+    memcpy(&cookie, nl_attr_get(upcall->userdata), sizeof cookie.sflow);
     dpif_sflow_received(ofproto->sflow, upcall->packet, &flow,
                         odp_in_port, &cookie);
 }
 
+static void
+handle_flow_sample_upcall(struct dpif_backer *backer,
+                          const struct dpif_upcall *upcall)
+{
+    struct ofproto_dpif *ofproto;
+    union user_action_cookie cookie;
+    struct flow flow;
+
+    if (ofproto_receive(backer, upcall->packet, upcall->key, upcall->key_len,
+                        &flow, NULL, &ofproto, NULL, NULL)
+        || !ofproto->ipfix) {
+        return;
+    }
+
+    memset(&cookie, 0, sizeof cookie);
+    memcpy(&cookie, nl_attr_get(upcall->userdata), sizeof cookie.flow_sample);
+
+    /* The flow reflects exactly the contents of the packet.  Sample
+     * the packet using it. */
+    dpif_ipfix_flow_sample(ofproto->ipfix, upcall->packet, &flow,
+                           cookie.flow_sample.collector_set_id,
+                           cookie.flow_sample.probability,
+                           cookie.flow_sample.obs_domain_id,
+                           cookie.flow_sample.obs_point_id);
+}
+
+static void
+handle_ipfix_upcall(struct dpif_backer *backer,
+                    const struct dpif_upcall *upcall)
+{
+    struct ofproto_dpif *ofproto;
+    struct flow flow;
+
+    if (ofproto_receive(backer, upcall->packet, upcall->key, upcall->key_len,
+                        &flow, NULL, &ofproto, NULL, NULL)
+        || !ofproto->ipfix) {
+        return;
+    }
+
+    /* The flow reflects exactly the contents of the packet.  Sample
+     * the packet using it. */
+    dpif_ipfix_bridge_sample(ofproto->ipfix, upcall->packet, &flow);
+}
+
 static int
 handle_upcalls(struct dpif_backer *backer, unsigned int max_batch)
 {
@@ -4108,6 +4199,16 @@ handle_upcalls(struct dpif_backer *backer, unsigned int max_batch)
             ofpbuf_uninit(buf);
             break;
 
+        case FLOW_SAMPLE_UPCALL:
+            handle_flow_sample_upcall(backer, upcall);
+            ofpbuf_uninit(buf);
+            break;
+
+        case IPFIX_UPCALL:
+            handle_ipfix_upcall(backer, upcall);
+            ofpbuf_uninit(buf);
+            break;
+
         case BAD_UPCALL:
             ofpbuf_uninit(buf);
             break;
@@ -4264,13 +4365,13 @@ update_stats(struct dpif_backer *backer)
     const struct dpif_flow_stats *stats;
     struct dpif_flow_dump dump;
     const struct nlattr *key;
+    struct ofproto_dpif *ofproto;
     size_t key_len;
 
     dpif_flow_dump_start(&dump, backer->dpif);
     while (dpif_flow_dump_next(&dump, &key, &key_len, NULL, NULL, &stats)) {
         struct flow flow;
         struct subfacet *subfacet;
-        struct ofproto_dpif *ofproto;
         struct ofport_dpif *ofport;
         uint32_t key_hash;
 
@@ -4281,7 +4382,6 @@ update_stats(struct dpif_backer *backer)
 
         ofproto->total_subfacet_count += hmap_count(&ofproto->subfacets);
         ofproto->n_update_stats++;
-        update_moving_averages(ofproto);
 
         ofport = get_ofp_port(ofproto, flow.in_port);
         if (ofport && ofport->tnl_port) {
@@ -4313,6 +4413,11 @@ update_stats(struct dpif_backer *backer)
         run_fast_rl();
     }
     dpif_flow_dump_done(&dump);
+
+    HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
+        update_moving_averages(ofproto);
+    }
+
 }
 
 /* Calculates and returns the number of milliseconds of idle time after which
@@ -5101,7 +5206,7 @@ facet_push_stats(struct facet *facet)
 }
 
 static void
-push_all_stats(void)
+push_all_stats__(bool run_fast)
 {
     static long long int rl = LLONG_MIN;
     struct ofproto_dpif *ofproto;
@@ -5115,13 +5220,21 @@ push_all_stats(void)
 
         HMAP_FOR_EACH (facet, hmap_node, &ofproto->facets) {
             facet_push_stats(facet);
-            run_fast_rl();
+            if (run_fast) {
+                run_fast_rl();
+            }
         }
     }
 
     rl = time_msec() + 100;
 }
 
+static void
+push_all_stats(void)
+{
+    push_all_stats__(true);
+}
+
 static void
 rule_credit_stats(struct rule_dpif *rule, const struct dpif_flow_stats *stats)
 {
@@ -5604,7 +5717,11 @@ rule_get_stats(struct rule *rule_, uint64_t *packets, uint64_t *bytes)
     struct rule_dpif *rule = rule_dpif_cast(rule_);
     struct facet *facet;
 
-    push_all_stats();
+    /* push_all_stats() can handle flow misses which, when using the learn
+     * action, can cause rules to be added and deleted.  This can corrupt our
+     * caller's datastructures which assume that rule_get_stats() doesn't have
+     * an impact on the flow table. To be safe, we disable miss handling. */
+    push_all_stats__(false);
 
     /* Start from historical data for 'rule' itself that are no longer tracked
      * in facets.  This counts, for example, facets that have expired. */
@@ -5731,6 +5848,7 @@ send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet)
                            ofp_port_to_odp_port(ofproto, flow.in_port));
 
     compose_sflow_action(ofproto, &odp_actions, &flow, odp_port);
+    compose_ipfix_action(ofproto, &odp_actions, &flow);
 
     nl_msg_put_u32(&odp_actions, OVS_ACTION_ATTR_OUTPUT, odp_port);
     error = dpif_execute(ofproto->backer->dpif,
@@ -5780,9 +5898,10 @@ compose_slow_path(const struct ofproto_dpif *ofproto, const struct flow *flow,
     ofpbuf_use_stack(&buf, stub, stub_size);
     if (slow & (SLOW_CFM | SLOW_LACP | SLOW_STP)) {
         uint32_t pid = dpif_port_get_pid(ofproto->backer->dpif, UINT32_MAX);
-        odp_put_userspace_action(pid, &cookie, sizeof cookie, &buf);
+        odp_put_userspace_action(pid, &cookie, sizeof cookie.slow_path, &buf);
     } else {
-        put_userspace_action(ofproto, &buf, flow, &cookie);
+        put_userspace_action(ofproto, &buf, flow, &cookie,
+                             sizeof cookie.slow_path);
     }
     *actionsp = buf.data;
     *actions_lenp = buf.size;
@@ -5792,14 +5911,43 @@ static size_t
 put_userspace_action(const struct ofproto_dpif *ofproto,
                      struct ofpbuf *odp_actions,
                      const struct flow *flow,
-                     const union user_action_cookie *cookie)
+                     const union user_action_cookie *cookie,
+                     const size_t cookie_size)
 {
     uint32_t pid;
 
     pid = dpif_port_get_pid(ofproto->backer->dpif,
                             ofp_port_to_odp_port(ofproto, flow->in_port));
 
-    return odp_put_userspace_action(pid, cookie, sizeof *cookie, odp_actions);
+    return odp_put_userspace_action(pid, cookie, cookie_size, odp_actions);
+}
+
+/* Compose SAMPLE action for sFlow or IPFIX.  The given probability is
+ * the number of packets out of UINT32_MAX to sample.  The given
+ * cookie is passed back in the callback for each sampled packet.
+ */
+static size_t
+compose_sample_action(const struct ofproto_dpif *ofproto,
+                      struct ofpbuf *odp_actions,
+                      const struct flow *flow,
+                      const uint32_t probability,
+                      const union user_action_cookie *cookie,
+                      const size_t cookie_size)
+{
+    size_t sample_offset, actions_offset;
+    int cookie_offset;
+
+    sample_offset = nl_msg_start_nested(odp_actions, OVS_ACTION_ATTR_SAMPLE);
+
+    nl_msg_put_u32(odp_actions, OVS_SAMPLE_ATTR_PROBABILITY, probability);
+
+    actions_offset = nl_msg_start_nested(odp_actions, OVS_SAMPLE_ATTR_ACTIONS);
+    cookie_offset = put_userspace_action(ofproto, odp_actions, flow, cookie,
+                                         cookie_size);
+
+    nl_msg_end_nested(odp_actions, actions_offset);
+    nl_msg_end_nested(odp_actions, sample_offset);
+    return cookie_offset;
 }
 
 static void
@@ -5834,7 +5982,7 @@ compose_sflow_cookie(const struct ofproto_dpif *ofproto,
     }
 }
 
-/* Compose SAMPLE action for sFlow. */
+/* Compose SAMPLE action for sFlow bridge sampling. */
 static size_t
 compose_sflow_action(const struct ofproto_dpif *ofproto,
                      struct ofpbuf *odp_actions,
@@ -5843,32 +5991,60 @@ compose_sflow_action(const struct ofproto_dpif *ofproto,
 {
     uint32_t probability;
     union user_action_cookie cookie;
-    size_t sample_offset, actions_offset;
-    int cookie_offset;
 
     if (!ofproto->sflow || flow->in_port == OFPP_NONE) {
         return 0;
     }
 
-    sample_offset = nl_msg_start_nested(odp_actions, OVS_ACTION_ATTR_SAMPLE);
-
-    /* Number of packets out of UINT_MAX to sample. */
     probability = dpif_sflow_get_probability(ofproto->sflow);
-    nl_msg_put_u32(odp_actions, OVS_SAMPLE_ATTR_PROBABILITY, probability);
-
-    actions_offset = nl_msg_start_nested(odp_actions, OVS_SAMPLE_ATTR_ACTIONS);
     compose_sflow_cookie(ofproto, htons(0), odp_port,
                          odp_port == OVSP_NONE ? 0 : 1, &cookie);
-    cookie_offset = put_userspace_action(ofproto, odp_actions, flow, &cookie);
 
-    nl_msg_end_nested(odp_actions, actions_offset);
-    nl_msg_end_nested(odp_actions, sample_offset);
-    return cookie_offset;
+    return compose_sample_action(ofproto, odp_actions, flow,  probability,
+                                 &cookie, sizeof cookie.sflow);
+}
+
+static void
+compose_flow_sample_cookie(uint16_t probability, uint32_t collector_set_id,
+                           uint32_t obs_domain_id, uint32_t obs_point_id,
+                           union user_action_cookie *cookie)
+{
+    cookie->type = USER_ACTION_COOKIE_FLOW_SAMPLE;
+    cookie->flow_sample.probability = probability;
+    cookie->flow_sample.collector_set_id = collector_set_id;
+    cookie->flow_sample.obs_domain_id = obs_domain_id;
+    cookie->flow_sample.obs_point_id = obs_point_id;
 }
 
-/* SAMPLE action must be first action in any given list of actions.
- * At this point we do not have all information required to build it. So try to
- * build sample action as complete as possible. */
+static void
+compose_ipfix_cookie(union user_action_cookie *cookie)
+{
+    cookie->type = USER_ACTION_COOKIE_IPFIX;
+}
+
+/* Compose SAMPLE action for IPFIX bridge sampling. */
+static void
+compose_ipfix_action(const struct ofproto_dpif *ofproto,
+                     struct ofpbuf *odp_actions,
+                     const struct flow *flow)
+{
+    uint32_t probability;
+    union user_action_cookie cookie;
+
+    if (!ofproto->ipfix || flow->in_port == OFPP_NONE) {
+        return;
+    }
+
+    probability = dpif_ipfix_get_bridge_exporter_probability(ofproto->ipfix);
+    compose_ipfix_cookie(&cookie);
+
+    compose_sample_action(ofproto, odp_actions, flow,  probability,
+                          &cookie, sizeof cookie.ipfix);
+}
+
+/* SAMPLE action for sFlow must be first action in any given list of
+ * actions.  At this point we do not have all information required to
+ * build it. So try to build sample action as complete as possible. */
 static void
 add_sflow_action(struct action_xlate_ctx *ctx)
 {
@@ -5879,6 +6055,14 @@ add_sflow_action(struct action_xlate_ctx *ctx)
     ctx->sflow_n_outputs = 0;
 }
 
+/* SAMPLE action for IPFIX must be 1st or 2nd action in any given list
+ * of actions, eventually after the SAMPLE action for sFlow. */
+static void
+add_ipfix_action(struct action_xlate_ctx *ctx)
+{
+    compose_ipfix_action(ctx->ofproto, ctx->odp_actions, &ctx->flow);
+}
+
 /* Fix SAMPLE action according to data collected while composing ODP actions.
  * We need to fix SAMPLE actions OVS_SAMPLE_ATTR_ACTIONS attribute, i.e. nested
  * USERSPACE action's user-cookie which is required for sflow. */
@@ -5893,7 +6077,7 @@ fix_sflow_action(struct action_xlate_ctx *ctx)
     }
 
     cookie = ofpbuf_at(ctx->odp_actions, ctx->user_cookie_offset,
-                       sizeof(*cookie));
+                       sizeof cookie->sflow);
     ovs_assert(cookie->type == USER_ACTION_COOKIE_SFLOW);
 
     compose_sflow_cookie(ctx->ofproto, base->vlan_tci,
@@ -5905,9 +6089,9 @@ compose_output_action__(struct action_xlate_ctx *ctx, uint16_t ofp_port,
                         bool check_stp)
 {
     const struct ofport_dpif *ofport = get_ofp_port(ctx->ofproto, ofp_port);
-    ovs_be16 flow_vlan_tci = ctx->flow.vlan_tci;
-    ovs_be64 flow_tun_id = ctx->flow.tunnel.tun_id;
-    uint8_t flow_nw_tos = ctx->flow.nw_tos;
+    ovs_be16 flow_vlan_tci;
+    uint32_t flow_skb_mark;
+    uint8_t flow_nw_tos;
     struct priority_to_dscp *pdscp;
     uint32_t out_port, odp_port;
 
@@ -5980,6 +6164,10 @@ compose_output_action__(struct action_xlate_ctx *ctx, uint16_t ofp_port,
         return;
     }
 
+    flow_vlan_tci = ctx->flow.vlan_tci;
+    flow_skb_mark = ctx->flow.skb_mark;
+    flow_nw_tos = ctx->flow.nw_tos;
+
     pdscp = get_priority(ofport, ctx->flow.skb_priority);
     if (pdscp) {
         ctx->flow.nw_tos &= ~IP_DSCP_MASK;
@@ -5987,10 +6175,15 @@ compose_output_action__(struct action_xlate_ctx *ctx, uint16_t ofp_port,
     }
 
     if (ofport->tnl_port) {
+         /* Save tunnel metadata so that changes made due to
+          * the Logical (tunnel) Port are not visible for any further
+          * matches, while explicit set actions on tunnel metadata are.
+          */
+        struct flow_tnl flow_tnl = ctx->flow.tunnel;
         odp_port = tnl_port_send(ofport->tnl_port, &ctx->flow);
         if (odp_port == OVSP_NONE) {
             xlate_report(ctx, "Tunneling decided against output");
-            return;
+            goto out; /* restore flow_nw_tos */
         }
 
         if (ctx->resubmit_stats) {
@@ -5999,6 +6192,7 @@ compose_output_action__(struct action_xlate_ctx *ctx, uint16_t ofp_port,
         out_port = odp_port;
         commit_odp_tunnel_action(&ctx->flow, &ctx->base_flow,
                                  ctx->odp_actions);
+        ctx->flow.tunnel = flow_tnl; /* Restore tunnel metadata */
     } else {
         odp_port = ofport->odp_port;
         out_port = vsp_realdev_to_vlandev(ctx->ofproto, odp_port,
@@ -6014,8 +6208,11 @@ compose_output_action__(struct action_xlate_ctx *ctx, uint16_t ofp_port,
     ctx->sflow_odp_port = odp_port;
     ctx->sflow_n_outputs++;
     ctx->nf_output_iface = ofp_port;
-    ctx->flow.tunnel.tun_id = flow_tun_id;
+
+    /* Restore flow */
     ctx->flow.vlan_tci = flow_vlan_tci;
+    ctx->flow.skb_mark = flow_skb_mark;
+ out:
     ctx->flow.nw_tos = flow_nw_tos;
 }
 
@@ -6431,11 +6628,6 @@ xlate_set_queue_action(struct action_xlate_ctx *ctx, uint32_t queue_id)
     }
 }
 
-struct xlate_reg_state {
-    ovs_be16 vlan_tci;
-    ovs_be64 tun_id;
-};
-
 static bool
 slave_enabled_cb(uint16_t ofp_port, void *ofproto_)
 {
@@ -6516,6 +6708,23 @@ xlate_fin_timeout(struct action_xlate_ctx *ctx,
     }
 }
 
+static void
+xlate_sample_action(struct action_xlate_ctx *ctx,
+                    const struct ofpact_sample *os)
+{
+  union user_action_cookie cookie;
+  /* Scale the probability from 16-bit to 32-bit while representing
+   * the same percentage. */
+  uint32_t probability = (os->probability << 16) | os->probability;
+
+  commit_odp_actions(&ctx->flow, &ctx->base_flow, ctx->odp_actions);
+
+  compose_flow_sample_cookie(os->probability, os->collector_set_id,
+                             os->obs_domain_id, os->obs_point_id, &cookie);
+  compose_sample_action(ctx->ofproto, ctx->odp_actions, &ctx->flow,
+                        probability, &cookie, sizeof cookie.flow_sample);
+}
+
 static bool
 may_receive(const struct ofport_dpif *port, struct action_xlate_ctx *ctx)
 {
@@ -6796,6 +7005,10 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
             }
             break;
         }
+
+        case OFPACT_SAMPLE:
+            xlate_sample_action(ctx, ofpact_get_SAMPLE(a));
+            break;
         }
     }
 
@@ -6930,6 +7143,7 @@ xlate_actions(struct action_xlate_ctx *ctx,
         initial_vals.tunnel_ip_tos = ctx->base_flow.tunnel.ip_tos;
 
         add_sflow_action(ctx);
+        add_ipfix_action(ctx);
 
         if (tunnel_ecn_ok(ctx) && (!in_port || may_receive(in_port, ctx))) {
             do_xlate_actions(ofpacts, ofpacts_len, ctx);
@@ -6939,6 +7153,7 @@ xlate_actions(struct action_xlate_ctx *ctx,
             if (in_port && !stp_forward_in_state(in_port->stp_state)) {
                 ofpbuf_clear(ctx->odp_actions);
                 add_sflow_action(ctx);
+                add_ipfix_action(ctx);
             }
         }
 
@@ -8828,6 +9043,7 @@ const struct ofproto_class ofproto_dpif_class = {
     set_netflow,
     get_netflow_ids,
     set_sflow,
+    set_ipfix,
     set_cfm,
     get_cfm_status,
     set_stp,
index d8db3ae..2f429e0 100644 (file)
@@ -1109,6 +1109,20 @@ struct ofproto_class {
     int (*set_sflow)(struct ofproto *ofproto,
                      const struct ofproto_sflow_options *sflow_options);
 
+    /* Configures IPFIX on 'ofproto' according to the options in
+     * 'bridge_exporter_options' and the 'flow_exporters_options'
+     * array, or turns off IPFIX if 'bridge_exporter_options' and
+     * 'flow_exporters_options' is NULL.
+     *
+     * EOPNOTSUPP as a return value indicates that 'ofproto' does not support
+     * IPFIX, as does a null pointer. */
+    int (*set_ipfix)(
+        struct ofproto *ofproto,
+        const struct ofproto_ipfix_bridge_exporter_options
+            *bridge_exporter_options,
+        const struct ofproto_ipfix_flow_exporter_options
+            *flow_exporters_options, size_t n_flow_exporters_options);
+
     /* Configures connectivity fault management on 'ofport'.
      *
      * If 'cfm_settings' is nonnull, configures CFM according to its members.
index 03ca59b..85fe781 100644 (file)
@@ -640,6 +640,19 @@ ofproto_set_sflow(struct ofproto *ofproto,
         return oso ? EOPNOTSUPP : 0;
     }
 }
+
+int
+ofproto_set_ipfix(struct ofproto *ofproto,
+                  const struct ofproto_ipfix_bridge_exporter_options *bo,
+                  const struct ofproto_ipfix_flow_exporter_options *fo,
+                  size_t n_fo)
+{
+    if (ofproto->ofproto_class->set_ipfix) {
+        return ofproto->ofproto_class->set_ipfix(ofproto, bo, fo, n_fo);
+    } else {
+        return (bo || fo) ? EOPNOTSUPP : 0;
+    }
+}
 \f
 /* Spanning Tree Protocol (STP) configuration. */
 
index b3a55a4..bb799b5 100644 (file)
@@ -68,6 +68,19 @@ struct ofproto_sflow_options {
     char *control_ip;
 };
 
+
+struct ofproto_ipfix_bridge_exporter_options {
+    struct sset targets;
+    uint32_t sampling_rate;
+    uint32_t obs_domain_id;  /* Bridge-wide Observation Domain ID. */
+    uint32_t obs_point_id;  /* Bridge-wide Observation Point ID. */
+};
+
+struct ofproto_ipfix_flow_exporter_options {
+    uint32_t collector_set_id;
+    struct sset targets;
+};
+
 struct ofproto_stp_settings {
     stp_identifier system_id;
     uint16_t priority;
@@ -229,6 +242,10 @@ int ofproto_set_snoops(struct ofproto *, const struct sset *snoops);
 int ofproto_set_netflow(struct ofproto *,
                         const struct netflow_options *nf_options);
 int ofproto_set_sflow(struct ofproto *, const struct ofproto_sflow_options *);
+int ofproto_set_ipfix(struct ofproto *,
+                      const struct ofproto_ipfix_bridge_exporter_options *,
+                      const struct ofproto_ipfix_flow_exporter_options *,
+                      size_t);
 int ofproto_set_stp(struct ofproto *, const struct ofproto_stp_settings *);
 int ofproto_get_stp_status(struct ofproto *, struct ofproto_stp_status *);
 
index 8aa7fbe..8d29184 100644 (file)
@@ -32,7 +32,6 @@
 
 /* XXX:
  *
- * Ability to generate metadata for packet-outs
  * Disallow netdevs with names like "gre64_system" to prevent collisions. */
 
 VLOG_DEFINE_THIS_MODULE(tunnel);
index febc351..9f99d64 100644 (file)
@@ -597,6 +597,10 @@ ovsdb_jsonrpc_session_get_status(const struct ovsdb_jsonrpc_remote *remote,
     struct reconnect_stats rstats;
     struct ds locks_held, locks_waiting, locks_lost;
 
+    status->bound_port = (remote->listener
+                          ? pstream_get_bound_port(remote->listener)
+                          : htons(0));
+
     if (list_is_empty(&remote->sessions)) {
         return false;
     }
index bf2a2fc..f2395fc 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
+/* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
 #define OVSDB_JSONRPC_SERVER_H 1
 
 #include <stdbool.h>
+#include "openvswitch/types.h"
 
 struct ovsdb;
 struct shash;
@@ -50,6 +51,7 @@ struct ovsdb_jsonrpc_remote_status {
     char *locks_waiting;
     char *locks_lost;
     int n_connections;
+    ovs_be16 bound_port;
 };
 bool ovsdb_jsonrpc_server_get_remote_status(
     const struct ovsdb_jsonrpc_server *, const char *target,
index 37bd1aa..53e6bb9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -166,7 +166,7 @@ parse_options(int argc, char *argv[])
         DAEMON_OPTION_ENUMS,
         TABLE_OPTION_ENUMS
     };
-    static struct option long_options[] = {
+    static const struct option long_options[] = {
         {"verbose", optional_argument, NULL, 'v'},
         {"help", no_argument, NULL, 'h'},
         {"version", no_argument, NULL, 'V'},
index 9d42471..82dd9c6 100644 (file)
@@ -1,4 +1,9 @@
 .\" -*- nroff -*-
+.de IQ
+.  br
+.  ns
+.  IP "\\$1"
+..
 .TH ovsdb\-server 1 "@VERSION@" "Open vSwitch" "Open vSwitch Manual"
 .\" This program's name:
 .ds PN ovsdb\-server
@@ -124,6 +129,29 @@ connections to database clients and reconnect.
 This command might be useful for debugging issues with database
 clients.
 .
+.IP "\fBovsdb\-server/add\-remote \fIremote\fR"
+Adds a remote, as if \fB\-\-remote=\fIremote\fR had been specified on
+the \fBovsdb\-server\fR command line.  (If \fIremote\fR is already a
+remote, this command succeeds without changing the configuration.)
+.
+.IP "\fBovsdb\-server/remove\-remote \fIremote\fR"
+Removes the specified \fIremote\fR from the configuration, failing
+with an error if \fIremote\fR is not configured as a remote.  This
+command only works with remotes that were named on \fB\-\-remote\fR or
+\fBovsdb\-server/add\-remote\fR, that is, it will not remove remotes
+added indirectly because they were read from the database by
+configuring a \fBdb:\fR[\fIdb\fB,\fR]\fItable\fB,\fIcolumn\fR remote.
+(You can remove a database source with \fBovsdb\-server/remove\-remote
+\fBdb:\fR[\fIdb\fB,\fR]\fItable\fB,\fIcolumn\fR, but not individual
+remotes found indirectly through the database.)
+.
+.IP "\fBovsdb\-server/list\-remotes"
+Outputs a list of the currently configured remotes named on
+\fB\-\-remote\fR or \fBovsdb\-server/add\-remote\fR, that is, it does
+not list remotes added indirectly because they were read from the
+database by configuring a
+\fBdb:\fR[\fIdb\fB,\fR]\fItable\fB,\fIcolumn\fR remote.
+.
 .so lib/vlog-unixctl.man
 .so lib/memory-unixctl.man
 .so lib/coverage-unixctl.man
index 2657e26..1ba7c3c 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
+/* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
 
 #include <errno.h>
 #include <getopt.h>
+#include <inttypes.h>
 #include <signal.h>
 #include <unistd.h>
 
@@ -76,6 +77,15 @@ static unixctl_cb_func ovsdb_server_exit;
 static unixctl_cb_func ovsdb_server_compact;
 static unixctl_cb_func ovsdb_server_reconnect;
 
+struct add_remote_aux {
+    struct sset *remotes;
+    struct db *dbs;
+    size_t n_dbs;
+};
+static unixctl_cb_func ovsdb_server_add_remote;
+static unixctl_cb_func ovsdb_server_remove_remote;
+static unixctl_cb_func ovsdb_server_list_remotes;
+
 static void parse_options(int *argc, char **argvp[],
                           struct sset *remotes, char **unixctl_pathp,
                           char **run_command);
@@ -101,6 +111,7 @@ main(int argc, char *argv[])
     bool exiting;
     int retval;
     long long int status_timer = LLONG_MIN;
+    struct add_remote_aux add_remote_aux;
 
     struct db *dbs;
     int n_dbs;
@@ -181,6 +192,16 @@ main(int argc, char *argv[])
     unixctl_command_register("ovsdb-server/reconnect", "", 0, 0,
                              ovsdb_server_reconnect, jsonrpc);
 
+    add_remote_aux.remotes = &remotes;
+    add_remote_aux.dbs = dbs;
+    add_remote_aux.n_dbs = n_dbs;
+    unixctl_command_register("ovsdb-server/add-remote", "REMOTE", 1, 1,
+                             ovsdb_server_add_remote, &add_remote_aux);
+    unixctl_command_register("ovsdb-server/remove-remote", "REMOTE", 1, 1,
+                             ovsdb_server_remove_remote, &remotes);
+    unixctl_command_register("ovsdb-server/list-remotes", "", 0, 0,
+                             ovsdb_server_list_remotes, &remotes);
+
     exiting = false;
     while (!exiting) {
         int i;
@@ -198,9 +219,13 @@ main(int argc, char *argv[])
             simap_destroy(&usage);
         }
 
+        /* Run unixctl_server_run() before reconfigure_from_db() because
+         * ovsdb-server/add-remote and ovsdb-server/remove-remote can change
+         * the set of remotes that reconfigure_from_db() uses. */
+        unixctl_server_run(unixctl);
+
         reconfigure_from_db(jsonrpc, dbs, n_dbs, &remotes);
         ovsdb_jsonrpc_server_run(jsonrpc);
-        unixctl_server_run(unixctl);
 
         for (i = 0; i < n_dbs; i++) {
             ovsdb_trigger_run(dbs[i].db, time_msec());
@@ -262,12 +287,12 @@ find_db(const struct db dbs[], size_t n_dbs, const char *db_name)
     return NULL;
 }
 
-static void
-parse_db_column(const struct db dbs[], size_t n_dbs,
-                const char *name_,
-                const struct db **dbp,
-                const struct ovsdb_table **tablep,
-                const struct ovsdb_column **columnp)
+static char * WARN_UNUSED_RESULT
+parse_db_column__(const struct db dbs[], size_t n_dbs,
+                  const char *name_, char *name,
+                  const struct db **dbp,
+                  const struct ovsdb_table **tablep,
+                  const struct ovsdb_column **columnp)
 {
     const char *table_name, *column_name;
     const struct ovsdb_column *column;
@@ -275,15 +300,17 @@ parse_db_column(const struct db dbs[], size_t n_dbs,
     const char *tokens[3];
     char *save_ptr = NULL;
     const struct db *db;
-    char *name;
 
-    name = xstrdup(name_);
+    *dbp = NULL;
+    *tablep = NULL;
+    *columnp = NULL;
+
     strtok_r(name, ":", &save_ptr); /* "db:" */
     tokens[0] = strtok_r(NULL, ",", &save_ptr);
     tokens[1] = strtok_r(NULL, ",", &save_ptr);
     tokens[2] = strtok_r(NULL, ",", &save_ptr);
     if (!tokens[0] || !tokens[1]) {
-        ovs_fatal(0, "\"%s\": invalid syntax", name_);
+        return xasprintf("\"%s\": invalid syntax", name_);
     }
     if (tokens[2]) {
         const char *db_name = tokens[0];
@@ -292,12 +319,13 @@ parse_db_column(const struct db dbs[], size_t n_dbs,
 
         db = find_db(dbs, n_dbs, tokens[0]);
         if (!db) {
-            ovs_fatal(0, "\"%s\": no database named %s", name_, db_name);
+            return xasprintf("\"%s\": no database named %s", name_, db_name);
         }
     } else {
         if (n_dbs > 1) {
-            ovs_fatal(0, "\"%s\": database name must be specified (because "
-                      "multiple databases are configured)", name_);
+            return xasprintf("\"%s\": database name must be specified "
+                             "(because multiple databases are configured)",
+                             name_);
         }
 
         table_name = tokens[0];
@@ -307,44 +335,61 @@ parse_db_column(const struct db dbs[], size_t n_dbs,
 
     table = ovsdb_get_table(db->db, table_name);
     if (!table) {
-        ovs_fatal(0, "\"%s\": no table named %s", name_, table_name);
+        return xasprintf("\"%s\": no table named %s", name_, table_name);
     }
 
     column = ovsdb_table_schema_get_column(table->schema, column_name);
     if (!column) {
-        ovs_fatal(0, "\"%s\": table \"%s\" has no column \"%s\"",
-                  name_, table_name, column_name);
+        return xasprintf("\"%s\": table \"%s\" has no column \"%s\"",
+                         name_, table_name, column_name);
     }
-    free(name);
 
     *dbp = db;
     *columnp = column;
     *tablep = table;
+    return NULL;
 }
 
-static void
+/* Returns NULL if successful, otherwise a malloc()'d string describing the
+ * error. */
+static char * WARN_UNUSED_RESULT
+parse_db_column(const struct db dbs[], size_t n_dbs,
+                const char *name_,
+                const struct db **dbp,
+                const struct ovsdb_table **tablep,
+                const struct ovsdb_column **columnp)
+{
+    char *name = xstrdup(name_);
+    char *retval = parse_db_column__(dbs, n_dbs, name_, name,
+                                     dbp, tablep, columnp);
+    free(name);
+    return retval;
+}
+
+/* Returns NULL if successful, otherwise a malloc()'d string describing the
+ * error. */
+static char * WARN_UNUSED_RESULT
 parse_db_string_column(const struct db dbs[], size_t n_dbs,
                        const char *name,
                        const struct db **dbp,
                        const struct ovsdb_table **tablep,
                        const struct ovsdb_column **columnp)
 {
-    const struct ovsdb_column *column;
-    const struct ovsdb_table *table;
-    const struct db *db;
+    char *retval;
 
-    parse_db_column(dbs, n_dbs, name, &db, &table, &column);
+    retval = parse_db_column(dbs, n_dbs, name, dbp, tablep, columnp);
+    if (retval) {
+        return retval;
+    }
 
-    if (column->type.key.type != OVSDB_TYPE_STRING
-        || column->type.value.type != OVSDB_TYPE_VOID) {
-        ovs_fatal(0, "\"%s\": table \"%s\" column \"%s\" is "
-                  "not string or set of strings",
-                  name, table->schema->name, column->name);
+    if ((*columnp)->type.key.type != OVSDB_TYPE_STRING
+        || (*columnp)->type.value.type != OVSDB_TYPE_VOID) {
+        return xasprintf("\"%s\": table \"%s\" column \"%s\" is "
+                         "not string or set of strings",
+                         name, (*tablep)->schema->name, (*columnp)->name);
     }
 
-    *dbp = db;
-    *columnp = column;
-    *tablep = table;
+    return NULL;
 }
 
 static OVS_UNUSED const char *
@@ -357,8 +402,13 @@ query_db_string(const struct db dbs[], size_t n_dbs, const char *name)
         const struct ovsdb_table *table;
         const struct ovsdb_row *row;
         const struct db *db;
+        char *retval;
 
-        parse_db_string_column(dbs, n_dbs, name, &db, &table, &column);
+        retval = parse_db_string_column(dbs, n_dbs, name,
+                                        &db, &table, &column);
+        if (retval) {
+            ovs_fatal(0, "%s", retval);
+        }
 
         HMAP_FOR_EACH (row, hmap_node, &table->rows) {
             const struct ovsdb_datum *datum;
@@ -588,8 +638,12 @@ query_db_remotes(const char *name, const struct db dbs[], size_t n_dbs,
     const struct ovsdb_table *table;
     const struct ovsdb_row *row;
     const struct db *db;
+    char *retval;
 
-    parse_db_column(dbs, n_dbs, name, &db, &table, &column);
+    retval = parse_db_column(dbs, n_dbs, name, &db, &table, &column);
+    if (retval) {
+        ovs_fatal(0, "%s", retval);
+    }
 
     if (column->type.key.type == OVSDB_TYPE_STRING
         && column->type.value.type == OVSDB_TYPE_VOID) {
@@ -630,7 +684,7 @@ update_remote_row(const struct ovsdb_row *row, struct ovsdb_txn *txn,
     struct ovsdb_jsonrpc_remote_status status;
     struct ovsdb_row *rw_row;
     const char *target;
-    char *keys[8], *values[8];
+    char *keys[9], *values[9];
     size_t n = 0;
 
     /* Get the "target" (protocol/host/port) spec. */
@@ -677,6 +731,10 @@ update_remote_row(const struct ovsdb_row *row, struct ovsdb_txn *txn,
         keys[n] = xstrdup("n_connections");
         values[n++] = xasprintf("%d", status.n_connections);
     }
+    if (status.bound_port != htons(0)) {
+        keys[n] = xstrdup("bound_port");
+        values[n++] = xasprintf("%"PRIu16, ntohs(status.bound_port));
+    }
     write_string_string_column(rw_row, "status", keys, values, n);
 
     ovsdb_jsonrpc_server_free_remote_status(&status);
@@ -691,12 +749,16 @@ update_remote_rows(const struct db dbs[], size_t n_dbs,
     const struct ovsdb_column *column;
     const struct ovsdb_row *row;
     const struct db *db;
+    char *retval;
 
     if (strncmp("db:", remote_name, 3)) {
         return;
     }
 
-    parse_db_column(dbs, n_dbs, remote_name, &db, &table, &column);
+    retval = parse_db_column(dbs, n_dbs, remote_name, &db, &table, &column);
+    if (retval) {
+        ovs_fatal(0, "%s", retval);
+    }
 
     if (column->type.key.type != OVSDB_TYPE_UUID
         || !column->type.key.u.uuid.refTable
@@ -838,6 +900,72 @@ ovsdb_server_reconnect(struct unixctl_conn *conn, int argc OVS_UNUSED,
     unixctl_command_reply(conn, NULL);
 }
 
+/* "ovsdb-server/add-remote REMOTE": adds REMOTE to the set of remotes that
+ * ovsdb-server services. */
+static void
+ovsdb_server_add_remote(struct unixctl_conn *conn, int argc OVS_UNUSED,
+                        const char *argv[], void *aux_)
+{
+    struct add_remote_aux *aux = aux_;
+    const char *remote = argv[1];
+
+    const struct ovsdb_column *column;
+    const struct ovsdb_table *table;
+    const struct db *db;
+    char *retval;
+
+    retval = (strncmp("db:", remote, 3)
+              ? NULL
+              : parse_db_column(aux->dbs, aux->n_dbs, remote,
+                                &db, &table, &column));
+    if (!retval) {
+        sset_add(aux->remotes, remote);
+        unixctl_command_reply(conn, NULL);
+    } else {
+        unixctl_command_reply_error(conn, retval);
+        free(retval);
+    }
+}
+
+/* "ovsdb-server/remove-remote REMOTE": removes REMOTE frmo the set of remotes
+ * that ovsdb-server services. */
+static void
+ovsdb_server_remove_remote(struct unixctl_conn *conn, int argc OVS_UNUSED,
+                           const char *argv[], void *remotes_)
+{
+    struct sset *remotes = remotes_;
+    struct sset_node *node;
+
+    node = sset_find(remotes, argv[1]);
+    if (node) {
+        sset_delete(remotes, node);
+        unixctl_command_reply(conn, NULL);
+    } else {
+        unixctl_command_reply_error(conn, "no such remote");
+    }
+}
+
+/* "ovsdb-server/list-remotes": outputs a list of configured rmeotes. */
+static void
+ovsdb_server_list_remotes(struct unixctl_conn *conn, int argc OVS_UNUSED,
+                          const char *argv[] OVS_UNUSED, void *remotes_)
+{
+    struct sset *remotes = remotes_;
+    const char **list, **p;
+    struct ds s;
+
+    ds_init(&s);
+
+    list = sset_sort(remotes);
+    for (p = list; *p; p++) {
+        ds_put_format(&s, "%s\n", *p);
+    }
+    free(list);
+
+    unixctl_command_reply(conn, ds_cstr(&s));
+    ds_destroy(&s);
+}
+
 static void
 parse_options(int *argcp, char **argvp[],
               struct sset *remotes, char **unixctl_pathp, char **run_command)
@@ -852,7 +980,7 @@ parse_options(int *argcp, char **argvp[],
         LEAK_CHECKER_OPTION_ENUMS,
         DAEMON_OPTION_ENUMS
     };
-    static struct option long_options[] = {
+    static const struct option long_options[] = {
         {"remote",      required_argument, NULL, OPT_REMOTE},
         {"unixctl",     required_argument, NULL, OPT_UNIXCTL},
         {"run",         required_argument, NULL, OPT_RUN},
index b50b39b..2ef4061 100644 (file)
@@ -66,7 +66,7 @@ main(int argc, char *argv[])
 static void
 parse_options(int argc, char *argv[])
 {
-    static struct option long_options[] = {
+    static const struct option long_options[] = {
         {"more", no_argument, NULL, 'm'},
         {"verbose", optional_argument, NULL, 'v'},
         {"help", no_argument, NULL, 'h'},
@@ -519,9 +519,10 @@ do_show_log(int argc, char *argv[])
             date = shash_find_data(json_object(json), "_date");
             if (date && date->type == JSON_INTEGER) {
                 time_t t = json_integer(date);
+                struct tm tm;
                 char s[128];
 
-                strftime(s, sizeof s, "%Y-%m-%d %H:%M:%S", gmtime(&t));
+                strftime(s, sizeof s, "%Y-%m-%d %H:%M:%S", gmtime_r(&t, &tm));
                 printf(" %s", s);
             }
 
index 9e9bf0f..55fbcba 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
+# Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -610,6 +610,8 @@ class Row(object):
         assert self._changes is not None
         if self._data is None:
             del self._idl.txn._txn_rows[self.uuid]
+        else:
+            self._idl.txn._txn_rows[self.uuid] = self
         self.__dict__["_changes"] = None
         del self._table.rows[self.uuid]
 
index 7d15f3e..ffd6a39 100644 (file)
@@ -18,6 +18,15 @@ import ovs.vlog
 import select
 import socket
 
+try:
+    import eventlet.patcher
+
+    def _using_eventlet_green_select():
+        return eventlet.patcher.is_monkey_patched(select)
+except:
+    def _using_eventlet_green_select():
+        return False
+
 vlog = ovs.vlog.Vlog("poller")
 
 POLLIN = 0x001
@@ -59,6 +68,10 @@ class _SelectSelect(object):
             timeout = None
         else:
             timeout = float(timeout) / 1000
+        # XXX workaround a bug in eventlet
+        # see https://github.com/eventlet/eventlet/pull/25
+        if timeout == 0 and _using_eventlet_green_select():
+            timeout = 0.1
 
         rlist, wlist, xlist = select.select(self.rlist, self.wlist, self.xlist,
                                             timeout)
index 7bfefc4..7dac5bb 100644 (file)
@@ -87,7 +87,7 @@ def make_unix_socket(style, nonblock, bind_path, connect_path):
                 try:
                     connect_dirfd = os.open(dirname, os.O_DIRECTORY | os.O_RDONLY)
                 except OSError, err:
-                    return get_exception_errno(e), None
+                    return get_exception_errno(err), None
                 short_connect_path = "/proc/self/fd/%d/%s" % (connect_dirfd, basename)
 
             if bind_path is not None:
@@ -96,7 +96,7 @@ def make_unix_socket(style, nonblock, bind_path, connect_path):
                 try:
                     bind_dirfd = os.open(dirname, os.O_DIRECTORY | os.O_RDONLY)
                 except OSError, err:
-                    return get_exception_errno(e), None
+                    return get_exception_errno(err), None
                 short_bind_path = "/proc/self/fd/%d/%s" % (bind_dirfd, basename)
 
             try:
index 7cfa415..25ae4ea 100644 (file)
@@ -71,7 +71,7 @@ class Vlog:
             f_level = LEVELS.get(f_level, logging.CRITICAL)
             if level >= f_level:
                 if f == "syslog":
-                    message = syslog_message
+                    message = "ovs|" + syslog_message
                 else:
                     message = "%s|%s" % (now, syslog_message)
                 logging.getLogger(f).log(level, message, **kwargs)
index 55a13a7..7e64132 100755 (executable)
@@ -48,8 +48,6 @@ start () {
     set "$@" $OVS_CTL_OPTS
     "$@"
 
-    ovs_ctl --protocol=gre enable-protocol
-
     touch /var/lock/subsys/openvswitch
 }
 
index 76b6fed..f6f113e 100644 (file)
@@ -29,6 +29,7 @@
 /test-packets
 /test-random
 /test-reconnect
+/test-sflow
 /test-sha1
 /test-stp
 /test-strtok_r
index 275ff53..4442eb5 100644 (file)
@@ -35,6 +35,7 @@ TESTSUITE_AT = \
        tests/tunnel.at \
        tests/lockfile.at \
        tests/reconnect.at \
+       tests/ovs-vswitchd.at \
        tests/ofproto-dpif.at \
        tests/ofproto-macros.at \
        tests/ofproto.at \
@@ -300,8 +301,6 @@ noinst_PROGRAMS += tests/test-byte-order
 tests_test_byte_order_SOURCES = tests/test-byte-order.c
 tests_test_byte_order_LDADD = lib/libopenvswitch.a
 
-EXTRA_DIST += tests/choose-port.pl
-
 # Python tests.
 CHECK_PYFILES = \
        tests/appctl.py \
diff --git a/tests/choose-port.pl b/tests/choose-port.pl
deleted file mode 100644 (file)
index 46c8db5..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- perl -*-
-
-# Picks a random TCP port and attempts to bind it, retrying a few
-# times if the chosen port is in use.  This is better than just
-# picking a random number without checking whether it is in use (but
-# of course a race window still exists).
-#
-# On success, prints a port number on stdout and exits with status 0.
-# On failure, prints an error on stderr and exits with a nonzero status.
-
-use warnings;
-use strict;
-use Socket;
-
-socket(SOCK, PF_INET, SOCK_STREAM, 0) || die "socket: $!\n";
-for (my ($i) = 0; ; $i++) {
-    my ($port) = int(rand(16383)) + 49152;
-    if (bind(SOCK, sockaddr_in($port, INADDR_ANY))) {
-        print "$port\n";
-        exit 0;
-    } elsif ($i < 10 && $!{EADDRINUSE}) {
-        # Address already in use.  Try again.
-    } else {
-        die "bind: $!\n";
-    }
-}
index 0bcd4b3..ffc8996 100644 (file)
@@ -292,7 +292,7 @@ AT_CHECK([grep 'active slave' stdout], [0], [dnl
 ])
 
 # Redirect the patch link between p0 and p2 so that no packets get
-# back and forth across them anymore.  Then wait 2.5 simulated
+# back and forth across them anymore.  Then wait 4 simulated
 # seconds.  The LACP state should become "expired" for p0 and p2.
 AT_CHECK([ovs-vsctl \
 -- add-port br0 null0 -- set int null0 type=patch options:peer=p2 -- set int p2 options:peer=null0 \
index 95cfba8..a6bcdf5 100644 (file)
@@ -88,8 +88,9 @@ userspace(pid=6633,sFlow(vid=9,pcp=7,output=10))
 userspace(pid=9765,slow_path())
 userspace(pid=9765,slow_path(cfm))
 userspace(pid=9765,slow_path(cfm,match))
-userspace(pid=9123,userdata=0x815309)
 userspace(pid=1234567,userdata(0102030405060708090a0b0c0d0e0f))
+userspace(pid=6633,flow_sample(probability=123,collector_set_id=1234,obs_domain_id=2345,obs_point_id=3456))
+userspace(pid=6633,ipfix)
 set(in_port(2))
 set(eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15))
 set(eth_type(0x1234))
index 8a40eb4..2ecbdb5 100644 (file)
@@ -114,6 +114,9 @@ ffff 0010 00002320 0014 04d2 162e 02 00
 # actions=dec_ttl(32768,12345,90,765,1024)
 ffff 0020 00002320 0015 000500000000 80003039005A02fd 0400000000000000
 
+# actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+ffff 0018 00002320 001d 3039 00005BA0 00008707 0000B26E
+
 ])
 sed '/^[[#&]]/d' < test-data > input.txt
 sed -n 's/^# //p; /^$/p' < test-data > expout
@@ -289,6 +292,9 @@ ffff 0010 00002320 0014 04d2 162e 02 00
 # actions=dec_ttl(32768,12345,90,765,1024)
 ffff 0020 00002320 0015 000500000000 80003039005A02fd 0400000000000000
 
+# actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+ffff 0018 00002320 001d 3039 00005BA0 00008707 0000B26E
+
 ])
 sed '/^[[#&]]/d' < test-data > input.txt
 sed -n 's/^# //p; /^$/p' < test-data > expout
index 06ebf23..2b9df96 100644 (file)
@@ -344,13 +344,13 @@ done
 OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
 AT_CHECK([cat ofctl_monitor.log], [0], [dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:64,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:42,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:42,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=1
 dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:64,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:42,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:42,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=1
 dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:64,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:42,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:42,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=1
 ])
 
 dnl Modified MPLS controller action.
@@ -365,13 +365,13 @@ done
 OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
 AT_CHECK([cat ofctl_monitor.log], [0], [dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:64,bos:0),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:43,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:43,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=0
 dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:64,bos:0),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:43,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:43,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=0
 dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:64,bos:0),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:43,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:43,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=0
 ])
 
 dnl Modified MPLS controller action.
@@ -384,13 +384,13 @@ done
 OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
 AT_CHECK([cat ofctl_monitor.log], [0], [dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:64,bos:1),metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=7,dl_src=40:44:44:44:44:44,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=7,dl_src=40:44:44:44:44:44,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=1
 dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:64,bos:1),metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=7,dl_src=40:44:44:44:44:44,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=7,dl_src=40:44:44:44:44:44,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=1
 dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:64,bos:1),metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=7,dl_src=40:44:44:44:44:44,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=7,dl_src=40:44:44:44:44:44,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=64,mpls_bos=1
 ])
 
 dnl Modified MPLS controller action.
@@ -403,13 +403,13 @@ done
 OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
 AT_CHECK([cat ofctl_monitor.log], [0], [dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:63,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:45,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:45,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=63,mpls_bos=1
 dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:63,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:45,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:45,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=63,mpls_bos=1
 dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:63,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:45,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:45,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=63,mpls_bos=1
 ])
 
 dnl Modified MPLS controller action.
@@ -422,13 +422,13 @@ done
 OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
 AT_CHECK([cat ofctl_monitor.log], [0], [dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:10,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:46,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:46,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=10,mpls_bos=1
 dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:10,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:46,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:46,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=10,mpls_bos=1
 dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:10,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:46,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:46,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=10,mpls_bos=1
 ])
 
 dnl Modified MPLS controller action.
@@ -441,13 +441,13 @@ done
 OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
 AT_CHECK([cat ofctl_monitor.log], [0], [dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:10,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:47,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:47,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=10,mpls_bos=1
 dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:10,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:47,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:47,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=10,mpls_bos=1
 dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:10,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:47,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:47,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=10,mpls_bos=1
 ])
 
 dnl Modified MPLS controller action.
@@ -460,32 +460,32 @@ done
 OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
 AT_CHECK([cat ofctl_monitor.log], [0], [dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:9,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:48,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:48,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=9,mpls_bos=1
 dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:9,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:48,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:48,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=9,mpls_bos=1
 dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mpls(label:10,tc:3,ttl:9,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:48,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=40:44:44:44:44:48,dl_dst=50:54:00:00:00:07,mpls_label=10,mpls_tc=3,mpls_ttl=9,mpls_bos=1
 ])
 
 dnl Modified MPLS actions.
 AT_CHECK([ovs-ofctl monitor br0 65534 -P nxm --detach --pidfile 2> ofctl_monitor.log])
 
 for i in 1 2 3; do
-    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:55:55:55:55:55,dst=50:54:00:00:00:07),eth_type(0x8847),mpls(label=100,tc=7,ttl=64,bos=1),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no)'
+    ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:55:55:55:55:55,dst=50:54:00:00:00:07),eth_type(0x8847),mpls(label=100,tc=7,ttl=64,bos=1)'
 done
 
 OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
 AT_CHECK([cat ofctl_monitor.log], [0], [dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xb total_len=60 in_port=1 (via action) data_len=60 (unbuffered)
-mpls(label:1000,tc:7,ttl:64,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:55:55:55:55:55,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:55:55:55:55:55,dl_dst=50:54:00:00:00:07,mpls_label=1000,mpls_tc=7,mpls_ttl=64,mpls_bos=1
 dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xb total_len=60 in_port=1 (via action) data_len=60 (unbuffered)
-mpls(label:1000,tc:7,ttl:64,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:55:55:55:55:55,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:55:55:55:55:55,dl_dst=50:54:00:00:00:07,mpls_label=1000,mpls_tc=7,mpls_ttl=64,mpls_bos=1
 dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xb total_len=60 in_port=1 (via action) data_len=60 (unbuffered)
-mpls(label:1000,tc:7,ttl:64,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:55:55:55:55:55,dl_dst=50:54:00:00:00:07
+mpls,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:55:55:55:55:55,dl_dst=50:54:00:00:00:07,mpls_label=1000,mpls_tc=7,mpls_ttl=64,mpls_bos=1
 ])
 
 dnl Modified MPLS ipv6 controller action.
@@ -498,13 +498,13 @@ done
 OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
 AT_CHECK([cat ofctl_monitor.log], [0], [dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xc total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mplsm(label:1000,tc:7,ttl:64,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=70:77:77:77:77:77,dl_dst=50:54:00:00:00:07
+mplsm,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=70:77:77:77:77:77,dl_dst=50:54:00:00:00:07,mpls_label=1000,mpls_tc=7,mpls_ttl=64,mpls_bos=1
 dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xc total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mplsm(label:1000,tc:7,ttl:64,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=70:77:77:77:77:77,dl_dst=50:54:00:00:00:07
+mplsm,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=70:77:77:77:77:77,dl_dst=50:54:00:00:00:07,mpls_label=1000,mpls_tc=7,mpls_ttl=64,mpls_bos=1
 dnl
 NXT_PACKET_IN (xid=0x0): cookie=0xc total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
-mplsm(label:1000,tc:7,ttl:64,bos:1),metadata=0,in_port=0,vlan_tci=0x0000,dl_src=70:77:77:77:77:77,dl_dst=50:54:00:00:00:07
+mplsm,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=70:77:77:77:77:77,dl_dst=50:54:00:00:00:07,mpls_label=1000,mpls_tc=7,mpls_ttl=64,mpls_bos=1
 ])
 
 
@@ -626,7 +626,7 @@ AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
  cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:44:46 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],set_mpls_ttl(10),CONTROLLER:65535
  cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:44:47 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],dec_mpls_ttl,set_mpls_ttl(10),CONTROLLER:65535
  cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:44:48 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],set_mpls_ttl(10),dec_mpls_ttl,CONTROLLER:65535
- cookie=0xb, n_packets=3, n_bytes=180, dl_src=50:55:55:55:55:55,dl_type=0x8847 actions=load:0x3e8->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535
+ cookie=0xb, n_packets=3, n_bytes=180, mpls,dl_src=50:55:55:55:55:55 actions=load:0x3e8->OXM_OF_MPLS_LABEL[[]],CONTROLLER:65535
  cookie=0xc, n_packets=3, n_bytes=180, dl_src=70:77:77:77:77:77 actions=push_mpls:0x8848,load:0x3e8->OXM_OF_MPLS_LABEL[[]],load:0x7->OXM_OF_MPLS_TC[[]],CONTROLLER:65535
  cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:66:66 actions=pop_mpls:0x0800,CONTROLLER:65535
  n_packets=3, n_bytes=180, dl_src=10:11:11:11:11:11 actions=CONTROLLER:65535
@@ -1208,10 +1208,13 @@ AT_CLEANUP
 
 dnl Test that sFlow samples packets correctly.
 AT_SETUP([ofproto-dpif - sFlow packet sampling])
-AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
-SFLOW_PORT=`cat stdout`
 OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
 
+ON_EXIT([kill `cat test-sflow.pid`])
+AT_CHECK([test-sflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > sflow.log], [0], [], [ignore])
+AT_CAPTURE_FILE([sflow.log])
+SFLOW_PORT=`parse_listening_port < test-sflow.log`
+
 ovs-appctl time/stop
 
 ADD_OF_PORTS([br0], 1, 2)
@@ -1222,9 +1225,6 @@ ovs-vsctl \
    set Bridge br0 sflow=@sf -- \
    --id=@sf create sflow targets=\"127.0.0.1:$SFLOW_PORT\" \
      header=128 sampling=1 polling=1
-ON_EXIT([kill `cat test-sflow.pid`])
-AT_CHECK([test-sflow --detach --no-chdir --pidfile $SFLOW_PORT:127.0.0.1 > sflow.log])
-AT_CAPTURE_FILE([sflow.log])
 
 dnl open with ARP packets to seed the bridge-learning.  The output
 dnl ifIndex numbers should be reported predictably after that.
@@ -1252,7 +1252,7 @@ AT_CHECK([[sort sflow.log | $EGREP 'HEADER|ERROR' | sed 's/ /\
        /g']], [0], [dnl
 HEADER
        dgramSeqNo=1
-       ds=127.0.0.1>0:1003
+       ds=127.0.0.1>2:1000
        fsSeqNo=1
        in_vlan=0
        in_priority=0
@@ -1261,7 +1261,7 @@ HEADER
        meanSkip=1
        samplePool=1
        dropEvents=0
-       in_ifindex=1003
+       in_ifindex=1004
        in_format=0
        out_ifindex=2
        out_format=2
@@ -1269,10 +1269,10 @@ HEADER
        pkt_len=64
        stripped=4
        hdr_len=60
-       hdr=FF-FF-FF-FF-FF-FF-50-54-00-00-00-07-08-06-00-01-08-00-06-04-00-01-50-54-00-00-00-07-C0-A8-00-01-00-00-00-00-00-00-C0-A8-00-02-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+       hdr=FF-FF-FF-FF-FF-FF-50-54-00-00-00-05-08-06-00-01-08-00-06-04-00-01-50-54-00-00-00-05-C0-A8-00-02-00-00-00-00-00-00-C0-A8-00-01-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
 HEADER
        dgramSeqNo=1
-       ds=127.0.0.1>0:1003
+       ds=127.0.0.1>2:1000
        fsSeqNo=2
        in_vlan=0
        in_priority=0
@@ -1283,16 +1283,16 @@ HEADER
        dropEvents=0
        in_ifindex=1003
        in_format=0
-       out_ifindex=1004
-       out_format=0
+       out_ifindex=2
+       out_format=2
        hdr_prot=1
        pkt_len=64
        stripped=4
        hdr_len=60
-       hdr=50-54-00-00-00-05-50-54-00-00-00-07-08-00-45-00-00-1C-00-00-00-00-40-01-F9-8D-C0-A8-00-02-C0-A8-00-01-00-00-FF-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+       hdr=FF-FF-FF-FF-FF-FF-50-54-00-00-00-07-08-06-00-01-08-00-06-04-00-01-50-54-00-00-00-07-C0-A8-00-01-00-00-00-00-00-00-C0-A8-00-02-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
 HEADER
        dgramSeqNo=1
-       ds=127.0.0.1>0:1003
+       ds=127.0.0.1>2:1000
        fsSeqNo=3
        in_vlan=0
        in_priority=0
@@ -1301,55 +1301,55 @@ HEADER
        meanSkip=1
        samplePool=3
        dropEvents=0
-       in_ifindex=1003
+       in_ifindex=1004
        in_format=0
-       out_ifindex=1004
+       out_ifindex=1003
        out_format=0
        hdr_prot=1
        pkt_len=64
        stripped=4
        hdr_len=60
-       hdr=50-54-00-00-00-05-50-54-00-00-00-07-86-DD-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+       hdr=50-54-00-00-00-07-50-54-00-00-00-05-08-00-45-00-00-1C-00-00-00-00-40-01-F9-8D-C0-A8-00-01-C0-A8-00-02-08-00-F7-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
 HEADER
        dgramSeqNo=1
-       ds=127.0.0.1>0:1004
-       fsSeqNo=1
+       ds=127.0.0.1>2:1000
+       fsSeqNo=4
        in_vlan=0
        in_priority=0
        out_vlan=0
        out_priority=0
        meanSkip=1
-       samplePool=1
+       samplePool=4
        dropEvents=0
-       in_ifindex=1004
+       in_ifindex=1003
        in_format=0
-       out_ifindex=2
-       out_format=2
+       out_ifindex=1004
+       out_format=0
        hdr_prot=1
        pkt_len=64
        stripped=4
        hdr_len=60
-       hdr=FF-FF-FF-FF-FF-FF-50-54-00-00-00-05-08-06-00-01-08-00-06-04-00-01-50-54-00-00-00-05-C0-A8-00-02-00-00-00-00-00-00-C0-A8-00-01-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+       hdr=50-54-00-00-00-05-50-54-00-00-00-07-08-00-45-00-00-1C-00-00-00-00-40-01-F9-8D-C0-A8-00-02-C0-A8-00-01-00-00-FF-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
 HEADER
        dgramSeqNo=1
-       ds=127.0.0.1>0:1004
-       fsSeqNo=2
+       ds=127.0.0.1>2:1000
+       fsSeqNo=5
        in_vlan=0
        in_priority=0
        out_vlan=0
        out_priority=0
        meanSkip=1
-       samplePool=2
+       samplePool=5
        dropEvents=0
-       in_ifindex=1004
+       in_ifindex=1003
        in_format=0
-       out_ifindex=1003
+       out_ifindex=1004
        out_format=0
        hdr_prot=1
        pkt_len=64
        stripped=4
        hdr_len=60
-       hdr=50-54-00-00-00-07-50-54-00-00-00-05-08-00-45-00-00-1C-00-00-00-00-40-01-F9-8D-C0-A8-00-01-C0-A8-00-02-08-00-F7-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+       hdr=50-54-00-00-00-05-50-54-00-00-00-07-86-DD-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
 ])
 
 AT_CHECK([[sort sflow.log | $EGREP 'IFCOUNTERS|ERROR' | head -6 | sed 's/ /\
@@ -1504,20 +1504,19 @@ dnl - Flow actions changing (in this case, due to MAC learning)
 dnl   cause a record to be sent.
 AT_SETUP([ofproto-dpif - NetFlow flow expiration])
 
-AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
-NETFLOW_PORT=`cat stdout`
-
 OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
 ADD_OF_PORTS([br0], 1, 2)
+
+ON_EXIT([kill `cat test-netflow.pid`])
+AT_CHECK([test-netflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > netflow.log], [0], [], [ignore])
+AT_CAPTURE_FILE([netflow.log])
+NETFLOW_PORT=`parse_listening_port < test-netflow.log`
+
 ovs-vsctl \
    set Bridge br0 netflow=@nf -- \
    --id=@nf create NetFlow targets=\"127.0.0.1:$NETFLOW_PORT\" \
      engine_id=1 engine_type=2 active_timeout=30 add-id-to-interface=false
 
-ON_EXIT([kill `cat test-netflow.pid`])
-AT_CHECK([test-netflow --detach --no-chdir --pidfile $NETFLOW_PORT:127.0.0.1 > netflow.log])
-AT_CAPTURE_FILE([netflow.log])
-
 for delay in 1000 30000; do
     ovs-appctl netdev-dummy/receive p1 '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=64,frag=no),icmp(type=8,code=0)'
     ovs-appctl netdev-dummy/receive p2 'in_port(1),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)'
@@ -1546,19 +1545,19 @@ AT_CLEANUP
 dnl Test that basic NetFlow reports active expirations correctly.
 AT_SETUP([ofproto-dpif - NetFlow active expiration])
 
-AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
-NETFLOW_PORT=`cat stdout`
-
 OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
 ADD_OF_PORTS([br0], 1, 2)
+
+ON_EXIT([kill `cat test-netflow.pid`])
+AT_CHECK([test-netflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > netflow.log], [0], [], [ignore])
+AT_CAPTURE_FILE([netflow.log])
+NETFLOW_PORT=`parse_listening_port < test-netflow.log`
+
 ovs-vsctl \
    set Bridge br0 netflow=@nf -- \
    --id=@nf create NetFlow targets=\"127.0.0.1:$NETFLOW_PORT\" \
      engine_id=1 engine_type=2 active_timeout=10 add-id-to-interface=false
 
-ON_EXIT([kill `cat test-netflow.pid`])
-AT_CHECK([test-netflow --detach --no-chdir --pidfile $NETFLOW_PORT:127.0.0.1 > netflow.log])AT_CAPTURE_FILE([netflow.log])
-
 AT_CHECK([ovs-appctl time/stop])
 n=1
 while test $n -le 60; do
@@ -1937,8 +1936,8 @@ AT_CHECK([ovs-appctl dpif/show | sed 's/ 10[[0-9]]\{3\}(ms)$/ 10000(ms)/'], [0],
 br0 (dummy@ovs-dummy):
        lookups: hit:0 missed:61
        flows: cur: 0, avg: 1.000, max: 1, life span: 10000(ms)
-               hourly avg: add rate: 0.641/min, del rate: 0.635/min
-               overall avg: add rate: 1.000/min, del rate: 0.984/min
+               hourly avg: add rate: 0.641/min, del rate: 0.641/min
+               overall avg: add rate: 1.000/min, del rate: 1.000/min
        br0 65534/100: (dummy)
        p1 1/1: (dummy)
        p2 2/2: (dummy)
index 9a6d5ab..e8ac9d0 100644 (file)
@@ -13,6 +13,23 @@ s/ n_bytes=0,//
 s/ idle_age=[0-9]*,//
 s/ hard_age=[0-9]*,//
 '
+}
+
+# parse_listening_port [SERVER]
+#
+# Parses the TCP or SSL port on which a server is listening from the
+# log, given that the server was told to listen on a kernel-chosen
+# port, file provided on stdin, and prints the port number on stdout.
+# You should specify the listening remote as ptcp:0:127.0.0.1 or
+# pssl:0:127.0.0.1.
+#
+# Here's an example of how to use this with ovsdb-server:
+#
+#    OVS_LOGDIR=`pwd`; export OVS_LOGDIR
+#    ovsdb-server --log-file --remote=ptcp:0:127.0.0.1 ...
+#    TCP_PORT=`parse_listening_port < ovsdb-server.log`
+parse_listening_port () {
+    sed -n 's/.*0:127\.0\.0\.1: listening on port \([0-9]*\)$/\1/p'
 }]
 m4_divert_pop([PREPARE_TESTS])
 
@@ -61,7 +78,7 @@ m4_define([OVS_VSWITCHD_START],
 /ofproto|INFO|datapath ID changed to fedcba9876543210/d']])
 
    dnl Add bridges, ports, etc.
-   AT_CHECK([ovs-vsctl -- add-br br0 -- set bridge br0 datapath-type=dummy other-config:datapath-id=fedcba9876543210 other-config:hwaddr=aa:55:aa:55:00:00 protocols=[[OpenFlow10,OpenFlow12,OpenFlow13]] fail-mode=secure -- $1 m4_if([$2], [], [], [| perl $srcdir/uuidfilt.pl])], [0], [$2])
+   AT_CHECK([ovs-vsctl -- add-br br0 -- set bridge br0 datapath-type=dummy other-config:datapath-id=fedcba9876543210 other-config:hwaddr=aa:55:aa:55:00:00 protocols=[[OpenFlow10,OpenFlow12,OpenFlow13]] fail-mode=secure -- $1 m4_if([$2], [], [], [| ${PERL} $srcdir/uuidfilt.pl])], [0], [$2])
 ])
 
 m4_divert_push([PREPARE_TESTS])
index f41bfc3..a87f4b5 100644 (file)
@@ -585,7 +585,7 @@ AT_CHECK(
      -- --id=@t0 create Flow_Table name=main \
      -- --id=@t1 create Flow_Table flow-limit=1024 \
      -- set bridge br0 'flow_tables={1=@t1,0=@t0}' \
-   | perl $srcdir/uuidfilt.pl],
+   | ${PERL} $srcdir/uuidfilt.pl],
   [0], [<0>
 <1>
 ])
@@ -628,7 +628,7 @@ AT_CHECK(
      -- --id=@t0 create Flow_Table name=main \
      -- --id=@t1 create Flow_Table flow-limit=1024 \
      -- set bridge br0 'flow_tables={1=@t1,0=@t0}' \
-   | perl $srcdir/uuidfilt.pl],
+   | ${PERL} $srcdir/uuidfilt.pl],
   [0], [<0>
 <1>
 ])
@@ -650,7 +650,7 @@ AT_CHECK(
   [ovs-vsctl \
      -- --id=@t0 create Flow_Table flow-limit=4 \
      -- set bridge br0 flow_tables:0=@t0 \
-   | perl $srcdir/uuidfilt.pl],
+   | ${PERL} $srcdir/uuidfilt.pl],
   [0], [<0>
 ])
 # Add 4 flows.
@@ -694,7 +694,7 @@ AT_CHECK(
   [ovs-vsctl \
      -- --id=@t0 create Flow_Table flow-limit=4 \
      -- set bridge br0 flow_tables:0=@t0 \
-   | perl $srcdir/uuidfilt.pl],
+   | ${PERL} $srcdir/uuidfilt.pl],
   [0], [<0>
 ])
 # Add 4 flows.
@@ -733,7 +733,7 @@ AT_CHECK(
   [ovs-vsctl \
      -- --id=@t0 create Flow_Table flow-limit=4 overflow-policy=evict \
      -- set bridge br0 flow_tables:0=@t0 \
-   | perl $srcdir/uuidfilt.pl],
+   | ${PERL} $srcdir/uuidfilt.pl],
   [0], [<0>
 ])
 # Add 4 flows.
@@ -791,7 +791,7 @@ AT_CHECK(
   [ovs-vsctl \
      -- --id=@t0 create Flow_Table flow-limit=4 overflow-policy=evict \
      -- set bridge br0 flow_tables:0=@t0 \
-   | perl $srcdir/uuidfilt.pl],
+   | ${PERL} $srcdir/uuidfilt.pl],
   [0], [<0>
 ])
 # Add 4 flows.
@@ -852,7 +852,7 @@ AT_CHECK(
                                    overflow-policy=evict \
                                    groups='"NXM_OF_IN_PORT[[]]"' \
      -- set bridge br0 flow_tables:0=@t0 \
-   | perl $srcdir/uuidfilt.pl],
+   | ${PERL} $srcdir/uuidfilt.pl],
   [0], [<0>
 ])
 # Add 4 flows.
@@ -934,7 +934,7 @@ AT_CHECK(
                                    overflow-policy=evict \
                                    groups='"NXM_OF_IN_PORT[[]]"' \
      -- set bridge br0 flow_tables:0=@t0 \
-   | perl $srcdir/uuidfilt.pl],
+   | ${PERL} $srcdir/uuidfilt.pl],
   [0], [<0>
 ])
 # Add 4 flows.
@@ -1534,7 +1534,7 @@ sort='
     }
     print $_ foreach sort(@buffer);
 '
-AT_CHECK([sed 's/ (xid=0x[[1-9a-fA-F]][[0-9a-fA-F]]*)//' monitor.log | perl -e "$sort"], [0],
+AT_CHECK([sed 's/ (xid=0x[[1-9a-fA-F]][[0-9a-fA-F]]*)//' monitor.log | ${PERL} -e "$sort"], [0],
 [NXST_FLOW_MONITOR reply (xid=0x0):
  event=ADDED table=0 cookie=0 in_port=0,dl_vlan=124 actions=output:2
 NXST_FLOW_MONITOR reply (xid=0x0):
@@ -1657,7 +1657,7 @@ ovs-appctl -t ovs-ofctl ofctl/block
 
 # Add $n_msgs flows.
 (echo "in_port=2,actions=output:2"
-perl -e '
+${PERL} -e '
     for ($i = 0; $i < '$n_msgs'; $i++) {
         print "cookie=1,reg1=$i,actions=drop\n";
     }
index 075f2e4..db19e01 100644 (file)
@@ -12,6 +12,7 @@ cookie=0x123456789abcdef hard_timeout=10 priority=60000 actions=controller
 actions=note:41.42.43,note:00.01.02.03.04.05.06.07,note
 actions=set_field:fe80:0123:4567:890a:a6ba:dbff:fefe:59fa->ipv6_src
 in_port=0 actions=resubmit:0
+actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 
 AT_CHECK([ovs-ofctl parse-flows flows.txt
@@ -28,6 +29,7 @@ OFPT_FLOW_MOD: ADD priority=60000 cookie:0x123456789abcdef hard:10 actions=CONTR
 OFPT_FLOW_MOD: ADD actions=note:41.42.43.00.00.00,note:00.01.02.03.04.05.06.07.00.00.00.00.00.00,note:00.00.00.00.00.00
 OFPT_FLOW_MOD: ADD actions=load:0xa6badbfffefe59fa->NXM_NX_IPV6_SRC[0..63],load:0xfe8001234567890a->NXM_NX_IPV6_SRC[64..127]
 OFPT_FLOW_MOD: ADD in_port=0 actions=resubmit:0
+OFPT_FLOW_MOD: ADD actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 AT_CLEANUP
 
@@ -43,6 +45,7 @@ cookie=0x123456789abcdef hard_timeout=10 priority=60000 actions=controller
 actions=note:41.42.43,note:00.01.02.03.04.05.06.07,note
 actions=set_field:fe80:0123:4567:890a:a6ba:dbff:fefe:59fa->ipv6_src
 in_port=0 actions=resubmit:0
+actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 
 AT_CHECK([ovs-ofctl --protocols OpenFlow12 parse-flows flows.txt
@@ -59,6 +62,7 @@ OFPT_FLOW_MOD (OF1.2): ADD table:255 priority=60000 cookie:0x123456789abcdef har
 OFPT_FLOW_MOD (OF1.2): ADD table:255 actions=note:41.42.43.00.00.00,note:00.01.02.03.04.05.06.07.00.00.00.00.00.00,note:00.00.00.00.00.00
 OFPT_FLOW_MOD (OF1.2): ADD table:255 actions=set_field:fe80:123:4567:890a:a6ba:dbff:fefe:59fa->ipv6_src
 OFPT_FLOW_MOD (OF1.2): ADD table:255 in_port=0 actions=resubmit:0
+OFPT_FLOW_MOD (OF1.2): ADD table:255 actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 AT_CLEANUP
 
@@ -116,6 +120,7 @@ send_flow_rem,actions=output:1,output:NXM_NX_REG0[],output:2,output:NXM_NX_REG1[
 check_overlap,actions=output:1,exit,output:2
 actions=fin_timeout(idle_timeout=5,hard_timeout=15)
 actions=controller(max_len=123,reason=invalid_ttl,id=555)
+actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 
 AT_CHECK([ovs-ofctl parse-flows flows.txt
@@ -150,6 +155,7 @@ NXT_FLOW_MOD: ADD table:255 send_flow_rem actions=output:1,output:NXM_NX_REG0[],
 NXT_FLOW_MOD: ADD table:255 check_overlap actions=output:1,exit,output:2
 NXT_FLOW_MOD: ADD table:255 actions=fin_timeout(idle_timeout=5,hard_timeout=15)
 NXT_FLOW_MOD: ADD table:255 actions=controller(reason=invalid_ttl,max_len=123,id=555)
+NXT_FLOW_MOD: ADD table:255 actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 AT_CLEANUP
 
@@ -183,6 +189,7 @@ dl_dst=01:00:00:00:00:00/01:00:00:00:00:00,actions=drop
 dl_dst=00:00:00:00:00:00/01:00:00:00:00:00,actions=drop
 dl_dst=aa:bb:cc:dd:ee:ff/fe:ff:ff:ff:ff:ff,actions=drop
 dl_dst=aa:bb:cc:dd:ee:ff/00:00:00:00:00:00,actions=drop
+actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ])
 AT_CHECK([ovs-ofctl -F nxm parse-flows flows.txt], [0], [stdout])
 AT_CHECK([[sed 's/ (xid=0x[0-9a-fA-F]*)//' stdout]], [0], [dnl
@@ -215,6 +222,7 @@ NXT_FLOW_MOD: ADD dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=drop
 NXT_FLOW_MOD: ADD dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=drop
 NXT_FLOW_MOD: ADD dl_dst=aa:bb:cc:dd:ee:ff/fe:ff:ff:ff:ff:ff actions=drop
 NXT_FLOW_MOD: ADD actions=drop
+NXT_FLOW_MOD: ADD actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ])
 AT_CLEANUP
 
@@ -245,6 +253,7 @@ reg0=123,actions=move:NXM_NX_REG0[0..5]->NXM_NX_REG1[26..31],load:55->NXM_NX_REG
 actions=move:OXM_OF_ETH_DST[]->OXM_OF_ETH_SRC[]
 actions=push:NXM_NX_REG0[0..31],pop:NXM_NX_REG0[]
 vlan_tci=0x1123/0x1fff,actions=drop
+actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 AT_CHECK([ovs-ofctl -F nxm -mmm parse-flows flows.txt], [0], [stdout], [stderr])
 AT_CHECK([[sed 's/ (xid=0x[0-9a-fA-F]*)//' stdout]], [0],
@@ -274,6 +283,7 @@ NXT_FLOW_MOD: ADD NXM_NX_REG0(0000007b) actions=move:NXM_NX_REG0[0..5]->NXM_NX_R
 NXT_FLOW_MOD: ADD <any> actions=move:NXM_OF_ETH_DST[]->NXM_OF_ETH_SRC[]
 NXT_FLOW_MOD: ADD <any> actions=push:NXM_NX_REG0[],pop:NXM_NX_REG0[]
 NXT_FLOW_MOD: ADD NXM_OF_VLAN_TCI_W(1123/1fff) actions=drop
+NXT_FLOW_MOD: ADD <any> actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 AT_CLEANUP
 
@@ -1466,6 +1476,12 @@ OXM_OF_VLAN_VID_W(1123/1f0f), OXM_OF_VLAN_PCP(01)  # Packets with VID=123 (maske
 OXM_OF_VLAN_VID_W(1000/1000)    # Packets with any VID, any PCP
 OXM_OF_VLAN_VID_W(1000/1000), OXM_OF_VLAN_PCP(01)  # Packets with any VID, PCP=1.
 
+# IP TOS
+OXM_OF_ETH_TYPE(0800) OXM_OF_IP_DSCP(f0)
+OXM_OF_ETH_TYPE(0800) OXM_OF_IP_DSCP(41)
+OXM_OF_ETH_TYPE(0800) OXM_OF_IP_DSCP(3f)
+OXM_OF_IP_DSCP(f0)
+
 # IP ECN
 OXM_OF_ETH_TYPE(0800) OXM_OF_IP_ECN(03)
 OXM_OF_ETH_TYPE(0800) OXM_OF_IP_ECN(06)
@@ -1662,6 +1678,12 @@ OXM_OF_VLAN_VID_W(1103/1f0f), OXM_OF_VLAN_PCP(01)
 OXM_OF_VLAN_VID_W(1000/1000)
 OXM_OF_VLAN_VID_W(1000/1000), OXM_OF_VLAN_PCP(01)
 
+# IP TOS
+nx_pull_match() returned error OFPBMC_BAD_VALUE
+nx_pull_match() returned error OFPBMC_BAD_VALUE
+OXM_OF_ETH_TYPE(0800), OXM_OF_IP_DSCP(3f)
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+
 # IP ECN
 OXM_OF_ETH_TYPE(0800), OXM_OF_IP_ECN(03)
 nx_pull_match() returned error OFPBMC_BAD_VALUE
index c5c3f47..439bd2d 100644 (file)
@@ -621,7 +621,7 @@ cp stdout out1
 AT_CHECK([RUN_OVS_VSCTL([list b], [get b br0 _uuid])],
   [0], [stdout], [], [OVS_VSCTL_CLEANUP])
 cp stdout out2
-AT_CHECK([perl $srcdir/uuidfilt.pl out1 out2], [0], 
+AT_CHECK([${PERL} $srcdir/uuidfilt.pl out1 out2], [0], 
   [[<0>
 
 _uuid               : <0>
@@ -632,6 +632,7 @@ external_ids        : {}
 fail_mode           : []
 flood_vlans         : []
 flow_tables         : {}
+ipfix               : []
 mirrors             : []
 name                : "br0"
 netflow             : []
@@ -742,7 +743,7 @@ AT_CHECK([
 cp stdout netflow-uuid
 AT_CHECK([RUN_OVS_VSCTL([list netflow `cat netflow-uuid`])],
   [0], [stdout], [], [OVS_VSCTL_CLEANUP])
-AT_CHECK([perl $srcdir/uuidfilt.pl netflow-uuid stdout], [0], 
+AT_CHECK([${PERL} $srcdir/uuidfilt.pl netflow-uuid stdout], [0], 
   [[<0>
 
 _uuid               : <0>
@@ -822,7 +823,7 @@ AT_CHECK([RUN_OVS_VSCTL([clear netflow `cat netflow-uuid` targets])],
 AT_CHECK([RUN_OVS_VSCTL([destroy b br2])], 
   [1], [], [ovs-vsctl: no row "br2" in table Bridge
 ], [OVS_VSCTL_CLEANUP])
-AT_CHECK([RUN_OVS_VSCTL([add i br1 name x])],
+AT_CHECK([RUN_OVS_VSCTL([add in br1 name x])],
   [1], [], [ovs-vsctl: cannot modify read-only column name in table Interface
 ], [OVS_VSCTL_CLEANUP])
 AT_CHECK([RUN_OVS_VSCTL([set port br1 name br2])],
@@ -1039,7 +1040,7 @@ AT_CHECK(
     [--id=@m create mirror name=mymirror select-dst-port=@eth0 select-src-port=@eth0 output-port=@eth1])],
   [0], [stdout], [], [OVS_VSCTL_CLEANUP])
 AT_CHECK(
-  [perl $srcdir/uuidfilt.pl stdout], [0], [dnl
+  [${PERL} $srcdir/uuidfilt.pl stdout], [0], [dnl
 
 
 
@@ -1053,7 +1054,7 @@ AT_CHECK(
     [list bridge br0])],
   [0], [stdout], [], [OVS_VSCTL_CLEANUP])
 AT_CHECK(
-  [sed -n -e '/uuid/p' -e '/name/p' -e '/mirrors/p' -e '/select/p' -e '/output/p' < stdout | $srcdir/uuidfilt.pl], [0], [dnl
+  [sed -n -e '/uuid/p' -e '/name/p' -e '/mirrors/p' -e '/select/p' -e '/output/p' < stdout | ${PERL} $srcdir/uuidfilt.pl], [0], [dnl
 [_uuid               : <0>
 name                : "eth0"
 _uuid               : <1>
@@ -1079,13 +1080,13 @@ AT_KEYWORDS([ovs-vsctl])
 OVS_VSCTL_SETUP
 AT_CHECK(
   [ovs-vsctl -vPATTERN:console:'%c|%p|%m' --no-wait -vreconnect:emer --db=unix:socket \
-     -- create Bridge name=br0 | $srcdir/uuidfilt.pl],
+     -- create Bridge name=br0 | ${PERL} $srcdir/uuidfilt.pl],
   [0], [<0>
 ], [vsctl|WARN|applying "create" command to table Bridge without --id option will have no effect
 ], [OVS_VSCTL_CLEANUP])
 AT_CHECK(
   [ovs-vsctl -vPATTERN:console:'%c|%p|%m' --no-wait -vreconnect:emer --db=unix:socket \
-     -- --id=@br0 create Bridge name=br0 | $srcdir/uuidfilt.pl],
+     -- --id=@br0 create Bridge name=br0 | ${PERL} $srcdir/uuidfilt.pl],
   [0], [<0>
 ], [vsctl|WARN|row id "@br0" was created but no reference to it was inserted, so it will not actually appear in the database
 ], [OVS_VSCTL_CLEANUP])
@@ -1095,7 +1096,7 @@ AT_CHECK(
      -- --id=@eth0 create Port name=eth0 interfaces=@eth0_iface \
      -- --id=@m0 create Mirror name=m0 output_port=@eth0 \
      -- --id=@br0 create Bridge name=br0 mirrors=@m0 \
-     -- set Open_vSwitch . bridges=@br0 | $srcdir/uuidfilt.pl],
+     -- set Open_vSwitch . bridges=@br0 | ${PERL} $srcdir/uuidfilt.pl],
   [0], [<0>
 <1>
 <2>
@@ -1113,7 +1114,7 @@ AT_KEYWORDS([ovs-vsctl])
 OVS_VSCTL_SETUP
 AT_CHECK([RUN_OVS_VSCTL([--id=@br0 create Bridge name=br0 -- add Open_vSwitch . bridges @br0 -- list b])],
   [0], [stdout], [], [OVS_VSCTL_CLEANUP])
-AT_CHECK([perl $srcdir/uuidfilt.pl stdout], [0], 
+AT_CHECK([${PERL} $srcdir/uuidfilt.pl stdout], [0], 
   [[<0>
 _uuid               : <1>
 controller          : []
@@ -1123,6 +1124,7 @@ external_ids        : {}
 fail_mode           : []
 flood_vlans         : []
 flow_tables         : {}
+ipfix               : []
 mirrors             : []
 name                : "br0"
 netflow             : []
diff --git a/tests/ovs-vswitchd.at b/tests/ovs-vswitchd.at
new file mode 100644 (file)
index 0000000..c552741
--- /dev/null
@@ -0,0 +1,27 @@
+AT_BANNER([ovs-vswitchd])
+
+dnl The OVS initscripts never make an empty database (one without even an
+dnl Open_vSwitch record) visible to ovs-vswitchd, but hand-rolled scripts
+dnl sometimes do.  At one point, "ovs-vswitchd --detach" would never detach
+dnl and use 100% CPU if this happened, so this test checks for regression.
+AT_SETUP([ovs-vswitchd detaches correctly with empty db])
+OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+OVS_LOGDIR=`pwd`; export OVS_LOGDIR
+OVS_DBDIR=`pwd`; export OVS_DBDIR
+OVS_SYSCONFDIR=`pwd`; export OVS_SYSCONFDIR
+ON_EXIT([kill `cat ovsdb-server.pid ovs-vswitchd.pid`])
+
+dnl Create database.
+touch .conf.db.~lock~
+AT_CHECK([ovsdb-tool create conf.db $abs_top_srcdir/vswitchd/vswitch.ovsschema])
+
+dnl Start ovsdb-server.  *Don't* initialize database.
+AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --log-file --remote=punix:$OVS_RUNDIR/db.sock], [0], [ignore], [ignore])
+AT_CAPTURE_FILE([ovsdb-server.log])
+
+dnl Start ovs-vswitchd.
+AT_CHECK([ovs-vswitchd --detach --no-chdir --pidfile --enable-dummy --disable-system --log-file], [0], [], [stderr])
+AT_CAPTURE_FILE([ovs-vswitchd.log])
+
+dnl ovs-vswitchd detached OK or we wouldn't have made it this far.  Success.
+AT_CLEANUP
index eec2a04..d014804 100644 (file)
@@ -141,7 +141,7 @@ m4_define([OVSDB_CHECK_EXECUTION],
    OVS_RUNDIR=`pwd`; export OVS_RUNDIR
    AT_CHECK([test-ovsdb execute "`$2`" m4_foreach([txn], [$3], [ 'txn'])],
      [0], [stdout], [])
-   AT_CHECK([perl $srcdir/uuidfilt.pl stdout], [0], [$4])
+   AT_CHECK([${PERL} $srcdir/uuidfilt.pl stdout], [0], [$4])
    AT_CLEANUP])
 
 OVSDB_CHECK_EXECUTION([uuid-name must be <id>],
index 3c32e2f..9ff7b1b 100644 (file)
@@ -28,7 +28,7 @@ m4_define([OVSDB_CHECK_IDL_C],
      [AT_CHECK([ovsdb-client transact unix:socket $2], [0], [ignore], [ignore], [kill `cat pid`])])
    AT_CHECK([test-ovsdb '-vPATTERN:console:test-ovsdb|%c|%m' -vjsonrpc -t10 idl unix:socket $3],
             [0], [stdout], [ignore], [kill `cat pid`])
-   AT_CHECK([sort stdout | perl $srcdir/uuidfilt.pl]m4_if([$6],,, [[| $6]]),
+   AT_CHECK([sort stdout | ${PERL} $srcdir/uuidfilt.pl]m4_if([$6],,, [[| $6]]),
             [0], [$4], [], [kill `cat pid`])
    OVSDB_SERVER_SHUTDOWN
    AT_CLEANUP])
@@ -46,7 +46,7 @@ m4_define([OVSDB_CHECK_IDL_PY],
      [AT_CHECK([ovsdb-client transact unix:socket $2], [0], [ignore], [ignore], [kill `cat pid`])])
    AT_CHECK([$PYTHON $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema unix:socket $3],
             [0], [stdout], [ignore], [kill `cat pid`])
-   AT_CHECK([sort stdout | perl $srcdir/uuidfilt.pl]m4_if([$6],,, [[| $6]]),
+   AT_CHECK([sort stdout | ${PERL} $srcdir/uuidfilt.pl]m4_if([$6],,, [[| $6]]),
             [0], [$4], [], [kill `cat pid`])
    OVSDB_SERVER_SHUTDOWN
    AT_CLEANUP])
@@ -57,16 +57,17 @@ m4_define([OVSDB_CHECK_IDL_TCP_PY],
    AT_SKIP_IF([test $HAVE_PYTHON = no])
    AT_KEYWORDS([ovsdb server idl positive Python with tcp socket $5])
    OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+   OVS_LOGDIR=`pwd`; export OVS_LOGDIR
    AT_CHECK([ovsdb-tool create db $abs_srcdir/idltest.ovsschema],
                   [0], [stdout], [ignore])
-   AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
-   TCP_PORT=`cat stdout`
-   AT_CHECK([ovsdb-server '-vPATTERN:console:ovsdb-server|%c|%m' --detach --no-chdir --pidfile="`pwd`"/pid --remote=ptcp:$TCP_PORT:127.0.0.1 --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore])
+   AT_CHECK([ovsdb-server --log-file '-vPATTERN:console:ovsdb-server|%c|%m' --detach --no-chdir --pidfile="`pwd`"/pid --remote=punix:socket --remote=ptcp:0:127.0.0.1 --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore])
+   TCP_PORT=`parse_listening_port < ovsdb-server.log`
+
    m4_if([$2], [], [],
      [AT_CHECK([ovsdb-client transact tcp:127.0.0.1:$TCP_PORT $2], [0], [ignore], [ignore], [kill `cat pid`])])
    AT_CHECK([$PYTHON $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema tcp:127.0.0.1:$TCP_PORT $3],
             [0], [stdout], [ignore], [kill `cat pid`])
-   AT_CHECK([sort stdout | perl $srcdir/uuidfilt.pl]m4_if([$6],,, [[| $6]]),
+   AT_CHECK([sort stdout | ${PERL} $srcdir/uuidfilt.pl]m4_if([$6],,, [[| $6]]),
             [0], [$4], [], [kill `cat pid`])
    OVSDB_SERVER_SHUTDOWN
    AT_CLEANUP])
index aff5854..df0157a 100644 (file)
@@ -36,7 +36,7 @@ m4_define([OVSDB_CHECK_MONITOR],
             [ignore], [ignore], [kill `cat server-pid client-pid`])
    AT_CHECK([ovs-appctl -t "`pwd`"/unixctl -e exit], [0], [ignore], [ignore])
    OVS_WAIT_UNTIL([test ! -e server-pid && test ! -e client-pid])
-   AT_CHECK([perl $srcdir/ovsdb-monitor-sort.pl < output | perl $srcdir/uuidfilt.pl], [0], [$7], [ignore])
+   AT_CHECK([${PERL} $srcdir/ovsdb-monitor-sort.pl < output | ${PERL} $srcdir/uuidfilt.pl], [0], [$7], [ignore])
    AT_CLEANUP])
 
 OVSDB_CHECK_MONITOR([monitor insert into empty table],
index 62eae38..5f73c00 100644 (file)
@@ -31,7 +31,7 @@ m4_define([OVSDB_CHECK_EXECUTION],
      [test ! -e pid || kill `cat pid`])
 cat stdout >> output
 ])
-   AT_CHECK([perl $srcdir/uuidfilt.pl output], [0], [$4], [ignore],
+   AT_CHECK([${PERL} $srcdir/uuidfilt.pl output], [0], [$4], [ignore],
             [test ! -e pid || kill `cat pid`])
    OVSDB_SERVER_SHUTDOWN
    AT_CLEANUP])
@@ -77,7 +77,7 @@ AT_DATA([txnfile], [[ovsdb-client transact unix:socket \
 ]])
 AT_CHECK([ovsdb-server --remote=punix:socket --unixctl="`pwd`"/unixctl db --run="sh txnfile"], [0], [stdout], [])
 cat stdout >> output
-AT_CHECK([perl $srcdir/uuidfilt.pl output], [0],
+AT_CHECK([${PERL} $srcdir/uuidfilt.pl output], [0],
   [[[{"uuid":["uuid","<0>"]}]
 [{"uuid":["uuid","<1>"]}]
 [{"rows":[{"_uuid":["uuid","<0>"],"_version":["uuid","<2>"],"name":"zero","number":0},{"_uuid":["uuid","<1>"],"_version":["uuid","<3>"],"name":"one","number":1}]}]
@@ -125,7 +125,7 @@ AT_DATA([txnfile], [[ovsdb-client transact unix:socket \
 ]])
 AT_CHECK([ovsdb-server --remote=punix:socket --unixctl="`pwd`"/unixctl db --run="sh txnfile"], [0], [stdout], [])
 cat stdout >> output
-AT_CHECK([perl $srcdir/uuidfilt.pl output], [0],
+AT_CHECK([${PERL} $srcdir/uuidfilt.pl output], [0],
   [[[{"uuid":["uuid","<0>"]}]
 [{"uuid":["uuid","<1>"]}]
 [{"rows":[{"_uuid":["uuid","<0>"],"_version":["uuid","<2>"],"name":"zero","number":0},{"_uuid":["uuid","<1>"],"_version":["uuid","<3>"],"name":"one","number":1}]}]
@@ -222,13 +222,55 @@ AT_CHECK(
         "columns": ["target", "is_connected"]}]']],
   [0], [stdout], [ignore])
 AT_CHECK(
-  [perl $srcdir/uuidfilt.pl stdout], 
+  [${PERL} $srcdir/uuidfilt.pl stdout], 
   [0], 
   [[[{"rows":[{"managers":"punix:socket1"}]},{"rows":[{"is_connected":false,"target":"punix:socket2"}]}]
 ]], 
   [ignore])
 AT_CLEANUP
 
+AT_SETUP([ovsdb-server/add-remote and remove-remote])
+AT_KEYWORDS([ovsdb server positive])
+OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+OVS_LOGDIR=`pwd`; export OVS_LOGDIR
+ordinal_schema > schema
+AT_CHECK([ovsdb-tool create db schema], [0], [ignore], [ignore])
+ON_EXIT([kill `cat *.pid`])
+AT_CHECK([ovsdb-server --detach --no-chdir --pidfile db])
+
+AT_CHECK([test ! -e socket1])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-remote punix:socket1])
+OVS_WAIT_UNTIL([test -S socket1])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes],
+  [0], [punix:socket1
+])
+
+AT_CHECK([test ! -e socket2])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-remote punix:socket2])
+OVS_WAIT_UNTIL([test -S socket2])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes],
+  [0], [punix:socket1
+punix:socket2
+])
+
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-remote db:x,y,z], [2],
+  [], ["db:x,y,z": no database named x
+ovs-appctl: ovsdb-server: server returned an error
+])
+
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-remote punix:socket1])
+OVS_WAIT_UNTIL([test ! -e socket1])
+AT_CHECK([test -S socket2])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes],
+  [0], [punix:socket2
+])
+
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-remote punix:socket2])
+OVS_WAIT_UNTIL([test ! -e socket2])
+AT_CHECK([test ! -e socket1])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes])
+AT_CLEANUP
+
 AT_SETUP([SSL db: implementation])
 AT_KEYWORDS([ovsdb server positive ssl $5])
 AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
@@ -254,15 +296,15 @@ AT_CHECK(
                 "certificate": "'"$PKIDIR/testpki-cert2.pem"'",
                 "ca_cert": "'"$PKIDIR/testpki-cacert.pem"'"}}]']],
   [0], [ignore], [ignore])
-AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
-SSL_PORT=`cat stdout`
+OVS_LOGDIR=`pwd`; export OVS_LOGDIR
 AT_CHECK(
-  [ovsdb-server --detach --no-chdir --pidfile="`pwd`"/pid \
+  [ovsdb-server --log-file --detach --no-chdir --pidfile="`pwd`"/pid \
         --private-key=db:SSL,private_key \
         --certificate=db:SSL,certificate \
         --ca-cert=db:SSL,ca_cert \
-         --remote=pssl:$SSL_PORT:127.0.0.1 --unixctl="`pwd`"/unixctl db],
+        --remote=pssl:0:127.0.0.1 --unixctl="`pwd`"/unixctl db],
   [0], [ignore], [ignore])
+SSL_PORT=`parse_listening_port < ovsdb-server.log`
 AT_CHECK(
   [[ovsdb-client \
         --private-key=$PKIDIR/testpki-privkey.pem \
@@ -277,7 +319,7 @@ AT_CHECK(
   [0], [stdout], [ignore], [test ! -e pid || kill `cat pid`])
 cat stdout >> output
 AT_CHECK_UNQUOTED(
-  [perl $srcdir/uuidfilt.pl output], [0], 
+  [${PERL} $srcdir/uuidfilt.pl output], [0], 
   [[[{"rows":[{"private_key":"$PKIDIR/testpki-privkey2.pem"}]}]
 ]], [ignore], [test ! -e pid || kill `cat pid`])
 OVSDB_SERVER_SHUTDOWN
@@ -326,7 +368,7 @@ AT_CHECK(
     done]],
   [0], [stdout], [ignore], [test ! -e pid || kill `cat pid`])
 dnl Check that all the crap is in fact in the database log.
-AT_CHECK([[perl $srcdir/uuidfilt.pl db | grep -v ^OVSDB | sed 's/"_date":[0-9]*/"_date":0/' | test-json --multiple -]], [0],
+AT_CHECK([[${PERL} $srcdir/uuidfilt.pl db | grep -v ^OVSDB | sed 's/"_date":[0-9]*/"_date":0/' | test-json --multiple -]], [0],
   [[{"cksum":"12345678 9","name":"ordinals","tables":{"ordinals":{"columns":{"name":{"type":"string"},"number":{"type":"integer"}},"indexes":[["number"]]}},"version":"5.1.3"}
 {"_comment":"add row for zero 0","_date":0,"ordinals":{"<0>":{"name":"zero"}}}
 {"_comment":"delete row for 0","_date":0,"ordinals":{"<0>":null}}
@@ -350,7 +392,7 @@ AT_CHECK([[perl $srcdir/uuidfilt.pl db | grep -v ^OVSDB | sed 's/"_date":[0-9]*/
 dnl Dump out and check the actual database contents.
 AT_CHECK([[ovsdb-client dump unix:socket ordinals]],
   [0], [stdout], [ignore])
-AT_CHECK([perl $srcdir/uuidfilt.pl stdout], [0], [dnl
+AT_CHECK([${PERL} $srcdir/uuidfilt.pl stdout], [0], [dnl
 ordinals table
 _uuid                                name  number
 ------------------------------------ ----- ------
@@ -379,7 +421,7 @@ AT_CHECK([test `wc -l < db` -eq 4], [0], [], [],
 dnl And check that the dumped data is the same too:
 AT_CHECK([ovsdb-client dump unix:socket ordinals], [0], [stdout], [ignore],
   [test ! -e pid || kill `cat pid`])
-AT_CHECK([perl $srcdir/uuidfilt.pl stdout], [0], [dnl
+AT_CHECK([${PERL} $srcdir/uuidfilt.pl stdout], [0], [dnl
 ordinals table
 _uuid                                name  number
 ------------------------------------ ----- ------
@@ -405,7 +447,7 @@ AT_CHECK([test `wc -l < db` -eq 6], [0], [], [],
 dnl Then check that the dumped data is correct.
 AT_CHECK([ovsdb-client dump unix:socket ordinals], [0], [stdout], [ignore],
   [test ! -e pid || kill `cat pid`])
-AT_CHECK([perl $srcdir/uuidfilt.pl stdout], [0], [dnl
+AT_CHECK([${PERL} $srcdir/uuidfilt.pl stdout], [0], [dnl
 ordinals table
 _uuid                                name  number
 ------------------------------------ ----- ------
@@ -437,18 +479,18 @@ m4_define([OVSDB_CHECK_EXECUTION],
    AT_KEYWORDS([ovsdb server positive ssl $5])
    AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
    OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+   OVS_LOGDIR=`pwd`; export OVS_LOGDIR
    $2 > schema
-   AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
-   SSL_PORT=`cat stdout`
    PKIDIR=$abs_top_builddir/tests
    AT_CHECK([ovsdb-tool create db schema], [0], [stdout], [ignore])
-   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile="`pwd`"/pid --private-key=$PKIDIR/testpki-privkey2.pem --certificate=$PKIDIR/testpki-cert2.pem --ca-cert=$PKIDIR/testpki-cacert.pem --remote=pssl:$SSL_PORT:127.0.0.1 --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore])
+   AT_CHECK([ovsdb-server --log-file --detach --no-chdir --pidfile="`pwd`"/pid --private-key=$PKIDIR/testpki-privkey2.pem --certificate=$PKIDIR/testpki-cert2.pem --ca-cert=$PKIDIR/testpki-cacert.pem --remote=pssl:0:127.0.0.1 --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore])
+   SSL_PORT=`parse_listening_port < ovsdb-server.log`
    m4_foreach([txn], [$3], 
      [AT_CHECK([ovsdb-client --private-key=$PKIDIR/testpki-privkey.pem --certificate=$PKIDIR/testpki-cert.pem --ca-cert=$PKIDIR/testpki-cacert.pem transact ssl:127.0.0.1:$SSL_PORT 'txn'], [0], [stdout], [ignore],
      [test ! -e pid || kill `cat pid`])
 cat stdout >> output
 ])
-   AT_CHECK([perl $srcdir/uuidfilt.pl output], [0], [$4], [ignore],
+   AT_CHECK([${PERL} $srcdir/uuidfilt.pl output], [0], [$4], [ignore],
             [test ! -e pid || kill `cat pid`])
    OVSDB_SERVER_SHUTDOWN
    AT_CLEANUP])
@@ -460,10 +502,10 @@ AT_BANNER([OVSDB -- ovsdb-server transactions (TCP sockets)])
 AT_SETUP([ovsdb-client get-schema-version - tcp socket])
 AT_KEYWORDS([ovsdb server positive tcp])
 ordinal_schema > schema
-AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
-TCP_PORT=`cat stdout`
 AT_CHECK([ovsdb-tool create db schema], [0], [ignore], [ignore])
-AT_CHECK([ovsdb-server --detach --no-chdir --pidfile="`pwd`"/pid --unixctl="`pwd`"/unixctl --remote=ptcp:$TCP_PORT:127.0.0.1 db], [0], [ignore], [ignore])
+OVS_LOGDIR=`pwd`; export OVS_LOGDIR
+AT_CHECK([ovsdb-server --log-file --detach --no-chdir --pidfile="`pwd`"/pid --unixctl="`pwd`"/unixctl --remote=ptcp:0:127.0.0.1 db], [0], [ignore], [ignore])
+TCP_PORT=`parse_listening_port < ovsdb-server.log`
 AT_CHECK([ovsdb-client get-schema-version tcp:127.0.0.1:$TCP_PORT ordinals], [0], [5.1.3
 ])
 OVSDB_SERVER_SHUTDOWN
@@ -487,18 +529,18 @@ m4_define([OVSDB_CHECK_EXECUTION],
   [AT_SETUP([$1])
    AT_KEYWORDS([ovsdb server positive tcp $5])
    OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+   OVS_LOGDIR=`pwd`; export OVS_LOGDIR
    $2 > schema
-   AT_CHECK([perl $srcdir/choose-port.pl], [0], [stdout])
-   TCP_PORT=`cat stdout`
    PKIDIR=$abs_top_builddir/tests
    AT_CHECK([ovsdb-tool create db schema], [0], [stdout], [ignore])
-   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile="`pwd`"/pid --remote=ptcp:$TCP_PORT:127.0.0.1 --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore])
+   AT_CHECK([ovsdb-server --log-file --detach --no-chdir --pidfile="`pwd`"/pid --remote=ptcp:0:127.0.0.1 --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore])
+   TCP_PORT=`parse_listening_port < ovsdb-server.log`
    m4_foreach([txn], [$3],
      [AT_CHECK([ovsdb-client transact tcp:127.0.0.1:$TCP_PORT 'txn'], [0], [stdout], [ignore],
      [test ! -e pid || kill `cat pid`])
 cat stdout >> output
 ])
-   AT_CHECK([perl $srcdir/uuidfilt.pl output], [0], [$4], [ignore],
+   AT_CHECK([${PERL} $srcdir/uuidfilt.pl output], [0], [$4], [ignore],
             [test ! -e pid || kill `cat pid`])
    OVSDB_SERVER_SHUTDOWN
    AT_CLEANUP])
@@ -536,7 +578,7 @@ m4_define([OVSDB_CHECK_EXECUTION],
       AT_CHECK([ovsdb-server --remote=punix:socket --unixctl="`pwd`"/unixctl db --run="sh txnfile"], [0], [stdout], [ignore])
       cat stdout >> output
 ])
-   AT_CHECK([perl $srcdir/uuidfilt.pl output], [0], [$4], [ignore])
+   AT_CHECK([${PERL} $srcdir/uuidfilt.pl output], [0], [$4], [ignore])
    AT_CLEANUP])
 
 EXECUTION_EXAMPLES
index 286d700..3282e0e 100644 (file)
@@ -24,7 +24,7 @@ m4_define([OVSDB_CHECK_EXECUTION],
      [AT_CHECK([ovsdb-tool transact db 'txn'], [0], [stdout], [ignore])
 cat stdout >> output
 ])
-   AT_CHECK([perl $srcdir/uuidfilt.pl output], [0], [$4])
+   AT_CHECK([${PERL} $srcdir/uuidfilt.pl output], [0], [$4])
    AT_CLEANUP])
 
 EXECUTION_EXAMPLES
@@ -41,7 +41,7 @@ AT_CHECK([[ovsdb-tool transact db '
       "row": {"name": "five", "number": 5}},
      {"op": "comment",
       "comment": "add row for 5"}]']], [0], [stdout], [ignore])
-AT_CHECK([perl $srcdir/uuidfilt.pl stdout], [0],
+AT_CHECK([${PERL} $srcdir/uuidfilt.pl stdout], [0],
  [[[{"uuid":["uuid","<0>"]},{}]
 ]])
 AT_CHECK([grep "add row for 5" db], [0], [ignore])
@@ -91,7 +91,7 @@ AT_CHECK(
     done]],
   [0], [stdout], [ignore])
 dnl Check that all the crap is in fact in the database log.
-AT_CHECK([[perl $srcdir/uuidfilt.pl db | grep -v ^OVSDB | sed 's/"_date":[0-9]*/"_date":0/' | test-json --multiple -]], [0],
+AT_CHECK([[${PERL} $srcdir/uuidfilt.pl db | grep -v ^OVSDB | sed 's/"_date":[0-9]*/"_date":0/' | test-json --multiple -]], [0],
   [[{"cksum":"12345678 9","name":"ordinals","tables":{"ordinals":{"columns":{"name":{"type":"string"},"number":{"type":"integer"}},"indexes":[["number"]]}},"version":"5.1.3"}
 {"_comment":"add row for zero 0","_date":0,"ordinals":{"<0>":{"name":"zero"}}}
 {"_comment":"delete row for 0","_date":0,"ordinals":{"<0>":null}}
@@ -115,7 +115,7 @@ AT_CHECK([[perl $srcdir/uuidfilt.pl db | grep -v ^OVSDB | sed 's/"_date":[0-9]*/
 dnl Dump out and check the actual database contents.
 AT_CHECK([[ovsdb-server --unixctl="`pwd`"/unixctl --remote=punix:socket --run "ovsdb-client dump unix:socket ordinals" db]],
   [0], [stdout], [ignore])
-AT_CHECK([perl $srcdir/uuidfilt.pl stdout], [0], [dnl
+AT_CHECK([${PERL} $srcdir/uuidfilt.pl stdout], [0], [dnl
 ordinals table
 _uuid                                name  number
 ------------------------------------ ----- ------
@@ -142,7 +142,7 @@ AT_CHECK([test `wc -l < db` -eq 4])
 dnl And check that the dumped data is the same too:
 AT_CHECK([[ovsdb-server --unixctl="`pwd`"/unixctl --remote=punix:socket --run "ovsdb-client dump unix:socket ordinals" db]],
   [0], [stdout], [ignore])
-AT_CHECK([perl $srcdir/uuidfilt.pl stdout], [0], [dnl
+AT_CHECK([${PERL} $srcdir/uuidfilt.pl stdout], [0], [dnl
 ordinals table
 _uuid                                name  number
 ------------------------------------ ----- ------
@@ -184,7 +184,7 @@ AT_CHECK(
 dnl Dump out and check the actual database contents.
 AT_CHECK([[ovsdb-server --unixctl="`pwd`"/unixctl --remote=punix:socket --run "ovsdb-client dump unix:socket ordinals" db]],
   [0], [stdout], [ignore])
-AT_CHECK([perl $srcdir/uuidfilt.pl stdout], [0], [dnl
+AT_CHECK([${PERL} $srcdir/uuidfilt.pl stdout], [0], [dnl
 ordinals table
 _uuid                                name  number
 ------------------------------------ ----- ------
@@ -206,7 +206,7 @@ AT_CHECK([test `wc -l < db` -eq 4])
 dnl And check that the dumped data is the same except for the removed column:
 AT_CHECK([[ovsdb-server --unixctl="`pwd`"/unixctl --remote=punix:socket --run "ovsdb-client dump unix:socket ordinals" db]],
   [0], [stdout], [ignore])
-AT_CHECK([perl $srcdir/uuidfilt.pl stdout], [0], [dnl
+AT_CHECK([${PERL} $srcdir/uuidfilt.pl stdout], [0], [dnl
 ordinals table
 _uuid                                number
 ------------------------------------ ------
@@ -247,7 +247,7 @@ AT_CHECK(
 dnl Dump out and check the actual database contents.
 AT_CHECK([[ovsdb-server --unixctl="`pwd`"/unixctl --remote=punix:socket --run "ovsdb-client dump unix:socket ordinals" db]],
   [0], [stdout], [ignore])
-AT_CHECK([perl $srcdir/uuidfilt.pl stdout], [0], [dnl
+AT_CHECK([${PERL} $srcdir/uuidfilt.pl stdout], [0], [dnl
 ordinals table
 _uuid                                number
 ------------------------------------ ------
@@ -269,7 +269,7 @@ AT_CHECK([test `wc -l < db` -eq 4])
 dnl And check that the dumped data is the same except for the added column:
 AT_CHECK([[ovsdb-server --unixctl="`pwd`"/unixctl --remote=punix:socket --run "ovsdb-client dump unix:socket ordinals" db]],
   [0], [stdout], [ignore])
-AT_CHECK([perl $srcdir/uuidfilt.pl stdout], [0], [dnl
+AT_CHECK([${PERL} $srcdir/uuidfilt.pl stdout], [0], [dnl
 ordinals table
 _uuid                                name number
 ------------------------------------ ---- ------
index fa2feef..1da6336 100644 (file)
@@ -9,7 +9,7 @@ m4_define([OVSDB_CHECK_TRIGGER],
   [AT_SETUP([$1])
    AT_KEYWORDS([ovsdb execute execution trigger positive $4])
    AT_CHECK([test-ovsdb trigger $2], [0], [stdout], [])
-   AT_CHECK([perl $srcdir/uuidfilt.pl stdout], [0], [$3])
+   AT_CHECK([${PERL} $srcdir/uuidfilt.pl stdout], [0], [$3])
    AT_CLEANUP])
 
 OVSDB_CHECK_TRIGGER([trigger fires immediately],
index 7cc708a..616ff2e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -56,7 +56,7 @@ parse_options(int argc, char *argv[])
         OPT_BOOTSTRAP_CA_CERT = UCHAR_MAX + 1,
         DAEMON_OPTION_ENUMS
     };
-    static struct option long_options[] = {
+    static const struct option long_options[] = {
         {"verbose", optional_argument, NULL, 'v'},
         {"help", no_argument, NULL, 'h'},
         DAEMON_LONG_OPTIONS,
index 5147a20..921f0fd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -234,12 +234,13 @@ static void
 parse_options(int argc, char *argv[])
 {
     enum {
-        DAEMON_OPTION_ENUMS
+        DAEMON_OPTION_ENUMS,
+        VLOG_OPTION_ENUMS
     };
-    static struct option long_options[] = {
-        {"verbose", optional_argument, NULL, 'v'},
+    static const struct option long_options[] = {
         {"help", no_argument, NULL, 'h'},
         DAEMON_LONG_OPTIONS,
+        VLOG_LONG_OPTIONS,
         {NULL, 0, NULL, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
@@ -254,11 +255,8 @@ parse_options(int argc, char *argv[])
         case 'h':
             usage();
 
-        case 'v':
-            vlog_set_verbosity(optarg);
-            break;
-
         DAEMON_OPTION_HANDLERS
+        VLOG_OPTION_HANDLERS
 
         case '?':
             exit(EXIT_FAILURE);
index 658259e..10d434e 100644 (file)
@@ -68,7 +68,7 @@ main(int argc, char *argv[])
 static void
 parse_options(int argc, char *argv[])
 {
-    static struct option long_options[] = {
+    static const struct option long_options[] = {
         {"timeout", required_argument, NULL, 't'},
         {"verbose", optional_argument, NULL, 'v'},
         {"help", no_argument, NULL, 'h'},
index 3eb93c5..edb996c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2011, 2012, 2013 Nicira, Inc.
  * Copyright (c) 2013 InMon Corp.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -556,12 +556,14 @@ static void
 parse_options(int argc, char *argv[])
 {
     enum {
-        DAEMON_OPTION_ENUMS
+        DAEMON_OPTION_ENUMS,
+        VLOG_OPTION_ENUMS
     };
-    static struct option long_options[] = {
+    static const struct option long_options[] = {
         {"verbose", optional_argument, NULL, 'v'},
         {"help", no_argument, NULL, 'h'},
         DAEMON_LONG_OPTIONS,
+        VLOG_LONG_OPTIONS,
         {NULL, 0, NULL, 0},
     };
     char *short_options = long_options_to_short_options(long_options);
@@ -576,11 +578,8 @@ parse_options(int argc, char *argv[])
         case 'h':
             usage();
 
-        case 'v':
-            vlog_set_verbosity(optarg);
-            break;
-
-            DAEMON_OPTION_HANDLERS
+        DAEMON_OPTION_HANDLERS
+        VLOG_OPTION_HANDLERS
 
         case '?':
             exit(EXIT_FAILURE);
index 3eecc7a..3422af3 100644 (file)
@@ -363,7 +363,7 @@ parse_options(int argc, char *argv[])
     enum {
         VLOG_OPTION_ENUMS
     };
-    static struct option long_options[] = {
+    static const struct option long_options[] = {
         VLOG_LONG_OPTIONS,
         {NULL, 0, NULL, 0},
     };
index 97bc247..da52593 100644 (file)
@@ -1,6 +1,6 @@
 AT_INIT
 
-AT_COPYRIGHT([Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
+AT_COPYRIGHT([Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -95,6 +95,7 @@ m4_include([tests/timeval.at])
 m4_include([tests/tunnel.at])
 m4_include([tests/lockfile.at])
 m4_include([tests/reconnect.at])
+m4_include([tests/ovs-vswitchd.at])
 m4_include([tests/ofproto.at])
 m4_include([tests/ofproto-dpif.at])
 m4_include([tests/ovsdb.at])
index 78e43f5..2eabb77 100644 (file)
@@ -398,7 +398,7 @@ br0 (dummy@ovs-dummy):
 
 dnl change UDP port to default
 
-AT_CHECK([ovs-vsctl -- set Interface p1 options:dst_port=8472])
+AT_CHECK([ovs-vsctl -- set Interface p1 options:dst_port=4789])
 
 AT_CHECK([ovs-appctl dpif/show], [0], [dnl
 br0 (dummy@ovs-dummy):
diff --git a/tutorial/.gitignore b/tutorial/.gitignore
new file mode 100644 (file)
index 0000000..97f3e31
--- /dev/null
@@ -0,0 +1 @@
+sandbox/
diff --git a/tutorial/Tutorial b/tutorial/Tutorial
new file mode 100644 (file)
index 0000000..c537bad
--- /dev/null
@@ -0,0 +1,835 @@
+Open vSwitch Advanced Features Tutorial
+=======================================
+
+Many tutorials cover the basics of OpenFlow.  This is not such a
+tutorial.  Rather, a knowledge of the basics of OpenFlow is a
+prerequisite.  If you do not already understand how an OpenFlow flow
+table works, please go read a basic tutorial and then continue reading
+here afterward.
+
+It is also important to understand the basics of Open vSwitch before
+you begin.  If you have never used ovs-vsctl or ovs-ofctl before, you
+should learn a little about them before proceeding.
+
+Most of the features covered in this tutorial are Open vSwitch
+extensions to OpenFlow.  Also, most of the features in this tutorial
+are specific to the software Open vSwitch implementation.  If you are
+using an Open vSwitch port to an ASIC-based hardware switch, this
+tutorial will not help you.
+
+This tutorial does not cover every aspect of the features that it
+mentions.  You can find the details elsewhere in the Open vSwitch
+documentation, especially ovs-ofctl(8) and the comments in the
+include/openflow/nicira-ext.h header file.
+
+>>> In this tutorial, paragraphs set off like this designate notes
+    with additional information that readers may wish to skip on a
+    first read.
+
+
+Getting Started
+===============
+
+This is a hands-on tutorial.  To get the most out of it, you will need
+Open vSwitch binaries.  You do not, on the other hand, need any
+physical networking hardware or even supervisor privilege on your
+system.  Instead, we will use a script called "ovs-sandbox", which
+accompanies the tutorial, that constructs a software simulated network
+environment based on Open vSwitch.
+
+You can use "ovs-sandbox" three ways:
+
+    * If you have already installed Open vSwitch on your system, then
+      you should be able to just run "ovs-sandbox" from this directory
+      without any options.
+
+    * If you have not installed Open vSwitch (and you do not want to
+      install it), then you can build Open vSwitch according to the
+      instructions in INSTALL, without installing it.  Then run
+      "./ovs-sandbox -b DIRECTORY" from this directory, substituting
+      the Open vSwitch build directory for DIRECTORY.
+
+    * As a slight variant on the latter, you can run "make sandbox"
+      from an Open vSwitch build directory.
+
+When you run ovs-sandbox, it does the following:
+
+    1. CAUTION: Deletes any subdirectory of the current directory
+       named "sandbox" and any files in that directory.
+
+    2. Creates a new directory "sandbox" in the current directory.
+
+    3. Sets up special environment variables that ensure that Open
+       vSwitch programs will look inside the "sandbox" directory
+       instead of in the Open vSwitch installation directory.
+
+    4. If you are using a built but not installed Open vSwitch,
+       installs the Open vSwitch manpages in a subdirectory of
+       "sandbox" and adjusts the MANPATH environment variable to point
+       to this directory.  This means that you can use, for example,
+       "man ovs-vsctl" to see a manpage for the ovs-vsctl program that
+       you built.
+
+    5. Creates an empty Open vSwitch configuration database under
+       "sandbox".
+
+    6. Starts ovsdb-server running under "sandbox".
+
+    7. Starts ovs-vswitchd running under "sandbox", passing special
+       options that enable a special "dummy" mode for testing.
+
+    8. Starts a nested interactive shell inside "sandbox".
+
+At this point, you can run all the usual Open vSwitch utilities from
+the nested shell environment.  You can, for example, use ovs-vsctl to
+create a bridge:
+
+    ovs-vsctl add-br br0
+
+From Open vSwitch's perspective, the bridge that you create this way
+is as real as any other.  You can, for example, connect it to an
+OpenFlow controller or use "ovs-ofctl" to examine and modify it and
+its OpenFlow flow table.  On the other hand, the bridge is not visible
+to the operating system's network stack, so "ifconfig" or "ip" cannot
+see it or affect it, which means that utilities like "ping" and
+"tcpdump" will not work either.  (That has its good side, too: you
+can't screw up your computer's network stack by manipulating a
+sandboxed OVS.)
+
+When you're done using OVS from the sandbox, exit the nested shell (by
+entering the "exit" shell command or pressing Control+D).  This will
+kill the daemons that ovs-sandbox started, but it leaves the "sandbox"
+directory and its contents in place.
+
+The sandbox directory contains log files for the Open vSwitch dameons.
+You can examine them while you're running in the sandboxed environment
+or after you exit.
+
+
+Motivation
+==========
+
+The goal of this tutorial is to demonstrate the power of Open vSwitch
+flow tables.  The tutorial works through the implementation of a
+MAC-learning switch with VLAN trunk and access ports.  Outside of the
+Open vSwitch features that we will discuss, OpenFlow provides at least
+two ways to implement such a switch:
+
+    1. An OpenFlow controller to implement MAC learning in a
+       "reactive" fashion.  Whenever a new MAC appears on the switch,
+       or a MAC moves from one switch port to another, the controller
+       adjusts the OpenFlow flow table to match.
+
+    2. The "normal" action.  OpenFlow defines this action to submit a
+       packet to "the traditional non-OpenFlow pipeline of the
+       switch".  That is, if a flow uses this action, then the packets
+       in the flow go through the switch in the same way that they
+       would if OpenFlow was not configured on the switch.
+
+Each of these approaches has unfortunate pitfalls.  In the first
+approach, using an OpenFlow controller to implement MAC learning, has
+a significant cost in terms of network bandwidth and latency.  It also
+makes the controller more difficult to scale to large numbers of
+switches, which is especially important in environments with thousands
+of hypervisors (each of which contains a virtual OpenFlow switch).
+MAC learning at an OpenFlow controller also behaves poorly if the
+OpenFlow controller fails, slows down, or becomes unavailable due to
+network problems.
+
+The second approach, using the "normal" action, has different
+problems.  First, little about the "normal" action is standardized, so
+it behaves differently on switches from different vendors, and the
+available features and how those features are configured (usually not
+through OpenFlow) varies widely.  Second, "normal" does not work well
+with other OpenFlow actions.  It is "all-or-nothing", with little
+potential to adjust its behavior slightly or to compose it with other
+features.
+
+
+Scenario
+========
+
+We will construct Open vSwitch flow tables for a VLAN-capable,
+MAC-learning switch that has four ports:
+
+    * p1, a trunk port that carries all VLANs, on OpenFlow port 1.
+
+    * p2, an access port for VLAN 20, on OpenFlow port 2.
+
+    * p3 and p4, both access ports for VLAN 30, on OpenFlow ports 3
+      and 4, respectively.
+
+>>> The ports' names are not significant.  You could call them eth1
+    through eth4, or any other names you like.
+
+>>> An OpenFlow switch always has a "local" port as well.  This
+    scenario won't use the local port.
+
+Our switch design will consist of five main flow tables, each of which
+implements one stage in the switch pipeline:
+
+    Table 0: Admission control.
+
+    Table 1: VLAN input processing.
+
+    Table 2: Learn source MAC and VLAN for ingress port.
+
+    Table 3: Look up learned port for destination MAC and VLAN.
+
+    Table 4: Output processing.
+
+The section below describes how to set up the scenario, followed by a
+section for each OpenFlow table.
+
+You can cut and paste the "ovs-vsctl" and "ovs-ofctl" commands in each
+of the sections below into your "ovs-sandbox" shell.  They are also
+available as shell scripts in this directory, named t-setup, t-stage0,
+t-stage1, ..., t-stage4.  The "ovs-appctl" test commands are intended
+for cutting and pasting and are not supplied separately.
+
+
+Setup
+=====
+
+To get started, start "ovs-sandbox".  Inside the interactive shell
+that it starts, run this command:
+
+    ovs-vsctl add-br br0 -- set Bridge br0 fail-mode=secure
+
+This command creates a new bridge "br0" and puts "br0" into so-called
+"fail-secure" mode.  For our purpose, this just means that the
+OpenFlow flow table starts out empty.
+
+>>> If we did not do this, then the flow table would start out with a
+    single flow that executes the "normal" action.  We could use that
+    feature to yield a switch that behaves the same as the switch we
+    are currently building, but with the caveats described under
+    "Motivation" above.)
+
+The new bridge has only one port on it so far, the "local port" br0.
+We need to add p1, p2, p3, and p4.  A shell "for" loop is one way to
+do it:
+
+    for i in 1 2 3 4; do
+        ovs-vsctl add-port br0 p$i -- set Interface p$i ofport_request=$i
+       ovs-ofctl mod-port br0 p$i up
+    done
+
+In addition to adding a port, the ovs-vsctl command above sets its
+"ofport_request" column to ensure that port p1 is assigned OpenFlow
+port 1, p2 is assigned OpenFlow port 2, and so on.
+
+>>> We could omit setting the ofport_request and let Open vSwitch
+    choose port numbers for us, but it's convenient for the purposes
+    of this tutorial because we can talk about OpenFlow port 1 and
+    know that it corresponds to p1.
+
+The ovs-ofctl command above brings up the simulated interfaces, which
+are down initially, using an OpenFlow request.  The effect is similar
+to "ifconfig up", but the sandbox's interfaces are not visible to the
+operating system and therefore "ifconfig" would not affect them.
+
+We have not configured anything related to VLANs or MAC learning.
+That's because we're going to implement those features in the flow
+table.
+
+To see what we've done so far to set up the scenario, you can run a
+command like "ovs-vsctl show" or "ovs-ofctl show br0".
+
+
+Implementing Table 0: Admission control
+=======================================
+
+Table 0 is where packets enter the switch.  We use this stage to
+discard packets that for one reason or another are invalid.  For
+example, packets with a multicast source address are not valid, so we
+can add a flow to drop them at ingress to the switch with:
+
+    ovs-ofctl add-flow br0 \
+        "table=0, dl_src=01:00:00:00:00:00/01:00:00:00:00:00, actions=drop"
+
+A switch should also not forward IEEE 802.1D Spanning Tree Protocol
+(STP) packets, so we can also add a flow to drop those and other
+packets with reserved multicast protocols:
+
+    ovs-ofctl add-flow br0 \
+        "table=0, dl_dst=01:08:c2:00:00:00/ff:ff:ff:ff:ff:f0, actions=drop"
+
+We could add flows to drop other protocols, but these demonstrate the
+pattern.
+
+We need one more flow, with a priority lower than the default, so that
+flows that don't match either of the "drop" flows we added above go on
+to pipeline stage 1 in OpenFlow table 1:
+
+    ovs-ofctl add-flow br0 "table=0, priority=0, actions=resubmit(,1)"
+
+(The "resubmit" action is an Open vSwitch extension to OpenFlow.)
+
+
+Testing Table 0
+---------------
+
+If we were using Open vSwitch to set up a physical or a virtual
+switch, then we would naturally test it by sending packets through it
+one way or another, perhaps with common network testing tools like
+"ping" and "tcpdump" or more specialized tools like Scapy.  That's
+difficult with our simulated switch, since it's not visible to the
+operating system.
+
+But our simulated switch has a few specialized testing tools.  The
+most powerful of these tools is "ofproto/trace".  Given a switch and
+the specification of a flow, "ofproto/trace" shows, step-by-step, how
+such a flow would be treated as it goes through the switch.
+
+
+== EXAMPLE 1 ==
+
+Try this command:
+
+    ovs-appctl ofproto/trace br0 in_port=1,dl_dst=01:08:c2:00:00:05
+
+The output should look something like this:
+
+    Flow: metadata=0,in_port=1,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=01:08:c2:00:00:05,dl_type=0x0000
+    Rule: table=0 cookie=0 dl_dst=01:08:c2:00:00:00/ff:ff:ff:ff:ff:f0
+    OpenFlow actions=drop
+
+    Final flow: unchanged
+    Datapath actions: drop
+
+The first block of lines describes an OpenFlow table lookup.  The
+first line shows the fields used for the table lookup (which is mostly
+zeros because that's the default if we don't specify everything).  The
+second line gives the OpenFlow flow that the fields matched (called a
+"rule" because that is the name used inside Open vSwitch for an
+OpenFlow flow).  In this case, we see that this packet that has a
+reserved multicast destination address matches the rule that drops
+those packets.  The third line gives the rule's OpenFlow actions.
+
+The second block of lines summarizes the results, which are not very
+interesting here.
+
+
+== EXAMPLE 2 ==
+
+Try another command:
+
+    ovs-appctl ofproto/trace br0 in_port=1,dl_dst=01:08:c2:00:00:10
+
+The output should be:
+
+    Flow: metadata=0,in_port=1,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=01:08:c2:00:00:10,dl_type=0x0000
+    Rule: table=0 cookie=0 priority=0
+    OpenFlow actions=resubmit(,1)
+
+           Resubmitted flow: unchanged
+           Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
+           Resubmitted  odp: drop
+           No match
+
+    Final flow: unchanged
+    Datapath actions: drop
+
+This time the flow we handed to "ofproto/trace" doesn't match any of
+our "drop" rules, so it falls through to the low-priority "resubmit"
+rule, which we see in the rule and the actions selected in the first
+block.  The "resubmit" causes a second lookup in OpenFlow table 1,
+described by the additional block of indented text in the output.  We
+haven't yet added any flows to OpenFlow table 1, so no flow actually
+matches in the second lookup.  Therefore, the packet is still actually
+dropped, which means that the externally observable results would be
+identical to our first example.
+
+
+Implementing Table 1: VLAN Input Processing
+===========================================
+
+A packet that enters table 1 has already passed basic validation in
+table 0.  The purpose of table 1 is validate the packet's VLAN, based
+on the VLAN configuration of the switch port through which the packet
+entered the switch.  We will also use it to attach a VLAN header to
+packets that arrive on an access port, which allows later processing
+stages to rely on the packet's VLAN always being part of the VLAN
+header, reducing special cases.
+
+Let's start by adding a low-priority flow that drops all packets,
+before we add flows that pass through acceptable packets.  You can
+think of this as a "default drop" rule:
+
+    ovs-ofctl add-flow br0 "table=1, priority=0, actions=drop"
+
+Our trunk port p1, on OpenFlow port 1, is an easy case.  p1 accepts
+any packet regardless of whether it has a VLAN header or what the VLAN
+was, so we can add a flow that resubmits everything on input port 1 to
+the next table:
+
+    ovs-ofctl add-flow br0 \
+        "table=1, priority=99, in_port=1, actions=resubmit(,2)"
+
+On the access ports, we want to accept any packet that has no VLAN
+header, tag it with the access port's VLAN number, and then pass it
+along to the next stage:
+
+    ovs-ofctl add-flows br0 - <<'EOF'
+       table=1, priority=99, in_port=2, vlan_tci=0, actions=mod_vlan_vid:20, resubmit(,2)
+       table=1, priority=99, in_port=3, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2)
+       table=1, priority=99, in_port=4, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2)
+EOF
+
+We don't write any rules that match packets with 802.1Q that enter
+this stage on any of the access ports, so the "default drop" rule we
+added earlier causes them to be dropped, which is ordinarily what we
+want for access ports.
+
+>>> Another variation of access ports allows ingress of packets tagged
+    with VLAN 0 (aka 802.1p priority tagged packets).  To allow such
+    packets, replace "vlan_tci=0" by "vlan_tci=0/0xfff" above.
+
+
+Testing Table 1
+---------------
+
+"ofproto/trace" allows us to test the ingress VLAN rules that we added
+above.
+
+
+== EXAMPLE 1: Packet on Trunk Port ==
+
+Here's a test of a packet coming in on the trunk port:
+
+    ovs-appctl ofproto/trace br0 in_port=1,vlan_tci=5
+
+The output shows the lookup in table 0, the resubmit to table 1, and
+the resubmit to table 2 (which does nothing because we haven't put
+anything there yet):
+
+    Flow: metadata=0,in_port=1,vlan_tci=0x0005,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
+    Rule: table=0 cookie=0 priority=0
+    OpenFlow actions=resubmit(,1)
+
+           Resubmitted flow: unchanged
+           Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
+           Resubmitted  odp: drop
+           Rule: table=1 cookie=0 priority=99,in_port=1
+           OpenFlow actions=resubmit(,2)
+
+                   Resubmitted flow: unchanged
+                   Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
+                   Resubmitted  odp: drop
+                   No match
+
+    Final flow: unchanged
+    Datapath actions: drop
+
+
+== EXAMPLE 2: Valid Packet on Access Port ==
+
+Here's a test of a valid packet (a packet without an 802.1Q header)
+coming in on access port p2:
+
+    ovs-appctl ofproto/trace br0 in_port=2
+
+The output is similar to that for the previous case, except that it
+additionally tags the packet with p2's VLAN 20 before it passes it
+along to table 2:
+
+    Flow: metadata=0,in_port=2,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
+    Rule: table=0 cookie=0 priority=0
+    OpenFlow actions=resubmit(,1)
+
+           Resubmitted flow: unchanged
+           Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
+           Resubmitted  odp: drop
+           Rule: table=1 cookie=0 priority=99,in_port=2,vlan_tci=0x0000
+           OpenFlow actions=mod_vlan_vid:20,resubmit(,2)
+
+                   Resubmitted flow: metadata=0,in_port=2,dl_vlan=20,dl_vlan_pcp=0,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
+                   Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
+                   Resubmitted  odp: drop
+                   No match
+
+    Final flow: unchanged
+    Datapath actions: drop
+
+
+== EXAMPLE 3: Invalid Packet on Access Port ==
+
+This tests an invalid packet (one that includes an 802.1Q header)
+coming in on access port p2:
+
+    ovs-appctl ofproto/trace br0 in_port=2,vlan_tci=5
+
+The output shows the packet matching the default drop rule:
+
+    Flow: metadata=0,in_port=2,vlan_tci=0x0005,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
+    Rule: table=0 cookie=0 priority=0
+    OpenFlow actions=resubmit(,1)
+
+           Resubmitted flow: unchanged
+           Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
+           Resubmitted  odp: drop
+           Rule: table=1 cookie=0 priority=0
+           OpenFlow actions=drop
+
+    Final flow: unchanged
+    Datapath actions: drop
+
+
+Implementing Table 2: MAC+VLAN Learning for Ingress Port
+========================================================
+
+This table allows the switch we're implementing to learn that the
+packet's source MAC is located on the packet's ingress port in the
+packet's VLAN.
+
+>>> This table is a good example why table 1 added a VLAN tag to
+    packets that entered the switch through an access port.  We want
+    to associate a MAC+VLAN with a port regardless of whether the VLAN
+    in question was originally part of the packet or whether it was an
+    assumed VLAN associated with an access port.
+
+It only takes a single flow to do this.  The following command adds
+it:
+
+    ovs-ofctl add-flow br0 \
+        "table=2 actions=learn(table=10, NXM_OF_VLAN_TCI[0..11], \
+                               NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], \
+                               load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]), \
+                         resubmit(,3)"
+
+The "learn" action (an Open vSwitch extension to OpenFlow) modifies a
+flow table based on the content of the flow currently being processed.
+Here's how you can interpret each part of the "learn" action above:
+
+    table=10
+
+        Modify flow table 10.  This will be the MAC learning table.
+
+    NXM_OF_VLAN_TCI[0..11]
+
+        Make the flow that we add to flow table 10 match the same VLAN
+        ID that the packet we're currently processing contains.  This
+        effectively scopes the MAC learning entry to a single VLAN,
+        which is the ordinary behavior for a VLAN-aware switch.
+
+    NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[]
+
+        Make the flow that we add to flow table 10 match, as Ethernet
+        destination, the Ethernet source address of the packet we're
+        currently processing.
+
+    load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]
+
+        Whereas the preceding parts specify fields for the new flow to
+        match, this specifies an action for the flow to take when it
+        matches.  The action is for the flow to load the ingress port
+        number of the current packet into register 0 (a special field
+        that is an Open vSwitch extension to OpenFlow).
+
+>>> A real use of "learn" for MAC learning would probably involve two
+    additional elements.  First, the "learn" action would specify a
+    hard_timeout for the new flow, to enable a learned MAC to
+    eventually expire if no new packets were seen from a given source
+    within a reasonable interval.  Second, one would usually want to
+    limit resource consumption by using the Flow_Table table in the
+    Open vSwitch configuration database to specify a maximum number of
+    flows in table 10.
+
+This definitely calls for examples.
+
+
+Testing Table 2
+---------------
+
+== EXAMPLE 1 ==
+
+Try the following test command:
+
+    ovs-appctl ofproto/trace br0 in_port=1,vlan_tci=20,dl_src=50:00:00:00:00:01 -generate
+
+The output shows that "learn" was executed, but it isn't otherwise
+informative, so we won't include it here.
+
+The "-generate" keyword is new.  Ordinarily, "ofproto/trace" has no
+side effects: "output" actions do not actually output packets, "learn"
+actions do not actually modify the flow table, and so on.  With
+"-generate", though, "ofproto/trace" does execute "learn" actions.
+That's important now, because we want to see the effect of the "learn"
+action on table 10.  You can see that by running:
+
+    ovs-ofctl dump-flows br0 table=10
+
+which (omitting the "duration" and "idle_age" fields, which will vary
+based on how soon you ran this command after the previous one, as well
+as some other uninteresting fields) prints something like:
+
+    NXST_FLOW reply (xid=0x4):
+     table=10, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
+
+You can see that the packet coming in on VLAN 20 with source MAC
+50:00:00:00:00:01 became a flow that matches VLAN 20 (written in
+hexadecimal) and destination MAC 50:00:00:00:00:01.  The flow loads
+port number 1, the input port for the flow we tested, into register 0.
+
+
+== EXAMPLE 2 ==
+
+Here's a second test command:
+
+    ovs-appctl ofproto/trace br0 in_port=2,dl_src=50:00:00:00:00:01 -generate
+
+The flow that this command tests has the same source MAC and VLAN as
+example 1, although the VLAN comes from an access port VLAN rather
+than an 802.1Q header.  If we again dump the flows for table 10 with:
+
+    ovs-ofctl dump-flows br0 table=10
+
+then we see that the flow we saw previously has changed to indicate
+that the learned port is port 2, as we would expect:
+
+    NXST_FLOW reply (xid=0x4):
+     table=10, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x2->NXM_NX_REG0[0..15]
+
+
+Implementing Table 3: Look Up Destination Port
+==============================================
+
+This table figures out what port we should send the packet to based on
+the destination MAC and VLAN.  That is, if we've learned the location
+of the destination (from table 2 processing some previous packet with
+that destination as its source), then we want to send the packet
+there.
+
+We need only one flow to do the lookup:
+
+    ovs-ofctl add-flow br0 \
+        "table=3 priority=50 actions=resubmit(,10), resubmit(,4)"
+
+The flow's first action resubmits to table 10, the table that the
+"learn" action modifies.  As you saw previously, the learned flows in
+this table write the learned port into register 0.  If the destination
+for our packet hasn't been learned, then there will be no matching
+flow, and so the "resubmit" turns into a no-op.  Because registers are
+initialized to 0, we can use a register 0 value of 0 in our next
+pipeline stage as a signal to flood the packet.
+
+The second action resubmits to table 4, continuing to the next
+pipeline stage.
+
+We can add another flow to skip the learning table lookup for
+multicast and broadcast packets, since those should always be flooded:
+
+    ovs-ofctl add-flow br0 \
+        "table=3 priority=99 dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 \
+          actions=resubmit(,4)"
+
+>>> We don't strictly need to add this flow, because multicast
+    addresses will never show up in our learning table.  (In turn,
+    that's because we put a flow into table 0 to drop packets that
+    have a multicast source address.)
+
+
+Testing Table 3
+---------------
+
+== EXAMPLE ==
+
+Here's a command that should cause OVS to learn that f0:00:00:00:00:01
+is on p1 in VLAN 20:
+
+    ovs-appctl ofproto/trace br0 in_port=1,dl_vlan=20,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01 -generate
+
+Here's an excerpt from the output that shows (from the "no match"
+looking up the resubmit to table 10) that the flow's destination was
+unknown:
+
+                       Resubmitted flow: unchanged
+                       Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
+                       Resubmitted  odp: drop
+                       Rule: table=3 cookie=0 priority=50
+                       OpenFlow actions=resubmit(,10),resubmit(,4)
+
+                               Resubmitted flow: unchanged
+                               Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
+                               Resubmitted  odp: drop
+                               No match
+
+You can verify that the packet's source was learned two ways.  The
+most direct way is to dump the learning table with:
+
+    ovs-ofctl dump-flows br0 table=10
+
+which ought to show roughly the following, with extraneous details
+removed:
+
+    table=10, vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
+
+>>> If you tried the examples for the previous step, or if you did
+    some of your own experiments, then you might see additional flows
+    there.  These additional flows are harmless.  If they bother you,
+    then you can remove them with "ovs-ofctl del-flows br0 table=10".
+
+The other way is to inject a packet to take advantage of the learning
+entry.  For example, we can inject a packet on p2 whose destination is
+the MAC address that we just learned on p1:
+
+    ovs-appctl ofproto/trace br0 in_port=2,dl_src=90:00:00:00:00:01,dl_dst=f0:00:00:00:00:01 -generate
+
+Here's an interesting excerpt from that command's output.  This group
+of lines traces the "resubmit(,10)", showing that the packet matched
+the learned flow for the first MAC we used, loading the OpenFlow port
+number for the learned port p1 into register 0:
+
+                               Resubmitted flow: unchanged
+                               Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
+                               Resubmitted  odp: drop
+                               Rule: table=10 cookie=0 vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01
+                               OpenFlow actions=load:0x1->NXM_NX_REG0[0..15]
+
+
+If you read the commands above carefully, then you might have noticed
+that they simply have the Ethernet source and destination addresses
+exchanged.  That means that if we now rerun the first ovs-appctl
+command above, e.g.:
+
+    ovs-appctl ofproto/trace br0 in_port=1,dl_vlan=20,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01 -generate
+
+then we see in the output that the destination has now been learned:
+
+                               Resubmitted flow: unchanged
+                               Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
+                               Resubmitted  odp: drop
+                               Rule: table=10 cookie=0 vlan_tci=0x0014/0x0fff,dl_dst=90:00:00:00:00:01
+                               OpenFlow actions=load:0x2->NXM_NX_REG0[0..15]
+
+
+Implementing Table 4: Output Processing
+=======================================
+
+At entry to stage 4, we know that register 0 contains either the
+desired output port or is zero if the packet should be flooded.  We
+also know that the packet's VLAN is in its 802.1Q header, even if the
+VLAN was implicit because the packet came in on an access port.
+
+The job of the final pipeline stage is to actually output packets.
+The job is trivial for output to our trunk port p1:
+
+    ovs-ofctl add-flow br0 "table=4 reg0=1 actions=1"
+
+For output to the access ports, we just have to strip the VLAN header
+before outputting the packet:
+
+    ovs-ofctl add-flows br0 - <<'EOF'
+        table=4 reg0=2 actions=strip_vlan,2
+        table=4 reg0=3 actions=strip_vlan,3
+        table=4 reg0=4 actions=strip_vlan,4
+EOF
+
+The only slightly tricky part is flooding multicast and broadcast
+packets and unicast packets with unlearned destinations.  For those,
+we need to make sure that we only output the packets to the ports that
+carry our packet's VLAN, and that we include the 802.1Q header in the
+copy output to the trunk port but not in copies output to access
+ports:
+
+    ovs-ofctl add-flows br0 - <<'EOF'
+        table=4 reg0=0 priority=99 dl_vlan=20 actions=1,strip_vlan,2
+        table=4 reg0=0 priority=99 dl_vlan=30 actions=1,strip_vlan,3,4
+        table=4 reg0=0 priority=50            actions=1
+EOF
+
+>>> Our rules rely on the standard OpenFlow behavior that an output
+    action will not forward a packet back out the port it came in on.
+    That is, if a packet comes in on p1, and we've learned that the
+    packet's destination MAC is also on p1, so that we end up with
+    "actions=1" as our actions, the switch will not forward the packet
+    back out its input port.  The multicast/broadcast/unknown
+    destination cases above also rely on this behavior.
+
+
+Testing Table 4
+---------------
+
+== EXAMPLE 1: Broadcast, Multicast, and Unknown Destination ==
+
+Try tracing a broadcast packet arriving on p1 in VLAN 30:
+
+    ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=30
+
+The interesting part of the output is the final line, which shows that
+the switch would remove the 802.1Q header and then output the packet to
+p3 and p4, which are access ports for VLAN 30:
+
+    Datapath actions: pop_vlan,3,4
+
+Similarly, if we trace a broadcast packet arriving on p3:
+
+    ovs-appctl ofproto/trace br0 in_port=3,dl_dst=ff:ff:ff:ff:ff:ff
+
+then we see that it is output to p1 with an 802.1Q tag and then to p4
+without one:
+
+    Datapath actions: push_vlan(vid=30,pcp=0),1,pop_vlan,4
+
+>>> Open vSwitch could simplify the datapath actions here to just
+    "4,push_vlan(vid=30,pcp=0),1" but it is not smart enough to do so.
+
+The following are also broadcasts, but the result is to drop the
+packets because the VLAN only belongs to the input port:
+
+    ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff
+    ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=55
+
+Try some other broadcast cases on your own:
+
+    ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=20
+    ovs-appctl ofproto/trace br0 in_port=2,dl_dst=ff:ff:ff:ff:ff:ff
+    ovs-appctl ofproto/trace br0 in_port=4,dl_dst=ff:ff:ff:ff:ff:ff
+
+You can see the same behavior with multicast packets and with unicast
+packets whose destination has not been learned, e.g.:
+
+    ovs-appctl ofproto/trace br0 in_port=4,dl_dst=01:00:00:00:00:00
+    ovs-appctl ofproto/trace br0 in_port=1,dl_dst=90:12:34:56:78:90,dl_vlan=20
+    ovs-appctl ofproto/trace br0 in_port=1,dl_dst=90:12:34:56:78:90,dl_vlan=30
+
+
+== EXAMPLE 2: MAC Learning ==
+
+Let's follow the same pattern as we did for table 3.  First learn a
+MAC on port p1 in VLAN 30:
+
+    ovs-appctl ofproto/trace br0 in_port=1,dl_vlan=30,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01 -generate
+
+You can see from the last line of output that the packet's destination
+is unknown, so it gets flooded to both p3 and p4, the other ports in
+VLAN 30:
+
+    Datapath actions: pop_vlan,3,4
+
+Then reverse the MACs and learn the first flow's destination on port
+p4:
+
+    ovs-appctl ofproto/trace br0 in_port=4,dl_src=20:00:00:00:00:01,dl_dst=10:00:00:00:00:01 -generate
+
+The last line of output shows that the this packet's destination is
+known to be p1, as learned from our previous command:
+
+    Datapath actions: push_vlan(vid=30,pcp=0),1
+
+Now, if we rerun our first command:
+
+    ovs-appctl ofproto/trace br0 in_port=1,dl_vlan=30,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01 -generate
+
+we can see that the result is no longer a flood but to the specified
+learned destination port p4:
+
+    Datapath actions: pop_vlan,4
+
+
+Contact 
+=======
+
+bugs@openvswitch.org
+http://openvswitch.org/
diff --git a/tutorial/automake.mk b/tutorial/automake.mk
new file mode 100644 (file)
index 0000000..d88d5b4
--- /dev/null
@@ -0,0 +1,12 @@
+EXTRA_DIST += \
+       tutorial/Tutorial \
+       tutorial/ovs-sandbox \
+       tutorial/t-setup \
+       tutorial/t-stage0 \
+       tutorial/t-stage1 \
+       tutorial/t-stage2 \
+       tutorial/t-stage3 \
+       tutorial/t-stage4
+
+sandbox: all
+       cd $(srcdir)/tutorial && ./ovs-sandbox -b $(abs_builddir)
diff --git a/tutorial/ovs-sandbox b/tutorial/ovs-sandbox
new file mode 100755 (executable)
index 0000000..db980d2
--- /dev/null
@@ -0,0 +1,234 @@
+#! /bin/sh
+#
+# Copyright (c) 2013 Nicira, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -e
+
+run () {
+    echo "$@"
+    (cd "$sandbox" && "$@") || exit 1
+}
+
+builddir=
+srcdir=
+schema=
+installed=false
+built=false
+for option; do
+    # This option-parsing mechanism borrowed from a Autoconf-generated
+    # configure script under the following license:
+
+    # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+    # 2002, 2003, 2004, 2005, 2006, 2009, 2013 Free Software Foundation, Inc.
+    # This configure script is free software; the Free Software Foundation
+    # gives unlimited permission to copy, distribute and modify it.
+
+    # If the previous option needs an argument, assign it.
+    if test -n "$prev"; then
+        eval $prev=\$option
+        prev=
+        continue
+    fi
+    case $option in
+        *=*) optarg=`expr "X$option" : '[^=]*=\(.*\)'` ;;
+        *) optarg=yes ;;
+    esac
+
+    case $dashdash$option in
+        --)
+            dashdash=yes ;;
+        -h|--help)
+            cat <<EOF
+ovs-sandbox, for starting a sandboxed dummy Open vSwitch environment
+usage: $0 [OPTION...]
+
+If you run ovs-sandbox from an OVS build directory, it uses the OVS that
+you built.  Otherwise, if you have an installed Open vSwitch, it uses
+the installed version.
+
+These options force ovs-sandbox to use a particular OVS build:
+  -b, --builddir=DIR   specify Open vSwitch build directory
+  -s, --srcdir=DIR     specify Open vSwitch source directory
+These options force ovs-sandbox to use an installed Open vSwitch:
+  -i, --installed      use installed Open vSwitch
+  -S, --schema=FILE    use FILE as vswitch.ovsschema
+
+Other options:
+  -h, --help           Print this usage message.
+EOF
+            exit 0
+            ;;
+
+        --b*=*)
+            builddir=$optarg
+            built=:
+            ;;
+        -b|--b*)
+            prev=builddir
+            built=:
+            ;;
+        --sr*=*)
+            srcdir=$optarg
+            built=false
+            ;;
+        -s|--sr*)
+            prev=srcdir
+            built=false
+            ;;
+        -i|--installed)
+            installed=:
+            ;;
+        --sc*=*)
+            schema=$optarg
+            installed=:
+            ;;
+        -S|--sc*)
+            prev=schema
+            installed=:
+            ;;
+        -*)
+            echo "unrecognized option $option (use --help for help)" >&2
+            exit 1
+            ;;
+        *)
+            echo "$option: non-option arguments not supported (use --help for help)" >&2
+            exit 1
+            ;;
+    esac
+    shift
+done
+
+if $installed && $built; then
+    echo "sorry, conflicting options (use --help for help)" >&2
+    exit 1
+elif $installed || $built; then
+    :
+elif test -e vswitchd/ovs-vswitchd; then
+    built=:
+    builddir=.
+elif (ovs-vswitchd --version) >/dev/null 2>&1; then
+    installed=:
+else
+    echo "can't find an OVS build or install (use --help for help)" >&2
+    exit 1
+fi
+
+if $built; then
+    if test ! -e "$builddir"/vswitchd/ovs-vswitchd; then
+        echo "$builddir does not appear to be an OVS build directory" >&2
+        exit 1
+    fi
+    builddir=`cd $builddir && pwd`
+
+    # Find srcdir.
+    case $srcdir in
+        '')
+            srcdir=$builddir
+            if test ! -e "$srcdir"/WHY-OVS; then
+                srcdir=`cd $builddir/.. && pwd`
+            fi
+            ;;
+        /*) ;;
+        *) srcdir=`pwd`/$srcdir ;;
+    esac
+    schema=$srcdir/vswitchd/vswitch.ovsschema
+    if test ! -e "$schema"; then
+        echo >&2 'source directory not found, please use --srcdir'
+        exit 1
+    fi
+
+    # Put built tools early in $PATH.
+    if test ! -e $builddir/vswitchd/ovs-vswitchd; then
+        echo >&2 'build not found, please change set $builddir or change directory'
+        exit 1
+    fi
+    PATH=$builddir/ovsdb:$builddir/vswitchd:$builddir/utilities:$PATH
+    export PATH
+else
+    case $schema in
+        '')
+            for schema in \
+                /usr/local/share/openvswitch/vswitch.ovsschema \
+                /usr/share/openvswitch/vswitch.ovsschema \
+                none; do
+                if test -r $schema; then
+                    break
+                fi
+            done
+            ;;
+        /*) ;;
+        *) schema=`pwd`/$schema ;;
+    esac
+    if test ! -r "$schema"; then
+        echo "can't find vswitch.ovsschema, please specify --schema" >&2
+        exit 1
+    fi
+fi
+
+# Create sandbox.
+rm -rf sandbox
+mkdir sandbox
+sandbox=`cd sandbox && pwd`
+
+# Set up environment for OVS programs to sandbox themselves.
+OVS_RUNDIR=$sandbox; export OVS_RUNDIR
+OVS_LOGDIR=$sandbox; export OVS_LOGDIR
+OVS_DBDIR=$sandbox; export OVS_DBDIR
+OVS_SYSCONFDIR=$sandbox; export OVS_SYSCONFDIR
+
+if $built; then
+    # Easy access to OVS manpages.
+    (cd "$builddir" && make install-man mandir="$sandbox"/man)
+    MANPATH=$sandbox/man:; export MANPATH
+fi
+
+# Ensure cleanup.
+trap 'kill `cat "$sandbox"/*.pid`' 0 1 2 3 13 14 15
+
+# Create database and start ovsdb-server.
+touch "$sandbox"/.conf.db.~lock~
+run ovsdb-tool create conf.db "$schema"
+run ovsdb-server --detach --no-chdir --pidfile -vconsole:off --log-file \
+    --remote=punix:"$sandbox"/db.sock
+
+# Start ovs-vswitchd.
+run ovs-vswitchd --detach --no-chdir --pidfile -vconsole:off --log-file \
+    --enable-dummy=override -vvconn -vnetdev_dummy
+
+cat <<EOF
+
+
+
+----------------------------------------------------------------------
+You are running in a dummy Open vSwitch environment.  You can use
+ovs-vsctl, ovs-ofctl, ovs-appctl, and other tools to work with the
+dummy switch.  
+
+Log files, pidfiles, and the configuration database are in the
+"sandbox" subdirectory.
+
+Exit the shell to kill the running daemons.
+EOF
+
+status=0; $SHELL || status=$?
+
+cat <<EOF
+----------------------------------------------------------------------
+
+
+
+EOF
+
+exit $status
diff --git a/tutorial/t-setup b/tutorial/t-setup
new file mode 100755 (executable)
index 0000000..4925d82
--- /dev/null
@@ -0,0 +1,8 @@
+#! /bin/sh -ve
+
+ovs-vsctl add-br br0 -- set Bridge br0 fail-mode=secure
+
+for i in 1 2 3 4; do
+    ovs-vsctl add-port br0 p$i -- set Interface p$i ofport_request=$i
+    ovs-ofctl mod-port br0 p$i up
+done
diff --git a/tutorial/t-stage0 b/tutorial/t-stage0
new file mode 100755 (executable)
index 0000000..55687ee
--- /dev/null
@@ -0,0 +1,9 @@
+#! /bin/sh -ve
+
+ovs-ofctl add-flow br0 \
+    "table=0, dl_src=01:00:00:00:00:00/01:00:00:00:00:00, actions=drop"
+
+ovs-ofctl add-flow br0 \
+    "table=0, dl_dst=01:08:c2:00:00:00/ff:ff:ff:ff:ff:f0, actions=drop"
+
+ovs-ofctl add-flow br0 "table=0, priority=0, actions=resubmit(,1)"
diff --git a/tutorial/t-stage1 b/tutorial/t-stage1
new file mode 100755 (executable)
index 0000000..97aed7e
--- /dev/null
@@ -0,0 +1,12 @@
+#! /bin/sh -ve
+
+ovs-ofctl add-flow br0 "table=1, priority=0, actions=drop"
+
+ovs-ofctl add-flow br0 \
+    "table=1, priority=99, in_port=1, actions=resubmit(,2)"
+
+ovs-ofctl add-flows br0 - <<'EOF'
+    table=1, priority=99, in_port=2, vlan_tci=0, actions=mod_vlan_vid:20, resubmit(,2)
+    table=1, priority=99, in_port=3, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2)
+    table=1, priority=99, in_port=4, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2)
+EOF
diff --git a/tutorial/t-stage2 b/tutorial/t-stage2
new file mode 100755 (executable)
index 0000000..f0d687e
--- /dev/null
@@ -0,0 +1,7 @@
+#! /bin/sh -ve
+
+ovs-ofctl add-flow br0 \
+    "table=2 actions=learn(table=10, NXM_OF_VLAN_TCI[0..11], \
+                           NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], \
+                           load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]), \
+                     resubmit(,3)"
diff --git a/tutorial/t-stage3 b/tutorial/t-stage3
new file mode 100755 (executable)
index 0000000..eb4ab3c
--- /dev/null
@@ -0,0 +1,8 @@
+#! /bin/sh -ve
+
+ovs-ofctl add-flow br0 \
+    "table=3 priority=50 actions=resubmit(,10), resubmit(,4)"
+
+ovs-ofctl add-flow br0 \
+    "table=3 priority=99 dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 \
+      actions=resubmit(,4)"
diff --git a/tutorial/t-stage4 b/tutorial/t-stage4
new file mode 100755 (executable)
index 0000000..3f71b92
--- /dev/null
@@ -0,0 +1,15 @@
+#! /bin/sh -ve
+
+ovs-ofctl add-flow br0 "table=4 reg0=1 actions=1"
+
+ovs-ofctl add-flows br0 - <<'EOF'
+    table=4 reg0=2 actions=strip_vlan,2
+    table=4 reg0=3 actions=strip_vlan,3
+    table=4 reg0=4 actions=strip_vlan,4
+EOF
+
+ovs-ofctl add-flows br0 - <<'EOF'
+    table=4 reg0=0 priority=99 dl_vlan=20 actions=1,strip_vlan,2
+    table=4 reg0=0 priority=99 dl_vlan=30 actions=1,strip_vlan,3,4
+    table=4 reg0=0 priority=50            actions=1
+EOF
index 162f7cf..d1bdaac 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -118,7 +118,7 @@ parse_target(const char *s_, struct in_addr *addr,
 static void
 parse_options(int argc, char *argv[])
 {
-    static struct option long_options[] = {
+    static const struct option long_options[] = {
         {"local", required_argument, NULL, 'l'},
         {"remote", required_argument, NULL, 'r'},
         {"batches", required_argument, NULL, 'b'},
@@ -472,6 +472,7 @@ cmd_rate(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
             printf("%.3f s elapsed, %u OK, %u failed, avg %.1f/s\n",
                    elapsed / 1000.0, completed - failures, failures,
                    completed / (elapsed / 1000.0));
+            fflush(stdout);
             prev = now;
 
             if (timeout && elapsed > timeout * 1000LL) {
index 51765bd..70bc2e6 100644 (file)
@@ -255,7 +255,7 @@ parse_options(int argc, char *argv[])
         DAEMON_OPTION_ENUMS,
         OFP_VERSION_OPTION_ENUMS
     };
-    static struct option long_options[] = {
+    static const struct option long_options[] = {
         {"hub",         no_argument, NULL, 'H'},
         {"noflow",      no_argument, NULL, 'n'},
         {"normal",      no_argument, NULL, 'N'},
index 5ad5f26..1f10491 100755 (executable)
@@ -30,7 +30,7 @@ done
 ## start ##
 ## ----- ##
 
-insert_openvswitch_mod_if_required () {
+insert_mod_if_required () {
     # If openvswitch is already loaded then we're done.
     test -e /sys/module/openvswitch -o -e /sys/module/openvswitch_mod && \
      return 0
@@ -52,10 +52,6 @@ insert_openvswitch_mod_if_required () {
     action "Inserting openvswitch module" modprobe openvswitch
 }
 
-insert_mod_if_required () {
-    insert_openvswitch_mod_if_required || return 1
-}
-
 ovs_vsctl () {
     ovs-vsctl --no-wait "$@"
 }
@@ -188,7 +184,6 @@ start_ovsdb () {
         done
         set "$@" -vconsole:emer -vsyslog:err -vfile:info
         set "$@" --remote=punix:"$DB_SOCK"
-        set "$@" --remote=db:Open_vSwitch,Open_vSwitch,manager_options
         set "$@" --private-key=db:Open_vSwitch,SSL,private_key
         set "$@" --certificate=db:Open_vSwitch,SSL,certificate
         set "$@" --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert
@@ -229,6 +224,17 @@ start_forwarding () {
            fi
            start_daemon "$OVS_VSWITCHD_PRIORITY" "$OVS_VSWITCHD_WRAPPER" "$@"
     fi
+
+    # Now that ovs-vswitchd has started and completed its initial
+    # configuration, tell ovsdb-server to conenct to the remote managers.  We
+    # used to do this at ovsdb-server startup time, but waiting for
+    # ovs-vswitchd to finish configuring means that remote managers see less
+    # churn in the database at startup or restart.  (For example, managers
+    # won't briefly see empty datapath-id or ofport columns for records that
+    # exist at startup.)
+    action "Enabling remote OVSDB managers" \
+       ovs-appctl -t ovsdb-server ovsdb-server/add-remote \
+           db:Open_vSwitch,Open_vSwitch,manager_options
 }
 
 ## ---- ##
index 3b6e6a5..2f9574f 100644 (file)
@@ -89,7 +89,7 @@ parse_options(int argc, char *argv[])
         OPT_MAY_CREATE,
         VLOG_OPTION_ENUMS
     };
-    static struct option long_options[] = {
+    static const struct option long_options[] = {
         {"statistics", no_argument, NULL, 's'},
         {"clear", no_argument, NULL, OPT_CLEAR},
         {"may-create", no_argument, NULL, OPT_MAY_CREATE},
index a441c3d..1684ddc 100644 (file)
@@ -37,9 +37,23 @@ else
     dbdir='@DBDIR@'
 fi
 
+ovs_ctl_log () {
+    echo "$@" >> "${logdir}/ovs-ctl.log"
+}
+
 ovs_ctl () {
-    echo "`date -u`:$@" >> "${logdir}/ovs-ctl.log"
-    "${datadir}/scripts/ovs-ctl" "$@" 2>&1 | tee -a "${logdir}/ovs-ctl.log"
+    case "$@" in
+        *"=strace"*)
+            # In case of running the daemon with strace, piping the o/p causes
+            # the script to block (strace probably does not close the inherited
+            # pipe). So, do not log the o/p to ovs-ctl.log.
+            "${datadir}/scripts/ovs-ctl" "$@"
+        ;;
+        *)
+            echo "`date -u`:$@" >> "${logdir}/ovs-ctl.log"
+            "${datadir}/scripts/ovs-ctl" "$@" 2>&1 | tee -a "${logdir}/ovs-ctl.log"
+        ;;
+    esac
 }
 
 VERSION='@VERSION@'
index 3cc618d..f46b9dc 100644 (file)
@@ -1241,6 +1241,30 @@ flow's creation, not since the receipt of the FIN or RST.)
 .RE
 .IP
 This action was added in Open vSwitch 1.5.90.
+.
+.IP "\fBsample(\fIargument\fR[\fB,\fIargument\fR]...\fB)\fR"
+Samples packets and sends one sample for every sampled packet.
+.IP
+\fIargument\fR takes the following forms:
+.RS
+.IP "\fBprobability=\fIpackets\fR"
+The number of sampled packets out of 65535.  Must be greater or equal to 1.
+.IP "\fBcollector_set_id=\fIid\fR"
+The unsigned 32-bit integer identifier of the set of sample collectors
+to send sampled packets to.  Defaults to 0.
+.IP "\fBobs_domain_id=\fIid\fR"
+When sending samples to IPFIX collectors, the unsigned 32-bit integer
+Observation Domain ID sent in every IPFIX flow record.  Defaults to 0.
+.IP "\fBobs_point_id=\fIid\fR"
+When sending samples to IPFIX collectors, the unsigned 32-bit integer
+Observation Point ID sent in every IPFIX flow record.  Defaults to 0.
+.RE
+.IP
+Refer to \fBovs\-vswitchd.conf.db\fR(8) for more details on
+configuring sample collector sets.
+.IP
+This action was added in Open vSwitch 1.10.90.
+.
 .IP "\fBexit\fR"
 This action causes Open vSwitch to immediately halt execution of further
 actions.  Those actions which have already been executed are unaffected.  Any
@@ -1555,3 +1579,4 @@ Prints the flow entries in the switch.
 .BR ovs\-appctl (8),
 .BR ovs\-controller (8),
 .BR ovs\-vswitchd (8)
+.BR ovs\-vswitchd.conf.db (8)
index ec775c7..9f97bbc 100644 (file)
@@ -151,7 +151,7 @@ parse_options(int argc, char *argv[])
         OFP_VERSION_OPTION_ENUMS,
         VLOG_OPTION_ENUMS
     };
-    static struct option long_options[] = {
+    static const struct option long_options[] = {
         {"timeout", required_argument, NULL, 't'},
         {"strict", no_argument, NULL, OPT_STRICT},
         {"readd", no_argument, NULL, OPT_READD},
@@ -1358,9 +1358,11 @@ monitor_vconn(struct vconn *vconn)
 
             if (timestamp) {
                 time_t now = time_wall();
+                struct tm tm;
                 char s[32];
 
-                strftime(s, sizeof s, "%Y-%m-%d %H:%M:%S: ", gmtime(&now));
+                strftime(s, sizeof s, "%Y-%m-%d %H:%M:%S: ",
+                         gmtime_r(&now, &tm));
                 fputs(s, stderr);
             }
 
index a506375..1cf9274 100755 (executable)
@@ -27,7 +27,7 @@ bits=2048
 
 # OS-specific compatibility routines
 case $(uname -s) in
-FreeBSD)
+FreeBSD|NetBSD)
     file_mod_epoch()
     {
         stat -r "$1" | awk '{print $10}'
index 85149a9..fd29b06 100644 (file)
@@ -172,10 +172,11 @@ Prints a brief overview of the database contents.
 .IP "\fBemer\-reset\fR"
 Reset the configuration into a clean state.  It deconfigures OpenFlow
 controllers, OVSDB servers, and SSL, and deletes port mirroring,
-\fBfail_mode\fR, NetFlow, and sFlow configuration.  This command also
-removes all \fBother\-config\fR keys from all database records, except
-that \fBother\-config:hwaddr\fR is preserved if it is present in a
-Bridge record.  Other networking configuration is left as-is.
+\fBfail_mode\fR, NetFlow, sFlow, and IPFIX configuration.  This
+command also removes all \fBother\-config\fR keys from all database
+records, except that \fBother\-config:hwaddr\fR is preserved if it is
+present in a Bridge record.  Other networking configuration is left
+as-is.
 .
 .SS "Bridge Commands"
 These commands examine and manipulate Open vSwitch bridges.
@@ -526,8 +527,14 @@ The global SSL configuration for \fBovs\-vswitchd\fR.  The record
 attached to the \fBOpen_vSwitch\fR table may be identified by
 specifying \fB.\fR as the record name.
 .IP "\fBsFlow\fR"
-An sFlow configuration attached to a bridge.  Records may be
+An sFlow exporter configuration attached to a bridge.  Records may be
 identified by bridge name.
+.IP "\fBIPFIX\fR"
+An IPFIX exporter configuration attached to a bridge.  Records may be
+identified by bridge name.
+.IP "\fBFlow_Sample_Collector_Set\fR"
+An IPFIX exporter configuration attached to a bridge for sampling
+packets on a per-flow basis using OpenFlow \fBsample\fR actions.
 .PP
 Record names must be specified in full and with correct
 capitalization.  Names of tables and columns are not case-sensitive,
@@ -931,6 +938,20 @@ Deconfigure sFlow from \fBbr0\fR, which also destroys the sFlow record
 (since it is now unreferenced):
 .IP
 .B "ovs\-vsctl \-\- clear Bridge br0 sflow"
+.SS "IPFIX"
+.PP
+Configure bridge \fBbr0\fR to send one IPFIX flow record per packet
+sample to UDP port 4739 on host 192.168.0.34, with Observation Domain
+ID 123 and Observation Point ID 456:
+.IP
+.B "ovs\-vsctl \-\- set Bridge br0 ipfix=@i \(rs"
+.IP
+.B "\-\- \-\-id=@i create IPFIX targets=\(rs\(dq192.168.0.34:4739\(rs\(dq obs_domain_id=123 obs_point_id=456"
+.PP
+Deconfigure the IPFIX settings from \fBbr0\fR, which also destroys the
+IPFIX record (since it is now unreferenced):
+.IP
+.B "ovs\-vsctl clear Bridge br0 ipfix"
 .SS "802.1D Spanning Tree Protocol (STP)"
 .PP
 Configure bridge \fBbr0\fR to participate in an 802.1D spanning tree:
index 18ace60..19ab472 100644 (file)
@@ -1453,6 +1453,7 @@ pre_cmd_emer_reset(struct vsctl_context *ctx)
     ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_mirrors);
     ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_netflow);
     ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_sflow);
+    ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_ipfix);
     ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_flood_vlans);
     ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_other_config);
 
@@ -1477,6 +1478,8 @@ cmd_emer_reset(struct vsctl_context *ctx)
     const struct ovsrec_netflow *nf, *next_nf;
     const struct ovsrec_ssl *ssl, *next_ssl;
     const struct ovsrec_sflow *sflow, *next_sflow;
+    const struct ovsrec_ipfix *ipfix, *next_ipfix;
+    const struct ovsrec_flow_sample_collector_set *fscset, *next_fscset;
 
     /* Reset the Open_vSwitch table. */
     ovsrec_open_vswitch_set_manager_options(ctx->ovs, NULL, 0);
@@ -1490,6 +1493,7 @@ cmd_emer_reset(struct vsctl_context *ctx)
         ovsrec_bridge_set_mirrors(br, NULL, 0);
         ovsrec_bridge_set_netflow(br, NULL);
         ovsrec_bridge_set_sflow(br, NULL);
+        ovsrec_bridge_set_ipfix(br, NULL);
         ovsrec_bridge_set_flood_vlans(br, NULL, 0);
 
         /* We only want to save the "hwaddr" key from other_config. */
@@ -1539,6 +1543,14 @@ cmd_emer_reset(struct vsctl_context *ctx)
         ovsrec_sflow_delete(sflow);
     }
 
+    OVSREC_IPFIX_FOR_EACH_SAFE (ipfix, next_ipfix, idl) {
+        ovsrec_ipfix_delete(ipfix);
+    }
+
+    OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH_SAFE (fscset, next_fscset, idl) {
+        ovsrec_flow_sample_collector_set_delete(fscset);
+    }
+
     vsctl_context_invalidate_cache(ctx);
 }
 
@@ -1668,6 +1680,7 @@ del_bridge(struct vsctl_context *ctx, struct vsctl_bridge *br)
 {
     struct vsctl_bridge *child, *next_child;
     struct vsctl_port *port, *next_port;
+    const struct ovsrec_flow_sample_collector_set *fscset, *next_fscset;
 
     HMAP_FOR_EACH_SAFE (child, next_child, children_node, &br->children) {
         del_bridge(ctx, child);
@@ -1677,6 +1690,13 @@ del_bridge(struct vsctl_context *ctx, struct vsctl_bridge *br)
         del_port(ctx, port);
     }
 
+    OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH_SAFE (fscset, next_fscset,
+                                                    ctx->idl) {
+        if (fscset->bridge == br->br_cfg) {
+            ovsrec_flow_sample_collector_set_delete(fscset);
+        }
+    }
+
     del_cached_bridge(ctx, br);
 }
 
@@ -2464,7 +2484,8 @@ struct vsctl_table_class {
 static const struct vsctl_table_class tables[] = {
     {&ovsrec_table_bridge,
      {{&ovsrec_table_bridge, &ovsrec_bridge_col_name, NULL},
-      {NULL, NULL, NULL}}},
+      {&ovsrec_table_flow_sample_collector_set, NULL,
+       &ovsrec_flow_sample_collector_set_col_bridge}}},
 
     {&ovsrec_table_controller,
      {{&ovsrec_table_bridge,
@@ -2518,6 +2539,17 @@ static const struct vsctl_table_class tables[] = {
      {{&ovsrec_table_flow_table, &ovsrec_flow_table_col_name, NULL},
       {NULL, NULL, NULL}}},
 
+    {&ovsrec_table_ipfix,
+     {{&ovsrec_table_bridge,
+       &ovsrec_bridge_col_name,
+       &ovsrec_bridge_col_ipfix},
+      {&ovsrec_table_flow_sample_collector_set, NULL,
+       &ovsrec_flow_sample_collector_set_col_ipfix}}},
+
+    {&ovsrec_table_flow_sample_collector_set,
+     {{NULL, NULL, NULL},
+      {NULL, NULL, NULL}}},
+
     {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
 };
 
@@ -4105,6 +4137,7 @@ try_again:
     if (txn) {
         ovsdb_idl_txn_abort(txn);
         ovsdb_idl_txn_destroy(txn);
+        the_idl_txn = NULL;
     }
     ovsdb_symbol_table_destroy(symtab);
     for (c = commands; c < &commands[n_commands]; c++) {
index 6dc3db2..eb1ab3c 100644 (file)
@@ -146,6 +146,23 @@ static struct hmap all_bridges = HMAP_INITIALIZER(&all_bridges);
 /* OVSDB IDL used to obtain configuration. */
 static struct ovsdb_idl *idl;
 
+/* We want to complete daemonization, fully detaching from our parent process,
+ * only after we have completed our initial configuration, committed our state
+ * to the database, and received confirmation back from the database server
+ * that it applied the commit.  This allows our parent process to know that,
+ * post-detach, ephemeral fields such as datapath-id and ofport are very likely
+ * to have already been filled in.  (It is only "very likely" rather than
+ * certain because there is always a slim possibility that the transaction will
+ * fail or that some other client has added new bridges, ports, etc. while
+ * ovs-vswitchd was configuring using an old configuration.)
+ *
+ * We only need to do this once for our initial configuration at startup, so
+ * 'initial_config_done' tracks whether we've already done it.  While we are
+ * waiting for a response to our commit, 'daemonize_txn' tracks the transaction
+ * itself and is otherwise NULL. */
+static bool initial_config_done;
+static struct ovsdb_idl_txn *daemonize_txn;
+
 /* Most recently processed IDL sequence number. */
 static unsigned int idl_seqno;
 
@@ -183,6 +200,7 @@ static void bridge_configure_netflow(struct bridge *);
 static void bridge_configure_forward_bpdu(struct bridge *);
 static void bridge_configure_mac_table(struct bridge *);
 static void bridge_configure_sflow(struct bridge *, int *sflow_bridge_number);
+static void bridge_configure_ipfix(struct bridge *);
 static void bridge_configure_stp(struct bridge *);
 static void bridge_configure_tables(struct bridge *);
 static void bridge_configure_dp_desc(struct bridge *);
@@ -371,8 +389,9 @@ bridge_init(const char *remote)
     ovsdb_idl_omit_alert(idl, &ovsrec_mirror_col_statistics);
 
     ovsdb_idl_omit(idl, &ovsrec_netflow_col_external_ids);
-
     ovsdb_idl_omit(idl, &ovsrec_sflow_col_external_ids);
+    ovsdb_idl_omit(idl, &ovsrec_ipfix_col_external_ids);
+    ovsdb_idl_omit(idl, &ovsrec_flow_sample_collector_set_col_external_ids);
 
     ovsdb_idl_omit(idl, &ovsrec_manager_col_external_ids);
     ovsdb_idl_omit(idl, &ovsrec_manager_col_inactivity_probe);
@@ -595,21 +614,13 @@ bridge_reconfigure_continue(const struct ovsrec_open_vswitch *ovs_cfg)
         bridge_configure_remotes(br, managers, n_managers);
         bridge_configure_netflow(br);
         bridge_configure_sflow(br, &sflow_bridge_number);
+        bridge_configure_ipfix(br);
         bridge_configure_stp(br);
         bridge_configure_tables(br);
         bridge_configure_dp_desc(br);
     }
     free(managers);
 
-    if (done) {
-        /* ovs-vswitchd has completed initialization, so allow the process that
-         * forked us to exit successfully. */
-        daemonize_complete();
-        reconfiguring = false;
-
-        VLOG_INFO_ONCE("%s (Open vSwitch) %s", program_name, VERSION);
-    }
-
     return done;
 }
 
@@ -936,6 +947,79 @@ bridge_configure_sflow(struct bridge *br, int *sflow_bridge_number)
     sset_destroy(&oso.targets);
 }
 
+/* Set IPFIX configuration on 'br'. */
+static void
+bridge_configure_ipfix(struct bridge *br)
+{
+    const struct ovsrec_ipfix *be_cfg = br->cfg->ipfix;
+    const struct ovsrec_flow_sample_collector_set *fe_cfg;
+    struct ofproto_ipfix_bridge_exporter_options be_opts;
+    struct ofproto_ipfix_flow_exporter_options *fe_opts = NULL;
+    size_t n_fe_opts = 0;
+
+    OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH(fe_cfg, idl) {
+        if (fe_cfg->bridge == br->cfg) {
+            n_fe_opts++;
+        }
+    }
+
+    if (!be_cfg && n_fe_opts == 0) {
+        ofproto_set_ipfix(br->ofproto, NULL, NULL, 0);
+        return;
+    }
+
+    if (be_cfg) {
+        memset(&be_opts, 0, sizeof be_opts);
+
+        sset_init(&be_opts.targets);
+        sset_add_array(&be_opts.targets, be_cfg->targets, be_cfg->n_targets);
+
+        if (be_cfg->sampling) {
+            be_opts.sampling_rate = *be_cfg->sampling;
+        } else {
+            be_opts.sampling_rate = SFL_DEFAULT_SAMPLING_RATE;
+        }
+        if (be_cfg->obs_domain_id) {
+            be_opts.obs_domain_id = *be_cfg->obs_domain_id;
+        }
+        if (be_cfg->obs_point_id) {
+            be_opts.obs_point_id = *be_cfg->obs_point_id;
+        }
+    }
+
+    if (n_fe_opts > 0) {
+        struct ofproto_ipfix_flow_exporter_options *opts;
+        fe_opts = xcalloc(n_fe_opts, sizeof *fe_opts);
+        opts = fe_opts;
+        OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH(fe_cfg, idl) {
+            if (fe_cfg->bridge == br->cfg) {
+                opts->collector_set_id = fe_cfg->id;
+                sset_init(&opts->targets);
+                sset_add_array(&opts->targets, fe_cfg->ipfix->targets,
+                               fe_cfg->ipfix->n_targets);
+                opts++;
+            }
+        }
+    }
+
+    ofproto_set_ipfix(br->ofproto, be_cfg ? &be_opts : NULL, fe_opts,
+                      n_fe_opts);
+
+    if (be_cfg) {
+        sset_destroy(&be_opts.targets);
+    }
+
+    if (n_fe_opts > 0) {
+        struct ofproto_ipfix_flow_exporter_options *opts = fe_opts;
+        size_t i;
+        for (i = 0; i < n_fe_opts; i++) {
+            sset_destroy(&opts->targets);
+            opts++;
+        }
+        free(fe_opts);
+    }
+}
+
 static void
 port_configure_stp(const struct ofproto *ofproto, struct port *port,
                    struct ofproto_port_stp_settings *port_s,
@@ -2190,11 +2274,16 @@ bridge_run(void)
             struct bridge *br, *next_br;
 
             VLOG_ERR_RL(&rl, "another ovs-vswitchd process is running, "
-                        "disabling this process until it goes away");
+                        "disabling this process (pid %ld) until it goes away",
+                        (long int) getpid());
 
             HMAP_FOR_EACH_SAFE (br, next_br, node, &all_bridges) {
                 bridge_destroy(br);
             }
+            /* Since we will not be running system_stats_run() in this process
+             * with the current situation of multiple ovs-vswitchd daemons,
+             * disable system stats collection. */
+            system_stats_enable(false);
             return;
         } else if (!ovsdb_idl_has_lock(idl)) {
             return;
@@ -2261,15 +2350,25 @@ bridge_run(void)
     }
 
     if (reconfiguring) {
-        if (cfg) {
-            if (!reconf_txn) {
-                reconf_txn = ovsdb_idl_txn_create(idl);
-            }
-            if (bridge_reconfigure_continue(cfg)) {
+        if (!reconf_txn) {
+            reconf_txn = ovsdb_idl_txn_create(idl);
+        }
+
+        if (bridge_reconfigure_continue(cfg ? cfg : &null_cfg)) {
+            reconfiguring = false;
+
+            if (cfg) {
                 ovsrec_open_vswitch_set_cur_cfg(cfg, cfg->next_cfg);
             }
-        } else {
-            bridge_reconfigure_continue(&null_cfg);
+
+            /* If we are completing our initial configuration for this run
+             * of ovs-vswitchd, then keep the transaction around to monitor
+             * it for completion. */
+            if (!initial_config_done) {
+                initial_config_done = true;
+                daemonize_txn = reconf_txn;
+                reconf_txn = NULL;
+            }
         }
     }
 
@@ -2279,6 +2378,20 @@ bridge_run(void)
         reconf_txn = NULL;
     }
 
+    if (daemonize_txn) {
+        enum ovsdb_idl_txn_status status = ovsdb_idl_txn_commit(daemonize_txn);
+        if (status != TXN_INCOMPLETE) {
+            ovsdb_idl_txn_destroy(daemonize_txn);
+            daemonize_txn = NULL;
+
+            /* ovs-vswitchd has completed initialization, so allow the
+             * process that forked us to exit successfully. */
+            daemonize_complete();
+
+            VLOG_INFO_ONCE("%s (Open vSwitch) %s", program_name, VERSION);
+        }
+    }
+
     /* Refresh interface and mirror stats if necessary. */
     if (time_msec() >= iface_stats_timer) {
         if (cfg) {
@@ -2322,6 +2435,9 @@ bridge_wait(void)
     const char *type;
 
     ovsdb_idl_wait(idl);
+    if (daemonize_txn) {
+        ovsdb_idl_txn_wait(daemonize_txn);
+    }
 
     if (reconfiguring) {
         poll_immediate_wake();
index 9736b79..78ebd31 100644 (file)
@@ -159,7 +159,7 @@ parse_options(int argc, char *argv[], char **unixctl_pathp)
         OPT_DISABLE_SYSTEM,
         DAEMON_OPTION_ENUMS
     };
-    static struct option long_options[] = {
+    static const struct option long_options[] = {
         {"help",        no_argument, NULL, 'h'},
         {"version",     no_argument, NULL, 'V'},
         {"mlockall",    no_argument, NULL, OPT_MLOCKALL},
index f679516..842bc20 100644 (file)
@@ -97,7 +97,11 @@ get_memory_stats(struct smap *stats)
 {
     if (!LINUX_DATAPATH) {
         unsigned int pagesize = get_page_size();
+#ifdef _SC_PHYS_PAGES
         long int phys_pages = sysconf(_SC_PHYS_PAGES);
+#else
+        long int phys_pages = 0;
+#endif
 #ifdef _SC_AVPHYS_PAGES
         long int avphys_pages = sysconf(_SC_AVPHYS_PAGES);
 #else
@@ -443,9 +447,11 @@ get_process_stats(struct smap *stats)
 static void
 get_filesys_stats(struct smap *stats OVS_UNUSED)
 {
-#if HAVE_SETMNTENT && HAVE_STATVFS
+#if HAVE_GETMNTENT_R && HAVE_STATVFS
     static const char file_name[] = "/etc/mtab";
+    struct mntent mntent;
     struct mntent *me;
+    char buf[4096];
     FILE *stream;
     struct ds s;
 
@@ -456,7 +462,7 @@ get_filesys_stats(struct smap *stats OVS_UNUSED)
     }
 
     ds_init(&s);
-    while ((me = getmntent(stream)) != NULL) {
+    while ((me = getmntent_r(stream, &mntent, buf, sizeof buf)) != NULL) {
         unsigned long long int total, free;
         struct statvfs vfs;
         char *p;
@@ -490,7 +496,7 @@ get_filesys_stats(struct smap *stats OVS_UNUSED)
         smap_add(stats, "file_systems", ds_cstr(&s));
     }
     ds_destroy(&s);
-#endif  /* HAVE_SETMNTENT && HAVE_STATVFS */
+#endif  /* HAVE_GETMNTENT_R && HAVE_STATVFS */
 }
 \f
 #define SYSTEM_STATS_INTERVAL (5 * 1000) /* In milliseconds. */
index 210ae87..56d666c 100644 (file)
@@ -6,6 +6,7 @@ digraph Open_vSwitch {
        Bridge [];
        Bridge -> sFlow [label="sflow?"];
        Bridge -> Mirror [label="mirrors*"];
+       Bridge -> IPFIX [label="ipfix?"];
        Bridge -> Port [label="ports*"];
        Bridge -> Controller [label="controller*"];
        Bridge -> Flow_Table [label="flow_tables value*"];
@@ -13,6 +14,10 @@ digraph Open_vSwitch {
        QoS [style=bold];
        QoS -> Queue [label="queues value*"];
        sFlow [];
+       Flow_Sample_Collector_Set [style=bold];
+       Flow_Sample_Collector_Set -> Bridge [label="bridge"];
+       Flow_Sample_Collector_Set -> IPFIX [label="ipfix?"];
+       IPFIX [];
        Open_vSwitch [style=bold];
        Open_vSwitch -> Bridge [label="bridges*"];
        Open_vSwitch -> SSL [label="ssl?"];
index 594ffb4..3f2ce3a 100644 (file)
@@ -1,6 +1,6 @@
 {"name": "Open_vSwitch",
  "version": "7.1.0",
- "cksum": "2234055133 17444",
+ "cksum": "432130924 19191",
  "tables": {
    "Open_vSwitch": {
      "columns": {
          "type": {"key": {"type": "uuid",
                           "refTable": "sFlow"},
                   "min": 0, "max": 1}},
+       "ipfix": {
+         "type": {"key": {"type": "uuid",
+                          "refTable": "IPFIX"},
+                  "min": 0, "max": 1}},
        "controller": {
          "type": {"key": {"type": "uuid",
                           "refTable": "Controller"},
        "external_ids": {
          "type": {"key": "string", "value": "string",
                   "min": 0, "max": "unlimited"}}}},
+   "IPFIX": {
+     "columns": {
+       "targets": {
+         "type": {"key": "string", "min": 1, "max": "unlimited"}},
+       "sampling": {
+         "type": {"key": {"type": "integer",
+                          "minInteger": 1,
+                          "maxInteger": 4294967295},
+                  "min": 0, "max": 1}},
+       "obs_domain_id": {
+         "type": {"key": {"type": "integer",
+                          "minInteger": 0,
+                          "maxInteger": 4294967295},
+                  "min": 0, "max": 1}},
+       "obs_point_id": {
+         "type": {"key": {"type": "integer",
+                          "minInteger": 0,
+                          "maxInteger": 4294967295},
+                  "min": 0, "max": 1}},
+       "external_ids": {
+         "type": {"key": "string", "value": "string",
+                  "min": 0, "max": "unlimited"}}}},
+   "Flow_Sample_Collector_Set": {
+     "columns": {
+       "id": {
+         "type": {"key": {"type": "integer",
+                          "minInteger": 0,
+                          "maxInteger": 4294967295},
+                  "min": 1, "max": 1}},
+       "bridge": {
+         "type": {"key": {"type": "uuid",
+                          "refTable": "Bridge"},
+                  "min": 1, "max": 1}},
+       "ipfix": {
+         "type": {"key": {"type": "uuid",
+                          "refTable": "IPFIX"},
+                  "min": 0, "max": 1}},
+       "external_ids": {
+         "type": {"key": "string", "value": "string",
+                  "min": 0, "max": "unlimited"}}},
+     "isRoot": true,
+     "indexes": [["id", "bridge"]]},
    "Controller": {
      "columns": {
        "target": {
index e717e6f..81339d2 100644 (file)
@@ -1,78 +1,92 @@
-.\" Generated from vswitch.gv with cksum "2197927206 1028"
+.\" Generated from vswitch.gv with cksum "2412173910 1224"
 .PS
 linethick = 1;
 linethick = 1;
-box at 3.269320992,2.78572 wid 0.5900294246 height 0.348215 "Bridge"
+box at 1.639964024,1.91216 wid 0.4050050488 height 0.23902 "Bridge"
 linethick = 1;
-box at 0.2708346627,1.9151825 wid 0.5416693254 height 0.348215 "sFlow"
+box at 5.72978744,1.31461 wid 0.3718099512 height 0.23902 "sFlow"
 linethick = 1;
-box at 0.996312758,1.9151825 wid 0.5706825992 height 0.348215 "Mirror"
+box at 6.22790512,1.31461 wid 0.3917250976 height 0.23902 "Mirror"
 linethick = 1;
-box at 2.795400377,1.9151825 wid 0.5223225 height 0.348215 "Port"
+box at 0.2589399268,1.31461 wid 0.35853 height 0.23902 "IPFIX"
 linethick = 1;
-box at 3.646577123,1.9151825 wid 0.831815992 height 0.348215 "Controller"
+box at 0.736994268,1.31461 wid 0.35853 height 0.23902 "Port"
 linethick = 1;
-box at 4.681541746,1.9151825 wid 0.889898254 height 0.348215 "Flow_Table"
+box at 1.321254756,1.31461 wid 0.570970976 height 0.23902 "Controller"
 linethick = 1;
-box at 6.103442877,1.9151825 wid 0.715790754 height 0.348215 "NetFlow"
+box at 2.03167,1.31461 wid 0.610839512 height 0.23902 "Flow_Table"
+linethick = 1;
+box at 5.17191476,1.31461 wid 0.491329512 height 0.23902 "NetFlow"
+linethick = 0.5;
+box at 0.35853,0.71706 wid 0.35853 height 0.23902 "QoS"
+box at 0.35853,0.71706 wid 0.302974444444444 height 0.183464444444444
 linethick = 0.5;
-box at 2.244036746,1.044645 wid 0.5223225 height 0.348215 "QoS"
-box at 2.244036746,1.044645 wid 0.466766944444444 height 0.292659444444444
+box at 0.35853,0.11951 wid 0.4116450244 height 0.23902 "Queue"
+box at 0.35853,0.11951 wid 0.356089468844444 height 0.183464444444444
 linethick = 0.5;
-box at 2.244036746,0.1741075 wid 0.5997028373 height 0.348215 "Queue"
-box at 2.244036746,0.1741075 wid 0.544147281744444 height 0.292659444444444
+box at 0.683884024,2.50971 wid 1.367720244 height 0.23902 "Flow_Sample_Collector_Set"
+box at 0.683884024,2.50971 wid 1.31216468844444 height 0.183464444444444
 linethick = 0.5;
-box at 4.052804742,3.6562575 wid 1.122018373 height 0.348215 "Open_vSwitch"
-box at 4.052804742,3.6562575 wid 1.06646281744444 height 0.292659444444444
+box at 2.177759024,2.50971 wid 0.770170244 height 0.23902 "Open_vSwitch"
+box at 2.177759024,2.50971 wid 0.714614688444444 height 0.183464444444444
+linethick = 1;
+box at 2.177759024,1.91216 wid 0.35853 height 0.23902 "SSL"
 linethick = 1;
-box at 4.052804742,2.78572 wid 0.5223225 height 0.348215 "SSL"
+box at 2.728795732,1.91216 wid 0.511215976 height 0.23902 "Manager"
 linethick = 1;
-box at 4.855649246,2.78572 wid 0.744762242 height 0.348215 "Manager"
+box at 0.916259268,0.71706 wid 0.517860732 height 0.23902 "Interface"
 linethick = 1;
-box at 3.056561627,1.044645 wid 0.754442619 height 0.348215 "Interface"
+spline -> from 1.83949792,1.821380204 to 1.83949792,1.821380204 to 1.872052444,1.809763832 to 1.905897676,1.799533776 to 1.938739024,1.79265 to 2.331687904,1.7101881 to 5.21254816,1.889883336 to 5.55052244,1.67314 to 5.63322336,1.620173168 to 5.6791152,1.516773116 to 5.70397328,1.43459804
+"sflow?" at 5.80627384,1.613385
 linethick = 1;
-spline -> from 2.976332891,2.75298779 to 2.976332891,2.75298779 to 2.604160699,2.706535909 to 1.945268276,2.607573206 to 1.402540377,2.437505 to 1.042625353,2.324752983 to 0.970266276,2.249190328 to 0.6287230754,2.08929 to 0.6011862332,2.076406045 to 0.5725420673,2.06282566 to 0.5439884373,2.049105989
-"sflow?" at 1.620174752,2.35045125
+spline -> from 1.839450116,1.821284596 to 1.839450116,1.821284596 to 1.872052444,1.809668224 to 1.905897676,1.799485972 to 1.938739024,1.79265 to 2.378774844,1.701153144 to 5.58780956,1.888544824 to 5.98219256,1.67314 to 6.07541036,1.622133132 to 6.1404238,1.518541864 to 6.18010112,1.43579314
+"mirrors*" at 6.30725976,1.613385
 linethick = 1;
-spline -> from 2.97514896,2.6812555 to 2.97514896,2.6812555 to 2.785302142,2.613214289 to 2.533333768,2.52177303 to 2.311729742,2.437505 to 1.95348615,2.301283292 to 1.543358523,2.137134741 to 1.277600835,2.029675592
-"mirrors*" at 2.592251746,2.35045125
+spline -> from 1.44033452,1.898966096 to 1.44033452,1.898966096 to 1.223830204,1.877406492 to 0.873952728,1.820806556 to 0.610839512,1.67314 to 0.505861928,1.614245472 to 0.4118171188,1.51466974 to 0.3474107896,1.435362904
+"ipfix?" at 0.733647988,1.613385
 linethick = 1;
-spline -> from 3.102665293,2.610428569 to 3.102665293,2.610428569 to 3.058372345,2.557708818 to 3.013382967,2.497746195 to 2.979188254,2.437505 to 2.917484556,2.32886192 to 2.871032675,2.19584379 to 2.840250469,2.091240004
-"ports*" at 3.187142252,2.35045125
+spline -> from 1.439569656,1.871861228 to 1.439569656,1.871861228 to 1.302372176,1.836725288 to 1.12195988,1.775010324 to 0.989255976,1.67314 to 0.907176508,1.610086524 to 0.84111138,1.512853188 to 0.797179504,1.43555412
+"ports*" at 1.132046524,1.613385
 linethick = 1;
-spline -> from 3.345719363,2.60952321 to 3.345719363,2.60952321 to 3.41111414,2.458537186 to 3.504923261,2.242017099 to 3.570387681,2.091100718
-"controller*" at 3.849725754,2.35045125
+spline -> from 1.43842236,1.800203032 to 1.43842236,1.800203032 to 1.39420366,1.765545132 to 1.353140024,1.72309518 to 1.327899512,1.67314 to 1.291090432,1.600334508 to 1.29022996,1.508168396 to 1.298165424,1.435506316
+"controller*" at 1.573564268,1.613385
 linethick = 1;
-spline -> from 3.563284095,2.664959038 to 3.563284095,2.664959038 to 3.610362763,2.646503643 to 3.658695005,2.628187534 to 3.704589742,2.6116125 to 3.942559873,2.525881967 to 4.036647566,2.578949933 to 4.246272996,2.437505 to 4.380335771,2.347038743 to 4.495594936,2.203852735 to 4.573734382,2.090195359
-"flow_tables value*" at 5.063603244,2.35045125
+spline -> from 1.733755472,1.79241098 to 1.733755472,1.79241098 to 1.76205544,1.754837036 to 1.792697804,1.71281732 to 1.819229024,1.67314 to 1.870666128,1.596127756 to 1.923776372,1.506495256 to 1.96402734,1.436127768
+"flow_tables value*" at 2.327146524,1.613385
 linethick = 1;
-spline -> from 3.560568018,2.655696519 to 3.560568018,2.655696519 to 3.607925258,2.638425055 to 3.657093216,2.622894666 to 3.704589742,2.6116125 to 4.143340642,2.507426572 to 5.333887727,2.659805456 to 5.726186746,2.437505 to 5.863383456,2.359713769 to 5.963947948,2.209215246 to 6.026557005,2.089638215
-"netflow?" at 6.204982371,2.35045125
+spline -> from 1.83949792,1.821523616 to 1.83949792,1.821523616 to 1.872100248,1.809907244 to 1.90594548,1.799629384 to 1.938739024,1.79265 to 2.27451432,1.721230824 to 4.744929432,1.870188088 to 5.02611256,1.67314 to 5.103077,1.61912148 to 5.13940804,1.516964332 to 5.15661748,1.435458512
+"netflow?" at 5.32154128,1.613385
 linethick = 0.5;
-spline -> from 1.285331208,1.9151825 to 1.285331208,1.9151825 to 1.629994415,1.9151825 to 2.201067015,1.9151825 to 2.533403411,1.9151825
-"select_src_port*" at 1.905502123,2.00223625
+spline -> from 6.03429892,1.412082356 to 6.03429892,1.412082356 to 6.01469928,1.420209036 to 5.9946216,1.427714264 to 5.9755,1.43412 to 5.56247344,1.571030656 to 5.44869992,1.583650912 to 5.01607372,1.626674512 to 4.690146048,1.65903782 to 4.606536852,1.636187508 to 4.279127256,1.626674512 to 2.80920206,1.583842128 to 2.396749148,1.813492544 to 0.976014268,1.43412 to 0.956271216,1.42886156 to 0.936289144,1.421882176 to 0.916689504,1.413898908
+"select_src_port*" at 4.647600488,1.613385
 linethick = 0.5;
-spline -> from 1.262209732,1.740239284 to 1.262209732,1.740239284 to 1.2953598,1.724778538 to 1.329693799,1.711546368 to 1.363818869,1.702353492 to 1.82882518,1.577483593 to 1.983711212,1.571981796 to 2.447185377,1.702353492 to 2.479917587,1.711616011 to 2.512649797,1.724848181 to 2.544128433,1.740239284
-"output_port?" at 1.905502123,1.789407242
+spline -> from 6.03429892,1.412082356 to 6.03429892,1.412082356 to 6.01469928,1.420209036 to 5.9946216,1.427714264 to 5.9755,1.43412 to 5.56247344,1.571030656 to 5.44869992,1.583650912 to 5.01607372,1.626674512 to 4.690146048,1.65903782 to 4.606536852,1.636187508 to 4.279127256,1.626674512 to 2.80920206,1.583842128 to 2.396749148,1.813492544 to 0.976014268,1.43412 to 0.956271216,1.42886156 to 0.936289144,1.421882176 to 0.916689504,1.413898908
+"output_port?" at 4.647600488,1.613385
 linethick = 0.5;
-spline -> from 1.066861117,1.739821426 to 1.066861117,1.739821426 to 1.126266596,1.618155105 to 1.224115011,1.465428006 to 1.363818869,1.39286 to 1.791148317,1.171047045 to 2.022641649,1.165684534 to 2.447185377,1.39286 to 2.583616014,1.465915507 to 2.675823346,1.618572963 to 2.730910959,1.740169641
-"select_dst_port*" at 1.905502123,1.47991375
+spline -> from 6.03429892,1.412082356 to 6.03429892,1.412082356 to 6.01469928,1.420209036 to 5.9946216,1.427714264 to 5.9755,1.43412 to 5.56247344,1.571030656 to 5.44869992,1.583650912 to 5.01607372,1.626674512 to 4.690146048,1.65903782 to 4.606536852,1.636187508 to 4.279127256,1.626674512 to 2.80920206,1.583842128 to 2.396749148,1.813492544 to 0.976014268,1.43412 to 0.956271216,1.42886156 to 0.936289144,1.421882176 to 0.916689504,1.413898908
+"select_dst_port*" at 4.647600488,1.613385
+linethick = 1;
+spline -> from 0.659121552,1.193092232 to 0.659121552,1.193092232 to 0.63507614,1.155470484 to 0.60854492,1.1138332 to 0.584260488,1.07559 to 0.533827268,0.996091948 to 0.4774089872,0.906459448 to 0.43358228,0.836713412
+"qos?" at 0.6871825,1.015835
+linethick = 1;
+spline -> from 0.773277504,1.19366588 to 0.773277504,1.19366588 to 0.804350104,1.090026808 to 0.848951236,0.941404172 to 0.880023836,0.837812904
+"interfaces+" at 1.108765976,1.015835
 linethick = 1;
-spline -> from 2.682021573,1.738149994 to 2.682021573,1.738149994 to 2.646921501,1.683340953 to 2.608269636,1.6226819 to 2.572890992,1.5669675 to 2.49948727,1.451151191 to 2.417238887,1.320570566 to 2.353376256,1.218961429
-"qos?" at 2.722832371,1.47991375
+spline -> from 0.35853,0.59611588 to 0.35853,0.59611588 to 0.35853,0.492476808 to 0.35853,0.3438732936 to 0.35853,0.2402533432
+"queues value*" at 0.690480976,0.418285
 linethick = 1;
-spline -> from 2.848259414,1.73898571 to 2.848259414,1.73898571 to 2.893527364,1.587999686 to 2.958504283,1.371479599 to 3.003772233,1.220563218
-"interfaces+" at 3.337083631,1.47991375
+spline -> from 0.877346812,2.38876588 to 0.877346812,2.38876588 to 1.043226692,2.285126808 to 1.280955984,2.136504172 to 1.446740256,2.032912904
+"bridge" at 1.390952988,2.210935
 linethick = 1;
-spline -> from 2.244036746,0.86844821 to 2.244036746,0.86844821 to 2.244036746,0.717462186 to 2.244036746,0.5009699562 to 2.244036746,0.3500117894
-"queues value*" at 2.727707381,0.60937625
+spline -> from 0.640764816,2.38852686 to 0.640764816,2.38852686 to 0.559115584,2.158876444 to 0.3827570672,1.66286214 to 0.3015046084,1.434311216
+"ipfix?" at 0.640717012,1.91216
 linethick = 1;
-spline -> from 3.657511074,3.480617854 to 3.657511074,3.480617854 to 3.582018062,3.433121328 to 3.509171484,3.375735496 to 3.453108869,3.3080425 to 3.370999772,3.208801225 to 3.324478248,3.070350941 to 3.298849624,2.960941788
-"bridges*" at 3.733630873,3.22098875
+spline -> from 1.906375716,2.389148312 to 1.906375716,2.389148312 to 1.85455618,2.356545984 to 1.804553196,2.317155488 to 1.766070976,2.27069 to 1.70971006,2.2025693 to 1.677776988,2.107534948 to 1.660185116,2.032434864
+"bridges*" at 1.958625488,2.210935
 linethick = 1;
-spline -> from 4.052804742,3.48006071 to 4.052804742,3.48006071 to 4.052804742,3.329074686 to 4.052804742,3.112554599 to 4.052804742,2.961638218
-"ssl?" at 4.173774633,3.22098875
+spline -> from 2.177759024,2.38876588 to 2.177759024,2.38876588 to 2.177759024,2.285126808 to 2.177759024,2.136504172 to 2.177759024,2.032912904
+"ssl?" at 2.260746768,2.210935
 linethick = 1;
-spline -> from 4.215281861,3.48006071 to 4.215281861,3.48006071 to 4.354567861,3.329074686 to 4.554234342,3.112554599 to 4.693450699,2.961638218
-"manager_options*" at 5.140976617,3.22098875
+spline -> from 2.289237952,2.38876588 to 2.289237952,2.38876588 to 2.384845952,2.285126808 to 2.52190002,2.136504172 to 2.617460216,2.032912904
+"manager_options*" at 2.924696524,2.210935
 .PE
index 2af04bd..b5bae78 100644 (file)
       </column>
 
       <column name="sflow">
-        sFlow configuration.
+        sFlow(R) configuration.
+      </column>
+
+      <column name="ipfix">
+        IPFIX configuration.
       </column>
 
       <column name="flood_vlans">
              with kernel version 2.6.26 or later.
            </p>
            <p>
-             As an experimental protocol, VXLAN has no officially assigned UDP
-             port.  Open vSwitch currently uses UDP destination port 8472.
-             The source port used for VXLAN traffic varies on a per-flow basis
-             and is in the ephemeral port range.
+             Open vSwitch uses UDP destination port 4789.  The source port used for
+             VXLAN traffic varies on a per-flow basis and is in the ephemeral port
+             range.
            </p>
           </dd>
 
           <dd>
             <p>
               Listens for SSL connections on the specified TCP <var>port</var>
-              (default: 6632).  If <var>ip</var>, which must be expressed as an
-              IP address (not a DNS name), is specified, then connections are
-              restricted to the specified local IP address.
+              (default: 6632).  Specify 0 for <var>port</var> to have the
+              kernel automatically choose an available port.  If <var>ip</var>,
+              which must be expressed as an IP address (not a DNS name), is
+              specified, then connections are restricted to the specified local
+              IP address.
             </p>
             <p>
               The <ref table="Open_vSwitch" column="ssl"/> column in the <ref
           <dt><code>ptcp:</code>[<var>port</var>][<code>:<var>ip</var></code>]</dt>
           <dd>
             Listens for connections on the specified TCP <var>port</var>
-            (default: 6632).  If <var>ip</var>, which must be expressed as an
-            IP address (not a DNS name), is specified, then connections are
-            restricted to the specified local IP address.
+            (default: 6632).  Specify 0 for <var>port</var> to have the kernel
+            automatically choose an available port.  If <var>ip</var>, which
+            must be expressed as an IP address (not a DNS name), is specified,
+            then connections are restricted to the specified local IP address.
           </dd>
         </dl>
         <p>When multiple managers are configured, the <ref column="target"/>
           chosen connection.
         </p>
       </column>
+
+      <column name="status" key="bound_port" type='{"type": "integer"}'>
+          When <ref column="target"/> is <code>ptcp:</code> or
+          <code>pssl:</code>, this is the TCP port on which the OVSDB server is
+          listening.  (This is is particularly useful when <ref
+          column="target"/> specifies a port of 0, allowing the kernel to
+          choose any available port.)
+      </column>
     </group>
 
     <group title="Connection Parameters">
   </table>
 
   <table name="sFlow">
-    <p>An sFlow(R) target.  sFlow is a protocol for remote monitoring
-    of switches.</p>
+    <p>A set of sFlow(R) targets.  sFlow is a protocol for remote
+    monitoring of switches.</p>
 
     <column name="agent">
       Name of the network device whose IP address should be reported as the
     </group>
   </table>
 
+  <table name="IPFIX">
+    <p>A set of IPFIX collectors.  IPFIX is a protocol that exports a
+    number of details about flows.</p>
+
+    <column name="targets">
+      IPFIX target collectors in the form
+      <code><var>ip</var>:<var>port</var></code>.
+    </column>
+
+    <column name="sampling">
+      For per-bridge packet sampling, i.e. when this row is referenced
+      from a <ref table="Bridge"/>, the rate at which packets should
+      be sampled and sent to each target collector.  If not specified,
+      defaults to 400, which means one out of 400 packets, on average,
+      will be sent to each target collector.  Ignored for per-flow
+      sampling, i.e. when this row is referenced from a <ref
+      table="Flow_Sample_Collector_Set"/>.
+    </column>
+
+    <column name="obs_domain_id">
+      For per-bridge packet sampling, i.e. when this row is referenced
+      from a <ref table="Bridge"/>, the IPFIX Observation Domain ID
+      sent in each IPFIX packet.  If not specified, defaults to 0.
+      Ignored for per-flow sampling, i.e. when this row is referenced
+      from a <ref table="Flow_Sample_Collector_Set"/>.
+    </column>
+
+    <column name="obs_point_id">
+      For per-bridge packet sampling, i.e. when this row is referenced
+      from a <ref table="Bridge"/>, the IPFIX Observation Point ID
+      sent in each IPFIX flow record.  If not specified, defaults to
+      0.  Ignored for per-flow sampling, i.e. when this row is
+      referenced from a <ref table="Flow_Sample_Collector_Set"/>.
+    </column>
+
+    <group title="Common Columns">
+      The overall purpose of these columns is described under <code>Common
+      Columns</code> at the beginning of this document.
+
+      <column name="external_ids"/>
+    </group>
+  </table>
+
+  <table name="Flow_Sample_Collector_Set">
+    <p>A set of IPFIX collectors of packet samples generated by
+    OpenFlow <code>sample</code> actions.</p>
+
+    <column name="id">
+      The ID of this collector set, unique among the bridge's
+      collector sets, to be used as the <code>collector_set_id</code>
+      in OpenFlow <code>sample</code> actions.
+    </column>
+
+    <column name="bridge">
+      The bridge into which OpenFlow <code>sample</code> actions can
+      be added to send packet samples to this set of IPFIX collectors.
+    </column>
+
+    <column name="ipfix">
+      Configuration of the set of IPFIX collectors to send one flow
+      record per sampled packet to.
+    </column>
+
+    <group title="Common Columns">
+      The overall purpose of these columns is described under <code>Common
+      Columns</code> at the beginning of this document.
+
+      <column name="external_ids"/>
+    </group>
+  </table>
+
 </database>