cfm: Send properly formatted CCMs.
[openvswitch] / lib / ofp-parse.c
index a80d45fe62608d12a653856dc8fbf233c6d54b5d..6b1cfa099034680f297b80b3f0c72550165fcffa 100644 (file)
@@ -26,6 +26,7 @@
 #include "bundle.h"
 #include "byte-order.h"
 #include "dynamic-string.h"
+#include "learn.h"
 #include "meta-flow.h"
 #include "netdev.h"
 #include "multipath.h"
@@ -228,7 +229,8 @@ parse_note(struct ofpbuf *b, const char *arg)
 }
 
 static void
-parse_named_action(enum ofputil_action_code code, struct ofpbuf *b, char *arg)
+parse_named_action(enum ofputil_action_code code, const struct flow *flow,
+                   struct ofpbuf *b, char *arg)
 {
     struct ofp_action_dl_addr *oada;
     struct ofp_action_vlan_pcp *oavp;
@@ -332,11 +334,15 @@ parse_named_action(enum ofputil_action_code code, struct ofpbuf *b, char *arg)
     case OFPUTIL_NXAST_RESUBMIT_TABLE:
     case OFPUTIL_NXAST_OUTPUT_REG:
         NOT_REACHED();
+
+    case OFPUTIL_NXAST_LEARN:
+        learn_parse(b, arg, flow);
+        break;
     }
 }
 
 static void
-str_to_action(char *str, struct ofpbuf *b)
+str_to_action(const struct flow *flow, char *str, struct ofpbuf *b)
 {
     char *pos, *act, *arg;
     int n_actions;
@@ -349,7 +355,7 @@ str_to_action(char *str, struct ofpbuf *b)
 
         code = ofputil_action_code_from_name(act);
         if (code >= 0) {
-            parse_named_action(code, b, arg);
+            parse_named_action(code, flow, b, arg);
         } else if (!strcasecmp(act, "drop")) {
             /* A drop action in OpenFlow occurs by just not setting
              * an action. */
@@ -462,6 +468,7 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
     } fields;
     char *string = xstrdup(str_);
     char *save_ptr = NULL;
+    char *act_str = NULL;
     char *name;
 
     switch (command) {
@@ -503,9 +510,6 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
     fm->out_port = OFPP_NONE;
     fm->flags = 0;
     if (fields & F_ACTIONS) {
-        struct ofpbuf actions;
-        char *act_str;
-
         act_str = strstr(string, "action");
         if (!act_str) {
             ofp_fatal(str_, verbose, "must specify an action");
@@ -518,14 +522,6 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
         }
 
         act_str++;
-
-        ofpbuf_init(&actions, sizeof(union ofp_action));
-        str_to_action(act_str, &actions);
-        fm->actions = ofpbuf_steal_data(&actions);
-        fm->n_actions = actions.size / sizeof(union ofp_action);
-    } else {
-        fm->actions = NULL;
-        fm->n_actions = 0;
     }
     for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
          name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
@@ -569,6 +565,17 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
             }
         }
     }
+    if (fields & F_ACTIONS) {
+        struct ofpbuf actions;
+
+        ofpbuf_init(&actions, sizeof(union ofp_action));
+        str_to_action(&fm->cr.flow, act_str, &actions);
+        fm->actions = ofpbuf_steal_data(&actions);
+        fm->n_actions = actions.size / sizeof(union ofp_action);
+    } else {
+        fm->actions = NULL;
+        fm->n_actions = 0;
+    }
 
     free(string);
 }
@@ -586,11 +593,9 @@ parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format,
 {
     enum nx_flow_format min_format, next_format;
     struct cls_rule rule_copy;
-    struct ofpbuf actions;
     struct ofpbuf *ofm;
     struct ofputil_flow_mod fm;
 
-    ofpbuf_init(&actions, 64);
     parse_ofp_str(&fm, command, string, verbose);
 
     min_format = ofputil_min_flow_format(&fm.cr);
@@ -615,8 +620,6 @@ parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format,
 
     ofm = ofputil_encode_flow_mod(&fm, *cur_format, *flow_mod_table_id);
     list_push_back(packets, &ofm->list_node);
-
-    ofpbuf_uninit(&actions);
 }
 
 /* Similar to parse_ofp_flow_mod_str(), except that the string is read from