Replace most uses of assert by ovs_assert.
[sliver-openvswitch.git] / lib / ofp-actions.c
index c6ba131..a439d13 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@
 #include "nx-match.h"
 #include "ofp-util.h"
 #include "ofpbuf.h"
+#include "util.h"
 #include "vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(ofp_actions);
@@ -49,7 +50,7 @@ output_from_openflow10(const struct ofp10_action_output *oao,
 }
 
 static enum ofperr
-enqueue_from_openflow10(const struct ofp_action_enqueue *oae,
+enqueue_from_openflow10(const struct ofp10_action_enqueue *oae,
                         struct ofpbuf *out)
 {
     struct ofpact_enqueue *enqueue;
@@ -479,7 +480,7 @@ ofpact_from_openflow10(const union ofp_action *a, struct ofpbuf *out)
         break;
 
     case OFPUTIL_OFPAT10_ENQUEUE:
-        error = enqueue_from_openflow10((const struct ofp_action_enqueue *) a,
+        error = enqueue_from_openflow10((const struct ofp10_action_enqueue *) a,
                                         out);
         break;
 
@@ -714,10 +715,24 @@ ofpact_from_openflow11(const union ofp_action *a, struct ofpbuf *out)
         ofpact_put_SET_VLAN_PCP(out)->vlan_pcp = a->vlan_pcp.vlan_pcp;
         break;
 
+    case OFPUTIL_OFPAT11_PUSH_VLAN:
+        if (((const struct ofp11_action_push *)a)->ethertype !=
+            htons(ETH_TYPE_VLAN_8021Q)) {
+            /* XXX 802.1AD(QinQ) isn't supported at the moment */
+            return OFPERR_OFPBAC_BAD_ARGUMENT;
+        }
+        ofpact_put_PUSH_VLAN(out);
+        break;
+
     case OFPUTIL_OFPAT11_POP_VLAN:
         ofpact_put_STRIP_VLAN(out);
         break;
 
+    case OFPUTIL_OFPAT11_SET_QUEUE:
+        ofpact_put_SET_QUEUE(out)->queue_id =
+            ntohl(((const struct ofp11_action_set_queue *)a)->queue_id);
+        break;
+
     case OFPUTIL_OFPAT11_SET_DL_SRC:
         memcpy(ofpact_put_SET_ETH_SRC(out)->mac,
                ((const struct ofp_action_dl_addr *) a)->dl_addr, ETH_ADDR_LEN);
@@ -780,7 +795,7 @@ ofpacts_from_openflow11(const union ofp_action *in, size_t n_in,
     static inline const struct STRUCT *                         \
     instruction_get_##ENUM(const struct ofp11_instruction *inst)\
     {                                                           \
-        assert(inst->type == htons(ENUM));                      \
+        ovs_assert(inst->type == htons(ENUM));                  \
         return (struct STRUCT *)inst;                           \
     }                                                           \
                                                                 \
@@ -903,7 +918,9 @@ decode_openflow11_instructions(const struct ofp11_instruction insts[],
         }
 
         if (out[type]) {
-            return OFPERR_OFPIT_BAD_INSTRUCTION;
+            return OFPERR_OFPBAC_UNSUPPORTED_ORDER; /* No specific code for
+                                                     * a duplicate instruction
+                                                     * exist */
         }
         out[type] = inst;
     }
@@ -1000,7 +1017,7 @@ ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow,
             insts[OVSINST_OFPIT11_CLEAR_ACTIONS]);
         ofpact_put_CLEAR_ACTIONS(ofpacts);
     }
-    /* TODO:XXX Write-Actions */
+    /* XXX Write-Actions */
     if (insts[OVSINST_OFPIT11_WRITE_METADATA]) {
         const struct ofp11_instruction_write_metadata *oiwm;
         struct ofpact_metadata *om;
@@ -1065,6 +1082,7 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports)
     case OFPACT_SET_VLAN_VID:
     case OFPACT_SET_VLAN_PCP:
     case OFPACT_STRIP_VLAN:
+    case OFPACT_PUSH_VLAN:
     case OFPACT_SET_ETH_SRC:
     case OFPACT_SET_ETH_DST:
     case OFPACT_SET_IPV4_SRC:
@@ -1136,24 +1154,38 @@ enum ofperr
 ofpacts_verify(const struct ofpact ofpacts[], size_t ofpacts_len)
 {
     const struct ofpact *a;
-    const struct ofpact_metadata *om = NULL;
+    enum ovs_instruction_type inst;
 
+    inst = OVSINST_OFPIT11_APPLY_ACTIONS;
     OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
-        if (om) {
-            if (a->type == OFPACT_WRITE_METADATA) {
-                VLOG_WARN("duplicate write_metadata instruction specified");
-                /* should be OFPERR_OFPET_BAD_ACTION? */
-                return OFPERR_OFPBAC_UNSUPPORTED_ORDER;
+        enum ovs_instruction_type next;
+
+        if (a->type == OFPACT_CLEAR_ACTIONS) {
+            next = OVSINST_OFPIT11_CLEAR_ACTIONS;
+        } else if (a->type == OFPACT_WRITE_METADATA) {
+            next = OVSINST_OFPIT11_WRITE_METADATA;
+        } else if (a->type == OFPACT_GOTO_TABLE) {
+            next = OVSINST_OFPIT11_GOTO_TABLE;
+        } else {
+            next = OVSINST_OFPIT11_APPLY_ACTIONS;
+        }
+
+        if (inst != OVSINST_OFPIT11_APPLY_ACTIONS && next <= inst) {
+            const char *name = ofpact_instruction_name_from_type(inst);
+            const char *next_name = ofpact_instruction_name_from_type(next);
+
+            if (next == inst) {
+                VLOG_WARN("duplicate %s instruction not allowed, for OpenFlow "
+                          "1.1+ compatibility", name);
             } else {
-                VLOG_WARN("write_metadata instruction must be specified after "
-                          "other instructions/actions");
-                return OFPERR_OFPBAC_UNSUPPORTED_ORDER;
+                VLOG_WARN("invalid instruction ordering: %s must appear "
+                          "before %s, for OpenFlow 1.1+ compatibility",
+                          next_name, name);
             }
+            return OFPERR_OFPBAC_UNSUPPORTED_ORDER;
         }
 
-        if (a->type == OFPACT_WRITE_METADATA) {
-            om = (const struct ofpact_metadata *) a;
-        }
+        inst = next;
     }
 
     return 0;
@@ -1358,6 +1390,7 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out)
     case OFPACT_SET_VLAN_VID:
     case OFPACT_SET_VLAN_PCP:
     case OFPACT_STRIP_VLAN:
+    case OFPACT_PUSH_VLAN:
     case OFPACT_SET_ETH_SRC:
     case OFPACT_SET_ETH_DST:
     case OFPACT_SET_IPV4_SRC:
@@ -1388,7 +1421,7 @@ static void
 ofpact_enqueue_to_openflow10(const struct ofpact_enqueue *enqueue,
                              struct ofpbuf *out)
 {
-    struct ofp_action_enqueue *oae;
+    struct ofp10_action_enqueue *oae;
 
     oae = ofputil_put_OFPAT10_ENQUEUE(out);
     oae->port = htons(enqueue->port);
@@ -1456,9 +1489,10 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out)
             = htons(ofpact_get_SET_L4_DST_PORT(a)->port);
         break;
 
+    case OFPACT_PUSH_VLAN:
     case OFPACT_CLEAR_ACTIONS:
     case OFPACT_GOTO_TABLE:
-        /* TODO:XXX */
+        /* XXX */
         break;
 
     case OFPACT_CONTROLLER:
@@ -1548,6 +1582,17 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out)
         ofputil_put_OFPAT11_POP_VLAN(out);
         break;
 
+    case OFPACT_PUSH_VLAN:
+        /* XXX ETH_TYPE_VLAN_8021AD case */
+        ofputil_put_OFPAT11_PUSH_VLAN(out)->ethertype =
+            htons(ETH_TYPE_VLAN_8021Q);
+        break;
+
+    case OFPACT_SET_QUEUE:
+        ofputil_put_OFPAT11_SET_QUEUE(out)->queue_id
+            = htonl(ofpact_get_SET_QUEUE(a)->queue_id);
+        break;
+
     case OFPACT_SET_ETH_SRC:
         memcpy(ofputil_put_OFPAT11_SET_DL_SRC(out)->dl_addr,
                ofpact_get_SET_ETH_SRC(a)->mac, ETH_ADDR_LEN);
@@ -1601,7 +1646,6 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out)
     case OFPACT_REG_MOVE:
     case OFPACT_REG_LOAD:
     case OFPACT_SET_TUNNEL:
-    case OFPACT_SET_QUEUE:
     case OFPACT_POP_QUEUE:
     case OFPACT_FIN_TIMEOUT:
     case OFPACT_RESUBMIT:
@@ -1654,7 +1698,7 @@ ofpacts_put_openflow11_instructions(const struct ofpact ofpacts[],
     const struct ofpact *a;
 
     OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
-        /* TODO:XXX Write-Actions */
+        /* XXX Write-Actions */
 
         if (a->type == OFPACT_CLEAR_ACTIONS) {
             instruction_put_OFPIT11_CLEAR_ACTIONS(openflow);
@@ -1711,6 +1755,7 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, uint16_t port)
     case OFPACT_SET_VLAN_VID:
     case OFPACT_SET_VLAN_PCP:
     case OFPACT_STRIP_VLAN:
+    case OFPACT_PUSH_VLAN:
     case OFPACT_SET_ETH_SRC:
     case OFPACT_SET_ETH_DST:
     case OFPACT_SET_IPV4_SRC:
@@ -1894,6 +1939,11 @@ ofpact_format(const struct ofpact *a, struct ds *s)
         ds_put_cstr(s, "strip_vlan");
         break;
 
+    case OFPACT_PUSH_VLAN:
+        /* XXX 802.1AD case*/
+        ds_put_format(s, "push_vlan:%#"PRIx16, ETH_TYPE_VLAN_8021Q);
+        break;
+
     case OFPACT_SET_ETH_SRC:
         ds_put_format(s, "mod_dl_src:"ETH_ADDR_FMT,
                       ETH_ADDR_ARGS(ofpact_get_SET_ETH_SRC(a)->mac));
@@ -1906,12 +1956,12 @@ ofpact_format(const struct ofpact *a, struct ds *s)
 
     case OFPACT_SET_IPV4_SRC:
         ds_put_format(s, "mod_nw_src:"IP_FMT,
-                      IP_ARGS(&ofpact_get_SET_IPV4_SRC(a)->ipv4));
+                      IP_ARGS(ofpact_get_SET_IPV4_SRC(a)->ipv4));
         break;
 
     case OFPACT_SET_IPV4_DST:
         ds_put_format(s, "mod_nw_dst:"IP_FMT,
-                      IP_ARGS(&ofpact_get_SET_IPV4_DST(a)->ipv4));
+                      IP_ARGS(ofpact_get_SET_IPV4_DST(a)->ipv4));
         break;
 
     case OFPACT_SET_IPV4_DSCP:
@@ -2045,7 +2095,7 @@ ofpacts_format(const struct ofpact *ofpacts, size_t ofpacts_len,
                 ds_put_cstr(string, ",");
             }
 
-            /* TODO:XXX write-actions */
+            /* XXX write-actions */
             ofpact_format(a, string);
         }
     }
@@ -2082,7 +2132,7 @@ ofpact_init(struct ofpact *ofpact, enum ofpact_type type, size_t len)
 void
 ofpact_update_len(struct ofpbuf *ofpacts, struct ofpact *ofpact)
 {
-    assert(ofpact == ofpacts->l2);
+    ovs_assert(ofpact == ofpacts->l2);
     ofpact->len = (char *) ofpbuf_tail(ofpacts) - (char *) ofpact;
 }