ofproto-dpif: Add 'force-miss-model' configuration
[sliver-openvswitch.git] / vswitchd / bridge.c
index f5c4202..4ac2b26 100644 (file)
@@ -67,13 +67,13 @@ struct if_cfg {
     struct hmap_node hmap_node;         /* Node in bridge's if_cfg_todo. */
     const struct ovsrec_interface *cfg; /* Interface record. */
     const struct ovsrec_port *parent;   /* Parent port record. */
-    uint16_t ofport;                    /* Requested OpenFlow port number. */
+    ofp_port_t ofport;                  /* Requested OpenFlow port number. */
 };
 
 /* OpenFlow port slated for removal from ofproto. */
 struct ofpp_garbage {
     struct list list_node;      /* Node in bridge's ofpp_garbage. */
-    uint16_t ofp_port;          /* Port to be deleted. */
+    ofp_port_t ofp_port;        /* Port to be deleted. */
 };
 
 struct iface {
@@ -86,7 +86,7 @@ struct iface {
     /* These members are valid only after bridge_reconfigure() causes them to
      * be initialized. */
     struct hmap_node ofp_port_node; /* In struct bridge's "ifaces" hmap. */
-    uint16_t ofp_port;          /* OpenFlow port number, */
+    ofp_port_t ofp_port;        /* OpenFlow port number, */
                                 /* OFPP_NONE if unknown. */
     struct netdev *netdev;      /* Network device. */
     const char *type;           /* Usually same as cfg->type. */
@@ -196,8 +196,8 @@ static size_t bridge_get_controllers(const struct bridge *br,
 static void bridge_add_del_ports(struct bridge *,
                                  const unsigned long int *splinter_vlans);
 static void bridge_refresh_ofp_port(struct bridge *);
+static void bridge_configure_flow_miss_model(const char *opt);
 static void bridge_configure_datapath_id(struct bridge *);
-static void bridge_configure_flow_eviction_threshold(struct bridge *);
 static void bridge_configure_netflow(struct bridge *);
 static void bridge_configure_forward_bpdu(struct bridge *);
 static void bridge_configure_mac_table(struct bridge *);
@@ -246,7 +246,8 @@ static bool mirror_configure(struct mirror *);
 static void mirror_refresh_stats(struct mirror *);
 
 static void iface_configure_lacp(struct iface *, struct lacp_slave_settings *);
-static bool iface_create(struct bridge *, struct if_cfg *, uint16_t ofp_port);
+static bool iface_create(struct bridge *, struct if_cfg *,
+                         ofp_port_t ofp_port);
 static bool iface_is_internal(const struct ovsrec_interface *iface,
                               const struct ovsrec_bridge *br);
 static const char *iface_get_type(const struct ovsrec_interface *,
@@ -256,9 +257,9 @@ static struct iface *iface_lookup(const struct bridge *, const char *name);
 static struct iface *iface_find(const char *name);
 static struct if_cfg *if_cfg_lookup(const struct bridge *, const char *name);
 static struct iface *iface_from_ofp_port(const struct bridge *,
-                                         uint16_t ofp_port);
+                                         ofp_port_t ofp_port);
 static void iface_set_mac(struct iface *);
-static void iface_set_ofport(const struct ovsrec_interface *, uint16_t ofport);
+static void iface_set_ofport(const struct ovsrec_interface *, ofp_port_t ofport);
 static void iface_clear_db_record(const struct ovsrec_interface *if_cfg);
 static void iface_configure_qos(struct iface *, const struct ovsrec_qos *);
 static void iface_configure_cfm(struct iface *);
@@ -266,7 +267,7 @@ static void iface_refresh_cfm_stats(struct iface *);
 static void iface_refresh_stats(struct iface *);
 static void iface_refresh_status(struct iface *);
 static bool iface_is_synthetic(const struct iface *);
-static uint16_t iface_pick_ofport(const struct ovsrec_interface *);
+static ofp_port_t iface_pick_ofport(const struct ovsrec_interface *);
 
 /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
  *
@@ -495,6 +496,13 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
     ovs_assert(!reconfiguring);
     reconfiguring = true;
 
+    ofproto_set_flow_eviction_threshold(
+        smap_get_int(&ovs_cfg->other_config, "flow-eviction-threshold",
+                     OFPROTO_FLOW_EVICTION_THRESHOLD_DEFAULT));
+
+    bridge_configure_flow_miss_model(smap_get(&ovs_cfg->other_config,
+                                              "force-miss-model"));
+
     /* Destroy "struct bridge"s, "struct port"s, and "struct iface"s according
      * to 'ovs_cfg' while update the "if_cfg_queue", with only very minimal
      * configuration otherwise.
@@ -613,7 +621,6 @@ bridge_reconfigure_continue(const struct ovsrec_open_vswitch *ovs_cfg)
             }
         }
         bridge_configure_mirrors(br);
-        bridge_configure_flow_eviction_threshold(br);
         bridge_configure_forward_bpdu(br);
         bridge_configure_mac_table(br);
         bridge_configure_remotes(br, managers, n_managers);
@@ -623,6 +630,13 @@ bridge_reconfigure_continue(const struct ovsrec_open_vswitch *ovs_cfg)
         bridge_configure_stp(br);
         bridge_configure_tables(br);
         bridge_configure_dp_desc(br);
+
+        if (smap_get(&br->cfg->other_config, "flow-eviction-threshold")) {
+            /* XXX: Remove this warning message eventually. */
+            VLOG_WARN_ONCE("As of June 2013, flow-eviction-threshold has been"
+                           " moved to the Open_vSwitch table.  Ignoring its"
+                           " setting in the bridge table.");
+        }
     }
     free(managers);
 
@@ -794,6 +808,25 @@ port_configure(struct port *port)
     free(s.lacp_slaves);
 }
 
+static void
+bridge_configure_flow_miss_model(const char *opt)
+{
+    enum ofproto_flow_miss_model model = OFPROTO_HANDLE_MISS_AUTO;
+
+    if (opt) {
+        if (strcmp(opt, "with-facets")) {
+            model = OFPROTO_HANDLE_MISS_WITH_FACETS;
+            VLOG_INFO("Handling all flow misses by creating facets.\n");
+        }
+        if (strcmp(opt, "without-facets")) {
+            model = OFPROTO_HANDLE_MISS_WITHOUT_FACETS;
+            VLOG_INFO("Handling all flow misses without creating facets.\n");
+        }
+    }
+
+    ofproto_set_flow_miss_model(model);
+}
+
 /* Pick local port hardware address and datapath ID for 'br'. */
 static void
 bridge_configure_datapath_id(struct bridge *br)
@@ -1268,13 +1301,14 @@ add_del_bridges(const struct ovsrec_open_vswitch *cfg)
 }
 
 static void
-iface_set_ofp_port(struct iface *iface, uint16_t ofp_port)
+iface_set_ofp_port(struct iface *iface, ofp_port_t ofp_port)
 {
     struct bridge *br = iface->port->bridge;
 
     ovs_assert(iface->ofp_port == OFPP_NONE && ofp_port != OFPP_NONE);
     iface->ofp_port = ofp_port;
-    hmap_insert(&br->ifaces, &iface->ofp_port_node, hash_int(ofp_port, 0));
+    hmap_insert(&br->ifaces, &iface->ofp_port_node,
+                hash_ofp_port(ofp_port));
     iface_set_ofport(iface->cfg, ofp_port);
 }
 
@@ -1309,7 +1343,7 @@ bridge_refresh_one_ofp_port(struct bridge *br,
 {
     const char *name = ofproto_port->name;
     const char *type = ofproto_port->type;
-    uint16_t ofp_port = ofproto_port->ofp_port;
+    ofp_port_t ofp_port = ofproto_port->ofp_port;
 
     struct iface *iface = iface_lookup(br, name);
     if (iface) {
@@ -1412,7 +1446,7 @@ bridge_refresh_ofp_port(struct bridge *br)
 static int
 iface_do_create(const struct bridge *br,
                 const struct if_cfg *if_cfg,
-                uint16_t *ofp_portp, struct netdev **netdevp)
+                ofp_port_t *ofp_portp, struct netdev **netdevp)
 {
     const struct ovsrec_interface *iface_cfg = if_cfg->cfg;
     const struct ovsrec_port *port_cfg = if_cfg->parent;
@@ -1440,7 +1474,7 @@ iface_do_create(const struct bridge *br,
     }
 
     if (*ofp_portp == OFPP_NONE) {
-        uint16_t ofp_port = if_cfg->ofport;
+        ofp_port_t ofp_port = if_cfg->ofport;
 
         error = ofproto_port_add(br->ofproto, netdev, &ofp_port);
         if (error) {
@@ -1476,7 +1510,7 @@ error:
  *
  * Return true if an iface is successfully created, false otherwise. */
 static bool
-iface_create(struct bridge *br, struct if_cfg *if_cfg, uint16_t ofp_port)
+iface_create(struct bridge *br, struct if_cfg *if_cfg, ofp_port_t ofp_port)
 {
     const struct ovsrec_interface *iface_cfg = if_cfg->cfg;
     const struct ovsrec_port *port_cfg = if_cfg->parent;
@@ -1538,7 +1572,7 @@ iface_create(struct bridge *br, struct if_cfg *if_cfg, uint16_t ofp_port)
 
             error = netdev_open(port->name, "internal", &netdev);
             if (!error) {
-                uint16_t fake_ofp_port = if_cfg->ofport;
+                ofp_port_t fake_ofp_port = if_cfg->ofport;
 
                 ofproto_port_add(br->ofproto, netdev, &fake_ofp_port);
                 netdev_close(netdev);
@@ -1559,23 +1593,6 @@ done:
     return ok;
 }
 
-/* Set Flow eviction threshold */
-static void
-bridge_configure_flow_eviction_threshold(struct bridge *br)
-{
-    const char *threshold_str;
-    unsigned threshold;
-
-    threshold_str = smap_get(&br->cfg->other_config,
-                             "flow-eviction-threshold");
-    if (threshold_str) {
-        threshold = strtoul(threshold_str, NULL, 10);
-    } else {
-        threshold = OFPROTO_FLOW_EVICTION_THRESHOLD_DEFAULT;
-    }
-    ofproto_set_flow_eviction_threshold(br->ofproto, threshold);
-}
-
 /* Set forward BPDU option. */
 static void
 bridge_configure_forward_bpdu(struct bridge *br)
@@ -3299,7 +3316,7 @@ iface_configure_lacp(struct iface *iface, struct lacp_slave_settings *s)
     key = smap_get_int(&iface->cfg->other_config, "lacp-aggregation-key", 0);
 
     if (portid <= 0 || portid > UINT16_MAX) {
-        portid = iface->ofp_port;
+        portid = ofp_to_u16(iface->ofp_port);
     }
 
     if (priority <= 0 || priority > UINT16_MAX) {
@@ -3487,12 +3504,12 @@ if_cfg_lookup(const struct bridge *br, const char *name)
 }
 
 static struct iface *
-iface_from_ofp_port(const struct bridge *br, uint16_t ofp_port)
+iface_from_ofp_port(const struct bridge *br, ofp_port_t ofp_port)
 {
     struct iface *iface;
 
-    HMAP_FOR_EACH_IN_BUCKET (iface, ofp_port_node,
-                             hash_int(ofp_port, 0), &br->ifaces) {
+    HMAP_FOR_EACH_IN_BUCKET (iface, ofp_port_node, hash_ofp_port(ofp_port),
+                             &br->ifaces) {
         if (iface->ofp_port == ofp_port) {
             return iface;
         }
@@ -3528,10 +3545,10 @@ iface_set_mac(struct iface *iface)
 
 /* Sets the ofport column of 'if_cfg' to 'ofport'. */
 static void
-iface_set_ofport(const struct ovsrec_interface *if_cfg, uint16_t ofport)
+iface_set_ofport(const struct ovsrec_interface *if_cfg, ofp_port_t ofport)
 {
     int64_t port_;
-    port_ = (ofport == OFPP_NONE) ? -1 : ofport;
+    port_ = (ofport == OFPP_NONE) ? -1 : ofp_to_u16(ofport);
     if (if_cfg && !ovsdb_idl_row_is_synthetic(&if_cfg->header_)) {
         ovsrec_interface_set_ofport(if_cfg, &port_, 1);
     }
@@ -3717,11 +3734,13 @@ iface_is_synthetic(const struct iface *iface)
     return ovsdb_idl_row_is_synthetic(&iface->cfg->header_);
 }
 
-static uint16_t
+static ofp_port_t
 iface_pick_ofport(const struct ovsrec_interface *cfg)
 {
-    uint16_t ofport = cfg->n_ofport ? *cfg->ofport : OFPP_NONE;
-    return cfg->n_ofport_request ? *cfg->ofport_request : ofport;
+    ofp_port_t ofport = cfg->n_ofport ? u16_to_ofp(*cfg->ofport)
+                                      : OFPP_NONE;
+    return cfg->n_ofport_request ? u16_to_ofp(*cfg->ofport_request)
+                                 : ofport;
 }
 
 \f
@@ -4099,7 +4118,7 @@ static void
 configure_splinter_port(struct port *port)
 {
     struct ofproto *ofproto = port->bridge->ofproto;
-    uint16_t realdev_ofp_port;
+    ofp_port_t realdev_ofp_port;
     const char *realdev_name;
     struct iface *vlandev, *realdev;