static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
-static void
-ofproto_initialize(void)
+/* Must be called to initialize the ofproto library.
+ *
+ * The caller may pass in 'iface_hints', which contains an shash of
+ * "iface_hint" elements indexed by the interface's name. The provider
+ * may use these hints to describe the startup configuration in order to
+ * reinitialize its state. The caller owns the provided data, so a
+ * provider will make copies of anything required. An ofproto provider
+ * will remove any existing state that is not described by the hint, and
+ * may choose to remove it all. */
+void
+ofproto_init(const struct shash *iface_hints)
{
- static bool inited;
+ size_t i;
- if (!inited) {
- inited = true;
- ofproto_class_register(&ofproto_dpif_class);
+ ofproto_class_register(&ofproto_dpif_class);
+
+ for (i = 0; i < n_ofproto_classes; i++) {
+ ofproto_classes[i]->init(iface_hints);
}
}
{
size_t i;
- ofproto_initialize();
for (i = 0; i < n_ofproto_classes; i++) {
const struct ofproto_class *class = ofproto_classes[i];
struct sset types;
{
size_t i;
- ofproto_initialize();
for (i = 0; i < n_ofproto_classes; i++) {
ofproto_classes[i]->enumerate_types(types);
}
*ofprotop = NULL;
- ofproto_initialize();
ofproto_unixctl_init();
datapath_type = ofproto_normalize_type(datapath_type);
hash_string(ofproto->name, 0));
ofproto->datapath_id = 0;
ofproto_set_flow_eviction_threshold(ofproto,
- OFPROTO_FLOW_EVICTON_THRESHOLD_DEFAULT);
+ OFPROTO_FLOW_EVICTION_THRESHOLD_DEFAULT);
ofproto->forward_bpdu = false;
ofproto->fallback_dpid = pick_fallback_dpid();
ofproto->mfr_desc = xstrdup(DEFAULT_MFR_DESC);
return dump->error == EOF ? 0 : dump->error;
}
-/* Attempts to add 'netdev' as a port on 'ofproto'. If successful, returns 0
- * and sets '*ofp_portp' to the new port's OpenFlow port number (if 'ofp_portp'
- * is non-null). On failure, returns a positive errno value and sets
- * '*ofp_portp' to OFPP_NONE (if 'ofp_portp' is non-null). */
+/* Attempts to add 'netdev' as a port on 'ofproto'. If 'ofp_portp' is
+ * non-null and '*ofp_portp' is not OFPP_NONE, attempts to use that as
+ * the port's OpenFlow port number.
+ *
+ * If successful, returns 0 and sets '*ofp_portp' to the new port's
+ * OpenFlow port number (if 'ofp_portp' is non-null). On failure,
+ * returns a positive errno value and sets '*ofp_portp' to OFPP_NONE (if
+ * 'ofp_portp' is non-null). */
int
ofproto_port_add(struct ofproto *ofproto, struct netdev *netdev,
uint16_t *ofp_portp)
{
- uint16_t ofp_port;
+ uint16_t ofp_port = ofp_portp ? *ofp_portp : OFPP_NONE;
int error;
error = ofproto->ofproto_class->port_add(ofproto, netdev, &ofp_port);
rule->evictable = was_evictable;
if (!evict) {
- error = OFPERR_OFPFMFC_ALL_TABLES_FULL;
+ error = OFPERR_OFPFMFC_TABLE_FULL;
goto exit;
} else if (evict->pending) {
error = OFPROTO_POSTPONE;
return error;
}
+static enum ofperr
+modify_flows_add(struct ofproto *ofproto, struct ofconn *ofconn,
+ const struct ofputil_flow_mod *fm,
+ const struct ofp_header *request)
+{
+ if (fm->cookie_mask != htonll(0) || fm->new_cookie == htonll(UINT64_MAX)) {
+ return 0;
+ }
+ return add_flow(ofproto, ofconn, fm, request);
+}
+
/* Implements OFPFC_MODIFY. Returns 0 on success or an OpenFlow error code on
* failure.
*
if (error) {
return error;
} else if (list_is_empty(&rules)) {
- return fm->cookie_mask ? 0 : add_flow(ofproto, ofconn, fm, request);
+ return modify_flows_add(ofproto, ofconn, fm, request);
} else {
return modify_flows__(ofproto, ofconn, fm, request, &rules);
}
if (error) {
return error;
} else if (list_is_empty(&rules)) {
- return fm->cookie_mask ? 0 : add_flow(ofproto, ofconn, fm, request);
+ return modify_flows_add(ofproto, ofconn, fm, request);
} else {
return list_is_singleton(&rules) ? modify_flows__(ofproto, ofconn,
fm, request, &rules)
* is not required in OpenFlow 1.0.1 and removed from OpenFlow 1.1.
* There is no good error code, so just state that the flow table
* is full. */
- error = OFPERR_OFPFMFC_ALL_TABLES_FULL;
+ error = OFPERR_OFPFMFC_TABLE_FULL;
}
if (!error) {
error = ofpacts_check(fm.ofpacts, fm.ofpacts_len,