netflow: Implement NetFlow active timeouts.
[openvswitch] / vswitchd / bridge.c
index 157dc68664b258261eb47506ca714a1617cd8490..ad9b46ef3b4e4439e62f87c4d4c66e2afa2e4c1e 100644 (file)
@@ -48,6 +48,7 @@
 #include "port-array.h"
 #include "proc-net-compat.h"
 #include "process.h"
+#include "secchan/netflow.h"
 #include "secchan/ofproto.h"
 #include "socket-util.h"
 #include "stp.h"
@@ -494,10 +495,7 @@ bridge_reconfigure(void)
         uint64_t dpid;
         struct iface *local_iface = NULL;
         const char *devname;
-        uint8_t engine_type = br->dpif.minor;
-        uint8_t engine_id = br->dpif.minor;
-        bool add_id_to_iface = false;
-        struct svec nf_hosts;
+        struct netflow_options nf_options;
 
         bridge_fetch_dp_ifaces(br);
         for (i = 0; i < br->n_ports; ) {
@@ -542,35 +540,46 @@ bridge_reconfigure(void)
         ofproto_set_datapath_id(br->ofproto, dpid);
 
         /* Set NetFlow configuration on this bridge. */
+        memset(&nf_options, 0, sizeof nf_options);
+        nf_options.engine_type = br->dpif.minor;
+        nf_options.engine_id = br->dpif.minor;
+        nf_options.active_timeout = -1;
+
         if (cfg_has("netflow.%s.engine-type", br->name)) {
-            engine_type = cfg_get_int(0, "netflow.%s.engine-type", 
+            nf_options.engine_type = cfg_get_int(0, "netflow.%s.engine-type", 
                     br->name);
         }
         if (cfg_has("netflow.%s.engine-id", br->name)) {
-            engine_id = cfg_get_int(0, "netflow.%s.engine-id", br->name);
+            nf_options.engine_id = cfg_get_int(0, "netflow.%s.engine-id",
+                                               br->name);
+        }
+        if (cfg_has("netflow.%s.active-timeout", br->name)) {
+            nf_options.active_timeout = cfg_get_int(0,
+                                                    "netflow.%s.active-timeout",
+                                                    br->name);
         }
         if (cfg_has("netflow.%s.add-id-to-iface", br->name)) {
-            add_id_to_iface = cfg_get_bool(0, "netflow.%s.add-id-to-iface",
-                    br->name);
+            nf_options.add_id_to_iface = cfg_get_bool(0,
+                                                   "netflow.%s.add-id-to-iface",
+                                                    br->name);
         }
-        if (add_id_to_iface && engine_id > 0x7f) {
+        if (nf_options.add_id_to_iface && nf_options.engine_id > 0x7f) {
             VLOG_WARN("bridge %s: netflow port mangling may conflict with "
                     "another vswitch, choose an engine id less than 128", 
                     br->name);
         }
-        if (add_id_to_iface && br->n_ports > 0x1ff) {
+        if (nf_options.add_id_to_iface && br->n_ports > 508) {
             VLOG_WARN("bridge %s: netflow port mangling will conflict with "
-                    "another port when 512 or more ports are used", 
+                    "another port when more than 508 ports are used", 
                     br->name);
         }
-        svec_init(&nf_hosts);
-        cfg_get_all_keys(&nf_hosts, "netflow.%s.host", br->name);
-        if (ofproto_set_netflow(br->ofproto, &nf_hosts,  engine_type, 
-                    engine_id, add_id_to_iface)) {
+        svec_init(&nf_options.collectors);
+        cfg_get_all_keys(&nf_options.collectors, "netflow.%s.host", br->name);
+        if (ofproto_set_netflow(br->ofproto, &nf_options)) {
             VLOG_ERR("bridge %s: problem setting netflow collectors", 
                     br->name);
         }
-        svec_destroy(&nf_hosts);
+        svec_destroy(&nf_options.collectors);
 
         /* Update the controller and related settings.  It would be more
          * straightforward to call this from bridge_reconfigure_one(), but we
@@ -1677,7 +1686,7 @@ port_includes_vlan(const struct port *port, uint16_t vlan)
 static size_t
 compose_dsts(const struct bridge *br, const flow_t *flow, uint16_t vlan,
              const struct port *in_port, const struct port *out_port,
-             struct dst dsts[], tag_type *tags)
+             struct dst dsts[], tag_type *tags, uint16_t *nf_output_iface)
 {
     mirror_mask_t mirrors = in_port->src_mirrors;
     struct dst *dst = dsts;
@@ -1696,7 +1705,9 @@ compose_dsts(const struct bridge *br, const flow_t *flow, uint16_t vlan,
                 dst++;
             }
         }
+        *nf_output_iface = NF_OUT_FLOOD;
     } else if (out_port && set_dst(dst, flow, in_port, out_port, tags)) {
+        *nf_output_iface = dst->dp_ifidx;
         mirrors |= out_port->dst_mirrors;
         dst++;
     }
@@ -1764,14 +1775,16 @@ print_dsts(const struct dst *dsts, size_t n)
 static void
 compose_actions(struct bridge *br, const flow_t *flow, uint16_t vlan,
                 const struct port *in_port, const struct port *out_port,
-                tag_type *tags, struct odp_actions *actions)
+                tag_type *tags, struct odp_actions *actions,
+                uint16_t *nf_output_iface)
 {
     struct dst dsts[DP_MAX_PORTS * (MAX_MIRRORS + 1)];
     size_t n_dsts;
     const struct dst *p;
     uint16_t cur_vlan;
 
-    n_dsts = compose_dsts(br, flow, vlan, in_port, out_port, dsts, tags);
+    n_dsts = compose_dsts(br, flow, vlan, in_port, out_port, dsts, tags,
+                          nf_output_iface);
 
     cur_vlan = ntohs(flow->dl_vlan);
     for (p = dsts; p < &dsts[n_dsts]; p++) {
@@ -1804,7 +1817,7 @@ is_bcast_arp_reply(const flow_t *flow)
 static bool
 process_flow(struct bridge *br, const flow_t *flow,
              const struct ofpbuf *packet, struct odp_actions *actions,
-             tag_type *tags)
+             tag_type *tags, uint16_t *nf_output_iface)
 {
     struct iface *in_iface;
     struct port *in_port;
@@ -1960,7 +1973,8 @@ process_flow(struct bridge *br, const flow_t *flow,
     }
 
 done:
-    compose_actions(br, flow, vlan, in_port, out_port, tags, actions);
+    compose_actions(br, flow, vlan, in_port, out_port, tags, actions,
+                    nf_output_iface);
 
     return true;
 }
@@ -2005,7 +2019,8 @@ bridge_port_changed_ofhook_cb(enum ofp_port_reason reason,
 
 static bool
 bridge_normal_ofhook_cb(const flow_t *flow, const struct ofpbuf *packet,
-                        struct odp_actions *actions, tag_type *tags, void *br_)
+                        struct odp_actions *actions, tag_type *tags,
+                        uint16_t *nf_output_iface, void *br_)
 {
     struct bridge *br = br_;
 
@@ -2018,7 +2033,7 @@ bridge_normal_ofhook_cb(const flow_t *flow, const struct ofpbuf *packet,
 #endif
 
     COVERAGE_INC(bridge_process_flow);
-    return process_flow(br, flow, packet, actions, tags);
+    return process_flow(br, flow, packet, actions, tags, nf_output_iface);
 }
 
 static void