From 10e05880439ed47ba19b7309c1d20b89fb1fdbc1 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 17 Mar 2009 17:23:35 -0700 Subject: [PATCH] secchan: Make default normal action do switching. The default normal action is what OFPP_NORMAL does in secchan when vswitchd is not running. Before, this was equivalent to OFPP_FLOOD. With this change, the behavior changes to acting as a learning switch. This makes the recent changes to in-band control more efficient when running in secchan without vswitchd, since we don't really want to flood all the packets to and from the controller. --- secchan/ofproto.c | 74 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 10 deletions(-) diff --git a/secchan/ofproto.c b/secchan/ofproto.c index e866ba9e..9525581e 100644 --- a/secchan/ofproto.c +++ b/secchan/ofproto.c @@ -45,6 +45,7 @@ #include "executer.h" #include "fail-open.h" #include "in-band.h" +#include "mac-learning.h" #include "netdev.h" #include "netflow.h" #include "odp-util.h" @@ -227,11 +228,14 @@ struct ofproto { /* Hooks for vswitchd. */ const struct ofhooks *ofhooks; void *aux; + + /* Used by default ofhooks. */ + struct mac_learning *ml; }; static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); -static const struct ofhooks null_ofhooks; +static const struct ofhooks default_ofhooks; static uint64_t pick_datapath_id(struct dpif *, uint64_t fallback_dpid); static uint64_t pick_fallback_dpid(void); @@ -331,8 +335,15 @@ ofproto_create(const char *datapath, const struct ofhooks *ofhooks, void *aux, p->n_snoops = 0; /* Initialize hooks. */ - p->ofhooks = ofhooks ? ofhooks : &null_ofhooks; - p->aux = aux; + if (ofhooks) { + p->ofhooks = ofhooks; + p->aux = aux; + p->ml = NULL; + } else { + p->ofhooks = &default_ofhooks; + p->aux = p; + p->ml = mac_learning_create(); + } /* Register switch status category. */ p->ss_cat = switch_status_register(p->switch_status, "remote", @@ -712,6 +723,8 @@ ofproto_destroy(struct ofproto *p) } free(p->snoops); + mac_learning_destroy(p->ml); + free(p); } @@ -1691,13 +1704,9 @@ xlate_output_action(struct action_xlate_ctx *ctx, xlate_table_action(ctx, ctx->flow->in_port); break; case OFPP_NORMAL: - if (ctx->ofproto->ofhooks->normal_cb) { - ctx->ofproto->ofhooks->normal_cb(ctx->flow, ctx->revalidating, - ctx->out, ctx->tags, - ctx->ofproto->aux); - } else { - add_output_group_action(ctx->out, DP_GROUP_FLOOD); - } + ctx->ofproto->ofhooks->normal_cb(ctx->flow, ctx->revalidating, + ctx->out, ctx->tags, + ctx->ofproto->aux); break; case OFPP_FLOOD: add_output_group_action(ctx->out, DP_GROUP_FLOOD); @@ -3102,3 +3111,48 @@ pick_fallback_dpid(void) ea[2] = 0x20; return eth_addr_to_uint64(ea); } + +static void +default_normal_ofhook_cb(const flow_t *flow, bool revalidating, + struct odp_actions *actions, tag_type *tags, + void *ofproto_) +{ + struct ofproto *ofproto = ofproto_; + int out_port; + + /* Drop frames for reserved multicast addresses. */ + if (eth_addr_is_reserved(flow->dl_dst)) { + return; + } + + /* Learn source MAC (but don't try to learn from revalidation). */ + if (!revalidating) { + tag_type rev_tag = mac_learning_learn(ofproto->ml, flow->dl_src, + 0, flow->in_port); + if (rev_tag) { + /* The log messages here could actually be useful in debugging, + * so keep the rate limit relatively high. */ + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 300); + VLOG_DBG_RL(&rl, "learned that "ETH_ADDR_FMT" is on port %"PRIu16, + ETH_ADDR_ARGS(flow->dl_src), flow->in_port); + ofproto_revalidate(ofproto, rev_tag); + } + } + + /* Determine output port. */ + out_port = mac_learning_lookup_tag(ofproto->ml, flow->dl_dst, 0, tags); + 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); + } else { + /* Drop. */ + } +} + +static const struct ofhooks default_ofhooks = { + NULL, + NULL, + NULL, + default_normal_ofhook_cb, +}; -- 2.30.2