Add ability to direct "packet-in"s to particular controllers.
[sliver-openvswitch.git] / lib / ofp-parse.c
index 3a1fcb7..58bf49d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011 Nicira Networks.
+ * Copyright (c) 2010, 2011, 2012 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -249,6 +249,66 @@ parse_note(struct ofpbuf *b, const char *arg)
     nan->len = htons(b->size - start_ofs);
 }
 
+static void
+parse_fin_timeout(struct ofpbuf *b, char *arg)
+{
+    struct nx_action_fin_timeout *naft;
+    char *key, *value;
+
+    naft = ofputil_put_NXAST_FIN_TIMEOUT(b);
+    while (ofputil_parse_key_value(&arg, &key, &value)) {
+        if (!strcmp(key, "idle_timeout")) {
+            naft->fin_idle_timeout = htons(str_to_u16(value, key));
+        } else if (!strcmp(key, "hard_timeout")) {
+            naft->fin_hard_timeout = htons(str_to_u16(value, key));
+        } else {
+            ovs_fatal(0, "invalid key '%s' in 'fin_timeout' argument", key);
+        }
+    }
+}
+
+static void
+parse_controller(struct ofpbuf *b, char *arg)
+{
+    enum ofp_packet_in_reason reason = OFPR_ACTION;
+    uint16_t controller_id = 0;
+    uint16_t max_len = UINT16_MAX;
+
+    if (!arg[0]) {
+        /* Use defaults. */
+    } else if (strspn(arg, "0123456789") == strlen(arg)) {
+        max_len = str_to_u16(arg, "max_len");
+    } else {
+        char *name, *value;
+
+        while (ofputil_parse_key_value(&arg, &name, &value)) {
+            if (!strcmp(name, "reason")) {
+                if (!ofputil_packet_in_reason_from_string(value, &reason)) {
+                    ovs_fatal(0, "unknown reason \"%s\"", value);
+                }
+            } else if (!strcmp(name, "max_len")) {
+                max_len = str_to_u16(value, "max_len");
+            } else if (!strcmp(name, "id")) {
+                controller_id = str_to_u16(value, "id");
+            } else {
+                ovs_fatal(0, "unknown key \"%s\" parsing controller action",
+                          name);
+            }
+        }
+    }
+
+    if (reason == OFPR_ACTION && controller_id == 0) {
+        put_output_action(b, OFPP_CONTROLLER)->max_len = htons(max_len);
+    } else {
+        struct nx_action_controller *nac;
+
+        nac = ofputil_put_NXAST_CONTROLLER(b);
+        nac->max_len = htons(max_len);
+        nac->reason = reason;
+        nac->controller_id = htons(controller_id);
+    }
+}
+
 static void
 parse_named_action(enum ofputil_action_code code, const struct flow *flow,
                    struct ofpbuf *b, char *arg)
@@ -367,6 +427,14 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
     case OFPUTIL_NXAST_DEC_TTL:
         ofputil_put_NXAST_DEC_TTL(b);
         break;
+
+    case OFPUTIL_NXAST_FIN_TIMEOUT:
+        parse_fin_timeout(b, arg);
+        break;
+
+    case OFPUTIL_NXAST_CONTROLLER:
+        parse_controller(b, arg);
+        break;
     }
 }
 
@@ -396,17 +464,6 @@ str_to_action(const struct flow *flow, char *str, struct ofpbuf *b)
                           "actions");
             }
             break;
-        } else if (!strcasecmp(act, "CONTROLLER")) {
-            struct ofp_action_output *oao;
-            oao = put_output_action(b, OFPP_CONTROLLER);
-
-            /* Unless a numeric argument is specified, we send the whole
-             * packet to the controller. */
-            if (arg[0] && (strspn(arg, "0123456789") == strlen(arg))) {
-               oao->max_len = htons(str_to_u32(arg));
-            } else {
-                oao->max_len = htons(UINT16_MAX);
-            }
         } else if (ofputil_port_from_string(act, &port)) {
             put_output_action(b, port);
         } else {
@@ -492,7 +549,8 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
         F_OUT_PORT = 1 << 0,
         F_ACTIONS = 1 << 1,
         F_TIMEOUT = 1 << 3,
-        F_PRIORITY = 1 << 4
+        F_PRIORITY = 1 << 4,
+        F_FLAGS = 1 << 5,
     } fields;
     char *string = xstrdup(str_);
     char *save_ptr = NULL;
@@ -505,7 +563,7 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
         break;
 
     case OFPFC_ADD:
-        fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY;
+        fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS;
         break;
 
     case OFPFC_DELETE:
@@ -517,11 +575,11 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
         break;
 
     case OFPFC_MODIFY:
-        fields = F_ACTIONS;
+        fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS;
         break;
 
     case OFPFC_MODIFY_STRICT:
-        fields = F_ACTIONS | F_PRIORITY;
+        fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS;
         break;
 
     default:
@@ -561,6 +619,10 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
             if (p->nw_proto) {
                 cls_rule_set_nw_proto(&fm->cr, p->nw_proto);
             }
+        } else if (fields & F_FLAGS && !strcmp(name, "send_flow_rem")) {
+            fm->flags |= OFPFF_SEND_FLOW_REM;
+        } else if (fields & F_FLAGS && !strcmp(name, "check_overlap")) {
+            fm->flags |= OFPFF_CHECK_OVERLAP;
         } else {
             char *value;
 
@@ -620,6 +682,19 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
     free(string);
 }
 
+/* Parses 's' as a set of OpenFlow actions and appends the actions to
+ * 'actions'.
+ *
+ * Prints an error on stderr and aborts the program if 's' syntax is
+ * invalid. */
+void
+parse_ofp_actions(const char *s_, struct ofpbuf *actions)
+{
+    char *s = xstrdup(s_);
+    str_to_action(NULL, s, actions);
+    free(s);
+}
+
 /* Parses 'string' as an OFPT_FLOW_MOD or NXT_FLOW_MOD with command 'command'
  * (one of OFPFC_*) and appends the parsed OpenFlow message to 'packets'.
  * '*cur_format' should initially contain the flow format currently configured
@@ -628,8 +703,8 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
  * flow. */
 void
 parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format,
-                       bool *flow_mod_table_id, char *string, uint16_t command,
-                       bool verbose)
+                       bool *flow_mod_table_id, const char *string,
+                       uint16_t command, bool verbose)
 {
     enum nx_flow_format min_format, next_format;
     struct cls_rule rule_copy;
@@ -689,7 +764,7 @@ parse_ofp_flow_mod_file(struct list *packets,
 
 void
 parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *fsr,
-                                 bool aggregate, char *string)
+                                 bool aggregate, const char *string)
 {
     struct ofputil_flow_mod fm;