Initial OpenFlow 1.3 support
[openvswitch] / ofproto / ofproto.c
index 182da63363e3fc952783d535f581ab9d2993ce78..bc3eb54123603f9878cfdd7696fc424f7112ed46 100644 (file)
@@ -1666,7 +1666,8 @@ alloc_ofp_port(struct ofproto *ofproto, const char *netdev_name)
          * flows. */
         while (ofp_port >= ofproto->max_ports) {
             for (ofproto->alloc_port_no++;
-                 ofproto->alloc_port_no < ofproto->max_ports; ) {
+                 ofproto->alloc_port_no < ofproto->max_ports;
+                 ofproto->alloc_port_no++) {
                 if (!bitmap_is_set(ofproto->ofp_port_ids,
                                    ofproto->alloc_port_no)) {
                     ofp_port = ofproto->alloc_port_no;
@@ -2128,7 +2129,7 @@ ofproto_rule_destroy(struct rule *rule)
 bool
 ofproto_rule_has_out_port(const struct rule *rule, uint16_t port)
 {
-    return (port == OFPP_NONE
+    return (port == OFPP_ANY
             || ofpacts_output_to_port(rule->ofpacts, rule->ofpacts_len, port));
 }
 
@@ -2170,7 +2171,7 @@ rule_execute(struct rule *rule, uint16_t in_port, struct ofpbuf *packet)
 
     assert(ofpbuf_headroom(packet) >= sizeof(struct ofp_packet_in));
 
-    flow_extract(packet, 0, NULL, in_port, &flow);
+    flow_extract(packet, 0, 0, NULL, in_port, &flow);
     return rule->ofproto->ofproto_class->rule_execute(rule, &flow, packet);
 }
 
@@ -2237,7 +2238,8 @@ handle_features_request(struct ofconn *ofconn, const struct ofp_header *oh)
     if (arp_match_ip) {
         features.capabilities |= OFPUTIL_C_ARP_MATCH_IP;
     }
-
+    /* FIXME: Fill in proper features.auxiliary_id for auxiliary connections */
+    features.auxiliary_id = 0;
     b = ofputil_encode_switch_features(&features, ofconn_get_protocol(ofconn),
                                        oh->xid);
     HMAP_FOR_EACH (port, hmap_node, &ofproto->ports) {
@@ -2260,7 +2262,9 @@ handle_get_config_request(struct ofconn *ofconn, const struct ofp_header *oh)
     buf = ofpraw_alloc_reply(OFPRAW_OFPT_GET_CONFIG_REPLY, oh, 0);
     osc = ofpbuf_put_uninit(buf, sizeof *osc);
     flags = ofproto->frag_handling;
-    if (ofconn_get_invalid_ttl_to_controller(ofconn)) {
+    /* OFPC_INVALID_TTL_TO_CONTROLLER is deprecated in OF 1.3 */
+    if (oh->version < OFP13_VERSION
+        && ofconn_get_invalid_ttl_to_controller(ofconn)) {
         flags |= OFPC_INVALID_TTL_TO_CONTROLLER;
     }
     osc->flags = htons(flags);
@@ -2293,8 +2297,10 @@ handle_set_config(struct ofconn *ofconn, const struct ofp_header *oh)
             }
         }
     }
+    /* OFPC_INVALID_TTL_TO_CONTROLLER is deprecated in OF 1.3 */
     ofconn_set_invalid_ttl_to_controller(ofconn,
-             (flags & OFPC_INVALID_TTL_TO_CONTROLLER));
+             (oh->version < OFP13_VERSION
+              && flags & OFPC_INVALID_TTL_TO_CONTROLLER));
 
     ofconn_set_miss_send_len(ofconn, ntohs(osc->miss_send_len));
 
@@ -2359,7 +2365,7 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh)
     }
 
     /* Verify actions against packet, then send packet if successful. */
-    flow_extract(payload, 0, NULL, po.in_port, &flow);
+    flow_extract(payload, 0, 0, NULL, po.in_port, &flow);
     error = ofpacts_check(po.ofpacts, po.ofpacts_len, &flow, p->max_ports);
     if (!error) {
         error = p->ofproto_class->packet_out(p, payload, &flow,
@@ -2541,7 +2547,7 @@ handle_port_stats_request(struct ofconn *ofconn,
     }
 
     ofpmp_init(&replies, request);
-    if (port_no != OFPP_NONE) {
+    if (port_no != OFPP_ANY) {
         port = ofproto_get_port(p, port_no);
         if (port) {
             append_port_stat(port, &replies);
@@ -2658,7 +2664,7 @@ next_matching_table(const struct ofproto *ofproto,
  * OpenFlow OFPFC_MODIFY and OFPFC_DELETE requests and puts them on list
  * 'rules'.
  *
- * If 'out_port' is anything other than OFPP_NONE, then only rules that output
+ * If 'out_port' is anything other than OFPP_ANY, then only rules that output
  * to 'out_port' are included.
  *
  * Hidden rules are always omitted.
@@ -2709,7 +2715,7 @@ exit:
  * OpenFlow OFPFC_MODIFY_STRICT and OFPFC_DELETE_STRICT requests and puts them
  * on list 'rules'.
  *
- * If 'out_port' is anything other than OFPP_NONE, then only rules that output
+ * If 'out_port' is anything other than OFPP_ANY, then only rules that output
  * to 'out_port' are included.
  *
  * Hidden rules are always omitted.
@@ -2807,6 +2813,12 @@ handle_flow_stats_request(struct ofconn *ofconn,
                                                &fs.byte_count);
         fs.ofpacts = rule->ofpacts;
         fs.ofpacts_len = rule->ofpacts_len;
+        fs.flags = 0;
+        if (rule->send_flow_removed) {
+            fs.flags |= OFPFF_SEND_FLOW_REM;
+            /* FIXME: Implement OF 1.3 flags OFPFF13_NO_PKT_COUNTS
+               and OFPFF13_NO_BYT_COUNTS */
+        }
         ofputil_append_flow_stats_reply(&fs, &replies);
     }
     ofconn_send_replies(ofconn, &replies);
@@ -3053,7 +3065,7 @@ handle_queue_stats_request(struct ofconn *ofconn,
         return error;
     }
 
-    if (oqsr.port_no == OFPP_ALL) {
+    if (oqsr.port_no == OFPP_ANY) {
         error = OFPERR_OFPQOFC_BAD_QUEUE;
         HMAP_FOR_EACH (port, hmap_node, &ofproto->ports) {
             if (!handle_queue_stats_for_port(port, oqsr.queue_id, &cbdata)) {
@@ -3173,6 +3185,8 @@ add_flow(struct ofproto *ofproto, struct ofconn *ofconn,
         return OFPERR_OFPFMFC_OVERLAP;
     }
 
+    /* FIXME: Implement OFPFF12_RESET_COUNTS */
+
     rule->ofproto = ofproto;
     rule->pending = NULL;
     rule->flow_cookie = fm->new_cookie;
@@ -3181,6 +3195,8 @@ add_flow(struct ofproto *ofproto, struct ofconn *ofconn,
     rule->hard_timeout = fm->hard_timeout;
     rule->table_id = table - ofproto->tables;
     rule->send_flow_removed = (fm->flags & OFPFF_SEND_FLOW_REM) != 0;
+    /* FIXME: Implement OF 1.3 flags OFPFF13_NO_PKT_COUNTS
+       and OFPFF13_NO_BYT_COUNTS */
     rule->ofpacts = xmemdup(fm->ofpacts, fm->ofpacts_len);
     rule->ofpacts_len = fm->ofpacts_len;
     rule->evictable = true;
@@ -3266,6 +3282,8 @@ modify_flows__(struct ofproto *ofproto, struct ofconn *ofconn,
         bool actions_changed;
         ovs_be64 new_cookie;
 
+        /* FIXME: Implement OFPFF12_RESET_COUNTS */
+
         if (rule_is_modifiable(rule)) {
             /* At least one rule is modifiable, don't report EPERM error. */
             error = 0;
@@ -3326,7 +3344,7 @@ modify_flows_loose(struct ofproto *ofproto, struct ofconn *ofconn,
 
     error = collect_rules_loose(ofproto, fm->table_id, &fm->match,
                                 fm->cookie, fm->cookie_mask,
-                                OFPP_NONE, &rules);
+                                OFPP_ANY, &rules);
     if (error) {
         return error;
     } else if (list_is_empty(&rules)) {
@@ -3351,7 +3369,7 @@ modify_flow_strict(struct ofproto *ofproto, struct ofconn *ofconn,
 
     error = collect_rules_strict(ofproto, fm->table_id, &fm->match,
                                  fm->priority, fm->cookie, fm->cookie_mask,
-                                 OFPP_NONE, &rules);
+                                 OFPP_ANY, &rules);
 
     if (error) {
         return error;
@@ -3515,17 +3533,6 @@ handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh)
     ofpbuf_use_stub(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
     error = ofputil_decode_flow_mod(&fm, oh, ofconn_get_protocol(ofconn),
                                     &ofpacts);
-    if (error) {
-        goto exit_free_ofpacts;
-    }
-
-    if (fm.flags & OFPFF10_EMERG) {
-        /* We do not support the OpenFlow 1.0 emergency flow cache, which
-         * 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_TABLE_FULL;
-    }
     if (!error) {
         error = ofpacts_check(fm.ofpacts, fm.ofpacts_len,
                               &fm.match.flow, ofproto->max_ports);
@@ -3536,7 +3543,7 @@ handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh)
     if (error) {
         goto exit_free_ofpacts;
     }
-
+    
     /* Record the operation for logging a summary report. */
     switch (fm.command) {
     case OFPFC_ADD:
@@ -4094,6 +4101,18 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
     case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
         return handle_flow_monitor_request(ofconn, oh);
 
+        /* FIXME: Change the following once they are implemented: */
+    case OFPTYPE_GET_ASYNC_REQUEST:
+    case OFPTYPE_METER_MOD:
+    case OFPTYPE_GROUP_REQUEST:
+    case OFPTYPE_GROUP_DESC_REQUEST:
+    case OFPTYPE_GROUP_FEATURES_REQUEST:
+    case OFPTYPE_METER_REQUEST:
+    case OFPTYPE_METER_CONFIG_REQUEST:
+    case OFPTYPE_METER_FEATURES_REQUEST:
+    case OFPTYPE_TABLE_FEATURES_REQUEST:
+        return OFPERR_OFPBRC_BAD_TYPE;
+
     case OFPTYPE_HELLO:
     case OFPTYPE_ERROR:
     case OFPTYPE_FEATURES_REPLY:
@@ -4113,6 +4132,14 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
     case OFPTYPE_FLOW_MONITOR_PAUSED:
     case OFPTYPE_FLOW_MONITOR_RESUMED:
     case OFPTYPE_FLOW_MONITOR_STATS_REPLY:
+    case OFPTYPE_GET_ASYNC_REPLY:
+    case OFPTYPE_GROUP_REPLY:
+    case OFPTYPE_GROUP_DESC_REPLY:
+    case OFPTYPE_GROUP_FEATURES_REPLY:
+    case OFPTYPE_METER_REPLY:
+    case OFPTYPE_METER_CONFIG_REPLY:
+    case OFPTYPE_METER_FEATURES_REPLY:
+    case OFPTYPE_TABLE_FEATURES_REPLY:
     default:
         return OFPERR_OFPBRC_BAD_TYPE;
     }