daemon: Integrate checking for an existing pidfile into daemonize_start().
[openvswitch] / vswitchd / bridge.c
index c367a065893f66b1fb8911838d1d1643b2e47cca..07daacdb6ac7ce3471da5a491c11896ae3424599 100644 (file)
@@ -81,8 +81,8 @@ COVERAGE_DEFINE(bridge_process_flow);
 COVERAGE_DEFINE(bridge_reconfigure);
 
 struct dst {
+    struct iface *iface;
     uint16_t vlan;
-    uint16_t dp_ifidx;
 };
 
 struct dst_set {
@@ -2085,69 +2085,17 @@ set_dst(struct dst *dst, const struct flow *flow,
         const struct port *in_port, const struct port *out_port,
         tag_type *tags)
 {
-    struct iface *iface;
-    uint16_t vlan;
+    dst->vlan = (out_port->vlan >= 0 ? OFP_VLAN_NONE
+                 : in_port->vlan >= 0 ? in_port->vlan
+                 : flow->vlan_tci == 0 ? OFP_VLAN_NONE
+                 : vlan_tci_to_vid(flow->vlan_tci));
 
-    vlan = (out_port->vlan >= 0 ? OFP_VLAN_NONE
-            : in_port->vlan >= 0 ? in_port->vlan
-            : flow->vlan_tci == 0 ? OFP_VLAN_NONE
-            : vlan_tci_to_vid(flow->vlan_tci));
+    dst->iface = (!out_port->bond
+                  ? port_get_an_iface(out_port)
+                  : bond_choose_output_slave(out_port->bond, flow,
+                                             dst->vlan, tags));
 
-    iface = (!out_port->bond
-             ? port_get_an_iface(out_port)
-             : bond_choose_output_slave(out_port->bond, flow, vlan, tags));
-    if (iface) {
-        dst->vlan = vlan;
-        dst->dp_ifidx = iface->dp_ifidx;
-        return true;
-    } else {
-        return false;
-    }
-}
-
-static void
-swap_dst(struct dst *p, struct dst *q)
-{
-    struct dst tmp = *p;
-    *p = *q;
-    *q = tmp;
-}
-
-/* Moves all the dsts with vlan == 'vlan' to the front of the 'n_dsts' in
- * 'dsts'.  (This may help performance by reducing the number of VLAN changes
- * that we push to the datapath.  We could in fact fully sort the array by
- * vlan, but in most cases there are at most two different vlan tags so that's
- * possibly overkill.) */
-static void
-partition_dsts(struct dst_set *set, int vlan)
-{
-    struct dst *first = set->dsts;
-    struct dst *last = set->dsts + set->n;
-
-    while (first != last) {
-        /* Invariants:
-         *      - All dsts < first have vlan == 'vlan'.
-         *      - All dsts >= last have vlan != 'vlan'.
-         *      - first < last. */
-        while (first->vlan == vlan) {
-            if (++first == last) {
-                return;
-            }
-        }
-
-        /* Same invariants, plus one additional:
-         *      - first->vlan != vlan.
-         */
-        while (last[-1].vlan != vlan) {
-            if (--last == first) {
-                return;
-            }
-        }
-
-        /* Same invariants, plus one additional:
-         *      - last[-1].vlan == vlan.*/
-        swap_dst(first++, --last);
-    }
+    return dst->iface != NULL;
 }
 
 static int
@@ -2198,7 +2146,7 @@ dst_is_duplicate(const struct dst_set *set, const struct dst *test)
     size_t i;
     for (i = 0; i < set->n; i++) {
         if (set->dsts[i].vlan == test->vlan
-            && set->dsts[i].dp_ifidx == test->dp_ifidx) {
+            && set->dsts[i].iface == test->iface) {
             return true;
         }
     }
@@ -2244,14 +2192,7 @@ compose_dsts(const struct bridge *br, const struct flow *flow, uint16_t vlan,
              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;
     struct dst dst;
-    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;
@@ -2262,20 +2203,44 @@ compose_dsts(const struct bridge *br, const struct flow *flow, uint16_t vlan,
                 && 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);
             }
         }
         *nf_output_iface = NF_OUT_FLOOD;
     } else if (out_port && set_dst(&dst, flow, in_port, out_port, tags)) {
         dst_set_add(set, &dst);
-        *nf_output_iface = dst.dp_ifidx;
-        mirrors |= out_port->dst_mirrors;
+        *nf_output_iface = dst.iface->dp_ifidx;
+    }
+}
+
+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)) {
+            struct dst dst;
+
             if (m->out_port) {
                 if (set_dst(&dst, flow, in_port, m->out_port, tags)
                     && !dst_is_duplicate(set, &dst)) {
@@ -2312,23 +2277,6 @@ compose_dsts(const struct bridge *br, const struct flow *flow, uint16_t vlan,
         }
         mirrors &= mirrors - 1;
     }
-
-    partition_dsts(set, flow_vlan);
-}
-
-static void OVS_UNUSED
-print_dsts(const struct dst_set *set)
-{
-    size_t i;
-
-    for (i = 0; i < set->n; i++) {
-        const struct dst *dst = &set->dsts[i];
-
-        printf(">p%"PRIu16, dst->dp_ifidx);
-        if (dst->vlan != OFP_VLAN_NONE) {
-            printf("v%"PRIu16, dst->vlan);
-        }
-    }
 }
 
 static void
@@ -2337,20 +2285,33 @@ compose_actions(struct bridge *br, const struct flow *flow, uint16_t vlan,
                 tag_type *tags, struct ofpbuf *actions,
                 uint16_t *nf_output_iface)
 {
+    uint16_t initial_vlan, cur_vlan;
+    const struct dst *dst;
     struct dst_set set;
-    uint16_t cur_vlan;
-    size_t i;
 
     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;
+    /* Output all the packets we can without having to change the VLAN. */
+    initial_vlan = vlan_tci_to_vid(flow->vlan_tci);
+    if (initial_vlan == 0) {
+        initial_vlan = OFP_VLAN_NONE;
+    }
+    for (dst = set.dsts; dst < &set.dsts[set.n]; dst++) {
+        if (dst->vlan != initial_vlan) {
+            continue;
+        }
+        nl_msg_put_u32(actions, ODP_ACTION_ATTR_OUTPUT, dst->iface->dp_ifidx);
     }
-    for (i = 0; i < set.n; i++) {
-        const struct dst *dst = &set.dsts[i];
+
+    /* Then output the rest. */
+    cur_vlan = initial_vlan;
+    for (dst = set.dsts; dst < &set.dsts[set.n]; dst++) {
+        if (dst->vlan == initial_vlan) {
+            continue;
+        }
         if (dst->vlan != cur_vlan) {
             if (dst->vlan == OFP_VLAN_NONE) {
                 nl_msg_put_flag(actions, ODP_ACTION_ATTR_STRIP_VLAN);
@@ -2362,8 +2323,9 @@ compose_actions(struct bridge *br, const struct flow *flow, uint16_t vlan,
             }
             cur_vlan = dst->vlan;
         }
-        nl_msg_put_u32(actions, ODP_ACTION_ATTR_OUTPUT, dst->dp_ifidx);
+        nl_msg_put_u32(actions, ODP_ACTION_ATTR_OUTPUT, dst->iface->dp_ifidx);
     }
+
     dst_set_free(&set);
 }