Introduce ofpacts, an abstraction of OpenFlow actions.
[sliver-openvswitch.git] / ofproto / in-band.c
index ae1f1b1..43461ad 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <stdlib.h>
 #include "classifier.h"
 #include "dhcp.h"
-#include "dpif.h"
 #include "flow.h"
 #include "netdev.h"
 #include "netlink.h"
 #include "odp-util.h"
+#include "ofp-actions.h"
 #include "ofproto.h"
 #include "ofpbuf.h"
 #include "ofproto-provider.h"
@@ -131,7 +131,7 @@ refresh_remote(struct in_band *ib, struct in_band_remote *r)
     {
         netdev_close(r->remote_netdev);
 
-        retval = netdev_open_default(next_hop_dev, &r->remote_netdev);
+        retval = netdev_open(next_hop_dev, "system", &r->remote_netdev);
         if (retval) {
             VLOG_WARN_RL(&rl, "cannot open netdev %s (next hop "
                          "to controller "IP_FMT"): %s",
@@ -267,8 +267,8 @@ in_band_rule_check(const struct flow *flow,
         unsigned int left;
 
         NL_ATTR_FOR_EACH_UNSAFE (a, left, actions, actions_len) {
-            if (nl_attr_type(a) == ODP_ACTION_ATTR_OUTPUT
-                && nl_attr_get_u32(a) == ODPP_LOCAL) {
+            if (nl_attr_type(a) == OVS_ACTION_ATTR_OUTPUT
+                && nl_attr_get_u32(a) == OVSP_LOCAL) {
                 return true;
             }
         }
@@ -310,10 +310,10 @@ update_rules(struct in_band *ib)
         ib_rule->op = DELETE;
     }
 
-    if (!eth_addr_is_zero(ib->local_mac)) {
+    if (ib->n_remotes && !eth_addr_is_zero(ib->local_mac)) {
         /* (a) Allow DHCP requests sent from the local port. */
         cls_rule_init_catchall(&rule, IBR_FROM_LOCAL_DHCP);
-        cls_rule_set_in_port(&rule, ODPP_LOCAL);
+        cls_rule_set_in_port(&rule, OFPP_LOCAL);
         cls_rule_set_dl_type(&rule, htons(ETH_TYPE_IP));
         cls_rule_set_dl_src(&rule, ib->local_mac);
         cls_rule_set_nw_proto(&rule, IPPROTO_UDP);
@@ -395,35 +395,25 @@ update_rules(struct in_band *ib)
     }
 }
 
-void
+/* Updates the OpenFlow flow table for the current state of in-band control.
+ * Returns true ordinarily.  Returns false if no remotes are configured on 'ib'
+ * and 'ib' doesn't have any rules left to remove from the OpenFlow flow
+ * table.  Thus, a false return value means that the caller can destroy 'ib'
+ * without leaving extra flows hanging around in the flow table. */
+bool
 in_band_run(struct in_band *ib)
 {
-    struct {
-        struct nx_action_set_queue nxsq;
-        union ofp_action oa;
-    } actions;
-    const void *a;
-    size_t na;
+    uint64_t ofpacts_stub[128 / 8];
+    struct ofpbuf ofpacts;
 
     struct in_band_rule *rule, *next;
 
-    memset(&actions, 0, sizeof actions);
-    actions.oa.output.type = htons(OFPAT_OUTPUT);
-    actions.oa.output.len = htons(sizeof actions.oa);
-    actions.oa.output.port = htons(OFPP_NORMAL);
-    actions.oa.output.max_len = htons(0);
-    if (ib->queue_id < 0) {
-        a = &actions.oa;
-        na = sizeof actions.oa / sizeof(union ofp_action);
-    } else {
-        actions.nxsq.type = htons(OFPAT_VENDOR);
-        actions.nxsq.len = htons(sizeof actions.nxsq);
-        actions.nxsq.vendor = htonl(NX_VENDOR_ID);
-        actions.nxsq.subtype = htons(NXAST_SET_QUEUE);
-        actions.nxsq.queue_id = htonl(ib->queue_id);
-        a = &actions;
-        na = sizeof actions / sizeof(union ofp_action);
+    ofpbuf_use_stub(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
+
+    if (ib->queue_id >= 0) {
+        ofpact_put_SET_QUEUE(&ofpacts)->queue_id = ib->queue_id;
     }
+    ofpact_put_OUTPUT(&ofpacts)->port = OFPP_NORMAL;
 
     refresh_local(ib);
     refresh_remotes(ib);
@@ -433,7 +423,8 @@ in_band_run(struct in_band *ib)
     HMAP_FOR_EACH_SAFE (rule, next, cls_rule.hmap_node, &ib->rules) {
         switch (rule->op) {
         case ADD:
-            ofproto_add_flow(ib->ofproto, &rule->cls_rule, a, na);
+            ofproto_add_flow(ib->ofproto, &rule->cls_rule,
+                             ofpacts.data, ofpacts.size);
             break;
 
         case DELETE:
@@ -446,6 +437,10 @@ in_band_run(struct in_band *ib)
             break;
         }
     }
+
+    ofpbuf_uninit(&ofpacts);
+
+    return ib->n_remotes || !hmap_is_empty(&ib->rules);
 }
 
 void
@@ -465,7 +460,7 @@ in_band_create(struct ofproto *ofproto, const char *local_name,
     int error;
 
     *in_bandp = NULL;
-    error = netdev_open_default(local_name, &local_netdev);
+    error = netdev_open(local_name, "system", &local_netdev);
     if (error) {
         VLOG_ERR("failed to initialize in-band control: cannot open "
                  "datapath local port %s (%s)", local_name, strerror(error));