python: Fix exception handler compatibility.
[cascardo/ovs.git] / ofproto / ofproto.c
index 2cdc8d4..528d5ac 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2015 Nicira, Inc.
+ * Copyright (c) 2009-2016 Nicira, Inc.
  * Copyright (c) 2010 Jean Tourrilhes - HP-Labs.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -544,7 +544,7 @@ ofproto_create(const char *datapath_name, const char *datapath_type,
     ofproto->sw_desc = NULL;
     ofproto->serial_desc = NULL;
     ofproto->dp_desc = NULL;
-    ofproto->frag_handling = OFPC_FRAG_NORMAL;
+    ofproto->frag_handling = OFPUTIL_FRAG_NORMAL;
     hmap_init(&ofproto->ports);
     hmap_init(&ofproto->ofport_usage);
     shash_init(&ofproto->port_by_name);
@@ -2033,24 +2033,18 @@ flow_mod_init(struct ofputil_flow_mod *fm,
               const struct ofpact *ofpacts, size_t ofpacts_len,
               enum ofp_flow_mod_command command)
 {
-    memset(fm, 0, sizeof *fm);
-    fm->match = *match;
-    fm->priority = priority;
-    fm->cookie = 0;
-    fm->new_cookie = 0;
-    fm->modify_cookie = false;
-    fm->table_id = 0;
-    fm->command = command;
-    fm->idle_timeout = 0;
-    fm->hard_timeout = 0;
-    fm->importance = 0;
-    fm->buffer_id = UINT32_MAX;
-    fm->out_port = OFPP_ANY;
-    fm->out_group = OFPG_ANY;
-    fm->flags = 0;
-    fm->ofpacts = CONST_CAST(struct ofpact *, ofpacts);
-    fm->ofpacts_len = ofpacts_len;
-    fm->delete_reason = OFPRR_DELETE;
+    *fm = (struct ofputil_flow_mod) {
+        .match = *match,
+        .priority = priority,
+        .table_id = 0,
+        .command = command,
+        .buffer_id = UINT32_MAX,
+        .out_port = OFPP_ANY,
+        .out_group = OFPG_ANY,
+        .ofpacts = CONST_CAST(struct ofpact *, ofpacts),
+        .ofpacts_len = ofpacts_len,
+        .delete_reason = OFPRR_DELETE,
+    };
 }
 
 static int
@@ -3255,23 +3249,13 @@ handle_features_request(struct ofconn *ofconn, const struct ofp_header *oh)
 static enum ofperr
 handle_get_config_request(struct ofconn *ofconn, const struct ofp_header *oh)
 {
-    struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
-    struct ofp_switch_config *osc;
-    enum ofp_config_flags flags;
-    struct ofpbuf *buf;
+    struct ofputil_switch_config config;
+    config.frag = ofconn_get_ofproto(ofconn)->frag_handling;
+    config.invalid_ttl_to_controller
+        = ofconn_get_invalid_ttl_to_controller(ofconn);
+    config.miss_send_len = ofconn_get_miss_send_len(ofconn);
 
-    /* Send reply. */
-    buf = ofpraw_alloc_reply(OFPRAW_OFPT_GET_CONFIG_REPLY, oh, 0);
-    osc = ofpbuf_put_uninit(buf, sizeof *osc);
-    flags = ofproto->frag_handling;
-    /* 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);
-    osc->miss_send_len = htons(ofconn_get_miss_send_len(ofconn));
-    ofconn_send_reply(ofconn, buf);
+    ofconn_send_reply(ofconn, ofputil_encode_get_config_reply(oh, &config));
 
     return 0;
 }
@@ -3279,16 +3263,20 @@ handle_get_config_request(struct ofconn *ofconn, const struct ofp_header *oh)
 static enum ofperr
 handle_set_config(struct ofconn *ofconn, const struct ofp_header *oh)
 {
-    const struct ofp_switch_config *osc = ofpmsg_body(oh);
     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
-    uint16_t flags = ntohs(osc->flags);
+    struct ofputil_switch_config config;
+    enum ofperr error;
+
+    error = ofputil_decode_set_config(oh, &config);
+    if (error) {
+        return error;
+    }
 
     if (ofconn_get_type(ofconn) != OFCONN_PRIMARY
         || ofconn_get_role(ofconn) != OFPCR12_ROLE_SLAVE) {
-        enum ofp_config_flags cur = ofproto->frag_handling;
-        enum ofp_config_flags next = flags & OFPC_FRAG_MASK;
+        enum ofputil_frag_handling cur = ofproto->frag_handling;
+        enum ofputil_frag_handling next = config.frag;
 
-        ovs_assert((cur & OFPC_FRAG_MASK) == cur);
         if (cur != next) {
             if (ofproto->ofproto_class->set_frag_handling(ofproto, next)) {
                 ofproto->frag_handling = next;
@@ -3299,12 +3287,13 @@ 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,
-             (oh->version < OFP13_VERSION
-              && flags & OFPC_INVALID_TTL_TO_CONTROLLER));
 
-    ofconn_set_miss_send_len(ofconn, ntohs(osc->miss_send_len));
+    if (config.invalid_ttl_to_controller >= 0) {
+        ofconn_set_invalid_ttl_to_controller(ofconn,
+                                             config.invalid_ttl_to_controller);
+    }
+
+    ofconn_set_miss_send_len(ofconn, config.miss_send_len);
 
     return 0;
 }
@@ -3345,7 +3334,7 @@ ofproto_check_ofpacts(struct ofproto *ofproto,
         return OFPERR_OFPMMFC_INVALID_METER;
     }
 
-    OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
+    OFPACT_FOR_EACH_FLATTENED (a, ofpacts, ofpacts_len) {
         if (a->type == OFPACT_GROUP
             && !ofproto_group_exists(ofproto, ofpact_get_GROUP(a)->group_id)) {
             return OFPERR_OFPBAC_BAD_OUT_GROUP;
@@ -3588,6 +3577,26 @@ handle_table_features_request(struct ofconn *ofconn,
     return 0;
 }
 
+static void
+query_table_desc__(struct ofputil_table_desc *td,
+                   struct ofproto *ofproto, uint8_t table_id)
+{
+    unsigned int count = ofproto->tables[table_id].n_flows;
+    unsigned int max_flows = ofproto->tables[table_id].max_flows;
+
+    td->table_id = table_id;
+    td->eviction = (ofproto->tables[table_id].eviction & EVICTION_OPENFLOW
+                    ? OFPUTIL_TABLE_EVICTION_ON
+                    : OFPUTIL_TABLE_EVICTION_OFF);
+    td->eviction_flags = OFPROTO_EVICTION_FLAGS;
+    td->vacancy = (ofproto->tables[table_id].vacancy_enabled
+                   ? OFPUTIL_TABLE_VACANCY_ON
+                   : OFPUTIL_TABLE_VACANCY_OFF);
+    td->table_vacancy.vacancy_down = ofproto->tables[table_id].vacancy_down;
+    td->table_vacancy.vacancy_up = ofproto->tables[table_id].vacancy_up;
+    td->table_vacancy.vacancy = max_flows ? (count * 100) / max_flows : 0;
+}
+
 /* This function queries the database for dumping table-desc. */
 static void
 query_tables_desc(struct ofproto *ofproto, struct ofputil_table_desc **descp)
@@ -3598,11 +3607,7 @@ query_tables_desc(struct ofproto *ofproto, struct ofputil_table_desc **descp)
     table_desc = *descp = xcalloc(ofproto->n_tables, sizeof *table_desc);
     for (i = 0; i < ofproto->n_tables; i++) {
         struct ofputil_table_desc *td = &table_desc[i];
-        td->table_id = i;
-        td->eviction = (ofproto->tables[i].eviction & EVICTION_OPENFLOW
-                        ? OFPUTIL_TABLE_EVICTION_ON
-                        : OFPUTIL_TABLE_EVICTION_OFF);
-        td->eviction_flags = OFPROTO_EVICTION_FLAGS;
+        query_table_desc__(td, ofproto, i);
     }
 }
 
@@ -4929,7 +4934,7 @@ modify_flows_start_loose(struct ofproto *ofproto, struct ofproto_flow_mod *ofm)
     enum ofperr error;
 
     rule_criteria_init(&criteria, fm->table_id, &fm->match, 0, CLS_MAX_VERSION,
-                       fm->cookie, fm->cookie_mask, OFPP_ANY, OFPG11_ANY);
+                       fm->cookie, fm->cookie_mask, OFPP_ANY, OFPG_ANY);
     rule_criteria_require_rw(&criteria,
                              (fm->flags & OFPUTIL_FF_NO_READONLY) != 0);
     error = collect_rules_loose(ofproto, &criteria, old_rules);
@@ -5006,7 +5011,7 @@ modify_flow_start_strict(struct ofproto *ofproto, struct ofproto_flow_mod *ofm)
 
     rule_criteria_init(&criteria, fm->table_id, &fm->match, fm->priority,
                        CLS_MAX_VERSION, fm->cookie, fm->cookie_mask, OFPP_ANY,
-                       OFPG11_ANY);
+                       OFPG_ANY);
     rule_criteria_require_rw(&criteria,
                              (fm->flags & OFPUTIL_FF_NO_READONLY) != 0);
     error = collect_rules_strict(ofproto, &criteria, old_rules);
@@ -5397,10 +5402,14 @@ handle_nxt_set_packet_in_format(struct ofconn *ofconn,
 static enum ofperr
 handle_nxt_set_async_config(struct ofconn *ofconn, const struct ofp_header *oh)
 {
+    enum ofperr error;
     uint32_t master[OAM_N_TYPES] = {0};
     uint32_t slave[OAM_N_TYPES] = {0};
 
-    ofputil_decode_set_async_config(oh, master, slave, false);
+    error = ofputil_decode_set_async_config(oh, master, slave, false);
+    if (error) {
+        return error;
+    }
 
     ofconn_set_async_config(ofconn, master, slave);
     if (ofconn_get_type(ofconn) == OFCONN_SERVICE &&
@@ -6216,30 +6225,12 @@ handle_group_features_stats_request(struct ofconn *ofconn,
     return 0;
 }
 
-static enum ofperr
-handle_queue_get_config_request(struct ofconn *ofconn,
-                                const struct ofp_header *oh)
+static void
+put_queue_config(struct ofport *ofport, struct ofpbuf *reply)
 {
-   struct ofproto *p = ofconn_get_ofproto(ofconn);
    struct netdev_queue_dump queue_dump;
-   struct ofport *ofport;
    unsigned int queue_id;
-   struct ofpbuf *reply;
    struct smap details;
-   ofp_port_t request;
-   enum ofperr error;
-
-   error = ofputil_decode_queue_get_config_request(oh, &request);
-   if (error) {
-       return error;
-   }
-
-   ofport = ofproto_get_port(p, request);
-   if (!ofport) {
-      return OFPERR_OFPQOFC_BAD_PORT;
-   }
-
-   reply = ofputil_encode_queue_get_config_reply(oh);
 
    smap_init(&details);
    NETDEV_QUEUE_FOR_EACH (&queue_id, &details, &queue_dump, ofport->netdev) {
@@ -6247,13 +6238,42 @@ handle_queue_get_config_request(struct ofconn *ofconn,
 
        /* None of the existing queues have compatible properties, so we
         * hard-code omitting min_rate and max_rate. */
+       queue.port = ofport->ofp_port;
        queue.queue_id = queue_id;
        queue.min_rate = UINT16_MAX;
        queue.max_rate = UINT16_MAX;
        ofputil_append_queue_get_config_reply(reply, &queue);
    }
    smap_destroy(&details);
+}
+
+static enum ofperr
+handle_queue_get_config_request(struct ofconn *ofconn,
+                                const struct ofp_header *oh)
+{
+   struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
+   ofp_port_t port;
+   enum ofperr error;
 
+   error = ofputil_decode_queue_get_config_request(oh, &port);
+   if (error) {
+       return error;
+   }
+
+   struct ofpbuf *reply = ofputil_encode_queue_get_config_reply(oh);
+   struct ofport *ofport;
+   if (port == OFPP_ANY) {
+       HMAP_FOR_EACH (ofport, hmap_node, &ofproto->ports) {
+           put_queue_config(ofport, reply);
+       }
+   } else {
+       ofport = ofproto_get_port(ofproto, port);
+       if (!ofport) {
+           ofpbuf_delete(reply);
+           return OFPERR_OFPQOFC_BAD_PORT;
+       }
+       put_queue_config(ofport, reply);
+   }
    ofconn_send_reply(ofconn, reply);
 
    return 0;
@@ -6380,22 +6400,24 @@ copy_buckets_for_insert_bucket(const struct ofgroup *ofgroup,
 
     ofputil_bucket_clone_list(&new_ofgroup->buckets, &ofgroup->buckets, NULL);
 
-    if (ofputil_bucket_check_duplicate_id(&ofgroup->buckets)) {
+    if (ofputil_bucket_check_duplicate_id(&new_ofgroup->buckets)) {
             VLOG_INFO_RL(&rl, "Duplicate bucket id");
             return OFPERR_OFPGMFC_BUCKET_EXISTS;
     }
 
     /* Rearrange list according to command_bucket_id */
     if (command_bucket_id == OFPG15_BUCKET_LAST) {
-        struct ofputil_bucket *new_first;
-        const struct ofputil_bucket *first;
+        if (!list_is_empty(&ofgroup->buckets)) {
+            struct ofputil_bucket *new_first;
+            const struct ofputil_bucket *first;
 
-        first = ofputil_bucket_list_front(&ofgroup->buckets);
-        new_first = ofputil_bucket_find(&new_ofgroup->buckets,
-                                        first->bucket_id);
+            first = ofputil_bucket_list_front(&ofgroup->buckets);
+            new_first = ofputil_bucket_find(&new_ofgroup->buckets,
+                                            first->bucket_id);
 
-        list_splice(new_ofgroup->buckets.next, &new_first->list_node,
-                    &new_ofgroup->buckets);
+            list_splice(new_ofgroup->buckets.next, &new_first->list_node,
+                        &new_ofgroup->buckets);
+        }
     } else if (command_bucket_id <= OFPG15_BUCKET_MAX && last) {
         struct ofputil_bucket *after;
 
@@ -6526,6 +6548,7 @@ delete_group__(struct ofproto *ofproto, struct ofgroup *ofgroup)
     flow_mod_init(&ofm.fm, &match, 0, NULL, 0, OFPFC_DELETE);
     ofm.fm.delete_reason = OFPRR_GROUP_DELETE;
     ofm.fm.out_group = ofgroup->group_id;
+    ofm.fm.table_id = OFPTT_ALL;
     handle_flow_mod__(ofproto, &ofm, NULL);
 
     hmap_remove(&ofproto->groups, &ofgroup->hmap_node);
@@ -6644,20 +6667,20 @@ ofproto_table_get_miss_config(const struct ofproto *ofproto, uint8_t table_id)
 
 static void
 table_mod__(struct oftable *oftable,
-            enum ofputil_table_miss miss, enum ofputil_table_eviction eviction)
+            const struct ofputil_table_mod *tm)
 {
-    if (miss == OFPUTIL_TABLE_MISS_DEFAULT) {
+    if (tm->miss == OFPUTIL_TABLE_MISS_DEFAULT) {
         /* This is how an OFPT_TABLE_MOD decodes if it doesn't specify any
          * table-miss configuration (because the protocol used doesn't have
          * such a concept), so there's nothing to do. */
     } else {
-        atomic_store_relaxed(&oftable->miss_config, miss);
+        atomic_store_relaxed(&oftable->miss_config, tm->miss);
     }
 
     unsigned int new_eviction = oftable->eviction;
-    if (eviction == OFPUTIL_TABLE_EVICTION_ON) {
+    if (tm->eviction == OFPUTIL_TABLE_EVICTION_ON) {
         new_eviction |= EVICTION_OPENFLOW;
-    } else if (eviction == OFPUTIL_TABLE_EVICTION_OFF) {
+    } else if (tm->eviction == OFPUTIL_TABLE_EVICTION_OFF) {
         new_eviction &= ~EVICTION_OPENFLOW;
     }
 
@@ -6668,6 +6691,16 @@ table_mod__(struct oftable *oftable,
                                    oftable->n_eviction_fields);
         ovs_mutex_unlock(&ofproto_mutex);
     }
+
+    if (tm->vacancy != OFPUTIL_TABLE_VACANCY_DEFAULT) {
+        ovs_mutex_lock(&ofproto_mutex);
+        oftable->vacancy_enabled = (tm->vacancy == OFPUTIL_TABLE_VACANCY_ON
+                                    ? OFPTC14_VACANCY_EVENTS
+                                    : 0);
+        oftable->vacancy_down = tm->table_vacancy.vacancy_down;
+        oftable->vacancy_up = tm->table_vacancy.vacancy_up;
+        ovs_mutex_unlock(&ofproto_mutex);
+    }
 }
 
 static enum ofperr
@@ -6691,7 +6724,7 @@ table_mod(struct ofproto *ofproto, const struct ofputil_table_mod *tm)
         struct oftable *oftable;
         OFPROTO_FOR_EACH_TABLE (oftable, ofproto) {
             if (!(oftable->flags & (OFTABLE_HIDDEN | OFTABLE_READONLY))) {
-                table_mod__(oftable, tm->miss, tm->eviction);
+                table_mod__(oftable, tm);
             }
         }
     } else {
@@ -6699,7 +6732,7 @@ table_mod(struct ofproto *ofproto, const struct ofputil_table_mod *tm)
         if (oftable->flags & OFTABLE_READONLY) {
             return OFPERR_OFPTMFC_EPERM;
         }
-        table_mod__(oftable, tm->miss, tm->eviction);
+        table_mod__(oftable, tm);
     }
 
     return 0;
@@ -7030,9 +7063,9 @@ handle_bundle_add(struct ofconn *ofconn, const struct ofp_header *oh)
 }
 
 static enum ofperr
-handle_geneve_table_mod(struct ofconn *ofconn, const struct ofp_header *oh)
+handle_tlv_table_mod(struct ofconn *ofconn, const struct ofp_header *oh)
 {
-    struct ofputil_geneve_table_mod gtm;
+    struct ofputil_tlv_table_mod ttm;
     enum ofperr error;
 
     error = reject_slave_controller(ofconn);
@@ -7040,26 +7073,26 @@ handle_geneve_table_mod(struct ofconn *ofconn, const struct ofp_header *oh)
         return error;
     }
 
-    error = ofputil_decode_geneve_table_mod(oh, &gtm);
+    error = ofputil_decode_tlv_table_mod(oh, &ttm);
     if (error) {
         return error;
     }
 
-    error = tun_metadata_table_mod(&gtm);
+    error = tun_metadata_table_mod(&ttm);
 
-    ofputil_uninit_geneve_table(&gtm.mappings);
+    ofputil_uninit_tlv_table(&ttm.mappings);
     return error;
 }
 
 static enum ofperr
-handle_geneve_table_request(struct ofconn *ofconn, const struct ofp_header *oh)
+handle_tlv_table_request(struct ofconn *ofconn, const struct ofp_header *oh)
 {
-    struct ofputil_geneve_table_reply gtr;
+    struct ofputil_tlv_table_reply ttr;
     struct ofpbuf *b;
 
-    tun_metadata_table_request(&gtr);
-    b = ofputil_encode_geneve_table_reply(oh, &gtr);
-    ofputil_uninit_geneve_table(&gtr.mappings);
+    tun_metadata_table_request(&ttr);
+    b = ofputil_encode_tlv_table_reply(oh, &ttr);
+    ofputil_uninit_tlv_table(&ttr.mappings);
 
     ofconn_send_reply(ofconn, b);
     return 0;
@@ -7209,11 +7242,11 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
     case OFPTYPE_BUNDLE_ADD_MESSAGE:
         return handle_bundle_add(ofconn, oh);
 
-    case OFPTYPE_NXT_GENEVE_TABLE_MOD:
-        return handle_geneve_table_mod(ofconn, oh);
+    case OFPTYPE_NXT_TLV_TABLE_MOD:
+        return handle_tlv_table_mod(ofconn, oh);
 
-    case OFPTYPE_NXT_GENEVE_TABLE_REQUEST:
-        return handle_geneve_table_request(ofconn, oh);
+    case OFPTYPE_NXT_TLV_TABLE_REQUEST:
+        return handle_tlv_table_request(ofconn, oh);
 
     case OFPTYPE_HELLO:
     case OFPTYPE_ERROR:
@@ -7246,7 +7279,7 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
     case OFPTYPE_TABLE_DESC_REPLY:
     case OFPTYPE_ROLE_STATUS:
     case OFPTYPE_REQUESTFORWARD:
-    case OFPTYPE_NXT_GENEVE_TABLE_REPLY:
+    case OFPTYPE_NXT_TLV_TABLE_REPLY:
     default:
         if (ofpmsg_is_stat_request(oh)) {
             return OFPERR_OFPBRC_BAD_STAT;