classifier: Add a batched miniflow lookup function.
[cascardo/ovs.git] / lib / learn.c
index 49d9efd..c5797eb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, 2013 Nicira, Inc.
+ * Copyright (c) 2011, 2012, 2013, 2014 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -96,13 +96,18 @@ learn_from_openflow(const struct nx_action_learn *nal, struct ofpbuf *ofpacts)
     learn->idle_timeout = ntohs(nal->idle_timeout);
     learn->hard_timeout = ntohs(nal->hard_timeout);
     learn->priority = ntohs(nal->priority);
-    learn->cookie = ntohll(nal->cookie);
-    learn->flags = ntohs(nal->flags);
+    learn->cookie = nal->cookie;
     learn->table_id = nal->table_id;
     learn->fin_idle_timeout = ntohs(nal->fin_idle_timeout);
     learn->fin_hard_timeout = ntohs(nal->fin_hard_timeout);
 
-    if (learn->flags & ~OFPFF_SEND_FLOW_REM || learn->table_id == 0xff) {
+    learn->flags = ntohs(nal->flags);
+    if (learn->flags & ~(NX_LEARN_F_SEND_FLOW_REM |
+                         NX_LEARN_F_DELETE_LEARNED)) {
+        return OFPERR_OFPBAC_BAD_ARGUMENT;
+    }
+
+    if (learn->table_id == 0xff) {
         return OFPERR_OFPBAC_BAD_ARGUMENT;
     }
 
@@ -116,7 +121,7 @@ learn_from_openflow(const struct nx_action_learn *nal, struct ofpbuf *ofpacts)
         }
 
         spec = ofpbuf_put_zeros(ofpacts, sizeof *spec);
-        learn = ofpacts->l2;
+        learn = ofpacts->frame;
         learn->n_specs++;
 
         spec->src_type = header & NX_LEARN_SRC_MASK;
@@ -244,14 +249,14 @@ learn_to_nxast(const struct ofpact_learn *learn, struct ofpbuf *openflow)
     struct nx_action_learn *nal;
     size_t start_ofs;
 
-    start_ofs = openflow->size;
+    start_ofs = ofpbuf_size(openflow);
     nal = ofputil_put_NXAST_LEARN(openflow);
     nal->idle_timeout = htons(learn->idle_timeout);
     nal->hard_timeout = htons(learn->hard_timeout);
     nal->fin_idle_timeout = htons(learn->fin_idle_timeout);
     nal->fin_hard_timeout = htons(learn->fin_hard_timeout);
     nal->priority = htons(learn->priority);
-    nal->cookie = htonll(learn->cookie);
+    nal->cookie = learn->cookie;
     nal->flags = htons(learn->flags);
     nal->table_id = learn->table_id;
 
@@ -276,12 +281,12 @@ learn_to_nxast(const struct ofpact_learn *learn, struct ofpbuf *openflow)
         }
     }
 
-    if ((openflow->size - start_ofs) % 8) {
-        ofpbuf_put_zeros(openflow, 8 - (openflow->size - start_ofs) % 8);
+    if ((ofpbuf_size(openflow) - start_ofs) % 8) {
+        ofpbuf_put_zeros(openflow, 8 - (ofpbuf_size(openflow) - start_ofs) % 8);
     }
 
     nal = ofpbuf_at_assert(openflow, start_ofs, sizeof *nal);
-    nal->len = htons(openflow->size - start_ofs);
+    nal->len = htons(ofpbuf_size(openflow) - start_ofs);
 }
 
 /* Composes 'fm' so that executing it will implement 'learn' given that the
@@ -302,17 +307,21 @@ learn_execute(const struct ofpact_learn *learn, const struct flow *flow,
     fm->priority = learn->priority;
     fm->cookie = htonll(0);
     fm->cookie_mask = htonll(0);
-    fm->new_cookie = htonll(learn->cookie);
-    fm->modify_cookie = fm->new_cookie != htonll(UINT64_MAX);
+    fm->new_cookie = learn->cookie;
+    fm->modify_cookie = fm->new_cookie != OVS_BE64_MAX;
     fm->table_id = learn->table_id;
     fm->command = OFPFC_MODIFY_STRICT;
     fm->idle_timeout = learn->idle_timeout;
     fm->hard_timeout = learn->hard_timeout;
     fm->buffer_id = UINT32_MAX;
     fm->out_port = OFPP_NONE;
-    fm->flags = learn->flags;
+    fm->flags = 0;
+    if (learn->flags & NX_LEARN_F_SEND_FLOW_REM) {
+        fm->flags |= OFPUTIL_FF_SEND_FLOW_REM;
+    }
     fm->ofpacts = NULL;
     fm->ofpacts_len = 0;
+    fm->delete_reason = OFPRR_DELETE;
 
     if (learn->fin_idle_timeout || learn->fin_hard_timeout) {
         struct ofpact_fin_timeout *oft;
@@ -371,8 +380,8 @@ learn_execute(const struct ofpact_learn *learn, const struct flow *flow,
     }
     ofpact_pad(ofpacts);
 
-    fm->ofpacts = ofpacts->data;
-    fm->ofpacts_len = ofpacts->size;
+    fm->ofpacts = ofpbuf_data(ofpacts);
+    fm->ofpacts_len = ofpbuf_size(ofpacts);
 }
 
 /* Perform a bitwise-OR on 'wc''s fields that are relevant as sources in
@@ -568,13 +577,17 @@ learn_parse__(char *orig, char *arg, struct ofpbuf *ofpacts)
         } else if (!strcmp(name, "fin_hard_timeout")) {
             learn->fin_hard_timeout = atoi(value);
         } else if (!strcmp(name, "cookie")) {
-            learn->cookie = strtoull(value, NULL, 0);
+            learn->cookie = htonll(strtoull(value, NULL, 0));
+        } else if (!strcmp(name, "send_flow_rem")) {
+            learn->flags |= NX_LEARN_F_SEND_FLOW_REM;
+        } else if (!strcmp(name, "delete_learned")) {
+            learn->flags |= NX_LEARN_F_DELETE_LEARNED;
         } else {
             struct ofpact_learn_spec *spec;
             char *error;
 
             spec = ofpbuf_put_zeros(ofpacts, sizeof *spec);
-            learn = ofpacts->l2;
+            learn = ofpacts->frame;
             learn->n_specs++;
 
             error = learn_parse_spec(orig, name, value, spec);
@@ -642,11 +655,14 @@ learn_format(const struct ofpact_learn *learn, struct ds *s)
     if (learn->priority != OFP_DEFAULT_PRIORITY) {
         ds_put_format(s, ",priority=%"PRIu16, learn->priority);
     }
-    if (learn->flags & OFPFF_SEND_FLOW_REM) {
-        ds_put_cstr(s, ",OFPFF_SEND_FLOW_REM");
+    if (learn->flags & NX_LEARN_F_SEND_FLOW_REM) {
+        ds_put_cstr(s, ",send_flow_rem");
+    }
+    if (learn->flags & NX_LEARN_F_DELETE_LEARNED) {
+        ds_put_cstr(s, ",delete_learned");
     }
     if (learn->cookie != 0) {
-        ds_put_format(s, ",cookie=%#"PRIx64, learn->cookie);
+        ds_put_format(s, ",cookie=%#"PRIx64, ntohll(learn->cookie));
     }
 
     for (spec = learn->specs; spec < &learn->specs[learn->n_specs]; spec++) {