#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"
/* 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);
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",
}
free(p->snoops);
+ mac_learning_destroy(p->ml);
+
free(p);
}
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);
ea[2] = 0x20;
return eth_addr_to_uint64(ea);
}
+\f
+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,
+};