xport->peer = NULL;
}
- list_remove(&xport->bundle_node);
+ if (xport->xbundle) {
+ list_remove(&xport->bundle_node);
+ }
+
hmap_remove(&xports, &xport->hmap_node);
hmap_remove(&xport->xbridge->xports, &xport->ofp_node);
return;
}
+ ovs_rwlock_wrlock(&xbridge->ml->rwlock);
if (!mac_learning_may_learn(xbridge->ml, flow->dl_src, vlan)) {
- return;
+ goto out;
}
mac = mac_learning_insert(xbridge->ml, flow->dl_src, vlan);
if (!in_xbundle->bond) {
mac_entry_set_grat_arp_lock(mac);
} else if (mac_entry_is_grat_arp_locked(mac)) {
- return;
+ goto out;
}
}
- if (mac_entry_is_new(mac) || mac->port.p != in_xbundle->ofbundle) {
+ if (mac->port.p != in_xbundle->ofbundle) {
/* 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);
in_xbundle->name, vlan);
mac->port.p = in_xbundle->ofbundle;
- mac_learning_changed(xbridge->ml, mac);
+ mac_learning_changed(xbridge->ml);
}
+out:
+ ovs_rwlock_unlock(&xbridge->ml->rwlock);
}
/* Determines whether packets in 'flow' within 'xbridge' should be forwarded or
return false;
case BV_DROP_IF_MOVED:
- mac = mac_learning_lookup(xbridge->ml, flow->dl_src, vlan, NULL);
+ ovs_rwlock_rdlock(&xbridge->ml->rwlock);
+ mac = mac_learning_lookup(xbridge->ml, flow->dl_src, vlan);
if (mac && mac->port.p != in_xbundle->ofbundle &&
(!is_gratuitous_arp(flow, &ctx->xout->wc)
|| mac_entry_is_grat_arp_locked(mac))) {
+ ovs_rwlock_unlock(&xbridge->ml->rwlock);
xlate_report(ctx, "SLB bond thinks this packet looped back, "
"dropping");
return false;
}
+ ovs_rwlock_unlock(&xbridge->ml->rwlock);
break;
}
}
}
/* Determine output bundle. */
- mac = mac_learning_lookup(ctx->xbridge->ml, flow->dl_dst, vlan,
- &ctx->xout->tags);
+ ovs_rwlock_rdlock(&ctx->xbridge->ml->rwlock);
+ mac = mac_learning_lookup(ctx->xbridge->ml, flow->dl_dst, vlan);
if (mac) {
struct xbundle *mac_xbundle = xbundle_lookup(mac->port.p);
if (mac_xbundle && mac_xbundle != in_xbundle) {
}
ctx->xout->nf_output_iface = NF_OUT_FLOOD;
}
+ ovs_rwlock_unlock(&ctx->xbridge->ml->rwlock);
}
/* Compose SAMPLE action for sFlow or IPFIX. The given probability is
ctx->rule->up.evictable = false;
}
- do_xlate_actions_again:
OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
struct ofpact_controller *controller;
const struct ofpact_metadata *metadata;
case OFPACT_GOTO_TABLE: {
/* It is assumed that goto-table is the last action. */
struct ofpact_goto_table *ogt = ofpact_get_GOTO_TABLE(a);
- struct rule_dpif *rule;
ovs_assert(ctx->table_id < ogt->table_id);
-
- ctx->table_id = ogt->table_id;
-
- /* Look up a flow from the new table. */
- rule = rule_dpif_lookup_in_table(ctx->xbridge->ofproto, flow, wc,
- ctx->table_id);
-
- ctx->xout->tags |= calculate_flow_tag(ctx->xbridge->ofproto,
- &ctx->xin->flow,
- ctx->table_id, rule);
-
- rule = ctx_rule_hooks(ctx, rule, true);
-
- if (rule) {
- if (ctx->rule) {
- ctx->rule->up.evictable = was_evictable;
- }
- ctx->rule = rule;
- was_evictable = rule->up.evictable;
- rule->up.evictable = false;
-
- /* Tail recursion removal. */
- ofpacts = rule->up.ofpacts;
- ofpacts_len = rule->up.ofpacts_len;
- goto do_xlate_actions_again;
- }
+ xlate_table_action(ctx, ctx->xin->flow.in_port.ofp_port,
+ ogt->table_id, true);
break;
}
if (tnl_port_should_receive(&ctx.xin->flow)) {
memset(&wc->masks.tunnel, 0xff, sizeof wc->masks.tunnel);
+ /* skb_mark is currently used only by tunnels but that will likely
+ * change in the future. */
+ memset(&wc->masks.skb_mark, 0xff, sizeof wc->masks.skb_mark);
}
if (ctx.xbridge->has_netflow) {
netflow_mask_wc(flow, wc);