Add IPFIX collector set configuration.  Add support for per-bridge
IPFIX sampling.

Signed-off-by: Romain Lenglet <[email protected]>
---
 ofproto/automake.mk          |   2 +
 ofproto/ofproto-dpif-ipfix.c | 160 +++++++++++++++++++++++++++++++++++++++++++
 ofproto/ofproto-dpif-ipfix.h |  29 ++++++++
 ofproto/ofproto-dpif.c       |  26 +++++++
 ofproto/ofproto-provider.h   |  11 +++
 ofproto/ofproto.c            |  12 ++++
 ofproto/ofproto.h            |   9 +++
 tests/ovs-vsctl.at           |   4 +-
 utilities/ovs-vsctl.8.in     |  26 +++++--
 utilities/ovs-vsctl.c        |  13 ++++
 vswitchd/bridge.c            |  34 ++++++++-
 vswitchd/vswitch.ovsschema   |  28 +++++++-
 vswitchd/vswitch.xml         |  53 +++++++++++++-
 13 files changed, 397 insertions(+), 10 deletions(-)
 create mode 100644 ofproto/ofproto-dpif-ipfix.c
 create mode 100644 ofproto/ofproto-dpif-ipfix.h

diff --git a/ofproto/automake.mk b/ofproto/automake.mk
index 69f014f..248c1e9 100644
--- a/ofproto/automake.mk
+++ b/ofproto/automake.mk
@@ -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 \
diff --git a/ofproto/ofproto-dpif-ipfix.c b/ofproto/ofproto-dpif-ipfix.c
new file mode 100644
index 0000000..446f2c6
--- /dev/null
+++ b/ofproto/ofproto-dpif-ipfix.c
@@ -0,0 +1,160 @@
+/*
+ * 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 "collectors.h"
+#include "ofproto.h"
+#include "sset.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_bridge_exporter {
+    struct collectors *collectors;
+    struct ofproto_ipfix_bridge_exporter_options *options;
+    uint32_t probability;
+};
+
+struct dpif_ipfix {
+    struct dpif_ipfix_bridge_exporter bridge_exporter;
+};
+
+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 void
+dpif_ipfix_bridge_exporter_clear(struct dpif_ipfix_bridge_exporter *exporter)
+{
+    collectors_destroy(exporter->collectors);
+    exporter->collectors = NULL;
+    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 (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->collectors)
+            < sset_count(&options->targets)) {
+        collectors_destroy(exporter->collectors);
+        collectors_create(&options->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_bridge_exporter_clear(exporter);
+            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);
+}
+
+void
+dpif_ipfix_set_options(
+    struct dpif_ipfix *di,
+    const struct ofproto_ipfix_bridge_exporter_options 
*bridge_exporter_options)
+{
+    dpif_ipfix_bridge_exporter_set_options(&(di->bridge_exporter),
+                                           bridge_exporter_options);
+}
+
+struct dpif_ipfix *
+dpif_ipfix_create(void)
+{
+    struct dpif_ipfix *di;
+    di = xzalloc(sizeof *di);
+    return di;
+}
+
+void
+dpif_ipfix_destroy(struct dpif_ipfix *di)
+{
+    if (di) {
+        dpif_ipfix_clear(di);
+        free(di);
+    }
+}
+
+void
+dpif_ipfix_clear(struct dpif_ipfix *di)
+{
+    dpif_ipfix_bridge_exporter_clear(&(di->bridge_exporter));
+}
diff --git a/ofproto/ofproto-dpif-ipfix.h b/ofproto/ofproto-dpif-ipfix.h
new file mode 100644
index 0000000..297be56
--- /dev/null
+++ b/ofproto/ofproto-dpif-ipfix.h
@@ -0,0 +1,29 @@
+/*
+ * 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
+
+struct ofproto_ipfix_bridge_exporter_options;
+
+struct dpif_ipfix *dpif_ipfix_create(void);
+void dpif_ipfix_destroy(struct dpif_ipfix *);
+void dpif_ipfix_set_options(
+    struct dpif_ipfix *,
+    const struct ofproto_ipfix_bridge_exporter_options *);
+void dpif_ipfix_clear(struct dpif_ipfix *);
+
+#endif /* ofproto/ofproto-dpif-ipfix.h */
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 84607fb..bd92694 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -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"
@@ -684,6 +685,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];
@@ -1240,6 +1242,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);
@@ -1788,6 +1791,28 @@ set_sflow(struct ofproto *ofproto_,
 }
 
 static int
+set_ipfix(
+    struct ofproto *ofproto_,
+    const struct ofproto_ipfix_bridge_exporter_options 
*bridge_exporter_options)
+{
+    struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
+    struct dpif_ipfix *di = ofproto->ipfix;
+
+    if (bridge_exporter_options) {
+        if (!di) {
+            di = ofproto->ipfix = dpif_ipfix_create();
+        }
+        dpif_ipfix_set_options(di, bridge_exporter_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)
 {
     struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
@@ -8653,6 +8678,7 @@ const struct ofproto_class ofproto_dpif_class = {
     set_netflow,
     get_netflow_ids,
     set_sflow,
+    set_ipfix,
     set_cfm,
     get_cfm_status,
     set_stp,
diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
index d8db3ae..2272ff2 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -1109,6 +1109,17 @@ 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', or turns off IPFIX if
+     * 'bridge_exporter_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);
+
     /* Configures connectivity fault management on 'ofport'.
      *
      * If 'cfm_settings' is nonnull, configures CFM according to its members.
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 03ca59b..e142759 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -640,6 +640,18 @@ ofproto_set_sflow(struct ofproto *ofproto,
         return oso ? EOPNOTSUPP : 0;
     }
 }
+
+int
+ofproto_set_ipfix(struct ofproto *ofproto,
+                  const struct ofproto_ipfix_bridge_exporter_options *oibeo)
+{
+    /* TODO: Check the options. */
+    if (ofproto->ofproto_class->set_ipfix) {
+        return ofproto->ofproto_class->set_ipfix(ofproto, oibeo);
+    } else {
+        return oibeo ? EOPNOTSUPP : 0;
+    }
+}
 
 /* Spanning Tree Protocol (STP) configuration. */
 
diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h
index cdd5bae..5cec201 100644
--- a/ofproto/ofproto.h
+++ b/ofproto/ofproto.h
@@ -68,6 +68,13 @@ 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_stp_settings {
     stp_identifier system_id;
     uint16_t priority;
@@ -229,6 +236,8 @@ 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 *);
 int ofproto_set_stp(struct ofproto *, const struct ofproto_stp_settings *);
 int ofproto_get_stp_status(struct ofproto *, struct ofproto_stp_status *);
 
diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at
index c5c3f47..bc798c6 100644
--- a/tests/ovs-vsctl.at
+++ b/tests/ovs-vsctl.at
@@ -632,6 +632,7 @@ external_ids        : {}
 fail_mode           : []
 flood_vlans         : []
 flow_tables         : {}
+ipfix               : []
 mirrors             : []
 name                : "br0"
 netflow             : []
@@ -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])],
@@ -1123,6 +1124,7 @@ external_ids        : {}
 fail_mode           : []
 flood_vlans         : []
 flow_tables         : {}
+ipfix               : []
 mirrors             : []
 name                : "br0"
 netflow             : []
diff --git a/utilities/ovs-vsctl.8.in b/utilities/ovs-vsctl.8.in
index 85149a9..003e99a 100644
--- a/utilities/ovs-vsctl.8.in
+++ b/utilities/ovs-vsctl.8.in
@@ -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.
@@ -528,6 +529,9 @@ specifying \fB.\fR as the record name.
 .IP "\fBsFlow\fR"
 An sFlow configuration attached to a bridge.  Records may be
 identified by bridge name.
+.IP "\fBIPFIX\fR"
+An IPFIX configuration attached to a bridge.  Records may be
+identified by bridge name.
 .PP
 Record names must be specified in full and with correct
 capitalization.  Names of tables and columns are not case-sensitive,
@@ -931,6 +935,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:
diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c
index 18ace60..4c1ec17 100644
--- a/utilities/ovs-vsctl.c
+++ b/utilities/ovs-vsctl.c
@@ -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,7 @@ 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;
 
     /* Reset the Open_vSwitch table. */
     ovsrec_open_vswitch_set_manager_options(ctx->ovs, NULL, 0);
@@ -1490,6 +1492,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 +1542,10 @@ cmd_emer_reset(struct vsctl_context *ctx)
         ovsrec_sflow_delete(sflow);
     }
 
+    OVSREC_IPFIX_FOR_EACH_SAFE (ipfix, next_ipfix, idl) {
+        ovsrec_ipfix_delete(ipfix);
+    }
+
     vsctl_context_invalidate_cache(ctx);
 }
 
@@ -2518,6 +2525,12 @@ 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},
+      {NULL, NULL, NULL}}},
+
     {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
 };
 
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 6dc3db2..d2c3907 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -183,6 +183,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 +372,8 @@ 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_manager_col_external_ids);
     ovsdb_idl_omit(idl, &ovsrec_manager_col_inactivity_probe);
@@ -595,6 +596,7 @@ 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);
@@ -936,6 +938,36 @@ 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 *cfg = br->cfg->ipfix;
+    struct ofproto_ipfix_bridge_exporter_options oibeo;
+
+    if (!cfg) {
+        ofproto_set_ipfix(br->ofproto, NULL);
+        return;
+    }
+
+    memset(&oibeo, 0, sizeof oibeo);
+
+    /* Collectors. */
+    sset_init(&oibeo.targets);
+    sset_add_array(&oibeo.targets, cfg->targets, cfg->n_targets);
+
+    oibeo.sampling_rate = SFL_DEFAULT_SAMPLING_RATE;
+    if (cfg->sampling) {
+        oibeo.sampling_rate = *cfg->sampling;
+    }
+    oibeo.obs_domain_id = *cfg->obs_domain_id;
+    oibeo.obs_point_id = *cfg->obs_point_id;
+
+    ofproto_set_ipfix(br->ofproto, &oibeo);
+
+    sset_destroy(&oibeo.targets);
+}
+
 static void
 port_configure_stp(const struct ofproto *ofproto, struct port *port,
                    struct ofproto_port_stp_settings *port_s,
diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema
index 594ffb4..0d1f4fd 100644
--- a/vswitchd/vswitch.ovsschema
+++ b/vswitchd/vswitch.ovsschema
@@ -1,6 +1,6 @@
 {"name": "Open_vSwitch",
  "version": "7.1.0",
- "cksum": "2234055133 17444",
+ "cksum": "4242091849 18457",
  "tables": {
    "Open_vSwitch": {
      "columns": {
@@ -70,6 +70,10 @@
          "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"},
@@ -383,6 +387,28 @@
        "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"}}}},
    "Controller": {
      "columns": {
        "target": {
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 2af04bd..24452b1 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -340,7 +340,11 @@
       </column>
 
       <column name="sflow">
-        sFlow configuration.
+        sFlow(R) configuration.
+      </column>
+
+      <column name="ipfix">
+        IPFIX configuration.
       </column>
 
       <column name="flood_vlans">
@@ -3118,8 +3122,8 @@
   </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
@@ -3160,4 +3164,47 @@
     </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="FlowSampleCollectorSet"/>.
+    </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="FlowSampleCollectorSet"/>.
+    </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="FlowSampleCollectorSet"/>.
+    </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>
-- 
1.8.1.3

_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

Reply via email to