#include "rconn.h"
#include "shash.h"
#include "status.h"
+#include "stp.h"
#include "svec.h"
#include "tag.h"
#include "timeval.h"
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)
{
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)
{
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);
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;
}
{
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);
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;
}
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. */
}