ofproto: Use active time for Flow Expiration duration (OpenFlow 0.9)
[sliver-openvswitch.git] / ofproto / ofproto.c
index baa5a8b..f25813f 100644 (file)
@@ -2577,7 +2577,7 @@ handle_flow_stats_request(struct ofproto *p, struct ofconn *ofconn,
     struct cls_rule target;
 
     if (arg_size != sizeof *fsr) {
-        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
     }
     fsr = (struct ofp_flow_stats_request *) osr->body;
 
@@ -2685,7 +2685,7 @@ handle_aggregate_stats_request(struct ofproto *p, struct ofconn *ofconn,
     struct ofpbuf *msg;
 
     if (arg_size != sizeof *asr) {
-        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
     }
     asr = (struct ofp_aggregate_stats_request *) osr->body;
 
@@ -2790,6 +2790,17 @@ add_flow(struct ofproto *p, struct ofconn *ofconn,
     uint16_t in_port;
     int error;
 
+    if (ofm->flags & htons(OFPFF_CHECK_OVERLAP)) {
+        flow_t flow;
+        uint32_t wildcards;
+
+        flow_from_match(&flow, &wildcards, &ofm->match);
+        if (classifier_rule_overlaps(&p->cls, &flow, wildcards,
+                                     ntohs(ofm->priority))) {
+            return ofp_mkerr(OFPET_FLOW_MOD_FAILED, OFPFMFC_OVERLAP);
+        }
+    }
+
     rule = rule_create(p, NULL, (const union ofp_action *) ofm->actions,
                        n_actions, ntohs(ofm->idle_timeout),
                        ntohs(ofm->hard_timeout));
@@ -2923,6 +2934,14 @@ handle_flow_mod(struct ofproto *p, struct ofconn *ofconn,
         return error;
     }
 
+    /* We do not support the emergency flow cache.  It will hopefully
+     * get dropped from OpenFlow in the near future. */
+    if (ofm->flags & htons(OFPFF_EMERG)) {
+        /* There isn't a good fit for an error code, so just state that the
+         * flow table is full. */
+        return ofp_mkerr(OFPET_FLOW_MOD_FAILED, OFPFMFC_ALL_TABLES_FULL);
+    }
+
     normalize_match(&ofm->match);
     if (!ofm->match.wildcards) {
         ofm->priority = htons(UINT16_MAX);
@@ -2982,7 +3001,7 @@ handle_ofmp(struct ofproto *p, struct ofconn *ofconn,
     size_t msg_len = ntohs(ofmph->header.header.length);
     if (msg_len < sizeof(*ofmph)) {
         VLOG_WARN_RL(&rl, "dropping short managment message: %zu\n", msg_len);
-        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
     }
 
     if (ofmph->type == htons(OFMPT_CAPABILITY_REQUEST)) {
@@ -2991,7 +3010,7 @@ handle_ofmp(struct ofproto *p, struct ofconn *ofconn,
         if (msg_len < sizeof(struct ofmp_capability_request)) {
             VLOG_WARN_RL(&rl, "dropping short capability request: %zu\n",
                     msg_len);
-            return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+            return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
         }
 
         ofmpcr = (struct ofmp_capability_request *)ofmph;
@@ -3014,13 +3033,13 @@ handle_vendor(struct ofproto *p, struct ofconn *ofconn, void *msg)
     struct nicira_header *nh;
 
     if (ntohs(ovh->header.length) < sizeof(struct ofp_vendor_header)) {
-        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
     }
     if (ovh->vendor != htonl(NX_VENDOR_ID)) {
         return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_VENDOR);
     }
     if (ntohs(ovh->header.length) < sizeof(struct nicira_header)) {
-        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
     }
 
     nh = msg;
@@ -3245,12 +3264,13 @@ compose_flow_exp(const struct rule *rule, long long int now, uint8_t reason)
 {
     struct ofp_flow_expired *ofe;
     struct ofpbuf *buf;
+    long long int last_used = rule->used ? now - rule->used : 0;
 
     ofe = make_openflow(sizeof *ofe, OFPT_FLOW_EXPIRED, &buf);
     flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, &ofe->match);
     ofe->priority = htons(rule->cr.priority);
     ofe->reason = reason;
-    ofe->duration = htonl((now - rule->created) / 1000);
+    ofe->duration = htonl((now - rule->created - last_used) / 1000);
     ofe->packet_count = htonll(rule->packet_count);
     ofe->byte_count = htonll(rule->byte_count);