static enum ofperr handle_flow_mod__(struct ofproto *, struct ofconn *,
const struct ofputil_flow_mod *,
const struct ofp_header *);
+static void calc_duration(long long int start, long long int now,
+ uint32_t *sec, uint32_t *nsec);
/* ofproto. */
static uint64_t pick_datapath_id(const struct ofproto *);
static size_t n_ofproto_classes;
static size_t allocated_ofproto_classes;
+unsigned flow_eviction_threshold = OFPROTO_FLOW_EVICTION_THRESHOLD_DEFAULT;
+
/* Map from datapath name to struct ofproto, for use by unixctl commands. */
static struct hmap all_ofprotos = HMAP_INITIALIZER(&all_ofprotos);
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
+/* The default value of true waits for flow restore. */
+static bool flow_restore_wait = true;
+
/* Must be called to initialize the ofproto library.
*
* The caller may pass in 'iface_hints', which contains an shash of
hmap_insert(&all_ofprotos, &ofproto->hmap_node,
hash_string(ofproto->name, 0));
ofproto->datapath_id = 0;
- ofproto_set_flow_eviction_threshold(ofproto,
- OFPROTO_FLOW_EVICTION_THRESHOLD_DEFAULT);
ofproto->forward_bpdu = false;
ofproto->fallback_dpid = pick_fallback_dpid();
ofproto->mfr_desc = NULL;
/* Sets the number of flows at which eviction from the kernel flow table
* will occur. */
void
-ofproto_set_flow_eviction_threshold(struct ofproto *ofproto, unsigned threshold)
+ofproto_set_flow_eviction_threshold(unsigned threshold)
{
- if (threshold < OFPROTO_FLOW_EVICTION_THRESHOLD_MIN) {
- ofproto->flow_eviction_threshold = OFPROTO_FLOW_EVICTION_THRESHOLD_MIN;
- } else {
- ofproto->flow_eviction_threshold = threshold;
- }
+ flow_eviction_threshold = MAX(OFPROTO_FLOW_EVICTION_THRESHOLD_MIN,
+ threshold);
}
/* If forward_bpdu is true, the NORMAL action will forward frames with
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;
+ }
+}
+
+void
+ofproto_set_flow_restore_wait(bool flow_restore_wait_db)
+{
+ flow_restore_wait = flow_restore_wait_db;
+}
+
+bool
+ofproto_get_flow_restore_wait(void)
+{
+ return flow_restore_wait;
+}
+
\f
/* Spanning Tree Protocol (STP) configuration. */
}
}
+/* Configures BFD on 'ofp_port' in 'ofproto'. This function has no effect if
+ * 'ofproto' does not have a port 'ofp_port'. */
+void
+ofproto_port_set_bfd(struct ofproto *ofproto, uint16_t ofp_port,
+ const struct smap *cfg)
+{
+ struct ofport *ofport;
+ int error;
+
+ ofport = ofproto_get_port(ofproto, ofp_port);
+ if (!ofport) {
+ VLOG_WARN("%s: cannot configure bfd on nonexistent port %"PRIu16,
+ ofproto->name, ofp_port);
+ return;
+ }
+
+ error = (ofproto->ofproto_class->set_bfd
+ ? ofproto->ofproto_class->set_bfd(ofport, cfg)
+ : EOPNOTSUPP);
+ if (error) {
+ VLOG_WARN("%s: bfd configuration on port %"PRIu16" (%s) failed (%s)",
+ ofproto->name, ofp_port, netdev_get_name(ofport->netdev),
+ strerror(error));
+ }
+}
+
+/* Populates 'status' with key value pairs indicating the status of the BFD
+ * session on 'ofp_port'. This information is intended to be populated in the
+ * OVS database. Has no effect if 'ofp_port' is not na OpenFlow port in
+ * 'ofproto'. */
+int
+ofproto_port_get_bfd_status(struct ofproto *ofproto, uint16_t ofp_port,
+ struct smap *status)
+{
+ struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
+ return (ofport && ofproto->ofproto_class->get_bfd_status
+ ? ofproto->ofproto_class->get_bfd_status(ofport, status)
+ : EOPNOTSUPP);
+}
+
/* Checks the status of LACP negotiation for 'ofp_port' within ofproto.
* Returns 1 if LACP partner information for 'ofp_port' is up-to-date,
* 0 if LACP partner information is not current (generally indicating a
ofport->change_seq = netdev_change_seq(netdev);
ofport->pp = *pp;
ofport->ofp_port = pp->port_no;
+ ofport->created = time_msec();
/* Add port to 'p'. */
hmap_insert(&p->ports, &ofport->hmap_node, hash_int(ofport->ofp_port, 0));
toggle = (config ^ port->pp.config) & mask;
if (toggle & OFPUTIL_PC_PORT_DOWN) {
if (config & OFPUTIL_PC_PORT_DOWN) {
- netdev_turn_flags_off(port->netdev, NETDEV_UP, true);
+ netdev_turn_flags_off(port->netdev, NETDEV_UP, NULL);
} else {
- netdev_turn_flags_on(port->netdev, NETDEV_UP, true);
+ netdev_turn_flags_on(port->netdev, NETDEV_UP, NULL);
}
toggle &= ~OFPUTIL_PC_PORT_DOWN;
}
{
struct ofputil_port_stats ops = { .port_no = port->pp.port_no };
+ calc_duration(port->created, time_msec(),
+ &ops.duration_sec, &ops.duration_nsec);
+
/* Intentionally ignore return value, since errors will set
* 'stats' to all-1s, which is correct for OpenFlow, and
* netdev_get_stats() will log errors. */
}
static void
-calc_flow_duration__(long long int start, long long int now,
- uint32_t *sec, uint32_t *nsec)
+calc_duration(long long int start, long long int now,
+ uint32_t *sec, uint32_t *nsec)
{
long long int msecs = now - start;
*sec = msecs / 1000;
fs.priority = rule->cr.priority;
fs.cookie = rule->flow_cookie;
fs.table_id = rule->table_id;
- calc_flow_duration__(rule->created, now, &fs.duration_sec,
- &fs.duration_nsec);
+ calc_duration(rule->created, now, &fs.duration_sec, &fs.duration_nsec);
fs.idle_timeout = rule->idle_timeout;
fs.hard_timeout = rule->hard_timeout;
fs.idle_age = age_secs(now - rule->used);
fr.cookie = rule->flow_cookie;
fr.reason = reason;
fr.table_id = rule->table_id;
- calc_flow_duration__(rule->created, time_msec(),
- &fr.duration_sec, &fr.duration_nsec);
+ calc_duration(rule->created, time_msec(),
+ &fr.duration_sec, &fr.duration_nsec);
fr.idle_timeout = rule->idle_timeout;
fr.hard_timeout = rule->hard_timeout;
rule->ofproto->ofproto_class->rule_get_stats(rule, &fr.packet_count,