sha1: Avoid unused variable warnings on big-endian systems.
[openvswitch] / ofproto / ofproto.c
index f0fc4ec73e485200560e76e02de3949ff76fe8ea..4c370d3b795361456a3c5e61a3acc23386b9b51c 100644 (file)
@@ -64,7 +64,8 @@ COVERAGE_DEFINE(ofproto_update_port);
 static void ofport_destroy__(struct ofport *);
 static void ofport_destroy(struct ofport *);
 
-static int rule_create(struct ofproto *, const struct cls_rule *,
+static int rule_create(struct ofproto *,
+                       const struct cls_rule *, uint8_t table_id,
                        const union ofp_action *, size_t n_actions,
                        uint16_t idle_timeout, uint16_t hard_timeout,
                        ovs_be64 flow_cookie, bool send_flow_removed,
@@ -432,20 +433,19 @@ ofproto_port_clear_cfm(struct ofproto *ofproto, uint16_t ofp_port)
 {
     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
     if (ofport && ofproto->ofproto_class->set_cfm) {
-        ofproto->ofproto_class->set_cfm(ofport, NULL, NULL, 0);
+        ofproto->ofproto_class->set_cfm(ofport, NULL);
     }
 }
 
 /* Configures connectivity fault management on 'ofp_port' in 'ofproto'.  Takes
- * basic configuration from the configuration members in 'cfm', and the set of
- * remote maintenance points from the 'n_remote_mps' elements in 'remote_mps'.
- * Ignores the statistics members of 'cfm'.
+ * basic configuration from the configuration members in 'cfm', and the remote
+ * maintenance point ID from  remote_mpid.  Ignores the statistics members of
+ * 'cfm'.
  *
  * This function has no effect if 'ofproto' does not have a port 'ofp_port'. */
 void
 ofproto_port_set_cfm(struct ofproto *ofproto, uint16_t ofp_port,
-                     const struct cfm *cfm,
-                     const uint16_t *remote_mps, size_t n_remote_mps)
+                     const struct cfm_settings *s)
 {
     struct ofport *ofport;
     int error;
@@ -457,9 +457,11 @@ ofproto_port_set_cfm(struct ofproto *ofproto, uint16_t ofp_port,
         return;
     }
 
+    /* XXX: For configuration simplicity, we only support one remote_mpid
+     * outside of the CFM module.  It's not clear if this is the correct long
+     * term solution or not. */
     error = (ofproto->ofproto_class->set_cfm
-             ? ofproto->ofproto_class->set_cfm(ofport, cfm,
-                                               remote_mps, n_remote_mps)
+             ? ofproto->ofproto_class->set_cfm(ofport, s)
              : EOPNOTSUPP);
     if (error) {
         VLOG_WARN("%s: CFM configuration on port %"PRIu16" (%s) failed (%s)",
@@ -468,22 +470,6 @@ ofproto_port_set_cfm(struct ofproto *ofproto, uint16_t ofp_port,
     }
 }
 
-/* Returns the connectivity fault management object associated with 'ofp_port'
- * within 'ofproto', or a null pointer if 'ofproto' does not have a port
- * 'ofp_port' or if that port does not have CFM configured.  The caller must
- * not modify or destroy the returned object. */
-const struct cfm *
-ofproto_port_get_cfm(struct ofproto *ofproto, uint16_t ofp_port)
-{
-    struct ofport *ofport;
-    const struct cfm *cfm;
-
-    ofport = ofproto_get_port(ofproto, ofp_port);
-    return (ofport
-            && ofproto->ofproto_class->get_cfm
-            && !ofproto->ofproto_class->get_cfm(ofport, &cfm)) ? cfm : NULL;
-}
-
 /* 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
@@ -624,7 +610,6 @@ ofproto_destroy(struct ofproto *p)
 
     ofproto_flush_flows__(p);
     HMAP_FOR_EACH_SAFE (ofport, next_ofport, hmap_node, &p->ports) {
-        hmap_remove(&p->ports, &ofport->hmap_node);
         ofport_destroy(ofport);
     }
 
@@ -887,7 +872,7 @@ ofproto_add_flow(struct ofproto *p, const struct cls_rule *cls_rule,
                  const union ofp_action *actions, size_t n_actions)
 {
     struct rule *rule;
-    rule_create(p, cls_rule, actions, n_actions, 0, 0, 0, false, &rule);
+    rule_create(p, cls_rule, 0, actions, n_actions, 0, 0, 0, false, &rule);
 }
 
 /* Searches for a rule with matching criteria exactly equal to 'target' in
@@ -1107,7 +1092,7 @@ ofproto_port_unregister(struct ofproto *ofproto, uint16_t ofp_port)
     struct ofport *port = ofproto_get_port(ofproto, ofp_port);
     if (port) {
         if (port->ofproto->ofproto_class->set_cfm) {
-            port->ofproto->ofproto_class->set_cfm(port, NULL, NULL, 0);
+            port->ofproto->ofproto_class->set_cfm(port, NULL);
         }
         if (port->ofproto->ofproto_class->bundle_remove) {
             port->ofproto->ofproto_class->bundle_remove(port);
@@ -1170,21 +1155,25 @@ update_port(struct ofproto *ofproto, const char *name)
     if (netdev) {
         port = ofproto_get_port(ofproto, ofproto_port.ofp_port);
         if (port && !strcmp(netdev_get_name(port->netdev), name)) {
+            struct netdev *old_netdev = port->netdev;
+
             /* 'name' hasn't changed location.  Any properties changed? */
             if (!ofport_equal(&port->opp, &opp)) {
                 ofport_modified(port, &opp);
             }
 
-            /* Install the newly opened netdev in case it has changed. */
+            /* Install the newly opened netdev in case it has changed.
+             * Don't close the old netdev yet in case port_modified has to
+             * remove a retained reference to it.*/
             netdev_monitor_remove(ofproto->netdev_monitor, port->netdev);
             netdev_monitor_add(ofproto->netdev_monitor, netdev);
-
-            netdev_close(port->netdev);
             port->netdev = netdev;
 
             if (port->ofproto->ofproto_class->port_modified) {
                 port->ofproto->ofproto_class->port_modified(port);
             }
+
+            netdev_close(old_netdev);
         } else {
             /* If 'port' is nonnull then its name differs from 'name' and thus
              * we should delete it.  If we think there's a port named 'name'
@@ -1234,7 +1223,8 @@ init_ports(struct ofproto *p)
  * flow table, and stores the new rule into '*rulep'.  Returns 0 on success,
  * otherwise a positive errno value or OpenFlow error code. */
 static int
-rule_create(struct ofproto *ofproto, const struct cls_rule *cls_rule,
+rule_create(struct ofproto *ofproto,
+            const struct cls_rule *cls_rule, uint8_t table_id,
             const union ofp_action *actions, size_t n_actions,
             uint16_t idle_timeout, uint16_t hard_timeout,
             ovs_be64 flow_cookie, bool send_flow_removed,
@@ -1243,6 +1233,20 @@ rule_create(struct ofproto *ofproto, const struct cls_rule *cls_rule,
     struct rule *rule;
     int error;
 
+    if (table_id == 0xff) {
+        if (ofproto->n_tables > 1) {
+            error = ofproto->ofproto_class->rule_choose_table(ofproto,
+                                                              cls_rule,
+                                                              &table_id);
+            if (error) {
+                return error;
+            }
+            assert(table_id < ofproto->n_tables);
+        } else {
+            table_id = 0;
+        }
+    }
+
     rule = ofproto->ofproto_class->rule_alloc();
     if (!rule) {
         error = ENOMEM;
@@ -1251,6 +1255,7 @@ rule_create(struct ofproto *ofproto, const struct cls_rule *cls_rule,
 
     rule->ofproto = ofproto;
     rule->cr = *cls_rule;
+    rule->table_id = table_id;
     rule->flow_cookie = flow_cookie;
     rule->created = time_msec();
     rule->idle_timeout = idle_timeout;
@@ -1452,7 +1457,7 @@ handle_set_config(struct ofconn *ofconn, const struct ofp_switch_config *osc)
  *
  * The log message mentions 'msg_type'. */
 static int
-reject_slave_controller(struct ofconn *ofconn, const const char *msg_type)
+reject_slave_controller(struct ofconn *ofconn, const char *msg_type)
 {
     if (ofconn_get_type(ofconn) == OFCONN_PRIMARY
         && ofconn_get_role(ofconn) == NX_ROLE_SLAVE) {
@@ -1675,21 +1680,14 @@ handle_table_stats_request(struct ofconn *ofconn,
     ots = ofpbuf_put_zeros(msg, sizeof *ots * p->n_tables);
     for (i = 0; i < p->n_tables; i++) {
         ots[i].table_id = i;
-        sprintf(ots[i].name, "table%d", i);
-        ots[i].wildcards = htonl(OVSFW_ALL);
+        sprintf(ots[i].name, "table%zu", i);
+        ots[i].wildcards = htonl(OFPFW_ALL);
         ots[i].max_entries = htonl(1000000); /* An arbitrary big number. */
         ots[i].active_count = htonl(classifier_count(&p->tables[i]));
     }
 
     p->ofproto_class->get_tables(p, ots);
 
-    if (ofconn_get_flow_format(ofconn) == NXFF_OPENFLOW10) {
-        /* OpenFlow 1.0 only supports the OFPFW_* bits. */
-        for (i = 0; i < p->n_tables; i++) {
-            ots[i].wildcards &= htonl(OFPFW_ALL);
-        }
-    }
-
     ofconn_send_reply(ofconn, msg);
     return 0;
 }
@@ -1773,7 +1771,6 @@ put_ofp_flow_stats(struct ofconn *ofconn, struct rule *rule,
     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
     struct ofp_flow_stats *ofs;
     uint64_t packet_count, byte_count;
-    ovs_be64 cookie;
     size_t act_len, len;
 
     if (rule_is_hidden(rule) || !rule_has_out_port(rule, out_port)) {
@@ -1789,9 +1786,8 @@ put_ofp_flow_stats(struct ofconn *ofconn, struct rule *rule,
     ofs->length = htons(len);
     ofs->table_id = rule->table_id;
     ofs->pad = 0;
-    ofputil_cls_rule_to_match(&rule->cr, ofconn_get_flow_format(ofconn),
-                              &ofs->match, rule->flow_cookie, &cookie);
-    put_32aligned_be64(&ofs->cookie, cookie);
+    ofputil_cls_rule_to_match(&rule->cr, &ofs->match);
+    put_32aligned_be64(&ofs->cookie, rule->flow_cookie);
     calc_flow_duration(rule->created, &ofs->duration_sec, &ofs->duration_nsec);
     ofs->priority = htons(rule->cr.priority);
     ofs->idle_timeout = htons(rule->idle_timeout);
@@ -1860,7 +1856,7 @@ handle_flow_stats_request(struct ofconn *ofconn, const struct ofp_header *oh)
 
     COVERAGE_INC(ofproto_flows_req);
     reply = start_ofp_stats_reply(oh, 1024);
-    ofputil_cls_rule_from_match(&fsr->match, 0, NXFF_OPENFLOW10, 0, &target);
+    ofputil_cls_rule_from_match(&fsr->match, 0, &target);
     FOR_EACH_MATCHING_TABLE (cls, fsr->table_id, ofproto) {
         struct cls_cursor cursor;
         struct rule *rule;
@@ -2008,6 +2004,18 @@ ofproto_get_netflow_ids(const struct ofproto *ofproto,
     ofproto->ofproto_class->get_netflow_ids(ofproto, engine_type, engine_id);
 }
 
+/* Checks the fault status of CFM for 'ofp_port' within 'ofproto'.  Returns 1
+ * if CFM is faulted (generally indiciating a connectivity problem), 0 if CFM
+ * is not faulted, and -1 if CFM is not enabled on 'ofp_port'. */
+int
+ofproto_port_get_cfm_fault(const struct ofproto *ofproto, uint16_t ofp_port)
+{
+    struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
+    return (ofport && ofproto->ofproto_class->get_cfm_fault
+            ? ofproto->ofproto_class->get_cfm_fault(ofport)
+            : -1);
+}
+
 static void
 query_aggregate_stats(struct ofproto *ofproto, struct cls_rule *target,
                       ovs_be16 out_port, uint8_t table_id,
@@ -2056,8 +2064,7 @@ handle_aggregate_stats_request(struct ofconn *ofconn,
     struct cls_rule target;
     struct ofpbuf *msg;
 
-    ofputil_cls_rule_from_match(&request->match, 0, NXFF_OPENFLOW10, 0,
-                                &target);
+    ofputil_cls_rule_from_match(&request->match, 0, &target);
 
     msg = start_ofp_stats_reply(oh, sizeof *reply);
     reply = append_ofp_stats_reply(sizeof *reply, ofconn, &msg);
@@ -2219,7 +2226,7 @@ add_flow(struct ofconn *ofconn, struct flow_mod *fm)
     }
 
     buf_err = ofconn_pktbuf_retrieve(ofconn, fm->buffer_id, &packet, &in_port);
-    error = rule_create(p, &fm->cr, fm->actions, fm->n_actions,
+    error = rule_create(p, &fm->cr, fm->table_id, fm->actions, fm->n_actions,
                         fm->idle_timeout, fm->hard_timeout, fm->cookie,
                         fm->flags & OFPFF_SEND_FLOW_REM, &rule);
     if (error) {
@@ -2503,7 +2510,7 @@ handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh)
         return error;
     }
 
-    error = ofputil_decode_flow_mod(&fm, oh, ofconn_get_flow_format(ofconn),
+    error = ofputil_decode_flow_mod(&fm, oh,
                                     ofconn_get_flow_mod_table_id(ofconn));
     if (error) {
         return error;
@@ -2544,19 +2551,6 @@ handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh)
     }
 }
 
-static int
-handle_tun_id_from_cookie(struct ofconn *ofconn, const struct ofp_header *oh)
-{
-    const struct nxt_tun_id_cookie *msg
-        = (const struct nxt_tun_id_cookie *) oh;
-    enum nx_flow_format flow_format;
-
-    flow_format = msg->set ? NXFF_TUN_ID_FROM_COOKIE : NXFF_OPENFLOW10;
-    ofconn_set_flow_format(ofconn, flow_format);
-
-    return 0;
-}
-
 static int
 handle_role_request(struct ofconn *ofconn, const struct ofp_header *oh)
 {
@@ -2608,7 +2602,6 @@ handle_nxt_set_flow_format(struct ofconn *ofconn, const struct ofp_header *oh)
 
     format = ntohl(msg->format);
     if (format == NXFF_OPENFLOW10
-        || format == NXFF_TUN_ID_FROM_COOKIE
         || format == NXFF_NXM) {
         ofconn_set_flow_format(ofconn, format);
         return 0;
@@ -2673,9 +2666,6 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
         return 0;
 
         /* Nicira extension requests. */
-    case OFPUTIL_NXT_TUN_ID_FROM_COOKIE:
-        return handle_tun_id_from_cookie(ofconn, oh);
-
     case OFPUTIL_NXT_ROLE_REQUEST:
         return handle_role_request(ofconn, oh);