In my opinion this is easier to understand than the way that these
two logically separate steps were previously entangled.
const struct port *in_port, const struct port *out_port,
struct dst_set *set, tag_type *tags, uint16_t *nf_output_iface)
{
const struct port *in_port, const struct port *out_port,
struct dst_set *set, tag_type *tags, uint16_t *nf_output_iface)
{
- mirror_mask_t mirrors = in_port->src_mirrors;
- int flow_vlan;
-
- flow_vlan = vlan_tci_to_vid(flow->vlan_tci);
- if (flow_vlan == 0) {
- flow_vlan = OFP_VLAN_NONE;
- }
if (out_port == FLOOD_PORT) {
struct port *port;
if (out_port == FLOOD_PORT) {
struct port *port;
&& port_includes_vlan(port, vlan)
&& !port->is_mirror_output_port
&& set_dst(&dst, flow, in_port, port, tags)) {
&& port_includes_vlan(port, vlan)
&& !port->is_mirror_output_port
&& set_dst(&dst, flow, in_port, port, tags)) {
- mirrors |= port->dst_mirrors;
dst_set_add(set, &dst);
}
}
dst_set_add(set, &dst);
}
}
} else if (out_port && set_dst(&dst, flow, in_port, out_port, tags)) {
dst_set_add(set, &dst);
*nf_output_iface = dst.iface->dp_ifidx;
} else if (out_port && set_dst(&dst, flow, in_port, out_port, tags)) {
dst_set_add(set, &dst);
*nf_output_iface = dst.iface->dp_ifidx;
- mirrors |= out_port->dst_mirrors;
+ }
+}
+
+static void
+compose_mirror_dsts(const struct bridge *br, const struct flow *flow,
+ uint16_t vlan, const struct port *in_port,
+ struct dst_set *set, tag_type *tags)
+{
+ mirror_mask_t mirrors;
+ int flow_vlan;
+ size_t i;
+
+ mirrors = in_port->src_mirrors;
+ for (i = 0; i < set->n; i++) {
+ mirrors |= set->dsts[i].iface->port->dst_mirrors;
+ }
+
+ if (!mirrors) {
+ return;
+ }
+
+ flow_vlan = vlan_tci_to_vid(flow->vlan_tci);
+ if (flow_vlan == 0) {
+ flow_vlan = OFP_VLAN_NONE;
}
while (mirrors) {
struct mirror *m = br->mirrors[mirror_mask_ffs(mirrors) - 1];
if (!m->n_vlans || vlan_is_mirrored(m, vlan)) {
}
while (mirrors) {
struct mirror *m = br->mirrors[mirror_mask_ffs(mirrors) - 1];
if (!m->n_vlans || vlan_is_mirrored(m, vlan)) {
if (m->out_port) {
if (set_dst(&dst, flow, in_port, m->out_port, tags)
&& !dst_is_duplicate(set, &dst)) {
if (m->out_port) {
if (set_dst(&dst, flow, in_port, m->out_port, tags)
&& !dst_is_duplicate(set, &dst)) {
}
mirrors &= mirrors - 1;
}
}
mirrors &= mirrors - 1;
}
-
- partition_dsts(set, flow_vlan);
dst_set_init(&set);
compose_dsts(br, flow, vlan, in_port, out_port, &set, tags,
nf_output_iface);
dst_set_init(&set);
compose_dsts(br, flow, vlan, in_port, out_port, &set, tags,
nf_output_iface);
+ compose_mirror_dsts(br, flow, vlan, in_port, &set, tags);
cur_vlan = vlan_tci_to_vid(flow->vlan_tci);
if (cur_vlan == 0) {
cur_vlan = OFP_VLAN_NONE;
}
cur_vlan = vlan_tci_to_vid(flow->vlan_tci);
if (cur_vlan == 0) {
cur_vlan = OFP_VLAN_NONE;
}
+
+ partition_dsts(&set, cur_vlan);
+
for (i = 0; i < set.n; i++) {
const struct dst *dst = &set.dsts[i];
if (dst->vlan != cur_vlan) {
for (i = 0; i < set.n; i++) {
const struct dst *dst = &set.dsts[i];
if (dst->vlan != cur_vlan) {