nicira-ext: Remove the autopath action.
[sliver-openvswitch.git] / ofproto / ofproto-dpif.c
index efd47b3..109e57c 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <errno.h>
 
-#include "autopath.h"
 #include "bond.h"
 #include "bundle.h"
 #include "byte-order.h"
@@ -510,7 +509,6 @@ struct ofport_dpif {
     struct list bundle_node;    /* In struct ofbundle's "ports" list. */
     struct cfm *cfm;            /* Connectivity Fault Management, if any. */
     tag_type tag;               /* Tag associated with this port. */
-    uint32_t bond_stable_id;    /* stable_id to use as bond slave, or 0. */
     bool may_enable;            /* May be enabled in bonds. */
     long long int carrier_seq;  /* Carrier status changes. */
     struct tnl_port *tnl_port;  /* Tunnel handle, or null. */
@@ -867,6 +865,10 @@ type_run(const char *type)
             drop_key_clear(backer);
         }
 
+        /* Clear the revalidation flags. */
+        tag_set_init(&backer->revalidate_set);
+        backer->need_revalidate = 0;
+
         HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
             struct facet *facet;
 
@@ -874,10 +876,6 @@ type_run(const char *type)
                 continue;
             }
 
-            /* Clear the revalidation flags. */
-            tag_set_init(&backer->revalidate_set);
-            backer->need_revalidate = 0;
-
             HMAP_FOR_EACH (facet, hmap_node, &ofproto->facets) {
                 if (need_revalidate
                     || tag_set_intersects(&revalidate_set, facet->tags)) {
@@ -1601,12 +1599,14 @@ port_construct(struct ofport *port_)
         if (odp_port_to_ofp_port(ofproto, port->odp_port) != OFPP_NONE) {
             VLOG_ERR("port %s already has an OpenFlow port number",
                      dpif_port.name);
+            dpif_port_destroy(&dpif_port);
             return EBUSY;
         }
 
         hmap_insert(&ofproto->backer->odp_to_ofport_map, &port->odp_port_node,
                     hash_int(port->odp_port, 0));
     }
+    dpif_port_destroy(&dpif_port);
 
     if (ofproto->sflow) {
         dpif_sflow_add_port(ofproto->sflow, port_, port->odp_port);
@@ -2213,8 +2213,7 @@ bundle_del_port(struct ofport_dpif *port)
 
 static bool
 bundle_add_port(struct ofbundle *bundle, uint32_t ofp_port,
-                struct lacp_slave_settings *lacp,
-                uint32_t bond_stable_id)
+                struct lacp_slave_settings *lacp)
 {
     struct ofport_dpif *port;
 
@@ -2241,8 +2240,6 @@ bundle_add_port(struct ofbundle *bundle, uint32_t ofp_port,
         lacp_slave_register(bundle->lacp, port, lacp);
     }
 
-    port->bond_stable_id = bond_stable_id;
-
     return true;
 }
 
@@ -2350,8 +2347,7 @@ bundle_set(struct ofproto *ofproto_, void *aux,
     ok = true;
     for (i = 0; i < s->n_slaves; i++) {
         if (!bundle_add_port(bundle, s->slaves[i],
-                             s->lacp ? &s->lacp_slaves[i] : NULL,
-                             s->bond_stable_ids ? s->bond_stable_ids[i] : 0)) {
+                             s->lacp ? &s->lacp_slaves[i] : NULL)) {
             ok = false;
         }
     }
@@ -2451,8 +2447,7 @@ bundle_set(struct ofproto *ofproto_, void *aux,
         }
 
         LIST_FOR_EACH (port, bundle_node, &bundle->ports) {
-            bond_slave_register(bundle->bond, port, port->bond_stable_id,
-                                port->up.netdev);
+            bond_slave_register(bundle->bond, port, port->up.netdev);
         }
     } else {
         bond_destroy(bundle->bond);
@@ -3163,6 +3158,9 @@ struct port_dump_state {
     uint32_t bucket;
     uint32_t offset;
     bool ghost;
+
+    struct ofproto_port port;
+    bool has_port;
 };
 
 static int
@@ -3181,12 +3179,20 @@ port_dump_next(const struct ofproto *ofproto_, void *state_,
     const struct sset *sset;
     struct sset_node *node;
 
+    if (state->has_port) {
+        ofproto_port_destroy(&state->port);
+        state->has_port = false;
+    }
     sset = state->ghost ? &ofproto->ghost_ports : &ofproto->ports;
     while ((node = sset_at_position(sset, &state->bucket, &state->offset))) {
         int error;
 
-        error = port_query_by_name(ofproto_, node->name, port);
-        if (error != ENODEV) {
+        error = port_query_by_name(ofproto_, node->name, &state->port);
+        if (!error) {
+            *port = state->port;
+            state->has_port = true;
+            return 0;
+        } else if (error != ENODEV) {
             return error;
         }
     }
@@ -3206,6 +3212,9 @@ port_dump_done(const struct ofproto *ofproto_ OVS_UNUSED, void *state_)
 {
     struct port_dump_state *state = state_;
 
+    if (state->has_port) {
+        ofproto_port_destroy(&state->port);
+    }
     free(state);
     return 0;
 }
@@ -5700,7 +5709,7 @@ compose_output_action__(struct action_xlate_ctx *ctx, uint16_t ofp_port,
 
     /* If 'struct flow' gets additional metadata, we'll need to zero it out
      * before traversing a patch port. */
-    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 18);
+    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 19);
 
     if (!ofport) {
         xlate_report(ctx, "Nonexistent output port");
@@ -5922,16 +5931,11 @@ execute_controller_action(struct action_xlate_ctx *ctx, int len,
 
     if (packet->l2 && packet->l3) {
         struct eth_header *eh;
+        uint16_t mpls_depth;
 
         eth_pop_vlan(packet);
         eh = packet->l2;
 
-        /* If the Ethernet type is less than ETH_TYPE_MIN, it's likely an 802.2
-         * LLC frame.  Calculating the Ethernet type of these frames is more
-         * trouble than seems appropriate for a simple assertion. */
-        ovs_assert(ntohs(eh->eth_type) < ETH_TYPE_MIN
-                   || eh->eth_type == ctx->flow.dl_type);
-
         memcpy(eh->eth_src, ctx->flow.dl_src, sizeof eh->eth_src);
         memcpy(eh->eth_dst, ctx->flow.dl_dst, sizeof eh->eth_dst);
 
@@ -5939,6 +5943,16 @@ execute_controller_action(struct action_xlate_ctx *ctx, int len,
             eth_push_vlan(packet, ctx->flow.vlan_tci);
         }
 
+        mpls_depth = eth_mpls_depth(packet);
+
+        if (mpls_depth < ctx->flow.mpls_depth) {
+            push_mpls(packet, ctx->flow.dl_type, ctx->flow.mpls_lse);
+        } else if (mpls_depth > ctx->flow.mpls_depth) {
+            pop_mpls(packet, ctx->flow.dl_type);
+        } else if (mpls_depth) {
+            set_mpls_lse(packet, ctx->flow.mpls_lse);
+        }
+
         if (packet->l4) {
             if (ctx->flow.dl_type == htons(ETH_TYPE_IP)) {
                 packet_set_ipv4(packet, ctx->flow.nw_src, ctx->flow.nw_dst,
@@ -5971,6 +5985,48 @@ execute_controller_action(struct action_xlate_ctx *ctx, int len,
     ofpbuf_delete(packet);
 }
 
+static void
+execute_mpls_push_action(struct action_xlate_ctx *ctx, ovs_be16 eth_type)
+{
+    ovs_assert(eth_type_mpls(eth_type));
+
+    if (ctx->base_flow.mpls_depth) {
+        ctx->flow.mpls_lse &= ~htonl(MPLS_BOS_MASK);
+        ctx->flow.mpls_depth++;
+    } else {
+        ovs_be32 label;
+        uint8_t tc, ttl;
+
+        if (ctx->flow.dl_type == htons(ETH_TYPE_IPV6)) {
+            label = htonl(0x2); /* IPV6 Explicit Null. */
+        } else {
+            label = htonl(0x0); /* IPV4 Explicit Null. */
+        }
+        tc = (ctx->flow.nw_tos & IP_DSCP_MASK) >> 2;
+        ttl = ctx->flow.nw_ttl ? ctx->flow.nw_ttl : 0x40;
+        ctx->flow.mpls_lse = set_mpls_lse_values(ttl, tc, 1, label);
+        ctx->flow.encap_dl_type = ctx->flow.dl_type;
+        ctx->flow.mpls_depth = 1;
+    }
+    ctx->flow.dl_type = eth_type;
+}
+
+static void
+execute_mpls_pop_action(struct action_xlate_ctx *ctx, ovs_be16 eth_type)
+{
+    ovs_assert(eth_type_mpls(ctx->flow.dl_type));
+    ovs_assert(!eth_type_mpls(eth_type));
+
+    if (ctx->flow.mpls_depth) {
+        ctx->flow.mpls_depth--;
+        ctx->flow.mpls_lse = htonl(0);
+        if (!ctx->flow.mpls_depth) {
+            ctx->flow.dl_type = eth_type;
+            ctx->flow.encap_dl_type = htons(0);
+        }
+    }
+}
+
 static bool
 compose_dec_ttl(struct action_xlate_ctx *ctx, struct ofpact_cnt_ids *ids)
 {
@@ -6112,26 +6168,6 @@ struct xlate_reg_state {
     ovs_be64 tun_id;
 };
 
-static void
-xlate_autopath(struct action_xlate_ctx *ctx,
-               const struct ofpact_autopath *ap)
-{
-    uint16_t ofp_port = ap->port;
-    struct ofport_dpif *port = get_ofp_port(ctx->ofproto, ofp_port);
-
-    if (!port || !port->bundle) {
-        ofp_port = OFPP_NONE;
-    } else if (port->bundle->bond) {
-        /* Autopath does not support VLAN hashing. */
-        struct ofport_dpif *slave = bond_choose_output_slave(
-            port->bundle->bond, &ctx->flow, 0, &ctx->tags);
-        if (slave) {
-            ofp_port = slave->up.ofp_port;
-        }
-    }
-    nxm_reg_load(&ap->dst, ofp_port, &ctx->flow);
-}
-
 static bool
 slave_enabled_cb(uint16_t ofp_port, void *ofproto_)
 {
@@ -6357,6 +6393,14 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
             nxm_execute_reg_load(ofpact_get_REG_LOAD(a), &ctx->flow);
             break;
 
+        case OFPACT_PUSH_MPLS:
+            execute_mpls_push_action(ctx, ofpact_get_PUSH_MPLS(a)->ethertype);
+            break;
+
+        case OFPACT_POP_MPLS:
+            execute_mpls_pop_action(ctx, ofpact_get_POP_MPLS(a)->ethertype);
+            break;
+
         case OFPACT_DEC_TTL:
             if (compose_dec_ttl(ctx, ofpact_get_DEC_TTL(a))) {
                 goto out;
@@ -6371,10 +6415,6 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
             multipath_execute(ofpact_get_MULTIPATH(a), &ctx->flow);
             break;
 
-        case OFPACT_AUTOPATH:
-            xlate_autopath(ctx, ofpact_get_AUTOPATH(a));
-            break;
-
         case OFPACT_BUNDLE:
             ctx->ofproto->has_bundle_action = true;
             xlate_bundle_action(ctx, ofpact_get_BUNDLE(a));