secchan: Honor OFPPC_NO_RECV, OFPPC_NO_RECV_STP, OFPPC_NO_FWD.
authorBen Pfaff <blp@nicira.com>
Fri, 1 May 2009 20:35:36 +0000 (13:35 -0700)
committerBen Pfaff <blp@nicira.com>
Fri, 1 May 2009 20:38:55 +0000 (13:38 -0700)
The refactoring of secchan and the kernel module dropped support for these
(required) OpenFlow port flags.  This commit reimplements them.

MISSING
secchan/ofproto.c

diff --git a/MISSING b/MISSING
index ec3d755dc169edd7735c22a9e6d14b04ea016aae..b55253fb4a96aa45761867ce43f0abaadc293cb8 100644 (file)
--- a/MISSING
+++ b/MISSING
@@ -6,9 +6,6 @@ reimplement them with the new architecture:
 - STP support in secchan (note that this is distinct from STP support
   in vswitchd).
 
-- The OFPPC_NO_RECV, OFPPC_NO_RECV_STP, and OFPPC_NO_FWD bits in port
-  configurations.
-
 - SNAT support in secchan (but SNAT is still supported in the kernel
   datapath).
 
index 71eaca4d7c4087f4d8591c06bb464d4afd085270..2252c0e946497f22c635de9c004bb5b481f2fe19 100644 (file)
@@ -63,6 +63,7 @@
 #include "rconn.h"
 #include "shash.h"
 #include "status.h"
+#include "stp.h"
 #include "svec.h"
 #include "tag.h"
 #include "timeval.h"
@@ -1804,12 +1805,6 @@ handle_set_config(struct ofproto *p, struct ofconn *ofconn,
     return 0;
 }
 
-static void
-add_output_action(struct odp_actions *actions, uint16_t port)
-{
-    odp_actions_add(actions, ODPAT_OUTPUT)->output.port = port;
-}
-
 static void
 add_output_group_action(struct odp_actions *actions, uint16_t group)
 {
@@ -1843,6 +1838,15 @@ struct action_xlate_ctx {
 static void do_xlate_actions(const union ofp_action *in, size_t n_in,
                              struct action_xlate_ctx *ctx);
 
+static void
+add_output_action(struct action_xlate_ctx *ctx, uint16_t port)
+{
+    const struct ofport *ofport = port_array_get(&ctx->ofproto->ports, port);
+    if (!ofport || !(ofport->opp.config & OFPPC_NO_FWD)) {
+        odp_actions_add(ctx->out, ODPAT_OUTPUT)->output.port = port;
+    }
+}
+
 static struct rule *
 lookup_valid_rule(struct ofproto *ofproto, const flow_t *flow)
 {
@@ -1892,7 +1896,7 @@ xlate_output_action(struct action_xlate_ctx *ctx,
 
     switch (ntohs(oao->port)) {
     case OFPP_IN_PORT:
-        add_output_action(ctx->out, ctx->flow->in_port);
+        add_output_action(ctx, ctx->flow->in_port);
         break;
     case OFPP_TABLE:
         xlate_table_action(ctx, ctx->flow->in_port);
@@ -1914,12 +1918,12 @@ xlate_output_action(struct action_xlate_ctx *ctx,
         add_controller_action(ctx->out, oao);
         break;
     case OFPP_LOCAL:
-        add_output_action(ctx->out, ODPP_LOCAL);
+        add_output_action(ctx, ODPP_LOCAL);
         break;
     default:
         odp_port = ofp_port_to_odp_port(ntohs(oao->port));
         if (odp_port != ctx->flow->in_port) {
-            add_output_action(ctx->out, odp_port);
+            add_output_action(ctx, odp_port);
         }
         break;
     }
@@ -1959,6 +1963,15 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
 {
     struct actions_iterator iter;
     const union ofp_action *ia;
+    const struct ofport *port;
+
+    port = port_array_get(&ctx->ofproto->ports, ctx->flow->in_port);
+    if (port && port->opp.config & (OFPPC_NO_RECV | OFPPC_NO_RECV_STP) &&
+        port->opp.config & (eth_addr_equals(ctx->flow->dl_dst, stp_eth_addr)
+                            ? OFPPC_NO_RECV_STP : OFPPC_NO_RECV)) {
+        /* Drop this flow. */
+        return;
+    }
 
     for (ia = actions_first(&iter, in, n_in); ia; ia = actions_next(&iter)) {
         uint16_t type = ntohs(ia->type);
@@ -2098,22 +2111,16 @@ update_port_config(struct ofproto *p, struct ofport *port,
             netdev_turn_flags_on(port->netdev, NETDEV_UP, true);
         }
     }
-    if (mask & OFPPC_NO_STP) {
-        /* XXX */
-    }
-    if (mask & OFPPC_NO_RECV) {
-        /* XXX */
-    }
-    if (mask & OFPPC_NO_RECV_STP) {
-        /* XXX */
+#define REVALIDATE_BITS (OFPPC_NO_RECV | OFPPC_NO_RECV_STP | OFPPC_NO_FWD)
+    if (mask & REVALIDATE_BITS) {
+        port->opp.config ^= mask & REVALIDATE_BITS;
+        p->need_revalidate = true;
     }
+#undef REVALIDATE_BITS
     if (mask & OFPPC_NO_FLOOD) {
         port->opp.config ^= OFPPC_NO_FLOOD;
         refresh_port_group(p, DP_GROUP_FLOOD);
     }
-    if (mask & OFPPC_NO_FWD) {
-        /* XXX */
-    }
     if (mask & OFPPC_NO_PACKET_IN) {
         port->opp.config ^= OFPPC_NO_PACKET_IN;
     }
@@ -3226,7 +3233,7 @@ default_normal_ofhook_cb(const flow_t *flow, const struct ofpbuf *packet,
     if (out_port < 0) {
         add_output_group_action(actions, DP_GROUP_FLOOD);
     } else if (out_port != flow->in_port) {
-        add_output_action(actions, out_port);
+        odp_actions_add(actions, ODPAT_OUTPUT)->output.port = out_port;
     } else {
         /* Drop. */
     }